Скачиваний:
56
Добавлен:
30.05.2020
Размер:
2.41 Mб
Скачать

 

 

Лхл

y2)

 

 

 

(x;ja' /'

^< (

\

(*» yt) '(XjY)

(x';Y)

Хх^у~^\У\7(Xі; Y)

(Xv'yJ (x4;yj

 

(x6;ya) (x4;j/4)

 

(0;0)

x

(0; 0)

 

 

; Уі) (x6; VbhsA**! У*)

(*i; yd

(X';Y)

(X;Y) (х6в) (*»Уд

(0;0)

в)

Мал. 150

таким чином: перетинає вершину (хх; ух), повністю проходить стороною з вершинами (хх; г/х) і (х7; у7), дотикається до верши­ ни (х5; у5), перетинає вершину (х3; г/3). Як визначено вище, оз­ накою розміщення точки (X; Y) поза межами багатокутника є парна кількість зафіксованих перетинів його сторін. Як про­ аналізувати цю ситуацію у даному випадку? Пропонується та­ кий хід міркувань. Прохід побудованого відрізка через верши­ ну (хх; г/х) характеризує перетин зразу двох сторін багатокутни­ ка з вершинами (хх; ух), 2; у2) і х; ух), 7; у7). Фіксуємо по­ точний стан кількості перетинів 1. Оскільки сторона багатокут­ ника гі ух), 7; у7) вже врахована, навіть якщо, як у нашому випадку, по ній проходить побудований відрізок, то переходи­ мо до наступної критичної точки. Нею є вершина (х5; у5). Але в ній не відбувається явного перетину сторін, а лише дотик до вершини багатокутника. Оскільки нас цікавить перетин, тому логічно цей факт не враховувати. У вершині (х3; у3), як і на ма­ люнку 150, а, відбувається перетин двох сторін у їх спільній вершині, тому необхідно врахувати цей перетин, збільшивши їх загальну кількість на 1. Таким чином, підраховано 2 явних перетини сторін заданого багатокутника і можна зробити вис­ новок, що точка (X; Y) лежить поза його межами.

Розглянемо малюнок 150, в. Побудований відрізок двічі до­ тикається до вершин (х6; г/6), (х4; у4). Але оскільки дотики не враховуються, то кількість перетинів становитиме 0, а це озна­ чає, що точка (X; У) лежить зовні заданого багатокутника.

262

Можна зробити попередній підсумок:

