Efficient auto-join using Dynamo

[Similar problem in C# has been presented in another post]

[We also offer a custom Dynamo node for this task, see here]


Joining model elements in Revit can be a tedious task. Surely it is something that most of us would like to automate with Dynamo. Hopefully we can easily find some custom nodes that can join elements. We can also do it with Python using a Revit API funtion:

JoinGeometryUtils.JoinGeometry(doc,a,b)

where doc is a current document and a and b are elements to join.

Efficiency problems will occur however, especially in case of more complex models. If we were going to create a script that eg. would try to join every possible wall with every possible floor it would take a considerate amount of time to execute and could produce numerous errors. Such a script would try to join elements that are not connected and often quite remote. This cannot be efficient πŸ™‚

So, before we try to join elements, it is worth checking whether they intersect or not. However, objects can often have a very complex geometry and thus such a check can also be time consuming. Therefore script presented below includes one more step. A preliminary check, that can quickly determine if tested elements are close enough to potentially intersect.

Every model element in Revit has a property called BoundingBox. Exactly as the name suggests, it is a smallest box that can fit the element. It can be relatively quickly tested whether two such boxes intersect or touch. Intersections test are way quicker for boxes than for complex geometry.

The code below takes as an input two lists of elements. Then, it test every element from the first list with every element from the second list – are their BoundingBoxes intersecting or not. As a result it outputs a list of pairs of elements that have intersecting boxes.

import clr

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

def overlap1D(a1, a2, b1, b2):
  if a2>=b1 and b2>=a1:
    return True
  return False
  
def bbIntersect(bbA, bbB):
  return overlap1D(bbA.Min.X,bbA.Max.X,bbB.Min.X,bbB.Max.X) and overlap1D(bbA.Min.Y,bbA.Max.Y,bbB.Min.Y,bbB.Max.Y) and overlap1D(bbA.Min.Z,bbA.Max.Z,bbB.Min.Z,bbB.Max.Z)

#The inputs to this node will be stored as a list in the IN variables.
listA = UnwrapElement(IN[0])
listB = UnwrapElement(IN[1])

output = []

for a in listA:
  bbA = a.get_BoundingBox(None)
  if not bbA is None:
    for b in listB:
      bbB = b.get_BoundingBox(None)
      if not bbB is None:
        if bbIntersect(bbA,bbB):
          output.append([a,b])

#Assign your output to the OUT variable.
OUT = output

This way we get a list of element pairs – potentially intersecting.

Below a Dynamo definition (download at the bottom) that will join all the walls and floors in the project for us:

The last node is also a custom Python piece of code joining two lists of elements:

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

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
#The inputs to this node will be stored as a list in the IN variables.
list_a = UnwrapElement(IN[0])
list_b = UnwrapElement(IN[1])

doc = DocumentManager.Instance.CurrentDBDocument
TransactionManager.Instance.EnsureInTransaction(doc)

output = []

for a,b in zip(list_a,list_b):
	try:
		JoinGeometryUtils.JoinGeometry(doc,a,b)
		output.append("OK")
	except Exception,e:
		output.append(str(e))


TransactionManager.Instance.TransactionTaskDone()

#Assign your output to the OUT variable.
OUT = output
Posts created 40

4 thoughts on “Efficient auto-join using Dynamo

  1. Hey! I’m pretty new to Dynamo, and this script seems great, (I’m trying to make it easier to get a pretty picture if I copy and paste groups of floors for a high rise) but I can’t seem to get it to join anything other than the walls on the ground floor. Am I missing something? Thanks!

  2. Hi, finally I found a graph that works fine so I decided to give you a feedback. I use it for a project of 200 apartments units. At first, when I run the graph, Revit crashed after like 20 minutes with no explanation. It even crashed when I froze the last node (I was trying to find out how many “joins” there are in the project). At the end, I had to split the project in 6 parts. So far I have 5 categories I have to join and it gets pretty tedious. Another thing is that it does not join touching elements (2 walls next to each other). Do you think you it could be possible to add this feature to your script? Good Job!

    1. Hi! Thanks for your feedback! I am happy that it (somewhat) works. If you have large projects you could also try our node package. It has a join node that was written in C# and is much faster and stable. It is available in the Dynamo Package Manager under name ‘Onion’.
      See more info here: http://lubim.co/dynamo-nodes/

      As for the touching elements – in theory it should join such elements, if they are perfectly touching. But there are some know precision problems in Revit. I think the script can be modified to accommodate this imprecision. I will look into that and try to modified the package node. Thanks for the tip! πŸ™‚

Leave a Reply

Your email address will not be published.

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top