Hello everyone,
I’m working with a Revit 2021 project that contains many text notes created using the standard Text Note tool. I’m developing a Dynamo script to replace these text notes with instances of a custom Generic Annotation family type instead.
So far, I’ve been able to:
- Extract the coordinates and text values from each Text Note,
- Create instances of the Generic Annotation family at the corresponding points,
- Assign the original text value to a parameter in the family.
However, I’m running into a visibility issue. The family instances are successfully created — they appear in the project browser and can be selected via the schedule or element ID — but they are not visible on the floor plan or at the level I’ve specified.
I’ve double-checked the level assignment and tried various views, but Revit doesn’t seem to find a suitable view where they can be seen or selected graphically. Has anyone encountered this behavior before? Could it be an issue with view range, annotation category behavior, or something specific to how Dynamo places annotation elements?
Any insights or suggestions would be greatly appreciated.
Thank you!
worth trying is to get the text node locations, but create a new set of locations/points with level.Elevation as their z components. then move on to the insertion of family instances.
Unfortunately, this didn’t help. I specifically added blocks in the script to overwrite the Z-coordinate to match the elevation of the target level. However, even with the correct coordinates, the annotation family instances are still created but remain completely invisible in any view.
I’m wondering if this is somehow related to the view context — maybe I need to explicitly define the view in which the annotations should be placed, but I can’t find a corresponding node for that in Dynamo.
i remember it happened to me once. i lifted them up slightly above the cut plane then everything shows up nicely. post a copy of that family if possible?
any chance that some view specific settings prevent them from showing up? visiblity? workplanes? filters?
edit:
what if u insert a family instance manually and check out its location? i cant read the name of that family type but i suppose we are talking abt text-to-tag conversion? iirc, a tag locates in 3d space though it looks flat. so i remember the z component actually matters.
Unfortunately, I wasn’t able to upload the family file since I’m a new user, but it’s a very simple Generic Annotation with a single text label.
To investigate the visibility issue, I manually placed a test instance of the annotation on the Roof Plan and checked its Z-coordinate — this is shown in the first image. The coordinate came out to be 7200, even though the Roof level itself is at 6000. So it’s clear that annotation symbols are placed slightly above the level’s cut plane — that part makes sense.
However, even when I replicate this in Dynamo — using the exact same Z-coordinate (7200), and placing the annotations at the exact same points where the original text notes are located — the annotation symbols are still completely invisible in any view.
I’ve also double-checked all visibility settings, view ranges, and category filters. The coordinates match exactly with the visible text notes, yet the new annotation elements simply don’t appear in any view.
i’ve just managed to reproduce the issue here. are u comfortable working with some api calls in python? i found a method overload in api doc that allows u to specify a host view when creating instances of generic annotations. it creates them without any issue as long as the locations are lifted appropriately.
anno = doc.Create.NewFamilyInstance(pt, fam_type, doc.ActiveView)
complete code snippet:
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
#Preparing input from dynamo to revit
fam_type = UnwrapElement(IN[0])
pt = IN[1].ToXyz()
switch = IN[2]
#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
anno = doc.Create.NewFamilyInstance(pt, fam_type, doc.ActiveView)
TransactionManager.Instance.TransactionTaskDone()
OUT = anno
i have a feeling that the internal implementation of this node is either using some other overloads that are not meant for placement of generic annotation or somehow revit allows such call to return without any exception thrown.
2 Likes
I think you should also try to get the view in which the text note is placed and use Family Instance By Point and View to place the annotation families. since 2D elements cannot be placed in 3D model? if your family instance was a model element then it would be placed on that point, it’s also the reason why it’s not visible in any view simply because it’s not there.
2 Likes
Yes, that approach works — creating the Generic Annotations through the API (or script) as shown does place them on the correct view, and I can finally see them on the plan. So that part is resolved.
However, now they’re always placed at the origin point (0,0,0), regardless of the coordinates I provide.
I’m passing a non-zero list of XYZ points, but it seems like the placement method is either ignoring it or failing to interpret it properly. I even tried modifying the sample code you posted — passing both pre-constructed XYZ coordinates and raw numeric lists — but nothing seems to allow the annotations to appear at the intended positions.
It feels like I’m really close — if I can just get the coordinate input to work correctly, everything else would fall into place.
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('ProtoGeometry')
from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.DesignScript.Geometry import Point as DSPoint # ← точка из Dynamo
doc = DocumentManager.Instance.CurrentDBDocument
# input
fam_type = UnwrapElement(IN[0])
ds_points = IN[1]
view = UnwrapElement(IN[2])
result = []
TransactionManager.Instance.EnsureInTransaction(doc)
for pt in ds_points:
if isinstance(pt, DSPoint):
xyz = XYZ(pt.X, pt.Y, pt.Z)
inst = doc.Create.NewFamilyInstance(xyz, fam_type, view)
result.append(inst)
TransactionManager.Instance.TransactionTaskDone()
OUT = result
yeah i agree, very close indeed.
something off upstream. u are using the dot operator accessing a point’s function on a list. [pt.ToXyz() for pt in pt_list]
is more appropriate. must be some list structure got messed up. not a huge issue.
about point geometry conversion:
- dynamo → revit, ToXyz()
- revit → dynamo, ToPoint()
2 Likes
It worked! The solution turned out to be surprisingly simple — the Clockwork package already had a node that does exactly what I needed. Now all the Generic Annotations are placed precisely where they should be.
It was an interesting debugging experience overall. I still don’t fully understand how coordinate placement for annotation symbols works under the hood in Revit, but I’ll definitely keep exploring.
Thanks to everyone who helped or followed along!
1 Like
Thank you very much for the detailed guidance and the time you spent helping me. For some reason, I get an error when using ToXyz()
. I suspect it’s due to the older version of Revit 2021 and Dynamo I’m working with.
But I think I’ll be able to adapt the code for newer versions or for other tasks.
In any case, this has been very helpful — I really appreciate it!
In any case, this has been very helpful — I really appreciate it!
no worries, @me if there’s struggle.
1 Like
Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
Traceback (most recent call last):
File “”, line 39, in
AttributeError: ‘Point’ object has no attribute ‘ToXYZ’
I’m still getting an error, unfortunately. It’s strange — I’ve looked at similar code examples where everything seemed to work fine. I guess this method just isn’t available in my setup.
In any case, I think it’s better to try things out in newer versions of Revit rather than struggle with 2021. For this particular task, I’ll just stick with the Clockwork node — it does the job well.
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('ProtoGeometry')
from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.DesignScript.Geometry import Point as DSPoint # Dynamo Point
doc = DocumentManager.Instance.CurrentDBDocument
# Входные данные
fam_type = UnwrapElement(IN[0])
raw_points = IN[1]
switch = IN[2]
# Совместимая с IronPython функция flatten
def flatten(lst):
result = []
for i in lst:
if isinstance(i, list):
result.extend(flatten(i))
else:
result.append(i)
return result
# Плоский список точек
ds_points = flatten(raw_points)
# Результат
result = []
TransactionManager.Instance.EnsureInTransaction(doc)
for pt in ds_points:
if isinstance(pt, DSPoint):
xyz = pt.ToXYZ()
inst = doc.Create.NewFamilyInstance(xyz, fam_type, doc.ActiveView)
result.append(inst)
TransactionManager.Instance.TransactionTaskDone()
OUT = result
probably try flatten the list and then feed to python node? may be it’s trying to convert “list” object and not the list elements.
1 Like