Dynamo Users Meet-Up

If you’re living in United Kingdom and you’re interested in Dynamo, computational design and automation, I strongly recommend getting involved with UK Dynamo User group. So far I’ve attended two meetings and it was a time well spent! Each meeting consists of 3-4 longer presentations and quick round of tips & tricks from other users. When the official part is over, there’s time for casual networking and it usually involves a pub nearby. In terms of topics covered on those meetings, some of my favorite lectures were about macros, add-ins, modelling from point cloud, computational design in structural engineering and linking Revit with Power BI.

Here’s a picture from May meeting, you can even spot me there:You can find them here, there’s an event happening in Manchester, 7th September.

Watch out when the tickets are out – because they might be gone within an hour!

Painting walls using Dynamo

Hello again! As it turns out, moving all your livelihood to a different country is quite an absorbing process and I had to skip on my blogging for a bit. But now I’m back and…

 

…picture a massive hospital model in Revit that’s in dire need of painting. The default tool for applying paint is not the most efficient one to say the least and the deadline is approaching. What do you do? Since taking a holiday break was not an option, my second guess was to use Dynamo for that.

This script can be broken into two parts.

First part deals with sorting the walls per width and base constraint. To my surprise, the former wasn’t as straight forward I thought (It might have something to do with family structure for “Walls” category). In order to get the value of width, I used the following combination of two Python scripts:

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
items = UnwrapElement(IN[0])
typelist = list()
for item in items:
      try:
        typelist.append(item.Document.GetElement(item.GetTypeId()))
      except:
        typelist.append(list())
OUT = typelist

and:

check = IN[0]
items = IN[1]
     if isinstance(check, (list)): OUT = items
else: OUT = items[0]

Combining those two with some basic BoolMasks leaves me with a list of walls-to-be-painted. Now to the second part – applying paint.

I must admit, my Revit API game isn’t the strongest, so to get this (simple, I know) script working I had to consult it with a colleague of mine. The final product is as follows:

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc =  DocumentManager.Instance.CurrentDBDocument

elems = UnwrapElement(IN[0])
paintmat = UnwrapElement(IN[1])

TransactionManager.Instance.EnsureInTransaction(doc)
for elem in elems:
     for geo in elem.get_Geometry(Options()):
             for face in geo.Faces:
                      doc.Paint(elem.Id, face, paintmat.Id)
TransactionManager.Instance.TransactionTaskDone()
OUT = elems

One interesting thing I’ve noticed is that the Python part of this Dynamo script seems to be “remembering” the values, i.e. when I’m done with painting one selections of walls and I want change the values by which I sort them – this script insists on painting the original selection. I think I’m missing something obvious here, feel free to enlighten me.

 

Purging unused linestyles in Revit with Dynamo and Python

All the best in 2017!

Lately, I’ve been dealing with models with far too many (i.e. more than zero) exploded dwgs inside, and being able to clean up all those leftover linestyles was crucial to me. Once you have to deal with 500+ positions when drafting a single detail, the blow to productivity is far too severe. Purging would be a smart move, yes?

As far as I know, you can’t achieve that with default purge functionality, and to my surprise – it’s not so obvious in Dynamo either. I’ve digged through internet (This thread was very helpful), and at some point I’ve realized that using Python was inevitable. I was reluctant, because my programming skills are basic at best, but as it turns out, “basic” is good enough and I’ve managed to complete my purging script. Here’s how it works:

LinePurge

 

My goal was to do as much as possible in “vanilla” Dynamo and as little as possible with Python. What you can see here is collecting all the linestyles used in project, saving all the unique ones and cross-checking them with list of linestyles available. This is the important distinction, as the first one can be easily done with basic dynamo nodes, the latter had to be achieved with following Python script:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

TransactionManager.Instance.EnsureInTransaction(doc)
lineStyle = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines)
lineStyleSubTypes = lineStyle.SubCategories
listNames = []
listId = []

for i in lineStyleSubTypes:
  name = i.Name
  ID = i.Id
  listNames.append(name)
  listId.append(ID)

TransactionManager.Instance.TransactionTaskDone()
OUT = listNames, listId

We start with the list of all available styles, then we throw away those that are used in the project and those with ID’s below zero (non-deletable system linestyles) – ending with list of unused ones. We feed that list to a second Python script that deletes elements by ID’s.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
from System.Collections.Generic import *

x = IN[0]
Left = list()
Erased = list()

for Id in x:
  try:
    doc.Delete(Id)
    Erased.append(Id)
  except:
    Left.append(Id)
OUT = Erased, Left

…and we’re done. Use with caution!

Import & export Excel spreadsheets with Dynamo

It’s November now and I’m back from vacation. I’m hoping to write a bit more as soon as I deal with accumulated work… but in the meantime: more dynamo scripts!
This one was a collaboration between me and a fellow structural engineer working on structural framing for a one particular high-rise in London. The idea goes like this – in order to automatize steel framing updates (and save countless hours), we need to establish a link between structural software and Revit model. Third-party software solutions were out of question, and long story short – we used Dynamo .xls export/import function to fill in the gap.

Export script:
export
Import script:
import

As you can see, there’s no mind blowing programming work involved, but it was customized to fit this particular task, it works and there are some neat node tricks here and there. As for the future development – I need to figure out a smart way to map beams with those from structural software, now it’s being done by finding a matching “RAM number” (project parameter used just for this task).
Hope you find this useful!

What I’m working on – Column arrangement coordination in Dynamo

…but let me start with explaining WHY I’m doing this. Imagine a high rise located somewhere in London, It will have 60-something floors, around 18000 beams, more than 2000 columns – and 2-5 people working on the structural model, just to make the tight deadlines possible. It would be hard to keep track. Now imagine a lot of design changes, structural supports moving left and right, columns disappearing and appearing again. And to top it all – very restrictive column schedule macro that doesn’t take “almost in line” as an answer. I need to be able to quickly see if all the columns are in line, are the column numbers assigned correctly and were there any last-minute design changes that I’m not aware of.

Now we get to the Dynamo part. This is what I have so far, and keep in mind this is just a very early version of this concept:

columnlocationc12

So what’s the deal here? First, we get all the columns from the model and choose the column “path” that we’re interested in (C12 here). Then it get’s trickier – as far as I know, Dynamo 1.1 (which I’ve used to write this) doesn’t have an easy way to get X,Y location of the center of the column (I know there’s a node for that in 1.2), so I’ve came up with following workaround: we get the coordinates value from Element.Solid – asking for maximum and minimum Y (thus getting the point in the middle), and we subtract this with value of the column below. If it’s zero – columns are in line. To make this work, columns should be sorted according to Z value, and to my suprise this wasn’t the default – somehow slopped columns mess up this order (that’s why the counter-intuitive sorting method)

As I said, this is still very early version, and here are my plans for further development:

  • Exporting to Excel
  • Export all the columns, not just one “line”
  • Checking X,Y values at the top and bottom, so that slopped columns won’t be seen as an “value other than zero”

Feel free to comment on this script – I’m still learning here!