半平面相交

#include<bits\stdc++.h>
using namespace std;
const int N=600;
const double eps= 1e-10;
struct P{
    double x,y;
    P(){x=y=0;}
    P(double _x,double _y){x=_x,y=_y;}
    P operator-(const P&a)const{return P(x-a.x,y-a.y);}
    P operator+(const P&a)const{return P(x+a.x,y+a.y);}
    P operator*(double a)const{return P(x*a,y*a);}
    void read(){scanf("%lf%lf",&x,&y);}
}p[N],a[N];
struct L{
    //
    P p,v;double a;
    L(){}
    L(P _p,P _v){p=_p,v=_v;}
    bool operator<(const L&b)const{return a<b.a;}
    void cal(){a=atan2(v.y,v.x);}
}line[N],q[N];
int n,m,i,cl;
//叉积
double cross(const P&a,const P&b){return a.x*b.y-a.y*b.x;}
//新的半平面,在这条向量a->b的逆时针方向
// 插入新直线
void newL(const P&a,const P&b){line[++cl]=L(a,b-a);}
// 顺时针?
bool left(const P&p,const L&l){return cross(l.v,p-l.p)>0;}

// 面积的交集
P pos(const L&a,const L&b){
    P x=a.p-b.p;double t=cross(b.v,x)/cross(a.v,b.v);
    return a.p+a.v*t;
}
// 主代码
double halfplane(){
    // 直线计算斜率
    for(int i=1;i<=cl;i++)line[i].cal();
    // 边排序(极角排序)
    sort(line+1,line+cl+1);
    // 双端队列
    int h=1,t=1;
    // 边1入队
    q[1]=line[1];
    for(int i=2;i<=cl;i++){
//       出队
//      队伍非空+顺时针方向
        while(h<t&&!left(p[t-1],line[i]))t--;
//        入队
//      队伍空
        while(h<t&&!left(p[h],line[i]))h++;
//      在队列里、
        if(fabs(cross(q[t].v,line[i].v))<eps)
            q[t]=left(q[t].p,line[i])?q[t]:line[i];
        else q[++t]=line[i];
        if(h<t)
            p[t-1]=pos(q[t],q[t-1]);
    }
    while(h<t&&!left(p[t-1],q[h]))t--;
    p[t]=pos(q[t],q[h]);
    if(t-h<=1)return 0;
    double ans=0;
    for(int i=h;i<t;i++)ans+=cross(p[i],p[i+1]);
    return (ans+cross(p[t],p[h]))/2;
}
int main(){
    scanf("%d",&n);
    while(n--){
        scanf("%d",&m);
        for(i=0;i<m;i++)a[i].read();
        for(i=0;i<m;i++)newL(a[i],a[(i+1)%m]);
    }
    printf("%.3f",halfplane());
}
posted @ 2021-11-12 13:39  yesuweiYYYY  阅读(32)  评论(0编辑  收藏  举报