圆的特征
圆被定义为给定中心位置(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()