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.

Podobne dokumenty