You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constpassTest=(// 判断 x 轴Math.max(x1,x2)>=Math.min(x3,x4)&&Math.max(x3,x4)>=Math.min(x1,x2)&&// 判断 y 轴Math.max(y1,y2)>=Math.min(y3,y4)&&Math.max(y3,y4)>=Math.min(y1,y2))
问题
在空间中有两条线段 P, Q ,由 4 个点组成,P1P2 ,Q1Q2 ,已知 4 个点的坐标,怎么判断两条线段是否相交?
快速排斥实验和跨立实验
只有同时通过这两个实验,这两条线段才是相交的。
已知点:
P1(x1, y1), P2(x2, y2), Q1(x3, y3), Q2(x4, y4)
快速排斥实验
这个实验主要是为了快速排除两条线段不相交的情况。
我们知道,一条线段两个点分别向水平和竖直方向扩展,可以得到一个矩形,那么,两条线段就可以得到两个矩形,如果这两个矩形是不相交的,那么这两条线段一定是不相交的。如果两个矩形相交呢?那我们还不能判断线段是否相交,需要再进行跨立实验才能确定,如下图:
快速排斥实验的公式就是判断两个矩形是否相交:
公式得到一个布尔值,表示是否通过实验,如果不通过,则表示线段不相交,可以直接得出结论;如果通过,则表示线段可能相交,需要继续进一步判断。
跨立实验
到这一步可以用向量来解决。
首先需要定义什么是跨立,举个例子,我们把线段 P 延长,得到一条直线,当线段 Q 的两个端点,分别在直线的两侧时,则说明线段 Q 跨立于线段 P 。
由这个定义可以得到,当两条线段相互跨立时,它们是相交的。
那么如何判断 Q 是否跨立 P 呢?我们知道,向量的叉乘,结果是一个向量,方向是垂直于两个向量组成的平面的,结果的值可能大于 0 或者小于 0 (为 0 时两个向量平行),表示方向是向里或者向外,跟两个向量的相对位置有关,可以用右手判断。
我们可以取两个辅助向量, P1Q1, P1Q2 ,分别与向量 P1P2 做叉乘,如果 P1Q1 与 P1Q2 分别在 P1P2 的两侧,那么两个叉乘的结果一定是一个正数跟一个负数,也就是相乘小于 0 。根据这点,我们就可以知道 Q 跨立 P 的条件了:
如果想判断 Q 的一个端点在 P 上的情况,判定条件改成 <= 0 即可。
如下图:
这边有个可能产生疑问的点,就是为什么需要进行两次跨立实验呢?即要判断 Q 跨立 P ,也要判断 P 跨立 Q 呢?判断其中一个不够吗?
是的,只判断一个是不够的,比如下面这种情况:
Q 跨立 P ,但是两条线段明显不相交,因此要反过来再判断 P 是否也跨立 Q 。
结论
因此,要判断两条线段是否相交,需要进行如下判断:
判断线段与矩形相交
在我的流程图项目中,实际上要判断的是线段跟矩形是否相交,那要怎么做呢?
按照上面的思路,先进行快速排斥实验,我们只需要构建一个矩形,如果不通过,则不相交,这没问题,那通过了呢?表示相交吗?不是的,比如这种情况:
那么快速排斥实验就没有用了吗?不是的,它还是可以快速排除掉一些不相交的情况,虽然跟接下来的步骤结合起来确实有点鸡肋。
那接下来要怎么做呢?其实比较简单的方式是,把矩形的 4 条边都取出来,分别与线段判断是否相交即可。如果要再判断线段是否在矩形内,再加上判断两个端点是否在矩形内即可。
除了快速排斥实验,我们换一种思路,可以快速得出一些相交的情况,即判断线段是否有端点在矩形内,这个比快速排斥实验更简单。
总结一下,有几种方式可以判断线段与矩形是否相交
方式一:
方式二:
总之,最后都是转换为两条线段相交的问题,如果比较懒,直接跟 4 条边判断就行,就是比较耗费性能。
对比一下,跟 4 条边判断,最多需要进行 4 次快速排斥实验, 8 次跨立实验。
而先判断端点的话,最多要判断 2 次端点是否在矩形内,2 此快速排斥实验, 4 次跨立实验。
The text was updated successfully, but these errors were encountered: