#include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;

typedef complex<double> P;
P pIN() { double x,y; cin >> x >> y; return P(x,y); }
namespace std {
  bool operator<(const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
  bool operator==(const P& a, const P &b) {
    return abs(a-b)<EPS;
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (EPS < norm(b) && norm(b) < norm(c)-EPS) return -2; // a--b--c on line
  return 0;
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() { resize(2); }
};
ostream &operator<<(ostream &os, const L &a) {
  os << a[0] << " -> " << a[1];
  return os;
}
typedef vector<P> G;
#define curr(g, i) g[i]
#define next(g, i) g[(i+1)%g.size()]
L line(const G &g, int i) {
  return L(g[i],g[(i+1)%g.size()]);
}
typedef int Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
double angle(const P &a, const P &b) {
  double ret = arg(b)-arg(a);
  return (ret>=0) ? ret : ret + 2*PI;
}
double area2(const G &g) {
  double A = 0;
  for (int i = 0; i < g.size(); ++i) {
    A += cross(g[i], next(g, i));
  }
  return A;
}

// PSLGが与えられたとき，極小サイクルの集合を取得
G getHolesSub(const Graph &g, const vector<P> &ps, int a, int b, map<pii,bool> &visited) {
  G res;
  int pre = a;
  int cur = b;
  res.push_back(ps[a]);
  while(cur != a) {
    visited[pii(pre,cur)] = 1;
    res.push_back(ps[cur]);
    P vec = ps[pre]-ps[cur];
    double minang = -1;
    int dst = -1;
    FOR(it, g[cur]) {
      double tang = angle(vec, ps[it->dst]-ps[cur]);
      if (chmax(minang, tang)) {
        dst = it->dst;
      }
    }
    if (dst == -1) return G();
    pre = cur;
    cur = dst;
  }
  visited[pii(pre,cur)] = 1;
  if (area2(res) > EPS) return res;
  return G();
}
vector<G> getHoles(const Graph &g, const vector<P> &ps) {
  map<pii, bool> visited;
  vector<G> ret;
  REP(i,g.size()) {
    FOR(it, g[i]) {
      if (visited.count(pii(it->src,it->dst))) continue;
      G t = getHolesSub(g, ps, it->src, it->dst, visited);
      if (t.size()) ret.push_back(t);
    }
  }
  return ret;
}

bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSS2(const L &s, const L &t) { // 接しているやつは交差と考えない
  REP(i, 2) {
    if (ccw(s[0], s[1], t[i]) == 0) {
      int c = ccw(s[0],s[1],t[!i]);
      if (s[0] == t[i]) {
        if (c!=-2&&c) return 0;
      } else if (s[1] == t[i]) {
        if (c!=2&&c) return 0;
      } else if (abs(c)==1) return 0;
    }
  }
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0];// same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

Graph segmentArrangement(const vector<L> &ss, vector<P> &ps) {
  int n = ss.size();
  REP(i,n) {
    ps.push_back( ss[i][0] );
    ps.push_back( ss[i][1] );
    for (int j = i+1; j < (int)ss.size(); ++j)
      if (intersectSS(ss[i], ss[j]))
        ps.push_back( crosspoint(ss[i], ss[j]) );
  }
  sort(ALL(ps)); ps.erase(unique(ALL(ps)), ps.end());

  Graph g(ps.size());
  REP(i,ss.size()) {
    int pre = -1;
    REP(j,ps.size()) {
      if (intersectSP(ss[i], ps[j])) {
        if (pre != -1) {
          double d = abs(ps[pre]-ps[j]);
          g[pre].push_back(Edge(pre,j,d));
          g[j].push_back(Edge(j,pre,d));
        }
        pre = j;
      }
    }
  }
  return g;
}

double area(const G &g) {
  return abs(area2(g)/2);
}

P p[100];

int main() {
  int n;
  while(cin >> n) {
    vector<L> ss;
    REP(i,n) {
      cin >> p[i].real() >> p[i].imag();
      if (i) {
        ss.push_back(L(p[i-1],p[i]));
      }
    }
    vector<P> ps;
    Graph g = segmentArrangement(ss, ps);
    vector<G> v = getHoles(g,ps);
    double ans = 0;
    FOR(it, v) {
      ans += area(*it);
    }
    printf("%.10f\n", ans);
  }
}

Measured memory_bytes: 2588