切割凸多边形,圆与多边形(块和圆盘,UVA 12296)

还以为要用卷包裹的方法求出所有区域呢。。。然后不会啊。。。

事实上可以用切割凸多边形的方法来求出所有区域。大白上有切割凸多边形的模板,在P277。

然后遍历所有圆,找到所有与之相交的多边形即可。

在这个过程中需要判断圆与多边形之间的关系。

大白上讲得很清楚了。

就是如果完全没有公共点,那就判断是否互相包含。具体一点就是看圆心是否在凸多边形内,凸多边形的任意一个点是否在圆内。

否则他们一定相交,如果是规范相交,那么他们一定相交。

否则他们的交点全都在多边形的点上。此时只需要判断是否有某个边完全在圆内即可。具体一点就是取边的中点,然后判断是否在圆内。


每组数据后输出一个空行。。。


代码

#include<bits/stdc++.h>
using namespace std;

struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){}
    void Read()
    {
        scanf("%lf %lf",&x,&y);
    }
};

typedef Point Vector;
typedef vector<Point>Poly;

const double eps = 1e-10;
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}

Point operator + (Point A,Vector B)
{
    return Point(A.x+B.x,A.y+B.y);
}

Vector operator - (Point A,Point B)
{
    return Vector(A.x-B.x,A.y-B.y);
}

Vector operator * (Vector V,double t)
{
    return Vector(V.x*t,V.y*t);
}

double Dot(Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}

double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}

double Len(Vector V)
{
    return sqrt(Dot(V,V));
}

double Dist(Point A,Point B)
{
    return Len(B-A);
}

Point MidPoint(Point A,Point B)
{
    return Point((A.x+B.x)/2,(A.y+B.y)/2);
}

bool OnLeft(Point P,Point A,Point B)
{
    return dcmp(Cross(B-A,P-A))>=0;
}

Point GetIntersection(Point A,Point B,Point C,Point D)
{
    Vector V1=B-A;
    Vector V2=D-C;
    Vector V3=C-A;
    double t=Cross(V3,V2)/Cross(V1,V2);
    return A+V1*t;
}

bool SegmentProperIntersection(Point A,Point B,Point C,Point D)
{
    Vector V1=C-A;
    Vector V2=D-A;
    Vector V3=A-C;
    Vector V4=B-C;
    return dcmp(Cross(B-A,V1))*dcmp(Cross(B-A,V2))<0&&dcmp(Cross(D-C,V3))*dcmp(Cross(D-C,V4))<0;
}

Poly GetPolyIntersection(Poly P,Point A,Point B)
{
    Poly ret;
    int sz=P.size();
    for(int i=0;i<sz;i++)
    {
        if(OnLeft(P[i],A,B)) ret.push_back(P[i]);
        if(SegmentProperIntersection(P[i],P[(i+1)%sz],A,B)) ret.push_back(GetIntersection(P[i],P[(i+1)%sz],A,B));
    }
    return ret;
}

bool OnSegment(Point P,Point A,Point B)
{
    Vector V1=A-P;
    Vector V2=B-P;
    return dcmp(Cross(V1,V2))==0&&dcmp(Dot(V1,V2))<=0;
}

bool IsPointInPoly(Point P,Poly poly)
{
    int wn=0;
    int n=poly.size();
    for(int i=0;i<n;i++)
    {
        if(OnSegment(P,poly[i],poly[(i+1)%n])) return false;
        int k=dcmp(Cross(poly[(i+1)%n]-poly[i],P-poly[i]));
        int d1=dcmp(poly[i].y-P.y);
        int d2=dcmp(poly[(i+1)%n].y-P.y);
        if(k>0&&d1<=0&&d2>0) wn++;
        if(k<0&&d2<=0&&d1>0) wn--;
    }
    return wn!=0;
}

Point shenchang(Point A,Point B)
{
    Vector V=B-A;
    return A+V*1.1;
}

