在没有for循环的情况下计算Python中点数组到线段之间的欧氏距离
Calculate the euclidian distance between an array of points to a line segment in Python without for loop
我正在寻找一个函数来计算具有两个坐标 (x, y) 的 numpy 点数组和一条线段之间的欧几里得距离。我的目标是在 0.01 秒内获得线段和 10k 点的结果。
我已经找到了单点的功能。但是 运行 for 循环非常低效。
我还发现了这个计算无限直线距离的函数:
def line_dists(points, start, end):
if np.all(start == end):
return np.linalg.norm(points - start, axis=1)
vec = end - start
cross = np.cross(vec, start - points)
return np.divide(abs(cross), np.linalg.norm(vec))
它非常有效,我想对有界线采用类似的方法。
感谢您的帮助。
设置 – 测试点 P
、端点 A
和 B
:
对 P - A
与 normalize(A - B)
进行点积,得到 signed 平行距离分量 s
A
。同样 B
和 t
.
取这两个数的最大值和零,得到夹紧的平行距离分量。如果该点位于线段的“边界”(Voronoi 区域?)之外,则此值为非零。
像以前一样使用叉积计算垂直距离分量。
使用毕达哥拉斯计算所需的最近距离(从P
到A
的灰线)。
上面是无分支的,因此很容易用 numpy
:
向量化
def lineseg_dists(p, a, b):
# Handle case where p is a single point, i.e. 1d array.
p = np.atleast_2d(p)
# TODO for you: consider implementing @Eskapp's suggestions
if np.all(a == b):
return np.linalg.norm(p - a, axis=1)
# normalized tangent vector
d = np.divide(b - a, np.linalg.norm(b - a))
# signed parallel distance components
s = np.dot(a - p, d)
t = np.dot(p - b, d)
# clamped parallel distance
h = np.maximum.reduce([s, t, np.zeros(len(p))])
# perpendicular distance component, as before
# note that for the 3D case these will be vectors
c = np.cross(p - a, d)
# use hypot for Pythagoras to improve accuracy
return np.hypot(h, c)
我正在寻找一个函数来计算具有两个坐标 (x, y) 的 numpy 点数组和一条线段之间的欧几里得距离。我的目标是在 0.01 秒内获得线段和 10k 点的结果。
我已经找到了单点的功能。但是 运行 for 循环非常低效。
我还发现了这个计算无限直线距离的函数:
def line_dists(points, start, end):
if np.all(start == end):
return np.linalg.norm(points - start, axis=1)
vec = end - start
cross = np.cross(vec, start - points)
return np.divide(abs(cross), np.linalg.norm(vec))
它非常有效,我想对有界线采用类似的方法。
感谢您的帮助。
设置 – 测试点 P
、端点 A
和 B
:
对
P - A
与normalize(A - B)
进行点积,得到 signed 平行距离分量s
A
。同样B
和t
.取这两个数的最大值和零,得到夹紧的平行距离分量。如果该点位于线段的“边界”(Voronoi 区域?)之外,则此值为非零。
像以前一样使用叉积计算垂直距离分量。
使用毕达哥拉斯计算所需的最近距离(从
P
到A
的灰线)。
上面是无分支的,因此很容易用 numpy
:
def lineseg_dists(p, a, b):
# Handle case where p is a single point, i.e. 1d array.
p = np.atleast_2d(p)
# TODO for you: consider implementing @Eskapp's suggestions
if np.all(a == b):
return np.linalg.norm(p - a, axis=1)
# normalized tangent vector
d = np.divide(b - a, np.linalg.norm(b - a))
# signed parallel distance components
s = np.dot(a - p, d)
t = np.dot(p - b, d)
# clamped parallel distance
h = np.maximum.reduce([s, t, np.zeros(len(p))])
# perpendicular distance component, as before
# note that for the 3D case these will be vectors
c = np.cross(p - a, d)
# use hypot for Pythagoras to improve accuracy
return np.hypot(h, c)