Tag/TextNote Multi-Category Elements

archi-lab
clockwork

#1

Hi guys!

I’m trying to tag multiple elements that belong to different categories and the tag needs to show the value of one of the parameters of the elements.

At the beginning I tried with “Create Annotation Tag” from archi-lab but then I realized that I would have needed a specific Family Type for each category of elements to tag (right?!) and I abandoned that way…

But then I thought that I don’t need a real tag for that 'cause I just want to visualize those “tags” in some floor views. So now I’m trying to use a simple Text Note through “TextNote.ByViewPointAndType” and locate it beside my element.


It’s not working so I assume I’m doing something wrong!
Basically I’m trying to put a text note that says “Test_Check” (for now…then it will become the value of a parameter that I already collected) close to each element I have in my floor plan (that’s why I’m putting every object in a bounding box and then I’m taking its point…not sure this is the best practice) and show it up properly in my floor plans.

What’s wrong? Best practice suggestions?

Thanks everyone :wink:


Multi Rebar Annotation Tag
Tag multiple Elements in multiple views
Material Tag Placement
#2

I would create a project parameter for the categories and tag that with the node from archi-lab


#3

Hi @andreatas ,

have you considered using a multi-category tag? the main reason why it might be a better approach is that the tag will always show the updated parameter value, whereas a text will have to be updated manually or via a script…


#4

Thanks guys!

@T_Pover the value to show in the tag is already a parameter and I’m querying it from the model…
You’d do with “create annotation tag”?

@Mostafa_El_Ayoubi that’s absolutely right! How does it work the multi-cateory? I looked everywhere but I couldn’t find much…
Which nodes do I need?


#5

It’s acutally something that doesn’t need Dynamo… You can create a multi category tag using the appropriate template :


#6

Exactly what Mostafa says :slight_smile: Multi Category tags are useful for this. If you want to use them in combination with the Archi-lab node “Create Annotation Tag” you’ll to need modify the code a bit though as it doesn’t support Multi-category tags as is. You can copy paste this into a python node and use the same inputs as with the Create Annotation Tag node:

#Copyright(c) 2015, Konrad K Sobon
# @arch_laboratory, http://archi-lab.net

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import Element wrapper extension methods
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

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

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

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

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN

locationPts = UnwrapElement(IN[0])
tagType = UnwrapElement(IN[1])
elements = UnwrapElement(IN[2])

if IN[4] != None:
	link = UnwrapElement(IN[4])
else:
	link = None
	
RunIt = IN[5]

if isinstance(IN[3], list):
	views = [UnwrapElement(i) for i in IN[3]]
else:
	views = UnwrapElement(IN[3])

def toRvtPoint(point):
	return point.ToXyz()

def toRvtId(_id):
	if isinstance(_id, int) or isinstance(_id, str):
		id = ElementId(int(_id))
		return id
	elif isinstance(_id, ElementId):
		return _id

def GetUVPoint(pt):
	if type(pt) == Autodesk.DesignScript.Geometry.Point:
		return Autodesk.Revit.DB.UV(pt.X, pt.Y)
	elif type(pt) == Autodesk.DesignScript.Geometry.UV:
		return Autodesk.Revit.DB.UV(pt.U, pt.V)

def CreateSpaceTag(space, uv, view):
	doc = DocumentManager.Instance.CurrentDBDocument
	return doc.Create.NewSpaceTag(space, uv, view)

tagTypeId = toRvtId(tagType.Id)

try:
	errorReport = None
	if RunIt:
		if tagType.Category.Name == "Room Tags":
			TransactionManager.Instance.EnsureInTransaction(doc)
			roomTags = []
			if isinstance(views, list):
				for i, j, k in zip(elements, views, locationPts):
					roomId = LinkElementId(i.Id)
					location = Autodesk.Revit.DB.UV(toRvtPoint(k).X, toRvtPoint(k).Y)
					roomTag = doc.Create.NewRoomTag(roomId, location, j.Id)
					roomTag.RoomTagType = tagType
					roomTags.append(roomTag)
			else:
				for i, j in zip(elements, locationPts):
					if link != None:
						roomId = LinkElementId(link.Id, i.Id)
					else:
						roomId = LinkElementId(i.Id)
					location = Autodesk.Revit.DB.UV(toRvtPoint(j).X, toRvtPoint(j).Y)
					roomTag = doc.Create.NewRoomTag(roomId, location, views.Id)
					roomTag.RoomTagType = tagType
					roomTags.append(roomTag)
			TransactionManager.Instance.TransactionTaskDone()
			result = roomTags
		elif tagType.Category.Name == "Space Tags":
			TransactionManager.Instance.EnsureInTransaction(doc)
			roomTags = []
			if isinstance(views, list):
				for i, j, k in zip(elements, views, locationPts):
					uv = GetUVPoint(k)
					spaceTag = CreateSpaceTag(i, uv, j)
					spaceTag.SpaceTagType = tagType
					roomTags.append(spaceTag)
			else:
				for i, j in zip(elements, locationPts):
					uv = GetUVPoint(j)
					spaceTag = CreateSpaceTag(i, uv, views)
					spaceTag.SpaceTagType = tagType
					roomTags.append(spaceTag)
			TransactionManager.Instance.TransactionTaskDone()
			result = roomTags
		elif tagType.Category.Name == "Multi-Category Tags"::
			TransactionManager.Instance.EnsureInTransaction(doc)
			tags = []
			if isinstance(views, list):
				for i,j,k in zip(elements, views, locationPts):
					location = toRvtPoint(k)
					tag = doc.Create.NewTag(j, i, False, TagMode.TM_ADDBY_MULTICATEGORY, TagOrientation.Horizontal, location)
					tag.ChangeTypeId(tagTypeId)
					tags.append(tag)
			else:
				for i, j in zip(elements, locationPts):
					location = toRvtPoint(j)
					tag = doc.Create.NewTag(views, i, False, TagMode.TM_ADDBY_MULTICATEGORY, TagOrientation.Horizontal, location)
					tag.ChangeTypeId(tagTypeId)
					tags.append(tag)
			TransactionManager.Instance.TransactionTaskDone()
			result = tags
		else:
			TransactionManager.Instance.EnsureInTransaction(doc)
			tags = []
			if isinstance(views, list):
				for i,j,k in zip(elements, views, locationPts):
					location = toRvtPoint(k)
					tag = doc.Create.NewTag(j, i, False, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, location)
					tag.ChangeTypeId(tagTypeId)
					tags.append(tag)
			else:
				for i, j in zip(elements, locationPts):
					location = toRvtPoint(j)
					tag = doc.Create.NewTag(views, i, False, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, location)
					tag.ChangeTypeId(tagTypeId)
					tags.append(tag)
			TransactionManager.Instance.TransactionTaskDone()
			result = tags
	else:
		result = "RunIt is set to False."
except:
	# if error accurs anywhere in the process catch it
	import traceback
	errorReport = traceback.format_exc()

#Assign your output to the OUT variable
if errorReport == None:
	OUT = result
else:
	OUT = errorReport

Or maybe @Konrad_K_Sobon can update his node to support multi-category tags :slight_smile:


Annotation Tag Failure from Tag Type ID
Tagging Attempts Cause Revit to Crash with Fatal Error
#7

