Добрый день!
Разрабатываю скрипт на Dynamo для автоматического изменения высоты пространств. Так как обычными нодами нельзя изменить данный параметр (only read), то пытаюсь реализовать запись через Python.
На вход подаю два списка:
IN[0] - список пространств
IN[1] - список высот, на которые нужно заменить
Длины списков одинаковые.
Сам код получился такой:
import clr
clr.AddReference("RevitNodes")
import Revit
space = IN[0]
hight = IN[1]
Revit.Transaction.Transaction.Start(space)
for i in space:
k=UnwrapElement(i).LookupParameter("Смещение сверху").Set(hight[2])
Revit.Transaction.Transaction.End(space)
OUT = space
Не получается подать на перезапись высоты списком. Если на "Set(hight[2])" подать одиночное значение, то все хорошо, если просто оставить "Set(hight)" или "Set(hight[i])" питон ругается
Pyton ругается потому что вы в значение пытаетесь сразу весь список подать.
Если у вас одинакового размера списки и по очереди нужно каждому элементу значение присвоить, то нужно в цикле перебирать не элементы, а индексы.
Попробуйте вот так:
import clr clr.AddReference("RevitNodes") import Revit space = IN[0] hight = IN[1] Revit.Transaction.Transaction.Start(space) for i in range(len(space)): k=UnwrapElement(space[i]).LookupParameter("Смещение сверху").Set(hight[i]) Revit.Transaction.Transaction.End(space) OUT = space
BIM-менеджер
Соавтор шаблонов ADSK КЖ/КМ 2021
Инженер-проектировщик КР, КЖ
Телеграм
Правила форума и некоторые нюансы по работе с текстовым редактором
Да, все заработало как надо, спасибо за помощь!
@tai эту же задачу можно решить и без обращения к индексам с помощью метода zip. Если списки равной длины, то это идеальный способ
for s, h in zip(space, height):
k=UnwrapElement(s).LookupParameter("Смещение сверху").Set(h)
И этот метод тоже работает, за hEight отдельное спасибо )
А кто-нибудь может подсказать, существуют курсы посвященные чисто Python в Dynamo, ну или DesignScript+Python?
@tai отличные курсы у Максима Степанникова на степике.
Ребят, я с этим питоном все не могу успокоится... )))
Делаю уже другой скрипт, но таже проблема, и наверно схожее должно быть решение, поэтому продолжаю в этой теме.
Делаю скрипт, в котором надо реализовать перемещение элементов (труб и воздуховодов) по оси X и У. Как и в первой задаче есть список элементов, список ΔX и ΔY.
На просторах интернета нашел следующий код:
import clr
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
#Входные данные для этого узла будут сохранены в виде списка в переменной IN.
doc = DocumentManager.Instance.CurrentDBDocument
app = DocumentManager.Instance.CurrentUIApplication.Application
dataEnteringNode = IN
elementId = IN[0].Id
TransactionManager.Instance.EnsureInTransaction(doc)
ElementTransformUtils.MoveElement(doc,ElementId(elementId),XYZ(IN[1],IN[2],0))
TransactionManager.Instance.TransactionTaskDone()
OUT = 0
Проверил, он работает, все классно, но опять только с одним элементом, я пытался через цикл for по аналогии с прошлой задачей заставить его работать со списками, ничего не вышло. Кто-нибудь может его допилить?
сайт исходника кода https://russianblogs.com/article/38012006102/
Да было б чтоб показывать )
Было много вариантов, но самый первый это просто добавить цикл for и в его тело поместить перемещение (Move) с транзакциями, что-то вроде такого:
import clr
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
#Входные данные для этого узла будут сохранены в виде списка в переменной IN.
doc = DocumentManager.Instance.CurrentDBDocument
app = DocumentManager.Instance.CurrentUIApplication.Application
dataEnteringNode = IN
elementId = IN[0].Id
x = IN[1]
y = IN[2]
for i in range(len(x)):
TransactionManager.Instance.EnsureInTransaction(doc)
ElementTransformUtils.MoveElement(doc,ElementId(elementId),XYZ(x[i],y[i],0))
TransactionManager.Instance.TransactionTaskDone()
# Присвоите свой вывод переменной OUT.
OUT = 0
Длины списков одинаковые поэтому длину можно рассчитывать с любого входящего списка
В этом коде Питон ругается на строку "elementId = IN[0].Id" - AttributeError: 'list' object has no attribute 'Id'
@tai Вы пытаетесь взять id у списка. В ошибке написано, что объект список не имеет такого атрибута.
Тоже над этим думал, но если этот код использовать как есть, подать один элемент и на X, Y по одному числу, то все работаеткак надо, даже с Id
@tai и что?) один элемент — это один элемент, список — это список, совершенно другой объект. покажите, что подаёте в Питон-скрипт, что там за структура списка
Скорее всего у вас там список из трёх подсписков. Когда вы подаёте подсписок IN[0] и берёте у него свойство Id, то Ревит берёт, естественно, айди у списка. Но список не имеет такого свойства.
если у вас там три равных списка, то можно делать такой цикл
TransactionManager.Instance.EnsureInTransaction(doc) for el, x, y in zip(IN[0], IN[1], IN[2]): ElementTransformUtils.MoveElement(doc, el.Id, XYZ(x,y,0)) TransactionManager.Instance.TransactionTaskDone()
Правда, меня тут смущает, что координата Z равно нулю, он ведь вам элементы «опустит» на ноль файла. Вы там что перемещаете?
Данный код перемещает элементы на указанное смещение относительно своего текущего положения.
Насчет списков, то пробовал подавать и три отдельных списка и один список, в котором три подсписка, ни первое, ни второе не получилось.
Задача, которую я решаю, это смещение выделенных воздуховодов и труб так, чтобы между ними было равное расстояние, например 100 мм. Постоянная ситуация, когда по коридору идут куча воздуховдов, труб, какие-то в изоляции, какие-то нет, хочется это все выровнять, но руками это долго. Ниже записал видео как должен работать данный скрипт.
Пока не знаю как преобразовать код, чтоб они обрабатывал элементы списком, поэтому пока разбиваю весь список по одному элементу.
@tai посмотрите какой-нибудь базовый курс по питону. Ваш путь в корне не верный.
Вы разбиваете список, пишете 9 элементов (при этом теряете 1 элемент исходного списка, так как индексация начинается с 0), а если будет не 9 элементов, а 90? Тогда что будете делать?
Разберитесь с циклами, это совсем не сложно и это база, если хотите писать или использовать скрипты в Dynamo.
На том же степике есть бесплатные курсы по основам программирования
@muratovbim так о том и речь, что не зная таких базовых вещей пытаться что-то сделать в коде - бесполезная трата времени.