判断两条线段是否相交

参考链接:
1
2

一、判断线段是否相交需要下面两步:

(1)快速排斥实验
(2)跨立实验

二、第一步快速排斥实验

在这里插入图片描述
对上图两条L1,L2线段来说,L1 x的最大值为d端点x=5,L2 x的最小值为a端点x=6,这就说明这两条线段肯定没有相交。
其他情况类似,代码表示如下:

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)

如果上面的四条判断有一个为真,则代表两条线段不相交;否则进行第二步判断。

三、第二步跨立实验

1、向量叉乘的几何意义

(1)二维向量叉乘公式
二维向量叉乘公式a(x1,y1),b(x2,y2),则a×b=(x1y2-x2y1),不需要证明的就是定义的运算。三维叉乘是行列式运算,也是叉积的定义,你把第三维看做0代入就行了。
在这里插入图片描述
(2)叉积与线段方向关系
两个坐标A(x1,y1),B(x2,y2),那么AxB的向量积就是x1y2-y1x2。
我们假定一个向量积R,R=x1y2-y1x2。
R<0 说明A在B的逆时针方向。
R=0 说明A与B共线,可能正向也可能反向。
R>0 说明A在B的顺时针方向。

2、举例说明

证明两条线段相交就要证明两条线段相互跨立,如果两条线段相交,那么一条线段两边的两个点要位于另一条线段的两边。
在这里插入图片描述
相交的情况下,我们从a点出发,分别沿ac,ad方向,得到两个向量,可以得到R>0;
在这里插入图片描述
不相交的情况下,我们从c点出发,分别沿ca,cb方向,得到两个向量,可以得到R<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;
}
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

<( ̄︶ ̄)Okay.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值