Tengo un LineString definido por dos puntos, esencialmente un segmento de línea recta, y quería proyectar un punto sobre él. Conozco .interpolate
.project
Sin embargo, cuando el punto está "fuera" del segmento, no quiero el punto más cercano en el segmento, pero quiero extender el segmento y dibujar una línea que pase por el punto y sea ortogonal al segmento de línea (extendido). Quiero la coordenada de la proyección.
Por ejemplo, si el punto está "dentro" del segmento
from shapely.geometry import Point from shapely.geometry import LineString point = Point(0.2, 0.5) dist = LineString([(0, 1), (1, 1)]).project(point) list(LineString([(0, 1), (1, 1)]).interpolate(dist).coords)
¿Alguien sabe qué hacer cuando el punto está fuera del segmento?
Probablemente sea más fácil hacerlo manualmente. Si denota el ángulo x - u - v
como alpha
, entonces
cos(alpha) = (v - u).(x - u) / (|x - u|*|v - u|)
.
denota el producto escalar, y | |
representa la norma euclidiana. La distancia d
de P(x)
a u
es por lo tanto:
d = cos(alpha)*|x - u| = (v - u).(x - u) / |v - u|
Habiendo calculado d
, el punto proyectado P(x)
se obtiene fácilmente como:
P(x) = u + d*(v - u)/|v - u|
La implementación:
import numpy as np from shapely.geometry import Point from shapely.geometry import LineString point = Point(0.2, 0.5) line = LineString([(0, 1), (1, 1)]) x = np.array(point.coords[0]) u = np.array(line.coords[0]) v = np.array(line.coords[len(line.coords)-1]) n = v - u n /= np.linalg.norm(n, 2) P = u + n*np.dot(x - u, n) print(P) #0.2 1.