实验1 中点画线和Bresenham画线算法的实现

合集下载

中点bresenham算法过程

中点bresenham算法过程

中点Bresenham算法是一种用于计算在直线上的格点的算法。

它是由Bresenham在1965年提出的,是一种高效的计算机图形学算法,通常用于直线、圆、椭圆等形状的绘制。

通过这篇文章,我们将详细介绍中点Bresenham算法的过程。

1. 背景知识在计算机图形学中,我们经常需要在屏幕上绘制直线、圆、椭圆等形状。

而计算机屏幕上的图像是由像素组成的,因此我们需要一种算法来计算出这些形状上的像素坐标,从而进行绘制。

中点Bresenham算法就是用来解决这个问题的。

2. 中点Bresenham算法的原理中点Bresenham算法的原理是通过巧妙的数学推导,找到离直线最近的像素点,从而确定需要绘制的像素坐标。

该算法通过利用误差项来判断下一个像素点的位置,具有高效、简洁的特点。

3. 中点Bresenham算法的过程中点Bresenham算法的过程可以分为以下几个步骤:3.1 初始化变量:首先需要确定直线的起点和终点,并初始化相关变量,如起点坐标(x0, y0)、终点坐标(x1, y1)、误差项d和增量变化量dx、dy等。

3.2 计算斜率k和误差项初始值:通过计算直线的斜率k,并根据斜率确定误差项的初始值。

3.3 循环计算像素点的坐标:根据误差项的大小,确定下一个像素点的位置,并更新误差项的值,直到绘制完整条直线。

4. 中点Bresenham算法的优势* 算法简洁高效:中点Bresenham算法通过简单的数学计算,即可确定直线上的像素坐标,避免了直接计算斜率导致的浮点数运算,因此在计算速度上具有较大优势。

* 适用范围广泛:中点Bresenham算法不仅适用于直线,还可以用于绘制圆、椭圆等图形,具有良好的通用性。

5. 中点Bresenham算法的应用中点Bresenham算法广泛应用于计算机图形学中的直线、圆、椭圆等图形的绘制。

其高效、简洁的特点使得它成为了计算机图形学中不可或缺的算法之一。

中点Bresenham算法是计算机图形学中的重要算法之一,通过巧妙的数学计算,实现了高效、简洁的直线绘制。

图形学--(中点画线法+Bresenham画线算法)

图形学--(中点画线法+Bresenham画线算法)
这俩种算法都是用来在计算机上画一条直线的那么我们为什么不直接用直线方程分别带点再打亮呢这是因为计算机中每个坐标点都是整数而直线是由一个个像素点组合而成的那么直接将坐标点再进行四舍五入整数化就好了啊的确这是一种方法但计算机中进行浮点数的四舍五入会使运算效率变差因此真正画直线时是用到上边这俩种方法的
图形学 --(中点画线法 +Bresenham画线算法)
(1)如果直线d>=0,则取下边的点也就是(x1+1,y1)。 (2)如果直线d<0,则取上边的点也就是(x1+1,y1+1)。
它的实际过程就是这样每次根据前边的点判断下一个点在哪,然后进行打亮,但这样每次判断的时候都得代入直线方程计算太麻烦了,我们将这俩种 情况分别代入直线方程中可以找出规律:
(1)当直线>=0时,经过化解得d1=d+a;
(2)当直线<0时,经过化解得d2=d+a+b;
(3)初始值d0=a+0.5b。
也就是说每次的增量要么为a,要么为a+b,那么这样判断的时候就简单多了,因为我们每次只是判断它的正负。所以给等式同时乘2,将其中浮点数0.5 化为整数,这样硬件操作时无疑更快了。
代码:
1 #include <iostream>
//增量d的初始值
34 for(x=x1;x<=x2;x++){
35 putpixel(x,y,GREEN); //打亮
36 if(d<0){
37
d+=2*dy;
38 }else{
39 y++;
40 d+=2*dy-2*dx;
41 }
42

分别解释直线生成算法dda法,中点画线法和bresenham法的基本原理

分别解释直线生成算法dda法,中点画线法和bresenham法的基本原理

分别解释直线生成算法dda法,中点画线法和
bresenham法的基本原理
直线生成算法DDA法、中点画线法和Bresenham法的基本原理如下:
1. DDA直线生成算法:基于差分运算的直线生成算法。

通过将直线分割成
若干个相邻的像素点,并按照一定的步长进行逐点绘制,实现直线的绘制。

算法主要涉及到线性插值的思想,即根据已知的两点坐标,通过计算它们之间的差值,然后根据这个差值和步长来确定新的像素点的位置。

2. 中点画线法:一种线段绘制算法,从线段的起点和终点出发,按照一定的规则向终点逐步逼近,并在途中以控制变量的方式得出每个像素点的坐标,从而绘制出所需的线条。

具体实现中,通过计算线段斜率的变化情况,分为斜率小于1和大于等于1两种情况,并采用Bresenham的对称性原理,以中点的颜色来控制每个像素点的生长方向,从而获得较高的绘制效率和图像质量表现。

3. Bresenham算法:通过一系列的迭代来确定一个像素点是否应该被绘制。

对于一条从点(x1,y1)到点(x2,y2)的直线,首先计算出斜率k。

然后,通过比较每个像素点的y值到直线上的y值,来决定哪些像素点应该被绘制。

当斜率k大于等于1时,在x方向上迭代,而对于每个x值,计算出y值,并将像素点(x,y)绘制。

当斜率k小于1时,在y方向上迭代,而对于每个y值,计算出x值,并将像素点(x,y)绘制。

以上内容仅供参考,如需更多信息,建议查阅相关文献或咨询数学专业人士。

《计算机图形学》实验指导书

《计算机图形学》实验指导书

计算机图形学实验指导书袁科计算机技术实验中心目录实验一实现DDA、中点画线算法和Bresenham画线算法 (24)实验二实现Bezier曲线 (25)实验三实现B样条曲线 (26)实验四实现多边形填充的边界标志算法 (27)实验五实现裁剪多边形的Cohen-Sutherland算法 (28)实验六二维图形的基本几何变换 (30)实验七画图软件的编制 (31)实验一实现DDA、中点画线算法和Bresenham画线算法【实验目的】1、掌握直线的多种生成算法;2、掌握二维图形显示原理。

【实验环境】VC++6.0/ BC【实验性质及学时】验证性实验,2学时,必做实验【实验内容】利用任意的一个实验环境,编制源程序,分别实现直线的三种生成算法,即数字微分法(DDA)、中点画线法以及Bresenham画线算法。

【实验原理】1、数字微分法(Digital Differential Analyzer,DDA)算法思想:基于直线的微分方程来生成直线。

ε=1/max(|△x|,|△y|)max(|△x|,|△y|)=|△x|,即|k|≤1 的情况:max(|△x|,|△y|)=|△y|,此时|k|≥1:2、中点画线法算法思想:每次在最大位移方向上走一步,另一方向是否走步取决于误差项的判断。

3、Bresenham画线算法算法思想:其基本思想同中点算法一样,即每次在最大位移方向上走一步,而另一个方向是否走步取决于误差项的判断。

【实验要求】1.上交源程序;2.上交实验报告,实验报告内容如下:(1) 实验名称(2) 实验目的(3) 算法实现的设计方法及程序流程图(4) 程序结果分析【分析与思考】(1) 上述所阐述的三个算法,其基本算法只能适用于直线的斜率(|K|<=1) 的情形,如何将上述算法进行推广,使其能够处理任意斜率的直线?(2) 计算机显示屏幕的坐标圆心在哪里,与我们平时的习惯有什么差异,如何协调二者?实验二 实现Bezier 曲线【实验目的】1、掌握Bezier 曲线的定义;2、能编程实现N 次Bezier 曲线的绘制与显示。

Bresenham直线算法

Bresenham直线算法

nidGIS专业实验报告(计算机图形学)实验.1 使用Bresenham画线算法,绘制一条直线段一.根据Bresenham画线算法,掌握绘制直线的程序设计方法。

注意,不能使用语言库中的画线函数。

二.理论基础1.中点Bresenham算法:在屏幕上建立平面直角坐标系,根据所给的坐标得出数学意义上的直线公式,然后在最大位移方向上依次选取最逼近直线的像素点,最终取所有像素点,得到的像素点尽可能的逼近直线,并填充颜色,显示出来。

三.算法设计与分析源码如下:#include<Gl/gl.h>#include<Gl/glu.h>#include<Gl/glut.h>void init(void){glClearColor(0.0,0.0,0.0,0.0);gluOrtho2D(0.0,50.0,.0,40.0);}int abs(int x){int y;if(x<=0)y=-x;elsey=x;return y;}void set_pixel(float x,float y){glPointSize(10);glBegin(GL_POINTS);glVertex2f(x,y);glEnd();}void voidline(int x1,int y1,int x2,int y2){int dx;int dy;int x;int y;int p;int const1;int const2;int inc;int tmp;dx=x2-x1;dy=y2-y1;if(dx*dy>=0)inc=1;elseinc=-1;if(abs(dx)>abs(dy)){if(dx<0){tmp=x1;x1=x2;x2=tmp;tmp=y1;y1=y2;y2=tmp;dx=-dx;dy=-dy;}p=2*dy-dx;const1=2*dy;const2=2*(dy-dx);x=x1;y=y1;set_pixel(x,y);while(x<x2){x++;if(p<0)p+=const1;else{y+=inc;p+=const2;}}}else{if(dy<0){tmp=x1;x1=x2;x2=tmp;tmp=y1;y1=y2;y2=tmp;dx=-dx;dy=-dy;}p=2*dx-dy;const1=2*dx;const2=2*(dx-dy);x=x1;y=y1;set_pixel(x,y);while(y<y2){y++;if(p<0)p+=const1;else{x+=inc;p+=const2;}set_pixel(x,y);}}}void display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(255,0.0,0.0);voidline(25,5,45,45);glPointSize(6.0);glFlush();}int main(int argc,char** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowSize(450,450);glutInitWindowPosition(100,100);glutCreateWindow("Bresenham 直线");init();glutDisplayFunc(display);glutMainLoop();return 0;}四.程序调试及运行结果的自我分析与自我评价写出输入的起始点和终点坐标,截图运行结果类似于下面图,换成你自己的图图1 Bresenham画线算法运行结果图四.实验心得及建议。

中点bresenham算法过程描述

中点bresenham算法过程描述

中点Bresenham算法是一种在计算机图形学中用于绘制直线的算法。

它是由Bresenham在1965年提出的,经过研究和改良后,成为一种非常高效的直线绘制算法。

1. 算法描述中点Bresenham算法的基本思想是利用线的对称性来进行计算,通过计算线上的各个像素点与理想直线的距离来确定下一个要绘制的像素点,从而高效地绘制直线。

2. 算法过程具体来说,中点Bresenham算法的计算过程如下:1) 首先确定直线的起点(x0, y0)和终点(x1, y1),并计算直线的斜率k = (y1 - y0) / (x1 - x0)。

