#include<iostream> #include<sstream> #include<string> #include<vector> #include<list> #include<set> #include<map> #include<stack> #include<queue> #include<algorithm> #include<numeric> #include<cmath> #pragma warning(disable:4996) using std::cin; using std::cout; using std::endl; using std::stringstream; using std::string; using std::vector; using std::list; using std::pair; using std::set; using std::multiset; using std::map; using std::multimap; using std::stack; using std::queue; using std::priority_queue; class Point { public: long double x, y; Point() {} Point(const long double &X, const long double &Y) { x = X; y = Y; } }; class Line { public: long double a, b, c;//ax+by=c long double x_min, x_max, y_min, y_max;//直线的值域 Line() {} Line(const Point &first, const Point &second) { x_min = std::min(first.x, second.x); x_max = std::max(first.x, second.x); y_min = std::min(first.y, second.y); y_max = std::max(first.y, second.y); if (first.x != second.x)//斜率式可行 { b = 1; a = -(first.y - second.y) / (first.x - second.x); c = first.y + a*first.x; } else//k->无穷 { b = 0; a = 1; c = first.x; } } bool lineIntersected(const Line &line)//直线相交的判定 { auto D = a*line.b - line.a*b; if (D) { return true; } return false; } bool lineParallel(const Line&line)//判断两直线是否平行 { auto D = a*line.b - line.a*b; if (!D) { return true; } return false; } bool lineOverlapped(const Line&line)//判断两直线是否重合(平行的特例) { auto D = a*line.b - line.a*b; auto Dx = c*line.b - line.c*b; auto Dy = a*line.c - line.a*c; if (!D&&!Dx&&!Dy) { return true; } return false; } long double fixed(long double value) { value *= 1000000000000.0; value += 0.5; value = floor(value); value /= 1000000000000.0; return value; } Point getIntersection(const Line&line)//行列式求两直线交点,要修正误差 { auto D = a*line.b - line.a*b; auto Dx = c*line.b - line.c*b; auto Dy = a*line.c - line.a*c; return{ fixed(Dx / D),fixed(Dy / D) }; } bool segmentIntersected(const Line &line) { if (lineIntersected(line)) { auto point = getIntersection(line); if (point.x >= x_min&&point.x <= x_max &&point.y >= y_min&&point.y <= y_max &&point.x >= line.x_min&&point.x <= line.x_max &&point.y >= line.y_min&&point.y <= line.y_max )//交点在两线段的值域内 { return true; } } return false; } bool segmentOverlapped(const Line &line) { if (lineOverlapped(line)) { if ((x_min <= line.x_max&&x_min >= line.x_min) || (x_max <= line.x_max&&x_max >= line.x_min)) { return true; } } return false; } }; class Rectangle { public: int left, right, top, bottom; bool inRectangle(const Point &point) { if (point.x >= left&&point.x <= right&&point.y >= bottom&&point.y <= top) { return true; } return false; } }; int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int T; while (cin >> T) { while (T--) { int n; cin >> n; vector<Line>line; for (int i = 0; i < n; i++) { long double x1, x2, y1, y2; cin >> x1 >> y1 >> x2 >> y2; line.push_back({ { x1,y1 },{ x2,y2 } }); } vector<bool>collided(n); for (int i = 0; i<n; i++) { for (int j = i + 1; j < n; j++) { if (line[i].segmentIntersected(line[j]) || line[i].segmentOverlapped(line[j])) { collided[i] = collided[j] = true; } } } cout << std::count(collided.begin(), collided.end(), false) << endl; } } return 0; }