Das ist eine sehr gute Frage. Ich habe vor einiger Zeit den gleichen Algorithmus auf c # implementiert. Der Algorithmus konstruiert eine gemeinsame Kontur aus zwei Polygonen (dh konstruiert eine Vereinigung ohne Löcher). Hier ist es.
Schritt 1. Erstellen Sie ein Diagramm, das die Polygone beschreibt.
Eingabe: erstes Polygon (n Punkte), zweites Polygon (m Punkte). Ausgabe: Grafik. Scheitelpunkt - Polygonpunkt des Schnittpunkts.
Wir sollten Kreuzungen finden. Durchlaufen Sie alle Polygonseiten in beiden Polygonen [O (n * m)] und finden Sie alle Schnittpunkte.
Wenn keine Kreuzung gefunden wird, fügen Sie einfach Scheitelpunkte hinzu und verbinden Sie sie mit der Kante.
Wenn Schnittpunkte gefunden werden, sortieren Sie sie nach Länge bis zu ihrem Startpunkt, fügen Sie alle Scheitelpunkte (Start, Ende und Schnittpunkte) hinzu und verbinden Sie sie (bereits in sortierter Reihenfolge) mit der Kante.
Schritt 2. Überprüfen Sie das konstruierte Diagramm
Wenn wir beim Erstellen des Diagramms keine Schnittpunkte gefunden haben, haben wir eine der folgenden Bedingungen:
- Polygon1 enthält Polygon2 - Rückgabe von Polygon1
- Polygon2 enthält Polygon1 - Polygon2 zurückgeben
- Polygon1 und Polygon2 schneiden sich nicht. Rückgabe von Polygon1 UND Polygon2.
Schritt 3. Suchen Sie den Scheitelpunkt unten links.
Finden Sie die minimalen x- und y-Koordinaten (minx, miny). Finden Sie dann den Mindestabstand zwischen (minx, miny) und den Punkten des Polygons. Dieser Punkt ist der Punkt unten links.
Schritt 4. Konstruieren Sie eine gemeinsame Kontur.
Wir beginnen, den Graphen vom linken unteren Punkt aus zu durchlaufen und fahren fort, bis wir wieder darin sind. Zu Beginn markieren wir alle Kanten als nicht besucht. Bei jeder Iteration sollten Sie den nächsten Punkt auswählen und als besucht markieren.
Um den nächsten Punkt auszuwählen, wählen Sie eine Kante mit einem maximalen Innenwinkel gegen den Uhrzeigersinn.
Ich berechne zwei Vektoren: Vektor1 für die aktuelle Kante und Vektor2 für jede nächste nicht besuchte Kante (wie im Bild dargestellt).
Für Vektoren berechne ich:
- Skalarprodukt (Punktprodukt). Es gibt einen Wert zurück, der sich auf einen Winkel zwischen Vektoren bezieht.
- Vektorprodukt (Kreuzprodukt). Es wird ein neuer Vektor zurückgegeben. Wenn die Z-Koordinate dieses Vektors positiv ist, gibt mir das Skalarprodukt den rechten Winkel gegen den Uhrzeigersinn. Andernfalls (Z-Koordinate ist negativ) berechne ich den Abrufwinkel zwischen Vektoren als 360 - Winkel vom Skalarprodukt.
Als Ergebnis erhalte ich eine Kante (und einen entsprechenden nächsten Scheitelpunkt) mit dem maximalen Winkel.
Ich füge jeden übergebenen Scheitelpunkt zur Ergebnisliste hinzu. Ergebnisliste ist das Vereinigungspolygon.
Bemerkungen
- Dieser Algorithmus ermöglicht es uns, mehrere Polygone zusammenzuführen, um sie iterativ mit Polygonpaaren anzuwenden.
- Wenn Sie einen Pfad haben, der aus vielen Bezierkurven und -linien besteht, sollten Sie diesen Pfad zuerst reduzieren.
Dies ist ein herausforderndes, aber gut verstandenes Thema, das häufig unter dem Namen "regulierte boolesche Operationen für Polygone" geführt wird. Sie können sich diese MathOverflow-Antwort ansehen , die die folgende Abbildung enthält (aus Alan Murtas Clipping-Bibliothek ), mit der rosa Union, die der OP kombiniert :
quelle
Sie müssen bestimmen, welche Punkte darin liegen . Nachdem Sie diese Punkte entfernt haben, können Sie einen Satz "äußerer" Punkte in den anderen einfügen. In Ihren Einfügepunkten (z. B. wo Sie den Pfeil im Bild rechts haben) mussten Sie Punkte aus den Eingabesätzen entfernen.
quelle
Gute Frage! Ich habe das noch nie versucht, aber ich werde es jetzt ausprobieren.
Erstens: Sie müssen wissen, wo sich diese beiden Formen überlappen. Zu diesem Zweck können Sie jede Kante in Polygon A betrachten und sehen, wo sie sich schneidet, und jede Kante in Polygon B. In diesem Beispiel sollten zwei Schnittpunkte vorhanden sein.
Dann: Machen Sie die Verbindungsform. Sie können alle Scheitelpunkte in A und B sowie die Schnittpunkte übernehmen und dann die Scheitelpunkte ausschließen, die in der endgültigen Form enthalten sind. Um diese Punkte zu finden, könnten Sie einfach jeden Scheitelpunkt von A innerhalb von B und jeden Scheitelpunkt von B innerhalb von A finden.
quelle
Versuchen Sie es mit gpc .
quelle
Eine Lösung, die ich bei der Verwendung von BSP-Bäumen gesehen habe, wird hier beschrieben .
Grundsätzlich wird der Schnittpunkt als Vereinigung der Kanten des Polygons A beschrieben , die sich innerhalb des Polygons B befinden (einschließlich Teilkanten und unter Verwendung eines BSP-Baums berechnet ). Dann können Sie A / B als ~ (~ A / \ ~ B ) definieren, wobei ~ das Umkehren der Wicklung des Polygons bezeichnet, / die Vereinigung bezeichnet und / \ den Schnittpunkt bezeichnet.
quelle
Wenn Sie Länder gruppieren, würde ich hoffen, dass es keine Überlappung gibt - Sie könnten einen ziemlich naiven Algorithmus verwenden, der nach gemeinsamen Scheitelpunkten sucht - eine einfache Ansicht wäre, durch die Punkte auf einem Polygon zu iterieren und zu prüfen, ob es sich um eines Ihrer anderen Polygone handelt und teilt den gleichen nächsten oder vorherigen Punkt, um festzustellen, ob eine Übereinstimmung vorliegt. Entfernen Sie dann einfach den gemeinsamen Scheitelpunkt, um Ihre Union zu erstellen
quelle
Ich musste heute das gleiche Problem lösen und fand die Lösung mit dieser Bibliothek: http://www.cs.man.ac.uk/~toby/alan/software/ .
Die Liste enthält viele Sprachimplementierungen, darunter Java, Obj-C, C #, Lua, Python und mehr.
quelle
Dies ist eine sehr alte Frage, aber die Union_- Funktion von Boost hat für mich funktioniert.
Siehe diesen Ausschnitt unten:
quelle
Ich habe das gleiche Problem festgestellt und das Problem auf folgende Weise gelöst
Cython-Wrapper für die C ++ - Übersetzung der Clipper-Bibliothek von Angus Johnson (Version 6.4.2) https://github.com/fonttools/pyclipper
quelle