#include <iostream>
#include <sstream>
#include <vector>
#include <list>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
using namespace std;

struct UnionFind {
    vector<int> data;
    UnionFind(int size) : data(size, -1) { }
    bool unionSet(int x, int y) {
        x = root(x); y = root(y);
        if (x != y) {
            if (data[y] < data[x]) swap(x, y);
            data[x] += data[y]; data[y] = x;
        }
        return x != y;
    }
    bool findSet(int x, int y) {
        return root(x) == root(y);
    }
    int root(int x) {
        return data[x] < 0 ? x : data[x] = root(data[x]);
    }
    int size(int x) {
        return -data[root(x)];
    }
};

struct Point {
    int x;
    int y;
    Point(): x(0), y(0) {}
    Point( int x, int y ): x( x ), y( y ) {}
    bool operator ==( Point p ) {
        return x == p.x && y == p.y;
    }
    Point operator -() {
        return Point( -x, -y );
    }
    Point operator -( Point p ) {
        return Point( x - p.x, y - p.y );
    }
};
typedef Point Vector;

struct Triangle {
    Vector a;
    Vector b;
    Vector c;
};

bool cross( Vector a, Vector b ) {
    return a.x * b.y - a.y * b.x > 0;
}

bool cross( Triangle ta, Triangle tb ) {
    if ( ta.a == tb.a ) return true;
    if ( ta.a == tb.b ) return true;
    if ( ta.a == tb.c ) return true;
    if ( ta.b == tb.a ) return true;
    if ( ta.b == tb.b ) return true;
    if ( ta.b == tb.c ) return true;
    if ( ta.c == tb.a ) return true;
    if ( ta.c == tb.b ) return true;
    if ( ta.c == tb.c ) return true;
    Vector AB = ta.b - ta.a;
    Vector BA = -AB;
    Vector BC = ta.c - ta.b;
    Vector CB = -BC;
    Vector CA = ta.a - ta.c;
    Vector AC = -CA;
    bool f1 = cross( AB, tb.a - ta.a ) != cross( AC, tb.a - ta.a );
    bool f2 = cross( BA, tb.a - ta.b ) != cross( BC, tb.a - ta.b );
    bool f3 = cross( CA, tb.a - ta.c ) != cross( CB, tb.a - ta.c );
    bool f4 = cross( AB, tb.b - ta.a ) != cross( AC, tb.b - ta.a );
    bool f5 = cross( BA, tb.b - ta.b ) != cross( BC, tb.b - ta.b );
    bool f6 = cross( CA, tb.b - ta.c ) != cross( CB, tb.b - ta.c );
    bool f7 = cross( AB, tb.c - ta.a ) != cross( AC, tb.c - ta.a );
    bool f8 = cross( BA, tb.c - ta.b ) != cross( BC, tb.c - ta.b );
    bool f9 = cross( CA, tb.c - ta.c ) != cross( CB, tb.c - ta.c );
    return ( f1 && f2 && f3 ) || ( f4 && f5 && f6 ) || ( f7 && f8 && f9 );
}

int main() {
    int n;
    while ( cin >> n ) {
        if ( n == 0 ) break;
        for ( int i = 0; i < n; ++ i ) {
            int m;
            cin >> m;
            int X[m][4], Y[m][4];
            for ( int j = 0; j < m; ++ j ) {
                for ( int k = 0; k < 4; ++ k ) {
                    cin >> X[j][k] >> Y[j][k];
                }
            }
            Triangle T[m][2];
            for ( int j = 0; j < m; ++ j ) {
                T[j][0].a = Vector( X[j][1], Y[j][1] );
                T[j][0].b = Vector( X[j][0], Y[j][0] );
                T[j][0].c = Vector( X[j][3], Y[j][3] );
                T[j][1].a = Vector( X[j][1], Y[j][1] );
                T[j][1].b = Vector( X[j][2], Y[j][2] );
                T[j][1].c = Vector( X[j][3], Y[j][3] );
            }
            
            int answer = 0;
            UnionFind uf( m );
            for ( int j = 0; j < m; ++ j ) {
                for ( int k = 0; k < m; ++ k ) {
                    if ( j == k ) continue;
                    for ( int l = 0; l < 2; ++ l ) {
                        if ( cross( T[j][0], T[k][l] ) ) uf.unionSet( j, k );
                        if ( cross( T[j][1], T[k][l] ) ) uf.unionSet( j, k );
                    }
                }
            }
            for ( int j = 0; j < m; ++ j ) {
                if ( uf.data[j] < 0 ) ++ answer;
            }
            cout << answer << endl;
        }
    }
    return 0;
}