Hide/unhide Annotations with Dynamo

批量隐藏标注

在实际工作中,我们给项目的不同阶段标注了不同的信息(大多是尺寸标注),在出图时,就遇到了问题:为了工作和绘图方便,两个阶段公用了一个视图,但是阶段1的图不需要阶段2的标注,反之亦然。所以在出图前夕,我们需要将多余的标注信息隐藏。的由于标注族(Annotation Families)不能用视图过滤器(view Filters)来进行隐藏/显示的操作,所以我做了一个小脚本来快速完成这项工作。

一个示例,橘色和蓝色分别代表不同的标注族,需要用脚本控制它们在某些视图的可见性。

这次我同样用到了来自DATA|SHAPES 的UI界面节点:

操作界面

使用过程:首先选择要改变可见性的族类别(Category),然后用一个关键词过滤出(Filter)需要被涵盖的族名称(Type Name),同时可选的给出要在哪些视图上进行操作(否则默认所有视图),最后选择要进行的操作(hide or unhide)。工作完成后,Dynamo会生成一个Excel表格作为结果报告。

Dynamo 脚本如下:

操作界面(UI) 和 结果报告(Report)这两部分无需赘言,这个脚本的重点在于Core的部分。下面具体解释一下Python Script:

# Coded by kj-luo
# kj-luo.com/

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *
clr.AddReference('System')
from System.Collections.Generic import List
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

# the IN-part, including the keywords of the names of view and family type, which participate in the game. "Switch" determins wether the Elements should be hidden or shown.
# 这里是python node的输入端。这里我们需要族的类别,族和视图的关键词(用于过滤),以及一个开关(Switch)用来判定操作是隐藏或者显示。
categoryId = UnwrapElement(IN[0]).Id
filterViewName = IN[1]
filterTypeName = IN[2]
switch = IN[3]

fiViewsName = []
fiElements = []
out = []


###### DEFINITIONS #############

# two definitions hide and unhide are separately coded
# 两个大同小异的definitions用来进行具体的隐藏和显示操作
def hide(doc,element,fiViewsName):
	report = []
	# here oView should be the views on which elements would be hidden.
	# 这里的oView列表就是最后需要被隐藏物件的列表
	oView = []

	# vitally important is, we can hide/unhide something from an owner view, but it dosen't affect the same element on dependent views.
	# So all dependent views must be collected in list oView.
	# 很重要的是,我在某个主视图隐藏一个图元后,这个主视图的相关视图上同一个图元并不会被影响到。所以所有相关视图都得被列出来。
	mView = doc.GetElement(element.OwnerViewId)
	oView.append(mView)
	dViews = [doc.GetElement(x) for x in mView.GetDependentViewIds() ]
	id = element.Id
	for v in dViews: oView.append(v)
	# iCollection list:
	hideId = List[ElementId]([id])

	# loop through all views (when they are in the filterd view list) and hide the element with its ID.
	# 通过循环找到所以需要操作的视图,并将上面的图元隐藏起来。
	for view in oView:
		if view.Name in fiViewsName:
			try:
				view.HideElements(hideId)
				report.append(str(id) +" hidden " + "(" + view.Name + ")")
			except:
				report.append(str(id) +" not hidden " + "(" + view.Name + ")")
		else:
			report.append(str(id) +" view is filtered " + "(" + view.Name + ")")

	# a report of the result would be very helpful
	# 最后生成一个报告
	return report
		
# the same for the definition unhide.
# 运用同样的道理做一个使图元显示的definition。
def unhide(doc,element,fiViewsName):
	report = []
	oView = []
	mView = doc.GetElement(element.OwnerViewId)
	oView.append(mView)
	dViews = [doc.GetElement(x) for x in mView.GetDependentViewIds() ]
	id = element.Id
	
	for v in dViews: oView.append(v)
	hideId = List[ElementId]([id])
	
	for view in oView:
		if view.Name in fiViewsName:
			try:
				view.UnhideElements(hideId)
				report.append(str(id) +" shown " + "(" + view.Name + ")")
			except:
				report.append(str(id) +" still hidden " + "(" + view.Name + ")")
		else:
			report.append(str(id) +" view is filtered " + "(" + view.Name + ")")
	return report
		

###### COLLECTIONS #############

# collect all view names excluding view templates
# 搜集所有除了视图样板外的视图对象
viewsName = [x.Name for x in FilteredElementCollector(doc).WhereElementIsNotElementType().OfClass(View).ToElements() if not x.IsTemplate]

# filter the views with keyword
# 用关键词过滤视图对象
if filterViewName:
	for viewName in viewsName:
		if filterViewName in viewName:
			fiViewsName.append(viewName)		
else: fiViewsName = viewsName

# collect all elements from the chosen category and type name. And as well filter them with the keyword.
# 同样的,根据族类别和族名称搜集最终要被操作的对象图元
elements =[x for x in FilteredElementCollector(doc).OfCategoryId(categoryId).WhereElementIsNotElementType().ToElements() ]
for ele in elements:
	try:
		typeName = doc.GetElement(ele.GetTypeId()).get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString()
		if filterTypeName in typeName: fiElements.append(ele)
	except: pass
	

###### TRANSACTION #############

TransactionManager.Instance.EnsureInTransaction(doc)
# now we can start the transaction
# 现在可以开启transaction
for ele in fiElements:
	viewId = ele.OwnerViewId.IntegerValue
	# if an element dosen't have an ownerId, it is not an Annotation.
	# 一个没有视图信息的图元并不是一个标注,所以这里被排除在外。
	if viewId == -1:
		out.append("Category not supported")
		break
		
	else:
		if switch: out.append(hide(doc,ele,fiViewsName))
		else: out.append(unhide(doc,ele,fiViewsName)) 
		
TransactionManager.Instance.TransactionTaskDone()

OUT = out

最后运行的结果报告(Report)会展示哪些图元在哪些视图(包括所有的主视图和相关视图)上被隐藏/显示了,如此:

每一行代表一个图元,如果包括相关视图会在同一行其它列展示。

如果对这个脚本稍加改动,操作对象就可以不限于标注图元,而是各个类别的族。这里就不作深入的讨论了。


发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注