椭圆对称性质原理:
(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 输入椭圆的两个半径r1和r2,并且输入椭圆的圆心。设置初始点(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;
}