Algorithm series eleven: circle generation algorithm

 

Google

        In plane analytic geometry, the equation of a circle can be described as (x – x 0 ) 2 + (y – y 0 ) 2 = R 2 , where (x 0 , y 0 ) are the coordinates of the center of the circle, and R is the radius of the circle, especially Yes , when (x 0 , y 0 ) is the coordinate center point, the circle equation can be simplified to x 2 + y 2 = R 2 . In computer graphics, circles, like straight lines, also have the problem of displaying or outputting on dot-matrix output devices, so a set of raster scan conversion algorithms are also needed. For simplification, we first consider the generation of a circle whose center is at the origin. For a circle whose center is not the origin, the circle at the corresponding position can be obtained by translation transformation of coordinates.

        Before scanning conversion, you need to understand the characteristics of a circle, that is, the eighth pair of circles. As shown in Figure 1:

Figure (1) Eighth symmetry of a circle

The circle with the center at the origin has four symmetry axes x = 0, y = 0, x = y and x = -y. If a point P(x, y) on the arc is known, the seven about the four symmetry axes can be obtained. Symmetry points: (x, -y), (-x, y), (-x, -y), (y, x), (y, -x), (-y, x), (-y, -x), this property is called eighth symmetry. Therefore, as long as one-eighth of the arc can be drawn, the whole circle can be obtained using the principle of symmetry.

There are several easier ways to get the scan conversion of the circle, first introduce the rectangular coordinate method. Given the circle equation: x 2 + y 2 = R 2 , if x is taken as the independent variable and y is solved, we get:

 

y =

 

When generating a circle, first scan and convert a quarter of the circle, let the independent variable x increase from 0 to R in unit steps, and solve y at each step, and then call the point drawing function to draw the circle point by point. But doing so, due to the power and square root operations, and both are floating-point operations, the algorithm efficiency is not high. And when x is close to the value of R (the center of the circle is at the origin), near the point (R, 0) on the circumference, because the slope of the circle tends to infinity, the floating-point number needs to be rounded up, making the circle larger gap. Next, let’s introduce the polar coordinate method. Assuming that the angle between a point P(x,y) and the x-axis on the arc in the rectangular coordinate system is θ, the polar coordinate equation of the circle is:

 

x = Rcosθ

y = Rsinθ

 

The generated circle uses the eighth symmetry of the circle, so that the value range of the independent variable θ is (0, 45°) to draw a complete circle. This method involves calculation of trigonometric functions and multiplication, which requires a large amount of calculation. Rectangular coordinate method and polar coordinate method are both inefficient algorithms, so they only exist as theoretical methods. These two methods are basically not used to generate circles in computer graphics. The following introduces several practical circle generation algorithms in computer graphics.

1. Midpoint circle method

        The first is the method of drawing a circle at the midpoint. Consider the center of the circle at the origin and the one-eighth arc of the circle with radius R in the first quadrant, which is determined clockwise from point (0, R) to point (R/, R/) This arc. Suppose a point P I (X I , Y I ) has is a point on the arc closest to the actual arc, then the next point Pi may be on one of both P1 or P2 just to the right of the bottom right, as Figure (2) shows:

Figure (2) Example of the dot-dash line method

Construct the discriminant function:

 

F(x, y)= x2 + y2 – R2

 

When F(x, y) = 0, it means the point is on the circle. When F(x, y)> 0, it means the point is outside the circle. When F(x, y)< 0, it means the point is inside the circle. If M is the midpoint of P 1 and P 2 , then the coordinates of M are (x i + 1, y i – 0.5). When F(x i + 1, y i – 0.5) <0, point M is in the circle Inside, it means that P 1 is closer to the actual arc, and P 1 should be taken as the next point of the circle. Analysis Similarly, when F. (X I +. 1, Y I - when 0.5)> 0, P 2 closer to the actual arc should be taken P 2 as the next point. When F(x i + 1, y i – 0.5) = 0, both P 1 and P 2 can be used as the next point of the circle, and the algorithm agrees to take P 2 as the next point.

