java 超定方程求解_求解离多条直线最近的点 (2D,3D,或任意维度的直线)

本文详细介绍了如何在2D、3D或更高维度空间中,通过最小二乘法解决多条直线的交点问题。当无公共交点时,文章提供方法寻找离直线集合最近的点。内容涵盖求解思路、代码实现及总结,特别引用了论文"Nearest approaches to multiple lines in n-dimensional space"。附带Python实现代码,适用于不同数量直线的场景。
摘要由CSDN通过智能技术生成

35838721b8c525594a9ccfb154f259b6.png

本文使用 Zhihu On VSCode 创作并发布

本文主要介绍如何求解多条线的交点(如果没有共同的交点,则寻找离多条线最近的点)。本文将分为以下几个部分:

  • 求解思路
  • 代码实现
  • 总结

一、求解思路

在空间中确定一条直线只需要两个点

equation?tex=p_s+%3D+%28p_%7Bsx%7D%2C+p_%7Bsy%7D%2C+p_%7Bsz%7D%29
equation?tex=p_e+%3D+%28p_%7Bex%7D%2C+p_%7Bey%7D%2C+p_%7Bez%7D%29。在数学中,我们可以将一条线描述成只有一个变量的方程:

equation?tex=p+%3D+p_s+%2B+s+%5Ccdot+u

其中

equation?tex=s是变量,
equation?tex=u+%3D+p_e+-+p_s+%3D+%28u_x%2C+u_y%2C+u_z%29,当
equation?tex=s%3D0时,
equation?tex=p+%3D+p_s,当
equation?tex=s%3D1时,
equation?tex=p+%3D+p_e。 平时会看到另外一种描述线的方式:

equation?tex=%5Cfrac%7Bp_x+-+p_%7Bsx%7D%7D%7Bu_x%7D+%3D+%5Cfrac%7Bp_y+-+p_%7Bsy%7D%7D%7Bu_y%7D++%3D+%5Cfrac%7Bp_z+-+p_%7Bsz%7D%7D%7Bu_z%7D+%3D+s

其实两者是等价的。

1.1 两条直线的交点

先从简单的问题讲起,对于求解两根线的交点:

equation?tex=p+%3D+p_%7Bs_1%7D+%2B+s%5Ccdot+u_1+%5C%5C%0A++p+%3D+p_%7Bs_2%7D+%2B+t%5Ccdot+u_2

假设

equation?tex=p_i是两条线的交点,那么:
equation?tex=p_i+%3D+p_%7Bs_1%7D+%2B+s%5Ccdot+u_1+%3D+p_%7Bs_2%7D+%2B+t%5Ccdot+u_2, 写成矩阵的方式,则有:

equation?tex=%5Cleft%5B%0A%5Cbegin%7Barray%7D%7Bcc%7D%0A+++u_%7B1x%7D+%26+-u_%7B2x%7D+%5C%5C%0A+++u_%7B1y%7D+%26+-u_%7B2y%7D+%5C%5C%0A+++u_%7B1z%7D+%26+-u_%7B2z%7D+%0A%5Cend%7Barray%7D%0A%5Cright%5D%0A%0A%5Cleft%5B%0A%5Cbegin%7Barray%7D%7Bc%7D%0A+++s+%5C%5C%0A+++t%0A%5Cend%7Barray%7D%0A%5Cright%5D%0A%0A%3D+%0A%0A%5Cleft%5B%0A%5Cbegin%7Barray%7D%7Bc%7D%0A+++p_%7Bs_2x%7D+-+p_%7Bs_1x%7D+%5C%5C%0A+++p_%7Bs_2y%7D+-+p_%7Bs_1y%7D+%5C%5C%0A+++p_%7Bs_2z%7D+-+p_%7Bs_1z%7D++%0A%5Cend%7Barray%7D%0A%5Cright%5D

这是个超定方程,通过最小二乘的方式则可以求解

equation?tex=%5Bs%2Ct%5D%5ET:

equation?tex=%5Cleft%5B%0A%5Cbegin%7Barray%7D%7Bc%7D%0A+++s+%5C%5C%0A+++t%0A%5Cend%7Barray%7D%0A%5Cright%5D%0A%3D+%28M%5ETM%29%5E%7B-1%7DM%5ETB

其中:

