【计算机图形学】基本图形元素:直线的生成算法

08年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大学生活。此系列是对四年专业课程学习的回顾,索引参见:http://blog.csdn.net/xiaowei_cqu/article/details/7747205

直线的DDA算法

【算法介绍】

设直线之起点为(x1,y1),终点为(x2,y2),则斜率m为:

直线中的每一点坐标都可以由前一点坐标变化一个增量(Dx, Dy)而得到,即表示为递归式:

并有关系:Dy = m • Dx。递归式的初值为直线的起点(x1, y1),这样,就可以用加法来生成一条直线。具体方法是:

直线方向的8个象限

按照直线从(x1,y1)到(x2,y2)的方向不同,分为8个象限。对于方向在第1a象限内的直线而言,D x=1,D y=m。对于方向在第1b象限内的直线而言,取值Dy=1,Dx=1/m。各象限中直线生成时Dx, Dy的取值列在下表之中。

当|dx|>|dy|时,|D x|=1, |D y|=m;否则:Dx=1/m,|Dy|=1

Dx, Dy的符号与dx, dy的符号相同

这两条规律可以导致程序的简化

【算法流程图】

【相关代码】

void PaintArea::drawLineDDA(QPainter &painter,int x0, int y0, int xEnd, int yEnd)

{

int dx=xEnd-x0,dy=yEnd-y0,steps,k;

float xIncrement,yIncrement,x=x0,y=y0;

if(fabs(dx)>fabs(dy)) steps=fabs(dx);

else steps=fabs(dy);

xIncrement=float(dx)/float(steps);

yIncrement=float(dy)/float(steps);

painter.drawPoint(round(x),round(y));

for(k=0;k

x+=xIncrement;

y+=yIncrement;

painter.drawPoint(round(x),round(y));

}

}

直线的Bresenham算法

这个算法由Bresenham在1965年提出。设直线从起点(x1, y1)到终点(x2, y2)。直线可表示为方程y=mx+b。其中

我们的讨论先将直线方向限于1a象限在这种情况下,当直线光栅化时,x每次都增加1个单元,即

而y的相应增加应当小于1。为了光栅化,yi+1只可能选择如下两种位置之一(如图)。

i+1的位置选择yi-1=yi 或者 yi+1=yi+1

选择的原则是看精确值y与yi及yi+1的距离d1及d2的大小而定。计算式为:

如果d1-d2>0,则yi+1=yi+1,否则yi+1=yi。因此算法的关键在于简便地求出d1-d2的符号。将上公式得

d1-d2=2y-2yi-1=2 (xi+1)-2yi+2b-1

用dx乘等式两边,并以Pi=dx(d1-d2)代入上述等式,得

Pi=2xidy-2yidx+2dy+dx(2b-1)

d1-d2是我们用以判断符号的误差。由于在1a象限,dx总大于0,所以Pi仍旧可以用作判断符号的误差。Pi-1为:

Pi+1=Pi+2dy-2dx(yi+1-yi)

误差的初值P1,可将x1, y1,和b代入式(4)中的xi, yi而得到:

P1=2dy-dx

Bresenham算法的优点是:

不用浮点数,只用整数;

只做整数加减法和乘2运算,而乘2运算可以用硬件移位实现。

Bresenham算法速度很快,并适于用硬件实现。

【算法流程图】

【相关代码】

void PaintArea::drawLineBresenham(QPainter &painter, int x0, int y0, int xEnd, int yEnd)

{

int x,y,dx,dy,e;

if(fabs(x0-xEnd)>fabs(y0-yEnd)){

dx=xEnd-x0; dy=yEnd-y0; e=-dx;

x=x0; y=y0;

for(int i=0;i<=dx;i++)

{painter.drawPoint(x,y);

x=x+1; e=e+2*dy;

if(e>=0) {y=y+1; e=e-2*dx; }}

}

else if(fabs(x0-xEnd)>fabs(y0-yEnd)){

dx=xEnd-x0; dy=yEnd-y0; e=-dx;

x=x0; y=y0;

for(int i=0;i<=dx;i++)

{ painter.drawPoint(x,y);

y=y+1; e=e+2*dx;

if(e>=0) {x=x+1; e=e-2*dy; }}

}

}

中点画线法

假定直线斜率k在0~1之间,当前象素点为(xp,yp),则下一个象素点有两种可选择点(xp+1,yp)或P2(xp+1,yp+1)。若P1与P2的中点(xp+1,yp+0.5)称为M,Q为理想直线与x=xp+1垂线的交点。当M在Q的下方时,则取P2应为下一个象素点;当M在Q的上方时,则取P1为下一个象素点。这就是中点画线法的基本原理。