现在将M点坐标(xi + 1, yi – 0.5)带入判别函数F(x, y),得到判别式d:

 

d = F(xi + 1, yi – 0.5)= (xi + 1)2 + (yi – 0.5)2 – R2

 

若d < 0,则取P1为下一个点,此时P1的下一个点的判别式为:

 

d’ = F(xi + 2, yi – 0.5)= (xi + 2)2 + (yi – 0.5)2 – R2

 

展开后将d带入可得到判别式的递推关系:

 

d’ = d + 2xi + 3

 

若d > 0,则取P2为下一个点,此时P2的下一个点的判别式为:

 

d’ = F(xi + 2, yi – 1.5)= (xi + 2)2 + (yi – 1.5)2 – R2

 

展开后将d带入可得到判别式的递推关系:

 

d’ = d + 2(xi - yi) + 5

 

特别的,在第一个象限的第一个点(0, R)时,可以推倒出判别式d的初始值d0

 

d0 = F(1, R – 0.5) = 1 – (R – 0.5)2 – R2 = 1.25 - R

 

根据上面的分析,可以写出中点画圆法的算法。考虑到圆心不在原点的情况,需要对计算出来的坐标进行了平移,下面就是通用的中点画圆法的源代码:

26 void MP_Circle(int xc , int yc , int r)

27 {

28     int x, y;

29     double d;

30 

31     x = 0;

32     y = r;

33     d = 1.25 - r;

34     CirclePlot(xc , yc , x , y);

35     while(x < y)

36     {

37         if(d < 0)

38         {

39             d = d + 2 * x + 3;

40         }

41         else

42         {

43             d = d + 2 * ( x - y ) + 5;

44             y--;

45         }

46         x++;

47         CirclePlot(xc , yc , x , y);

48     }

49 }

 参数xc和yc是圆心坐标,r是半径,CirclePlot()函数是参照圆的八分对称性完成八个点的位置计算的辅助函数。

2  改进的中点画圆法-Bresenham算法

        中点画圆法中,计算判别式d使用了浮点运算,影响了圆的生成效率。如果能将判别式规约到整数运算,则可以简化计算,提高效率。于是人们针对中点画圆法进行了多种改进,其中一种方式是将d的初始值由1.25 – R改成1 – R,考虑到圆的半径R总是大于2,因此这个修改不会响d的初始值的符号,同时可以避免浮点运算。还有一种方法是将d的计算放大两倍,同时将初始值改成3 – 2R,这样避免了浮点运算,乘二运算也可以用移位快速代替,采用3 – 2R为初始值的改进算法,又称为Bresenham算法:

52 void Bresenham_Circle(int xc , int yc , int r)

53 {

54     int x, y, d;

55 

56     x = 0;

57     y = r;

58     d = 3 - 2 * r;

59     CirclePlot(xc , yc , x , y);

60     while(x < y)

61     {

62         if(d < 0)

63         {

64             d = d + 4 * x + 6;

65         }

66         else

67         {

68             d = d + 4 * ( x - y ) + 10;

69             y--;

70         }

71         x++;

72         CirclePlot(xc , yc , x , y);

73     }

74 }

3、  正负判定画圆法

        除了中点画圆算法,还有一种画圆算法也是利用当前点产生的圆函数进行符号判别,利用负反馈调整以决定下一个点的产生来直接生成圆弧,就是正负法,下面就介绍一下正负法的算法实现。

        正负法根据圆函数:F(x, y)= x2 + y2 – R2的值,将平面区域分成圆内和圆外,如图(3)所示:

图(3)正负法判定示意图

假设圆弧的生成方向是从A到B方向,当某个点Pi被确定以后,Pi的下一个点Pi+1的取值就根据F(xi, yi)的值进行判定,判定的原则是:

 

1、当F(xi, yi)≤ 0时:取xi+1 = xi+1,yi+1 = yi。即向右走一步,从圆内走向圆外。对应图(3-a)中的从Pi到Pi+1

