计算3D中两条线(线段)之间的最短距离

时间:2009-03-09 18:55:41

标签: algorithm geometry

我有两个线段:X1,Y1,Z1 - X2,Y2,Z2和X3,Y3,Z3 - X4,Y4,Z4

我试图找到两段之间的最短距离。

我一直在寻找一个小时的解决方案,但所有这些解决方案似乎都是使用线条而不是线段。

任何想法如何解决这个问题,或任何来源?

6 个答案:

答案 0 :(得分:27)

我将用matlab来回答这个问题,但是可以使用其他编程环境。我将补充说,此解决方案可以解决任意数量的维度(> = 3)。

假设我们在空间中有两个线段,PQ和RS。以下是一些随机点。

> P = randn(1,3)
P =
     -0.43256      -1.6656      0.12533

> Q = randn(1,3)
Q =
      0.28768      -1.1465       1.1909

> R = randn(1,3)
R =
       1.1892    -0.037633      0.32729

> S = randn(1,3)
S =
      0.17464     -0.18671      0.72579

无限线PQ(t)很容易定义为

PQ(u) = P + u*(Q-P)

同样,我们有

RS(v) = R + v*(S-R)

对于每一行,当参数为0或1时,我们得到返回行上的一个原始端点。因此,我们知道PQ(0)== P,PQ(1)== Q,RS(0)== R和RS(1)== S.

这种以参数方式定义线的方法在许多情况下非常有用。

接下来,想象一下我们沿着PQ线往下看。我们能找到从线段RS到无限线PQ的最小距离点吗?这最容易通过投影到PQ行的零空间来完成。

> N = null(P-Q)
N =
     -0.37428     -0.76828
       0.9078     -0.18927
     -0.18927      0.61149

因此,null(P-Q)是一对跨越与PQ正交的二维子空间的基矢量。

> r = (R-P)*N
r =
      0.83265      -1.4306

> s = (S-P)*N
s =
       1.0016     -0.37923

基本上我们所做的是将矢量RS投影到与线PQ正交的2维子空间(平面)中。通过减去P(线PQ上的点)得到r和s,我们确保无限线穿过该投影平面中的原点。

实际上,我们已经将其缩小到找到投影平面中从线rs(v)到原点(0,0)的最小距离。回想一下,rs(v)行由参数v定义为:

rs(v) = r + v*(s-r)

rs(v)行的法线向量将为我们提供所需。由于原始空间为3维,我们已将其减少到2维,因此我们可以简单地完成。否则,我只是再次使用null。这个小技巧适用于二维:

> n = (s - r)*[0 -1;1 0];
> n = n/norm(n);

n现在是一个单位长度的向量。无限线rs(v)到原点的距离很简单。

> d = dot(n,r)
d =
       1.0491

看到我也可以使用s来获得相同的距离。实际距离是abs(d),但事实证明,无论如何d都是正的。

> d = dot(n,s)
d =
       1.0491

我们可以从中确定v吗?是。回想一下原点是连接点r和s的线的d个单位的距离。因此,对于标量v的某些值,我们可以写d n = r + v (sr)。用向量(sr)形成该等式的每一边的点积,并求解v

> v = dot(s-r,d*n-r)/dot(s-r,s-r)
v =
       1.2024

这告诉我们,线段rs与原点的最接近的接近发生在线段的端点之外。因此,rs与原点的最接近的点是点rs(1)= s。

从投影中退出,这告诉我们线段RS到无限线PQ的最近点是点S.

分析中还有一个步骤可以采取。线段PQ上最近的点是什么?这一点是否落在线段内,还是落在端点之外?

我们将点S投射到PQ线上。 (这个表达式很容易从我之前的类似逻辑推导出来。请注意,我已经使用\来完成工作。)

> u = (Q-P)'\((S - (S*N)*N') - P)'
u =
      0.95903

看到你位于区间[0,1]。我们已经解决了这个问题。 PQ上的点是

> P + u*(Q-P)
ans =
      0.25817      -1.1677       1.1473

并且,两个线段上最近点之间的距离是

> norm(P + u*(Q-P) - S)
ans =
        1.071

当然,所有这些都可以压缩成几行代码。但它有助于将其全部扩展以了解其工作原理。

答案 1 :(得分:19)

一种基本方法与计算两条线之间的最短距离相同,但有一个例外。

如果您查看大多数算法以找到两条线之间的最短距离,您会发现它找到每条线上最接近的点,然后计算它们之间的距离。

将此扩展到线段(或光线)的技巧是查看该点是否超出线的一个端点,如果是,则使用终点而不是无限线上的实际最近点

有关具体样本,请参阅:

http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm

更具体地说:

http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm#dist3D_Segment_to_Segment()

答案 2 :(得分:2)

我会参数化两个线段,每个参数使用一个参数,在0和1之间,包括0和1。然后找出两个线函数之间的差异,并将其作为线性优化问题中的目标函数,并将参数作为变量。

所以说你有一条从(0,0,0)到(1,0,0)的线和另一条从(0,1,0)到(0,0,0)的线(是的,我正在使用容易的)。这些线可以参数化为(1 * t,0 * t,0 * t),其中t位于[0,1]和(0 * s,1 * s,0 * s),其中s位于[0,1] ],独立于t。

然后你需要最小化||(1 * t,1 * s,0)||其中t,s位于[0,1]。这是一个非常简单的问题需要解决。

答案 3 :(得分:0)

如何将线段扩展为无限线并找到两条线之间的最短距离。然后在每条线上找到作为最短距离线段的终点的点。

如果每一行的点都在原始线段上,那么您就有了答案。如果每条线的点不在原始线段上,则该点是原始线段的端点之一。

答案 4 :(得分:0)

基于在两条无限线之间找到然后将无限线限制在有限线之间找到两条有限线之间的距离并不总是有效。例如,尝试这一点

Q=[5 2 0]
P=[2 2 0]
S=[3 3.25 0]
R=[0 3 0]

基于无限逼近算法选择R和P进行距离计算(距离= 2.2361),但R和S中间某处距离P点的距离较近。显然,从R到S线选择P和[2 3.166]的距离较短,为1.1666。通过精确计算并找到从P到R S线的正交线,即使这个答案也会变得更好。

答案 5 :(得分:0)

首先,找到最接近线段在其扩展线之间桥接的方法。让我们称之为LineSeg BR。

如果BR.endPt1落在LS1上且BR.endPt2落在LS2上,你就完成了......只计算BR的长度。

如果桥BR与LS1相交但不与LS2相交,则使用这两个距离中较短的一个:smallerOf(dist(BR.endPt1,LS2.endPt1),dist(BR.endPt1,LS2.endPt2))

如果桥BR与LS2相交但不与LS1相交,则使用这两个距离中较短的一个:smallerOf(dist(BR.endPt2,LS1.endPt1),dist(BR.endPt2,LS1.endPt2))

如果这些条件都不成立,则最近的距离是相对的线段Segs上最接近的端点配对。