2019-07-13

Saving time: Optimizing a Dull Structural Task with Dynamo

I have the pleasure today of hosting a guest blog post, from a longtime Twitter friend that I was fortunate enough to meet up with in person this year, Tom Kunsman! As if working in this industry isn't cool enough, we also bond over our love of Legos and Space Science! 

Before we get to Tom's article on saving time with Dynamo, here are some links to past articles from guest authors: 


Saving time: Optimizing a Dull Structural Task with Dynamo 

Dynamo is often used to not just create parametric geometry, but to optimize workflows and maximize project efficiency.

Recently, I was working on a structural project and was slogging through one of those very repetitive tasks. This was, of course, the manual editing of a dimension on a beam system, in order to place the label below them which specifies the number of structural members and spacing required between them.


As I trudged through this task, I realized that Dynamo could be leveraged to perform this task, in less time than it would take to do manually. The data for all the members and spacing was available in the system family parameters already, so all we had to do was find a way to tap into it and put it where we want it.  

1.     Beam Framing Systems and Their Parameters

First, let’s look at a framing bay, to understand what information we are trying to gather (notice the values below the dimension segments).


Initially, when I began working through this problem, I was going to have users select the beam system, then the dimension, but relating the two pieces of data proved difficult.

One of the more frustrating aspects of Revit is the inability to access all of the parameters with in a project, when you want to use them in tags or with other parameters. Take a look at the parameters of the beam system. Note that “Centerline Spacing” is grayed out, which means that the user cannot modify this value.


Thankfully, with Dynamo, we can access this information, along with the “Number of Lines” value, to apply to the dimension spacing.

NOTE: This access has the added benefit of eliminating the opportunity for user error.

1.     Building a Solution in Dynamo

Instead of continuing to attempt to find native Revit options, I decided to turn to the amazing Dynamo community of users. And, since I was using custom nodes from a package called Rhythm, I sought assistance directly from the package author, John Pierson.

After brainstorming for a bit, we came up with this simple graph:


We’ll take a look at each group of nodes, by function, to understand the logic.

A.     Gathering User Inputs

The first step in our process is to select the multi-segment dimension that we wish to have the beam system values written to. This can be done with a simple Select Model Element node and a Number Slider node. Keep reading, if you aren’t sure why I included the number slider.


TIP: Renaming a node can be done simply by double-clicking on the title of the node and typing in a new label. Renaming nodes can help new Dynamo users more quickly understand which nodes require user input or selection.

I have renamed the “Select Model Element” node to read “Select Dimension”, and “Number Slider” has been changed to “Buffer for Dimension”.

A.     Collect and Compare Beam Systems

Next, we need to grab the structural beam systems, along with their bounding boxes. This is accomplished through the use of the following nodes: Categories, All Elements of Category and Element.BoundingBox.


A.     Projecting the Point and Generating the Bounding Box

Obtaining the underlying geometry of a multi-segment dimension is difficult. The end result actually places a point at the mid-point of each segment, and then copyies and offsets that point until it intersects the beam system.

With this method, Dynamo can understand which segment of a dimension corresponds to which beam system. Basically, we are playing laser tag with the dimension and the beam systems, which actually mimics what a user would do manually.
  1. Find the related dimension string
  2. Scan over and locate the beam system to pull data from
  3. Push the data to the dimension string

By using the Dimension.GetCurve node, we can place a point at the mid-point and then generate a curve along the normal vector from that point. This is where the “buffer for dimension” Number Slider gets input to the Geometry.Translate node.

This translate node places another dynamo point at a distance away from the midpoint of each of the selected multi-segment dimensions, which is how we are able to grab the related beam system. Since the dimension will not intersect the system, we simply project a point of our own towards it.

The last node in this group is the BoundingBox.ByGeometry. This generates the bounding box of the point that was offset from the mid-point of the dimension line. We will then look to see if the bounding box of this point intersects with the bounding box of the beam system.

A.     Select Objects to Check

The next step is performed by this group of nodes, which does an intersection check between the bounding boxes.



In the BoundingBox.Intersects node we input the Structural Beam System collection to the boundingBox input and for the other input we use the data from dimension point and translation group that was mentioned above.

Flowing from the BoundingBox.Intersects node we use the IndexOf node.

We also use a Code Block node with a true statement. So, we are ONLY selecting beam systems that do intersect with the offset midpoint of the selected dimension.

