Currently I writing JavaScript code that will place objects on screen accross the ellipse.
I trying to find algorithm that will solve one of this problems, ellipse will be perfect, but if it is too expensive Beizier curve will be ok too.
I'm sorry, but unforunately my math doesn't let me to use answers that I found (https://mathoverflow.net/questions/28070/finding-n-points-that-are-equidistant-around-the-circumference-of-an-ellipse , Equidistant points across Bezier curves ), so I need help to translate it to code or just advice how to do this.
If you need visualisation of my question you can look at second page of this doc:
http://www.saccade.com/writing/graphics/RE-PARAM.PDF
Ok I retracted mine close vote your question is a slight different then those I linked
- but as you can see not much :)
Have played with mine code a bit so here is the result for equidistant points
//---------------------------------------------------------------------------
void draw()
{
TCanvas *scr=Form1->Canvas;
//if (scr->FHandle==NULL) return;
scr->Brush->Color=clWhite;
scr->Rectangle(0,0,Form1->ClientWidth,Form1->ClientHeight);
double x0,y0,rx,ry,n,l0,ll0;
x0=Form1->ClientWidth>>1; // ellipse position (midle of form)
y0=Form1->ClientHeight>>1;
rx=200; // ellipse a
ry=50; // ellipse b
n=33.0; // segments
//l0=2.0*M_PI*sqrt(0.5*((rx*rx)+(ry*ry)));
l0=(rx-ry)/(rx+ry); l0*=3.0*l0; l0=M_PI*(rx+ry)*(1.0+(l0/(10.0+sqrt(4.0-l0))));
// compute segment size
l0/=n; ll0=l0*l0;
int i,j,k,kd;
AnsiString s;
double a,da,x,y,xx,yy,ll,mm,r=2.0;
for (kd=10,k=0;;k++) // kd+1 passes
{
a=0.0; if (!k) da=0.0;
xx=rx*sin(a+0.5*da);
yy=ry*cos(a+0.5*da);
da=l0/sqrt((xx*xx)+(yy*yy));
x=x0+rx*cos(a);
y=y0+ry*sin(a);
if (k==kd) // draw in last pass only
{
scr->Pen->Color=clRed;
scr->MoveTo(x ,y );
scr->LineTo(x0,y0);
scr->Ellipse(x-r,y-r,x+r,y+r);
scr->Pen->Color=clBlue;
scr->Font->Color=clBlue;
}
for (i=n;i>0;i--)
{
// approximate angular step to match l0 (as start point for fitting)
xx=rx*sin(a+0.5*da);
yy=ry*cos(a+0.5*da);
da=l0/sqrt((xx*xx)+(yy*yy));
// next point position
xx=x; yy=y; a+=da;
x=x0+rx*cos(a);
y=y0+ry*sin(a);
// fit it to be really l0
ll=((xx-x)*(xx-x))+((yy-y)*(yy-y)); ll=fabs(ll0-ll);
for (da*=0.1,a-=da,j=0;j<5;) // accuracy recursion layers
{
a+=da;
x=x0+rx*cos(a);
y=y0+ry*sin(a);
mm=((xx-x)*(xx-x))+((yy-y)*(yy-y)); mm=fabs(ll0-mm);
if (mm>ll) { a-=da; da=-0.1*da; j++; } else ll=mm; // if acuracy stop lovering change direction
}
x=x0+rx*cos(a);
y=y0+ry*sin(a);
if (k==kd) // draw in last pass only
{
// draw the lines and dots
scr->MoveTo(xx,yy);
scr->LineTo(x ,y );
scr->Ellipse(x-r,y-r,x+r,y+r);
// print the difference^2
ll=((xx-x)*(xx-x))+((yy-y)*(yy-y));
s=AnsiString().sprintf("%.2lf",ll0-ll);
xx=0.5*(x+xx)+20.0*cos(a)-0.5*double(scr->TextWidth(s));
yy=0.5*(y+yy)+20.0*sin(a)-0.5*double(scr->TextHeight(s));
scr->TextOutA(xx,yy,s);
}
}
if (k==kd)
{
scr->MoveTo(x ,y );
scr->LineTo(x0,y0);
s=AnsiString().sprintf("%.4lf",2.0*M_PI-a);
xx=x+60.0*cos(a)-0.5*double(scr->TextWidth(s));
yy=y+60.0*sin(a)-0.5*double(scr->TextHeight(s));
scr->TextOutA(xx,yy,s);
break;
}
// rescale l0
a=2.0*M_PI/a; // a should be 2*PI if no error -> 1.0
l0*=0.5+0.5*a; // just iterate
ll0=l0*l0;
}
}
//---------------------------------------------------------------------------
It compose from the code from the second linked Q/A but anyway this is what it does
k/kd
loop loops the whole thing kd
-times
and in each it go a bit closer to the result by rescaling segment size l0,ll0
. In the last pass it also draws the segments ... The more passes there are the more precision you get. With current overkill it can handle even rx=4.0*ry
eccentric ellipses (or vice versa). For common ellipses is sufficient that kd=1,2 or 3
i
loop go through all segments
first estimate step by the formula from linked Q/A and then use iterative fitting of segment size to l0
via most inner 'j' loop
inner most j
loop
just step angle and see if segment is closer to wanted size if not change direction of step and its magnitude 10
times to increase accuracy the more recursion layers for j
it is the more precise this gets
at the end of k/kd
loop
the angle should be 2*PI
so if it is more or less then rescale l0
accordingly but to avoid oscillations use also averaging with original l0
size
That is all