Room Boundaries with Dynamo

Ever wanted to create a bunch of finishing walls and floors using pre-existing rooms in a large REVIT project? I recently did and these are my findings.

To tackle the problem you can go down two different roads: either write a custom API command or use Dynamo. Yes, Dynamo, that GH-like tool I was willing to test but handn’t find the time to. So after giving a fast try to the API and finding some hiccups with the selection of FloorTypes and WallTypes, I decided to give Dynamo a try.

If you don’t know anything about Dynamo I recommend you read this Q&A with its Authors

Computational BIM

I love the concept of computational BIM as much as I love the way REVIT treats data. It’s huge consistency across the whole platform makes it perfect for a tool like Dynamo, however, most of the domestic issues I’ve ever faced in a project could be solved by using that same consistency through family edition, schedules and normal user interface. Besides, for more geometrically complex problems I have been using Grasshopper for several years, so until now I hadn’t found the right problem to tackle with Dynamo. Until now.

That portion of problems where a GH-like approach to REVIT entities and operation is what I understand as Computational BIM, or, put in other words, the kind of problems that have little to do with geometry, roofs, adaptive components.

Being an experienced GH user might help you in understanding the workflow of Dynamo but I suggest you forget for a while about the way you script components, deal with trees and datatypes in GH, else you’ll have a hard time. Dynamo has a different approach to many things:

  • You don’t bake things but act on REVIT elements that get created or updated when something changes in your definition.
  • Nodes can be created in a similar way to GH Clusters with the interesting advantage of allowing inserting them in the same node, in a recursive fashion.
  • Nodes can also be scripted directly using Python and accessing REVIT entities and API tools through wrappers (I wished I understood what a wrapper is)
  • Available tools depend on whether you’re working on a Project or a Family file.
  • Code blocks are like GH panels with super-powers. Check here.

In my opinion, Dynamo has a great phylosophical advantage against GH, it is completely OpenSource, which has made its community quite strong and expert in less time. There is a lot of information out there, just check the Dynamobim.org site

Room Boundaries

Let’s get down to the issue. I wanted to retrieve the boundary of all the rooms in my document in order to use them to create a finish floor and walls using that boundary.

First, and main problem, is that there is no direct way, not that I was aware of, to retrieve the boundary of a room once you select it. So to do so you have two options:

  • Use Nathan Miller’s LunchBox package, which you can download by clicking Packages > Search For Package and once installed, use the Lunchbox Room Elemenent Collector.
  • Script your own Dynamo Node.

Which one do think I picked? 🙂

The best way to get started with Dynamo Scripting I found is to read this page on the Dynamo GitHub repository . This post also resulted quite useful.

Let’s have a look at the code, I tried to add comments to make it clearer.

#This script was composed by Roberto Molinos - www.modelical.com

import clr
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

# Import ToDSType(bool) extension method, not sure we need this
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# Make sure the GeometryConversion utilities are accesible see https://github.com/DynamoDS/Dynamo/issues/1946
clr.ImportExtensions(Revit.GeometryConversion) 

# Unwrap
rooms = []
for i in IN[0]:
	rooms.append(UnwrapElement(i)) #This kind of opens the Revit element so it can be used by Dynamo Script
# Curve array
curves = []
# Boundary options for rooms
opt = SpatialElementBoundaryOptions()
# Iterate through every room
for room in rooms:
	if room.Area > 0: # Make sure it has positive Area, i.e is placed
		rvBoundary = room.GetBoundarySegments(opt) # Get room boundary
		dsBoundary = [] # A Dynamo list to hold the boundary per room, remember it can be complex, with holes		
		for rvLoop in rvBoundary: # For each loop in the room boundary
			dsLoop = [] # A list to hold each room's loop
			for rvPiece in rvLoop:	# Retrieve each segment of the loop
				dsPiece = Revit.GeometryConversion.RevitToProtoCurve.ToProtoType(rvPiece.Curve,True) # Read the segment as Curve and convert to Dynamo geometry
				dsLoop.append(dsPiece) # Add the piece to the Dynamo Loop
			dsBoundary.Add(dsLoop) # Add the Dynamo Loop to the Dynamo Boundary
		curves.append(dsBoundary) # Add the Dynamo Boundary per room to the Curves list
#Output
OUT = curves

Here you can see the whole definition, click to download it: Modelical-RoomBoundaries

And, if you click on the RUN button within a file with some rooms in it, just like I did, you should get something like this.

You may notice there’s another Scripting Node in my definition. Just a tiny piece of code which reuses most of the large one, to find the thickness of the wall type selected.

#This script was composed by Roberto Molinos - www.modelical.com

import clr
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

# Unwrap
walltype = UnwrapElement(IN[0])

#Output
OUT = walltype.Width

And this is where I see the strongest point of Dynamo: If you’re a bit familiar with Revit API you can access almost any parameter with ease and use it you your benefit.

Let me know your thoughts!

3 comments on “Room Boundaries with Dynamo”

  1. Hello how can i do room separator and curtain walls ignores and Do not build the wall

  2. Hi Roberto, I’m not sure which Revit version you used for the script, but as far as I know, the BoundarySegment class doesn’t have a Curve method from 2022 onwards, or perhaps even earlier. In my code, I replaced it with GetCurve() method and it worked. I also replaced Add with append in dsBoundary.append(dsLoop). Apart from that, it works smoothly 🙂 Many thanks!”

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit exceeded. Please complete the captcha once again.

  • Before submitting your inquiry, take a look at the basic information on data protection here.

    Modelical.com informs you that the personal data you provide will be processed by MODELICAL CONSULTORIA S.L. as the party responsible for this website.

    Purpose of the collection and processing of personal data: To send the information that the user requires through the website. - Legitimation: Consent of the interested party. - Recipients: Hosting: Gigas, 100% Spanish and 100% secure hosting. - Rights: You may exercise your rights of access, rectification, limitation and deletion of unsubscribe@modelical.com data as well as the right to lodge a complaint with a supervisory authority.