中点算法是基于隐函数方程设计的,使用像素网格中点来判断如何选取距离理想直线最近的像素点,直线的中点算法不仅与 Bresenham 算法产生同样的像素点集,二期还可以推广到圆和椭圆。
直线的隐函数表示
F
(
x
,
y
)
=
y
?
k
x
?
b
=
0
F(x, y) = y -kx -b = 0
F(x,y)=y?kx?b=0
理想直线将平面划分成三个区域
对于直线上的点, $F(x, y) = 0 $
对于直线上方的点,
F
(
x
,
y
)
>
0
F(x, y) >0
F(x,y)>0
对于直线下方的点,
F
(
x
,
y
)
<
0
F(x, y) <0
F(x,y)<0
中点误差项
d i = F ( x i + 1 , y i + 0.5 ) = y i + 0.5 ? k ( x i + 1 ) ? b d_i = F(x_i + 1, y_i + 0.5) = y_i + 0.5 - k(x_i + 1) -b di?=F(xi?+1,yi?+0.5)=yi?+0.5?k(xi?+1)?b
y i + 1 = { y i + 1 d i < 0 y i d i ≥ 0 y_{i+1} = \begin{cases} y_i + 1 & d_i < 0 \\ y_i & d_i \geq 0 \end{cases} yi+1?={yi?+1yi??di?<0di?≥0?
中点误差项的递推公式
d
i
+
1
=
d
i
+
1
?
k
d_{i+1} = d_{i} + 1 - k
di+1?=di?+1?k
上一步选择 P u P_u Pu? 后,中点误差项的增量为 1 ? k 1-k 1?k
d
i
+
1
=
d
i
?
k
d_{i+1} = d_i - k
di+1?=di??k
上一步选择
P
d
P_d
Pd? 后,中点误差项的增量为
?
k
-k
?k
直线的起点坐标扫描转换后的像素为 P 0 ( x 0 , y 0 ) P_0(x_0, y_0) P0?(x0?,y0?) .从像素 P 0 P_0 P0? 出发沿着主位移 x x x 方向的递增一个单位,第一个参与判断的中点是 M ( x 0 + 1 , y 0 + 0.5 ) M(x_0+1, y_0 + 0.5) M(x0?+1,y0?+0.5)。 代入中点误差项计算公式, d d d 的初始值为
d 0 = 0.5 ? k d_0 = 0.5 - k d0?=0.5?k
void MidPointLine(CDC* pDC, CPoint P0, CPoint P1) {
COLORREF crColor = RGB(0, 0, 0);
double k, d;
int dx = P1.x - P0.x;
int dy = P1.y - P1.y;
k = double (dy) / dx;
d = 0.5 -k;
double inColorUp = 1 - k;
double inColorDown = -k;
for (int x=P0.x, y= P0.y; x <P1.x; x++) {
pDC->SetPixelV(x, y, crColor)
if (d <0) {
y++;
d += inColorUp;
}
else {
d += inColorDown;
}
}
}
中点算法是一种浮点数算法,现在的计算机做浮点数运算和整数运算一样快
中点算法设计巧妙,不需要取证操作
中点算法同样适用于绘制圆和椭圆
参考 《计算几何算法与实现》孔令德