计算机图形学实验2-画线和画圆

实验要求:

1. 学习并使用DDA算法进行画直线,同时学会Bresenham算法画直线。

2. 学会画弧线并明白原理

DDA算法直线:

#include <iostream>
#include <math.h>
#include <GL\glut.h>
using namespace std;
GLint bx, ex, by, ey;
// 画点
void draw(GLint x, GLint y) {
	glBegin(GL_POINTS);
	glVertex2i(x, y);
	glEnd();
}
// DDA算法
void BRE(GLint x1, GLint x2, GLint y1, GLint y2) {
	glClear(GL_COLOR_BUFFER_BIT);
	GLint dx = abs(x1 - x2);
	GLint dy = abs(y1 - y2);
	GLfloat e = dy / float(dx);
	if (dy < dx) { // x为步长
		// x1 < x2
		if (x1 < x2) {
			// y1 < y2
			if (y1 < y2) {
				float x = x1, y = y1;
				for (GLint i = x1; i <= x2; i++) {
					draw(i, int(y + 0.5));
					y = y + e;
				}
			}
			// y1 > y2
			else {
				float x = x1, y = y1;
				for (GLint i = x1; i <= x2; i++) {
					draw(i, int(y - 0.5));
					y = y - e;
				}
			}

		}
		// x1 > x2
		else {
			// y1 < y2
			if (y1 < y2) {
				float x = x1, y = y1;
				for (GLint i = x1; i >= x2; i--) {
					draw(i, int(y + 0.5));
					y = y + e;
				}
			}
			// y1 > y2
			else {
				float x = x1, y = y1;
				for (GLint i = x1; i >= x2; i--) {
					draw(i, int(y - 0.5));
					y = y - e;
				}
			}
		}
	}
	// y为步长
	else {
		// y1 < y2
		if (y1 < y2) {
			// x1 < x2
			if (x1 < x2) {
				float x = x1, y = y1;
				for (GLint i = y1; i <= y2; i++) {
					draw(int(x + 0.5), i);
					x = x + 1 / e;
				}
			}
			// x1 > x2
			else {
				float x = x1, y = y1;
				for (GLint i = y1; i <= y2; i++) {
					draw(int(x - 0.5), i);
					x = x - 1 / e;
				}
			}
		}
		// y1 > y2
		else {
			// x1 < x2
			if (x1 < x2) {
				float x = x1, y = y1;
				for (GLint i = y1; i >= y2; i--) {
					draw(int(x + 0.5), i);
					x = x + 1 / e;
				}
			}
			// x1 > x2
			else {
				float x = x1, y = y1;
				for (GLint i = y1; i >= y2; i--) {
					draw(int(x - 0.5), i);
					x = x - 1 / e;
				}
			}
		}
	}

}
// 图形描绘
void display() {
	BRE(bx, ex, by, ey);
}
// 鼠标点击
void click(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
		ex = x;
		ey = y;
		BRE(bx, ex, by, ey);
		glutSwapBuffers();
	}
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		bx = x;
		by = y;
	}
}
// 鼠标移动
void move(int x, int y) {
	ex = x;
	ey = y;
	BRE(bx, ex, by, ey);
	glutSwapBuffers();
}
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(800, 800);
	glutCreateWindow("DDA算法画直线");
	glClearColor(1, 1, 1, 1);//设置绘制窗口颜色为白色
	//glClear(GL_COLOR_BUFFER_BIT);//清除窗口内容
	glMatrixMode(GL_PROJECTION);/*设置为投影类型模式和其他观察参数*/
	//glLoadIdentity();/*设置为投影类型模式和其他观察参数*/
	gluOrtho2D(0, 800, 800, 0);/*设置为投影类型模式和其他观察参数,观察窗口的大小要与画布大小一致,所以直接设置全局变量即可*/
	glPointSize(3.0f);//设置点的大小
	glColor3f(10, -10, -10);//设置点的颜色
	glutDisplayFunc(&display);
	glutMouseFunc(click);
	glutMotionFunc(move);
	glutMainLoop();
	return 0;
}

使用方法:

用鼠标左键点击,并按住不放开,拖动鼠标进行绘制直线

Bresenham算法:

