UVA10969计算几何+交叉圆形成的圆弧长

  1 /*UVA 10969计算几何
  2 这道题和LA2572相似,但相对简单些。
  3 思路:求圆间的交点,顺序枚举出圆上的圆弧,中点判断是否被覆盖。
  4 */
  5 #include <stdio.h>
  6 #include <stdlib.h>
  7 #include <string.h>
  8 #include <math.h>
  9 #include <ctype.h>
 10 #include <string>
 11 #include <iostream>
 12 #include <sstream>
 13 #include <vector>
 14 #include <queue>
 15 #include <stack>
 16 #include <map>
 17 #include <list>
 18 #include <set>
 19 #include <algorithm>
 20 #define INF 0x3f3f3f3f
 21 #define eps 1e-7
 22 #define eps2 1e-3
 23 using namespace std;
 24 
 25 struct Point
 26 {
 27     double x,y;
 28     Point() {}
 29     Point(double xx,double yy)
 30     {
 31         x=xx;
 32         y=yy;
 33     }
 34 };
 35 struct Circle
 36 {
 37     Point O;
 38     double r;
 39     Circle() {}
 40     Circle(Point O1,double r1)
 41     {
 42         O=O1;
 43         r=r1;
 44     }
 45     Point point(double a)
 46     {
 47         return Point(O.x+cos(a)*r,O.y+sin(a)*r);
 48     }
 49 };
 50 typedef Point Vector;
 51 
 52 bool operator==(Point A,Point B)
 53 {
 54     if ((fabs(A.x-B.x)<1e-10) && (fabs(A.y-B.y)<1e-10)) return true;
 55     else return false;
 56 }
 57 Vector operator-(Point A,Point B)//表示A指向B
 58 {
 59     return Vector(A.x-B.x,A.y-B.y);
 60 }
 61 Vector operator*(Vector A,double k)
 62 {
 63     return Vector(A.x*k,A.y*k);
 64 }
 65 Vector operator+(Point A,Point B)//表示A指向B
 66 {
 67     return Vector(B.x+A.x,B.y+A.y);
 68 }
 69 double Dot(Vector A,Vector B)
 70 {
 71     return A.x*B.x+A.y*B.y;
 72 }
 73 double Length(Vector A)
 74 {
 75     return sqrt(Dot(A,A));
 76 }
 77 double Cross(Vector A,Vector B)
 78 {
 79     return A.x*B.y-A.y*B.x;
 80 }
 81 int dcmp(double x)
 82 {
 83     if(fabs(x)<1e-10) return 0;
 84     else if(x>0) return 1;
 85     else return -1;
 86 }
 87 double angle(Vector v)
 88 {
 89     return atan2(v.y,v.x);
 90 }
 91 double normal(double rad)
 92 {
 93     return rad-2*M_PI*floor(rad/(2*M_PI));
 94 }
 95 
 96 Point GetMid(double a,double b,double r,double x,double y)//圆上两点,获得中点的坐标
 97 {
 98     double arf=(b+a)/2;
 99     double xx=r*cos(arf)+x;
100     double xy=r*sin(arf)+y;
101     Point P=Point(xx,xy);
102     return P;
103 }
104 bool PInCircle(Point P,Circle C)//判断点在圆内
105 {
106     double dis=Length(P-C.O);
107     if (dis-C.r>1e-6) return false;
108     else return true;
109 }
110 void getcircleinter(Point c1,double r1,Point c2,double r2,vector<double>& rad)
111 {
112     double d=Length(c1-c2);
113     if(dcmp(d)==0) return;
114     if(dcmp(r1+r2-d)<0) return;
115     if(dcmp(fabs(r1-r2)-d)>0) return;
116     double a=angle(c2-c1);
117     double da=acos((r1*r1+d*d-r2*r2)/(2*r1*d));
118     rad.push_back(normal(a+da));
119     rad.push_back(normal(a-da));
120 }
121 
122 int n;
123 Circle CC[110];//
124 vector<double> Arf[110];//圆心角
125 
126 int cas;
127 int main()
128 {
129     cin>>cas;
130     while(cas--)
131     {
132         double ans=0.0;
133         cin>>n;
134         for(int i=1; i<=n; i++)//读取信息
135         {
136             double x,y,r;
137             cin>>r>>x>>y;
138             CC[i]=Circle(Point(x,y),r);
139         }
140         for(int i=1; i<=n; i++) {Arf[i].clear();Arf[i].push_back(0);Arf[i].push_back(2*M_PI);}
141 
142         for(int i=1; i<=n; i++)//获得圆上的交点的角度
143         for(int j=1; j<=n; j++)
144             getcircleinter(CC[i].O,CC[i].r,CC[j].O,CC[j].r,Arf[i]);
145 
146         for(int i=1; i<=n; i++) //枚举n个圆上的圆弧
147         {
148             int k=Arf[i].size();
149             sort(Arf[i].begin(),Arf[i].end());
150 
151             for(int j=0; j<k-1; j++) //枚举每条弧
152             {
153                 Point Mid=GetMid(Arf[i][j],Arf[i][j+1],CC[i].r,CC[i].O.x,CC[i].O.y);
154 
155                 bool ok=true;//表示这条圆弧可见
156                 for(int l=i+1; l<=n; l++) //判断中点是否可见
157                     if (PInCircle(Mid,CC[l])) ok=false;
158 
159                 if(ok) ans+=(Arf[i][j+1]-Arf[i][j])*CC[i].r;
160             }
161         }
162 
163         printf("%.3lf\n",(ans));//放缩回来
164     }
165     return 0;
166 }

 

posted @ 2014-02-26 21:38  little_w  阅读(384)  评论(0编辑  收藏  举报