首先设置变量用于进行鼠标交互和键盘交互:
int m = 0;GLdouble m1 =0, m2 = 0;
1.实验入口主函数:
//主函数int main(int argc, char** argv) {glutInit(&argc, argv);//初始化openGlglutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(100, 100);//显示窗口的位置glutInitWindowSize(350, 150);//显示窗口的大小glutCreateWindow("实验1");//表示用键盘来进行交互的init();//自定义的方法glutDisplayFunc(display);//绘制函数glutKeyboardFunc(myKayBoard);//点击键盘的时候就会调用该方法glutMouseFunc(mouseMoton);//鼠标点击时会调用该方法glutMainLoop();return 0;}
2.对窗口进行一些初始化:
void init(void) {glClearColor(1.0, 1.0, 1.0, 0.0);//申明一个刷新的颜色glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, 500, 0, 500);//glShadeModel(GL_FLAT);}
3.显示函数的编写:
void display(void) {glClear(GL_COLOR_BUFFER_BIT);//用颜色刷新glColor3f(0.8, 0.5, 0.6);//绘制的颜色glPointSize(1);//绘制像素的大小if (m==0)bresenham(1.08,2.00, 373.80,367.66);if (m==1)halfzd(99.09,120.08,373.80, 367.66);if (m==2)myDDA(140.7, 200.3, 373.80, 367.66);glFlush();}
4.关于DDA算法的实现:
void myDDA(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) {x1 = x1 + m1;y1 = y1 + m2;double dx = fabs(x2 - x1);double dy = fabs(y2 - y1);double steps;if (dx > dy)steps = dx;elsesteps = dy;double stepX = dx / steps;double stepY = dy / steps;glBegin(GL_POINTS);for (int i = 0;i < (int)steps;i++) {glVertex2f(x1, y1);x1 += stepX;y1 += stepY;}glEnd();}
5.关于中点画线算法的实现:
void halfzd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) {double a = y1+m2-y2;double b = x2-x1-m1;double d = a + a + b;double d1 = a + a;double d2 = a + b + a + b;glBegin(GL_POINTS);glVertex2f(x1+m1, y1+m2);while (x1+m1 < x2) {if (d < 0) {x1++;y1++;d += d2;}else {x1++;d += d1;}glVertex2f(x1+m1, y1+m2);}glEnd();}
6.关于Bresenham画线算法的实现:
void bresenham(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) {double dx = x2 - x1-m1;double dy = y2 - y1-m2;double k = dy / dx;double e = 0.5;glBegin(GL_POINTS);//表示画一个点for (int i = 0;i <= dx;i++) {glVertex2f(x1+m1, y1+m2);x1 = x1 + 1;e = e + k;if (e >= 0) {y1++;e = e - 1;}}glEnd();}
7.对于鼠标点击函数
void mouseMoton(GLint button,GLint state,GLint x,GLint y) {//鼠标左点击if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {m1 = x;m2 = y;glutPostRedisplay();}//鼠标滚轮键if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) {m1 = x;m2 = y;glutPostRedisplay();}//鼠标右点击if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {m1 = x;m2 = y;glutPostRedisplay();}}
8.键盘点击函数:
void myKayBoard(unsigned char key, int x, int y) {//key对应键盘上面的一个键switch (key){case'z':m = 0;break;case'x':m = 1;break;case'c':m = 2;break;}//改变值后我们要使图形重新显示一遍glutPostRedisplay();}
完整版代码如下:
#include <iostream>#include <windows.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> int m = 0;GLdouble m1 =0, m2 = 0;void bresenham(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) {double dx = x2 - x1-m1;double dy = y2 - y1-m2;double k = dy / dx;double e = 0.5;glBegin(GL_POINTS);//表示画一个点for (int i = 0;i <= dx;i++) {glVertex2f(x1+m1, y1+m2);x1 = x1 + 1;e = e + k;if (e >= 0) {y1++;e = e - 1;}}glEnd();}void halfzd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) {double a = y1+m2-y2;double b = x2-x1-m1;double d = a + a + b;double d1 = a + a;double d2 = a + b + a + b;glBegin(GL_POINTS);glVertex2f(x1+m1, y1+m2);while (x1+m1 < x2) {if (d < 0) {x1++;y1++;d += d2;}else {x1++;d += d1;}glVertex2f(x1+m1, y1+m2);}glEnd();}void myDDA(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) {x1 = x1 + m1;y1 = y1 + m2;double dx = fabs(x2 - x1);double dy = fabs(y2 - y1);double steps;if (dx > dy)steps = dx;elsesteps = dy;double stepX = dx / steps;double stepY = dy / steps;glBegin(GL_POINTS);for (int i = 0;i < (int)steps;i++) {glVertex2f(x1, y1);x1 += stepX;y1 += stepY;}glEnd();}//键盘点击函数void myKayBoard(unsigned char key, int x, int y) {//key对应键盘上面的一个键switch (key){case'z':m = 0;break;case'x':m = 1;break;case'c':m = 2;break;}//改变值后我们要使图形重新显示一遍glutPostRedisplay();}//鼠标点击函数void mouseMoton(GLint button,GLint state,GLint x,GLint y) {//鼠标左点击if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {m1 = x;m2 = y;glutPostRedisplay();}//鼠标滚轮键if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) {m1 = x;m2 = y;glutPostRedisplay();}//鼠标右点击if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {m1 = x;m2 = y;glutPostRedisplay();}}void display(void) {glClear(GL_COLOR_BUFFER_BIT);//用颜色刷新glColor3f(0.8, 0.5, 0.6);//绘制的颜色glPointSize(1);//绘制像素的大小if (m==0)bresenham(1.08,2.00, 373.80,367.66);if (m==1)halfzd(99.09,120.08,373.80, 367.66);if (m==2)myDDA(140.7, 200.3, 373.80, 367.66);glFlush();}void init(void) {glClearColor(1.0, 1.0, 1.0, 0.0);//申明一个刷新的颜色glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, 500, 0, 500);//glShadeModel(GL_FLAT);}//主函数int main(int argc, char** argv) {glutInit(&argc, argv);//初始化openGlglutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(100, 100);//显示窗口的位置glutInitWindowSize(350, 150);//显示窗口的大小glutCreateWindow("实验1");//表示用键盘来进行交互的init();//自定义的方法glutDisplayFunc(display);//绘制函数glutKeyboardFunc(myKayBoard);//点击键盘的时候就会调用该方法glutMouseFunc(mouseMoton);//鼠标点击时会调用该方法glutMainLoop();return 0;}
实验结果:
在实验中我同时写入了ADD划线算法,中点画线算法、Bresenham画线算法,可以通过键盘的输入来控制不同算法的显示窗口的显示,跟人进行交互:
运行后的窗口图形如下,为默认的Bresenham画线算法:
当我们键盘输入x时,该窗口的显示切换到中点画线算法,会出现下图所示:
当我们从键盘键入c时,该窗口的显示切换到中点画线算法,会出现如下所示:
在我们的每一个图形窗口可以通过鼠标左键,或者鼠标右键,或者滚动鼠标轮,我们可以自由切换任意的线段方向。也就是可以处理任意方向和任意斜率的直线端,也对非整数坐标进行了处理。比如如下: