#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cassert>
#include<iostream>
#include<sstream>
#include<string>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<utility>
#include<numeric>
#include<algorithm>
#include<bitset>
#include<complex>
#include<stack>

using namespace std;

typedef long long Int;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<string> vstring;
typedef vector<pint> vpint;
typedef stringstream SS;

template<class T> void chmin(T &t, T f) { if (t > f) t = f; }
template<class T> void chmax(T &t, T f) { if (t < f) t = f; }

#define rep(i,n) for(int i=0;i<(n);++i)
#define repn(i,m,n) for(int i=(m);i<(n);++i)
#define repd(i,n) for(int i=(n)-1;i>=0;--i)
#define repnd(i,m,n) for(int i=(n)-1;i>=(m);--i)
#define rep0(i,n) for(i=0;i<(n);++i)
#define repn0(i,m,n) for(i=(m);i<(n);++i)
#define repd0(i,n) for(i=(n)-1;i>=0;--i)
#define repnd0(i,m,n) for(i=(n)-1;i>=(m);--i)
#define repc(i,n) for(int i=0;i<=(n);++i)
#define repcn(i,m,n) for(int i=(m);i<=(n);++i)
#define repcd(i,n) for(int i=(n);i>=0;--i)
#define repcnd(i,m,n) for(int i=(n);i>=(m);--i)
#define repc0(i,n) for(i=0;i<=(n);++i)
#define repcn0(i,m,n) for(i=(m);i<=(n);++i)
#define repcd0(i,n) for(i=(n);i>=0;--i)
#define repcnd0(i,m,n) for(i=(n);i>=(m);--i)
#define all(n) n.begin(),n.end()
#define sz(n) ((int)(n).size())
#define IL for(;;)
#define MP make_pair
#define PB push_back
#define X second
#define Y first
#define p_queue(n) priority_queue<n,vector<n>,greater<n> >
#define PUTLINE cout<<"LINE:"<<__LINE__<<endl;

const int INF = 2147483647/3;
const double EPS = 1e-10;
const double PI = acos(-1.0);

const int dx[]={1,-1,0,0,1,1,-1,-1,0};
const int dy[]={0,0,1,-1,1,-1,1,-1,0};

int sig(double r) { return r < -EPS ? -1 : r > EPS ? 1 : 0; }

struct P {
	double x, y;
	P() {}
	P(double x, double y) : x(x), y(y) {}
	P operator+(const P &a) const { return P(x + a.x, y + a.y); }
	P operator-(const P &a) const { return P(x - a.x, y - a.y); }
	P operator*(const P &a) const { return P(x * a.x - y * a.y, x * a.y + y * a.x); }
	P operator-() const { return P(-x, -y); }
	P operator*(const double &k) const { return P(x * k, y * k); }
	P operator/(const double &k) const { return P(x / k, y / k); }
	double abs2() const { return x * x + y * y; }
	double abs() const { return sqrt(abs2()); }
	double arg() const { return atan2(y, x); }
	double dot(const P &a) const { return x * a.x + y * a.y; }
	double det(const P &a) const { return x * a.y - y * a.x; }
	P proj(const P &a) const { double k = dot(a) / abs2(); return P(x * k, y * k); }
	bool operator<(const P &a) const { return x != a.x ? x < a.x : y < a.y; }
	bool operator==(const P &a) const { return sig(x - a.x) == 0 && sig(y - a.y) == 0; }
};

ostream &operator<<(ostream&os, const P&a) { os << "(" << a.x << ", " << a.y << ")"; return os; }
double tri(P a, P b, P c) { return (b - a).det(c - a); }

struct L {
	P a, b;
	L() {}
	L(P a, P b) : a(a), b(b) {}
	P vec() const { return b - a; }
	P proj(const P &p) const { return a + vec().proj(p - a); }
	P refl(const P &p) const { return proj(p) * 2 - p; }
	int iSP(const P &p) const {
		int s = sig(vec().det(p - a));
		if (s != 0) return s;
		if (sig(vec().dot(p - a)) < 0) return -2;
		if (sig(-vec().dot(p - b)) < 0) return 2;
		return 0;
	}
	int iLL(const L &l) const {
		if (sig(vec().det(l.vec()))) return 1;
		if (sig(vec().det(l.a - a))) return 0;
		return -1;
	}
	bool iLS(const L &l) const { return sig(tri(a, b, l.a)) * sig(tri(a, b, l.b)) <= 0; }
	bool iSS(const L &l) const { return this->iSP(l.a) * this->iSP(l.b) <= 0 && l.iSP(a) * l.iSP(b) <=0; }
	P pLL(const L &l) const { return a + vec() * (l.a - a).det(l.vec()) / b.det(l.vec()); }
	double dLP(const P &p) const { return abs(tri(a, b, p)) / vec().abs(); }
	double dSP(const P &p) const {
		if (sig(vec().dot(p - a)) <= 0) return (p - a).abs();
		if (sig(vec().dot(p - b)) >= 0) return (p - b).abs();
		return dLP(p);
	}
	double dLL(const L &l) const { return iLL(l) ? 0 : dLP(l.a); }
	double dLS(const L &l) const { return iLS(l) ? 0 : min(dLP(l.a), dLP(l.b)); }
	double dSS(const L &l) const { return iSS(l) ? 0 : min(min(dSP(l.a), dSP(l.b)), min(l.dSP(a), l.dSP(b))); }
};

int uf[110];
P p[110][4];
L l[110][4];

int root(int x) { return (uf[x] < 0) ? x : (uf[x] = root(uf[x])); }

bool conn(int x, int y) {
	x = root(x);
	y = root(y);
	if (x == y) return 0;
	if (uf[x] > uf[y]) swap(x,y);
	uf[x] += uf[y];
	uf[y] = x;
	return 1;
}

int main() {
	int n, m;
	IL {
		cin >> n;
		if (n == 0) break;
		rep (iii, n) {
			cin >> m;
			rep (i, m) {
				uf[i] = -1;
				rep (j, 4) cin >> p[i][j].x >> p[i][j].y;
				rep (j, 4) l[i][j] = L(p[i][j], p[i][(j + 1) % 4]);
			}
			int res = m;
			rep (i, m) rep (j, m) if (i != j) {
				L g = L((p[i][0] + p[i][2]) / 2, (p[j][0] + p[j][2]) / 2);
				bool ok = false;
				rep (ii, 4) rep (jj, 4) if(l[i][ii].iSS(l[j][jj])) ok = true;
				int ii, jj;
				rep0 (ii, 4) if (l[i][ii].iSS(g)) break;
				rep0 (jj, 4) if (l[j][jj].iSS(g)) break;
				if (ii == 4 || jj == 4) ok = true;
				if (ok && conn(i, j)) --res;
			}
			cout << res << endl;
		}
	}
	return 0;
}

Measured memory_bytes: 0