Первый скрипт в Dynamo: нумерация помещений по шагам
Собираем первый рабочий граф в Dynamo на живой задаче: нумерация помещений. Ноды, порты, уровни списков и две ловушки, на которых спотыкаются все новички.
212 помещений в трёхсекционном жилом доме. Их нужно перенумеровать после того, как планировки поехали: секция, этаж, порядок по часовой стрелке. Руками это часа три, если не отвлекаться и не сбиться на седьмом этаже. Скрипт делает то же самое за 40 секунд, и большую часть этого времени Revit просто перерисовывает марки.
Разберём такой скрипт от пустого холста до записанного параметра. Не «обзор возможностей», а конкретная сборка: какие ноды, в какой порт, что сломается и почему.
Почему именно нумерация
Первую автоматизацию выбирают неправильно. Берут что-нибудь красивое: расстановку по кривой, генеративный фасад, разбор IFC. Потом две недели ковыряются, бросают и делают вывод, что Dynamo «не для реальных задач».
Нумерация помещений подходит идеально по трём причинам. Она вам действительно нужна. Результат виден глазами сразу, без запуска спецификаций. И она содержит почти все базовые кирпичи: сбор элементов, чтение параметра, сортировка, группировка, запись обратно в модель.
Версии. У меня под рукой Revit 2022 (Dynamo 2.12), 2023 и 2024 (Dynamo 2.17 и выше). Всё, что ниже, работает во всех трёх без пакетов из Package Manager. Это важно: скрипт без внешних пакетов вы потом отдадите коллеге, и у него он тоже запустится.
Открываем и настраиваем
Вкладка «Управление» (Manage) → Dynamo. Открывается стартовое окно, жмём New.
Первое, что нужно сделать до всего остального: переключить режим запуска. Внизу левой панели есть выпадающий список Run: Automatic / Manual / Periodic. По умолчанию стоит Automatic, и это единственная настройка, из-за которой новички теряют модели. В автоматическом режиме граф пересчитывается на каждое ваше действие. Подключили ноду записи параметра, случайно задели значение, и Dynamo уже записал что-то в 212 помещений. Ctrl+Z в Revit это откатывает, но не всегда так, как вы ждёте.
Ставьте Manual. Запуск только по кнопке Run, когда вы к нему готовы.
Сборка графа
Ноды ищутся двойным кликом по пустому холсту. Начинаем.
1. Categories. Выпадающий список всех категорий Revit. Выбираем «Помещения» (Rooms). Выход у ноды один, называется Category.
2. All Elements of Category. Вход Category соединяем с выходом предыдущей ноды. На выходе получаем список всех помещений в модели. Раскройте превью под нодой: там должно быть 212 строк вида Room. Если ноль, значит вы в файле, где помещений нет, или они в связанной модели (об этом ниже).
3. Element.GetParameterValueByName. Здесь начинается работа с данными. Вход element берёт наш список, вход parameterName ждёт строку. Строку даём через ноду String, вписываем туда Уровень. Именно так, как параметр называется в вашей локализации Revit, с той же буквой и без лишних пробелов. Русский Revit ждёт русское имя, английский - Level. Это причина примерно половины пустых выходов на первом часу знакомства с Dynamo.
4. List.GroupByKey. Раскладывает помещения по уровням. Вход list - помещения, вход keys - уровни с предыдущей ноды. На выходе два порта: groups (списки помещений по этажам) и uniqueKeys (сами уровни). Нам нужен groups.
5. Сортировка внутри этажа. Помещения на этаже лежат в том порядке, в каком их создавал проектировщик, то есть в случайном. Сортируем по координате. Берём Element.GetLocation (в Dynamo 2.13+ это ядро, в 2.12 придётся взять Clockwork или маленький Python-узел), из точки достаём Point.X и Point.Y, дальше List.SortByKey.
Честно: сортировка «по часовой стрелке» через координаты работает только на регулярных планировках. На доме-башне с ядром посередине я в итоге сортировал по углу от центра секции. Это отдельная история и лишние полчаса.
6. Code Block с номерами. Двойной клик, пишем:
"К" + (1..List.Count(rooms));
Code Block - это текстовое поле для языка DesignScript. Он умеет то, ради чего иначе пришлось бы ставить пять нод. Запись 1..25 даёт диапазон чисел, 1..#25 - ровно 25 значений, "К" + число склеивает строку.
7. Element.SetParameterByName. Финал. Вход element - отсортированный список, parameterName - строка Номер, value - наши номера.
Порты, связи и лейсинг
Три вещи, которые в учебниках проговаривают вскользь, а на практике съедают вечер.
Цвет и направление. Выход всегда справа, вход слева. Тянуть можно в любую сторону, но связь пойдёт только выход → вход. Порт, подсвеченный красным после запуска, означает не «ошибку соединения», а ошибку внутри ноды: наведите курсор, там текст предупреждения.
Лейсинг (Lacing). Правый клик по ноде → Lacing. Три варианта: Shortest, Longest, Cross Product. Разница видна, когда на входах списки разной длины. Подаёте 212 помещений и одно имя параметра: при Shortest обработается одно помещение, при Longest все 212. Значение по умолчанию Auto обычно угадывает, но не всегда. Пустой результат при живых входных данных - первый подозреваемый именно лейсинг.
Уровни списков (List Levels). У входного порта есть маленькая стрелка >, за ней настройка @L1, @L2, @L3. После GroupByKey у вас список списков: этажи, внутри этажей помещения. Нода, которая ждёт плоский список, на вложенном ведёт себя странно. Иногда ошибка, иногда молча берёт первый уровень. Переключение на @L2 заставляет ноду работать с каждым подсписком отдельно. Разобравшись с этим один раз, вы закрываете половину вопросов «почему у меня не считается».
Ловушка, о которой не пишут
Запускаем. Dynamo желтеет, в предупреждениях висит что-то про duplicate number, а в модели вместо К1, К2, К3 появились К1, К2 2, К3 3.
Причина простая. Номер помещения в Revit уникален в пределах проекта. Пока вы пишете новые номера, старые ещё на месте. Скрипт добирается до пятого помещения, пытается записать К5, а К5 уже занят помещением на другом этаже. Revit не ругается на весь скрипт, он тихо дописывает суффикс.
Лечится в два прохода. Первый: пишем всем помещениям временные значения, которых в проекте гарантированно нет.
// Code Block, проход 1: временные номера
"tmp_" + (1..List.Count(rooms));
Второй проход пишет уже финальные. Тот же граф, только строка префикса другая, а перед ним нода записи временных значений. В моей практике это две ветки одного графа с ручным запуском по очереди. Некрасиво, зато работает и не требует объяснений при передаче коллеге.
Вторая мелочь того же рода: помещения без границ (Not Enclosed) и незамещённые (Redundant) тоже попадают в выборку. Их лучше отфильтровать через Element.GetParameterValueByName по площади и List.FilterByBoolMask, иначе нумерация поедет на пустых объектах.
Проверка результата
Скрипт отработал, но верить ему на слово нельзя. Три способа убедиться, что всё встало правильно:
- спецификация помещений, отсортированная по номеру, глазами по 20 строкам с каждого этажа;
- фильтр вида, подсвечивающий помещения с пустым номером красным (10 минут настройки, дальше пользуетесь всегда);
- обратный прогон Dynamo: собрать номера и прогнать через
List.CountиList.UniqueItems- если числа разошлись, где-то дубли.
Третий вариант я держу отдельным маленьким графом-проверялкой. Он ничего не пишет в модель, только считает. Полезно давать его вместе с основным скриптом.
Где это не работает
Скрипт не тронет помещения в связанной модели. All Elements of Category собирает элементы только текущего документа. Для связей нужен другой набор нод и права на запись, которых у вас в чужом файле нет.
Не сработает и на файлах, где номер помещения заполняется из внешней таблицы через плагин заказчика: скрипт запишет своё, плагин при следующей синхронизации перезапишет обратно. Такое встречалось на объекте с BIM-регламентом от техзаказчика, там нумерацию отдавали их системе.
Не ждите, что первый граф будет работать вечно. Обновили Revit до следующей версии - проверьте. Ноды ядра стабильны, но параметры проекта и шаблоны меняются чаще, чем сам Dynamo.
И честно про экономию времени. Написание этого скрипта с нуля новичком занимает от четырёх часов до двух дней. На одном доме он не окупается. Окупается на пятом, когда его запускают за минуту и без раздумий.
Три сообщения, которые вы точно увидите
Ошибки в Dynamo выглядят одинаково: нода желтеет, под ней текст. Текст английский и не всегда честный. Разберём три самых частых.
«Warning: Element.GetParameterValueByName operation failed. The parameter name is not found.»
Перевод на человеческий: параметра с таким именем у элемента нет. В девяти случаях из десяти виновата не модель, а строка на входе. Лишний пробел в конце, латинская C вместо русской, «Номер помещения» вместо «Номер». Лечится за минуту: выделите элемент в Revit, откройте свойства, скопируйте имя параметра оттуда буква в букву. Второй по частоте виновник - локализация: граф писали в русском Revit, запускают в английском.
«Warning: Element.SetParameterByName operation failed. The parameter is read-only.»
Вы пытаетесь писать в поле, которое считает сам Revit. Площадь помещения, объём, периметр, отметка уровня. Список read-only параметров нигде не опубликован полностью, узнаётся опытом. Если запись нужна принципиально, значение кладут в отдельный общий параметр и уже его выводят в спецификацию.
«Dereferencing a non-pointer.»
Самое загадочное сообщение Dynamo и самое частое у новичков. Означает примерно следующее: нода ждала один элемент, а получила список, или наоборот. Иногда в цепочку пробрался null от помещения без границ. Порядок разбора такой: раскрыть превью у каждой ноды слева направо, найти первую, где вместо данных пустота, и смотреть уровни списков у её входа. В 80% случаев проблема решается переключением порта на @L2 или вставкой List.Flatten.
Отдельная разновидность беды: ошибок нет, предупреждений нет, а в модели ничего не изменилось. Проверьте режим запуска. Manual требует нажать Run, и первое время об этом забывают все.
Что проверить, прежде чем показывать граф коллеге
- Граф сохранён в режиме Manual.
- Все ноды подписаны по-русски: через месяц вы сами не вспомните, что делает
Code Blockв углу холста. - Пакеты не используются вообще. Если без Clockwork не обошлось, напишите это в описании графа.
- На пустой выборке скрипт не падает, а сообщает «обработано 0 элементов». Это отдельная ветка с
List.Count, минут на десять работы, зато пользователь понимает, что произошло. - Файл лежит не на вашем рабочем столе.
- Вы прогнали граф дважды подряд на одной модели и результат не изменился. Скрипт, который при повторном запуске дописывает префикс поверх префикса, вернётся к вам вечером пятницы.
Короткие ответы на частые вопросы
Нужно ли уметь программировать? Для первого графа нет. Уровня «понимаю, что такое список и цикл» достаточно. Python понадобится, когда захочется условий сложнее двух ветвей.
Скрипт может испортить модель? Может. Он делает ровно то, что написано, включая запись не туда. Отсюда правило про копию файла и Manual-режим. Ctrl+Z после запуска откатывает всё изменённое графом одним шагом, но только пока вы не сделали в Revit ничего другого.
Почему у коллеги мой .dyn не открывается? Три причины по частоте: у него старше версия Dynamo (граф из 2.17 в 2.12 не откроется), нет установленного пакета, другая локализация Revit и не совпали имена параметров.
Сколько времени уходит на освоение? Первый рабочий граф собирается за вечер. Уверенность приходит примерно к десятому, это два-три месяца по паре часов в неделю. Дальше вы перестаёте искать готовые скрипты в интернете и пишете свои быстрее, чем находите чужие.
Следующий шаг
Соберите этот граф на копии рабочего файла. Не на боевом. Дойдя до первой записи параметра, сохраните файл под новым именем и только потом жмите Run.
Когда граф заработает, его захотят коллеги. Отдавать .dyn по почте не надо, для этого есть Dynamo Player: как подготовить скрипт к передаче, разобрано в отдельной статье. Если руки чешутся автоматизировать не нумерацию, а заполнение параметров пачкой, начните с этого разбора. А когда скриптов станет больше десятка и захочется настоящих кнопок в интерфейсе, посмотрите на pyRevit.
Задача сложнее учебной? Опишите её в Telegram или через форму на странице контактов: посмотрим, решается ли она графом за вечер или там уже нужен плагин. Что мы делаем на таких задачах, коротко описано в разделе услуг.
Нужен похожий BIM/AI процесс?
Напишите в Telegram или на email — разберём задачу и предложим архитектуру решения.
Telegram Оставить заявку