#include <bits/stdc++.h>
using namespace std;

using ld = long double;
using point = std::complex<ld>;
using polygon = std::vector<point>;

constexpr ld eps = 1e-10;
constexpr ld pi = std::acos(-1.0);

bool comp(point a, point b) {
    return std::real(a) < std::real(b) || (std::real(a) <= std::real(b) && std::imag(a) < std::imag(b));
}

std::vector<point> unique(std::vector<point> ps) {
    std::sort(std::begin(ps), std::end(ps), comp);
    std::vector<point> res;
    for(auto& p : ps) {
        if(res.empty() || abs(res.back() - p) > eps) {
            res.push_back(p);
        }
    }
    return res;
}

ld dot(point const& a, point const& b) {
    return std::real(std::conj(a) * b);
}
ld cross(point const& a, point const& b) {
    return std::imag(std::conj(a) * b);
}

int ccw(point a, point b, point c) {
    b -= a; c -= a;
    if(cross(b, c) > eps) return 1;            // a -> b -> c : counterclockwise
    if(cross(b, c) < -eps) return -1;          // a -> b -> c : clockwise
    if(dot(b, c) < 0) return 2;                // c -> a -> b : line
    if(std::norm(b) < std::norm(c)) return -2; // a -> b -> c : line
    return 0;                                  // a -> c -> b : line
}

struct segment {
    segment() : a(0, 0), b(0, 0) {}
    segment(point a, point b) : a(a), b(b) {}
    point a, b;
};

struct line {
    line() : a(0, 0), b(0, 0) {}
    line(point a, point b) : a(a), b(b) {}
    line(segment s) : a(s.a), b(s.b) {}
    point a, b;
};

struct circle {
    circle() : p(point(0, 0)), r(0) {}
    circle(point p_, long double r_) : p(p_), r(r_) {}
    point p;
    long double r;
};

bool isis_ll(line l, line m) {
    return cross(l.b - l.a, m.b - m.a) != 0;
}

bool isis_ls(line l, segment s) {
    return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) <= 0;
}

bool isis_lp(line l, point p) {
    return (std::abs(cross(l.b - p, l.a - p)) < eps);
}

bool isis_sp(segment s, point p) {
    return (std::abs(s.a - p) + std::abs(s.b - p) - std::abs(s.b - s.a) < eps);
}

bool isis_ss(segment s, segment t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0
        && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

point is_ll(line s, line t) {
    point sv = s.b - s.a, tv = t.b - t.a;
    assert(cross(sv, tv) != 0);
    return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

point is_ss(segment s1, segment s2) {
    assert(isis_ss(s1, s2));
    point sv = s1.b - s1.a, tv = s2.b - s2.a;
    if(cross(sv, tv) == 0) {
        if(std::abs(s1.a - s2.a) < eps || std::abs(s1.a - s2.b) < eps) {
            return s1.a;
        } else {
            return s1.b;
        }
    } else {
        return is_ll(line(s1), line(s2));
    }
}

point proj(line l, point p) {
    long double t = dot(p - l.a, l.a - l.b) / std::norm(l.a - l.b);
    return l.a + t * (l.a - l.b);
}

class union_find {
public:
    union_find(int n) : par(n, -1) {}

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

    bool unite(int x, int y) {
        x = root(x); y = root(y);
        if(x == y) return false;
        if(par[x] < par[y]) swap(x, y);
        par[x] += par[y];
        par[y] = x;
        return true;
    }

private:
    vector<int> par;
};

// 0 -> on, 1 -> in, 2 -> out
int is_in_polygon(polygon const& poly, point p) {
    const int n = poly.size();
    ld sum = 0;
    for(int i = 0; i < n; ++i) {
        point p1 = poly[i], p2 = poly[(i + 1) % n];
        if(isis_sp(segment(p1, p2), p)) {
            return 0;
        }
        sum += arg((p2 - p) / (p1 - p));
    }
    return std::abs(sum) < pi / 2 ? 2 : 1; // @todo: should check < 0.5 ?
}

bool isis_pp(polygon const& p1, polygon const& p2) {
    const int n = p1.size(), m = p2.size();
    for(int i = 0; i < n; ++i) {
        if(is_in_polygon(p2, p1[i]) != 2) return true;
    }
    for(int i = 0; i < m; ++i) {
        if(is_in_polygon(p1, p2[i]) != 2) return true;
    }
    for(int i = 0; i < n; ++i) {
        segment s1(p1[i], p1[(i + 1) % n]);
        for(int j = 0; j < m; ++j) {
            segment s2(p2[j], p2[(j + 1) % m]);
            if(isis_ss(s1, s2)) return true;
        }
    }
    return false;
}

int main() {
    int n;
    while(cin >> n, n) {
        for(int _ = 0; _ < n; ++_) {
            int m; cin >> m;
            int ans = m;
            vector<polygon> ps(m);
            union_find uf(m);
            for(int i = 0; i < m; ++i) {
                for(int j = 0; j < 4; ++j) {
                    int x, y; cin >> x >> y;
                    ps[i].emplace_back(x, y);
                }
            }
            for(int i = 0; i < m; ++i) {
                for(int j = i + 1; j < m; ++j) {
                    if(isis_pp(ps[i], ps[j])) {
                        ans -= uf.unite(i, j);
                    }
                }
            }
            cout << ans << endl;
        }
    }
}

