好吧,我撤回了我的接近投票,你的问题与我链接的问题略有不同
玩过我的代码,所以这是等距点的结果
//---------------------------------------------------------------------------
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;
}
}
//---------------------------------------------------------------------------
它由第二个链接的代码组成Q/A但无论如何,这就是它的作用
-
k/kd
循环循环整个事情kd
-times
在每个中,通过重新调整段大小,它会更接近结果l0,ll0
。在最后一遍中,它还绘制了线段……遍数越多,获得的精度就越高。以目前的过度杀伤力,它甚至可以处理rx=4.0*ry
偏心椭圆(或反之亦然)。对于常见的椭圆就足够了kd=1,2 or 3
-
i
循环遍历所有段
首先根据链接的公式估计步骤Q/A然后使用分段大小的迭代拟合l0
通过最内部的“j”循环
-
最里面j
loop
只是步距角,如果不改变步距的方向及其大小,看看段是否更接近所需的尺寸10
递归层数越多,精度越高j
越精确
-
在......的最后k/kd
loop
角度应该是2*PI
所以如果它或多或少则重新调整l0
相应地,但为了避免振荡,也使用原始平均值l0
size
就这些