finden überlappende Rechtecke Algorithmus
sagen wir, ich habe eine riesige Menge von nicht-überlappenden Rechteck mit ganzzahligen Koordinaten, die fest ein für alle mal
Habe ich ein weiteres Rechteck mit ganzzahligen Koordinaten, deren Koordinaten verschieben (aber Sie können davon ausgehen, dass Ihre Größe ist konstant)
Was ist der effizienteste Weg, um herauszufinden, welche Rechtecke sind in sich überschneidenden (oder innen) Ein?
Kann ich nicht einfach eine Schleife durch mein set, wie es ist zu groß. Dank
edit : die Rechtecke sind alle parallel zu der Achse
- Sie haben auf jeden Fall zu überprüfen, und jedes Rechteck. Wenn Sie zu tun, um machen Sie es schnell, auch das ist eine andere Frage...
- Erinnert mich an ein US-immigration-Formular Frage. Umschreibung es - "Sind Sie ein terrorist?" 😀
- Doug T : NÖ
- Quad-Bäume: en.wikipedia.org/wiki/Quadtree
- m0skit0 :ich dachte, der mit einer Variante des Austragungs-und beschneiden, ich glaube nicht, dass ich brauche, um zu überprüfen, alle der Rechtecke
- Räumliche Datenstrukturen zur Rettung kommen hier. Der Nachteil ist, müssen Sie in der Regel auf der Suche eine Menge, um zu amortisieren sich die Kosten für den Bau der Struktur.
- Versuchen Sie auch eine Suche nach "R-Bäume".
- So, die erste position gesucht werden, die mit einer der beschriebenen Methoden. Allerdings, wenn Sie haben diese position, wenn Sie oben/unten/Links/rechts-Zeiger in Ihre Objekte, die Sie sollten in der Lage sein, um die nächste Kreuzung, ohne erneut die Suche..
- Dumme person-Algorithmus (meint 'superrectangles' kollidieren nicht]: ich denke, man könnte organisieren, die eine Reihe von Rechtecken in Gruppen, sind begrenzt durch eine 'superrectangle'. Diese superrectangles in Gruppen, und wiederholen Sie, bis Sie haben ein mega superrectangle. Nun, sehen Sie, wenn Rechteck
A
ist innerhalb der Grenzen der jede der subrectangles. Wenn es ist, teilen Sie die superrectangle, und versuchen Sie es erneut. Wiederholen Sie, bis es ist nichts mehr übrig. - Sie sind im Grunde die Beschreibung einer bounding volume Hierarchie (In diesem Fall wäre es das Begrenzungsbereich-Hierarchie, wenn)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Persönlich würde ich dies lösen, mit einem KD-Baum oder ein BIH-Baum. Sie sind beide adaptive räumliche Datenstrukturen, die eine log(n) bei der Suche Zeit. Ich habe eine Implementierung für meine Ray-Tracer, und Sie Schreien.
-- UPDATE --
Speichern Sie alle Ihre festen Rechtecke in dem KD-Baum. Wenn Sie testen Kreuzungen, Durchlaufen die KD-Baum wie folgt:
Diese Funktion sollte funktionieren, nach der Umwandlung von pseudo-code, aber der Algorithmus ist korrekt. Dies ist eine log(n) search-Algorithmus, und wahrscheinlich die langsamste Implementierung von it - (konvertieren von rekursiv mit stack-basiert).
-- UPDATE -- Hinzugefügt eine einfache KD-Baum-Gebäude-Algorithmus
Die einfachste form eines KD-Baumes, enthält die Flächen/Volumen-Formen ist die folgende:
Gibt es eine Reihe von offensichtlichen Optimierungen hier, aber die build-Zeit ist in der Regel nicht so wichtig wie die Suche nach Zeit. That being said, eine gut bauen Baum ist, was macht die Suche schnell. Look-up SAH-KD-Tree, wenn Sie möchten lernen, wie man eine schnelle kd-Baum.
Ich Wette, Sie könnten eine Art von Ableitung eines quadtree, dies zu tun. Werfen Sie einen Blick auf dieses Beispiel.
Können Sie erstellen, die zwei Vektoren Rechteck Indizes (weil zwei Diagonale Punkte eindeutig definieren das Rechteck), und Sortieren Sie Sie, indem Sie eine der Koordinaten. Dann suchen Sie überlappt mit diesen beiden index-arrays, die gehen, um logarithmische statt lineare Komplexität.
Können Sie eine zufällige "walking" - Algorithmus ... im Grunde erstellen Sie eine Liste von Nachbarn für alle Ihre Feste position Rechtecke. Dann nach dem Zufallsprinzip wählen Sie eine der festen position der Rechtecke, und überprüfen, um zu sehen, wo die Ziel-Rechteck ist im Vergleich zu den gängigen fixed-position-Rechteck. Wenn es nicht in das Rechteck, das Sie nach dem Zufallsprinzip ausgesucht als Ausgangspunkt, dann wird es in eine der acht Richtungen, die korrespondierend zu einem bestimmten Nachbarn, der Ihrer aktuellen position fixiert Rechteck (D. H. für eine gegebene Rechteck es wird ein Rechteck in der N, NE, E, SE, S, SW, W, NW Richtungen). Wählen Sie die benachbarten Rechteck in die nächste Richtung gegeben, um Ihr Ziel, Rechteck -, und re-test. Dies ist im wesentlichen eine randomisierte inkrementelle Konstruktion, Algorithmus, und es ist die Leistung neigt dazu, sehr gut für geometrische Probleme (in der Regel logarithmisch, die für eine einzelne iteration, und O(n log n) für die wiederholte Iterationen).
Erstellen Sie eine matrix mit "quadrant" - Elementen, wobei jeder quadrant repräsentiert eine N*M Speicherplatz in Ihrem system, mit N und M wird die Höhe und Breite an der breitesten und höchsten Rechtecke, jeweils. Jedes Rechteck wird platziert in einem Quadranten element auf der Grundlage der oberen linken Ecke (jedes Rechteck wird in genau einem Quadranten). Gegeben ein Rechteck Ein, überprüfen Sie auf Kollisionen zwischen Rechtecke in Einem eigenen Quadranten und die 8 angrenzenden Quadranten.
Dies ist ein Algorithmus, den ich erinnere mich da empfohlen, als eine einfache Optimierung für brute-force-hit-tests bei der Kollisionsprüfung für game design. Es funktioniert am besten, wenn Sie hauptsächlich den Umgang mit kleinen Objekten, obwohl, wenn Sie ein paar große Objekte können Sie vermeiden, wrecking seine Effizienz durch durchführen der Kollisionserkennung für Sie separat und nicht indem Sie in einem Quadranten, wodurch quadrant Größe.
Als Sie sich nicht überlappen, würde ich vorschlagen, einen Ansatz ähnlich (aber nicht gleich) Jason Moore (B).
Sortieren Sie das array von x der oberen linken Ecke.
Und Art eine Kopie von y der linken oberen Ecke. (natürlich würden Sie nur Sortieren, die Pointer auf diese, um Speicherplatz zu sparen).
Jetzt einmal zwei Sätze Sliding_Window_X und Sliding_Window_Y.
Suchen Sie mit binary search sobald Sie Ihre x-Koordinate (oben Links) für Ihre Ein Fenster, in dem x-array sortiert und Ihre y-Koordinate. Sie setzen Ihre Ergebnisse in die corrospondng Sliding_Window_Set. Nun fügen Sie alle folgenden Rechtecke in der sortierten Arrays haben eine geringere x(y) (diesmal unten rechts) koordinieren als Ihre rechts unten A.
Dem Ergebnis, dass Sie in Ihrem Sliding_Window-sets, die windows -, die sich überschneiden, mit dem Ein in einem Koordinatensystem. Die überdeckung von A ist die Schnittmenge von Sliding_Window_X und _Y.
Den Sliding_Window sets können problemlos dargestellt werden, indem nur 2 zahlen (begin-und end-index des corrosponding sortierten array).
Wie Sie sagen, Sie bewegen Ein, es ist jetzt wirklich einfach, zu berechnen, die sich überschneiden. Je nach Richtung können Sie nun hinzufügen/entfernen von Elementen der Sliding_Window gesetzt. I. e. Sie nehmen einfach das nächste element aus der sortierten array an der Vorderseite/Ende des Satzes und vielleicht entfernen Sie am Ende.
Topcoder bietet eine Möglichkeit, um zu bestimmen, liegt ein Punkt innerhalb eines Rechtecks. Es sagt, dass, sagen wir, wir haben einen Punkt x1,y1 und ein Rechteck. Sollten wir wählen einen beliebigen Punkt sehr weit Weg vom aktuellen Ort des Verweises in dem rechteckigen Koordinatensystem sagen, x2,y2.
Nun wir sollten ein Liniensegment, das die Punkte x1,y1 und x2,y2. Wenn das Liniensegment schneidet ungerade Anzahl von Seiten des gegebenen Rechtecks (es werden 1 in unserem Fall, kann diese Methode erweitert werden, um Allgemeine Polygone als gut), dann ist der Punkt x1,y1 liegt innerhalb des Rechtecks und, wenn es schneidet sogar die Anzahl der Seiten liegt außerhalb des Rechtecks.
Gegeben sind zwei Rechtecke, wir müssen wiederholen Sie diesen Vorgang für jede Ecke der 1 Dreieck möglicherweise liegen in der zweiten Dreieck. Auf diese Weise wären wir in der Lage, um zu bestimmen, ob sich zwei Rechtecke überlappen, auch wenn Sie nicht ausgerichtet auf die x-oder y-Achse.
Intervall-Bäume: Sind BSTs entwickelt, mit der Einnahme von 'lo' - Wert als Schlüssel, in einem Intervall. So, zum Beispiel, wenn wir einfügen wollen (23, 46) in dem Baum, wir würden einfügen mit '23' in den BST.
Auch, mit Intervall-Bäume an jedem Knoten, halten wir den maximalen Ausschlag (hi-Wert) der sub-Baum verwurzelt an diesem Knoten.
Dieser Reihenfolge von Platzhaltern können Sie uns Suche für alle 'R' Schnittpunkte in R(logN) Zeit. [Wir suchen nach der ersten Kreuzung in logN Zeit und alle R in RlogN Zeit] Bitte beziehen Sie sich auf Intervall-Bäume Dokumentation, wie insert, search fertig ist und die details von Komplexität.
Nun für dieses problem nutzen wir einen Algorithmus, bekannt als sweep-line-Algorithmus. Vorstellen, dass wir eine vertikale Linie (parallel zur y-Achse), die fegt den 2D-Raum-und in diesem Prozess schneidet die Rechtecke.
1) Ordnen Sie die Rechtecke in aufsteigender Reihenfolge der x-cordinates (left-edge-wise), die entweder über die Priorität der Warteschlange oder über die Sortierung . Komplexität NlogN wenn N Rechtecke.
2) Da diese Linie fegt von Links nach rechts, sind die Schnittmenge Fällen:
Wenn die Linie schneidet die linke Seite eines Rechtecks nie gesehen, fügen Sie die y-co-ords des Rechtecks Seite der Intervall-Baum. [sagen, (x1,y1) und (x1,y2) sind Links-Rand-Koordinaten der Rechteck-hinzufügen-Intervall (y1, y2) der Intervall-Baum] ---> (NlogN)
Mache eine Bereichssuche auf die Intervall-Baum. [sagen, (x1,y1) und (x1,y2) sind Links-Rand-Koordinaten des Rechtecks, nehmen Sie das Intervall (y1,y2) und ein Intervall Kreuzung Abfrage auf dem Baum zu finden, der alle Kreuzungen] ---> RlogN (in der Praxis)
Wenn die Linie schneidet die Rechte Seite des Rechtecks, entfernen Sie das y-Koords aus der Intervall-Baum ist wie das Rechteck ist nun komplett abgearbeitet. ----> NlogN
Gesamt-Komplexität : NlogN + RlogN
Lassen Sie Ihre Rechteck sein (Xi1,Yi1,Xi2,Yi2), wo ich variiert von 0 bis N.
Rechteck A und B können sich NICHT kreuzenden, wenn Ax1 > Bx2 || Ay1 < By2 || Bx1 > Ax2 || By1 < Ay2.
Erstellen von Baum ist optimiert für range/interval (Für exa: segment-Baum oder Intervall-Baum)
Sehen http://w3.jouy.inra.fr/unites/miaj/public/vigneron/cs4235/l5cs4235.pdf
Verwenden Sie diesen Baum zu finden set von triangle, während Ihr Dreieck ist das ändern von Koordinaten.
Durch die Berechnung der Fläche eines jeden Rechtecks und der überprüfung der Länge L, Höhe H und die Fläche von Rechtecken, ob unter-oder überschreitet nicht die Länge und die Höhe und Fläche eines Rechtecks Ein
Methode (A)
Man könnte eine Intervall-Baum oder segment-Baum. Wenn die Bäume waren so angelegt, dass Sie würde ausgeglichen werden, dies würde Ihnen eine Laufzeit von O(log n). Ich nehme an, diese Art der Vorverarbeitung ist praktisch, denn es würde nur passieren, wenn (wie es scheint, Sie beschäftigen sich mehr mit der Laufzeit, sobald das Rechteck beginnt sich zu bewegen, als Sie mit der Menge der anfänglichen Vorverarbeitung für die erste Zeit). Der Speicherplatz wäre O(n) oder O(n log n) je nach Ihrer Auswahl oben.
Methode (B)
Gegeben, dass Ihre große Menge der Rechtecke mit fester Größe, und nie ändern Sie Ihre Koordinaten, und dass Sie sich nicht überlappen, könnten Sie versuchen, einen etwas anderen Stil des Algorithmus/Heuristik als vorgeschlagen, von anderen hier (vorausgesetzt, Sie Leben können mit einer einmaligen, im Voraus Vorverarbeitung Gebühr).
Preprocessing-Algorithmus [O(n log n) oder O(n^2) Laufzeit {nur einmal ausgeführt, obwohl}, O(n) space]
Berechnen Sie ein Verteilungsfunktion und ein cumulative distribution function der horizontalen Koordinaten. (Laufzeit von O(1) O(n^2) je nach Methode verwendet und welche Art von distribution Sie Ihre Daten verfügt)
Wenn a) die Rechtecke die horizontalen Koordinaten Folgen einige natürlich vorkommenden Prozess, dann können Sie wahrscheinlich schätzen Ihre Verteilungsfunktion durch die Verwendung einer bekannten Verteilung (ex: normal, exponentielle, uniform, etc.).
b) Wenn Ihr Rechtecke, horizontalen Koordinaten Folgen Sie einer bekannten Verteilung, dann berechnen Sie eine benutzerdefinierte/geschätzte Verteilung durch die Schaffung einer Histogramm.
Berechnen Sie ein Verteilungsfunktion und ein cumulative distribution function der vertikalen Koordinaten.
Wenn a) die Rechtecke die vertikalen Koordinaten Folgen einige natürlich vorkommenden Prozess, dann können Sie wahrscheinlich schätzen Ihre Verteilungsfunktion durch die Verwendung einer bekannten Verteilung (ex: normal, exponentielle, uniform, etc.).
b) Wenn die Rechtecke die vertikalen Koordinaten nicht nach einer bekannten Verteilung, dann berechnen Sie eine benutzerdefinierte/geschätzte Verteilung durch die Schaffung einer Histogramm.
Echtzeit-Kreuzung zu Finden-Algorithmus [Überall von O(1) O(log n) O(n) {Hinweis: wenn Sie O(n), dann ist die Konstante vor dem n wäre sehr klein} Laufzeit, je nachdem wie gut die Verteilungs-Funktionen, passen Sie das dataset]
Unter die horizontale Koordinate, Ihre beweglichen Rechteck und stecken Sie es in die kumulative Dichte-Funktion der horizontalen Koordinaten der vielen Rechtecke. Diese Ausgabe wird eine Wahrscheinlichkeit (Wert zwischen 0 und 1). Multiplizieren Sie diesen Wert mal n (wo n ist die Anzahl der vielen Rechtecke, die Sie haben). Dieser Wert wird dem array-index zu überprüfen, in der sortiert Rechteck-Liste. Wenn das Rechteck von diesem array-index geschieht, zu verschneiden, dann sind Sie fertig und können mit dem nächsten Schritt fortfahren. Andernfalls müssen Sie zum Scannen der umliegenden Nachbarn, um zu bestimmen, wenn die Nachbarn die sich mit der bewegten Rechtecks. Sie können angreifen, der diesen Teil des Problems mehrere Möglichkeiten:
a) ein linear-scan, bis zu finden die sich überschneidenden Rechteck oder finden Sie ein Rechteck auf der anderen Seite der sich bewegenden Rechteck
b) berechnen Sie eine Konfidenzintervall über die Wahrscheinlichkeits-Dichte-Funktionen, die Sie berechnet, um Ihnen eine bestmögliche Schätzung zu möglichen Grenzen (d.h. ein Intervall, in denen ein Schnittpunkt liegen muss). Führen Sie dann eine binäre Suche auf diesem kleinen Intervall. Wenn die binäre Suche nicht, dann wieder zurück zu einer linearen Suche in Teil (a).
Tun die gleiche Sache wie Schritt 1, aber tun Sie es für die vertikalen Teile anstatt der horizontalen Teile.
Wenn Schritt 1 ergab eine Kreuzung zu und Schritt 2 ergab eine Kreuzung und die sich überschneidenden Rechteck in Schritt 1 wurde das gleiche Rechteck wie in Schritt 2, dann ist das Rechteck muss die Schnittmenge mit dem beweglichen Rechteck. Ansonsten gibt es keinen Schnittpunkt.
Verwenden Sie ein R+ - Baum, das ist dann wahrscheinlich genau die spezifische Struktur, die Sie suchen. R+ - Bäume explizit erlauben keine überschneidungen in den internen (nicht-Blatt -) Struktur im Austausch für Geschwindigkeit. Solange kein Objekt vorhanden ist in mehrere Blätter auf einmal, es gibt keine überschneidungen. In Ihrer Umsetzung, sondern als Unterstützung überlagern, wenn ein Objekt Hinzugefügt werden muss, um mehrere Blätter, die nur true zurückgeben, statt.
Hier ist eine detaillierte Beschreibung der Daten Struktur, einschließlich, wie Sie zur Verwaltung der Rechtecke:
Der R+-tree: A dynamic index for multi-dimensional objects