首先,两个几何对象 A 和 B 之间的距离是多少?它是 A 和 B 上任意两点之间的最小距离,即。dist(A,B) = min { EuclideanLength(x - y) | x in A, y in B}
. (如果它存在并且是唯一的,在你的情况下它就是这样。)
正如你EuclideanLength((x,y,z)) = sqrt(x^2 + y^2 + z^2)
已经知道的那样。因为sqrt
是严格增加,所以最小化就足够了SquareEuclideanLength((x,y,z)) = x^2 + y^2 + z^2
,这大大简化了问题。
在您的问题中,对象是 line segmentA := {v1 + t*(v2-v1) | 0 <= t <= 1}
和 line B := {p + s*d | s is any real number}
。(别担心你问的是一条射线,一条线真的是你想要的。)
现在计算距离归结为找到合适的t
和最小s
的SquareEuclideanLength(v1 + t*(v2-v1) - p - s*d)
,然后计算EuclideanLength(v1 + t*(v2-v1) - p - s*d)
得到真正的距离。
为了解决这个问题,我们需要一些解析几何。因为d
不为零,所以我们可以将每个向量写v
为与 : 正交的部分和:d
的倍数的部分之和。对于这样的“正交分解”,它总是成立。d
v = Ov + Mv
SquareEuclideanLength(v) = SquareEuclideanLength(Ov) + SquareEuclideanLength(Mv)
因为d = Md
在上面
SquareEuclideanLength(v1 + t*(v2-v1) - p - s*d) =
SquareEuclideanLength(Ov1 + t*(Ov2-Ov1) - Op)
+ SquareEuclideanLength(Mv1 + t*(Mv2-Mv1) - Mp - s*d)
左加数不依赖于s
,无论您选择如何,t
您都可以找到s
右加数为 0 !(记住Mv1
, Mv2
, ... 是 的倍数d
。)
O
因此,要找到最小值,您只需要M
像上面那样找到这样的地图并找到最小化器t
。
假设这d
是标准化的,这些实际上是由Ov := CrossProduct(v, d)
and给出的,但相信我,如果不标准化Mv := DotProduct(v, d)*d
,这也有效。d
所以现在找到距离的方法是:找到0 <= t <= 1
最小化
SquareEuclideanLength(Cross(v1 - p, d) + t*Cross(v2 - v1, d))
= SquareEuclideanLength(Cross(v1 - p, d))
+ 2*t*Dot(Cross(v1 - p, d), Cross(v2 - v1, d))
+ t^2 SquareEuclideanLength(Cross(v2 - v1, d))
.
您已经从点线距离计算中知道了这个公式(就是这样),它是通过对t
0 进行微分来解决的。
所以这个方程的最小值是
t = -Dot(Cross(v1 - p, d), Cross(v2 - v1, d))/SquareEuclideanLength(Cross(v2 - v1, d))
使用此t
计算v1 + t*(v2 - v1)
,线段 A 上最接近线 B 的点,您可以将其插入点线距离算法以找到所需的距离。
我希望这可以帮助你 !