Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // 简单多边形与圆面积交
- #include <cstdio>
- #include <cstring>
- #include <cmath>
- #include <algorithm>
- using namespace std;
- const double eps = 1e-8;
- const double pi = acos(-1.0);
- const int maxn = 103;
- struct Point {
- double x, y;
- Point(){}
- Point (double tx,double ty)
- {
- this->x = tx;
- this->y = ty;
- }
- Point operator - (const Point &t) const {
- Point res;
- res.x = x - t.x;
- res.y = y - t.y;
- return res;
- }
- }p[maxn];
- double multi(Point &o, Point &a, Point &b) { // 点积
- return (a.x-o.x)*(b.x-o.x) + (a.y-o.y)*(b.y-o.y);
- }
- double cross(Point &o, Point &a, Point &b) { // 叉积
- return (a.x-o.x)*(b.y-o.y) - (b.x-o.x)*(a.y-o.y);
- }
- double cp(Point &a, Point &b) {
- return a.x*b.y - b.x*a.y;
- }
- double angle(Point &a, Point &b) { // 两向量夹角
- double ans = fabs((atan2(a.y, a.x) - atan2(b.y, b.x)));
- return ans > pi+eps ? 2*pi-ans : ans;
- }
- void cir_line(Point ct, double r, Point l1, Point l2, Point& p1, Point& p2) { // 直线与圆
- double a1, a2, b1, b2, A, B, C, t1, t2;
- a1 = l2.x - l1.x; a2 = l2.y - l1.y;
- b1 = l1.x - ct.x; b2 = l1.y - ct.y;
- A = a1*a1 + a2*a2;
- B = (a1*b1 + a2*b2)*2;
- C = b1*b1 + b2*b2 - r*r;
- t1 = (-B - sqrt(B*B - 4.0*A*C))/2.0/A;
- t2 = (-B + sqrt(B*B - 4.0*A*C))/2.0/A;
- p1.x = l1.x + a1*t1; p1.y = l1.y + a2*t1;
- p2.x = l1.x + a1*t2; p2.y = l1.y + a2*t2;
- }
- double cir_polygon(Point ct, double R, Point *p, int n) { // 圆与简单多边形
- Point o, a, b, t1, t2;
- double sum=0, res, d1, d2, d3, sign;
- o.x = o.y = 0;
- p[n] = p[0];
- for (int i=0; i < n; i++) {
- a = p[i]-ct;
- b = p[i+1]-ct;
- sign = cp(a,b) > 0 ? 1 : -1;
- d1 = a.x*a.x + a.y*a.y;
- d2 = b.x*b.x + b.y*b.y;
- d3 = sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
- if (d1 < R*R+eps && d2 < R*R+eps) { //两个点都在圆内
- res = fabs(cp(a, b));
- }
- else if (d1 < R*R-eps || d2 < R*R-eps) { //一个点在圆内
- cir_line(o, R, a, b, t1, t2);
- if ((a.x-t2.x)*(b.x-t2.x) < eps && (a.y-t2.y)*(b.y-t2.y) < eps) {
- t1 = t2;
- }
- if (d1 < d2)
- res = fabs(cp(a, t1)) + R*R*angle(b, t1);
- else
- res = fabs(cp(b, t1)) + R*R*angle(a, t1);
- }
- else if (fabs(cp(a, b))/d3 > R-eps) { // 两个点都在园外,且线段与圆之多只有一个交点
- res = R*R*angle(a, b);
- }
- else { // 线段与圆有两个交点
- cir_line(o, R, a, b, t1, t2);
- if (multi(t1, a, b) > eps || multi(t2, a, b) > eps) {
- res = R*R*angle(a, b);
- }
- else {
- res = fabs(cp(t1, t2));
- if (cross(t1, t2, a) < eps)
- res += R*R*(angle(a, t1) + angle(b, t2));
- else
- res += R*R*(angle(a, t2) + angle(b, t1));
- }
- }
- sum += res * sign;
- }
- return fabs(sum)/2.0;
- }
- int main()
- {
- int t,ca=1;
- scanf("%d",&t);
- while(t--)
- {
- Point cen;
- double R;
- scanf("%lf%lf%lf",&cen.x,&cen.y,&R);
- Point p[4]; double a,b,c,d;
- scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
- p[0] = Point(a,b);
- p[1] = Point(c,b);
- p[2] = Point(c,d);
- p[3] = Point(a,d);
- printf("Case %d: %lf\n",ca++,cir_polygon(cen,R,p,4));
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment