swift 我需要一个沿着椭圆做匀速运动的方程

2ledvvac  于 2023-06-28  发布在  Swift
关注(0)|答案(3)|浏览(201)

我正在编写一些类似行星围绕太阳运动的东西,为了移动行星,我使用了一个函数

CGPointMake(object.center.x + 1, sqrt(75*75*150*150 - 75*75*(object.center.x - 300)*(object.center.x - 300))/150 + 150)

使用椭圆方程,其中a = 150,B = 75,p = 300,q = 150,但当物体接近x = 450左右时,它的速度上升,我猜这是因为pitagora,因为它经过的路径是c = sqrt((x-x 0)^2*(y-y 0)^2)
我注意到我的c总是在0.5左右,但是当它到达x域的末端时,它上升到0.8,所以我需要一个程序或数学解决方案来使对象以相同的速度绕椭圆曲线移动
谢谢你!

k4emjkb1

k4emjkb11#

如果你想要真实的

然后行星更接近主焦点(恒星系统的质量中心…非常接近星星)移动得更快,所以在这里使用Kepler's equationC++ implementation of mine.别忘了检查出所有的子链接,在这个答案中,你可以找到你需要的一切.

如果你想要匀速

然后利用参数椭圆方程

x(a)=x0+rx*cos(a)
y(a)=y0+ry*sin(a)

其中a是Angular <0,2.0*PI>(x0,y0)是椭圆中心,(rx,ry)是椭圆半轴(半径)。
如果a以恒定速度递增,则面积增加是恒定的,因此a是平均圆周角,而不是椭圆上的可视Angular !!!有关更多信息,请查看此处:

这是他速度公式的近似值椭圆轴对齐,由x0,y0,rx,ry(rx>=ry)周长近似值l定义:

h=(rx-ry)/(rx+ry); h*=3.0*h; l=M_PI*(rx+ry)*(1.0+(h/(10.0+sqrt(4.0-h))));

如果你想在周长上有n个大小相等的台阶块,那么

l/=n;

初始计算:

double x0,y0,rx,ry,n,l,h;
x0=Form1->ClientWidth>>1;  // center is centered on form
y0=Form1->ClientHeight>>1;
rx=200; // semiaxises rx>=ry !!!
ry=75;
n=40.0; // number of chunks per ellipse (1/speed)
//l=2.0*M_PI*sqrt(0.5*((rx*rx)+(ry*ry)));  // not accurate enough
h=(rx-ry)/(rx+ry); h*=3.0*h; l=M_PI*(rx+ry)*(1.0+(h/(10.0+sqrt(4.0-h)))); // this is more precise
l/=n; // single step size in units,pixels,or whatever

第一个缓慢的暴力攻击(黑色):

int i;
double a,da,x,y,xx,yy,ll;
a=0.0;
x=x0+rx*cos(a);
y=y0+ry*sin(a);
for (i=n;i>0;i--)
    {
    xx=x; yy=y;
    for (da=a;;)
        {
        a+=0.001;
        x=x0+rx*cos(a);
        y=y0+ry*sin(a);
        ll=sqrt(((xx-x)*(xx-x))+((yy-y)*(yy-y)));
        if (ll>=l) break;
        } da=a-da;
    scr->MoveTo(5.0+50.0*a,5.0);
    scr->LineTo(5.0+50.0*a,5.0+300.0*da);

    scr->MoveTo(x0,y0);
    scr->LineTo(xx,yy);
    scr->LineTo(x ,y );
    ll=sqrt(((xx-x)*(xx-x))+((yy-y)*(yy-y)));
    scr->TextOutA(0.5*(x+xx)+20.0*cos(a),0.5*(y+yy)+20.0*sin(a),floor(ll));
    }

现在近似值(蓝色):

a=0.0; da=0;
x=x0+rx*cos(a);
y=y0+ry*sin(a);
for (i=n;i>0;i--)
    {
    scr->MoveTo(5.0+50.0*a,5.0+300.0*da);
    xx=rx*sin(a);
    yy=ry*cos(a);
    da=l/sqrt((xx*xx)+(yy*yy)); a+=da;
    scr->LineTo(5.0+50.0*a,5.0+300.0*da);

    xx=x; yy=y;
    x=x0+rx*cos(a);
    y=y0+ry*sin(a);

    scr->MoveTo(x0,y0);
    scr->LineTo(xx,yy);
    scr->LineTo(x ,y );
    ll=sqrt(((xx-x)*(xx-x))+((yy-y)*(yy-y)));
    scr->TextOutA(0.5*(x+xx)+40.0*cos(a),0.5*(y+yy)+40.0*sin(a),floor(ll));
    }

这是干净的椭圆步骤(没有调试绘制)

a=???; // some initial angle
// point on ellipse 
x=x0+rx*cos(a);
y=y0+ry*sin(a);
// next angle by almost constant speed
xx=rx*sin(a);
yy=ry*cos(a);
da=l/sqrt((xx*xx)+(yy*yy)); a+=da;
// next point on ellipse ...
x=x0+rx*cos(a);
y=y0+ry*sin(a);

这里的输出比较蛮力和近似:

[edit 2]精度略有提升

a,da=???; // some initial angle and step (last)
 x=x0+rx*cos(a);
 y=y0+ry*sin(a);
 // next angle by almost constant speed
 xx=rx*sin(a+0.5*da); // use half step angle for aproximation ....
 yy=ry*cos(a+0.5*da);
 da=l/sqrt((xx*xx)+(yy*yy)); a+=da;
 // next point on ellipse ...
 x=x0+rx*cos(a);
 y=y0+ry*sin(a);

近似半步角导致更接近蛮力攻击的结果

33qvvth1

33qvvth12#

嗯...
你可以用SpriteKit很容易地伪造这样的东西。注意:您的整个应用程序不必使用SpriteKit。您可以相当容易地将SKView放入非SpriteKit应用程序中。
不管怎样...
创造你的星球。。

SKSpritNode *planet = [SKSpritNode spriteNodeWithImageNamed:@"mars"];
[solarSystemView addChild:planet];

创建椭圆路径...

UIBezierPath *ellipse = [UIBezierPath bezierPathWithOvalInRect:/*your rect*/]; //or create it any other way.

创建操作...

SKAction *singleOrbit = [SKAction followPath:ellipse.CGPath speed:10];
SKAction *orbit = [SKAction repeatActionForever:singleOrbit];

运行操作...

[planet runAction:orbit];
iq0todco

iq0todco3#

在文章“椭圆的运动学”中,给出了点沿着椭圆的运动的公式:1.制服,2.均匀加速,3.椭圆形(Kepler)。证明了只有当移动3个Kepler定律满足https://www.academia.edu/94295697/Ellipse_kinematics

相关问题