1965 年,Bresenham 为数字绘图仪开发了一种绘制直线的算法,该算法同样使用于光栅扫描显示器,被称为 Bresenham 算法。
算法的目标是选择表示直线的最佳光栅位置。Bresenhan 算法在主位移方向上每次递增一个单位。另一个方向的增量为 0 或 1,取决于理想直线于最近网格点的距离,这一距离称为误差项,误差项用 d 表示。
当 x x x 方向递增一个单位,有 d = d + k d = d+ k d=d+k; 则
y
i
+
1
=
{
y
i
+
1
;
d
≥
0.5
y
i
d
<
0.5
y_{i+1} = \begin{cases} y_i + 1; &\quad d \geq 0.5\\ y_i &\quad d < 0.5 \end{cases}
yi+1?={yi?+1;yi??d≥0.5d<0.5?
误差项初始值
d
0
=
0
d_0 = 0
d0?=0, 如果
d
≥
0.5
d \geq 0.5
d≥0.5,
y
y
y 方向递增一个单位并且将
d
d
d 减 1.
消除 0.5 的影响
令 e = d ? 0.5 e = d -0.5 e=d?0.5. 当 x x x 方向走一步,有 e = e + k e = e + k e=e+k, 则
y i + 1 = { y i + 1 ; e ≥ 0 y i e < 0.5 y_{i+1} = \begin{cases} y_i + 1; &\quad e \geq 0\\ y_i &\quad e < 0.5 \end{cases} yi+1?={yi?+1;yi??e≥0e<0.5?
e 0 = ? 0.5 e_0 = -0.5 e0?=?0.5 , 如果 e ≥ 0 e \geq 0 e≥0, 则 e = e ? 1 e = e -1 e=e?1
消除浮点数的影响,斜率和 e e e, 进行整数化
当
0
≤
k
≤
1
0 \leq k \leq 1
0≤k≤1,
Δ
x
\Delta x
Δx 为正
e
=
2
Δ
x
e
=
2
Δ
x
(
d
?
0.5
)
=
?
Δ
x
+
2
Δ
x
d
e = 2 \Delta x e = 2 \Delta x (d-0.5) = -\Delta x + 2 \Delta x d
e=2Δxe=2Δx(d?0.5)=?Δx+2Δxd
初始值
e
0
=
?
Δ
x
e_0 = -\Delta x
e0?=?Δx
当 x 方向走一步,有
e
+
=
2
Δ
y
e += 2 \Delta y
e+=2Δy
如果 e ≥ 0 e \geq 0 e≥0 有
e = 2 Δ x ( e ? 1 ) = 2 Δ x e ? 2 Δ x e ? = 2 Δ x e = 2 \Delta x (e-1) = 2 \Delta x e - 2 \Delta x \\ e -= 2 \Delta x e=2Δx(e?1)=2Δxe?2Δxe?=2Δx
void BresenhamLine(CDC* pDC, CPoint P0, CPoint P1)
{
COLORREF crColor = RGB(0, 0, 0);
int dx = P1.x - P0.x;
int dy = P1.y - P0.y;
int e = - dx;
for (int x=P0.x, y=P0.y; x < P1.x; x++) {
pDC->SetPixelV(x, y, crColor);
e += 2 * dy;
if (e >= 0) {
y++;
e -= 2 * dx;
}
}
}
整数 Bresenham 算法是一种经典的直线光栅化算法, 使用了最小的计算量,使得单点生成算法已经没有改进的余地。
参考 《计算几何算法与实现》孔令德