DDA算法和Bresenham算法

本文结构如下:

  • 1、DDA算法
  • 2、Bresenham算法
  • 3、代码实现核心部分

1、DDA算法

DDA算法是计算机图形学中最简单的绘制直线算法。其主要思想是由直线公式y = kx + b推导出来的。
我们已知直线段两个端点P0(x0,y0)和P1(x1,y1),就能求出 k 和 b 。

在k,b均求出的条件下,只要知道一个x值,我们就能计算出一个y值。如果x的步进为1(x每次加1,即x = x +1),那么y的步进就为k+b;同样知道一个y值也能计算出x值,此时y的步进为1,x的步进为(1-b)/k。根据计算出的x值和y值,向下取整,得到坐标(x’,y’),并在(x’,y’)处绘制直线段上的一点。

为进一步简化计算,通常可令b取0,将起点看作(0,0)。设当前点为(xi, yi)则用DDA算法求解(xi+1,yi+1)的计算公式可以概括为:

  • xi+1 = xi + xStep (1)
  • yi+1 = yi + yStep (2)

我们一般通过计算 Δx 和 Δy 来确定xStep和yStep:

  • 如果 Δx > Δy ,说明x轴的最大差值大于y轴的最大差值,x轴方向为步进的主方向,xStep = 1,yStep = k;
  • 如果 Δy> Δx,说明y轴的最大差值大于x轴的最大差值,y轴方向为步进的主方向,yStep = 1,xStep = 1 / k。

根据这个公式,就能通过(xi,yi)迭代计算出(xi+1、yi+1),然后在坐标系中绘制计算出的(x,y)坐标点。

2、Bresenham算法

Bresenham算法也是一种计算机图形学中常见的绘制直线的算法,其本质思想也是步进的思想,但由于避免了浮点运算,相当于DDA算法的一种改进算法。

设直线的斜率为k,当|k| <=1时,x方向为主步进方向;当|k| >1时,y方向为主步进方向。现以|k| <1时为例,推导Bresenham算法的原理。

Bresenham算法直线绘制示意图
图片来自:http://st251256589.blog.163.com/blog/static/16487644920114112817666/

图中绘制了一条直线,蓝色点表示该直线上的点,红色点表示光栅下绘制的点。
假设当前点是(xi,yi)
- 如果int(yi+0.5) = yi,则在点(xi, round(yi))处绘制.
- 如果int(yi+0.5) = yi + 1,则在点(xi, round(yi)+1)处绘制。

上述逻辑可简述为:当x方向是主要步进方向时,以每一小格的中点为界,如果当前的yi在中点(图中红色短线)下方,则y取round(yi); 如果当前的yi在中点上方,则y取rund(yi)+1。

引用部分:现考虑这种方法的误差,因为直线的起始点在像素中心,所以误差项d的初值d0=0。x下标每增加1,d的值相应递增。直线的斜率值k,即d=d+k。一旦d≥1,就把它减去1,这样保证d在0、1之间。当d≥0.5时,最接近于当前像素的右上方像素(x+1,y+1)而当d<0.5时,更接近于右方像素(x+1,y)为方便计算,令e=d-0.5,e的初值为-0.5,增量为k。当e≥0时,取当前像素(xi,yi)的右上方像素(x+1,y+1),而当e<0时,更接近于右方像素(x+1,y)可以改用整数以避免除法。由于算法中只用到误差项的符号,因此可作如下替换:
e1 = 2e * Δx。

参考:
http://blog.csdn.net/xdg_blog/article/details/52848891
http://www.cnblogs.com/weiweishuo/archive/2013/03/11/2954443.html

3、代码实现

1、DDA算法

void CGView::DrawDDALine(int startx,int starty, int endx, int endy)
{   CDC* pDC = GetDC();DrawStandLine(pDC);//绘制标准直线int x0 = startx; int y0 = starty ;int x1 = endx; int y1 = endy; int color=RGB(255,0,0);int x; float dx,dy,y,k;dx = x1-x0, dy = y1-y0;k = dy / dx,y = y0;int x2 = startx; int y2 = endx;for(x = x0;x <= x1;x++){   //(20,360)是坐标轴的起点x2 = 20 + x * 30; //30是坐标轴的单位刻度pDC->Ellipse( x2 - 5, y2 - 5, x2 + 5, y2 + 5 );y = k * x + k;y = (int)(y+0.5);y2 = 360 - y * 30;}
}

2、Bresenham算法

void CGView::DrawBresenham(int startx,int starty, int endx, int endy)
{CDC* pDC = GetDC();DrawStandLine(pDC);//绘制标准直线int x0, y0, x1, y1;x0 = startx; y0 =starty;x1 = endx; y1 = endy;int x, y, dx, dy;  dx = x1-x0, dy = y1- y0; x = x0;y = y0;double k = dy / dx;//如果 >1,则y方向是主要步进方向,需要转换坐标系方向if(abs(k)>1){Swap(startx,starty,endx,endy);}int e = -dx; int x2 = 20, y2 = 360; //(20,360)是坐标轴的起点for (int x=x0; x<=x1; x++){ pDC->Ellipse( x2 - 5, y2 - 5, x2 + 5, y2 + 5 );x2 += 30;e += 2 * dy;if (e > 0){ y++;y2 -= 30; //30是坐标轴的单位刻度e -= 2*dx;}}
}

