import std.stdio;
import std.c.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.regex;
import std.typecons;

const EPS = 1e-8;

struct Point {
    double y, x;
    Point opBinary(string op)(in Point a) const {
        static if (op == "+" || op == "-") {
            return Point(mixin("y" ~ op ~ "a.y"),
                         mixin("x" ~ op ~ "a.x"));
        }
    }
    Point opBinary(string op)(double a) const {
        static if (op == "*" || op == "/") {
            return Point(mixin("y" ~ op ~ "a"),
                         mixin("x" ~ op ~ "a"));
        }
    }
}
double norm(in Point a) {
    return sqrt(a.x * a.x + a.y * a.y);
}
double dot(in Point a, in Point b) {
    return a.x * b.x + a.y * b.y;
}
double cross(in Point a, in Point b) {
    return a.x * b.y - a.y * b.x;
}
int CCW(Point a, Point b, Point c) {
    b = b - a; c = c - a;
    if (cross(b, c) > EPS) return +1;
    if (cross(b, c) < EPS) return -1;
    if (dot(b, c) < 0) return +2;
    if (b.norm < c.norm) return -2;
    return 0;
}
 
struct Rect {
    Point[4] vs;
}
int next(int x) { return (x + 1) % 4; }
bool contains(in Rect a, in Point p) {
    int ccw = CCW(a.vs[0], a.vs[1], p);
    return iota(0, 4, 1).all!(delegate(i) {
        /*writeln("CCW: ",CCW(a.vs[i], a.vs[i.next], p),
            a.vs[i], a.vs[i.next], p);*/
        return ccw == CCW(a.vs[i], a.vs[i.next], p);
    });
}
bool contains(in Rect a, in Rect b) {
    //writeln(a, b);
    return iota(0, 4, 1).all!((i) => a.contains(b.vs[i]));
}
bool intersect(in Point s1, in Point t1, in Point s2, in Point t2) {
    return CCW(s1, t1, s2) * CCW(s1, t1, t2) <= 0 &&
        CCW(s2, t2, s1) * CCW(s2, t2, t1) <= 0;
}
bool intersect(in Rect a, in Rect b) {
    foreach (i; 0 .. 4)
        foreach (j; 0 .. 4)
            if (intersect(a.vs[i], a.vs[i.next], b.vs[i], b.vs[i.next]))
                return true;
    return false;
}

int N;
void main() {
    Rect[] rs;

    bool solve() {
        scanf("%d\n", &N);
        if (N == 0) return false;
        foreach (i; 0 ..  N) {
            int M; scanf("%d\n", &M);
            rs = new Rect[M];
            foreach (j; 0 .. M) {
                foreach (k; 0 .. 4) {
                    int y, x; scanf("%d %d", &y, &x);
                    rs[j].vs[k] = Point(y, x);
                }
            }

            void F() {
                auto X = new bool[M];
                X[] = true;
                foreach (a; 0 .. M) {
                    foreach (b; 0 .. M) {
                        if (a == b) continue;
                        if (rs[a].contains(rs[b])) {
                            X[b] = false;
                        }
                        if (rs[a].intersect(rs[b])) {
                            X[b] = false;
                        }
                    }
                }
                writeln(X.count(true));
            }

            F;
        }
        return true;
    }

    while (solve) {}
}