equation?tex=M+%0A%3D+%0A%5Cleft%5B%0A%5Cbegin%7Barray%7D%7Bcc%7D%0A+++u_%7B1x%7D+%26+-u_%7B2x%7D+%5C%5C%0A+++u_%7B1y%7D+%26+-u_%7B2y%7D+%5C%5C%0A+++u_%7B1z%7D+%26+-u_%7B2z%7D+%0A%5Cend%7Barray%7D%0A%5Cright%5D%0A%2C+%5Cquad+%0AB+%3D+%0A%5Cleft%5B%0A%5Cbegin%7Barray%7D%7Bc%7D%0A+++p_%7Bs_2x%7D+-+p_%7Bs_1x%7D+%5C%5C%0A+++p_%7Bs_2y%7D+-+p_%7Bs_1y%7D+%5C%5C%0A+++p_%7Bs_2z%7D+-+p_%7Bs_1z%7D++%0A%5Cend%7Barray%7D%0A%5Cright%5D

得到

equation?tex=%5Bs%2Ct%5D%5ET之后,我们可以分别代入表达直线的公式,得到直线
equation?tex=p+%3D+p_%7Bs_1%7D+%2B+s%5Ccdot+u_1 和直线
equation?tex=p+%3D+p_%7Bs_2%7D+%2B+t%5Ccdot+u_2 上的点
equation?tex=p_s
equation?tex=p_t,如果两个点相同,则说明这两条直线有交点
equation?tex=p_s+%2F+p_t;如果两个点是不同的点,则说明两条直线没有交点,且
equation?tex=%28p_s+%2B+p_t%29%2F2则是离两条直线最近的点,如图下图所示。

0f82cf219471659fdf7ba5719d5d096e.png
Image

1.2 两条直线的交点,另外一种表达方式

同样对于两条直线:

equation?tex=p+%3D+p_%7Bs_1%7D+%2B+a_1%5Ccdot+u_1+%5C%5C%0A++p+%3D+p_%7Bs_2%7D+%2B+a_2%5Ccdot+u_2

假设

equation?tex=%28x_1%2C+y_1%2C+z_1%29
equation?tex=%28x_2%2C+y_2%2C+z_2%29 分别是上面两条直线上的点,那么我们则有:

equation?tex=%5Cleft%5C%7B%0A++++++%5Cbegin%7Barray%7D%7Blr%7D%0A++++++++1+%5Ccdot+x_1+%2B+0%5Ccdot+y_1+%2B+0+%5Ccdot+z_1+-+u_%7B1x%7D+%5Ccdot+a_1+-+0%5Ccdot+a_2+%3D+p_%7Bs_1x%7D+%5C%5C%0A++++++++0+%5Ccdot+x_1+%2B+1%5Ccdot+y_1+%2B+0+%5Ccdot+z_1+-+u_%7B1y%7D+%5Ccdot+a_1+-+0%5Ccdot+a_2+%3D+p_%7Bs_1y%7D+%5C%5C%0A++++++++0+%5Ccdot+x_1+%2B+0%5Ccdot+y_1+%2B+1+%5Ccdot+z_1+-+u_%7B1z%7D+%5Ccdot+a_1+-+0%5Ccdot+a_2+%3D+p_%7Bs_1z%7D+%5C%5C%0A++++++++1+%5Ccdot+x_2+%2B+0%5Ccdot+y_2+%2B+0+%5Ccdot+z_2+-+0+%5Ccdot+a_1+-+u_%7B2x%7D%5Ccdot+a_2+%3D+p_%7Bs_2x%7D+%5C%5C%0A++++++++0+%5Ccdot+x_2+%2B+1%5Ccdot+y_2+%2B+0+%5Ccdot+z_2+-+0+%5Ccdot+a_1+-+u_%7B2y%7D%5Ccdot+a_2+%3D+p_%7Bs_2y%7D+%5C%5C%0A++++++++0+%5Ccdot+x_2+%2B+0%5Ccdot+y_2+%2B+1+%5Ccdot+z_2+-+0+%5Ccdot+a_1+-+u_%7B2z%7D%5Ccdot+a_2+%3D+p_%7Bs_2z%7D+%5C%5C%0A++++++%5Cend%7Barray%7D++%0A%5Cright.

我们假设

