At the start of last week, I was delighted to participate in the very first UK Dynamo User Group Dynamo Day. I was invited to speak about my experience with Dynamo and also had the opportunity to take part in a Dynamo workshop. This was the first event of this kind to be organised in London and as part of it, the UK Dynamo User Group meeting was the first one ever to be ticketed. It goes without saying I was eager for that day to come, and the UKDynUG did not disappoint. The organisation was brilliant, and along with all the excellent professional perks of being there, there was also vegan desert after lunch, so pretty much all my needs were satisfied.

The intermediate workshop was carried by John Pierson, and had a lovely air or accessibility, even though it was meant for people with some experience. John was really great breaking things down and handing us practical tools as well as helping us understand the underlining concepts of the algorithms we were exploring. We even got to create our own custom package – something I had never attempted, because I assumed it was way too complicated, but actually turns out is beautifully straight forward.

Following the workshops, we moved on to a series of talks, opened by yours truly. My talk aimed to show simple every day usage of Dynamo that anyone can implement in a working project. I built on simple graphs for running checks on schedules and moved onto mass placement of families under a system of rules. This kicked off an evening with an excellent range of presentations:

Giacomo Bergonzoni & Fabrizio Sampietro spoke about the challenges of Historical BIM and how Dynamo can help overcome them – having had some experience on listed building refurbishment in BIM, I have to say – this is some admirable work that they are doing.

Nicolas Leguina talked about Computational design & workflows on a specific project with a tight budget, and it was really great to see the genuinely creative usage of various software in a way to help a seriously understaffed project.

Radu Gidei talked about alternative uses of Dynamo, and I must admit I was very impressed by his angle; it is also true that what his research has done requires experience and knowledge that not anyone in an architectural studio has.

Hands down the most visually exciting presentation was by Long Nguyen from the university of Stuttgart. He presented his custom package DynaShapes – do look it up – and gave us a demonstration that made me think of the animators that did Merida’s hair.

gif: https://www.bustle.com/articles/76537-what-your-favorite-disney-princess-hair-says-about-you-from-snow-whites-lob-to-meridas-pretty

Sol Amour & Mark Thorley from Designtech closed the evening talking about Project Refinery. Project Refinery follows on from the form finding exploration of Project Fractal, but also explores optimisation and refinement as well as allowing for randomisation. Refinery seems like something that can bring great depth to conceptual design without demanding the proportional work. The Project is still a work in progress and the duo called out to anyone who is trying it out for feedback.

The event culminated to the usual networking drinks and it was amazing to share experiences with so many people equally excited about computation. I hope to see all of you on the field soon!

More about the Dynamo Day you can find soon here and following the #DynamoDay.

Cover image currency of Sol Amour.

It has been a while since I last posted and that’s because I’ve recently started consulting for the splendid architectural company of Glenn Howells Architects. As I am trying to help their awesomely cute young architectural staff overcome the initial hurdles of taking up Revit, I enjoy the dynamics of travelling between their Birmingham and London offices.

What has taken the most part of my working hours lately, however, has been my recent recruitment with BIG. The BIG, as in Bjarke Ingles Group BIG. A studio that I’ve always admired both for their visionary architecture and for the unique image that they have managed to coin for themselves – that of a rebellious, beer drinking, bearded intellectual. Or maybe that’s just Bjarke Ingles himself, I’m not too sure.

Anyways, those and other (successful) projects have been taking a lot of my time, but they have also given me the opportunity to build some new, handy Dynamo definitions that I will now share with you. As you can imagine from the title of the post, I am going to show you 3 separate definitions, all of them using Python script extensively to achieve their tasks.

Batch Sheet Creation

“This should be in by default!” you sometimes exclaim when working with Revit, am I right? And it should. It annoys the hell out of me that Revit still doesn’t give you those simple, trivial even functionalities that end up wasting if not the majority than at least some of your production time.

The graph is pretty simple, as I said everything is inside the Python node.

