Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции Компьютерная графика.doc
Скачиваний:
48
Добавлен:
10.12.2018
Размер:
572.93 Кб
Скачать

3.5. Общий алгоритм Брезенхема

Для получения общего алгоритма растровой развертки необходимо избавиться от ограничений, которые мы до сих пор накладывали на расположение отрезка на плоскости, а именно от требования 0k1.

Чтобы реализация алгоритма Брезенхема была полной, необходимо обрабатывать отрезки во всех квадрантах. Модификацию легко сделать, учитывая номер квадранта, в котором лежит отрезок и его угловой коэффициент. Когда абсолютная величина углового коэффициента больше 1, y постоянно изменяется на единицу, а критерий ошибки Брезенхема используется для принятия решения об изменении величины x. Выбор постоянно изменяющейся (на +1 или –1) координаты зависит от квадранта (рис.3).

x=x-1

y=y+1

x=x+1

y=y+1

x=x-1

y=y-1

x=x+1

y=y-1

Рис.3. Общий алгоритм Брезенхема

Таким образом, учитывая ориентацию отрезка относительно положительных направлений осей координат и меняя переменные x,y в случае k по модулю больше 1, получаем окончательную общую версию алгоритма Брезенхема, которая называется восьмисвязной разверткой отрезка.

Пример процедуры общего алгоритма Брезенхема для восьмисвязной развертки отрезка:

Procedure Line_8 (x1,y1,x2,y2: integer);

Var

x,y,s1,s2,dx,dy,e,z: integer;

change: boolean;

Begin

x:=x1; y:=y1; dx:=abs(x2-x1); dy:=abs(y2-y1);

s1:=sign(x2-x1); s2:=sign(y2-y1);

if dy>dx then

begin

z:=dx; dx:=dy; dy:=z; change:=true

end

else change:=false;

e:=2dy-dx;

for i:=1 to dx do

begin

PutPixel (x,y,color);

While e>=0 do

begin

if change then x:=x+s1 else y:=y+s2;

e:=e-2dx

end;

if change then y:=y+s2 else x:=x+s1;

e:=e+2dy

end;

PutPixel (x,y,color)

End.

Функция sign возвращает значения –1,0,+1 для отрицательного, нулевого и положительного аргумента соответственно (реализована не во всех версиях Паскаля).

3.6. Алгоритм Брезенхема для генерации окружности

В растр нужно разлагать не только линейные, но и другие, более сложные функции.

Д ля того чтобы нарисовать окружность необходимо сгенерировать только 1/8 часть. Остальные ее части могут быть получены последовательными отражениями. Если сгенерирован первый октант (от 0 до 45 против часовой стрелки), то второй октант можно получить зеркальным отражением относительно прямой y=x, что дает в совокупности первый квадрант. Первый квадрант отражается относительно прямой x=0 для получения соответствующей части окружности во втором квадранте. Верхняя полуокружность отражается относительно прямой y=0 для завершения построения полной окружности (рис.4).

Рис.4. Генерация окружности

Д ля вывода алгоритма рассмотрим первую четверть окружности с центром в начале координат (рис.5). Заметим, что если работа алгоритма начинается в точке x=0, y=R, то при генерации окружности по часовой стрелке в первом квадранте y является монотонно убывающей функцией аргумента x. Аналогично, если исходной точкой является точка x=R, y=0, то при генерации окружности против часовой стрелки x будет монотонно убывающей функцией аргумента y.

Предположим, что центр окружности и начальная точка находятся точно в точках растра, выберем для нашего случая генерацию по часовой стрелке с началом в точке x=0, y=R.

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

,

,

.

Разность между квадратами расстояний от центра окружности до диагонального пикселя () и от центра до точки на окружности R2 равна

.

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

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

.

При <0 расстояние от окружности до диагонального пикселя () больше, чем до горизонтального пикселя (). Напротив, если >0, расстояние до горизонтального пикселя () больше. Таким образом:

  • при 0 выбираем в точке (),

  • при >0 выбираем в точке (),

  • при =0, когда расстояние от окружности до обоих пикселов одинаково, выбираем горизонтальный шаг.

Если >0, то диагональная точка () находится вне окружности. В данной ситуации ясно, что должен быть выбран либо пиксель (), т.е. , либо (), т.е. . Далее проверяется разность между квадратом расстояний от окружности до диагонального пикселя и вертикального пикселов, т.е.

.

При <0 расстояние от окружности до вертикального пикселя () больше и следует выбирать диагональный шаг к пикселю (). Напротив, в случае >0 расстояние от окружности до диагонального пикселя больше и следует выбрать вертикальное движение к пикселю (). Таким образом:

  • при 0 выбираем в (),

  • при >0 выбираем (),

  • здесь в случае =0, т.е. когда расстояния равны, выбран диагональный шаг.

Подведем итог полученных результатов:

<0

0 выбираем пиксель ()  ,

>0 выбираем пиксель ()  ,

>0

0 выбираем пиксель ()  ,

>0 выбираем пиксель ()  ,

=0 выбираем пиксель ()  ,

Легко разработать простые рекуррентные соотношения для реализации пошагового алгоритма. Сначала рассмотрим горизонтальный шаг к пикселю (). Обозначим это новое положение пикселов (i+1). Тогда координаты нового пикселя и значение равны:

,

,

Аналогично координаты нового пикселя и значение для шага к пикселю () таковы:

,

,

.

То же самое для шага к пикселю () :

,

,

.

Выполняя частные алгебраические преобразования и используя метод Брезенхема, получим следующий алгоритм:

Procedure Mich_Circle (radius; color: integer);

Var

x,y,d: integer;

Begin

x:=0;

y:=radius;

d:=3-2radius

While x<y do

begin

CirclePoint (x,y,color);

if d<0 then d:=d+4x+6

else

begin

d:=d+4(x-y)+10;

y:=y-1

end;

x:=x+1

end;

if x=y then CirclePoint (x,y,color)

End.

Процедура CirclePoint имеет вид:

Procedure CirclePoint (x,y,color: integer);

Begin

PutPixel (x,y,color);

PutPixel (y,x,color);

PutPixel (y,-x, color);

PutPixel (-x,-y, color);

PutPixel (x,-y, color);

PutPixel (-y,-x, color);

PutPixel (-y,x, color);

PutPixel (-x,y, color)

End.