Geometrische Algorithmen Geometrische Algorithmen Einführung Einführung Geometrische Algorithmen Motivation Effiziente Algorithmen, die aufgrund geometrischer Daten (v.a. Koordinaten) im d-dimensionalen Raum gewisse Eigenschaften ausnutzen Bin Hu Algorithmen und Datenstrukturen 2 Arbeitsbereich für Algorithmen und Datenstrukturen Institut für Computergraphik und Algorithmen Technische Universität Wien Anwendung Bildverarbeitung Computergraphik Chip Design ... Geometrische Algorithmen Geometrische Algorithmen Scan-Line Prinzip Grundlagen Scan-Line Prinzip Idee Gegeben eine Menge von Objekten in einem 2D Raum Teil I Scan-Line Prinzip Vertikale Linie fegt v.l.n.r. über die Objektmenge und betrachtet nur Objekte, die gegenwärtig relevant sind Statisches 2D Problem → dynamisches 1D Problem Aufteilung der Objekte bezüglich Scanline L Tote Objekte – liegen vollständig links von L Aktive Objekte – werden gegenwärtig von L geschnitten Inaktive Objekte – liegen rechts von L, werden zukünftig von L geschnitten Geometrische Algorithmen Geometrische Algorithmen Scan-Line für Schnitt iso-orientierter Liniensegmente Scan-Line für Schnitt iso-orientierter Liniensegmente Einführung Einführung Schnitt iso-orientierter Liniensegmente Aufgabenstellung Gegeben: n horizontale und vertikale Liniensegmente s1 , . . . , sn Gesucht: Alle Paare sich schneidender Segmente Vereinfachte Annahme Alle Anfangs- und Endpunkte horizontaler Segmenten und alle vertikalen Segmente haben paarweise verschiedene x-Koordinaten H F B C A E G Naives Verfahren Alle Paare von Liniensegmenten auf Schnitt testen. Laufzeit: O(n2 ) D Geometrische Algorithmen Scan-Line für Schnitt iso-orientierter Liniensegmente Algorithmus Scan-Line Verfahren Scan-Line L fegt v.l.n.r. über die Fläche und trifft auf die Liniensegmente. Mögliche Fälle: 1 Anfangspunkt eines horizontalen Segments s: s in L einfügen 2 Endpunkt eines horizontalen Segments s: s aus L löschen 3 Vertikales Segment s: s mit allen Liniensegmenten in L auf Schnitt testen Bemerkung Scan-Line muss sich nicht kontinuierlich fortbewegen ⇒ Es genügt, Haltepunkte bei relevanten Ereignissen zu setzen Geometrische Algorithmen Scan-Line für Schnitt iso-orientierter Liniensegmente Algorithmus Algorithmus 1 Scan-Line für iso-orientierte Liniensegmente 1: Q = Menge der Haltepunkte in aufsteigender x-Reihenfolge; 2: L = ∅ ; // Menge der aktiven Segmente, nach y sortiert 3: solange (Q 6= ∅) { 4: p = nächster Haltepunkt von Q; 5: falls (p Anfangspunkt eines h. Segments s) dann { 6: Füge s in L ein; 7: } sonst { 8: falls (p Endpunkt eines h. Segments s) dann { 9: Entferne s aus L; 10: } sonst { 11: // p ist x-Wert eines v. Segments [(p, yu ), (p, yo )] 12: Für alle h. Segmente t aus L mit y-Koord. zwischen [yu , yo ]: gebe (s, t) als sich schneidendes Paar aus; 13: } 14: } 15: } Geometrische Algorithmen Geometrische Algorithmen Scan-Line für Schnitt iso-orientierter Liniensegmente Scan-Line für Schnitt iso-orientierter Liniensegmente Algorithmus Algorithmus Beispiel: B C Realisierung von L? Benötigte Operationen: A D 1 Einfügen eines neuen Elements 2 Entfernen eines Elements 3 Bestimmen aller Elemente in [(p, yu ), (p, yo )] (Bereichsabfrage) E A A AAADD 0 EDDE EE (A,B) Mögliche Datenstrukturen Balancierte Binärbäume (AVL, Rot-Schwarz, etc.) Randomisierte Skiplisten ... (A,C) (C,D) Geometrische Algorithmen Scan-Line für Schnitt iso-orientierter Liniensegmente Analyse Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Einführung Schnitt von allgemeinen Liniensegmenten Aufgabenstellung Analyse Bereichsabfrage: O(log n + r ) mit r = Anzahl der Elemente zwischen [(p, yu ), (p, yo )] Gesamtlaufzeit: O(n log n + R) mit R = Anzahl der sich schneidenden Segmente Gegeben: Menge S = {s1 , . . . , sn } von n Liniensegmenten in der Ebene Gesucht: Menge echter Schnittpunkte (Kreuzung von Segmenten, die keine Endpunkte sind) y x Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Einführung Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Einführung Beobachtungen Schneiden sich Segmente si mit sj , dann... Vereinfachende Annahmen Kein Segment ist senkrecht Schnitt zweier Segmente ist leer oder genau ein Punkt Nie mehr als 2 Segmente schneiden sich in einem Punkt Alle Endpunkte und Schnittpunkte haben paarweise verschiedene x-Koordinaten Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Algorithmus waren si und sj “Nachbarn” unmittelbar vor dem Schnittpunkt ⇒ Es genügt, nur benachbarte Segmente auf Schnitt zu testen vertauscht sich die Anordnung von si und sj in L nach dem Schnittpunkt ⇒ Schnittpunkte sind auch Ereignisse ⇒ Sie werden während des Scans dynamisch zur Ereignisstruktur hinzugefügt Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Algorithmus 40 Zu betrachende Ereignisse Anfang eines Segments Ende eines Segments Schnitt zweier Segmente Verwendete Datenstrukturen Ereignisstruktur ES: speichert Ereignisse, aufsteigend nach x-Koordinaten sortiert Initialisierung: Anfangs- und Endpunkte aller Segmente Scan-Line-Status Struktur SSS: speichert die aktiven Segmente, nach y -Koordinaten sortiert Initialisierung: Leere Menge KAPITEL 3. GEOMETRISCHE ALGORITHMEN Algorithmus 14 Algorithmus für das Segment-Schnitt Problem in allgemeiner Lage Initialisiere ES und SSS; Sortiere die 2n Endpunkte aufsteigend nach x-Koordinate; Speichere resultierende Ereignisse in ES ; solange ES nicht leer { E = ES.NächstesEreignis(); falls E ist Segment Anfang dann { SSS.FügeEin(E.Segment); VS = SSS.Vorg(E.Segment); E 0 = TesteSchnittErzeugeEreignis(E,VS); falls E 0 6= ∅ dann { ES.FügeEin(E’); } NS = SSS.Nachf(E.Segment); 0 E = TesteSchnittErzeugeEreignis(E,NS); falls E 0 6= ∅ dann { ES.FügeEin(E’); } } falls E ist Segment Ende dann { VS = SSS.Vorg(E.Segment); NS = SSS.Nachf(E.Segment); SSS.Entferne(E.Segment); E 0 = TesteSchnittErzeugeEreignis(VS,NS) falls E 0 6= ∅ dann { ES.FügeEin(E’); } } falls E ist Schnittpunkt dann { Gib E.SegmentO und E.SegmentU aus; SSS.Vertausche(E.SegmentO,E.SegmentU); VS= SSS.Vorg(E.SegmentU); E 0 =TesteSchnittErzeugeEreignis(E.SegmentU,VS); falls E 0 6= ∅ dann { ES.FügeEin(E’); } NS = SSS.Nachf(E.SegmentO); E 0 = TesteSchnittErzeugeEreignis(E.SegmentO,NS); falls E 0 6= ∅ dann { ES.FügeEin(E’); } } } Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Algorithmus Algorithmus 2 Scan-Line für allgemeine Liniensegmente Initialisiere ES und SSS; solange ES nicht leer { E = ES.NächstesEreignis(); falls E ist Segment Anfang dann { ... } falls E ist Segment Ende dann { ... } falls E ist Schnittpunkt dann { ... } } Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Algorithmus Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Algorithmus Fall 1: E ist Anfang eines Segments 1 E in Scan-Line-Status Struktur SSS einfügen 2 E mit seinem Vorgänger auf Schnitt testen Gegebenenfalls Schnittpunkt in Ereignisstruktur ES einfügen 3 E mit seinem Nachfolger auf Schnitt testen Gegebenenfalls Schnittpunkt in Ereignisstruktur ES einfügen Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Algorithmus Fall 3: E ist Schnittpunkt zweier Segmente so und su Fall 2: E ist Ende eines Segments 1 2 Vorgänger und Nachfolger von E auf Schnitt testen Gegebenenfalls Schnittpunkt in Ereignisstruktur ES einfügen 1 E als Schnittpunkt von so und su ausgeben 2 Reihenfolge von so und su in Scan-Line-Status Struktur SSS vertauschen 3 su mit seinem Vorgänger auf Schnitt testen Gegebenenfalls Schnittpunkt in Ereignisstruktur ES einfügen 4 so mit seinem Nachfolger auf Schnitt testen Gegebenenfalls Schnittpunkt in Ereignisstruktur ES einfügen E aus Scan-Line-Status Struktur SSS entfernen Geometrische Algorithmen Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Scan-Line für Schnitt von allgemeinen Liniensegmenten Analyse Zusammenfassung Analyse Anzahl der Ereignisse: 2n + k mit k = Anzahl der Schnittpunkte, k = O(n2 ) Zusammenfassung Zugriff auf Ereignisstruktur ES: O(log n2 ) = O(log n) Scan-Line fegt über eine Menge von Objekten Zugriff auf Scan-Line-Status Struktur SSS: O(log n) Unterteilung: Tote Objekte, Aktive Objekte, Inaktive Objekte Äußere Schleife wird maximal 2n + k mal durchlaufen Nur gegenwärtig Aktive Objekte werden betrachtet Pro Durchlauf maximal 5 Operationen auf ES und SSS Statisches 2D Problem → dynamisches 1D Problem Gesamtaufwand: O((n + k) log n) Speicheraufwand: O(n2 ) Geometrische Algorithmen Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufgabenstellung Gegeben Teil II k-dimensionaler, rechteckiger Bereich D n Punkte im k -dimensionalen Raum Mehrdimensionale Bereichssuche Gesucht Alle Punkte, die in D liegen Geometrische Algorithmen Geometrische Algorithmen Mehrdimensionale Bereichssuche Mehrdimensionale Bereichssuche Lösungsansätze Beispiele 1-dimensionaler Fall Realisierung: Balancierte Binärbäume, Skiplisten, etc. Beispiele k = 1: Zahlen in einer Folge zwischen a und b Aufwand: O(log n + R), R . . . Anzahl der Punkte im Bereich k = 2: Städte in einem Quadrat mit 100 km Seitenlänge und Mittelpunkt Wien k > 2: Datenbankabfragen: Personen mit Eigenschaften Höhere Dimensionen Naive Methode: alle Punkte durchtesten → O(k · n) haben Informatik studiert zwischen 25 und 39 Jahre alt jährliches Einkommen zwischen 30.000,- und 50.000,besitzen kein Handy Grid-Methode: Suchraum in Gridzellen unterteilen Mehrdimensionale Bäume Geometrische Algorithmen Geometrische Algorithmen Mehrdimensionale Bereichssuche Mehrdimensionale Bereichssuche Suche Zweidimensionale Bäume A C G D B E B A E D G C F Struktur wie binäre Suchbäume Knoten representieren Punkte Verwendet abwechselnd x- und y -Koordinaten als Schlüssel F Algorithmus 3 Bereichssuche(Knoten p, Richtung d, Bereich D) falls p 6= NULL dann { falls d == vert dann { (l, r ) = (D.y1 , D.y2 ); coord = p.y; rNeu = horiz; } sonst { (l, r ) = (D.x1 , D.x2 ); coord = p.x; rNeu = vert; } falls p ∈ D dann Ausgabe von p; falls l < coord dann Bereichssuche(p.left, rNeu, D); falls coord < r dann Bereichssuche(p.right, rNeu, D); } Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufbau Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufbau Vorgangsweise Aufbau Erstellung eines effizienten Baums? → Möglichst balanciert, damit Höhe in O(log n) 1 Punkte nach x- bzw. y -Koordinaten sortieren → Folgen X und Y 2 Folge Y am Median-Element aufteilen → Median-Element kommt in die Wurzel → Teilfolgen Y1 und Y2 (beide etwa gleich lang) → Teilfolgen X1 und X2 : dieselben Elemente wie in Y1 und Y2 in gleicher Reihenfolge wie in X 3 Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufbau Algorithmus 4 Aufbau(l, r , knoten, Xdir ) falls l ≤ r dann { m = d l+r 2 e; falls Xdir == true dann { knoten.eintrag = X [m]; Partitioniere Feld(Y , l, r , m); } sonst { knoten.eintrag = Y [m]; Partitioniere Feld(X , l, r , m); } lsohn = neuer linker Sohn(knoten); rsohn = neuer rechter Sohn(knoten); Aufbau(l, m − 1, lsohn, !Xdir ); Aufbau(m + 1, r , rsohn, !Xdir ); } Analoge Fortsetzung mit X1 und Y1 , sowie X2 und Y2 , usw. bis Teilfolgen aus einem Element → Blätter des Baumes Geometrische Algorithmen Mehrdimensionale Bereichssuche Analyse Aufbau Rekursion: T (n) = 2T ( n2 ) + c · n → Θ(n log n) Bereichsabfrage √ O( n + R), R . . . Anzahl der Punkte im Bereich Geometrische Algorithmen Geometrische Algorithmen Mehrdimensionale Bereichssuche Mehrdimensionale Bereichssuche Höhere Dimensionen Zusammenfassung Erweiterung auf kD Bäume Analog wie 2D Bäume alle Dimensionen (in abwechselnder Reihenfolge) durchlaufen Zusammenfassung Effiziente Bereichsabfrage mittels mehrdimensionale Bäume Jede Ebene entspricht eine bestimmte Dimension Performance Aufbau: Θ(k · n log n) 1 Suche: O(k · n1− k + R) Aufbau des Baumes mittels Aufteilung der sortierten Punktefolge an den Median-Elementen → balanciert Suche analog wie bei Binärbäumen, unter Beachtung der aktuellen Dimension