BCF Reader Update

This post is long overdue, but I finally take the time to update my BCF Reader.


First of all, I have tested it on a larger set of BCF files, and I hope these will make it more robust, especially if something is wrong within the BCF file. My experiences include files coming from Tekla BIMSight, Matteo Cominetti’s BCFier and Kubus BIM Collab.

I have to remove the support for Word 97-2003 Documents (*.doc), since the library I use does not support them. I will see how I can integrate them back in a future release.

Among the change, I add a small progress bar to allow you to pour yourself a coffee when dealing with huge quantities of notes.

I also add Status and Verbal Status to the report, just after the date. A more subtle change, the default path to save your report is now the same than the BCF file itself.

I improve the Readme file to include a small explanation on how to use the BCF Reader.

I spotted some problems with styles in the Word template. To be sure to have all of them available in the BCF Reader, you must write a few lines in your Word template, apply your styles to them, then delete them. This will ensure that you have created these styles in your Word template before using it.

Finally, I want to thank Julien Benoit and François Lahouste for their comments and their files.

As usual, you can download the BCF Reader here, and check the code here.


Today, it will not be a blog post but an invitation.

Next week, the BIM World event will be held in Paris. This event will gather a large panel of architects, engineers, contractors, manufacturers, and software developers, all interested in Building Information Modeling and related technologies.


I will be representing my company Ingérop here, and will present our last projects using BIM.


I will also give a short speech “Développer les compétences du BIM” about implementing Building Information Modeling in an engineering consultancy firm, and the consequences of this paradigm shift.

I would be happy to meet you there and exchange with you, so if you happen to be in Paris next week, the exhibition will be held on Wednesday and Thursday at the CNIT Center in La Défence.

See you there ….

Insulation Tag

I am not very fond of duct and pipe insulations in Revit. If the concept is very useful, I find difficult to add and edit them. Furthermore, seeing the insulation on every duct and pipe can quickly clutters the view. We want to know how much insulation we have, but we don’t want to see it everywhere.

In a technical drawing, we generally represent insulation only on small parts of the duct, with an annotation, and then infer that the duck is covered everywhere else.

To adapt this method on Revit, I create two detail components, representing the insulation on a round and on a rectangular duct.


This components have a “Width” instance parameter for setting their width regarding the thickness of the insulation.


I also create a small piece of code to instantiate these components on selected ducts and pipes.

The idea is to pick a series of duct and pipe, read their insulation thickness, and add a detail component with the corresponding thickness. Like this, we can control where we want to see an insulation, and improve the overall legibility of the drawing.


This solution allow me to create quickly some annotations to represent the insulation without having to display it everywhere. However, this is more a workaround than a real solution. Nothing here is adaptive, and you have to restart the tool each time you edit or even move your duct.

public void InsulationTag()
			UIDocument uidoc = this.ActiveUIDocument;
			Document doc = uidoc.Document;
			Reference r = null;
			//Retrive the two symbols
			FamilySymbol rectangularSymbol = null;
			FamilySymbol roundSymbol = null;
			ICollection<Element> collection = new FilteredElementCollector(doc).OfClass(typeof(FamilySymbol)).OfCategory(BuiltInCategory.OST_DetailComponents).ToElements();
			foreach (Element element in collection)
				FamilySymbol current = element as FamilySymbol;
				// This NewFamilyInstance overload requires a curve based family
				if (current.Family.Name == "DuctInsulationAnnotationRectangular")
					rectangularSymbol = current;
				else if (current.Family.Name == "DuctInsulationAnnotationRound")
					roundSymbol = current;

				while (true) {
					using( Transaction t = new Transaction( doc ) )
						t.Start( "Annotate Insulations" );

						r = uidoc.Selection.PickObject(ObjectType.Element, new SelectionFilter(),"Pick a duct");
						if (r != null)
							MEPCurve mepCurve = doc.GetElement(r.ElementId) as MEPCurve;
							//Get the middle of the duct
							LocationCurve locCurve = mepCurve.Location as LocationCurve;
							XYZ insertionPoint = locCurve.Curve.Evaluate(0.5,true);
							//Get the angle
							XYZ vector = locCurve.Curve.GetEndPoint(1) - locCurve.Curve.GetEndPoint(0);
							double angle = new XYZ(1,0,0).AngleTo(vector);
							//Get the insulation
							ICollection<ElementId> insulationIds = InsulationLiningBase.GetInsulationIds(doc,r.ElementId);
							if (insulationIds.Count !=0)
								InsulationLiningBase insulation = doc.GetElement(insulationIds.First()) as InsulationLiningBase;
								if (insulation != null)
									FamilySymbol symbol = null;
									double widht;
									try {
										widht = insulation.Width;
										//Select the detail familly
										symbol = rectangularSymbol;
									} catch (Autodesk.Revit.Exceptions.InvalidOperationException) {
										Parameter outerDiameter = mepCurve.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
										if (outerDiameter != null)
											widht = insulation.Thickness*2 + outerDiameter.AsDouble();
											widht = insulation.Diameter;
										//Select the detail familly
										symbol = roundSymbol;
									//Create the annotation
									FamilyInstance annotation = doc.Create.NewFamilyInstance(insertionPoint,symbol,doc.ActiveView);
									//Change the witdh
									//rotate the component
									annotation.Location.Rotate(Line.CreateUnbound(insertionPoint,new XYZ(0,0,1)),-angle);

			catch( Autodesk.Revit.Exceptions.OperationCanceledException )

public class SelectionFilter : ISelectionFilter
		#region ISelectionFilter Members

		public bool AllowElement(Element elem)

			if (elem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctCurves) return true;
			if (elem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves) return true;

			return false;

		public bool AllowReference(Reference refer, XYZ pos)
			if (refer.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_NONE) return false;

			if (refer.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_SURFACE) return true;
			if (refer.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_LINEAR) return true;

			return false;