Линии Брезенхема без диагонального движения - PullRequest
1 голос
/ 20 января 2012

Существует ли модифицированный алгоритм Брезенхэма, в котором шаг от одного пикселя к следующему не может быть по диагонали, только по горизонтали или по вертикали?Или любой другой алгоритм, который делает это?(Предпочтительно 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 ]

5 голосов
/ 28 февраля 2015

Ответ Джеймса довольно крутой, но, как он прокомментировал, он немного искажает линию. Другая простая модификация оригинального Брезенхэма рисует линию без диагональных шагов, которая ближе к «реальной» линии.

Это реализация оригинального алгоритма Брезенхэма:

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. Я не проверил его полностью, но он должен работать так же хорошо, как и оригинальный Брезенхем. Это может быть даже немного быстрее.

4 голосов
/ 20 января 2012

Должна быть тривиальная модификация - скажем, вы находитесь в квадранте, то есть я иду вверх и вправо. Вместо того, чтобы делать диагональ, сделайте вверх ... и затем вправо.

Вместо:

  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
1 голос
/ 01 октября 2017

Я обнаружил, что ответ Франца Д. приводит к появлению линий, которые близко не соответствуют оригиналу при приближении к горизонтали или вертикали. Хотя приведенная ниже функция не идеальна, я обнаружил, что она дает более хорошие результаты.

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
...