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

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

设有点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张图片

应用:

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;
}



 

你可能感兴趣的:(计算几何之线段性质(一):判断两线段相交)