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

template<class T> T abs2(T a){
	return a < 0 ? -a : a;
}

template<class T> struct fraction {
	T a;
	T b;

	fraction() : a(0), b(1) {}
	fraction(T x) : a(x), b(1) {}
	fraction(T _a, T _b) : a(_a), b(_b) { reduce(); }
	friend std::ostream& operator << (std::ostream& out, const fraction& n) { return out << n.a << '/' << n.b; }

	fraction neg() const {
		fraction res {-a, b};
		return res;
	}
	friend fraction neg(const fraction& m) { return m.neg(); }

	fraction abs() const {
		fraction res {abs2(a), abs2(b)};
		return res;
	}
	friend fraction abs(const fraction& m) { return m.abs(); }

	fraction operator- () const {
		return neg();
	}
	fraction operator+ () const {
		return fraction(*this);
	}

	friend bool operator == (const fraction& x, const fraction& y){
		return x.a * y.b == x.b * y.a;
	}
	friend bool operator != (const fraction& x, const fraction& y){
		return x.a * y.b != x.b * y.a;
	}
	friend bool operator < (const fraction& x, const fraction& y){
		return x.a * y.b < x.b * y.a;
	}
	friend bool operator <= (const fraction& x, const fraction& y){
		return x.a * y.b <= x.b * y.a;
	}
	friend bool operator > (const fraction& x, const fraction& y){
		return x.a * y.b > x.b * y.a;
	}
	friend bool operator >= (const fraction& x, const fraction& y){
		return x.a * y.b >= x.b * y.a;
	}

	void reduce(){
		T g = __gcd(abs2(a), abs2(b));
		a /= g;
		b /= g;
		if(b < 0) { a = -a; b = -b; }
	}

	fraction& operator += (const fraction& o){
		*this = {a * o.b + b * o.a, b * o.b};
		reduce();
		return *this;
	}
	fraction& operator -= (const fraction& o){
		*this = {a * o.b - b * o.a, b * o.b};
		reduce();
		return *this;
	}
	fraction& operator *= (const fraction& o){
		*this = {a * o.a, b * o.b};
		reduce();
		return *this;
	}
	fraction& operator /= (const fraction& o){
		*this = {a * o.b, b * o.a};
		reduce();
		return *this;
	}
	friend fraction operator + (const fraction& a, const fraction& b) { return fraction(a) += b; }
	friend fraction operator - (const fraction& a, const fraction& b) { return fraction(a) -= b; }
	friend fraction operator * (const fraction& a, const fraction& b) { return fraction(a) *= b; }
	friend fraction operator / (const fraction& a, const fraction& b) { return fraction(a) /= b; }
};


