1. 数值微分法DDA(Digital Differential Analyzer)
基本思想:先对一个方向的坐标取单位步长的变化,然后计算另一方向坐标相应的变化值。
当一条直线的斜率不为0时,它可以用方程y=kx+b来表示,假定直线的起点和终点分别为(x1,y1),(x2,y2),且都为整数,那么k = (y2-y1)/(x2-x1);
由k的大小确定取单位步长的方向:
① |k|<1,取增长单位步长方向为x轴(Δx=1),y的增量大小为
y
i
+
1
=
k
(
x
i
+
1
)
+
b
=
y
i
+
k
y_{i+1}=k(x_i+1)+b= y_i+k
yi+1=k(xi+1)+b=yi+k
②|k|>1,则取增长单位步长方向为y轴(Δy=1),可得如下x的增量方程:
x
i
+
1
=
x
i
+
1
k
x_{i+1}=x_i+\frac1k
xi+1=xi+k1
③若开始的端点在终点右方,则有
Δx = -1时
y
i
+
1
=
k
(
x
i
−
1
)
+
b
=
y
i
−
k
y_{i+1}=k(x_i-1)+b= y_i-k
yi+1=k(xi−1)+b=yi−k
Δy = -1时
x
i
+
1
=
x
i
−
1
k
x_{i+1}=x_i-\frac1k
xi+1=xi−k1
实例:绘制从A(11,7)到B(3,2)的直线
k =(y2-y1)/(x2-x1)=0.625,增量方向为x轴,且起点在终点右侧,Δx=-1,y的改变量Δy=-0.625
i i i | x i x_i xi | y i y_i yi | 坐标(四舍五入) |
---|---|---|---|
0 | x 0 = 11 x_0 = 11 x0=11 | y 0 = 7 y_0 = 7 y0=7 | (11,7) |
1 | x 1 = 10 x_1 = 10 x1=10 | y 1 = 6.375 y_1 = 6.375 y1=6.375 | (10,6) |
2 | x 2 = 9 x_2 = 9 x2=9 | y 2 = 5.75 y_2 = 5.75 y2=5.75 | (9,6) |
3 | x 3 = 8 x_3 = 8 x3=8 | y 3 = 5.125 y_3 = 5.125 y3=5.125 | (8,5) |
4 | x 4 = 7 x_4 = 7 x4=7 | y 4 = 4.5 y_4 = 4.5 y4=4.5 | (7,5) |
…… | …… | …… | …… |
在C++,MFC中实现代码如下
void Draw(CDC *pCD,int x1,int y1,int x2,int y2,COLORREF color)
{
//该程序考虑到了k范围不同,以及k不存在时的情况
int dx,dy,n,k;
double xinc,yinc,x,y;
dx = x2-x1;
dy = y2-y1;
if(abs(dx)-abs(dy)>0) //比较两参数的绝对值哪一个大,哪一个就作为步长参数(n),
此参数将作为沿直线所画出点的数目
n = abs(dx);
else
n = abs(dy);
xinc = (double)dx/n;
yinc = (double)dy/n;
x = x1;
y = y1;
for(k = 0;k<n;k++)
{
pCD->SetPixel(floor(x + 0.5),floor(y + 0.5),color);
x+=xinc;
y+=yinc;
}
}
2. 中点画线法
基本思想:假设直线的起点和终点分别为(x1,y1)和(x2,y2),则方程为:
a
x
+
b
y
+
c
=
0
ax+by+c=0
ax+by+c=0其中a=y1-y2, b=x2-x1, c=x1y2-x2y1
且
构造判别式:中点M(xi+1,yi+0.5),如下图所示
d=F(M)=F(xi+1,yi+0.5) =a(xi+1)+b(yi+0.5)+c
当d<0,M在直线(Q点)下方,取右上方P1;
当d>0,M在直线(Q点)上方,取右方P2;
当d=0,选P1或P2均可,约定取P2;
①若d>0,即M在直线上方,取P2。再下一个象素的判别式为
d1=F(xi+2, yi+0.5)= a(xi +1)+b(yi +0.5)+c +a =d+a; 增量为a。
②若d<0,即M在直线下方,取P1.再下一个象素的判别式为
d2= F(xi+2, yi+1.5)= a(xi +1)+b(yi +0.5)+c +a +b =d+a+b ; 增量为a+b
③d的初始值(第一个象素应取左端点(x1,y1))
d0= F(x0+1, y0+0.5)= F(x0, y0) +a +0.5b= a +0.5b
注:由于0.5b很有可能出现小数,不易于计算,此处我们都去增量大两倍,d1 = 2a;d2 = 2(a+b);d0=2a+b.
实例:绘制从A(11,7)到B(3,2)的直线
取B为起点,A为终点,计算相关参量:
a = y1 –y2 = 2 - 7 = -5;
b = x2-x1 = 11 – 3 = 8;
d0 = 2a+b = -2
d1 = 2a = -10
d2 = 2*(a+b) = 6
i i i | x i x_i xi | y i y_i yi | d i d_i di | 坐标 |
---|---|---|---|---|
0 | 3 | 2 | -2 | (3,2) |
1 | 4 | 3 | 4 | (4,3) |
2 | 5 | 3 | -6 | (5,3) |
3 | 6 | 4 | 0 | (6,4) |
4 | 7 | 4 | -10 | (7,4) |
…… | …… | …… | …… | …… |
3. Bresenham画线算法
基本思想:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列像素中与此交点最近的像素.
如图所示,先假设直线的斜率在0~1之间。设Pi-1是已选定的离直线最近的象素,现在要决定下一个象素是Ti还是Si:
若s<t,则Si比较靠近直线,应选Si;
若s>=t,则应选Ti。
在此不再详细阐述,有兴趣请自行查阅资料。