【发布时间】:2010-10-12 06:29:39
【问题描述】:
我有两条线段:X1,Y1,Z1 - X2,Y2,Z2 和 X3,Y3,Z3 - X4,Y4,Z4
我正在尝试找到两个段之间的最短距离。
我一直在寻找解决方案几个小时,但所有这些似乎都适用于线条而不是线段。
有任何想法如何解决这个问题,或者任何来源的furmulae?
【问题讨论】:
我有两条线段:X1,Y1,Z1 - X2,Y2,Z2 和 X3,Y3,Z3 - X4,Y4,Z4
我正在尝试找到两个段之间的最短距离。
我一直在寻找解决方案几个小时,但所有这些似乎都适用于线条而不是线段。
有任何想法如何解决这个问题,或者任何来源的furmulae?
【问题讨论】:
我会用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 正交的二维子空间(平面)中。通过减去P(PQ线上的一个点)得到r和s,我们保证了无限长的线在这个投影平面上通过原点。
实际上,我们已将其简化为找到从线 rs(v) 到投影平面中原点 (0,0) 的最小距离。回想一下,rs(v) 行由参数 v 定义为:
rs(v) = r + v*(s-r)
线 rs(v) 的法线向量将为我们提供我们需要的东西。由于原始空间是 3-d,因此我们已将其减少为 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 的某个值,我们可以写为 dn = 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 的这个表达式很容易从与我之前所做的类似的逻辑中推导出来。请注意,我已经使用 \ 来完成这项工作。)
> u = (Q-P)'\((S - (S*N)*N') - P)'
u =
0.95903
看到 u 位于区间 [0,1] 中。我们已经解决了这个问题。 PQ线上的点是
> P + u*(Q-P)
ans =
0.25817 -1.1677 1.1473
而且,两条线段上最近点之间的距离是
> norm(P + u*(Q-P) - S)
ans =
1.071
当然,所有这些都可以压缩成几行代码。但它有助于扩展它以了解其工作原理。
【讨论】:
一种基本方法与计算两条线之间的最短距离相同,但有一个例外。
如果您查看大多数用于查找 2 条线之间最短距离的算法,您会发现它会找到每条线上最近的点,然后计算它们之间的距离。
将此扩展到线段(或射线)的技巧是查看该点是否超出线的端点之一,如果是,则使用端点而不是无限线上的实际最近点.
具体示例见:
http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
更具体地说:
http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm#dist3D_Segment_to_Segment()
【讨论】:
D < SMALL_NUM 路由,这就是您获得的值。它不应该被选择,而且确实没有被选择。您需要确保正确转录代码。
我会将两个线段参数化为每个使用一个参数,范围在 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] 中。这是一个很容易解决的问题。
【讨论】:
如何将线段延伸成无限的线并找到两条线之间的最短距离。然后找到每条线上作为最短距离线段端点的点。
如果每条线的点都在原始线段上,那么你就有答案了。如果每条线的一个点不在原始线段上,则该点是原始线段的端点之一。
【讨论】:
根据找到两条无限线之间的距离来寻找两条有限线之间的距离,然后将无限线绑定到有限线并不总是有效。例如试试这个点
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 线的正交线,即使这个答案也可以变得更好。
【讨论】:
首先,找到在它们的延长线之间桥接的最接近线段。我们称之为 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))
如果这些条件都不成立,则最近的距离是相对线段上最近的一对端点。
【讨论】: