计算几何之线段性质(一):判断两线段相交

本文介绍了计算几何中的线段相交问题,包括点在线段上的判断方法和两线段相交的判断算法,包括快速排斥实验和跨立实验。提供了具体的数学表达式和应用场景,如线段与直线相交、点在矩形内的判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在研究线段相交之前,我们首先来看一下点定位中是如何判断点是否在线段上的:

设有点Q及线段P1P2,判断Q在线段P1P2上包括两条依据:

(1)(Q-P1)×(P2-P1)=0(这里×表示叉积);

(2)Q在以P1P2为对角线的矩形内。

前者保证了Q在直线P1P2上,后者保证了点Q不在线段P1P2的延长线或反向延长线上。

代码入下:

typedef struct node
{
    double x,y;
}Point;
bool on_segment(Point p1,Point p2,Point q)
{
    if((q.x-p1.x)*(p2.y-p1.y)==(p2.x-p1.x)*(1.y-p1.y)&&min(p1.x,p2.x)<=q.x&&q.x<=max(p1.x,p2.x)&&min(p1.y,p2.y)<=q.y&&q.y<=max(p1.y,p2.y))
      return true;
    else return false;
}


有了点定位的概念,接下来我们看一下如何判断两线段相交:

 

对于给定4个点确定的两条线段A1A2,B1B2:

typedef  struct {

  double  x, y;

} Point;

Point A1,A2,B1,B2;

 

判断两线段是否相交需要分两步确定:

 

1.快速排斥实验

设以线段A1A2和线段B1B2为对角线的矩形为M,N;

若M,N 不相交,则两个线段显然不相交;

判断矩形相交,只需判断某一矩形是否有顶点在另一个矩形内即可。

所以:只有当满足第一个条件时,两个线段才可能相交。

 

2.跨立实验

如果两线段相交,则两线段必然相互跨立对方.若A1A2跨立B1B2,则矢量( A1 - B1 ) 和(A2-B1)位于矢量(B2-B1)的两侧,

即:((A1-B1) × (B2-B1) )·( (A2-B1) × (B2-B1))<0。

上式可以改写成:((A1-B1) × (B2-B1)) · ((B2-B1) × (A2-B1))>0。

(A1-B1) × (B2-B1)=0时,说明A1B1和B2B1共线,但前面已经通过了快速排斥实验,所以A1一定在B1B2上,所以判断线段A1A2是否跨立B1B2的依据就是::((A1-B1) × (B2-B1)) · ((B2-B1) × (A2-B1))>=0。

同理,判断线段B1B2是否跨立A1A2的依据是::((B1-A1) × (A2-A1)) · ((A2-A1) × (B2-A1))>=0。

如图:

应用:

1.       判断两个线段相交

2.       判断线段与直线相交

3.       判断点在矩形内

代码如下:

/*
若线段v1和线段v2的界限框同时在x方向和y方向相交且v1(或者v2)跨立于v2(或者v1)所在的直线,则返回true,否则返回false
*/
typedef struct node
{
    double x,y;
}Point;
typedef struct line
{
    Point start,end;
}vector;
double multi(Point p1,Point p2,Point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
bool cross(vector v1,vector v2)
{
    if(max(v1.start.x,v1.end.x)>=min(v2.start.x,v2.end.x)&&max(v2.start.x,v2.end.x)>=min(v1.start.x,v1.end.x)&&max(v1.start.y,v1.end.y)>=min(v2.start.y,v2.end.y)&&max(v2.start.y,v2.end.y)>=min(v1.start.y,v1.end.y)&&multi(v2.start,v1.end,v1.start)*multi(v1.end,v2.end,v1.start)>=0&&multi(v1.start,v2.end,v2.start)*multi(v2.end,v1.end,v2.start)>=0)
      return true;
    return false;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值