Workflow: Manage coordination between spaces and rooms

Original post at: Space-Room coordination

The following workflow uses custom nodes from the packages: “SpringNodes”, “Archi-Lab”, “SteamNodes” and “MEPover”.
There are a few things to consider when managing your spaces:

A: Make sure the levels between the host model and the linked model are aligned;
B: Make sure the levels share the same computation height;
C: Create and coordinate spaces and rooms;
D: Set the limit offset of the spaces.

A. Aligning levels
The first one is easy as this is usually done when setting up your model. I take it everyone knows how to use the copy/monitor function, so let’s skip this step.

B. Set computation heights
If you only have a few levels in your project it is no problem: just manually check the computation height of the linked levels and the host levels and set the same computation height. However, if there are a lot of levels, Dynamo can come in handy. Here’s a simple workflow for setting the level’s computation height:

  1. Find the levels from both the host model and the linked architectural model
  2. With a dictionary you can create a list of keys and a list of associated values. In the example above the keys are the elevation values of the levels from the host model and the values are the levels themselves (also from the host model). After that the ‘search keys’ will look up the values associated with those keys.
    The level elevation values from the linked model are used to return the levels from the host model. By using this workflow you will be able to match levels from the linked model to levels in the host model. If however there are levels which can’t find a matching height, then a null value will be returned.
  3. Retrieve the computation height values from the levels in the linked model and use those to set the computation height of the levels in the host model. In this case the SetParameter node gives a warning, because there is a level in the linked model that can’t find a matching level in the host model (like stated in step 2). This doesn’t have to be a problem, just make sure there aren’t any rooms hosted to that level.
    If there are rooms hosted to that level then the next steps will fail as the spaces we are going to generate always need to be associated to a level.

C. Space creation and coordination
This is the hardest part. There is no single right way to manage the coordination between your spaces and the rooms from the linked model. If you are not in the same office as the architect it’s almost impossible to keep track of the changes in the linked model. It would mean checking every space that no longer has a matching room number and looking for that room’s new location or it could also have been deleted altogether.
I therefore put some thought into creating a workflow that would work for any situation, regardless of the changes to the rooms. The only prerequisite for this to work well is that every room has a unique room number (sadly I still run into a lot of architectural models with duplicate room numbers, even though Revit gives explicit warnings stating that this is actually a bad idea…).
let’s assume that every space has the same number as the room it is associated with. Now whenever you load a new architetural model, the spaces will retain their space numbers (basically the state of the old architectural model). All you need to do is find the difference between the new rooms and the existing spaces. There’s basically three options to choose from:
1: A room number has been deleted
2: A room number still exists in the model (and might have moved)
3: A room number is new

To gather the information above we can use a really useful data structure known as a ‘Set’.
Sets are a collection of unique items upon which you can perform some functions you can’t do as efficiently with lists. Luckily Dynamo has included a few nodes for working with sets. There are 2 important methods that can be used with sets: ‘SetDifference’ and ‘SetIntersection’. Explaining these is best done through an example:

As you can see, this way it’s possible to find out exactly what we are looking for. Now let’s have a look at the next challenge: associating room/space numbers with actual rooms and spaces. We can achieve this by using a dictionary in which the keys are the space/room numbers and the values are the actual spaces/rooms. The output of the dictionaries will be the data to use for creating, managing or deleting the current spaces. Here is the result (with explanation):

  1. First gather the rooms, spaces and their respective numbers.
  2. Use the SetDifference node (room numbers in input 1, space numbers in input 2) in order to have the new room numbers from the linked model returned. Those room numbers are used as input for the dictionary which will return the room elements. Secondly, get those rooms’ locations and use them for the creation of new spaces.
  3. Use the SetDifference node but reverse the input order (space numbers in input 1 and room numbers in input 2). This way the space numbers for which there is no longer a room number available in the linked model are returned. With the dictionary the space elements are returned. All that’s left is to simply delete these spaces.
  4. Find out which rooms and spaces with the same numbers are still in both the models, using the SetIntersection node. With the dictionary we retrieve the space elements. Because this doesn’t tell us whether the rooms and spaces are still in the same location, we need to check their locations and then move the spaces if necessary. Sadly Dynamo doesn’t allow moving spaces to different levels with any of the normal nodes. For this reason I created the node: “Space coordination move to associated room”. This node will find the room in the linked document with the same room number as the space. It will check its location and if that location isn’t the same as the space it will attempt to move the spaces to rooms with the same numbers.

After this make sure that the new space numbers change to match the associated room numbers. After that you can repeat this entire workflow for every new linked model update you receive.

Space number to duct network concatenate

Revit has a built in function that can let you know in which space an air terminal is located. Rhythm has a great node: ‘Element.Space’ for this. Unfortunately most other elements that you’d like associated with a space don’t have access to this space information. The node ‘Space number to network concatenate’ can assign the air terminal’s space number to every upstream element in the connected duct network. While traversing it will concatenate every space number into the parameter with a comma.

