#include #include #include #include #include using namespace std; // geometric data structures and algorithms static const double EPS = 1e-10; typedef complex Point; typedef pair LineSeg; double outer(Point p, Point q) { return imag(conj(p)*q); } double inner(Point p, Point q) { return p.real()*q.real()+p.imag()*q.imag(); } bool cross( const LineSeg& ls1, const LineSeg& ls2, double* ps ) { Point p1=ls1.first, d1=ls1.second-ls1.first; Point p2=ls2.first, d2=ls2.second-ls2.first; double f = outer(d1,d2); if( abs(f) == 0 ) { if( abs(outer(p2-p1, d1)) < EPS ) { double a = inner( (p2-p1), d1 ) / abs(d1); double b = inner( (p2+d2-p1), d1 ) / abs(d1); assert( b<0 || 1 EPS ); assert( min(abs(t), abs(t-1)) > EPS ); *ps = s; return true; } // graph data structures and algorithms typedef pair Vert; typedef map > Graph; Vert make_vert(int i, int j) { return i& ls ) { Graph G; // First, construct the graph over crossing points for(int i=0; i!=ls.size(); ++i) { // enumerate all crossing points on ls[i] vector< pair > cross_pts; for(int j=0; j!=ls.size(); ++j) if( j != i ) { double p; if( cross(ls[i], ls[j], &p) ) cross_pts.push_back( make_pair(p,j) ); } // sort them sort( cross_pts.begin(), cross_pts.end() ); { for(int j=1; j EPS ); } // adjacent points are connected for(int j=1; jsecond.size(); ++j) for(int k=0; k!=G[it->second[j]].size(); ++k) for(int l=0; l!=G[G[it->second[j]][k]].size(); ++l) if( it->first == G[G[it->second[j]][k]][l] ) ++count; return count/6; } int main() { int T; cin >> T; while( T-- ) { // Input vector lines; { int N; cin >> N; assert( 1 < N && N <= 500 ); while( N-- ) { int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; assert( -10000 < x1 && x1 < 10000 ); assert( -10000 < y1 && y1 < 10000 ); assert( -10000 < x2 && x2 < 10000 ); assert( -10000 < y2 && y2 < 10000 ); lines.push_back( LineSeg(Point(x1,y1), Point(x2,y2)) ); } } // Solve & Output cout << solve(lines) << endl; } }