光栅图形学(二):圆弧的扫描转换算法

圆的特征


  圆被定义为给定中心位置(xp,yp)的距离为 r 的点集。圆心位于原点的圆有4条对称轴。

  • x=0
  • x=y
  • x=-y
  • y=0

  若已知圆弧上一点(x,y),可以得到其关于4条对称轴的其他7个点,这种性质被称为八对称性

  因此只要扫描转换1/8圆弧,就可以用八对称性求出整个圆弧的像素集。

 

中点画圆法


 

  构造函数 F(x,y) = x2 + y2 - R2,如果点在圆内,F<0;否则,F > 0。

  对于初始点(xp,yp),需要考虑的是中点 M(xp+1,yp-0.5),即 F(M)=(xp+1)2+(yp-0.5)2 - R2。(给定点 [0, r],则 d=1.25-r)

  (1)若 d<0, 即中点在圆内,目标点在在上半格,而且下一个判别式 d1=F(xp+2, yp-0.5)= d+2xp+3。

  (2)若 d>0, 即中点在圆外,目标点在下半格,而且下一个判别式 d2 = F(xp+2, yp-1.5)= d+2(xp-yp)+5。

 1 // 伪代码
 2 void MidPointCircle(int r) {
 3     int x, y;
 4     float d;
 5     x = 0; y = r;
 6     d = 1.25 - r;
 7     draw(x, y);
 8     while (x <= y) {
 9         if (d < 0)
10             d += 2*x+3;
11         else
12             {d+=2*(x-y)+5; y--;}
13         x++;
14         draw(x, y);
15     }
16 }

效果如下:

 


完整代码


 

 1 import numpy as np 
 2 import matplotlib.pyplot as plt 
 3 from matplotlib.ticker import MultipleLocator
 4 
 5 def MidPointCircle(r):
 6     x = 0; y = r
 7     d = 1.25 - r
 8     a = [x]; b = [y]
 9     while x <= y:
10         if d < 0:
11             d += 2*x+3
12         else:
13             d += 2*(x-y)+5
14             y -= 1
15         x += 1
16         a.append(x)
17         b.append(y)
18     # 利用对称性把其余七个八分圆补全
19     for i in range(len(a)):
20         a.append(b[i])
21         b.append(a[i])
22     for i in range(len(a)):
23         a.append(a[i])
24         b.append(-b[i])
25     for i in range(len(a)):
26         a.append(-a[i])
27         b.append(b[i])
28     plt.scatter(a, b, color='r')
29 
30 
31 # 画圆
32 ax = plt.figure().add_subplot(111)
33 ax.set_xlim(-25, 25)
34 ax.set_ylim(-25, 25)
35 ax.xaxis.grid(True)
36 ax.yaxis.grid(True)
37 ax.xaxis.set_major_locator(MultipleLocator(1))
38 ax.yaxis.set_major_locator(MultipleLocator(1))
39 x = y = np.arange(-25, 25, 0.1)
40 x, y = np.meshgrid(x, y)
41 plt.contour(x, y, x**2+y**2, [400])
42 
43 MidPointCircle(20)
44 
45 plt.show()

 

posted @ 2017-03-19 22:37 mangoyuan 阅读(...) 评论(...) 编辑 收藏