Opengl直线生成算法(Bresenham、DDA、逐点、中点)

1.Bresenham.cpp

#include<gl/glut.h>
#include<math.h>


void Bres_Line(int x1, int y1, int x2, int y2)
{
	glColor3f(0.0f, 0.0f, 1.0f);//设置颜色,蓝色
	glPointSize(3);//栅格化点,直径为3

	int dx = abs(x2 - x1);//计算|∆x|
	int dy = abs(y2 - y1);//计算|∆y|
	if (dx == 0 && dy == 0)   return;
	int flag = 0;
	int temp;
	if (dx < dy)       //将斜率变换至0≤|k|≤1区间
	{
		flag = 1;
		temp = x1, x1 = y1, y1 = temp;//交换x1,y1
		temp = x2, x2 = y2, y2 = temp;//交换x2,y2
		temp = dx, dx = dy, dy = temp;//交换dx,dy
		int tx = (x2 - x1) > 0 ? 1 : -1; //若斜率是0≤k≤1,加1,若斜率是-1≤k≤0,减1
		int ty = (y2 - y1) > 0 ? 1 : -1;
		int curx = x1; //当前像素x坐标   
		int cury = y1; //当前像素y坐标
		//画起点
		glBegin(GL_POINTS);
		glVertex2i(x1, x2);
		glEnd();
		int d = 2 * dy - dx; //d初值
		while (curx != x2)
		{	//迭代公式
			if (d < 0)
				d += 2 * dy;
			else
			{
				cury += ty;
				d += 2 * (dy - dx);
			}
			if (flag)//若发生过斜率变换
			{
				glBegin(GL_POINTS);
				glVertex2i(cury, curx);
				glEnd();
			}
			else
			{
				glBegin(GL_POINTS);
				glVertex2i(curx, cury);
				glEnd();
			}
			curx += tx;//下一个像素的x坐标
		}
	}
}

	void myDisplay()
	{
		glClearColor(1.0, 1.0, 1.0, 1.0);//清除颜色,白色
		glClear(GL_COLOR_BUFFER_BIT);//消除缓冲区,使用上述清除颜色消除


		//Bres_Line(0, 0, 200, 200);
		//Bres_Line(200, 200, 0, 0);
		Bres_Line(0, 200, 100, 100);

		glFlush();//强制刷新
	}

	void Reshape(int w, int h)
	{
		glViewport(0, 0, (GLsizei)w, (GLsizei)h); //定义视口大小
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);//使左下角坐标为(0,0),右上角坐标为(w,h)
	}

	void main(int argc, char* argv[])
	{
		glutInit(&argc, argv);//初始化GLUT
		glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//显示模式
		glutInitWindowPosition(100, 100);//窗口位置,窗口左上角在屏幕的坐标
		glutInitWindowSize(400, 400);//窗口大小
		glutCreateWindow("Bresenham画线法");//创建窗口,参数是窗口的标题
		glutDisplayFunc(myDisplay);//告诉GLUT哪个函数负责绘图,即注册一个绘图函数myDisplay
		glutReshapeFunc(Reshape); //窗口发生改变时,使用什么函数进行重绘
		glutMainLoop();//处理永不结束的循环监听
	}

2.DDA.cpp

在这里插入图片描述

#include<gl/glut.h>
#include<math.h>


void LineDDA(int x1, int y1, int x2, int y2)
{
	// 求Δm = max(|Δx|, |Δy|) 
	int dm = 0;
	if (abs(x2 - x1) >= abs(y2 - y1))	//abs是求绝对值的函数
		dm = abs(x2 - x1);	//x为计长方向
	else
		dm = abs(y2 - y1); 	//y为计长方向

	//求∆𝒙⁄∆𝒎,与(∆𝒚)⁄∆𝒎,计长方向会等于1
	float dx = (float)(x2 - x1) / dm;
	float dy = (float)(y2 - y1) / dm;

	// 对当前坐标进行四舍五入
	float x = x1 + 0.5;
	float y = y1 + 0.5;

	// 循环画点,x方向增加为∆𝒙⁄∆𝒎  , y方向增量为( ∆𝒚)⁄∆𝒎
	glColor3f(0.0f, 0.0f, 1.0f);//蓝色
	glPointSize(5);
	for (int i = 0; i < dm; i++)
	{
		glBegin(GL_POINTS);
		glVertex2i((int)x, (int)y);
		glEnd();
		x += dx;
		y += dy;
	}
}

