First of all, huge thanks to Brian Washburn for taking the original Door Numbering definition and upgrading it to Dynamo 0.8.0 version. Also, Brian pointed out to me a handful of potential issues that I hope I was able to address here. Overall, his input allowed me to make this definition a more robust solution able to handle a larger variety of conditions. Again, thank you!
Also, huge thanks to Sonya Parton from Grimshaw’s AUS office. Your input about angle/sorting of doors allowed me to make some much needed improvements.
Now, let’s get to it. This workflow is not something that I can just wrap up into custom nodes because most of the stuff that I am doing here is project specific or just my personal preference. Not everyone will want to add a letter suffix to a door number, so I am not going to force it on anyone.
Before I drill down to nuts and bolts of this definition, let’s make sure that everyone has a few things installed:
- I am using Archi-lab (Grimshaw) package for most of the custom nodes. Get it from Package Manager
- I am using Andreas’ custom node Element.Location from Clockwork for Dynamo 0.7.X package.
- This definition was made in Dynamo 0.8.0 so it might be good to have that installed.
There is a few steps worth following when numbering doors:
- Number your Rooms first. :-) This definition will number doors based on Room numbers so its quite important.
- Make sure that ALL door families have Room Calculation Point enabled. How do you know if you did it or not? Edit the Door family in question and under properties check if Room Calculation is checked on or off.
- Create a filter. I always create a filter to exclude doors that I don’t want to include in the numbering process. Why? Example? Sure, for example a wall opening that someone thought would be a good idea to model as a door. I am game with that technique, but then I have to make sure that this pseudo doors are excluded from the schedule/numbering somehow. So I always add, a new Shared Parameter called Schedule Exclude or simply type “Exclude” into Comments for that elements.
I think we are ready now to get started. First let’s get our filters out and ready to go. I usually filter for couple things to make sure that I am getting all of the right doors:
This part should be pretty straight forward. I first filter for all of the doors (Categories = Doors) on a given level (Levels = LEVEL 01). Then I check all of the doors that this returns for whether they were Demolished. If a door was already demolished I don’t want to include it in my numbering sequence so I use List.FilterByBoolMask node to exclude all doors that were Demolished (Phase Demolished node returns a Phase Id, if Phase Id is equal to -1 that means door was not demolished because it doesn’t have a Demolished Phase property).
Ps. Something to look out for when filtering doors by Level. Curtain Wall panels that are doors, will report their level to be the same as the Wall Base Level that is hosting them. That means that if you have a Curtain Wall that spans multiple levels, a door placed on a second level will not necessarily return base level as Level 02 since wall base level is 01. Keep that in mind when working with Doors.
Next up is my “manual” filter that I use to exclude all doors that are not really doors (openings, portals etc). This sequence check if parameter Comments equals to EXCLUDE and removes those doors from the list. So far so good.
This part is a little more involved. What is happening is that I am extracting a FromRoom and ToRoom property from each door. My logic for assigning door numbers is that every door gets a number of the room that it swings into. The exception is that if a door swings into a circulation space then it will get a number of a space that it swings from. Custom Python node in the image above is doing just that. the Second input that has List.Create feeding into it is just listing spaces that I want to apply the reverse logic to (if a door swings into CIRC ). Here’s the code for the custom node:
Once, we have our doors and rooms that they swing into its time to do some work to sort them in a nice clockwise order. In order to sort them I first need to extract a location point from a door. Now, here’s a tricky part: Element.Location node will not always return a location point. One exception is a Door family that was created as a Curtain Wall panel. It’s still a Door, but it doesn’t have the same properties as typical door. The workaround for that is to use the Transform Origin point instead. This has worked well for me. Then all we have to do is re-combine the two lists and then start sorting them by an angle in relation to a Room Location point. Don’t worry about the FamilyInstance.Location node going yellow and throwing an error. It is, supposed to do that for the Curtain Wall doors, and I am using that Null values to re-assembly my list. Let’s make an amendment to what I said about my numbering logic. Now, once we have sorted all of the doors for what room they get assigned to, its time to sort them into an order (clockwise) given that there will be more than one door swinging into the room. Each door will get a suffix (a letter A, B, C, D etc). Doors are sorted in a clockwise order from a Room Location point (intersection of room reference lines or as some call it the room X). Now, we collect Door Location point and create a vector from each Room location point to that. Then using Y Axis as our zero angle we measure out all angles from room location to each door assigned to the room. Now, ordering is based on angle between Y axis and a door. Since Dynamo returns angles that are always less than 90 (it does quad based angle measurement where angle returned is always the smallest angle to that vector). That’s why I have that Angle Adjustment Python node in there to convert all angles into more familiar 360 degree angles in relation to the Room Location Point.
This creates a list of angle values for all our doors, and we are ready to group them, assign numbers to them and then enjoy some beer time. In this last section we do couple important things. First we Group and order all of the doors by their angle and room number, and then we add a proper suffix before finally writing that information to a door Mark parameter. Here is code for grouping and adding suffix:
This is it! We are done. I hope this helps everyone get their head around this definition. Here are the files: Download