Материал: 252_337

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Враховуючи обидва кроки, пояснення об'єднання яких ви­ ходить за межі даного посібника, загальне перетворення систе­ ми координат xyz у систему x'y'z' задається таким записом:

coscp

- sin ф sin у

sincpcosy

А= sincp

coscpsin\(i

-coscpcosy

0

cosy

siny

Це означає, що точка (х; у; z) із заданої поверхні переходить у точку (х'; у') на картинній площині, де

х' = х coscp + у snup, у' = -х sincp sin\|/ + у coscp simp + z cosy. Можна визначити і зворотне перетворення, яке описується

такими співвідношеннями:

х = х' coscp - у' sincp sinij/ + z' cos\|/ sincp; у = x' sincp + y' sinv|/ coscp - z' cosy coscp; z = y' cosi|/ + z' siny.

Останнє представлення значень x, у, z через x'y'z' дає змо­ гу виконати заміну змінних і отримати рівняння поверхні F(x', у', z') = 0 у новій системі координат x'y'z', в якій уже на­ прям проектування паралельний осі Oz' і проектування ведеть­ ся на площину х'Оу'. Надалі координати х', у', z' будемо позна­ чати через х, у, z. Отримане перетворене рівняння поверхні можна представити у вигляді z = f(x, у).

Тепер переходимо до другої, основної частини побудови про­ екції заданої поверхні на площину. Для кращого подальшого розуміння алгоритму уявимо собі, як можна цю поверхню на­ малювати на аркуші паперу. Нехай глибина малюнка спрямо­ вана уздовж осі Oz. Якщо уявити собі, що ми малюємо поверх­ ню, просуваючись з певним кроком по осі Oz від найближчої частини малюнка до найдальшої, то це будуть зображення його перерізів, для яких значення z буде сталим. Малювання логічно почати із найближчого перерізу: фрагмент поверхні, що належить йому, буде зображено повністю. Далі у решти пе­ рерізів малюватимемо лише ті частини фрагментів поверхні, що «виглядатимуть» із-за тих, що вже намальовані.

Тепер перейдемо на мову математики. Розглянемо побудову графіків функцій, що відповідають сталим значенням z. Це оз­ начає, що для кожного z, що змінюється у циклі від zx до z2 (zt < z2), перебираються значення х із деякого діапазону і таким чином підраховуються точки (х; у; z), що лежать на поверхні.

Описана послідовність дій дає змогу побудувати графік функції двох змінних без усунення невидимих ліній, однак таке зображення поверхні буде не зовсім зрозумілим. У зв'язку з цим постає задача про таку побудову поверхні, при якій би усувались невидимі лінії.

Зведемо тривимірну задачу до двовимірної: вся задана по­ верхня може бути представлена у вигляді послідовності ліній

312

у = f(x, z), які лежать у паралель­

У

 

 

 

 

 

 

 

 

них площинах 2 = 2; і не перетина­

 

 

 

 

ються (мал. 176).

 

 

 

 

— -

 

Отже, маємо такий алгоритм по­

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

r

 

 

будови графіка функції у = f(x, z):

 

 

У S

 

 

 

для кожної площини z =ziy поряд­

 

 

 

ку зростання г,

починаючи

з най­

 

 

 

 

 

 

 

 

 

 

 

 

[y=f(X,2)

ближчої

точки

спостереження,

 

zt

/

^—>¥

 

 

 

 

 

 

 

 

 

виводяться лінії і при зображенні

 

 

 

 

 

поточної

лінії

виводиться

лише

 

 

 

 

 

о

 

 

X

та її частина, яка не закриваєть­

 

Мал. 176

ся раніше

виведеними лініями.

 

 

 

Якщо у деякій площині z = const

 

 

 

 

 

при деякому х одержується точка у, більша за всі попередні у, то дана точка видима, у протилежному випадку - невидима. Для визначення тих частин лінії у = f(x, z), які не закривають­ ся попередньо намальованими лініями, вводяться до розгляду дві лінії горизонту - верхня та нижня.

Визначимо поетапне виконання алгоритму плаваючого го­ ризонту.

На першому кроці виконання алгоритму лінії горизонту не розглядаються, оскільки перший розріз поверхні для z1 розміщений ближче до спостерігача, ніж інші, нічим не закри­ вається і тому він виводиться повністю. На цьому самому кроці визначаються перші значення ліній горизонту, які будуть ви­ користані на наступному кроці: для кожного значення х визна­ чається максимальне та мінімальне значення у.

Друга лінія теж повністю виводиться, а лінії горизонту ко­ регуються так: нижня лінія горизонту в усіх своїх точках х дорівнює мінімуму серед значень у для двох уже виведених ліній, а верхня лінія - максимуму.

Розглянемо область екрана між верхньою та нижньою лінією горизонту - вона є проекцією частини графіка функції

у = f(x, z) у смузі z1<z < z2. Для інших ліній у = f(x, z) при і > 2

ті частини ліній, які при проектуванні потрапляють в область між двома лініями горизонту, стають невидимими. Кожна нас­ тупна лінія буде виводитися лише для тих значень х, для яких її проекція лежить поза межами області, що задається двома лініями горизонту.

Роботу цього алгоритму на конкретному прикладі можна на­ очно пояснити так. Нехай необхідно зобразити панораму па­ горбів, що розміщені один за одним. Якщо на передньому плані знаходитиметься найвищий пагорб, то визначене на цьому кроці максимальне і мінімальне значення ліній горизонту буде залишатися і на наступних кроках найбільшим, а тому на ек­ рані монітора за першим пагорбом сховаються всі решта. Якщо

313

ж пагорби будуть упорядковані за зростанням їх висоти, тобто на першому плані знаходитиметься найнижчий з них, потім наступний за висотою і т. д., а останнім - найвищий, то на кож­ ному кроці виконання алгоритму значення максимальної та мінімальної ліній горизонту будуть корегуватися - максималь­ на збільшуватиметься, а мінімальна зменшуватиметься. Та­ ким чином, у результаті на екрані монітора можна буде побачи­ ти, як за кожним із пагорбів виглядає наступний.

Таким чином, тепер алгоритм виглядає так: якщо при деяко­ му значенні х значення у на поточній кривій більше за відповідне значення з верхнього горизонту або менше за зна­ чення нижнього горизонту, то точка у видима, у протилежно­ му випадку - невидима.

Пояснимо математично основні моменти, на яких базується описаний алгоритм. Нехай проекцією лінії у = f(x, zt) на кар­ тинну площину є лінія у = yt(x), де (х; у) - координати точки на картинній площині. Тоді контурні лінії у™"* (х) і у™п (х) визнача­ ються такими співвідношеннями:

уГх(х)=тахуі(х), у™п(х)= тіп Уі(х).

На екран виводяться тільки ті частини лінії у = yh{x), які знаходяться вище від лінії у™ах(х) або нижче від лінії у™т(х).

Є різні способи представлення ліній горизонту, але однією з найпростіших і найефективніших реалізацій цього методу є ре­ алізація, при якій кожна лінія горизонту задається набором значень з кроком 1 піксель, тобто для кожного цілого значення змінної х (хтіп < х < хтах) обчислюються відповідні значення

уГ(х)іуГ(х).

Перейдемо до представлення алгоритму, що реалізує метод плаваючого горизонту, мовою програмування.

Для зручнішого оперування значеннями ліній горизонту введемо масиви h_max[x] та h_min[x], елементами яких будуть відповідно поточні максимальне та мінімальне значення для кожного х.

За основу тієї частини алгоритму, яка визначає екранні ко­ ординати видимої точки поверхні, візьмемо розглянутий вище алгоритм Брезенхема для відображення відрізка прямої. Однак при цьому врахуємо, що координати кінців цих відрізків

(Xj;

г/х) та (х2; у2) по осі абсцис відрізняються на 1 (х2

- х1 = 1), а

відповідні значення

ух та у2 обчислюються за формулами:

у1 =

f(zt, хг), у2 = f(zt,

х2).

 

Окрім цього, слід звернути увагу на те, що суттєвим фактором для визначення видимих точок поверхні є значення кутового

коефіцієнта k = — -. Якщо воно менше від 1, то із збільшенням

2 _ * 1

314

значення х збільшуватиметься і

 

 

 

 

 

 

 

 

 

 

значення у, а це означає, що

 

~щ~щ

 

 

 

 

•__•

максимальне значення лінії го­

•

• •

_•

 

 

•

ризонту для кожного х буде ви­

 

 

 

 

 

 

 

 

•

•

•

 

• •

значене коректно (мал. 177, а).

 

 

 

 

 

 

 

 

 

 

А от у разі вертикального розта-

,.

 

 

0,

 

 

 

 

шування точок (мал. 177, б), се-

 

 

 

Мал. 177

 

 

 

 

 

 

ред яких усі є видимими, може

 

 

 

 

 

 

 

 

 

 

статися так, що першою буде розглянута точка з більшим зна­ ченням у і саме воно стане поточним значенням верхньої лінії горизонту для точки Ї. А це означатиме для алгоритму, що решта точок цієї вертикалі є невидимими, що суперечить ре­ альності.

Тому у реалізації алгоритму присутні дві окремі процедури, які передбачають розгляд двох варіантів значень кутового ко­ ефіцієнта k.

Можна запропонувати такий варіант основної частини про­ грами:

for Z := z1 to z2 do

{Цикл побудови перерізів заданої поверхні по осі Oz.)

for X := x m i n to x m a x - 1 do

{Перегляд усіх значень x з кроком 1.}

begin

 

 

 

х1 := х; х2 := х + 1;

{Початкові значення кінців відрізка у поточному перерізі.}

у1 : = f ( z , x 1 ) ; y 2 : = f ( z , x 2 ) ;

 

 

n := abs(x2 - х1); m := abs(y2 - у1);

{Ініціалізація початкових значень}

sx := sign(x2 - х1); sy := sign(y2 - у1);

{для побудови відрізка}

х_р := х 1 ; у_р := у 1 ; s := 0; є := 0;

{за алгоритмом Брезенхема.}

{Визначення процедури залежно від значення кутового коефіцієнта.}

if m < n then k_less_1 else k_more_1

 

 

end;

 

 

 

Тепер розглянемо процедуру, що реалізує випадок к <

1:

procedure k_less_1;

 

 

 

begin

 

 

 

n2 := 2 * n; m2 := 2 * m;

{Ініціалізація початкових значень.}

while S < n - 1 do

{Цикл для побудови всіх точок поточної лінії.}

begin

{Лічильник точок, крок по осі Ох, обчислення відхилення.}

s := s + 1; х := х + sx; є := є + т 2 ;

 

 

{Якщо відхилення більше ніж 1, то зміщення по осі Оу і перерахунок}

if є > n then begin у := у + sy; є := є - n2 end;

{відхилення.}

if у < h_min[x]

{Якщо значення ординати поточної точки менше}

 

{від лінії нижнього горизонту, то виведення точки}

 

{і перевизначення значення лінії нижнього горизонту,}

then begin PutPixel(x, у, d ) ; h_min[x] := у end

{якщо значення ординати поточної точки більше від лінії} else if у > h_max[x] {верхнього горизонту, ТО}

{виведення точки і перевизначення значення лінії верхнього горизонту.}

then begin PutPixel(x, у, с2); h max[x] := у end;

end;

end;

315

Для вертикального розташування точок процедура може бу­ ти такою:

procedure k_more_1; begin

С := m; m := n; n := c;

 

{Ініціалізація початкових значень.}

n2 := 2 * n; m2 := 2 * m;

 

 

u := x; v := y; xO := x; yO := y;

 

 

while s < n - 1 do

{Цикл для побудови всіх точок поточної лінії.}

begin

 

{Лічильник точок, крок по осі Оу,}

s : = s + 1;v:=v + sy; є := є + m2;

{обчислення відхилення.}

{Якщо відхилення більше ніж 1, то зміщення по осі Оу і перерахунок}

if є > n then begin u := u + sx; є := є - n2 end;

{відхилення.}

 

{Якщо значення ординати поточної точки менше лінії}

if у < h_min[x]

 

{нижнього горизонту, то}

then begin

 

 

 

PutPixel(x, у, с1);

 

{виведення точки.}

if U <> х

{Перевизначення значення лінії нижнього горизонту.}

then

 

 

 

begin

 

 

 

if sy > 0 then h_min[xO] := yO else h_min[x] := y;

xO := u; yO := v

 

 

end

 

 

 

end

 

 

 

 

{Якщо значення ординати поточної точки більше лінії}

else if у > h_max[x]

{верхнього горизонту, то}

then

 

 

 

begin

 

 

 

PutPixel(x, у, с1);

 

{виведення точки.}

if U О х {Перевизначення значення лінії верхнього горизонту.} then

begin

if sy > 0 then h_max[xO] := yO else h_max[x] := y; xO:=u;yO:=v

end; end

else if u <> x then begin xO u; yO := vend x := u; у := v

end;

end;

Варто звернути увагу на деякі недоліки описаного методу плаваючого горизонту.

1.Може статися так, що при деякому значенні х значення у(х) невідоме. У такому разі можна запропонувати взяти у якості цього значення середнє між двома сусідніми значеннями.

2.Якщо функція задана малою кількістю точок і має досить гострі піки, то наведений алгоритм може дати некоректні ре­ зультати.

316

Источник: https://studfile.net/preview/14502490/