基于Bresenham算法画圆

bresenham算法画圆思想与上篇 bresenham算法画线段 思想是一致的

画圆x^2+y^2=R^2

 

 

将他分为8个部分,如上图

 

1.

只要画出1中1/8圆的圆周,剩下的就可以通过对称关系画出这个圆

X变化从0->R

那为什么不采用从-R->R呢,

Y=+-sqrt(R^2-x^2);

dy/dx=-x/(sqrt(R^2-x^2)) =-x/y

所以采用从-R到R,每次横坐标增1,计算量大,而且在(x=+-R,y=0)处,x的很小变化就引起了y的很大变化。

 所以不是采用x从-R--->R变化。而是采用1/8画圆法。

2.

在2这1/8圆周上,x值单调增加,y值单调递减,且fabs(dx/dy)=fabs(-x/y)<=1;所以圆周上相应点的y值变化小于1.

假设当前点为(x1,y1)这下个点为(x1+1,y1)或(x1+1,y1-1)

d1=(x1+1)^2+y1^2-R^2;

d2=R^2-(x1+1)^2-(y1-1)^2;

p=d1-d2 若p>0 选点(x1+1,y1-1)否则选点(x1+1,y1)

p=2(x1+1)^2+2y1^2-2y1-2R^2+1

接下来就是求p了。

P1=3-2R(坐标为x=0,y=R)

然后仿照线段算法得出p(i+1)=p(i)+4(Xi-Yi)+10(pi>0)否则P(i+1)=p(i)+4Xi+6

这样就可以成功画出1/8圆弧了

3.接下来的问题,是剩下的部分怎么处理,

有两种方法:

方法一:存储器将前1/8的坐标存储起来,然后通过镜像求出其他圆弧坐标,调整顺序输出,即可得到。

方法二:分别求出对应的8个圆弧的算法式,一次画弧。

算法比较:前者算法比较简单,但是存储数据,需要较大的RAM,一旦在计算高精度,大半径的圆时,数据存储量就比较大,可能就需要扩充RAM。后者代码比较多,占用较多的程序存储空间。


然后从控制理论角度考虑:前者是先计算后执行,实时性比较差,后者运算和控制交叉进行。但不会减少总时间。

综上所述,当圆的精度低时,可以采用方法一。当圆精度高,半径大,或者对运动过程中实时性要求比较高时,采用方法二。

 在实际的实现过程中,发现按照方法二实现,圆无法画整。因为每次后面1/8圆弧都是与前面的1/8圆弧最好一个点相接的,这样累积下来,势必造成首尾无法相接,最后是采用方法一和方法二结合实现方法二的,即画一半圆,然后利用对称性实现的【即方法一的思想】。

方法一代码实现:


方法二代码是实现:



说明:上述代码实现均是基于stm32处理器,tftLCD2.8寸屏上实现的

关于p的求法如果有疑问,可以参考上篇文章基于Bresenham和DDA算法画线段


对于屏上画点,对各坐标点赋值有疑问的可以参考这篇资料看看bresenham直线算法与画圆算法 

 下面两幅图,是方法二实现的两种比较,如果采用单一的 画8个圆弧,会出现累积误差,圆无法闭合。


图1


图 2
posted @ 2013-08-15 17:32  stoneFang  阅读(291)  评论(0编辑  收藏  举报