2) 然后计算直线的斜率误差delta = |k| - 0.5。

3) 初始化绘制像素点的坐标(x, y),初始误差值为0。

4) 对于直线斜率绝对值小于1的情况:a) 如果斜率k大于0,则初始误差值为0.5,否则为-0.5。

b) 从x0到x1的范围内,依次计算每个像素点的y坐标,并根据误差值确定下一个像素点的位置,并更新误差值。

c) 如果误差值大于0,表示下一个像素点在直线的下边,否则在上边。

5) 对于直线斜率绝对值大于1的情况,可以通过将直线绘制区域进行旋转并交换x和y坐标来处理。

6) 最终绘制直线时,可以根据具体的应用场景选择存储像素点的方式,比如直接在屏幕上绘制,或者存储在像素数组中后再一次性绘制等。

3. 算法优势中点Bresenham算法相对于其他直线绘制算法的优势在于:它避免了复杂的浮点数计算,减少了计算量,提高了绘制的效率。

尤其在早期计算机硬件性能有限的情况下,该算法表现出了明显的优势,成为了广泛使用的直线绘制算法。

4. 算法应用中点Bresenham算法不仅仅局限于直线的绘制,它还可以应用于其他图形的绘制,比如圆、椭圆、矩形等。

在计算机图形学和图像处理领域,Bresenham算法及其改进版本被广泛应用于各种图形的绘制和处理中。

5. 算法总结中点Bresenham算法是一种非常经典且高效的直线绘制算法,它通过简单的整数运算和位操作实现了高效的直线绘制,成为了计算机图形学中不可或缺的重要工具之一。

计算机图形学实验一:画直线

计算机图形学实验一:画直线

贵州大学实验报告学院:计算机科学与技术专业:计算机科学与技术班级:计科131如果 d<0,则M在理想直线下方,选右上方P1点;如果 d=0,则M在理想直线上,选P1/ P2点。

由于d是xi和yi的线性函数,可采用增量计算提高运算效率。

1.如由pi点确定在是正右方P2点(d>0).,则新的中点M仅在x方向加1,新的d值为:d new=F(xi+2,yi+0.5)=a(xi+2)+b(yi+0.5)+c而 d old=F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+cd new=d old+a= d old-dy2.如由pi点确定是右上方P1点(d<0),则新的中点M在x和y方向都增加1,新的d值为d new=F(xi+2,yi+1.5)=a(xi+2)+b(yi+1.5)+c而 d old=F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+cd new=d old+a+b= d old-dy+dx在每一步中,根据前一次第二迭中计算出的d值的符号,在正右方和右上方的两个点中进行选择。

d的初始值: d0=F(x0+1,y0+0.5)=F(x0,y0)+a+b/2=a+b/2=-dy+dx/2 F(x0,y0)=0,(x0,y0)在直线上。

为了消除d的分数,重新定义 F(x,y)=2(ax+by+c)则每一步需要计算的d new 是简单的整数加法dy=y1-y0,dx=x1-x0d0=-2dy+dxd new=d old-2*dy,当 d old>=0d new=d old-2(dy-dx),当d old<0Bresenham画线算法算法原理:与DDA算法相似,Bresenham画线算法也要在每列象素中找到与理想直线最逼近的象素点。

根据直线的斜率来确定变量在x或y方向递增一个单位。

