#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct circle {
    int x;
    int y;
    int r;

    circle() {}
    circle(int x, int y, int r) : x(x), y(y), r(r) {}

    long long dist(circle c) {
        long long d = (x - c.x) * 1ll * (x - c.x) + (y - c.y) * 1ll * (y - c.y);
        long long d1 = (r + c.r) * 1ll * (r + c.r);
        return d - d1;
    }

    int touch(circle c) {
        long long d = (x - c.x) * 1ll * (x - c.x) + (y - c.y) * 1ll * (y - c.y);
        if (d == (r + c.r) * 1ll * (r + c.r)) {
            return 1;
        }
        if (d == (r - c.r) * 1ll * (r - c.r)) {
            return -1;
        }
        return 0;        
    }

    bool operator<(const circle & c) const {
        if (r != c.r) {
            return r < c.r;
        }
        if (x != c.x) {
            return x < c.x;
        }
        return y < c.y;
    }

    bool operator==(const circle & c) const {
        return x == c.x && y == c.y && r == c.r;
    }
};

struct arc {
    circle c;
    int id;
    bool top;

    arc () {}
    arc(circle c, int id, bool top) : c(c), id(id), top(top) {}

    bool operator<(const arc & a) const {
        if (id == a.id) {
            return top < a.top;
        }
        ll d2 = (c.x - a.c.x) * 1ll * (c.x - a.c.x) + (c.y - a.c.y) * 1ll * (c.y - a.c.y);
        if (d2 <= (c.r - a.c.r) * 1ll * (c.r - a.c.r)) {
            if (c.r < a.c.r) {
                return a.top;
            }
            return !top;
        }
        return c.y < a.c.y;
    }
};

struct point {
    circle c;
    int id;
    bool left;

    point() {}
    point(circle c, int id, bool left) : c(c), id(id), left(left) {}

    bool operator<(const point & p) const {
        if (c.x + (1 - 2 * left) * c.r != p.c.x + (1 - 2 * p.left) * p.c.r) {
            return c.x + (1 - 2 * left) * c.r < p.c.x + (1 - 2 * p.left) * p.c.r;
        }
        if (c.y != p.c.y) {
            return c.y < p.c.y;
        }
        if (left != p.left) {
            return left < p.left;
        }
        if (left) {
            return c.r > p.c.r;
        }
        return c.r < p.c.r;
    }
};

struct vec {
    int x;
    int y;
    
    vec() {}
    vec(int x, int y) : x(x), y(y) {}

    void norm() {
        int g = __gcd(abs(x), abs(y));
        x /= g;
        y /= g;
    }

    vec operator+(const vec & v) const {
        return vec{x + v.x, y + v.y};
    }

    vec operator-(const vec & v) const {
        return vec{x - v.x, y - v.y};
    }

    bool operator<(const vec & v) const {
        if (x < v.x) {
            return x < v.x;
        }
        return y < v.y;
    }
};

void solve() {
    int n;
    cin >> n;
    vector<circle> c(n);
    vector<point> points(2 * n);
    for (int i = 0; i < n; ++i) {
        int x, y, r;
        cin >> x >> y >> r;
        c[i] = {x, y, r};
        points[2 * i] = {c[i], i, false};
        points[2 * i + 1] = {c[i], i, true};
    }
    sort(points.begin(), points.end());
    set<arc> s;
    vector<int> in(n, -1);
    vector<vector<int>> out(n);
    for (int i = 0; i < 2 * n - 1; ++i) {
        auto cur = points[i];
        auto next = points[i + 1];
        if (cur.c.x + (1 - 2 * cur.left) * cur.c.r == next.c.x + (1 - 2 * next.left) * next.c.r 
                    && cur.c.y == next.c.y && cur.left != next.left) {
            out[cur.id].push_back(next.id);
            out[next.id].push_back(cur.id);
        }
    }
    for (auto & p : points) {
        if (p.left) {
            arc top = {p.c, p.id, 1};
            arc bottom = {p.c, p.id, 0};
            auto it = s.upper_bound(top);
            if (it != s.end()) {
                int pos = p.c.touch(it->c);
                if (pos == -1) {
                    in[p.id] = it->id;
                }
                if (pos == 1) {
                    out[p.id].push_back(it->id);
                    out[it->id].push_back(p.id);
                }
            }
            if (it != s.begin()) {
                --it;
                int pos = p.c.touch(it->c);
                if (pos == -1) {
                    in[p.id] = it->id;
                }
                if (pos == 1) {
                    out[p.id].push_back(it->id);
                    out[it->id].push_back(p.id);
                }
            }
            s.insert(top);
            s.insert(bottom);
        } else {
            arc top = {p.c, p.id, 1};
            arc bottom = {p.c, p.id, 0};
            s.erase(top);
            s.erase(bottom);
            auto it = s.upper_bound(top);
            if (it != s.end()) {
                int pos = p.c.touch(it->c);
                if (pos == -1) {
                    in[p.id] = it->id;
                }
                if (pos == 1) {
                    out[p.id].push_back(it->id);
                    out[it->id].push_back(p.id);
                }
            }
            if (it != s.begin()) {
                --it;
                int pos = p.c.touch(it->c);
                if (pos == -1) {
                    in[p.id] = it->id;
                }
                if (pos == 1) {
                    out[p.id].push_back(it->id);
                    out[it->id].push_back(p.id);
                }
            }
        }
    }
    for (auto & edges : out) {
        sort(edges.begin(), edges.end() );
        edges.erase(unique(edges.begin(), edges.end()), edges.end());
    }
    vector<size_t> idx(c.size());
    iota(idx.begin(), idx.end(), 0);
    sort(idx.begin(), idx.end(), [&c] (size_t i1, size_t i2) {
        return c[i1] < c[i2];
    });
    vector<map<vec, int>> intersections(n);
    for (int i : idx) {
        if (in[i] != -1) {
            vec v = vec{c[i].x, c[i].y} - vec{c[in[i]].x, c[in[i]].y};
            v.norm();
            int val = 1;
            if (intersections[i].find(v) != intersections[i].end()) {
                val += intersections[i][v];
            }
            intersections[in[i]][v] = val;
        }
    }
    ll ans = 0;
    for (int i = 0; i < n; ++i) {
        for (int j : out[i]) {
            vec v1 = vec{c[j].x, c[j].y} - vec{c[i].x, c[i].y};
            v1.norm();
            vec v2 = vec{-v1.x, -v1.y};
            ll val1 = 1;
            if (intersections[i].find(v1) != intersections[i].end()) {
                val1 += intersections[i][v1];
            }
            ll val2 = 1;
            if (intersections[j].find(v2) != intersections[j].end()) {
                val2 += intersections[j][v2];
            }
            ans += val1 * val2;
        }
    }
    cout << ans / 2 << "\n";
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    cerr << clock() * 1.0 / CLOCKS_PER_SEC << "\n";
    return 0;
}
