- •Київ кнутд 2007
- •1.2 Сфери використання
- •1.3 Головнi поняття I операцiї
- •1.4 Типи графiчних приладiв
- •2 Алгоритми растрової графiки
- •2.1 Растрова I векторна графiка
- •2.1.1 Цифровий диференцiйний аналiзатор
- •2.1.2 Алгоритм Брезенхема побудови вiдрiзкiв
- •2.1.3 Алгоритм Брезенхема креслення кола
- •2.1.4 Алгоритм Брезенхема побудови елiпса
- •2.2 Растрова розгортка багатокутникiв.
- •2.2.1 Алгоритм заповнення з упорядкованими списками ребер
- •2.2.2 Алгоритм заповнення за ребрами
- •2.2.3 Алгоритм заповнення iз списком ребер I прапорцем
- •2.2.4 Простий алгоритм заповнення iз зачiпкою
- •2.2.5 Алгоритм заповнення по рядкам iз зачiпкою
- •2.3 Ефект драбини
- •3. Лабораторнi роботи
- •3.1 Лабораторна робота BresLine на тему "Виведення вiдрiзкiв прямих за алгоритмом Брезенхема"
- •3.2 Лабораторна робота BresCirc на тему "Виведення дуг кола за алгоритмом Брезенхема".
- •3.3 Лабораторна робота BresEllips на тему "Виведення елiпсiв за алгоритмом Брезенхема".
- •3.4 Лабораторна робота FloodLine на тему "Заповнення полiгональних фiгур".
- •3.5 Лабораторна робота FloodCirc на тему "Заповнення довiльних областей".
- •4. Література
- •1 Вступ 5
- •2 Алгоритми растрової графiки 8
- •4. Література 54
2.1.4 Алгоритм Брезенхема побудови елiпса
Опис алгоритму. Побудова ітераційного алгоритму типа Брезенхема побудови еліпса є аналогічною побудові алгоритму Брезенхема для прямої. Загальний алгоритм формування еліпсів, осі яких не є паралельними осям координат див. у [14].
Наведемо далi "алгоритм середньої точки" для еліпса з центром у початку координат i напiвосями, що паралельні осям координат. Тоді рівняння еліпса має вигляд
b2 x2 + a2 y2 - a2 b2 = 0, a, b>0. |
(5) |
Для визначення того, який з пiкселiв є найближчим до еліпсу алгоритм використовує значення рівняння еліпса у середній точці між пiкселами. Якщо це значення є від’ємним, то середня точка знаходиться у середині еліпса, додатним -- зовні еліпса.
Отже, алгоритм вибирає, який з двох пiкселiв ближче до елiпса, аналiзуючи знак функцiї елiпса, яка обраховується у поточнiй точцi.
Виникає питання, який з сусiднiх пiкселiв треба дослiджувати на k-му кроцi iтерацiйного алгоритму при переходi вiд пiксела A (інше позначення A00[xk - 1, yk - 1]) до наступного пiксела. Цей вибiр залежить вiд вiдношення dy/dx, тобто вiд нахилу "дотичної до елiпса".
При dy/dx>-1, алгоритм здiйснює вибiр мiж двома пiкселами, що розташованi вертикально пiксел A+0[xk - 1+1, yk - 1] або пiксел A+-[xk – 1 +1, yk – 1 - 1].
При dy/dx<-1 --- мiж двома пiкселями, що розташованi горизонтально пiксел A0-[xk - 1, yk - 1-1] або пiксел A+0[xk – 1 + 1, yk - 1].
При dy/dx>-1, алгоритм визначає для кожного пiкселя, що формується, яка з двох точок -- A+0 або A+- -- розташована ближче до елiпса. Для цього перевiряємо, розташована середня точка B = (A+0 + A+-)/2 вiдрiзка [A+0 A+-] у серединi або зовнi елiпса.Легко перевiрити, що B[xk – 1 +1, yk – 1 - 1/2]. Тому все залежить вiд знаку функцiї вiдхилення
k = k (B) = b2(xk – 1 +1)2 + a2 (yk – 1 - 1/2)2 - a2 b2. |
(6) |
Так саме як у алгоритмi Брезенхема, значення k обчислюються iтеративним чином.
k - k – 1 = [b2(xk – 1 +1)2 + a2 (yk – 1 - 1/2)2 - a2 b2]
-[b2x2k – 1 + a2(yk – 1 -1/2)2 - a2 b2] = 2b2 xk-1+b2.
Пiсля знаходження рiзницi k i k-1 (тобто k y) ще треба множити x2k на сталу. Але цього можна уникнути, обчислюючи k x (також як k y) додаючи 2b2 на кожному iтерацiйному кроцi.
Якщо пiксел A+0 є ближчим до елiпса ( k), то нове значення k, яке буде обчислено, можна використати як k-1 у наступнiй iтерацiї. Але, якщо до елiпса ближче точка A+- , то k треба скорегувати, зробивши зсув на один крок донизу.
Якщо [xk ,yk +1/2] -- середня точка мiж пікселами A+0 i A+- , то [xk-1, yk-1 -1/2] - середня точка, що є нижчою пiкселя A+- i
k - k-1 = [b2x2k-1+a2(yk-1-1/2)2 -a2b2] - [b2x2k-1+a2(yk-1+1/2)2 -a2b2]=-2a2yk-1.
Якщо dy/dx<-1, то треба вибирати мiж пiкселями A+0 i A+- , що розташованi горизонтально.
Якщо вибрано пiксел A+0, то треба скористатись точкою [xk-1+1/2, yk-1-1] i iнкремент (добавка) для дорівнює
k- k-1=[b2(xk-1+1/2)2+a2(yk-1-1/2)2-a2b2]-[b2(xk-1+1/2)2+a2(yk-1-1/2)2-a2b2]=
= - 2a2 yk-1+a2.
Якщо вибрано пiксел A0- , то треба значення k-1 скорегувати на крок у правому напрямку
k - k-1 = [b2(xk-1+1/2)2+a2yk-12-a2b2]-[b2(xk-1-1/2)2+a2y2k-1-a2b2]=2b2xk-1.
Це вказує, як формувати вiдповiднi значення iтерацiйним чином з використанням лише додавання або вiднiмання при виконаннi iтерацiйних циклiв.
Попереднiй аналiз вiдрiзняє випадки, коли dy/dx<-1 i dy/dx>-1. Залишилось розглянути випадок, коли dy/dx=-1. Розглядаючи (5) як тотожнiсть, де y=y(x), отримаємо
2b2x+2a2yy'=0
dy/dx=-(2b2x)/(2a2y)=-1
2b2x=2a2y.
Але у алгоритмi вже використовуються величини 2b2x i 2a2y для обчислення приростiв ky i kx, то останнi можна використовувати для визначення моменту, коли значення dy/dx досягне значення -1.
Наведений далi алгоритм креслить за стрiлкою годинника дугу елiпса у першiй чвертi, тобто вiд точки (0,b) до точки (a,0) (на екранi це буде третя чверть).
Спочатку вважаємо, що dy/dx>-1 i вибiр здiйснюємо мiж вертикальними пiкселями, до того, коли стане dy/dx=-1.
При виконаннi умови dy/dx=1 старi значення знаходились для вертикальних пiкселiв, а треба перейти до вибору горизонтальних пiкселiв. У цей момент треба iнкремент для k обчислити за виразом
k - k-1=[b2(xk-1+1/2)2+a2(yk-1-1)2-a2b2] -[b2(xk-1+1)2+a2(yk-1-1/2)2-a2b2]=
=3(a2-b2)/4-(b2xk-1+a2yk-1).
Оскільки алгоритм пiдраховує величини 2b2xk-1 i 2a2yk-1, то останнiй вираз можна пiдраховувати за формулою
k - k-1=3(a2-b2)/4-(2b2xk-1+2a2yk-1)/2.
При виконаннi умови dy/dx<-1 алгоритм здiйснює вибiр горизонтальних пiкселiв.
Реалiзацiя алгоритму. Програма, що наведена далi, є швидкою та ефективною, так як всi обчислення значень змiнних зведенi до додавання та вiднiмання. Внутрiшнi цикли не мiстять множень завдяки попередньому обчисленню значень a2, b2, 2a2, 2b2 (вiдповiдно, змiннi Sqr_a, Sqr_b, TwoSqr_a, TwoSqr_b). Початковi значення змiнних пiдраховуються при припущеннi, що перший пiксел виводимо у точцi (0,b).
Таким чином, початкове значення обчислюється для середньої точки мiж пiкселями з координатами (1,b) i (1,b-1), тобто у точцi (1,b-1/2):
:=b2(1)2+a2(b-1/2)2-a2b2=b2-a2b+a2/4.
Початковi значення для dy i dx (їм вiдповiдають змiннi k i x опису алгоритму):
dx:=2b2 0=0, dy:=2a2(b)=2a2b=TwoSqr_a*b.
Процедура BresenhamEllipse є точною реалiзацiєю наведеного алгоритму.
Спочатку вона формує всi пік селі мiж (0,b) i точкою, де похiдна dy/dx стає рiвною -1.
Потiм процедура корегує значення d ( k при dy/dx=-1).
Далi iтеративний вибiр пiкселiв продовжується до досягнення осi OX.
Процедура викликає процедуру Set4Pixels для малювання кожного з чотирьох пiкселiв, що вiдповiдають поточному сформованому пiкселю у чотирьох квадрантах вiдносно фактичного центру елiпса (xc, y0).
Вiдсiкання точок, яки не є видимими у клiєнтської частинi форми, при цьому не робиться (це здiйснюється системними засобами).
Вiдповiднi процедури.
Процедура виведення пiкселiв.
procedure Set4Pixels(x,y,xc,yc:Integer;Color:Tcolor);
begin {Set4Pixels}
Form1.Canvas.Pixels[xc+x,yc+y]:=Color;
Form1.Canvas.Pixels[xc+x,yc-y]:=Color;
Form1.Canvas.Pixels[xc-x,yc+y]:=Color;
Form1.Canvas.Pixels[xc-x,yc-y]:=Color;
end; {Set4Pixels}
Процедура виведення дуги елiпса у четвертому квадрантi.
procedure RastrBresEllipse(Xc,Yc,a,b,Color:integer);
var
Sqr_a,TwoSqr_a,Sqr_b,TwoSqr_b,x,y,d,dx,dy:integer;
begin {RastrBresEllipse}
if (a>0)and(b>0)
then begin {(a>0)and(b>0)}
// початкове встановлення змiнних
x:=0; y:=b;
Sqr_a:=sqr(a); Sqr_b:=sqr(b);
TwoSqr_a:=2*Sqr_a; TwoSqr_b:=2*Sqr_b;
dx:=0; dy:=b*TwoSqr_a;
// вивiд при dy/dx>-1
while (dx<dy) do
begin {while (dx<dy)}
Set4Pixels(x,y,xc,yc,Color);
if (d>0)
then begin {d>0}
y:=y-1; dy:=dy-TwoSqr_a; d:=d-dy;
end {d>0}
else begin {d<=0}
x:=x+1; dx:=dx+TwoSqr_b; d:=d+Sqr_b+dx;
end; {d<=0}
end; {while (dx<dy)}
// пiдправка при dy/dx=-1
d:=d+round(3*(Sqr_a-Sqr_b)/4+(dx+dy)/2);
// вивiд при dy/dx<-1
while (y>=0) do
begin {while (y>=0)}
Set4Pixels(x,y,xc,yc,Color);
if (d<0)
then begin {d<0}
x:=x+1; dx:=dx+TwoSqr_b; d:=d+dx;
end {d<0}
else begin {d>=0}
y:=y-1; dy:=dy-TwoSqr_a; d:=d-(Sqr_a+dy);
end; {d>=0}
end; {while (y>=0)}
end; {(a>0)and(b>0)}
end; {RastrBresEllipse}
Лiтература.[11]