另一个方向y或x实验内容#include"stdafx.h"#include<glut.h>#include<iostream>#include<cmath>#include<stdio.h>using namespace std;void init(){glClearColor(1.0, 1.0, 1.0, 1.0);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0.0, 200.0, 0.0, 150.0);}void IntegerBresenhamline(){int x1 = 10, y1 = 10, x2 = 150, y2 = 100;int dx = abs(x2 - x1);int dy = abs(y2 - y1);int x, y;int e = -dx;if (x1 > x2){x = x2;y = y2;x2 = x1;}else{x = x1;y = y1;}glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glBegin(GL_LINES);glVertex2i(x, y);while (x < x2){if (e >= 0){y++;e = e - 2 * dx;}glVertex2i(x, y);x++; e += 2 * dy;}glEnd();glFlush();}void MidPointLine(){int x, y, x1 = 10, y1 = 10, x2 = 150, y2 = 100;int dy = y1 - y2;int dx = x2 - x1;int d = 2 * dy + dx;int dx1 = 2 * dy;int dx2 = 2 * (dx + dy);if (x1 > x2){x = x2;y = y2;x2 = x1;}else{x = x1;y = y1;}glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glBegin(GL_LINES);glVertex2i(x, y);while (x < x2){if (d<0){y++; x++;d += dx2;}else{x++, d += dx1;}glVertex2i(x, y);}glEnd();glFlush();}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(50, 100);glutInitWindowSize(400, 300);int choice;printf("输入你想画的直线 0代表Bresenham 1代表中点画线\n");while (1){scanf("%d", &choice);switch (choice){case 0:glutCreateWindow("Bresenham Draw Line");init();glutDisplayFunc(IntegerBresenhamline);glutMainLoop();break;case 1:glutCreateWindow("middle Point Line");init();glutDisplayFunc(MidPointLine);glFlush();glutMainLoop();break;default:printf("输入有误,请重新输入\n");break;}}return 0;}实验结果实验总结通过这次试验我对于中点生成算法和Bresenham生成算法有了进一步的了解,在平时上课的基础上对计算机图形学有了更深的认识,同时对课程内容也更加了解。

分别解释直线生成算法dda法、中点画线法和bresenham法的基本原理

分别解释直线生成算法dda法、中点画线法和bresenham法的基本原理

分别解释直线生成算法dda法、中点画线法和bresenham法的基本原理DDA直线生成算法、中点画线法和Bresenham法都是计算机图形学中用于生成直线的算法。

以下是这三种算法的基本原理:1.DDA直线生成算法(Digital Differential Analyzer):DDA算法是一种基于差分运算的直线生成算法。

其基本原理是,通过计算直线起点和终点之间的差值(横向差值dx 和纵向差值dy),并根据步长来决定下一个像素点的位置。

算法首先确定差值中绝对值较大的一方作为基准,步长设为1,另一方则按比例进行调整,以保持线段的斜率不变。

在实现过程中,DDA算法需要遍历每一个像素点,根据差值的正负和大小来确定新像素点的位置。

2.中点画线法:中点画线法的基本原理是,通过计算线段上当前像素点与相邻两个像素点构成的线段与理想直线的距离,来决定下一个像素点的位置。

具体实现时,设定线段的中点为M,理想直线与线段的交点为Q。

通过比较M和Q的位置关系来确定下一个像素点:若M在Q上方,则取上方的像素点为下一个点;若M在Q下方,则取下方的像素点为下一个点;若M与Q重合,则可任意选择上方或下方的像素点。

中点画线法以中点M作为判别标志,逐点生成直线。

3.Bresenham法:Bresenham算法的原理是基于直线的斜率和截距来计算每个像素点的位置。

在计算机屏幕上,每个像素点都有一个坐标值。

Bresenham算法通过计算直线上每个像素点的坐标值来绘制直线,避免了使用浮点数运算,从而提高了计算效率。

在实现过程中,Bresenham算法根据直线的斜率以及当前像素点的位置,计算出下一个像素点的位置,并逐点绘制出直线。

计算机图形学 实验 数值微分(DDA)法、中点画线法、Bresenham算法

