DDA算法和Bresenham画线算法
一、原理
DDA算法先计算出直线的斜率,然后从起点开始开始,确定最佳于逼近于直线的y的坐标。在此过程中每一次迭代,都会通过Xi和Yi计算出Xi+1和Yi+1,从而形成一条直线
DDA算法仅适用于|k|<=1的情形下。在这种情况下,x每多增加1,y最多增加1,故在迭代的过程的每一步,只要确定一个像素,而当直线的斜率k的绝对值超过1时必须把x、y的地位交换,y每增加1,x相应的增加1/k.
DDA 算法的本质,就是通过数值分值解微分方程,通过同时对x和y各增加一个小增量,计算在下一步的x、y值,显然DDA算法为一个增量算法
Bresenham画线算法过各行、各列像素的中心构造出一组虚拟的网格线,按照直线从起点到终点的顺序计算直线与各垂直网格的交点,然后确定该列像素与此交点最近的像素。例如x列的像素已确定,其行的下标为y。那么下一个像素的列坐标为x+1.而行坐标要么不变,要么递增
二、代码实现
#include<GL\glut.h>
#include<iostream>
#include<cmath>
using namespace std;
//DDA算法绘制直线
void swapvalue(int* a, int* b);//函数的预定义
void DrowDDA(int x1, int y1, int x2, int y2)
{
glColor3f(1.0, 0.0, 0.0); //所要画线的颜色为红色
glPointSize(3.0f);
int m = 0;
//选择两个点的坐标的距离的最大值
if (abs(x2 - x1) >= abs(y2 - y1))
{
m = abs(x2 - x1); // x 为计长方向
}
else
{
m = abs(y2 - y1); // y 为计长方向
}
float dx = (float)(x2 - x1) / m; // 当 x 为计长方向,dx = 1
float dy = (float)(y2 - y1) / m; // 当 y 为计长方向,dy = 1
float x = x1;
float y = y1;
for (int i = 0; i < m; ++i)//循环设置定点
{
glBegin(GL_POINTS);//把每一个顶点做为一个定点处理,绘制N个定点
glVertex2f((int)x, (int)y);//设置定点
glEnd();
glFlush();
x += dx;
y += dy;
}
}
/*
Bresenham 画直线法
*/
void DrowBres(int x1, int y1, int x2, int y2)
{
glColor3f(0.0, 0.0, 1.0); // 蓝色
glPointSize(2.0f);
int dx = abs(x2 - x1);
int dy = abs(y2 - y1);
// 两点重合
if (dx == 0 && dy == 0)
{
glBegin(GL_POINTS);
glVertex2f(x1, y1);
glEnd();
glFlush();
return;
}
int flag = 0; // 将斜率变换到 0 <= |k| <= 1 区间
if (dx < dy)
{
flag = 1;
swapvalue(&x1, &y1);//交换两个变量的值
swapvalue(&x2, &y2);//交换两个变量的值
swapvalue(&dx, &dy);//交换两个变量的值
}
int tx = (x2 - x1) > 0 ? 1 : -1;
int ty = (y2 - y1) > 0 ? 1 : -1;
int curx = x1;
int cury = y1;
int dS = 2 * dy;
int dT = 2 * (dy - dx);
int d = dS - dx;
while (curx != x2)
{
if (d < 0)
d += dS;
else
{
cury += ty;
d += dT;
}
if (flag)
{
glBegin(GL_POINTS);
glVertex2f(cury, curx);//画点
glEnd();
glFlush();
}
else
{
glBegin(GL_POINTS);
glVertex2f(curx, cury);//画点
glEnd();
glFlush();
}
curx += tx;
}
}
/*
交换两个int 类型的变量的值
*/
void swapvalue(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void display(void)
{
// 用当前背景色填充窗口,如果不写这句会残留之前的图像
glClear(GL_COLOR_BUFFER_BIT);
int x1 = 0, y1 = 0, x2 = 500, y2 = 500;
int x12 = 0, y12 = 0, x22 = 500, y22 = 500;
DrowDDA(x1, y1, x2, y2);//使用DDA算法绘制直线
DrowBres(x12, y12, x22, y22);//使用Bresenham画直线
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);//初始化glut的库
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//使用单缓存或者RGB moshi
glutInitWindowPosition(200, 200);//窗口的位置
glutInitWindowSize(400, 400);//窗口的大小
glutCreateWindow("张扬的OpenGl程序");
glutDisplayFunc(display);//调用函数
glClearColor(1.0, 1.0, 1.0, 0.0); //窗口的背景为白色
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 200.0, 0.0, 150.0);
glutMainLoop();//让 glut 程序进入事件循环。在一个glut程序中最多只能调用一次。一旦调用,会直到程序结束才返回。
return 0;
}
三、实现结果