【算法流程图】

【相关代码】

void PaintArea::drawLineMiddle(QPainter &painter, int x0, int y0, int xEnd, int yEnd)

{

int a,b,d,x,y;

if(fabs(x0-xEnd)>fabs(y0-yEnd)){

a=y0-yEnd; b=xEnd-x0; d=2*a+b; x=x0; y=y0;

painter.drawPoint(x,y);

while(x

{ if(d<0) {x++;y++;d+=2*(a+b); }

else{x++;d+=2*a; }

painter.drawPoint(x,y);

}

}

else if(fabs(x0-xEnd)>fabs(y0-yEnd) &&(x0-xEnd))<0)){

a=y0-yEnd; b=xEnd-x0; d=2*a+b; x=x0; y=y0;

painter.drawPoint(x,y);

while(x>xEnd)

{ if(d<0) {x--;y--; d-=2*(a+b); }

else{x--;d-=2*a; }

painter.drawPoint(x,y);

}

}

else if(fabs(x0-xEnd)

a=y0-yEnd; b=xEnd-x0; d=2*a+b; x=x0; y=y0;

painter.drawPoint(x,y);

while(y>yEnd)

{ if(d<0) {y++;x++;d+=2*(a+b); }

else{y++;d+=2*a; }

painter.drawPoint(x,y);

}

}

else if(fabs(x0-xEnd)0)){

a=y0-yEnd; b=xEnd-x0; d=2*a+b; x=x0; y=y0;

painter.drawPoint(x,y);

while(x>xEnd)

{ if(d<0) {x--;y--; d-=2*(a+b); }

else{x--;d-=2*a; }

painter.drawPoint(x,y);

}

}

else if(fabs(x0-xEnd)0){

a=y0-yEnd; b=xEnd-x0; d=2*a+b; x=x0; y=y0;

painter.drawPoint(x,y);

while(y>yEnd)

{ if(d<0) {y++;x++;d+=2*(a+b); }

else{y++;d+=2*a; }

painter.drawPoint(x,y);

}

}

}

软件截图

这个绘图软件是用QT写的,我会另外写一篇介绍编程结构,敬请期待~

结果分析

此次实验自己真的倾注了很大的心血。

因为很喜欢计算机图形学,所以很想做个像模像样的东西出来,于是就下定决心借实验的机会做个简易的windows画板。也是第一次正式的使用QT开发,摸索的过程使得整个实验拖了很长时间。最终的结果还是比较令自己满意的,至少基本功能都实现了,界面也还看得过去。

过于注重表面,算法上功夫不足,有些“舍本逐末”

我是把整个软件做差不多了,才开始细细得来研究图元的基本算法(开始都是调用qt自带的绘制函数)。调试算法的过程才深刻感觉这比整个软件更花时间(可能因为整个软件并没有很复杂的架构)。由于时间有限,很多地方没有细细改进。尤其是对于k的几种情况,就生生的写了很冗余的代码,实在是丑啊。

以后再继续改进。

要改进的地方还有很多。比如算法结构重构,不要写那么冗余。然后再尝试一些填充算法自己实现,还有自己会试着做做简单的图像处理,变形拉伸什么的。

总之,坚持动手,学以致用。

转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7762419

5楼a_xiaozhen1小时前好复杂啊!都有点看不懂!Re: xiaowei_cqu1小时前回复a_xiaozhen这是图形学的基础函数,不过一般都不用自己写的4楼hitalex7小时前原来是位技术女~赞!nPS:我是从豆瓣过来的...Re: xiaowei_cqu1小时前回复hitalex原来是位豆友~3楼tomsoft昨天 22:52不错,我一直在研究动态的矢量图形,有几点说明一下:n1)没有作抗锯齿,可以考虑SuperSample算法,使用BoxFilter就足够了,很简单的。n2)实际在真正实现中很多情况会使用ScanLine算法,而非直接这样绘制,如果您在看图形学算法,注意ScanLine算法;Re: xiaowei_cqu9小时前回复tomsoft您说的我没接触过,回头去看一看,谢前辈指点~2楼z1074971432昨天 20:09继续研究画圆,圆弧之类的n直线裁切,我是研究GUI实现时研究的Re: xiaowei_cqu昨天 21:21回复z1074971432嗯,会更新圆的画法1楼yong199105140昨天 15:41师姐,牛b的呢Re: xiaowei_cqu昨天 16:02回复yong199105140 : )

