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 Teil I Scan-Line Prinzip Geometrische Algorithmen Scan-Line Prinzip Grundlagen Scan-Line Prinzip Idee Gegeben eine 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 sich schneidender Segmente 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 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 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 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 Binärbä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 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 40 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); E 0 = 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 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 Teil II Mehrdimensionale Bereichssuche Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufgabenstellung Gegeben k-dimensionaler, rechteckiger Bereich D n Punkte im k-dimensionalen Raum 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 Handy Geometrische Algorithmen Mehrdimensionale Bereichssuche Lösungsansätze 1-dimensionaler Fall Realisierung: Balancierte Binärbä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) Grid-Methode: Suchraum in Gridzellen unterteilen Mehrdimensionale Bäume Geometrische Algorithmen Mehrdimensionale Bereichssuche 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 Geometrische Algorithmen Mehrdimensionale Bereichssuche Suche 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 Aufbau Erstellung eines effizienten Baums? → Möglichst balanciert, damit Höhe in O(log n) Geometrische Algorithmen Mehrdimensionale Bereichssuche Aufbau Vorgangsweise 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 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 ); } 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) 1 Suche: O(k · n1− k + 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 Binärbäumen, unter Beachtung der aktuellen Dimension