Bresenham快速画直线算法

  现在的计算机的图像的都是用像素表示的,无论是点、直线、圆或其他图形最终都会以点的形式显示。人们看到屏幕的直线只不过是模拟出来的,人眼不能分辨出来而已。那么计算机是如何画直线的呢,其实有比较多的算法,这里讲的是Bresenham的算法,是光栅化的画直线算法。直线光栅化是指用像素点来模拟直线,比如下图用蓝色的像素点来模拟红色的直线。

给定两个点起点P1(x1, y1), P2(x2, y2),如何画它们直连的直线呢,即是如何得到上图所示的蓝色的点。假设直线的斜率0<k>0,直线在第一象限,Bresenham算法的过程如下:

1.画起点(x1, y1).

2.准备画下一个点,X坐标加1,判断如果达到终点,则完成。否则找下一个点,由图可知要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点。

  2.1.如果线段ax+by+c=0与x=x1+1的交点y坐标大于(y+*y+1))/2则选右上那个点

  2.2.否则选右下那个点。

3.画点

4.跳回第2步

5.结束

  算法的具体过程是怎样的呢,其实就是在每次画点的时候选取与实现直线的交点y坐标的差最小的那个点,例如下图:

关键是如何找最近的点,每次x都递增1,y则增1或者不增1,由上图,假设已经画了d1点,那么接下来x加1,但是选d2 还是u点呢,直观上可以知道d2与目标直线和x+1直线的交点比较近即纵坐标之差小也即与(x+1, y+1)点纵坐标差大于0.5,所当然是选d2,其他点了是这个道理。

一、             算法原理简介:

算法原理的详细描述及部分实现可参考:

http://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html

      假设以(x, y)为绘制起点,一般情况下的直观想法是先求m = dy /dx(即x每增加1 y的增量),然后逐步递增x, 设新的点为x1 = x + j, y1 = round(y + j * m)。可以看到,这个过程涉及大量的浮点运算,效率上是比较低的(特别是在嵌入式应用中,DSP可以一周期内完成2次乘法,一次浮点却要上百个周期)。

       下面,我们来看一下Bresenham算法,如Fig. 1,(x, y +ε)的下一个点为(x, y + ε + m),这里ε为累加误差。可以看出,当ε+m < 0.5时,绘制(x + 1, y)点,否则绘制(x + 1, y + 1)点。每次绘制后,ε将更新为新值:

            ε = ε + m ,如果(ε + m) <0.5 (或表示为2*(ε + m) < 1)

            ε = ε + m – 1, 其他情况

    将上述公式都乘以dx, 并将ε*dx用新符号ξ表示,可得

            ξ = ξ + dy, 如果2*(ξ + dy) < dx

            ξ = ξ + dy – dx, 其他情况

    可以看到,此时运算已经全变为整数了。以下为算法的伪代码:

            ξ ← 0, y ← y1

            For x ← x1 to x2 do

                Plot Point at (x, y)

                If (2(ξ + dy) < dx)

                    ξ ←ξ + dy

                Else

                    y ← y + 1,ξ ←ξ + dy – dx

                End If

            End For

二、             算法的注意点:

 

 在实际应用中,我们会发现,当dy > dx或出现Fig.2 右图情况时时,便得不到想要的结果,这是由于我们只考虑dx > dy x, y的增量均为正的情况所致。经过分析,需要考虑8种不同的情况,如Fig. 3所示:

 

    当然,如果直接在算法中对8种情况分别枚举, 那重复代码便会显得十分臃肿,因此在设计算法时必须充分考虑上述各种情况的共性,后面将给出考虑了所有情况的实现代码。

三、             算法的实现

以下代码的测试是利用Opencv 2.0进行的,根据需要,只要稍微修改代码便能适应不同环境

代码1:

 