#include <iostream>
#include <math.h>
#include <GL/glut.h>
using namespace std;
GLint bx, ex, by, ey;
// 画点
void draw(GLint x, GLint y) {
	glBegin(GL_POINTS);
	glVertex2i(x, y);
	glEnd();
}
// bresenham算法
void BRE(GLint x1, GLint x2, GLint y1, GLint y2) {
	glClear(GL_COLOR_BUFFER_BIT);
	GLint dx = abs(x1 - x2);
	GLint dy = abs(y1 - y2);
	int tx = x2 > x1 ? 1 : -1;
	int ty = y2 > y1 ? 1 : -1;
	GLint e = (x1 - x2) * tx;
	GLfloat k = (y2 - y1) / float(x2 - x1); // 判断是以x为步长还是以y为步长
	if (abs(k) < 1) { // x为步长
		if (tx > 0) {
			GLint y = y1;
			for (GLint x = x1; x <= x2; x++) {
				draw(x, y);
				if (ty > 0) {
					e = e + 2 * dy;
					if (e >= 0) {
						y++;
						e = e - 2 * dx;
					}
				}
				else {
					e = e - 2 * dy;
					if (e <= 0) {
						y--;
						e = e + 2 * dx;
					}
				}
			}
		}
		else {
			GLint y = y1;
			for (GLint x = x1; x >= x2; x--) {
				draw(x, y);
				if (ty > 0) {
					e = e + 2 * dy;
					if (e >= 0) {
						y++;
						e = e - 2 * dx;
					}
				}
				else {
					e = e - 2 * dy;
					if (e <= 0) {
						y--;
						e = e + 2 * dx;
					}
				}
			}
		}
	}
	else {
		e = (y1 - y2) * ty;
		if (ty > 0) {
			GLint x = x1;
			for (GLint y = y1; y <= y2; y++) {
				draw(x, y);
				if (tx > 0) {
					e = e + 2 * dx;
					if (e >= 0) {
						x++;
						e = e - 2 * dy;
					}
				}
				else {
					e = e - 2 * dx;
					if (e <= 0) {
						x--;
						e = e + 2 * dy;
					}
				}
			}
		}
		else {
			GLint x = x1;
			for (GLint y = y1; y >= y2; y--) {
				draw(x, y);
				if (tx > 0) {
					e = e + 2 * dx;
					if (e >= 0) {
						x++;
						e = e - 2 * dy;
					}
				}
				else {
					e = e - 2 * dx;
					if (e <= 0) {
						x--;
						e = e + 2 * dy;
					}
				}
			}
		}
	}
}
// 图形描绘
void display() {
	BRE(bx, ex, by, ey);
}
// 鼠标点击
void click(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
		ex = x;
		ey = y;
		BRE(bx, ex, by, ey);
		glutSwapBuffers();
	}
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		bx = x;
		by = y;
	}
}
// 鼠标移动
void move(int x, int y) {
	ex = x;
	ey = y;
	BRE(bx, ex, by, ey);
	glutSwapBuffers();
}
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(800, 800);
	glutCreateWindow("Bresenham算法画直线");
	glClearColor(1, 1, 1, 1);//设置绘制窗口颜色为白色
	//glClear(GL_COLOR_BUFFER_BIT);//清除窗口内容
	glMatrixMode(GL_PROJECTION);/*设置为投影类型模式和其他观察参数*/
	//glLoadIdentity();/*设置为投影类型模式和其他观察参数*/
	gluOrtho2D(0, 800, 800, 0);/*设置为投影类型模式和其他观察参数,观察窗口的大小要与画布大小一致,所以直接设置全局变量即可*/
	glPointSize(3.0f);//设置点的大小
	glColor3f(10, -10, -10);//设置点的颜色
	glutDisplayFunc(&display);
	glutMouseFunc(click);
	glutMotionFunc(move);
	glutMainLoop();
	return 0;
}

画弧线算法

#include <iostream>
#include <math.h>
#include <GL\glut.h>
using namespace std;
GLint bx, ex, by, ey;
// 画点
void draw(GLint x, GLint y) {
	glBegin(GL_POINTS);
	glVertex2i(x, y);
	glEnd();
}
void CirclePoint(int x, int y, int x1, int y1) {
	draw(x + x1, y + y1); draw(x + x1, -y + y1); draw(-x + x1, y + y1); draw(-x + x1, -y + y1);
	draw(y + x1, x + y1); draw(-y + x1, x + y1); draw(y + x1, -x + y1); draw(-y + x1, -x + y1);
}
// 中心画圆
void BRE(GLint x1, GLint x2, GLint y1, GLint y2) {
	glClear(GL_COLOR_BUFFER_BIT);
	int dx = abs(x2 - x1), dy = abs(y2 - y1);

	float r = sqrt(pow(dx, 2) + pow(dy, 2));
	//float r = 100;
	GLint x = 0, y = r;
	float d = 1.25 - r;
	CirclePoint(x, y, x1, y1);
	cout << "xy" << x << "  " << y << endl;
	while (x <= y) {
		if (d < 0) {
			d += 2 * x + 3;
		}
		else {
			d += 2 * (x - y) + 5;
			y--;
		}
		x++;
		CirclePoint(x, y, x1, y1);
	}

}
// 图形描绘
void display() {
	BRE(bx, ex, by, ey);
}
// 鼠标点击
void click(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
		ex = x;
		ey = y;
		BRE(bx, ex, by, ey);
		glutSwapBuffers();
	}
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		bx = x;
		by = y;
	}
}
// 鼠标移动
void move(int x, int y) {
	ex = x;
	ey = y;
	cout << "鼠标" << x << " " << y << endl;
	BRE(bx, ex, by, ey);
	glutSwapBuffers();
}
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(800, 800);
	glutCreateWindow("圆");
	//glClear(GL_COLOR_BUFFER_BIT);//清除窗口内容
	glMatrixMode(GL_PROJECTION);/*设置为投影类型模式和其他观察参数*/
	glLoadIdentity();/*设置为投影类型模式和其他观察参数*/
	gluOrtho2D(0, 800, 800, 0);/*设置为投影类型模式和其他观察参数,观察窗口的大小要与画布大小一致,所以直接设置全局变量即可*/
	glClearColor(1, 1, 1, 1);//设置绘制窗口颜色为白色
	glPointSize(3.0f);//设置点的大小
	glColor3f(10, -10, -10);//设置点的颜色
	glutDisplayFunc(&display);
	glutMouseFunc(click);
	glutMotionFunc(move);
	glutMainLoop();
	return 0;
}

注意:

在使用这些代码时需要对环境进行配置,若环境没有配置好,将会出现运行出错

环境配置:

配置glut的环境就不在这里多说了,可以在网上进行搜索。

在将代码写完之后,需要点击“项目”一栏,选择“管理Nuget程序包”,在搜索栏中搜索“nupengl”,回车进行下载

(两个都是一样的,下载一个即可 )

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值