该代码试图找到两个线段的交点 - AB 和 CD。
有许多不同的方式来解释它是如何做的,这取决于你如何解释这些操作。
假设 A 点有坐标 (xa, ya), B - (xb, yb) 等等。比方说
dxAB = xb - xa
dyAB = yb - ya
dxCD = xd - xc
dyCD = yd - yc
下列两个线性方程组
| dxAB dxCD | | t | | xc-xa |
| | * | | = | |
| dyAB dyCD | | u | | yc-ya |
如果求解t
和,将为您提供 AB 线(值)和 CDu
线(值)上的交点的比例位置。如果该点属于相应的线段,这些值将位于范围内,如果该点位于线段之外(在包含该线段的线上),则这些值将位于该范围之外。t
u
[0, 1]
为了求解这个线性方程组,我们可以使用著名的克莱默规则。为此,我们需要行列式
| dxAB dxCD |
| |
| dyAB dyCD |
这正是determinant(b - a, c - d)
您的代码。(实际上,我在这里的内容是determinant(b - a, d - c)
,但这对于本解释而言并不重要。您发布的代码出于某种原因交换了 C 和 D,请参见下面的 PS 注释)。
我们还需要行列式
| xc-xa dxCD |
| |
| yc-ya dyCD |
这完全determinant(c-a,c-d)
来自您的代码,并且决定了
| dxAB xc-xa |
| |
| dyAB yc-ya |
这正是determinant(b-a,c-a)
。
根据克莱默规则划分这些行列式将为我们提供 和 的值t
,u
这正是您发布的代码中所做的。
然后代码继续测试 的值t
并u
检查这些段是否实际相交,即两者是否都t
属于u
范围[0, 1]
。如果他们这样做了,它会通过评估来计算实际的交点a*t+b*(1-t)
(等效地,它可以评估c*u+d*(1-u)
)。(再次,请参阅下面的 PS 说明)。
PS在原始代码中,点 D 和 C 在某种意义上是“交换”的c - d
,就像我d - c
在解释中所做的那样。但这对算法的总体思路没有影响,只要注意符号即可。
a*(1-t)+t*b
这种 C 点和 D 点的交换也是求交点时使用表达式的原因。通常,正如我的解释,人们希望看到类似的东西a*t+b*(1-t)
。(不过,我对此表示怀疑。我希望a*t+b*(1-t)
即使在您的版本中也能看到那里。可能是一个错误。)
PPS作者如果代码忘记检查det == 0
(或非常接近于 0),这将在段并行的情况下发生。