画线算法
要在光栅监视器上显示一条线段,图形系统必须先将两端点投影到整数屏幕坐标,并确定离两端点间的直线路径最近的像素位置。接下来将颜色值装入帧缓存相应的像素坐标处。这一过程将一条线段数字化为一组离散的整数位置,图形学画线算法就是研究如何高效处理这个过程。
【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;} } }