实验要求:
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”,回车进行下载
(两个都是一样的,下载一个即可 )