It works beautifully!! Thanks @T_Pover !!!
There’s just a duplicate colon at some point which I deleted. Let me re-paste the corrected working Python script just for the sake of future users:

    #Copyright(c) 2015, Konrad K Sobon
    # @arch_laboratory, http://archi-lab.net

    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *

    # Import Element wrapper extension methods
    clr.AddReference("RevitNodes")
    import Revit
    clr.ImportExtensions(Revit.Elements)

    # Import geometry conversion extension methods
    clr.ImportExtensions(Revit.GeometryConversion)

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

    doc = DocumentManager.Instance.CurrentDBDocument
    uiapp = DocumentManager.Instance.CurrentUIApplication
    app = uiapp.Application

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

    import sys
    pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
    sys.path.append(pyt_path)

    #The inputs to this node will be stored as a list in the IN variable.
    dataEnteringNode = IN

    locationPts = UnwrapElement(IN[0])
    tagType = UnwrapElement(IN[1])
    elements = UnwrapElement(IN[2])

    if IN[4] != None:
    	link = UnwrapElement(IN[4])
    else:
    	link = None
    	
    RunIt = IN[5]

    if isinstance(IN[3], list):
    	views = [UnwrapElement(i) for i in IN[3]]
    else:
    	views = UnwrapElement(IN[3])

    def toRvtPoint(point):
    	return point.ToXyz()

    def toRvtId(_id):
    	if isinstance(_id, int) or isinstance(_id, str):
    		id = ElementId(int(_id))
    		return id
    	elif isinstance(_id, ElementId):
    		return _id

    def GetUVPoint(pt):
    	if type(pt) == Autodesk.DesignScript.Geometry.Point:
    		return Autodesk.Revit.DB.UV(pt.X, pt.Y)
    	elif type(pt) == Autodesk.DesignScript.Geometry.UV:
    		return Autodesk.Revit.DB.UV(pt.U, pt.V)

    def CreateSpaceTag(space, uv, view):
    	doc = DocumentManager.Instance.CurrentDBDocument
    	return doc.Create.NewSpaceTag(space, uv, view)

    tagTypeId = toRvtId(tagType.Id)

    try:
    	errorReport = None
    	if RunIt:
    		if tagType.Category.Name == "Room Tags":
    			TransactionManager.Instance.EnsureInTransaction(doc)
    			roomTags = []
    			if isinstance(views, list):
    				for i, j, k in zip(elements, views, locationPts):
    					roomId = LinkElementId(i.Id)
    					location = Autodesk.Revit.DB.UV(toRvtPoint(k).X, toRvtPoint(k).Y)
    					roomTag = doc.Create.NewRoomTag(roomId, location, j.Id)
    					roomTag.RoomTagType = tagType
    					roomTags.append(roomTag)
    			else:
    				for i, j in zip(elements, locationPts):
    					if link != None:
    						roomId = LinkElementId(link.Id, i.Id)
    					else:
    						roomId = LinkElementId(i.Id)
    					location = Autodesk.Revit.DB.UV(toRvtPoint(j).X, toRvtPoint(j).Y)
    					roomTag = doc.Create.NewRoomTag(roomId, location, views.Id)
    					roomTag.RoomTagType = tagType
    					roomTags.append(roomTag)
    			TransactionManager.Instance.TransactionTaskDone()
    			result = roomTags
    		elif tagType.Category.Name == "Space Tags":
    			TransactionManager.Instance.EnsureInTransaction(doc)
    			roomTags = []
    			if isinstance(views, list):
    				for i, j, k in zip(elements, views, locationPts):
    					uv = GetUVPoint(k)
    					spaceTag = CreateSpaceTag(i, uv, j)
    					spaceTag.SpaceTagType = tagType
    					roomTags.append(spaceTag)
    			else:
    				for i, j in zip(elements, locationPts):
    					uv = GetUVPoint(j)
    					spaceTag = CreateSpaceTag(i, uv, views)
    					spaceTag.SpaceTagType = tagType
    					roomTags.append(spaceTag)
    			TransactionManager.Instance.TransactionTaskDone()
    			result = roomTags
    		elif tagType.Category.Name == "Multi-Category Tags":
    			TransactionManager.Instance.EnsureInTransaction(doc)
    			tags = []
    			if isinstance(views, list):
    				for i,j,k in zip(elements, views, locationPts):
    					location = toRvtPoint(k)
    					tag = doc.Create.NewTag(j, i, False, TagMode.TM_ADDBY_MULTICATEGORY, TagOrientation.Horizontal, location)
    					tag.ChangeTypeId(tagTypeId)
    					tags.append(tag)
    			else:
    				for i, j in zip(elements, locationPts):
    					location = toRvtPoint(j)
    					tag = doc.Create.NewTag(views, i, False, TagMode.TM_ADDBY_MULTICATEGORY, TagOrientation.Horizontal, location)
    					tag.ChangeTypeId(tagTypeId)
    					tags.append(tag)
    			TransactionManager.Instance.TransactionTaskDone()
    			result = tags
    		else:
    			TransactionManager.Instance.EnsureInTransaction(doc)
    			tags = []
    			if isinstance(views, list):
    				for i,j,k in zip(elements, views, locationPts):
    					location = toRvtPoint(k)
    					tag = doc.Create.NewTag(j, i, False, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, location)
    					tag.ChangeTypeId(tagTypeId)
    					tags.append(tag)
    			else:
    				for i, j in zip(elements, locationPts):
    					location = toRvtPoint(j)
    					tag = doc.Create.NewTag(views, i, False, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, location)
    					tag.ChangeTypeId(tagTypeId)
    					tags.append(tag)
    			TransactionManager.Instance.TransactionTaskDone()
    			result = tags
    	else:
    		result = "RunIt is set to False."
    except:
    	# if error accurs anywhere in the process catch it
    	import traceback
    	errorReport = traceback.format_exc()

    #Assign your output to the OUT variable
    if errorReport == None:
    	OUT = result
    else:
    	OUT = errorReport

