画线算法
要在光栅监视器上显示一条线段,图形系统必须先将两端点投影到整数屏幕坐标,并确定离两端点间的直线路径最近的像素位置。接下来将颜色值装入帧缓存相应的像素坐标处。这一过程将一条线段数字化为一组离散的整数位置,图形学画线算法就是研究如何高效处理这个过程。
【DDA算法】
DDA算法又叫数值微分法,基于以下的数值推导过程:
算法步骤:
①输入线段两个端点的像素位置。端点间水平和垂直差值赋给dx和dy。
②dx和dy中绝对值较大一个赋给参数steps,该值是这条直线段的像素数目
③先绘制起始位置(x0,y0),再调整每一步的x和y,逐一绘制余下像素。
【代码】
inlineint round(constfloat a)
{
returnint (a+0.5);
}
void lineDDA(int x0,inty0,int xend,intyend)
{
intdx=xend-x0;
intdy=yend-y0;
intk;
floatxincrement,yincrement;
if(fabs(dx)>fabs(dy))
k=fabs(dx);
else
k=fabs(dy);
xincrement=float(dx)/float(k);
yincrement=flaot(dy)/float(k);
setPixel(round(x),round(y))
for(int i=0;i<k;i++)
{
x+=xincrement;
y+=yincrement;
setPixel(round(x),round(y));//只有坐标轴上增加斜率K大于0.5时才会在坐标轴上加1
}
}
【Bresenham画线算法】
过各行各列象素中心构造一组虚拟网格线。按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后根据误差项的符号确定该列象素中与此交点最近的象素。
核心思想:
假设:k=dy/dx。因为直线的起始点在象素中心,所以误差项d的初值d0=0。
X下标每增加1,d的值相应递增直线的斜率值k,即d=d+k。一旦d≥1,就把它减去1,这样保证d在0、1之间。
当d≥0.5时,最接近于当前象素的右上方象素(x+1,y+1)
而当d<0.5时,更接近于右方象素(x+1,y)
为方便计算,令e=d-0.5,
e的初值为-0.5,增量为k。
当e≥0时,取当前象素(xi,yi)的右上方象素(x+1,y+1)
而当e<0时,更接近于右方象素(x+1,y)
可以改用整数以避免除法。由于算法中只用到误差项的符号,因此可作如下替换:
e1 = 2*e*dx
代码:
voidBresenhamline (int x0,int y0,int x1, int y1,int color)
{
int x, y, dx, dy;
float k, e;
dx = x1-x0, dy = y1- y0, k=dy/dx;
e=-0.5, x=x0, y=y0;
for (i=0; i<=dx; i++)
{ drawpixel (x, y, color);
x=x+1,e=e+k;
if (e>=0)
{ y++, e=e-1;}
}
}
//或者将e扩大2dx倍;
voidBresenhamline (int x0,int y0,int x1, int y1,int color)
{
int x, y, dx, dy;
float k, e;
dx = x1-x0, dy = y1- y0, k=dy/dx;
e=-dx, x=x0, y=y0;
for (i=0; i<=dx; i++)
{ drawpixel (x, y, color);
x=x+1,e=e+2dy;
if (e>=0)
{ y++, e=e-2dx;}
}
}