Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 三维空间中点与线之间的最短距离_Python_Numpy_Vector_3d_Distance - Fatal编程技术网

Python 三维空间中点与线之间的最短距离

Python 三维空间中点与线之间的最短距离,python,numpy,vector,3d,distance,Python,Numpy,Vector,3d,Distance,我试图使用numpy或python中的任何东西来找到从点(x0,y0,z0)到由(x1,y1,z1)和(x2,y2,z2)连接的线的最小距离。不幸的是,我在网上只能找到与2d空间相关的内容,而且我对python还相当陌生。任何帮助都将不胜感激。提前谢谢 StackOverflow不支持Latex,所以我将对一些数学问题进行润色。一种解决方案来自这样一种想法:如果你的直线跨越了点p和q,那么对于某些实值t,该直线上的每个点都可以表示为t*(p-q)+q。然后,您希望最小化给定点r与该直线上任何点之

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

StackOverflow不支持Latex,所以我将对一些数学问题进行润色。一种解决方案来自这样一种想法:如果你的直线跨越了点
p
q
,那么对于某些实值
t
,该直线上的每个点都可以表示为
t*(p-q)+q
。然后,您希望最小化给定点
r
与该直线上任何点之间的距离,并且距离是单个变量
t
的函数,因此标准微积分技巧可以正常工作。考虑下面的例子,它计算<代码> r>代码>与<>代码> P<代码> > <代码> q>代码>之间的最小距离。通过手工,我们知道答案应该是
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亿。唯一真正的限制是
p
q
必须是不同的点,以便它们之间有一条唯一的线

我在上面的例子中对代码进行了分解,以展示我从数学角度思考代码的两个不同步骤(查找
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.        ])

很可能我遗漏了一些简化,或者其他可以加快速度的事情,但这至少应该是一个好的开始。

这重复了@Hans Musgrave的解决方案,但想象一下我们对这些一无所知 “标准微积分技巧”很好用,但在线性代数方面也很差

我们只知道:

  • 如何计算两点之间的距离
  • 直线上的点可以表示为两点和参数的函数
  • 我们知道找到一个函数的极小值
  • (列表与代码块不是朋友)

    def距离(a、b):
    “”“计算两点之间的距离。”“”
    返回np.linalg.norm(a-b)
    def线到点的距离(p、q、r):
    “”“计算点r和穿过p和q的线之间的距离。”
    def foo(t:浮动):
    #x是直线上的点,取决于t
    x=t*(p-q)+q
    #我们返回一个距离,它也取决于t
    返回距离(x,r)
    #哪个t使距离最小?
    t0=sci.优化.最小化(foo,0.1).x[0]
    返回foo(t0)
    #在本例中,距离为5
    p=np.array([0,0,0])
    q=np.数组([2,0,0])
    r=np.array([1,5,0])
    断言abs(线到点的距离(p,q,r)-5)<0.00001
    
    您不应该将此方法用于实际计算,因为它使用 当你有一个封闭形式的解时的近似值,但它可能有用
    要揭示一些逻辑,就要找到邻近的答案

    一旦你有了一个2d的例子,你只需要做两次,因为你有把事情复杂化的天赋)@EvgenyPogrebnyak对此表示抱歉。我应该改变什么?也许,给一些线索,d()和t()做什么以及为什么?我想说这是一个非常简单的答案。
    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