equation?tex=%28x_1%2C+y_1%2C+z_1%29
equation?tex=%28x_2%2C+y_2%2C+z_2%29 是同一个点,或者是最小而成找到的距离两条直线的最近的一个点
equation?tex=%28x%2C+y%2C+z%29,那么我们创建vector
equation?tex=m:

equation?tex=m+%3D+%5Cleft%5B%0A%5Cbegin%7Barray%7D%7Bc%7D%0A+++x+%5C%5C%0A+++y+%5C%5C%0A+++x+%5C%5C%0A+++a_1+%5C%5C%0A+++a_2%0A%5Cend%7Barray%7D%0A%5Cright%5D

那么我们定义

equation?tex=M
equation?tex=d 为 :

equation?tex=M+%3D+%5Cleft%5B%0A%5Cbegin%7Barray%7D%7Bccccc%7D%0A+++1+%26+0+%26+0+%26+-u_%7B1x%7D+%26+0+%5C%5C%0A+++0+%26+1+%26+0+%26+-u_%7B1y%7D+%26+0+%5C%5C%0A+++0+%26+0+%26+1+%26+-u_%7B1z%7D+%26+0+%5C%5C%0A+++1+%26+0+%26+0+%26+0+%26+-u_%7B2x%7D+%5C%5C%0A+++0+%26+1+%26+0+%26+0+%26+-u_%7B2y%7D+%5C%5C%0A+++0+%26+0+%26+1+%26+0+%26+-u_%7B2z%7D+%0A%5Cend%7Barray%7D%0A%5Cright%5D%0A%2C%0A%0Ad+%3D+%5Cleft%5B%0A%5Cbegin%7Barray%7D%7Bc%7D%0A+++p_%7Bs_1x%7D+%5C%5C%0A+++p_%7Bs_1y%7D+%5C%5C%0A+++p_%7Bs_1z%7D+%5C%5C%0A+++p_%7Bs_2x%7D+%5C%5C%0A+++p_%7Bs_2y%7D+%5C%5C%0A+++p_%7Bs_2z%7D%0A%5Cend%7Barray%7D%0A%5Cright%5D

通过矩阵运算,我们可以求解

equation?tex=m+%3D+%28G%5ET+G%29%5E%7B-1%7DG%5ET+d
equation?tex=m 中前三维即为我们要求解的离两条直线最近的点,将
equation?tex=m 中后两维代入到直线方程中则可以分别得到两条直线上相邻最近的两个点。

1.3 多条直线的交点
这一部分描述的方法来自论文 "Nearest approaches to multiple lines in n-dimensional space"。

上面描述的解释方式可以很好的扩展到任意大于两条直线的情况,同时也可以扩展到更高维度的情况下,接下来将描述一下求解三条直线求解交点的情况:

