#include #include #include #include #include #include using namespace std; typedef pair PDD; typedef vector VPDD; PDD operator + (PDD a, PDD b) { return PDD(a.first + b.first, a.second + b.second); } PDD operator - (PDD a, PDD b) { return PDD(a.first - b.first, a.second - b.second); } PDD operator * (PDD a, double b) { return PDD(a.first * b, a.second * b); } double dot(PDD a, PDD b) { return a.first * b.first + a.second * b.second; } double xpr(PDD a, PDD b) { return a.second * b.first - a.first * b.second; } PDD norm(PDD x) { return PDD(x.second, -x.first); } ostream &operator << (ostream &out, const PDD &x) { return out << '(' << setprecision(2) << x.first << ',' << setprecision(2) << x.second << ')'; } #define EPS 1e-6 int main(void) { int cases; cin >> cases; for (int casei = 1; casei <= cases; ++casei) { int n; cin >> n; VPDD pts; for (int i = 0; i < n; ++i) { double x, y; cin >> x >> y; pts.push_back(PDD(x, y)); } // trick to make wrap-around work without needing mod pts.push_back(pts[0]); double area = 0.0; for (int i = 0; i < n; ++i) { PDD a = pts[i], b = pts[i+1]; // range of line which is included in final shape double lo = -1e9; double hi = +1e9; for (int j = 0; j < n; ++j) { if (i == j) continue; PDD c = pts[j], d = pts[j+1]; // direction of crossing double dir = dot(norm(b-a), d-c); // s at point of intersection (or NaN if parallel) double s = xpr(d-c, a-c) / xpr(b-a, d-c); if (abs(dir) < EPS) { // parallel lines double pdir = dot(b-a, d-c); // +ve if same direction double side = dot(norm(b-a), d-a); // +ve if right // excluded by same dir to the right or opposite // dir to the left. if (pdir * side > EPS) lo = 1e9; } else if (dir > 0) { // crossing from left to right hi = min(hi, s); } else { // crossing from right to left lo = max(lo, s); } } if (lo < hi) { // if there is some line left, add it to the area area += xpr(a + (b-a) * lo, a + (b-a) * hi) * 0.5; } } // print the final area printf("%0.2lf\n", area); } return 0; }