The remaining nodes: List.AllIndicesOf, List.RemoveItemAtIndex and the second Code Block, with the value of negative one, will remove any Beam System that may have been misplaced or does not have a corresponding dimension.

A.     Get the Index of the Beam System

Next, we need to get the Beam System index, and for that we can use the List.GetItemAtIdex node.

For the list port we feed a wire from the All Elements of Category from when we had selected all of the beam systems.
With the index port we wire in the list output from the List.RemoveItemAtIndex node. Again, this just helps to eliminate any misplaced beam systems in the current view.



A.     Obtain the Dimension Value of the Beam System



We need to get the dimension value of the beam system, which is where this group of nodes comes in.


The first step in getting the dimension value of the beam system is to use the Element.Parameters to get the parameters.

Next, we need to get the String value from that object with the String from Object node. This enables us to search for and isolate just the centerline spacing.

After converting to a string, we can then search for the centerline spacing by using String.Contains and a Code Block with “Centerline Spacing”.

NOTE: Dynamo and Revit require exact spelling and case sensitivity.

This can be done with the List.FilterByBoolMask node. The String.Split node groups the Centerline Spacing with the associated value associated with the spacing. This is helpful because we get the user-understandable value of the dimension and not the decimal value.

A.     Assemble the String

Now it’s time to build the string (text value) that will be written below the dimension value.


In the first part of this group we have the Rhythm node BeamSystem.Members, which obtains the framing members from the beam system. For the Beamsystem input port, we connect a wire from the List.GetItemAtIndex node while we were .

This gets connected to the Count node, allowing us to obtain the number of beams from the framing system.

From the group where we obtained the dimensional value of the beam spacing (the centerline spacing), we connect the String.Split to the List.LastItem, since we only need the spacing value from that list.

You can use a simple + (addition) node and a Code Block to add one to the number of lines. This is what builds our custom below value for dimensions (the part which used to be manual).

In our final step, we need to use the Dimension.SetBelowValue node from the Rhythm package. For the dimension port, we feed in the Dimension line that we picked all the way back in the beginning of this logic, with the Select Dimension node.

Finally, for the belowValue port, we feed in the wire from the Code Block where we had added the count of the number of beams and the spacing.

A.     Placing the Annotation

After the user runs this script, Revit places a Dynamo point at the midpoint of each segment of the multi-segment dimension line as well as a Dynamo point offset from that point.

NOTE: This offset point needs to be within the beam system you are trying to reference. 

NOTE: Remember our “buffer dimension”? This buffer dimension may need to be modified depending on how far the user has placed the dimension line from the beam system.

1.     Summarizing our Dynamo Solution

So, the next time you need to specify the number of members in a framing system, and the spacing between them, keep in mind that you can automate the process with the following Dynamo workflow:

A.     Have the user make selections and input the required tolerance
B.     Collect and compare your beam systems
C.     Project points and generate corresponding bounding boxes
D.     Select objects to check
E.     Obtain the index of the beam system
F.     Assemble the data string
G.    Place the data string below it’s related dimension

Stepping through your process in a Dynamo graph is important, because not every project is the same. Building flexibility into our graphs in this manner sets us up for success. As always, I would encourage you to test any script like this out on a test project, before using it in production.

I hope this example can demonstrate to any structural designers and engineers who may not already be aware, just how they might be able use Dynamo on a project with beam systems. That might spark other ideas, too, because utilizing a script on a mundane task can also save so much time and effort.

Much of the logic behind this solution was provided by John Pierson. Using my initial thoughts and the resulting idea for improvement, John was able to expand upon what I provided and assist with the onerous task of obtaining the dimension geometry.

Tom Kunsman is a structural designer with over 20 years’ experience and continues to find ways to utilize Dynamo in structural and other disciplines. He has experience in BIM Execution Plans BxP, Revit family content creation in all disciplines, and continues learning how to adopt or improve established BIM workflows. 
Twitter: @tkunsman 

John Pierson is a Design Technology Specialist at Parallax Team and a Revit certified professional for all disciplines. He is an active member of the Dynamo community and currently manages the Dynamo package called Rhythm. 
Twitter: @60secondrevit


Before you go, please take 3 minutes out of your day to participate in the AUGI Annual Salary Survey. https://www.surveymonkey.com/r/2019AUGISalarySurvey