中点椭圆算法(下)
假设已经在整数屏幕坐标中给定rx,ry和椭圆中心,在中点椭圆算法中我们仅需增量的整数运算来确定决策参数的值。增量r2y 、r2x和2r2yx和2r2xy仅需在程序的开始求值一次。中点椭圆算法可以概括为下列步骤:
中点椭园算法的步骤
1.输入rx、ry和椭圆中心(xc,yc),并得到椭圆(中心在原点)上的第一个点:
2.计算区域1中决策参数的初始值:
3.在区域1中的每个xk位置,从k=0开始,完成下列测试:假如p1k<0,沿中心在(0,0)的椭圆的下一个点为(xk+1,yk),并且
否则,沿椭圆的下一个点为(xk+1, yk-1),并且
其中
并且直到2r2yx>=2r2xy。
4.使用区域1中计算的最后点(x0,y0)来计算区域2中参数初始值:
5.在区域2每个yk位置处,从k=0开始,完成下列测试:假如p2k>0,沿中心为(0,0)的椭圆的下一个点为(xk, yk-1)并且
否则,沿椭圆的下一个点为(xk+1,yk-1)并且
使用与区域1中相同的x和y增量进行计算,直到y=0。
6.确定其他三个象限中的对称点。
7.将计算出的每个像素位置(x,y)移到中心在(xc,yc)的椭圆轨迹上,并按坐标值绘制点:
中心椭圆算法画图
给定输入椭圆参数rx=8和ry=6,我们将给出中点椭圆算法的步骤,从而确定第一象限内椭圆轨迹上的光栅像素位置。决策参数的初始值和增量则计算为
对于区域1,圆心在原点的椭圆的初始点为(x0,y0)=(0,6),决策参数的初始值为
下表列出了使用中心算法计算的后续决策参数值和椭圆轨迹的位置。
对于区域2,初始点为(x0,y0)= (7,3),初始决策参数为
第一象限中椭圆轨迹的其余位置计算为
下面的程序给出了采用中点算法来显示椭圆的例子。椭圆参数Rx , Ry , xCenter和yCenter的值输人过程ellipseMidpoint。第一象限曲线上的位置经计算并传递给过程ellipsePlotPoints。其他三个象限的椭圆位置利用对称性来获得,与这些位置对应的帧缓存中的椭圆颜色由子程序setPixel设定。
inline int round(const float a){return int (a + 0.5);} /*The following procedure accepts values for an ellipse *center position and its semimajor and semimajor axes,then *calculates ellipse positions using the midpoint algorithm. */ void ellipseMidpoint(int xCenter,int yCenter,int Rx, int Ry) { int Rx2 = Rx * Rx; int Ry2 = Ry * Ry; int twoRx2 = 2 * Rx2; int twoRy2 = 2 * Ry2; int p; int x = 0; int y = Ry; int px = 0; int py = twoRx2 * y; void ellipsePlotPoints(int, int, int, int); /*Plot the initial point in each quadrant.*/ ellipsePlotPoints(xCenter, yCenter, x, y); /*Region 1*/ p = round(Ry2 - (Rx2 * Ry) + (0.25 * Rx2)); while (px < py){ x++; px += twoRy2; if (p < 0) p += Ry2 + px; else{ y--; py -= twoRx2; p += Ry2 + px - py; } ellipsePlotPoints(xCenter , yCenter, x, y); } /*Region 2*/ p = round (Ry2 * (x + 0.5) * (x + 0.5) + Rx2 *(y - 1) * (y -1) - Rx2 * Ry2); while (y > 0){ y--; py -= twoRx2; if(p > 0) p += Rx2 - py; else { x++; px += twoRy2; p += Rx2 - py + px; } ellipsePlotPoints(xCenter, yCenter, x, y); } } void ellipsePlotPoints(int xCenter,int yCenter,int x, int y); { setPixel(xCenter + x,yCenter + y); setPixel(xCenter - x,yCenter + y); setPixel(xCenter + x,yCenter - y); setPixel(xCenter - x,yCenter - y); }