Automatic Tagging

Hey guys,

So, I’m trying to make a script that allows me to auto-tag all the families in my project following certain conditions. Basically, it finds the best distribution for the text.

So far, I’ve been able to make the text rotate according to the dimensions, shrink or enlarge, and add line breaks.

Now I’m trying to take it to the next level. First of all, I don’t know why when I switch to a section view in my “Views” node, Dynamo doesn’t do anything. It will only work if I close the program and run it again with that node already set, but in that case, I can’t switch back to my floor plan without going through the same process.

Also, in a section view, most of the families are not completely visible, so I would like to add a condition to the script where it finds the largest visible “square” that the family can show and then fits the text in there. Any ideas on how to achieve this?

AUTO-TAGGING.dyn (182.8 KB)

if you use DynamoPlayer it’s works ?

Increase the depth of your solids (so that they overlap), then perform solid subtractions.

The first problema was related to Element Binding, apparently if Dynamo detects that it already exists a note created with that script it will not create another one even if it has different parameters, the solution was this python script:

import clr

import math

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

# Inputs from Dynamo (Same order as the native node)

views = IN[0] # view

locations = IN[1] # location

texts = IN[2] # text

alignments = IN[3] # alignment

note_types = IN[4] # type

keep_readables = IN[5] # keepRotatedTextReadable

rotations = IN[6] # rotation

# Helper function to ensure all inputs are iterable (lists)

def to_list(obj):

if hasattr(obj, '\__iter_\_') and not isinstance(obj, str): return obj

else: return \[obj\]

views = to_list(views)

locations = to_list(locations)

texts = to_list(texts)

alignments = to_list(alignments)

note_types = to_list(note_types)

keep_readables = to_list(keep_readables)

rotations = to_list(rotations)

# Match the length of all lists to process multiple notes at once

max_len = max(len(views), len(locations), len(texts), len(alignments), len(note_types), len(keep_readables), len(rotations))

def pad_list(lst, size):

if len(lst) == 0: return \[None\] \* size

return lst + \[lst\[-1\]\] \* (size - len(lst))

views = pad_list(views, max_len)

locations = pad_list(locations, max_len)

texts = pad_list(texts, max_len)

alignments = pad_list(alignments, max_len)

note_types = pad_list(note_types, max_len)

keep_readables = pad_list(keep_readables, max_len)

rotations = pad_list(rotations, max_len)

notes = []

TransactionManager.Instance.EnsureInTransaction(doc)

for view, loc, text, align, n_type, keep_read, rot in zip(views, locations, texts, alignments, note_types, keep_readables, rotations):

try:

    view_id = UnwrapElement(view).Id

   

    \# 1. TEXT TYPE

    if n_type:

        type_id = UnwrapElement(n_type).Id

    else:

        type_id = doc.GetDefaultElementTypeId(ElementTypeGroup.TextNoteType)

       

    options = TextNoteOptions(type_id)

   

    \# 2. ROTATION (Dynamo sends degrees, Revit uses radians)

    if rot is not None:

        options.Rotation = rot \* (math.pi / 180.0)

       

    \# 3. ALIGNMENT

    if align:

        align_str = str(align).lower()

        if "center" in align_str:

            options.HorizontalAlignment = HorizontalTextAlignment.Center

        elif "right" in align_str:

            options.HorizontalAlignment = HorizontalTextAlignment.Right

        else:

            options.HorizontalAlignment = HorizontalTextAlignment.Left

           

    \# CREATE NOTE

    note = TextNote.Create(doc, view_id, loc.ToXyz(), text, options)

   

    \# 4. READABILITY (Keep Rotated Text Readable)

    if keep_read is not None:

        param = note.get_Parameter(BuiltInParameter.TEXT_ALIGN_KEEP_READABLE)

        if param and not param.IsReadOnly:

            param.Set(1 if keep_read else 0)

           

    notes.append(note)

except Exception as e:

    notes.append("Error: " + str(e))

TransactionManager.Instance.TransactionTaskDone()

OUT = notes

Working now in the second part of the solution

Formatted and minor refactor of code (untested)

import math

import clr

clr.AddReference("RevitNodes")
import Revit

clr.ImportExtensions(Revit.GeometryConversion)

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

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

doc = DocumentManager.Instance.CurrentDBDocument


# Helper function to ensure all inputs are iterable (lists)
def to_list(obj):
    if hasattr(obj, "__iter__") and not isinstance(obj, str):
        return obj
    else:
        return [obj]


max_len = max(map(len, map(to_list, IN)))


def pad_list(lst, size=max_len):
    if len(lst) == 0:
        return [None] * size

    return lst + [lst[-1]] * (size - len(lst))


# Inputs from Dynamo (Same order as the native node)
# views, locations, texts, alignments, note_types, keep_readables, rotations
inputs = list(map(pad_list, map(to_list, IN)))

notes = []

TransactionManager.Instance.EnsureInTransaction(doc)

for view, loc, text, align, n_type, keep_read, rot in zip(*inputs):
    try:
        view_id = UnwrapElement(view).Id

        # 1. TEXT TYPE
        if n_type:
            type_id = UnwrapElement(n_type).Id

        else:
            type_id = doc.GetDefaultElementTypeId(ElementTypeGroup.TextNoteType)

        options = TextNoteOptions(type_id)

        # 2. ROTATION (Dynamo sends degrees, Revit uses radians)
        if rot is not None:
            options.Rotation = rot * (math.pi / 180.0)

        # 3. ALIGNMENT
        if align:
            align_str = str(align).lower()

            if "center" in align_str:
                options.HorizontalAlignment = HorizontalTextAlignment.Center

            elif "right" in align_str:
                options.HorizontalAlignment = HorizontalTextAlignment.Right

            else:
                options.HorizontalAlignment = HorizontalTextAlignment.Left

        # CREATE NOTE
        note = TextNote.Create(doc, view_id, loc.ToXyz(), text, options)

        # 4. READABILITY (Keep Rotated Text Readable)
        if keep_read is not None:
            param = note.get_Parameter(BuiltInParameter.TEXT_ALIGN_KEEP_READABLE)

            if param and not param.IsReadOnly:
                param.Set(1 if keep_read else 0)

        notes.append(note)

    except Exception as e:
        notes.append("Error: " + str(e))

TransactionManager.Instance.TransactionTaskDone()

OUT = notes