int CEnginApp::Draw_Line(int x0, int y0, // starting position int x1, int y1, // ending positionCOLORREF color,    // color indexUNINT *vb_start, int lpitch) // video buffer and memory pitch
{// this function draws a line from xo,yo to x1,y1 using differential error// terms (based on Bresenahams work)
RECT cRect;//GetWindowRect(m_hwnd,&m_x2d_ClientRect);
GetClientRect(m_hwnd, &cRect);ClientToScreen(m_hwnd, (LPPOINT)&cRect);ClientToScreen(m_hwnd, (LPPOINT)&cRect+1);vb_start = vb_start + cRect.left + cRect.top*lpitch;int dx,             // difference in x'sdy,             // difference in y'sdx2,            // dx,dy * 2
        dy2, x_inc,          // amount in pixel space to move during drawingy_inc,          // amount in pixel space to move during drawingerror,          // the discriminant i.e. error i.e. decision variableindex;          // used for looping// pre-compute first pixel address in video buffervb_start = vb_start + x0 + y0*lpitch;// compute horizontal and vertical deltasdx = x1-x0;dy = y1-y0;// test which direction the line is going in i.e. slope angleif (dx>=0){x_inc = 1;} // end if line is moving rightelse{x_inc = -1;dx    = -dx;  // need absolute value
} // end else moving left// test y component of slopeif (dy>=0){y_inc = lpitch;} // end if line is moving downelse{y_inc = -lpitch;dy    = -dy;  // need absolute value
} // end else moving up// compute (dx,dy) * 2dx2 = dx << 1;dy2 = dy << 1;// now based on which delta is greater we can draw the lineif (dx > dy){// initialize error termerror = dy2 - dx; // draw the linefor (index=0; index <= dx; index++){// set the pixel*vb_start = color;// test if error has overflowedif (error >= 0) {error-=dx2;// move to next linevb_start+=y_inc;} // end if error overflowed// adjust the error termerror+=dy2;// move to the next pixelvb_start+=x_inc;} // end for
} // end if |slope| <= 1else{// initialize error termerror = dx2 - dy; // draw the linefor (index=0; index <= dy; index++){// set the pixel*vb_start = color;// test if error overflowedif (error >= 0){error-=dy2;// move to next linevb_start+=x_inc;} // end if error overflowed// adjust the error termerror+=dx2;// move to the next pixelvb_start+=y_inc;} // end for
} // end else |slope| > 1// return successreturn(1);} // end Draw_Line

 

代码2:

int CEnginApp::Draw_Line2(int x1,int y1,int x2, int y2,COLORREF color,UNINT *vb_start, int lpitch) 
{RECT cRect;//GetWindowRect(m_hwnd,&m_x2d_ClientRect);
GetClientRect(m_hwnd, &cRect);ClientToScreen(m_hwnd, (LPPOINT)&cRect);ClientToScreen(m_hwnd, (LPPOINT)&cRect+1);vb_start = vb_start + cRect.left + cRect.top*lpitch;int dx = x2 - x1;int dy = y2 - y1;int ux = ((dx > 0) << 1) - 1;//x的增量方向,取或-1int uy = ((dy > 0) << 1) - 1;//y的增量方向,取或-1int x = x1, y = y1, eps;//eps为累加误差
eps = 0;dx = abs(dx); dy = abs(dy); if (dx > dy) {for (x = x1; x != x2; x += ux){Plot_Pixel_32(x,y,0,255,0,255,vb_start,lpitch);eps += dy;if ((eps << 1) >= dx){y += uy; eps -= dx;}}}else{for (y = y1; y != y2; y += uy){Plot_Pixel_32(x,y,0,255,0,255,vb_start,lpitch);eps += dx;if ((eps << 1) >= dy){x += ux; eps -= dy;}}}      return 1;
}

