1. 数值微分法
已知过端点P0(x0,y0)P_0(x_0,y_0)P0(x0,y0),P1(x1,y1)P_1(x_1,y_1)P1(x1,y1)的直线段L(P0,P1)L(P_0,P_1)L(P0,P1);直线斜率k=y1−y0x1−x0k = \frac{y_1 - y_0}{x_1 - x_0}k=x1−x0y1−y0。画线的过程为:从xxx的左端点x0x_0x0开始,向右端点步进,步长为1(像素),按y=kx+by = kx +by=kx+b计算相应的yyy坐标,并取像素点(x,round(y))(x,round(y))(x,round(y))作为当前坐标。但这样做,计算每一个点需要做一个乘法、一个加法。设步长为Δx\Delta xΔx,有xi+1=xi+Δxx_{i+1} = x_i + \Delta xxi+1=xi+Δx,于是
(1.1)yi+1=kxi+1+b=kxi+kΔx+b=yi+kΔx y_{i+1} = kx_{i+1} + b = kx_i + k \Delta x + b = y_i + k\Delta x \tag{1.1} yi+1=kxi+1+b=kxi+kΔx+b=yi+kΔx(1.1)
当Δx=1\Delta x = 1Δx=1时,有yi+1=yi+ky_{i+1} = y_i + kyi+1=yi+k。即xxx每递增1,yyy递增kkk(即直线的斜率)。这样,计算就由一个乘法和加法减少为一个加法。
- 算法程序:DDA画线算法程序
void DDALine(int x0, int y0, int x1, int y1, int color)
{
int x;
float dx, dy, y, k;
dx = x1 - x0, dy = y1 - y0;
k = dy/dx, y = y0;
for(x = x0; x < x1; x++,y+=k)
{
drawpiexl(x, int(y + 0.5), color);
}
}
注意: 用int(y + 0.5)取整的目的是为取离真正交单近的像素网格点作为光栅化的点。
应当注意的是,上述算法仅适用于k≤1k \leq 1k≤1的情形。在这种情况下,xxx每增加1,yyy最多增加1。当∣k∣≥1|k| \ge 1∣k∣≥1时,必须把x,yx,yx,y地位互换,yyy每增加1,xxx相应增加1/k1/k1/k。本节的其它算法也是如此。在这个算法中,yyy与kkk必须用浮点数表示,而且每一步都要对yyy进行四舍五入后取整,这使得该算法不利于硬件的实现。
2.中点画线法
通过观察可以发现,画直线段的过程中,当前像素点(xp,yp)(x_p,y_p)(xp,yp),下一个像素点有两种选择点P1(xp+1,yp)P_1(x_p+1,y_p)P1(xp+1,yp)或P1(xp+1,yp+1)P_1(x_p+1,y_p+1)P