2015-06-16 1 views
2

Я пытаюсь осуществить линию Bresenham рисунка со сглаживанием, используя эту статью: http://members.chello.at/~easyfilter/bresenham.htmlСглаживание линии Bresenham не работает, как ожидалось

А вот функция:

void ColoringScene::drawLineAA(int x0, int y0, int x1, int y1, int r, int g, int b, int a) 
{ 
    float dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; 
    float dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; 
    float err = dx-dy, e2, x2;      /* error value e_xy */ 
    float ed = dx+dy == 0 ? 1 : sqrt((float)dx*dx+(float)dy*dy); 

    for (;;){           /* pixel loop */ 
     setPixel(x0, y0, r, g, b, a*abs(err-dx+dy)/ed); 
     e2 = err; x2 = x0; 
     if (2*e2 >= -dx) {         /* x step */ 
      if (x0 == x1) break; 
      if (e2+dy < ed) setPixel(x0, y0 + sy, r, g, b, a*(e2+dy)/ed); 
      err -= dy; x0 += sx; 
     } 
     if (2*e2 <= dy) {          /* y step */ 
      if (y0 == y1) break; 
      if (dx-e2 < ed) setPixel(x2 + sx, y0, r, g, b, a*(dx-e2)/ed); 
      err += dx; y0 += sy; 
     } 
    } 
} 

Не знаю, что это что-то меняет, но я изменил все int's на float. Просто чтобы убедиться, что деление работает на поплавках. В любом случае результат целых чисел одинаковый.

Теперь пример вызова:

drawLineAA(10, 10, 50, 400, 255, 0, 0, 255); 
drawLineAA(100, 10, 500, 40, 255, 0, 0, 255); 

Результаты в этом: enter image description here

Если я изменяю y0 + SY к у0 - SY так:

if (e2+dy < ed) setPixel(x0, y0 - sy, r, g, b, a*(e2+dy)/ed); 

Выход становится это:

enter image description here

Если я изменяю x2 + SX х2 - Sx, как это:

if (dx-e2 < ed) setPixel(x2 - sx, y0, r, g, b, a*(dx-e2)/ed); 

Выход сейчас:

enter image description here

Так последняя конфигурация обоих негативов, что дает:

enter image description here

Практически все, но появляются некоторые дыры. Так что это все еще неправильно. Я не могу понять, почему он неправильно рисует. Когда я попробовал обычный брэшенхам без сглаживания, и он работает без проблем.

Также важно отметить, что в моем случае я использую текстуру cocos2d-x, поэтому y переворачивается. Вот почему у меня есть этот метод:

void ColoringScene::setPixel(int x, int y, int r, int g, int b, int a){ 
    if(x < 0 || x >= img->getWidth() || y < 0 || y >= img->getHeight()) return; 
    int index = (x + (img->getHeight() - y - 1) * img->getWidth()) * 4; 
    data[index] = r; 
    data[index + 1] = g; 
    data[index + 2] = b; 
    data[index + 3] = a; 
} 

Возможно, проблема в этом. Как я могу это исправить?
С уважением

ответ

1

Этот алгоритм кажется неправильным.

  • x0==x1 или y0==y1 является фатальной ошибкой.
  • dx==dy является фатальной ошибкой.
  • Установка ed=1, когда dx+dy=0 полностью произвольно.
  • 2*e2==dy и 2*e2==-dx приводит к рисованию трех пикселей на шаг.

Рекомендации: обработайте dx = dy, dx = -dy, dx = 0, dy = 0 как особые случаи, делайте отдельные случаи для каждого октананта, не используйте поплавки, если они вам не нужны.

+0

Да, похоже. Я нашел еще один алгоритм, и он работает :) – Makalele