点到线段的投影Python Shapely

sof*_*led 5 python gis point projection shapely

我有一个由两个点定义的LineString,因此本质上是一个直线段,我想在其上投影一个点。我知道.project.interpolate。但是,当点在线段“外部”时,我不希望线段上最近的点,而是要扩展线段并绘制一条穿过该点并与(延伸的)线段正交的线。我想要投影的坐标。

在此处输入图片说明

例如,如果该点在“段内”

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)
Run Code Online (Sandbox Code Playgroud)

任何人都知道该点在线段之外怎么办?

ewc*_*wcz 5

手动执行此操作可能最简单。如果将角度表示x - u - valpha,则

cos(alpha) = (v - u).(x - u) / (|x - u|*|v - u|)
Run Code Online (Sandbox Code Playgroud)

其中.表示点积,并| |表示欧几里得范数。因此dP(x)与的距离为u

d = cos(alpha)*|x - u| = (v - u).(x - u) / |v - u|
Run Code Online (Sandbox Code Playgroud)

经过计算dP(x)可以很容易地获得投影点:

P(x) = u + d*(v - u)/|v - u|
Run Code Online (Sandbox Code Playgroud)

实现:

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.
Run Code Online (Sandbox Code Playgroud)