计算机图形学 实验 数值微分(DDA)法、中点画线法、Bresenham算法
当d=0,选P1或P2均可,约定取P1为下一个象素;
但这样做,每一个象素计算量是4个加法,两个乘法。
d是xp, yp的线性函数,因此可采用增量计算,提高运算效率。
若当前象素处于d0情况,则取正右方象素P1(xp+1, yp),要判下一个象素位置,应计算d1=F(xp+2, yp+0.5)=a(xp+2)+b(yp+0.5)=d+a;增量为a。
e=-0.5,x=x0,y=y0;
for(i=0;i<=dx;i++)
{
pdc->SetPixel(x,y,color);
x=x+1;
e=e+k;
if(e>=0)
{
y++,e=e-1;
}
}
}
void CMy1View::On1()
{
// TODO: Add your command handler code here
当M在Q的下方,则P2应为下一个象素点;
当M在Q的上方,应取P1为下一点。
构造判别式:d=F(M)=F(xp+1,yp+0.5)=a(xp+1)+b(yp+0.5)+c,其中a=y0-y1, b=x1-x0, c=x0y1-x1y0。
当d<0,M在L(Q点)下方,取右上方P2为下一个象素;
当d>0,M在L(Q点)上方,取右方P1为下一个象素;
设直线方程为:,其中k=dy/dx。因为直线的起始点在象素中心,所以误差项d的初值d0=0。
X下标每增加1,d的值相应递增直线的斜率值k,即d=d+k。一旦d≥1,就把它减去1,这样保证d在0、1之间。

实验1中点画线和Bresenham画线算法的实现

实验1中点画线和Bresenham画线算法的实现

实验1中点画线和Bresenham画线算法的实现计算机图形学实验报告实验1 使用画线算法,绘制直线段一.实验目的及要求(1)掌握图形学中常用的三种画线算法:数值微分法、中点画线法和Bresenham画线算法。

(2)掌握绘制直线的程序设计方法。

(3)掌握使用文件来保存直线段的方法。

(4)掌握从文本文件中恢复出直线的方法。

二.实验内容使用VC++ 6.0开发环境,分别实现中点画线算法和Bresenham 画线算法,绘制直线(注意,不能使用VC中已有的绘制直线的函数),并以文本文件的形式保存绘制的结果,可以从文本文件中恢复出以前绘制过的直线。

三.算法设计与分析Bresenham算法绘制直线的程序(仅包含整数运算)。

void MidBresenhamLine(int x0,int y0,int x1,int y1,int color) {int dx,dy,d,UpIncre,DownIncre,x,y;if(x0>x1){x=x1;x1=x0;x0=x;y=y1;y1=y0;y0=y;}x=x0;y=y0;dx=x1-x0;dy=y1-y0;d=dx-2*dy;UpIncre=2*dx-2*dy;DownIncre=-2*dy;while(x<=x1){putpixel(x,y,color);X++;if(d<0){y++;d+=UpIncre;}else d+=DownIncre;}}四.程序调试及运行结果的自我分析与自我评价// testView.cpp : implementation of the CT estView class#include "stdafx.h"#include "test.h"#include "testDoc.h"#include "testView.h"#include // ifstream、ofstream等位于其中#include#include // string类型需要#include "DlgInput.h" //CDlgInput类的头文件using namespace std;#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView)//{{AFX_MSG_MAP(CTestView)ON_COMMAND(ID_MENUITEM32771, OnMenuitem32771)ON_COMMAND(ID_MENUBRESENHAMLINE, OnMenubresenhamline) ON_COMMAND(ID_MENUCLEARVIEW, OnMenuclearview)ON_COMMAND(ID_FILE_OPEN, OnFileOpen)ON_COMMAND(ID_FILE_SA VE, OnFileSave)//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW,CView::OnFilePrintPreview) END_MESSAGE_MAP()// CTestView construction/destructionCTestView::CTestView(){// TODO: add construction code herem_nFlag = -1; // 不是任何绘图类型}CTestView::~CT estView(){}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}// CTestView drawingvoid CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereif(1==m_nFlag) // 中点画线{MidPointLine(m_X0, m_Y0, m_X1, m_Y1, RGB(255,0,0) );}else if(2==m_nFlag) // Bresenham画线{BresenhamLine(m_X0, m_Y0, m_X1, m_Y1, RGB(0,255,0) );}}// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add extra initialization before printing}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add cleanup after printing}// CTestView diagnostics#ifdef _DEBUGvoid CTestView::AssertValid() const{CView::AssertValid();}void CTestView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CTestDoc* CTestView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CT estD oc)));return (CT estDoc*)m_pDocument;}#endif //_DEBUG// CTestView message handlersvoid CTestView::OnMenuitem32771(){// TODO: Add your command handler code herem_nFlag = 1; // 中点画线CDlgInput dlg;if(IDOK==dlg.DoModal()){m_X0=dlg.m_nX0;m_Y0=dlg.m_nY0;m_X1=dlg.m_nX1;m_Y1=dlg.m_nY1;RedrawWindow(); //重绘窗口}}void CTestView::OnMenubresenhamline(){// TODO: Add your command handler code herem_nFlag = 2; // Bresenham画线CDlgInput dlg;if(IDOK==dlg.DoModal()){m_X0=dlg.m_nX0;m_Y0=dlg.m_nY0;m_X1=dlg.m_nX1;m_Y1=dlg.m_nY1;RedrawWindow(); //重绘窗口}}// 算法: 中点画线// 输入: 起点(x0,y0),终点(x1,y1);// 输入要求x0<=x1;void CTestView::MidPointLine( int x0, int y0, int x1, int y1, int color ){CDC * pDC=GetDC();int a,b,d0,d1,d2,d3,d4,d5,d,x,y;a=y0-y1;b=x1-x0; // 之前的设置已经保证始终有x1>=x0d=2*a+b;d0=2*a-b;d1=2*a;d2=2*(a+b);d3=2*b;d4=2*(a-b);d5=a-2*b;x=x0;y=y0;pDC->SetPixel(x,y,color);if(x==x1) // 斜率k为无穷大{if(y<=y1){while(y<=y1){pDC->SetPixel(x,y,color);y++;}}else{while(y>=y1){pDC->SetPixel(x,y,color);y--;}}}// if 斜率k为无穷大else // 斜率k为有限值{// double k=-a/b;// if( k+1>1e-6 && k-1<1e-6 || fabs(k-1)<1e-6 || fabs(k+1)<1e-6) // |k|<=1(即:-1<= k <=1),与1e-6比较是浮点数比较方法if( -b<=-a && -a<=b ) // 用浮点数比较在|k|=1.0f时容易出问题,所以直接用整数比较(将斜率k转换为a与b的比较;之前的设置已经保证b为正数){if(y<=y1){while(x<x1)< p="">{if(d<0){x++;y++;d+=d2;}else{x++;d+=d1;}pDC->SetPixel(x,y,color);}}else{while(x<x1)< p="">{if(d0<0){ x++;d0+=d1;}else{ x++;y--; d0+=d4; }pDC->SetPixel(x,y,color);}}}// if( |k|<=1 )else // |k|>1{if(y<=y1){while(x<x1)< p="">{if(d<0){y++;d+=d3;}else{y++;x++;d+=d2;}pDC->SetPixel(x,y,color);}}else{while(x<x1)< p="">{if(d5<0){ x++;y--; d5+=d4;}else{y--; d5+=-2*b;}pDC->SetPixel(x,y,color);}}}// else( |k|>1 )}// else 斜率k为有限值ReleaseDC(pDC);}// 算法: Bresenham画线// 输入: 起点(x0,y0),终点(x1,y1);// 输入要求x0<=x1;void CTestView::BresenhamLine( int x0, int y0, int x1, int y1, int color ){ CDC * pDC=GetDC();int x,y,dx,dy,e;dx=x1-x0;dy=y1-y0;e=-dx;x=x0;y=y0;while(x<=x1){ pDC->SetPixel(x,y,color);x++;e=e+2*dy;if(e>0){y++;e=e-2*dx;}}}void CTestView::OnMenuclearview(){// TODO: Add your command handler code here m_X0=0;m_Y0=0;m_X1=0;m_Y1=0;RedrawWindow();//重绘窗口}// 打开过去保存的文件,该文件包含直线的端点坐标void CTestView::OnFileOpen(){// TODO: 在此添加命令处理程序代码if( m_nFlag!=1 && m_nFlag!=2 ){MessageBox("请先在菜单中选择绘制直线的方法!","提示",MB_ICONWARNING);return;}CFileDialog dlgFile (TRUE, _T("txt"), _T(""),OFN_FILEMUSTEXIST| OFN_HIDEREADONL Y, _T("线段端点坐标文件(*.txt)|*.txt||"), this);if( IDOK == dlgFile.DoModal()){CString fileName = dlgFile.GetFileName();ifstream rFile;rFile.open(fileName,ios::in);if ( ! rFile.is_open() ){MessageBox("文件打开失败!","提示",MB_ICONW ARNING);return;}CString strLine0;string strLine;int nX,nY;// 起点、终点,两个坐标rFile>>strLine;strLine0 = strLine.c_str();nX = atoi( strLine0.Left( strLine0.Find(",") ) ); // 解析文件,如“220,221”表示一个点的x、y坐标nY = atoi( strLine0.Mid( strLine0.Find(",")+1 ) );m_X0 = nX;m_Y0 = nY;rFile>>strLine;strLine0 = strLine.c_str();nX = atoi( strLine0.Left( strLine0.Find(",") ) );nY = atoi( strLine0.Mid( strLine0.Find(",")+1 ) );m_X1 = nX;m_Y1 = nY;RedrawWindow();rFile.close();}}// 保存当前视图上绘制的所有直线的端点坐标void CTestView::OnFileSave(){// TODO: 在此添加命令处理程序代码CFileDialog dlgFile(FALSE, _T("txt"), _T(""), OFN_OVERWRITEPROMPT, _T("线段端点坐标文件(*.txt)|*.txt||"), this);if( IDOK == dlgFile.DoModal()) // 保存文件{CString strFileName = dlgFile.GetFileName(); // 包含完整路径的文件名称ofstream wFile;wFile.open(strFileName,ios::out|ios::ate|ios::app);if ( ! wFile.is_open() ){MessageBox(strFileName+"文件创建失败!","提示",MB_ICONW ARNING);return;}wFile<<m_x0<<","<<m_y0<<="">wFile<<m_x1<<","<<m_y1<<="">五.实验心得及建议实验心得:Bresenham算法是一种很方便很实用很简单的算法,它对任意斜率的直线段具有通用性。

DDA算法 中点画线算法 Bresenham算法

DDA算法 中点画线算法 Bresenham算法

实验1直接绘制实验(提示:#表示Project的编号,##表示Project题目)学号姓名上交时间1.问题描述如何利用OpenGL实现直线光栅化的DDA算法、中点画线算法和Bresenham算法2.算法描述DDA算法:据直线公式y = kx + b来推导出来的,其关键之处在于如何设定单位步进,即一个方向的步进为单位步进,另一个方向的步进必然是小于1。

中点划线法:在画直线段的过程中,当前像素点为(xp ,yp ),下一个像素点有两种可选择点P1(xp +1,yp )或P2(xp +1,yp +1)。

若M=(xp +1,yp +0.5)为P1与P2之中点,Q 为P理想直线与x=xp +1垂线的交点。

当M在Q的下方,则P2应为下一个像素点;M在Q的上方,应取P1为下一个像素点。

Bresenham算法:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。

实验结果成功运行三个算法,并且能转换出通用Bresenham算法。

3.分析与评论(分析每个算法的运行时间,对你的本实验的工作进行评论,同时也可以对老师提出建议。

)附录: Source Code(in C)#include <GL/glut.h> //需要正确安装GLUT,安装方法如预备知识中所述void myDisplay(void){glClearColor(0.0, 0.0, 0.0, 0.0);glClear(GL_COLOR_BUFFER_BIT);glColor3f (1.0f, 1.0f, 1.0f);glRectf(-0.5f, -0.5f, 0.5f, 0.5f);glBegin (GL_TRIANGLES);glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (0.0f, 1.0f);glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (0.8f, -0.5f);glColor3f (0.0f, 0.0f, 1.0f); glVertex2f (-0.8f, -0.5f);glEnd ();glColor3f(1,0,0);glBegin(GL_LINE_LOOP);glVertex2f (0.0f, 0.5f);glVertex2f (0.4f, -0.25f);glVertex2f (-0.4f, -0.25f);glEnd ();glPointSize(3);glBegin (GL_POINTS);glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (-0.4f, -0.4f);glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (0.0f, 0.0f);glColor3f (0.0f, 0.0f, 1.0f); glVertex2f (0.4f, 0.4f);glEnd ();glFlush();}int main(intargc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition(100, 100);glutInitWindowSize(400, 400);glutCreateWindow("Hello World!");glutDisplayFunc(&myDisplay);glutMainLoop();return 0;}通用算法:int Sign(int n){if(n>0) return 1;if(n==0) return 0;if(n<0) return -1;}void Bresenham(int x0,int y0,int x1,int y1,void (*setPixel)(intx,int y)){ int x,y,dx,dy,s1,s2,temp=0,interchange;x=x0; y=y0;dx=abs(x1-x0); dy=abs(y1-y0);s1=Sign(x1-x0); s2=Sign(y1-y0);if(dy>dx){temp=dx; dx=dy; dy=temp;interchange=1;}elseinterchange=0;int e=2*dy-dx;for(inti=1;i<=dx;++i){setPixel(x,y);while(e>0){if(interchange==1)x=x+s1;elsey=y+s2;e=e-2*dx;}if(interchange==1)y=y+s2;elsex=x+s1;e=e+2*dy;}}(以上是实验报告的最小要求,以后可以会根据各个Project的不同情况增加内容。

直线生成算法 DDA画线算法、中点画线算法、Bresenham画线算法

直线生成算法 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);}四:程序运行截图:。

