还以为要用卷包裹的方法求出所有区域呢。。。然后不会啊。。。
事实上可以用切割凸多边形的方法来求出所有区域。大白上有切割凸多边形的模板,在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;
}