求多边形相交面积(暴力 / 半平面交)

暴力: 貌似只适用于求两个多边形的相交面积,但是可以求任意多边形(凹凸)。
1.设两个多边形点集为P1P2,相交区域点集为P
2.遍历P1的点是否在P2内,若在内部,则加入点集P;对P2也做相同操作。
3.遍历P1的边和P2的边,求出两个多边形的交点,将交点加入P。
4.求点集P的面积。

半平面交: 这个只适用凸包,但是可以求任意个凸包最终相交的面积。
1.把每个凸包的点按照逆时针排序。(当然也看自己的算法是要什么顺序,大多数需要逆时针)
2.将每个凸包的边放入边集L。
3.求边集L的半平面交,再求半平面交的面积。
求一次半平面交:O(nlogn),n为边数

题目:ECNU 1624

暴力就不写了,写个半平面交的:

#include<bits/stdc++.h>
#define ll long long
#define lf double
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define Rep(i,l,r) for(int i=(l);i<=(r);i++)
using namespace std;

struct Point {double x, y;};
typedef Point vector_t;
typedef Point point_t;
struct Line {Point x;vector_t v;};

double Cross(const vector_t& x, const vector_t& y) {return x.x * y.y - x.y * y.x;}  //叉积
vector_t operator*(const vector_t& v, double t) {return (vector_t){v.x * t, v.y * t};}
vector_t operator+(const vector_t& a, const vector_t& b) {return (vector_t){a.x + b.x, a.y + b.y};}
Point operator-(const Point& a, const Point& b) {return (Point){a.x - b.x, a.y - b.y};}

point_t GetLineIntersection(Line a,Line b){//求两直线交点
    Point P=a.x;vector_t v=a.v;
    Point Q=b.x;vector_t w=b.v;
    vector_t u = P-Q;
    double t = Cross(w, u)/Cross(v, w);
    return P+v*t;//由直线的点向式而来
}

double eps=1e-6;
Point tmpP[500];
Line tmpL[500];
bool cmp1(const Line& a,const Line& b) { return atan2(a.v.y,a.v.x)<atan2(b.v.y,b.v.x); }//极角排序
int dcmp(double x){ if(fabs(x)<eps)return 0; if(x>0)return 1; return -1;}
bool Onleft(Line l,Point p) { return dcmp(Cross(l.v,(p-l.x))) > 0; }//ToLeftTest
int HalfPol(Line *l,int n,vector<Point> &p)
{
    sort(l,l+n,cmp1);//把边按极角排序
    int hd = 0,tl = 0;
    tmpL[0] = l[0];
    for(int i=0;i<n;i++)
    {
        while(hd<tl&&!Onleft(l[i],tmpP[tl-1]))tl--;
        while(hd<tl&&!Onleft(l[i],tmpP[hd]))hd++;
        tmpL[++tl] = l[i];
        if(!dcmp(Cross(tmpL[tl].v,tmpL[tl-1].v)))
        {
            tl--;
            if(Onleft(tmpL[tl],l[i].x))tmpL[tl]=l[i];
        }
        if(hd<tl)tmpP[tl-1] = GetLineIntersection(tmpL[tl-1],tmpL[tl]);//求两直线交点
    }
    while(hd<tl&&!Onleft(tmpL[hd],tmpP[tl-1]))tl--;
    if(tl-hd<=1)return 0;
    tmpP[tl] = GetLineIntersection(tmpL[hd],tmpL[tl]);
    for(int i=hd;i<=tl;i++)p.push_back(tmpP[i]);
    return tl-hd+1;
}
double PolygonArea(point_t* p, int n){//p为端点集合,n为端点个数
    double s = 0;
    for(int i = 1; i < n-1; i++)
        s += Cross(p[i]-p[0], p[i+1]-p[0]);
    return s/2;
}

int n,m;
Point P[205];
Line L[205];
vector<Point>s;
Point ss[205];

int main()
{
    cin>>n;
    int cntl=0;
    Rep(i,0,n-1){
        double x,y;cin>>x>>y;
        P[i].x=x;P[i].y=y;
    }
    for(int i=0;i<n;i++){
        L[cntl++].v=P[i]-P[(i+1)%n];
        L[cntl].x=P[(i+1)%n];
    }
    cin>>m;
    Rep(i,0,m-1){
        double x,y;cin>>x>>y;
        P[i].x=x;P[i].y=y;
    }
    for(int i=0;i<m;i++){//题目按顺时针给的,就反着来
        L[cntl].v=P[i]-P[(i+1)%m];
        L[cntl].x=P[(i+1)%m];
        cntl++;
    }
    int sn=HalfPol(L,cntl,s);
    std::copy(s.begin(),s.end(),ss);//把s的数据copy到ss
    double S=PolygonArea(ss,sn);
    printf("%.2lf\n",S);
    return 0;
}

参考:ECNU 1624 求交集多边形面积
ECNU 1624 求交集多边形面积

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值