DDA法,中点法,Bresenham法画直线

DDA法,中点法,Bresenham法画直线

实验名称 DDA 法,中点法,Bresenham 法画直线一、实验目的学会用DDA 法,中点法,Bresenham 法这三种思想画直线,同时,对画直线的操作有一定的了解。

二、实验原理及内容1. DDA 法的基本思想如下:已知过端点P0(x0,y0) , P1(x1,y1)的直线段L :y=kx+b ,直线斜率为k=(y1-y0)/x1-x0 ,从x 的左端点x0开始,向x 右端点步进。

步长=1(个象素),计算相应的y 坐标y=kx+b ;取象素点(x, round(y))作为当前点的坐标。

2. 中点法的基本思想如下:当前象素点为(xp, yp) 。

下一个象素点为P1 或P2 。

设M=(xp+1, yp+0.5),为p1与p2之中点,Q 为理想直线与x=xp+1垂线的交点。

将Q 与M 的y 坐标进行比 较。

当M 在Q 的下方,则P2 应为下一个象素点;M 在Q 的上方,应取P1为下一点。

构造判别式:d=F(M)=F(xp+1,yp+0.5)=a(xp+1)+b(yp+0.5)+c ,其中a=y0-y1, b=x1-x0, c=x0y1-x1y0当d<0,M 在L(Q 点)下方,取右上方P2为下一个象素;当d>0,M 在L(Q 点)上方,取右方P1为下一个象素;当d=0,选P1或P2均可,约定取P1为下一个象素;但这样做,每一个象素的计算量是4个加法,两个乘法。

采用增量算法改进如下:d 是xp, yp 的线性函数,因此可采用增量计算,提高运算效率。

若当前象素处于d 0情况,则取正右方象素P1 (xp+1, yp), 要判下一个象素位置,应计算d1=F(xp+2, yp+0.5)=a(xp+2)+b(yp+0.5)+c=d+a ; 增量为a ,若d<0时,则取右上方象素P2 (xp+1, yp+1)。

要判断再下一象素,则要计算d2= F(xp+2, yp+1.5)=a(xp+2)+b(yp+1.5)+c=d+a+b ;增量为a +b画线从(x0, y0)开始,d 的初值d0=F(x0+1, y0+0.5)=F(x0, y0)+a+0.5b =a+0.5b 。

计算机图形学实验一 基本图形生成算法

计算机图形学实验一 基本图形生成算法

实验一基本图形生成算法实验题目:基本图形生成算法学号:20101104879姓名:王薇班级:10级计科指导老师:林民完成日期:2012.3.1实验目的:掌握中点Bresenham绘制直线的原理设计中点Bresenham算法编程实现中点Bresenham算法实验描述:使用中点Bresenham算法绘制斜率为0≤k≤1的直线。

算法设计:直线中点Bresenham算法1. 输入直线的起点坐标P0(x0,y0)和终点坐标P1(x1,y1)。

2. 定义直线当前点坐标x,y、定义中点偏差判别式d、定义直线斜率k、定义像素点颜色rgb。

3. x=x0,y=y0,计算d=0.5-k,k=(y1-y0)/(x1-x0),rgb=RGB(0,0,255)。

4. 绘制点(x,y),判断d的符号。

若d<0,则(x,y)更新为(x+1,y+1),d 更新为d+1-k;否则(x,y)更新为(x+1,y),d更新为d-k。

5. 如果当前点x 小于x1,重复步骤4,否则结束。

源程序:1)// TestView.h#include "InputDlg.h"//对话框头文件class CTestView : public CView{}2)//TestView.cppvoid CTestView::OnMbline()//菜单函数{InputDlg dlg;if(dlg.DoModal()==IDOK){AfxGetMainWnd()->SetWindowText(":直线中点Bresenham算法");RedrawWindow();Mbline(dlg.m_x0, dlg.m_y0, dlg.m_x1, dlg.m_y1);}}void CTestView::Mbline(double x0, double y0,double x1,double y1) //直线中点Bresenham函数{CClientDC dc(this);COLORREF rgb=RGB(0,0,255); //定义直线颜色为蓝色double x,y,d,k;x=x0;y=y0;k=(y1-y0)/(x1-x0);d=0.5-k;for(x=x0;x<=x1;x++){dc.SetPixel(ROUND(x),ROUND(y),rgb);if(d<0){y++;d+=1-k;}elsed-=k;}}运行结果:。

计算机图形学实验指导(一、二)

计算机图形学实验指导(一、二)

电脑图形学实验指导实验一、直线的扫描转换算法实验实验目的掌握中点Bresenham直线扫描转换算法的思想。

实验环境实验内容问题描述:给定两个点的坐标P0(x0,y0),P1(x1,y1),使用中点Bresenham直线扫描转换算法画出连接两点的直线。

中点Bresenham直线扫描转换算法原理见课本。

实验基本步骤首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。

其次、使用中点Bresenham直线扫描转换算法实现自己的画线函数,函数原型可表示如下:void DrawLine(CDC *pDC, int p0x, int p0y, int p1x, int p1y);在函数中,可通过调用CDC成员函数SetPixel来画出扫描转换过程中的每个点。

COLORREF SetPixel(int x, int y, COLORREF crColor );再次、找到文档视图程序框架视图类的OnDraw成员函数,调用DrawLine函数画出不同斜率情况的直线,如下列图:最后、调试程序直至正确画出直线。

实验要求1写出中点Bresenham直线扫描转换算法的程序并在vc6下编译和调试通过,画出具有各种斜率范围的直线(仅使用GDI函数SetPixel函数)。

2按规定的实验格式写出实验报告,包含实验代码〔自己写的画线函数〕,结果〔截图〕。

