zju1648 判断两条线段是否相交
2007-08-28 01:59
417 查看
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;
}
设以线段 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;
}
相关文章推荐
- 判断两条线段是否相交
- 已知两条线段端点,判断是否相交及交点
- 判断两条线段是否相交
- 判断两条线段是否相交
- 如何判断平面上两条线段(注意是线段)是否相交?(某公司校园招聘面试试题)
- Circuit Board(zju1648,判断线段相交)
- 判断两条线段是否相交
- 判断两条线段是否相交(三种算法)
- 关于如何判断在平面上的两条线段是否相交
- 判断两条线段是否相交 计算几何
- 两条线段知道端点line1(x1,y1)(x2,y2)line2(x3,y3)(x4,y4),判断两条线段是否相交,交点坐标(x,y)
- 判断两条线段是否相交
- 判断是否两条线段相交
- 判断两条线段是否相交
- 模板——判断两条线段是否相交(严格与不严格)
- 判断两条线段是否相交
- 判断两条线段是否相交
- 计算几何 --- 判断两条线段是否相交(平面内)
- zoj 1648 判断线段是否相交
- 判断两条线段是否相交