📜  线生成算法

📅  最后修改于: 2021-01-13 09:33:42             🧑  作者: Mango


一条线连接两个点。它是图形中的基本元素。要绘制一条线,您需要两个点之间可以绘制一条线。在以下三种算法中,我们将一行的第一点称为$ 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算法是另一种增量扫描转换算法。该算法的最大优点是,它仅使用整数计算。在x轴上以单位间隔移动,并在每个步骤中在两个不同的y坐标之间进行选择。

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

布雷森汉姆的世代

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

底子和底子

从上图可以看出,数学线上$ 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} $$

$$ 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步的第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-从k = 0开始,沿线的每个$ X_ {k} $,执行以下测试-

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

$$ p_ {k + 1} = p_ {k} + 2dy $$否则,

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

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

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

对于m> 1,找出是否需要在每次递增y的同时递增x。

求解后,决策参数$ 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

隐式方程