#include <algorithm>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;

#define reps(i,f,n) for(int i=f; i<int(n); ++i)
#define rep(i,n) reps(i,0,n)

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;

const int INF = 1001001001;
typedef complex<int> P;

struct UF
{
	vi par, rank;
	UF(int n) : par(n), rank(n, 0) {
		rep(i, n) par[i] = i;
	}
	
	int find(int x) {
		return par[x]==x ? x : (par[x] = find(par[x]));
	}
	void unite(int x, int y) {
		x = find(x);
		y = find(y);
		if(x == y) return;
		
		if(rank[x] < rank[y])
			par[x] = y;
		else
			par[y] = x;
		rank[x] += rank[x] == rank[y];
	}
	bool same(int x, int y) {
		return find(x) == find(y);
	}
};

bool cross(vector<P>& A, vector<P>& B)
{
	rep(_, 2){
		rep(i, 4){
			bool ok = true;
			rep(j, 4){
				P x = A[j] - A[(j+1)%4];
				P p = B[i] - A[(j+1)%4];
				if(x.real()*p.imag() - x.imag()*p.real() < 0){
					ok = false;
					break;
				}
			}
			if(ok)
				return true;
		}
		swap(A, B);
	}
	return false;
}

int main()
{
	int n;
	while(scanf("%d", &n), n){
		rep(i, n){
			int m;
			scanf("%d", &m);

			vector<P> rect[100];
			rep(j, m){
				rect[j].resize(4);
				rep(k, 4)
					scanf("%d%d", &rect[j][k].real(), &rect[j][k].imag());
			}

			UF uf(m);
			rep(j, m) reps(k, j+1, m){
				if(cross(rect[j], rect[k]))
					uf.unite(j, k);
			}

			int tmp[100];
			rep(j, m)
				tmp[j] = uf.find(j);
			sort(tmp, tmp+m);
			printf("%d\n", unique(tmp, tmp+m)-tmp);
		}
	}
	return 0;
}