Bresenham线没有对角线运动

时间:2012-01-20 02:46:35

标签: php algorithm line bresenham

是否有改进的Bresenham算法,其中从一个像素到下一个像素的步长不允许对角线,只是水平或垂直?或者其他算法呢? (PHP首选)

Right:
0 0 0 1
0 0 1 1
0 1 1 0
1 1 0 0

Wrong:
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0

3 个答案:

答案 0 :(得分:5)

詹姆斯'答案非常酷,但正如他评论的那样,它有点偏斜了。原始Bresenham的另一个简单修改是绘制了一条没有对角线台阶的线条,更接近真实的"线。

这是原始Bresenham算法的实现:

public void line(int x0, int y0, int x1, int y1, int value) {
    int xDist =  Math.abs(x1 - x0);
    int yDist = -Math.abs(y1 - y0);
    int xStep = (x0 < x1 ? +1 : -1);
    int yStep = (y0 < y1 ? +1 : -1);
    int error = xDist + yDist;

    plot(x0, y0, value);

    while (x0 != x1 || y0 != y1) {
        if (2*error > yDist) {
            // horizontal step
            error += yDist;
            x0 += xStep;
        }

        if (2*error < xDist) {
            // vertical step
            error += xDist;
            y0 += yStep;
        }

        plot(x0, y0, value);
    }
}

修改只是 水平或垂直步骤,而不是两者,取决于错误指示符是否更接近水平或垂直步骤:

public void lineNoDiag(int x0, int y0, int x1, int y1, int value) {
    int xDist =  Math.abs(x1 - x0);
    int yDist = -Math.abs(y1 - y0);
    int xStep = (x0 < x1 ? +1 : -1);
    int yStep = (y0 < y1 ? +1 : -1);
    int error = xDist + yDist;

    plot(x0, y0, value);

    while (x0 != x1 || y0 != y1) {
        if (2*error - yDist > xDist - 2*error) {
            // horizontal step
            error += yDist;
            x0 += xStep;
        } else {
            // vertical step
            error += xDist;
            y0 += yStep;
        }

        plot(x0, y0, value);
    }
}

这有效地选择了最小化误差的步骤,从而产生更接近实线的线。

代码是Java,但应该可以轻松移植到PHP。我还没有彻底测试它,但它应该和原来的Bresenham一样好用。它甚至可能更快一点。

答案 1 :(得分:4)

应该是一个微不足道的修改 - 让我们说你在象限I - 即向上和向右。而不是做对角线,做一个...然后一个右。

而不是:

  for x from x0 to x1
             plot(x,y)
             error := error + deltaerr
             if error ≥ 0.5 then
                 y := y + 1
                 error := error - 1.0

这样的事情:

for x from x0 to x1
         plot(x,y)
         error := error + deltaerr
         if error ≥ 0.5 then
             y := y + 1
             plot(x,y)
             error := error - 1.0

答案 2 :(得分:1)

我发现弗兰兹D的回答产生的线条在接近水平或垂直时与原始线条不匹配。虽然下面的功能并不完美,但我发现它可以产生更好的效果。

Function BresenhamLineNew : Void( x0 : Int, y0 : Int, x1 : Int, y1 : Int )

    Local dx : Int = Abs( x1 - x0 )
    Local dy : Int = Abs( y1 - y0 )

    Local sx : Int = -1
    Local sy : Int = -1

    If x0 < x1 Then sx = 1
    If y0 < y1 Then sy = 1

    Local err : Int = dx - dy
    Local e2 : Int

    While True

        DrawRect x0, y0, 1, 1

        If x0 = x1 And y0 = y1 Then Exit

        e2 = 2 * err

        If dy > dx
            If e2 > -dy
                err = err - dy
                x0 = x0 + sx
            Elseif e2 < dx
                err = err + dx
                y0 = y0 + sy
            Endif
        Else
            If e2 < dx
                err = err + dx
                y0 = y0 + sy
            Elseif e2 > -dy
                err = err - dy
                x0 = x0 + sx
            Endif
        Endif

    Wend

End Function