#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

class Point{
public:
	double x,y;

	Point(double x = 0,double y = 0):x(x),y(y){}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}
};

typedef Point Vector;
typedef vector<Point> Polygon;

int num_sets,num_point,Q;
int N;
int boss[100],height[100];
Polygon info[100];

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int is_same(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	if(boss_x == boss_y)return;

	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

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

double dot(Vector a,Vector b){
	return a.x*b.x + a.y*b.y;
}

Point calc_minus(Point a,Point b){
	Point ret;

	ret.x = a.x-b.x;
	ret.y = a.y-b.y;

	return ret;
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

void func(){

	scanf("%d",&N);
	for(int i = 0; i < N; i++){
		boss[i] = i;
		height[i] = 0;
	}

	for(int i = 0; i < N; i++)info[i].clear();

	double x,y;
	for(int i = 0; i < N; i++){
		for(int k = 0; k < 4; k++){
			scanf("%lf %lf",&x,&y);
			info[i].push_back(Point(x,y));
		}
	}

	int ret;

	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(i == k)continue;

			for(int p = 0; p < info[i].size(); p++){
				ret = contains(info[k],info[i][p]);
				if(ret >= 1){
					unite(i,k);
					break;
				}
			}
		}
	}

	int ans = 0;
	for(int i = 0; i < N; i++){
		if(get_boss(i) == i)ans++;
	}

	printf("%d\n",ans);
}

int main(){

	while(true){
		scanf("%d",&num_sets);
		if(num_sets == 0)break;

		for(int i = 0; i < num_sets; i++)func();
	}

	return 0;
}

