Bresenham 画圆算法原理

前言

首先简要介绍一下生成圆的方法:

  1. 直接利用圆的方程生成圆
  2. 利用圆的对称性生成圆

方法一由于会涉及到浮点运算等因素,不采取该方案。
ps. 这部分想要知道为什么可以参考 计算机图形学 圆及椭圆的扫描转换_百度文库 前面一点。
方法二的原理如下图,利用圆的对称性,我们只需要对一个八分圆进行扫描转换。
在这里插入图片描述

在这里我们不妨选择第一象限上斜率绝对值小于1的那八分圆进行扫描转换,以及假设圆心为 (0, 0) 。也就是下图。
友情提示:圆在某点的斜率是该点处切线斜率。圆心不在 (0, 0) 处的点可以通过平移得到。
在这里插入图片描述

Bresenham 画圆算法原理

如下图,在 0≤x≤y 的 1/8 圆周上,像素坐标 x 值单调增加,y 值单调减少。
设第 i 步已确定 ( x i , y i ) (x_i, y_i) xi,yi是要画圆上的像素点,看第 i+1 步像素点 ( x i + 1 , y i + 1 ) (x_{i+1}, y_{i+1}) xi+1,yi+1应如何确定。下一个像素点只能是 H ( x i + 1 , y i ) H(x_i+1, y_i) Hxi+1,yi或者 D ( x i + 1 , y i − 1 ) D(x_i+1,y_i-1) Dxi+1,yi1中的一个 。
8分圆的某段

具体选哪个就得看 d H 和 d D d_H 和 d_D dHdD 二者的比较了:

  1. d H d_H dH 更小,下一个像素点就选 H ( x i + 1 , y i ) H(x_i+1, y_i) Hxi+1,yi
  2. d D d_D dD 更小,下一个像素点就选 D ( x i + 1 , y i − 1 ) D(x_i+1,y_i-1) Dxi+1,yi1
  3. 一样大,选哪个都行。

比较方法就是做差: d H − d D d_H - d_D dHdD,然后将结果与0进行比较。

那么问题是 d H 和 d D d_H 和 d_D dHdD 二者的值是怎么求得呢?这里就涉及到一个近似:

两个近似

在这里插入图片描述

在这里插入图片描述

近似方法:
将 CH 近似为 d H d_H dH
将 DB 近似为 d D d_D dD

由大图显而易见可以知道 CH 和 DB 的值:
C H = O H − O C = ( x i + 1 ) 2 + y i 2 − R = d H CH = OH - OC = \sqrt{(x_i+1)^2 + y_i^2} - R = d_H CH=OHOC=(xi+1)2+yi2 R=dH
D H = O B − O D = R − ( x i + 1 ) 2 + ( y i − 1 ) 2 = d D DH = OB - OD = R - \sqrt{(x_i+1)^2 + (y_i-1)^2} = d_D DH=OBOD=R(xi+1)2+(yi1)2 =dD

这里由于涉及到了根号运算,因此又做了一个近似:
d H = ( x i + 1 ) 2 + y i 2 − R 2 d_H = (x_i+1)^2 + y_i^2 - R^2 dH=(xi+1)2+yi2R2
d D = R 2 − ( x i + 1 ) 2 − ( y i − 1 ) 2 d_D = R^2 - (x_i+1)^2 - (y_i-1)^2 dD=R2(xi+1)2(yi1)2

构造判别式

我们不妨构造如下判别式
p i = d H − d D p_i = d_H - d_D pi=dHdD
     = ( x i + 1 ) 2 + y i 2 − R 2 − ( R 2 − ( x i + 1 ) 2 + ( y i − 1 ) 2 ) \space\space\space\space= (x_i+1)^2 + y_i^2 - R^2 - (R^2 - (x_i+1)^2 + (y_i-1)^2)     =(xi+1)2+yi2R2(R2(xi+1)2+(yi1)2)
     = 2 ( x i + 1 ) 2 + 2 y i 2 − 2 y i − 2 R 2 + 1 \space\space\space\space= 2(x_i+1)^2 + 2y_i^2-2y_i\textcolor{red}{-2R^2+1}     =2(xi+1)2+2yi22yi2R2+1

圆与网格点的关系

关系由来

在这里插入图片描述

圆与网格点有且仅有上述5种关系,情况分别如上:
在这里插入图片描述
其中的BCEF均为该网格上的中点。

首先,我们得再次强调的一点是,在 0≤x≤y 的 1/8 圆周上的每点的斜率绝对值都小于1。即它们与 x 轴负方向的倾角都不能超过图中的 FE 线段。

由于,我们现在点亮的点是 P ( x i , y i ) P(x_i, y_i) P(xi,yi) ,所以圆与 x=1 的交点应该在 BF 之间。由于此段圆弧的斜率均小于1,因此圆与 x=2 的交点应该在 CE 之间,由此上上图中的 5 条圆弧都有了解释:
圆弧1:圆与 x=1 的交点在 BP 间,且该圆斜率变化很小(半径很大)
圆弧4,5:我个人认为是在接近 y=x 这条直线处的网格可以产生这种情况

关系含义

