Bresenham 布雷森汉姆算法画圆的原理与编程实现教程
注意:Bresenham的圆算法只是中点画圆算法的优化版本。区别在于Bresenham的算法只使用整数算术,而中点画圆法仍需要浮点数。注意:不要因为我提到了中点画圆法你就去先看完计算机图形学中点画圆法教程再看Bresenham算法,这样是浪费时间。中点画圆法和Bresenham画圆法只是思想一样,但是思路并没有很大关联。所以直接看Bresenham算法就可以。
看下面这个图,这就是一个像素一个像素的画出来的。我们平常的圆也是一个像素一个像素的画出来的,你可以试试在“画图”这个软件里面画一个圆然后放大很多倍,你会发现就是一些像素堆积起来的。
我们看出来圆它是一个上下左右都对称,而且也是中心对称的。所以我们只用画好八分之一圆弧就可以,其他地方通过对称复制过去就好。
看下面这幅图,绿线夹住的那部分就是八分之一圆弧。注意我们是逆时针画圆的(即从水平那个地方即(r,0)开始画因为一开始我们只知道水平位置的像素点该放哪其他地方我们都不知道)。Bresenham 算法画完一个点(x,y)后注意x,y都是整数。他们代表的是x,y方向上的第几个像素。
,它下一步有两个选择(x,y+1),(x-1,y+1)。也就是说y一定增加,但是x要么保持不变要么减一(你也可以让x一定增加y要么不变要么加一,其实差不多的)。当程序画到粉红色那个像素点的时候,程序选择下一步要绘制的点为(x-1,y+1)。当程序画到黄色的那个像素点时候,程序选择下一步要绘制的点为(x,y+1)。
我们看看粉色的那个点的下一步是如何抉择的。
Bresenham是根据待选的两个点哪个离圆弧近就下一步选哪个。那它是怎么判断的呢?这两个点一定有一个在圆弧内一个在圆弧外。到底选哪个?Bresenham的方法就是直接计算两个点离圆弧之间的距离,然后判断哪个更近就选哪个。如下图所示:
那么怎么用数学量化他们离圆弧的距离呢?
答:前面我们提到了,当前粉红色这个点坐标为 ( x k , y k ) (x_k,y_k) (xk,yk),下一步它有两种可能的走法绿色 ( x k − 1 , y k + 1 ) (x_k-1,y_k+1) (xk−1,yk+1),紫色坐标为 ( x k , y k + 1 ) (x_k,y_k+1) (xk,yk+1)
d 1 = ( x k − 1 ) 2 + ( y k + 1 ) 2 − r 2 d1 = (x_k-1)^2+(y_k+1)^2-r^2 d1=(xk−1)2+(yk+1)2−r2
d 2 = ( x k ) 2 + ( y k + 1 ) 2 − r 2 d2 = (x_k)^2+(y_k+1)^2-r^2 d2=(xk)2+(yk+1)2−r2
注意: d 1 = ( x k − 1 ) 2 + ( y k + 1 ) 2 − r 2 d1 = (x_k-1)^2+(y_k+1)^2-r^2 d1=(xk−1)2+(yk+1)2−r2小于0的,因为绿色那个点一定在圆内侧。 d 2 = ( x k ) 2 + ( y k + 1 ) 2 − r 2 d2 = (x_k)^2+(y_k+1)^2-r^2 d2=(xk)2+(yk+1)2−r2一定是大于等于0的,因为紫色那个点一定在圆外侧。
所以我们只用比较 P k = d 1 + d 2 P_k = d1+d2 Pk=d1+d2到底是大于0还是小于0就能确定选哪个点了。大于0选绿色 ( x k − 1 , y k + 1 ) (x_k-1,y_k+1) (xk−1,yk+1)那个点(因为紫色那个点偏离圆弧程度更大)。小于0则选紫色 ( x k , y k + 1 ) (x_k,y_k+1) (xk,yk+1)那个点。
好了Bresenham画圆法我讲完了。
你或许会问,不对啊。我在网上看到的关于Bresenham画圆法的博客还有其他公式。确实我还有一个小细节没讲。你用上面的方法是已经可以画圆了,剩下的就是一些提高计算效率的小细节。
P k = d 1 + d 2 = ( x k − 1 ) 2 + ( y k + 1 ) 2 − r 2 + ( x k ) 2 + ( y k + 1 ) 2 − r 2 P_k = d1+d2= (x_k-1)^2+(y_k+1)^2-r^2+(x_k)^2+(y_k+1)^2-r^2 Pk=d1+d2=(x