template <typename T> struct Point {
public:
	T x, y;
	Point() : x(0), y(0) {}
	Point(T x_, T y_) : x(x_), y(y_) {}
	template <typename U> explicit Point(const Point<U>& p) : x(p.x), y(p.y) {}
	Point(const std::pair<T, T>& p) : x(p.first), y(p.second) {}
	Point(const std::complex<T>& p) : x(real(p)), y(imag(p)) {}
	explicit operator std::pair<T, T> () const { return std::pair<T, T>(x, y); }
	explicit operator std::complex<T> () const { return std::complex<T>(x, y); }

	friend std::ostream& operator << (std::ostream& o, const Point& p) { return o << '(' << p.x << ',' << p.y << ')'; }
	friend std::istream& operator >> (std::istream& i, Point& p) { return i >> p.x >> p.y; }
	friend bool operator == (const Point& a, const Point& b) { return a.x == b.x && a.y == b.y; }
	friend bool operator != (const Point& a, const Point& b) { return !(a==b); }

	Point operator + () const { return Point(+x, +y); }
	Point operator - () const { return Point(-x, -y); }

	Point& operator += (const Point& p) { x += p.x, y += p.y; return *this; }
	Point& operator -= (const Point& p) { x -= p.x, y -= p.y; return *this; }
	Point& operator *= (const T& t) { x *= t, y *= t; return *this; }
	Point& operator /= (const T& t) { x /= t, y /= t; return *this; }

	friend Point operator + (const Point& a, const Point& b) { return Point(a.x+b.x, a.y+b.y); }
	friend Point operator - (const Point& a, const Point& b) { return Point(a.x-b.x, a.y-b.y); }
	friend Point operator * (const Point& a, const T& t) { return Point(a.x*t, a.y*t); }
	friend Point operator * (const T& t ,const Point& a) { return Point(t*a.x, t*a.y); }
	friend Point operator / (const Point& a, const T& t) { return Point(a.x/t, a.y/t); }

	friend bool operator < (const Point& a, const Point& b){
		return std::tie(a.x, a.y) < std::tie(b.x, b.y);
	}

	T dist2() const { return x * x + y * y; }
	auto dist() const { return std::sqrt(dist2()); }
	Point unit() const { return *this / this->dist(); }
	auto angle() const { return std::atan2(y, x); }

	T int_norm() const { return __gcd(x,y); }
	Point int_unit() const { if (!x && !y) return *this; return *this / this->int_norm(); }

	// Convenient free-functions, mostly for generic interop
	friend auto norm(const Point& a) { return a.dist2(); }
	friend auto abs(const Point& a) { return a.dist(); }
	friend auto unit(const Point& a) { return a.unit(); }
	friend auto arg(const Point& a) { return a.angle(); }
	friend auto int_norm(const Point& a) { return a.int_norm(); }
	friend auto int_unit(const Point& a) { return a.int_unit(); }

	Point perp_cw() const { return Point(y, -x); }
	Point perp_ccw() const { return Point(-y, x); }

	friend T dot(const Point& a, const Point& b) { return a.x * b.x + a.y * b.y; }
	friend T cross(const Point& a, const Point& b) { return a.x * b.y - a.y * b.x; }
	friend T cross3(const Point& a, const Point& b, const Point& c) { return cross(b-a, c-a); }

	// Complex numbers and rotation
	friend Point conj(const Point& a) { return Point(a.x, -a.y); }

	// Returns conj(a) * b
	friend Point dot_cross(const Point& a, const Point& b) { return Point(dot(a, b), cross(a, b)); }
	friend Point cmul(const Point& a, const Point& b) { return dot_cross(conj(a), b); }
	friend Point cdiv(const Point& a, const Point& b) { return dot_cross(b, a) / b.norm(); }

	// Must be a unit vector; otherwise multiplies the result by abs(u)
	Point rotate(const Point& u) const { return dot_cross(conj(u), *this); }
	Point unrotate(const Point& u) const { return dot_cross(u, *this); }

	friend bool lex_less(const Point& a, const Point& b) {
		return std::tie(a.x, a.y) < std::tie(b.x, b.y);
	}

	friend bool same_dir(const Point& a, const Point& b) { return cross(a,b) == 0 && dot(a,b) > 0; }

	// check if 180 <= s..t < 360
	friend bool is_reflex(const Point& a, const Point& b) { auto c = cross(a,b); return c ? (c < 0) : (dot(a, b) < 0); }

	// operator < (s,t) for angles in [base,base+2pi)
	friend bool angle_less(const Point& base, const Point& s, const Point& t) {
		int r = is_reflex(base, s) - is_reflex(base, t);
		return r ? (r < 0) : (0 < cross(s, t));
	}

	friend auto angle_cmp(const Point& base) {
		return [base](const Point& s, const Point& t) { return angle_less(base, s, t); };
	}
	friend auto angle_cmp_center(const Point& center, const Point& dir) {
		return [center, dir](const Point& s, const Point& t) -> bool { return angle_less(dir, s-center, t-center); };
	}

	// is p in [s,t] taken ccw? 1/0/-1 for in/border/out
	friend int angle_between(const Point& s, const Point& t, const Point& p) {
		if (same_dir(p, s) || same_dir(p, t)) return 0;
		return angle_less(s, p, t) ? 1 : -1;
	}
};

using ll = int64_t;

using i128 = int64_t;

vector<ll> x, y, r;

struct Circle {
	int id;
	int which;
	Circle(int _id, int _which) : id(_id), which(_which) {}

	bool contains(Circle& b){
		return (r[id] > r[b.id]) && (i128(x[id] - x[b.id]) * (x[id] - x[b.id]) + i128(y[id] - y[b.id]) * (y[id] - y[b.id]) <= i128(r[id] - r[b.id]) * (r[id] - r[b.id]));
	}
};