line划线计算机图像学,【计算机图形学】根本图形元素:直线的生成算法相关推荐

  1. 计算机图形学:Cohen-Sutherland直线段剪裁算法及梁友栋-Barsky裁剪算法(算法原理及代码实现)

    一.算法实现原理 Cohen-Sutherland直线段剪裁算法: 算法原理: (1)判断线段两端是否都落在窗口内,如果是,则线段完全可见,否则进行下一步 (2)判断线段两端是否都落在窗口外,如果是, ...

  2. 华北电力大学计算机图形学实验报告,华北电力大学计算机图形学实验报告分析.doc...

    华北电力大学计算机图形学实验报告分析 科 技 学 院 课程设计(综合实验)报告 ( 2013 -- 2014 年度第 2 学期) 实验名称 OpenGL基本图元绘制实验 课程名称 计算机图形学 | | ...

  3. [转载]一个图形爱好者的书架/白话说学计算机图形学

    1.一个图形爱好者的书架 原文地址:http://blog.csdn.net/nhsoft/archive/2004/06/23/22992.aspx          早几天看到有人把自己在大学四年 ...

  4. 计算机图形动画处理实训报告,西安石油大学计算机图形学 实验报告.doc

    文档介绍: 西安石油大学计算机图形学_实验报告实验报告 -计算机图形学实验大作业 课程名称计算机图形学 实验名称二维绘图系统与计算机动画 姓名 学号 专业班级 成绩 指导教师爨莹 实验报告 课程名称计 ...

  5. 计算机图形学(1)基本图形算法

    计算机图形学--基本图形算法 光栅图形中点的表示 屏幕坐标系在左上角 地址=(Xmax-Xmin)[每行像素点数]*(Y-Ymin)[行数]+(X-Xmin)[行中位置]+基地址 直线扫描转换算法 假 ...

  6. 计算机图形学真实感显示代码,计算机图形学实验 - 真实感图形场景的生成

    <计算机图形学实验 - 真实感图形场景的生成>由会员分享,可在线阅读,更多相关<计算机图形学实验 - 真实感图形场景的生成(4页珍藏版)>请在人人文库网上搜索. 1.计算机图形 ...

  7. 计算机图形学直线线型实验报告,计算机图形学实验报告-直线中点bresenham算法的实现资料.doc...

    计算机图形学实验报告-直线中点bresenham算法的实现资料.doc (10页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 29.90 积分 计算机图形 ...

  8. 计算机图形学01:直线生成算法(DDA算法)

    作者:非妃是公主 专栏:<计算机图形学> 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成.--曾国藩 文章目录 专栏推 ...

  9. 计算机图形学实验报告 裁剪,计算机图形学-实验报告三-图形裁剪算法

    <计算机图形学-实验报告三-图形裁剪算法>由会员分享,可在线阅读,更多相关<计算机图形学-实验报告三-图形裁剪算法(9页珍藏版)>请在人人文库网上搜索. 1.图形裁剪算法1. ...

最新文章

  1. opensuse使用zypper安装软件
  2. fancy approach for making your code listed used for short essays, no need for listing in outline
  3. shell 编程学习笔记(一)
  4. Ubuntu 用户安装 MATE
  5. SCNCHECKPOINT
  6. 深度学习(23)随机梯度下降一: 随机梯度下降简介
  7. Windows Server 2008 R2 搭建FTP服务
  8. 语言题库安装包312mb_大学为什么要考取计算机二级,以后很需要,附二级Msoffice题库...
  9. 谈谈Linux下动态库查找路径的问题
  10. cygwin/msys: fatal error LNK1104: 无法打开文件“kernel32.lib”
  11. 软件是指示计算机运行所需的程序,计算机文化基础知识点
  12. nature 计算机论文,10分钟读懂6篇Nature/Science系列文章
  13. nanomsg应用中的问题整理
  14. SqlServer中的Top * With Ties
  15. 对于最小二乘法的解释
  16. 2000国家大地坐标系
  17. 一个简洁的layui主题,可以用于旅游网页的制作
  18. HDF5 windows编译 release版本、Debug版本
  19. 微信小程序跳转到H5网页
  20. 好的用户界面-界面设计的一些技巧

热门文章

  1. Linux 命令(109)—— ping 命令
  2. oracle查询表在库中所占空间(表名所有字母必须大写‘table_name’)
  3. LuoguP2756 飞行员配对方案问题(最大流)
  4. sscanf 与 sscanf_s的区别
  5. [转载]网站分析的最基本度量(3)——网站分析工具如何辨别UV
  6. 2oracle单行函数
  7. [转]WebGL All in One 全傻瓜简介
  8. 第一节:创建SpringBoot项目并运行HelloWorld
  9. Vue单文件项目自定义组件入门
  10. python27换行_python 27 :用句点字符匹配换行