Чтобы создать точки решетки внутри эллипса, мы должны знать, где горизонтальная линия пересекает этот эллипс.
Уравнение эллипса с нулевым центром, повернутое на угол Theta:
x = a * Cos(t) * Cos(theta) - b * Sin(t) * Sin(theta)
y = a * Cos(t) * Sin(theta) + b * Sin(t) * Cos(theta)
Для упрощенияВ расчетах мы можем ввести псевдокруг Fi и величину M (константы для данного эллипса)
Fi = atan2(a * Sin(theta), b * Cos(theta))
M = Sqrt((a * Sin(theta))^2 + (b * Cos(theta))^2)
, поэтому
y = M * Sin(Fi) * Cos(t) + M * Cos(Fi) * Sin(t)
y/M = Sin(Fi) * Cos(t) + Cos(Fi) * Sin(t)
y/M = Sin(Fi + t)
, а решение для данной горизонтальной линии в положении y равно
Fi + t = ArcSin( y / M)
Fi + t = Pi - ArcSin( y / M)
t1 = ArcSin( y / M) - Fi //note two values
t2 = Pi - ArcSin( y / M) - Fi
Замените оба значения t в первом уравнении и получите значения X для заданного Y, а также сгенерируйте одну последовательность точек решетки
Чтобы получить верхнюю и нижнюю координаты, дифференцируйте y
y' = M * Cos(Fi + t) = 0
th = Pi/2 - Fi
tl = -Pi/2 - Fi
найти соответствующие y и использовать их в качестве начальной и конечной Y-координат для линий.
import math
def ellipselattice(cx, cy, a, b, theta):
res = []
at = a * math.sin(theta)
bt = b * math.cos(theta)
Fi = math.atan2(at, bt)
M = math.hypot(at, bt)
ta = math.pi/2 - Fi
tb = -math.pi/2 - Fi
y0 = at * math.cos(ta) + bt *math.sin(ta)
y1 = at * math.cos(tb) + bt *math.sin(tb)
y0, y1 = math.ceil(cy + min(y0, y1)), math.floor(cy + max(y0, y1))
for y in range(y0, y1+1):
t1 = math.asin(y / M) - Fi
t2 = math.pi - math.asin(y / M) - Fi
x1 = a * math.cos(t1) * math.cos(theta) - b* math.sin(t1) * math.sin(theta)
x2 = a * math.cos(t2) * math.cos(theta) - b* math.sin(t2) * math.sin(theta)
x1, x2 = math.ceil(cx + min(x1, x2)), math.floor(cx + max(x1, x2))
line = [(x, y) for x in range(x1, x2 + 1)]
res.append(line)
return res
print(ellipselattice(0, 0, 4, 3, math.pi / 4))