## 中点Bresenham 算法及实现

2010-12-04 20:08  风恋残雪  阅读(1125)  评论(0编辑  收藏  举报

(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),否则结束。

#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);
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);
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);
}
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;
}