杭电 1086 You can Solve a Geometry Problem too 判断线段是否相交.

来源:互联网 发布:个股评测软件 编辑:程序博客网 时间:2024/05/18 13:29
判断两线段是否相交  有一个比较容易理解的快速排斥试验.
首先我们获得两条线段 我们首先需要把两个线段都自行扩张成为一个矩形 如下图:
根据观察就能知道 如果两个矩形不相交的话 两条线段是一定不会相交的.
所以通过快速排斥试验我们就能直接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;}



0 0
原创粉丝点击