现在的位置: 首页 > 综合 > 正文

zju1648 判断两条线段是否相交

2013年12月02日 ⁄ 综合 ⁄ 共 1921字 ⁄ 字号 评论关闭

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

【上篇】
【下篇】

抱歉!评论已关闭.