这里不仔细讲原理,只是把我写的算法发出来,跟大家分享下,如果有错误的话,还请大家告诉我,如果写的不好,也请指出来,一起讨论进步。
只写出0<=k<=1时的Bresenham算法绘图过程
(1) 输入直线的两端点,P0(x0, y0)和P1(x1, y1).
(2) 计算初始值dx, dy, d = dx - 2 * dy, x = x0, y = y0.
(3) 绘制点(x, y), 判断d的符号。若d < 0, 则(x, y)更新为(x+1, y+1), d更新为d + 2 * dx - 2 * dy;否则(x, y)更新为(x+1, y), d 更新为d - 2 * dy
(4)当直线没有画完时,重复步骤 (3),否则结束。
水平、垂直和|k| = 1的直线可以直接装入帧缓冲存储器而无须进行画线处理,我的程序也处理了下。下面我把自己写的程序写下来,与大家分享,如有错误还请指出,只是粗略得测试了下没发下错误。
#include <GL/freeglut.h> void init (void) { glClearColor (0.0f, 0.0f, 0.0f, 1.0f); } void drawLine (int x1, int y1, int x2, int y2) { int dx, dy, d, upInc, downInc, leftInc, rightInc, x, y; if (x1 == x2) { // 斜率 k 不存在 if (y1 < y2) { y = y1; glBegin (GL_POINTS); do { glVertex2i (x1, y); ++ y; }while (y <= y2); glEnd (); } else { y = y2; glBegin (GL_POINTS); do { glVertex2i (x1, y); ++ y; }while (y <= y1); glEnd (); } } else if (y1 == y2) { // k = 0 if (x1 < x2) { glBegin (GL_POINTS); x = x1; do { glVertex2i (x, y1); ++ x; }while (x <= x2); glEnd (); } else { glBegin(GL_POINTS); x = x2; do { glVertex2i (x, y1); ++ x; }while (x <= x1); glEnd (); } } else { if (x1 > x2) { int temp = x1; x1 = x2; x2 = temp; temp = y1; y1 = y2; y2 = temp; } x = x1; y = y1; dx = x2 - x1; dy = y2 -y1; // k == 1 if (dx == dy) { glBegin (GL_POINTS); do { glVertex2i (x, y); ++ x; ++ y; }while (x <= x2); glEnd (); } // k == -1 else if (dx == -dy) { glBegin (GL_POINTS); do { glVertex2i (x, y); ++ x; -- y; }while (x <= x2); glEnd (); } else { if (dy > 0) { // 0 <k < 1 if (dy < dx) { dy <<= 1; d = dx - dy; dx <<= 1; upInc = dx - dy; downInc = -dy; glBegin (GL_POINTS); while (x <= x2) { glVertex2i (x, y); ++ x; if (d < 0) { ++ y; d += upInc; } else { d += downInc; } } glEnd (); } else { // k > 1 dx <<= 1; d = dx - dy; dy <<= 1; rightInc = dx - dy; leftInc = dx; glBegin (GL_POINTS); while (y <= y2) { glVertex2i (x, y); ++ y; if (d > 0) { ++ x; d += rightInc; } else { d += leftInc; } } // while glEnd (); } } // if (dy > 0) else { // 0 > k > -1 if (-dy < dx) { dy <<= 1; d = -dx - dy; dx <<= 1; downInc = -dx - dy; upInc = -dy; glBegin (GL_POINTS); while (x <= x2) { glVertex2i (x, y); ++ x; if (d > 0) { d += downInc; -- y; } else { d += upInc; } } // while glEnd (); } // if (-dy > dx) else { // k < -1 dx <<= 1; d = -dx - dy; dy <<= 1; leftInc = - dx; rightInc = -dx - dy; glBegin (GL_POINTS); while (y >= y2) { glVertex2i (x, y); -- y; if (d < 0) { d += rightInc; ++ x; } else { d += leftInc; } } glEnd (); } } } } } void display (void) { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); glColor3f (1.0f, 0.0f, 0.0f); // Vertical line drawLine (0, -200, 0, 200); // Horizontal line drawLine (-200, 0, 200, 0); // k = 1 line drawLine (-200, -200, 200, 200); // k = -1 line drawLine (-200, 200, 200, -200); // k = 1/2 line drawLine (200, 100, -200, -100); // k = 2 line drawLine (-100, -200, 100, 200); // k = -1/2 line drawLine (-200, 100, 200, -100); // k = -2 line drawLine (-100, 200, 100, -200); drawLine (30, 120, 10, 70); drawLine (10, 70, 30, 10); drawLine (30, 10, 60, 50); drawLine (60, 50, 80, 10); drawLine (80, 10, 120, 80); drawLine (120, 80, 70, 80); drawLine (70, 80, 30, 120); glutSwapBuffers (); } void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); if (w <= h) { gluOrtho2D (-200.0, 200.0, -200.0 * (GLfloat) h / (GLfloat) w, 200.0 * (GLfloat) h / (GLfloat) w); } else { gluOrtho2D (-200.0 * (GLfloat) w / (GLfloat) h,200.0 * (GLfloat) w / (GLfloat) h, -200.0, 200.0); } glMatrixMode (GL_MODELVIEW); glLoadIdentity (); } void keyboard (unsigned char key, int x, int y) { switch (key) { case 27: // 'VK_ESCAPE' exit (0); break; default: break; } } int main (int argc, char ** argv) { glutInit (&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize (600, 600); glutCreateWindow ("Bresenham line"); init (); glutReshapeFunc (reshape); glutDisplayFunc (display); glutKeyboardFunc (keyboard); glutMainLoop (); return 0; }