【计算机图形学】图元的扫描转换之圆的扫描转换

本文深入探讨了中点圆算法的原理与实现,通过对比不同圆的扫描转换方法,介绍了中点圆算法如何利用增量计算和八方向对称性高效绘制圆。详细解释了算法中的关键步骤,包括中点的选择、增量计算以及初始条件设定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相关资料来源于网络,侵删歉。
如果文章中存在错误,请下方评论告知我,谢谢!


圆的扫描转换

前提
1.圆心在原点
2.半径R为整数

首先我们直接可以想到这种方法,由圆的方程x^{2}+y^{2}=R^{2} ,得到y=\pm sqrt(R^{2}-x^{2})。那么给定一个范围的x,每一个x对应一个y,圆就被绘制出来了。但是,这种方法效率很低,平方计算,开平方计算,还需要对x、y取整,点分布不均匀,如下图。

接下来我们又想到,由圆的参数方程,x=Rcosθ,y=Rsinθ,θ从0到90度,得到1/4圆,可由对称性得到完整的圆。这种方法减小了点的分布不均匀,但是效率仍然很低,因为涉及浮点运算,乘法运算,取整运算。这种方法能否改进呢?

八方向对称性
由圆的多种对称,只需要圆上一点,我们就可以找到圆上的另外7个点,如图。为此,我们计算一个45度的圆弧就可以得到完整的圆。

中点圆算法
(注:这种思想与直线的扫描转换类似,如果不理解请先阅读那篇文章。)
我们考虑第二个八分圆,P点为已点亮像素,那么下一个要点亮的像素是E或者SE,如图。

构造函数F(x,y)=x^{2}+y^{2}-R^{2},存在三种情况:
如果F(x,y)=0,那么点在圆上;
如果F(x,y)>0,那么点在圆外;
如果F(x,y)<0,那么点在圆内。

取E和SE的中点M,将M点代入F(x,y),根据符号可判断M点与圆的位置关系。
当F(x,y)>0时,M点在圆外,弧线离SE更近,应取SE点;
当F(x,y)<0时,M点在圆内,弧线离E点更近,应取E点;
当F(x,y)=0时,M点在圆上,取SE和E都行。(当连续的M点总是在圆上时,应总是取SE或E的其一)
但是,直接代入存在浮点运算,平方运算,效率较低。我们仍然采用增量算法来优化。

我们由P点可以推出M点的坐标,再由M点的坐标可以推出下一个中点M'的坐标。
d=F(x_{M},y_{M})=F(x_{P}+1,y_{P}-0.5)=F(x_{P},y_{P})+2x_{P}-y_{P}+1.25
当d<0,即M点在弧线下方,此时取E点,下一个中点M'的坐标为(x_{P}+2,y_{P}-0.5),如图。(请自行考虑为什么是M'点)

F(x_{M'},y_{M'})=F(x_{P}+2,y_{P}-0.5)=F(x_{p},y_{p})+4x_{P}-y_{P}+4.25=d+2x_{p}+3
比较得知,M点与M'点代入F(x,y)相差2xp+3,即增量为2xp+3。

当d=0,即M点在弧线上,此时取E和SE皆可,这里取SE点。
当d>0,即M点在弧线上方,此时取SE点,下一个中点M'的坐标为(x_{P}+2,y_{P}-1.5),如图

F(x_{M'},y_{M'})=F(x_{P}+2,y_{P}-1.5)=F(x_{P},y_{P})+4x_{p}-3y_{p}+6.25=d+2(x_{P}-y_{P})+5
比较得知,M点与M'点代入F(x,y)相差2(xp-yp)+5,即增量为2(xp-yp)+5。

综上:
当中点M在弧线下方时,即d<0,取E点,下一个要判断的是d+2xp+3的符号。
当中点M在弧线上或上方时,即d>=0,取SE点,下一个要判断的是d+2(xp-yp)+5的符号。
然后再根据符号取E点或者SE点。

在实现算法前,我们需要知道P的初始坐标P0,和d的初值d0。
我们从(0,R)点开始画圆,所以P0点坐标为(0,R),则d_{0}=F(1,R-0.5)=1.25-R
因为我们只需要判断d的符号,为了效率,我们将d0乘以4得5-4R,去除浮点数,同样,我们也需要将上面讨论的增量乘以4,得8xp+12,8(xp-yp)+20。

实现(这里只给出基础算法,具体的[待编写])

void MidpointCircle(int R, int color){
	int x,y,d;
	x=0;y=R; 
	d=5-4*R;
	WritePixel(x,y,color);
	while(x<y){
		if(d<0){
			d+=8*x+12;
			x++; 
		}
		else{
			d+=8*(x-y)+20;
			x++;
			y--;
		}
		WritePixel(x,y,color);
	}
}

认真考虑后发现,其实我们没必要乘4。
d=1.25-R,设h=d-0.25=1-R,那么d=h+0.25。我们之前在比较d与0的关系,现在只要比较h与-0.25的关系。由于h是整数,所以只要比较h与0的关系即可。有一点需要注意,当h=0时,比较h与-0.25的关系,h>-0.25,但是现在比较h与0的关系,h=0,即使这样,也不影响结果。

MidpointCircle(int R, int color){
	int x,y,h;
	x=0;y=R; 
	h=1-R;
	WritePixel(x,y,color);
	while(x<y){
		if(h<0){
			h+=2*x+3;
			x++; 
		}
		else{
			h+=2*(x-y)+5;
			x++;
			y--;
		}
		WritePixel(x,y,color);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wingrez

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值