Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции КГ / Лекции КГ.doc
Скачиваний:
340
Добавлен:
10.05.2015
Размер:
7 Mб
Скачать

7Рис. 8.59 – Тор (а), параллельная (б) и центральная (в) проекции его линий очерка.

    1. Основные растровые алгоритмы

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

Данная процедура неоднозначна, так как "достаточно точно" можно понимать по-разному. Кроме того, алгоритмы визуализации графических примитивов должны быть простыми и работать исключительно быстро, поскольку иначе теряется преимущество векторной графики - малый объем занимаемой памяти и, соответственно, высокая скорость обработки.

Рассмотрим растровое отображение простейшей фигуры – отрезка. Процесс последовательной смены цвета множества пикселов, изображающих отрезок, называется растровой разверткой отрезка.

Простейшее решение состоит в следующем: по координатам отрезка получить уравнение прямой и, подставляя в него целочисленные значения координат, менять цвет у получающихся точек. Если концы отрезка имеют координаты (x1, y1)и(x2, y2), то отрезок задается уравнением:

(0)

При этом xменяется отx1доx2. Напишем простейшую процедуру построения отрезка:

dY:=ABS(Y2-Y1)/(X2-X1));

y:=y1;

for x:=x1 to x2 do

begin

PutPixel(x, round(y));

y:=y+dy

end;

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

а) б)

Рис. 8.60 - Четырехсвязная (а) и восьмисвязная (б) развертки отрезка.

Четырехсвязная развертка отрезка включает те и только те точки, квадратные окрестности которых пересекаются с отрезком. Восьмисвязная развертка отрезка включает те и только те точки, боковые стороны квадратных окрестностей которых пересекаются с отрезком.

Приведем алгоритм для генерации четырехсвязной развертки:

x:=x1;

y:=y1;

n:=x2-x1;

m:=y2-y1;

d:=(m/n);

e:=d/2;

for i:=1 to n+m do

begin

x:=x+1;

e:=e+d; { отклонение }

if e>0.5 then

begin

y:=y+1;

e:=e-1

end

else

begin

x:=x+1;

e:=e+d

end;

PutPixel(x,y)

end;

Здесь в переменной ехранится разница между координатойYтекущей точки отрезка и координатойYточки пересечения отрезка с правой границей квадратной окрестности текущей точки растровой развертки. Приe0.5отрезок пересекает окрестность точки, лежащей справа от текущей, и нужно сместиться вправо. Приe0.5отрезок пересекает окрестность точки, лежащей выше текущей, и надо сместиться вверх ().

Рис. 8.61 – Схема работы алгоритма четырехсвязной развертки отрезка.

Как указывалось выше, очень важна эффективность алгоритма развертки. Как известно, компьютер работает с целыми числами гораздо быстрее, чем с вещественными. Поэтому было бы очень желательно придумать такой алгоритм растровой развертки, который использовал бы только целые числа. Целочисленные алгоритмы для развертки графических примитивов были разработаны инженером компании IBMБрезэнхемом и носят его имя.

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

Procedure Bresenham(x1,y1,x2,y2,Color: integer);

var

dx,dy,incr1,incr2,d,x,y,xend: integer;

begin

dx:= ABS(x2-x1);

dy:= Abs(y2-y1);

d:=2*dy-dx; {начальное значение для d}

incr1:=2*dy; {приращение для d<0}

incr2:=2*(dy-dx); {приращение для d>=0}

if x1>x2 then {начинаем с точки с меньшим знач. x}

begin

x:=x2;

y:=y2;

xend:=x1;

end

else

begin

x:=x1;

y:=y1;

xend:=x2;

end;

PutPixel(x,y,Color); {первая точка отрезка}

While x<xend do

begin

x:=x+1;

if d<0 then

d:=d+incr1 {выбираем нижнюю точку}

else

begin

y:=y+1;

d:=d+incr2; {выбираем верхнюю точку, y-возрастает}

end;

PutPixel(x,y,Color);

end;{while}

end;{procedure}

Еще одна задача, часто решаемая в ходе визуализации – заливка цветом некоторой заданной границей области. Область обычно задается или в векторном виде массивом координат вершин многоугольника, или в растровом – набором пикселов определенного цвета, образующих замкнутый контур.

Для решения задачи заливки векторного многоугольника необходимо закрашивать тем или иным цветом выводимые на экран пиксели в зависимости от того, лежат они внутри многоугольника или снаружи. Таким образом, задача векторной заливки сводится к задаче определения принадлежности точки P(x,y)многоугольнику, заданному координатами вершин. Идея алгоритма для решения этой задачи состоит в следующем (Рис. 8 .62).

Рис. 8.62 –Определение принадлежности точки многоугольнику.

Проведем через точку Pгоризонтальную полупрямую (луч) и определим число пересечений этой полупрямой с ребрами многоугольника. Если это числонечетно, то точкаРлежит внутри многоугольника,четно– снаружи.

Заполнение растровой области хорошо знакомо программистам, поскольку почти во всех языках программирования есть соответствующие команды (например, в языке Pascalэто команда FloodFill, вDelphi– метод FloodFill объектаTCanvasи т.д.)

Рис. 8.63 – Заполнение растровой области с затравкой.

Граница области является четырех- или восьмисвязной растровой кривой, все пикселы которой имеют один и тот же цвет. Внутри области могут находиться "острова", которые закрашивать не надо. Предполагается, что внутри области задана точка начала закраски, называемая затравкой (Рис. 8 .63).

Для выполнения заливки используется специальная структура данных, называемая стеком (stack). Стек работает по принципу "первым вошел – последним вышел" (Рис. 8 .64).

Рис. 8.64 - Стек.

Хорошим аналогом стека является магазин автомата Калашникова (программистская шутка гласит, что АКМ – лучшее средство для превращения стека в очередь). При извлечении значений из стека нужно помнить о том, что теперь они будут идти в обратном порядке. Если мы занесли в стек сначала а, потомb, потомc, то первым извлечетсяс, затемbи, наконец,а.

Эффективный алгоритм заливки основан на построчном сканировании заполняемой области. Вот его схема:

Инициализируем стек, помещая в него координаты затравочного пиксела. Пока стек не пуст:

извлекаем пиксел (х,у) из стека;

заполняем максимально возможный интервал, в котором находится пиксел, вправо и влево вплоть до достижения граничных пикселов;

запоминаем крайнюю левую Lx и крайнюю правую Rx абсциссы заполненного интервала;

в соседних строках над и под интервалом (Lx,Rx) находим незаполненные к настоящему моменту внутренние пикселы области, которые, как мы уже заметили, объединены в интервалы, а в каждом из этих интервалов находим крайние правые пикселы. Каждый из этих пикселов вносим в стек в качестве затравочного.

Такой алгоритм правильно заполняет область любой конфигурации, в том числе и с "островами" внутри.