本文内容摘引自《计算机图形学教程》
数值微分法概述
数值微分法如下图所示:
代码
void DDA_line2(int x1, int y1, int x2, int y2)
{
float increx, increy, x, y, length;
int i;
if (abs(x2 - x1) > abs(y2 - y1))
length = abs(x2 - x1);
else
length = abs(y2 - y1);
increx = (x2 - x1) / length;
increy = (y2 - y1) / length;
x = x1;
y = y1;
for (i = 1; i <= length; i++)
{
putpixel(int(x + 0.5), int(y + 0.5), RED);
x += increx;
y += increy;
}
}
注意
直线斜率计算式:K=(y2-y1)/(x2-x1),众所周知只能针对非垂直于X轴的直线,否则x2=x1会出现除以零的错误。那么DDA算法中是否考虑了呢?答案是肯定的,测试DDA算法,DDA_line(10,0,10,100)会发现垂直的直线生成成功,并未报错,这是为什么呢?
生成直线(x1,y1)->(x2,y2),设 条件1为:x1≠x2、条件2为:y1≠y2,则一般情况下条件1和条件2至少成立一个。当x1=x2时,y1不等于y2,所以abs(y2-y1)>abs(x2-x1),所以会选择计算y方向的增量Δy来引起x的变换,即k=(x2-x1)/(y2-y1),则y每次+1或者-1,而x不变。反之亦然,则可生成垂直x轴或y轴的直线。
然后当x1=x2,y1=y2时,这种特殊情况下会导致除以零,但是上文代码中length为float类型,除以length=0不会报错,但是会得到类型值为:-nan(ind)。由于length=0,因此循环体一次也不会执行,导致这个点不会被生成出来。
改进算法:
void DDA_line(int x1, int y1, int x2, int y2)
{
float k, length;
if (abs(x2 - x1) > abs(y2 - y1))
length = abs(x2 - x1);
else
length = abs(y2 - y1);
float dx = (x2 - x1) / length;
float dy = (y2 - y1) / length;
float x = x1, y = y1;
putpixel(x, y, RED);
for (int i = 1; i < length ; i++)
{
x += dx;
y += dy;
putpixel(int(x+0.5), int(y+0.5), RED);
}
}
上述改进算法一定会生成起点。