前言
本次举例都是以X轴为主位移
中点算法的原理和其它算法也都差不多,都是当主位移方向递增一个单位,判断另一个方向的增量是否为1或0,区别在于是取决于中点误差项的值。
一、中点算法是什么?
-
中点算法是根据直线的隐形方程F(x,y)=y-kx-b=0将平面划分为3个区域:
- 对于直线上的点,F(x,y)=0;
- 对于直线上方的点,F(x,y)>0;
- 对于直线下方的点,F(x,y)<0;
-
中点误差项
- 设当前点坐标为Pi(Xi,Yi)在直线上,那么当选取下一个坐标时就要先获取中点坐标(Xi+1,Yi+0.5),根据中点坐标来获取中点误差项d,即
di=F(Xi+1,Yi+0.5)=Yi+0.5-k(Xi+1)-b - 判断中点在直线下方还是上方,当在上方时,也就是di>0,那么下一个坐标点距离Pd点近,则选取Pd这个点作为下一个坐标点,当在下方时,也就是di<0,那么下一个坐标点距离Pu点近,则选取Pu这个点作为下一个坐标点。
- 设当前点坐标为Pi(Xi,Yi)在直线上,那么当选取下一个坐标时就要先获取中点坐标(Xi+1,Yi+0.5),根据中点坐标来获取中点误差项d,即
-
中点误差项递推公式
- 当di<0时,下一步进行判断的中点为M(Xi+2,Yi+1.5),则递推公式为
di+1=F(Xi+2,Yi+1.5)运算完后得di+1-k。即中点误差项增量为1-k。 - 当di>0时,下一步进行判断的中点为M(Xi+2,Yi+0.5),则递推公式为
di+1=F(Xi+2,Yi+0.5)运算完后得di-k。即中点误差项增量为-k。
- 当di<0时,下一步进行判断的中点为M(Xi+2,Yi+1.5),则递推公式为
-
中点误差项的起始值
- 由于开始是从第一个点开始,参与判断的中点是(X0+1,Y0+0.5)带入公式后得到
Y0-kX0-b-k+0.5而由于第一个点是在直线上的所以Y0-kX0-b=0,所以d0=0.5-k,算法至此也就完成了
- 由于开始是从第一个点开始,参与判断的中点是(X0+1,Y0+0.5)带入公式后得到
二、中点算法整数化
1.为什么要整数化
由于上面所说的中点算法存在一个缺点,在推断中点误差项时,包含有小数与斜率k,而此算法只需要知道d的符号,而不需要具体值,所以可以消除那些小数与斜率,从而得到一个新的误差项e来代替d,
e=2△xdi
2.e公式的由来
根据上述所推出的中点误差项d,我们发现其中包含0.5和k,而要消除这两个只要对齐乘以一个2和△x便可以消除0.5和k,因为0.5*2变为1,这个也不一定非得乘2,其余也可以,而k=△y/△x,所以乘以△x便可以消除。
3.整数化后的中点误差项
- 由于e=2△xdi,便可以将上述求出来的di带入便可以获得初始值,以及增量,在此我直接列出
- 初始值e0=△x-2△y
- ei<0的增量为2△x-2△y
- ei>=0的增量为-2△y
三、两者的核心代码
本次代码都只针对X轴为主位移方向
float d = 0.5 - k;
int y = starty;
for (int x = startx; x < endx; x++) {
if (d < 0) {
d += 1 - k;
putpixel(x, y + 1, LIGHTBLUE);
y = y + 1;
}
else {
d += -k;
putpixel(x, y, LIGHTBLUE);
y = y;
}
}
int e = dx - 2 * dy;
int Y = starty;
for (int x = startx ; x < endx; x++) {
if (e < 0) {
e += 2 * dx - 2 * dy;
putpixel(x, Y + 1, LIGHTBLUE);
Y = Y + 1;
}
else {
e += -2 * dy;
putpixel(x, Y, LIGHTBLUE);
Y = Y;
}
}