If you want the real thing
then the planets closer to the primary focus point (center of mass of stellar system ... very close to star) are moving faster so use Kepler's equation here: C++ implementation of mine. Do not forget to check out all the sub-links in that answer you can find there everything you need.
If you want constant speed instead
Then use parametric ellipse equation
x(a)=x0+rx*cos(a)
y(a)=y0+ry*sin(a)
where a
is angle <0,2.0*PI>
(x0,y0)
is the ellipse center and (rx,ry)
are the ellipse semi axises (radii).
if a
is incremented with constant speed then the area increase is constant so the a
is the mean circular angle not the visual on ellipse !!! For more info look here:
[edit1] as MartinR pointed out the speed is not constant
so here is approximation with his formula for speed. Ellipse is axis aligned defined by x0,y0,rx,ry
(rx>=ry)
the perimeter aproximation l
:
h=(rx-ry)/(rx+ry); h*=3.0*h; l=M_PI*(rx+ry)*(1.0+(h/(10.0+sqrt(4.0-h))));
if you want to have n
chunks of equal sized steps along the perimeter then
l/=n;
initial computations:
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
first the slow bruteforce attack (black):
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));
}
Now the approximation (Blue):
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));
}
This is clean ellipse step (no debug draws)
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);
Here the output of comparison bruteforce and approximation:
[edit2] little precision boost
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);
the half step angle in approximation lead to much closer result to bruteforce attack
rx<=ry
(but not sure if in all circumstances ... the only thing that could go wrong is perimeter computation) – Tay