litera p
Transkrypt
litera p
Temat: Geometria obliczeniowa 1. Oznaczenia Punkty - małe litery: p, q, r, s, itd. Współrzędne punktu p na płaszczyźnie - (x(p), y(p)) Odcinek o początku i końcu odpowiednio w punktach p i q: p - q Wektor o początku i końcu odpowiednio w punktach p i q: p → q Prosta zawierająca punkty p i q: pq Półprosta zaczynająca się w punkcie p i zawierająca punkt q: .pq 2. Operacje elementarne Operacje arytmetyczne: dodawanie, odejmowanie, mnożenie, dzielenie 3. Założenia i uwagi • rozważane są obiekty geometryczne na płaszczyźnie w kartezjańskim układzie współrzędnych • algorytmy powinny realizować jak najmniej operacji powodujących przybliżenia 4. Podstawowe algorytmy geometryczne a) Algorytm sprawdzania, po której stronie prostej leży punkt WP: Trzy punkty: p = (x, y), q = (z, t), r = (u, v) WK: Odpowiedź na pytanie: Po której stronie prostej pq leży punkt r r ϕ q p Punkt r leży po lewej stronie prostej pq p q ϕ r Punkt r leży po prawej stronie prostej pq q p ϕ Punkty p, q i r są współliniowe r Algorytm Obliczamy wartość wyznacznika det( p, q, r ) , którego znak jest równy znakowi sinusa kąta nachylenia wektora p → r do wektora p → q . x det ( p, q, r ) = z u y 1 t 1 v 1 • Jeżeli det( p , q, r ) > 0 to sin ϕ > 0 i wówczas punkt r leży po lewej stronie prostej pq. • Jeżeli det( p , q, r ) < 0 to sin ϕ < 0 i wówczas punkt r leży po prawej stronie prostej pq. • Jeżeli det( p , q, r ) = 0 to sin ϕ = 0 i wówczas punkty p, q i r są współliniowe. b) Algorytm sprawdzania, czy dwa dane punkty leżą po tej samej stronie prostej WP: Cztery punkty: p = (x, y), q = (z, t), a = (d, c), b = (e, f ) WK: Odpowiedź na pytanie , czy punkty a i b leżą po tej samej stronie prostej pq. p a b q Algorytm Przypomnijmy funkcję znaku liczby: 1 gdy x > 0 sgn (x ) = 0 gdy x = 0 − 1 gdy x < 0 Punkty a i b leżą po tej samej stronie prostej pq wówczas, gdy: sgn(det( p, q, a )) = sgn(det( p, q, b )) c) Algorytm sprawdzania, czy punkt należy do odcinka WP: Trzy punkty: p = (x, y), q = (z, t), r = (u, v) WK: Odpowiedź na pytanie, czy punkt r należy do odcinka p - q. Y q r p 0 X Algorytm Jeżeli punkt r należy do odcinka p-q, to rzuty prostokątne r na osie (OX i OY) "zawierają się" w rzutach prostokątnych odcinka p-q. Wynika stąd, że r należy do odcinka p-q wtedy i tylko wtedy gdy: (x( p ) ≤ x(r ) ≤ x(q ) ∨ y ( p ) ≤ y (r ) ≤ y (q )) ∧ sgn (det ( p, q, r )) = 0 d) Algorytm sprawdzania, czy dwa odcinki się przecinają WP: Cztery punkty: p = (x, y), q = (z, t), a = (b, c), d = (e, f ) wyznaczające dwa odcinki: p-q i a-d. WK: Odpowiedź na pytanie , czy odcinki p-q i a-d przecinają się. a p a p d d q q Algorytm Rozwiązanie opiera się na spostrzeżeniu, że dwa odcinki przecinają się wtedy i tylko wtedy, gdy punkty p i q leżą po przeciwnych stronach prostej ad i punkty a i d leżą po przeciwnych stronach prostej pq lub któryś z końców jednego z odcinków należy do drugiego. Czyli: sgn(det( p, q, a)) ≠ sgn(det( p, q, d )) ∧ sgn(det(a, d, p)) ≠ sgn(det(a, d, q)) ∨ (sgn(det( p, q, a)) = 0 (sgn(det( p, q, d )) = 0 (sgn(det(a, d, p)) = 0 (sgn(det(a, d, q)) = 0 ∧ (x( p) ≤ x(a) ≤ x(q) ∨ y( p) ≤ y(a) ≤ y(q))) ∨ ∧ (x( p) ≤ x(d ) ≤ x(q) ∨ y( p) ≤ y(d ) ≤ y(q))) ∨ ∧ (x(a) ≤ x( p) ≤ x(d ) ∨ y(a) ≤ y( p) ≤ y(d ))) ∨ ∧ (x(a) ≤ x(q) ≤ x(d ) ∨ y(a) ≤ y(q) ≤ y(d ))) 5. Problem przynależności punktu do wielokąta WP: Dany jest ciąg punktów: w0 , w1 ,..., wn −1 określający n wierzchołkowy wielokąt W i taki, że dla każdego i = 0,1,..., n − 1 odcinek wi − wi +1 jest bokiem wielokąta W (i+1 jest wyliczane modulo n). Dany jest również punkt p. WK: Odpowiedź na pytanie, czy punkt p należy do wielokąta W. Jeżeli punkt p leży na boku wielokąta, to stwierdzamy, że należy do wielokąta a) Przypadek wielokąta wypukłego - algorytm realizowany techniką dziel i zwyciężaj Algorytm (opis) Załóżmy, że W ma więcej niż trzy wierzchołki. Prowadzimy przekątną łączącą w0 z w(n-1)/2. Są trzy możliwości. 1) Punkt p leży na prostej w0 - w(n-1)/2. W tym przypadku łatwo stwierdzić, czy p należy do odcinka w0 - w(n-1)/2, czy leży poza nim. 2) Punkt p leży po lewej stronie prostej w0 - w(n-1)/2. Należy sprawdzić rekurencyjnie, czy p leży wewnątrz wielokąta o wierzchołkach w0, w2, ..., w(n-1)/2. 3) Punkt p leży po prawej stronie prostej w0 - w(n-1)/2. Należy sprawdzić rekurencyjnie, czy x leży wewnątrz wielokąta o wierzchołkach w0, w(n-1)/2, w(n-1)/2+1, ..., wn-1. w0 p w5 w1 w4 w2 w3 Rozmiar zadania: n – liczba wierzchołków wielokąta W Operacja elementarna: - operacja sprawdzania, po której stronie prostej leży punkt, - operacja sprawdzania, czy punkt leży wewnątrz trójkąta, - operacja sprawdzania, czy punkt należy do odcinka 1 dla n ≤ 3 n T max (n ) = T + 2 dla n > 3 max 2 k Przyjmijmy, że n jest potęgą dwójki, czyli n = 2 , dla pewnego k. ( ) T max (n ) = T max 2 k −1 + 2 = ( ) = T max 2 k − 2 + 2 + 2 = ... = = 1 + 21+42 2 + ... + 2 = 2 ( k − 1) + 1 = 2 (log 2 n − 1) + 1 43 k −1 = Θ (log 2 n ) b) Przypadek dowolnego wielokąta Algorytm rozwiązujący problem przynależności w tym przypadku opiera się na zależności pomiędzy liczbą przecięć dowolnej półprostej o początku w punkcie p, a bokami wielokąta. p l Punkt p należy do wielokąta W wtedy i tylko wtedy, gdy półprosta .pl przecina boki wielokąta nieparzystą ilość razy. Zachodzą przy tym dwa przypadki szczególne: • Półprosta .pl przechodzi przez wierzchołek wielokąta. • Półprosta .pl zawiera bok wielokąta. Uwaga !!! Zanim zostanie zrealizowany krok algorytmu polegający na wyznaczeniu liczby przecięć półprostej .pl z bokami wielokąta, należy sprawdzić, czy punkt p nie zawiera się w którymś z boków wielokąta. Możemy to sprawdzić stosując algorytm c) z algorytmów podstawowych. y yx x p yx c v d b l c b v d yx • Prosta pl zawiera bok b wielokąta. Niech c i d będą bokami sąsiadującymi z b, a x i y ich końcami nie należącymi do b. Jeżeli punkty x i y leżą po przeciwnych stronach prostej pl, to przyjmujemy, że liczba punktów przecięcia pl z bokami b, c i d wynosi 1. W przeciwnym razie przyjmujemy, że liczba ta wynosi 0. • Prosta pl przecina brzeg w wierzchołku v i nie zawiera żadnego z boków z nimi sąsiadujących. Niech b i c będą tymi, a x i y ich końcami różnymi od v. Jeżeli x i y leżą po przeciwnych stronach prostej pl, to przyjmujemy, że liczba punktów przecięcia z bokami b i c wynosi 1. W przeciwnym razie przyjmujemy, że liczba ta wynosi zero. Ponieważ koszt obliczeń związanych z każdym bokiem i wierzchołkami n - kąta jest stały, złożoność sprawdzenia, czy punkt leży w jego wnętrzu, jest O(n). 6. Otoczka wypukła Otoczką wypukłą dowolnego niepustego zbioru punktów S nazywamy najmniejszy zbiór wypukły zawierający S. Można udowodnić, że jeśli S jest zbiorem skończonym, to jego otoczka wypukła jest wielokątem wypukłym o wierzchołkach ze zbioru S (czasami zredukowanym do odcinka lub punktu). WP: Skończony zbiór punktów S = {p1 , p 2 ,..., p n }. WK: Ciąg punktów W : po1 , po 2 ,..., pow taki, że p oi ∈ S (dla każdego i = 1, 2, ..., w), wyznaczający wierzchołki najmniejszego wielokąta wypukłego zawierającego wszystkie punkty z S. Kolejność punktów w ciągu W określa kolejność wierzchołków na obwodzie wielokąta w kierunku przeciwnym do ruchu wskazówek zegara. po2= p6 po3= p9 po1= p2 p3 po4= p1 p7 po7 = p10 p5 po5 = p8 po6 = p4 a) Algorytm naiwny Algorytm naiwny wyznaczania otoczki wypukłej opiera się na następującym spostrzeżeniu (*): Punkt p nie jest punktem otoczki wypukłej zbioru S wtedy i tylko wtedy, gdy leży wewnątrz pewnego trójkąta o wierzchołkach z S, różnych od p, lub należy do odcinka łączącego dwa punkty z S, różne od p. po2= p6 po3= p9 po4= p1 po1= p2 p3 p7 po7 = p10 p5 po5 = p8 po6 = p4 Punkt p3 nie należy do otoczki wypukłej ponieważ leży wewnątrz trójkąta p9 p1 p4. Punkt p5 nie należy do otoczki wypukłej ponieważ należy do odcinka p6 - p8 . Algorytm naiwny Krok 1: Sprawdzić, które punkty ze zbioru S należą do otoczki wypukłej stosując kryterium określonym w spostrzeżeniu (*). Krok 2: Uporządkować znalezione punkty w kolejności ich występowania na obwodzie otoczki wypukłej. Koszt czasowy algorytmu naiwnego Rozmiar zadania: n = S - liczba punktów zbioru S. Operacja elementarna: - operacja sprawdzania, czy punkt należy do trójkąta (odcinka) w Kroku 1, - operacja porównania wykonana w trakcie sortowania w Kroku 2. Koszt czasowy Kroku 1: Dla n punktów trzeba sprawdzić co n najwyżej 3 różnych trójkątów. Stąd koszt Kroku 1 jest 4 O(n ). Koszt czasowy Kroku 2: Jeżeli zastosujemy optymalną metodę sortowania to koszt czasowy Kroku 2 jest O(nlogn). Całkowity koszt czasowy algorytmu naiwnego jest więc rzędu O(n4). Efektywne algorytmy rozwiązujące problem otoczki wypukłej, algorytm Grahama i Jarvisa, mają zasadniczo niższy koszt. Sortowanie zbioru punktów w celu wyznaczenia kolejności punktów otoczki po obwodzie wielokąta WP: Zbiór P = {p1 , p2 ,..., pn } - punktów będących wierzchołkami wielokąta wypukłego W. WK: Posortowany ciąg punktów zbioru P według niemalejącej wartości kąta nachylenia ich wektorów wodzących do osi OX. p6 p3 p2 p1 O p5 X p4 Algorytm 1. Wyznaczamy centroid wielokąta W. Jest to punkt o współrzędnych: (x( p1 ) + x( p 2 ) + ... + x( p n )) ( y ( p1 ) + y ( p 2 ) + ... + y ( p n )) , n n Bez straty ogólności możemy przyjąć, że środek układu współrzędnych znajduje się w centroidzie wielokąta W. 2. W celu porównania kątów nachylenia wektorów wodzących sortowanych punktów do osi OX obliczamy wartości następującej funkcji alfa, określonej dla wszystkich punktów płaszczyzny różnych od punktu O. y( p ) d ( p) , 2 - y( p ) , d ( p ) alfa( p ) = y( p ) 2 + , d ( p) y( p ) , 4 d ( p) gdy x( p ) ≥ 0 ∧ y ( p ) ≥ 0 gdy x( p ) ≤ 0 ∧ y ( p ) ≥ 0 gdy x( p ) ≤ 0 ∧ y ( p ) ≤ 0 gdy x( p ) ≥ 0 ∧ y ( p ) < 0 gdzie d ( p ) = x( p ) + y( p ) . Można udowodnić, że kąt nachylenia wektora wodzącego punktu pi jest mniejszy równy od kąta nachylenia wektora wodzącego punktu pj wtedy i tylko wtedy, gdy: alfa ( pi ) ≤ alfa ( p j ) . Funkcja alfa umożliwia wyznaczenie kolejności wierzchołków na obwodzie wielokąta wypukłego w czasie O(nlogn). b) Algorytm Grahama Algorytm Grahama opiera się na następującym spostrzeżeniu (**): Każdy punkt nie będący wierzchołkiem otoczki wypukłej musi należeć do wnętrza trójkąta o wierzchołkach: O i pewne dwa kolejne wierzchołki otoczki (lub leży na jednym z boków takiego trójkąta). p3 p2 p6 p1 O p4 s=p5 X p7 Punkt p6 nie należy do otoczki ponieważ leży we wnętrzu trójkąta O p1 p3 . Punkt p4 nie należy do otoczki ponieważ punkt ten leży na boku trójkąta O p7 p1 . Algorytm Krok 1: Wybieramy dowolny punkt O leżący wewnątrz otoczki wypukłej, na przykład centroid. Umieszczamy w nim środek układu współrzędnych i obliczamy współrzędne punktów wejściowych w nowym układzie współrzędnych. Krok 2: Porządkujemy punkty p1, p2, ... , pn leksykograficznie względem współrzędnych biegunowych (α i , ri ) , gdzie α i jest kątem nachylenia wektora wodzącego O → pi do osi OX, a ri jego długością. (Aby nie liczyć pierwiastków, w sortowaniu 2 porównujemy alfa ( p i ) zamiast α i oraz ri zamiast ri ). Z uporządkowanych punktów tworzymy dwukierunkową listę cykliczną, w której dla każdego punktu p, next(p) jest następnym (cyklicznie) punktem w wyżej zdefiniowanym porządku, a pred(p) poprzednim. Spośród punktów o najmniejszej współrzędnej y ustalamy punkt s z najmniejszą współrzędną x. Krok 3: Przeglądamy punkty na liście, usuwając te, które nie są wierzchołkami otoczki wypukłej. Po zakończeniu działania algorytmu lista będzie zawierała tylko wierzchołki otoczki wypukłej w kolejności ich występowania na obwodzie. Listę przeglądamy, zaczynając od punktu s i kierując się w stronę przeciwną do ruchu wskazówek zegara ( zgodnie ze wskaźnikiem next). W celu wyeliminowania zbędnych punktów zawsze sprawdzamy trzy kolejne punkty q1 , q 2 i q3 z bieżącej listy. Jeśli punkt q2 leży wewnątrz trójkąta Oq1q3 to usuwamy go z otoczki i przechodzimy do sprawdzania punktów q0 , q1 , q3 . W przeciwnym razie kolejną badaną trójką punktów są q2 , q3 , q4 . Przeglądanie kończymy z chwilą osiągnięcia wierzchołka startowego s. Algorytm realizujący Krok 3 można zapisać następująco: q:=s; while next(q) <> s do if next(q) leży wewnątrz trójkąta O q next(next(q)) then begin next(q):=next(next(q); pred(next(q)):=q; if q <> s then q:=pred(q); { usunięcie punktu next(q) z listy } end else q:=next(q); q3 q4 q2 q1 O q6 q5 = s X q7 Koszt czasowy algorytmu Grahama Na złożoność algorytmu Grahama decydujący wpływ ma Krok 2. Kroki 1 i 2 wykonywane są w czasie liniowym. Krok 2 można zrealizowany w czasie O(nlogn), stosując efektywną metodę sortowania (np. sortowanie przez scalanie, sortowanie przez połówkowe wstawianie czy sortowanie szybkie). Łatwo zauważyć, że zamiast sprawdzać, czy punkt next(q) leży wewnątrz trójkąta O q next(next(q)) można testować, czy next(q) leży po lewej stronie (lub należy do) wektora q → next(next(q )) . Złożoność algorytmu Grahama nie zależy od liczby punktów otoczki wypukłej. Następny algorytm rozwiązujący problem otoczki, algorytm Jarvisa, ma złożoność O(kn), gdzie k jest liczbą punktów otoczki wypukłej w danym n elementowym zbiorze punktów.