圆的特性
(x – xc)*(x – xc) +(y – yc)*(y – yc) = r*r
圆的对称性
已知一个圆心在原点的圆上一点为(x, y),根据对称性,可得另外七个8分圆上的对应点(y, x),(y, –x),(x, –y),(–x, –y),(–y, –x),(–y, x),(–x, y)。中点画圆法
根据圆的对称性,只需讨论1/8圆弧(取第一象限内以y=x为界的上半部分),即确定最佳逼近于该圆弧的像素点集。
2)对于圆外的点,F (x, y) > 0;
3)对于圆内的点,F (x, y) < 0。
1)若F (M)>0,则M在圆外,P2离圆弧更近,取P2为下一像素
2)若F (M)<0,则M在圆内,P1离圆弧更近,取P1为下一像素
3)若F (M)=0,在P1和P2中任取一个即可,约定取P2
d = F(M)= F (xp+1, yp–0.5)
=(xp+1)*(xp+1) + (yp–0.5)*(yp–0.5) – r*r (1式)
d1 = F (xp+2, yp–0.5)
= (xp+2)*(xp+2) + (yp–0.5)*(xp+2) – r*r
= d + 2xp + 3
所以沿正右方向,d 的增量为2xp+3
若d≥0,取P2为下一像素,则再下一个像素的判别式为:
d2 = F(xp+2, yp–1.5)
= (xp+2)*(xp+2) + (yp–1.5)*(yp–1.5) – r*r
= d + (2xp +3)+(–2yp +2)
所以沿右下方向,d 的增量为2(xp–yp)+ 5
d的初始值:从圆的正上方开始,第一个像素是(0, r),代入到1式,则判别式 d 的初始值为:
d0 = F (1, r – 0.5)= 1+(r – 0.5)*(r – 0.5) – r*r = 1.25 – r
中点画圆法的算法步骤:
1. 输入圆的半径r。
2. 计算初始值d=1.25-r,x=0,y=r,画点(x, y)。
3. 若x<y,则执行下列各步,否则算法结束。
4. 求下一个点:若d<0,则先将d更新为d+2x+3,再将(x, y)更新为(x+1, y);否则先将d更新为d+2(x-y)+5,再将(x, y)更新为(x+1, y-1)。
5. 画点(x, y),返回3。
中点画圆法的改进:
1)若用e = d – 0.25代替d,则d0 = 1.25 – r 对应于e0 = 1 – r。
2)判别式d<0对应于e < –0.25。算法中其他与d有关的式子可把d直接换成e。这样,就可以写出完全用整数实现的中点画圆算法。
改进后的中点画圆法的算法步骤:
1. 输入圆的半径r。
2. 计算初始值d=1-r,x=0,y=r,画点(x, y)。
3. 若x<y,则执行下列各步,否则算法结束。
4. 求下一个点:若d<0,则先将d更新为d+2x+3,再将(x, y)更新为(x+1, y);否则先将d更新为d+2(x-y)+5,再将(x, y)更新为(x+1, y-1)。
5. 画点(x, y),返回3。
代码:
void wholeC(int xc, int yc, int x, int y, int color) {
putpixel(xc + x, yc + y, color); putpixel(xc + x, yc - y, color);
putpixel(xc - x, yc + y, color); putpixel(xc - x, yc - y, color);
putpixel(xc + y, yc + x, color); putpixel(xc + y, yc - x, color);
putpixel(xc - y, yc + x, color); putpixel(xc - y, yc - x, color);
}
void Mcircle(int xc, int yc, int r, int color) {
int x = 0, y = r, d = 1 - r;
wholeC(xc, yc, x, y, color);
while (x <= y) {
if (d < 0) {
d += 2 * x + 3;
x++;
}
else {
d += 2 * (x - y) + 5;
x++;
y--;
}
wholeC(xc, yc, x, y, color);
}
}