除草,把最近的10k代码拉出来表演
#include<bits/stdc++.h>
#define deb(x) cerr<< #x <<" = " <<x<<endl
using namespace std;
const int maxn=1010;
const double eps=5e-9;
const double pi=acos(-1);
double form(double x){
while(x>=2*pi)x-=2*pi;
while(x<0)x+=2*pi;
return x;
}
int sgn(double x){return (x>eps)-(x<-eps);}
int sgn(double a,double b){return sgn(a-b);}
double sqr(double x){return x*x;}
namespace Union{
struct P{
double x,y;
P(){}
P(double x,double y):x(x),y(y){}
double len2(){
return sqr(x)+sqr(y);
}
double len(){
return sqrt(len2());
}
void print(){
fprintf(stderr,"(%.3f,%.3f)\n",x,y);
}
P turn90(){return P(-y,x);}
P norm(){return P(x/len(),y/len());}
P rot(double rad){
return P(x*cos(rad)-y*sin(rad),x*sin(rad)+y*cos(rad));
}
void read(){
scanf("%lf%lf",&x,&y);
}
};
bool operator<(P a,P b){
return sgn(a.x,b.x) ? a.x<b.x : a.y<b.y;
}
bool operator==(P a,P b){
return !sgn(a.x-b.x) and !sgn(a.y-b.y);
}
P operator+(P a,P b){
return P(a.x+b.x,a.y+b.y);
}
P operator-(P a,P b){
return P(a.x-b.x,a.y-b.y);
}
P operator*(P a,double b){
return P(a.x*b,a.y*b);
}
P operator/(P a,double b){
return P(a.x/b,a.y/b);
}
double operator^(P a,P b){
return a.x*b.x + a.y*b.y;
}
double operator*(P a,P b){
return a.x*b.y - a.y*b.x;
}
double det(P a,P b,P c){
return (b-a)*(c-a);
}
double dis(P a,P b){
return (b-a).len();
}
double Area(vector<P>poly){
double ans=0;
for(int i=1;i<poly.size();i++)
ans+=(poly[i]-poly[0])*(poly[(i+1)%poly.size()]-poly[0]);
return ans/2;
}
struct L{
P a,b;
L(){}
L(P a,P b):a(a),b(b){}
P v(){return b-a;}
};
bool onLine(P p,L l){
return sgn((l.a-p)*(l.b-p))==0;
}
bool onSeg(P p,L s){
return onLine(p,s) and sgn((s.b-s.a)^(p-s.a))>=0 and sgn((s.a-s.b)^(p-s.b))>=0;
}
bool parallel(L l1,L l2){
return sgn(l1.v()*l2.v())==0;
}
P intersect(L l1,L l2){
double s1=det(l1.a,l1.b,l2.a);
double s2=det(l1.a,l1.b,l2.b);
return (l2.a*s2-l2.b*s1)/(s2-s1);
}
P project(P p,L l){
return l.a+l.v()*((p-l.a)^l.v())/l.v().len2();
}
double dis(P p,L l){
return fabs((p-l.a)*l.v())/l.v().len();
}
struct C{
P o;
double r;
C(){}
C(P _o,double _r):o(_o),r(_r){}
void read(){
o.read();
scanf("%lf",&r);
}
P at(double rad){
return o+P(r,0).rot(rad);
}
double ang(P p){
double t=atan2(p.y-o.y,p.x-o.x);
return form(t);
}
};
bool operator==(C a,C b){
return a.o==b.o && !sgn(a.r-b.r);
}
bool inPoly(P p,vector<P>poly,bool strict){
int cnt=0;
for(int i=0;i<poly.size();i++){
P a=poly[i],b=poly[(i+1)%poly.size()];
if(onLine(p,L(a,b)))
return !strict;
int x=sgn(det(a,p,b));
int y=sgn(a.y-p.y);
int z=sgn(b.y-p.y);
cnt+=(x>0&&y<=0&&z>0);
cnt-=(x<0&&z<=0&&y>0);
}
return cnt;
}
bool inC(P p,C c,bool strict){
double d=dis(p,c.o);
if(strict){
return sgn(d,c.r)<0;
}else{
return sgn(d,c.r)<=0;
}
}
// 求圆与直线的交点
//turn90() P(-y,x)
double lfix(double x){return sgn(x)?x:0;}
bool intersect(C a, L l, P &p1, P &p2) {
double x = ((l.a - a.o)^ (l.b - l.a)),
y = (l.b - l.a).len2(),
d = x * x - y * ((l.a - a.o).len2() - a.r * a.r);
if (sgn(d) < 0) return false;
d = max(d, 0.0);
P p = l.a - ((l.b - l.a) * (x / y)), delta = (l.b - l.a) * (sqrt(d) / y);
p1 = p + delta, p2 = p - delta;
return true;
}
// 求圆与圆的交点,注意调用前要先判定重圆
bool intersect(C a, C b, P &p1, P &p2) {
double s1 = (a.o - b.o).len();
if (sgn(s1 - a.r - b.r) > 0 || sgn(s1 - fabs(a.r - b.r)) < 0) return false;
double s2 = (a.r * a.r - b.r * b.r) / s1;
double aa = (s1 + s2) * 0.5, bb = (s1 - s2) * 0.5;
P o = (b.o - a.o) * (aa / (aa + bb)) + a.o;
P delta = (b.o - a.o).norm().turn90() * sqrt(lfix(a.r * a.r - aa * aa));
p1 = o + delta, p2 = o - delta;
return true;
}
// 求点到圆的切点,按关于点的顺时针方向返回两个点
bool tang(const C &c, const P &p0, P &p1, P &p2) {
double x = (p0 - c.o).len2(), d = x - c.r * c.r;
if (d < eps) return false; // 点在圆上认为没有切点
P p = (p0 - c.o) * (c.r * c.r / x);
P delta = ((p0 - c.o) * (-c.r * sqrt(d) / x)).turn90();
p1 = c.o + p + delta;
p2 = c.o + p - delta;
return true;
}
// 求圆到圆的外共切线,按关于 c1.o 的顺时针方向返回两条线
vector<L> extan(const C &c1, const C &c2) {
vector<L> ret;
if (sgn(c1.r - c2.r) == 0) {
P dir = c2.o - c1.o;
dir = (dir * (c1.r / dir.len())).turn90();
ret.push_back(L(c1.o + dir, c2.o + dir));
ret.push_back(L(c1.o - dir, c2.o - dir));
} else {
P p = (c1.o * -c2.r + c2.o * c1.r) / (c1.r - c2.r);
P p1, p2, q1, q2;
if (tang(c1, p, p1, p2) && tang(c2, p, q1, q2)) {
if (c1.r < c2.r) swap(p1, p2), swap(q1, q2);
ret.push_back(L(p1, q1));
ret.push_back(L(p2, q2));
}
}
return ret;
}
// 求圆到圆的内共切线,按关于 c1.o 的顺时针方向返回两条线
vector<L> intan(const C &c1, const C &c2) {
vector<L> ret;
P p = (c1.o * c2.r + c2.o * c1.r) / (c1.r + c2.r);
P p1, p2, q1, q2;
if (tang(c1, p, p1, p2) && tang(c2, p, q1, q2)) { // 两圆相切认为没有切线
ret.push_back(L(p1, q1));
ret.push_back(L(p2, q2));
}
return ret;
}
C c[maxn];
vector<P> poly[maxn];
int n,m;
vector<P> intersect(vector<P>poly,C c){
vector<P>ans;
for(int i=0;i<poly.size();i++){
L l=L(poly[i],poly[(i+1)%poly.size()]);
if(!sgn(l.v().len()))
continue;
P p1,p2;
if(intersect(c,l,p1,p2)){
if(onSeg(p1,l)){
ans.push_back(p1);
//cerr<<"ins"<<endl;
//p1.print();
}
if(onSeg(p2,l))
ans.push_back(p2);
}
}
return ans;
}
double calcCir(C cir){
vector<double>ang;
ang.push_back(0);
ang.push_back(pi);
double ans=0;
for(int i=1;i<=n;i++){
if(cir==c[i])continue;
P p1,p2;
if(intersect(cir,c[i],p1,p2)){
ang.push_back(form(cir.ang(p1)));
ang.push_back(form(cir.ang(p2)));
}
}
for(int i=1;i<=m;i++){
vector<P>tmp;
tmp=intersect(poly[i],cir);
//deb(tmp.size());
for(int j=0;j<tmp.size();j++){
// tmp[j].print();
ang.push_back(form(cir.ang(tmp[j])));
}
}
sort(ang.begin(),ang.end());
for(int i=0;i<ang.size();i++){
double t1=ang[i],t2=(i+1==ang.size()?ang[0]+2*pi:ang[i+1]);
P p=cir.at((t1+t2)/2);
int ok=1;
for(int j=1;j<=n;j++){
if(cir==c[j])continue;
if(inC(p,c[j],true)){
ok=0;
break;
}
}
for(int j=1;j<=m&&ok;j++){
if(inPoly(p,poly[j],true)){
ok=0;
break;
}
}
if(ok){
double r=cir.r,x0=cir.o.x,y0=cir.o.y;
ans+=(r*r*(t2-t1)+r*x0*(sin(t2)-sin(t1))-r*y0*(cos(t2)-cos(t1)))/2;
/*cerr<<"---"<<endl;
cerr<<t1<<" "<<t2<<endl;
cerr<<x0<<" "<<y0<<endl;
cerr<<ans<<endl;*/
}
}
return ans;
}
P st;
bool bySt(P a,P b){
return dis(a,st)<dis(b,st);
}
double calcSeg(L l){
double ans=0;
vector<P>pt;
pt.push_back(l.a);
pt.push_back(l.b);
/*cerr<<"line "<<endl;
l.a.print();
l.b.print();
*/
for(int i=1;i<=n;i++){
P p1,p2;
if(intersect(c[i],l,p1,p2)){
if(onSeg(p1,l))
pt.push_back(p1);
if(onSeg(p2,l))
pt.push_back(p2);
}
}
st=l.a;
sort(pt.begin(),pt.end(),bySt);
for(int i=0;i+1<pt.size();i++){
P p1=pt[i],p2=pt[i+1];
P p=(p1+p2)/2;
int ok=1;
for(int j=1;j<=n;j++){
if(sgn(dis(p,c[j].o),c[j].r)<0){
ok=0;
break;
}
}
if(ok){
double x1=p1.x,y1=p1.y,x2=p2.x,y2=p2.y;
// fprintf(stderr,"(%.4f,%.4f)->(%.4f,%.4f)\n",x1,y1,x2,y2);
double res=(x1*y2-x2*y1)/2;
//deb(res);
ans+=res;
}
}
//cerr<<endl;
return ans;
}
C cc[maxn];
double calc(){
int nn=0;
m=1;
for(int i=1;i<=n;i++){
int ok=1;
for(int j=i+1;j<=n;j++){
if(c[i]==c[j]){
ok=0;
}
}
if(ok)
cc[++nn]=c[i];
}
n=nn;
for(int i=1;i<=n;i++)
c[i]=cc[i];
// deb(poly[1].size());
/*deb(Area(poly[1]));
for(int i=0;i<poly[1].size();i++)
poly[1][i].print();*/
if(Area(poly[1])<0){
reverse(poly[1].begin(),poly[1].end());
}
double ans=0;
for(int i=1;i<=n;i++){
ans+=calcCir(c[i]);
//cerr<<sqr(c[i].r)*pi<<endl;
}
double res=0;
for(int i=0;i<poly[1].size();i++){
P p1=poly[1][i],p2=poly[1][(i+1)%poly[1].size()];
if(p1==p2)continue;
res+=calcSeg(L(p1,p2));
}
// cerr<<res<<endl;
// cerr<<"Area"<<endl;
ans+=res;
return ans;
}
vector<P> convex(vector<P>p){
sort(p.begin(),p.end());
/*deb(p.size());
for(int i=0;i<p.size();i++)
p[i].print();*/
vector<P>ans,S;
for(int i=0;i<p.size();i++){
while(S.size()>=2
&& sgn(det(S[S.size()-2],S.back(),p[i]))<=0)
S.pop_back();
S.push_back(p[i]);
}//dw
ans=S;
S.clear();
for(int i=(int)p.size()-1;i>=0;i--){
while(S.size()>=2
&& sgn(det(S[S.size()-2],S.back(),p[i]))<=0)
S.pop_back();
S.push_back(p[i]);
}//up
for(int i=1;i+1<S.size();i++)
ans.push_back(S[i]);
/*deb(ans.size());
for(int i=0;i<ans.size();i++)
ans[i].print();
exit(0);*/
return ans;
}
}
struct P{
double x,y,z;
P(){}
P(double _x,double _y,double _z):x(_x),y(_y),z(_z){}
void read(){
scanf("%lf%lf%lf",&x,&y,&z);
}
double len(){
return sqrt(x*x+y*y+z*z);
}
}p[maxn];
double r[maxn];
double operator^(P a,P b){
return a.x*b.x+a.y*b.y+a.z*b.z;
}
P operator*(P a,P b){
return P(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
P operator/(P a,double b){
return P(a.x/b,a.y/b,a.z/b);
}
int main(){
int n,m;
P D;
while(cin>>n>>m){
Union::n=n;
D.read();
if(!n&&!m&&!D.x&&!D.y&&!D.z)break;
for(int i=1;i<=n;i++){
p[i].read();
scanf("%lf",&r[i]);
}
D=D/D.len();
P X,Y,Z=D;
if(sgn((P(1,0,0)*Z).len())){
X=P(1,0,0)*Z;
Y=Z*X;
}else{
X=P(0,1,0)*Z;
Y=Z*X;
}
X=X/X.len();
Y=Y/Y.len();
double rad=acos(Z^P(0,0,-1));
double rat=cos(rad);
for(int i=1;i<=n;i++){
Union::c[i].o.x=(X^p[i]);
Union::c[i].o.y=(Y^p[i]);
Union::c[i].r=r[i];
//Union::c[i].o.print();
//cerr<<Union::c[i].r<<endl;
}
//cerr<<endl;
vector<Union::P>pt,ch;
pt.resize(m);
for(int i=0;i<m;i++){
P p;p.read();
pt[i].x=(X^p);
pt[i].y=(Y^p);
}
ch=Union::convex(pt);
//for(int i=0;i<ch.size();i++)
// ch[i].print();
Union::poly[1]=ch;
// cerr<<Union::calc()<<endl;
printf("%.4f\n",Union::calc()/rat);
}
return 0;
}