The node will stop traversing once it can no longer find an opposing flow direction, encounters a different system classification, encounters an element it has already encountered (and thus has entered some kind of loop) or there is nothing connected to the current element.



  • Air terminal: the starting air terminals from where the traversal into the duct network will start.
  • ParameterName: the parameter of the elements in the duct network to which the space numbers will be written to.
  • Category: only elements of these categories will have their parameter written to. Supports multiple categories.
  • SizeLimitFactor: an optional input that controls how far into the network the parameters will be written. The node will stop when the element’s size in the network is ‘factor’ times as big as the starting size. The default is set to 20.


  • The input elements are returned unless the air terminal is not located in a space, in which case a string indicating no space is found is returned.

The node can be found in the MEPover package version 2017.2.13 and up.

MEPover Node Index

Created by Taco Pover, MEPover is a package for working with MEP elements and focuses on creating pipes, ducts, cable trays and conduits and extracting MEP-System information.

For most of the nodes more detailed information can be found here: MEPover nodes

Current Node List:

CableTray.ByLines Creates CableTray by Lines, CableTrayType, Level, Width and Height
Conduit.ByLines Creates conduits by Line, ConduitType, Level and Diameter
Duct or pipe systems all elements Returns all the elements in the provided systems
Duct upstream components by category This node will try to return the connected elements in the upstream network. It will stop once it encounters an element twice or encounters a different system classification or cannot find a connector with an opposing direction. The output can be filtered by input Categories
Duct upstream components This node will try to return the connected elements in the upstream network. It will stop once it encounters an element twice or encounters a different system classification or cannot find a connector with an opposing direction.
DuctRectangular.ByLines Create ducts by Lines, DuctType, MechanicalFittingType, Level, Width and Height
DuctRound.ByLines Create round Ducts by Lines, DuctType, SystemType, Level and Diameter
Elbow.ByMEPCurves Takes in a list of MEPCurves (pipe, duct, cable tray, conduit)  and will attempt to create elbows where possible. A margin can be entered for max distance between connectors
ElectricalCircuit Get Panels and Elements Returns the Panels and Elements belonging to the given electrical circuits
ElectricalFitting connector count Returns the number of connectors on the cable tray or conduit fitting
Element.ConnectorSystemType Returns the MEP System Type of the connectors of the element
Element.Domain Returns the domain of connectors on the element i.e. (domainHvac, domainPiping etc.)
Element.ElectricalCircuit Returns the electrical circuit of the element
Element.System Returns the mechanical or plumbing system of the element
Elements in view by category Returns all the elements in the selected view(s) by the selected categor(y)(ies)
Family types of family Returns every family type of the given Family
GetParameterAsProjectUnits Returns the parameter value in the same unit type as the project settings
GetParameterAsValueString Returns the parameter values without conversion to the revit internal unit system. The suffix boolean toggles the project units on or off
Mechanical System Graphic Override set LineColor Sets the linecolor of the mechanical system graphic override
Mechanical System Graphic Override set LinePattern Sets the line pattern in the mechanical system type’s graphic override
Mechanical System Graphic Override set LineWeight This will change the lineweight override of the mechanical system type
MechanicalFitting info Gets the fitting Part Type and number of connectors
MEP connector info Returns location, connector info and connected elements
MEP Curve connected fittings Returns the fittings, ducts accessories and terminals connected to the given duct, cable tray, pipe or conduit. Also return air terminals on Ducts
MEP Fitting connected MEPCurves Returns the pipes, ducts, conduits or cable trays that are connected to the given fittings
MEP Fitting TakeoffFitting (Tap) Create a new TakeoffFitting or Tap by takeoff pipe and through pipe
MEPFitting.ByMEPCurves Creates a UnionFitting or ElbowFitting by 2 MEPCurves (Ducts, Cable Trays, Pipes or Conduits).
Pipe.ByLines Creates a pipe by Line, PipeType, SystemType, Level and Diameter
Room or Space reset center location This node will attempt to reset the location of the room or space to its default center location
Rooms place automatically for all levels This node will attempt to create rooms automatically for every level
SetParameterAsProjectUnits Sets the parameters by project unit inputs, no need to convert to Revit internal units first.
SetParameterSetValueString Sets the parameters by strings. Useful for setting numerical values that are affected by Revit’s internal  unit conversion. Does not work for parameters that are stored as elementId
Space number to duct network concatenate This node will attempt to write the space numbers to connected duct objects in the network. Input AirTerminals need to be placed in spaces. ParameterName is the parameter to write the space number to. Numbers will be concatenated if they serve multiple spaces. Multiple Categories supported
Space number to duct network This node will attempt to write the space number to connected duct objects in the network. Input AirTerminals need to be placed in spaces. ParameterName is the parameter to write the space number to. Numbering stops when it encounters an element from another space. Multiple Categories supported
Tag Get Location Returns the location of the tags
Tag Get View Return the view on which the tag is placed
View.GetCropBoxCurves returns the curves of a view crop box, even irregular shapes. Returns an empty list if the crop view is not active for a given view
View.SetCropBoxCurves Input views and lists of curves to set the view crop regions
View.ViewRange absolute Returns the 4 view range values relative in absolute Z values
View.ViewRange relative Returns the 4 view range values relative to the view’s level