#include #include #include #include #include #include #include #include #define EPSILON (1e-12) #define LT(x,y) (((x)-(y)) <= -EPSILON) #define NE(x,y) (fabs((x)-(y)) >= EPSILON) #define foreach(T,p,c) for(T p = (c).begin(); p != (c).end(); p++) #define UPDOWN(b0,b1) (((b0)<(b1)) ? UP : DOWN) using namespace std; //////////////////////////////////////////////////////////////////////////// enum type_t { THRU, DOWN, UP, HORIZONTAL }; struct point_t { double a, a_other; type_t type; public: point_t(void) { } point_t(double a, double o, type_t t) : a(a), a_other(o), type(t) { } }; typedef map< double, vector > data_t; //////////////////////////////////////////////////////////////////////////// bool operator <(const point_t &p1, const point_t &p2) { if(NE(p1.a, p2.a)) return LT(p1.a, p2.a); return LT(p1.a_other, p2.a_other); } double dist(double a1, double b1, double a2, double b2) { return sqrt((a2-a1) * (a2-a1) + (b2-b1) * (b2-b1)); } double solve(const vector &a, const vector &b) { int n = min(a.size(), b.size()); data_t data; for(int i = 0; i < n; i++) { data.insert(make_pair( b[i], vector() )); } // create data foreach(data_t::iterator, p, data) { double b0 = p->first; for(int i = 0; i < n; i++) { int j = (i + 1) % n; if(b[i] == b0 && b[j] == b0) { double ai = min(a[i], a[j]); double aj = max(a[i], a[j]); p->second.push_back( point_t(ai, aj, HORIZONTAL) ); continue; } if(b[i] == b0) { p->second.push_back( point_t(a[i], a[j], UPDOWN(b0, b[j])) ); continue; } if(b[j] == b0) { p->second.push_back( point_t(a[j], a[i], UPDOWN(b0, b[i])) ); continue; } if((b[i] < b0 && b0 < b[j]) || (b[j] < b0 && b0 < b[i])) { double a0 = a[i] + (a[j] - a[i]) * (b0 - b[i]) / (b[j] - b[i]); p->second.push_back( point_t(a0, a0, THRU) ); continue; } } } foreach(data_t::iterator, p, data) { sort(p->second.begin(), p->second.end()); } double S = 0.0; // non-horizontal parts foreach(data_t::iterator, p, data) { data_t::iterator q = p; if(++q == data.end()) break; double bp = p->first; double bq = q->first; vector::iterator pv = p->second.begin(); vector::iterator qv = q->second.begin(); double x = 0.0; double h = 0.0; while(pv != p->second.end() && qv != q->second.end()) { while(pv->type == DOWN || pv->type == HORIZONTAL) ++pv; while(qv->type == UP || qv->type == HORIZONTAL) ++qv; double a0p = (pv++)->a; double a0q = (qv++)->a; while(pv->type == DOWN || pv->type == HORIZONTAL) ++pv; while(qv->type == UP || qv->type == HORIZONTAL) ++qv; double a1p = (pv++)->a; double a1q = (qv++)->a; x += (a1p - a0p) + (a1q - a0q); h += dist(a0p, bp, a0q, bq) + dist(a1p, bp, a1q, bq); } S += x * h; } // horizontal parts foreach(data_t::iterator, p, data) { double xe = 0.0; double xp = 0.0; double a_left = HUGE_VAL; bool upper = false; bool lower = false; foreach(vector::iterator, pv, p->second) { if(pv->type == HORIZONTAL) { xp += pv->a_other - pv->a; continue; } switch(pv->type) { case THRU: upper = !upper; lower = !lower; break; case UP: upper = !upper; break; case DOWN: lower = !lower; break; } if(a_left == HUGE_VAL) { assert(upper || lower); a_left = pv->a; } if(!upper && !lower) { xe += pv->a - a_left; a_left = HUGE_VAL; } } S += 2 * xp * xe - xp * xp; } // I really wonder if this code is correct return S; } int main(void) { ifstream cin("I.txt"); int n; while(cin >> n) { if(n == 0) break; vector a(n), b(n); for(int i = 0; i < n; i++) cin >> a[i] >> b[i]; // cout << fixed << setprecision(4) << solve(a, b) << endl; cout << setprecision(13) << solve(a, b) << endl; } }