实验二、多边形填充算法实验实验目的掌握边标志算法或有效边表算法进行多边形填充的基本设计思想。

实验环境实验内容问题描述:给定多边形的顶点的坐标P0(x0,y0),P1(x1,y1),P2(x2,y2),P3(x3,y3),P4(x4,y4)…使用边标志算法或有效边表算法进行多边形填充。

边标志算法或有效边表算法原理见课本。

实验基本步骤首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。

其次、实现边标志算法或有效边表算法函数,如下:void FillPolygon(CDC *pDC, int px[], int py[], int ptnumb);px:该数组用来表示每个顶点的x坐标py :该数组用来表示每个顶点的y坐标ptnumb:表示顶点个数注意实现函数FillPolygon可以直接通过窗口的DC〔设备描述符〕来进行多边形填充,不需要使用帧缓冲存储。

直线中点Bresenham算法实验报告

直线中点Bresenham算法实验报告

附页:一实验分析要求和算法如上表格所示二核心算法1.CTestView.h文件// TestView.h : interface of the CTestView class/////////////////////////////////////////////////////////////////////////////#if !defined(AFX_TESTVIEW_H__A75FDCFB_621C_4E38_A154_C344803E6372__INCLUDED_) #define AFX_TESTVIEW_H__A75FDCFB_621C_4E38_A154_C344803E6372__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include "InputDlg.h"//对话框头文件class CTestView : public CView{protected: // create from serialization onlyCTestView();DECLARE_DYNCREA TE(CTestView)// Attributespublic:CTestDoc* GetDocument();// Operationspublic:void Mbline();//直线中点Bresenham函数// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CTestView)public:virtual void OnDraw(CDC* pDC); // overridden to draw this viewvirtual BOOL PreCreateWindow(CREATESTRUCT& cs);protected:virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);//}}AFX_VIRTUAL// Implementationpublic:virtual ~CTestView();#ifdef _DEBUGvirtual void AssertValid() const;virtual void Dump(CDumpContext& dc) const;#endifprotected:double x0, y0, x1, y1;//直线的起点和终点坐标// Generated message map functionsprotected://{{AFX_MSG(CTestView)afx_msg void OnMENUMbline();//}}AFX_MSGDECLARE_MESSAGE_MAP()};#ifndef _DEBUG // debug version in TestView.cppinline CTestDoc* CTestView::GetDocument(){ return (CTestDoc*)m_pDocument; }#endif///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCA TION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_TESTVIEW_H__A75FDCFB_621C_4E38_A154_C344803E6372__INCLUDED_) 2.CTestView. cpp文件// TestView.cpp : implementation of the CTestView class#include "stdafx.h"#include "Test.h"#include "TestDoc.h"#include "TestView.h"#define ROUND(a) int(a+0.5) //四舍五入#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView)//{{AFX_MSG_MAP(CTestView)ON_COMMAND(ID_MENUMbline, OnMENUMbline)//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CTestView construction/destructionCTestView::CTestView(){// TODO: add construction code here}CTestView::~CTestView(){}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREA TESTRUCT csreturn CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CTestView drawingvoid CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data here}/////////////////////////////////////////////////////////////////////////////// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add extra initialization before printing}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CTestView diagnostics#ifdef _DEBUGvoid CTestView::AssertValid() const{CView::AssertValid();}void CTestView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CTestDoc* CTestView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));return (CTestDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CTestView message handlersvoid CTestView::Mbline() //直线中点Bresenham函数{CClientDC dc(this);COLORREF rgb=RGB(0,0,255); //定义直线颜色为蓝色double x,y,d,k;x=x0;y=y0;k=(y1-y0)/(x1-x0);d=0.5-k;for(x=x0;x<=x1;x++){dc.SetPixel(ROUND(x),ROUND(y),rgb);if(d<0){y++;d+=1-k;}elsed-=k;}}void CTestView::OnMENUMbline()//菜单函数{// TODO: Add your command handler code hereInputDlg dlg;if(dlg.DoModal()==IDOK){x0=dlg.m_x0;y0=dlg.m_y0;x1=dlg.m_x1;y1=dlg.m_y1;}AfxGetMainWnd()->SetWindowText("基本图形扫描转换:Mbline");RedrawWindow();Mbline();}四结果截图五小结通过本次实验的设计,让我对计算机图形图像处理有了更加深刻的理解,学会了这种绘制直线的算法Bresenham。

分别解释直线生成算法dda法、中点画线法和bresenham法的基本原理。

分别解释直线生成算法dda法、中点画线法和bresenham法的基本原理。

分别解释直线生成算法dda法、中点画线法和bresenham法
的基本原理。

一、DDA(Digital Differential Analyzer)法
DDA法是一种基于像素的直线生成算法,其基本原理是通过在直线的每个像素点上应用微分关系来计算出该点的位置。

具体来说,首先选择一个起始点,然后在直线上每隔一个像素点进行微分计算,得到该点相对于前一个点的增量。

在直线的终点处,由于没有前一个点的信息,需要使用特殊的方法进行处理。

DDA法生成的线条在视觉上较为平滑,且无需进行线条绘制。

二、中点画线法
中点画线法是一种基于连续点的直线生成算法,其基本原理是每隔一定数量的点在直线上绘制一个点,以生成直线。

该算法的优点是计算量较小,适用于实时性要求较高的场景。

但是,由于该算法生成的线条不够平滑,因此在一些对线条质量要求较高的场景下可能无法满足要求。

三、Bresenham法
Bresenham法是一种基于二进制运算的直线生成算法,其基本原理是通过比较相邻像素之间的灰度级差异来决定线条的绘制。

算法首先确定直线的起点和终点,然后根据灰度级差异的大小和二进制运算的特点,确定在直线上绘制点的位置。

Bresenham法生成的线条在视觉上较为清晰,且具有较好的连续性。

同时,由于该算法采用了二进制运算,因此在处理大量数据时具有较高的效率。

总结:DDA法、中点画线法和Bresenham法是常用的直线生成算法,每种算法都有其适用的场景和优缺点。

在实际应用中,需要根据具体需求和场景选择合适的算法,以达到最佳的直线生成效果。

实验报告(Bresenham画线算法)

实验报告(Bresenham画线算法)

实验报告(Bresenham 画线算法)一、实验目的根据Bresenham 画线算法,掌握绘制直线的程序设计方法。

二、实验原理为了说明算法原理,我们首先考虑斜率非负且不超过 1 的直线的光栅化过程。

设直线的起点坐标为 (x s , y s ),终点坐标为(x e , y e ),则直线的方程为:dy y x B dx =+因此,其隐函数表示为:(,)0F x y dy x dx y B dx ax by c =⋅-⋅+⋅=++= 其中:,,a dy b dx c B dx ==-=⋅显然,对于直线上的点,F(x , y) 等于零;对于直线下方的点,F(x , y) 大于零;而对直线上方的点,F(x,y) 小于零。

假设当前选择的像素点是 (xi , yi),那么下一步要选择的像素点可能是 NE (xi+1 , yi+1),也可能是 E (xi+1 , yi)。

选择的原则是看哪一个离直线与 x = xi+1 的交点最近。

运用中点法则,我们只需考察中点 M 在直线的哪一侧,即计算: F(M) = F(xi + 1, yi + 1/2) = a(xi + 1) + b( yi + 0.5) + c 并确定其正负号。

由于根据函数值 F(xi+1, yi + 1/2) 进行判定,所以我们定义一个判定函数如下: di = 2F(xi + 1, yi + 1/2)根据定义:di = 2a(xi + 1) + 2byi + b + 2c当 d i < 0 时,M 在直线的上方,取 E 为下一个像素点;当 d > 0时, M 在直线的下方,取 NE 为下一个像素点;当 d = 0时,两者都可以选,我们约定选 E 。

