2016-01-08 2 views
0

Я пытаюсь использовать Bresenham's Line Drawing Algorithm, чтобы нарисовать линию на сетке 20х20.Ошибка с алгоритмом рисования линии Брешенема

Так что, в основном, когда переменная deltaerror (из вики) больше 1 (когда изменение y больше, чем изменение x), значение y становится почти вдвое больше, чем оно должно быть. Надеюсь, я лучше объясню это в комментариях к коду. Я также думаю, что нашел источник ошибки, о которой я также расскажу в комментариях.

Это код, который я сделал, в основном скопированный из псевдокода в вики.

public static void drawLine(Tile t1, Tile t2) { 
    int dx = t2.x_index - t1.x_index; 
    int dy = t2.y_index - t1.y_index; 
    double error = 0; 
    double d_error = Math.abs((double) dy/dx); // dx =/= 0, therefore no vertical lines 

    // when d_error is greater than 1, the bug occurs 

    int y = t1.y_index; 
    if (d_error <= 1) { // if related acute angle is < 45 degrees 
     if (dx < 0) { // line drawn towards left side of screen 
      for (int x=t1.x_index; x>=t2.x_index; x--) { 
       Board.tiles[x][y].setColour(Color.red); 
       error += d_error; 
       while (error >= 0.5) { 
        Board.tiles[x][y].setColour(Color.red); 
        y += dy > 0 ? +1 : -1;// this is where I think the error occurs. In the 
              // wiki for the algorithm, this should be some 
              // function sign(T) which "decides whether t is 
              // positive or negative". I wasn't really sure 
              // what this meant, so I just assumed it returned 
              // -1 if it was negative and +1 if it was positive. 
              // Also it's the only place where y is edited 
              // that seems to be where the error is occurring. 
        error -= 1.0; 
       } 
      } 
     } else if (dx > 0) { // line drawn towards right side of screen 
      for (int x=t1.x_index; x<=t2.x_index; x++) { 
       Board.tiles[x][y].setColour(Color.red); 
       error += d_error; 
       while (error >= 0.5) { 
        Board.tiles[x][y].setColour(Color.red); 
        y += dy > 0 ? +1 : -1; 
        error -= 1.0; 
       } 
      } 
     } 

    // update: switched x and y values when d_error is greater than 1. 

    } else { // if related acute angle is > 45 degrees 
     dx = t2.y_index - t1.y_index; // switch x and y values 
     dy = t2.x_index - t1.x_index; 

     d_error = Math.abs((double) dy/dx); // recalculate d_error 
     y = t1.x_index; 
     if (dx < 0) { // line drawn towards left side of screen 
      for (int x=t1.y_index; x>=t2.y_index; x--) { 
       Board.tiles[x][y].setColour(Color.red); 
       error += d_error; 
       while (error >= 0.5) { 
        Board.tiles[x][y].setColour(Color.red); 
        y += dy > 0 ? +1 : -1; 
        error -= 1.0; 
       } 
      } 
     } else if (dx > 0) { // line drawn towards right side of screen 
      for (int x=t1.y_index; x<=t2.y_index; x++) { 
       Board.tiles[x][y].setColour(Color.red); 
       error += d_error; 
       while (error >= 0.5) { 
        Board.tiles[x][y].setColour(Color.red); 
        y += dy > 0 ? +1 : -1; 
        error -= 1.0; 
       } 
      } 
     } 
    } 
} 

Благодарим за помощь!

EDIT: Переключенные значения x и y, когда d_error больше 1. Линия исчезает, когда наклон выше 1 и ниже -1.

+0

I * подозреваемый *, что строка 'error - = 1.0' должна находиться вне циклов' while', хотя я не уверен на 100%. Можете ли вы сделать это изменение и сообщить мне, исправляет ли он это? – templatetypedef

+0

@templatetypedef Это только рисовало линию вдоль осей x и y. – alexanderd5398

+0

Угадайте, я был неправ. :-) Спасибо за проверку. – templatetypedef

ответ

1

Цитирую быстро Google-результат:

http://www.math.ubc.ca/~cass/courses/m308-02b/projects/puhalovic/#alldirections

«С откосов больше 1 или меньше -1, мы должны взять предыдущую реализацию и обмен всех х и у значения в» переместить "вычисления обратно в" Первый октант "."

IOW: Реализация учебника для bresenham работает только для линий с (на ваших условиях) d_error<=1. Вам нужно будет выполнить замену, указанную в ссылке выше.

+0

Итак, когда наклон больше 1 или меньше -1, я просто переключаю значения x и y? – alexanderd5398

+1

Я бы сказал, да, это именно так. Наиболее простой реализацией будет один большой блок if-else для этих двух случаев. – ThorngardSO

+0

попробовал это, линия просто исчезает сейчас, когда d_error> 1 – alexanderd5398