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



Все такие структуры поместим в список (далее - 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. При ее возникновении указанный цикл выполняет локальную сортировку САР методом "пузырька".
Преимущество двух приведенных алгоритмов перед последующими состоит в том, что операции вывода на экран (относительно "медленные" во многих системах) для каждого пикселя выполняются не более одного раза. Недостатком является использование динамических структур данных (списков), что сильно усложняет код и требует дополнительной памяти.
Существует класс систем, в которых использование динамических структур данных нежелательно (вследствие ограниченности ресурса памяти или отсутствия удобных средств разработки программ), в то время как замедление работы из-за частого обращения к видеопамяти некритично (сюда относятся, например, мобильные телефоны и другие портативные устройства, имеющие графический дисплей). В таких системах эффективным будет использование следующих алгоритмов, оперирующих непосредственно с данными в видеобуфере (то есть с "содержимым" экрана).
