#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
using namespace std;

typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 998244353;
typedef long double ld;
typedef complex<ld> Point;
const ll INF = mod * mod;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
const ld eps = 1e-8;
const ld pi = acos(-1.0);
typedef pair<ld, ld> LDP;
typedef pair<ll, ll> LP;
typedef vector<int> vec;
typedef vector<string> svec;

bool eq(ld a, ld b) {
	return (abs(a - b) < eps);
}

class Line {
public:
	Point a, b;
};
class Circle {
public:
	Point p; ld r;
};

ld dot(Point a, Point b) {
	return real(conj(a)*b);
}
ld cross(Point a, Point b) {
	return imag(conj(a)*b);
}
namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		return lhs.real() == rhs.real() ? lhs.imag() < rhs.imag() : lhs.real() < rhs.real();
	}
}
Point proj(Line l, Point p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}

ld dist_lp(Line l, Point p) {
	return abs(p - proj(l, p));
}

int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps)return 1;//a,b,cが反時計回り
	if (cross(b, c) < -eps)return -1;//a,b,cが時計回り
	if (dot(b, c) < 0)return 2;//c,a,bの順に一直線
	if (norm(b) < norm(c))return -2;//a,b,cの順に一直線
	return 0;//a,c,bの順に一直線
}
bool isis_ll(Line l, Line m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}
Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a; Point tv = t.b - t.a;
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

//直線lに幅dをつける
vector<Line> make_w(Line l, ld d) {
	Point dif = l.b - l.a;
	dif = dif*Point{0, 1};
	dif = dif * (d / abs(dif));
	vector<Line> ret;
	for (int id = 1; id >= -1; id -= 2) {
		Point a = l.a + dif * (ld)id;
		Point b = l.b + dif * (ld)id;
		ret.push_back({ a,b });
	}
	return ret;
}

typedef vector<Point> polygon;
polygon ConvexHull(polygon p) {
	int n = p.size();
	int k = 0;
	sort(p.begin(), p.end());
	polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = p[i++]) {
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], p[i]) <= 0)--k;
	}
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) {
		while (k >= t && ccw(ch[k - 2], ch[k - 1], p[i]) <= 0)--k;
	}
	ch.resize(k - 1);
	return ch;
}
polygon convex_cut(const polygon &p, Line l) {
	vector<Point> ret;
	rep(i, p.size()) {
		Point a = p[i], b = p[(i + 1) % p.size()];
		if (ccw(l.a, l.b, a) != -1)ret.push_back(a);
		if (ccw(l.a, l.b, a)*ccw(l.a, l.b, b)<0) {
			ret.push_back(is_ll({ a,b }, l));
		}
	}
	return ret;
}
ld area(const polygon &p){
	ld ret = 0;
	int n = p.size();
	rep(j, n)ret += cross(p[j], p[(j + 1) % n]);
	return ret / 2.0;
}
ld max_distance(const polygon &p) {
	//assert(p.size()>1);
	polygon g = ConvexHull(p);
	int n = g.size(), a = 0, b = 1;
	ld ret = abs(g[0] - g[1]);
	while (a < n) {
		Point p1 = g[a%n], p2 = g[(a + 1) % n];
		Point q1 = g[b%n], q2 = g[(b + 1) % n];
		if (arg((p2 - p1) / (q1 - q2)) > 0)++b; else ++a;
		ret = max(ret, abs(p1 - q1));
	}
	return ret;
}

vector<Point> is_cc(Circle c1, Circle c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d*d + c1.r*c1.r - c2.r*c2.r) / (2 * d);
	ld dfr = c1.r*c1.r - rc * rc;
	if (abs(dfr) < eps)dfr = 0.0;
	if (dfr < 0.0)return res;
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0)res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}
bool in_Circle(Circle a, Circle b) {
	ld dist = abs(b.p - a.p);
	return dist < b.r - a.r+eps;
}

int n;
void solve() {
	vector<pair<pair<ld,int>, LDP>> v;
	rep(i, n) {
		ld x, y, r; cin >> x >> y >> r;
		v.push_back({ {x - r,0},{y - r,y + r} });
		v.push_back({ {x + r,1},{y - r,y + r} });
	}
	sort(v.begin(), v.end());
	vector<pair<LDP,int>> u;
	ld ans = 0;
	ld loc = -1;
	rep(i, v.size()) {
		//cout << i << endl;
		if (i > 0&&v[i].first.first!=v[i-1].first.first) {
			ld sum = 0;
			rep(j, u.size()) {
				sum += u[j].first.second - u[j].first.first;
			}
			//cout << sum << " " << v[i].first.first - loc << endl;
			ans += sum * (v[i].first.first - loc);
		}
		int id = v[i].first.second;
		ld l = v[i].second.first, r = v[i].second.second;
		if (id == 0) {
			vector<LDP> used;
			int len = u.size();
			rep(j, len) {
				ld la = u[j].first.first, lb = u[j].first.second;
				if (min(lb, r) > max(la, l)) {
					if (la < l) {
						u[j].first.first = l;
						u.push_back({ {la,l},u[j].second });
					}
					if (r<lb) {
						u[j].first.second = r;
						u.push_back({ {r,lb},u[j].second });
					}
					u[j].second++;
					used.push_back({ la,lb });
				}
			}
			ld cur = l;
			rep(j, used.size()) {
				ld a = used[j].first, b = used[j].second;
				if (a > cur) {
					u.push_back({ {cur,a},1 });
				}
				cur = used[j].second;
			}
			if (r >cur) {
				u.push_back({ {cur,r},1 });
			}
			sort(u.begin(), u.end());
		}
		else {
			rep(j, u.size()) {
				ld la = u[j].first.first, lb = u[j].first.second;
				if (min(lb, r) > max(la, l)) {
					u[j].second--;
					//cout << u[j].first.first << " " << u[j].first.second << " " << u[j].second << endl;
				}
			}
			for (int j = (int)u.size() - 1; j >= 0; j--) {
				if (u[j].second == 0)u.erase(u.begin() + j);
			}
		}
		loc = v[i].first.first;
		//rep(j, u.size())cout << u[j].first.first << " " << u[j].first.second << " "<<u[j].second<<endl;
	}
	cout << ans << endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(2);
	int t = 1;
	while (cin >> n, n) {
		cout << t << " ";
		solve();
		t++;
	}
	//solve();
	//stop
	return 0;
}



Measured memory_bytes: 3360