Московский государственный университет имени М.В.Ломоносова
Опубликован: 23.04.2007 | Доступ: свободный | Студентов: 3285 / 447 | Оценка: 4.18 / 3.71 | Длительность: 17:54:00
ISBN: 978-5-9556-0098-7
Специальности: Программист
Лекция 6:

Заполнение многоугольников и областей

< Лекция 5 || Лекция 6: 1234 || Лекция 7 >

Алгоритм со списком активных ребер

Попробуем несколько видоизменить предыдущий алгоритм. Вместо того чтобы хранить в памяти точки пересечения контура с каждой строкой растра, ограничимся лишь одной строкой - текущей. А именно, организуем список "активных" ребер (САР), в котором будем хранить информацию обо всех ребрах многоугольника, пересекаемых текущей строкой. Удобство такого подхода в том, что при переходе к новой строке не требуется полностью переформировывать САР. Достаточно лишь удалить из него "закончившиеся" ребра (то есть ребра из САР, чей нижний конец оказался выше нового значения y ) и добавить вновь появившиеся.

Перейдем к формальному описанию алгоритма. Для каждого ребра создадим структуру данных:

y = \lceil y_1 \rceil;
dx =\frac{x_2 - x_1}{y_2 - y_1};
x = x_1 + dx \cdot (y - y_1).

Все такие структуры поместим в список (далее - y-список) и упорядочим его по возрастанию y.

САР = пустой;
y = y_список[ первый элемент ].y;
do
{
      САР.Добавить( ребра из y-списка, у которых
                                 ребро.y = y);
      // сохраняя упорядоченность САР по возрастанию x
      y_список.Удалить( ребра, у которых ребро.y = y );

      Закрасить промежутки ( x_2i - 1, x_2i ) в строке y;
      y++;

      foreach( ребро из САР по порядку )
      {
            if(y > ребро.y2)
                  удалить ребро из САР;
            else
            {
                  ребро.x += ребро.dx;
                  while(соседнее_слева_ребро(ребро).x > ребро.x)
                        поменять местами в САР ребро с соседним;
            }
      }
}
while(САР не пуст);
Листинг 6.2. Растеризация с САР

Ребра, помещенные в САР, удаляются из y-списка с той целью, чтобы свести проверку наличия в y-списке ребер, начинающихся с данного уровня y, к проверке этого условия для первого ребра в списке (это справедливо в силу упорядоченности списка). Цикл while используется для сохранения упорядоченности САР, которая может нарушиться при изменении значений x на dx.

Пример такой ситуации показан на рис. 6.3. При ее возникновении указанный цикл выполняет локальную сортировку САР методом "пузырька".

Локальная сортировка САР.

Рис. 6.3. Локальная сортировка САР.

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

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

< Лекция 5 || Лекция 6: 1234 || Лекция 7 >