点到线段的投影 Python Shapely
Projection of a point to a line segment Python Shapely
我有一个由两点定义的 LineString,因此本质上是一条直线段,我想在其上投影一个点。我知道 .project
和 .interpolate
。然而,当点是 "outside" 线段时,我不想要线段上的最近点,但我想扩展线段并画一条线穿过该点并且与(扩展的)线段正交.我要投影的坐标。
例如,如果点是 "within" 段
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)
任何人都知道当点在线段之外时该怎么办?
手动执行此操作可能最简单。如果将角度 x - u - v
表示为 alpha
,则
cos(alpha) = (v - u).(x - u) / (|x - u|*|v - u|)
其中.
表示点积,| |
表示欧氏范数。
P(x)
与 u
的距离 d
因此:
d = cos(alpha)*|x - u| = (v - u).(x - u) / |v - u|
计算 d
后,投影点 P(x)
很容易得到:
P(x) = u + d*(v - u)/|v - u|
实施:
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.
您也可以考虑使用 scikit-spatial
如下:
from skspatial.objects import Line
line = Line.from_points(point_a=[0,1], point_b=[1,1])
point = (1.2, 0.5) # example of a point not "within" the line segment
projected_point = line.project_point(point)
print(projected_point)
输出:
[1.2 1. ]
我有一个由两点定义的 LineString,因此本质上是一条直线段,我想在其上投影一个点。我知道 .project
和 .interpolate
。然而,当点是 "outside" 线段时,我不想要线段上的最近点,但我想扩展线段并画一条线穿过该点并且与(扩展的)线段正交.我要投影的坐标。
例如,如果点是 "within" 段
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)
任何人都知道当点在线段之外时该怎么办?
手动执行此操作可能最简单。如果将角度 x - u - v
表示为 alpha
,则
cos(alpha) = (v - u).(x - u) / (|x - u|*|v - u|)
其中.
表示点积,| |
表示欧氏范数。
P(x)
与 u
的距离 d
因此:
d = cos(alpha)*|x - u| = (v - u).(x - u) / |v - u|
计算 d
后,投影点 P(x)
很容易得到:
P(x) = u + d*(v - u)/|v - u|
实施:
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.
您也可以考虑使用 scikit-spatial
如下:
from skspatial.objects import Line
line = Line.from_points(point_a=[0,1], point_b=[1,1])
point = (1.2, 0.5) # example of a point not "within" the line segment
projected_point = line.project_point(point)
print(projected_point)
输出:
[1.2 1. ]