椭圆的中点生成算法

时间:2021-09-29 04:23:30

椭圆对称性质原理:

1)圆是满足x轴对称的,这样只需要计算原来的1/2点的位置;

2)圆是满足y轴对称的,这样只需要计算原来的1/2点的位置;

通过上面分析可以得到实际上我们计算椭圆生成时候,只需要计算1/4个椭圆就可以实现对于所有点的生成了。

例如:分析出来目标点(x,y)必然存在(x,-y),(-x,y),(-x,-y)的另外3个点。关于中心画圆算法,通过计算x = 0 y = 0 1/4椭圆的范围,然后通过对称原理得到其他3/4个点的信息。(R2表示椭圆厂轴的半径)

椭圆中点生成算法是将椭圆在第一象限中分为两个部分:

1)对于斜率绝对值小于1的区域内在x方向取单位量;

2)对于斜率绝对值大于1的区域内在y方向取单位量;

斜率可以通过椭圆的标准方程中获得为

K = - (ry*ry)*x/(rx*rx)*y;

这里中点椭圆生成算法同样和Bresenham算法有很多相似之处,同样有一个决定下一个位置的关键值P来做权衡处理。在中点画椭圆算法中,通过平移的方法将假设圆心在坐标原点,然后计算,最后再平移到真实原心位置。

 

中点椭圆算法内容:

1 输入椭圆的两个半径r1r2,并且输入椭圆的圆心。设置初始点(x0,y0)的位置为(0,r2);

2 计算区域1*决策参数的初始值

p = ry*ry - rx*rx*ry + 1/4*(rx*rx);

3 在区域1中的每个Xn为止,从n = 0 开始,直到|K|(斜率)小于-1时后结束;

1)如果p < 0 ,绘制下一个点(x+1,y),并且计算

p = p + r2*r2*(3+2*x);

2)如果P >=0 ,绘制下一个点(x+1,y-1),并且计算

p = p + r2*r2*(3+2*point.x) - 2*r1*r1*(y-1)

4 设置新的参数初始值;

p = ry*ry(X0+1/2)*(X0+1/2) + rx*rx*(Y0-1) - rx*rx*ry*ry;

5 在区域2中的每个Yn为止,从n = 0开始,直到y = 0时结束。

1)如果P>0的情况下,下一个目标点为(x,y-1),并且计算

p = p - 2rx*rx*(Yn+1) + rx*rx;

2)如果p<=0的情况下,下一个目标点为(x+1,y-1),并且计算

p = p - 2rx*rx*Y(n+1) + 2ry*ry*(Xn+1)+rx*rx;

6 更具对称性原理计算其他3个象限的坐标。

7 急速拿出中心位置在(x1,y1)的位置

    x = x + x1;

    y = y + y1;

  

实例代码:

#include <math.h>

//

// Function : Drawellipse()

// Draw the ellipse

//

BOOL CCEDraw::Drawellipse( LONG lCenterX, LONG lCenterY, unsigned long ulRadiusX, unsigned long ulRadiusY)

{

     Point point;

     Point temp;

     int p ; //评价参数

     //使用x递增的最小y值,通过斜率为,计算得到

     long minYofDeltaX = long( ulRadiusY*ulRadiusY/sqrt(ulRadiusY*ulRadiusY+ulRadiusX*ulRadiusX) );

 

     point.x = 0;

     point.y = ulRadiusY; 

 

     // 计算区域*决策参数的初始值

     p =  ulRadiusY*ulRadiusY - ulRadiusX*ulRadiusX*ulRadiusY + 1/4*(ulRadiusX*ulRadiusX);

 

     while( minYofDeltaX < point.y)

     {

         if( p < 0)

         {

              ++point.x ;

              p = p + ulRadiusY*ulRadiusY*(3+2*point.x);

         }

         else

         {

              ++point.x;

              --point.y;

              p = p + ulRadiusY*ulRadiusY*(3+2*point.x) - 2*ulRadiusX*ulRadiusX*(point.y-1) ;

         }

         DrawPixel( lCenterX+point.x, lCenterY+point.y, 0 );

         DrawPixel( lCenterX+point.x, lCenterY-point.y, 0 );

         DrawPixel( lCenterX-point.x, lCenterY+point.y, 0 );

         DrawPixel( lCenterX-point.x, lCenterY-point.y, 0 );

     }

 

     p = ulRadiusY*ulRadiusY*(0+1/2)*(0+1/2) + ulRadiusX*ulRadiusX*(ulRadiusY-1)*(ulRadiusY-1) - ulRadiusX*ulRadiusX*ulRadiusY*ulRadiusY;

 

     while(point.y > 0)

     {

         if(p > 0)

         {

             --point.y;

             p = p - 2*ulRadiusX*ulRadiusX*point.y - 2*ulRadiusX*ulRadiusX + ulRadiusX*ulRadiusX;

         }

         else

         {

              --point.y;

              ++point.x;

              p = p - 2*ulRadiusX*ulRadiusX*point.y - 2*ulRadiusX*ulRadiusX + ulRadiusX*ulRadiusX + 2*ulRadiusY*ulRadiusY*point.x + 2*ulRadiusY*ulRadiusY ;

         }

         DrawPixel(lCenterX+point.x, lCenterY+point.y, 0);

         DrawPixel(lCenterX+point.x, lCenterY-point.y, 0);

         DrawPixel(lCenterX-point.x, lCenterY+point.y, 0);

         DrawPixel(lCenterX-point.x, lCenterY-point.y, 0);

     }

     return TRUE;

}