Shared family

The Shared checkbox in the Revit family editor allows us to use nested families just like the root one.

SharedCheckBox

Checking the Shared checkbox is only useful when this family is nested into another. When you load the root family into your project, Revit will also load the nested one. You will then be able to see it in the Project Browser and in schedules, and your shared family will behave just like any other families, except that it is nested into another.

This function is very useful to insert additional elements upon existing ones, according to specific rules.

As an example, I add a light switch to a door family. This light switch is wall-based, and will appear alongside of every doors in the project. As this light switch is a shared family, these instances appear on the electrical fixture schedule.

Visible

Furthermore, these nested families only appear in schedules if they are visible in the project. I use this property to select on which door I want a light switch. I add a Yes/No parameter on my family to control the visibly of the switch. Once hidden in the project, the switch doesn’t appear in the schedule either.

Hidden

Using shared families is a very efficient way to insert elements in a model, and is a good starting point for rule-based modeling.

But once every light switch families have been inserted in the model through their host, we generally want to be able to adapt the position of some of these elements.

To do so, I wrote a few lines of code to create a copy of every nested light switch directly in the model. These new light switches are no longer nested, and can be easily modified to fit the local configuration. Furthermore, these elements are now electrical fixtures families, and can be added to an electrical circuit to perform load calculations.

Extracted

 

public void ExtractNestedFamillies()
{
	
	UIDocument uidoc = this.ActiveUIDocument;
	Autodesk.Revit.DB.Document doc = uidoc.Document;
	
	//Select a family instance
	FamilyInstance fi = doc.GetElement(
		uidoc.Selection.PickObject(
			ObjectType.Element ).ElementId )
		as FamilyInstance;
	
	// Create a filter to retrive all instance of this family
	List<ElementFilter> filters = new List<ElementFilter>();
	foreach (ElementId symbolId in 
			 fi.Symbol.Family.GetFamilySymbolIds()) 
	{
		filters.Add(new FamilyInstanceFilter(doc,symbolId));
	}
	ElementFilter filter = new LogicalOrFilter(filters);

	// Apply the filter to the elements in the active document
	FilteredElementCollector collector = 
		new FilteredElementCollector(doc);
	ICollection<Element> familyInstances = 
		collector.WherePasses(filter).ToElements();
	
	using (Transaction tx = new Transaction(doc)) {
		
		tx.Start("Extract Nested Familes");
		
		//Loop on all family instances in the project
		foreach (Element element in familyInstances) {
			
			FamilyInstance instance = element as FamilyInstance;
			
			ICollection<ElementId> subElementsIds = 
				instance.GetSubComponentIds();
			
			//Loop on all nested family
			foreach (ElementId id in subElementsIds) {

				Element ee = doc.GetElement(id);
				FamilyInstance f = ee as FamilyInstance;
				
				//The fammily is face based
				if (f.HostFace != null)
				{
					Element host = f.Host;
					Face face = host.GetGeometryObjectFromReference(
						f.HostFace) as Face;
					LocationPoint locPoint = f.Location as LocationPoint;
					doc.Create.NewFamilyInstance(
						face,locPoint.Point,f.HandOrientation,f.Symbol);
				}
				//The fammily is host based
				else if (f.Host !=null)
				{
					LocationPoint locPoint = f.Location as LocationPoint;
					Level level = doc.GetElement( f.LevelId) as Level;
					
					FamilyInstance fam = doc.Create.NewFamilyInstance(
						locPoint.Point,f.Symbol,f.Host,
						level,StructuralType.NonStructural);
					
					//Flip the family if necessary
					if (instance.CanFlipFacing)
					{
						if (instance.FacingFlipped) {fam.flipFacing();}
					}
					if (instance.CanFlipHand)
					{
						if (instance.HandFlipped) {fam.flipHand();}
					}
				}
				//The family is point based
				else
				{
					LocationPoint locPoint = f.Location as LocationPoint;
					Level level = doc.GetElement( f.LevelId) as Level;
					doc.Create.NewFamilyInstance(
						locPoint.Point,f.Symbol,level,
						StructuralType.NonStructural);
				}
			}

		}
		
		tx.Commit();
	}

}

Automatic Modeling

Most questions I encounter these days turn around using building information modeling for producing construction drawings, schedules or clash detection reports. These features are important, of course, but they remain centered around using a more or less complete building model. But a largely overlooked use of building information model is the ability to automatically model building elements. In fact, object-oriented modeling should allow us to simply describe our solutions and let the computer implement them in our building model, and even warn us when something doesn’t fit.

Lead by this thought, and a problem raised by one of my colleague, I started looking again toward slab insulations. Before BIM, slab insulation was simply annotated on the drawing, and taken into account when creating a building section. Now, for coordination purpose, we have to spend large amount of time modeling everywhere a fairly simple element like insulation, without real added value.

There is nothing new with this problem, and I was already trying to find a solution for modeling insulation layers on the upper face of a series of spaces with my latest version of RoomFinishes, without finding a decent solution.

But while looking for something totally different, I came across this article in AUGI about room and spaces in Revit. So after five years working with Revit, I realized than by checking this small checkbox in the “Area and Volume Computations”, the room continues up until it fit a room bounding element, a ceiling or a floor.

VolumeComputation

Energized by this nice discovery, I created a small application for automatically modeling insulation. This application retrieves every faces of a given room, and uses the higher ones as references for modeling floors and walls as insulations.

Insulation

The only problem here is framing. They are not room bounding elements, and the upper face of the room does not fit the shape of the beam. I solved temporary this problem by creating a small floor under the beam.

beam

While doing this, I realized there is a lot of tricky cases, where insulation have to be modeled as wall or slab regarding of the configuration.

The entire code for this application can be found here. It is quite messy, but I hope it can help you anyway.

This small example illustrates one of the possibilities of working with building information models, where information can actually help us focus more on the actual design of the building and less on the representation of this design in the model.

IfcPropertySet

A very interesting feature of the IFC model is the IfcPropertySet . According to the official IFC specification, the IfcPropertySet is “a container class that holds properties within a property tree”. This allow to add user-defined properties to IFC elements or types. To make an analogy with Revit, it is pretty much like creating shared parameter.

Since the IFC exporter for Revit is accessible as open source code, a new exporter have been developed, and offer far more control over the creation of IFC files from Revit. One of the improvement is the ability to select Revit properties to be exported as IfcPropertySet.

The default option only export common IFC properties, but you can also export the entire set of Revit properties, or just selected ones, through user-defined property sets.

IFCExportProperties

To create one, I download one of the example coming along with the source code of the new exporter.

In this example, we can see the global syntax for creating user defined property sets.

I use it to create my own PropertySet Definition File, and use it to export Creation Phase and Demolition Phase to a new PropertySet called Phases.

PropertySet:     Phases     I     IfcElement
Creation Phase     Text     Phase Created
Demolition Phase     Text     Phase Demolished

In this definition file, we set up the name of the PropertySet, its use (on instances or on types) and the list of elements were we want to apply our properties.
Then we add the mapping between IFC (left member) and Revit properties (right member), along with its data type (Text, Real, Integer or Boolean)

We add this file in the IFC Export configuration, and export our IFC file. We can now see these properties appearing under the Phases set :

Before :

Before

After :

After

If IFC export and import is still not powerfull enought in many software solutions to enable geometrical modifications directly in the IFC file, there are plenty of opportunities to add metadata to the element, directly in IFC.