EPS = 1e-9

class Point
  attr_accessor :x, :y
  def initialize(x = 0, y = 0)
    @x = x
    @y = y
  end

  def +(right)
    Point.new(@x + right.x, @y + right.y)
  end
  def -(right)
    Point.new(@x - right.x, @y - right.y)
  end
  def [](idx)
    idx == 0 ? @x : @y
  end
  def []=(idx, val)
    @x = val if idx == 0
    @y = val if idx == 1
  end
end

class Tetragon
  attr_accessor :points
  def initialize()
    @points = Array.new(4){ Point.new }
  end
  def [](idx)
    @points[idx]
  end
end

def dot(a, b)
  a.x * b.x + a.y * b.y
end

def cross(a, b)
  a.x * b.y - b.x * a.y
end

def is_intersected_ls(a1, a2, b1, b2)
  cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < EPS and cross(b2-b1, a1-b1) * cross(b2-b1, a2-b1) < EPS
end

def cont(tet, pnt)
  area = cross(tet[1] - tet[0], tet[2] - tet[0]).abs + cross(tet[1] - tet[3], tet[2] - tet[3]).abs

  4.times{ |i| area -= cross(tet[i] - pnt, tet[(i+1)%4] - pnt).abs }
  
  area.abs < EPS
end

def col(a, b)
  4.times{ |i| return true if cont(a, b[i]) or cont(b, a[i]) }

  4.times{ |i| 4.times{ |j| return true if is_intersected_ls(a[i], a[(i+1)%4], b[j], b[(j+1)%4]) } }

  false
end

class UnionFind
  def initialize(size)
    @data = Array.new(size, -1)
  end
  def unite(a, b)
    a = root(a); b = root(b)
    if(a != b)
      a, b = b, a if @data[b] < @data[a]
      @data[a] += @data[b]; @data[b] = a
    end
    a != b
  end
  def same(a, b)
    root(a) == root(b)
  end
  def root(a)
    @data[a] < 0 ? a : @data[a] = root(@data[a])
  end
  def size(a)
    -@data[root(a)]
  end
  def count
    @data.count{ |val| val < 0 }
  end
end


while n = gets.chomp.to_i and n != 0
  n.times do
    m = gets.chomp.to_i
    tetras = Array.new(m){ Tetragon.new }

    m.times{ |i| gets.split(" ").map(&:to_i).each_with_index{ |j, k| tetras[i][k / 2][k % 2] = j } }

    uft = UnionFind.new(m)

    m.times{ |i| m.times{ |j| uft.unite(i, j) if col(tetras[i], tetras[j]) } }

    puts uft.count
  end
end