Як намалювати пряму лінію між двома точками в растровій карті?


17

Я граю з карти висоти (растрові карти), намагаюся створити щось своє в своїй грі, і для цього мені потрібно реалізувати деякі основні методи малювання. Я швидко зрозумів, що малювати прямі лінії не так просто, як я думав.

Це просто, якщо ваші точки поділяють координату X або Y або якщо вони вирівняні, щоб ви могли намалювати ідеально діагональну лінію. Але у всіх інших випадках її складніше.

Який алгоритм ви використовуєте, щоб визначити, які пікселі потрібно пофарбувати, щоб він став «прямою» лінією?

Відповіді:



21

Лінійний алгоритм Брезена може бути використаний для визначення точок в растровій сітці для побудови щоб досягти відповідного візуального наближення відрізка лінії.

Алгоритм охоплює растерізацію лінії, визначеної початковими та кінцевими точками, у просторі координат, де походження знаходиться в лівій верхній частині. Цілісні координати передбачаються для відображення в піксельних центрах. Зокрема, основна форма алгоритму охоплює лише один октант кола: той, де у лінії є координати X і Y, що збільшуються, але негативний нахил з абсолютним значенням менше 1. Усі інші октанти можна отримати як прості перетворення цього основний октант.

У psuedocode ця основна форма виглядає так:

void DrawLine(Point origin, Point endpoint, Bitmap surface) {
    deltaX = endpoint.X - origin.X
    deltaY = endpoint.Y - origin.Y
    error = 0

    // Note the below fails for completely vertical lines.
    deltaError = absoluteValue(deltaY / deltaX)

    Y = origin.Y
    for (X from origin.X to endpoint.X) {
        surface.PlotPixel(X, Y)
        error = error + deltaError 
        if (error >= 0.5) {
            ++Y;
            error -= 1.0
        }
    }
}

На веб-сайті Rosetta Code є колекція конкретних реалізацій на різних мовах .

Можливо, вас також зацікавить лінійний алгоритм Ву , який дозволяє виконувати згладжування.


3
Просто хочу попередити перехожих не виводити включений псевдокод з контексту, оскільки це не вийде з поля. Він працює лише для конкретного октанта (прочитайте решту відповіді). Якщо ви шукаєте код для копіювання / вставки, спробуйте посилання на веб-сайт Коду Розетти.
congusbongus

1
Для всіх, хто хоче перевірити версію c лінійного алгоритму Ву, я хотів би попередити вас, що вона неповна. У _dla_changebrightness при зміні яскравості ви повинні змінити його з: to->red = br * (float)from->red;до цього таке: to->red = (br * (float)from->red) + ((1-br) * (float) to->red);. Зробіть те ж саме для зеленого та синього шаблону
Фредрік Бостон Вестман

2

Ось надзвичайно простий спосіб малювання ліній. Функцію можна легко змінити для використання в проектах.

void draw_line(float x0, float y0, const float& x1, const float& y1)
{
    float x{x1 - x0}, y{y1 - y0};
    const float max{std::max(std::fabs(x), std::fabs(y))};
    x /= max; y /= max;
    for (float n{0}; n < max; ++n)
    {
        // draw pixel at ( x0, y0 )
        x0 += x; y0 += y;
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.