equation?tex=%5Cleft%5C%7B%0A++++++%5Cbegin%7Barray%7D%7Blr%7D%0A++++++++1+%5Ccdot+x_1+%2B+0%5Ccdot+y_1+%2B+0+%5Ccdot+z_1+-+u_%7B1x%7D+%5Ccdot+a_1+-+0%5Ccdot+a_2+-+0%5Ccdot+a_3+%3D+p_%7Bs_1x%7D+%5C%5C%0A++++++++0+%5Ccdot+x_1+%2B+1%5Ccdot+y_1+%2B+0+%5Ccdot+z_1+-+u_%7B1y%7D+%5Ccdot+a_1+-+0%5Ccdot+a_2+-+0%5Ccdot+a_3+%3D+p_%7Bs_1y%7D+%5C%5C%0A++++++++0+%5Ccdot+x_1+%2B+0%5Ccdot+y_1+%2B+1+%5Ccdot+z_1+-+u_%7B1z%7D+%5Ccdot+a_1+-+0%5Ccdot+a_2+-+0%5Ccdot+a_3+%3D+p_%7Bs_1z%7D+%5C%5C%0A++++++++1+%5Ccdot+x_2+%2B+0%5Ccdot+y_2+%2B+0+%5Ccdot+z_2+-+0+%5Ccdot+a_1+-+u_%7B2x%7D%5Ccdot+a_2+-+0%5Ccdot+a_3+%3D+p_%7Bs_2x%7D+%5C%5C%0A++++++++0+%5Ccdot+x_2+%2B+1%5Ccdot+y_2+%2B+0+%5Ccdot+z_2+-+0+%5Ccdot+a_1+-+u_%7B2y%7D%5Ccdot+a_2+-+0%5Ccdot+a_3+%3D+p_%7Bs_2y%7D+%5C%5C%0A++++++++0+%5Ccdot+x_2+%2B+0%5Ccdot+y_2+%2B+1+%5Ccdot+z_2+-+0+%5Ccdot+a_1+-+u_%7B2z%7D%5Ccdot+a_2+-+0%5Ccdot+a_3+%3D+p_%7Bs_2z%7D+%5C%5C%0A++++++++1+%5Ccdot+x_3+%2B+0%5Ccdot+y_3+%2B+0+%5Ccdot+z_3+-+0+%5Ccdot+a_1+-+0%5Ccdot+a_2+-+u_%7B3x%7D%5Ccdot+a_3+%3D+p_%7Bs_3x%7D+%5C%5C%0A++++++++0+%5Ccdot+x_3+%2B+1%5Ccdot+y_3+%2B+0+%5Ccdot+z_3+-+0+%5Ccdot+a_1+-+0%5Ccdot+a_2+-+u_%7B3y%7D%5Ccdot+a_3+%3D+p_%7Bs_3y%7D+%5C%5C%0A++++++++0+%5Ccdot+x_3+%2B+0%5Ccdot+y_3+%2B+1+%5Ccdot+z_3+-+0+%5Ccdot+a_1+-+0%5Ccdot+a_2+-+u_%7B3z%7D%5Ccdot+a_3+%3D+p_%7Bs_3z%7D+%0A++++++%5Cend%7Barray%7D++%0A%5Cright.

在这种情况下

equation?tex=G 变成
equation?tex=9%5Ctimes+6的维度,
equation?tex=d变成
equation?tex=9+%5Ctimes+1的维度。接下来的计算,则和上一小节描述的一样。

对于

equation?tex=n_1条直线,
equation?tex=n_2-D的情况,
equation?tex=G 变成
equation?tex=%28n_1%5Ccdot+n_2%29%5Ctimes+%28n_2+%2B+n_1%29的维度,
equation?tex=d变成
equation?tex=%28n_1+%5Ccdot+n_2%29+%5Ctimes+1的维度。

二、代码实现

了解了数学原理之后,代码实现则非常简单,本文提供上述思路的python实现版本,只需要numpy依赖库。

import numpy as np

def intersection_of_multi_lines(strt_points, directions):  
    '''
    strt_points: line start points; numpy array, nxdim
    directions: list dierctions; numpy array, nxdim  

    return: the nearest points to n lines 
    '''
    
    n, dim = strt_points.shape

    G_left = np.tile(np.eye(dim), (n, 1))  
    G_right = np.zeros((dim*n, n))  

    for i in range(n):
        G_right[i*dim:(i+1)*dim, i] = -directions[i, :]

    G = np.concatenate([G_left, G_right], axis=1)  
    d = strt_points.reshape((-1, 1)) 

    m = np.linalg.inv(np.dot(G.T, G)).dot(G.T).dot(d)   

    # return m[0:dim]  
    return m

if __name__ == '__main__':

    ##########################################################################################
    ##test case   
    strt_point = np.zeros((2, 3))
    strt_point[0, :] = np.array([0, 0, -10])
    strt_point[1, :] = np.array([-10, 0, 0])

    directions = np.zeros((2, 3))
    directions[0, :] = np.array([1, 0, 0])
    directions[1, :] = np.array([0, 1, 0])  

    inters = intersection_of_multi_lines(strt_point, directions)   
    print('[DEBUG] intersection {}'.format(inters))

读者可以自己尝试一下,使用不同的数量的直线,求解相邻最近的点。下图展示了一些求解结果,结果图来自[1].

c10df55f3be760fec24ab90080f4821f.png
Image

三、总结

本文主要描述了一下怎么求解与多条直线相邻最近的点的方法,从最简单的两条直线引入问题的基础解法,然后描述了一种可以扩展到多条直线,更高维度的方法,并且提供了代码实现。

参考

[1] https://books.google.co.kr/
[2] https://www.crewes.org/ForOurSponsors/ResearchReports/2010/CRR201032.pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值