3 d空间中点与线之间的最短距离

时间:2018-06-06 19:13:55

标签: python numpy vector 3d distance

我正在尝试使用numpy或python中的任何内容找到从点(x0,y0,z0)到由(x1,y1,z1)和(x2,y2,z2)连接的线的最小距离。不幸的是,我在网上找到的所有内容都与2d空间有关,而且我对python来说相当新。任何帮助将不胜感激。提前谢谢!

2 个答案:

答案 0 :(得分:4)

StackOverflow不支持Latex,所以我要掩饰一些数学。一种解决方案来自这样的想法:如果您的线条跨越点pq,那么对于某些实值t*(p-q)+q,该线上的每个点都可以表示为t 。然后,您希望最小化给定点r与该行上任何点之间的距离,并且距离方便地是单个变量t的函数,因此标准微积分技巧可以正常工作。请考虑以下示例,该示例计算rpq跨越的行之间的最小距离。我们知道答案应该是1

import numpy as np

p = np.array([0, 0, 0])
q = np.array([0, 0, 1])
r = np.array([0, 1, 1])

def t(p, q, r):
    x = p-q
    return np.dot(r-q, x)/np.dot(x, x)

def d(p, q, r):
    return np.linalg.norm(t(p, q, r)*(p-q)+q-r)

print(d(p, q, r))
# Prints 1.0

这适用于任何数量的维度,包括2,3和10亿。唯一真正的限制是pq必须是不同的点,以便它们之间有一条唯一的线。

我在上面的例子中打破了代码,以便显示我从数学上思考它的方式产生的两个不同步骤(找到t然后计算距离)。这不一定是最有效的方法,如果你想知道各种各样的点和同一条线的最小距离肯定不是 - 如果尺寸的数量很小则加倍。要获得更有效的方法,请考虑以下事项:

import numpy as np

p = np.array([0, 0, 0])  # p and q can have shape (n,) for any
q = np.array([0, 0, 1])  # n>0, and rs can have shape (m,n)
rs = np.array([          # for any m,n>0.
    [0, 1, 1],
    [1, 0, 1],
    [1, 1, 1],
    [0, 2, 1],
])

def d(p, q, rs):
    x = p-q
    return np.linalg.norm(
        np.outer(np.dot(rs-q, x)/np.dot(x, x), x)+q-rs,
        axis=1)

print(d(p, q, rs))
# Prints array([1.        , 1.        , 1.41421356, 2.        ])

我可能会有一些简化,或者其他可能加速的事情,但至少应该是一个好的开始。

答案 1 :(得分:0)

这复制了@Hans Musgrave解决方案,但想象一下我们什么都不知道 “标准微积分技巧”在线性代数中“工作正常”而且非常糟糕。

我们所知道的是:

  1. 如何计算两点之间的距离
  2. 一个在线点可以表示为两个点和一个参数
  3. 的函数
  4. 我们知道找到一个最小功能
  5. (列表不是代码块的朋友)

    def distance(a, b):
        """Calculate a distance between two points."""
        return np.linalg.norm(a-b)
    
    def line_to_point_distance(p, q, r):
        """Calculate a distance between point r and a line crossing p and q."""
        def foo(t: float):
            # x is point on line, depends on t 
            x = t * (p-q) + q
            # we return a distance, which also depends on t        
            return distance(x, r)
        # which t minimizes distance?
        t0 = sci.optimize.minimize(foo, 0.1).x[0]
        return foo(t0)
    
    # in this example the distance is 5
    p = np.array([0, 0, 0])
    q = np.array([2, 0, 0])
    r = np.array([1, 5, 0])
    
    assert abs(line_to_point_distance(p, q, r) - 5) < 0.00001 
    

    您不应该将此方法用于实际计算,因为它使用 你有一个封闭形式的解决方案的近似值,但也许它有用 揭示一些逻辑提出相邻的答案。