在我们内部开发使用的一个工具中,我们需要几乎从 0 开始实现一个高效的二维图像渲染引擎。比较幸运的是,我们只需要画直线、圆以及矩形,其中比较复杂的是画直线和圆。画直线和圆已经有非常多的成熟的算法了,我们用的是Bresenham的算法。

计算机是如何画直线的?简单来说,如下图所示,真实的直线是连续的,但我们的计算机显示的精度有限,不可能真正显示连续的直线,于是我们用一系列离散化后的点(像素)来近似表现这条直线。

  (上图来自于互联网络,《计算机图形学的概念与方法》柳朝阳,郑州大学数学系)

接下来的问题就是如何尽可能高效地找到这些离散的点,Bresenham直线算法就是一个非常不错的算法。

Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。是计算机图形学中最先发展出来的算法。

  (引自wiki百科布雷森漢姆直線演算法)

这个算法的流程图如下:

可以看到,算法其实只考虑了斜率在 0 ~ 1 之间的直线,也就是与 x 轴夹角在 0 度到 45 度的直线。只要解决了这类直线的画法,其它角度的直线的绘制全部可以通过简单的坐标变换来实现。

下面是一个C语言实现版本。

// 交换整数 a 、b 的值
inline void swap_int(int *a, int *b) {*a ^= *b;*b ^= *a;*a ^= *b;
}// Bresenham's line algorithm
void draw_line(IMAGE *img, int x1, int y1, int x2, int y2, unsigned long c) {// 参数 c 为颜色值int dx = abs(x2 - x1),dy = abs(y2 - y1),yy = 0;if (dx < dy) {yy = 1;swap_int(&x1, &y1);swap_int(&x2, &y2);swap_int(&dx, &dy);}int ix = (x2 - x1) > 0 ? 1 : -1,iy = (y2 - y1) > 0 ? 1 : -1,cx = x1,cy = y1,n2dy = dy * 2,n2dydx = (dy - dx) * 2,d = dy * 2 - dx;if (yy) { // 如果直线与 x 轴的夹角大于 45 度while (cx != x2) {if (d < 0) {d += n2dy;} else {cy += iy;d += n2dydx;}putpixel(img, cy, cx, c);cx += ix;}} else { // 如果直线与 x 轴的夹角小于 45 度while (cx != x2) {if (d < 0) {d += n2dy;} else {cy += iy;d += n2dydx;}putpixel(img, cx, cy, c);cx += ix;}}
}

可以看到,在画线的循环中,这个算法只用到了整数的加法,所以可以非常的高效。

接下来,我们再来看一看Bresenham画圆算法

Bresenham画圆算法又称中点画圆算法,与Bresenham 直线算法一样,其基本的方法是利用判别变量来判断选择最近的像素点,判别变量的数值仅仅用一些加、减和移位运算就可以计算出来。为了简便起见,考虑一个圆 心在坐标原点的圆,而且只计算八分圆周上的点,其余圆周上的点利用对称性就可得到。

为什么只计算八分圆周上的点就可以了呢?和上面的直线算法类似,圆也有一个“八对称性”,如下图所示。

显然,我们只需要知道了圆上的一个点的坐标 (x, y) ,利用八对称性,我们马上就能得到另外七个对称点的坐标。

和直线算法类似,Bresenham画圆算法也是用一系列离散的点来近似描述一个圆,如下图。

  (上图来自于互联网络,《计算机图形学的概念与方法》柳朝阳,郑州大学数学系)

Bresenham画圆算法的流程图如下。

可以看到,与画线算法相比,画圆的循环中用到了整数的乘法,相对复杂了一些。

下面是一个C语言实现版本。

// 八对称性
inline void _draw_circle_8(IMAGE *img, int xc, int yc, int x, int y, unsigned long c) {// 参数 c 为颜色值putpixel(img, xc + x, yc + y, c);putpixel(img, xc - x, yc + y, c);putpixel(img, xc + x, yc - y, c);putpixel(img, xc - x, yc - y, c);putpixel(img, xc + y, yc + x, c);putpixel(img, xc - y, yc + x, c);putpixel(img, xc + y, yc - x, c);putpixel(img, xc - y, yc - x, c);
}//Bresenham's circle algorithm
void draw_circle(IMAGE *img, int xc, int yc, int r, int fill, unsigned long c) {// (xc, yc) 为圆心,r 为半径// fill 为是否填充// c 为颜色值// 如果圆在图片可见区域外,直接退出if (xc + r < 0 || xc - r >= img->w ||yc + r < 0 || yc - r >= img->h) return;int x = 0, y = r, yi, d;d = 3 - 2 * r;if (fill) {// 如果填充(画实心圆)while (x <= y) {for (yi = x; yi <= y; yi ++)_draw_circle_8(img, xc, yc, x, yi, c);if (d < 0) {d = d + 4 * x + 6;} else {d = d + 4 * (x - y) + 10;y --;}x++;}} else {// 如果不填充(画空心圆)while (x <= y) {_draw_circle_8(img, xc, yc, x, y, c);if (d < 0) {d = d + 4 * x + 6;} else {d = d + 4 * (x - y) + 10;y --;}x ++;}}
}

可以看到,Bresenham画圆算法(中点圆算法)的实现也非常简单。在另一个项目中,我还有一个 Python 实现的版本,不过那段代码和其余部分结合得比较紧,有点难抠,这次就不贴出来了。