#8

Hey guys!

Now the script gives me an error which I don’t understand:
"Traceback(most recent call last):
File “”, line 129, in
File “”, line 55, in toRvtPoint
AttributeError: ‘List[object]’ object has no attribute ‘ToXyz’

Here also a screenshot (when not working)

And here is when it’s working… (I can’t see the difference…what’s going on?)


#9

You could try flattening the list that goes into the Elements port. It seems like you’re feeding it a list instead of elements.


#10

Hi @andreatas,
I think it has to do with the list structure. The output of List.FilterByBoolMask in the first picture has more levels of nested lists than the output of Springs.Filter.ByCategoryName . Maybe List.Flatten can solve your problem :

EDIT : Just saw that @T_Pover already answered that … :slight_smile:


#11

Hi guys!

Thanks for that…I didn’t notice that!

Now it works for the active view…is the script supposed to work also for multiple views?


#12

I believe it should work with multiple vies as well, but you if you want to do that you have to feed it a view for every tag you want to place. So if you want to tag 300 elements, you have to feed it 300 views as well.


#13

@T_Pover so for multiple views I can just tag one element per view? Because in one one view I can tag multiple elements…


#14

What I do is use List.Count to count to number of tags per view and then use List.OfRepeatedItems to duplicate the views to the same number as the number of tags. That way you’ll end up with a view for every tag.


#15

@T_Pover
Yeah I get it…for the moment it’s fine 'cause I will have to run the script floor by floor anyway.

Maybe in the future I’ll try to modify the script to have all the tags for the elements at the same floor on the same plan and I’ll post it here :wink:

Thanks a lot!!


#18

Hello :slight_smile:

Nice touch on the code. Also thanks @Konrad_K_Sobon.

Code works ok on revit 2018 but has a problem on Revit 2019

See pictures. I think is an API change.
Do you have any idea for a quick/temporary fix?


#19

Hi,

You’re Right :
NewTag : <ObsoleteAttribute(“This method is deprecated in Revit 2018 and will be removed in a future version. Use IndependentTag.Create() instead.”)>

The new Create Tag Method can be found here :
http://www.revitapidocs.com/2018.1/1f622654-786a-b8fd-1f81-278698bacd5b.htm


#20

Hi,

I followed the instructions but I think I need more help :slight_smile:See pictures

Thank you!4 5

Or the error I think is about i parameter (reference)?


Create Annotation Tag with multiple TagTypes
#21

Solved :slight_smile:

7

Thank you


Creating views and tagging elements
#22

May you transfer the script to me,thanks