#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <deque>
#include <complex>
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REP(i,a) FOR(i,0,a)
const int C_CW=1,C_CCW=-1,C_STR=0,C_OPO=-2,C_RET=2;
const int INF=1<<30;
const double EPS=1e-10;
using namespace std;
typedef complex<long double> cld;
typedef struct{
	cld point[4];
} quad;
typedef vector<quad> vq;
int unions[100];
int cross(cld a,cld b){
	return (conj(a)*b).imag();
}
long double dot(cld a,cld b){
	return (a*conj(b)).real();
}
int ccw(cld o,cld a,cld b){
	a-=o;
	b-=o;
	if(cross(a,b)>0)	return C_CCW;
	if(cross(a,b)<0)	return C_CW;
	if(dot(a,b)<0)	return C_OPO;
	if(norm(a)<norm(b)) return C_STR;
	return C_RET;
	
}
bool isInside(quad a,cld b){
	bool flag=false,flagb=false;
	REP(i,4)
		if(ccw(a.point[i],a.point[(i+1)%4],b)==C_CCW)	return false;
	return true;
}
bool isCollision(quad a,quad b){
	REP(i,4){
	if(isInside(a,b.point[i]))	return true;
	if(isInside(b,a.point[i]))	return true;
	}
	return false;
}
int find(int i){
	if(unions[i]==i)
		return i;
	return find(unions[i]);
}
void unit(int i,int j){
	unions[find(i)]=min(find(i),find(j));
	unions[find(j)]=min(find(i),find(j));
}
int main() {
	// your code goes here
	int N;
	while(cin >> N && N){
		REP(i,N){
			vq qs;
			int M;
			cin >> M;
			REP(j,M)
				unions[j]=j;
			REP(j,M){
				quad x;
				REP(k,4){
					int tmp,tmpb;
					cin >> tmp >> tmpb;
					x.point[k]=cld(tmp,tmpb);
				}
				qs.push_back(x);
			}
			int noHit=0;
			REP(i,M)
				FOR(j,i+1,M)
					if(isCollision(qs[i],qs[j])){
						unit(i,j);
						break;
					}
			REP(i,M)
				if(find(i)==i)
					noHit++;
			cout << noHit << endl;
		}
	}
	
	return 0;
}