Inside the python node, we will first see all the import statements. We need certain libraries and in most cases, those will be quite similar, that’s why I have a separate image which I will refer to when speaking about the other two scripts. One thing that I find myself doing over and over again is copying these statements from an old python node when I start working on a new one. You might find it handy to keep a default python script node stored with your favorite presets.

After we have that covered, we can start writing the specifics of our script. The node will take 2 user parameters – the number of ‘copies’ and the desired sheet number pattern (this is something you might want to change outside as well as inside the python script if your project sheet numbering follows a different pattern style). To complement the ‘duplication’ nature of the definition, we need to be working within an active sheet view which parameters we will copy. The bulk of the code is executed inside an ‘if’ statement, which makes sure we are inside such a view.

Next, we will do some basic string manipulation to make sure we create a new sheet sequence with appropriate numbering. The following piece of code is taken from a node written by Dimiter Venkov (respect) which basically retrieves all elements in the view. What we need to get is the TitleBlock from the active view sheet (which automatically means that if we don’t have a TitleBlock on the sheet, we will get an error).   Of course, we can always replace this with another input to the python node which feeds an existing in the document TitleBlock.

Once that’s done, we are ready to create as many sheets as we want. In a new Transaction, we iterate over the number of sheets we have chosen to make and we increment the sheet_number each time to make sure we create those unique sheet numbers.

That’s it! You are free to change anything around that code to make it fit the different scenarios you have in mind.

Duplicate Views and Place on Sheets

Here, we will still be creating new sheets, but this time, the focus is on duplicating a number of views first and then placing them on new sheets. This is yet another example of something that we wish we were given out-of-the-box and something that made a lot of people out there create custom macros, plugins, and dynamo definitions in an attempt to patch that Revit hole (I’ve spoken about the View Duplicatorplugin in one of my previous posts). This python script is just another take on the same subject. Let’s take a look.

This time, the sheet creation part is externalized and handled by the Sheet.ByNameNumberTitleBlockAndView node. You can find this lengthy title under the Revit/Views/Sheet tab. It takes a couple of parameters (you can see how we generate the TitleBlock this time) and the one we care about the most is the View or the list of Views that we would like to duplicate. This is done inside the python node, which itself takes 5 string parameters – a Prefix and a Suffix of the views that we are looking for, a Prefix and a Suffix with which we are going to replace the old ones (this gives you control over how the views will be named) and a string that will supply our sheets with unique numbers.

The so-called ‘Sheet Sequence’ code block has a little quirkiness that I’d like to explain – since normally we would be looking for a sequential sheet numbering, the string is of the format “xx-nn%02d”. What that means is that, once inside python, the sheet number will append the alphabetical part of the provided string, while incrementing the numerical one. Not only that but the numerical part, the way you can see it on the image, will be of the form “100” and it will increment to “101”, “102” and so on. The “02d” part after the “%” sign tells the formatted to treat whatever integer it is given as a double decimal number. So, if you would like to replace that with a single number, you would change it to “xx-nn%01d”. Mini exercise – if you want your sheet sequence to be “SK-3020”,  “SK-3021” … you will have to put? That’s right, “SK-302%01d”. As we will not be selecting the views directly from the project, we would like to be able to find them from all the other existing views. In a suitably maintained project, your view names will follow a certain pattern and this will make a lot of sense. If, for some reason, this method of selecting views does not work for you, feel free to change the python node to your liking.

As we agreed, all the import statements are the same as the ones we had before, so we can just skip that part and go straight to the core of the node. We are retrieving all views in the project and we match the ones that have the Prefix and Suffix strings in their names (hint – if those strings are left blank “”, this code will obviously match every single view in the project). There is one more requirement that you need to be aware of:

v.ViewType == ViewType.FloorPlan

This will only check our FloorPlan views. We can certainly change that when we are looking for CeilingPlans, AreaPlans and so on. For more information on the correct names of all view types, you can refer to the View.ViewType Property in the Revit Api documentation.

