在没有for循环的情况下,在Python中计算点阵列到线段之间的欧式距离


问题内容

我正在寻找一个函数来计算具有两个坐标(x,y)和线段的点的numpy点数组之间的欧几里得距离。我的目标是使线段和10k点的结果在0.01秒内。

我已经找到了单点功能。但是运行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,端点AB

在此处输入图片说明

  • 取的点积P - Anormalize(A - B)以获得 签名 平行距离分量sA。和B和同样t

  • 取这两个数字的最大值和零,以得到钳制的平行距离分量。仅当点在线段的“边界”( Voronoi区域 ?)之外时,该值才会为非零。

  • 使用叉积,与以前一样计算垂直距离分量。

  • 使用毕达哥拉斯(Pythagoras)计算所需的最近距离(从P到的灰线A)。

上面的代码是无分支的,因此很容易通过以下方式向量化numpy

def lineseg_dists(p, a, b):

    # 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)