代码改变世界

中点Bresenham 算法及实现

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

这里不仔细讲原理,只是把我写的算法发出来,跟大家分享下,如果有错误的话,还请大家告诉我,如果写的不好,也请指出来,一起讨论进步。

只写出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;
}