使用OpenGL编程实现Bresenham直线扫描转换算法
《图形学》实验四:中点Bresenham算法画直线
《图形学》实验四:中点Bresenham算法画直线VC++6.0,OpenGL使⽤中点Bresenham算法画直线。
1//中点Bresenham算法⽣成直线2 #include <gl/glut.h>3 #include <math.h>45#define WIDTH 500 //窗⼝宽度6#define HEIGHT 500 //窗⼝⾼度7#define DRAWLINE1 MidpointBresenham(100,200,200,100); //画直线8#define DRAWLINE2 MidpointBresenham(200,100,450,400); //画直线910#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") //取消控制台1112void Init() //初始化13 {14 glClearColor(1.0f,1.0f,1.0f,1.0f); //设置背景颜⾊,完全不透明15 glColor3f(1.0f,0.0f,0.0f); //设置画笔颜⾊1617 glMatrixMode(GL_PROJECTION); //设置投影18 gluOrtho2D(0.0, WIDTH, 0.0, HEIGHT); //设置投影区域19 }2021void MidpointBresenham(int x0,int y0,int x1,int y1) //中点Bresenham算法画线22 {23int dx,dy,d,UpIncre,DownIncre,x,y;24if(x0>x1){25 x=x1;x1=x0;x0=x;26 y=y1;y1=y0;y0=y;27 }28 x = x0,y = y0;29 dx = x1-x0;30 dy = y1-y0;31if(dy>0&&dy<=dx){ //0<k<=132 d = dx-2*dy;33 UpIncre = 2*dx-2*dy;34 DownIncre = -2*dy;35while(x<=x1){36 glBegin(GL_POINTS);37 glVertex2i(x,y);38 glEnd();39 x++;40if(d<0){41 y++;42 d+=UpIncre;44else45 d+=DownIncre;46 }47 }48else if((dy>=(-dx))&&dy<=0) //-1<=k<=049 {50 d=dx-2*dy;51 UpIncre=-2*dy;52 DownIncre=-2*dx-2*dy;53while(x<=x1)54 {55 glBegin(GL_POINTS);56 glVertex2i(x,y);57 glEnd();58 x++;59if(d>0)60 {61 y--;62 d+=DownIncre;63 }64else d+=UpIncre;65 }66 }67else if(dy<(-dx)) //k<-168 {69 d=-dy-2*dx;70 UpIncre=2*dx+2*dy;71 DownIncre=2*dx;72while(y>=y1)73 {74 glBegin(GL_POINTS);75 glVertex2i(x,y);76 glEnd();77 y--;78if(d<0)79 {80 x++;81 d-=UpIncre;82 }83else d-=DownIncre;84 }85 }8687else//k>1和k不存在88 {89 d=dy-2*dx;90 UpIncre=2*dy-2*dx;91 DownIncre=-2*dx;92while(y<=y1)93 {94 glBegin(GL_POINTS);95 glVertex2i(x,y);96 glEnd();97 y++;98if(d<0)99 {100 x++;101 d+=UpIncre;103else d+=DownIncre;104 }105 }106 }107108void Display() //显⽰函数109 {110 glClear(GL_COLOR_BUFFER_BIT); //清空颜⾊堆栈111112 DRAWLINE1 //画直线113 DRAWLINE2 //画直线114115 glFlush(); //清空缓冲区指令116 }117118int main(int argc,char** argv)119 {120 glutInit(&argc,argv);121 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); //初始化显⽰模式122 glutInitWindowSize(WIDTH,HEIGHT); //设置窗⼝尺⼨123 glutInitWindowPosition(200,100); //设置窗⼝位置124 glutCreateWindow("画直线"); //创建窗⼝125126 glutDisplayFunc(Display); //注册显⽰函数127 Init(); //初始化128 glutMainLoop(); //进⼊程序循环129return0;130 }Freecode :。
bresenham算法实现直线段插值函数
在计算机图形学中,Bresenham算法是一种用于在离散坐标系上绘制直线段的算法。
它是一种高效的算法,能够准确地计算出直线段上的所有像素点,使得在计算机屏幕上显示出直线段来。
Bresenham算法的实现可以帮助我们更好地理解画线原理,并且在计算机视觉、图像处理等领域有着广泛的应用。
1. Bresenham算法的原理Bresenham算法是通过计算直线段的斜率来确定每个像素点的位置。
具体来说,它利用了直线的对称性和整数的特性,通过计算像素点与真实直线的距离来判断下一个像素点应该取的位置。
这样可以避免使用浮点运算,使得算法更加高效。
2. 实现Bresenham算法的关键步骤在实现Bresenham算法时,需要考虑以下几个关键步骤:- 初始化各个变量,包括起始点(x0, y0)和终点(x1, y1),以及斜率的计算值,例如dx和dy。
- 根据斜率的正负情况,确定每个像素点的增量步长,以便在遍历过程中准确计算出像素点来。
- 利用对称性和整数特性,进行迭代计算,逐步确定直线段上的所有像素点的位置。
3. Bresenham算法的优缺点Bresenham算法作为一种离散直线段插值算法,具有以下几个优点:- 算法简单高效,节省存储空间和运算时间。
- 可以高效地解决像素化显示问题,避免了浮点运算的复杂性。
- 在硬件上实现时,只需少量的资源就能完成计算,适合嵌入式系统和图形处理器。
然而,Bresenham算法也存在一些缺点,比如对于曲线的绘制就不太奏效,因为它是基于直线段的形式来处理的。
4. 我对Bresenham算法的理解在我看来,Bresenham算法是一种经典的离散直线段插值算法,其思想简洁高效。
它通过逐步迭代的方式,计算出直线段上的所有像素点位置,使得在计算机屏幕上显示出直线段来更加精确。
这种算法的实现可以帮助我们更好地理解画线的原理,对于理解计算机图形学和计算机视觉都有着重要的意义。
总结起来,Bresenham算法作为一种高效的离散直线段插值算法,具有着重要的理论和实际价值。
实验1 opengl基本图形绘制
实验一、直线的扫描转换系别:计算机学院专业班级: 10信科2姓名:学号实验日期: 2013-3-27 实验报告日期:2013-3-27一、实验目的:理解直线的不同生成算法,并用程序实现。
二、实验环境:1熟悉VC6.0开发平台;2熟悉OpenGL开发库;三、实验内容:1.使用OpenGL中的基本画点函数,分别使用DDA算法、中点算法、Bresenham算法画直线。
要求为每一种算法分别建立对应的函数,函数参数为直线段的端点坐标。
四、实验报告内容1、程序源码;void MidpointMethod(Point point1,Point point2){int x ,y,d,times1,times2,stepX,stepY; //k表示斜率int a,b,c; //a,b ,c分别为直线方程 aX+bY+c=0的参数int i;float k;x=point1.x; y=point1.y;times1=abs(point1.x-point2.x);//循环次数times2=abs(point2.y-point1.y);a=point2.y-point1.y; //求出直线方程 aX+bY+c=0的参数的参数ab=point1.x-point2.x; //求出直线方程 aX+bY+c=0的参数的参数bc=point1.x*(point1.y-point2.y)+point1.y*(point2.x-point1.x); //求出直线方程 aX+bY+c=0的参数的参数cstepX=b/abs(b)*(-1); //stepX表示该直线在X轴上的延伸方向,stepX值为1,表示直线像素点的横坐标跳步的方向与x轴一样,否则为-1 stepY=a/abs(a); //stepY表示该直线在y轴上的延伸方向,stepY 值为1,表示直线像素点的纵坐标跳步的方向与Y轴一样,否则为-1k=((float)a)/((float)b)*(-1); //求出斜率kglPointSize(1.0f);glBegin(GL_POINTS);if((0<=k)&&(k<=1)) //斜率为0到1的情况{d=a+0.5*b; //初值for(i=0;i<=times1;i++){x=x+stepX;if(stepX*d>=0) //判断y方向是否走步,stepX表示该直线在X轴上的延伸方向,stepX值为1,表示直线像素点的横坐标跳步的方向与x轴一样,否则为-1 //{y+=stepY;d=d+a+b;}elsed=d+a;glVertex2i(x,y);}}else if((1<k)&&(k<=10000)) //斜率大于1的情况{d=b+0.5*a;for(i=0;i<times2;i++) //times表示循环要执行的次数{y+=stepY;if(d*stepY<=0) //判断中点是否在直线的上方,stepY表示该直线在y轴上的延伸方向,stepX值为1,表示直线像素点的纵坐标跳步的方向与x轴一样,否则为-1{x+=stepX;d=d+a+b;}else d=d+b;glVertex2i(x,y);}}else if((-1<=k)&&(k<0)) //斜率为-1到0的情况{d=a+0.5*b;for(i=0;i<=times1;i++){x=x+stepX;if(stepX*d<=0){y+=stepY;d=d+a-b;}elsed=d+a;glVertex2i(x,y);}}else if((-10000<=k)&&(k<-1)) //斜率为小于-1的情况{d=a*0.5+b;for(i=0;i<=times2;i++){y=y+stepY;if(stepY*d>=0){x+=stepX;d=d-a+b;}elsed=d+b;glVertex2i(x,y);}}else //斜率无限大的情况{for(i=0;i<times2;i++){y+=1;glVertex2i(x,y);}}glEnd();}2、实验报告;报告中包含以下内容:①自己编写的绘图函数及其辅助函数。
opengl 扫描线算法
if (active->next) {
fillScan (scan, active);
updateActiveList (scan, active);
resortActiveList (active);
glutInitWindowSize (WINDOW_WIDTH, WINDOW_HEIGHT); // Set display-window width and height.
glutCreateWindow ("saomiaoxian"); // Create display window.
#define WINDOW_HEIGHT 400
typedef struct tEdge {
int yUpper;
float xIntersect, dxPerScan;
struct tEdge * next;
} Edge;
struct dcPt {
int x;
dcPt pts[] = {
20, 20,
90, 10,
90, 90,
80,70,
60,90,
10,60
};
scanFill (4, pts);
glFlush ( );
}
void main (int argc, char ** argv)
while (p != NULL) {
if (edge->xIntersect < p->xIntersect)
p = NULL;
else {
OpenGL中点Bresenham绘制直线算法
OpenGL中点Bresenham绘制直线算法本⽂实例为⼤家分享了OpenGL中点Bresenham绘制直线算法,供⼤家参考,具体内容如下环境macos xcode编译器代码#include <GLUT/GLUT.h>#include <iostream>#include<iostream>#include<cstdlib>#include<ctime>using namespace std;float wid = 400; //设置窗⼝的⼤⼩,约定窗⼝必须为正⽅形float height = wid; //设置窗⼝的⼤⼩int numbers = 20; //设置划分的⽹格的个数float t = wid/numbers; //模拟像素下的单位1/*参数设置说明:输⼊直线的两点A(x1,y1);B(x2,y2)您应当确保参数范围在-400~400.且为整数。
*⽀持不同斜率*⽀持两点位置颠倒*/int x1 = -300,y1=-400,x2 =400,y2 = 100;void draw_point(float x, float y,int k_kind,int d_kind);float translater(int x);void swap(int &a, int &b){ int tmp = 0;tmp = b;b = a;a = tmp; }void bresenham(int x1, int y1,int x2, int y2){/*函数说明:bresenham算法部分参数说明:与openGL已有的划线函数⼀样,要求⽤户提供的是点的起点(x1,y1)和终点(x2,y2)为了便于观察,我们会绘制原像素下的直线。
这⾥的坐标要求是-1 ~ 1*/int k_kind = 0; //k_kind⽤来表⽰斜率的类型。
0是0~1;1是1~⽆穷;2是0~-1;3是负⽆穷~-1int d_kind =0; //d_kind⽤来表⽰dy正负的类型。
python语言实现的bresenham算法
python语言实现的bresenham算法Bresenham算法是一种用于绘制直线的经典算法,它能够有效地计算出直线上的像素点,减少了计算与绘制的开销。
本文将逐步介绍如何使用Python语言实现Bresenham算法。
第一步,我们需了解Bresenham算法的原理及其背后的数学思想。
该算法基于直线的一般方程y = mx + b,其中m为斜率,b为y轴截距。
Bresenham算法的核心在于决策,即在每一个像素点处,选择最合适的下一个像素点。
其思想是,在给定的直线段中,比较由当前像素点到两个候选像素点的斜率值,从而决定下一步绘制的方向。
利用整数计算,避免了实数运算,提高了运行效率。
接下来,我们将使用Python语言实现Bresenham算法。
首先,需要引入必要的图形库,如matplotlib或者pygame。
这些库能够帮助我们在屏幕上绘制图形。
以matplotlib为例,我们首先需要创建一个画布,并在画布上绘制直线。
代码如下:pythonimport matplotlib.pyplot as plt# 创建画布fig, ax = plt.subplots()# 绘制直线def bresenham(x1, y1, x2, y2): dx = abs(x2 - x1)dy = abs(y2 - y1)if x1 < x2:sx = 1else:sx = -1if y1 < y2:sy = 1else:sy = -1err = dx - dywhile True:ax.plot(x1, y1, 'bo')if x1 == x2 and y1 == y2:breake2 = 2 * errif e2 > -dy:err = err - dyx1 = x1 + sxif e2 < dx:err = err + dxy1 = y1 + sy# 调用函数绘制直线bresenham(1, 1, 10, 8)# 显示画布plt.show()在上述代码中,我们首先创建了一个画布,并用`fig, ax = plt.subplots()`语句生成对应的`figure`和`axes`。
直线段的扫描转换_计算机专业_OpenGL实验_Exp
注:1、实验报告的内容: 一、实验目的;二、实验原理;三、实验步骤;四、实验结果;五、讨论分析(完成指定的思考题和作业题);六、改进实验建议。
2、各专业可在满足学校对实验教学基本要求的前提下,根据专业特点自行设计实验报告的格式,所设计的实验报告在使用前需交实践教学管理科备案。
五、实验步骤1、复习有关直线扫描转换算法的基本原理,明确实验目的和要求;2、依据算法思想,绘制程序流程图;3、设计程序界面,要求操作方便;4、用C/C++语言编写源程序并调试、执行;5、分析实验结果6、对程序设计过程中出现的问题进行分析与总结;7、打印源程序或把源程序以文件的形式提交;8、按格式要求完成实验报告。
六、实验报告要求:1、各种算法的基本原理;2、各算法的流程图3、实验结果及分析(比较三种算法的特点,界面插图并注明实验条件)4、实验总结(含问题分析及解决方法)七、实验原理1、DDA算法(数值微分法)数值微分法(DDA法,Digital Differential Analyzer)是一种直接从直线的微分方程生成直线的方法。
给定直线的两端点P0(x0, y0)和P1(x1, y1),得到直线的微分方程如下:DDA算法原理:由于直线的一阶导数是连续的,而且对于△x和△y是成正比的,故此可以通过在当前位置上分别加上二个小增量来求下一点的x,y坐标,如下图所示。
则有:其中,ε=1/max(|△x|,|△y|)分两种情况讨论如下:(1)max(|△x|,|△y|)=|△x|,即|k|≤1的情况:(2)max(|△x|,|△y|)=|△y|,此时|k|≥1:注意:由于在光栅化的过程中不可能绘制半个像素点,因此对求出的xi+1,yi+1的值需要四舍五入。
2、中点Bresenham算法给定直线的两个端点坐标,可以得到直线的方程为:此时直线将平面分成三个区域:对于直线上的点,F(x, y)=0;对于直线上方的点,F(x, y)>0;对于直线下方的点,F(x, y)<0,如下图所示。
Bresenham直线算法与画圆算法(转)
Bresenham直线算法与画圆算法(转)在我们内部开发使用的一个工具中,我们需要几乎从0 开始实现一个高效的二维图像渲染引擎。
比较幸运的是,我们只需要画直线、圆以及矩形,其中比较复杂的是画直线和圆。
画直线和圆已经有非常多的成熟的算法了,我们用的是Bresenham的算法。
计算机是如何画直线的?简单来说,如下图所示,真实的直线是连续的,但我们的计算机显示的精度有限,不可能真正显示连续的直线,于是我们用一系列离散化后的点(像素)来近似表现这条直线。
(上图来自于互联网络,《计算机图形学的概念与方法》柳朝阳,郑州大学数学系)接下来的问题就是如何尽可能高效地找到这些离散的点,Bresenham直线算法就是一个非常不错的算法。
Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在n维光栅上最接近的点。
这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。
是计算机图形学中最先发展出来的算法。
(引自wiki 百科布雷森漢姆直線演算法)这个算法的流程图如下:可以看到,算法其实只考虑了斜率在 0 ~ 1 之间的直线,也就是与 x 轴夹角在 0 度到 45 度的直线。
只要解决了这类直线的画法,其它角度的直线的绘制全部可以通过简单的坐标变换来实现。
下面是一个C 语言实现版本。
1 2 3 4 5 // 交换整数 a 、b 的值inline void swap_int(int *a, int *b) {*a ^= *b;*b ^= *a;*a ^= *b;6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 }// Bresenham's line algorithmvoid draw_line(IMAGE *img, int x1, int y1, int x2, int y2, unsigned long c) {// 参数 c 为颜色值int dx = abs(x2 - x1),dy = abs(y2 - y1),yy = 0;if (dx < dy) {yy = 1;swap_int(&x1, &y1);swap_int(&x2, &y2);swap_int(&dx, &dy);}int ix = (x2 - x1) > 0 ? 1 : -1,iy = (y2 - y1) > 0 ? 1 : -1,cx = x1,cy = y1,n2dy = dy * 2,n2dydx = (dy - dx) * 2,d = dy * 2 - dx;if (yy) { // 如果直线与 x 轴的夹角大于 45 度while (cx != x2) {if (d < 0) {d += n2dy;} else {cy += iy;d += n2dydx;}putpixel(img, cy, cx, c);cx += ix;}} else { // 如果直线与 x 轴的夹角小于 45 度while (cx != x2) {if (d < 0) {d += n2dy;} else {cy += iy;d += n2dydx;}50515253putpixel(img, cx, cy, c);cx += ix;}}}可以看到,在画线的循环中,这个算法只用到了整数的加法,所以可以非常的高效。
编程实现bresenham直线扫描生成算法
编程实现bresenham直线扫描生成算法bresenham直线扫描生成算法是通过像素的光栅显示和扫描转换算法来画出直线的算法,这种算法能够用最少的计算量来在任意一个像素点中完成直线的绘制。
Bresenham有着广泛的应用,因为它是强力而有效的。
它其中它最常用于计算机图形学中用于绘制矢量图形。
在讨论具体实现之前,必须弄清楚所需要解决的基本问题。
bresenham直线扫描生成算法需要实现以下3步骤:1. 从起点到终点用步进方式移动;2. 确定像素点的位置;3. 对所有的像素点进行计算。
从实现的角度考虑,bresenham直线生成算法可以按照以下几个步骤来实现:1. 从起点开始,计算直线斜率,使用步长deltaX和deltaY来确定两个像素点的间距;2. 计算两个像素点在x-轴上的距离,用deltaX和deltaY来确定像素点的位置,并且求出它们在y-轴上的距离;3. 计算当前像素点处的梯度,以及梯度的变化度;4. 根据第2步计算得到的deltaX和deltaY,求出当前像素点处的误差值;5. 根据第3步和第4步计算得到的梯度和误差值,确定下一个像素点的位置,不断迭代,直至到达终点(两个像素点的距离小于等于1);6. 绘制出直线。
不管是正斜率直线还是负斜率直线,都可以使用bresenham直线算法来实现。
具体实现时,我们需要声明两个变量deltaX和deltaY,分别根据步长计算点P(x,y)处误差值dx 和dy。
我们需要对dx和dy进行比较,若dx>dy,则每次跨x轴取整累加1,而每次跨y轴取float,反之取整只累加,这样从零开始就可以得到下一个要绘制的像素点。
总的来说,bresenham直线扫描生成算法是在直线的代价最优的情况下计算最优的像素点的位置,从而实现直线的绘制。
经过广泛的使用,Bresenham法已经得到了广泛的接受,并受到了越来越多的使用。
直线Bresenham算法原理及其实现
实现绘制各种情况直线的Bresenham算法,并将实现的算法应用于任意多边形的绘制,要求多边形的顶点由键盘输入或鼠标拾取,绘制的多边形顶点要准确,图形应该封闭。
要求掌握Bresenham算法的基本原理和算法设计,画出算法实现的程序流程图,使用C或者VC++实现算法,并演示。
-Implementation of the Bresenham line drawing algorithm for various situations, and to achieve an arbitrary polygon rendering algorithm is applied to require the polygon vertices from the keyboard input or mouse pick up and draw the polygon vertices to accurately, graphics should be closed. Bresenham algorithm required to master the basic theory and algorithm design, draw algorithm flow chart of procedures for the use of C or VC++ algorithm, and demonstrate.文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):ii\Debug\ii.exe..\.....\ii.ilk..\.....\ii.obj..\.....\ii.pch..\.....\ii.pdb..\.....\ii.res..\.....\iiDoc.obj..\.....\iiView.obj..\.....\MainFrm.obj..\.....\StdAfx.obj..\.....\vc60.idb..\.....\vc60.pdb..\ii.cpp..\ii.dsp..\ii.dsw..\ii.h..\ii.ncb..\ii.opt..\ii.plg..\ii.rc..\iiDoc.cpp..\iiDoc.h..\iiView.cpp ..\iiView.h..\MainFrm.cpp ..\MainFrm.h ..\ReadMe.txt ..\res\ii.ico..\...\ii.rc2..\...\iiDoc.ico ..\...\Toolbar.bmp ..\Resource.h ..\StdAfx.cpp..\Debug ..\resii。
Bresenham算法与OpenGL技术在DICOM图像处理中的研究
dm, 是 以二进制 文件 的形式 存储 的。D C M 文 c 它 IO
件可 分 为 两 个 部 分 : 件 元 ( i t If m t n 文 Fl Mea no ai ) e r o
和数 据集 ( a e) D t St a
。如 图 I 示 , 中文 件元 所 其
法。并使用 Beehm 算法改进 了L T的生成 , rsn a U 提高 医学影像 的显示效 率。
关键 词
DC M IO
医学 图像
窗宽
窗位 A
实时显 示
中图法分类号 T 7 1 1 P5. ;
文献标志码
随 着 U ( 声 成 像 ) C 计 算 机 断层 成 像 ) I超 、 T( 、 MR ( I核磁共 振成 像 ) C 计 算 机 X 线 成像 ) 电子 、R( 、 内窥镜 、E ( 电子 发 射 断层 成 像 ) MI 分 子 影 PT 正 和 ( 像 ) 医疗 影像 系统 ( A S 不 断涌 现 , 等 PC ) 利用 计 算 机 对 医学 影像 设 备采 集 到 的 图像 进 行 后 处 理 的 医 学 图像处 理 与 分 析 技 术 越来 越 成 为 放 射 科 医 生 和 临 床 医生进行 疾病 诊 断 的重 要 辅 助手 段 - 。 因此 , , 人 们 需要 一 种 能 够 被 广 泛 接 受 的 图 像 标 准 。D C M IO 是美 国放 射 学 会 和 美 国 国家 电器 制 造 商 协 会 组 织
⑥
2 1 SiTc . n r. 0 2 c eh E gg .
B eeh m 算 法 与 O e G rsn a pn L技 术 在 D C M 图像处理中的研究 IO
openGL画直线、圆、椭圆
drawEllipse(250,250,60,40);
/* and flush that buffer to the screen */
glFlush();
}
int main(int argc, char** argv)
{
/* Standard GLUT initialization */
}
}
void dda_line(int xa,int ya,int xb,int yb)//画直线
{
GLfloat delta_x,delta_y,x,y;
int dx,dy,steps;
dx=xb-xa;
dy=yb-ya;
if(abs(dx)>abs(dy))
steps=abs(dx);
else
steps=abs(dy);
cout<<"************************************************"<<endl;
cout<<"****请选择如下操作: *****"<<endl;
cout<<"**** 1.用DDA画线*****"<<endl;
cout<<"**** 2.用Bresenham算法画圆*****"<<endl;
使用openGl画直线(DDA算法)、画圆、椭圆(Bresenham算法)
#include<stdlib.h>
#include<iostream.h>
bresebham 算法
实验名称:C语言图形实验环境的建立以及光栅图形学算法班级:学号:姓名:【实验目的】掌握OpenGL图形实验环境的建立方法;掌握直线及圆的扫描转换算法。
能画出常见的简单图形;能编写、调试通过直线及圆的扫描转换算【实验内容】1、实验环境搭建:测试给定的实例2、在上述程序的基础上编写中点画线算法、Bresenham算法3、编写Bresenham画圆算法实验结果:1.测试给定的实例1、源程序#include <GL/glut.h>#include<math.h>void DDALine(void){float x1=0.0,y1=0.0,x2=500,y2=500;double dx,dy,e,x,y;int i;glClear(GL_COLOR_BUFFER_BIT);dx=x2-x1;dy=y2-y1;e=(fabs(dx)>fabs(dy))? fabs(dx):fabs(dy);dx/=e;dy/=e;x=x1;y=y1;for(i=0;i<=e;i++){glBegin(GL_POINTS);glColor3f(0.8,0.5,0.5);glVertex2f(x/1000,y/1000);glEnd();x+=dx;y+=dy;}glFlush();}void main(int argc, char **argv) {glutInit(&argc, argv); //初始化glutglutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);//设置窗口的模式-深度缓存,单缓存,颜色模型glutInitWindowPosition(200,200); //设置窗口的位置glutInitWindowSize(400,400); //设置窗口的大小glutCreateWindow("DDA Line"); //创建窗口并赋予titleglutDisplayFunc(&DDALine);//调用renderScene把绘制传送到窗口glutMainLoop(); //进入循环等待}2、运行结果截图2.中点划线法:1.源程序#include <GL/glut.h>#include<math.h>void MidpointLine(void){int x0=0.0,y0=0.0,x1=500,y1=500;float a,b,delta1,delta2,d,x,y;a=y0-y1;b=x1-x0;d=2*a+b;delta1=2*a;delta2=2*(a+b);x=x0;y=y0;glClear(GL_COLOR_BUFFER_BIT);while(x<x1){if(d<0){x++;y++;d+=delta2;}else{x++;d+=delta1;}glBegin(GL_POINTS);glColor3f(0.8,0.5,0.5);glVertex2f(x/1000,y/1000);glEnd();}glFlush();}void main(int argc, char **argv) {glutInit(&argc, argv); //初始化glutglutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);//设置窗口的模式-深度缓存,单缓存,颜色模型glutInitWindowPosition(200,200); //设置窗口的位置glutInitWindowSize(400,400); //设置窗口的大小glutCreateWindow("MidpointLine"); //创建窗口并赋予titleglutDisplayFunc(&MidpointLine);//调用renderScene把绘制传送到窗口glutMainLoop(); //进入循环等待} 2程序运行图2.Bresenhamlin1.源程序#include <GL/glut.h>#include<math.h>void bresenham(void){int x1=0.0,y1=0.0,x2=500,y2=500;float x,y,dx,dy,p;glClear(GL_COLOR_BUFFER_BIT);x=x1;y=y1;dx=x2-x1;dy=y2-y1;p=2*dy-dx;for(;x<=x2;x++){glBegin(GL_POINTS);glColor3f(1.0,1.0,1.0);glVertex2f(x/1000,y/1000);glEnd();if(p>=0){y++;p+=2*(dy-dx);}else{p+=2*dy;}}glFlush();}void main(int argc, char **argv) {glutInit(&argc, argv); //初始化glutglutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);//设置窗口的模式-深度缓存,单缓存,颜色模型glutInitWindowPosition(200,200); //设置窗口的位置glutInitWindowSize(400,400); //设置窗口的大小glutCreateWindow("bresenham"); //创建窗口并赋予titleglutDisplayFunc(&bresenham);//调用renderScene把绘制传送到窗口glutMainLoop(); //进入循环等待}2.运行结果4.bresenham画圆算法1.源程序#include <GL/glut.h>#include<math.h>void BresenhamCircle(void){float r=300;double p,x,y;glClear(GL_COLOR_BUFFER_BIT);x=0;y=r;p=3-2*r;for(;x<=y;x++){if(p>=0){p+=4*(x-y)+10;y--;glBegin(GL_POINTS);glColor3f(0.8,0.5,0.5);glVertex2f(x/1000,y/1000);glVertex2f(-x/1000,-y/1000);glVertex2f(y/1000,x/1000);glVertex2f(-y/1000,-x/1000);glVertex2f(x/1000,-y/1000);glVertex2f(-x/1000,y/1000);glVertex2f(y/1000,-x/1000);glVertex2f(-y/1000,x/1000);glEnd();}else{p+=4*x+6;glBegin(GL_POINTS);glColor3f(0.8,0.5,0.5);glVertex2f(x/1000,y/1000);glVertex2f(-x/1000,-y/1000);glVertex2f(y/1000,x/1000);glVertex2f(-y/1000,-x/1000);glVertex2f(x/1000,-y/1000);glVertex2f(-x/1000,y/1000);glVertex2f(y/1000,-x/1000);glVertex2f(-y/1000,x/1000);glEnd();}}glFlush();}void main(int argc, char **argv) {glutInit(&argc, argv); //初始化glutglutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);//设置窗口的模式-深度缓存,单缓存,颜色模型glutInitWindowPosition(400,400); //设置窗口的位置glutInitWindowSize(400,400); //设置窗口的大小glutCreateWindow("Bresenham Circle"); //创建窗口并赋予titleglutDisplayFunc(&BresenhamCircle);//调用renderScene把绘制传送到窗口glutMainLoop(); //进入循环等待}运行结果:3、函数功能及使用说明1.int main(int argc, char *argv[]),这个是带命令行参数的main函数2.glutInit,对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次。
OpenGL-实验2直线生成算法实现教学文案
实验 2 直线生成算法实现1. 实验目的理解基本图形元素光栅化的基本原理, 掌握一种基本图形元素光栅化算法, 利用0penGL 实现直线光栅化的DDA 算法。
2. 实验内容(1) 根据所给的直线光栅化的示范源程序, 在计算机上编译运行, 输出正确结果。
(2) 指出示范程序采用的算法, 以此为基础将其改造为中点线算法或Bresenham 算法,写入实验报告。
(3) 根据示范代码,将其改造为圆的光栅化算法,写入实验报告。
(4) 了解和使用OpenGL 的生成直线的命令,来验证程序运行结果。
3. 实验原理示范代码原理DDA 算法。
下面介绍OpenGL 画线的一些基础知识和glutReshapeFunc( ) 函数。
(1)数学上的直线没有宽度,但0penGL 的直线则是有宽度的。
同时, OpenGL 的直线必须是有限长度,而不是像数学概念那样是无限的。
可以认为,OpenGL的“直线”概念与数学上的“线段” 接近,它可以由两个端点来确定。
这里的线由一系列顶点顺次连接而成, 有闭合和不闭合两种。
前面的实验已经知道如何绘“点” ,那么OpenGL 是如何知道拿这些顶点来做什么呢? 是依次画出来,还是连成线? 或者构成一个多边形? 或是做其他事情? 为了解决这一问题, OpenGL 要求:指定顶点的命令必须包含在gIBegin函数之后,glEnd函数之前(否则指定的顶点将被忽略),并由glBegin 来指明如何使用这些点。
例如:glBegin(GL P0INTS) ,glVertex2f(0.0f, 0.0f);glVertex2f(0.5f, 0.0f);glEnd();则这两个点将分别被画出来。
如果将GL_POINTS替换成GL_LINES则两个点将被认为是直线的两个端点,OpenGL将会画出一条直线。
还可以指定更多的顶点,然后画出更复杂的图形。
另一方面,gIBegin 支持的方式除了GL_POINTS和GL_LINES还有GL LINE STRIP GL LINEL0O P、GL TRIANGLE S GL TRIANGLE STRIP GL TRIANGLE_FA等几何图元。
详解直线扫描算法之---bresenham改进算法(任何斜率,任何方向)
先标明这转载自/xxxxxx91116/article/details/6295714直线扫描算法之---bresenham改进算法(任何斜率,任何方向)by zxx图形学神马的全都是数学,看来以后我不能搞这个,伤脑筋,所以先把我现在懂得先记录下来吧。
不过呢,我的水平实在有限,对于算法这种东西实在难以说明白,请大家包涵。
书上讲的实在是太过简略,所以这里我把一些简单的推导过程都记录下来:1.重温bresenham未改进算法(斜率在0-1之间的直线)我想要记录的是bresenham改进算法,所以在讲解改进算法之前,我先用一个简单的例子说明一下未改进算法的思想:这是一个斜率k在0-1之间的一条直线,我就用斜率为0-1之间的直线来重温:首先,如图1所示,假设x列的像素已定,其坐标为(x,y),那么下一个坐标一定是:(x+1,y+1)或者(x+1,y)。
而是哪一个取决于d的值,如果d>0.5那么就是(x+1,y+1),如果d<0.5,那么就是(x+1,y),而d是什么呢?当然是斜率了。
(原因如下:y=kx+b当x增加1时:y=kx+k+b所以当x增加1是,y方向的增量是d。
)所以每次我们只需要让d=d+k(k是斜率)即可,当d>=1时,就让d减一,这样就保证了d在0-1之间。
当d>0.5,下一个点取(x+1,y+1)当d<0.5,下一个点取(x+1,y)然后呢,我们为了判断的方便,让e=d-0.5,这样就变成了:当e>0,下一个点取(x+1,y+1)当e<0,下一个点取(x+1,y)2.过渡,重温之后,我们就想要改进,为什么要改进呢?因为我们这里面有0.5,还有k,k里面有dx/dy,这些除法和小数都不是我们想要的,我们想要的是,只有整数,且只有加法的算法,下面就全面讨论一下改进算法。
3.改进算法篇(不同斜率,不同方向)这里,我们主要分为4个角度来说明:A.斜率在0-1只间B.斜率在1-无穷之间C.斜率在0-(-1)之间D.斜率在(-1)-负无穷之间E.两种特殊情况,两条直线。
《计算机图形学》练习题(问题详解)
《计算机图形学》练习题1.直线扫描转换的Bresenham算法(1) 请写出生成其斜率介于0和1之间的直线的Bresenham算法步骤。
(2) 设一直线段的起点和终点坐标分别为(1,1)和(8,5),请用Bresenham算法生成此直线段,确定所有要绘制象素坐标。
(1)输入线段的两个端点,并将左端点存储在(x0,y0)中将(x0,y0)装入帧缓存,画出第一个点计算常量∆x, ∆y, 2∆y, and 2∆y-2∆x,并得到决策参数的第一个值:p0 = 2∆y - ∆x④从k=0开始,在沿线路径的每个xk处,进行下列检测:如果pk < 0,下一个要绘制的点就是(xk +1,yk) ,并且pk+1 = pk + 2∆y否则下一个要绘制的点就是(xk +1, yk +1),并且pk+1 = pk + 2∆y- 2∆x⑤重复步骤4,共∆x-1次(2)m=(5-1)/(8-1)=0.57x=7 y=4P0=2y-x=12y=8 2y-2x=-6k pk (xk+1,yk+1)0 1 (2,2)1 -5 (3,2)2 3 (4,3)3 -3 (5,3)4 5 (6,4)5 -1 (7,4)6 7 (8,5)2.已知一多边形如图1所示,其顶点为V1、V2、V3、V4、V5、V6,边为E1、E2、E3、E4、E5、E6。
用多边形的扫描填充算法对此多边形进行填充时(扫描线从下到上)要建立边分类表(sorted edge table)并不断更新活化边表(active edge list)。
(1) 在表1中填写边分类表中每条扫描线上包含的边(标明边号即可); (2) 在表2中写出边分类表中每条边结构中各成员变量的初始值(3) 指出位于扫描线y=6,7,8,9和10时活化边表中包含那些边,并写出这些边中的x 值、y max 值、和斜率的倒数值1/m 。
表1边分类表x 表2 边的初始值4 1 1 9 7 4 6 0 05 1 9 76 0 06 1 9 6 6 0 07 1 1 8 7 7 9 0 1 -18 2 7 9 9 1 -19 3 3 6 9 9 9 1 -13. 二维变换(1) 记P(xf,yf)为固定点,sx、sy分别为沿x轴和y轴方向的缩放系数,请用齐次坐标(Homogeneous Coordinate)表示写出二维固定点缩放变换的变换矩阵。
Bresenham画线算法详解及其OpenGL编程实现
Bresenham画线算法详解及其OpenGL编程实现Bresenham是由Bresenham提出的⼀种精确⽽有效地光栅线⽣成算法,该算法仅使⽤增量整数计算。
另外,它还可以⽤于显⽰其它曲线。
我们以斜率⼤于0⼩于1的线段来进⾏考虑。
以单位x间隔进⾏取样。
每次绘制了当前像素点(x k,y k)之后,需要确定下⼀个要绘制的点是(x k+1,y k)还是(x k+1,y k+1),需要判断哪⼀个点像素点更接近线路径。
在取样位置,我们使⽤d1和d2来表⽰两个像素和线路径的偏移。
在像素列位置x k+1处的直线上的y坐标可计算为:y=m(x k+1)+b那么:d1=y-y k=m(x k+1)+b-y kd2=(y k+1)-y=y k+1-m(x k+1)-b要确定那个像素点更接近于线路径,需测试这两个像素的偏移的差:d1-d2=2m(x k+1)-2y k+2b-1为了使⽤整数进⾏计算,将决策参数定义为:p k=dx*(d1-d2)=2*x k-2dx*y k+cpk和d1-d2符号相同。
其中m=dy/dx,c=2dy+dx(2b-1)。
C是常量,与像素位置⽆关且会在循环计算pk时被消除。
假如y k处的像素⽐y k+1处的像素更接近于线路径,则pk为负,绘制下⾯的像素。
反之为正,绘制上⾯的像素。
我们可以利⽤递增整数运算得到后继的决策参数值。
由k的式⼦可以得出:p k+1=2dy*x k+1-2dx*y k+1+c则:p k+1-p k=2dy(x k+1-x k)-2dx(y k+1-y k)p k+1=p k+2dy-2dx(y k+1-y k)⽽y k+1-y k取1或者0取决于p k的符号。
⽽起始像素位置(x0,y0)的参数p0可以计算得出:再分享⼀下我⽼师⼤神的⼈⼯智能教程吧。
零基础!通俗易懂!风趣幽默!还带黄段⼦!希望你也加⼊到我们⼈⼯智能的队伍中来!p0=2dy-dx由此可以得出斜率⼤于0⼩于1的Bresenham画线算法步骤如下:1、输⼊线段两个端点坐标,将左端点存储在(x0,y0)中;2、画出第⼀个点。
使用OpenGL编程实现Bresenham直线扫描转换算法
实验要求:学习Visual C++ 6.0 集成编程环境的使用,OpenGL编程环境的设置,OpenGL语法及基本函数的使用等基础知识,并编程实现Bresenham直线扫描转换算法,得出相应的输出图形。
源程序:#include<GL/glut.h>void k1() //0<k<1{glClear(GL_COLOR_BUFFER_BIT);glColor3f(0.0,0.0,1.0);glBegin(GL_POINTS);GLint x1=0,y1=0,x2=400,y2=200;GLint x=x1,y=y1;GLint dx=x2-x1,dy=y2-y1,dT=2*(dy-dx),dS=2*dy;GLint d=2*dy-dx;glV ertex2i(x,y);while(x<x2){x++;if(d<0)d=d+dS;else{y++;d=d+dT;}glV ertex2i(x,y);}glEnd();glFlush();}void k2() //k>1{glClear(GL_COLOR_BUFFER_BIT);glColor3f(0.0,1.0,0.0);glBegin(GL_POINTS);GLint x1=0,y1=0,x2=200,y2=400;GLint x=x1,y=y1;GLint dx=x2-x1,dy=y2-y1,dT=2*(dx-dy),dS=2*dx;GLint d=2*dx-dy;glV ertex2i(x,y);while(y<y2){y++;if(d<0)d=d+dS;else{x++;d=d+dT;}glV ertex2i(x,y);}glEnd();glFlush();}void k3() //-1<k<0{glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,0.0);glBegin(GL_POINTS);GLint x1=0,y1=400,x2=400,y2=200;GLint x=x1,y=y1;GLint dx=x2-x1,dy=y2-y1,dT=2*dy,dS=2*dy+2*dx;GLint d=2*dy-dx;glV ertex2i(x,y);while(x<x2){x++;if(d<0){y--;d=d+dS;}elsed=d+dT;glV ertex2i(x,y);}glEnd();glFlush();}void k4() //k<-1{glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,1.0);glBegin(GL_POINTS);GLint x1=0,y1=400,x2=200,y2=0;GLint x=x1,y=y1;GLint dx=x2-x1,dy=y2-y1,dT=-2*dy-2*dx,dS=-2*dx;GLint d=-dy-2*dx;glV ertex2i(x,y);while(y>y2){y--;if(d>0)d=d+dS;else{x++;d=d+dT;}glV ertex2i(x,y);}glEnd();glFlush();}void main(int argc,char ** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowSize(400,400);glutInitWindowPosition(200,100);glutCreateWindow("0<k<1(k=1/2)");glClearColor(1.0,1.0,0.0,0.0);gluOrtho2D(0.0,400.0,0.0,400.0);glutDisplayFunc(k1);glutCreateWindow("1<k(k=2)");glClearColor(1.0,0.0,1.0,0.0);gluOrtho2D(0.0,400.0,0.0,400.0);glutDisplayFunc(k2);glutCreateWindow("-1<k<0(k= -1/2)");glClearColor(0.0,1.0,1.0,0.0);gluOrtho2D(0.0,400.0,0.0,400.0);glutDisplayFunc(k3);glutCreateWindow("K<-1(k=-2)");glClearColor(0.0,1.0,0.0,0.0);gluOrtho2D(0.0,400.0,0.0,400.0);glutDisplayFunc(k4);glutMainLoop();}。
2.3直线扫描转换Bresenham算法
x
i
1
i i
i 1
y y
1
(e>0) (e≤0)
x y
i 1
x
i
1
i i
i 1
y y
1
(e>0) (e≤0)
e > 0,y方向递增1;e<0,y方向不递增 e = 0 时,可任取上、下光栅点显示 • e初 = -0.5 • 每走一步有e = e+k • if (e>0) then e=e-1
d
该算法的思想是通过各行、各列像素中心构造一组虚拟网格 线,按照直线起点到终点的顺序,计算直线与各垂直网格线 的交点,然后根据误差项的符号确定该列象素中与此交点最 近的象素。
k d k k
(xi,yi)
d
d
假设每次x+1,y的递增(减)量为0或1,它取决于实际直线与 最近光栅网格点的距离,这个距离的最大误差为0.5。
关键是把这个算法的效率也搞到整数加法,否则就 是失败。如何提高到整数加法?
x y
i 1
x
i
i i
1 1
i 1
y y
(d>0.5) (d≤0.5)
如何把这个算法的效率也提高到整数加法? 改进1:令 e = d-0.5
x y
i 1
所以该算法集中了dda和中点两个算法的优点而且应用范围广泛小结1计算机科学问题的核心就是算法2领会算法中所蕴含的创新思想3科学研究无止境学术面前人人平等把一个含有乘法和一个加法的普通直线算法是如何通过改进和完善其性能最终变成整数加法的一个精彩过程改进和完善算法的过程中所体现出来的一些闪光的思想是我们所要认识和领会的学会研究性学习对已有的算法提出质疑找出其不足
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验要求:
学习Visual C++ 6.0 集成编程环境的使用,OpenGL编程环境的设置,OpenGL语法及基本函数的使用等基础知识,并编程实现Bresenham直线扫描转换算法,得出相应的输出图形。
源程序:
#include<GL/glut.h>
void k1() //0<k<1
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0,0.0,1.0);
glBegin(GL_POINTS);
GLint x1=0,y1=0,x2=400,y2=200;
GLint x=x1,y=y1;
GLint dx=x2-x1,dy=y2-y1,dT=2*(dy-dx),dS=2*dy;
GLint d=2*dy-dx;
glV ertex2i(x,y);
while(x<x2)
{
x++;
if(d<0)
d=d+dS;
else
{
y++;
d=d+dT;
}
glV ertex2i(x,y);
}
glEnd();
glFlush();
}
void k2() //k>1
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0,1.0,0.0);
glBegin(GL_POINTS);
GLint x1=0,y1=0,x2=200,y2=400;
GLint x=x1,y=y1;
GLint dx=x2-x1,dy=y2-y1,dT=2*(dx-dy),dS=2*dx;
GLint d=2*dx-dy;
glV ertex2i(x,y);
while(y<y2)
{
y++;
if(d<0)
d=d+dS;
else
{
x++;
d=d+dT;
}
glV ertex2i(x,y);
}
glEnd();
glFlush();
}
void k3() //-1<k<0
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
GLint x1=0,y1=400,x2=400,y2=200;
GLint x=x1,y=y1;
GLint dx=x2-x1,dy=y2-y1,dT=2*dy,dS=2*dy+2*dx;
GLint d=2*dy-dx;
glV ertex2i(x,y);
while(x<x2)
{
x++;
if(d<0)
{
y--;
d=d+dS;
}
else
d=d+dT;
glV ertex2i(x,y);
}
glEnd();
glFlush();
}
void k4() //k<-1
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,1.0);
glBegin(GL_POINTS);
GLint x1=0,y1=400,x2=200,y2=0;
GLint x=x1,y=y1;
GLint dx=x2-x1,dy=y2-y1,dT=-2*dy-2*dx,dS=-2*dx;
GLint d=-dy-2*dx;
glV ertex2i(x,y);
while(y>y2)
{
y--;
if(d>0)
d=d+dS;
else
{
x++;
d=d+dT;
}
glV ertex2i(x,y);
}
glEnd();
glFlush();
}
void main(int argc,char ** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(400,400);
glutInitWindowPosition(200,100);
glutCreateWindow("0<k<1(k=1/2)");
glClearColor(1.0,1.0,0.0,0.0);
gluOrtho2D(0.0,400.0,0.0,400.0);
glutDisplayFunc(k1);
glutCreateWindow("1<k(k=2)");
glClearColor(1.0,0.0,1.0,0.0);
gluOrtho2D(0.0,400.0,0.0,400.0);
glutDisplayFunc(k2);
glutCreateWindow("-1<k<0(k= -1/2)");
glClearColor(0.0,1.0,1.0,0.0);
gluOrtho2D(0.0,400.0,0.0,400.0);
glutDisplayFunc(k3);
glutCreateWindow("K<-1(k=-2)");
glClearColor(0.0,1.0,0.0,0.0);
gluOrtho2D(0.0,400.0,0.0,400.0);
glutDisplayFunc(k4);
glutMainLoop();
}。