(1)直线生成算法.doc
直线生成算法——Bresenham法
直线生成算法——Bresenham法最近的研究涉及在像素图上作直线,自己也不想花时间摸索,于是在网上找到了Bresenham的直线生成算法,有一篇博客讲得清晰明了,但是算法上有些问题,我进行了改进和移植,下面讲解Bresenham的直线生成算法时也是参考这篇博文。
1.算法简介图1算法思想:图1中,连接M点和N点的直线经过点B,由于是像素图,所以实际上B 点应该由A点或者C点代替。
当B点更靠近A点时,选择点A(x+1,y+1);当B点更靠近C点时,选择点C(x+1,y)。
因此,当ε+m < 0.5时,绘制(x + 1, y)点,否则绘制(x + 1, y + 1)点,这里ε为累加误差,表达式为:式中:表示在第n次计算时的值,表示在第n+1次计算时的值;m就是直线的斜率。
由于斜率m的值有正有负,有可能为0,也可能为∞,为了避免分别讨论这些情况,将上述公式两边都乘以dx, 并将ε*dx用ξ表示,则有式中:表示在第n次计算时的值,表示在第n+1次计算时的值;dx为起点和终点横坐标之差,dy为起点和终点纵坐标之差。
还需说明一点,由直线斜率的定义故值得注意的是,现在我们只考虑dx > dy,且x,y的增量均为正的情况,但实际上有8种不同的情况(但是算法思想不变),如图2所示如图22.算法程序前文提到的那篇博文提出了一种方法,能将这8种情况都考虑,很巧妙。
但是实际应用时发现程序运行结果不是完全对,多次检查之后将程序进行了修改。
修改后的算法VB程序如下‘**************************************************************************** Type mypos '自定义数据类型x As Integery As IntegerEnd Type‘**************************************************************************** Function Bresenham(arr() As mypos, x1, y1, x2, y2)Dim x!, y!, dx!, dy!, ux%, uy%, eps!Dim cnt%ReDim arr(100)dx = x2 - x1dy = y2 - y1If dx >= 0 Then ux = 1If dx < 0 Then ux = -1If dy >= 0 Then uy = 1If dy < 0 Then uy = -1x = x1y = y1eps = 0dx = Abs(dx): dy = Abs(dy)cnt = 0If dx >= dy ThenFor x = x1 To x2 Step uxcnt = cnt + 1If 2 * (eps + dy) < dx Theneps = eps + dyarr(cnt).x = xarr(cnt).y = yElseeps = eps + dy - dxIf cnt >= 2 Then y = y + uy 'cnt大于2才执行y = y + uy,即排除起始坐标点,否则造成错误结果arr(cnt).x = xarr(cnt).y = yEnd IfNext xElseFor y = y1 To y2 Step uycnt = cnt + 1If 2 * (eps + dx) < dy Theneps = eps + dxarr(cnt).x = xarr(cnt).y = yElseeps = eps + dx - dyIf cnt >= 2 Then x = x + ux 'cnt大于2才执行x = x + ux,即排除起始坐标点,否则造成错误结果arr(cnt).x = xarr(cnt).y = yEnd IfNext yEnd Ifarr(0).x = cnt’记录元素个数End Function如果大家有不同看法,还希望共同讨论3.程序运行结果(VB+ OpenGL)图3图4绘制y=x,0≤x≤10,图3是原程序运行结果,图4时修改后的程序运行结果,原程序运行得到的起点是(0,1),但实际应该是(0,0)图5图6绘制直线[第1个坐标为起点,第2个坐标为终点](5,5)-(15,15)、(5,10)-(15,15)、(5,15)-(15,15)、(5,20)-(15,15)、(5,25)-(15,15);(25,5)-(15,15)、(25,10)-(15,15)、(25,15)-(15,15)、(25,20)-(15,15)、(25,25)-(15,15);(5,5)-(15,15)、(10,5)-(15,15)、(15,5)-(15,15)、(20,5)-(15,15)、(25,5)-(15,15);(5,25)-(15,15)、(10,25)-(15,15)、(15,25)-(15,15)、(20,25)-(15,15)、(25,25)-(15,15);图5是原程序运行结果,图6是修改后的程序运行结果。
第4讲 直线生成
Bresenham算法
对于直线斜率k在0~1之间的情况,从给定线段的左端点 P0(x0, y0)开始,逐步处理每个后续列(x位置),并在扫描线 y值最接近线段的像素上绘出一点
yi+1 y
d2 d1
yi
xi
xi+1
Bresenham算法
对于直线斜率k在0~1之间的情况,从给定线段的左端点 P0(x0, y0)开始,逐步处理每个后续列(x位置),并在扫描线 y值最接近线段的像素上绘出一点
x
void DDALine(int x0,int y0,int x1,int y1,int color) 综合的c程序 int i; float dx, dy, length,x,y; if (fabs(x1-x0)>=fabs(y1-y0)) length=fabs(x1-x0); else length=fabs(y1-y0); dx = (x1-x0)/length; dy=(y1-y0)/length; i=1;x= x0;y= y0; while(i<=length) { SetPixel (int(x+0.5), int(y+0.5), color); x=x+dx; y=y+dy; i++;
光栅化和扫描转换是光栅图形学的基本问题,其算法的好 坏对系统的效率有直接的关系。
直线段的扫描转换
• 假定
(1)编程语言提供了一个显示像素函数: SetPixel(x,y,color); 其中,x和y为像素的位置坐标,color为像素的颜色。 (2)所给出的坐标数据为整数类型
直线段的扫描转换
• 问题
DDA算法
DDA算法与基本算法相比,减少了浮点乘法,提 高了效率。 但是x与dx、y与dy用浮点数表示,每一步要进行 四舍五入后取整,不利于硬件实现,因而效率仍 有待提高。
直线生成算法DDA、Midpoint、Bresenham
1、直线生成算法1.算法分析1)DDA设直线两端点:P1(x1,y1)及 P0(x0,y0),dx=x1-x0,dy=y1-y0直线斜率:k=dy/dx直线方程: y=k*x+b有:y1=k*x1+b=k*x0+k*dx+b=y0+k*dx当dx=1时,有y1=y0+k算法复杂度:加法+取整优点:避免了y=k*x+b 方程中的浮点乘法,比直接用点斜式画线快 缺点:需浮点数加法及取整运算,不利于硬件实现.2)Midpoint当前像素点为P(xP,yP),下一个像素点有两种可选择点P1(xP+1,yP),P2(xP+1,yP+1)。
若M=(xP+1,yP+0.5)为P1与P2的中点,Q 为理想直线与x=xP+1垂线的交点。
x Pi=(xi, yi ) M Q P1 p2y当M 在Q 的上方时,应取P1为下一点;当M 在Q 的下方时,应取P2为下一点;直线段L (P0(x0,y0),P1(x1,y1)),用方程F (x,y )=ax+by+c=0表示 a=y0-y1,b=x1-x0,c=x0y1-x1y0有点与L 的关系:线上:F (x,y )=0上方:F (x,y )>0下方:F (x,y )<0判别式:d=F(M)=F(xP+1,yP+0.5)=a(xP+1)+b(yP+0.5)+cD 是xP,yP 的线性函数,可采用增量计算,提高运算效率:1)若d>=0,取P1,d1=d+a,增量为a2)若d<=,取P2,d2=d+a+b,增量为a+b可用2d 代替d 来摆脱浮点运算,写出仅含整数运算的算法3)Bresenhamy x F(x,y)=0 F(x,y)>0 F(x,y)<0 (x1,y1)(x0,y0)设直线方程为y=kx+b,有y1=y0+k(x-x0)=y0+k是否增1取决于误差项d的值,初始值d0=0X每增加1,有d=d+k令e=d-0.5,e0=-0.5,增量为k当e>=0时,取当前像素(xi,yi)的右上方像素(xi+1,yi+1),e 减小1;当e<0时,更接近于右方像素(xi+1,yi)。
直线的生成算法
实验一基本图形元素生成算法1.实验目的:1)熟练掌握基本图形元素生成算法。
2)对高级语言的图形模式的设定有比较详细的了解。
3)对基本图形类(或函数)的调用方法有一个比较详细的了解。
2.实验内容:该学生自己选定一种基本图形(直线段),编写生成该基本图形的源程序,并能在计算机上编译运行,画出正确的图形。
3.实验步骤:1)DDA算法、Bresenham算法进行比较,选定比较合适的算法。
2)画出程序流程图;3)编写程序的源程序;4)编辑源程序并进行调试;5)进行特殊模式的运行测试,并结合情况进行调整。
6)打印源程序或把源程序以文件的形式提交。
4.实验报告:源代码:main.cpp#include <iostream>#include <cmath>using namespace std;class Point{protected:int xx,yy;public:Point(int a=0,int b=0):xx(a),yy(b){}Point(const Point& p):xx(p.xx),yy(p.yy){}void setPos(int x,int y){xx=x,yy=y;}int getX(){return xx;}int getY(){return yy;}~Point(){}};class Line{protected:Point p1,p2;public:Line(Point p,Point q):p1(p),p2(q){}void DDAline(){//数值微分法绘制直线int dx,dy,epsl,k;float x,y,xIncre,yIncre;dx=p2.getX()-p1.getX();dy=p2.getY()-p1.getY();x=p1.getX(),y=p1.getY();if(fabs(dx)>fabs(dy))epsl=fabs(dx);else epsl=fabs(dy);xIncre=(float)dx/(float)epsl;yIncre=(float)dy/(float)epsl;for(k=0;k<=epsl;k++){cout<<"("<<(int)(x+0.5)<<","<<(int)(y+0.5)<<")"<<endl; x+=xIncre;y+=yIncre;}}void MidBresenhamline(){//k>=0&&k<=1中点Bresenham算法int dx,dy,d,UpIncre,DownIncre,x,y;int m=p1.getX(),n=p2.getX();if(m>n){p1.setPos(p2.getX(),p2.getY());p2.setPos(p1.getX(),p1.getY());}x=p1.getX();y=p1.getY();dx=p2.getX()-p1.getX();dy=p2.getY()-p1.getY();d=dx-2*dy;UpIncre=2*dx-2*dy;DownIncre=-2*dy;while(x<=p2.getX()){cout<<"("<<x<<","<<y<<")"<<" "<<"d="<<d<<endl;x++;if(d<0){y++;d+=UpIncre;}else d+=DownIncre;}}~Line(){}};int main(){int x0,y0,x1,y1;int flag;cout<<"Please enter the value of vairable x0,y0,x1,y1in order:"; cin>>x0>>y0>>x1>>y1;Point pa(x0,y0),pb(x1,y1);//创建两个点对象Line line(pa,pb);//由两个点对象组合成一个线对象cout<<"Please enter the identifier of algorithms:"<<endl;cout<<"1.DDAline"<<endl<<"2.MidBresenhamline"<<endl;cin>>flag;if(1==flag)line.DDAline();else if(2==flag)line.MidBresenhamline();else cout<<"Run Failed!"<<endl;return 0;}流程图:DDA算法绘制直线流程中点Bresenham算法图形:。
直线的生成
实验一: 直线数学上,理想的直线是由无数个点构成的集合,没有宽度。
计算机绘制直线是在显示器所给定的有限个像素组成的矩阵中,确定最佳逼近该直线的一组像素,并且按扫描线顺序,对这些像素进行写操作,实现显示器绘制直线,即通常所说的直线的扫描转换,或称直线光栅化。
由于一图形中可能包含成千上万条直线,所以要求绘制直线的算法应尽可能地快。
本节介绍一个像素宽直线的常用算法:数值微分法(DDA)、中点画线法、Bresenham 算法。
一. DDA(数值微分)算法DDA算法原理:如图1-1所示,已知过端点的直线段;直线斜率为,从的左端点开始,向右端点步进画线,步长=1(个像素),计算相应的坐标;取像素点[ , round(y)] 作为当前点的坐标。
计算,当,即当x每递增1,y递增k(即直线斜率)。
1的情形。
在这种情况下,x每增加1, y最多增加1。
当时,必须把x,y地位互换,y每增加1,x相应增加1/k(请参阅后面的Visual C++程序)。
注意:上述分析的算法仅适用于k二. 生成直线的中点画线法中点画线法的基本原理如图1-2所示。
在画直线段的过程中,当前像素点为P,下一个像素点有两种选择,点P1或P2。
M为P1与P2中点,Q为理想直线与X=Xp+1垂线的交点。
当M在Q的下方时,则P2应为下一个像素点;当M在Q的上方时,应取P1为下一点。
中点画线法的实现:令直线段为L[ p0(x0,y0), p1(x1, y1)],其方程式F(x, y)=ax+by+c=0。
其中,a=y0–y1, b=x1–x0, c=x0y1–x1y0;点与L的关系如下。
在直线上,F(x, y)=0;在直线上方,F(x, y)>0;在直线下方,F(x, y)<0。
把M代入F(x, y),判断F的符号,可知Q点在中点M的上方还是下方。
为此构造判别式d=F(M)=F(xp+1, yp+0.5)=a(xp+1)+b(yp+0.5)+c。
直线算法综述
南昌大学学生姓名:陈凯学号:405906111033学院:机电工程学院专业:机械设计及理论论文题目:直线生成算法文献综述2012年9月14日1直线生成算法综述陈凯(南昌大学机电工程学院江西南昌 330031 )摘要:本文对现有的直线生成算法进行综述,介绍了各种算法的原理、优缺点、算法基础等。
详细说明了基于并行填充模式的直线生成算法,并以此为例子比较了其与Bresenham算法的效率和误差大小,综述了各种算法的适用条件。
关键字:直线算法并行填充模式 Bresenham算法引言直线是光栅图形学中最基本的元素之一, 直线生成算法的效率和质量直接影响着图形应用系统的效率和质量。
直到最近几年,为了提高直线的绘制速度, 仍然有大量的研究工作出现。
这些工作集中在如何一次生成位于直线上尽可能多的像素,在计算机中生成直线的常用算法有数值微分法(DDA)、中点画线法和1965年出现的Bresenham算法。
其中Bresenham算法是依据直线的斜率,快速生成直线,这种算法在直线段接近坐标的时候有很高的效率,但是随着斜率的增大, 其效率会显著下降。
以上所说的各种直线生成算法的特点都是一次生成尽可能的像素的数目。
但是, 若增加每次生成像素的数量, 则会由于pattern数量过多, 造成对误差值判断操作次数增加, 致使直线生成的效率反而会下降。
因此本文查看了大量的文献,找出了生成直线的其余常用算法,对常用的直线生成算法进行综述,并评价其各自的优缺点。
正文1、对称式八步直线生成算法由Bresenham 直线生成算法的基本思想可知, 生成的下一个像素与当前像素之间存在两种关系——沿轴向或沿斜向。
如当前像素点为P, 则下一个像素点12只能选择轴向或者斜向的下一个邻近像素点。
若使用4个像素的生成模式来生成直线, 即当n= 4时, 可以将直线依据其斜率划分为六类, 那么通过研究可供选择的生成模式集,每一种被选取的生成模式与这些直线的斜率范围的关系我们发现,直线的斜率不同, 其可选模式构成的模式集也不同;每类直线可供选择的生成模式集中均包含五种生成模式;直线的斜率决定了生成该直线时可供选择的生成模式集。
直线和圆弧的生成算法
第3章直线和圆弧的生成算法3.1直线图形的生成算法数学上的直线是没有宽度、由无数个点构成的集合,显然,光栅显示器只能近地似显示直线。
当我们对直线进展光栅化时,需要在显示器有限个像素中,确定最优逼近该直线的一组像素,并且按扫描线顺序,对这些像素进展写操作,这个过程称为用显示器绘制直线或直线的扫描转换。
由于在一个图形中,可能包含成千上万条直线,所以要求绘制算法应尽可能地快。
本节我们介绍一个像素宽直线绘制的三个常用算法:数值微分法〔DDA〕、中点画线法和Bresenham算法。
3.1.1逐点比拟法3.1.2数值微分(DDA)法设过端点P0(x0,y0)、P1(x1,y1)的直线段为L(P0,P1),如此直线段L的斜率L的起点P0的横坐标x0向L的终点P1的横坐标x1步进,取步长=1(个像素),用L的直线方程y=kx+b计算相应的y坐标,并取像素点(x,round(y))作为当前点的坐标。
因为:y i+1= kx i+1+b= k1x i+b+k∆x= y i+k∆x所以,当 x =1; y i+1= y i+k。
也就是说,当x每递增1,y递增k(即直线斜率)。
根据这个原理,我们可以写出DDA〔Digital Differential Analyzer〕画线算法程序。
DDA画线算法程序:void DDALine(int x0,int y0,int x1,int y1,int color){ int x;float dx, dy, y, k;dx = x1-x0;dy=y1-y0;k=dy/dx,;y=y0;for (x=x0;x< x1;x++){ drawpixel (x, int(y+0.5), color);y=y+k;}}注意:我们这里用整型变量color表示像素的颜色和灰度。
举例:用DDA方法扫描转换连接两点P0〔0,0〕和P1〔5,2〕的直线段。
x int(y+0.5) y0 0 01 02 13 14 2图3 直线段的扫描转换注意:上述分析的算法仅适用于|k| ≤1的情形。
计算机图形学直线段生成绘制的实现算法
计算机图形学直线段⽣成绘制的实现算法实验⼆直线段⽣成绘制的实现算法班级 10信计专接本学号 20100504008 姓名吴晓楠分数⼀、实验⽬的和要求:1.了解计算机图形学的原理、⽅法和应⽤。
2.熟悉直线的⽣成算法,掌握直线的绘制3.实现C语⾔编写图形程序。
学会了解VC++的基本应⽤同时了解TC图形环境配置,学习简单的图形画法,并⽐较画法的优劣,尝试在计算机实现,得到图形,验证⽐较图形。
⼆、实验内容:1、掌握直线段的⽣成算法,并⽤C/WIN-TC/VC++实现算法,包括中点法⽣成直线,微分数值法⽣成直线段等。
2、编程实现DDA算法、Bresenham算法、中点画线法绘制直线段三、实验结果分析1、⽣成直线的DDA算法算法思想:⼀个坐标轴上以单位间隔增量,决定另⼀个坐标轴上最靠近线段路径的对应整数值。
假定x2﹣x1的绝对值⼤于y2﹣y1的绝对值,取x为⼀个象素单位长,即x 每次递增⼀个象素,然后利⽤下式计算相应的y值:yk+1﹦yk﹢△y﹦yk﹢m·△x 对于|m|>1的线段,可通过计算由Y⽅向的增量△y引起的改变来⽣成直线:xk+1﹦xk﹢△x﹦xk﹢m·△y⽣成直线的DDA算法思想是源⽤初中直线的⽅程得出来的,⽽⽣成直线的中点算法是通过将DDA算法的⽅程式改为隐函数形式,然后通过与中点的⽐较确定该取的像素,绘制图线。
/* DDA */#includevoid linedda(int x0,int y0,int x1,int y1,int color){int x,dy,dx,y;float m;dx=x1-x0;dy=y1-y0;m=dy/dx;y=y0;for(x=x0;x<=x1;x++){putpixel(x,(int)(y+0.5),color);y+=m;}}main(){int a,b,c,d,e;int graphdriver=DETECT;int graphmode=0;initgraph(&graphdriver,&graphmode,""); cleardevice();a=0;b=100;c=200;d=300;e=200;linedda(a,b,c,d,e);getch();closegraph();}运⾏结果:VC++环境:#include#include// 四舍五⼊int Round(float x){return (int)(x < 0 ? x - 0.5 : x + 0.5); }// 使⽤ DDA 算法画任意斜率的直线(包括起始点,不包括终⽌点)void Line_DDA(int x1, int y1, int x2, int y2, int color){float x, y; // 当前坐标点float cx, cy; // x、y ⽅向上的增量int steps = abs(x2 - x1) > abs(y2 - y1) ? abs(x2 - x1) : abs(y2 - y1); x = (float)x1;y = (float)y1;cx = (float)(x2 - x1) / steps;cy = (float)(y2 - y1) / steps;for(int i = 0; i < steps; i++){putpixel(Round(x), Round(y), color); // 在坐标 (x, y) 处画⼀个 color 颜⾊的点x += cx;y += cy;}}// 主函数void main(){initgraph(640, 480);// 测试画线Line_DDA(100, 100, 100, 478, RED);// 按任意键退出getch();}2、Bresenham直线算法是⽤来描绘由两点所决定的直线的算法,它会算出⼀条线段在 n 维光栅上最接近的点。
《计算机图形学》实验报告
《计算机图形学》实验报告一、实验目的计算机图形学是一门研究如何利用计算机生成、处理和显示图形的学科。
通过本次实验,旨在深入理解计算机图形学的基本原理和算法,掌握图形的生成、变换、渲染等技术,并能够运用所学知识解决实际问题,提高对图形学的应用能力和编程实践能力。
二、实验环境本次实验使用的编程语言为 Python,使用的图形库为 Pygame。
开发环境为 PyCharm。
三、实验内容1、直线的生成算法DDA 算法(Digital Differential Analyzer)Bresenham 算法DDA 算法是通过计算直线的斜率来确定每个像素点的位置。
它的基本思想是根据直线的斜率和起始点的坐标,逐步计算出直线上的每个像素点的坐标。
Bresenham 算法则是一种基于误差的直线生成算法。
它通过比较误差值来决定下一个像素点的位置,从而减少了计算量,提高了效率。
在实验中,我们分别实现了这两种算法,并比较了它们的性能和效果。
2、圆的生成算法中点画圆算法中点画圆算法的核心思想是通过判断中点的位置来确定圆上的像素点。
通过不断迭代计算中点的位置,逐步生成整个圆。
在实现过程中,需要注意边界条件的处理和误差的计算。
3、图形的变换平移变换旋转变换缩放变换平移变换是将图形在平面上沿着指定的方向移动一定的距离。
旋转变换是围绕一个中心点将图形旋转一定的角度。
缩放变换则是改变图形的大小。
通过矩阵运算来实现这些变换,可以方便地对图形进行各种操作。
4、图形的填充种子填充算法扫描线填充算法种子填充算法是从指定的种子点开始,将相邻的具有相同颜色或属性的像素点填充为指定的颜色。
扫描线填充算法则是通过扫描图形的每一行,确定需要填充的区间,然后进行填充。
在实验中,我们对不同形状的图形进行了填充,并比较了两种算法的适用情况。
四、实验步骤1、直线生成算法的实现定义直线的起点和终点坐标。
根据所选的算法(DDA 或Bresenham)计算直线上的像素点坐标。
直线生成算法
中点画线法
• •void Midpoint Line (int x0,int y0,int x1, int y1,int color) { int a, b, d1, d2, d, x, y; • a=y0-y1; b=x1-x0; d=2*a+b; • d1=2*a ; d2=2* (a+b); • x=x0; y=y0; • putpixel(x, y, color); • while (x<x1) • { if (d<0) {x++; y++; d+=d2; } • else {x++; d+=d1;} • putpixel (x, y, color); • } /* while */ • } /* mid PointLine */
P2 Q
P=(xp,yp) P1
∴欲判断 M 点是在 Q 点上方还是在 Q 点下方,只需把 M 代入 F(x,y),并检查它的符号。
中点画线法
构造判别式:d=F(M)=F(xp+1,yp+0.5) =a(xp+1)+b(yp+0.5)+c 当d<0,M在直线(Q点)下方,取右上 方P2; 当d>0,M在直线(Q点)上方,取右方 P1; 当d=0,选P1或P2均可,约定取P1; 能否采用增量算法呢?
批注本地保存成功开通会员云端永久保存去开通
计算机地图制图
• Turbo C提供了非常丰富的图形函数, 所有 图形函数的原型均在graphics. h中,将集成 开发环境Options/Linker中的Graphics lib选 为on, 只有这样才能保证正确使用图形函数。
直线生成算法 DDA画线算法、中点画线算法、Bresenham画线算法
101x x y y x y k --=∆∆=Bkx y i i +=()()111111<+==∆∆+=∆++=+∆+=+=++++k ky y x let xk y y x k B kx B x x k B kx y i i i i i i i i ()111111>+==∆∆+-=-=+++k k x x y let ky k B k y k B k y x i i i i i 实验一、直线生成算法DDA 画线算法一 .名称:DDA 画线算法;二 . 算法分析:1.设直线两端点为:P1(x1,y1)及 P0(x0,y0),2.则直线斜率3.则直线方程为4.当 k <1 , x 每增加1,y 最多增加1(或增加小于1)。
5.当 k>1 ,y 每增加1,x 最多增加1 (或增加小于1) 。
y ix i y i +1 x i +1三.算法实现:void CHuayahuaView::OnDda() //DDA画直线{// TODO: Add your command handler code hereCDC* pdc1 = GetDC();int color = RGB(255,0,0);int x1=10,y1=20,x2=200,y2=200;double k=(y2-y1)*1.0/(x2-x1);//k<1;double y=y1;for(int i=x1;i<=x2;i++){pdc1->SetPixel(i,(int)(y+0.5),color);y=y+k;}ReleaseDC(pdc1);}四:程序截图:中点画线算法一.实验名称:中点画线算法二.算法分析:直线方程直线将二维空间划分为三个区域:如F(x,y)=0, 则(x,y) 在直线上如F(x,y)<0, 则(x,y)在直线下方如F(x,y)>0, 则(x,y)在直线上方条件: a= -(y1-y0)b=(x1-x0)c= -B(x1-x0)三.代码实现:void CHuayahuaView::MidPointLine(){// TODO: Add your command handler code hereCDC* pdc1 = GetDC();int color = RGB(255,0,0);int x1=30,y1=50,x2=200,y2=100;//斜率;int x,y,a,b,d,d0,d1,d2;a=y2-y1;b=x2-x1;d=2*a+b;d1=2*a;d2=2*(a+b);x=x1,y=y1;pdc1->SetPixel(x,(int)(y+0.5),color);while(x < x2){if(d>0){x++;y++;d+=d2;}else{x++;d+=d1;}pdc1->SetPixel(x,(int)(y+0.5),color);}ReleaseDC(pdc1);}四.程序截图:Bresenham画线算法一.算法名称:Bresenham画线算法二.算法分析:定义决策变量d = d+k (0<k<1)设0<k<1,如直线上的一点为(x,y),则点,为: (x+1,y) (d<0.5) 或(x+1,y+1)(d>=0.5) 当d>1时,让以证0<=d<1d0=0定义决策变量d = d+k (0<k<1)设0<k<1,如直线上的一点为( x,y), 则下一点为: (x+1,y) (d<0.5) 或(x+1,y+1)(d>=0.5) 当d>1时, 让d=d-1,以保证0<=d<1定义决策变量e = d-0.5 (0<k<1),e0 = -0.5则下一点为:(x+1,y) (e<0) 或(x+1,y+1)(e>=0) 当e >0时, 让e=e-1, (重新初始化误差项)由于算法只用到误差项的符号,为了改用整数以避免除法,可以作如下替换:e = 2*e*dx定义决策变量e = 2*e*dx, e0 = - dx;e=e +2*dy则下一点为: (x+1,y) (e <0) ;或(x+1,y+1)(e >=0) 当e >0时, 让e= e - dx, (重新初始化误差项)三.算法实现:void CHuayahuaView::Breshnham(){// TODO: Add your command handler code hereCDC* pdc2 = GetDC();int color = RGB(255,0,0);int x1=50,y1=50,x2=200,y2=150;int x,y,dx,dy,e;dx=x2-x1;dy=y2-y1;e=-dx;x=x1;y=y1;for(int i=0;i<=dx;i++){pdc2->SetPixel(x,(int)(y+0.5),color);x++;e=e+2*dy;if(e>=0){y++;e=e-2*dx;}}ReleaseDC(pdc2);}四:程序运行截图:。
计算机图形学 直线生成算法实现
实验二直线生成算法实现班级 08信计学号 80姓名分数一、实验目的和要求:1、理解直线生成的基本原理2、掌握几种常见的直线的生成算法3、实现直线生成的算法二、实验内容:1.了解直线的生成原理2.掌握几种基本的直线生成算法:DDA算法、bresenham画线法、中点画线法3.实现直线生成的,在屏幕上任意生成一条直线三、实现程序程序1#define pi 3.141592#define MAX(a,b) (a>b)? a:b#define MIN(a,b) (a<b)? a:b#include "graphics.h"#include "math.h"struct rectangle{int xmin;int xmax;int ymin;int ymax;};struct point{float x;float y;};struct point pot[2];struct rectangle rect={150,490,100,380};int x=0,y=0;void zhongxing(int x,int y,int s){ int i;for(i=x-5;i<=x+5;i++){ putpixel(i,y,s);}for(i=y-5;i<=y+5;i++){ putpixel(x,i,s);}}void add(int x,int y,int i){pot[i].x=x;pot[i].y=y;}int clip(float q,float d,float *t0,float *t1){ float r;if(q<0){ r=d/q;if(r>*t1)return(0);else if(r>*t0){ *t0=r;return(1);}}else if(q>0){ r=d/q;if(r<*t0)return(0);else if(r<*t1){ *t1=r;return(1);}}else if(d<0)return(0);return(1);}void liang(struct point * pot,struct rectangle * rect){ float delatx,delaty,t0,t1;t0=0;t1=1;delatx=pot[1].x-pot[0].x;if(clip(-delatx,pot[0].x-rect->xmin,&t0,&t1))if(clip(delatx,rect->xmax-pot[0].x,&t0,&t1)){ delaty=pot[1].y-pot[0].y;if(clip(-delaty,pot[0].y-rect->ymin,&t0,&t1))if(clip(delaty,rect->ymax-pot[0].y,&t0,&t1)){ line((int)(pot[0].x+t0*delatx),(int)(pot[0].y+t0*delaty), (int)(pot[0].x+t1*delatx),(int)(pot[0].y+t1*delaty)); }}}void main(){int driver=DETECT,mode; int i=0,j,key; registerbgidriver(EGAVGA_driver);initgraph(&driver,&mode,"\\tc"); initgraph(&driver,&mode,"\\tc");zhongxing(x,y,4);setcolor(3);rectangle(150,100,490,380);/**/for(;;){ if(bioskey(1)){ key=bioskey(0);if(key==0x4d00){ zhongxing(x,y,0);x+=5;zhongxing(x,y,4);rectangle(150,100,490,380);}if(key==0x011b){printf("esc be press");break;}if(key==0x4b00){ zhongxing(x,y,0);x-=5;zhongxing(x,y,4);rectangle(150,100,490,380);}if(key==0x5000){zhongxing(x,y,0);y+=5;zhongxing(x,y,4);rectangle(150,100,490,380);}if(key==0x4800){zhongxing(x,y,0);y-=5;zhongxing(x,y,4);rectangle(150,100,490,380);}if(key==0x1c0d){ add(x,y,i);circle(x,y,3);i+=1;}if(key==0x3920){liang(pot,&rect);for(j=0;j<2;j++){ pot[j].x=0;pot[j].y=0;}i=0;}}}getch();closegraph();}程序2(1)DDA算法程序实现的完整源程序#include<stdio.h>#include<graphics.h>#include<math.h>#define YS 100000dda_line(int xa,int ya,int xb,int yb,int c){float delta_x,delta_y,x,y;int dx,dy,steps,k;dx=xb-xa;dy=yb-ya;if(abs(dx)>abs(dy)) /*判断步长的方向*/steps=abs(dx); /*steps作为控制数K<1*/elsesteps=abs(dy); /*steps作为控制数K>1*/delta_x=(float)dy / (float)steps; /*值为±1域±1/m*/ delta_y=(float)dy / (float)steps; /*值为±1域±m*/ x=xa;y=ya;putpixel(x,y,c); /*画起点,c为点的颜色*/for(k=1;k<=steps;k++) /*循坏画点成直线*/{x+=delta_x;y+=delta_y;putpixel(x,y,c);delay(YS);}}main(){int x1=250,y1=250,x2=300,y2=300,c=5;int dx,dy,n,k,i,f;int x,y;int gdriver,gmode;gdriver=DETECT;initgraph(&gdriver,&gmode," ");dda_line(x1,y1,x2,y2,c);getch();closegraph();}(2)改进的Bresenham画线算法程序实现的完整源程序#include<stdio.h>#include<graphics.h>#include<math.h>#define YS 100000bresenham_line(int x0,int y0,int x1,int y1,int c){int x,y,dx,dy,e,i;dx=x1-x0;dy=y1-y0;e=-dx;x=x0,y=y0;for(i=0;i<=dx;i++){putpixel(x,y,c++);/*c++不同描点不同颜色*/delay(YS);x++,e=e+2*dy;if(e>0){y++;e=e-2*dx;}}}main(){int x0=100,y0=100,x1=200,y1=200,c=1;int gdriver,gmode;gdriver=DETECT;initgraph(&gdriver,&gmode," ");bresenham_line(x0,y0,x1,y1,c);getch();closegraph();}(3)中点算法实现的完整源程序#include <stdio.h>#include <stdlib.h>#include <math.h>#include <conio.h>#include <graphics.h>#define rad 0.0174532925#define NUMBER 24/*此程序写出的图形,(0,0)在左上方,即以原y轴的负半轴为正,x轴不变,类似于抛物运动。
直线生成算法的实现
直线生成算法的实现1.数字微分法:数字微分法是直线生成算法的一种基本方法,其核心思想是通过对直线的斜率进行离散化处理,从而得到直线上的像素点。
具体步骤如下:步骤1:根据直线的起点和终点坐标,计算直线的斜率k=(y2-y1)/(x2-x1)。
步骤2:根据斜率k的值,判断直线属于四种情况:0<=k<=1、k>1、-1<=k<0、k<-1步骤3:对于不同的斜率范围,采取不同的策略进行像素点的生成。
对于斜率0<=k<=1,直线的横坐标增加1,纵坐标按照斜率增加1,每次增加1后判断纵坐标是否需要增加1对于斜率k>1,直线的纵坐标增加1,横坐标按照1/k增加。
每次增加1后判断横坐标是否需要增加1对于斜率-1<=k<0,直线的横坐标减少1,纵坐标按照斜率减少1,每次减少1后判断纵坐标是否需要减少1对于斜率k<-1,直线的纵坐标减少1,横坐标按照1/,k,减少。
每次减少1后判断横坐标是否需要减少1步骤4:重复步骤3直到直线上所有的像素点都生成完毕。
2. Bresenham算法:Bresenham算法是一种角度固定的画线算法,通过判断像素点与理想直线之间的距离来确定下一个像素点的位置。
具体步骤如下:步骤1:根据直线的起点和终点坐标,计算直线的斜率k=(y2-y1)/(x2-x1)。
步骤2:初始化误差项d=-1/2步骤3:循环直到达到直线的终点。
步骤4:根据斜率k的值,判断直线属于四种情况。
对于0<=k<=1,判断d<k-1/2,如果满足则x坐标加1,否则x、y坐标同时加1对于k>1,判断d<-1/2,如果满足则y坐标加1,否则x、y坐标同时加1对于-1<=k<0,判断d>k+1/2,如果满足则x坐标减1,否则x、y坐标同时加1对于k<-1,判断d>-1/2,如果满足则y坐标减1,否则x、y坐标同时加1步骤5:更新误差项d=d+k。
直线生成算法
}else{
g.drawLine(x0,y0,x0,y0-= 20);
d_1+= -2 *b* 20;
}
}
}
}
g.setColor(c);
}
实验结果
在下图中原点位于左上点,水平向右为X轴正方向,垂直向下为Y轴正方向。
DDA算法:
通过给定的斜率k,描绘出一条直线;
贵州大学计算机图形学实验报告
学院:计算机科学与信息学院专业:软件工程班级:
姓名
学号
实验组
实验时间
指导教师
成绩
实验项目名称
实验一直线生成算法
实验目的
通过本实验,了解并掌握在光栅显示系统中直线的生成和显示算法.
实验要求
1、能够使用DDA数值微分法绘制直线;
2、通过给定的斜率k,描绘出一条直线;
3、能够使用中点画线算法绘制|k|<=1的直线。
能够使用中点画线算法绘制|k|<=1的直线。
能够使用中点画线算法绘制|k|>=1的直线
实验总结
在本次实验中,我对图形的了解跟具体了,并且也加深了自己对java基本语法的一些巩固,还掌握了一些基本的划线算法原理,但是编写程序的过程不是很顺利,自己对算法的了解起初不是很深刻,对伪码的解读能力不是很强,在调试过程中,一直出现了很多bug,而且自己代码的集成度不是很高,自己的界面很粗糙,相比星期一同学演示的c#代码,我的界面非常不能入目,在以后的实验中,我要尽量使自己的代码少出bug,并且也会注重自己的界面。争取得到更好的效果。
Color c = g.getColor();
g.setColor(Color.RED);
计算机图形学-直线的生成算法的实现
实验二 直线的生成算法的实现班级 08信计2班 学号 59 姓名 分数一、实验目的和要求1.理解直线生成的基本原理。
2.掌握几种常用的直线生成算法。
3.利用Visual C++实现直线生成的DDA 算法。
二、实验内容1.了解直线的生成原理,尤其是Bresenham 画线法原理。
2.掌握几种基本的直线生成算法:DDA 画线法、Bresenham 画线法、中点画线法。
3.利用Visual C++实现直线生成的DDA 算法,在屏幕上任意生成一条直线。
三、实验步骤1.直线的生成原理:(1)DDA 画线法也称数值微分法,是一种增量算法。
是一种基于直线的微分方程来生成直线的方法。
(2)中点画线法原理以下均假定所画直线的斜率[0,1]k ∈,如果在x 方向上的增量为1,则y 方向上的增量只能在01之间。
中点画线法的基本原理是:假设在x 坐标为p x 的各像素点中,与直线最近者已经确定为(,)p p P x y ,用小实心圆表示。
那么,下一个与直线最近的像素只能是正右方的1(1,)p p P x y +,或右上方的2(1,1)p p P x y ++,用小空心圆表示。
以M 为1P 和2P 的中点,则M 的坐标为(1,0.5)p p x y ++。
又假设Q 是理想直线与垂直线1p x x =+的交点。
显然,若M 在Q 的下方,则2P 离直线近,应取2P 为下一像素点;若M 在Q 的上方,则1P 离直线近,应取1P 为下一像素点。
(3)B resenham 画线法原理直线的中点Bresenham 算法的原理:每次在主位移方向上走一步,另一个方向上走不走步取决于中点偏差判别式的值。
给定理想直线的起点坐标为P0(x0,y0),终点坐标为P1(x1,y1),则直线的隐函数方程为:0b kx y y)F(x,=--= (3-1)构造中点偏差判别式d 。
b x k y y x F y x F d i i i i M M -+-+=++==)1(5.0)5.0,1(),(⎩⎨⎧≥<+=+)0( )0( 11d y d y y i i i(1) 当d<0时b x k y y x F d i i i i i -+-+=++=+)2(5.1)5.1,2(1k d k b x k y i i i -+=-+-+-+=11)1(5.0⑵ 当d ≥0时b x k y y x F d i i i i i -+-+=++=+)2(5.0)5.0,2(1k d k b x k y i i i -=--+-+=)1(5.02.实现前面所述的各种直线生成算法,包括DDA 算法、中点生成算法、Bresenham 生成算法等。
计算机图形学 3.1直线生成算法
yi 0.5 k ( xi 1) b 1 k d i 1 k
⑵当d≥0时
(3-4)
d i 1 F ( xi 2, yi 0.5) yi 0.5 k ( xi 2) b yi 0.5 k ( xi 1) b k d i k
P2 Q
∴欲判断M点是在Q点上方还是
在Q点下方,只需把M代入F(x,y), 并检查它的符号。
P=(xp,yp) P1
3.1.2 中点画线法
构造判别式: d=F(M)=F(xp+1,yp+0.5) =yp+0.5-k(xp+1)-b 当d<0,M在直线(Q点)下方,取右 上方P2;
P2 Q
当d>0,M在直线(Q点)上方,取正
(3-5)
2.中点偏差判别式的初始值
直线的起点坐标为P0(x0,y0),x为主位 移方向。因此,第一个中点是(x 0+1,y 0+0.5),相应的d的初始值为:
d 0 F ( x0 1, y0 0.5) y0 0.5 k ( x0 1) b
y 0 kx0 b k 0.5
已知起点、终点,欲生成一条直线,算法应满足
几点要求:
(1)所画的线要直; (2)具有精确的起点和终点; (4)画直线速度快。
(3)所显示的亮度沿直线不变,与直线的长度和方向无关;
3.1.1 数值微分法(DDA算法)
假定直线的起点、终点分别为:(x0,y0), (x1,y1),且都为整数。
。
。 。
(X i , Yi)
M(x i+2,y i+1.5) M(x i+1,y i+0.5) P(xi,yi) M(x i+1,y i+0.5) P(xi,yi)
直线生成算法
1、作业名称直线生成算法2、算法实现(代码)//line.h#ifndef _LINE_H_#define_LINE_H_#include<windows.h>class CLine{private:COLORREF m_color;HDC m_hdc;public:CLine(HDC,COLORREF);void Draw_Line_DDA(int x1,int y1,int x2,int y2);void Draw_Line_MID(int x1,int y1,int x2,int y2);void Draw_Line_Bresham(int x1,int y1,int x2,int y2); };#endif//Line.cpp#include"line.h"#include<algorithm>#define abs(x) ((x)>0?(x):-(x))CLine::CLine(HDC hdc,COLORREFcolor):m_hdc(hdc),m_color(color){}void CLine::Draw_Line_DDA(int x1,int y1,int x2,int y2) {float dx,dy,k;switch(abs(x2-x1)>abs(y2-y1)){case true:{int x;float y;if(x1>x2){std::swap(x1,x2);std::swap(y1,y2);}dx=x2-x1;dy=y2-y1;k=dy/dx;y=y1;for(x=x1;x<=x2;++x){SetPixel(m_hdc,x,int(y+0.5),m_color);y=y+k;}}break;case false:{int y;float x;if(y1>y2){std::swap(x1,x2);std::swap(y1,y2);}dx=x2-x1;dy=y2-y1;k=dx/dy;x=x1;for(y=y1;y<=y2;++y){SetPixel(m_hdc,int(x+0.5),y,m_color);x=x+k;}}break;}}void CLine::Draw_Line_MID(int x1,int y1,int x2,int y2) {int a,b,d1,d2,d,x,y;if(x2<x1){d=x1;x1=x2;x2=d;d=y1;y1=y2;y2=d;}a=y1-y2;b=x2-x1;x=x1;y=y1;if(a<=0&&a>=-b){d=2*a+b;d1=2*a;d2=2*(a+b);while(x<=x2){SetPixel(m_hdc,x,y,m_color);if(d<=0){x++;y++;d+=d2;}else{x++;d+=d1;}}}if(a>0&&a<=b){d=2*a-b;d1=2*(a-b);d2=2*a;while(x<=x2){SetPixel(m_hdc,x,y,m_color);if(d>0){x++;y--;d+=d1;}else{x++;d+=d2;}}}if(a<-b){d1=2*(a+b);d2=2*b;while(y<=y2){SetPixel(m_hdc,x,y,m_color);if (d>0){x++;y++;d+=d1;}else{y++;d+=d2;}}}if(a>b){d=a-2*b;d2=2*(a-b);while(y>=y2){SetPixel(m_hdc,x,y,m_color);if(d<=0){x++;y--;d+=d2;}else{y--;d+=d1;}}}}void CLine::Draw_Line_Bresham(int x1,int y1,int x2,int y2) {int x,y,dx,dy,e;switch(abs(x2-x1)>abs(y2-y1)){case true:{if(y1>y2){std::swap(x1,x2);std::swap(y1,y2);}x=x1;y=y1;dx=x2-x1;dy=y2-y1;e=-dx;for(int i=0;i<=dx;++i){SetPixel(m_hdc,x,y,m_color);++x;e+=dy<<1;if(e>=0){++y;e-=dx<<1;}}x=x2;y=y2;for(int i=0;i>=dx;--i){SetPixel(m_hdc,x,y,m_color);++x;e-=dy<<1;if(e<=0){--y;e-=dx<<1;}}}break;case false:{if(x1>x2){std::swap(x1,x2);std::swap(y1,y2);}x=x1;y=y1;dx=x2-x1;dy=y2-y1;e=-dy;for(int i=0;i<=dy;++i){SetPixel(m_hdc,x,y,m_color);++y;e+=dx<<1;if(e>=0){++x;e-=dy<<1;}}x=x2;y=y2;for(int i=0;i>=dy;--i){SetPixel(m_hdc,x,y,m_color);++y;e-=dx<<1;if(e<=0){--x;e-=dy<<1;}}}break;}}//winmain.cpp#include<windows.h>#include"line.h"#include<time.h>LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){int start,end;HDC hdc;PAINTSTRUCT ps;CLine *gra1,*gra2,*gra3;char ch[256];switch( msg ){case WM_PAINT:hdc=BeginPaint(hWnd, &ps);gra1=new CLine(hdc,RGB(128,0,255));gra2=new CLine(hdc,RGB(255,128,0));gra3=new CLine(hdc,RGB(0,255,128));gra1->Draw_Line_DDA(300,200,120,258);gra1->Draw_Line_DDA(120,258,230,105);gra1->Draw_Line_DDA(230,105,230,295);gra1->Draw_Line_DDA(230,295,120,142);gra1->Draw_Line_DDA(120,142,300,200);gra2->Draw_Line_MID(300,300,120,358);gra2->Draw_Line_MID(120,358,230,205);gra2->Draw_Line_MID(230,205,230,395);gra2->Draw_Line_MID(230,395,120,242);gra2->Draw_Line_MID(120,242,300,300);gra3->Draw_Line_Bresham(400,300,220,358);gra3->Draw_Line_Bresham(220,358,330,205);gra3->Draw_Line_Bresham(330,205,330,395);gra3->Draw_Line_Bresham(330,395,220,242);gra3->Draw_Line_Bresham(220,242,400,300);delete gra1;delete gra2;delete gra3;EndPaint(hWnd,&ps);break;case WM_DESTROY:PostQuitMessage( 0 );return 0;}return DefWindowProc( hWnd, msg, wParam, lParam );}INT WINAPI WinMain(HINSTANCEhInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd ){WNDCLASSwc={CS_HREDRAW|CS_VREDRAW,MsgProc,0,0,hInstan ce,NULL,LoadCursor(NULL,IDC_ARROW),HBRUSH(6),NULL,TEXT("win32")};RegisterClass(&wc);HWND hWnd=CreateWindow( TEXT("win32"), TEXT("直线的生成算法"),WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, wc.hInstance, NULL );ShowWindow( hWnd, SW_SHOWDEFAULT );UpdateWindow( hWnd );MSG msg={0};while( msg.message!=WM_QUIT ){if(PeekMessage( &msg,NULL, 0u, 0u,PM_REMOVE ) ){TranslateMessage( &msg );DispatchMessage( &msg );}}UnregisterClass(TEXT("win32"),wc.hInstance);return 0;}3、算法分析DDA算法设直线两端点为:P1(x1,y1)及P2(x2,y2),则直线斜率为k=(y2-y1)/(x2-x1)1|k|<1时当△x=1时△y=k y i+1=y i+k|k|>1时当△y=1时△x=1/k x i+1=x i+1/k优点:与基本算法相比,在扫描过程中减少了浮点运算,提高了效率。
直线生成算法
}
1.2 正负法
基本原理:假设直线斜小于1。设 P=(x,y)是直线上的一点(用Δ表 示),点P正右方或右上方的点分 别为(xi+1,yi)和(xi+1,yi+1),设M表 示PB和PT的中点,设Q是直线与 垂直线x=xi+1的交点,若M在Q的 下方,则 PT 离直线近,应取为 下一个像素;否则应取PB 。
当 xi1 0 当 xi1 0
( (
xi1 xi1
) )
m m,
1,
当 (xi1) 0 当 (xi1) 0
Bresenham 算法源代码
m=(double)dy/(double)dx; e = m–0.5; for(i=0;i<dx;i++) { gl_Point(x,y); if(e>=0){
模式3
模式4
0.75×2≥yi+2 –yir>0.5×2
yi+2–yir >0.75×2
1.4 改进#43;2–yi,r –0.5,可得下面的递推公式
( xi4 ) yi4 yi2,r 0.5
yi2 yi2,r 2m 0.5
yi2
yi,r
y=y+1; e=e–1; } x=x+1;e=e+m; } 其中dy=ye–ys,dx=xe–xs。 缺点:有除法和浮点数
1.4 改进后的Bresenham 算法
基本原理:设0≤m≤1,每次循环绘制两个象素,共有四种绘 制模式
模式1
模式2
yi+2-yir ≤0.25×2
0.5×2≥yi+2 –
yir>0.25×2
d0 a 0.5b
x x 1
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程名称:计算机图形学指导教师:罗晓辉
上机实践名称:基本图形(直线)生成算法
年级:2008
姓名:孔广波
学号:312008*********
上机实践成绩:
上机实践日期:2011-4-10 实验一: 直线生成算法
上机实践报告
一、实验目的
理解直线生成的基本原理,掌握儿种常见的直线生成算法,利用Microsoft Visual C++6.0实现直线生成的DDA算法。
二、实验内容:
1)了解直线的生成原理。
2)掌握儿种基本的直线生成算法:DDA画线法、Bresenham画线法、中点画线法。
3)利用Microsoft Visual C++6.0实现直线生成的DDA算法,在屏幕上任意生成一条直线。
三、实验步骤:
1)预习教材关于直线的生成原理。
2)仿照教材关于直线生成的DDA算法,使用Microsoft Visual C++6.0实现该算法。
3)调试、编译、运行程序。
四、实验分析、源程序和结果:
(1.1)中点算法分析:
中点画线算法原理示意图
直线斜率:k属于[0, 1]
线段的隐式方程:F(x,y) = ax + by + c = 0
((x0 , y0), ( xl , yl )为两端点,式中a = yO - yl , b = xl - xO , c = xO * yl - xl * yO)
直线上方的点:F(x , y) > 0
直线下方的点:F ( x , y ) < 0
构造判别式:d = F(M) = F(Xp+l,Yp + 0.5)
由d>0, V0 可判定下一个象素,d 的初始值:d0 = F( X0 + 1 , Y0 + 0.5 ) = F( X0 , Y0 ) + a + 0.5b 因(X0, YO)在直线上,F(X0 , YO ) = 0,所以,dO = a + 0.5b
(1.2)具体实现代码:
void CGView::Line_DDA(long plxjong ply,long p2x,long p2y,CDC *pDC)〃画直线算法实现
(
int a,b,del 1 ,del2,d,x,y;
b=p2x-plx;
a=ply-p2y;
d=2*a+b;
dell=2*a;
del2=2*(a+b);
x=plx;
y=piy;
pDC->SetFixel(x,y,mJPenColor);
while(x<p2x)
(
if(d<0)
{
x++;y++;
d+=del2;
}
else
{
x++;
d+=dell;
}
pDC->SetPixel(x,y-2,m_lPenColor);
pDC->SetPixel(x,y-1 ,m_lPenColor);
pDC->SetPixeI(x,y,m_lPenColor);
pDC->SetPixel(x,y+1 ,m_IPenColor);
pDC->SetPixel(x,y,m_lPenColor);
(1.3)实验结果:
S3无标题-G
Jo
文件建)编辑但) E )筌图查者W )精
助冬)
Ax = xl - xO. Ay = yl - yO
图表1中点算法实验结果 (2.DDDA 算法分析:
条件:
八待扫描转换的直线段:Fo (xO,yO ),R (xl,yl ) 斜率:
〃? = △),/* 直线方程:y = m^x+B
直接求交算法: 划分区
间:[xO,xl]: 计算纵坐标: 月=m * x, + B
取整:{■,*到{(耳,光兀
月,=round 、) = (int )(月 + 0.5) (2.2)具体实现代码:
void CGView::Line_DDA(long plx,long ply,long p2x,long p2y,CDC *pDC) (
long x;
float dx,dy,y,k;
dx=p2x-plx;
dy=p2y-ply;
k=dy/dx;
y=piy ;
for(x=pl x;x<=p2x;x++)
pDC->SetPixel(xJong(y-1.5),m_lPenColor);
pDC->SetPixel(x,long(y-0.5),m_IPenColor);
pDC->SetPixel(x,long(y+1.5),m_lPenColor);
pDC->SetPixel(x,long(y+0.5),m_lPenColor);
pDC->SetPixel(xJong(y+1.5),m_lPenColor);
y=y+k;
}
(2.3)实验结果:
图表2 DDA算法结果
五、总结:
此次上机采用了两种算法:DDA算法,中点算法,都实现了直线的绘制。
通过上机,使得我们对这两种算法的原理更加的了解,有利于编程。
这次上机也遇到了不少的细节问题,当时一时半会没有看出来,感谢老师的帮助,才使得任务顺利的完成。
六、附录
参考书籍:
陈传波,陆枫主编,《计算机图形学基础》,电子工业出版社,2002年3月;
孙家广等编,《计算机图形学》(第三版),清华大学出版社,1998年9月;
孙立镌编著,《计算机图形学》,哈尔滨工业大学出版社,2000年5月;。