di 的计算需要做 4 次加法和两次乘法。

因此,为了有效地计算判定函数,我们需要建立关于 di 的递推公式。

显然,di 的变化依赖于下一个像素点选的是 NE 还是 E 。

当 di < 0 时,下一个像素点是 E ,那么:di+1= 2F(xi + 2, yi + 1/2) = 2a(xi + 2) + 2byi + b + 2c = di + 2a 当 di > 0 时,下一个像素点是 NE ,则:d i+1= 2F (x i + 2, y i + 1 + 1/2) = 2a (x i + 2) + 2b (y i +1)+b+2c= d i + 2a + 2b由此,得到计算判定函数 di 的递推公式:12,022,0i i i i i d dy d d d dy dx d ++<⎧=⎨+->⎩因为直线上的第一个像素点就是直线的起点 (xs, ys),所以判定函数 di 的初值为:d0 = 2a(xs + 1) + 2bys + b + 2c = 2dy - dx故满足条件的直线的 Bresnham 算法的步骤如下:Step 1.初始化dx = xe - xs , dy = ye - ys , x = xs , y = ys , d = 2dy -dx ; Step 2.当 x < xe 时,执行下述操作:(1)画像素点 (x, y);(2)求下一个像素点:x = x + 1;if (d > 0) then y = y + 1;(3)计算判定函数 d :if (d > 0) then d = d + 2dy - 2dx ;else d = d + 2dy ;Step 3.算法结束。

Bresenham画圆算法与中点画圆法

Bresenham画圆算法与中点画圆法

Bresenham画圆算法与中点画圆法Bresenham画圆算法不失⼀般性,假设圆的圆⼼位于坐标原点(如果圆⼼不在原点,可以通过坐标平移使其与原点重合),半径为R。

以原点为圆⼼的圆C有四条对称轴:x = 0, y = 0, x = y和x = -y。

若已知圆弧上⼀点P1=C(x, y),利⽤其对称性便可以得到关于四条对称轴的其它7个点,即: P2=C(x,-y), P3=C(-x, y), P4=C(-x,-y), P5=C(y,x), P6=C(-y,x), P7=C(y,-x), P8=C(-y,-x)。

这种性质称为⼋对称性。

因此,只要扫描转换⼋分之⼀圆弧,就可以通过圆弧的⼋对称性得到整个圆。

【Bresenham算法】简单图形的扫描转换常⽤算法是Bresenham算法。

它的思想在于⽤误差量来衡量点选取的逼近程度。

其过程如下:以平⾯⼆维图形的扫描转换为例,设要画的图形⽅程为F(x, y)=0,要画的区域为[x0, x](不妨设x⽅向是最⼤位移⽅向,即△x > △y),则F(x,y) 也是⼀个误差度量函数,我们拿离散的点值代⼊如果⼤于0则正向偏离,否则负向偏离,等于0的情况⽐较少,它表⽰的是不偏离即恰好与真实点重合。

既然x是最⼤位移⽅向,那每次对x⾃增1,相应的y可以选择不增或增1(或-1,具体问题具体分析),选择的⽅法就是d = F(x + 1, y ± 0.5)的正负情况进⾏判断从⽽选择y的值。

实际情况中还要考虑到浮点数的计算问题,因为基本的图形扫描转换算法最好能够硬件实现,所以摆脱浮点数是最好的,常⽤的⽅法是对d 进⾏递推,⽽不是直接由F(x,y)给出(直接给出速度会慢)。

【圆的扫描转换算法】以画圆为例,给出圆⼼的坐标(0, 0)和半径R,求圆图像的最佳逼近点。

圆是中⼼对称的特殊图形,所以可以将圆⼋等分,则只须对⼋分之⼀圆孤求解,其它圆孤可以由对称变换得到,我们求的⼋分之⼀圆孤为(0, R) -(R√2,R√2),可知最⼤位移⽅向是x⽅向,x0 = 0, y0 = R,每次对x⾃增,然后判断y是否减1,直到x >= y为⽌(从点(0, R)到圆的⼋分之⼀处就有这种情况)。

1.论述直线的bresenham算法的原理,方法和步骤。

1.论述直线的bresenham算法的原理,方法和步骤。

论述直线的bresenham算法的原理,方法和步骤。

Bresenham算法是一种用于计算直线段的算法,它是一种基于中点画线思想的折线逼近算法。

该算法可以在二维平面中以最小的误差逼近直线。

B resenham算法的主要优点是它只需要计算整数坐标,而不需要使用浮点数计算,因此运行速度快,精度高。

Bresenham算法的原理是:从直线的一个端点开始,按照一定的方向和步长绘制一系列点,直到另一个端点为止。

这些点之间的间距逐渐减小,使得视觉效果上形成一条直线。

在这个过程中,通过计算每个点的坐标,可以得到一条近似于直线的折线。

Bresenham算法的方法如下:1. 初始化参数:设定直线的两个端点坐标(x1,y1)和(x2,y2),以及画线的方向变量k。

初始方向k等于两点横坐标之差与纵坐标之差的比值,即k = (y2 - y1) / (x2 - x1)。

2. 计算第一个点:根据初始方向k,计算第一个点的坐标。

第一个点的横坐标为x1 + k/2,纵坐标为y1。

3. 迭代计算后续点:从第二个点开始,每次迭代都将当前点的横坐标加上k,纵坐标加上1/k。

同时,检查当前点的横坐标是否超过终点坐标x2,如果是,则结束绘制。

4. 输出结果:将计算出的所有点按照顺序连接起来,形成一条折线,这条折线近似于原始直线。

Bresenham算法的步骤如下:1. 初始化参数:设置直线的两个端点坐标和方向k。

2. 计算第一个点:根据方向k,计算第一个点的坐标。

3. 迭代计算后续点:按照迭代公式,依次计算出所有点的位置。

4. 输出结果:将计算出的所有点连接起来,形成一条折线。

5. 终止条件:当计算出的点的横坐标超过终点坐标时,绘制过程结束。

通过以上方法和步骤,Bresenham算法可以高效地绘制出直线段,适用于各种图形绘制和计算场景。

在实际应用中,可以根据需要调整算法的参数和精度,以满足不同的需求。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算机图形学实验报告实验1 使用画线算法,绘制直线段一.实验目的及要求(1)掌握图形学中常用的三种画线算法:数值微分法、中点画线法和Bresenham画线算法。

(2)掌握绘制直线的程序设计方法。

(3)掌握使用文件来保存直线段的方法。

(4)掌握从文本文件中恢复出直线的方法。

二.实验内容使用VC++ 6.0开发环境,分别实现中点画线算法和Bresenham画线算法,绘制直线(注意,不能使用VC中已有的绘制直线的函数),并以文本文件的形式保存绘制的结果,可以从文本文件中恢复出以前绘制过的直线。

三.算法设计与分析Bresenham算法绘制直线的程序(仅包含整数运算)。