调用代码:

                        DD_INIT_STRUCT(ddsd);if (FAILED(lpSface[PrimarySface]->Lock(NULL,&ddsd,DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,NULL)))return false;int x1,y1,x2,y2;for (int i=0;i<100;i++){srand(time(0));x1=rand()%750;y1=rand()%550;x2=rand()%750;y2=rand()%550;Draw_Line2(x1,y1,x2,y2,RGB(0,255,0),(UNINT *)ddsd.lpSurface,ddsd.lPitch>>2);}if (FAILED(lpSface[PrimarySface]->Unlock(NULL)))return false;

 

 效果图:

转载于:https://www.cnblogs.com/gamesky/archive/2012/08/21/2648623.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/482717.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国产光刻机正式宣布:今年出货150台

来源&#xff1a;世界先进制造技术论坛在芯片领域&#xff0c;有一个叫光刻机的设备&#xff0c;不是印钞机&#xff0c;但却比印钞机还金贵。全球只有荷兰一家叫做阿斯麦&#xff08;ASML&#xff09;的公司集全球高端制造业之大成&#xff0c;一年时间造出二十台高端设备&…

元宇宙的“42条共识”

来源&#xff1a; 量子学派*以下内容、图片综合自《图说元宇宙》《设计元宇宙》系列01元宇宙不是一天建成的罗马不是一天建成的&#xff0c;元宇宙也一样。人类从未像今天这样&#xff0c;可以自己成为“创世主”。元宇宙融合了信息技术&#xff08;5G/6G&#xff09;、互联网时…

手把手教你用java读写excel表格文件(POI,EasyExcel)

视频链接-我是学习之星我为狂神打call~ 【狂神说Java】POI及EasyExcel一小时搞定通俗易懂 想给项目添加一个表格导入导出功能吗&#xff1f; “xxx管理系统”没有导入导出功能逼格不够了&#xff1f; 想简单入手下 how to 用java 生成excel又找不到合适的教程&#xff1f; com…

欢迎参加2022年第一次《城市大脑建设标准规范》专家研讨会

来源&#xff1a;世界数字大脑标准研究组2018年以来&#xff0c;城市大脑正成为智慧城市和智能产业的新热点&#xff0c;有近500个城市提出城市大脑的建设规划&#xff0c;数千家大中型科技企业进入城市大脑的建设领域。如何理清城市大脑的概念和定义&#xff0c;制定统一的城市…

Spring常用注解的讲解

转载&#xff0c;原文链接 作者&#xff1a;字母哥博客 本文出自&#xff1a;springboot深入浅出系列 文章目录一、常用注解回顾1.1 RequestBody与ResponseBody1.2. RequestMapping注解1.3. RestController与Controller1.4. PathVariable 与RequestParam二、接收复杂嵌套对象参…

复杂系统与人工生命:十年研究概览

来源&#xff1a;集智俱乐部作者&#xff1a;Thomas McAtee、Claudia Szabo译者&#xff1a;陈翔 审校&#xff1a;刘培源编辑&#xff1a;邓一雪导语人工生命&#xff08;artificial life&#xff09;是通过仿真建模、机器技术和生物化学等方式模拟自然生命系统&#xff0c;进…

5.1传输层概述

5.1传输层概述 文章目录传输层概述传输层的两个协议传输层的寻址与端口传输层概述 传输层的两个协议 传输层的寻址与端口

多细胞生命进击之路:单细胞为何放弃自由,长成复杂的多细胞?

来源&#xff1a;集智俱乐部作者&#xff1a;Veronique Greenwood译者&#xff1a;赵雨亭审校&#xff1a;张澳编辑&#xff1a;邓一雪导语人类作为复杂的多细胞生命&#xff0c;似乎理所当然地认为&#xff0c;多细胞生命相对单细胞生命有绝对的优势。但实际上单细胞生命进化为…

5.2 UDP协议

5.2 UDP协议 文章目录用户数据报协议udp概述udp首部形式udp校验用户数据报协议udp概述 udp首部形式 udp校验

焦李成院士:进化优化与深度学习的思考

