ALGORYTMY GEOMETRYCZNE
ZNAJDOWNIE OTOCZKI WYPUKŁEJ ZBIORU PUNKTÓW NA PŁASZCZYŹNIE
DANE : Q = {p1,...,pn }, n3 , pi R2 - zbiór punktów na płaszczyźnie WYNIK : Otoczka wypukła zbioru Q. DEF. Otoczką wypukłą zbioru punktów Q na płaszczyźnie nazywamy najmniejszy zbiór wypukły na płaszczyźnie zawierający Q. FAKT. Jeśli |Q| < 0 , to otoczką wypukłą zbioru Q jest najmniejszy wielokąt wypukły P , taki że każdy punkt ze zbioru Q leży albo na brzegu , albo w jego wnętrzu.
GRAHAM-SCAN (Q) { Q = {p1,...,pn}, n3 , jest danym zbiorem punktów na płaszczyźnie.} Algorytm wyznacza stos S zawierający wszystkie wierzchołki otoczki wypukłej CH(Q) uporządkowane przeciwnie do ruchu wskazówek zegara . Procedura korzysta z funkcji TOP(S) , której wartością jest element na szczycie stosu oraz NEXT-TO-TOP(S) , której wartością jest element poprzedzający wierzchołek stosu ; obie procedury nie modyfikują S }
begin Wyznacz punkt p0 = (x0, y0) , gdzie : y0 = min { yi : pi = (xi, yi) Q } x0 = min { xi : pi = (xi, y0) Q } ; Posortuj punkty ze zbioru Q – {p0} ze względu na współrzędną kątową w biegunowym układzie współrzędnych o środku w p0 przeciwnie do ruchu wskazówek zegara; jeśli więcej niż jeden punkt ma taką samą współrzędną kątową, usuń wszystkie z wyjątkiem punktu położonego najdalej od p0. Oznacz otrzymany zbiór : Q’ = { p0, p1, ... , pm };
T(n) = O(nlgn) Utwórz stos pusty S; PUSH (p0,S); PUSH (p1,S); PUSH (p2,S); { punkty p0, p1, p2 są na stosie S } for i := 3 to m do begin while (przejście od NEXT-TO-TOP(S) przez TOP(S) do pi nie oznacza skrętu w lewo w TOP(S) ) do POP(S); PUSH( pi , S); end; return S; end ; T(n) = O(nlgn)
ALGORYTM TESTUJĄCY CZY W ZBIORZE ODCINKÓW NA PŁASZCZYŹNIE ISTNIEJE PARA ODCINKÓW PRZECINAJĄCYCH SIĘ
ANY-SEGMENTS_INTERSECT (S); { S jest skończonym zbiorem odcinków na płaszczyźnie S = { S1,... Sn } ; Si = [ kiL, kiP ] i = 1,...,n Zakładamy, że żaden odcinek nie jest prostopadły do osi Ox oraz żadne trzy różne odcinki nie przecinają się w jednym punkcie. Procedura sprawdza czy w S istnieje co najmniej jedna para odcinków przecinających się }
begin T := ; Utwórz listę LS posortowanych końców odcinków z S w kolejności od najmniejszej współrzędnej x do największej , w przypadku równych – najpierw punkt o mniejszej współrzędnej y; dla każdego zaznacz czy jest lewym czy prawym końcem odcinka;
for każdy punkt p z listy LS do begin if p jest lewym końcem odcinka s then INSERT (T,s); if (ABOVE (T,s) istnieje i przecina s ) or ( BELOW (T,s) istnieje i przecina s ) then return TRUE end; if p jest prawym końcem odcinka s then if oba odcinki (ABOVE (T,s ) and (BELOW (T,s)) istnieją and (ABOVE (T,s) przecina BELOW (T,s) ) then return TRUE; DELETE (T,s); return FALSE;
ZNAJDOWANIE NAJMNIEJ ODLEGŁEJ PARY PUNKTÓW W ZBIORZE PUNKTÓW NA PŁASZCZYŹNIE DANE : n N, n 2; Q = { p1, ... pn } : pi R2, pi = (xi, yi) 1 i n WYNIK : p, p' Q : ** (p,p') = min { d(p,q ) ;p,q P }
ZNAJDŹ-PARĘ-NAJMNIEJ-ODLEGŁYCH-PUNKTÓW( P,X,Y); { Algorytm stosuje metodę "dziel i zwyciężaj" Każde wywołanie rekurencyjne algorytmu otrzymuje jako dane wejściowe : P Q tablicę X zawierającą punkty ze zbioru P posortowane według współrzędnej x. tablicę Y zawierającą punkty ze zbioru P posortowane według współrzędnej y. } (1) Sprawdzamy czy |P| 3 TAK : wyznacz = min {d(p,q), p,q P } porównując odległości wszystkich par punktów w P; niech p, q : d(p, q ) = NIE : DZIEL (2)
(2) DZIEL Podziel P na dwa "równoliczne" podzbiory PL, PR tzn .: |PL| = |P| / 2 , |PR| = |P| / 2 przy pomocy prostej x = l , prostopadłej do osi Ox (ozn. prosta l) tak, że : wszystkie punkty z PL leżą na lewo od prostej l lub na prostej a wszystkie punkty z PR leżą na prawo od prostej l lub na prostej Podziel X na tablice XL, XR zawierające ,odpowiednio, punkty z PL, PR , posortowane według współrzędnej x ; Podziel Y na tablice YL, YR posortowane według współrzędnej y ;
(3) ZWYCIĘŻAJ Dwa wywołania rekurencyjne : ZNAJDŹ-PARĘ-NAJMNIEJ-ODLEGŁYCH-PUNKTÓW ( PL, XL, YL); WYNIK : L, pL, qL ZNAJDŹ-PARĘ-NAJMNIEJ-ODLEGŁYCH-PUNKTÓW ( PR, XR, YR); WYNIK : R , pR , qR
Oblicz : = min {L , R } , niech p, q : d(p, q ) = (4) POŁĄCZ : Oblicz : = min {L , R } , niech p, q : d(p, q ) = Oblicz = min { , * } gdzie * = min { d(pL, pR) ; pL PL ,pR PR } Aby wyznaczyć * wystarczy : rozpatrywać punkty z PL o współrzędnych x z przedziału [ l - , l ] i punkty z PR o współrzędnych x z przedziału [l, l + ] (i) Utwórz tablicę Y' z tablicy Y zawierającą te punkty uporządkowane według współrzędnej y; (ii) Dla każdego p Y' znajdź punkty w Y' w promieniu od p, oblicz odległości od p i wyznacz najmniejśzą (*) i punkty p*, q*, ( tzn.: * = d(p*, q*) )
Istotna obserwacja : Dla każdego p Y' wystarczy przeglądać 7 punktów z Y' powyżej p