打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
如何判断2个线段相交

判断 2 个线段相交有很多方法,最直接的方法就是直接计算两条直线的交点,然后看看交点是否分别在这两条线段上。这样的方法很容易理解,但是代码实现比较麻烦。

还有一种常用的方法是通过向量叉积来判断的,这种方法不需要算出直线方程,在代码实现上比较简便。
用这种方法判别线段是否相交一般分为两步:
1. 快速排斥实验
2. 跨立实验

快速排斥实验

我们首先判断两条线段在 x 以及 y 坐标的投影是否有重合。
也就是判断下一个线段中 x 较大的端点是否小于另一个线段中 x 较小的段点,若是,则说明两个线段必然没有交点,同理判断下 y。


如上图所示,代码表示如下:

max(C.x,D.x)<min(A.x,B.x) || max(C.y,D.y)<min(A.y,B.y) ||

max(A.x,B.x)<min(C.x,D.x) || max(A.y,B.y)<min(C.y,C.y)

如果上面的四条判断有一个为真,则代表两线段必不可交,否则应该进行第二步判断。
显然,上图通不过快速排斥实验。

跨立实验

矢量叉积

计算矢量叉积是与直线和线段相关算法的核心部分。
设矢量 P = (x1, y1),Q = ( x2, y2 ),则矢量叉积定义为:P × Q = x1*y2 - x2*y1,其结果是一个矢量,与为 P Q 向量所在平面的法向量。显然有性质 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q )。
叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:
  若 P × Q > 0 , 则 P 在 Q 的顺时针方向。
  若 P × Q < 0 , 则 P 在 Q 的逆时针方向。
  若 P × Q = 0 , 则 P 与 Q 共线,但可能同向也可能反向。

通过叉积来判断线段相交


如果两线段相交那么就意味着它们互相跨立,即如上图点 A 和 B 分别在线段 CD 两侧,点 C 和 D 分别在线 AB 两侧。
判断 A 点与 B 点是否在线段 DC 的两侧,即向量 A-D 与向量 B-D 分别在向量 C-D 的两端,也就是其叉积是异号的,即 (AD)×(CD)(BD)×(CD)<0
同时也要证明 C 点与 D 点在线段 AB 的两端,两个同时满足,则表示线段相交。

然后我们来看看临界情况,也就是上式恰好等于 0 的情况下:

当出现如上图所示的情况的时候,(AD)×(CD)(BD)×(CD)=0,显然,这种情况是相交的。只要将等号直接补上即可。

再接得想一想,如果没有第一步的快速排斥实验,仅判断第二步,会出现什么问题?

当出现如上所示的情况的时候,叉积都为 0, 可以通过跨立实验,但是两个线段并没有交点。不过还好,这种情况在第一步快速排斥已经被排除了。

代码

struct Line {
    double x1;
    double y1;
    double x2;
    double y2;
};

bool intersection(const Line &l1, const Line &l2)
{
    //快速排斥实验
    if ((l1.x1 > l1.x2 ? l1.x1 : l1.x2) < (l2.x1 < l2.x2 ? l2.x1 : l2.x2) ||
        (l1.y1 > l1.y2 ? l1.y1 : l1.y2) < (l2.y1 < l2.y2 ? l2.y1 : l2.y2) ||
        (l2.x1 > l2.x2 ? l2.x1 : l2.x2) < (l1.x1 < l1.x2 ? l1.x1 : l1.x2) ||
        (l2.y1 > l2.y2 ? l2.y1 : l2.y2) < (l1.y1 < l1.y2 ? l1.y1 : l1.y2))
    {
        return false;
    }
    //跨立实验
    if ((((l1.x1 - l2.x1)*(l2.y2 - l2.y1) - (l1.y1 - l2.y1)*(l2.x2 - l2.x1))*
        ((l1.x2 - l2.x1)*(l2.y2 - l2.y1) - (l1.y2 - l2.y1)*(l2.x2 - l2.x1))) > 0 ||
        (((l2.x1 - l1.x1)*(l1.y2 - l1.y1) - (l2.y1 - l1.y1)*(l1.x2 - l1.x1))*
        ((l2.x2 - l1.x1)*(l1.y2 - l1.y1) - (l2.y2 - l1.y1)*(l1.x2 - l1.x1))) > 0)
    {
        return false;
    }
    return true;
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
计算几何 点到线段的距离 点在简单多边形内 点到凸多边形的距离
点到线段的最短距离
(判断点在多边形内)-引射线判断法
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">线,段和平面的交点(2D和3D)</font></font>
判断两条线段是否相交(三种算法)
计算几何
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服