zoukankan      html  css  js  c++  java
  • 简单多边形与圆相交模板

    分5种情况,模板转载自:http://hi.baidu.com/billdu/item/703ad4e15d819db52f140b0b

    题目大意:给你个简单多边形,和一个圆心在原点处的圆,求这个多边形与圆的重合部分的面积。

    也就是这个意思了……

    但是这看上去也太恶心了,怎么办?其实想一想就知道,我们平日求多边形面积用的就是三角形剖分,所以说我们应该化繁为简,通过求出来各三角形与圆的交,从而求出总面积。而且,剖分用的原点正好在圆心,这是很方便的一件事情。

    现在问题就转化成一个顶点在圆心的三角形了。但是这才是麻烦的开始,除去退化情况,我们应该至少考虑到以下五种情况:

    (一)三角形的两条边全部短于半径。

    最方便了,不是么?

    (二)三角形的两条边全部长于半径,且另一条边与圆心的距离也长于半径。

    只需要求出扇形的面积即可。

    (三)三角形的两条边全部长于半径,但另一条边与圆心的距离短于半径,并且垂足落在这条边上。

    求出扇形的面积,再减去那个弓形的面积。也就是说再挖去一个扇形,补上一个三角形。

    (四)三角形的两条边全部长于半径,但另一条边与圆心的距离短于半径,且垂足未落在这条边上。

    与上一个很像……一开始我就在这里WA了很长时间。事实上只需求一个扇形。

    (五)三角形的两条边一条长于半径,另外一条短于半径。

    先求出交点,再剖成扇形和三角形求解。

    代码:HDU 4404

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <functional>
    #include <numeric>
    #include <sstream>
    #include <stack>
    
    #define CL(arr, val) memset(arr, val, sizeof(arr))
    #define REP(i, n)for((i) = 0; (i) < (n); ++(i))
    #define FOR(i, l, h)for((i) = (l); (i) <= (h); ++(i))
    #define FORD(i, h, l)for((i) = (h); (i) >= (l); --(i))
    #define L(x)(x) << 1
    #define R(x)(x) << 1 | 1
    #define MID(l, r)(l + r) >> 1
    #define Min(x, y)x < y ? x : y
    #define Max(x, y)x < y ? y : x
    #define E(x)(1 << (x))
    #define iabs(x) (x) < 0 ? -(x) : (x)
    #define OUT(x)printf("%I64d\n", x)
    #define lowbit(x)(x)&(-x)
    #define Read()freopen("data.in", "r", stdin)
    #define Write()freopen("data.out", "w", stdout);
    
    const double eps = 1e-10;
    typedef long long LL;
    const int inf = ~0u>>2;
    
    using namespace std;
    
    inline double max (double a, double b) { if (a > b) return a; else return b; }
    inline double min (double a, double b) { if (a < b) return a; else return b; }
    inline int fi (double a)
    {
        if (a > eps) return 1;
        else if (a >= -eps) return 0;
        else return -1;
    }
    class Vector
    {
    public:
        double x, y;
        Vector (void) {}
        Vector (double x0, double y0) : x(x0), y(y0) {}
        double operator * (const Vector& a) const { return x * a.y - y * a.x; }
        double operator % (const Vector& a) const { return x * a.x + y * a.y; }
        Vector verti (void) const { return Vector(-y, x); }
        double length (void) const { return sqrt(x * x + y * y); }
        Vector adjust (double len)
        {
            double ol = len / length();
            return Vector(x * ol, y * ol);
        }
        Vector oppose (void) { return Vector(-x, -y); }
    };
    class point
    {
    public:
        double x, y;
        point (void) {}
        point (double x0, double y0) : x(x0), y(y0) {}
        Vector operator - (const point& a) const { return Vector(x - a.x, y - a.y); }
        point operator + (const Vector& a) const { return point(x + a.x, y + a.y); }
    };
    class segment
    {
    public:
        point a, b;
        segment (void) {}
        segment (point a0, point b0) : a(a0), b(b0) {}
        point intersect (const segment& s) const
        {
            Vector v1 = s.a - a, v2 = s.b - a, v3 = s.b - b, v4 = s.a - b;
            double s1 = v1 * v2, s2 = v3 * v4;
            double se = s1 + s2;
            s1 /= se, s2 /= se;
            return point(a.x * s2 + b.x * s1, a.y * s2 + b.y * s1);
        }
        point pverti (const point& p) const
        {
            Vector t = (b - a).verti();
            segment uv(p, p + t);
            return intersect(uv);
        }
        bool on_segment (const point& p) const
        {
            if (fi(min(a.x, b.x) - p.x) <= 0 && fi(p.x - max(a.x, b.x)) <= 0 &&
                fi(min(a.y, b.y) - p.y) <= 0 && fi(p.y - max(a.y, b.y)) <= 0) return true;
            else return false;
        }
    };
    
    double radius;
    point polygon[110];
    
    double kuras_area (point a, point b, double cx, double cy)
    {
        point ori(cx, cy);
        int sgn = fi((b - ori) * (a - ori));
        double da = (a - ori).length(), db = (b - ori).length();
        int ra = fi(da - radius), rb = fi(db - radius);
        double angle = acos(((b - ori) % (a - ori)) / (da * db));
        segment t(a, b); point h, u; Vector seg;
        double ans, dlt, mov, tangle;
    
        if (fi(da) == 0 || fi(db) == 0) return 0;
        else if (sgn == 0) return 0;
        else if (ra <= 0 && rb <= 0) return fabs((b - ori) * (a - ori)) / 2 * sgn;
        else if (ra >= 0 && rb >= 0)
        {
            h = t.pverti(ori);
            dlt = (h - ori).length();
            if (!t.on_segment(h) || fi(dlt - radius) >= 0)
                return radius * radius * (angle / 2) * sgn;
            else
            {
                ans = radius * radius * (angle / 2);
                tangle = acos(dlt / radius);
                ans -= radius * radius * tangle;
                ans += radius * sin(tangle) * dlt;
                return ans * sgn;
            }
        }
        else
        {
            h = t.pverti(ori);
            dlt = (h - ori).length();
            seg = b - a;
            mov = sqrt(radius * radius - dlt * dlt);
            seg = seg.adjust(mov);
            if (t.on_segment(h + seg)) u = h + seg;
            else u = h + seg.oppose();
            if (ra == 1) swap(a, b);
            ans = fabs((a - ori) * (u - ori)) / 2;
            tangle = acos(((u - ori) % (b - ori)) / ((u - ori).length() * (b - ori).length()));
            ans += radius * radius * (tangle / 2);
            return ans * sgn;
        }
    }
    
    const double pi = acos(-1.0);
    
    int main ()
    {
        //freopen("data.in", "r", stdin);
    
        int n;
        double area, x, y, cx, cy;
        double x0, y0, v0, th, t, g;
        double vx, vy;
    
        while(~scanf("%lf%lf%lf%lf%lf%lf%lf", &x0, &y0, &v0, &th, &t, &g, &radius)) {
            if(x0 == 0 && y0 == 0 && v0 == 0 && th == 0 && t == 0 && g == 0 && radius == 0)  break;
            vx = v0*cos(pi*th/180.0); vy = v0*sin(pi*th/180.0);
            cx = x0 + vx*t;
            cy = y0 + (vy*t - 0.5*g*t*t);
            scanf("%d", &n);
            for(int i = 0; i < n; ++i) {
                scanf("%lf%lf", &x, &y);
                polygon[i] = point(x, y);
            }
            area = 0;
            for (int i = 0; i < n; i++)
                area += kuras_area(polygon[i], polygon[(i + 1) % n], cx, cy);
            printf("%.2f\n", fabs(area));
        }
        return 0;
    }
  • 相关阅读:
    vue2.0实践的一些细节
    数据库之一
    angularJS实用的开发技巧
    移动端开发的一些技巧总结(2)
    vue入门学习(基础篇)
    JS继承之原型继承
    css3动画
    使用 xlsx 前端解析 excel 文件
    webpack4 打包 library 遇到的坑
    roc-charts 开发笔记:JS广度优先查找无向无权图两点间最短路径
  • 原文地址:https://www.cnblogs.com/vongang/p/2700682.html
Copyright © 2011-2022 走看看