椭圆的算法原理

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

椭圆的算法原理

圆心在原点、长半轴为a 、短半轴为b 的椭圆方程的隐函数表达式为:

椭圆将平面划分成三个区域:对于椭圆上的点,F(x ,y)=0;对于椭圆外的点,F (x ,y )>0;对于椭圆内的点,F (x ,y )<0,如下图所示。

考虑到椭圆对称性,可以用对称轴x =0,y =0,把椭圆分成4等份。只要绘制出第一象限内1/4椭圆弧,如图3-10的阴影部分Ⅰ和Ⅱ所示,根据对称性就可绘制出整个椭圆,这称为四分法绘制椭圆算法。已知第一象限内的点 0

),(222222=-+=b a y a x b y x

F

P (x ,y ),可以顺时针得到另外3个对称点:P (x,-y ),P (-x ,-y ),P (-x ,y )。

在处理第一象限的1/4椭圆弧时,进一步以法矢量两个分量相等的点把它分为两部分,上半部分Ⅰ和下半部分Ⅱ。该椭圆上一点P (x ,y )处的法矢量为:

式中,i 和j 是沿x 轴向和沿y 轴向的单位矢量。

在图3-11所示的部分Ⅰ的AC 椭圆弧段,法矢量的x 向分量小于y 向分量,斜率k 处处满足|k|<1,|△x|>|△y|,所以x 方向为主位移方向;在C 点,法矢量的x 向分量等于y 向分量,斜率k 满足k =-1,|△x|=|△y|;在部分Ⅱ的CB 椭圆弧段,法矢量x 向分量大于y 向分量,斜率k 处处满足|k|>1,|△y|>|△x|,所以y 方向为主位移方向。

yj a xi b j y F i x F y x N 2222),(+=∂∂+∂∂=

, )

图3-11

椭圆的中点Bresenham 算法的原理:在部分Ⅰ:每次在主位移x 方向上走一步,y 方向上退不退步取决于中点偏差判别式的值;在部分Ⅱ:每次在主位移方向y 上退一步,x 方向上走不走步取决于中点偏差判别式的值。

222/b a a +222/b a b

+

由于x方向为主位移方向,假定当前点是P(xi,yi),下一步只能在正右方的像素Pu(x i+1,y i)和右下方的像素Pd(x i+1,yi-1)中选取。

由于y方向为主位移方向,假定当前点是P(xi,yi),下一步只能在正下方像素Pl(x i,y i-1)和右下方的像素Pr(x i+1,yi-1)中选取。

1、构造上半部分Ⅰ中点偏差判别式

在上半部分Ⅰ,x方向每次加1,y方向上减不减1取决于中点偏差判别式的值。从P(xi,yi)走第一步,为了选取下一像素点的,需将Pu(x i+1,y i)和Pd(x i+1,yi

-1)的中点M (x i +1,y i -0.5)代入隐函数,构造中点偏差判别式:

当d1<0时,中点M 在椭圆内,下一像素点应点亮Pu ,即y 方向不退步;当d>0时,中点M 在椭圆外,下一像素点应点亮Pd ,即y 方向退一步;当d =0时,中点M 在椭圆上,Pu 、Pd 和椭圆的距离相等,点亮Pu 或Pd 均可,约定取Pd ,如图3-13所示。

2、上半部分Ⅰ的递推公式

图3-13中,为了能够继续判断椭圆上的每个点,需要给出中点偏差判别式d1的递推公式和初始值。

2

222221)5.0()1()5.0,1(),(b a y a x b y x F y x F d i i i i M M --++=-+==

3、中点偏差判别式的递推公式

现在如果考虑主位移方向再走一步,应该选取哪个中点代入中点偏差判别式以决定应该点亮的像素,如图3-14所示,分两种情况讨论。

⑴当d1<0时,下一步的中点坐标为:

M(x i+2,y i-0.5)。所以下一步中点偏差判别式为:

⑵当d1≥0时,下一步的中点坐标为:M(x i+2,y i-

1.5)。所以下一步中点偏差判别式为:

4、中点偏差判别式d1的初值

上半部分椭圆的起点为A (0,b ),因此,第一个中点是(1,b -0.5),对应的d1的初值为:

void MidPointEllipse(int a,int b,int value)

{

int x=0;

int y=b;

double d=b*b-a*a*(b-0.25);

cout<<"首点的坐标为:("<

int n=2;

while(a*a*(y-0.5)>b*b*(x+1)) //区域1

{

if(d<0)

d=d+b*b*(2*x+3);

else

{

d=d+b*b*(2*x+3)+a*a*(-2*y+2);

y--;

} x=x++; 2222210(1,0.5)(0.5)d F b b a b a b =-=+--

cout<<"区域1第"<

}

d=b*b*(x+0.5)*(x+0.5)+a*a*(y-1)*(y-1)-a*a*b*b;

n=2;

while(y>=0) //区域2

{

if(d<0)

{

d=d+b*b*(2*x+2)+a*a*(-2*y+3);

x++;

}

else

d=d+a*a*(-2*y+3);

y--;

cout<<"区域2第"<

}

}

相关文档
最新文档