Bresenham算法如何同时跟踪一个变量中的x和y错误?

时间:2017-11-25 03:09:29

标签: algorithm line bresenham

考虑Rosetta Code的这个片段(用C语言编写):

void line(int x0, int y0, int x1, int y1) {

  int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
  int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; 
  int err = (dx>dy ? dx : -dy)/2, e2;

  for(;;){
    setPixel(x0,y0);
    if (x0==x1 && y0==y1) break;
    e2 = err;
    if (e2 >-dx) { err -= dy; x0 += sx; }
    if (e2 < dy) { err += dx; y0 += sy; }
  }
}

我理解当X是驱动轴时Bresenham算法如何工作。在这种情况下,我们只是跟踪y误差,当我们增加x时,我们按比例增加y误差。如果超过某个阈值,我们也会增加y并相应地更新错误。使用一些简单的代数变化,整体可以用整数算法

完成

但我无法对这个特定代码做出正面或反面。 一个变量如何同时跟踪两个错误?

1 个答案:

答案 0 :(得分:0)

我不确定这是否是澄清问题的正确方法。让我们从这里开始。

该代码可以通过先确定 sx sy 来解决不同方向的问题。它带来的另一个方便点是它可以绘制四种斜率(k) image1-1: different slope in coordinate system

像1-1所示,其他6条蓝线可以投影在k> 1和0 <= k <= 1粗体蓝线上。因此在这种情况下,我们只需要处理k> 1和0 <= k <= 1情况。

现在,让我们看一下有关不同斜率(k)值的公式。 image1-2: formula about different slope(k) value

  • 1。

当0 <= k <= 1 dx> dy时,我们选择err = dx / 2

e2 < dy
e2-dy < 0

  (e2 - dy)/dx
= e2/dx - dy/dx    (∵e2 = dx/2
= (dx/2)/dx - dy/dx
= 1/2 - k
[follow the image1-2 can know that it is exactly the initial value of error term: 0.5 - k]

在这种情况下,e2> -dx呢? 您可以绘制坐标系以模拟过程。 例如:(0,0)->(6,2)。 开头的err = 3。点(3,0)(x坐标中e2的位置)到点(-3,0)(x坐标中-dx的位置)之间的距离大于点(0,3)( y坐标中e2的位置)到(0,2)(y坐标中dy的位置)

这可能意味着,虽然 err-= dy 每次都会使err减小,但是用一种不精确的方式来表示:e2到达y坐标(e2

// inside if(e2 > -dx)
err -= dy;
err = err - dy;
err/dx = err/dx - dy/dx;
err/dx = err/dx - k;
//it is exactly: di+1 = di - k

//inside if(e2 < dy)
err += dx;
err/dx = err/dx + dx/dx;
//it is exactly: di+1 = di + 1

因此,每次在for循环中,您都将进入第一个if情况,而当e2

  • 2。

当k> 1为dy> dx时,我们选择err = -dy / 2

e2 > -dx
e2+dx > 0

  (e2 + dx)/dx
= e2/dx + dx/dx    (∵e2 = -dy/2
= (-dy/2)/dx - dx/dx
= -k/2 + 1
[follow the image1-2 can know that it is exactly the initial value of error term: 1 - 0.5k]

其余部分类似于前一个0 <= k <= 1的情况,不同之处在于我们每次都进入第二种if-case,并决定是否要移至第一种if-case以移动x。