如同光栅画线算法,每步都以间隔单位取样并确定离指定圆最近的像素位置。为了减少计算量,可以将圆八分,根据Bresenham画线算法。我们首先给出点位置函数:
即可得知:(1),
位于圆边界内;(2)
,
位于圆边界上;(3)
,
位于圆边界外。
第一象限中,假设在绘制了像素点,下一步需要确定绘制的位置是
,还是
更接近圆。
则决策参数的圆函数方程在这两个像素的中点求值得到,
或
其中是
还是
,取决于
的符号。
算法过程:
1.输入圆半径和圆心
,并得到圆周上的第一个点:
2.计算决策参数的初始值:
3.在每个位置,从
开始,完成下列测试:假如
,圆心在
的圆的下一个点为
,并且
否则,圆的下一个点是,并且
其中且
。
4.确定在其他七个八分圆中的对称点。
5.将每个计算出的像素位置移动到圆心在
的圆路径上,并画坐标值:
6.重复步骤3到步骤5,直至。
1 class ScreenPt { 2 private: 3 GLint x, y; 4 5 public: 6 ScreenPt() { 7 x = y = 0; 8 } 9 void setCoords(GLint xCoordValue, GLint yCoordValue) { 10 x = xCoordValue; 11 y = yCoordValue; 12 } 13 GLint getx() const { 14 return x; 15 } 16 GLint gety() const { 17 return y; 18 } 19 void incrementx() { 20 ++x; 21 } 22 void decrementy() { 23 --y; 24 } 25 }; 26 27 void setPixel(GLint xCoord, GLint yCoord) 28 { 29 glBegin(GL_POINTS); 30 glVertex2i(xCoord, yCoord); 31 glEnd(); 32 } 33 34 void circlePlotPoints(GLint xc, GLint yc, ScreenPt circPt) 35 { 36 setPixel(xc + circPt.getx(), yc + circPt.gety()); 37 setPixel(xc - circPt.getx(), yc + circPt.gety()); 38 setPixel(xc + circPt.getx(), yc - circPt.gety()); 39 setPixel(xc - circPt.getx(), yc - circPt.gety()); 40 setPixel(xc + circPt.gety(), yc + circPt.getx()); 41 setPixel(xc - circPt.gety(), yc + circPt.getx()); 42 setPixel(xc + circPt.gety(), yc - circPt.getx()); 43 setPixel(xc - circPt.gety(), yc - circPt.getx()); 44 } 45 46 void circleMidpoint(GLint xc, GLint yc, GLint radius) 47 { 48 ScreenPt circPt; 49 50 GLint p = 1 - radius; //Initial value for midpoint parameter 51 52 circPt.setCoords(0, radius); //Set coords for top point of circle. 53 // Plot the initial point in each circle quadrant 54 circlePlotPoints(xc, yc, circPt); 55 // Calculate next point and polt in each octant 56 while (circPt.getx() < circPt.gety()) { 57 circPt.incrementx(); 58 if (p < 0) { 59 p += 2 * circPt.getx() + 1; 60 } 61 else { 62 circPt.decrementy(); 63 p += 2 * (circPt.getx() - circPt.gety()) + 1; 64 } 65 circlePlotPoints(xc, yc, circPt); 66 } 67 }