В субботу 20 июля я сделал короткий стрим о том, как сделать то, что написано в заголовке статьи. В итоге сделать до конца не получилось. Я думал, что там всё будет просто, но в программировании я слабоват, так что потерпел неудачу. Но потом добил этот алгоритм и теперь выложу код сюда.
Я планировал эфир на полчасика. Тык-тык, быстро накидаю ноды и код в Питоне, буду красавчик.
Я обосрался. У меня получилось обработать элементы с первого уровня вложенности, но ведь вложенность может быть очень разной.
В итоге три часа сидел и разбирался, как решить проблему. Вроде получилось, я решил выложить код сюда, чтобы вы могли тоже применять его в своей работе, заодно дадите обратную связь по тому, как скрипт обрабатывает элементы с большой вложенностью.
Ограничения
Скрипт работает только с параметрами экземпляра с типом данных текст. То есть копировать значения можно только из текстового параметра в текстовый и только из параметра экземпляра в параметр экземпляра.
Если не знаете, что такое экземпляр и тип данных, читайте статью про виды параметров и статью про понятия типа и экземпляра.
Скрипт написал для работы с инженерными система и в первую очередь для копирования параметра «Имя системы».
Алгоритм
Скрипт состоит из двух частей: нодов и кода в Питоне.
Нодами я получаю элементы для обработки и выбираю имена параметров, из которых копирую и в которые записываю значения. Эти имена параметров можно вывести в Проигрыватель Динамо.
Если вам нужен иной принцип отбора элементов, то поменяйте эту нодовую часть. Вот так выглядит у меня:
Вторая часть скрипта — это код в Питоне. Я приведу его ниже, скопируйте его и вставлять в нод Python Script. Если вы программист, дальше не читайте или читайте с закрытыми глазами, иначе из них пойдёт кровь. Я предупредил.
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager as DM
from RevitServices.Transactions import TransactionManager as TM
doc = DM.Instance.CurrentDBDocument
TM.Instance.EnsureInTransaction(doc) # Открытие транзакции
### Действия внутри транзакции ###
TM.Instance.TransactionTaskDone() # Закрытие транзакции
element_list = UnwrapElement(IN[0])
param_get_value = IN[1]
param_set_value = IN[2]
parent_elements = [] # получаем фэмили инстансы, которые не являются общими вложенными
TM.Instance.EnsureInTransaction(doc) # Открытие транзакции
for element in element_list:
if isinstance(element, FamilyInstance):
if element.SuperComponent:
pass
else:
parent_elements.append(element)
elif isinstance(element, MEPSystem):
pass
else:
param_value = element.LookupParameter(param_get_value).AsString() # имя системы
element.LookupParameter(param_set_value).Set(param_value)
def flat_list(leveled_list):
flatten = []
if isinstance(leveled_list, list):
for item in leveled_list:
if isinstance(item, list):
for subitem in item:
flatten.extend(flat_list(subitem))
else: flatten.append(item)
else:flatten.append(leveled_list)
return flatten
def subcomponents(element):
all_subs = []
if element.GetSubComponentIds():
sub_Id_list = element.GetSubComponentIds()
for sub_Id in sub_Id_list:
sub = doc.GetElement(sub_Id)
if sub.GetSubComponentIds():
all_subs.append(sub)
all_subs.append(subcomponents(sub))
else:
all_subs.append(sub)
return all_subs
all_subcomponents = []
for el in parent_elements:
param_value = el.LookupParameter(param_get_value).AsString() # имя системы
el.LookupParameter(param_set_value).Set(param_value)
if el.GetSubComponentIds():
shared_nested = flat_list(subcomponents(el))
for sn in shared_nested:
sn.LookupParameter(param_set_value).Set(param_value)
all_subcomponents.append(sn)
TM.Instance.TransactionTaskDone() # Закрытие транзакции
OUT = parent_elements, all_subcomponents
Вот такой код. На выходе первый список — это родительские семейства, то есть те, которые не являются вложенными. Второе список — это все вложенные общие со всех уровней, которые обработал скрипт.