using System;
using System.Collections;
using System.Collections.Generic;
 
class TEST{
	static void Main(){
		while(true){
			int n=int.Parse(Console.ReadLine());
			if(n==0)break;
			Sol mySol =new Sol(n);
			mySol.Solve();
		}
	}
}

class Sol{
	public void Solve(){
		double PI=Math.PI;
		//偏角は0<=t<2*PI　で記述する
		List<Circle> LC=new List<Circle>();
		for(int i=0;i<N;i++){
			var d=rda();
			LC.Add(new Circle(d[0],d[1],d[2]));
		}
		
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++){
				//i:自分 j:相手
				if(i==j)continue;
				double dX=LC[j].X-LC[i].X;
				double dY=LC[j].Y-LC[i].Y;
				double d=Math.Sqrt(dX*dX+dY*dY);
				double r=LC[i].R;
				double R=LC[j].R;
				
				if(d>=r+R){//離れている
					continue;
				}
				if(R>=d+r){//含まれる→全周を除外
					LC[i].MergeAngle(new Interval(0,2*PI));
					continue;
				}
				if(r>=d+R){//含む→除外無し
					continue;
				}
				
				//d==0のケースは除外済み（含む or 含まれる）
				//（まったく同じ円が2つある時には両方除かれる（問題文から無しと判断する））
				
				
				//dの偏角を求める
				double darg=Math.Acos(Math.Abs(dX)/d);
				if(dX>=0 && dY >=0){;}
				if(dX<0 && dY >=0){darg=PI-darg;}
				if(dX<0 && dY <0){darg=darg+PI;}
				if(dX>=0 && dY <0){darg=2*PI-darg;}
				
				//除外される円周角を求める
				double ang=Math.Acos((r*r+d*d-R*R)/(2.0*r*d));
				Interval I=new Interval(darg-ang,darg+ang);
				if(I.L>=0 && I.R<2*PI){
					LC[i].MergeAngle(I);
					continue;
				}
				if(I.L<0){
					I.L=0;
					LC[i].MergeAngle(I);
					I.L=2.0*PI+darg-ang;
					I.R=2.0*PI;
					LC[i].MergeAngle(I);
					continue;
				}
				if(I.R>2.0*PI){
					I.R=2.0*PI;
					LC[i].MergeAngle(I);
					I.L=0.0;
					I.R=darg+ang-2.0*PI;
					LC[i].MergeAngle(I);
					continue;
				}
			}
		}
		
		double ans=0.0;
		for(int i=0;i<N;i++){
			double ang_rest=2.0*PI;
			for(int j=0;j<LC[i].Angles.Count;j++){
				ang_rest-=LC[i].Angles[j].Length;
			}
			ans+=LC[i].R*ang_rest;
		}
		Console.WriteLine(ans);
		
	}
	int N;
	public Sol(int n_){
		N=n_;
	}

	class Circle{
		public double X;
		public double Y;
		public double R;
		public List<Interval> Angles;//常にdisjoint union になっている。
		public Circle(double x_,double y_,double r_){
			X=x_;Y=y_;R=r_;
			Angles=new List<Interval>();
		}
		public void MergeAngle(Interval I){
			List<Interval> Next=new List<Interval>();
			double r=I.R;
			double l=I.L;
			for(int i=0;i<Angles.Count;i++){
				if(Angles[i].R<l || Angles[i].L>r){
					Next.Add(Angles[i]);
					continue;
				}
				r=Math.Max(r,Angles[i].R);
				l=Math.Min(l,Angles[i].L);
			}
			Next.Add(new Interval(l,r));
			this.Angles=Next;
		}
	}
	
	class Interval{
		public double L;
		public double R;
		public Interval(double l_,double r_){
			L=l_;R=r_;
		}
		public double Length{get{return R-L;}}
	}
	
	


	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(){return Console.ReadLine().Split(' ');}
	static int[] ria(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>int.Parse(e));}
	static long[] rla(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>long.Parse(e));}
	static double[] rda(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>double.Parse(e));}
}

Measured memory_bytes: 5964