using frac = fraction<i128>;

pair<bool, Point<frac> > tangency_point(int a, int b){
	Point<i128> p(x[a], y[a]);
	Point<i128> q(x[b], y[b]);
	i128 d2 = (p - q).dist2();
	if(d2 == i128(r[a] + r[b]) * i128(r[a] + r[b])){
		Point<frac> p128(p.x, p.y);
		Point<frac> q128(q.x, q.y);
		return {true, p128 + (q128 - p128) * frac(r[a], r[a] + r[b])};
	}
	if(d2 == i128(r[a] - r[b]) * i128(r[a] - r[b])){
		Point<frac> p128(p.x, p.y);
		Point<frac> q128(q.x, q.y);
		return {true, p128 + (q128 - p128) * frac(r[a], r[a] - r[b])};
	}
	return {false, {}};
}

// ostream& operator << (ostream& o, i128 x){
// 	if(x < 0) o << '-';
// 	x = x < 0 ? -x : x;
// 	ll a = ll(x / ll(1e18));
// 	ll b = ll(x % ll(1e18));
// 	string s = to_string(b);
// 	if(a) {
// 		o << a;
// 		s = string(18 - s.size(), '0') + s;
// 	}
// 	o << s;
// 	return o;
// }


template<class T> int sgn(T x){
	return int(x > 0) - int(x < 0);
}

void solve(){
	int N;
	cin >> N;
	x.resize(N), y.resize(N), r.resize(N);
	for(int i = 0; i < N; i++){
		cin >> x[i] >> y[i] >> r[i];
	}
	vector<pair<ll,pair<int,int>> > events;
	for(int i = 0; i < N; i++){
		events.push_back({x[i] - r[i], {1, i}});
		events.push_back({x[i] + r[i], {0, i}});
	}
	sort(events.begin(), events.end());

	auto cmp = [&](Circle a, Circle b) -> bool {
		if(a.contains(b)){
			return 2 * a.which < 1;
		}
		if(b.contains(a)){
			return 1 < 2 * b.which;
		}
		return tie(y[a.id], x[a.id], a.which) < tie(y[b.id], x[b.id], b.which);
	};
	set<Circle, decltype(cmp) > s(cmp);
	vector<pair<Circle, Circle> > z;
	for(pair<ll, pair<int,int> > e : events){
		int v = e.second.second;
		vector<Circle> q = {Circle(v, 0), Circle(v, 1)};
		if(e.second.first == 0){
			for(Circle c : q){
				auto f = s.find(c);
				if(f == s.end()) continue;
				auto f2 = next(f);
				if(f2 != s.end() && f != s.begin()) z.push_back({*prev(f), *f2});
				s.erase(f);
			}
		} else {
			for(Circle c : q){
				s.insert(c);
				auto f = s.find(c);
				if(f != s.end()){
					auto f2 = next(f);
					if(f2 != s.end()){
						z.push_back({*f, *f2});
					}
					if(f != s.begin()){
						auto f1 = prev(f);
						z.push_back({*f1, *f});
					}
				}
			}
		}
	}
	map<Point<frac>, set<int>> to_points;
	for(auto [c1, c2] : z){
		if(c1.id == c2.id) continue;
		auto [ok, p] = tangency_point(c1.id, c2.id);
		if(ok){
			to_points[p].insert(c1.id);
			to_points[p].insert(c2.id);
		}
	}
	for(int i = 0; i < N; i++){
		to_points[Point<frac>(x[i] + r[i], y[i])].insert(i);
		to_points[Point<frac>(x[i] - r[i], y[i])].insert(i);
	}
	ll pairs = 0;
	for(auto [p, ids] : to_points){
		if(ids.size() == 1) continue;
		vector<ll> cnt(9);
		for(int i : ids){
			Point<frac> del = Point<frac>(x[i], y[i]) - p;
			int dir = 4 + sgn(del.x) * 3 + sgn(del.y);
			cnt[dir]++;
		}
		for(int i = 0; i < 4; i++){
			pairs += cnt[i] * cnt[8 - i];
		}
	}
	cout << pairs << '\n';
}

int main(){
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while(T--) solve();
}
