#include <bits/stdc++.h>   using namespace std;   template <class T>   ostream &operator<<(ostream &out, const vector<T> &data) {     out <<  [ ;     for (int i = 0; i < data.size(); ++i)       out << data[i] << (i == data.size() - 1 ?    :  , );     out <<  ] ;     return out;   }   template <class T>   ostream &operator<<(ostream &out, const set<T> &s) {     out <<  { ;     for (typename set<T>::iterator itr = s.begin(); itr != s.end(); ++itr)       out << *itr <<    ;     out <<  } ;     return out;   }   template <class T>   ostream &operator<<(ostream &out, const multiset<T> &s) {     out <<  { ;     for (typename multiset<T>::iterator itr = s.begin(); itr != s.end(); ++itr)       out << *itr <<    ;     out <<  } ;     return out;   }   template <class T1, class T2>   ostream &operator<<(ostream &out, const pair<T1, T2> &p) {     out <<  (  << p.first <<  ,  << p.second <<  ) ;     return out;   }   template <class T1, class T2>   ostream &operator<<(ostream &out, const map<T1, T2> &m) {     for (typename map<T1, T2>::const_iterator itr = m.begin(); itr != m.end();          ++itr)       out << itr->first <<  ->  << itr->second <<    ;     return out;   }   const double eps = 1e-6;   const double pi = acos(-1.0);   const double INF = 1e20;   inline int sign(double d) { return d < -eps ? -1 : d > eps; }   inline double sqr(double x) { return x * x; }   struct Point {     int id;     double x, y;     Point() {       x = 0.0;       y = 0.0;     }     Point(double nx, double ny) : x(nx), y(ny) {}     Point turnLeft() const { return Point(-y, x); }     Point turnRight() const { return Point(y, -x); }     Point rotate(double ang) const {       return Point(x * cos(ang) - y * sin(ang), x * sin(ang) + y * cos(ang));     }     inline double length() { return sqrt(x * x + y * y); }     void normalize() {       double r = length();       if (sign(r) != 0) x /= r, y /= r;     }     inline bool equal(const Point &other) const {       return sign(x - other.x) == 0 && sign(y - other.y) == 0;     }     friend ostream &operator<<(ostream &out, const Point &point) {       out <<  (  << point.x <<  ,  << point.y <<  ) ;       return out;     }     friend istream &operator>>(istream &in, Point &point) {       in >> point.x >> point.y;       return in;     }   };   bool comPointByX(const Point &a, const Point &b) { return a.x < b.x; }   bool comPointEqual(const Point &a, const Point &b) { return a.equal(b); }   inline Point operator+(const Point &a, const Point &b) {     return Point(a.x + b.x, a.y + b.y);   }   inline Point operator-(const Point &a, const Point &b) {     return Point(a.x - b.x, a.y - b.y);   }   inline Point operator*(const Point &a, double d) {     return Point(a.x * d, a.y * d);   }   inline Point operator/(const Point &a, double d) {     if (sign(d) == 0) return Point();     return Point(a.x / d, a.y / d);   }   inline bool operator==(const Point &a, const Point &b) {     return a.x == b.x && a.y == b.y;   }   inline bool operator!=(const Point &a, const Point &b) {     return a.x != b.x || a.y != b.y;   }   inline double dist(const Point &a, const Point &b) {     return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));   }   inline double sqrdist(const Point &a, const Point &b) {     return sqr(a.x - b.x) + sqr(a.y - b.y);   }   inline double operator^(const Point &a, const Point &b) {     return a.x * b.y - a.y * b.x;   }   inline double cross(const Point &p, const Point &a, const Point &b) {     return (a - p) ^ (b - p);   }   inline double operator*(const Point &a, const Point &b) {     return a.x * b.x + a.y * b.y;   }   inline double dot(const Point &p, const Point &a, const Point &b) {     return (a - p) * (b - p);   }   inline double segDegree(const Point &p, const Point &a, const Point &b) {     double d = dot(p, a, b);     double cosd = d / dist(a, p) / dist(b, p);     if (cosd > 1.0) cosd = 1.0;     if (cosd < -1.0) cosd = -1.0;     return acos(cosd);   }   inline double segDegree(double a, double b, double c) {     double ret = a * a + b * b - c * c;     ret = ret / a / b / 2;     if (ret > 1.0) ret = 1.0;     if (ret < -1.0) ret = -1.0;     return acos(ret);   }   inline double triangleArea(double a, double b, double c) {     double p = (a + b + c) / 2;     return sqrt(p * (p - a) * (p - b) * (p - c));   }   inline bool onSeg(const Point &p, const Point &a, const Point &b) {     return (sign(cross(p, a, b)) == 0 && sign(dot(p, a, b)) <= 0);   }   inline bool onRay(const Point &p, const Point &a, const Point &b) {     return (sign(cross(p, a, b)) == 0 && sign(dot(a, p, b)) >= 0);   }   inline bool onLine(const Point &p, const Point &a, const Point &b) {     return sign(cross(p, a, b)) == 0;   }   pair<Point, Point> onLine(double A, double B, double C) {     if (sign(A) == 0) return make_pair(Point(0, -C / B), Point(1, -C / B));     if (sign(B) == 0) return make_pair(Point(-C / A, 0), Point(-C / A, 1));     if (fabs(A + B + C) < eps)       return make_pair(Point(-(C + B) / A, 1), Point(2, -(C + A * 2) / B));     return make_pair(Point(-(C + B) / A, 1), Point(1, -(C + A) / B));   }   vector<Point> interLine(const Point &a, const Point &b, const Point &c,                           const Point &d) {     vector<Point> inters;     double u = cross(a, c, b), v = cross(a, b, d);     if (sign(u + v) == 0) return inters;     Point p = (c * v + d * u) / (u + v);     inters.push_back(p);     return inters;   }   vector<Point> interSeg(const Point &a, const Point &b, const Point &c,                          const Point &d) {     vector<Point> inters = interLine(a, b, c, d);     if (inters.size() == 0) return inters;     const Point &p = inters[0];     if (onSeg(p, a, b) && onSeg(p, c, d))       return inters;     else {       inters.clear();       return inters;     }   }   pair<Point, Point> getVerticalEquallySegment(const Point &a, const Point &b) {     Point mid = (a + b) / 2;     Point dir = mid - a;     dir = dir.turnLeft();     Point begin = mid - dir;     Point end = mid + dir;     return make_pair(begin, end);   }   Point getMinimumDistPointOnLine(const Point &a, const Point &b,                                   const Point &p) {     if (onLine(p, a, b)) return p;     pair<Point, Point> vertical = getVerticalEquallySegment(a, b);     const Point &q = p + (vertical.second - vertical.first);     vector<Point> inter = interLine(a, b, p, q);     return inter[0];   }   Point getMinimumDistPointOnSeg(const Point &a, const Point &b, const Point &p) {     Point q = getMinimumDistPointOnLine(a, b, p);     if (onSeg(q, a, b)) return q;     if (dist(a, p) < dist(b, p))       return a;     else       return b;   }   Point getMinimumDistPointOnRay(const Point &a, const Point &b, const Point &p) {     Point q = getMinimumDistPointOnLine(a, b, p);     if (onRay(q, a, b)) return q;     if (dist(a, p) < dist(b, p))       return a;     else       return b;   }   Point getReflectionPointByLine(const Point &a, const Point &b, const Point &p) {     Point q = getMinimumDistPointOnLine(a, b, p);     return q * 2 - p;   }   vector<Point> interCir(const Point &a, const Point &b, double r1, double r2) {     vector<Point> ret;     double d = dist(a, b), d1 = ((sqr(r1) - sqr(r2)) / d + d) / 2;     if (sign(r1 + r2 - d) < 0 || sign(abs(r1 - r2) - d) > 0) return ret;     Point mid = a + ((b - a) / d) * d1;     if (sign(r1 + r2 - d) == 0) {       ret.push_back(mid);       return ret;     }     Point incr = (b - a).turnLeft() / d * sqrt(sqr(r1) - sqr(d1));     ret.push_back(mid - incr);     ret.push_back(mid + incr);     return ret;   }   double interCirArea(Point a, Point b, double ra, double rb) {     double d, dA, dB;     d = dist(a, b);     if ((d < eps) || (d + ra <= rb) || (d + rb <= ra))       return sqr((rb < ra) ? rb : ra) * pi;     if (d >= ra + rb) return 0;     dA = (sqr(d) + sqr(ra) - sqr(rb)) / d / 2;     dB = d - dA;     return sqr(ra) * acos(dA / ra) - dA * sqrt(sqr(ra) - sqr(dA)) +            sqr(rb) * acos(dB / rb) - dB * sqrt(sqr(rb) - sqr(dB));   }   vector<Point> interLineCir(const Point &o, double r, const Point &a,                              const Point &b) {     vector<Point> ret;     double d = dist(a, b), h = fabs(cross(a, b, o)) / d;     if (sign(r - h) < 0) return ret;     double d1 = ((sqr(dist(o, a)) - sqr(dist(o, b))) / d + d) / 2;     Point mid = a + (b - a) / d * d1;     if (sign(r - h) == 0) {       ret.push_back(mid);       return ret;     }     Point incr = (b - a) / d * sqrt(sqr(r) - sqr(h));     ret.push_back(mid - incr);     ret.push_back(mid + incr);     return ret;   }   vector<Point> interSegCir(const Point &o, double r, const Point &a,                             const Point &b) {     vector<Point> temp = interLineCir(o, r, a, b);     vector<Point> ret;     for (int i = 0; i < temp.size(); ++i)       if (onSeg(temp[i], a, b)) ret.push_back(temp[i]);     return ret;   }   vector<Point> tangentCirPoint(const Point &o, double r, const Point &a) {     vector<Point> ret;     double d = dist(a, o);     if (sign(d - r) < 0) return ret;     if (sign(r - d) == 0) {       ret.push_back(a);       return ret;     }     return interCir(o, a, r, sqrt(sqr(d) - sqr(r)));   }   inline bool inCircle(const Point &p, const pair<Point, double> &circle) {     double dis = dist(p, circle.first);     return sign(dis - circle.second) <= 0;   }   double distOnCircle(const Point &a, const Point &b, const Point &o, double r) {     double costheta = (a - o) * (b - o) / r / r;     double theta = acos(costheta);     return r * theta;   }   pair<Point, double> minCoverCircle(const Point &a, const Point &b,                                      const Point &c) {     if (a.equal(b)) return make_pair((b + c) / 2, dist(b, c) / 2);     if (b.equal(c)) return make_pair((c + a) / 2, dist(c, a) / 2);     if (c.equal(a)) return make_pair((a + b) / 2, dist(a, b) / 2);     if (onLine(a, b, c)) {       if (onSeg(a, b, c)) return make_pair((b + c) / 2, dist(b, c) / 2);       if (onSeg(b, a, c)) return make_pair((a + c) / 2, dist(a, c) / 2);       return make_pair((a + b) / 2, dist(a, b) / 2);     }     pair<Point, double> minCircle;     minCircle.second = INF;     pair<Point, double> cir1 = make_pair((a + b) / 2, dist(a, b) / 2);     pair<Point, double> cir2 = make_pair((b + c) / 2, dist(b, c) / 2);     pair<Point, double> cir3 = make_pair((a + c) / 2, dist(a, c) / 2);     if (inCircle(c, cir1) && cir1.second < minCircle.second) minCircle = cir1;     if (inCircle(a, cir2) && cir2.second < minCircle.second) minCircle = cir2;     if (inCircle(b, cir3) && cir3.second < minCircle.second) minCircle = cir3;     Point mid1 = (a + b) / 2;     Point mid2 = (b + c) / 2;     Point turn1 = (b - a).turnLeft();     Point turn2 = (c - b).turnLeft();     turn1 = mid1 + turn1;     turn2 = mid2 + turn2;     vector<Point> inters = interLine(mid1, turn1, mid2, turn2);     pair<Point, double> cir4 = make_pair(inters[0], dist(inters[0], a));     if (cir4.second < minCircle.second) minCircle = cir4;     return minCircle;   }   double getCircleTriangleInterArea(const Point &o, double r, const Point &a,                                     const Point &b) {     vector<Point> abcir = interSegCir(o, r, a, b);     if (abcir.size() == 2 && dist(a, abcir[0]) > dist(a, abcir[1]))       swap(abcir[0], abcir[1]);     abcir.insert(abcir.begin(), a);     abcir.push_back(b);     double ret = 0;     for (int i = 0; i < abcir.size() - 1; ++i) {       Point &t1 = abcir[i];       Point &t2 = abcir[i + 1];       if (inCircle((t1 + t2) / 2, make_pair(o, r)))         ret += fabs(cross(o, t1, t2) / 2);       else         ret += segDegree(o, t1, t2) * r * r * 0.5;     }     return ret;   }   class Polygon {    public:     vector<Point> pt;     inline void clear() { pt.clear(); }     inline int size() const { return (int)pt.size(); }     inline void addPoint(Point a) { pt.push_back(a); }     inline void removePoint() { pt.pop_back(); }     inline Point &operator[](int offset) { return pt[offset]; }     inline void getSeg(int offset, Point &a, Point &b) {       a = pt[offset];       b = pt[(offset + 1) % pt.size()];     }     int inside(const Point &p) {       int N = (int)pt.size();       bool positiveSign = false;       bool negativeSign = false;       for (int i = 0; i < N; ++i) {         Point &now = pt[i];         Point &next = pt[(i + 1) % N];         Point t1 = next - now;         Point t2 = p - next;         int s = sign(t1 ^ t2);         if (s == 0) {           if (onSeg(p, now, next))             return 0;           else             return -1;         }         if (s > 0) positiveSign = true;         if (s < 0) negativeSign = true;       }       if (positiveSign && negativeSign)         return -1;       else         return 1;     }     double interCirArea(const Point &o, double r) {       int N = (int)pt.size();       double ret = 0;       for (int i = 0; i < N; ++i) {         Point &now = pt[i];         Point &next = pt[(i + 1) % N];         double area = getCircleTriangleInterArea(o, r, now, next);         if (cross(now, next, o) >= 0)           ret += area;         else           ret -= area;       }       return ret;     }     int interCircle(const Point &o, double r, vector<Point> &inters) {       inters.clear();       bool ok = true;       for (int i = 0; i < pt.size(); ++i)         if (!inCircle(pt[i], make_pair(o, r))) ok = false;       if (ok) return 1;       if (inside(o) == 1) {         double mindis = 1e20;         for (int i = 0; i < pt.size(); ++i) {           Point a = pt[i];           Point b = pt[(i + 1) % pt.size()];           Point p = getMinimumDistPointOnSeg(a, b, o);           mindis = min(mindis, dist(p, o));         }         if (mindis >= r) return 2;       }       for (int i = 0; i < pt.size(); ++i) {         Point a = pt[i];         Point b = pt[(i + 1) % pt.size()];         vector<Point> ps = interSegCir(o, r, a, b);         inters.insert(inters.end(), ps.begin(), ps.end());       }       return inters.size() > 0 ? 3 : 4;     }     Point getMinDistPointInPolygon(const Point &p) {       if (inside(p) >= 0) return p;       int N = (int)pt.size();       double minDis = INF;       Point ret;       for (int i = 0; i < N; ++i) {         Point &a = pt[i];         Point &b = pt[(i + 1) % N];         Point nowMin = getMinimumDistPointOnSeg(a, b, p);         double nowDis = dist(nowMin, p);         if (nowDis < minDis) minDis = nowDis, ret = nowMin;       }       return ret;     }     Polygon cut(const Point &a, const Point &b) {       Polygon newPoly;       Point temp;       for (unsigned int i = 0; i < pt.size(); i++) {         Point &nowP = pt[i];         Point &nextP = pt[(i + 1) % pt.size()];         if (sign(cross(a, b, nowP)) <= 0) newPoly.addPoint(nowP);         if (sign(cross(a, b, nowP)) * sign(cross(a, b, nextP)) < 0) {           vector<Point> inters = interLine(nowP, nextP, a, b);           if (inters.size() > 0) newPoly.addPoint(inters[0]);         }       }       return newPoly;     }     vector<Point> polyInterLine(const Point &a, const Point &b) {       int N = (int)pt.size();       vector<Point> ret;       Point temp;       for (int i = 0; i < N; ++i) {         Point &now = pt[i];         Point &next = pt[(i + 1) % N];         if (sign(cross(a, b, now)) * sign(cross(a, b, next)) <= 0) {           vector<Point> inters = interLine(a, b, now, next);           if (inters.size() > 0) ret.push_back(inters[0]);         }       }       return ret;     }     double area() {       int size = this->size();       if (size <= 2) return 0.0;       addPoint(this->pt[0]);       double ans = 0;       for (int i = 0; i < size; ++i) ans += (pt[i] ^ pt[i + 1]);       removePoint();       return fabs(ans / 2);     }     double length() {       int size = this->size();       addPoint(pt[0]);       double ans = 0;       for (int i = 0; i < size; ++i) ans += dist(pt[i], pt[i + 1]);       removePoint();       return ans;     }     pair<Point, Point> getDiameter() {       if (this->size() == 0) return make_pair(Point(0, 0), Point(0, 0));       if (this->size() == 1) return make_pair(pt[0], pt[0]);       if (this->size() == 2) return make_pair(pt[0], pt[1]);       pair<Point, Point> answer;       double diameter = 0.0;       for (unsigned int i = 0; i < pt.size(); ++i)         for (unsigned int j = i + 1; j < pt.size(); ++j) {           double now = sqrdist(pt[i], pt[j]);           if (now > diameter) {             diameter = now;             answer = make_pair(pt[i], pt[j]);           }         }       return answer;     }     pair<Point, double> getMinCoverCircle() {       vector<Point> &points = pt;       if (points.size() == 0) return make_pair(Point(0, 0), 0);       if (points.size() == 1) return make_pair(points[0], 0);       if (points.size() == 2)         return make_pair((points[0] + points[1]) / 2,                          dist(points[0], points[1]) / 2);       Point a = points[0];       Point b = points[1];       Point c = points[2];       pair<Point, double> nowCircle = minCoverCircle(a, b, c);       while (true) {         bool found = false;         double maxDis = nowCircle.second;         Point maxDisPoint;         for (unsigned int i = 0; i < points.size(); ++i) {           double dis = dist(points[i], nowCircle.first);           if (sign(dis - maxDis) > 0) {             maxDis = dis;             maxDisPoint = points[i];             found = true;           }         }         if (!found) break;         Point d = maxDisPoint;         Point newa, newb, newc;         pair<Point, double> cir1 = minCoverCircle(a, b, d);         pair<Point, double> cir2 = minCoverCircle(a, c, d);         pair<Point, double> cir3 = minCoverCircle(b, c, d);         pair<Point, double> minCircle;         minCircle.second = INF;         if (inCircle(c, cir1) && cir1.second < minCircle.second) {           minCircle = cir1;           c = d;         } else {           if (inCircle(b, cir2) && cir2.second < minCircle.second) {             minCircle = cir2;             b = d;           } else {             if (inCircle(a, cir3) && cir3.second < minCircle.second) {               minCircle = cir3;               a = d;             }           }         }         nowCircle = minCircle;       }       return nowCircle;     }     friend ostream &operator<<(ostream &out, const Polygon &poly) {       int size = poly.size();       for (int i = 0; i < size; ++i) out << poly.pt[i] <<   t ;       return out;     }   };   bool comPs(const pair<Point, int> &a, const pair<Point, int> &b) {     int s = sign(a.first.x - b.first.x);     if (s < 0) return true;     if (s > 0) return false;     return a.second < b.second;   }   double unionArea(vector<Polygon> &polys) {     double ans = 0;     int N = (int)polys.size();     if (N == 0) return ans;     vector<pair<double, double> > lines;     for (int i = 0; i < N; ++i)       for (int j = 0; j < polys[i].size(); ++j) {         Point a, b;         polys[i].getSeg(j, a, b);         if (fabs(a.x - b.x) < eps) continue;         double deg = atan2(b.y - a.y, b.x - a.x);         double bb = a.y - (b.y - a.y) * a.x / (b.x - a.x);         bool close = false;         for (int k = 0; k < lines.size(); ++k)           if (fabs(lines[k].first - deg) < eps &&               fabs(lines[k].second - bb) < eps)             close = true;         if (close) continue;         lines.push_back(make_pair(deg, bb));         vector<pair<Point, int> > ps;         for (int k = 0; k < N; ++k) {           bool isPar = false;           for (int l = 0; l < polys[k].size(); ++l) {             Point c, d;             polys[k].getSeg(l, c, d);             if (fabs(c.x - d.x) < eps) continue;             if (onLine(c, a, b) && onLine(d, a, b)) {               int dir = (c.x < d.x) ? 2 : 1;               if (c.x > d.x) swap(c, d);               ps.push_back(make_pair(c, dir * 2));               ps.push_back(make_pair(d, dir * 2 + 1));               isPar = true;               break;             }           }           if (isPar) continue;           vector<Point> inters;           for (int l = 0; l < polys[k].size(); ++l) {             Point c, d;             polys[k].getSeg(l, c, d);             vector<Point> t = interLine(a, b, c, d);             for (int z = 0; z < t.size(); ++z)               if (onSeg(t[z], c, d)) inters.push_back(t[z]);           }           sort(inters.begin(), inters.end(), comPointByX);           inters.resize(unique(inters.begin(), inters.end(), comPointEqual) -                         inters.begin());           if (inters.size() >= 2) {             ps.push_back(make_pair(inters.front(), 0));             ps.push_back(make_pair(inters.back(), 1));           }         }         sort(ps.begin(), ps.end(), comPs);         int cntPosi = 0, cntNega = 0;         int cntIn = 0;         for (int k = 0; k < ps.size(); ++k) {           double x2 = ps[k].first.x;           double y2 = ps[k].first.y;           double x1 = 0, y1 = 0;           if (k > 0) {             x1 = ps[k - 1].first.x;             y1 = ps[k - 1].first.y;           }           double area = (x2 - x1) * (y2 + y1) / 2;           if (cntPosi > 0 && cntNega == 0 && x2 - x1 > eps && cntIn == 0)             ans += area;           if (cntPosi == 0 && cntNega > 0 && x2 - x1 > eps && cntIn == 0)             ans -= area;           int id = ps[k].second;           if (id == 2) cntPosi++;           if (id == 4) cntNega++;           if (id == 0) cntIn++;           if (id == 3) cntPosi--;           if (id == 5) cntNega--;           if (id == 1) cntIn--;         }       }     return ans;   }   struct ConvexHull {     static inline bool cmp(const Point &a, const Point &b) {       return a.y < b.y || (a.y == b.y && a.x < b.x);     }     static Polygon convexHull(const vector<Point> &points,                               bool needInnerEdgePoint = false) {       vector<Point> p(points.begin(), points.end());       vector<int> stack(p.size() + 1);       Polygon poly;       poly.clear();       if (p.size() == 0) return poly;       if (p.size() == 1) {         poly.addPoint(points[0]);         return poly;       }       sort(p.begin(), p.end(), ConvexHull::cmp);       int threshold = 0;       if (needInnerEdgePoint) threshold = 1;       int N = (int)p.size();       int top = -1;       stack[++top] = 0;       stack[++top] = 1;       for (int i = 2; i < N; i++) {         while (top >= 1 &&                sign(cross(p[stack[top - 1]], p[i], p[stack[top]])) >= threshold)           top--;         stack[++top] = i;       }       int temp_top = top;       stack[++top] = N - 2;       for (int i = N - 3; i >= 0; i--) {         while (top >= temp_top + 1 &&                sign(cross(p[stack[top - 1]], p[i], p[stack[top]])) >= threshold)           top--;         stack[++top] = i;       }       for (int i = 0; i < top; ++i) poly.addPoint(p[stack[i]]);       return poly;     }   };   class HalfPlanes {    public:     Polygon poly;     HalfPlanes(double maxRange) {       poly.addPoint(Point(-maxRange, -maxRange));       poly.addPoint(Point(maxRange, -maxRange));       poly.addPoint(Point(maxRange, maxRange));       poly.addPoint(Point(-maxRange, maxRange));     }     void intersect(const Point &a, const Point &b) { poly = poly.cut(a, b); }     void intersect(double A, double B, double C) {       pair<Point, Point> ab = onLine(A, B, C);       pair<Point, Point> cd = getVerticalEquallySegment(ab.first, ab.second);       Point a = ab.first, b = ab.second, c = cd.first, d = cd.second;       double vc = A * c.x + B * c.y + C;       if (vc > 0) {         if (sign(cross(a, b, c)) > 0) swap(a, b);       } else {         if (sign(cross(a, b, d)) > 0) swap(a, b);       }       poly = poly.cut(a, b);     }     void intersect(const Point &a, const Point &b, const Point &c) {       if (sign(cross(a, b, c)) <= 0)         poly = poly.cut(a, b);       else         poly = poly.cut(b, a);     }   };   class Voronoy {    public:     vector<Point> ps;     vector<HalfPlanes> planes;     Voronoy(vector<Point> &points, double maxRange) {       int N = (int)points.size();       ps = points;       planes.resize(N, HalfPlanes(maxRange));       for (int i = 0; i < N; ++i)         for (int j = i + 1; j < N; ++j) {           pair<Point, Point> v = getVerticalEquallySegment(ps[i], ps[j]);           planes[i].intersect(v.first, v.second, ps[i]);           planes[j].intersect(v.first, v.second, ps[j]);         }     }   };   struct Point3D {     double x, y, z;     Point3D() {}     Point3D(double xx, double yy, double zz) {       x = xx;       y = yy;       z = zz;     }     double len() { return sqrt(x * x + y * y + z * z); }   };   Point3D operator+(const Point3D &a, const Point3D &b) {     return Point3D(a.x + b.x, a.y + b.y, a.z + b.z);   }   Point3D operator-(const Point3D &a, const Point3D &b) {     return Point3D(a.x - b.x, a.y - b.y, a.z - b.z);   }   double dist(const Point3D &a, const Point3D &b) {     return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y) + sqr(a.z - b.z));   }   double dot(const Point3D &a, const Point3D &b) {     return a.x * b.x + a.y * b.y + a.z * b.z;   }   Point3D cross(const Point3D &u, const Point3D &v) {     Point3D ret;     ret.x = u.y * v.z - v.y * u.z;     ret.y = u.z * v.x - u.x * v.z;     ret.z = u.x * v.y - u.y * v.x;     return ret;   }   Point3D planeVector(const Point3D &a, const Point3D &b, const Point3D &c) {     return cross(a - b, b - c);   }   double distToPlane(const Point3D &p, const Point3D &s1, const Point3D &s2,                      const Point3D &s3) {     Point3D plane = planeVector(s1, s2, s3);     return dot(plane, p - s1) / plane.len();   }   Point ps[4];   Point a, b, c, d;   class State {    public:     double x, y, z;     State operator+(const State &other) {       State ret;       ret.x = x + other.x;       ret.y = y + other.y;       ret.z = z + other.z;       return ret;     }     State operator-(const State &other) {       State ret;       ret.x = x - other.x;       ret.y = y - other.y;       ret.z = z - other.z;       return ret;     }     State operator*(double k) {       State ret;       ret.x = x * k;       ret.y = y * k;       ret.z = z * k;       return ret;     }     friend ostream &operator<<(ostream &out, const State &state) {       out << state.x <<     << state.y <<     << state.z;       return out;     }   };   double func(const State &s) {     Point p(s.x, s.y);     double ret = dist(Point(0, 0), p);     ret += dist(getMinimumDistPointOnLine(c, d, p), p);     return ret;   }   class GoldSplitSearch {    public:     static State findMinimum(State &begin, State &end,                              double (*func)(const State &s)) {       const double tou = (sqrt(5.0) - 1) / 2;       State a = begin;       State b = end;       for (int k = 0; k < 200; ++k) {         State x1 = a + (b - a) * (1 - tou);         State x2 = a + (b - a) * tou;         double f1 = func(x1);         double f2 = func(x2);         if (f1 > f2)           a = x1;         else           b = x2;       }       return a;     }   };   double getAns(Point aa, Point bb, Point cc, Point dd) {     c = cc;     d = dd;     double scale = 100000 / (bb - aa).length();     Point na = (aa - bb) * scale + bb;     Point nb = (bb - aa) * scale + aa;     State begin;     begin.x = na.x;     begin.y = na.y;     State end;     end.x = nb.x;     end.y = nb.y;     State s = GoldSplitSearch::findMinimum(begin, end, func);     return func(s);   }   int N;   vector<Polygon> polys;   void init() {     double ans = 0;     cin >> N;     polys.clear();     for (int i = 0; i < N; ++i) {       vector<Point> ps(4);       for (int j = 0; j < 4; ++j) cin >> ps[j];       Polygon poly = ConvexHull::convexHull(ps);       polys.push_back(poly);       ans += poly.area();     }     ans = ans / (unionArea(polys));     printf( %.10f n , ans);   }   void york() {}   int main() {     init();     york();     return 0;   }