Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- double INF = 1e100;
- double eps = 1e-12;
- struct PT
- {
- double x, y;
- PT() {}
- PT(double x, double y) : x(x), y(y) {}
- PT(const PT &p) : x(p.x), y(p.y) {}
- PT operator + (const PT &p) const
- {
- return PT(x+p.x, y+p.y);
- }
- PT operator - (const PT &p) const
- {
- return PT(x-p.x, y-p.y);
- }
- PT operator * (double c) const
- {
- return PT(x*c, y*c );
- }
- PT operator / (double c) const
- {
- return PT(x/c, y/c );
- }
- bool operator<(const PT &rhs) const
- {
- return make_pair(y,x) < make_pair(rhs.y,rhs.x);
- }
- bool operator==(const PT &rhs) const
- {
- return make_pair(y,x) == make_pair(rhs.y,rhs.x);
- }
- };
- double dot(PT p, PT q)
- {
- return p.x*q.x+p.y*q.y;
- }
- double len (PT p)
- {
- return sqrt(p.x*p.x+p.y*p.y);
- }
- double dist2(PT p, PT q)
- {
- return dot(p-q,p-q);
- }
- double cross(PT p, PT q)
- {
- return p.x*q.y-p.y*q.x;
- }
- ostream &operator<<(ostream &os, const PT &p)
- {
- os << "(" << p.x << "," << p.y << ")";
- }
- // rotate a point CCW or CW around the origin
- PT RotateCCW90(PT p)
- {
- return PT(-p.y,p.x);
- }
- PT RotateCW90(PT p)
- {
- return PT(p.y,-p.x);
- }
- PT RotateCCW(PT p, double t)
- {
- return PT(p.x*cos(t)-p.y*sin(t), p.x*sin(t)+p.y*cos(t));
- }
- // project point c onto line through a and b
- // assuming a != b
- PT ProjectPointLine(PT a, PT b, PT c)
- {
- return a + (b-a)*dot(c-a, b-a)/dot(b-a, b-a);
- }
- // project point c onto line segment through a and b
- PT ProjectPointSegment(PT a, PT b, PT c)
- {
- double r = dot(b-a,b-a);
- if (fabs(r) < eps) return a;
- r = dot(c-a, b-a)/r;
- if (r < 0) return a;
- if (r > 1) return b;
- return a + (b-a)*r;
- }
- // compute distance from c to segment between a and b
- double DistancePointSegment(PT a, PT b, PT c)
- {
- return sqrt(dist2(c, ProjectPointSegment(a, b, c)));
- }
- // compute distance between point (x,y,z) and plane ax+by+cz=d
- double DistancePointPlane(double x, double y, double z,
- double a, double b, double c, double d)
- {
- return fabs(a*x+b*y+c*z-d)/sqrt(a*a+b*b+c*c);
- }
- // determine if lines from a to b and c to d are parallel or collinear
- bool LinesParallel(PT a, PT b, PT c, PT d)
- {
- return fabs(cross(b-a, c-d)) < eps;
- }
- bool LinesCollinear(PT a, PT b, PT c, PT d)
- {
- return LinesParallel(a, b, c, d)
- && fabs(cross(a-b, a-c)) < eps
- && fabs(cross(c-d, c-a)) < eps;
- }
- // determine if line segment from a to b intersects with
- // line segment from c to d
- bool SegmentsIntersect(PT a, PT b, PT c, PT d)
- {
- if (LinesCollinear(a, b, c, d))
- {
- if (dist2(a, c) < eps || dist2(a, d) < eps ||
- dist2(b, c) < eps || dist2(b, d) < eps) return true;
- if (dot(c-a, c-b) > 0 && dot(d-a, d-b) > 0 && dot(c-b, d-b) > 0)
- return false;
- return true;
- }
- if (cross(d-a, b-a) * cross(c-a, b-a) > 0) return false;
- if (cross(a-c, d-c) * cross(b-c, d-c) > 0) return false;
- return true;
- }
- // compute intersection of line passing through a and b
- // with line passing through c and d, assuming that unique
- // intersection exists; for segment intersection, check if
- // segments intersect first
- PT ComputeLineIntersection(PT a, PT b, PT c, PT d)
- {
- b=b-a;
- d=c-d;
- c=c-a;
- assert(dot(b, b) > eps && dot(d, d) > eps);
- return a + b*cross(c, d)/cross(b, d);
- }
- // compute center of circle given three points
- PT ComputeCircleCenter(PT a, PT b, PT c)
- {
- b=(a+b)/2;
- c=(a+c)/2;
- return ComputeLineIntersection(b, b+RotateCW90(a-b), c, c+RotateCW90(a-c));
- }
- // determine if point is in a possibly non-convex polygon (by William
- // Randolph Franklin); returns 1 for strictly interior points, 0 for
- // strictly exterior points, and 0 or 1 for the remaining points.
- // Note that it is possible to convert this into an *exact* test using
- // integer arithmetic by taking care of the division appropriately
- // (making sure to deal with signs properly) and then by writing exact
- // tests for checking point on polygon boundary
- bool PointInPolygon(const vector<PT> &p, PT q)
- {
- bool c = 0;
- for (int i = 0; i < p.size(); i++)
- {
- int j = (i+1)%p.size();
- if ((p[i].y <= q.y && q.y < p[j].y ||
- p[j].y <= q.y && q.y < p[i].y) &&
- q.x < p[i].x + (p[j].x - p[i].x) * (q.y - p[i].y) / (p[j].y - p[i].y))
- c = !c;
- }
- return c;
- }
- // determine if point is on the boundary of a polygon
- bool PointOnPolygon(const vector<PT> &p, PT q)
- {
- for (int i = 0; i < p.size(); i++)
- if (dist2(ProjectPointSegment(p[i], p[(i+1)%p.size()], q), q) < eps)
- return true;
- return false;
- }
- // compute intersection of line through points a and b with
- // circle centered at c with radius r > 0
- vector<PT> CircleLineIntersection(PT a, PT b, PT c, double r)
- {
- vector<PT> ret;
- b = b-a;
- a = a-c;
- double A = dot(b, b);
- double B = dot(a, b);
- double C = dot(a, a) - r*r;
- double D = B*B - A*C;
- if (D < -eps) return ret;
- ret.push_back(c+a+b*(-B+sqrt(D+eps))/A);
- if (D > eps)
- ret.push_back(c+a+b*(-B-sqrt(D))/A);
- return ret;
- }
- // compute intersection of circle centered at a with radius r
- // with circle centered at b with radius R
- vector<PT> CircleCircleIntersection(PT a, PT b, double r, double R)
- {
- vector<PT> ret;
- double d = sqrt(dist2(a, b));
- if (d > r+R || d+min(r, R) < max(r, R)) return ret;
- double x = (d*d-R*R+r*r)/(2*d);
- double y = sqrt(r*r-x*x);
- PT v = (b-a)/d;
- ret.push_back(a+v*x + RotateCCW90(v)*y);
- if (y > 0)
- ret.push_back(a+v*x - RotateCCW90(v)*y);
- return ret;
- }
- // This code computes the area or centroid of a (possibly nonconvex)
- // polygon, assuming that the coordinates are listed in a clockwise or
- // counterclockwise fashion. Note that the centroid is often known as
- // the "center of gravity" or "center of mass".
- double ComputeSignedArea(const vector<PT> &p)
- {
- double area = 0;
- for(int i = 0; i < p.size(); i++)
- {
- int j = (i+1) % p.size();
- area += p[i].x*p[j].y - p[j].x*p[i].y;
- }
- return area / 2.0;
- }
- double ComputeArea(const vector<PT> &p)
- {
- return fabs(ComputeSignedArea(p));
- }
- PT ComputeCentroid(const vector<PT> &p)
- {
- PT c(0,0);
- double scale = 6.0 * ComputeSignedArea(p);
- for (int i = 0; i < p.size(); i++)
- {
- int j = (i+1) % p.size();
- c = c + (p[i]+p[j])*(p[i].x*p[j].y - p[j].x*p[i].y);
- }
- return c / scale;
- }
- // tests whether or not a given polygon (in CW or CCW order) is simple
- bool IsSimple(const vector<PT> &p)
- {
- for (int i = 0; i < p.size(); i++)
- {
- for (int k = i+1; k < p.size(); k++)
- {
- int j = (i+1) % p.size();
- int l = (k+1) % p.size();
- if (i == l || j == k) continue;
- if (SegmentsIntersect(p[i], p[j], p[k], p[l]))
- return false;
- }
- }
- return true;
- }
- double angle (PT p, PT q)
- {
- return acos(dot(p, q)/(len(p)*len(q)));
- }
- double angle2 (PT a, PT b, PT c) //returns angle ABC
- {
- return angle (a-b, c-b);
- }
- PT incentre (PT a, PT b, PT c)
- {
- double angb = angle (a-b, c-b);
- double anga = angle (b-a, c-a);
- double angc = angle (a-c, b-c);
- PT p1 = RotateCCW(c-b, angb/2.0)+b;
- PT p2 = RotateCCW(b-c, -angc/2.0)+c;
- PT d = ComputeLineIntersection(b, p1, c, p2);
- return d;
- }
- #define REMOVE_REDUNDANT
- double area2(PT a, PT b, PT c)
- {
- return cross(a,b) + cross(b,c) + cross(c,a);
- }
- #ifdef REMOVE_REDUNDANT
- bool between(const PT &a, const PT &b, const PT &c)
- {
- return (fabs(area2(a,b,c)) < eps && (a.x-b.x)*(c.x-b.x) <= 0 && (a.y-b.y)*(c.y-b.y) <= 0);
- }
- #endif
- void ConvexHull(vector<PT> &pts)
- {
- sort(pts.begin(), pts.end());
- pts.erase(unique(pts.begin(), pts.end()), pts.end());
- vector<PT> up, dn;
- for (int i = 0; i < pts.size(); i++)
- {
- while (up.size() > 1 && area2(up[up.size()-2], up.back(), pts[i]) >= 0) up.pop_back();
- while (dn.size() > 1 && area2(dn[dn.size()-2], dn.back(), pts[i]) <= 0) dn.pop_back();
- up.push_back(pts[i]);
- dn.push_back(pts[i]);
- }
- pts = dn;
- for (int i = (int) up.size() - 2; i >= 1; i--) pts.push_back(up[i]);
- #ifdef REMOVE_REDUNDANT
- if (pts.size() <= 2) return;
- dn.clear();
- dn.push_back(pts[0]);
- dn.push_back(pts[1]);
- for (int i = 2; i < pts.size(); i++)
- {
- if (between(dn[dn.size()-2], dn[dn.size()-1], pts[i])) dn.pop_back();
- dn.push_back(pts[i]);
- }
- if (dn.size() >= 3 && between(dn.back(), dn[0], dn[1]))
- {
- dn[0] = dn.back();
- dn.pop_back();
- }
- pts = dn;
- #endif
- }
- int main ()
- {
- }
Add Comment
Please, Sign In to add comment