绘制任意斜率的直线

淮海工学院计算机工程学院

实验报告书

课程名: 计算机图形学

题 目: 绘制任意斜率的直线 班 级: 学 号: 2012122827 姓 名:

一、实验目的或要求

1. 掌握任意斜率直线的绘制算法。

2. 掌握直线中点Bresenham 算法的基本原理,能够用VC++实现该算法。

二、 实验内容

1、掌握直线段的生成算法,并用C++实现算法,包括中点法生成

直线。

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 */

#include

void 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

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) { }

// 使用 DDA 算法画任意斜率的直线(包括起始点,不包括终止点) void Line_DDA(int x1, int y1, int x2, int y2, int color) {

float x, y;

// 当前坐标点

return (int)(x

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

putpixel(Round(x), Round(y), color);

颜色的点 x += cx; y += cy;

}

}

// 主函数 void main() { initgraph(640, 480);

// 测试画线

Line_DDA(100, 100, 100, 478, RED);

// 按任意键退出 getch(); }

// 在坐标 (x, y) 处画一个 color

2、Bresenham 直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。是计算机图形学中最先发展出来的算法。 Bresenham 画法与中点法相似,都是通过每列象素中确定与理想直线最近的像素来进行直线的扫描的转换的。通过各行、各列的象素中心构造一组虚拟网格线的交点,然后确定该列象素中与此交点最近的像素。该算法的巧妙之处在于可以采用增量计算,使得对于每一列,只需要检查一个误差项的符号,就可以确定该列的所有对象。

根据直线的斜率确定选择变量在X 方向上或在Y 方向上每次递增一个单位,另一变量的增量为0或1,它取决于实际直线与最近网格点位置的距离,这一距离称为误差。设第k 步的误差为ek ,选取上面象素点后的积累误差为:ek+1﹦ek ﹢(m ﹣1)选取下面的象素点后的积累误差为:ek+1﹦ek ﹢m

/* Bresenham */程序代码如下: #include #include

// 使用 Bresenham 算法画任意斜率的直线(包括起始点,不包括终止点) void Line_Bresenham(int x1, int y1, int x2, int y2, int color) {

int x = x1; int y = y1;

int dx = abs(x2 - x1); int dy = abs(y2 - y1); int s1 = x2 > x1 ? 1 : -1; int s2 = y2 > y1 ? 1 : -1;

bool interchange = false; // 默认不互换 dx、dy if (dy > dx) { }

int temp = dx; dx = dy; dy = temp;

interchange = true;

// 当斜率大于 1 时,dx 、dy 互换

}

int p = 2 * dy - dx; for(int i = 0; i

putpixel(x, y, color); if (p >= 0) { }

if (!interchange)

x += s1;

// 当斜率

if (!interchange)

y += s2;

// 当斜率 > 1 时,选取左右象素点 // 当斜率

else

x += s1;

p -= 2 * dx;

else

y += s2;

// 当斜率 > 1 时,选取 y 为步长

p += 2 * dy;

// 主函数 void main() { }

运行结果如下:

initgraph(640, 480);

// 测试画线

Line_Bresenham(10, 100, 100, 478,BLUE); Line_Bresenham(10, 478, 638, 1, RED);

// 按任意键退出 getch();

3、生成直线的中点算法

算法思想:

中点算法主要是利用椭圆的正负划分性,利用已知或以求出的点,根据递推关系来判断下一个点的位置。

中点算法有效地消除了DDA 浮点运算效率低下的问题,将直线的斜率m 转化为可加的数,然后通过中点来确定要选择的点,这样使得中点算法的效率大大提高,使之成为被图形软件广泛采用的算法之一。

代码如下:

#include #include

// 使用中点算法画任意斜率的直线(包括起始点,不包括终止点) void Line_Midpoint(int x1, int y1, int x2, int y2, int color) {

int d, d1, d2; if (-a

d = 2 * a + b; d1 = 2 * a; d2 = 2 * (a + b); while(x != x2) {

if (d

y += cy, d += d2;

// 斜率绝对值

putpixel(x, y, color); int x = x1, y = y1;

int a = y1 - y2, b = x2 - x1; int cx = (b >= 0 ? 1 : (b = -b, -1)); int cy = (a

else

}

}

}

x += cx;

putpixel(x, y, color);

else { }

// 斜率绝对值 > 1

d = 2 * b + a; d1 = 2 * b; d2 = 2 * (a + b); while(y != y2) { }

if(d

d += d1;

else

x += cx, d += d2;

y += cy;

putpixel(x, y, color);

// 主函数 void main() {

initgraph(640, 480);

// 测试画线

Line_Midpoint(100, 50, 100, 478, GREEN); Line_Midpoint(1, 478, 638, 1, BLUE);

// 按任意键退出 getch();

四、实验结果

1、 该程序实现了三种算法的直线段绘制 2、 比较三种算法的结果:

像素逼近效果由好到差依次为:Bresenham 算法、DDA 算法、中点算法 执行速度由快到慢依次为: 中点算法、DDA 算法、Bresenham 算法

五、实验分析与体会

通过此次实验我对计算机图形学有了实际的认识,计算机图形学对我们的生活有很多的益处。学习之后我知道了计算机图形学是研究怎样利用计算机来显示,生成和处理图形的原理,方法和技术的一门学科。虽然一开始有些许不懂和茫然,但是经过老师的指导,我还是完成了这次的实验。

淮海工学院计算机工程学院

实验报告书

课程名: 计算机图形学

题 目: 绘制任意斜率的直线 班 级: 学 号: 2012122827 姓 名:

一、实验目的或要求

1. 掌握任意斜率直线的绘制算法。

2. 掌握直线中点Bresenham 算法的基本原理,能够用VC++实现该算法。

二、 实验内容

1、掌握直线段的生成算法,并用C++实现算法,包括中点法生成

直线。

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 */

#include

void 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

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) { }

// 使用 DDA 算法画任意斜率的直线(包括起始点,不包括终止点) void Line_DDA(int x1, int y1, int x2, int y2, int color) {

float x, y;

// 当前坐标点

return (int)(x

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

putpixel(Round(x), Round(y), color);

颜色的点 x += cx; y += cy;

}

}

// 主函数 void main() { initgraph(640, 480);

// 测试画线

Line_DDA(100, 100, 100, 478, RED);

// 按任意键退出 getch(); }

// 在坐标 (x, y) 处画一个 color

2、Bresenham 直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。是计算机图形学中最先发展出来的算法。 Bresenham 画法与中点法相似,都是通过每列象素中确定与理想直线最近的像素来进行直线的扫描的转换的。通过各行、各列的象素中心构造一组虚拟网格线的交点,然后确定该列象素中与此交点最近的像素。该算法的巧妙之处在于可以采用增量计算,使得对于每一列,只需要检查一个误差项的符号,就可以确定该列的所有对象。

根据直线的斜率确定选择变量在X 方向上或在Y 方向上每次递增一个单位,另一变量的增量为0或1,它取决于实际直线与最近网格点位置的距离,这一距离称为误差。设第k 步的误差为ek ,选取上面象素点后的积累误差为:ek+1﹦ek ﹢(m ﹣1)选取下面的象素点后的积累误差为:ek+1﹦ek ﹢m

/* Bresenham */程序代码如下: #include #include

// 使用 Bresenham 算法画任意斜率的直线(包括起始点,不包括终止点) void Line_Bresenham(int x1, int y1, int x2, int y2, int color) {

int x = x1; int y = y1;

int dx = abs(x2 - x1); int dy = abs(y2 - y1); int s1 = x2 > x1 ? 1 : -1; int s2 = y2 > y1 ? 1 : -1;

bool interchange = false; // 默认不互换 dx、dy if (dy > dx) { }

int temp = dx; dx = dy; dy = temp;

interchange = true;

// 当斜率大于 1 时,dx 、dy 互换

}

