zju1648 判断两条线段是否相交

1     快速排斥试验   
设以线段      P1P2      为对角线的矩形为R,     
设以线段      Q1Q2为对角线的矩形为T,   
如果R和T不相交,显然两线段不会相交。   
    
2     跨立试验   
如果两线段相交,则两线段必然相互跨立对方。   
若P1P2跨立Q1Q2      ,则矢量( P1- Q1)     
和(P2-Q1)位于矢量( Q2-Q1)的两侧,   
即(P1- Q1)×(Q2 -Q1) * (P2 - Q1)×( Q2 - Q1 ) >     0。   
上式可改写成(P1-Q1)×(Q2 -Q1) * (Q2 - Q1)×(P2 -Q1) > 0。   
当(P1 -Q1)×(Q2 -Q1)=0 时,说明( P1 - Q1)和(Q2 - Q1)共线,   
但是因为已经通过快速排斥试验,所以      P1      一定在线段      Q1Q2上;   
同理,(Q2 -Q1)×(P2 -Q1)=0 说明      P2      一定在线段      Q1Q2上。   
所以判断P1P2跨立Q1Q2的依据是:   
( P1 - Q1 )×(Q2 - Q1) * (Q2 - Q1)×( P2 -Q1) >=      0。   
同理判断Q1Q2跨立P1P2的依据是:   
( Q1 - P1 )×( P2 - P1) * ( P2 - P1)×(Q2 - P1) >= 0。   

X:为叉积 叉积的计算公式为:  P1 X P2 = x1y2 - x2y1;
----以下是代码:

#include < iostream >
#include
< string >
using   namespace  std;
struct  Point
{
double x;
double y;
}
;
struct  segmemt
{
     Point s;
Point t;
}
;
double  MAX( double  a, double  b)
{
if(a>b)return a;
return b;
}

double  MIN( double  a, double  b)
{
if(a<b)return a;
return b;
}

// 判断p在不在ps---pe的顺时针或逆时针
/* m = (pe-ps) X (p-ps) m>0 逆时针 m==0 3点在同一直线 m<0 顺时针 */
double  mulpti(Point ps , Point pe , Point p)
{
double m;

m
=(pe.x-ps.x)*(p.y-ps.y)-(p.x-ps.x)*(pe.y-ps.y);

return m;
}

bool  inser(Point p1, Point p2 , Point p3, Point p4)
{
if(MAX(p1.x,p2.x)>=MIN(p3.x,p4.x) &&
     MAX(p3.x,p4.x)
>=MIN(p1.x,p2.x) &&
     MAX(p1.y,p2.y)
>=MIN(p3.y,p4.y) &&
     MAX(p3.y,p4.y)
>=MIN(p1.y,p2.y) &&
     mulpti(p1,p2,p3)
*mulpti(p1,p2,p4)<=0 &&
     mulpti(p3,p4,p1)
*mulpti(p3,p4,p2)<=0)
     
return true;
else
     
return false;
}

int  main()
{
int n,i,j;
bool flag;
segmemt list[
2000];
while(cin>>n)
{
   flag 
= true;
         
for(i=0;i<n;i++)
   
{
    cin
>>list[i].s.x>>list[i].s.y;
             cin
>>list[i].t.x>>list[i].t.y;
   }

   
if(n>1)
   
{
             
for(i=0;i<n-1;i++)
    
{
     
for(j=i+1;j<n;j++)
     
{
                     
if(inser(list[i].s,list[i].t,list[j].s,list[j].t))
      
{
                           flag 
= false;
         
break;
      }

     }

     
if(flag == false)
      
break;
    }

   }

   
if(flag)
    cout
<<"ok!"<<endl;
   
else
    cout
<<"burned!"<<endl;
}

return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值