The rest of the code is pretty straight forward to follow, with the only exception of how we create the duplicate view and change access its properties.

v_duplicate = doc.GetElement(v.Duplicate(ViewDuplicateOption.Duplicate))

v_duplicate.ViewName = new_name

There are few things happening in that first line. First of all, we create a new view with the following piece of the code: v.Duplicate(ViewDuplicateOption.Duplicate). There are three options that we can use – .Duplicate, .AsDependent, .WithDetailing. I will leave cracking this complicated code to you. Then we get an object (v_duplicate) by retrieving the newly create view from the document via doc.GetElement. Finally, we can manipulate that object and assign our desirable name to it.

There are lots of ways to break the above code and that is simply because of the many different ways to define the task, especially in the string manipulation part. As always, this is meant to be a guideline and a source of python code that you can string together in a fashion that will do your bidding.

Workset Tidy-Up

Our final definition deals with the tedious task of cleaning up worksets. I don’t think that the problem needs explanation and I am sure that we are all familiar with the fact that our project files need maintenance. The definition that I will show you works especially well in a scenario where Worksets attribution follows the Revit Categories, but even in a non-standard setup it can still be modified in such a way as to allow you to automate at least part of the whole process.

I believe that the graph is easy to read – we get elements by Categories and check if their Workset parameter is not equal to the desired one. If it’s not, then we will assign the correct one. Of course, we can simply override the Workset parameter blindly, but that will take more time while the above solution will be snappy and quick the more we use it. It also has embedded the resources to make a more complex solution that filters elements by some other input. Finally, if the setup of your project is robust enough, you can batch collect categories by name and funnel those into their respected Worksets, potentially creating a 1 button solution for the whole problem.

As it turns out, this definition does not have any Python code in it. I got confused, as my usual workflow in Dynamo inevitably involves Python scripting. I would like to say a few words about that and I think that this is as good place as any for my little Grasshopper/Dynamo tirade that has been building inside for a while now.

“Dynamo is Grasshopper for Revit”. How many times have we heard this line? I bet a lot. And while Dynamo seems to have started as a Grasshopper for Revit and while there are certainly enough people out there that drive steadily in that direction, I personally think that because of the underlying differences between the two core programs that those “add-ons” serve – Rhino and Revit – there will and should always be a difference between GH and Dynamo. Rhino deals with complex geometry in a simple way. Revit deals with simple building components in a complex and granular way. Grasshopper has a clean, well-defined interface that intuits the way you deal with it. It is hard to say that Dynamo has any interface at all. It is ugly, awkward, has tons of outdated, free components that no one knows how to use but the builders themselves (there is no certainty in that either) and it forces its users to deal with scripting first hand. And you know what? I think that’s great! I think that scripting is not so hard and that Dynamo will eventually create a more knowledgeable and intelligent community around itself than the cry-baby generation of Rhino geometry junkies. By the way, I don’t mean that. I love Rhino and Grasshopper, I do, I do, I do. But that’s exactly why we should leave complex geometry to Rhino and embrace the documentation awesomeness of Revit and bring it to the next level with our Python augmented Dynamo super powers!

Peace out.

Oh, and you can download the three definitions here: Batch Sheet CreationDuplicate Views and Place on SheetsWorksets Tidy-Up.

When managing projects of non-small sizes, one of the tedious routines that you are required to go through is to somehow match information that is part of the project’s Sheet set and its View set. The idea of cross-referencing data between various elements is native for information management, yet Revit does not yet cover that aspect for us. Dynamo, however, does (so, in a sense, Revit does. Duh).

Traditionally, we could approach that task as follows:

 

  • load all sheets
  • load all views
  • for each sheet and view, see which view the sheet is sat on and finally
  • check if the corresponding parameters match and if not
  • do something (make them equal)

 

