zoukankan      html  css  js  c++  java
  • POJ 2986 A Triangle and a Circle(三角形和圆形求交)

    Description

    Given one triangle and one circle in the plane. Your task is to calculate the common area of these two figures.

    Input

    The input will contain several test cases. Each line of input describes a test case. Each test case consists of nine floating point numbers, x1y1x2y2x3y3x4y4 and r, where (x1y1), (x2y2) and (x3y3) are the three vertices of the triangle and (x4y4) is the center of the circle and r is the radius. We guarantee the triangle and the circle are not degenerate.

    Output

    For each test case you should output one real number, which is the common area of the triangle and the circle, on a separate line. The result should be rounded to two decimal places.

    题目大意:求一个三角形和一个圆形的交的面积。

    思路:圆心和三个三角形的三个点连线,把一个三角形划分为3个三角形,利用有向面积来算。然后就变成了求一个三角形和圆的交的面积,其中三角形的一个顶点为圆心。然后各种分情况讨论(但是要分的情况起码会比直接算一个普通三角形和圆形的交要少得多)。我的姿势似乎不是很高级,好像有些什么奇怪的公式……

    PS:调了一下发现居然是以前用的模板错了……

    代码(1938MS):

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 using namespace std;
      7 
      8 const int MAXN = 10010;
      9 const double EPS = 1e-10;
     10 const double PI = acos(-1.0);//3.14159265358979323846
     11 const double INF = 1;
     12 
     13 inline int sgn(double x) {
     14     return (x > EPS) - (x < -EPS);
     15 }
     16 
     17 inline double sqr(double x) {
     18     return x * x;
     19 }
     20 
     21 struct Point {
     22     double x, y, ag;
     23     Point() {}
     24     Point(double x, double y): x(x), y(y) {}
     25     void read() {
     26         scanf("%lf%lf", &x, &y);
     27     }
     28     bool operator == (const Point &rhs) const {
     29         return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0;
     30     }
     31     bool operator < (const Point &rhs) const {
     32         if(y != rhs.y) return y < rhs.y;
     33         return x < rhs.x;
     34     }
     35     Point operator + (const Point &rhs) const {
     36         return Point(x + rhs.x, y + rhs.y);
     37     }
     38     Point operator - (const Point &rhs) const {
     39         return Point(x - rhs.x, y - rhs.y);
     40     }
     41     Point operator * (const double &b) const {
     42         return Point(x * b, y * b);
     43     }
     44     Point operator / (const double &b) const {
     45         return Point(x / b, y / b);
     46     }
     47     double operator * (const Point &rhs) const {
     48         return x * rhs.x + y * rhs.y;
     49     }
     50     double length() {
     51         return sqrt(x * x + y * y);
     52     }
     53     double angle() {
     54         return atan2(y, x);
     55     }
     56     Point unit() {
     57         return *this / length();
     58     }
     59     void makeAg() {
     60         ag = atan2(y, x);
     61     }
     62     void print() {
     63         printf("%.10f %.10f
    ", x, y);
     64     }
     65 };
     66 typedef Point Vector;
     67 
     68 double dist(const Point &a, const Point &b) {
     69     return (a - b).length();
     70 }
     71 
     72 double cross(const Point &a, const Point &b) {
     73     return a.x * b.y - a.y * b.x;
     74 }
     75 //ret >= 0 means turn right
     76 double cross(const Point &sp, const Point &ed, const Point &op) {
     77     return cross(sp - op, ed - op);
     78 }
     79 
     80 double area(const Point& a, const Point &b, const Point &c) {
     81     return fabs(cross(a - c, b - c)) / 2;
     82 }
     83 //counter-clockwise
     84 Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) {
     85     Point t = p - o;
     86     double x = t.x * cos(angle) - t.y * sin(angle);
     87     double y = t.y * cos(angle) + t.x * sin(angle);
     88     return Point(x, y) + o;
     89 }
     90 
     91 double includedAngle(const Point &a, const Point &b, const Point &o) {
     92     double ret = abs((a - o).angle() - (b - o).angle());
     93     if(sgn(ret - PI) > 0) ret = 2 * PI - ret;
     94     return ret;
     95 }
     96 
     97 struct Seg {
     98     Point st, ed;
     99     double ag;
    100     Seg() {}
    101     Seg(Point st, Point ed): st(st), ed(ed) {}
    102     void read() {
    103         st.read(); ed.read();
    104     }
    105     void makeAg() {
    106         ag = atan2(ed.y - st.y, ed.x - st.x);
    107     }
    108 };
    109 typedef Seg Line;
    110 
    111 //ax + by + c > 0
    112 Line buildLine(double a, double b, double c) {
    113     if(sgn(a) == 0 && sgn(b) == 0) return Line(Point(sgn(c) > 0 ? -1 : 1, INF), Point(0, INF));
    114     if(sgn(a) == 0) return Line(Point(sgn(b), -c/b), Point(0, -c/b));
    115     if(sgn(b) == 0) return Line(Point(-c/a, 0), Point(-c/a, sgn(a)));
    116     if(b < 0) return Line(Point(0, -c/b), Point(1, -(a + c) / b));
    117     else return Line(Point(1, -(a + c) / b), Point(0, -c/b));
    118 }
    119 
    120 void moveRight(Line &v, double r) {
    121     double dx = v.ed.x - v.st.x, dy = v.ed.y - v.st.y;
    122     dx = dx / dist(v.st, v.ed) * r;
    123     dy = dy / dist(v.st, v.ed) * r;
    124     v.st.x += dy; v.ed.x += dy;
    125     v.st.y -= dx; v.ed.y -= dx;
    126 }
    127 
    128 bool isOnSeg(const Seg &s, const Point &p) {
    129     return (p == s.st || p == s.ed) ||
    130         (((p.x - s.st.x) * (p.x - s.ed.x) < 0 ||
    131           (p.y - s.st.y) * (p.y - s.ed.y) < 0) &&
    132          sgn(cross(s.ed, p, s.st)) == 0);
    133 }
    134 
    135 bool isIntersected(const Point &s1, const Point &e1, const Point &s2, const Point &e2) {
    136     return (max(s1.x, e1.x) >= min(s2.x, e2.x)) &&
    137         (max(s2.x, e2.x) >= min(s1.x, e1.x)) &&
    138         (max(s1.y, e1.y) >= min(s2.y, e2.y)) &&
    139         (max(s2.y, e2.y) >= min(s1.y, e1.y)) &&
    140         (cross(s2, e1, s1) * cross(e1, e2, s1) >= 0) &&
    141         (cross(s1, e2, s2) * cross(e2, e1, s2) >= 0);
    142 }
    143 
    144 bool isIntersected(const Seg &a, const Seg &b) {
    145     return isIntersected(a.st, a.ed, b.st, b.ed);
    146 }
    147 
    148 bool isParallel(const Seg &a, const Seg &b) {
    149     return sgn(cross(a.ed - a.st, b.ed - b.st)) == 0;
    150 }
    151 
    152 //return Ax + By + C =0 's A, B, C
    153 void Coefficient(const Line &L, double &A, double &B, double &C) {
    154     A = L.ed.y - L.st.y;
    155     B = L.st.x - L.ed.x;
    156     C = L.ed.x * L.st.y - L.st.x * L.ed.y;
    157 }
    158 //point of intersection
    159 Point operator * (const Line &a, const Line &b) {
    160     double A1, B1, C1;
    161     double A2, B2, C2;
    162     Coefficient(a, A1, B1, C1);
    163     Coefficient(b, A2, B2, C2);
    164     Point I;
    165     I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1);
    166     I.y =   (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1);
    167     return I;
    168 }
    169 
    170 bool isEqual(const Line &a, const Line &b) {
    171     double A1, B1, C1;
    172     double A2, B2, C2;
    173     Coefficient(a, A1, B1, C1);
    174     Coefficient(b, A2, B2, C2);
    175     return sgn(A1 * B2 - A2 * B1) == 0 && sgn(A1 * C2 - A2 * C1) == 0 && sgn(B1 * C2 - B2 * C1) == 0;
    176 }
    177 
    178 double Point_to_Line(const Point &p, const Line &L) {
    179     return fabs(cross(p, L.st, L.ed)/dist(L.st, L.ed));
    180 }
    181 
    182 double Point_to_Seg(const Point &p, const Seg &L) {
    183     if(sgn((L.ed - L.st) * (p - L.st)) < 0) return dist(p, L.st);
    184     if(sgn((L.st - L.ed) * (p - L.ed)) < 0) return dist(p, L.ed);
    185     return Point_to_Line(p, L);
    186 }
    187 
    188 double Seg_to_Seg(const Seg &a, const Seg &b) {
    189     double ans1 = min(Point_to_Seg(a.st, b), Point_to_Seg(a.ed, b));
    190     double ans2 = min(Point_to_Seg(b.st, a), Point_to_Seg(b.ed, a));
    191     return min(ans1, ans2);
    192 }
    193 
    194 struct Circle {
    195     Point c;
    196     double r;
    197     Circle() {}
    198     Circle(Point c, double r): c(c), r(r) {}
    199     void read() {
    200         c.read();
    201         scanf("%lf", &r);
    202     }
    203     double area() const {
    204         return PI * r * r;
    205     }
    206     bool contain(const Circle &rhs) const {
    207         return sgn(dist(c, rhs.c) + rhs.r - r) <= 0;
    208     }
    209     bool contain(const Point &p) const {
    210         return sgn(dist(c, p) - r) <= 0;
    211     }
    212     bool intersect(const Circle &rhs) const {
    213         return sgn(dist(c, rhs.c) - r - rhs.r) < 0;
    214     }
    215     bool tangency(const Circle &rhs) const {
    216         return sgn(dist(c, rhs.c) - r - rhs.r) == 0;
    217     }
    218     Point pos(double angle) const {
    219         Point p = Point(c.x + r, c.y);
    220         return rotate(p, angle, c);
    221     }
    222 };
    223 
    224 double CommonArea(const Circle &A, const Circle &B) {
    225     double area = 0.0;
    226     const Circle & M = (A.r > B.r) ? A : B;
    227     const Circle & N = (A.r > B.r) ? B : A;
    228     double D = dist(M.c, N.c);
    229     if((D < M.r + N.r) && (D > M.r - N.r)) {
    230         double cosM = (M.r * M.r + D * D - N.r * N.r) / (2.0 * M.r * D);
    231         double cosN = (N.r * N.r + D * D - M.r * M.r) / (2.0 * N.r * D);
    232         double alpha = 2 * acos(cosM);
    233         double beta = 2 * acos(cosN);
    234         double TM = 0.5 * M.r * M.r * (alpha - sin(alpha));
    235         double TN = 0.5 * N.r * N.r * (beta - sin(beta));
    236         area = TM + TN;
    237     }
    238     else if(D <= M.r - N.r) {
    239         area = N.area();
    240     }
    241     return area;
    242 }
    243 
    244 int intersection(const Seg &s, const Circle &cir, Point &p1, Point &p2) {
    245     double angle = includedAngle(s.ed, cir.c, s.st);
    246     double B = dist(cir.c, s.st);
    247     double a = 1, b = -2 * B *  cos(angle), c = sqr(B) - sqr(cir.r);
    248     double delta = sqr(b) - 4 * a * c;
    249     if(sgn(delta) < 0) return 0;
    250     double x1 = (-b - sqrt(delta)) / (2 * a), x2 = (-b + sqrt(delta)) / (2 * a);
    251     Vector v = (s.ed - s.st).unit();
    252     p1 = s.st + v * x1;
    253     p2 = s.st + v * x2;
    254     return 1 + sgn(delta);
    255 }
    256 
    257 double CommonArea(const Circle &cir, Point p1, Point p2) {
    258     if(cir.contain(p1) && cir.contain(p2)) {
    259         return area(cir.c, p1, p2);
    260     } else if(!cir.contain(p1) && !cir.contain(p2)) {
    261         Point q1, q2;
    262         int t = intersection(Line(p1, p2), cir, q1, q2);
    263         if(t == 0) {
    264             double angle = includedAngle(p1, p2, cir.c);
    265             return 0.5 * sqr(cir.r) * angle;
    266         } else {
    267             double angle1 = includedAngle(p1, p2, cir.c);
    268             double angle2 = includedAngle(q1, q2, cir.c);
    269             if(isOnSeg(Seg(p1, p2), q1))return 0.5 * sqr(cir.r) * (angle1 - angle2 + sin(angle2));
    270             else return 0.5 * sqr(cir.r) * angle1;
    271         }
    272     } else {
    273         if(cir.contain(p2)) swap(p1, p2);
    274         Point q1, q2;
    275         intersection(Line(p1, p2), cir, q1, q2);
    276         double angle = includedAngle(q2, p2, cir.c);
    277         double a = area(cir.c, p1, q2);
    278         double b = 0.5 * sqr(cir.r) * angle;
    279         return a + b;
    280     }
    281 }
    282 
    283 struct Triangle {
    284     Point p[3];
    285     Triangle() {}
    286     Triangle(Point *t) {
    287         for(int i = 0; i < 3; ++i) p[i] = t[i];
    288     }
    289     void read() {
    290         for(int i = 0; i < 3; ++i) p[i].read();
    291     }
    292     double area() const {
    293         return ::area(p[0], p[1], p[2]);
    294     }
    295     Point& operator[] (int i) {
    296         return p[i];
    297     }
    298 };
    299 
    300 double CommonArea(Triangle tir, const Circle &cir) {
    301     double ret = 0;
    302     ret += sgn(cross(tir[0], cir.c, tir[1])) * CommonArea(cir, tir[0], tir[1]);
    303     ret += sgn(cross(tir[1], cir.c, tir[2])) * CommonArea(cir, tir[1], tir[2]);
    304     ret += sgn(cross(tir[2], cir.c, tir[0])) * CommonArea(cir, tir[2], tir[0]);
    305     return abs(ret);
    306 }
    307 
    308 struct Poly {
    309     int n;
    310     Point p[MAXN];//p[n] = p[0]
    311     void init(Point *pp, int nn) {
    312         n = nn;
    313         for(int i = 0; i < n; ++i) p[i] = pp[i];
    314         p[n] = p[0];
    315     }
    316     double area() {
    317         if(n < 3) return 0;
    318         double s = p[0].y * (p[n - 1].x - p[1].x);
    319         for(int i = 1; i < n; ++i)
    320             s += p[i].y * (p[i - 1].x - p[i + 1].x);
    321         return s / 2;
    322     }
    323 };
    324 //the convex hull is clockwise
    325 void Graham_scan(Point *p, int n, int *stk, int &top) {//stk[0] = stk[top]
    326     sort(p, p + n);
    327     top = 1;
    328     stk[0] = 0; stk[1] = 1;
    329     for(int i = 2; i < n; ++i) {
    330         while(top && cross(p[i], p[stk[top]], p[stk[top - 1]]) <= 0) --top;
    331         stk[++top] = i;
    332     }
    333     int len = top;
    334     stk[++top] = n - 2;
    335     for(int i = n - 3; i >= 0; --i) {
    336         while(top != len && cross(p[i], p[stk[top]], p[stk[top - 1]]) <= 0) --top;
    337         stk[++top] = i;
    338     }
    339 }
    340 //use for half_planes_cross
    341 bool cmpAg(const Line &a, const Line &b) {
    342     if(sgn(a.ag - b.ag) == 0)
    343         return sgn(cross(b.ed, a.st, b.st)) < 0;
    344     return a.ag < b.ag;
    345 }
    346 //clockwise, plane is on the right
    347 bool half_planes_cross(Line *v, int vn, Poly &res, Line *deq) {
    348     int i, n;
    349     sort(v, v + vn, cmpAg);
    350     for(i = n = 1; i < vn; ++i) {
    351         if(sgn(v[i].ag - v[i-1].ag) == 0) continue;
    352         v[n++] = v[i];
    353     }
    354     int head = 0, tail = 1;
    355     deq[0] = v[0], deq[1] = v[1];
    356     for(i = 2; i < n; ++i) {
    357         if(isParallel(deq[tail - 1], deq[tail]) || isParallel(deq[head], deq[head + 1]))
    358             return false;
    359         while(head < tail && sgn(cross(v[i].ed, deq[tail - 1] * deq[tail], v[i].st)) > 0)
    360             --tail;
    361         while(head < tail && sgn(cross(v[i].ed, deq[head] * deq[head + 1], v[i].st)) > 0)
    362             ++head;
    363         deq[++tail] = v[i];
    364     }
    365     while(head < tail && sgn(cross(deq[head].ed, deq[tail - 1] * deq[tail], deq[head].st)) > 0)
    366         --tail;
    367     while(head < tail && sgn(cross(deq[tail].ed, deq[head] * deq[head + 1], deq[tail].st)) > 0)
    368         ++head;
    369     if(tail <= head + 1) return false;
    370     res.n = 0;
    371     for(i = head; i < tail; ++i)
    372         res.p[res.n++] = deq[i] * deq[i + 1];
    373     res.p[res.n++] = deq[head] * deq[tail];
    374     res.n = unique(res.p, res.p + res.n) - res.p;
    375     res.p[res.n] = res.p[0];
    376     return true;
    377 }
    378 
    379 //ix and jx is the points whose distance is return, res.p[n - 1] = res.p[0], res must be clockwise
    380 double dia_rotating_calipers(Poly &res, int &ix, int &jx) {
    381     double dia = 0;
    382     int q = 1;
    383     for(int i = 0; i < res.n - 1; ++i) {
    384         while(sgn(cross(res.p[i], res.p[q + 1], res.p[i + 1]) - cross(res.p[i], res.p[q], res.p[i + 1])) > 0)
    385             q = (q + 1) % (res.n - 1);
    386         if(sgn(dist(res.p[i], res.p[q]) - dia) > 0) {
    387             dia = dist(res.p[i], res.p[q]);
    388             ix = i; jx = q;
    389         }
    390         if(sgn(dist(res.p[i + 1], res.p[q]) - dia) > 0) {
    391             dia = dist(res.p[i + 1], res.p[q]);
    392             ix = i + 1; jx = q;
    393         }
    394     }
    395     return dia;
    396 }
    397 //a and b must be clockwise, find the minimum distance between two convex hull
    398 double half_rotating_calipers(Poly &a, Poly &b) {
    399     int sa = 0, sb = 0;
    400     for(int i = 0; i < a.n; ++i) if(sgn(a.p[i].y - a.p[sa].y) < 0) sa = i;
    401     for(int i = 0; i < b.n; ++i) if(sgn(b.p[i].y - b.p[sb].y) < 0) sb = i;
    402     double tmp, ans = dist(a.p[0], b.p[0]);
    403     for(int i = 0; i < a.n; ++i) {
    404         while(sgn(tmp = cross(a.p[sa], a.p[sa + 1], b.p[sb + 1]) - cross(a.p[sa], a.p[sa + 1], b.p[sb])) > 0)
    405             sb = (sb + 1) % (b.n - 1);
    406         if(sgn(tmp) < 0) ans = min(ans, Point_to_Seg(b.p[sb], Seg(a.p[sa], a.p[sa + 1])));
    407         else ans = min(ans, Seg_to_Seg(Seg(a.p[sa], a.p[sa + 1]), Seg(b.p[sb], b.p[sb + 1])));
    408         sa = (sa + 1) % (a.n - 1);
    409     }
    410     return ans;
    411 }
    412 
    413 double rotating_calipers(Poly &a, Poly &b) {
    414     return min(half_rotating_calipers(a, b), half_rotating_calipers(b, a));
    415 }
    416 
    417 /*******************************************************************************************/
    418 
    419 Triangle tir;
    420 Circle cir;
    421 
    422 int main() {
    423     while(scanf("%lf%lf", &tir[0].x, &tir[0].y) != EOF) {
    424         tir[1].read();
    425         tir[2].read();
    426         cir.read();
    427         //cout<<Point_to_Line(cir.c, Line(tir[0], tir[1]))<<endl;
    428         if(sgn(cross(tir[0], tir[1], tir[2])) == 0) puts("0.00");
    429         else printf("%.2f
    ", CommonArea(tir, cir) + EPS);
    430     }
    431 }
    View Code
  • 相关阅读:
    idea语法检查红线隐藏配置
    spring security
    linux centos7下安装fastdfs
    定时任务在多个服务实例之间最多只执行一次
    C++11:01auto关键字
    chap3 数组 #C
    django之模型层 各种查询 数据库查询优化相关 事务使用
    django orm 中表与表之间建关系 视图层 路由层 django请求生命周期
    django 静态文件的配置 orm 中 字段与数据的增删改查 使用MySQL数据库
    BOM,DOM, JS,JQ
  • 原文地址:https://www.cnblogs.com/oyking/p/3428509.html
Copyright © 2011-2022 走看看