int p = 2 * dy - dx; for(int i = 0; i

putpixel(x, y, color); if (p >= 0) { }

if (!interchange)

x += s1;

// 当斜率

if (!interchange)

y += s2;

// 当斜率 > 1 时,选取左右象素点 // 当斜率

else

x += s1;

p -= 2 * dx;

else

y += s2;

// 当斜率 > 1 时,选取 y 为步长

p += 2 * dy;

// 主函数 void main() { }

运行结果如下:

initgraph(640, 480);

// 测试画线

Line_Bresenham(10, 100, 100, 478,BLUE); Line_Bresenham(10, 478, 638, 1, RED);

// 按任意键退出 getch();

3、生成直线的中点算法

算法思想:

中点算法主要是利用椭圆的正负划分性,利用已知或以求出的点,根据递推关系来判断下一个点的位置。

中点算法有效地消除了DDA 浮点运算效率低下的问题,将直线的斜率m 转化为可加的数,然后通过中点来确定要选择的点,这样使得中点算法的效率大大提高,使之成为被图形软件广泛采用的算法之一。

代码如下:

#include #include

// 使用中点算法画任意斜率的直线(包括起始点,不包括终止点) void Line_Midpoint(int x1, int y1, int x2, int y2, int color) {

int d, d1, d2; if (-a

d = 2 * a + b; d1 = 2 * a; d2 = 2 * (a + b); while(x != x2) {

if (d

y += cy, d += d2;

// 斜率绝对值

putpixel(x, y, color); int x = x1, y = y1;

int a = y1 - y2, b = x2 - x1; int cx = (b >= 0 ? 1 : (b = -b, -1)); int cy = (a

else

}

}

}

x += cx;

putpixel(x, y, color);

else { }

// 斜率绝对值 > 1

d = 2 * b + a; d1 = 2 * b; d2 = 2 * (a + b); while(y != y2) { }

if(d

d += d1;

else

x += cx, d += d2;

y += cy;

putpixel(x, y, color);

// 主函数 void main() {

initgraph(640, 480);

// 测试画线

Line_Midpoint(100, 50, 100, 478, GREEN); Line_Midpoint(1, 478, 638, 1, BLUE);

// 按任意键退出 getch();

四、实验结果

1、 该程序实现了三种算法的直线段绘制 2、 比较三种算法的结果:

像素逼近效果由好到差依次为:Bresenham 算法、DDA 算法、中点算法 执行速度由快到慢依次为: 中点算法、DDA 算法、Bresenham 算法

五、实验分析与体会

通过此次实验我对计算机图形学有了实际的认识,计算机图形学对我们的生活有很多的益处。学习之后我知道了计算机图形学是研究怎样利用计算机来显示,生成和处理图形的原理,方法和技术的一门学科。虽然一开始有些许不懂和茫然,但是经过老师的指导,我还是完成了这次的实验。


相关文章

  • 计算机图形学--绘制直线
  • 计 算 机 图 形 学 专 业: 班 级: 学 号:姓 名:实 验 报 告 信息与计算科学 1002班 10080602** ***** 1. 实验目的 熟悉CDC 类的MoveTo ()和LineTo ()直线段绘制函数. 熟悉斜率-1 ...查看


  • 高中数学(文科)知识点有哪些啊 请帮我总结一下
  • 1.集合.简易逻辑 理解集合.子集.补集.交集.并集的概念: 了解空集和全集的意义: 了解属于.包含.相等关系的意义: 掌握有关的术语和符号,并会用它们正确表示一些简单的集合. 理解逻辑联结词"或"."且&qu ...查看


  • 几何画板视频全集
  • 实例1利用画点工具任意画三点 实例2绘制线段 实例3绘制过同一点的三条直线 实例4绘制相同端点的三条射线 实例5绘制三个同心圆 实例6绘制共点圆 实例7绘制圆在第一象限内的部分 实例8绘制三角形的中线 实例9绘制三角形的三条角平分线 实例1 ...查看


  • 对"直线的倾斜角与斜率"一堂课的思考
  • 对"直线的倾斜角与斜率"一堂课的思考 --如何进行这堂课的教学设计 人民教育出版社 张劲松 直线是几何中最基本的图形之一,很多几何图形,如射线.线段.三角形.四边形等都可以由直线得到.直线是原始概念,只有描述性的定义,没 ...查看


  • 高中数学精品论文:切线与割线斜率关系的深度探析
  • 切线与割线斜率关系的深度探析 江苏南通高等师范学校 1 226100 曹军 问题提出 笔者在文[1]得出如下结论: 设Y=火龙)是定义在开区间(a,b)上的可导函 h(x)lni.>0,此时I h(x)I面.=h(x)mi.=一击A3 ...查看


  • 直线的点斜式方程教案
  • §8.2.2直线的点斜式方程教学设计 方新 一.教学目标: 1.掌握由一点和斜率导出直线方程的方法: 2.掌握直线方程的点斜式的求法以及之间的联系: 3.通过学生经历直线方程的发现过程,培养学生化归数学问题的能力: 4.揭示"数& ...查看


  • 高中数学解题四大思想方法
  • 圆锥曲线中一个有趣的性质 x 2y 2 性质1 曲线C 为:椭圆2+2=1(a >b >0) ,点P (x 0, y 0) a b (x 0≠0)为曲线C 上的任意一点,过P 作两条相异的直线分别交曲线C 于 图 1 A ,B ...查看


  • 临床化学自建检测系统分析性能确认的分析测量范围和临床可报告范围重点
  • ・946・・ 论著・ 临床化学自建检测系统分析性能确认的 分析测量范围和临床可报告范围 张秀明 范勇利 温冬梅 阚丽娟 萧金丽 陈康 [摘要] 目的 探讨临床化学自建检测系统分析测量范围(AMR)和临床可报告范围(CRR)的确认方法.方法 ...查看


  • 大学物理仿真刚体的转动惯量实验报告
  • 大学物理仿真实验 --刚体转动惯量的测量 班级: 姓名: 学号: 实验名称:刚体转动惯量的测量 一.实验目的 在研究摆的重心升降问题时,惠更斯发现了物体系的重心与后来欧勒称之为转动惯量的量.转动惯量是表征刚体转动惯性大小的物理量,它与刚体的 ...查看


热门内容