Now, there is one little bug that has been migrating with every update of Dynamo, and the brand new 1.0.0 (Congratulations!) version still apparently still got it – when retrieving elements by Category, the View Category will spit a message which states that Template Views are not Views. That’s fine. There is an even nicer node that simplifies the task for us:

Sheet.Views

What this node is supposed to do is to only select those Views that are place on the set of Sheets it is given. Now we can skip a step, retrieve only the Views that matter, and continue with our cross-referencing. .. but this node ,too, does not work.

That’s also fine. Here is the solution to the problem, written in python code.

.. and here is what the definition looks like:

What we did here is that we collected all the sheets in the project, using the Dynamo node of retrieving All Elements by Category, then we fed the resulting list together with a couple of shared parameters, which both the Sheet and the Views of the project use, and we executed the python code which, on one hand matched the information of those shared parameters, and on the other, gave us a handy list of ‘failed’ views. Those ‘failed’ views are simply the views that had View Templates assigned on, controlling and thus ‘locking’ the shared parameters.

While we are on the subject of python and getting instance parameters from elements, I want to point out the correct (at least for now) way of doing it.

The general syntax of this command in Python is:

element.Parameter[“Parameter Name”].AsString() – to get (can also be .AsInteger(), .AsDouble()) the parameter, or

element.Parameter[“Parameter Name”].Set – to set the parameter.

This is important to know as a lot of times Dynamo tasks revolve around Parameter manipulation and there is hardly any information out there that explains how this can be achieved in Dynamo with Python.

I hope that custom Dynamo definition can be of help to you in your BIM journeys my friends! Good night and best of luck.

Greetings young Revitalizers!

 

After I’ve posted the ‘Controlling Revit Hatch Pattern Line Weights‘ blog post, I’ve decided that I like the title so much, that I will make the second part. OK, it may not be the title, but the fact that after playing around with the solution I gave earlier, there were still areas that I couldn’t gain control over – mainly Material Hatch Patterns.

In my previous post, I’ve suggested overriding the Line Weights Pen assignment of the Surface/Cut Patterns of Walls, Floors, Ceilings and Roofs with Pen #16 and giving that Pen the minimum value of 0.025mm. That roughly covers 50% of your content through a typical set of drawings. The other 50% of all the hatches come from the patterns assigned in the Material of the object. Sadly, we have no control over those.

As I wrote earlier, one of the former solutions to this issue conceptualized by the community was to ‘upgrade’ all other objects to a higher Pen value (in a way incrementing +1 their current value) and use Pen #1 only for hatches. This is exactly the approach I decided to take this time around. Here are the steps that explain the process:

As you know, the default values of Pen #1 are somewhat thick. We can crank down that number to the aforementioned 0.025mm, but then a whole lot of other objects become thin and we don’t need that.

 

The answer is in this single Python Node which takes all BUT the Categories with names containing the ‘pattern’ phrase and increments their current value with a single number. That way, your walls, which have previously had the values of Surface – 1, Cut -3, now have the values of Surface – 2, Cut – 4.

Here is a shot of the (important part of the) Python script within the node. Alternatively, you can download the definition – it will require the usual installation of Dynamo 0.92 + IronPython.

Warning: after you run the script, if you try to undo the process in Revit, you will no longer be able to successfully run the script in the current Dynamo session. You would need to restart Dynamo and do it again.

I hope you found that useful – happy drawing and don’t forget to subscribe!

Revit is an amazing CAD program. (And so is ArchiCAD, all right. I just happen to know and use Revit). Despite the fact that it has been around for quite some time and given the monstrosity of Autodesk as a company (therefore allowing it to push its products like no other), I feel that it has taken more than it should have to get Revit to the prestigious spot that it is now occupying. Of course, Building Information Modelling wasn’t as important as it is now, but I think that one of the reasons that made it difficult for Revit to shine (and allowed AutoCAD to still be lurking around) was the lack of sex-appeal, and I am referring to the quality of the draftsmanship it allowed us to produce out of the box.