来源&#xff1a;AI科技评论作者&#xff1a;焦李成整理&#xff1a;维克多编辑&#xff1a;青暮2021年12月17日&#xff0c;西安电子科技大学人工智能学院教授、欧洲科学院外籍院士、IEEE Fellow焦李成受邀参加2021中国计算机大会“下一代演化计算发展趋势”论坛&#xff0c;并…

5.3.1 TCP协议特点和TCP报文段格式

5.3.1 TCP协议特点和TCP报文段格式 文章目录tcp协议的特点tcp 报文段首部格式tcp协议的特点 tcp 报文段首部格式

互补性:从不同的角度思考同一个事物时,发现它同时具有不同甚至相互矛盾的性质...

来源&#xff1a;混沌巡洋舰检验一流智力的标准是头脑中能同时持有两种截然相反的观点&#xff0c;却能并行不悖。——弗朗西斯斯科特菲茨杰拉德显然&#xff0c;这种互补性推翻了学术的本体论。真理是什么&#xff1f;我们之所以要提出彼拉多的问题&#xff0c;并不是出于怀疑…

5.3.2 TCP连接管理

5.3.2 TCP连接管理 文章目录tcp 连接管理tcp的连接简历TCP传输连接中的SYN、ACK、SEQ、 AN分别是什么意思?syn洪泛攻击tcp的连接释放tcp 连接管理 tcp的连接简历 TCP传输连接中的SYN、ACK、SEQ、 AN分别是什么意思? syn洪泛攻击 tcp的连接释放

2021年量子计算的研发现状与未来展望

来源&#xff1a;AI科技评论作者&#xff1a;杏花编辑&#xff1a;青暮从硬件、软件和算法以及各国政策等方面展现量子技术最新进展。超导量子计算过去宣称实现的量子霸权在最新的获得戈登贝尔奖被宣告打破&#xff0c;但谷歌和IBM依然在这一领域有着雄心勃勃的计划。离子阱则凭…

5.3.3 TCP可靠传输

5.3.3 TCP可靠传输 文章目录

【动态规划】洛谷 P1282 多米诺骨牌

【动态规划】洛谷 P1282 多米诺骨牌 时间限制: 1 Sec 内存限制: 128 MB 题目描述 多米诺骨牌有上下2个方块组成&#xff0c;每个方块中有1~6个点。现有排成行的 上方块中点数之和记为S1&#xff0c;下方块中点数之和记为S2&#xff0c;它们的差为|S1-S2|。例如在图8-1中&#…

深度学习在工业推荐如何work?Netflix这篇论文「深度学习推荐系统Netflix案例分析」阐述DL在RS的优劣与经验教训...

来源&#xff1a;专知深度学习在推荐系统中如何发挥作用是一个重要的问题。最近来自Netflix的文章详细阐述了这一点指出&#xff1a;在建模用户物品交互方面&#xff0c;深度学习相比传统基线方法并无太大优势&#xff0c;而对于异质特征的表示融入深度学习则具有很好建模性能。…

5.3.4 TCP流量控制

5.3.4 TCP流量控制 文章目录tcp流量控制tcp流量控制

Nature封面,硅量子计算达到99%的准确率

来源&#xff1a;ScienceAI编辑&#xff1a;萝卜皮在 2022 年 1 月 20 日发布的《Nature》上&#xff0c;有三篇论文独立介绍了基于硅的量子计算平台&#xff0c;它们使用了多量子比特纠缠&#xff1a;一篇来自新南威尔士大学&#xff08;UNSW&#xff09; Andrea Morello 团队…

[poj3261]Milk Patterns

求出后缀数组和height数组&#xff0c;然后二分答案后分组查询&#xff0c;一个块内如果有超过k个那么这个答案就可以。 1 #include<bits/stdc.h>2 using namespace std;3 #define N 500054 int n,m,ans,a[N],b[N],h[N],sum[N],ra[N<<1],sa[N];5 char s[N],s1[N];6…