#include<cstdio> #include<cstring> #include<vector> #include<queue> #include<iostream> #include<algorithm> #include<cmath> using namespace std; const double eps = 1e-6; const int MAXN = 20010; const double lim = 10000; const double PI = acos(-1.0); int n, m; inline int cmp(double x) { if (x > eps)return 1; return x < -eps ? -1 : 0; } struct V { double x, y; double ang; double angle() {//求取极角 return atan2(y, x); } V(double X = 0, double Y = 0) { //初始化 x = X, y = Y; ang = atan2(y, x); } bool operator ==(const V &b) { return cmp(x-b.x)&&cmp(y-b.y); } }; typedef V P; V operator +(V a, V b) { return V(a.x + b.x, a.y + b.y); } V operator -(V a, V b) { return V(a.x - b.x, a.y - b.y); } V operator *(V a, double b) { return V(a.x *b, a.y*b ); } V operator /(V a, double b) { return V(a.x /b, a.y/b ); } struct L { P s, t; double ang; L(P X = V(), P Y = V()) { s = X, t = Y, ang = (Y - X).angle(); } }; typedef L S; double cross(V a, V b) { return a.x*b.y - a.y*b.x; } bool operator <(const L &a, const L &b) { double r = a.ang - b.ang; if (cmp(r) != 0) return cmp(r) == -1; //极角相同,默认偏下的更大 return cmp(cross(a.t - a.s, b.t - a.s)) == -1; } double dot(V a, V b) { return a.x*b.x + a.y*b.y; } bool is_parallel(L a, L b) { return cmp(cross(a.t - a.s, b.t - b.s)) == 0; } P intersection(L a, L b) { return a.s + (a.t - a.s)*(cross(b.t - b.s, a.s-b.s)) / cross(a.t - a.s, b.t - b.s); } double area(P *p, int n) { double res = 0; p[n + 1] = p[1]; for (int i = 1; i <= n; i++) res += cross(p[i], p[i + 1]); return fabs(res / 2); } bool is_right(L a, P b) //判断点b是否在直线的右边(和起点连成的向量方向和直线向量方向相反) { return cmp(cross(a.t - a.s, b - a.s)) < 0; } bool SI(L *l, int n, P *s, int &m) //增量法求半平面交 { static L que[MAXN]; static P que2[MAXN]; int head = 0, tail = 0; sort(l + 1, l + 1 + n); que[head]=l[1]; for (int i = 2; i <= n; i++) { if (cmp(l[i].ang - l[i - 1].ang)) { if (head<tail && (is_parallel(que[head], que[head + 1]) || is_parallel(que[tail], que[tail - 1]))) //若两个直线共线,但是极角不同,则没有半平面交 return false; while (head < tail&&is_right(l[i], que2[tail - 1])) tail--; while (head < tail&&is_right(l[i], que2[head ])) head++; que[++tail] = l[i]; if (head < tail) que2[tail - 1] = intersection(que[tail],que[tail-1]); } } while (head < tail&&is_right(que[head], que2[tail-1])) tail--; while (head < tail&&is_right(que[tail], que2[head ])) head++; if (tail - head <= 1) return false; que2[tail] = intersection(que[head], que[tail]); m = 0; for (int i = head; i <= tail; i++) s[++m] = que2[i]; return true; } P p[MAXN]; L l[MAXN]; double solve() //求取半平面交的面积 //SI函数计算结果只是得到了半平面交的多边形数组 { P a = P(0, 0), b = P(lim, 0), c = P(lim, lim), d = P(0, lim); l[++n] = L(a, b); l[++n] = L(b, c); l[++n] = L(c, d); l[++n] = L(d, a); if (!SI(l, n, p, m)) return 0; return area(p, m); } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { P a, b; scanf("%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y); //直线方向,从起点指向终点 //向量表示,终点减去起点 l[i] = L(a, b); } printf("%.1f", solve()); return 0; }