#include <bits/stdc++.h>
using namespace std;
const double EPS = 1e-9;
const double INF = 1e6;
const double PI = atan2(0, -1);
const int maxn = 550;
inline int sgn(double x) {
  if (fabs(x) < EPS) return 0;
  return x < 0 ? -1 : 1;
}
inline int iseq(double x, double y) { return sgn(x - y) == 0; }
struct Point {
  double x, y;
  Point(double x = 0, double y = 0) : x(x), y(y) {}
  double Angle() { return atan2(y, x); }
};
inline Point operator+(Point A, Point B) { return Point(A.x + B.x, A.y + B.y); }
inline Point operator-(Point A, Point B) { return Point(A.x - B.x, A.y - B.y); }
inline Point operator*(double x, Point A) { return Point(x * A.x, x * A.y); }
inline double operator*(Point A, Point B) { return A.x * B.x + A.y * B.y; }
inline double operator%(Point A, Point B) { return A.x * B.y - A.y * B.x; }
inline double Length2(Point A) { return A * A; }
inline double Length(Point A) { return sqrt(A * A); }
inline double Distance2(Point A, Point B) { return Length2(A - B); }
inline double Distance(Point A, Point B) { return Length(A - B); }
inline bool operator==(Point A, Point B) { return iseq(Distance(A, B), 0); }
inline bool operator<(Point A, Point B) {
  return iseq(A.x, B.x) ? sgn(A.y - B.y) == -1 : sgn(A.x - B.x) == -1;
}
struct Line {
  Point P, Q;
  Line() {}
  Line(Point A, Point B) {
    P = A;
    Q = B;
  }
  Point Direction() { return Q - P; }
};
inline int IsOnLine(Point P, Line l) { return sgn((l.P - P) % (l.Q - P)) == 0; }
inline int IsOnSegment(Point P, Line l) {
  if (P == l.P || P == l.Q) return 1;
  return sgn((l.P - P) % (l.Q - P)) == 0 && sgn((l.P - P) * (l.Q - P)) <= 0;
}
inline bool IsSegmentOverlap(Line A, Line B) {
  if (iseq(A.Direction() % B.Direction(), 0))
    return IsOnSegment(A.P, B) + IsOnSegment(A.Q, B) + IsOnSegment(B.P, A) +
               IsOnSegment(B.Q, A) >=
           2;
  else
    return false;
}
inline bool IsSegmentIntersected(Line A, Line B) {
  if (IsOnSegment(A.P, B) || IsOnSegment(A.Q, B)) return true;
  if (IsOnSegment(B.P, A) || IsOnSegment(B.Q, A)) return true;
  int sgn1 = sgn((A.P - B.P) % B.Direction()),
      sgn2 = sgn((A.Q - B.P) % B.Direction());
  int sgn3 = sgn((B.P - A.P) % A.Direction()),
      sgn4 = sgn((B.Q - A.P) % A.Direction());
  return sgn1 * sgn2 == -1 && sgn3 * sgn4 == -1;
}
inline Point getLineIntersection(Line A, Line B) {
  Point v = A.Direction(), w = B.Direction();
  Point u = B.P - A.P;
  return A.P + ((w % u) / (w % v)) * v;
}
int n;
vector<Point> Rect[maxn];
double area1, area2;
inline double getPolygonArea(const vector<Point> &A) {
  double ans = 0;
  for (auto j = 1u; j + 1 < A.size(); ++j)
    ans += (A[j] - A[0]) % (A[j] - A[0]) * 0.5;
  return ans;
}
inline bool IsInPolygon(Point P, const vector<Point> &A) {
  double area1 = getPolygonArea(A), area2 = 0.0;
  for (auto j = 0u; j + 1 < A.size(); ++j)
    area2 += (A[j] - P) % (A[j + 1] - P) * 0.5;
  return iseq(area1, area2);
}
inline bool IsPolygonOverlap(vector<Point> P[], int i, int j) {
  int sgn = 1;
  for (auto k = 0u; k < P[i].size(); ++k)
    if (!IsInPolygon(P[i][k], P[j])) {
      sgn = 0;
      break;
    }
  if (!sgn) return false;
  if (iseq(getPolygonArea(P[i]), getPolygonArea(P[j]))) return i < j;
  return true;
}
struct info {
  Point P;
  double ang;
  int delta;
  info() {}
  info(Point x, double y, int z) {
    P = x;
    ang = y;
    delta = z;
  }
};
inline int operator<(const info &A, const info &B) {
  if (iseq(A.ang, B.ang))
    return A.delta > B.delta;
  else
    return A.ang < B.ang;
}
inline double getPosition(Point P, Line l) {
  return ((P - l.P) * l.Direction()) / (l.Direction() * l.Direction());
  return (P.x - l.P.x) / (l.Q.x - l.P.x);
}
double ans[maxn];
double getAreaUnion(vector<Point> P[], int n, double *ans) {
  for (int i = 1; i <= n; ++i) ans[i] = 0.0;
  static vector<pair<double, int>> PointList;
  double aans = 0;
  for (int i = 1; i <= n; ++i)
    for (auto j = 0u; j + 1 < P[i].size(); ++j) {
      Line A(P[i][j], P[i][j + 1]);
      PointList.clear();
      for (int k = 1; k <= n; ++k)
        if (i != k)
          for (auto w = 0u; w + 1 < P[k].size(); ++w) {
            Line B(P[k][w], P[k][w + 1]);
            int p1 = -sgn((B.P - A.P) % A.Direction());
            int p2 = -sgn((B.Q - A.P) % A.Direction());
            if (!p1 && !p2) {
              if (i < k && sgn(A.Direction() * B.Direction()) == 1) {
                PointList.push_back(
                    make_pair(min(1.0, max(getPosition(B.P, A), 0.0)), 1));
                PointList.push_back(
                    make_pair(min(1.0, max(getPosition(B.Q, A), 0.0)), -1));
              }
            } else {
              Point tp = getLineIntersection(A, B);
              if (p1 >= 0 && p2 < 0)
                PointList.push_back(
                    make_pair(min(1.0, max(getPosition(tp, A), 0.0)), 1));
              if (p1 < 0 && p2 >= 0)
                PointList.push_back(
                    make_pair(min(1.0, max(getPosition(tp, A), 0.0)), -1));
            }
          }
      PointList.push_back(make_pair(0.0, 1));
      PointList.push_back(make_pair(1.0, -1));
      sort(PointList.begin(), PointList.end());
      double S0 = A.P % A.Q * 0.5;
      double lst = 0;
      int now = 0;
      for (auto l = 0u, r = 0u; l < PointList.size();) {
        ans[now] += S0 * (PointList[l].first - lst);
        lst = PointList[l].first;
        for (r = l + 1; r < PointList.size() && iseq(PointList[r].first, lst);
             ++r)
          ;
        for (auto w = l; w < r; ++w) now += PointList[w].second;
        l = r;
      }
    }
  return ans[1];
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= 4; ++j) {
      Point P;
      scanf("%lf%lf", &P.x, &P.y);
      Rect[i].push_back(P);
    }
    if (sgn((Rect[i][1] - Rect[i][0]) % (Rect[i][2] - Rect[i][0])) == -1)
      reverse(Rect[i].begin(), Rect[i].end());
    area1 += (Rect[i][1] - Rect[i][0]) % (Rect[i][3] - Rect[i][0]);
    Rect[i].push_back(Rect[i][0]);
  }
  area2 = getAreaUnion(Rect, n, ans);
  printf("%.10lf\n", area1 / area2);
  return 0;
}