-якщо відрізок з кінцями у точках (X; У), (х'; У) перетинає сторону багатокутника не у вершинах, що їй належать, то не­ обхідно враховувати один перетин;

-якщо відрізок з кінцями у точках (X; У), (х'; У) перетинає дві суміжні сторони багатокутника у їх спільній вершині, то необхідно враховувати один перетин;

-якщо відрізок з кінцями у точках (X; У), (х'; У) дотикаєть­ ся до спільної вершини двох суміжних сторін багатокутника, то перетин не враховується.

Цікавим є випадок, коли задана точка (X; У) збігається з вер­ шиною багатокутника (мал. 150, г). У такому випадку подаль­ ший перегляд сторін багатокутника беззмістовний, його можна припинити і дати позитивну відповідь щодо належності точки (X; У) заданому багатокутнику.

Перейдемо до формулювання алгоритму визначення поло­ ження точки (X; У) відносно заданого багатокутника. Але попе­ редньо введемо деякі домовленості щодо запису умов перетину відрізків. Для побудованого відрізка з кінцями у точках (X; У), (х'; у) завжди дивитимемося із додатково побудованої точки (х'; У) у задану точку (X; У). Розглядаючи сторони багатокут­

ника з кінцями у вершинах (х;; у.), (xt + 1; уі + j), дивитимемося із вершини (хг; yt) у вершину (х; + 1; у1 + г ). Для спрощення запи­ су виразів точки позначатимемо так: р, р', pv р2, • ••,рп-

Попередньо перераховано досить багато різних умов, які дають змогу дослідити цей факт. Спробуємо визначити їх пріоритетність, що дасть змогу скоротити кількість виконува­ них перевірок. Розглянемо деякий поточний крок, на якому досліджується можливий перетин відрізка з кінцями у точках р' ір та сторони багатокутника з вершинами у точках pt тарі + 1.

1. Оскільки відсоток сторін, з якими відбувається перетин побудованого відрізка, найчастіше значно менший, ніж тих, з якими такого перетину немає, то на першому місці повинно бу­ ти визначення можливості перетину. Таку інформацію дає пе­ ревірка умови перетину обмежуючих прямокутників зі сторо­ нами, паралельними осям координат, для досліджуваних відрізків. Для побудованого нами відрізка з кінцями у точках р' ір, що паралельний осі Ох, таким обмежувальним прямокут­ ником буде сам цей відрізок, а для сторони багатокутника з вершинами у точках pt т&рі + 1 лівою нижньою вершиною буде точка з координатами (х/; у/), правою верхньою - (х'і + 1; у'і + 1)-

На малюнку 151, а зображено випадок, коли одна зі сторін багатокутника ptpi +1 явно перетинає відрізок з кінцями у точках р' і р. Інший випадок, зображений на малюнку 151, б, є сумнівним щодо їх перетину: перетин обмежуючого прямокутника сторони рірі + j і відрізкадо' існує, однак перетину самих відрізків немає.

263

(х,і у)

(x'i+1; y'i+1)

(ХГ>УІ)

« » 5 УІ+і)

 

 

 

 

\№Л

 

(x1; Y)

(*.';»,')

 

(x';Y)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(xi+1; yi+l)

(x[; y[)

'•"-i+i! У1+1)

a)

 

 

6)

 

 

 

 

Мал. 151

 

 

 

 

Для запису умови можливого перетину відрізків з кінцями у точках р', р і pt, рі+1 необхідно врахувати такі дві обставини: відрізок з кінцями у точках р', р паралельний осі Ох; значення х' за побудовою більше від значення абсцис будь-яких вершин багатокутника. Отже, з урахуванням зазначених особливостей умова наявності можливого перетину виглядатиме так:

(х'і+і > = х ) a n d > = УD a n d (У'і+і >= У)-

2. На другому кроці у разі підозри на перетин поточної сто­ рони і побудованого відрізка необхідно перевірити одночасне виконання умов:

[(р -р') х (р. -р')\ • [(р-р') х 1+1 -р')] < 0; [(Рі+і -Pt) х W -РіУ\ {(Ріп ~РІ)Х(Р ~Рі)] < о.

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

зїх кінцями.

3.До третього кроку переходимо для перевірки можливого проходу побудованого відрізка через вершину багатокутника.

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

Перш ніж записати умову наявності проходу побудованого відрізка через вершину багатокутника, проаналізуємо, через

яку саме вершину -pt чир і + 1 - він пройде.

На кожному кроці виконання алгоритму розглядається по­

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

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

264

Отже, перетин відрізка з кінцями у точках р ір' з вершиною р.+1 поточної сторони багатокутника визначатиметься такими умовами:

[(Р - Р') х (РІ - Р')] ІІР ~ Р') х (Рі+1 - Р'П = 0; tiPi+l -РІ) х ІР' 'Рі)] • [(РІ+І ~РІ)Х(Р -Рі)] < 0.

Однак лишається відкритим питання, якого типу відбувся прохід через вершину - перетин чи дотик. Відповідь на нього можна отримати, перевіривши, як розміщені вершиниpt_t ipt+1 відносно прямої, що проведена через відрізок з кінцями у точ­ ках р' ір. Якщо вони знаходяться у різних півплощинах, то це є ознакою того, що має місце перетин у вершині рі і необхідно збільшити кількість перетинів на 1. Якщо вершини р1_1 і рі+1 знаходяться в одній півплощині, то це означає, що має місце дотик побудованого відрізка до вершини pt і при цьому кіль­ кість перетинів залишається незмінною.

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

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

[(Р - Р') х (РІ ~ Р')] • ІІР - Р') х і+і - Р')] < 0;

