其他分享
首页 > 其他分享> > 处理椭圆和矩形的面积相交问题

处理椭圆和矩形的面积相交问题

作者:互联网

首先将椭圆的圆心移动到原点处,同时矩形也进行相应的移动。

在次之后,使用仿射变换,选定任意一个轴变换使其变成圆,那么相应的矩形也同等比例的变换。

变换之后,来一个板子把他们整合起来,结束。

  1 int dcmp(double x) {
  2     if (fabs(x) < eps)return 0;
  3     return x > 0 ? 1 : -1;
  4 }
  5 struct Point {
  6     double x, y;
  7     Point(double _x = 0, double _y = 0) {
  8         x = _x;y = _y;
  9     }
 10 };
 11 Point operator + (const Point& a, const Point& b) {
 12     return Point(a.x + b.x, a.y + b.y);
 13 }
 14 Point operator - (const Point& a, const Point& b) {
 15     return Point(a.x - b.x, a.y - b.y);
 16 }
 17 Point operator * (const Point& a, const double& p) {
 18     return Point(a.x * p, a.y * p);
 19 }
 20 Point operator / (const Point& a, const double& p) {
 21     return Point(a.x / p, a.y / p);
 22 }
 23 bool operator < (const Point& a, const Point& b) {
 24     return a.x < b.x || (dcmp(a.x - b.x) == 0 && a.y < b.y);
 25 }
 26 bool operator == (const Point& a, const Point& b) {
 27     return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
 28 }
 29 double Dot(Point  a, Point b) {
 30     return a.x * b.x + a.y * b.y;
 31 }
 32 double Length(Point a) {
 33     return sqrt(Dot(a, a));
 34 }
 35 double Angle(Point a, Point b) {
 36     return acos(Dot(a, b) / Length(a) / Length(b));
 37 }
 38 double angle(Point a) {
 39     return atan2(a.y, a.x);
 40 }
 41 double Cross(Point a, Point b) {
 42     return a.x * b.y - a.y * b.x;
 43 }
 44 Point vecunit(Point a) {
 45     return a / Length(a);
 46 }
 47 Point Normal(Point a) {
 48     return Point(-a.y, a.x) / Length(a);
 49 }
 50 Point Rotate(Point a, double rad) {
 51     return Point(a.x * cos(rad) - a.y * sin(rad), a.x * sin(rad) + a.y * cos(rad));
 52 }
 53 double Area2(Point a, Point b, Point c) {
 54     return Length(Cross(b - a, c - a));
 55 }
 56 bool OnSegment(Point p, Point a1, Point a2) {
 57     return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) <= 0;
 58 }
 59 struct Line {
 60     Point p, v;
 61     double ang;
 62     Line() {};
 63     Line(Point p, Point v) :p(p), v(v) {
 64         ang = atan2(v.y, v.x);
 65     }
 66     bool operator < (const Line& L) const {
 67         return ang < L.ang;
 68     }
 69     Point point(double d) {
 70         return p + (v * d);
 71     }
 72 };
 73 bool OnLeft(const Line& L, const Point& p) {
 74     return Cross(L.v, p - L.p) >= 0;
 75 }
 76 Point GetLineIntersection(Point p, Point v, Point q, Point w) {
 77     Point u = p - q;
 78     double t = Cross(w, u) / Cross(v, w);
 79     return p + v * t;
 80 }
 81 Point GetLineIntersection(Line a, Line b) {
 82     return GetLineIntersection(a.p, a.v, b.p, b.v);
 83 }
 84 double PolyArea(vector<Point> p) {
 85     int n = p.size();
 86     double ans = 0;
 87     for (int i = 1;i < n - 1;i++)
 88         ans += Cross(p[i] - p[0], p[i + 1] - p[0]);
 89     return fabs(ans) / 2;
 90 }
 91 struct Circle
 92 {
 93     Point c;
 94     double r;
 95     Circle() {}
 96     Circle(Point c, double r) :c(c), r(r) {}
 97     Point point(double a) //根据圆心角求点坐标      
 98     {
 99         return Point(c.x + cos(a) * r, c.y + sin(a) * r);
100     }
101 };
102 
103 bool InCircle(Point x, Circle c) {
104     return dcmp(c.r - Length(c.c - x)) >= 0;
105 }
106 bool OnCircle(Point x, Circle c) {
107     return dcmp(c.r - Length(c.c - x)) == 0;
108 }
109 int getSegCircleIntersection(Line L, Circle C, Point* sol) {
110     Point nor = Normal(L.v);
111     Line p1 = Line(C.c, nor);
112     Point ip = GetLineIntersection(p1, L);
113     double dis = Length(ip - C.c);
114     if (dcmp(dis - C.r) > 0)return 0;
115     Point dxy = vecunit(L.v) * sqrt(C.r * C.r - dis * dis);
116     int ret = 0;
117     sol[ret] = ip + dxy;
118     if (OnSegment(sol[ret], L.p, L.point(1)))ret++;
119     sol[ret] = ip - dxy;
120     if (OnSegment(sol[ret], L.p, L.point(1)))ret++;
121     return ret;
122 }
123 double SegCircleArea(Circle C, Point a, Point b) {
124     double a1 = angle(a - C.c);
125     double a2 = angle(b - C.c);
126     double da = fabs(a1 - a2);
127     if (da > pi)da = pi * 2 - da;
128     return dcmp(Cross(b - C.c, a - C.c)) * da * C.r * C.r / 2.0;
129 }
130 double PolyCircleArea(Circle C, Point* p, int n) {
131     double ret = 0;
132     Point sol[2];
133     p[n] = p[0];
134     for (int i = 0;i < n;i++) {
135         double t1, t2;
136         int cnt = getSegCircleIntersection(Line(p[i], p[i + 1] - p[i]), C, sol);  //判断线段与圆有几个交点,  
137     //  cout<<"cnt="<<cnt<<" "<<p[i].x<<" "<<p[i].y<<" "<<p[i+1].x<<" "<<p[i+1].y<<endl;  
138     //  cout<<"C: "<<C.c.x<<" "<<C.c.y<<" "<<C.r<<endl;  
139     //  cout<<"sol ";for(int j=0;j<cnt;j++)cout<<sol[j].x<<" "<<sol[j].y<<" ";cout<<endl; 
140         //cout << cnt << endl;
141         if (cnt == 0) {  //0个交点,判断线段在多边形内部还是外部。  
142             if (!InCircle(p[i], C) || !InCircle(p[i + 1], C))ret += SegCircleArea(C, p[i], p[i + 1]); //外部直接计算圆弧面积   
143             else ret += Cross(p[i + 1] - C.c, p[i] - C.c) / 2;  //内部计算三角形面积。
144         }
145         if (cnt == 1) {
146             if (InCircle(p[i], C) && (!InCircle(p[i + 1], C) || OnCircle(p[i + 1], C)))ret += Cross(sol[0] - C.c, p[i] - C.c) / 2, ret += SegCircleArea(C, sol[0], p[i + 1]);//,cout<<"jj-1"<<endl;  
147             else ret += SegCircleArea(C, p[i], sol[0]), ret += Cross(p[i + 1] - C.c, sol[0] - C.c) / 2;//,cout<<"jj-2"<<endl;  
148         }
149         if (cnt == 2) {  //两个交点  
150             if ((p[i] < p[i + 1]) ^ (sol[0] < sol[1]))swap(sol[0], sol[1]);
151             ret += SegCircleArea(C, p[i], sol[0]);
152             ret += Cross(sol[1] - C.c, sol[0] - C.c) / 2;
153             ret += SegCircleArea(C, sol[1], p[i + 1]);
154         }
155         // cout<<ret<<endl;      
156     }
157     return fabs(ret);
158 }

 

标签:椭圆,return,Point,double,相交,Length,dcmp,const,矩形
来源: https://www.cnblogs.com/xyisreallycuteeee/p/15081016.html