0

好吧...我数学不太好(甚至没有完成我们的高中版本)并且现在真的很累,但是我需要围绕质心椭圆绕四个物体运行并且已经卡住了一段时间,但这并不是我没有尝试过或自己来过任何地方。到目前为止,这是我想出的:

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 我做错了什么,但我现在不知道是什么。

我有点累,现在会试着睡一觉,看看我明天能不能解决它,但这里真的会得到一些帮助。

4

1 回答 1

1

这封装了每个椭圆的数学,并显示了示例用法;你将不得不为你想要的任何输出添加代码。

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()
于 2012-06-03T17:19:27.900 回答