杭电 1086 You can Solve a Geometry Problem too 判断线段是否相交.
2015-12-10 22:43
183 查看
判断两线段是否相交 有一个比较容易理解的快速排斥试验.
首先我们获得两条线段 我们首先需要把两个线段都自行扩张成为一个矩形 如下图:
根据观察就能知道 如果两个矩形不相交的话 两条线段是一定不会相交的.
所以通过快速排斥试验我们就能直接pass掉很多情况.
如果给出四个点(两条线段)我们可以通过以下代码实现判断快速排斥:
以下是跨立试验的过程:
判断线段是否相交问题.要用到叉乘向量的知识 这里贴上向量叉乘的函数:
在线段判断是否相交的函数中用处:
判断向量bc在向量ab的顺时针方向还是逆时针方向.
下边图是我盗来的图~对应理解一下吧0.0
现在请读者在纸上画出两个图 一个是线段ab和cd相交的图 一个是不相交的图
然后对应如下代码体会其作用:
u。v只考虑其大于0小于0还是为0(只考虑其实正数 负数还是0)
表示两条线段的所处几何方向
这时候你画的图就有用了~
如果ab和cd相交的情况下 向量bc是在ab的顺时针方向,并且向量bd是在ab的逆时针方向.是不是有点柳暗花明的感觉了~?
别着急 .我们继续看.如果确实有以上结论了是否就能判断ab和cd一定相交了呢?
这里上个图:
图片转载声明:http://blog.csdn.net/lishuhuakai/article/details/8263160
对应理解一下 只有一组满足是不够的~~~~~
所以这里还需要再填上另外一组 :
所以如果有了
u*v<=0.00000001 && w*z<=0.00000001
我们就能判断出两线段是一定相交的了~
下边给上AC完整代码:
首先我们获得两条线段 我们首先需要把两个线段都自行扩张成为一个矩形 如下图:
根据观察就能知道 如果两个矩形不相交的话 两条线段是一定不会相交的.
所以通过快速排斥试验我们就能直接pass掉很多情况.
如果给出四个点(两条线段)我们可以通过以下代码实现判断快速排斥:
if(!(min(a.x,b.x)<=max(c.x,d.x) && min(c.y,d.y)<=max(a.y,b.y)&& min(c.x,d.x)<=max(a.x,b.x) && min(a.y,b.y)<=max(c.y,d.y)))
以下是跨立试验的过程:
判断线段是否相交问题.要用到叉乘向量的知识 这里贴上向量叉乘的函数:
struct point { double x,y; }; void chacheng(point a,point b,point c) { return (c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y); }
在线段判断是否相交的函数中用处:
判断向量bc在向量ab的顺时针方向还是逆时针方向.
下边图是我盗来的图~对应理解一下吧0.0
现在请读者在纸上画出两个图 一个是线段ab和cd相交的图 一个是不相交的图
然后对应如下代码体会其作用:
u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);//c.b.a//u的正负表示bc在ab的顺时针方向还是逆时针方向. v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y);//d.b.a//同理
u。v只考虑其大于0小于0还是为0(只考虑其实正数 负数还是0)
表示两条线段的所处几何方向
这时候你画的图就有用了~
如果ab和cd相交的情况下 向量bc是在ab的顺时针方向,并且向量bd是在ab的逆时针方向.是不是有点柳暗花明的感觉了~?
别着急 .我们继续看.如果确实有以上结论了是否就能判断ab和cd一定相交了呢?
这里上个图:
图片转载声明:http://blog.csdn.net/lishuhuakai/article/details/8263160
对应理解一下 只有一组满足是不够的~~~~~
所以这里还需要再填上另外一组 :
w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y);//a.d.c z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y);//b.d.c
所以如果有了
u*v<=0.00000001 && w*z<=0.00000001
我们就能判断出两线段是一定相交的了~
下边给上AC完整代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
struct dian
{
double x,y;
};
struct xian
{
dian a;dian b;
};
//判断两条线段是否相交 首先一定要通过快速排斥试验之后 再通过跨立试验之后就能判断了这两线段相交.
bool judge(dian a,dian b,dian c,dian d)
{
//快速排斥
if(!(min(a.x,b.x)<=max(c.x,d.x) && min(c.y,d.y)<=max(a.y,b.y)&& min(c.x,d.x)<=max(a.x,b.x) && min(a.y,b.y)<=max(c.y,d.y)))
//判断两条线段组成的矩形是否相交 如果不相交 那么这两条线是不会相交的.
//特别要注意一个矩形含于另一个矩形之内的情况
return false;
double u,v,w,z;
//定a定c.
//c.d在ab两端 a.b在cd两端.就能判断相交.
u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);//c.b.a//u的正负表示bc在ab的顺时针方向还是逆时针方向. v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y);//d.b.a//同理
w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y);//a.d.c z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y);//b.d.c
return (u*v<=0.00000001 && w*z<=0.00000001);
}
int main()
{
int n;
xian str[101];
while(cin>>n && n!=0)
{
int count=0;
for(int i=0;i<n;i++)
{
cin>>str[i].a.x>>str[i].a.y>>str[i].b.x>>str[i].b.y;
}
for(int i=0;i<n;i++)//遍历所有点什么的还是比较容易理解的~.
for(int j=i+1;j<n;j++)
if(judge(str[i].a,str[i].b,str[j].a,str[j].b)) count++;
cout<<count<<endl;
}
return 0;
}
相关文章推荐
- install 命令
- 对web的request的全部值进行了提取
- Android 自定义View修炼-自定义加载进度动画XCLoadingImageView
- 六要点实现Unity3D开发性能优化
- iOS运用fabric记录crash日志过程
- 机器学习中的范数规则化之(一)L0、L1与L2范数(转)
- 关于图像合成所引申的几个函数
- 我收录整理的优秀OC技术类文章
- C++ 关联容器
- Linux基础5 命令的帮助
- Ashmem 对 Android 内存分配与共享的增强
- HDOJ 1716 排列2 (next_permutation或dfs)
- JQuery获取append后的动态元素:live()和on()
- 第二章 Linux系统安装 - VMware虚拟机安装、卸载与使用
- 子类重写父类属性和方法
- Fuse学习<1>
- 数据库常见面试题目
- CentOS 6.5 系统 LAMP(Apache+MySQL+PHP)源码安装步骤
- iOS常用开发资源整理
- 简单的图片轮播