[(РІ+І ~РІ) х (Р'-Рі)][(РІ+І -РІ) х (Р-Рі)] = 0.

В іншому випадку не виключений збіг з вершиною багато­ кутника. У такому разі виконуватимуться умови:

[(Р - Р') х (pt - р')] • [(р - р') х і+1 - р')] = 0;

[(Рі+і -РІ) х (Р'-РІ)] [(РІ+І ~РІ)Х(Р -РІ)] = 0.

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

5. І наостанок слід зазначити: у разі невиконання всіх опи­ саних вище умов можна зробити висновок, що відрізок, утворе­ ний точкамир' ір, і поточна сторона багатокутника з вершина­ ми у точках рі ірі+1 не перетинаються. У такому разі, якщо ще не всі сторони багатокутника розглянуто, необхідно переходи­ ти до аналізу наступної сторони.

Тепер уже можна розглянути представлення описаного ал­

горитму у вигляді фрагмента Pascal-програми:

 

х_0 := х т а х + 1; у_0 := у_1; count := 0;

{Блок ініціалізації.}

і := 1; flag := false;

 

265

r e p e at

{Перегляд ребер заданого багатокутника.}

if і < П then

{Якщо не досягнуто останньої вершини, то визначення вершин}

begin

{охоплюючого прямокутника для поточного ребра.}

х_3 := тах(х[і], х[і + 1]);

у_2 := min(y[i], у[і + 1]); у_3 := тах(у[і], у[і + 1]);

end

 

else

{Визначення вершин охоплюючого прямокутника для ребра}

begin

{з останньою вершиною багатокутника.}

х_3 := тах(х[і], х[1]);

у_2 := тіп(у[і], у[1]); у_3 := тах(у[і], у[1]);

end;

{Якщо охоплюючі прямокутники перетинаються,}

if (х_3 >= х_1) and (у_1 >= у_2) and (у_3 >= у_1)

then

{то визначення параметрів для умови перетину відрізків:}

begin

 

р_0_12 := (х_1 - х_0) * (у[і - у_0) - (х[і] - х_0) * (у_1 - у_0);

if і < п

 

then

{якщо не досягнута остання вершина багатокутника;}

begin

р_0_13 ; (x_1 - x_0) * (y[i + 1 ] - y_0) - (x[i + 1 ] - x_0) * (y_1 - y_0);

р_2_30

:

(x[i +

1] - x[i]) * (y_0 - y[i]) - (x_0 - x[i])

*

(y[i +

1]

- y[i]);

р_2_31

:

(x[i +

1 ] - x[i]) * (y_i - y[i]) - (x_1 - x[i]) *

(y[i +

1 ]

- y[i]);

end

 

 

 

 

 

 

 

 

else

 

 

{якщо досягнута остання вершина багатокутника.}

begin

 

 

 

 

 

 

 

 

Р_0_13

= (х_1

- х_0)

(У[1] - У_0) - (х[1] - х_0) * (у_1

- у_0);

Р_2_30

= (х[1] - х[і])

(У_0 - у[і]) - (х_0 - х[і]) *

(у[1 ]

- у[і]);

Р_2_31

= (х[1] - х[і])

' ( у _ і - у [ і ] ) - ( х _ і - х [ і ] ) * ( у [ і ] - у [ і ] ) ;

end;

 

 

 

 

 

 

 

 

if (Р_0_12 * р_0_13 < 0) and (р_2_30 * р_2_31 < 0)

 

{Якщо відрізки}

then inc(count) {перетинаються в одній точці, то збільшити лічильник на 1,}

else

{у протилежному випадку}

begin

 

if І < П - 1

{обчислення параметрів ознаки для вершини: перетин чи дотик.}

then

 

begin

{Якщо не досягнуто останнього ребра багатокутника.}

а := (х[і] - х_1 )*(у_0 - у_1) - (у[і] - у_1 )*(х_0 - х_1);

b := (х[і + 2] - х_1 )*(у_0 - у_1) - (у[і + 2] - у_1 )*(х_0 - х_1);

end

 

else

{Якщо досягнуто останнього ребра багатокутника.}

begin

 

а:= (х[і] - х_1) * (у_0 - у_1) - (у[і] - у_1) * (х_0 - х_1);

Ь:= (х[1] - х_1) * (у_0 - у_1) - (у[1] - у_1) * (х_0 - х_1); end;

{Якщо є перетин,} if (р_0_12 * р_0_13 = 0) and (р_2_30 * р_2_31 < 0) and (а * b < 0)

then inc(count)

{то збільшити лічильник на 1,}

 

{інакше якщо точка збігається з вершиною,}

else if (р_0_12 * р_0_13 <= 0) and (р_2_30 * р_2_31=

0)

then flag := true;

{то завершення

пошуку.}

end;

end;

266

I inc(i)

{Перехід до наступної вершини багатокутника.}

until flag or (і = n);

 

if flag or Odd(count) {Точка належить багатокутнику, коли вона збігається з однією}

then writeln(f_OUt, 'Yes') {із вершин або кількість перетинів ребер непарна.}

else writeln(f_out,'No');

Оскільки для визначення положення точки відносно задано­ го n-кутника необхідно порахувати кількість перетинів побудо­ ваного горизонтального відрізка з його сторонами, то оцінка ефективності роботи такого алгоритму буде лінійною і станови­ тиме О(га).

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

Щодо вигляду самого багатокутника, то обов'язковим є не тільки задання багатокутників як з невеликою кількістю вер­ шин, наприклад до 10, так і з достатньо великою, наприклад близько 100.

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

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

Побудова опуклої оболонки

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

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

267

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

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

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

Це далеко не кращий алгоритм щодо часу його виконання. Його можна визначити як повноперебірний. Оцінку ефектив­ ності цього алгоритму можна визначити так. На кроці побудо­ ви прямих для визначених пар точок оцінка ефективності ста­ новить 0(п2). Однак для кожної такої прямої необхідно пере­ глянути решту точок для визначення їхнього розміщення на площині відносно цієї прямої, що становить 0(гі). Таким чи­ ном, загальна оцінка запропонованого алгоритму буде 0(п3).

Далі розглянемо більш ефективні методи розв'язання побу­ дови опуклої оболонки.

Метод додавання точок

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

 

Розглянемо фрагмент побудови

 

деякої опуклої оболонки для 4-х то­

 

чок (мал. 153). Зручно розглядати

А ..

ці точки у певній послідовності.

Р*

Зрозуміло, що крайня зліва точка,

Мал 153

Щ0 м а є найменше значення по осі

 

абсцис, увійде до опуклої оболонки.

Саме тому почнемо перегляд з неї. Далі розглядатимемо точки у порядку зростання значень їх абсцис. Саме за цією ознакою на малюнку 153 визначена послідовність точок р^,р2^Р^Рі'

Якщо переглядати точки згідно з послідовністю їх задання, то спочатку будуть з'єднані точки р1 ір2, потім р2 ір3, і наоста-

268

нокрд» РІ- Отримана ламана не буде опуклою оболонкою, у ній зайвими є два відрізки, позначені на малюнку 153 пунктиром. Вірною побудовою буде з'єднання відрізками точок рх, р3, р4 . Як визначити коректність побудови цієї ламаної? Із точки р1 спостерігатимемо за переміщенням із точки р2 у точку р3. При цьому буде виконано лівий поворот, тобто поворот проти годин­ никової стрілки. Запам'ятаємо цей факт.

Далі перейдемо у точку р2 і з неї спостерігатимемо за пе­ реміщенням із точки р3 у точку р4. Тепер буде здійснено правий поворот, тобто поворот за годинниковою стрілкою. Отже, пору­ шена ознака незмінного повороту при обході опуклою оболон­ кою: оскільки ми виконуємо обхід за годинниковою стрілкою, то повинні весь час робити правий поворот. Якщо вилучити із перегляду точку р2, то, спостерігаючи із точкир1 за переміщен­ ням із точки р3 У точку j?4, зафіксуємо правий поворот.

Розглянемо технічні моменти запропонованого алгоритму, а саме як формувати послідовність точок, що утворюють опуклу оболонку, та як вилучати із неї ті точки, які виявилися зайвими.

Найпростіше усі точки поточного стану опуклої оболонки запи­ сувати у стек. Першим елементом стеку завжди буде точкар1 упо­ рядкованої послідовності всіх заданих точок. На і-му кроці з точ­ ки рі дивитимемося у точки рі+1 і рі+2. Якщо матиме місце вираз

(Рі+і ~ РІ) * (Р/+2 - Рд = (ХІ+І - ХІЩ+І - У І) ~ (ХІ+2 - *ЩІг ~ У І) % °» т о

це означатиме, що виконано правий поворот проти годинни­ кової стрілки і точка рі + 1є претендентом на вершину опуклої оболонки та повинна бути занесена до вершини стеку.

А як бути у протилежному ви­ падку, якщо точка рі+1 до стеку не заноситься? Розглянемо малюнок 154. На перших двох кроках у стек буде занесено точки рх, р2, р3. Для точки р4 умова належності опуклій оболонці не виконується, і вона не потрапляє до стеку.

Але з малюнка 154 видно, що і точки р2, р3 також необхідно виключити. Для цього треба

дослідити верхній елемент стеку, у нашому випадку це точкар3 . Якщо і для пари точок р3 ірь не виконується необхідна умова, то стек зменшується на один елемент шляхом виключення з нього точки, що знаходиться у його вершині, тобто р3. Така послідовність дій продовжується до тих пір, поки не знайдеться у вершині стеку точка, для якої разом із точкою рь необхідна умова виконається. Тоді точка р5 занесеться у стек і для нашого прикладу поточний вміст стеку буде таким: pvp5. До речі, відки­ нуті точки р2, р3, р4 будуть брати участь у наступному перегляді, коли будуватиметься нижня частина опуклої оболонки.

269

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

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

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

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

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

випадку матимемо одну під множину точок порожню, а до дру­ гої будуть віднесені решта точок (мал. 155). Але й у цьому разі всі точки переглядатимуться лише по одному разу.

Таким чином, можна сформулювати основні етапи алгорит­ му побудови опуклої оболонки методом додавання точок.

1.Упорядкувати всі задані точки за зростанням значень їх абсцис х., зберігши у масиві mast їх початкову нумерацію.

2.Розбити всі точки з номерами від mas2 до masn_1 на дві підмножини, визначивши цей факт перевіркою умови: якщо

(Хі ~ Хта8)(Утаа„ ~ У mas) " U/l ~ Утае)(Хтав„ " Xmas) < 0, ДЄ і = maS2,

270

mas3, ..., masn_x, то такі точки належать до однієї підмножини, у протилежному випадку - до іншої. Відповідні підмножини можуть утворювати два масиви з номерами вершин у порядку зростання їх абсцис. Одночасно необхідно дізнатися, яка з підмножин точок знаходиться над прямою, а яка - під нею. Для цього треба визначити, у яку підмножину потрапить точка з максимальним значенням ординати. Саме з цієї підмножини точок починається побудова опуклої оболонки.

3.Занести у стек порядковий номер першої точки верхньої упорядкованої під послідовності, що відповідає верхній під мно­ жині точок.

4.Якщо не досягнуто останньої точки верхньої підмножини точок, то визначити напрям повороту для наступних двох то­ чок цієї під послідовності. У протилежному випадку перейти до п. 7.

5.Якщо поворот правий, то занести номер нової точки опук­ лої оболонки до стеку і перейти до п. 4.

6.У протилежному випадку зменшити значення вершини стеку на 1 і перейти до п. 4.

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

Наведемо фрагмент основної частини програми, що реалізує описаний алгоритм.

SOrt(1, п);

{Упорядкування точок за зростанням значень абсцис.}

w := 1; V := 1;

{Розбиття множини точок на дві підмножини.}

Р 1 [ 1 ] : = р [ 1 ] ; р 2 [ 1 ] : = р [ 1 ] ; х1[1]:=х[1];х2[1]:=х[1];

у1[1]:=у[1];у2[1]:=у[1]; for і := 2 to п - 1 do

begin

if (х[і] - х[1]) * (у[п] - у[1]) - (у[і] - у[1]) * (х[Щ - х[1]) <= 0 then begin inc(w); p1[w] := p[i]; x1[w] :=x[i]; y1[w] :=y[i] end else begin inc(v); p2[v] := p[i]; x2[v] := x[i]; y2[v] := y[i] end;

end;

 

inc(w); inc(v);

{Дописування до двох множин крайньої справа точки.}

р1 [w] := p[n]; х1 [w] := x[n]; у1 [w] := у[п]; p2[v] := p[n]; x2[v] := x[n]; y2[v] := у[п];

Х_0

:= х[1]; у_0 := у[1];

{Обчислення параметрів для визначення}

х_1

:= х1 [2]; у_1 := у1 [2];

{«верхньої» і «нижньої» підмножини.}

х_2:=х2[2];у_2:=у2[2];

 

 

{Визначення положення підмножин відносно прямої,}

 

 

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

if (х_1 - х_0) * (у_2 - у_0) - (х_2 - х_0) * (у_1 - у_0) <= 0

then for і := 1 to (v div 2) do

{Упорядкування за спаданням точок,}

271