zoukankan      html  css  js  c++  java
  • 多边形与圆相交面积计算

    POJ 3675 裸的题了。直接上模板就行了。注意的是,求出的是有向面积,有可能是负数。

    #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
    ", x)
    #define lowbit(x)(x)&(-x)
    #define Read()freopen("data.in", "r", stdin)
    #define Write()freopen("data.out", "w", stdout);
    
    const double eps = 1e-8;
    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 (){
    	int n;
    	while(scanf("%lf",&radius)!=EOF){
    		scanf("%d",&n);
    		for(int i=0;i<n;i++){
    			scanf("%lf%lf",&polygon[i].x,&polygon[i].y);
    		}
    		double ans=0;
    		for(int i=0;i<n;i++){
    			ans+=kuras_area(polygon[i],polygon[(i+1)%n],0,0);
    		}
    		printf("%.2lf
    ",fabs(ans));
    	}
    }
    

      

    HDU 3982。很明显,求出切割的半平面交之后就可以得出一个多边形。然后求多边形与圆面积相交部分即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    const double eps = 1e-6;
    typedef long long LL;
    const int inf = ~0u>>2;
    const int MAXN=4222; 
    
    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;
    }
    
    struct Point {
    	double x,y;
    	Point(double xx,double yy){x=xx; y=yy;}
    	Point(){}
    }convex[MAXN],cherry;
    
    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); }
        void _copy(Point t){
        	x=t.x; y=t.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[MAXN];//多边形 
    
    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);
    
    struct 	Line {
    	Point a,b;
    	double ang;
    }line[MAXN/2],st[MAXN/2];
    int n,cnt;
    
    double operator *(const Point x,const Point y){
    	return x.x*y.y-x.y*y.x;
    }
    Point operator -(Point x,const Point y){
    	x.x-=y.x; x.y-=y.y;
    	return x;
    }
    Point operator * (const Line &x,const Line &y){	//交点 
    	double a1=(y.b-x.a)*(y.a-x.a),a2=(y.a-x.b)*(y.b-x.b);
    	Point r;
    	r.x=(x.a.x*a2+x.b.x*a1)/(a2+a1);
    	r.y=(x.a.y*a2+x.b.y*a1)/(a2+a1);
    	return r;
    }
    
    bool operator ==(const Point &a,const Point &b){
    	return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;
    }
    
    bool operator <(const Line &x,const Line &y){
    	if(fabs(x.ang-y.ang)<eps)
    	return (y.b-x.a)*(x.b-y.a)>eps;
    	return x.ang <y.ang;
    }
    
    bool JudgeOut(const Line &x,const Point &p){
    	return (p-x.a)*(x.b-x.a)>eps;
    }
    
    bool Parellel(const Line &x,const Line &y){
    	return fabs((x.b-x.a)*(y.b-y.a))<eps;
    }
    
    void HplaneI(){
    	sort(line,line+n);
    	int top=1,bot=0,tmp=1;
    	for(int i=1;i<n;i++){
    		if(line[i].ang-line[i-1].ang>eps) line[tmp++]=line[i];
    	}
    	n=tmp;
    	st[0]=line[0],st[1]=line[1];
    	for(int i=2;i<n;i++){
    		if(Parellel(st[top],st[top-1])||Parellel(st[bot],st[bot+1]))return ;
    		while(bot<top&&JudgeOut(line[i],st[top]*st[top-1])) top--;
    		while(bot<top&&JudgeOut(line[i],st[bot]*st[bot+1])) bot++;
    		st[++top]=line[i];
    	}
    	while(bot<top&&JudgeOut(st[bot],st[top]*st[top-1])) top--;
    	while(bot<top&&JudgeOut(st[top],st[bot]*st[bot+1])) bot++;
    	if(top<=bot+1) return ;
    	st[++top]=st[bot]; cnt=0;
    	for(int i=bot;i<top;i++){
    		polygon[cnt++]._copy(st[i]*st[i+1]);
    	}
    }
    
    int main(){
    	int T,icase=0;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%lf%d",&radius,&n);
    		for(int i=0;i<n;i++){
    			scanf("%lf%lf%lf%lf",&line[i].a.x,&line[i].a.y,&line[i].b.x,&line[i].b.y);
    		}
    		scanf("%lf%lf",&cherry.x,&cherry.y);
    		for(int i=0;i<n;i++){
    			if((line[i].a-cherry)*(line[i].b-cherry)<0){
    				swap(line[i].a,line[i].b);
    			}
    			line[i].ang=atan2(line[i].b.y-line[i].a.y,line[i].b.x-line[i].a.x);
    		}
    		line[n].a=Point(-radius,-radius); line[n].b=Point(radius,-radius); line[n++].ang=0;
    		line[n].a=Point(radius,-radius); line[n].b=Point(radius,radius); line[n++].ang=pi/2;
    		line[n].a=Point(radius,radius); line[n].b=Point(-radius,radius); line[n++].ang=pi;
    		line[n].a=Point(-radius,radius); line[n].b=Point(-radius,-radius); line[n++].ang=-pi/2;
    		cnt=0;
    		HplaneI();
    		double ans=0;
    
    		for(int i=0;i<cnt;i++){
    	//		printf("%lf %lf 
    ",polygon[i].x,polygon[i].y);
    			ans+=kuras_area(polygon[i],polygon[(i+1)%cnt],0,0);
    		}
    		printf("Case %d: ",++icase);
    		printf("%.5lf",fabs(fabs(ans)-pi*radius*radius)<eps?100:fabs(ans)/(pi*radius*radius)*100);
    		puts("%");
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    【个人实战】作品展播BI大屏【部分见github主页】
    JAVA设计模式之单例(singleton)
    你所不知道的redis安装方法,穿一手鞋,看一手资料
    zookeeper实现分布式锁总结,看这一篇足矣(设计模式应用实战)
    JAVA设计模式之状态模式(state)
    JAVA设计模式之适配器模式(adapter)
    JAVA设计模式之构建器模式(builder)
    Redis实现分布式锁(设计模式应用实战)
    JAVA设计模式之享元模式(flyweight)
    JAVA设计模式之组合模式(composite)
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4509854.html
Copyright © 2011-2022 走看看