Bresenham 画圆算法原理
文章目录
- 前言
- Bresenham 画圆算法原理
- 两个近似
- 构造判别式
- 圆与网格点的关系
- 关系由来
- 关系含义
- pip_ipi 递推
- 画圆
- 程序伪码
- 圆与网格点的关系图示
前言
首先简要介绍一下生成圆的方法:
- 直接利用圆的方程生成圆
- 利用圆的对称性生成圆
方法一由于会涉及到浮点运算等因素,不采取该方案。
ps. 这部分想要知道为什么可以参考 计算机图形学 圆及椭圆的扫描转换_百度文库 前面一点。
方法二的原理如下图,利用圆的对称性,我们只需要对一个八分圆进行扫描转换。
在这里我们不妨选择第一象限上斜率绝对值小于1的那八分圆进行扫描转换,以及假设圆心为 (0, 0) 。也就是下图。
友情提示:圆在某点的斜率是该点处切线斜率。圆心不在 (0, 0) 处的点可以通过平移得到。
Bresenham 画圆算法原理
如下图,在 0≤x≤y 的 1/8 圆周上,像素坐标 x 值单调增加,y 值单调减少。
设第 i 步已确定(xi,yi)(x_i, y_i)(xi,yi)是要画圆上的像素点,看第 i+1 步像素点(xi+1,yi+1)(x_{i+1}, y_{i+1})(xi+1,yi+1)应如何确定。下一个像素点只能是H(xi+1,yi)H(x_i+1, y_i)H(xi+1,yi)或者D(xi+1,yi−1)D(x_i+1,y_i-1)D(xi+1,yi−1)中的一个 。
具体选哪个就得看 dH和dDd_H 和 d_DdH和dD 二者的比较了:
- dHd_HdH 更小,下一个像素点就选 H(xi+1,yi)H(x_i+1, y_i)H(xi+1,yi)
- dDd_DdD 更小,下一个像素点就选 D(xi+1,yi−1)D(x_i+1,y_i-1)D(xi+1,yi−1)
- 一样大,选哪个都行。
比较方法就是做差:dH−dDd_H - d_DdH−dD,然后将结果与0进行比较。
那么问题是 dH和dDd_H 和 d_DdH和dD 二者的值是怎么求得呢?这里就涉及到一个近似:
两个近似
近似方法:
将 CH 近似为 dHd_HdH
将 DB 近似为 dDd_DdD
由大图显而易见可以知道 CH 和 DB 的值:
CH=OH−OC=(xi+1)2+yi2−R=dHCH = OH - OC = \sqrt{(x_i+1)^2 + y_i^2} - R = d_HCH=OH−OC=(xi+1)2+yi2−R=dH
DH=OB−OD=R−(xi+1)2+(yi−1)2=dDDH = OB - OD = R - \sqrt{(x_i+1)^2 + (y_i-1)^2} = d_DDH=OB−OD=R−(xi+1)2+(yi−1)2=dD
这里由于涉及到了根号运算,因此又做了一个近似:
dH=(xi+1)2+yi2−R2d_H = (x_i+1)^2 + y_i^2 - R^2dH=(xi+1)2+yi2−R2
dD=R2−(xi+1)2−(yi−1)2d_D = R^2 - (x_i+1)^2 - (y_i-1)^2dD=R2−(xi+1)2−(yi−1)2
构造判别式
我们不妨构造如下判别式
pi=dH−dDp_i = d_H - d_Dpi=dH−dD
=(xi+1)2+yi2−R2−(R2−(xi+1)2+(yi−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+yi2−R2−(R2−(xi+1)2+(yi−1)2)
=2(xi+1)2+2yi2−2yi−2R2+1\space\space\space\space= 2(x_i+1)^2 + 2y_i^2-2y_i\textcolor{red}{-2R^2+1} =2(xi+1)2+2yi2−2yi−2R2+1
圆与网格点的关系
关系由来
圆与网格点有且仅有上述5种关系,情况分别如上:
其中的BCEF均为该网格上的中点。
首先,我们得再次强调的一点是,在 0≤x≤y 的 1/8 圆周上的每点的斜率绝对值都小于1。即它们与 x 轴负方向的倾角都不能超过图中的 FE 线段。
由于,我们现在点亮的点是 P(xi,yi)P(x_i, y_i)P(xi,yi) ,所以圆与 x=1 的交点应该在 BF 之间。由于此段圆弧的斜率均小于1,因此圆与 x=2 的交点应该在 CE 之间,由此上上图中的 5 条圆弧都有了解释:
圆弧1:圆与 x=1 的交点在 BP 间,且该圆斜率变化很小(半径很大)
圆弧4,5:我个人认为是在接近 y=x 这条直线处的网格可以产生这种情况
关系含义
构造判别式:pi=dH−dDp_i = d_H-d_Dpi=dH−dD
- 精确圆弧是③,则dH>0和dD>0d_H >0和d_D>0dH>0和dD>0
若pi<0,即dH<dD应选H点若p_i<0,即d_H <d_D应选H点若pi<0,即dH<dD应选H点
若pi≥0,即dH≥dD应选D点若p_i≥0,即d_H ≥d_D应选D点若pi≥0,即dH≥dD应选D点 - 若精确圆弧是①或②,显然H是应选择点,而此时dH≤0,dD>0d_H ≤0,d_D>0dH≤0,dD>0,必有pi<0p_i<0pi<0。
- 若精确圆弧是④或⑤,显然D是应选择点,而此时dH>0,dD≤0d_H >0,d_D≤0dH>0,dD≤0,必有pi>0p_i>0pi>0。
得出结论:pip_ipi 做判别量,pi<0p_i<0pi<0 时,选H点为下一个像素点,pi≥0p_i≥0pi≥0 时,选D点为下一个像素点。
pip_ipi 递推
因为 pip_ipi 代表此次选择哪个点的判别式,如果我们知道下一次选点的判别式和其关系就可以节省很多思考。所以我们要从 pip_ipi 计算 pi+1p_{i+1}pi+1。
ps. 对 pi+1p_{i+1}pi+1 数学意义的解释:此次点亮的点我们称做(xi,yi)(x_i, y_i)(xi,yi),下一次点亮的点我们就称做 (xi+1,yi+1)(x_{i+1}, y_{i+1})(xi+1,yi+1)。 xi+1x_{i+1}xi+1 的值和 xix_ixi 是有递推关系的(xi+1=xi+1x_{i+1}=x_i+1xi+1=xi+1 ,见关系由来
下的图)。而此次我们将判断点亮哪个点的判别式记作 pip_ipi,类似的,下次判断点亮哪个点的判别式我们就记作 pi+1p_{i+1}pi+1
pi=dH−dDp_i = d_H - d_Dpi=dH−dD
=(xi+1)2+yi2−R2−(R2−(xi+1)2+(yi−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+yi2−R2−(R2−(xi+1)2+(yi−1)2)
=2(xi+1)2+2yi2−2yi−2R2+1\space\space\space\space= 2(x_i+1)^2 + 2y_i^2-2y_i\textcolor{red}{-2R^2+1} =2(xi+1)2+2yi2−2yi−2R2+1
pi+1=2(xi+1+1)2+2yi+12−2yi+1−2R2+1p_{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+12−2yi+1−2R2+1
pi+1−pi=4xi+6+2(yi+12−yi2−yi+1+yi)p_{i+1}-p_i=4x_i+6+2(y_{i+1}^2-y_i^2-y_{i+1}+y_i)pi+1−pi=4xi+6+2(yi+12−yi2−yi+1+yi)
- 当 pi≥0p_i≥0pi≥0 时,应选D点,此时 D 点的 y 坐标和 P 的 y 坐标的关系是 yi+1=yi−1y_{i+1} = y_i - 1yi+1=yi−1,带入上式有:
pi+1=pi+4(xi−yi)+10p_{i+1}=p_i+4(x_i-y_i)+10pi+1=pi+4(xi−yi)+10 - 当 pi<0p_i<0pi<0 时,应选H点,此时 H 点的 y 坐标和 P 的 y 坐标的关系是 yi+1=yiy_{i+1} = y_iyi+1=yi,带入上式有:
pi+1=pi+4xi+6p_{i+1}=p_i+4x_i+6pi+1=pi+4xi+6
画圆
画圆的起始点是(0, R),即 x1=0,y1=Rx_1=0, y_1=Rx1=0,y1=R,带入前式。即令 i=1 ,就得到:
pi=3−2Rp_i=3-2Rpi=3−2R
剩下的递推就行。
程序伪码
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),画八个对称的点,就可以画出全部圆周。若加一个平移,就可以画出圆心在任意位置的圆周
圆与网格点的关系图示
情况一:x2+y2=10000x^2+y^2=10000x2+y2=10000
其中 142+992=999714^2+99^2=9997142+992=9997
情况五:x2+y2=10000x^2+y^2=10000x2+y2=10000,那条横线是 y=77.5
其中 652+762=1000165^2+76^2=10001652+762=10001
时间有限,姑且只画这俩。
Bresenham 画圆算法原理相关推荐
- 中点Bresenham画圆算法|MFC|计算机图形学
中点Bresenham画圆算法|MFC|计算机图形学 Bresenham中点画圆算法 计算机图形学-基本图元的生成-圆 基于学习直线的生成算法后,又展开了圆.椭圆的讲解: 此次试验是简单的MFC应用, ...
- 【计算机图形学】小白谈计算机图形学(二)画圆篇之中点画圆法,Bresenham画圆算法,椭圆实操,线型处理详解
小白谈计算机图形学(二)画圆篇之中点画圆法,Bresenham画圆算法,椭圆实操,线型处理详解 引言 如何画圆 基本思想 中点画圆法 中点画圆基本思路 中点画圆改进 Bresenham画圆算法 Bre ...
- Bresenham画圆算法
Bresenham 画圆算法适合于生成整圆,它使用8路对称法,只计算出90°~45°内的点,移动方向为+x,-y. 递推公式: 完整代码: 加上Sleep函数,减慢画圆速度,以便观察画圆过程. #in ...
- 计算机图形学实习教程之基本图形的生成(直线DDA算法,直线中点算法,Bresenham画圆算法),利用C#实现,附源码
环境:Win10+Visual Studio 2022 Community 在本次实验中需要用到上一篇文章实验内容的代码及环境,详情请见:传送门 目录 一.实验目的 二.实验过程 1.生成直线的DDA ...
- bresenham算法画圆c语言,bresenham画圆算法
中点画圆算法在一个方向上取单位间隔,在另一个方向的取值由两种可能取值的中点离圆的远近而定.实际处理中,用决策变量的符号来确定象素点的选择,因此算法效率较高. 设要显示圆的圆心在原点(0,0),半径为R ...
- C语言——中点画圆算法和Bresenham画圆算法(easyx图形库)
一.中点画圆法 首先是中点画圆法,考虑圆心在原点,半径为R的圆在第一象限内的八分之一圆弧,从点(0, R)到点(R/ , R/ )顺时针方向确定这段圆弧.假定某点Pi(xi, yi)已经是该圆弧上最接 ...
- 【计算机图形学】中点画圆算法和Bresenham画圆算法
在平面解析几何中,圆的方程可以描述为(x – x0)2 + (y – y0)2 = R2,其中(x0, y0)是圆心坐标,R是圆的半径,特别的,当(x0, y0)就是坐标中心点时,圆方程可以简化为x2 ...
- python3画圆、直线_Bresenham直线算法与画圆算法
在我们内部开发使用的一个工具中,我们需要几乎从 0 开始实现一个高效的二维图像渲染引擎.比较幸运的是,我们只需要画直线.圆以及矩形,其中比较复杂的是画直线和圆.画直线和圆已经有非常多的成熟的算法了,我 ...
- java用中点画圆法_Bresenham画圆算法 与中点画圆法
Bresenham画圆算法 不失一般性,假设圆的圆心位于坐标原点(如果圆心不在原点,可以通过坐标平移使其与原点重合),半径为R.以原点为圆心的圆C有四条对称轴:x = 0, y = 0, x = y和 ...
最新文章
- layui如何集成文件服务器,layui使用upload组件实现文件上传功能
- Lnc2cancer 3.0,lncRNAs和circRNAs数据更新及分析工具使用指南
- cat查看tomcat日志 linux_方法篇:tomcat日志切割和定期删除
- gitlab 修改HTTP连接方式中的IP和端口
- SQLSERVER复制订阅中的数据库版本选择
- 解决IDEA中自动生成返回值带final修饰的问题
- 前用户sudo免密码
- 网络创业:网站盈利模式分析分类
- @Results用法总结
- 命令与征服3 凯恩之怒
- 计算机音乐谱子十年,十年曲谱钢琴曲_十年 钢琴谱
- 单片机控制电路的多图纸原理图和层次式设计
- 实现带头结点单链表的就地逆置问题。
- matlab调整视频播放速度,会声会影如果调整视频播放速度
- python psutil 进程cpu_python 模块psutil获取进程信息
- react-router v4 路由改变页面不刷新
- FCPX插件 66种手绘漫画MG动画元素包 Comic Pop 破解版
- SAP-ABAP-SQL语句中CAST字段类型转换示例,CONCAT连接示例,SUBSTRING截断示例
- JAVA核心技术,卷1
- python编程之旅 random随机库 第一课 制作简单的随机数程序