计算机图形学OpenGL学习实验二——Bresenham画线算法的模拟

  • 写在开头:

相关实验是学校开设课程的相关实验,本人所作较为粗浅,若有同校师弟浏览,望看懂借鉴而非照搬全抄。


  • 实验目的:

理解Bresenham画线算法


  • 实验内容:

用Bresenham画线算法实现水平、垂直、斜率大于1、斜率小于1、斜率为正、斜率为负等各种情况(不能直接调用OpenGL画线函数)。


  • 实现效果及步骤(或流程)

实现效果:

         绘制了一个大小为40 × 40 网格图(坐标为0~39),用以模拟屏幕像素。以(20,20)为中心,绘制了六条“直线”。这些“直线”模拟了当屏幕像素点被放大至肉眼可见时,Bresenham算法绘制直线时的绘制情况。

计算机图形学OpenGL学习实验二——Bresenham画线算法的模拟_第1张图片

实现流程:

       首先判断斜率是否小于1,如果是则计算p值(p=2dy –dx),而后选择起点并绘制起点;接着判断斜率正负,如果为正,则x递增1,通过p值判断y值,并且计算相应的p值,否则x递减1。

       如果斜率大于1,则将求p值公式x、y互换,并且将x递增或递减的变化过程改为y递增或递减。

具体流程见下图。

计算机图形学OpenGL学习实验二——Bresenham画线算法的模拟_第2张图片


  • 创新设计和实现方法

创新设计:

        使用正方形块模拟屏幕像素点,绘制屏幕网格图,展示Bresenham算法选点的过程。

实现方法:

    1.网格的绘制:

        设置矩形块为线性填充,使用二维数组blocks[40][40]存储矩形块,取blocks[x][y],即代表取屏幕坐标(x,y)。

相关代码如下:

void initBlocks() {

glPolygonMode(GL_FRONT, GL_LINE);

GLint x = 0, y = 0;

glColor3f(0.0, 0.0, 1.0);

//初始化矩形块坐标

for (int i = 0; i < 40; i++) {

       for (int j = 0; j < 40; j++) {

              blocks[i][j].point[0] = x;

              blocks[i][j].point[1] = y;

              y +=  10;

       }

       y = 0;

       x += 10;

}

//绘制矩形

for (int i = 0; i < 40; i++) {

       for (int j = 0; j < 40; j++) {

              glRecti(blocks[i][j].point[0], blocks[i][j].point[1],

                     blocks[i][j].point[0] + 10, blocks[i][j].point[1] + 10);

       }

}

glFlush();

}

 

2.绘制“像素点”

        如果需要绘制点(x,y),那么绘制矩形块blocks[x][y]即可。

        相关代码如下:

//选取像素块

void setPixel(GLint x, GLint y) {

glPolygonMode(GL_FRONT, GL_FILL);//设置矩形为填充模式

glColor3f(0.0, 1.0, 0.0);

glRecti(blocks[x][y].point[0], blocks[x][y].point[1],

blocks[x][y].point[0] + 10, blocks[x][y].point[1] + 10);

glFlush();

}

  • 源代码
#include 
#include 

void bresenham(GLint x1, GLint y1, GLint x2, GLint y2);
GLsizei winWidth = 400, winHeight = 400;

//“像素块”
struct block {
	GLint point[2];
};

block blocks[40][40];

//初始化像素块
void initBlocks() {
	glPolygonMode(GL_FRONT, GL_LINE);
	GLint x = 0, y = 0;
	glColor3f(0.0, 0.0, 1.0);
	for (int i = 0; i < 40; i++) {
		
		for (int j = 0; j < 40; j++) {
			
			blocks[i][j].point[0] = x;
			blocks[i][j].point[1] = y;
			y +=  10;
		}
		y = 0;
		x += 10;
	}
	for (int i = 0; i < 40; i++) {
		for (int j = 0; j < 40; j++) {
			glRecti(blocks[i][j].point[0], blocks[i][j].point[1],
				blocks[i][j].point[0] + 10, blocks[i][j].point[1] + 10);
		}
	}
	//调试用
	//for (int i = 0; i < 40; i++) {

	//	for (int j = 0; j < 40; j++) {
	//		std::cout << i << ","  < 0 && dy_sigend > 0)) {
			//判断所给点的起点
			if (x1 > x2) {
				x = x2;
				y = y2;
				x2 = x1;
			}
			else {
				x = x1;
				y = y1;
			}
			setPixel(x, y);

			while (x < x2) {
				x++;
				if (p < 0) {
					p += twoDy;
				}
				else {
					++y;
					p += twoDyMinusDx;
				}
				setPixel(x, y);
			}
		}
		else {
			//判断所给点的起点
			if (x1 < x2) {
				x = x2;
				y = y2;
				x2 = x1;
			}
			else {
				x = x1;
				y = y1;
			}
			setPixel(x, y);

			while (x > x2) {
				x--;
				if (p < 0) {
					p += twoDy;
				}
				else {
					++y;
					p += twoDyMinusDx;
				}
				setPixel(x, y);
			}
		}
		
	}
	else {
		p = twoDx - dy;
		//判断斜率正负
		if ((dx_sigend < 0 && dy_sigend < 0) || (dx_sigend > 0 && dy_sigend > 0)) {
			//判断所给点的起点
			if (y1 > y2) {
				x = x2;
				y = y2;
				y2 = y1;
			}
			else {
				x = x1;
				y = y1;
			}
			setPixel(x, y);

			while (y < y2) {
				y++;
				if (p < 0) {
					p += twoDx;
				}
				else {
					++x;
					p += twoDxMinusDy;
				}
				setPixel(x, y);
			}
		}
		else {
			//判断所给点的起点
			if (y1 < y2) {
				x = x2;
				y = y2;
				y2 = y1;
			}
			else {
				x = x1;
				y = y1;
			}
			setPixel(x, y);

			while (y > y2) {
				y--;
				if (p < 0) {
					p += twoDx;
				}
				else {
					++x;
					p += twoDxMinusDy;
				}
				setPixel(x, y);
			}
		}
	}
	

}

void winReshapeFcn(GLint newWidth, GLint newHeight) {
	glClear(GL_COLOR_BUFFER_BIT);
	glViewport(0, 0, newWidth, newHeight);
	glLoadIdentity();
	gluOrtho2D(0.0, GLdouble(newWidth), 0.0, GLdouble(newHeight));

	winWidth = newWidth;
	winHeight = newHeight;
}


void main(int argc, char ** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(winWidth, winHeight);
	glutCreateWindow("CGLab3_CaiYiPei");

	init();

	glutDisplayFunc(displayFcn);
	glutReshapeFunc(winReshapeFcn);

	glutMainLoop();
}

 

你可能感兴趣的:(计算机图形学OpenGL学习实验二——Bresenham画线算法的模拟)