How to identify orphaned tags?

@Mark.Ackerley great analysis. I didn’t realize that Material Tags don’t have the Text property. In that case I agree with you that we have to get a little bit more creative. How about a geometric approach to the problem? Each Tag has a property called BoundingBox and if it has text in the Tag, the BBox will be bigger. If there is no text, the BBox will be smaller. What’s even more important to us, is that the HeadPosition of the Tag that has no text will be very close to the edge of the Bounding box, as opposed to one that has some text in it, since text would stretch the BBox further out. Here’s my approach:

Ps. The breakdown of the geometry + distance calculations can be made a little “less nodes”, but I wanted to be really explicit.

Here’s the code for those two Python nodes:

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

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

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument

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

import System
from System import Array
from System.Collections.Generic import *

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


def process_list(_func, _list):
    return map(lambda x: process_list(_func, x) if type(x) == list else _func(x), _list)

def get_points(tag):
	e = UnwrapElement(tag)
	bb = e.get_BoundingBox(doc.ActiveView)
	a = Autodesk.DesignScript.Geometry.Point.ByCoordinates(bb.Min.Y, bb.Min.Z, bb.Min.X)
	b = Autodesk.DesignScript.Geometry.Point.ByCoordinates(bb.Max.Y, bb.Min.Z, bb.Min.X)
	c = Autodesk.DesignScript.Geometry.Point.ByCoordinates(bb.Max.Y, bb.Max.Z, bb.Max.X)
	d = Autodesk.DesignScript.Geometry.Point.ByCoordinates(bb.Min.Y, bb.Max.Z, bb.Max.X)
	return [a,b,c,d]

try:
    errorReport = None
    output = process_list(get_points, IN[0])
except:
    import traceback
    errorReport = traceback.format_exc()

if None == errorReport:
    OUT = output
else:
    OUT = errorReport
# Copyright(c) 2019, Konrad K Sobon
# @arch_laboratory, http://archi-lab.net

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

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument

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

import System
from System import Array
from System.Collections.Generic import *

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


def process_list(_func, _list):
    return map(lambda x: process_list(_func, x) if type(x) == list else _func(x), _list)

def get_head_position(tag):
	try:
		e = UnwrapElement(tag)
		p = e.TagHeadPosition
		return Autodesk.DesignScript.Geometry.Point.ByCoordinates(p.Y, p.Z, p.X)
	except:
		return None

try:
    errorReport = None
    output = process_list(get_head_position, IN[0])
except:
    import traceback
    errorReport = traceback.format_exc()

if None == errorReport:
    OUT = output
else:
    OUT = errorReport

And here’s a little preview video:

Finally Dynamo Definition:

orphanedTags.dyn (46.7 KB)

Ps. I had another look at the issue here, and posted a detailed solution on my blog: http://archi-lab.net/identifying-orphaned-tags-and-dynamo-bugs/ That should cover all of the issues raised above.

6 Likes