Geometrische Algorithmen Geometrische Algorithmen Bin Hu Algorithmen und Datenstrukturen 2 Arbeitsbereich für Algorithmen und Datenstrukturen Institut für Computergraphik und Algorithmen Technische Universität Wien Geometrische Algorithmen Einführung Einführung Motivation Effiziente Algorithmen, die aufgrund geometrischer Daten (v.a. Koordinaten) im d-dimensionalen Raum gewisse Eigenschaften ausnutzen Anwendung Bildverarbeitung Computergraphik Chip Design Geometrische Algorithmen Part I Scan-Line Prinzip Geometrische Algorithmen Scan-Line Prinzip Grundlagen Scan-Line Prinzip Idee Gegeben: Menge von Objekten in einem 2D Raum 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 Scan-Line für Schnitt iso-orientierter Liniensegmente Einführung Schnitt iso-orientierter Liniensegmente Aufgabenstellung Gegeben: n horizontale und vertikale Liniensegmente s1 , . . . , sn Gesucht: Alle Paare von Segmente, die sich schneiden H F B C A E G D Geometrische Algorithmen Scan-Line für Schnitt iso-orientierter Liniensegmente Einführung Vereinfachte Annahme Alle Anfangs- und Endpunkte horizontaler Segmenten und alle vertikalen Segmente haben paarweise verschiedene x-Koordinaten Naives Verfahren Alle Paare von Liniensegmenten auf Schnitt testen. Laufzeit: O(n2 ) 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 Beispiel: B C A D E A A AAADD 0 EDDE EE (A,B) (A,C) (C,D) 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 Scan-Line für Schnitt iso-orientierter Liniensegmente Algorithmus Realisierung von L? Benötigte Operationen: 1 Einfügen eines neuen Elements 2 Entfernen eines Elements 3 Bestimmen aller Elemente in [ (p, yu ), (p, yo ) ] (Bereichsabfrage) Mögliche Datenstrukturen Balancierte Suchbäume (AVL, Rot-Schwarz, etc.) Randomisierte Skiplisten ... Geometrische Algorithmen Scan-Line für Schnitt iso-orientierter Liniensegmente Analyse 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 Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Einführung Schnitt von allgemeinen Liniensegmenten Aufgabenstellung 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 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 Ereignisse Anfangspunkt eines Segments Endpunkt eines Segments weitere Ereignisse? Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Einführung Beobachtungen Schneiden sich Segmente si mit sj , dann... 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 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 Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Algorithmus Algorithmus 2 Scan-Line 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.Segment,VS); falls E 0 6= ∅ und E 0 ∈ / ES dann { ES.FügeEin(E 0 ); } NS = SSS.Nachf(E.Segment); E 0 = TesteSchnittErzeugeEreignis(E.Segment,NS); falls E 0 6= ∅ und E 0 ∈ / ES dann { ES.FügeEin(E 0 ); } } 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= ∅ und E 0 ∈ / ES dann { ES.FügeEin(E 0 ); } } 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= ∅ und E 0 ∈ / ES dann { ES.FügeEin(E 0 ); } NS = SSS.Nachf(E.SegmentO); E 0 = TesteSchnittErzeugeEreignis(E.SegmentO,NS); falls E 0 6= ∅ und E 0 ∈ / ES dann { ES.FügeEin(E 0 ); } } } Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Algorithmus Algorithmus 3 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 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 2: E ist Ende eines Segments 1 Vorgänger und Nachfolger von E auf Schnitt testen Gegebenenfalls Schnittpunkt in Ereignisstruktur ES einfügen 2 E aus Scan-Line-Status Struktur SSS entfernen Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Algorithmus Fall 3: E ist Schnittpunkt zweier Segmente so und su 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 Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Analyse Analyse Anzahl der Ereignisse: 2n + k mit k = Anzahl der Schnittpunkte, k = O(n2 ) Zugriff auf Ereignisstruktur ES: O(log n2 ) = O(log n) Zugriff auf Scan-Line-Status Struktur SSS: O(log n) Äußere Schleife wird maximal 2n + k mal durchlaufen Pro Durchlauf maximal 5 Operationen auf ES und SSS Gesamtaufwand: O((n + k) log n) Speicheraufwand: O(n2 ) Geometrische Algorithmen Scan-Line für Schnitt von allgemeinen Liniensegmenten Zusammenfassung Zusammenfassung Scan-Line fegt über eine Menge von Objekten Unterteilung: Tote Objekte, Aktive Objekte, Inaktive Objekte Nur gegenwärtig Aktive Objekte werden betrachtet Statisches 2D Problem → dynamisches 1D Problem Geometrische Algorithmen Part II Mehrdimensionale Bereichssuche Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufgabenstellung Gegeben n Punkte im k-dimensionalen Raum k-dimensionaler, rechteckiger Bereich D Gesucht Alle Punkte, die in D liegen Geometrische Algorithmen Mehrdimensionale Bereichssuche Beispiele Beispiele k = 1: Zahlen in einer Folge zwischen a und b k = 2: Städte in einem Quadrat mit 100 km Seitenlänge und Mittelpunkt Wien k > 2: Datenbankabfragen: Personen mit Eigenschaften haben Informatik studiert zwischen 25 und 39 Jahre alt jährliches Einkommen zwischen 30.000,- und 50.000,besitzen kein Smartphone Geometrische Algorithmen Mehrdimensionale Bereichssuche Lösungsansätze 1-dimensionaler Fall Realisierung: Balancierte Suchbäume, Skiplisten, etc. Aufwand: O(log n + R), R . . . Anzahl der Punkte im Bereich Höhere Dimensionen Naive Methode: alle Punkte durchtesten → O(k · n) Mehrdimensionale Bäume Geometrische Algorithmen Mehrdimensionale Bereichssuche Zweidimensionale Bäume A C G D B E B A E D G F C F Struktur wie binäre Suchbäume Knoten representieren Punkte Verwendet abwechselnd x- und y -Koordinaten als Schlüssel Geometrische Algorithmen Mehrdimensionale Bereichssuche Suche Algorithmus 4 Bereichssuche(Knoten p, Richtung d, Bereich D) falls p 6= NULL dann { falls d == vertikal dann { min = D.y1 ; max = D.y2 ; coord = p.y ; rNeu = horizontal; } sonst { min = D.x1 ; max = D.x2 ; coord = p.x; rNeu = vertikal; } falls p ∈ D dann Ausgabe von p; falls min ≤ coord dann Bereichssuche(p.left, rNeu, D); falls coord ≤ max dann Bereichssuche(p.right, rNeu, D); } Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufbau Aufbau Erstellung eines effizienten Baums? → Möglichst balanciert, damit Höhe in O(log n) Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufbau Vorgehensweise 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 Analoge Fortsetzung mit X1 und Y1 , sowie X2 und Y2 , usw. bis Teilfolgen aus einem Element → Blätter des Baumes Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufbau Algorithmus 5 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); } links = neuer linker Nachfolgeknoten; rechts = neuer rechter Nachfolgeknoten; Aufbau(l, m − 1, links, !Xdir ); Aufbau(m + 1, r , rechts, !Xdir ); } 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 Mehrdimensionale Bereichssuche Höhere Dimensionen Erweiterung auf kD Bäume Analog wie 2D Bäume alle Dimensionen (in abwechselnder Reihenfolge) durchlaufen Performance Aufbau: Θ(k · n log n) Suche: O(k · n 1− k1 + R) Geometrische Algorithmen Mehrdimensionale Bereichssuche Zusammenfassung Zusammenfassung Effiziente Bereichsabfrage mittels mehrdimensionale Bäume Jede Ebene entspricht eine bestimmte Dimension Aufbau des Baumes mittels Aufteilung der sortierten Punktefolge an den Median-Elementen → balanciert Suche analog wie bei Suchbäume, unter Beachtung der aktuellen Dimension