struct Circle
{
    Point c;
    double r;
    Circle(Point c=Point(),double r=0):c(c),r(r){}
    void Read()
    {
        c.Read();
        scanf("%lf",&r);
    }
    bool Contain(Point P)
    {
        return dcmp(Dist(c,P)-r)<0;
    }
};

bool InSegment(Point P,Point A,Point B)
{
    Vector V1=A-P;
    Vector V2=B-P;
    return dcmp(Cross(V1,V2))==0&&dcmp(Dot(V1,V2))<0;
}

bool IsSegmentCircleProperIntersection(Point A,Point B,Circle C)
{
    Vector V=B-A;
    double a=V.x;
    double b=A.x-C.c.x;
    double c=V.y;
    double d=A.y-C.c.y;
    double e=a*a+c*c;
    double f=2*(a*b+c*d);
    double g=b*b+d*d-C.r*C.r;
    double delta=f*f-4*e*g;
    if(dcmp(delta)<=0) return false;
    double t;
    t=(-f-sqrt(delta))/(2*e);
    Point X=A+V*t;
    if(InSegment(X,A,B)) return true;
    t=(-f+sqrt(delta))/(2*e);
    Point Y=A+V*t;
    if(InSegment(Y,A,B)) return true;
    return false;
}

bool IsCirclePolyIntersection(Circle C,Poly P)
{
    if(IsPointInPoly(C.c,P)) return true;
    int n=P.size();
    for(int i=0;i<n;i++)
    {
        if(C.Contain(P[i])) return true;
        if(C.Contain(MidPoint(P[i],P[(i+1)%n]))) return true;
        if(IsSegmentCircleProperIntersection(P[i],P[(i+1)%n],C)) return true;
    }
    return false;
}

double PolyArea(Poly P)
{
    double ret=0;
    int n=P.size();
    for(int i=1;i<n-1;i++)
        ret+=Cross(P[i]-P[0],P[i+1]-P[0]);
    return ret/2;
}

const int maxn = 25;
vector<Poly>polys[2];
int now;
int n,m,L,W;
vector<int>id[maxn];
double area[maxn*maxn];

int main()
{
    while(scanf("%d %d %d %d",&n,&m,&L,&W)==4&&n&&m&&L&&W)
    {
        Point A,B;
        now=0;
        Poly s;
        s.push_back(Point(0,0));
        s.push_back(Point(L,0));
        s.push_back(Point(L,W));
        s.push_back(Point(0,W));
        polys[now].clear();
        polys[now].push_back(s);
        for(int i=0;i<n;i++)
        {
            polys[now^1].clear();
            A.Read();
            B.Read();
            A=shenchang(B,A);
            B=shenchang(A,B);
            for(unsigned int i=0;i<polys[now].size();i++)
            {
                Poly P=GetPolyIntersection(polys[now][i],A,B);
                if(P.size()>2) polys[now^1].push_back(P);
                P=GetPolyIntersection(polys[now][i],B,A);
                if(P.size()>2) polys[now^1].push_back(P);
            }
            now^=1;
        }
        Circle C;
        for(int i=0;i<m;i++)
        {
            C.Read();
            id[i].clear();
            for(unsigned int j=0;j<polys[now].size();j++)
                if(IsCirclePolyIntersection(C,polys[now][j]))
                    id[i].push_back(j);
        }
        for(unsigned int i=0;i<polys[now].size();i++)
            area[i]=PolyArea(polys[now][i]);
        for(int i=0;i<m;i++)
        {
            vector<double>vec;
            for(unsigned int j=0;j<id[i].size();j++)
                vec.push_back(area[id[i][j]]);
            sort(vec.begin(),vec.end());
            printf("%d",vec.size());
            for(unsigned int j=0;j<vec.size();j++)
                printf(" %.2lf",vec[j]);
            puts("");
        }
        puts("");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值