Исправление аппроксимаций алгоритма линейной растеризации

В настоящее время я делаю заголовок для создания простой графики в консоли С++. 2 дня назад я добавил функцию для рисования линий с использованием алгоритма растеризации, используемого здесь.

Но у меня есть проблема: поскольку декартова плоскость консоли работает только с целыми числами, моя функция ничего не рисует, когда числа, заданные при приближении, равны 0, поэтому я блуждал, если бы вы могли сделать что-то вроде этого:

if ( y == 0 ) 
{ 
    //fix using some kind of 'forecast' of what y could be
}

так вот мой код:

void Engine::line(int ax, int ay, int bx, int by, int color)
{

    int i = 0;

    if(ax < bx)
        i = 1;
    if(ax > bx)
        i = -1;


    int dx = bx - ax;
    int dy = by - ay;

    for (int x = ax; x != bx; x+=i)
    {
        int y = ay + (by - ay) * (x - ax)/(bx - ax);

        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, color);

        Engine::gotoxy(x,y); printf("%c", 219);
    }
}

И вот мой вывод, где, если линия сильно наклонена, она не отображается должным образом: image

Я действительно надеюсь, что вы можете мне помочь, но если нет, можете ли вы дать мне лучший алгоритм, который все еще прост, но отлично работает с целыми числами? (не тот, что у Брезенхэма)


person Community    schedule 24.01.2019    source источник
comment
Что не так с изображением? Это разъединенность? Если это так, вам просто нужно сравнить abs(ax-bx) и abs(ay-by) и сделать так, чтобы внешний цикл повторял большее значение.   -  person Martin Bonner supports Monica    schedule 24.01.2019
comment
Кроме того, вместо использования приращения я бы использовал std::swap(ax,by), если ax > bx   -  person Martin Bonner supports Monica    schedule 24.01.2019
comment
Я рекомендую использовать en.wikipedia.org/wiki/Bresenham%27s_line_algorithm. Это не так сложно реализовать, как описывает Википедия.   -  person Max Langhof    schedule 24.01.2019


Ответы (2)


Традиционный подход состоит в том, чтобы написать свой алгоритм 2, 4 или 8 раз в зависимости от октанта диагонали, которую вы хотите нарисовать. в основном, когда |dx| > |ди| вы делаете шаг на 1 в x. Когда |дх| ‹ |ди| вы шаг за шагом 1 в y.

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

Вы также можете посмотреть на трюк со сглаживанием Wu, который использует остаток с плавающей запятой для затенения 2 перекрывающихся пикселей, хотя, как вы затем примените это к текстовому режиму, это ваша проблема, извините.

person Gem Taylor    schedule 24.01.2019

Используя тот же алгоритм, вы можете повысить точность, сначала вычислив y в вещественном числе, а затем округлив его до ближайшего целого числа. Это можно объединить с предыдущим ответом.

person Damien    schedule 24.01.2019