Алгоритм заполнения полигонов - PullRequest
1 голос
/ 04 августа 2009

Я хочу эффективный алгоритм для заполнения полигона изображением, я хочу заполнить изображение в трапеции. в настоящее время я делаю это в два этапа
1) Сначала выполните StretchBlt на изображении,
2) Выполнить столбец столбец вертикальный StretchBlt,

Есть ли лучший способ реализовать это? Есть ли общий и быстрый алгоритм, который может заполнить любой многоугольник?

Спасибо, Sunny

Ответы [ 2 ]

1 голос
/ 28 августа 2009

Можно ли обойти проблему и использовать OpenGL, чтобы сделать это для вас? OpenGL может выполнять рендеринг в контексты памяти, и если вы можете воспользоваться преимуществами любого аппаратного ускорения, сделав это, вы полностью затормозите любые изменения кода, которые вы можете сделать на ЦП (хотя на некоторых старых картах рендеринг контекста памяти может не иметь возможности использовать преимущества аппаратное обеспечение).

Если вы хотите сделать это полностью в программном обеспечении, возможно, вам подойдет MESA .

1 голос
/ 28 августа 2009

Я не могу помочь вам с частью искажения, но заполнение полигонов довольно просто, особенно если они выпуклые.

Для каждой строки развертки Y есть таблица, индексированная Y, содержащая minX и maxX.

Для каждого ребра запустите алгоритм рисования линий DDA и используйте его для заполнения записей таблицы.

Для каждой строки Y теперь у вас есть minX и maxX, так что вы можете просто заполнить этот сегмент строки сканирования.

Сложная часть - это ментальный трюк - не думайте о координатах как об указании пикселей. Представьте, что координаты лежат между пикселями. Другими словами, если у вас есть прямоугольник, идущий от точки 0,0 к точке 2,2, он должен светиться 4 пикселя, а не 9. Большинство проблем с заполнением полигонов связаны с этой проблемой.

ДОБАВЛЕНО: ОК, звучит так, будто вы действительно спрашиваете, как растянуть изображение до непрямоугольной формы (но трапециевидной). Я бы сделал это в терминах параметров s и t, переходя от 0 к 1. Другими словами, местоположение в исходном прямоугольнике (x + w0*s, y + h0*t). Затем определите функцию так, чтобы s и t также отображались на позиции в трапеции, такие как ((x+t*a) + w0*s*(t-1) + w1*s*t, y + h1*t). Это определяет отображение координат между двумя фигурами. Затем просто отсканируйте x и y, преобразовав в s и t, и сопоставьте точки из одной в другую. Вы, вероятно, хотите иметь небольшой фильтр сглаживания, а не прямое копирование.

ДОБАВЛЕНО, чтобы попытаться дать лучшее объяснение: Я предполагаю, что у вашего прямоугольника и трапеции верхний и нижний края параллельны оси X. Нижний левый угол прямоугольника - <x0,y0>, а нижний левый угол трапеции - <x1,y1>. Я предполагаю, что ширина и высота прямоугольника <w,h>. Для трапеции я предполагаю, что она имеет высоту h1, и что ее нижняя ширина равна w0, а ее верхняя ширина w1. Я предполагаю, что его левый край «наклоняется» на расстояние a, так что положение его верхнего левого угла равно <x1+a, y1+h1>. Теперь предположим, что вы итерируете <x,y> по прямоугольнику. В каждой точке вычислите s = (x-x0)/w и t = (y-y0)/h, которые находятся в диапазоне от 0 до 1. (Я дам вам понять, как это сделать без использования плавающей запятой.) Затем преобразуйте это в координату трапеции, как xt = ((x1 + t*a) + s*(w0*(1-t) + w1*t)) и yt = y1 + h1*t. Тогда <xt,yt> - это точка на трапеции, соответствующая <x,y> в прямоугольнике. Теперь я дам вам понять, как сделать копирование :-) Удачи.

P.S. И, пожалуйста, не забывайте - координаты падают между пикселями, а не на них.

...