2、当F(xi, yi)> 0时:取xi+1 = xi,yi+1 = yi - 1。即向下走一步,从圆外走向圆内。对应图(3-b)中的从Pi到Pi+1

 

由于下一个点的取向到底是向圆内走还是向圆外走取决于F(xi, yi)的正负,因此称为正负法。对于判别式F(xi, yi)的递推公式,也要分两种情况分别推算:

 

1、当F(xi, yi)≤ 0时,Pi的下一个点Pi+1取xi+1 = xi+1,yi+1 = yi,判别式F(xi+1, yi+1)的推算过程是:

F(xi+1, yi+1)= F(xi+1,yi) = (xi+1)2+yi2-R2 = (xi2+yi2-R2)+2xi+1 = F(xi,yi)+2xi+1

 

2、当F(xi, yi)> 0时,Pi的下一个点Pi+1取xi+1 = xi,yi+1 = yi - 1,判别式F(xi+1, yi+1)的推算过程是:

F(xi+1, yi+1)= F(xi,yi-1) = xi2+(yi-1)2 - R2 = (xi2+yi2-R2) - 2yi + 1 = F(xi,yi) - 2yi+1

 

设画圆的初始点是(0,R),判定式的初始值是0,正负法生成圆的算法如下:

105 void Pnar_Circle(int xc, int yc, int r)

106 {

107     int x, y, f;

108 

109     x = 0;

110     y = r;

111     f = 0;

112     while(x <= y)

113     {

114         CirclePlot(xc, yc, x, y);

115         if(f <= 0)

116         {

117             f = f + 2 * x + 1;

118             x++;

119         }

120         else

121         {

122             f = f - 2 * y + 1;

123             y--;

124         }

125     }

126 }

        改进的中点划线算法和正负法虽然都避免了浮点运算,并且计算判别式时用到的乘法都是乘2运算,可以用移位代替,但是实际效率缺有很大差别。因为正负法并不是严格按照x方向步进的,因此就会出现在某个点的下一个点在两个位置上重复画点的问题,增加了不必要的计算。此外,从生成圆的质量看,中点画圆法和改进的中点画圆法都比正负法效果好。

4、  快速画圆法

        除了中点画圆法和正负法,本文再介绍一种圆的光栅扫描算法,就是快速画圆法。快速画圆法的生成效果和中点画圆法差不多,但是判别式的计算只用了加减法,没有用任何乘法,因此被成为快速画圆法。我找不到快速画圆法的理论依据,只是把算法的实现写出来,供有兴趣的读者参考。以下就是快速画圆法的实现算法:

128 void Fast_Circle(int xc , int yc , int r)

129 {

130     int x, y, d;

131 

132     x = 0;

133     y = r;

134     d = -r / 2;

135     CirclePlot(xc , yc , x , y);

136     if(r % 2 == 0)

137     {

138         while(x < y)

139         {

140             x++;

141             if(d < 0)

142                 d += x;

143             else

144             {

145                 y--;

146                 d += x - y;

147             }

148 

149             CirclePlot(xc , yc , x , y);

150         }

151     }

152     else

153     {

154         while(x < y)

155         {

156             x++;

157             if(d < 0)

158               d += x + 1;

159             else

160             {

161               y--;

162               d += x - y + 1;

163             }

164 

165             CirclePlot(xc , yc , x , y);

166         }

167     }

168 }

        There are many round raster scan conversion algorithms. The ones introduced in this article are simple and easy to understand. In addition to the several methods introduced in this article, there are also many round raster conversion algorithms, such as polygon approximation algorithms. Interested Readers can refer to computer graphics to study the realization of the algorithm.

 

 

 

 

 

Reference materials:

 

[1] Computational Geometry: Algorithm Design and Analysis Zhou Peide, Tsinghua University Press, 2005

[2] Computational Geometry: Algorithms and Applications De Berger (translated by Deng Junhui) Tsinghua University Press, 2005

[3] Computer Graphics Sun Jiaguang, Yang Changgui, Tsinghua University Press, 1995

 

 

 

Guess you like

Origin blog.csdn.net/orbit/article/details/7253285