Растровое преобразование графических примитивов
Алгоритмы заполнения областей
Для заполнения областей, ограниченных замкнутой линией, применяются два основных подхода: затравочное заполнение и растровая развертка.
Методы первого типа исходят из того, что задана некоторая точка (затравка) внутри контура и задан критерий принадлежности точки границе области (например, задан цвет границы). В алгоритмах ищут точки, соседние с затравочной и расположенные внутри контура. Если обнаружена соседняя точка, принадлежащая внутренней области контура, то она становится затравочной и поиск продолжается рекурсивно.
Методы растровой развертки основаны на сканировании строк растра и определении, лежит ли точка внутри заданного контура области. Сканирование осуществляется чаще всего "сверху вниз", а алгоритм определения принадлежности точки заданной области зависит от вида ее границы.
Сначала рассмотрим простой алгоритм заполнения с затравкой с использованием стека. Под стеком в данном случае мы будем понимать массив, в который можно последовательно помещать значения и последовательно извлекать, причем извлекаются элементы не в порядке поступления, а наоборот: по принципу "первым пришел - последним ушел" ("first in - last out"). Алгоритм заполнения выглядит следующим образом:
Поместить затравочный пиксель в стек Пока стек не пуст: Извлечь пиксель из стека Инициализировать пиксель Для каждого из четырех соседних пикселей: Проверить, является ли он граничным и был ли он инициализирован Если нет, то поместить пиксель в стек
Алгоритм можно модифицировать таким образом, что соседними будут считаться восемь пикселей (добавляются элементы, расположенные в диагональном направлении).
Методы растровой развертки рассмотрим сначала в применении к заполнению многоугольников. Простейший метод построения состоит в том, чтобы для каждого пикселя растра проверить его принадлежность внутренности многоугольника. Но такой перебор слишком неэкономичен, поскольку фигура может занимать лишь незначительную часть экрана, а геометрический поиск - задача трудоемкая, сопряженная с длинными вычислениями. Алгоритм станет более эффективным, если предварительно выявить минимальный прямоугольник, в который погружен контур многоугольника, но и этого может оказаться недостаточно.
В случае, когда многоугольник, ограничивающий область, задан списком вершин и ребер (ребро определяется как пара вершин), можно предложить еще более экономный метод. Для каждой сканирующей строки определяются точки пересечения с ребрами многогранника, которые затем упорядочиваются по координате . Определение того, какой интервал между парами пересечений есть внутренний для многогранника, а какой нет, является достаточно простой логической задачей. При этом если сканирующая строка проходит через вершину многогранника, то это пересечение должно быть учтено дважды в случае, когда вершина является точкой локального минимума или максимума. Для поиска пересечений сканирующей строки с ребрами можно использовать алгоритм Брезенхема построения растрового образа отрезка.
В заключение в качестве примера приведем алгоритм закраски внутренней области треугольника, основанный на составлении полного упорядоченного списка всех отрезков, составляющих этот треугольник. Для записи горизонтальных координат концов этих отрезков будем использовать два массива и размерностью, равной числу пикселей растра по вертикали (рис. 8.11).
Построение начинается с инициализации массивов и : массив заполняется нулями, а массив - числом , равным числу пикселей растра по горизонтали. Затем определяем значения , ограничивающие треугольник в вертикальном направлении. Теперь, используя модифицированный алгоритм Брезенхема, занесем границы отрезков в массивы и . Для этого всякий раз при переходе к очередному пикселю при формировании отрезка вместо его инициализации будем сравнивать его координату с содержимым -й ячейки массивов. Если , то записываем координату в массив . Аналогично при условии координату записываем в массив .
Если теперь последовательно применить алгоритм Брезенхема ко всем трем сторонам треугольника, то мы получим нужным образом заполненные массивы границ. Остается только проинициализировать пиксели внутри отрезков .
Этот алгоритм можно легко распространить на случай произвольного выпуклого многоугольника.
Вопросы и упражнения
- Что такое разложение в растр?
- Какова математическая основа растрового разложения в алгоритме Брезенхема?
- По какому критерию инициализируется пиксель в этом алгоритме?
- Чем отличаются ветви алгоритма при углах наклона <45 и >45 ?
- Какую часть окружности достаточно построить, чтобы затем путем отражений получить окружность целиком?
- Какую часть эллипса достаточно построить, чтобы затем путем отражений получить эллипс целиком?
- Назовите два типа алгоритмов заполнения областей.
- Какая структура данных используется в алгоритмах с затравкой?
- Какие данные используются при построении растровой развертки треугольника?