两种算法的运行结果情况如下图所示,从图中可已看出,两种算法都能绘制出直线段,但是在细节稍有不同,当x=4时,DDA算法的y值为3,而Bresenham的算法y为2。在不过从效率上看,由于Bresenham避免了浮点运算,所以效率更高。

本文参考了网上的资料,包括图片、文字等。在文中均给出了链接。时间太久了,代码已经找不到出处了。如有疏漏,请指出。

DDA算法和Bresenham算法相关推荐

  1. 游戏中DDA算法和Bresenham算法的应用

    在角色扮演或即时战略游戏中,经常会将角色以最佳的方式走到指定地点.游戏场景的地面情况复杂,而且场面大,若采用盲目式搜索,例如盲目穷举法,则几乎要遍历整个场景,效率非常低,造成角色反应速度过慢,实践证明 ...

  2. BF算法和KMP算法

    给定两个字符串S和T,在主串S中查找子串T的过程称为串匹配(string matching,也称模式匹配),T称为模式.这里将介绍处理串匹配问题的两种算法,BF算法和KMP算法. BF算法 (暴力匹配 ...

  3. Algorithm:C++语言实现之字符串相关算法(字符串的循环左移、字符串的全排列、带有同个字符的全排列、串匹配问题的BF算法和KMP算法)

    Algorithm:C++语言实现之字符串相关算法(字符串的循环左移.字符串的全排列.带有同个字符的全排列.串匹配问题的BF算法和KMP算法) 目录 一.字符串的算法 1.字符串的循环左移 2.字符串 ...

  4. 操作系统之存储管理——FIFO算法和LRU算法

    操作系统之进程调度--优先权法和轮转法(附上样例讲解) 操作系统之银行家算法-详解流程及案例数据 操作系统之多线程编程-读者优先/写者优先详解 操作系统之存储管理--FIFO算法和LRU算法 操作系统 ...

  5. 若S作主串,P作模式串,试分别写出利用BF算法和KMP算法的匹配过程。

    目   录 题目: 百度文库-答案: (1) (2) MOOC标准答案: (1) (2) mooc答案-截图: 数据结构(C语言版)-严蔚敏2007 题目: 设字符串S='aabaabaabaac', ...

  6. Prim算法和Kruskal算法

       Prim算法和Kruskal算法都能从连通图找出最小生成树.区别在于Prim算法是以某个顶点出发挨个找,而Kruskal是先排序边,每次选出最短距离的边再找. 一.Prim(普里姆算法)算法: ...

  7. 基于Huffman算法和LZ77算法的文件压缩的改进方向

    基于Huffman算法和LZ77算法的文件压缩(八) 到这里已经简单实现基于Huffman算法和LZ77算法的文件压缩, GitHub源码:点我 根据基于Huffman算法和LZ77算法的文件压缩(七 ...

  8. 最短路径Dijkstra算法和Floyd算法整理、

    转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径-Dijkstra算法和Floyd算法 Dijks ...

  9. 用Spark学习FP Tree算法和PrefixSpan算法

    在FP Tree算法原理总结和PrefixSpan算法原理总结中,我们对FP Tree和PrefixSpan这两种关联算法的原理做了总结,这里就从实践的角度介绍如何使用这两个算法.由于scikit-l ...

  10. 【Java数据结构与算法】第二十章 Dijkstra算法和Floyd算法

    第二十章 Dijkstra算法和Floyd算法 文章目录 第二十章 Dijkstra算法和Floyd算法 一.Dijkstra算法 1.介绍 2.代码实现 二.Floyd算法 1.介绍 2.代码实现 ...

最新文章

  1. Java---实现运行任意目录下class中加了@MyTest的空参方法(实现图形界面)
  2. 从用户需求看互联网基础设施服务商www.shzhenai.com
  3. ruby 反射机制常用方法
  4. mysql连接nginx_nginx四层负载均衡连接mysql
  5. mysql国际化_Java的Struts框架中的主题模板和国际化设置
  6. Nacos自定义扩展的 Data Id 配置
  7. memcached 安装小结-1
  8. python 关于excelcsv与cookie的部分笔记
  9. java多因子认证,Milvus 实战|生物多因子认证系列 (二):人脸识别
  10. 设计配色专辑,很值得设计师拥有
  11. proxmoxve打造云桌面_最大亮点!山东众志电子为山东财经大学东方学院打造首个200点位云桌面考场...
  12. 智能优化算法:蛇优化算法-附代码
  13. C语言 5个数最值问题
  14. C# CommandName四个属性
  15. 使用NGUI实现拖拽功能(拼图小游戏)
  16. 使用C语言自定义函数计算三角形周长
  17. 腾讯2018秋招笔试真题(2)
  18. 如何查看Tomcat是否安装配置成功
  19. requests使用socks代理
  20. Sanity Testing 和 Smoke Testing的区别

热门文章

  1. 无盘工作站建立全攻略
  2. 临渊羡鱼 不如退而结网
  3. 【Python】调用WPS V9 API,实现Word转PDF
  4. (Android-RTC-8)分析HardwareVideoEncoder—BitrateAdjuster
  5. 西门子主程序调用子程序_西门子PLC调用子程序的方法
  6. 淘淘商城系列——Solr集群搭建
  7. 笨方法学python 习题23
  8. zbb20180815 网盘搜索引擎
  9. linux宽松模式,三星N9200刷机包 V35.0 自编译官方内核 Selinux置为宽松模式 修复问题 稳定流畅...
  10. ES6 推荐网络文档书籍