#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <queue>
#include <set>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()

const double EPS = 1e-8;
const double INF = 1e12;
typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}

struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
};

typedef vector<P> G;

int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > 0)   return +1;       // counter clockwise
  if (cross(b, c) < 0)   return -1;       // clockwise
  if (dot(b, c) < 0)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}


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)];
  }
};

bool judge(G g, P p) {
  REP(i,4)
    if (ccw(g[i], g[(i+1)%4], p) == 1) return 0;
  return 1;
}
bool judge2(G g1, G g2) {
  REP(i,4) if (judge(g1, g2[i])) return 1;
  REP(i,4) if (judge(g2, g1[i])) return 1;
  REP(i,4) REP(j,4) {
    if (intersectSS(L(g1[i], g1[(i+1)%4]), L(g2[j], g2[(j+1)%4]))) return 1;
  }
  return 0;
}

int main() {
  int N;
  while(cin>>N,N) {
    while(N--) {
      int n;
      cin >> n;
      G g[n];
      REP(i,n) {
        REP(j,4) {
          int x,y;
          cin >> x >> y;
          g[i].push_back(P(x,y));
        }
      }
      UnionFind uf(n);
      REP(i,n) {
        REP(j,i) {
          if (judge2(g[i], g[j]))
            uf.unionSet(i,j);
        }
      }
      set<int> se;
      REP(i,n)
        se.insert(uf.root(i));
      cout << se.size() << endl;
    }
  }
}