Algoritmer for Delaunay-triangulering Øyvind Hjelle oyvindhj@simula.no, +47 67 82 82 75 Simula Research Laboratory, www.simula.no September 21, 2009
Innhold Algoritmer 1 En enkel algoritme 2 Radial Sweep 3 Steg-for-steg 4 Inkrementelle algoritmer 5 Splitt-og-hersk Innsetting av punkter Punkt-lokalisering Tidsforbruk
Enkel LOP-basert algoritme Direkte resultat fra kapitlene foran. Vi bruker: Algoritme (I) fra første del: Triangulering av et lukka polygon basert på fremskutte punkt. Algoritme (II); innsetting av et punkt i en triangulering. LOP (lokal optimerings-prosedyre) som swapper sidekanter etter Delaunay-kriterier til trianguleringen er Delaunay.
Gitt et punktsett P. Algoritme 1 Beregn Q = ConvHull(P). 2 Algoritme (I) på Q gir en triangulering. 3 Algoritme (II) for å sette inn alle punkter fra P innen for Q i gir en triangulering (P). 4 LOP på sidekantene i helt til ingen sidekanter kan swappes gir: = En triangulering (P) der alle sidekanter er lokalt optimale. I følge Teorem ( ) er Delaunay.
Kommentarer: ConvHull(P) kan beregnes i O(N log N). Step 4 er av orden O(N 2 ) i verste fall. Krever en effektiv punktlokaliserings-algoritme i Step 3. Algoritmen er ikke spesielt rask. Algoritmen kan være ustabil da vi ikke får swappet bort smale trekanter etter hvert. Hvordan kan vi få den mer stabil?
Radial Sweep algoritme Bytter ut Step 1,2,3 i enkel algoritme. (Figur på neste lysark) 1 Velg et punkt p nær senteret av P og lag sidekanter {e p,pi } i=1 N 1 ; figur (a) 2 Sorter og ordne {P \ p} på retning og avstand fra p og lag randkanter E B1 ; figur (b) triangulering (P). 3 Lag trekanter {t pi 1,p i,p i+1 } på randen av (P) og oppdater randen etter hvert. Repeter til Conv(P) er dekket av trekanter (P); figur (c). 4 LOP på sidekantene i (P) helt til ingen sidekanter kan swappes; figur (d) = En triangulering der alle sidekanter er lokalt optimale. I følge Teorem ( ) er (P) nå Delaunay
(a) (b) p (c) (d)
Kommentarer til Radial Sweep. Algoritmen er statisk, dvs. man må kjenne alle punktene når man starter algoritmen. Sortering er av orden O(N log N) Step 4 av orden O(N 2 ) i verste fall.
Steg-for-steg algoritme Metoden går ut på å lage en og en Delaunay-trekant fra punkter i P til vi har en Delaunay-triang. (P). Hvordan kan vi velge tre punkter a, b og c fra P slik at t a,b,c er en Delaunay-trekant? Fra forrige kapittel har vi: Lemma (sirkel-lemma) Den omskrivende sirkel til en trekant i en Delaunay-triangulering av P omslutter ingen punkter fra P. Men, kan det finnes en trekant t a,b,c slik at C(t a,b,c ) ikke omslutter punkter fra P, men som likevel ikke er Delaunay?
Vi gjør nå resultatet komplett slik at det er implikasjonener begge veier ( hvis og bare hvis )! Theorem ( ) En trekant t a,b,c med hjørnepunkter a, b og c fra et punktsett P er en Delaunay-trekant i (P) (hvis og bare hvis) C(t a,b,c ) omslutter ingen punkter fra P. = Hvis t a,b,c er en Delaunay-trekant i en Delaunay-triangulering (P), så omslutter C(t a,b,c ) ingen punkter fra P (i følge sirkel-lemma).
Bevis med voksende sirkel (growing circle) b α p t b,a,p c t a,b,c e b α C(t a,b,c ) a
Proof. =. Vi lager et konstruktivt bevis som samtidig definerer en algoritme. Anta at C(t a,b,c ) omslutter ingen punkter fra P, se figur. La sirkelen vokse på motsatt side av e b fra c til den når et punkt p. Hvis et punkt fra P ikke kan nås, må e b være en kant på ConvHull(P); velg en annen sidekant i t a,b,c som e b etc. Lag trekanten t b,a,p ; C(t b,a,p ) omslutter nå ingen punkter fra P. Gjenta dette med en ny e b hver gang til hele Conv(P) er dekket av trekanter {t i } T i=1 i en triangulering (P). C(t i ), i = 1,..., T omslutter nå ingen punkter i P. > (P) er en Delaunay-triangulering i følge Teorem ( ) og Teorem ( ) (eller Corollar). >> t a,b,c er en Delaunay trekant.
Algoritme (steg-for-steg) 1 Finn en Delaunay-sidekant e pi,p j fra P; for eksempel: 1 p i og p j er to nærmste naboer i P, eller: 2 p i og p j er to naboer på ConvHull(P). 2 Lag den første voksende sirkelen C I tilfelle (a); la C ha senter i (p i + p j )/2 I tilfelle (b), la C være uendelig stor med senter utenfor Conv(P) 3 Resten blir som konstruksjonen i beviset ovenfor.
Kommentarer til steg-for-steg algoritme: Vi trenger en passende underliggende data-struktur for P slik at søk etter et hjørnepunkt p til en Delaunay-trekant t a,b,p blir effektiv. Hvis ikke, blir tidsforbruket alltid O(N 2 ). Algoritmen undersøker vinkelen α med toppunkt i p, se figur. Punktet p som gir max α velges. Algoritmen er statisk.
Inkrementelle algoritmer for Delaunay-triangulering. Inkrementelle algoritmer på et punktsett P kjennetegnes ved: 1 Starter med en initiell Delaunay-triangulering I, for eks.: (a) I ( P); der P er et subsett av P ( I kan være en trekant) (b) I (S) der S er temporære punkter som ikke hører til P. p i Conv(S), i = 1,..., N. 2 De gjenværende punktene blir satt inn ett og ett (i vilkårlig rekkefølge). 3 Trianguleringen oppdateres til å være Delaunay for hvert punkt som settes inn. 4 I tilfellet (b) over må S fjernes til slutt. *) Det vil lønne seg å sortere punktene, f.eks. leksikografisk på x og y for effektiv lokalisering.
Step 2 Hvordan kan vi sette inn et punkt p i en Delaunay-triangulering N (P) slik at N+1 (P p) også er Delaunay? (a) (b) p Q p R p p Definition Influens-regionen R p = er trekantene som må endres ved innsetting av p. Definition Influens-polygonet Q p = er randen til R p.
Alternativ (a): (i) finn R p (ii) fjern alle trekantene i R p (iii) retrianguler {Q p p}. Alternativ (b): (i) finn trekanten t pi,p j,p k slik at p t pi,p j,p k (ii) lag sidekanter e p,pi, e p,pj og e p,pk ; (iii) swap kanter til trianguleringen er Delaunay. HVORDAN ER R p?
Lemma En trekant t i må endres når p settes inn hvis og bare hvis p C(t i ). Proof. Beviset følger direkte fra Teorem ( ) over.
Theorem La N+1 være Delaunay-trianguleringen fra innsetting av p i en Delaunay-triangulering N. Da vil alle nye (og endrede) trekanter i N+1 ha p som en felles node. Motbevis. Merk først at kun trekantene innenfor Q p i N vil endres. Anta at det er (blir) en Delaunay-trekant t pi,p j,p k i N+1 innenfor Q p slik at p ikke er en node i t pi,p j,p k. p i, p j og p k er Voronoi-naboer relativt til {P p}. > Da er de også Voronoi-naboer i P i følge Lemma ( ); og > siden t pi,p j,p k er en Delaunay-trekant i N+1, er den også en Delaunay-trekant i N. >> Motsigelse: Siden t pi,p j,p k er innenfor Q p har vi at p C(t pi,p j,p k ) og følgelig kan t pi,p j,p k ikke være en Delaunay-trekant i N+1.
(a) (b) Q p p R p Konsekvenser: Nodene til trekantene i N innenfor R p hører til Q p R p er sammenhengende (hvis p er innenfor N ) Q p er stjerneformet s.a. alle noder i Q p er synlige fra p Algoritme (1, med R p og Q p.) 1 Finn R p, dvs. {t i } slik at p C(t i ); Figur (a) 2 Fjern alle t i 3 Lag sidekanter {e p,pi } der p i er punkter på Q p.
(c) (d) p Hvis p ligger utenfor N må vi sørge for at randen til N+1 blir konveks slik: p forbindes til alle punkter på ConvHull(P) som er synlige fra p.
Punktinnsetting og rekursiv swapping Innsetting av p i en triangulering: N (P) N+1 (P p) Det fremgår av det foregående at: 1 Influensregionen R p er sammenhengende når p er innenfor N 2 R p er ofte begrenset (men i verste fall kan R p være hele (P) Vi skal utnytte dette til å lage en rask og kompakt algoritme basert kun på swapping.
p p p p p Algoritme (2, med swapping) 1 Lokaliser en trekant t pi,p j,p k slik at p t pi,p j,p k 2 Sett inn sidekanter e p,pi, e p,pj og e p,pk. 3 Swap kanter innenfor R p i henhold til Delaunay-kriteriene. I punkt 3 kan vi f.eks. kjøre LOP, men vi skal utlede en smartere swappe-strategi (men som fortsatt kun swapper kanter som ikke er lokalt optimale)...
Rekursiv swappeprosedyre (Step 3). (a) (b) e 1,1 e 1,3 ' e 1 p e 1 p e 1,2 e 3 e 3 e 1,4 e 2 e 2 e p,pi, e p,pj og e p,pk kan ikke swappes. Kun e 1, e 2 and e 3 i (a) er kandidater for swapping med LOP. (Alle andre kanter er diagonaler i de samme kvadrilateraler som før innsetting av p og er derfor lokalt optimale siden N er Delaunay.) SWAP, f.eks. e 1 til e 1 ; se figur (b). Merk at e 1 swappes til punktet p. e 1,1 og e 1,2 motsatt e 1 fra p blir nye kandidater for swapping.
(a) (b) e 1,1 e 1,3 ' e 1 p e 1 p e 1,2 e 3 e 3 e 1,4 e 2 e 2 Start på rekursiv swapping. Men, hva med e 1,3 og e 1,4? Generelt blir også disse kandidater, men: Hypotese( ): e 1,3 og e 1,4 (som begge har noder i p) er ikke kandidater for swapping (vises senere). SWAP e 1,2 og rekursjon, se over. (e 1,1 er lokalt optimal i dette eksempelet).
(a) (b) e 1,1 e 1,3 ' e 1 p e 1 p e 1,2 e 3 e 3 e 1,4 e 2 e 2 Algoritme (recswapdelaunay(edge e i )) 1 if (swaptest(e i ) == OK) 2 RETURN 3 swapedge(e i ) // til p 4 recswapdelaunay(e i,1 ) // rekursjon 5 recswapdelaunay(e i,2 ) // rekursjon
p p p p p Konklusjon så langt (hvis hypotesen holder): Kan swappe rekursivt utover fra p uten å måtte beregne influensregionen R p.... flere konklusjoner følger senere...
c x e i,3 e i,1 b p ' e i e i,2 C e i,4 C a Se animasjon. Hypotese( ): Lemma Hver kant-swap i algoritme recswapdelaunay(edge e i ) genererer maks. to kandidater for swapping.
c x e i,3 e i,1 b p ' e i e i,2 C e i,4 C a Proof. Må vise at e i,3 og e i,4 er lokalt optimale etter at e i er swappet til e i. Vi gjør dette for e i,3 ved å se på kvadrilateralet (p,b,c,x). Må altså vise at x / C i figuren. p C (p.g.a. at e i ble swappet), men ellers er C punktfri siden t a,b,c er Delaunay i N. C : (c p b) C (siden (c p b) interpolerer p.) > (c p b) er punktfri og >> x / C og e i,3 er lokalt optimal. Tilsvarende for e i,4 følger fra symmetri.
c x e i,3 e i,1 b p ' e i e i,2 C e i,4 C a
Observasjoner og flere resultater: Swapping starter i 3 avgrensede vinkel-sektorer utspent av p og e i, i = 1,2,3 (som dekker hele planet) For hver swap deles en vinkelsektor i to (rekursjon). Hver kant som sjekkes er på motsatt side av p i en trekant med p som node En kant swappes alltid til p og vil ikke swappes igjen i recswapdelaunay Lemma Ingen kanter sjekkes mer enn en gang i recswapdelaunay.
En vinkelsektor (p,e i ) i R 2 er ferdigbehandlet hvis e i ikke skal swappes. > recswapdelaunay convergerer. >> Alle kanter i N+1 er lokalt optimale og N+1 er Delaunay. Det følger fra Lemma: Corollary Følgende er Delaunay-kanter: 1 e p,pi, e p,pj og e p,pk (nye kanter som ikke swappes) 2 Alle kanter som swappes (til p) 3 Alle kanter som passerer swaptest. Dette er forskjellig fra generell LOP på en vilkårlig triangulering der en swap av en kant ikke nødvendigvis gir en Delaunay-kant.
Verifisering av Korollar med: Tidligere teorem: En kant e i,j mellom to punkter p i og p j i P er en Delaunay-kant. det eksisterer en sirkel C gjennom p i og p j slik at det indre av C ikke inneholder punkter fra P. (a) C C (b) C C t i p p ' e i e i t i 1 e p,pi, e p,pj og e p,pk ; figur (a). 2 Alle kanter som swappes (til p); figur (b) C inneholder kun p = C er punktfri. 3 Alle kanter som passerer swaptest.; figur (b). (i så fall: p / C)
Punktinnsetting forts.... Hvis p settes inn på en eksisterende indre kant dekkes dette av teorien og recswapdelaunay uten spesialbehandling Hvis p settes inn på på en rand-kant e i må vi splitte e i hvis vi ikke tillater degenererte trekanter. Hvis p settes inn utenfor trianguleringen: Får nye initielle kanter e p,p1,e p,p2,e p,p3,... der p 1,p 2,p 3,... er alle noder som er synlige fra p. Ellers er teorien den samme (og recswapdelaunay).
Tidsforbruk for inkrementelle algoritmer Først: tidsforbruk for en worst-case konfigurasjon av P. (a) 1 (b) (c) 2 3 4 5 6 8 7 10 9 La P = {(x i,y i )} være punkter uniformt fordelt på en parabel y = 1 2 x2 ; figur (a). Start med t p1,p 2,p 3 og sett inn punkter i rekkefølgen: p 4,p 5,...,p 10. Anta at vi har satt inn p k slik at ({p 1,...,p k }) er Delaunay. Ved innsetting av p k+1 er influensregionen R p = ({p 1,...,p k }); dvs. alle trekantene må endres for at ({p 1,...,p k+1 }) skal være Delaunay; figur (b) og (c).
Tidsforbruk for å triangulere N punkter blir: siden N (i 1) = 1 2 N2 1 2 N 3 = O(N2 ). i=4 1 + 2 + 3 + + n = n(n + 1)/2 = 1 2 n2 + 1 2 n
25 15 10 5-4 -2 0 2 x 4-5 O(N), O(N log N), O(N 2 )
Kommentarer: Punktkonfigurasjoner som gir worst-case opptrer nesten aldri i praksis. Tidsforbruket er valigvis mer avhengig av den underliggende data-struktur enn av teoretisk orden på algoritmer. I praksis, hvis man har en passende data-struktur, har de flese algoritmer et O(N log N) eller nesten O(N) forløp.
Punkt-lokalisering Problem Gitt et punkt p og en start-trekant t i i (P). Finn trekanten t ι i (P) slik at p t ι ; eller avgjør om p er utenfor. Raske algoritmer for Problem er viktige i, inkrementelle algoritmer evaluering av (P) etc.
Eksempel på løsning av Problem Gitt en dart d i = (v i,e i,t i ) orientert mot klokka i t i. La H(d i ) være halvplanet til venstre for d i som inneholder v i og noden i α 0 (d i ). Da er p t i p H(d i ) H (α 1 α 0 (d i )) H (α 0 α 1 (d i )) Anta at randen til (P) er konveks: α 2 (d b ) = d b og p / H(d b ) = p er utenfor (P).
d i p
Algoritme: d i Gitt p = (x,y) og en dart d i = (v i,e i,t i ) orientert mot klokka i t i. p Algoritme (Punktlokalisering) 1 d start := d i 2 if p H(d i ) 3 d i := α 1 α 0 (d i ) // next edge ccw. in t i 4 if d i == d start 5 FOUND := true, RETURN // inside t i 6 else // try to move to the adjacent triangle 7 if α 2 (d i ) == d i // check if on boundary 8 FOUND := false, RETURN // outside 9 d start := α 0 α 2 (d i ) 10 d i := α 1 α 2 (d i ) // next edge ccw. in adj. t ι 11 GOTO Step 2
template <class PointType, class DartType> bool locateface(pointtype& point, DartType& dart iter) { DartType dart start = dart iter; DartType dart prev; for (;;) { // endless loop if (dart iter.inlefthalfplane(point)) { dart iter.alpha0().alpha1(); if (dart iter == dart start) return true; // left to all edges in face } else { // try to move to the adjacent triangle dart prev = dart iter; dart iter.alpha2(); if (dart iter == dart prev) return false; // iteration to outside boundary dart start = dart iter; dart start.alpha0(); dart iter.alpha1(); // avoid twice on same edge and ccw in next } } // end for }
Splitt-og-hersk algoritme Splitt-og-hersk (divide-and-conquer) er en generell teknikk brukt innen mange områder av CG, for eksempel i algoritmer for: Konveks omhylning Nærmeste naboer Voronoi-diagram Generelt er splitt-og-hersk algoritmer av orden O(N log N). Splitt-og-hersk er den eneste (kjente) triangulerings-algoritmen som teoretisk er av orden O(N log N). Siden det finnes standard splitt og-hersk algoritmer for å finne Voronoi-diagrammet V D(P), kan vi også avlede Delaunay-trianguleringen fra V D(P) i O(N) tid. Vi skal se på en splitt-og-hersk algoritme for å finne Delaunay-trianguleringen direkte.
Rekursiv oppdeling av P ւ P = P 0 0 ց P 1 0 P 1 1 ւ ց ւ ց P0 2 P1 2 P2 2 P3 2 ւ ց ւ ց ւ ց ւ ց P 3 0 P 3 1 P 3 2 P 3 3 P 3 4 P 3 5 P 3 6 P 3 7
0 0 = (P) {}}{ 1 0 1 1 { }} { 2 0 2 1 { }} { 2 2 2 3 { }} { 3 0 3 1 { }} { 3 2 3 3 { }} { 3 4 3 5 { }} { 3 6 3 7
Løsning 1 Sorterer punktsettet P leksikografisk på X og Y : p i = (x i,y i ) < (x j,y j ) = p j x i < x j, eller x i = x j og y i < y j. 2 Deler opp P rekursivt i punktsett P 1,...,P N slik at hvert P i inneholder noen få punkter. N er et partall. 3 Lag Delaunay-trianguleringer (P 1 ),..., (P N ). 4 Sy sammen ( merge ) to og to nabo-trianguleringer (P L ) og (P R ) til (P L P R ). Step 3 og 4 gjøres rekursivt til vi har en Delaunay-triangulering (P). Vi skal se nærmere på step 4.
(a) e u (b) p p R p L e b
(a) e u (b) p p R p L e b Gitt (P L ) og (P R ), finn (P L P R ): 1 Finn ConvHull(P L P R ). Siden ConvHull(P L ) og ConvHull(P R ) er funnet, kan dette gjøres i (max) O(N) tid ved å finne e b og e u ; figur (a). 2 Start sammensying ved e b : Finn punktet p fra (P L ) eller (P R ) som danner en Delaunay-trekant med e b. Bruk en voksende sirkel slik som i steg-for-steg algoritmen. t pl,p R,p i figur (a) er nå en Delaunay-trekant i (P L P R ) følge Teorem ( ). Sidekanter i (P L ) og (P R ) som skjerer t pl,p R,p fjernes. Sett e b til den nye sidekanten og repeter helt til e u nås. 3 (P L P R ) er nå Delaunay siden ingen punkter i {P L P R } er innenfor en omskrevet sirkel til en trekant i (P L P R ).
Tidsforbruk for splitt-og-hersk (teoretisk). La t(n) = tidsforbruk for Delaunay-triangulering av N punkter. Sammensyingen av (P L ) og (P R ) er av orden O(N): M(N/2,N/2) er tidsforbruk for å sy sammen (P L ) og (P R ) hver med N/2 noder. Siden M(N/2,N/2) er lineær i tid er 2M(N/4,N/4) = M(N/2,N/2). Vi får følgende rekursjons-formel: t(n) = 2t(N/2) + M(N/2,N/2) t(1) = 0 Vi skal nå se at dette vil gi t(n) = O(N log N). Viktig: I praksis er splitt-og-hersk-algoritmen ikke nødvendigvis raskere enn andre algoritmer selv om den (teoretisk) er den eneste som er O(N log N).
Bevis for O(N log N) Anta at P ble delt inn i 2 k subsett: t(n) = 2t(N/2) + M(N/2,N/2) = 2(2t(N/4) + M(N/4,N/4)) + M(N/2,N/2) = 4t(N/4) + 2M(N/2,N/2) (bruker 2M(N/4,N/4) = M(N = 8t(N/8) + 3M(N/2,N/2) = 16t(N/16) + 4M(N/2, N/2) = = 2 k t(n/2 k ) + km(n/2,n/2).
t(n) = 2 k t(n/2 k ) + km(n/2,n/2). Anta at totalt antall punkter er N = 2 m Hvis N er stor og k er stor er m k Fra tidligere: worst-case for Delaunay-triangulering er O(N 2 ). 1. ledd er av orden: 2 k (N/2 k ) 2 = 2 k (2 m /2 k ) 2 = 2 2m k 2 m (siden m k) = N; dvs. O(N) 2. ledd er av orden: M(N/2,N/2) er O(N): kn mn, men m = log 2 N (siden N = 2 m ); dvs. N log 2 N eller O(N log N)