首先,两个几何对象 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的倍数的部分之和。对于这样的“正交分解”,它总是成立。dv = Ov + MvSquareEuclideanLength(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)).
您已经从点线距离计算中知道了这个公式(就是这样),它是通过对t0 进行微分来解决的。
所以这个方程的最小值是
t = -Dot(Cross(v1 - p, d), Cross(v2 - v1, d))/SquareEuclideanLength(Cross(v2 - v1, d))
使用此t计算v1 + t*(v2 - v1),线段 A 上最接近线 B 的点,您可以将其插入点线距离算法以找到所需的距离。
我希望这可以帮助你 !