Gegeben zwei Polygone:
POLYGON((1 0, 1 8, 6 4, 1 0))
POLYGON((4 1, 3 5, 4 9, 9 5, 4 1),(4 5, 5 7, 6 7, 4 4, 4 5))
Wie kann ich die Vereinigung (kombiniertes Polygon) berechnen?
Daves Beispiel verwendet den SQL-Server, um die Union herzustellen, aber ich muss dasselbe im Code erreichen. Ich suche nach einer mathematischen Formel oder einem Codebeispiel in einer beliebigen Sprache, die die tatsächliche Mathematik aufdeckt. Ich versuche Karten zu erstellen, die Länder dynamisch in Regionen zusammenfassen. Ich habe hier eine verwandte Frage gestellt: Gruppieren von geographischen Formen
Das ist eine sehr gute Frage. Ich habe vor einiger Zeit denselben Algorithmus in c # implementiert. Der Algorithmus konstruiert eine gemeinsame Kontur aus zwei Polygonen (d. H. Konstruiert eine Vereinigung ohne Löcher). Hier ist es.
Eingabe: erstes Polygon (n Punkte), zweites Polygon (m Punkte). Ausgabe: Grafik. Scheitelpunkt - Polygon-Schnittpunkt.
Wir sollten Schnittpunkte finden. Durchlaufen Sie alle Polygonseiten in beiden Polygonen [O (n * m)] und suchen Sie nach Schnittpunkten.
Wenn keine Kreuzung gefunden wird, fügen Sie einfach Scheitelpunkte hinzu und verbinden Sie sie mit dem Rand.
Wenn Schnittpunkte gefunden werden, sortieren Sie diese nach Länge bis zum Startpunkt, fügen Sie alle Knoten (Start-, End- und Schnittpunkte) hinzu und verbinden Sie sie (bereits in der Reihenfolge ) Mit dem Edge .
Wenn beim Erstellen des Diagramms keine Schnittpunkte gefunden wurden, liegt eine der folgenden Bedingungen vor:
Ermitteln Sie die minimalen x- und y-Koordinaten (minx, miny). Dann ermitteln Sie den Mindestabstand zwischen (Minx, Miny) und den Polygonpunkten. Dieser Punkt wird der Punkt ganz links sein.
Wir beginnen, den Graphen vom linken unteren Punkt aus zu durchqueren und fahren fort, bis wir wieder hinein kommen. Am Anfang markieren wir alle Kanten als nicht besucht. Bei jeder Wiederholung sollten Sie den nächsten Punkt auswählen und als besucht markieren.
Um den nächsten Punkt zu wählen, wählen Sie eine Kante mit einem maximalen Innenwinkel gegen den Uhrzeigersinn.
Ich berechne zwei Vektoren: vector1 für die aktuelle Kante und vector2 für jede nächste nicht besuchte Kante (wie im Bild dargestellt).
Für Vektoren berechne ich:
Als Ergebnis bekomme ich eine Kante (und einen entsprechenden nächsten Scheitelpunkt) mit dem maximalen Winkel.
Ich füge jeden übergebenen Knoten zur Ergebnisliste hinzu. Ergebnisliste ist das Vereinigungspolygon .
Dies ist ein herausforderndes, aber gut verstandenes Thema, das häufig unter dem Namen "Regularisierte Boolesche Operationen auf Polygonen" geführt wird. Sie können sich diese MathOverflow-Antwort ansehen, das die folgende Abbildung enthält (aus Alan Murtas Schnittbibliothek ), mit der pinkfarbenen Vereinigung der OPs kombinieren :
Sie müssen bestimmen, welche Punkte in liegen. Nach dem Entfernen dieser Punkte können Sie einen Satz "Außenpunkte" in den anderen einfügen. An den Einfügepunkten (z. B. wo sich der Pfeil rechts im Bild befindet) mussten Sie Punkte aus den Eingabesätzen entfernen.
Gute Frage! Ich habe das noch nie versucht, aber ich werde jetzt einen Riss darauf werfen.
Erstens: Sie müssen wissen, wo sich diese beiden Formen überlappen. Um dies zu tun, können Sie jede Kante in Polygon A und die Schnittpunkte und Kante in Polygon B sehen. In diesem Beispiel sollten zwei Schnittpunkte vorhanden sein.
Dann: Machen Sie die Vereinigungsform. Sie können alle Scheitelpunkte in A und B sowie die Schnittpunkte nehmen und dann die Scheitelpunkte ausschließen, die in der endgültigen Form enthalten sind. Um diese Punkte zu finden, sieht es so aus, als könnten Sie einfach einen Scheitelpunkt von A finden, der sich in B befindet, und einen Scheitelpunkt von B, der sich in A befindet.
Versuchen Sie gpc .
Eine Lösung, die ich mit BSP-Bäumen gesehen habe, ist hier .
Grundsätzlich beschreibt es den Schnittpunkt als Vereinigung der Kanten des Polygons A, die sich innerhalb des Polygons B befinden (einschließlich Teilkanten und mit einem BSP-Baum berechnet). Dann können Sie A/B als ~ (~) definierenEIN/\~B), wobei ~ die Wicklung des Polygons umkehrt,/die Vereinigung und/\ den Schnittpunkt.
Wenn Sie Länder gruppieren, hoffe ich, dass es keine Überschneidungen gibt. Sie könnten einen ziemlich naiven Algorithmus verwenden, der nach gemeinsam genutzten Scheitelpunkten sucht. Eine einfache Ansicht wäre, die Punkte eines Polygons zu durchlaufen und zu prüfen, ob sie sich auf einem der anderen Polygone befinden und teilt denselben nächsten oder vorherigen Punkt, um zu sehen, ob es eine Übereinstimmung gibt. Dann entfernen Sie einfach den gemeinsamen Scheitelpunkt, um Ihre Vereinigung zu erstellen
Ich musste dieses Problem heute lösen und fand die Lösung mit dieser lib: http://www.cs.man.ac.uk/~toby/alan/software/ .
Es gibt viele Sprachimplementierungen die Liste hier einschließlich Java, Obj-C, C #, Lua, Python und mehr.
Ich bin auf dasselbe Problem gestoßen und habe das Problem folgendermaßen gelöst
Cython-Wrapper für die C++ - Übersetzung der Angus Johnson's Clipper-Bibliothek (Version 6.4.2) https://github.com/fonttools/pyclipper
pc = pyclipper.Pyclipper()
def get_poly_union(polygons):
pc.AddPaths(polygons, pyclipper.PT_SUBJECT, True)
solution = pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
return solution[0]
print_image = image.copy()
solution = get_poly_union(polygons_array)
#polygons_array=[polygon,polygon,polygon, ...,polygon] and polygon=[point,point,point...,point]
cv2.drawContours(print_image, [np.asarray(solution)], -1, (0, 255, 0), 2)
plt.imshow(print_image)
Dies ist eine sehr alte Frage, aber Union_ Funktion von Boost hat für mich funktioniert.
Sehen Sie sich diesen Ausschnitt unten an:
#include <iostream>
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/foreach.hpp>
int main()
{
typedef boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > polygon;
polygon green, blue;
boost::geometry::read_wkt(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", green);
boost::geometry::read_wkt(
"POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))", blue);
std::vector<polygon> output;
boost::geometry::union_(green, blue, output);
int i = 0;
std::cout << "green || blue:" << std::endl;
BOOST_FOREACH(polygon const& p, output)
{
std::cout << i++ << ": " << boost::geometry::area(p) << std::endl;
for (int i = 0; i < p.outer().size(); i++)
{
std::cout << p.outer().at(i).x() << " " << p.outer().at(i).y() << std::endl;
}
}
return 0;
}