DDA画线算法+代码详解-直线扫描算法之一
本文目录结构如下
1、直线扫描算法简介
2、DDA直线扫描算法
2.1 公式推理
1、求斜率K:
2、当|K| <= 1 时
3、当|K| > 1 时
4、当|K|不存在时
2.2 疑惑解答
疑问一:当|K|>1 和 |K|<1,步进主方向为什么不一样
疑问二:K为什么要取绝对值,K<0 会怎样
3、代码验证及下载
3.1具体代码:
3.2 测试用例下载
3.3工程代码下载
1、直线扫描算法简介
在数学上直线是由无数个点组成,在光栅显示器上,用有限个逼近的像素点来表示直线,因此最终显示的屏幕上的也不是光滑的线。如图所示
2、DDA直线扫描算法
利用斜线方程: $$y=kx+b$$求每个逼近的像素点坐标,每个像素点坐标值都是整数并且不小于零
2.1 公式推理
已知起点P0(X0,Y0)和终点Pn(Xn,Yn),如图所示
1、求斜率K:
$$k=\frac{Yn-Y0}{Xn-X0} (Xn \neq X0)$$为了提高运算速度,要避免乘法,采用加法运算,因此采用增量计算;
2、当|K| <= 1 时
x轴方向为步进的主方向
- X(i+1) = Xi + 1;
- Y(i+1) = Yi + K;
备注:因为像素点坐标是整数,所有Y值要四舍五入,即int(Y+0.5)
3、当|K| > 1 时
y轴方向为步进的主方向
- Y(i+1) = Yi + 1;
- X(i+1) = Xi + 1/k;
备注:因为像素点坐标是整数,所有X值要四舍五入,即int(X+0.5)
4、当|K|不存在时
即Xn = X0,说明绘制的是一条垂直的线
- X(i+1) = Xi ;
2.2 疑惑解答
疑问一:当|K|>1 和 |K|<1,步进主方向为什么不一样
如果|k|>1 ,仍然采用X轴为主步进方向,像素点少;如图所示
疑问二:K为什么要取绝对值,K<0 会怎样
因为当K < 0 和 K > 0 的计算方法完全一样,自己可以举个例子验证一下;要记住一点,像素点的坐标值是正整数
3、代码验证及下载
3.1具体代码:
//输入参数分别是起点坐标P(X0,Y0) 和终点坐标(Xn,Yn);
void LineDDA(int X0, int Y0, int Xn, int Yn)
{
//定义斜率K
int dx = Xn - X0;
int dy = Yn - Y0;
int steps;//步数
int direction;//方向 0--x方向 1--y方向
float xIncrement, yIncrement;//每一步增加的数值
float x = X0, y = Y0;//求出的中间像素点
if (abs(dx) > abs(dy))
{
steps = abs(dx);//步数
direction = 0;//确认X步进主方向
}
else
{
steps = abs(dy);
direction = 1;//确认Y步进主方向
}
xIncrement = float(dx) / float(steps); //x每步骤增量
yIncrement = float(dy) / float(steps); //y的每步增量
//开始画点
glBegin(GL_POINTS);
for (int k = 0; k <= steps; ++k)
{
//x主步进方向
if (direction == 0)
{
glVertex2i(int(x), int(y + 0.5));//点坐标
}
else //y主步进方向
{
glVertex2i(int(x+0.5), int(y));// 点坐标
}
x += xIncrement; //x点+增量
y += yIncrement; //y点+增量
}
glEnd();
}
//绘制函数
void display()
{
glClear(GL_COLOR_BUFFER_BIT); // 擦除背景色
glColor3f(1, 0, 0);//红色
LineDDA(100, 400, 100, 100);//第一条 竖线
LineDDA(200, 200, 300, 300);//第二条 斜线
LineDDA(200, 300, 300, 200);//第三条 斜线
glFlush();//绘制结束
}
3.2 效果如图 vs2017软件:(opengl环境配置参看博客)
3.3 工程代码下载