Ich muss in Google Maps einen Schwerpunkt (oder Beschriftungspunkt) für unregelmäßig geformte Polygone finden. Ich zeige InfoWindows für Pakete und brauche einen Platz, um das InfoWindow zu verankern, das sich garantiert auf der Oberfläche befindet. Siehe Bilder unten.
In Wirklichkeit brauche ich nichts Google Maps-spezifisches, sondern suche nur nach einer Idee, wie man diesen Punkt automatisch findet.
Meine erste Idee war es, den "falschen" Schwerpunkt zu finden, indem ich die durchschnittlichen Breiten und Längen und die zufällig platzierten Punkte von dort aus nehme, bis ich einen finde, der das Polygon schneidet. Ich habe bereits den Point-in-Polygon-Code. Das kommt mir einfach furchtbar "hackig" vor.
Ich sollte beachten, dass ich keinen Zugriff auf den serverseitigen Code habe, der die Geometrie ausgibt, sodass ich nichts wie ST_PointOnSurface (the_geom) tun kann.
Möglicherweise möchten Sie Folgendes überprüfen: http://github.com/tparkin/Google-Maps-Point-in-Polygon
Es scheint einen Ray Casting-Algorithmus zu verwenden, der dem von Ihnen vorgestellten Fall entsprechen sollte.
Hier gibt es einen Blogbeitrag dazu. http://appdelegateinc.com/blog/2010/05/16/point-in-polygon-checking/
quelle
Ein (älterer) ESRI-Algorithmus berechnet den Massenmittelpunkt und verschiebt ihn nach dem Testen auf Einbeziehung in das Polygon bei Bedarf horizontal, bis er innerhalb des Polygons liegt. (Dies kann auf viele Arten geschehen, je nachdem, welche grundlegenden Operationen in Ihrer Programmierumgebung verfügbar sind.) Dies führt dazu, dass Beschriftungspunkte ziemlich nahe am visuellen Zentrum des Polygons erzeugt werden: Probieren Sie es in der Abbildung aus.
quelle
Ich habe mein Problem gelöst, indem ich den populären epoly-Code von http://econym.org.uk/gmap erweitert habe . Im Grunde war das, was ich getan habe:
Erweiterter epoly Code unten:
Immer noch ein bisschen verrückt, aber es scheint zu funktionieren.
quelle
Ein anderer 'schmutziger' Algorithmus, um das zu tun:
Nehmen Sie den Begrenzungsrahmen der Geometrie
(Xmax, Ymax, Xmin, Ymin)
Schleife, bis ein zufälliger Punkt
( Xmin+rand*(Xmax-Xmin), Ymin+rand*(Ymax-Ymin) )
in der Geometrie gefunden wird (mit Google-Maps-Point-in-Polygon )quelle
In Anbetracht Ihrer jüngsten Klarstellung, dass Sie eine rein interne Position bevorzugen, können Sie jeden Punkt in der medialen Achsentransformation auswählen, der sich nicht auch an der Grenze des Polygons befindet. (Wenn Sie keinen Code für eine MAT haben, können Sie ihn durch negatives Puffern des Polygons approximieren. Bei einer binären oder sekantenbasierten Suche wird schnell ein kleines inneres Polygon erzeugt, das einem Teil der MAT nahekommt. Verwenden Sie einen beliebigen Punkt an der Grenze.)
quelle
Warum nicht den Schwerpunkt nur für die vertikale Position (Breitengrad) verwenden? Anschließend können Sie das Etikett horizontal positionieren, indem Sie den durchschnittlichen Längengrad bei diesem Breitengrad auswählen . (Dazu müssen Sie den Längengrad für eine Polygonkante bei einem bestimmten Breitengrad ermitteln, was Ihnen keine Probleme bereiten sollte.)
Achten Sie auch auf U-Formen und komplexere. :) Wählen Sie unter Umständen den Durchschnitt des äußersten rechten Längenpaars (jedes Paar würde einem Schnitt des Polygons entsprechen), da das Infofenster so ausgerichtet ist.
Dies gibt Ihnen auch ein wenig mehr Kontrolle über die Positionierung. Beispielsweise kann es hilfreich sein, das Infofenster vertikal auf 66 oder 75% zu positionieren, um mehr vom Polygon sichtbar zu machen. (Oder es kann nicht! Aber Sie haben den Knopf zu zwicken.)
quelle
Wie wäre es, wenn Sie nur den Punkt verwenden, auf den der Benutzer geklickt hat, um ihn auszuwählen, wenn er vom betreffenden Benutzer ausgewählt wurde?
quelle
Ich versuche das auch zu lösen. Ich habe meinen Polygonen die Bedingung auferlegt, dass sie keine sich kreuzenden Linien haben dürfen, die in das eingehen, was ich beschreiben werde.
Mein Ansatz verwendet also Triangulation. Nehmen Sie einen zufälligen Scheitelpunkt (möglicherweise nehmen Sie einen Scheitelpunkt am äußersten Punkt N, E, W oder S, um die Dinge zu vereinfachen).
Zeichnen Sie von diesem Scheitelpunkt Linien zu dem einen Scheitelpunkt entfernten Scheitelpunkt, dh wenn Ihr Scheitelpunkt Scheitelpunkt 3 ist, schauen Sie auf Scheitelpunkt 3 + 2.
Konstruieren Sie eine Linie von Ihrem ursprünglichen Scheitelpunkt zu diesem Scheitelpunkt. Wenn die konstruierte Linie:
Dann haben Sie ein Dreieck konstruiert, das sich innerhalb des Polygons befindet. Wenn der erfolgreiche Eckpunkt n + 2 war, ist Ihr Dreieck {n, n + 1, n + 2}, was wir als {v, v1, v2} bezeichnen. Wenn nicht, versuchen Sie es mit dem nächsten Scheitelpunkt und fahren Sie fort, bis alle Scheitelpunkte ausprobiert wurden.
Wenn Sie ein Dreieck finden, ermitteln Sie dessen Mittelpunkt, indem Sie eine Linie vom Scheitelpunkt v zum Mittelpunkt von v1 und v2 ziehen. Der Mittelpunkt dieser Linie liegt garantiert innerhalb des Dreiecks und innerhalb des Polygons.
Ich habe dies noch nicht codiert, aber ich kann sehen, wie ich darüber nachdenke, dass ein Polygon mit sich kreuzenden Linien tatsächlich einige exotische Zustände hervorruft, bei denen dies nicht funktioniert. Wenn dies die Art von Polygonen ist, die Sie haben, müssen Sie jedes Liniensegment auf dem Polygon testen und sicherstellen, dass es nicht gekreuzt wird. Überspringen Sie Liniensegmente, die gekreuzt sind, und ich denke, es wird funktionieren.
quelle
https://github.com/mapbox/polylabel kann nützlich sein (Javascript und C ++). C # -Implementierung hier: https://gist.github.com/dfaivre/acfef42cdbf411555956e9eba65dd30d .
Original SO Frage hier: /programming//a/38522611/79113
quelle