橢圓與圓不同,不能八分只能四分。中點橢圓算法將分成兩部分應用於第一象限。在斜率絕對值小於1的區域內在x方向取單位步長,在斜率絕對值大於1的區域內在y方向取單位步長。
取,可定義橢圓函數為
即決策參數。
從開始,在
方向取單位步長直到區域1和區域2的界限處,然后轉還為
方向的單位步長,再覆蓋第一象限中剩余的曲線段。不過,每一步都要檢測曲線斜率值。
斜率方程:
在區域1和區域2的交界區,,且
因此,移除區域1的條件是
和中點畫圓算法一樣,通過該中點對決策函數求值來確定沿橢圓軌跡的下一個位置:
在下一個取樣位置,區域1的決策參數可求值為
或
其中,根據
的符號取值為
或
。
如果,遞增增量為
;如果
,遞增增量為
。
在區域2中,在負方向以單位步長取樣。
在下一個位置對橢圓函數求值:
或
其中,的設置根據
的符號可取值為
或
。
算法過程:
1.輸入、
和橢圓中心
,並得到橢圓上的第一個點:
2.計算區域1中決策參數的初始值:
3.在區域1中的每個位置,從
開始,假如
,沿中心在
的橢圓的下一個點為
,並且
否則,沿橢圓的下一個點為,並且
其中
並且直到。
4.使用區域1中計算的最后點來計算區域2中參數的初始值:
5.在區域2的每個位置處,從
開始,假如
,沿中心為
的橢圓的下一個點為
,並且
否則,沿橢圓的下一個點,並且
使用與區域1中相同的和
增量進行計算,直到
。
6.確定其他三個象限中的對稱點。
7.將計算出的每個像素位置移動到中心在
的橢圓軌跡上,並按坐標值繪制點:
1 inline int Round(const float a) { return static_cast<int>(a + 0.5); } 2 3 void setPixel(GLint xCoord, GLint yCoord) 4 { 5 glBegin(GL_POINTS); 6 glVertex2i(xCoord, yCoord); 7 glEnd(); 8 } 9 10 void ellipsePlotPoints(int xCenter, int yCenter, int x, int y) 11 { 12 setPixel(xCenter + x, yCenter + y); 13 setPixel(xCenter - x, yCenter + y); 14 setPixel(xCenter + x, yCenter - y); 15 setPixel(xCenter - x, yCenter - y); 16 } 17 18 void ellipseMidpoint(int xCenter, int yCenter, int Rx, int Ry) 19 { 20 int Rx2 = Rx * Rx; 21 int Ry2 = Ry * Ry; 22 int twoRx2 = 2 * Rx2; 23 int twoRy2 = 2 * Ry2; 24 int p; 25 int x = 0; 26 int y = Ry; 27 int px = 0; 28 int py = twoRx2 * y; 29 // Plot the initial point in each quadrant 30 ellipsePlotPoints(xCenter, yCenter, x, y); 31 /* Region 1 */ 32 p = Round(Ry2 - (Rx2 * Ry) + (0.25 * Rx2)); 33 while (px < py) { 34 x++; 35 px += twoRy2; 36 if (p < 0) { 37 p += Ry2 + px; 38 } 39 else { 40 y--; 41 py -= twoRx2; 42 p += Ry2 + px - py; 43 } 44 ellipsePlotPoints(xCenter, yCenter, x, y); 45 } 46 /* Region 2 */ 47 p = Round(Ry2 * (x + 0.5) * (x + 0.5) + Rx2 * (y - 1) * (y - 1) - Rx2 * Ry2); 48 while (y > 0) { 49 y--; 50 py -= twoRx2; 51 if (p > 0) { 52 p += Rx2 - py; 53 } 54 else { 55 x++; 56 px += twoRx2; 57 p += Rx2 - py + px; 58 } 59 ellipsePlotPoints(xCenter, yCenter, x, y); 60 } 61 }