直线生成算法

直线连接两点,是图形的基本元素,要画直线,需要两个点,在这两个点之间画直线。在以下三个算法中,我们将直线的一点称为$X_{0}, Y_{0}$,将直线的第二个点称为$X_{1}, Y_{1}$。

DDA 算法

数字差分分析仪 (DDA) 算法是一种简单的直线生成算法,这里将逐步解释。

步骤 1 − 获取两个端点 $(X_{0}, Y_{0})$ 和 $(X_{1}, Y_{1})$ 的输入。

步骤 2 −计算两个端点之间的差值。

dx = X1 - X0
dy = Y1 - Y0

步骤 3 − 根据步骤 2 中计算出的差值,您需要确定放置像素的步数。如果 dx > dy,则您需要在 x 坐标上采取更多步骤;否则在 y 坐标上。

if (absolute(dx) > absolute(dy))
   Steps = absolute(dx);
else
   Steps = absolute(dy);

步骤4 − 计算x坐标和y坐标的增量。

Xincrement = dx / (float) steps;
Yincrement = dy / (float) steps;

步骤5 − 成功增加x和y坐标后,放置像素,完成线条的绘制。

for(int v=0; v < Steps; v++)
{
   x = x + Xincrement;
   y = y + Yincrement;
   putpixel(Round(x), Round(y));
}

Bresenham 的线生成

Bresenham 算法是另一种增量扫描转换算法。该算法的一大优势是,它只使用整数计算。以单位间隔沿 x 轴移动,并在每一步中选择两个不同的 y 坐标。

例如,如下图所示,从位置 (2, 3) 开始,您需要在 (3, 3) 和 (3, 4) 之间进行选择。您希望点更接近原始线。

Bresenham 的线生成

在样本位置 $X_{k}+1$,与数学线的垂直分离标记为 $d_{upper}$ 和 $d_{lower}$。

dupper and dlower

从上图可以看出,$x_{k}+1$ 处数学线上的 y 坐标为 −

Y = m($X_{k}$+1) + b

因此,$d_{upper}$ 和 $d_{lower}$ 如下所示 −

$$d_{lower} = y-y_{k}$$

$$= m(X_{k} + 1) + b - Y_{k}$$

and

$$d_{upper} = (y_{k} + 1) - y$$

$= Y_{k} + 1 - m (X_{k} + 1) - b$

您可以使用这些来简单地判断哪个像素更接近数学线。这个简单的决定是基于两个像素位置之间的差异。

$$d_{lower} - d_{upper} = 2m(x_{k} + 1) - 2y_{k} + 2b - 1$$

让我们用 dy/dx 代替 m,其中 dxdy 是端点之间的差异。

$$dx (d_{lower} - d_{upper}) =dx(2\frac{\mathrm{d} y}{\mathrm{d} x}(x_{k} + 1) - 2y_{k} + 2b - 1)$$

$$ = 2dy.x_{k} - 2dx.y_{k} + 2dy + 2dx(2b-1)$$

$$ = 2dy.x_{k} - 2dx.y_{k} + C$$

因此,沿线第 k 步的决策参数 $P_{k}$ 由 −

给出

$$p_{k} = dx(d_{lower} - d_{upper})$$

$$ = 2dy.x_{k} - 2dx.y_{k} + C$$

决策参数 $P_{k}$ 的符号与 $d_{lower} - d_{upper}$ 的符号相同。

如果 $p_{k}$ 为负,则选择下像素,否则选择上像素像素。

请记住,坐标变化沿 x 轴以单位步骤发生,因此您可以使用整数计算完成所有操作。在步骤 k+1 时,决策参数为 −

$$p_{k +1} = 2dy.x_{k + 1} - 2dx.y_{k + 1} + C$$

从中减去 $p_{k}$ 可得到 −

$$p_{k + 1} - p_{k} = 2dy(x_{k + 1} - x_{k}) - 2dx(y_{k + 1} - y_{k})$$

但是,$x_{k+1}$ 与 $(xk)+1$ 相同。所以 −

$$p_{k+1} = p_{k} + 2dy - 2dx(y_{k+1} - y_{k})$$

其中,$Y_{k+1} – Y_{k}$ 为 0 或 1,具体取决于 $P_{k}$ 的符号。

第一个决策参数 $p_{0}$ 在 $(x_{0}, y_{0})$ 处求值,结果为 −

$$p_{0} = 2dy - dx$$

现在,记住以上所有要点和计算,这里是斜率 m < 1 − 的 Bresenham 算法

步骤 1 −输入线的两个端点,将左端点存储在$(x_{0}, y_{0})$中。

步骤 2 − 绘制点$(x_{0}, y_{0})$。

步骤 3 − 计算常数 dx、dy、2dy 和 (2dy – 2dx),并获取决策参数的第一个值作为 −

$$p_{0} = 2dy - dx$$

步骤 4 − 在线上每个 $X_{k}$ 处,从 k = 0 开始,执行以下测试 −

如果 $p_{k}$ < 0,下一个要绘制的点是(x_{k}+1,y_{k})并且

$$p_{k+1} = p_{k} + 2dy$$ Otherwise,

$$(x_{k}, y_{k}+1)$$

$$p_{k+1} = p_{k} + 2dy - 2dx$$

步骤 5 − 重复步骤 4 (dx – 1) 次。

对于 m > 1,确定是否需要每次增加 x 并增加 y。

求解后,决策参数 $P_{k}$ 的方程将非常相似,只是方程中的 x 和 y 互换了。

中点算法

中点算法源于 Bresenham,由 Pitteway 和 Van Aken 修改。假设您已经将点 P 放在 (x, y) 坐标处,直线的斜率为 0 ≤ k ≤ 1,如下图所示。

现在您需要决定将下一个点放在 E 还是 N。这可以通过确定最接近点 N 或 E 的交点 Q 来选择。如果交点 Q 最接近点 N,则 N 被视为下一个点;否则为 E。

中点算法

要确定这一点,首先计算中点 M(x+1, y + ½)。如果直线与连接 E 和 N 的垂直线的交点 Q 在 M 下方,则将 E 作为下一个点;否则将 N 作为下一个点。

为了检查这一点,我们需要考虑隐式方程 −

F(x,y) = mx + b - y

对于任何给定 X 处的正 m,

  • 如果 y 在线上,则 F(x, y) = 0
  • 如果 y 在线上方,则 F(x, y) < 0
  • 如果 y 低于该线,则 F(x, y) > 0
Implicit Equation