void MidBresenhamLine(int x0,int y0,int x1,int y1,int color){int dx,dy,d,UpIncre,DownIncre,x,y;if(x0>x1){x=x1;x1=x0;x0=x;y=y1;y1=y0;y0=y;}x=x0;y=y0;dx=x1-x0;dy=y1-y0;d=dx-2*dy;UpIncre=2*dx-2*dy;DownIncre=-2*dy;while(x<=x1){putpixel(x,y,color);X++;if(d<0){y++;d+=UpIncre;}else d+=DownIncre;}}四.程序调试及运行结果的自我分析与自我评价// testView.cpp : implementation of the CTestView class#include "stdafx.h"#include "test.h"#include "testDoc.h"#include "testView.h"#include <iostream> // ifstream、ofstream等位于其中#include <fstream>#include <string> // string类型需要#include "DlgInput.h" //CDlgInput类的头文件using namespace std;#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView)//{{AFX_MSG_MAP(CTestView)ON_COMMAND(ID_MENUITEM32771, OnMenuitem32771)ON_COMMAND(ID_MENUBRESENHAMLINE, OnMenubresenhamline) ON_COMMAND(ID_MENUCLEARVIEW, OnMenuclearview)ON_COMMAND(ID_FILE_OPEN, OnFileOpen)ON_COMMAND(ID_FILE_SA VE, OnFileSave)//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP()// CTestView construction/destructionCTestView::CTestView(){// TODO: add construction code herem_nFlag = -1; // 不是任何绘图类型}CTestView::~CTestView(){}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}// CTestView drawingvoid CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereif(1==m_nFlag) // 中点画线{MidPointLine(m_X0, m_Y0, m_X1, m_Y1, RGB(255,0,0) );}else if(2==m_nFlag) // Bresenham画线{BresenhamLine(m_X0, m_Y0, m_X1, m_Y1, RGB(0,255,0) );}}// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add extra initialization before printing}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add cleanup after printing}// CTestView diagnostics#ifdef _DEBUGvoid CTestView::AssertValid() const{CView::AssertValid();}void CTestView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CTestDoc* CTestView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));return (CTestDoc*)m_pDocument;}#endif //_DEBUG// CTestView message handlersvoid CTestView::OnMenuitem32771(){// TODO: Add your command handler code herem_nFlag = 1; // 中点画线CDlgInput dlg;if(IDOK==dlg.DoModal()){m_X0=dlg.m_nX0;m_Y0=dlg.m_nY0;m_X1=dlg.m_nX1;m_Y1=dlg.m_nY1;RedrawWindow(); //重绘窗口}}void CTestView::OnMenubresenhamline(){// TODO: Add your command handler code herem_nFlag = 2; // Bresenham画线CDlgInput dlg;if(IDOK==dlg.DoModal()){m_X0=dlg.m_nX0;m_Y0=dlg.m_nY0;m_X1=dlg.m_nX1;m_Y1=dlg.m_nY1;RedrawWindow(); //重绘窗口}}// 算法: 中点画线// 输入: 起点(x0,y0),终点(x1,y1);// 输入要求x0<=x1;void CTestView::MidPointLine( int x0, int y0, int x1, int y1, int color ) {CDC * pDC=GetDC();int a,b,d0,d1,d2,d3,d4,d5,d,x,y;a=y0-y1;b=x1-x0; // 之前的设置已经保证始终有x1>=x0d=2*a+b;d0=2*a-b;d1=2*a;d2=2*(a+b);d3=2*b;d4=2*(a-b);d5=a-2*b;x=x0;y=y0;pDC->SetPixel(x,y,color);if(x==x1) // 斜率k为无穷大{if(y<=y1){while(y<=y1){pDC->SetPixel(x,y,color);y++;}}else{while(y>=y1){pDC->SetPixel(x,y,color);y--;}}}// if 斜率k为无穷大else // 斜率k为有限值{// double k=-a/b;// if( k+1>1e-6 && k-1<1e-6 || fabs(k-1)<1e-6 || fabs(k+1)<1e-6) // |k|<=1(即:-1<= k <=1),与1e-6比较是浮点数比较方法if( -b<=-a && -a<=b ) // 用浮点数比较在|k|=1.0f时容易出问题,所以直接用整数比较(将斜率k转换为a与b的比较;之前的设置已经保证b为正数){if(y<=y1){while(x<x1){if(d<0){x++;y++;d+=d2;}else{x++;d+=d1;}pDC->SetPixel(x,y,color);}}else{while(x<x1){if(d0<0){ x++;d0+=d1;}else{ x++;y--; d0+=d4; }pDC->SetPixel(x,y,color);}}}// if( |k|<=1 )else // |k|>1{if(y<=y1){while(x<x1){if(d<0){y++;d+=d3;}else{y++;x++;d+=d2;}pDC->SetPixel(x,y,color);}}else{while(x<x1){if(d5<0){ x++;y--; d5+=d4;}else{y--; d5+=-2*b;}pDC->SetPixel(x,y,color);}}}// else( |k|>1 )}// else 斜率k为有限值ReleaseDC(pDC);}// 算法: Bresenham画线// 输入: 起点(x0,y0),终点(x1,y1);// 输入要求x0<=x1;void CTestView::BresenhamLine( int x0, int y0, int x1, int y1, int color ){ CDC * pDC=GetDC();int x,y,dx,dy,e;dx=x1-x0;dy=y1-y0;e=-dx;x=x0;y=y0;while(x<=x1){ pDC->SetPixel(x,y,color);x++;e=e+2*dy;if(e>0){y++;e=e-2*dx;}}}void CTestView::OnMenuclearview(){// TODO: Add your command handler code herem_X0=0;m_Y0=0;m_X1=0;m_Y1=0;RedrawWindow();//重绘窗口}// 打开过去保存的文件,该文件包含直线的端点坐标void CTestView::OnFileOpen(){// TODO: 在此添加命令处理程序代码if( m_nFlag!=1 && m_nFlag!=2 ){MessageBox("请先在菜单中选择绘制直线的方法!","提示",MB_ICONWARNING);return;CFileDialog dlgFile (TRUE, _T("txt"), _T(""),OFN_FILEMUSTEXIST| OFN_HIDEREADONL Y, _T("线段端点坐标文件(*.txt)|*.txt||"), this);if( IDOK == dlgFile.DoModal()){CString fileName = dlgFile.GetFileName();ifstream rFile;rFile.open(fileName,ios::in);if ( ! rFile.is_open() ){MessageBox("文件打开失败!","提示",MB_ICONW ARNING);return;}CString strLine0;string strLine;int nX,nY;// 起点、终点,两个坐标rFile>>strLine;strLine0 = strLine.c_str();nX = atoi( strLine0.Left( strLine0.Find(",") ) ); // 解析文件,如“220,221”表示一个点的x、y坐标nY = atoi( strLine0.Mid( strLine0.Find(",")+1 ) );m_X0 = nX;m_Y0 = nY;rFile>>strLine;strLine0 = strLine.c_str();nX = atoi( strLine0.Left( strLine0.Find(",") ) );nY = atoi( strLine0.Mid( strLine0.Find(",")+1 ) );m_X1 = nX;m_Y1 = nY;RedrawWindow();rFile.close();}}// 保存当前视图上绘制的所有直线的端点坐标void CTestView::OnFileSave(){// TODO: 在此添加命令处理程序代码CFileDialog dlgFile(FALSE, _T("txt"), _T(""), OFN_OVERWRITEPROMPT, _T("线段端点坐标文件(*.txt)|*.txt||"), this);if( IDOK == dlgFile.DoModal()) // 保存文件CString strFileName = dlgFile.GetFileName(); // 包含完整路径的文件名称ofstream wFile;wFile.open(strFileName,ios::out|ios::ate|ios::app);if ( ! wFile.is_open() ){MessageBox(strFileName+"文件创建失败!","提示",MB_ICONW ARNING);return;}wFile<<m_X0<<","<<m_Y0<<endl;// 将坐标对按行写到txt文件中wFile<<m_X1<<","<<m_Y1<<endl;// 将坐标对按行写到txt文件中五.实验心得及建议实验心得:Bresenham算法是一种很方便很实用很简单的算法,它对任意斜率的直线段具有通用性。

相关文档
最新文档