您的线将类似于 cv + p,其中 v 是方向向量,p 是它通过的点。
从直线到盒子上最近点的方向将垂直于直线,因此获取一对v 的法线,例如n 和m。
实际最近点将是n 和m 的线性组合,其中一个点位于直线上。 (你从线上的一个点开始,沿着一条垂直于这条线的线到达你的目标点,这条线的每一条垂直线都是通过该点的法线的线性组合。)
所以解决an + bm + cv + p = s,其中s 是你盒子的每个角落。
不失一般性,我们可以假设v 在其前两个组件中的任何一个都不为零。 (如果它有一个,排列索引使其成为第三个。如果它有两个,这将成为一个更简单的问题,我们可以单独解决。)
这意味着我们可以使用n = (1, 0, N) 和m = (0, 1, M)。
由于n * v = 0和m * v = 0,我们可以找到N = -v1/v3和M = -v2/v3。我们不会做所有这些替换,只要知道这些是数字而不是变量就足够了。
现在我们要解决an + bm + cv = s - p。我们可以用普通代数来做。我们得到
c = (s3 - p3 - N(s1 - p1)- M(s2 - p2))/(v3 - N v1 - M v2)
然后cv + p 是您的直线上离该角最近的点。
同时我们还有:
b = s2 - p2 - v2 c
a = s1 - p1 - v1 c
线到你的角落的距离是|an + bm|,所以距离的平方是
D^2 = (an + bm) * (an + bm) = (a^2 + b^2 + (aM + bM)^2)
当您查看角落时,您可以考虑您有一个盒子这一事实。选择一个角落,去一个邻居,然后去那个让你从那个角落对角线的邻居。如果这三个值中的一个值在同一方向上比其他两个值更远,则最近的点将不在通往它的边缘上。这将删除所有涉及它的边缘。由于这条线可能会直接穿过您的盒子,因此这可能不会发生。但这不太可能。
对于构成边的每一对角(不排除),我们有一个范围为c 值x c0 + (1-x) c1 和x in [0,1],它们表示直线上距离最近点的最近点的范围在边缘。
对应的a和b的值为
a = s1-p1-v2(x c0 + (1-x)c1) = s1-p1-v2-(c0-c1)v2 x
b = s2-p2-v1(x c0 + (1-x)c1) = s2-p2-v1-(c0-c1)v1 x
同样,知道常数很重要,所以我们把它们写成:
a = A0 + A1x
b = B0 + B1x
现在,从上面
D^2 = (a^2 + b^2 + (aN + bM)^2)
所以我们可以得到 x 的平方距离。
D^2 = (A0 + A1 x)^2 + (B0 + B1 x)^2 +
(A0 N + A1 Nx)^2 + (B0 M + B1 MX)^2
将这一切相乘,x 项将是每个正方形的中间项,x^2 项将是每个正方形的平方项。
很明显,抛物线k + rx + qx^2 的最小值是r + 2qx = 0 在'x = -1/2 r/q,通过微分。
所以最小值将是
x = -(A0 A1 + B0 B2 + (NA0 A1 + MB0 B1))/
(A1^2 + B1^2 + (A1 N + B1 M)^2)
当x 介于 0 和 1 之间时,您有一个最小值或最大值。通过比较这些结果,您应该能够丢弃最大值。
如果最小值出现在面上,而不是边上,则限定值过多。在那种情况下,答案显然是零——这条线碰到了盒子。