Room Numbering with Dynamo

Here’s a quick video preview of this workflow: YouTube

Following up on Window/Door Numbering tools that I was working on previously, I wanted to add another aspect to it. Below is a workflow that will allow you to automatically number rooms. Combining those two tools we can significantly reduce time that it takes to produce this basic yet extremely important piece of information. It will also eliminate the human error factor out of the Room/Door/Window numbering and ensure that our schedules are fully coordinated. Here’s a workflow in detail:

  1. First we start by collecting all of the rooms on a given floor. I like to do this per floor because I want to keep the room numbers organized per floor. For example, I want Ground Floor rooms to be in the 100 series, First Floor in 200 series, and so on. I use a Get Rooms by Level node that I made earlier and posted to Package Manager. However, that node collects all rooms, regardless of whether they are actually placed or not. I use a little bit of Python to filter out all Redundant Rooms. Then all I need is room location to get me started on sorting their order.

Python code to filter out unplaced rooms:

#The input to this node will be stored in the IN variable.
_dataEnteringNode = IN_
_rooms = IN_
_valid_room, room_name = [], []
for i in rooms:
    if i.Area != 0:
        _valid_room.append(i)
#Assign your output to the OUT variable
_OUT = valid_room
  1. Next is the meat of this workflow. I use Python to sort rooms into the order that I want them in (left to right and top to bottom). I need to extract Y Axis value, X Axis value as well as give it an input number for how many imaginary rows I am splitting my plan into. Here’s a Python code:

    # Default imports
    _import clr_
    _clr.AddReference('RevitAPI')_
    _clr.AddReference('RevitAPIUI')_
    _from Autodesk.Revit.DB import *_
    _import Autodesk_
    _import sys_
    _import clr_
    _path = r'C:\Autodesk\Dynamo\Core'_
    _exec_path = r'C:\Autodesk\Dynamo\Core\dll'_
    _pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'_
    _sys.path.append(path)_
    _sys.path.append(exec_path)_
    _sys.path.append(pyt_path)_
    _clr.AddReference('LibGNet')_
    _from Autodesk.LibG import *_
    #The input to this node will be stored in the IN0…INX variable(s).
    _dataEnteringNode = IN0_
    _from itertools import groupby_
    _import string_
    _yAxis = IN0_
    _xAxis = IN1_
    _room = IN2_
    _numRange = IN3_
    _lst = []_
    #convert yaxis values from revit length to strings and strip “m”, “mm” or “ft” designation_
    for i in yAxis:
        _lst.append(float(i.ToString().strip(string.ascii_letters)))_
    #define range min and max values, step_
    _lstMin = min(lst)_
    _lstMax = max(lst) + 1e-12_
    _step = (lstMax – lstMin) / numRange_
    #convert yaxis values to corresponding ranges_
    _rangeNum = [int((x-lstMin) / step) for x in lst]_  
    #sort input lists into corresponding groups then sort values within them_
    _grps = sorted(zip(rangeNum, xAxis, room), key=lambda x: (x[0], x[1]))_
    _rangeNum, xAxis, room = [], [], []_
    for i, grp in groupby(grps, lambda x: x[0]):
        _sub_rangeNum, sub_xAxis, sub_room = [], [], []_
        for j in grp:
            _sub_rangeNum.append(j[0])_
            _sub_xAxis.append(j[1])_
            _sub_room.append(j[2])_
        _sub_rangeNum, sub_xAxis, sub_room.reverse()_
        _rangeNum.extend(sub_rangeNum)_
        _xAxis.extend(sub_xAxis)_
        _room.extend(sub_room)_
    _rangeNum, xAxis, room.reverse()_
    #define outputs_
    _OUT = rangeNum, xAxis, room_
    
  2. Once we have our rooms all sorted in a proper order, all we need to do is to assign a proper room number to them. Like I mentioned before, I wanted to assign numbers in series of 100s based on the level that I am on. I also wanted the ability to skip a certain number and its multiples of 10. Here’s the process to achieve that:

    #The input to this node will be stored in the IN0…INX variable(s).
    _dataEnteringNode = IN0_
    _lstLength = IN0_
    _skipNum = IN2_
    _count = int(IN1)_
    _lst = []_
    #while len(lst) < lstLength:_
    while len(lst) < lstLength:
        _count += 1_
        if count % 10 == skipNum:
            continue
        _countFormat = str(count).zfill(3)_
        _lst.append(countFormat)_
    #define outputs_
    _OUT = lst_
    
  3. Once we have our number sequence, all we need to do is pass it on to rooms. I used a custom node called Set List Instance Parameters to achieve that. You will need a Transaction node with it since we are modifying a Revit Database by changing room numbers.

I hope this helps some of you save some time. Make sure to check out the Window/Door Numbering post that I have made earlier. Those two workflows combined can be a huge time saver.

Good luck!

Ps. This post has been recently updated to Dynamo 0.8.0 and can be found at Door Numbering for Dynamo 0.8.0