Dynamo15 августа 20261767 слов

Первый скрипт в Dynamo: нумерация помещений по шагам

Собираем первый рабочий граф в 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, иначе нумерация поедет на пустых объектах.

Проверка результата

Скрипт отработал, но верить ему на слово нельзя. Три способа убедиться, что всё встало правильно:

Третий вариант я держу отдельным маленьким графом-проверялкой. Он ничего не пишет в модель, только считает. Полезно давать его вместе с основным скриптом.

Где это не работает

Скрипт не тронет помещения в связанной модели. 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, и первое время об этом забывают все.

Что проверить, прежде чем показывать граф коллеге

Короткие ответы на частые вопросы

Нужно ли уметь программировать? Для первого графа нет. Уровня «понимаю, что такое список и цикл» достаточно. Python понадобится, когда захочется условий сложнее двух ветвей.

Скрипт может испортить модель? Может. Он делает ровно то, что написано, включая запись не туда. Отсюда правило про копию файла и Manual-режим. Ctrl+Z после запуска откатывает всё изменённое графом одним шагом, но только пока вы не сделали в Revit ничего другого.

Почему у коллеги мой .dyn не открывается? Три причины по частоте: у него старше версия Dynamo (граф из 2.17 в 2.12 не откроется), нет установленного пакета, другая локализация Revit и не совпали имена параметров.

Сколько времени уходит на освоение? Первый рабочий граф собирается за вечер. Уверенность приходит примерно к десятому, это два-три месяца по паре часов в неделю. Дальше вы перестаёте искать готовые скрипты в интернете и пишете свои быстрее, чем находите чужие.

Следующий шаг

Соберите этот граф на копии рабочего файла. Не на боевом. Дойдя до первой записи параметра, сохраните файл под новым именем и только потом жмите Run.

Когда граф заработает, его захотят коллеги. Отдавать .dyn по почте не надо, для этого есть Dynamo Player: как подготовить скрипт к передаче, разобрано в отдельной статье. Если руки чешутся автоматизировать не нумерацию, а заполнение параметров пачкой, начните с этого разбора. А когда скриптов станет больше десятка и захочется настоящих кнопок в интерфейсе, посмотрите на pyRevit.

Задача сложнее учебной? Опишите её в Telegram или через форму на странице контактов: посмотрим, решается ли она графом за вечер или там уже нужен плагин. Что мы делаем на таких задачах, коротко описано в разделе услуг.

Нужен похожий BIM/AI процесс?

Напишите в Telegram или на email — разберём задачу и предложим архитектуру решения.

Telegram Оставить заявку