For the majority of the architects, or at least, the ones that I know and have worked with, design expression is of extraordinary importance. So much so, that Illustrator/Corel have always been an inseparable part of all our submissions. The ability to control every bit of detail in one’s drawings is of such importance that, again, lots of people prefer to work in a 2D package than to take the world of benefits that comes with using Revit.

One instance where Revit has failed to deliver user control, where it is needed, is in the assignment of line weights for wall hatch patterns. I remember a project where we finally decided to overlay all of the walls with filled regions in order to achieve the desired look (it wasn’t my idea, but I played along).

Cutting to the chase, let me explain about the technical side of the problem. There are several system families that use fill patterns, for either their section or projection representation. The type of those patterns comes from the material of said element. So far we were able to override the color of the pattern (and indeed one of the “viable” workarounds has been to assign a grey color (to the pattern) in an attempt to give it a lighter touch). But we weren’t able to assign a different line weight to those patterns.

In theory, Revit allows you to change the default values for “all” object styles from the object style interface. For some reason, however, those hatch patterns are not among the categories that users have control over.

Here is an old thread in which the discussion revolves around another workaround in which pen 1, which is the default number for the patterns (trial-and-error) is set to the lowest possible value. And since pen 1 is the default for a lot more objects, we were supposed to beef up all the remaining values with +1. However, one immediate problem might be that, as with the hatch patterns themselves, there probably are more categories which line weight assignment has not been exposed. Furthermore, it’s one of that task that feels time-consuming in a debilitating kind of way. This is another approach, but it still doesn’t feel right to me.

The good news is that nowadays we have Dynamo! While setting up a company templates the other day, I remembered how pressured I felt trying to fix the same issue on a deadline before, so I decided to give it another go. I started by theorizing that I can programmatically increment all the line weights as described in the existing workaround. While I actually managed to achieve this, I was really surprised to find that now my hatch patterns were controlled by pen #2. It took a little bit of back and forth until I finally narrowed it down to just a few Categories that controlled those pesky infills. I was able to take control over 4 family categories – walls, floors, ceilings, and roofs. Each of those, in turn, had a surface pattern and a cut pattern property that I was able to override.

You can see this short video demonstrating the functionality of the definition. There is still more investigation that I need to do because I still have no idea how to override the values for the non-system families’ pattern infills.

Having said that, this definition can be useful to a lot of people out there just the way it is right now. You can download the Dynamo definition here. You would need to have Dynamo 0.90 installed, but that shouldn’t be a problem as it comes pre-installed with Revit 2015. If you have any questions, please feel free to contact me.

Have you ever had the daunting task to create hundreds of sheets in Revit? And when you finally got through the tedious process of copying and pasting numbers and names you find out that you need to change a single letter to the prefix to all the hundreds of sheets? A simple ‘Find and Replace’ function is all you need, sadly one does not ship with Revit.

Revit, however, comes with the brilliant ‘Dynamo’ plugin! Those of you who love using Rhino’s ‘Grasshopper’ (I know I do) are also going to love Dynamo, as it looks quite similar and it too gives you the feeling of an overpowered ninja once you get past that initial learning curve.

Speaking of a learning curve, the following example is really simple, yet it does a few things to accelerate your progress and get things up and running. First of all, you will need to light up Dynamo and create a new custom node. Follow the prompts and give the node a name that you can recognize, appropriate description and assign a Category – since it deals with strings, I’ve chosen Core|String for mine. This is what you’d like the node to look like at the end:

This node takes string 3 arguments – your original text, the bit that needs to be replaced and what it needs to be replaced with. Finally, it gives you the result unsurprisingly in string format.

And this is how it can be used in the context of a Dynamo definition.

You can download the custom node and the dynamo definition.

I hope you found this brief tutorial helpful. For related articles, check our ‘Dynamo’ section and if you have a special request, please contact us with it.

And as always – don’t forget to subscribe 🙂