ACWING 2805. 凸多边形

ACWING 2805. 凸多边形

描述

逆时针给出 \(n\) 个凸多边形的顶点坐标,求它们交的面积。

思路

半平面交模板。

代码

#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define pdd pair<double,double> 
const int N=510;
int cnt;
struct Line{
    pdd st,ed;
}line[N];
const double EPS=1e-8;
int sign(double x){
    if(fabs(x)<EPS) return 0;
    if(x<0) return -1;
    return 1;
}
double dcmp(double x,double y){
    if(fabs(y-x)<EPS) return 0;
    if(x<y) return -1;
    return 1;
}
double get_angle(const Line &a){
    return atan2(a.ed.y-a.st.y,a.ed.x-a.st.x);
}

pdd operator-(pdd a,pdd b){
    return {a.x-b.x,a.y-b.y};
}
double cross(pdd a,pdd b){
    return a.x*b.y-a.y*b.x;
} 
double area(pdd a,pdd b,pdd c){
    return cross(b-a,c-a);
}
bool cmp(const Line &a,const Line &b){
    double A=get_angle(a),B=get_angle(b);
    if(!dcmp(A,B)) return sign(area(a.st,a.ed,b.ed))<0;
    return A<B;
}
pdd get_line_intersection(pdd p,pdd v,pdd q,pdd w){
    auto u=p-q;
    double t=cross(w,u)/cross(v,w);
    return {p.x+v.x*t,p.y+v.y*t};
}
pdd get_line_intersection(Line a,Line b){
    return get_line_intersection(a.st,a.ed-a.st,b.st,b.ed-b.st);
}
pdd pg[N],ans[N];
int q[N];
bool on_right(Line &a,Line &b,Line &c){
    auto o=get_line_intersection(b,c);
    return sign(area(a.st,a.ed,o))<=0;
}
double half_plane_intersection(){
    sort(line,line+cnt,cmp);
    int hh=0,tt=-1;
    for(int i=0;i<cnt;i++){
        if(i && !dcmp(get_angle(line[i]),get_angle(line[i-1]))) continue;
        while(hh+1<=tt && on_right(line[i],line[q[tt-1]],line[q[tt]])) tt--;
        while(hh+1<=tt && on_right(line[i],line[q[hh]],line[q[hh+1]])) hh++;
        q[++tt]=i;
    }
    while(hh+1<=tt && on_right(line[q[hh]],line[q[tt-1]],line[q[tt]])) tt--;
    while(hh+1<=tt && on_right(line[q[tt]],line[q[hh]],line[q[hh+1]])) hh++;
    q[++tt]=q[hh];
    int k=0;
    for(int i=hh;i<tt;i++){
        ans[k++]=get_line_intersection(line[q[i]],line[q[i+1]]);
    }
    double res=0;
    for(int i=1;i+1<k;i++){
        res+=area(ans[0],ans[i],ans[i+1]);
    }
    return res/2;
}
int main(){
    int n,m;
    scanf("%d",&n);
    while(n--){
        scanf("%d",&m);
        for(int i=0;i<m;i++) cin>>pg[i].x>>pg[i].y;
        for(int i=0;i<m;i++){
            line[cnt++]={pg[i],pg[(i+1)%m]};
        }

    }
    double res=half_plane_intersection();
    printf("%.3lf\n",res);
    return 0;
}
posted @ 2021-02-15 21:07  ans20xx  阅读(39)  评论(0编辑  收藏  举报