好吧......我不是很擅长数学(甚至没有完成我们的高中版本)而且现在真的很累,但是我需要在质心周围以椭圆形方式围绕四个物体运行并且被卡住了一段时间了,但这并不像我自己没有尝试或来过任何地方。这是我到目前为止所提出的:
from math import cos,sin,pi,sqrt,atan2
def orbit(p, deg, pivot=(0.32563325, 0.123498),ellipse=(0.5, 0.743992)):
# p = current (x,y)-position of current object,
# Pivot = (x,y)-position of point to orbit around,
# retrieved by centroid((x1,y1),(x2,y2),(x3,y3),(x4,y4))
# Ellipse = (width,height) of ellipse to rotate around
# retrieved by ellipse((x1,y1),(x2,y2),(x3,y3),(x4,y4))
px,py = pivot
if ellipse == (0.0,0.0):
o = polar(p[0]-px,p[1]-py)[0]
xr,yr = 1.0,1.0
else:
ew,eh = ellipse
if ew < eh:
o = eh/2 # Distance to the point most far away from the middle of the ellipse (Outer radius)
xr = ew/eh # Horizontal ratio of ellipse so we can move it back properly into ellipse after performing circular orbit
yr = 1.0 # Verical movement will not be affected because it's on the large axis
else:
o = ew/2
xr = 1.0
yr = eh/ew
x,y = p[0]-px,p[1]-py # Subtract pivot's position (that's the the point I want to orbit around)
d,a = polar(x,y) # Get angle
x,y = rect(o,a+deg) # Move point as far away from middle as it will be as most and make circular orbit around pivot by deg degrees
x,y = x*xr,y*yr # Move points back to elliptic shape by multiplying positions with according ratio <--- I guess it's here something goes wrong
x,y = x+px,y+py # Move point back to original position by adding pivot's positions
return x,y
# Other functions
def centroid(*points):
x,y = izip(*points)
return (sum(x) / len(points), sum(y) / len(points))
def ellipse(*points):
x,y = izip(*points)
xd,yd = max(x)-min(x),max(y)-min(y)
return (xd,yd)
def polar(x,y):
d = sqrt(x**2 + y**2)
a = atan2(y,x) * (180.0/pi)
return d, a
def rect(d,a):
x = d * cos(a*pi/180.0)
y = d * sin(a*pi/180.0)
return x, y
如果我使用ellipse =(0.0,0.0)并将所有东西都放在一个“普通”圆圈而不是椭圆形状中,它就可以正常工作,所以我想当我尝试将x / y位置与比率相乘时ew / eh或eh / ew我做错了什么但我现在无法弄清楚是什么。
我有点累了,现在试着睡一会儿,看看我明天是否可以解决,但是这里有一些帮助真的很适合。
答案 0 :(得分:1)
这封装了每个Ellipse的数学运算,并显示了样本用法;你必须为你想要的任何输出添加代码。
from math import sin, cos, pi
class Ellipse(object):
@classmethod
def fromBox(cls, p1=(-1.,-1.), p2=(1.,1.), period=1., offs=0., clockwise=False):
"""
Construct an Ellipse from an axis-aligned bounding box
p1, p2 diagonally-opposed corners of the bounding box
period time for a complete orbit
offs offset into initial rotation
clockwise direction of rotation
"""
x1,y1 = p1
x2,y2 = p2
# find center point
cx, cy = (x1 + x2)*0.5, (y1 + y2)*0.5
# find major and minor semi-axes and corresponding theta
a,b = abs(x2 - x1)*0.5, abs(y2 - y1)*0.5
if a >= b:
theta = 0.0
else:
a,b = b,a
theta = pi/2
# return an Ellipse object
return cls(cx, cy, a, b, theta, period, offs, clockwise)
def __init__(self, x=0., y=0., a=1., b=1., theta=0., period=1., offs=0., clockwise=False):
"""
Create an ellipse
x,y center point
a semi-major axis
b semi-minor axis
theta major axis inclination (in radians)
period time for a complete orbit
offs offset into initial rotation
clockwise direction of rotation
"""
self.x = x
self.y = y
self.period = -period if clockwise else period
self._freq = self.period / (2. * pi)
self.offs = offs
s_th = sin(theta)
c_th = cos(theta)
self._ast = a * s_th
self._act = a * c_th
self._bst = b * s_th
self._bct = b * c_th
def at(self, t):
"""
Evaluate the ellipse at time t
"""
_t = (t - self.offs) * self._freq
st = sin(_t)
ct = cos(_t)
return self.x + self._act*ct - self._bst*st, self.y + self._act*st + self._bst*ct
def main():
a = Ellipse.fromBox((-0.67436675, -0.376502), (1.32563325, 0.623498))
b = Ellipse(0.32563325, 0.123498, 0.9, 0.6, pi/6)
c = Ellipse(0.32563325, 0.123498, 1.1, 0.5, pi/4)
d = Ellipse(0.32563325, 0.123498, 1.0, 0.5, pi/2)
t_step = 0.03
for t in xrange(200):
drawCircle(a.at(t*t_step), "red")
drawCircle(b.at(t*t_step), "blue")
drawCircle(c.at(t*t_step), "green")
drawCircle(d.at(t*t_step), "yellow")
if __name__=="__main__":
main()