/**
 *    author:  tourist
 *    created: 08.11.2024 23:02:23
**/
#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

struct Circle {
  int64_t x;
  int64_t y;
  int64_t r;
};

typedef pair<int64_t, int64_t> Fraction;
typedef pair<Fraction, Fraction> Touch;

Fraction MakeFraction(int64_t a, int64_t b) {
  assert(b != 0);
  if (b < 0) {
    a = -a;
    b = -b;
  }
  auto g = gcd(abs(a), abs(b));
  return {a / g, b / g};
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int tt;
  cin >> tt;
  while (tt--) {
    int n;
    cin >> n;
    vector<Circle> c(2 * n);
    for (int i = 0; i < n; i++) {
      cin >> c[i].x >> c[i].y >> c[i].r;
    }
    sort(c.begin(), c.begin() + n, [&](const Circle& a, const Circle& b) {
      return a.r > b.r;
    });
    for (int i = 0; i < n; i++) {
      c[2 * n - 1 - i] = c[i];
    }
    //          i == lower
    // 2n - 1 - i == upper
    auto CompareImpl = [&](auto&& self, int i, int j) -> bool {
      // assert that their x-segments have positive intersection
      assert(c[i].x + c[i].r > c[j].x - c[j].r);
      assert(c[j].x + c[j].r > c[i].x - c[i].r);

      if (c[i].x - c[i].r < c[j].x - c[j].r) {
        return !self(self, j, i);
      }

      // check at circle i's leftmost point
      auto at = c[i].x - c[i].r;
      auto dis = c[j].r * c[j].r - (c[j].x - at) * (c[j].x - at);
      if (j < n) {
        // c[i].y  ?  c[j].y - sqrt(dis)
        // sqrt(dis)  ?  c[j].y - c[i].y
        auto rhs = c[j].y - c[i].y;
        if (rhs < 0) {
          return false;
        }
        if (dis != rhs * rhs) {
          return dis < rhs * rhs;
        }
      } else {
        // c[i].y  ?  c[j].y + sqrt(dis)
        // c[i].y - c[j].y  ?  sqrt(dis)
        auto lhs = c[i].y - c[j].y;
        if (lhs < 0) {
          return true;
        }
        if (lhs * lhs != dis) {
          return lhs * lhs < dis;
        }
      }
      return i < j;
    };
    auto Compare = [&](int i, int j) -> bool {
      return CompareImpl(CompareImpl, i, j);
    };
    set<int, decltype(Compare)> s(Compare);
    vector<pair<int64_t, int>> events;
    for (int i = 0; i < n; i++) {
      events.emplace_back(c[i].x - c[i].r, i);
    }
    for (int i = n; i < 2 * n; i++) {
      events.emplace_back(c[i].x + c[i].r, i - 2 * n);
    }
    sort(events.begin(), events.end());

    map<Touch, set<int>> mp;
    // Check if circles i and j intersect, add their touch point if so
    auto Check = [&](int i, int j) {
      i = min(i, 2 * n - 1 - i);
      j = min(j, 2 * n - 1 - j);
      if (i == j) {
        return;
      }
      if (c[i].r > c[j].r) {
        swap(i, j);
      }
      auto dist = (c[i].x - c[j].x) * (c[i].x - c[j].x) + (c[i].y - c[j].y) * (c[i].y - c[j].y);
      for (auto d : {c[i].r + c[j].r, c[i].r - c[j].r}) {
        if (dist == d * d) {
          auto px = MakeFraction(c[i].x * d + (c[j].x - c[i].x) * c[i].r, d);
          auto py = MakeFraction(c[i].y * d + (c[j].y - c[i].y) * c[i].r, d);
          Touch p = {px, py};
          mp[p].insert(i);
          mp[p].insert(j);
        }
      }
    };

    // Add leftmost and rightmost points of each circle
    for (int i = 0; i < n; i++) {
      auto px1 = MakeFraction(c[i].x - c[i].r, 1);
      auto px2 = MakeFraction(c[i].x + c[i].r, 1);
      auto py = MakeFraction(c[i].y, 1);
      mp[Touch {px1, py}].insert(i);
      mp[Touch {px2, py}].insert(i);
    }

    for (auto& [_, i] : events) {
      if (i >= 0) {
        s.insert(i);
        s.insert(2 * n - 1 - i);
        auto it1 = s.find(i);
        auto it2 = s.find(2 * n - 1 - i);
        assert(it1 != s.end() && it2 != s.end() && next(it1) == it2);
        if (it1 != s.begin()) {
          Check(*prev(it1), i);
        }
        if (next(it2) != s.end()) {
          Check(i, *next(it2));
        }
      } else {
        i += 2 * n;
        auto it1 = s.find(2 * n - 1 - i);
        auto it2 = s.find(i);
        assert(it1 != s.end() && it2 != s.end() && next(it1) == it2);
        if (it1 != s.begin() && next(it2) != s.end()) {
          Check(*prev(it1), *next(it2));
        }
        s.erase(i);
        s.erase(2 * n - 1 - i);
      }
    }

    int64_t ans = 0;
    for (auto& [pt, indices] : mp) {
      auto [xf, yf] = pt;
      int pos = 0;
      int neg = 0;
      for (int i : indices) {
        auto dx = c[i].x * xf.second - xf.first;
        auto dy = c[i].y * yf.second - yf.first;
        assert(dx != 0 || dy != 0);
        if (dy > 0 || (dy == 0 && dx > 0)) {
          pos += 1;
        } else {
          neg += 1;
        }
      }
      ans += int64_t(pos) * neg;
    }
    cout << ans << '\n';
  }
  return 0;
}
