Algorithmische Geometrie: Schnittpunkte von Strecken Nico Düvelmeyer WS 2009/2010, 3.11.2009
3 Phasen im Algorithmenentwurf 1. Konzentration auf das Hauptproblem 2. Verallgemeinerung auf entartete Eingaben 3. Implementation
Überblick 1 Gleitebenenverfahren für Schnittpunkte 2 Die doppelt verkettete Kantenliste 3 Berechnung der Überlagerung zweier Ebenenaufteilungen Flächendaten
Einschub Balancierter Baum Es gibt Datenstrukturen (Bsp. AVL-Baum), mit denen garantiert sortierte Mengen effizient verwaltet werden können. Speicherplatzbedarf in O(n). Suchen eines Elements in der sortierten Menge in O(log n). Hinzufügen und Löschen von Elementen: O(log n).
Auftrag Schnittpunkte Gegeben: n Strecken der Ebene Gesucht: Menge aller Schnittpunkte der abgeschlossenen Strecken, unter Angabe der beteiligten Strecken Die Laufzeit soll ausgabeabhängig möglichst gut sein.
Überblick 1 Gleitebenenverfahren für Schnittpunkte 2 Die doppelt verkettete Kantenliste 3 Berechnung der Überlagerung zweier Ebenenaufteilungen Flächendaten
Anfangsidee Wir scheiden nur Strecken, deren y-bereiche sich auch schneiden.
Anfangsidee Wir scheiden nur Strecken, deren y-bereiche sich auch schneiden. Status: Menge der Strecken, die die Gleitgerade schneiden. Ereignispunkte: Anfangs- und Endpunkte der Strecken Schnittpunktbestimmung: nur Strecken, die gleichzeitig im Status sind
Anfangsidee Wir scheiden nur Strecken, deren y-bereiche sich auch schneiden. Status: Menge der Strecken, die die Gleitgerade schneiden. Ereignispunkte: Anfangs- und Endpunkte der Strecken Schnittpunktbestimmung: nur Strecken, die gleichzeitig im Status sind Problem: wir schneiden noch zu viele Paare von (weit entfernten) Strecken!
Verfeinerung
Verfeinerung Status: Sortierte Liste T der Strecken, wie sie die Gleitgerade (von links nach rechts) schneiden. Balancierter Suchbaum. Schnittpunktbestimmung: nur benachbarte Strecken in T Ereignispunkte: Anfangs-, End- und Schnittpunkte der Strecken, sortiert nach Abarbeitung: Von oben nach unten, bei Gleichheit von links nach rechts. Zu jedem Punkt ist eine Menge dort beginnender Strecken gespeichert. Balancierter Suchbaum. Kein Heap, da bereits enthaltene Punkte nicht nochmals eingefügt werden sollen. Ereigniswarteschlange Q.
Algorithmus 3.3 (Hauptschleife) Eingabe: Menge S von Strecken der Ebene Ausgabe: Eine Menge von Schnittpunkten mit Angabe der beteiligten Strecken 1: Funktion SUCHESCHNITTPUNKTE(S) 2: Initialisiere eine leere Ereigniswarteschlange Q. Füge die Randpunkte der Strecken von S in Q ein. Zu den oberen Randpunkten wird auch die zugehörige Strecke gespeichert. Für horizontale Strecken betrachten wir den linken Randpunkt als oberes Ende (Anfangspunkt). 3: Initialisiere einen leeren Statusbaum T. 4: Solange Q nicht leer ist, mache 5: Bestimme den nächsten Ereignispunkt p aus Q und lösche diesen. 6: BEHANDELEREIGNISPUNKT(p)
Algorithmus 3.3 (BEHANDELEREIGNISPUNKT Teil 1/2) 7: Unterprogramm BEHANDELEREIGNISPUNKT(p) 8: Bezeichne mit U(p) die Menge der Strecken (aus Q), die in p beginnen. 9: Suche alle Strecken in T, die p enthalten. L(p) sei die Menge jener Strecken, für die p das untere Ende ist, und C(p) die Menge der Strecken von T mit p im Inneren. 10: Wenn L(p) U(p) C(p) mehr als eine Strecke enthält, dann 11: Melde p als Schnittpunkt, zusammen mit L(p), U(p) und C(p). 12: Lösche die Strecken in L(p) C(p) aus T. 13: Füge die Strecken in U(p) C(p) neu in richtiger Reihenfolge in T ein (horizontale Strecken zum Schluss). Löschen und Neueinfügen der Strecken von C(p) vertauscht deren Reihenfolge
Algorithmus 3.3 (BEHANDELEREIGNISPUNKT Teil 2/2) 14: Wenn U(p) C(p) = dann 15: Bestimme linken Nachbarn s l und rechten Nachbarn s r von p in T. 16: SUCHENEUESEREIGNIS(s l,s r,p) 17: sonst 18: Sei s die Strecke am weitesten links von U(p) C(p) in T, 19: und s l deren linker Nachbar in T. 20: SUCHENEUESEREIGNIS(s l,s,p) falls s l existiert. 21: Sei s die Strecke am weitesten rechts von U(p) C(p) in T, 22: und s r deren rechter Nachbar in T. 23: SUCHENEUESEREIGNIS(s,s r,p) falls s r existiert.
Algorithmus 3.3 (SUCHENEUESEREIGNIS) 24: Unterprogramm SUCHENEUESEREIGNIS(s l, s r, p) 25: Wenn s l und s r sich unterhalb der Gleitebene schneiden (inklusive: direkt rechts von p auf dieser), und wenn deren Schnittpunkt noch nicht in Q enthalten ist, dann 26: Füge den Schnittpunkt in Q ein.
Satz 3.4 Alle Schnittpunkte und zugehörige Strecken werden korrekt von Algorithmus 3.3 bestimmt.
Satz 3.4 Alle Schnittpunkte und zugehörige Strecken werden korrekt von Algorithmus 3.3 bestimmt. Beweis. Mit Induktion folgt, dass jeder Schnittpunkt auch erkannt wird sobald zwei der beteiligten Strecken benachbart werden. Dies passiert nur an Ereignispunkten. Bei der Behandlung jedes Schnittpunktes p enthält T tatsächlich alle Strecken, die von der Waagerechten geschnitten werden, bis auf Strecken aus U(p).
Satz 3.5 Die Laufzeit von Algorithmus 3.3 für n Strecken mit I Schnittpunkten ist in O((n + I) log n).
Beweis Satz 3.5 (Hauptschleife) 1: Funktion SUCHESCHNITTPUNKTE(S) 2: Initialisiere eine leere Ereigniswarteschlange Q. Zeit O(1) Füge die Randpunkte der Strecken von S in Q ein. Zu den oberen Randpunkten wird auch die zugehörige Strecke gespeichert. Für horizontale Strecken betrachten wir den linken Randpunkt als oberes Ende (Anfangspunkt). 2n mal Grundoperation Suchen. Maximal 2n mal Grundoperation Einfügen in Q oder alternativ Einfügen in Streckenmenge. Dabei Größe von Q maximal 2n. Zeit: O(n log n). 3: Initialisiere einen leeren Statusbaum T. Zeit O(1) 4: Solange Q nicht leer ist, mache 5: Bestimme den nächsten Ereignispunkt p aus Q und lösche diesen. Maximal 2n + I Durchläufe, Grundoperationen in Q, von Größe maximal 2n + I. Zeit: 2(2n + I) log(2n + I) O((n + I) log n) 6: BEHANDELEREIGNISPUNKT(p) Beachte: I < n 2, log(2n + I) < log(2n 2 ) = log 2 + 2 log n O(log n).
Satz 3.5 (SUCHENEUESEREIGNIS) 24: Unterprogramm SUCHENEUESEREIGNIS(s l, s r, p) 25: Wenn s l und s r sich unterhalb der Gleitebene schneiden (inklusive: direkt rechts von p auf dieser), und wenn deren Schnittpunkt noch nicht in Q enthalten ist, dann 26: Füge den Schnittpunkt in Q ein. Jeder Durchlauf dieses Unterprogramms benötigt Zeit in O(log Q ), das ist in O(log n).
Beweis Satz 3.5 (BEHANDELEREIGNISPUNKT Teil 1/2) Unterprogramm BEHANDELEREIGNISPUNKT(p) wird maximal 2n + I mal ausgeführt. 7: Unterprogramm BEHANDELEREIGNISPUNKT(p) 8: Bezeichne mit U(p) die Menge der Strecken (aus Q), die in p beginnen. Zeit: O( U(p) ) 9: Suche alle Strecken in T, die p enthalten. L(p) sei die Menge jener Strecken, für die p das untere Ende ist, und C(p) die Menge der Strecken von T mit p im Inneren. Zeit: O(log T + L(p) C(p) ) 10: Wenn L(p) U(p) C(p) mehr als eine Strecke enthält, dann 11: Melde p als Schnittpunkt, zusammen mit L(p), U(p) und C(p). Zeit O( L(p) C(p) U(p) ) 12: Lösche die Strecken in L(p) C(p) aus T. Zeit: O( L(p) C(p) log T ) 13: Füge die Strecken in U(p) C(p) neu in richtiger Reihenfolge in T ein (horizontale Strecken zum Schluss). Zeit O( U(p) C(p) log T )
Beweis Satz 3.5 (BEHANDELEREIGNISPUNKT Teil 2/2) 14: Wenn U(p) C(p) = dann 15: Bestimme linken Nachbarn s l und rechten Nachbarn s r von p in T. O( T ) 16: SUCHENEUESEREIGNIS(s l,s r,p) Zeit: O(log n) 17: sonst 18: Sei s die Strecke am weitesten links von U(p) C(p) in T, Zeit: O(log T ) 19: und s l deren linker Nachbar in T. Zeit: O(log T ) 20: SUCHENEUESEREIGNIS(s l,s,p) falls s l existiert. Zeit: O(log n) 21: Sei s die Strecke am weitesten rechts von U(p) C(p) in T, Zeit: O(log T ) 22: und s r deren rechter Nachbar in T. Zeit: O(log T ) 23: SUCHENEUESEREIGNIS(s,s r,p) falls s r existiert. Zeit: O(log n)
Beweis Satz 3.5 (Abschluss) m(p) := L(p) U(p) C(p) Zeitaufwand von BEHANDELEREIGNISPUNKT(p) in O(m(p) log n). m := p m(p), Zeitaufwand aller Aufrufe zusammen in O(m log n).
Beweis Satz 3.5 (Abschluss) m(p) := L(p) U(p) C(p) Zeitaufwand von BEHANDELEREIGNISPUNKT(p) in O(m(p) log n). m := p m(p), Zeitaufwand aller Aufrufe zusammen in O(m log n). k: Größe der Ausgabe (Anzahl ausgegebener Punkte plus jeweils der Anzahl der ausgegebenen zugehörigen Strecken) m O(n + k).
Beweis Satz 3.5 (m O(n + I)) n e Knoten: Schnitt- und Endpunkte, n e 2n + I. n k Kanten: ungeteilte Abschnitte der gegebenen Strecken. n f Flächen: n f 2n k /3 (Flächen-Kanten-Inzidenzen doppelt zählen, keine Zweiecke ) Eulersche Polyederformel (Zusammenhangskomponenten): n e + n f n k 2 n k 3n e 6, da n k n e + n f 2 n e + 2n k /3 2. m(p) gleich dem Grad des Knotens p. m die Summe der Grade aller Knoten, m = 2n k m 6(2n + I) 12 < 12(n + I).
Satz 3.6 Die I Schnittpunkte von n Strecken können mit einem Algorithmus (Modifikation von Algorithmus 3.3) mit Laufzeit in O((n + I) log n) und Speicherbedarf in O(n) berechnet werden.
Überblick 1 Gleitebenenverfahren für Schnittpunkte 2 Die doppelt verkettete Kantenliste 3 Berechnung der Überlagerung zweier Ebenenaufteilungen Flächendaten
Beispiel Ebenenaufteilung
Datenstruktur 3.7: Doppelt verkettete Kantenliste 3 Datenlisten: für Knoten, Flächen und Halbkanten. KNOTEN v i KOORDINATEN = f (v i ) R 2 INZIDENTEHALBKANTE: Verweis auf eine Halbkante mit Anfang v i FLÄCHE f i AUSSENRAND: Halbkante des Außenrandes INNENRÄNDER: Menge von Halbkanten, 1 je Loch
Datenstruktur 3.7: Doppelt verkettete Kantenliste (Forts.) HALBKANTE h i ANFANG: Anfangsknoten GEGENÜBER: inverse Halbkante INZIDENTEFLÄCHE: links liegende Fläche NACHFOLGER: nachfolgende Halbkante der links liegenden Fläche VORGÄNGER: vorausgehende Halbkante der links liegenden Fläche weitere Attribute. gültig, wenn tatsächlich Aufteilung der Ebene
Beispiel doppelt verkettete Kantenliste e 1,1 v 1 v 2 1,2 e 3,2 e 4,1 e 4,2 e 3,1 e 2,2 e 2,1 v 3 v 4
Beispiel doppelt verkettete Kantenliste e 1,1 v 1 v 2 1,2 e 3,2 e 4,1 e 4,2 e 3,1 e 2,2 e 2,1 v 3 v 4 KNOTEN KOORDINATEN INZIDENTEHALBKANTE v 1 (0,4) v 2 (2,4) v 3 (2,2) v 4 (1,1) e 1,1 e 4,2 e 2,1 e 2,2
Beispiel doppelt verkettete Kantenliste e 1,1 v 1 v 2 1,2 e 3,2 e 4,1 e 4,2 e 3,1 v 3 e 2,2 e 2,1 FLÄCHE AUSSENRAND INNENRÄNDER v 4 f 1 nil e 1,1 f 2 e 4,1 nil
Beispiel doppelt verkettete Kantenliste HALBKANTE ANFANG GEGENÜBER INZIDENTEFLÄCHE NACHFOLGER VORGÄNGER e 1,1 v 1 e 1,2 f 1 e 4,2 e 3,1 e 1,2 v 2 e 1,1 f 2 e 3,2 e 4,1 e 2,1 v 3 e 2,2 f 1 e 2,2 e 4,2 e 2,2 v 4 e 2,1 f 1 e 3,1 e 2,1 e 3,1 v 3 e 3,2 f 1 e 1,1 e 2,2 e 3,2 v 1 e 3,1 f 2 e 4,1 e 1,2 e 4,1 v 3 e 4,2 f 2 e 1,2 e 3,2 e 4,2 v 2 e 4,1 f 1 e 2,1 e 1,1
Überblick 1 Gleitebenenverfahren für Schnittpunkte 2 Die doppelt verkettete Kantenliste 3 Berechnung der Überlagerung zweier Ebenenaufteilungen Flächendaten
Auftrag Kartenüberlagerung Gegeben: Zwei doppelt verkettete Kantenlisten für Ebenenaufteilungen S 1, S 2. Gesucht: Doppelt verkettete Kantenlisten für Überlagerung Ü(S 1, S 2 ) von S 1 und S 2. Als Attribute der Flächen sollen Paare der ursprünglichen Attribute gebildet werden.
neues Gleitebenenverfahren neu: D, anfangs Vereinigung von Kopien der Ausgangsdaten. merken uns Beziehung zwischen Halbkanten in D und Strecken in T lokale Operationen, um die Kantenverknüpfung sicherzustellen
Beispiel 3.9 Kante k von S 1 geht durch Knoten v von S 2. k wurde bisher durch 2 Halbkanten dargestellt, daraus werden jetzt vier! Bisherige Enden von k sind leicht korrigiert. Im Punkt v muss die exakte zyklische Position bestimmt werden und dann entsprechend die Verknüpftung durchgeführt werden. Zeitaufwand für die Korrektur von k beim Ereignispunkt v: O(m(v)), wobei m(v) weiterhin die Anzahl von Originalkanten ist, die zu v inzident sind (für die Suche der richtigen Positionen in der zyklischen Reihenfolge).
Fazit: Halbkanten- und Knotenrekords Knoten- und Halbkantendatensätze korrekt bis auf INZIDENTEFLÄCHE Gesamtzeitaufwand dafür ist in O((n + k) log n). n: Summe der Komplexitäten von S 1 und S 2 k: Komplexität vom Ergebnis
Flächendaten Untersuchung Zyklen von Halbkanten. innere und äußere Ränder der Flächen Zuordnung der Ränder einer Fläche Hilfsgraph G, Knoten: Zyklen und Kanten in G: Rand links eines inneren Rands
Satz 3.10 Jede Zusammenhangskomponente des Graphen G stimmt genau mit der Menge von Zyklen überein, die mit einer Fläche inzidieren. Beweis. Skript
Lokale Seiteninformationen Nach dem Gleitebenendurchlauf kann in Zeit O(n + k) die Flächenverknüpfung der doppelt verketteten Kantenliste berechnet werden.
Lokale Seiteninformationen Nach dem Gleitebenendurchlauf kann in Zeit O(n + k) die Flächenverknüpfung der doppelt verketteten Kantenliste berechnet werden. Speichern wir zusätzlich noch von allen Knoten die zugehörigen Seiteninformationen während des Ebenendurchlaufs, können wir auch die Attribute der neuen Flächen allein durch lokale Betrachtungen effizient bestimmen. Dies erfordert eine Erweiterung der Informationen, die in T gespeichert werden, und deren Aktualisierung an den Ereignispunkten.
Algorithmus 3.11 Eingabe: Zwei doppelt verkettete Kantenlisten für Ebenenaufteilungen S 1, S 2. Ausgabe: Doppelt verkettete Kantenlisten D für Überlagerung Ü(S 1, S 2 ). Als Attribute der Flächen sollen Paare der ursprünglichen Attribute gebildet werden.
Algorithmus 3.11 1: Funktion KARTENÜBERLAGERUNG(S 1, S 2 ) 2: Kopiere die Datenstrukturen für S 1 und S 2 in eine neue gemeinsame doppelt verkettete Kantenliste D. 3: Berechne alle Schnittpunkte zwischen Kanten von S 1 und S 2 mit dem Gleitebenenverfahren SUCHESCHNITTPUNKTE in Algorithmus 3.3. Zusätzlich zu den Änderungen an T und Q ist bei den Ereignispunkten folgendes zu tun: Aktualisiere D entsprechend den lokalen Änderungen (siehe Beispiel 3.9) falls Kanten von sowol S 1 und S 2 beteiligt sind. Speichere die Halbkante l(p) direkt links vom Ereignispunkt p zusätzlich in der Repräsentation von p in der Datenstruktur D. Nun ist D bis auf Seiteninformationen korrekt
Algorithmus 3.11 4: Bestimme die Randzyklen von Ü(S 1, S 2 ) beim Durchlaufen (Tiefensuche) von D. 5: Baue den Graph G mit Knotenn entsprechend den Randzyklen und Kanten, die jedes Loch mit dem linken Nachbarn verbinden. Verwende dafür l(p). Bestimme die Zusammenhangskomponenten von G. 6: Für alle Zusammenhangskomponenten K von G mache 7: C der eindeutige äußere Randzyklus von K. Lege einen neue Flächen-Datensatz für die zugehörige Fläche f an. Setze AUSSENRAND(f ) auf eine Halbkante von C, und füge in INNENRÄNDER(f ) für alle Löcher in K je eine Halbkante ein. Durchlaufe alle diese Randzyklen und setze alle Referenzen INZIDENTEFLÄCHE auf f. 8: Bestimme die Attribute aller neuen Flächen f durch lokale Informationen an jeweils einer Ecken von f.
Satz 3.12 Sei S 1 eine Ebenenaufteilung der Komplexität n 1, S 2 eine solcher der Komplexität n 2, und n := n 1 + n 2. Die Überlagerung von S 1 und S 2 kann in Zeit O(n log n + k log n) berechnet werden, wobei k die Komplexität der Überlagerung ist.
Folgerung 3.13 Für zwei ebene Polygone P 1, P 2 mit n 1 bzw. n 2 Ecken kann P 1 P 2, P 1 P 2 und P 1 \ P 2 jeweils in Zeit O((n + k) log n) berechnet werden, wobei n := n 1 + n 2 und k die Komplexität des Ergebnisses ist.
Bemerkung 3.14 Eine untere Schranke für den Worst-Case-Zeitaufwand der allgemeinen Schnittpunktbestimmung ist Ω(n log n + k). Aber es gibt auch O(n + k)-algorithmen, die ausnutzen, dass zwei gegebene Ebenenaufteilungen jeweils zusammenhängend sind.