2015-10-23 34 views
12

Dire che ho il seguente Poligono e Point:la coordinata del punto più vicino a Poligono Shapely

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

enter image description here

posso calcolare la distanza del punto al poligono ...

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

... ma mi piacerebbe conoscere la coordinata del punto sul bordo del poligono dove la distanza più breve misura.

Il mio approccio iniziale è quello di tamponare il punto da esso le distanze al poligono, e trovare il punto in cui quel cerchio è tangente al poligono:

>>> buff=point.buffer(dist) 

enter image description here Tuttavia, io non sono sicuro di come per calcolare quel punto. I due poligoni non si intersecano quindi list(poly.intersection(buff)) non mi darà quel punto.

Sono sulla buona strada con questo? C'è un metodo più semplice?

+2

Duplicato? http: // StackOverflow.it/questions/10983872/distance-from-a-a-a-a-polgon –

+0

@Oleg, non credo che questo sia un duplicato. Come ho detto sopra, non ho problemi a calcolare la distanza minima dal poligono. Sto cercando di trovare il punto sul confine del poligono dove viene misurata la distanza minima. – AJG519

+0

Sarebbe curioso sapere come ottenere la distanza se il punto si trova all'interno del poligono. Ad esempio, quando: 'point = Point (4,4)' – kuanb

risposta

14

Esiste un modo semplice per eseguire questa inoltro su funzioni ben formate. Innanzitutto, è necessario ottenere l'anello esterno del poligono e proiettare il punto sull'anello. È obbligatorio ottenere l'esterno come LinearRing poiché i poligoni non hanno la funzione di proiezione. Contro l'intuizione, questo dà una distanza, la distanza dal primo punto dell'anello al punto dell'anello più vicino a il punto dato. Quindi, basta usare quella distanza per ottenere il punto con la funzione di interpolazione. Guarda il codice qui sotto.

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] 

E 'importante ricordare che questo metodo funziona solo se si conosce il punto è al di fuori l'esterno del poligono. Se il punto si trova all'interno di uno dei suoi anelli interni, è necessario adattare il codice per quella situazione.

Se il poligono non ha anelli interni, il codice funzionerà anche per i punti all'interno del poligono. Questo perché in realtà stiamo lavorando con l'anello esterno come una stringa di linea e ignorando se la stringa di linea proviene da un poligono o meno.

È facile estendere questo codice al caso generale di calcolo della distanza di qualsiasi punto (all'interno o all'esterno del poligono) nel punto più vicino nel limite del poligono. Hai solo bisogno di calcolare il punto (e la distanza) più vicino dal punto a tutti gli anelli linea: l'anello esterno e ogni anello interno del poligono. Quindi, mantieni il minimo di quelli.

enter image description here

+0

questo è perfetto. Non avevo familiarità con quelle funzioni di Shapely. Può funzionare anche se il punto esterno fosse invece un poligono? Ho provato a usare pol_ext.project() sia in un poligono che in una stringa lineare, ma ho ricevuto il messaggio di errore "il terzo argomento di GEOSProject_r deve essere Point *". Qualche suggerimento su questo? – AJG519

+0

Non che io sappia. Penso che per questo non hai altra scelta che implementare qualcosa da te. La risposta di Tome Karzes può essere facilmente aggiunta a quello scenario (ma usando uno dei poligoni come "il punto", dal momento che hai il metodo sopra). – eguaio

+0

Nella risposta alla domanda http://stackoverflow.com/questions/38514607/find-shortest-path-from-one-geometry-to-other-on-shapely/38997756#38997756 puoi trovare un'implementazione di Tom Karzes algoritmo suggerito per ottenere la distanza tra due elementi che non attraversano le linee. Il codice può essere facilmente adattato per ottenere la distanza tra una stringa lineare e un punto e non dipende da funzioni ben formate. – eguaio

0

Ci sono due casi da considerare: (1) il punto più vicino si trova su un bordo e (2) il punto più vicino è un vertice. Il caso (2) è facile da controllare: basta prendere la distanza da ciascun vertice e trovare il minimo. Il caso (1) richiede un po 'più di matematica, ma non è poi così male. Devi fare due cose per caso (1): (a) trovare dove la normale dal punto al bordo interseca il bordo, e (b) verificare che si trovi all'interno del segmento di linea (al contrario di estendere una delle termina). Se non è nel segmento di linea, ignoralo (uno dei vertici sarà il punto più vicino su quel bordo).