转载于:https://www.cnblogs.com/wlzy/p/8695226.html

Bresenham直线算法与画圆算法相关推荐

  1. python3画圆、直线_Bresenham直线算法与画圆算法

    在我们内部开发使用的一个工具中,我们需要几乎从 0 开始实现一个高效的二维图像渲染引擎.比较幸运的是,我们只需要画直线.圆以及矩形,其中比较复杂的是画直线和圆.画直线和圆已经有非常多的成熟的算法了,我 ...

  2. 计算机图形学实习教程之基本图形的生成(直线DDA算法,直线中点算法,Bresenham画圆算法),利用C#实现,附源码

    环境:Win10+Visual Studio 2022 Community 在本次实验中需要用到上一篇文章实验内容的代码及环境,详情请见:传送门 目录 一.实验目的 二.实验过程 1.生成直线的DDA ...

  3. Bresenham 画圆算法原理

    文章目录 前言 Bresenham 画圆算法原理 两个近似 构造判别式 圆与网格点的关系 关系由来 关系含义 pip_ipi​ 递推 画圆 程序伪码 圆与网格点的关系图示 前言 首先简要介绍一下生成圆 ...

  4. 【计算机图形学】小白谈计算机图形学(二)画圆篇之中点画圆法,Bresenham画圆算法,椭圆实操,线型处理详解

    小白谈计算机图形学(二)画圆篇之中点画圆法,Bresenham画圆算法,椭圆实操,线型处理详解 引言 如何画圆 基本思想 中点画圆法 中点画圆基本思路 中点画圆改进 Bresenham画圆算法 Bre ...

  5. 中点Bresenham画圆算法|MFC|计算机图形学

    中点Bresenham画圆算法|MFC|计算机图形学 Bresenham中点画圆算法 计算机图形学-基本图元的生成-圆 基于学习直线的生成算法后,又展开了圆.椭圆的讲解: 此次试验是简单的MFC应用, ...

  6. Bresenham画圆算法

    Bresenham 画圆算法适合于生成整圆,它使用8路对称法,只计算出90°~45°内的点,移动方向为+x,-y. 递推公式: 完整代码: 加上Sleep函数,减慢画圆速度,以便观察画圆过程. #in ...

  7. mfc 画圆算法 画椭圆算法

    mfc画圆算法 求半径:圆心一点:m_ptOrigin1,圆上一点:m_ptOrigin2 注释:这里的m_ptOrigin1,m_ptOrigin2均为Cpoint类型 R=int(sqrt(pow ...

  8. java用中点画圆法_Bresenham画圆算法 与中点画圆法

    Bresenham画圆算法 不失一般性,假设圆的圆心位于坐标原点(如果圆心不在原点,可以通过坐标平移使其与原点重合),半径为R.以原点为圆心的圆C有四条对称轴:x = 0, y = 0, x = y和 ...

  9. matlab八分之一中点画圆算法,中点八分画圆算法

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #define W 800 #define H 600 void drawCircle(SDL_Renderer* r ...

  10. bresenham算法画圆c语言,bresenham画圆算法

    中点画圆算法在一个方向上取单位间隔,在另一个方向的取值由两种可能取值的中点离圆的远近而定.实际处理中,用决策变量的符号来确定象素点的选择,因此算法效率较高. 设要显示圆的圆心在原点(0,0),半径为R ...

最新文章

  1. jQuery学习笔记——事件
  2. QML模块定义qmldir文件
  3. linux的lsm--TCB组成部分的新视角
  4. 《RESTful Web Services》第一章 使用统一接口
  5. Elasticsearch高级查询2:ES 高级查询
  6. 【祈福】一句话让你的网页为灾区祈福(让网页变灰色)
  7. 管理c语言源代码,c语言源代码---------------个人图书管理系统
  8. 基于深度学习生成音乐
  9. VScode SSH远程连接失败
  10. qlv格式转mp4格式(简单、高效)
  11. 2012百度移动开发者大会汇报
  12. 口布杯花的60种叠法_餐巾折花艺术3餐巾折杯花.ppt
  13. openSetting:fail can only be invoked by user TAP gesture.
  14. 【算法+LeetCode题解+剑指Offer题解】算法思想、排序搜索、数据结构、数学、特殊解法、设计(全总结)
  15. C# 模拟鼠标移动和点击
  16. 网址短连接 short url
  17. JavaScript高级程序设计(第4版)学习随笔【第五章】
  18. 信息泄露,那些央视没报的“内鬼
  19. 3GPP TS 23501-g51 中英文对照 | 4.3.5 Service Exposure in Interworking Scenarios
  20. 使用PYQT5打开电脑摄像头并进行拍照

热门文章

  1. 为什么我一直强调大家要两条腿走路?
  2. 从大厂出来后,我工资翻了一翻
  3. python基础知识——函数(上)
  4. 联想台式机usb驱动_windows安装系列教程—驱动安装
  5. python找不到指定的路径_[Python学习]错误篇二:切换当前工作目录时出错——FileNotFoundError: [WinError 3] 系统找不到指定的路径...
  6. python相机拍照显示_Python无法从Raspberry Pi相机以最高分辨率拍照
  7. android textview api,Android API中文文档TextView
  8. 图像数据流识别圆形_python opencv :使用Hough变换检测圆形,数钱。
  9. 获取vue一个对象的所有属性_VUE中computed计算属性和data数据获取的问题
  10. go语言中顺序查找的案例--人名查找