问题
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
回答1:
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/kdloop loops the whole thingkd-timesand 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 evenrx=4.0*ryeccentric ellipses (or vice versa). For common ellipses is sufficient thatkd=1,2 or 3iloop go through all segmentsfirst estimate step by the formula from linked Q/A and then use iterative fitting of segment size to
l0via most inner 'j' loopinner most
jloopjust step angle and see if segment is closer to wanted size if not change direction of step and its magnitude
10times to increase accuracy the more recursion layers forjit is the more precise this getsat the end of
k/kdloopthe angle should be
2*PIso if it is more or less then rescalel0accordingly but to avoid oscillations use also averaging with originall0size
That is all
来源:https://stackoverflow.com/questions/27874695/find-equidistant-points-on-ellipse-or-beizier-curves