python中许多线的最近交点

时间:2018-08-30 03:48:58

标签: python numpy

我需要一个好的算法来计算最接近python中线集合的点,最好使用最小二乘法。我在无效的python实现上找到了这篇文章:

Finding the centre of multiple lines using least squares approach in Python

然后我在Matlab中找到了每个人都喜欢的资源...但是我不确定如何将其转换为python:

https://www.mathworks.com/matlabcentral/fileexchange/37192-intersection-point-of-lines-in-3d-space

我很难相信有人还没有做过……肯定是numpy或标准软件包的一部分,对吧?我可能只是没有在寻找正确的词-但是我还没有找到它。我可以分别定义两个点或一个点和一个方向来定义线。任何帮助将不胜感激!

以下是我正在处理的一组示例要点:

第一组线的初始XYZ点

array([[-7.07107037,  7.07106748,  1. ],
       [-7.34818339,  6.78264559,  1. ],
       [-7.61352972,  6.48335745,  1. ],
       [-7.8667115 ,  6.17372055,  1. ],
       [-8.1072994 ,  5.85420065,  1. ]])

属于第一组线的角度

[-44.504854, -42.029223, -41.278573, -37.145774, -34.097022]

第二组线的初始XYZ点

array([[ 0., -20. ,  1. ],
       [ 7.99789129e-01, -19.9839984,  1. ],
       [ 1.59830153e+00, -19.9360366,  1. ],
       [ 2.39423914e+00, -19.8561769,  1. ],
       [ 3.18637019e+00, -19.7445510,  1. ]])

属于第二组线的角度

[89.13244, 92.39087, 94.86425, 98.91849, 99.83488]

解决方案应该是原点或非常接近原点(数据只是有点杂乱,这就是为什么线条在单个点上没有完美相交的原因)。

3 个答案:

答案 0 :(得分:4)

如果this wikipedia equation具有任何重量:

然后您可以使用:

def nearest_intersection(points, dirs):
    """
    :param points: (N, 3) array of points on the lines
    :param dirs: (N, 3) array of unit direction vectors
    :returns: (3,) array of intersection point
    """
    dirs_mat = dirs[:, :, np.newaxis] @ dirs[:, np.newaxis, :]
    points_mat = points[:, :, np.newaxis]
    I = np.eye(3)
    return np.linalg.lstsq(
        (I - dirs_mat).sum(axis=0),
        ((I - dirs_mat) @ points_mat).sum(axis=0),
        rcond=None
    )[0]

如果您需要帮助以第一原理导出/检查该方程式,那么math.stackexchange.com将是一个更好的地方。

  

当然这是numpy的一部分

请注意,numpy为您提供了足够的工具来非常简洁地表达这一点

答案 1 :(得分:3)

这是使用this link

中描述的方法的解决方案
def intersect(P0,P1):
    """P0 and P1 are NxD arrays defining N lines.
    D is the dimension of the space. This function 
    returns the least squares intersection of the N
    lines from the system given by eq. 13 in 
    http://cal.cs.illinois.edu/~johannes/research/LS_line_intersect.pdf.
    """
    # generate all line direction vectors 
    n = (P1-P0)/np.linalg.norm(P1-P0,axis=1)[:,np.newaxis] # normalized

    # generate the array of all projectors 
    projs = np.eye(n.shape[1]) - n[:,:,np.newaxis]*n[:,np.newaxis]  # I - n*n.T
    # see fig. 1 

    # generate R matrix and q vector
    R = projs.sum(axis=0)
    q = (projs @ P0[:,:,np.newaxis]).sum(axis=0)

    # solve the least squares problem for the 
    # intersection point p: Rp = q
    p = np.linalg.lstsq(R,q,rcond=None)[0]

    return p

作品

enter image description here

编辑:这是嘈杂的测试数据的生成器

n = 6
P0 = np.stack((np.array([5,5])+3*np.random.random(size=2) for i in range(n)))
a = np.linspace(0,2*np.pi,n)+np.random.random(size=n)*np.pi/5.0
P1 = np.array([5+5*np.sin(a),5+5*np.cos(a)]).T

答案 2 :(得分:1)

这是我最终使用的最终代码。感谢kevinkayaks和其他所有人的回应!非常感谢您的帮助!

此函数的前半部分只是将点和角度的两个集合转换为方向向量。我相信其余的内容基本上与Eric和Eugene提出的内容相同。我碰巧首先在Kevin's身上获得了成功,并一直坚持下去,直到对我来说这是一个端到端的解决方案。

request.Headers.Add(ApiCustomHttpHeaders.UserId, "1");