1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include<bits/stdc++.h>
#define rep(i,k,n) for(ll i= (ll) k;i< (ll) n;i++)
#define all(v) (v).begin(), (v).end()
#define SZ(v) (ll)((v).size())
#define pb push_back
#define ft first
#define sd second
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const long long INF = 1e18L + 1;
const int IINF = 1e9 + 1;

using namespace std;

template<class TH> void _dbg(const char *sdbg, TH h){ cerr<<sdbg<<'='<<h<<endl; }
template<class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
  while(*sdbg!=',')cerr<<*sdbg++;
  cerr<<'='<<h<<','; _dbg(sdbg+1, a...);
}

#ifdef LOCAL
#define DBG(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#else
#define DBG(...) (__VA_ARGS__)
#define cerr if(0)cout
#endif

typedef long double R;
typedef complex<R> C;

typedef long long RL;
typedef complex<RL> CL;

#define x real()
#define y imag()

const R eps = 1e-16;

bool eq(R r1, R r2) { return abs(r1 - r2) < eps; }

bool eq(const C& c1,const C& c2) { return eq(c1.x, c2.x) and eq(c1.y, c2.y); }

R dot(const C& c1, const C& c2) { return c1.x * c2.x + c1.y * c2.y;}
R det(const C& c1, const C& c2) { return c1.x * c2.y - c1.y * c2.x;}

RL dot(const CL& c1, const CL& c2) { return c1.x * c2.x + c1.y * c2.y;}
RL det(const CL& c1, const CL& c2) { return c1.x * c2.y - c1.y * c2.x;}

C to_C(const CL& cl){ return C(cl.x, cl.y);}

struct line{
	CL nl;
    RL cl;
	C n, d;
    R c;
    line() = default;
    line(CL p1, CL p2)
        :nl{(p2 - p1) * CL(0, 1)}, cl{dot(p1, nl)}, n{to_C(nl) / abs(to_C(nl))}, d{n.y, -n.x}, c{dot(to_C(p1), n)} {}

   	bool operator <(const line& other) const {
        RL de = det(nl, other.nl);
        if(de == 0){
            return c > other.c;
        } else {
            return de > 0;
        }
    }
	
	C val(R t) const { return c * n + t * d;}

	R tis(const line& other) const {
		return (other.c - c * dot(n, other.n)) / dot(d, other.n);
	}
};

ostream& operator <<(ostream& o, const line& l){ return o << l.n << " " << l.c;}

C is(const line& a, const line& b) { return a.val(a.tis(b));}


namespace hplane{
    const int N = 200000;
    line lns[2 * N + 1];
    C poly[2 * N + 1];
    int jd1, jd2, ju1, ju2, ans_sz, poly_sz, n = 0;
    inline int cnt(){ return ju2 + jd2 - ju1 - jd1 + 2; }
    void add(const line& l){ lns[n++] = l;}
    void clear(){ n = 0;}

    bool empty_is(const line& l1, const line& l2) { return det(l1.nl, l2.nl) == 0 and dot(l1.nl, l2.nl) < 0 and l1.c + eps > -l2.c;}
    
    bool wrong(const line& l_prev, const line& l_last, const line& l_new) { 
        if(det(l_last.nl, l_new.nl) != 0) {
            return l_last.tis(l_new) < l_last.tis(l_prev) + eps;
        } else {
            return false;
        }
    }

    int cor(int j1, int j2){
        sort(lns + j1, lns + j2 + 1);
        j2 = unique(lns + j1, lns + j2 + 1, [](line& l1, line& l2){ return dot(l1.nl, l2.nl) > 0 and det(l1.nl, l2.nl) == 0;}) - lns - 1;
        int j = min(j1 + 1, j2);
        rep(i, j1 + 2, j2 + 1){
            j++;
            while(j >= j1 + 2 and wrong(lns[j - 2], lns[j - 1], lns[i])){
                j--;        
            }
            lns[j] = lns[i]; 
        }
        return j;
    }

    void c_front(int& j1, int& j2, int& j3){
        while((j3 - j2) >= 1 and wrong(lns[j1], lns[j2], lns[j2 + 1])) j2++;
    }
    void c_back(int& j1, int& j2, int& j3){
        while((j2 - j1) >= 1 and wrong(lns[j2 - 1], lns[j2], lns[j3])) j2--;
    }
    void solve(){
        ju1 = partition(lns, lns + n, [](const line& l){ return det(CL(1, 0), l.nl) > 0 or (l.nl.y == 0 and l.nl.x < 0);}) - lns;
        ju2 = n - 1;
        jd1 = 0; jd2 = ju1 - 1;
        jd2 = cor(jd1, jd2); ju2 = cor(ju1, ju2);
        int chck = 0;
        while(chck != cnt() and (jd2 - jd1) >= 0 and (ju2 - ju1) >= 0 and ((jd2 - jd1) >= 1 or (ju2 - ju1) >= 1)){
            if(empty_is(lns[jd1], lns[ju2]) or empty_is(lns[ju1], lns[jd2])){
                ans_sz = 0; return;
            }
            chck = cnt();
            c_front(jd2, ju1, ju2);
            c_back(ju1, ju2, jd1);
            c_front(ju2, jd1, jd2);
            c_back(jd1, jd2, ju1);
        }
        rep(i, jd1, jd2 + 1){
            lns[i - jd1] = lns[i];
        }
        rep(i, ju1, ju2 + 1){
            lns[jd2 + 1 - jd1 + i - ju1] = lns[i];
        }
        ans_sz = cnt();
    }

    void get_poly(){
        if(ans_sz > 2){
            poly_sz = ans_sz;
            rep(i, 0, ans_sz){
                poly[i] = is(lns[i], lns[(i + 1) % ans_sz]);
            }
        } else {
            poly_sz = 0;
        }
    }
}

R triangle_area(C v1, C v2, C v3){ return fabs(det(v2 - v1, v2 - v3)) / 2.0; }

const ll M = 100;

CL mages[M + 1][2];

int main()
{
#ifndef LOCAL
	ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif
	ll n; cin >> n;
	rep(i, 0, n){
		rep(j, 0, 2){
			ll xx, yy; cin >> xx >> yy;
			mages[i][j] = CL(xx, yy);
		}
	}
	rep(i, 0, n){
		rep(ii, 0, 2){
			rep(j, 0, n){
				if(j != i){
					rep(jj, 0, 2){
						line ll1(mages[i][ii], mages[j][jj]), ll2(mages[j][jj], mages[i][ii]);
						for(auto l : {ll1, ll2}){
							bool both_off = false;
							rep(k, 0, n){
								if(k != i and k != j){
									if(dot(l.nl, mages[k][0]) < l.cl and dot(l.nl, mages[k][1]) < l. cl){
										both_off = true;
									}
								}
							}
							if(!both_off){
								hplane::add(l);
							}
						}
					}
				}
			}
		}
	}
	hplane::solve();
	hplane::get_poly();
	R res = 0;
	rep(i, 1, hplane::poly_sz - 1){
		res += triangle_area(hplane::poly[0], hplane::poly[i], hplane::poly[i + 1]);
	}
	cout << setprecision(15) << fixed << res << "\n";
    return 0;
}