您的位置:首页 > 其它

1288: 计算几何练习题——线段相交

2014-04-27 11:35 323 查看
描述

线段相交测试在计算几何中是经常用到的,给定线段P1P2(P1和P2是线段的两端点,且不重合)、P3P4(P3和P4是线段的两端点,且不重合),判断P1P2和P3P4是否相交。P1P2和P3P4不重合,即指只存在一个点P,它既落在P1P2上又落在P3P4上(含线段的端点)。

输入

输入数据有多组,第一行为测试数据的组数N,下面包括2N行,每组测试数据含2行,第一行为P1P2的坐标值,第二行为P3P4的坐标值,比如下面的数据

1

0 0 1 1

2 2 3 3

表示P1、P2、P3、P4的坐标分别为:P1(0,0),P2(1,1),P3(2,2),P4(3,3)

输出

判断每组数据中的线段P1P2和P3P4是否相交,如果相交输出YES,否则输出NO。每组数据输出占一行。

样例输入

1
0 0 1 1
2 2 3 3


样例输出

NO


题目来源
http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1288
判断两条线段是否相交首先要满足两个条件:

1.快速排斥实验,即以两条线段为对角线的矩形不相交

2.跨立实验,即任意线段的两个端点在另一条线段的不同侧,

不过满足上面两条件后还要注意一点,就是两条线段可能有重合部分,这也要加以判断.

#include <iostream>
#include <cmath>
using namespace std;
struct Node
{
double x,y;
};
double cross(double x1,double y1,double x2,double y2)//计算叉乘
{
return x1*y2-x2*y1;
}

bool kspc(Node a,Node b,Node c,Node d)//快速排斥
{
if(min(a.x,b.x)>max(c.x,d.x) ||
min(a.y,b.y)>max(c.y,d.y) ||
max(a.x,b.x)<min(c.x,d.x) ||
max(a.y,b.y)<min(c.y,d.y))
return false;
return true;
}
bool klsy(Node a,Node b,Node c,Node d)//跨立实验
{
if(cross(c.x-a.x,c.y-a.y,c.x-d.x,c.y-d.y)*cross(c.x-b.x,c.y-b.y,c.x-d.x,c.y-d.y)<=0 &&
cross(a.x-c.x,a.y-c.y,a.x-b.x,a.y-b.y)*cross(a.x-d.x,a.y-d.y,a.x-b.x,a.y-b.y)<=0)
return true;
return false;
}
bool deng_node(Node a,Node b)//判断两点是否相等
{
if(a.x==b.x && a.y==b.y)
return true;
return false;
}
int main()
{
int n;
Node d1[2],d2[2];
cin>>n;
while(n--)
{
cin>>d1[0].x>>d1[0].y>>d1[1].x>>d1[1].y;
cin>>d2[0].x>>d2[0].y>>d2[1].x>>d2[1].y;
if(kspc(d1[0],d1[1],d2[0],d2[1]) &&
klsy(d1[0],d1[1],d2[0],d2[1]))//同时满足快速排斥和跨立实验
{
if(fabs(cross(d2[0].x-d1[0].x,d2[0].y-d1[0].y,d2[0].x-d2[1].x,d2[0].y-d2[1].y))<0.000001 &&
fabs(cross(d2[0].x-d1[1].x,d2[0].y-d1[1].y,d2[0].x-d2[1].x,d2[0].y-d2[1].y))<0.000001)//如果两条线段有重合
{
if((deng_node(d1[0],d2[0])&&!deng_node(d1[1],d2[1])) ||
(deng_node(d1[0],d2[1])&&!deng_node(d1[1],d2[0])) ||
(deng_node(d1[1],d2[0])&&!deng_node(d1[0],d2[1])) ||
(deng_node(d1[1],d2[1])&&!deng_node(d1[0],d2[0])) )//如果重合的只是一个端点
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
else
cout<<"YES"<<endl;
}
else
cout<<"NO"<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: