• 线段相交(快速排斥和跨立)


    题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1264

    本来想用斜率来算,后来觉得要分太多情况,上网发现用快速排斥+跨立就能做

    快速排斥的意思是当两条线段分别构成的矩形范围没有相交,那么两直线肯定没没有交点,如下图

    如何判断两个矩形相交?一种错误的思路是一个矩形中的点在另一个矩形里,单如果是十字相交的矩形就不成立

    我的方法是找到两个矩形的中心点C1,C2,设两个矩形的宽和高分别为W1,H1,W2,H2

    那么只要满|C1.x-C2.x|<=(W1+W2)/2 && |C1.y-C2.y|<=(H1+H2)/2就是相交

    bool MBR(rec a1,rec a2)
    {
        p c[3];
        double w[3],h[3];
        c[1].x=(a1.left.x+a1.right.x)/2;
        c[1].y=(a1.left.y+a1.right.y)/2;
        c[2].x=(a2.left.x+a2.right.x)/2;
        c[2].y=(a2.left.y+a2.right.y)/2;
        w[1]=a1.right.x-a1.left.x;
        w[2]=a2.right.x-a2.left.x;
        h[1]=a1.left.y-a1.right.y;
        h[2]=a2.left.y-a2.right.y;
        if(abs(c[1].x-c[2].x)<=(w[1]+w[2])/2&&abs(c[1].x-c[2].x)<=(w[1]+w[2])/2)
            return true;
        return false;
        
    }

    排除必然不相交的情况后再来看哪些情况相交,这里用到跨立

    跨立即一向量跨过另一向量,如下图只需AC向量和AD向量在AB向量两侧,同时CA向量和CB向量在CD向量的两侧即可证明

    怎么实现在两侧?用向量叉乘(ACxAB)·(ABXAD)<=0即可说明AC与AD在AB两侧(要注意考虑重合的情况)

    以下是完整代码

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct p
    {
        double x,y;
    };
    struct vec
    {
        double x,y;
    };
    struct rec
    {
        p left,right;
    };
    
    rec rectangle(p a1,p a2)
    {
        rec r;
        
        r.left.x=min(a1.x,a2.x);
        r.left.y=max(a1.y,a2.y);
        r.right.x=max(a1.x,a2.x);
        r.right.y=min(a1.y,a2.y);
        return r;    
    }
    vec vector(p a1,p a2)
    {
        vec v;
        
        v.x=a2.x-a1.x;
        v.y=a2.y-a1.y;
        return v;
    }
    double vec_pro(vec v1,vec v2)
    {
        return v1.x*v2.y-v1.y*v2.x;
    }
    bool MBR(rec a1,rec a2)
    {
        p c[3];
        double w[3],h[3];
        c[1].x=(a1.left.x+a1.right.x)/2;
        c[1].y=(a1.left.y+a1.right.y)/2;
        c[2].x=(a2.left.x+a2.right.x)/2;
        c[2].y=(a2.left.y+a2.right.y)/2;
        w[1]=a1.right.x-a1.left.x;
        w[2]=a2.right.x-a2.left.x;
        h[1]=a1.left.y-a1.right.y;
        h[2]=a2.left.y-a2.right.y;
        if(abs(c[1].x-c[2].x)<=(w[1]+w[2])/2&&abs(c[1].x-c[2].x)<=(w[1]+w[2])/2)
            return true;
        return false;
        
    }
    int main()
    {
        int t;
        
        cin>>t;
        while(t--)
        {    
            rec r[3];
            p a[5];
            bool is_intersect=true,need_judge=true;
            for(int i=1;i<=4;i++)
                cin>>a[i].x>>a[i].y;
                r[1]=rectangle(a[1],a[2]);
                r[2]=rectangle(a[3],a[4]);
                if(!MBR(r[1],r[2]))
                {
                    is_intersect=false;
                    need_judge=false;
                }
                if(need_judge)
                {
                    vec AB=vector(a[1],a[2]);
                    vec AC=vector(a[1],a[3]);
                    vec AD=vector(a[1],a[4]);
                    vec CA=vector(a[3],a[1]);
                    vec CB=vector(a[3],a[2]);
                    vec CD=vector(a[3],a[4]);
                    if(vec_pro(AB,AC)*vec_pro(AB,AD)<=0&&vec_pro(CD,CA)*vec_pro(CD,CB)<=0)
                        is_intersect=true;
                    else
                        is_intersect=false;
                }
                if(is_intersect)
                    cout<<"Yes"<<endl;
                else
                    cout<<"No"<<endl;
        }
    }
  • 相关阅读:
    tcp传送报文
    整理下本周工作中遇到的疑问;uid/euid/suid;docker镜像管理
    网络隔离
    ubuntu 只有客人会话登录(第一次深刻感受文件权限的威力 )
    ubuntu 只有客人会话登录(第一次深刻感受文件权限的威力)
    使用gdb查看栈帧的情况,有ebp
    使用gdb查看栈帧的情况, 没有ebp
    再看perf是如何通过dwarf处理栈帧的
    dwarf是如何处理栈帧的?
    数据库设计的误区—>CHAR与VARCHAR
  • 原文地址:https://www.cnblogs.com/NDKY9/p/7451976.html
Copyright © 2020-2023  润新知