void myDisplay()
{
	glClearColor(1.0, 1.0, 1.0, 1.0);//清除颜色,白色
	glClear(GL_COLOR_BUFFER_BIT);//消除缓冲区,使用上述清除颜色消除

	glColor3f(1.0f, 0.0f, 0.0f);//设置颜色,红色
	glLineWidth(5);
	glBegin(GL_LINES);
	glVertex3f(200.0f, 200.0f, 0.0f);
	glVertex3f(400.0f, 400.0f, 0.0f);
	glEnd();

	//LineDDA(0, 0, 200, 200);
	//LineDDA(200, 200, 0, 0);
	LineDDA(0, 200, 100, 100);

	glFlush();//强制刷新
}

void Reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h); //定义视口大小
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);//使左下角坐标为(0,0),右上角坐标为(w,h)
}

void main(int argc, char* argv[])
{
	glutInit(&argc, argv);//初始化GLUT
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//显示模式
	glutInitWindowPosition(100, 100);//窗口位置,窗口左上角在屏幕的坐标
	glutInitWindowSize(400, 400);//窗口大小
	glutCreateWindow("LineDDA");//创建窗口,参数是窗口的标题
	glutDisplayFunc(myDisplay);//告诉GLUT哪个函数负责绘图,即注册一个绘图函数myDisplay
	glutReshapeFunc(Reshape); //窗口发生改变时,使用什么函数进行重绘
	glutMainLoop();//处理永不结束的循环监听
}

3.中点画线法
在这里插入图片描述

#include<gl/glut.h>
#include<math.h>


void MidPLine(int x0, int y0, int x1, int y1)
{
    glColor3f(0.0f, 0.0f, 1.0f);//设置颜色,蓝色
    glPointSize(3);//栅格化点,直径为3

    int a, b, d, x, y, temp, tag = 0;
    if (abs(x1 - x0) < abs(y1 - y0))	//若斜率的绝对值大于1,将坐标x和坐标y互换
    {
        temp = x0, x0 = y0, y0 = temp;
        temp = x1, x1 = y1, y1 = temp;
        tag = 1;
    }
    if (x0 > x1)//保证x0<x1
    {
        temp = x0, x0 = x1, x1 = temp;
        temp = y0, y0 = y1, y1 = temp;
    }
    a = y0 - y1;//判别式的a
    b = x1 - x0;//判别式的b
    d = a + b / 2;//判别式的初值
    if (y0 < y1)//斜率为正
    {
        x = x0; y = y0;
        glBegin(GL_POINTS);//画起点
        glVertex2i(x, y);
        glEnd();
        while (x < x1)
        {
            if (d < 0) //判别式<0,取点P2,增量为a+b
            {
                x++; y++; d = d + a + b;
            }
            else//判别式>=0,取点P1,增量为a
            {
                x++; d += a;
            }
            if (tag)//斜率大于1
            {
                glBegin(GL_POINTS);
                glVertex2i(y, x);
                glEnd();
            }
            else
            {
                glBegin(GL_POINTS);
                glVertex2i(x, y);
                glEnd();
            }
        }  /* while */
    }
    else//斜率为负(y0>=y1)
    {
        x = x1;
        y = y1;
        glBegin(GL_POINTS);//画起点
        glVertex2i(x, y);
        glEnd();
        while (x > x0)
        {
            if (d < 0)//判别式<0,增量为-a+b
            {
                x--; y++; d = d - a + b;
            }
            else//判别式>=0,增量为-a
            {
                x--; d -= a;
            }
            if (tag)//斜率大于1
            {
                glBegin(GL_POINTS);
                glVertex2i(y, x);
                glEnd();
            }
            else
            {
                glBegin(GL_POINTS);
                glVertex2i(x, y);
                glEnd();
            }
        }  /* while */
    }
}
void myDisplay()
{
    glClearColor(1.0, 1.0, 1.0, 1.0);//清除颜色,白色
    glClear(GL_COLOR_BUFFER_BIT);//消除缓冲区,使用上述清除颜色消除


    //MidPLine(0, 0, 200, 200);
    //MidPLine(200, 200, 0, 0);
    //MidPLine(0, 200, 100, 100);
    MidPLine(200, 200, 400, 0);

    glFlush();//强制刷新
}

void Reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h); //定义视口大小
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);//使左下角坐标为(0,0),右上角坐标为(w,h)
}

void main(int argc, char* argv[])
{
    glutInit(&argc, argv);//初始化GLUT
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//显示模式
    glutInitWindowPosition(100, 100);//窗口位置,窗口左上角在屏幕的坐标
    glutInitWindowSize(400, 400);//窗口大小
    glutCreateWindow("中点画线法");//创建窗口,参数是窗口的标题
    glutDisplayFunc(myDisplay);//告诉GLUT哪个函数负责绘图,即注册一个绘图函数myDisplay
    glutReshapeFunc(Reshape); //窗口发生改变时,使用什么函数进行重绘
    glutMainLoop();//处理永不结束的循环监听
}
4.逐点画线法
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200514194717379.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjI4NTI1,size_16,color_FFFFFF,t_70)

#include<gl/glut.h>
#include<math.h>

void PrintLine(int x1, int y1, int x2, int y2)
{
int x, y, xA, yA;
if (y1 > y2) //平移直线的坐标,使y值较小的点位于坐标原点
{
yA = y1 - y2; xA = x1 - x2;
}
else
{
yA = y2 - y1; xA = x2 - x1;
}
int F = x = y = 0; //偏移量初值
int n = abs(xA) + abs(yA); //循环总步长
for (int i = 0; i < n; i++) {
if (xA > 0) { //在第一象限
if (F >= 0) { x++; F -= yA; }//笔在上方,向右走,并计算新的偏移量
else { y++; F += xA; }//笔在下方,向上走,并计算新的偏移量
}
else {//在第二象限
if (F >= 0) { y++; F += xA; }//笔在下方,向上走,并计算新的偏移量
else { x–; F += yA; }//笔在上方,向左走,并计算新的偏移量
}
glColor3f(0.0f, 0.0f, 1.0f);//设置颜色,蓝色
glPointSize(3);//栅格化点,直径为3
if (y1 > y2)//平移直线的坐标,恢复原来位置
{
glBegin(GL_POINTS);
glVertex2i(x + x2, y + y2);
glEnd();
}
else
{
glBegin(GL_POINTS);
glVertex2i(x + x1, y + y1);
glEnd();
}
}
}

void myDisplay()
{
glClearColor(1.0, 1.0, 1.0, 1.0);//清除颜色,白色
glClear(GL_COLOR_BUFFER_BIT);//消除缓冲区,使用上述清除颜色消除

PrintLine(0, 0, 200, 200);
//PrintLine(200, 200, 0, 0);
//PrintLine(0, 200, 100, 100);

glFlush();//强制刷新

}

void Reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h); //定义视口大小
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);//使左下角坐标为(0,0),右上角坐标为(w,h)
}

void main(int argc, char* argv[])
{
glutInit(&argc, argv);//初始化GLUT
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//显示模式
glutInitWindowPosition(100, 100);//窗口位置,窗口左上角在屏幕的坐标
glutInitWindowSize(400, 400);//窗口大小
glutCreateWindow(“逐点画线法”);//创建窗口,参数是窗口的标题
glutDisplayFunc(myDisplay);//告诉GLUT哪个函数负责绘图,即注册一个绘图函数myDisplay
glutReshapeFunc(Reshape); //窗口发生改变时,使用什么函数进行重绘
glutMainLoop();//处理永不结束的循环监听
}


以上是Opengl的学习笔记,仅供参考呀
  • 10
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值