在这里插入图片描述
构造判别式: p i = d H − d D p_i = d_H-d_D pi=dHdD

  1. 精确圆弧是③,则 d H > 0 和 d D > 0 d_H >0和d_D>0 dH>0dD>0
    若 p i < 0 , 即 d H < d D 应 选 H 点 若p_i<0,即d_H <d_D应选H点 pi<0dH<dDH
    若 p i ≥ 0 , 即 d H ≥ d D 应 选 D 点 若p_i≥0,即d_H ≥d_D应选D点 pi0dHdDD
  2. 若精确圆弧是①或②,显然H是应选择点,而此时 d H ≤ 0 , d D > 0 d_H ≤0,d_D>0 dH0dD>0,必有 p i < 0 p_i<0 pi<0
  3. 若精确圆弧是④或⑤,显然D是应选择点,而此时 d H > 0 , d D ≤ 0 d_H >0,d_D≤0 dH>0dD0,必有 p i > 0 p_i>0 pi>0

得出结论: p i p_i pi 做判别量, p i < 0 p_i<0 pi<0 时,选H点为下一个像素点, p i ≥ 0 p_i≥0 pi0 时,选D点为下一个像素点。

p i p_i pi 递推

因为 p i p_i pi 代表此次选择哪个点的判别式,如果我们知道下一次选点的判别式和其关系就可以节省很多思考。所以我们要从 p i p_i pi 计算 p i + 1 p_{i+1} pi+1
ps. 对 p i + 1 p_{i+1} pi+1 数学意义的解释:此次点亮的点我们称做 ( x i , y i ) (x_i, y_i) (xi,yi),下一次点亮的点我们就称做 ( x i + 1 , y i + 1 ) (x_{i+1}, y_{i+1}) (xi+1,yi+1) x i + 1 x_{i+1} xi+1 的值和 x i x_i xi 是有递推关系的( x i + 1 = x i + 1 x_{i+1}=x_i+1 xi+1=xi+1 ,见关系由来下的图)。而此次我们将判断点亮哪个点的判别式记作 p i p_i pi,类似的,下次判断点亮哪个点的判别式我们就记作 p i + 1 p_{i+1} pi+1
p i = d H − d D p_i = d_H - d_D pi=dHdD
     = ( x i + 1 ) 2 + y i 2 − R 2 − ( R 2 − ( x i + 1 ) 2 + ( y i − 1 ) 2 ) \space\space\space\space= (x_i+1)^2 + y_i^2 - R^2 - (R^2 - (x_i+1)^2 + (y_i-1)^2)     =(xi+1)2+yi2R2(R2(xi+1)2+(yi1)2)
     = 2 ( x i + 1 ) 2 + 2 y i 2 − 2 y i − 2 R 2 + 1 \space\space\space\space= 2(x_i+1)^2 + 2y_i^2-2y_i\textcolor{red}{-2R^2+1}     =2(xi+1)2+2yi22yi2R2+1

p i + 1 = 2 ( x i + 1 + 1 ) 2 + 2 y i + 1 2 − 2 y i + 1 − 2 R 2 + 1 p_{i+1}=2(x_{i+1}+1)^2 + 2y_{i+1}^2-2y_{i+1}\textcolor{red}{-2R^2+1} pi+1=2(xi+1+1)2+2yi+122yi+12R2+1
p i + 1 − p i = 4 x i + 6 + 2 ( y i + 1 2 − y i 2 − y i + 1 + y i ) p_{i+1}-p_i=4x_i+6+2(y_{i+1}^2-y_i^2-y_{i+1}+y_i) pi+1pi=4xi+6+2(yi+12yi2yi+1+yi)

  1. p i ≥ 0 p_i≥0 pi0 时,应选D点,此时 D 点的 y 坐标和 P 的 y 坐标的关系是 y i + 1 = y i − 1 y_{i+1} = y_i - 1 yi+1=yi1,带入上式有:
    p i + 1 = p i + 4 ( x i − y i ) + 10 p_{i+1}=p_i+4(x_i-y_i)+10 pi+1=pi+4(xiyi)+10
  2. p i < 0 p_i<0 pi<0 时,应选H点,此时 H 点的 y 坐标和 P 的 y 坐标的关系是 y i + 1 = y i y_{i+1} = y_i yi+1=yi,带入上式有:
    p i + 1 = p i + 4 x i + 6 p_{i+1}=p_i+4x_i+6 pi+1=pi+4xi+6

画圆

画圆的起始点是(0, R),即 x 1 = 0 , y 1 = R x_1=0, y_1=R x1=0,y1=R,带入前式。即令 i=1 ,就得到:
p i = 3 − 2 R p_i=3-2R pi=32R
剩下的递推就行。

程序伪码

void BresenhamCircle(int R){     
	int x,y,p;
	x=0;  y=R;
	p=3-2*R;
	for(;x<=y;x++){       
		SetPixel(x,y);
		if(p>=0){
			p+=4*(x-y)+10;
			y--;
		}
		else {
			p+=4*x+6;
		}
	}
}

在这里插入图片描述
根据对称性,只需修改语句 SetPixel(x,y),画八个对称的点,就可以画出全部圆周。若加一个平移,就可以画出圆心在任意位置的圆周

圆与网格点的关系图示

情况一: x 2 + y 2 = 10000 x^2+y^2=10000 x2+y2=10000
其中 1 4 2 + 9 9 2 = 9997 14^2+99^2=9997 142+992=9997

在这里插入图片描述

情况五: x 2 + y 2 = 10000 x^2+y^2=10000 x2+y2=10000,那条横线是 y=77.5
其中 6 5 2 + 7 6 2 = 10001 65^2+76^2=10001 652+762=10001

在这里插入图片描述

时间有限,姑且只画这俩。

  • 61
    点赞
  • 246
    收藏
    觉得还不错? 一键收藏
  • 39
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值