Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
269
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.59 KB | None | 0 0
  1. struct point {
  2.     double x, y;
  3.     point(double _x = 0.0, double _y = 0.0) : x(_x), y(_y) {}
  4.     bool operator== (const point& other) const {
  5.         return fabs(x - other.x) < EPS && fabs(y - other.y) < EPS;
  6.     }
  7. };
  8.  
  9. struct point_i {
  10.     int x, y;
  11.     point_i(int _x = 0, int _y = 0) : x(_x), y(_y) {}
  12. };
  13.  
  14. double dist(point p1, point p2) {
  15.     // Euclidean distance
  16.     // hypot(dx, dy) returns sqrt(dx * dx + dy * dy)
  17.     return hypot(p1.x - p2.x, p1.y - p2.y);
  18. }
  19.  
  20. // rotate p by theta degrees CCW w.r.t origin (0, 0)
  21. point rotate(point p, double theta) { double rad = theta * PI / 180.0;
  22.     return point(p.x * cos(rad) - p.y * sin(rad),
  23.             p.x * sin(rad) + p.y * cos(rad));
  24. }
  25.  
  26. // ax + by + c = 0
  27. struct line { double a, b, c; };
  28. // the answer is stored in the third parameter (pass by reference)
  29. void pointsToLine(point p1, point p2, line &l) {
  30.     if (fabs(p1.x - p2.x) < EPS) {
  31.         // vertical line is fine
  32.         l.a = 1.0;
  33.         l.b = 0.0;
  34.         l.c = -p1.x;
  35.         // default values
  36.     } else {
  37.         l.a = -(double)(p1.y - p2.y) / (p1.x - p2.x);
  38.         l.b = 1.0;
  39.         // IMPORTANT: we fix the value of b to 1.0
  40.         l.c = -(double)(l.a * p1.x) - p1.y;
  41.     }
  42. }
  43.  
  44. bool areParallel(line l1, line l2) {
  45.     // check coefficients a & b
  46.     return (fabs(l1.a-l2.a) < EPS) && (fabs(l1.b-l2.b) < EPS);
  47. }
  48.  
  49. bool areSame(line l1, line l2) {
  50.     // also check coefficient c
  51.     return areParallel(l1 ,l2) && (fabs(l1.c - l2.c) < EPS);
  52. }
  53.  
  54. // returns true (+ intersection point) if two lines are intersect
  55. bool areIntersect(line l1, line l2, point &p) {
  56.     if (areParallel(l1, l2)) return false;
  57.  
  58.     // no intersection
  59.     // solve system of 2 linear algebraic equations with 2 unknowns
  60.     p.x = (l2.b * l1.c - l1.b * l2.c) / (l2.a * l1.b - l1.a * l2.b);
  61.  
  62.     // special case: test for vertical line to avoid division by zero
  63.     if (fabs(l1.b) > EPS)   p.y = -(l1.a * p.x + l1.c);
  64.     else                    p.y = -(l2.a * p.x + l2.c);
  65.  
  66.     return true;
  67. }
  68.  
  69. struct vec {
  70.     double x, y;
  71.     vec(double _x, double _y) : x(_x), y(_y) {}
  72. };
  73. vec toVec(point a, point b) {
  74.     // convert 2 points to vector a->b
  75.     return vec(b.x - a.x, b.y - a.y);
  76. }
  77.  
  78. vec scale(vec v, double s) {
  79.     return vec(v.x * s, v.y * s);
  80. }
  81.  
  82. // nonnegative s = [<1 .. 1 .. >1]
  83. // shorter.same.longer
  84. point translate(point p, vec v) {
  85.     // translate p according to v
  86.     return point(p.x + v.x , p.y + v.y);
  87. }
  88.  
  89. double dot(vec a, vec b) { return (a.x * b.x + a.y * b.y); }
  90.  
  91. double norm_sq(vec v) { return v.x * v.x + v.y * v.y; }
  92.  
  93. // returns the distance from p to the line defined by
  94. // two points a and b (a and b must be different)
  95. // the closest point is stored in the 4th parameter (byref)
  96. double distToLine(point p, point a, point b, point &c) {
  97.     // formula: c = a + u * ab
  98.     vec ap = toVec(a, p), ab = toVec(a, b);
  99.     double u = dot(ap, ab) / norm_sq(ab);
  100.     c = translate(a, scale(ab, u));
  101.     // translate a to c
  102.     return dist(p, c);
  103. }
  104.  
  105. // returns the distance from p to the line segment ab defined by
  106. // two points a and b (still OK if a == b)
  107. // the closest point is stored in the 4th parameter (byref)
  108. double distToLineSegment(point p, point a, point b, point &c) {
  109.     vec ap = toVec(a, p), ab = toVec(a, b);
  110.     double u = dot(ap, ab) / norm_sq(ab);
  111.  
  112.     if (u < 0.0) {
  113.         c = point(a.x, a.y);
  114.         // closer to a
  115.         return dist(p, a);
  116.     }
  117.  
  118.     // Euclidean distance between p and a
  119.     if (u > 1.0) { c = point(b.x, b.y);
  120.         // closer to b
  121.         return dist(p, b);
  122.     }
  123.  
  124.     // Euclidean distance between p and b
  125.     return distToLine(p, a, b, c);
  126. }
  127.  
  128. // since oa . ob = |oa| x |ob| x cos(theta) -> theta = acos(oa . ob / (|oa| x |ob|))
  129. double angle(point a, point o, point b) { // RETURNS ANGLE AOB IN RAD
  130.     vec oa = toVec(o, a), ob = toVec(o, b);
  131.     return acos(dot(oa, ob) / sqrt(norm_sq(oa) * norm_sq(ob)));
  132. }
  133.  
  134. double cross(vec a, vec b) { return a.x * b.y - a.y * b.x; }
  135.  
  136. // note: to accept collinear points, we have to change the ā€˜> 0ā€™
  137. // returns true if point r is on the left side of line pq
  138. bool ccw(point p, point q, point r) {
  139.     return cross(toVec(p, q), toVec(p, r)) > 0;
  140. }
  141.  
  142. // returns true if point r is on the same line as the line pq
  143. bool collinear(point p, point q, point r) {
  144.     return fabs(cross(toVec(p, q), toVec(p, r))) < EPS;
  145. }
  146.  
  147. bool lineSegmentIntersect(point p1, point p2, point q1, point q2) {
  148.     point i;
  149.     line l1, l2;
  150.  
  151.     pointsToLine(p1, p2, l1);
  152.     pointsToLine(q1, q2, l2);
  153.  
  154.     if (areSame(l1, l2))
  155.         return min(q1.x, q2.x) <= max(p1.x, p2.x) && max(q1.x, q2.x) >= min(p1.x, p2.x)  && min(q1.y, q2.y) <= max(p1.y, p2.y) && max(q1.y, q2.y) >= min(p1.y, p2.y);
  156.  
  157.     if (areIntersect(l1, l2, i) == false) return false;
  158.     return fabs(dist(p1, i) + dist(i, p2) - dist(p1, p2)) < EPS && fabs(dist(q1, i) + dist(i, q2) - dist(q1, q2)) < EPS;
  159. }
  160.  
  161. // Circle
  162.  
  163. int insideCircle(point_i p, point_i c, int r) {
  164.     int dx = p.x - c.x, dy = p.y - c.y;
  165.     int Eucl = dx * dx + dy * dy, rSq = r * r;
  166.     return Eucl < rSq ? 0 : Eucl == rSq ? 1 : 2; // inside/border/outside
  167. }
  168.  
  169. struct Circle {
  170.     point c;
  171.     double r;
  172.  
  173.     const double PI = acos(-1);
  174.  
  175.     double area() { return PI * r * r; }
  176.     double perimeter() { return 2 * PI * r; }
  177.     bool isInside(point p) { return dist(c, p) <= r; }
  178.     double arcLength(double angle) { return angle / 360.0 * perimeter(); }
  179.     double chordLength(double angle) { angle *= PI / 180.0; return 2 * r * sin(angle / 2); }
  180.     double sectorArea(double angle) { angle *= PI / 180.0; return angle * area(); }
  181.     double segmentArea(double angle) { return sectorArea(angle) - r * chordLength(angle) / 2.0; }
  182. };
  183.  
  184. // a function to get a valid center of a circle given
  185. // the 2 pts of intersection between it and another and its radius
  186. bool circle2PtsRad(point p1, point p2, double r, point &c) {
  187.     double d2 = (p1.x - p2.x) * (p1.x - p2.x) +
  188.                 (p1.y - p2.y) * (p1.y - p2.y);
  189.     double det = r * r / d2 - 0.25;
  190.     if (det < 0.0) return false;
  191.     double h = sqrt(det);
  192.     c.x = (p1.x + p2.x) * 0.5 + (p1.y - p2.y) * h;
  193.     c.y = (p1.y + p2.y) * 0.5 + (p2.x - p1.x) * h;
  194.     return true;
  195. } // to get the other center, reverse p1 and p2
  196.  
  197. // Triangles
  198.  
  199. double Heron(double a, double b, double c) {
  200.     double s = (a + b + c) / 2.0;
  201.     return sqrt(s * (s - a) * (s - b) * (s - c));
  202. }
  203.  
  204. double rCircumCircle(double ab, double bc, double ca) {
  205.     return ab * bc * ca / (4.0 * Heron(ab, bc, ca));
  206. }
  207.  
  208. double rCircumCircle(point a, point b, point c) {
  209.     return rCircumCircle(dist(a, b), dist(b, c), dist(c, a));
  210. }
  211.  
  212.  
  213. double rInCircle(double ab, double bc, double ca) {
  214.     return Heron(ab, bc, ca) / (0.5 * (ab + bc + ca));
  215. }
  216.  
  217. double rInCircle(point a, point b, point c) {
  218.     return rInCircle(dist(a, b), dist(b, c), dist(c, a));
  219. }
  220.  
  221. // assumption: the required points/lines functions have been written
  222. // returns 1 if there is an inCircle center, returns 0 otherwise
  223. // if this function returns 1, ctr will be the inCircle center
  224. // and r is the same as rInCircle
  225. int inCircle(point p1, point p2, point p3, point &ctr, double &r) {
  226.     r = rInCircle(p1, p2, p3);
  227.     if (fabs(r) < EPS) return 0;
  228.     // no inCircle center
  229.     line l1, l2;
  230.     // compute these two angle bisectors
  231.     double ratio = dist(p1, p2) / dist(p1, p3);
  232.     point p = translate(p2, scale(toVec(p2, p3), ratio / (1 + ratio)));
  233.     pointsToLine(p1, p, l1);
  234.     ratio = dist(p2, p1) / dist(p2, p3);
  235.     p = translate(p1, scale(toVec(p1, p3), ratio / (1 + ratio)));
  236.     pointsToLine(p2, p, l2);
  237.     areIntersect(l1, l2, ctr);
  238.     return 1;
  239. }
  240.  
  241. // cosine rule:
  242. //      c^2 = a^2 + b^2 - 2ab(cos(theta))
  243. //  sine rule:
  244. //      a / sin(A) = b / sin(B) = c / sine(C) = 2R
  245.  
  246.  
  247. // Polygons
  248.  
  249. // we assume that the points are entered in ccw order
  250. // P[0] is always equal P[n]
  251.  
  252. double perimeter(const vector<point> &P) {
  253.     double result = 0.0;
  254.     for (int i = 0; i < (int) P.size() - 1; ++i)
  255.         result += dist(P[i], P[i + 1]);
  256.     return result;
  257. }
  258.  
  259. double area(const vector<point> &P) {
  260.     double result = 0.0, x1, y1, x2, y2;
  261.     for (int i = 0; i < (int) P.size() - 1; ++i) {
  262.         x1 = P[i].x, x2 = P[i + 1].x;
  263.         y1 = P[i].y, y2 = P[i + 1].y;
  264.         result += x1 * y2 - x2 * y1;
  265.     }
  266.     return result / 2.0;
  267. }
  268.  
  269. bool isConvex(const vector<point> &P) {
  270.     // returns true if all three
  271.     int sz = (int)P.size(); // consecutive vertices of P form the same turns
  272.     if (sz <= 3) return false; // a point/sz=2 or a line/sz=3 is not convex
  273.     bool isLeft = ccw(P[0], P[1], P[2]); // remember one result
  274.     for (int i = 1; i < sz-1; i++) { // then compare with the others
  275.         if (ccw(P[i], P[i+1], P[(i+2) == sz ? 1 : i+2]) != isLeft)
  276.             return false; // different sign -> this polygon is concave
  277.     }
  278.     return true;
  279. } // this polygon is convex
  280.  
  281. bool isConvex_with_collinear(const vector<point> &P) {
  282.     int sz = (int) P.size();
  283.     if (sz <= 3) return false;
  284.     int s = 0;
  285.     while (s < sz - 1 && collinear(P[s], P[s + 1], P[(s + 2) == sz ? 1 : s + 2]))
  286.         ++s;
  287.     if (s == sz - 1) return false;
  288.  
  289.     bool isLeft = ccw(P[s], P[s + 1], P[(s + 2) == sz ? 1 : s + 2]);
  290.     for (int i = 0; i < sz - 1; ++i) {
  291.         if (collinear(P[i], P[s + 1], P[(s + 2) == sz ? 1 : s + 2]))
  292.             continue;
  293.         if (ccw(P[i], P[s + 1], P[(s + 2) == sz ? 1 : s + 2]) != isLeft)
  294.             return false;
  295.     }
  296.     return true;
  297. }
  298.  
  299. // returns true if point p is in either convex/concave polygon P
  300. bool inPolygon_angle(point pt, const vector<point> &P) {
  301.     if ((int)P.size() == 0) return false;
  302.     double sum = 0;
  303.     // assume the first vertex is equal to the last vertex
  304.     for (int i = 0; i < (int)P.size()-1; i++) {
  305.         if (ccw(pt, P[i], P[i+1]))
  306.             sum += angle(P[i], pt, P[i+1]); // left turn/ccw
  307.         else sum -= angle(P[i], pt, P[i+1]); // right turn/cw
  308.     }
  309.    
  310.     return fabs(fabs(sum) - 2*PI) < EPS;
  311. }
  312.  
  313. // another solution is to cut the polygon into triangle and check that the sum of
  314. // area of those triangle is equal to the area of the polygon
  315. bool inPolygon(point pt, const vector<point> &P) {
  316.     if ((int) P.size() == 0) return false;
  317.     double A = 0.0;
  318.     for (int i = 0; i < (int) P.size() - 1; ++i) {
  319.         point a = pt, b = P[i], c = P[i + 1];
  320.         A += Heron(dist(a, b), dist(b, c), dist(a, c));
  321.     }
  322.     return fabs(A - area(P)) < EPS;
  323. }
  324.  
  325. // line segment p-q intersect with line A-B.
  326. point lineIntersectSeg(point p, point q, point A, point B) {
  327.     double a = B.y - A.y;
  328.     double b = A.x - B.x;
  329.     double c = B.x * A.y - A.x * B.y;
  330.     double u = fabs(a * p.x + b * p.y + c);
  331.     double v = fabs(a * q.x + b * q.y + c);
  332.     return point((p.x * v + q.x * u) / (u+v), (p.y * v + q.y * u) / (u+v));
  333. }
  334.  
  335. // cuts polygon Q along the line formed by point a -> point b
  336. // (note: the last point must be the same as the first point)
  337. vector<point> cutPolygon(point a, point b, const vector<point> &Q) {
  338.     vector<point> P;
  339.     for (int i = 0; i < (int)Q.size(); i++) {
  340.         double left1 = cross(toVec(a, b), toVec(a, Q[i])), left2 = 0;
  341.         if (i != (int)Q.size()-1) left2 = cross(toVec(a, b), toVec(a, Q[i+1]));
  342.         if (left1 > -EPS) P.push_back(Q[i]);
  343.         // Q[i] is on the left of ab
  344.         if (left1 * left2 < -EPS)
  345.         // edge (Q[i], Q[i+1]) crosses line ab
  346.         P.push_back(lineIntersectSeg(Q[i], Q[i+1], a, b));
  347.     }
  348.     if (!P.empty() && !(P.back() == P.front()))
  349.         P.push_back(P.front());
  350.     // make Pā€™s first point = Pā€™s last point
  351.     return P;
  352. }
  353.  
  354. point pivot(0, 0);
  355. bool angleCmp(point a, point b) {
  356.     // angle-sorting function
  357.     if (collinear(pivot, a, b)) // special case
  358.         return dist(pivot, a) < dist(pivot, b); // check which one is closer
  359.     double d1x = a.x - pivot.x, d1y = a.y - pivot.y;
  360.     double d2x = b.x - pivot.x, d2y = b.y - pivot.y;
  361.     return (atan2(d1y, d1x) - atan2(d2y, d2x)) < 0; // compare two angles
  362. }
  363.  
  364. vector<point> convexHull(vector<point> P) {
  365.     if (P.empty()) return P;
  366.     // the content of P may be reshuffled
  367.     int i, j, n = (int)P.size();
  368.     if (n <= 3) {
  369.         if (!(P[0] == P[n-1])) P.push_back(P[0]); // safeguard from corner case
  370.         return P;
  371.     }
  372.     // special case, the CH is P itself
  373.     // first, find P0 = point with lowest Y and if tie: rightmost X
  374.     int P0 = 0;
  375.     for (i = 1; i < n; i++)
  376.         if (P[i].y < P[P0].y || (P[i].y == P[P0].y && P[i].x > P[P0].x))
  377.             P0 = i;
  378.     point temp = P[0]; P[0] = P[P0]; P[P0] = temp; // swap P[P0] with P[0]
  379.  
  380.     // second, sort points by angle w.r.t. pivot P0
  381.     pivot = P[0];
  382.     // use this global variable as reference
  383.     sort(++P.begin(), P.end(), angleCmp); // we do not sort P[0]
  384.  
  385.     // third, the ccw tests
  386.     vector<point> S;
  387.     S.push_back(P[n-1]); S.push_back(P[0]); S.push_back(P[1]); // initial S
  388.     i = 2; // then, we check the rest
  389.     while (i < n) { // NOTE: N must be >= 3 for this method to work
  390.         j = (int)S.size()-1;
  391.         if (collinear(S[j - 1], S[j], P[i])) { // MAY change if the points on the line are collinear
  392.             S.pop_back();
  393.             S.push_back(P[i++]);
  394.         }
  395.         else if (ccw(S[j-1], S[j], P[i])) S.push_back(P[i++]); // left turn, accept
  396.         else S.pop_back(); // or pop the top of S until we have a left turn
  397.     }
  398.    
  399.     return S; // return the result
  400. }
  401.  
  402. vector<point> convexPolygonIntersection(vector<point> &P1, vector<point> &P2) {
  403.     int sz1 = (int) P1.size() - 1;
  404.     int sz2 = (int) P2.size() - 1;
  405.  
  406.     vector<point> I;
  407.     for (int i = 0; i < sz1; ++i) {
  408.         for (int j = 0; j < sz2; ++j) {
  409.             if (lineSegmentIntersect(P1[i], P1[i + 1], P2[j], P2[j + 1])) {
  410.                 point In;
  411.                 line l1, l2;
  412.                 pointsToLine(P1[i], P1[i + 1], l1);
  413.                 pointsToLine(P2[j], P2[j + 1], l2);
  414.                 if (areIntersect(l1, l2, In))
  415.                     I.push_back(In);
  416.             }
  417.         }
  418.         if (inPolygon(P1[i], P2)) {
  419.             I.push_back(P1[i]);
  420.         }
  421.     }
  422.  
  423.     for (int i = 0; i < sz2; ++i) {
  424.         for (int j = 0; j < sz1; ++j) {
  425.             if (lineSegmentIntersect(P2[i], P2[i + 1], P1[j], P1[j + 1])) {
  426.                 point In;
  427.                 line l1, l2;
  428.                 pointsToLine(P1[j], P1[j + 1], l1);
  429.                 pointsToLine(P2[i], P2[i + 1], l2);
  430.                 if (areIntersect(l1, l2, In))
  431.                     I.push_back(In);
  432.             }
  433.         }
  434.         if (inPolygon(P2[i], P1))
  435.             I.push_back(P2[i]);
  436.     }
  437.  
  438.     return convexHull(I);
  439. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement