2015-10-23 16 views
12

Sagen wir, ich habe folgendes Polygon und Point:Suche Koordinate nächsten Punkt auf Polygon Shapely

>>> poly = Polygon([(0, 0), (2,8), (14, 10), (6,1)]) 
>>> point=Point(12,4) 

enter image description here

ich die Entfernung der Punkt berechnen kann auf das Polygon ...

>>> dist=point.distance(poly) 
>>> print dist 
2.49136439561 

... aber ich würde gerne die Koordinate des Punktes an der Polygongrenze kennen, an der die kürzeste Distanz gemessen wird.

Mein erster Ansatz ist es, den Punkt durch seinen Abstand zum Polygon zu puffern, und finden Sie den Punkt, an dem die Kreistangente zu dem Polygon ist:

>>> buff=point.buffer(dist) 

enter image description here Allerdings bin ich mir nicht sicher, wie um diesen Punkt zu berechnen. Die beiden Polygone kreuzen sich nicht, also gibt mir list(poly.intersection(buff)) diesen Punkt nicht.

Bin ich damit auf dem richtigen Weg? Gibt es eine einfachere Methode?

+2

Doppelt? http: // Stapelüberlauf.com/questions/10983872/Abstand von einem Punkt zu einem Polygon –

+0

@Oleg, ich glaube nicht, dass dies ein Duplikat ist. Wie ich oben erwähnt habe, habe ich kein Problem, den Mindestabstand zum Polygon zu berechnen. Ich versuche den Punkt an der Polygongrenze zu finden, an dem der Mindestabstand gemessen wird. – AJG519

+0

Wäre neugierig zu wissen, wie man die Entfernung erreichen kann, wenn der Punkt innerhalb des Polygons liegt. Zum Beispiel, wenn: 'Punkt = Punkt (4,4)' – kuanb

Antwort

14

Es gibt eine einfache Möglichkeit, dies auf formschöne Funktionen zu übertragen. Zuerst müssen Sie den äußeren Ring des Polygons erhalten und den Punkt auf den Ring projizieren. Es ist zwingend notwendig, das Äußere als LinearRing zu erhalten, da Polygone keine Projektionsfunktion haben. Im Gegensatz zur Intuition gibt dies eine Entfernung, die Entfernung vom ersten Punkt des Rings zu dem Punkt in dem Ring am nächsten zu den gegebenen Punkt. Dann verwenden Sie nur diese Entfernung, um den Punkt mit die Interpolate-Funktion zu erhalten. Siehe den folgenden Code.

from shapely.geometry import Polygon, Point, LinearRing 

poly = Polygon([(0, 0), (2,8), (14, 10), (6,1)]) 
point = Point(12,4) 

pol_ext = LinearRing(poly.exterior.coords) 
d = pol_ext.project(point) 
p = pol_ext.interpolate(d) 
closest_point_coords = list(p.coords)[0] 

Es ist wichtig, dass diese Methode funktioniert nur zu erwähnen, wenn Sie die Punkt wissen außerhalb der Außenseite des Polygons ist. Wenn sich der Punkt innerhalb eines seiner inneren Ringe befindet, müssen Sie den Code für diese Situation anpassen.

Wenn das Polygon keine inneren Ringe hat, funktioniert der Code auch für Punkte innerhalb des Polygons. Das liegt daran, dass wir tatsächlich mit dem äußeren Ring als Linienkette arbeiten und ignorieren, ob die Linienkette von einem Polygon kommt oder nicht.

Es ist einfach, diesen Code auf den allgemeinen Fall der Berechnung der Entfernung eines beliebigen Punktes (innerhalb oder außerhalb des Polygons) zum nächsten Punkt in der Polygongrenze zu erweitern. Sie müssen nur den nächsten Punkt (und Abstand) vom Punkt zu allen Linienringen berechnen: dem äußeren Ring und jedem inneren Ring des Polygons. Dann behalten Sie nur das Minimum von diesen.

enter image description here

+0

ist dies perfekt. Ich kannte diese formschönen Funktionen nicht. Kann das auch funktionieren, wenn der äußere Punkt stattdessen ein Polygon ist? Ich habe versucht, pol_ext.project() sowohl zu einem Polygon als auch zu einer Linienfolge zu verwenden, bekomme aber die Fehlermeldung "Das dritte Argument von GEOSProject_r muss Point * sein". Irgendwelche Vorschläge dazu? – AJG519

+0

Nicht, dass ich weiß. Ich denke, dafür hast du keine andere Wahl, als etwas selbst zu implementieren. Tome Karzes Antwort kann leicht zu diesem Szenario hinzugefügt werden (aber mit einem der Polygone als "der Punkt", da Sie die obige Methode haben). – eguaio

+0

In der Antwort der Frage http://stackoverflow.com/questions/38514607/find-shortest-path-from-one-geometry-to-other-on-shapely/38997756#38997756 können Sie eine Implementierung von Tom Karzes finden vorgeschlagener Algorithmus, um den Abstand zwischen zwei sich nicht überschneidenden Linien zu erhalten. Der Code dort kann leicht angepasst werden, um den Abstand zwischen einer Linienfolge und einem Punkt zu erhalten, und hängt nicht von formschönen Funktionen ab. – eguaio

0

Es gibt zwei Fälle, die zwei berücksichtigen: (1) der nächste Punkt liegt an einer Kante und (2) der nächste Punkt ist ein Eckpunkt. Fall (2) ist leicht zu überprüfen - nehmen Sie einfach die Entfernung zu jedem Eckpunkt und finden Sie das Minimum. Fall (1) beinhaltet etwas mehr Mathematik, ist aber immer noch nicht so schlecht. Sie müssen zwei Dinge für den Fall (1) tun: (a) Finden Sie, wo die Normale vom Punkt zur Kante die Kante schneidet, und (b) verifizieren Sie, dass sie innerhalb des Liniensegments liegt (im Gegensatz zu einem der endet). Wenn es nicht auf dem Liniensegment liegt, ignoriere es (einer der Scheitelpunkte ist der nächste Punkt an dieser Kante).

Verwandte Themen