zoukankan      html  css  js  c++  java
  • 线段相交(快速排斥和跨立)

    题目: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;
        }
    }
  • 相关阅读:
    为什么要进行需求分析?通常对软件系统有哪些需求?
    面向过程(或者叫结构化)分析方法与面向对象分析方法到底区别在哪里?请根据自己的理解简明扼要的回答。
    我们说 软件企业 = 软件 + 商业模式 下面提到的一个游戏团队, 有很好的软件,但是商业模式和其他软件之外的因素呢?有没有考虑到? http://news.cnblogs.com/n/528911/
    14软件工程第八次作业
    14软件工程第七次作业
    14软件工程第六次作业
    14软件工程第五次作业
    14软件工程第四次作业
    14软件工程第三次作业
    14软件工程第二次作业
  • 原文地址:https://www.cnblogs.com/NDKY9/p/7451976.html
Copyright © 2011-2022 走看看