CG_实验2_基本图形元素(直线)生成算法的实现
- 格式:docx
- 大小:31.24 KB
- 文档页数:7
实验二: 直线的生成算法的实现班级 08信计2班学号 20080502055 姓名分数一、实验目的和要求:1.理解直线生成的原理;2.掌握几种常用的直线生成算法;3.利用C实现直线生成的DDA算法。
二、实验内容:1.了解直线的生成原理2、掌握几种基本的直线生成算法: DDA画线法、中点画线法、Bresenham画线法。
3、仿照教材关于直线生成的DDA算法, 编译程序。
4.调试、编译、运行程序。
三、实验过程及结果分析1.直线DDA算法:算法原理:已知过端点P0(x0,y0), P1(x1,y1)的直线段L(P0,P1), 斜率为k=(y1-y0)/(x1-x0), 画线过程从x的左端点x0开始, 向x右端点步进, 步长为1个像素, 计算相应的y坐标为y=kx+B。
计算y i+1 = kx i+B=kx i +B+kx=y i +kx当x=1,yi+1=yi+k, 即当x每递增1, y递增k。
由计算过程可知, y与k可能为浮点数, 需要取y整数, 源程序中round(y)=(int)(y+0.5)表示y四舍五入所得的整数值。
(1)程序代码:#include"stdio.h"#include"graphics.h"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<=x1;x++){putpixel(x,(int)(y+0.5),color);y+=m;setbkcolor(7);}}main(){int a,b,c,d,e;int graphdriver=DETECT;int graphmode=0;initgraph(&graphdriver,&graphmode,"");a=100;b=100;c=200;d=300;e=5;linedda(a,b,c,d,e);getch();closegraph();}运行结果:2.中点画线算法:假定所画直线的斜率为k∈[0,1], 如果在x方向上增量为1, 则y方向上的增量只能在0~1之间。
实验二直线段生成绘制的实现算法班级 08信计(2)班学号 20080502085 姓名王景超分数一、实验目的和要求:1.理解基本图形元素光栅化的基本原理2. 掌握一种基本图形元素光栅化算法3. 利用OpenGL实现直线光栅化的DDA算法二、实验内容:1. 根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果;2. 指出示范程序采用的算法,以此为基础将其改造为中点线算法或Bresenham算法,写入实验报告;3. 根据示范代码,将其改造为圆的光栅化算法,写入实验报告;4. 了解和使用OpenGL的生成直线的命令,来验证程序运行结果。
三、实验结果分析:1.该程序实现了三种算法的直线段绘制2.比较三种算法的结果:像素逼近效果由好到差依次为:B算法、DDA算法、中点算法执行速度由快到慢依次为:中点算法、DDA算法、B算法程序代码如下:/* WIN-TC BGI 图形编程模板*/#include "Conio.h"#include "graphics.h"#define closegr closegraphvoid initgr(void) /* BGI初始化*/{int gd = DETECT, gm = 0; /* 和gd = VGA,gm = VGAHI是同样效果*/registerbgidriver(EGA VGA_driver);/* 注册BGI驱动后可以不需要.BGI文件的支持运行*/initgraph(&gd, &gm, "");}/*-----------------------------数值微分法生成直线-----------------------------*/ void LineDDA1(int x0,int y0,int x1,int y1,int color)/*假定x0<x1,直线斜率m<-1*/{int y;float dy,dx,x,m;dx=x1-x0;dy=y1-y0;m=dx/dy;x=x0;for(y=y0;y>=y1;y--){putpixel((int)(x+0.5),y,color);x-=m;}}void LineDDA2(int x0,int y0,int x1,int y1,int color)/*假定x0<x1,直线斜率-1<=m<=1*/{int x;float dy,dx,y,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;}}void LineDDA3(int x0,int y0,int x1,int y1,int color)/*假定x0<x1,直线斜率m>1*/{int y;float dy,dx,x,m;dx=x1-x0;dy=y1-y0;m=dx/dy;x=x0;for(y=y0;y<=y1;y++){putpixel((int)(x+0.5),y,color);x+=m;}}/*----------------------------中点算法生成直线--------------------------------*/ void MidPointLine1(int x0,int y0,int x1,int y1,int color){ /*假定x0<x1,直线斜率m<-1*/int dx,dy,incrE,incrNE,d,x,y;dx=x1-x0;dy=y1-y0;d=-2*dx-dy;incrE=-2*dx;incrNE=-2*(dx+dy);x=x0;y=y0;putpixel(x,y,color);while(y>=y1){if(d>0)d+=incrE;else{ d+=incrNE;x++;}y--;putpixel(x,y,color);}}void MidPointLine2(int x0,int y0,int x1,int y1,int color) { /*假定x0<x1,直线斜率-1<m<0*/int dx,dy,incrE,incrNE,d,x,y;dx=x1-x0;dy=y1-y0;d=-(dx+2*dy);incrE=-2*dy;incrNE=-2*(dx+dy);x=x0;y=y0;putpixel(x,y,color);while(x<x1){if(d<=0)d+=incrE;else{ d+=incrNE;y--;}x++;putpixel(x,y,color);}}void MidPointLine3(int x0,int y0,int x1,int y1,int color) { /* 假定x0<x1,直线斜率0<=m<=1 */int dx,dy,incrE,incrNE,d,x,y;dx=x1-x0;dy=y1-y0;d=dx-2*dy;incrE=-2*dy;incrNE=2*(dx-dy);x=x0;y=y0;putpixel(x,y,color);while(x<x1){if(d>0) d+=incrE;else{d+=incrNE;y++;}x++;putpixel(x,y,color);}}void MidPointLine4(int x0,int y0,int x1,int y1,int color){ /*假定x0<x1,直线斜率m>1*/int dx,dy,incrE,incrNE,d,x,y;dx=x1-x0;dy=y1-y0;d=2*dx-dy;incrE=2*dx;incrNE=2*(dx-dy);x=x0;y=y0;putpixel(x,y,color);while(x<x1){if(d<=0)d+=incrE;else{ d+=incrNE;x++;}y++;putpixel(x,y,color);}}/*-------------------------Bresenham算法生成直线-----------------------------*/ BresenhamLine(int x0,int y0,int x1,int y1,int color){int x,y,dx,dy,i;float m,d;dx=x1-x0;dy=y1-y0;m=dy/dx;d=0;x=x0;y=y0;putpixel(x,y,color);for(i=0;i<=dx;i++){d+=m;if(d>=0.5){y+=1;d-=1;}x++;putpixel(x,y,color);}}/*-------------------------------建立坐标系----------------------------------*/ void LineH(int x0,int x1,int y0,int color){int x,y;x=x0; y=y0;while(x<x1){putpixel(x,y,color);x++;}}void LineV(int y0,int y1,int x0,int color){int x,y;x=x0; y=y0;while(y<y1){putpixel(x,y,color);y++;}}int x0,y0,x1,y1,color,dx1,dy1;float m;int main(void){initgr(); /* BGI初始化*//*****此部分添加你自己的代码,例如line(25, 25, 220, 220);circle(100, 100, 50);等等*****//*-------------------------显示各种斜率的直线--------------------------------*/ MidPointLine1(300,400,340,240,125);MidPointLine2(240,340,400,300,255);MidPointLine3(240,300,400,340,255);MidPointLine4(300,240,340,400,255);LineH(240,400,320,255);LineV(240,400,320,255);outtextxy(398,318,">");outtextxy(280,420,"MidPointLine");LineDDA1(180,280,220,120,125);LineDDA2(120,220,280,180,255);LineDDA2(120,180,280,220,255);LineDDA3(180,120,220,280,255);LineH(120,280,200,255);LineV(120,280,200,255);outtextxy(180,300,"LineDDA");BresenhamLine(322,53,430,182,255);outtextxy(330,160,"Bresenham");/*----------------------------程序输入部分-----------------------------------*/ printf("firstpoint x0,y0:\n");scanf("%d,%d",&x0,&y0);printf("lastpoint x1,y1:\n");scanf("%d,%d",&x1,&y1);printf("color:\n");scanf("%d",&color);dx1=x1-x0;dy1=y1-y0;m=dy1/dx1;if(m<-1)MidPointLine1(x0,y0,x1,y1,color);else if(m>=-1&&m<0)MidPointLine2(x0,y0,x1,y1,color) ;else if(m>=0&&m<=1)MidPointLine3(x0,y0,x1,y1,color) ;elseMidPointLine4(x0,y0,x1,y1,color) ;getch(); /* 暂停一下,看看前面绘图代码的运行结果*/ closegr(); /* 恢复TEXT屏幕模式*/return 0;}运行结果:。
实验二直线的生成算法的实现班级 08信计二班学号 20080502086 姓名分数一、实验目的和要求:1、理解直线生成的基本原理2、熟悉直线的生成算法,掌握直线的绘制3、实现直线生成的DDA 中点画法 Bresenham算法4、了解Visual C++等编程环境中常用控件命令与绘图函数,初步掌握在试验设计集成下进行图形处理程序的设计方法二、实验内容:1、了解直线生成的原理直线DDA算法,中点画线算法,Bresenham画线算法2、编程实现DDA算法、Bresenham算法、中点画法绘制直线段三、实验结果分析1.DDA算法// 程序名称:基于 DDA 算法画任意斜率的直线#include <graphics.h>#include <conio.h>// 四舍五入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, 1, 1, 478, GREEN);Line_DDA(1, 478, 638, 1, GREEN);// 按任意键退出getch();closegraph();}2.中点算法// 程序名称:基于中点算法画任意斜率的直线#include <graphics.h>#include <conio.h>// 使用中点算法画任意斜率的直线(包括起始点,不包括终止点)void Line_Midpoint(int x1, int y1, int x2, int y2, int color){int x = x1, y = y1;int a = y1 - y2, b = x2 - x1;int cx = (b >= 0 ? 1 : (b = -b, -1));int cy = (a <= 0 ? 1 : (a = -a, -1));putpixel(x, y, color);int d, d1, d2;if (-a <= b) // 斜率绝对值 <= 1{d = 2 * a + b;d1 = 2 * a;d2 = 2 * (a + b);while(x != x2){if (d < 0)y += cy, d += d2;elsed += d1;x += cx;putpixel(x, y, color);}}else // 斜率绝对值 > 1{d = 2 * b + a;d1 = 2 * b;d2 = 2 * (a + b);while(y != y2){if(d < 0)d += d1;elsex += cx, d += d2;y += cy;putpixel(x, y, color);}}}// 主函数void main(){initgraph(640, 480);// 测试画线Line_Midpoint(100, 1, 1, 478,YELLOW);Line_Midpoint(1, 478, 638, 1, YELLOW);// 按任意键退出getch();closegraph();}3. Bresenham 算法// 程序名称:基于 Bresenham 算法画任意斜率的直线#include <graphics.h>#include <conio.h>// 使用 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、dyif (dy > dx) // 当斜率大于 1 时,dx、dy 互换{int temp = dx;dx = dy;dy = temp;interchange = true;}int p = 2 * dy - dx;for(int i = 0; i < dx; i++){putpixel(x, y, color);if (p >= 0){if (!interchange) // 当斜率 < 1 时,选取上下象素点y += s2;else // 当斜率 > 1 时,选取左右象素点x += s1;p -= 2 * dx;}if (!interchange)x += s1; // 当斜率 < 1 时,选取 x 为步长elsey += s2; // 当斜率 > 1 时,选取 y 为步长p += 2 * dy;}}// 主函数void main(){initgraph(640, 480);// 测试画线Line_Bresenham(100, 1, 1, 478, RED);Line_Bresenham(1, 478, 638, 1, RED);// 按任意键退出getch();closegraph();}实验结果分析三种算法运算结果比较:像素逼近效果由好到差依次为:B算法、DDA算法、中点算法执行速度由快到慢依次为:中点算法、DDA算法、B算法。
实验二:直线生成算法班级 13软件+道铁1班学号 20132110050115姓名丁益1.实验目的a)通过实验,进一步理解直线段扫描转换的DDA算法、中点画线自算法及bresenham算法的基本原理,掌握以上算法生成直线段的基本过程。
b)通过编程,掌握在C/C++环境下完成用DDA算法、中点画线算法及bresenham算法对任意直线段的扫描转换,以及在C/C++环境下完成用中点画圆及椭圆的绘制方法。
2.实验内容c)阅读《openGL三维程序设计》(电子书)第二部分第四章,掌握OpenGL基本建模方法,并调试其中程序。
d)参考教材第6章,编程实现整数DDA算法、中点画线法和Bresenham画线法,绘制直线(直线宽度和线型可自定)。
2.1 DDA直线生成2.1.1算法原理已知过端点P0(x0,y0),P1(x1,y1)的直线段L(P0,P1),斜率为k=(y1-y0)/(x1-x0),画线过程从x的左端点x0开始,向x右端点步进,步长为1个像素,计算相应的y坐标为y=kx+B。
计算y i+1 = kx i+B=kx i +B+kx=y i +kx当x=1,y i+1=y i+k,即当x每递增1,y递增k。
由计算过程可知,y与k可能为浮点数,需要取y整数,源程序中round(y)=(int)(y+0.5)表示y四舍五入所得的整数值。
2.1.2 算法流程2.1.3 算法实现关键代码#include<GL/glut.h>#include<math.h>void Init(){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,200.0,0.0,150.0);}void lineDDA(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);elsesteps=fabs(dy);xIncrement=float(dx)/float(steps);yIncrement=float(dy)/float(steps);for(k=0;k<steps;k++){x+=xIncrement;y+=yIncrement;glBegin(GL_POINTS);glVertex2i(x,(int)(y+0.5));glEnd();}glFlush();}void myDisplay(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,0.0);lineDDA(50,50,100,120);}int main(int argc,char** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowPosition(100,100);glutInitWindowSize(400,400);glutCreateWindow("Hello World");Init();glutDisplayFunc(myDisplay);glutMainLoop();return 0;}2.1.4算法运行示例及中间结果2.2 Brese nham直线生成2.2.1算法原理Bresenham算法的基本原理是:过各行各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。
OpenGL 实验2直线生成算法实现实验2 直线生成算法实现1. 实验目的理解基本图形元素光栅化的基本原理, 掌握一种基本图形元素光栅化算法, 利用0penGL实现直线光栅化的 DDA算法。
2. 实验内容(1)根据所给的直线光栅化的示范源程序, 在计算机上编译运行, 输出正确结果。
(2)指出示范程序采用的算法, 以此为基础将其改造为中点线算法或 Bresenham算法,写入实验报告。
(3)根据示范代码,将其改造为圆的光栅化算法,写入实验报告。
(4)了解和使用OpenGL的生成直线的命令,来验证程序运行结果。
3. 实验原理示范代码原理DDA算法。
下面介绍 OpenGL画线的一些基础知识和glutReshapeFunc ()函数。
(1)数学上的直线没有宽度,但0penGL的直线则是有宽度的。
同时, OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。
可以认为, OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定。
这里的线由一系列顶点顺次连接而成, 有闭合和不闭合两种。
前面的实验已经知道如何绘“点”,那么 OpenGL是如何知道拿这些顶点来做什么呢? 是依次画出来,还是连成线? 或者构成一个多边形? 或是做其他事情? 为了解决这一问题, OpenGL要求:指定顶点的命令必须包含在 glBegin函数之后, glEnd函数之前(否则指定的顶点将被忽略),并由 glBegin来指明如何使用这些点。
例如:glBegin(GL P0INTS) , glVertex2f(0.0f, 0.0f);glVertex2f(0.5f, 0.0f); glEnd();则这两个点将分别被画出来。
如果将 GL_POINTS替换成 GL_LINES,则两个点将被认为是直线的两个端点, OpenGL将会画出一条直线。
还可以指定更多的顶点, 然后画出更复杂的图形。
另一方面, glBegin支持的方式除了 GL_POINTS和 GL_LINES,还有GL LINE STRIP、 GL LINE L0��P、 GL TRIANGLES、 GL TRIANGLE STRIP、 GL TRIANGLE_FAN等几何图元。
实验二基本图形元素(直线)生成算法的实现
1.实验目的:
理解基本图形元素光栅化的基本原理,掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法。
2.实验内容:
(1)根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果;
(2)指出示范程序采用的算法,以此为基础将其改造为中点线算法或Bresenham算法,写入实验报告;
(3)根据示范代码,将其改造为圆的光栅化算法,写入实验报告;
(4)了解和使用OpenGL的生成直线的命令,来验证程序运行结果。
3.实验原理:
示范代码原理参见教材直线光栅化一节中的DDA算法。
下面介绍下OpenGL画线的一些基础知识和glutReshapeFunc()函数。
(1)数学上的直线没有宽度,但OpenGL的直线则是有宽度的。
同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。
可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定。
这里的线由一系列顶点顺次连结而成,有闭合和不闭合两种。
前面的实验已经知道如何绘“点”,那么OpenGL是如何知道拿这些顶点来做什么呢?是一个一个的画出来,还是连成线?或者构成一个多边形?或是做其它事情呢?为了解决这一问题,OpenGL要求:指定顶点的命令必须包含在glBegin函数之后,glEnd函数之前(否则指定的顶点将被忽略),并由glBegin来指明如何使用这些点。
例如:
glBegin(GL_POINTS);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.5f, 0.0f);
glEnd();
则这两个点将分别被画出来。
如果将GL_POINTS替换成GL_LINES,则两个点将被认为是直线的两个端点,OpenGL将会画出一条直线。
还可以指定更多的顶点,然后画出更复杂的图形。
另一方面,glBegin 支持的方式除了GL_POINTS和GL_LINES,还有GL_LINE_STRIP,GL_LINE_LOOP,GL_TRIANGLES,GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN等,每种方式的大致效果见下图:
图B-2 OpenGL几何图元类型
(2)首次打开窗口、移动窗口和改变窗口大小时,窗口系统都将发送一个事件,以通知程序员。
如果使用的是GLUT,通知将自动完成,并调用向glutReshapeFunc()注册的函数。
该函数必须完成下列工作:Ÿ 重新建立用作新渲染画布的矩形区域;
Ÿ 定义绘制物体时使用的坐标系。
如:
void Reshape(int w, int h)
{// 设置视口大小为整个窗口大小
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
// 单位化投影矩阵。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// 定义二维正视投影矩阵
gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);
}
在GLUT内部,将给该函数传递两个参数:窗口被移动或修改大小后的宽度和高度,单位为像素。
glViewport()调整像素矩形,用于绘制整个窗口。
接下来三个函数调整绘图坐标系,使左下角位置为(0,0),右上角为(w, h)。
4.实验代码:
#include <GL/glut.h>
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;
glColor3f (1.0f, 1.0f, 0.0f);
glPointSize(1);
for(x=x0;x<=x1; x++)
{
glBegin (GL_POINTS);
glVertex2i (x, (int)(y+0.5));
glEnd ();
y+=m;
}
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f (1.0f, 0.0f, 0.0f);
glRectf(25.0, 25.0, 75.0, 75.0);
glPointSize(5);
glBegin (GL_POINTS);
glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (0.0f, 0.0f); glEnd ();
LineDDA(0, 0, 200, 300);
glBegin (GL_LINES);
glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (100.0f, 0.0f);
glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (180.0f, 240.0f);
glEnd ();
glFlush();
}
void Init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void Reshape(int w, int h)
{// 设置视口大小为整个窗口大小
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
// 单位化投影矩阵。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("Hello World!");
Init();
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutMainLoop();
return 0;
}
注:glShadeModel选择平坦或光滑渐变模式。
GL_SMOOTH为缺省值,为光滑渐变模式,GL_FLAT为平坦渐变模式。
5.思考题
示范代码有个小错误,能否指出并改正?请将结果写入实验报告。