Найти тему
Хроники Георга

Занимательное Dynamo. Расстановка текстовых меток для топографической подосновы

Введение: вообще говоря, я давно хотел написать набор материалов "погружение в dynamo" параллельно с моим освоением этого модуля, но как-то не сложилось. Постараюсь это компенсировать серией статей, где буду рассматривать разные рабочие примеры использования Dynamo для решения задач по автоматизации рутинных операций (преимущественно, в Civil 3D).

Что мы будем делать: статья будет посвящена рабочему процессу написания скрипта Dynamo, расставляющему по чертежу набор текстовых меток по заданному правилу. При этом я буду отходить от использования встроенных нодов (отдельных "команд") и Design Script, а применять Python-инструкции.

Лого Dynamo
Лого Dynamo

1. Постановка вопроса и краткий обзор решения проблемы

Итак, у нас есть набор DWG-планшетов с фиксированной структурой именования (набор чисел) на территорию СПб. Нас интересует получение шаблона-разграфки на всю территорию, для чего необходимо циклом пройтись по всем квадратам и расставить там нужный код.

https://rgis.spb.ru/mapui/ - Интернет-ГИС-ресурс для СПб, где обозначенные квадраты в частности и фигурируют

Наша сетка квадратов будет состоять из нескольких "уровней":

  • уровень 1 (4000х4000м);
  • уровень 2 (М 1:2000) (1000х1000м), их 16 штук в глобальных;
  • уровень 3 (М 1:500) (250х250м), их 16 штук в тысячных квадратах;

Всего квадратов уровня 1 - 45*48 штук; крайний левый угол - в точке (0,0) МСК 1964.

Пример наименования планшетов топоосновы для квадрата уровня 1 - 2428. Выделенный красной рамкой квадратик имеет код 2428-11-08
Пример наименования планшетов топоосновы для квадрата уровня 1 - 2428. Выделенный красной рамкой квадратик имеет код 2428-11-08

2. Определяем структуру скрипта, используемые ноды, тестовый прогон

Для работы скрипта нам понадобится нод, создающий текст в заданной точке с набором настроек (красный текст). Остальную "болванку" - на картинке выше кроме красного текста мы создадим в виде прямоугольного массива (это проще).

Формируем "подоснову" для работы - сетка квадратов первого уровня, в середине каждого из квадратов которой будет размещен наш красный текст, отображающий номер каждого из квадратов
Формируем "подоснову" для работы - сетка квадратов первого уровня, в середине каждого из квадратов которой будет размещен наш красный текст, отображающий номер каждого из квадратов

Использовать мы будем базовый нод MText.Create из стандартного набора команд и параметры для него из этого же класса

Базовый нод MText.Create
Базовый нод MText.Create

Теперь подключаем к нему набор вспомогательных нодов, описывающих стиль текста, его содержимое, точку привязки, слой и текущий чертеж (Document.Current и ModelSpace). Кстати, если не указать слой, то скрипт выполнится без ошибок, а объектов создано не будет :D

Примечание: особенность реализации скриптов Dynamo в AutoCAD состоит в необходимости указывать пространство (Block) действия данного скрипта. Почти всегда - это пространство модели, но иногда может быть и пространство отдельного Листа.

Тестовый прогон нода
Тестовый прогон нода

Первый прогон скрипта всегда рекомендуется делать для одного значения, до момента подключения иных конструкций - чтобы было легче отлаживать работу скрипта (особенно при использовании пользовательских python-скриптов или библиотек на C# )

Да-да, вот такими небольшими шагами идем к конечной цели (Оригинал: https://avatars.mds.yandex.net/get-zen_doc/198359/pub_5b031feb83090562e4b1650f_5b0e832057906a66d8e239bb/scale_1200)
Да-да, вот такими небольшими шагами идем к конечной цели (Оригинал: https://avatars.mds.yandex.net/get-zen_doc/198359/pub_5b031feb83090562e4b1650f_5b0e832057906a66d8e239bb/scale_1200)
Анализируем поведение текста
Анализируем поведение текста

Видим, что выравнивание у нас применилось, а вот высота - нет. Она записалась в параметр "Пользовательская высота". Почему так происходит я, честно, не знаю - придется исправить это потом вручную.

Примечание: в качестве текстового стиля используется текущий активный стиль.

3. Создаем циклы для будущих значений

Теперь переходим к клубничке - созданию Python' скрипта. который будет генерировать цикл и фиксировать его в списки, которые впоследствии будут подаваться на вход нашего нода для создания объекта MText.

Именуем Python скрипт и задаем ему группу входных параметров через элемент CodeBlock - точку начала отсчета цикла, размер сетки по горизонтали и по вертикали и размер квадрата планшета
Именуем Python скрипт и задаем ему группу входных параметров через элемент CodeBlock - точку начала отсчета цикла, размер сетки по горизонтали и по вертикали и размер квадрата планшета
Записываем сам Python скрипт и далее проанализируем его работу:
Записываем сам Python скрипт и далее проанализируем его работу:
  1. Инициализируем группу входных параметров - то, что мы подаем слева на Python-нод;
  2. Инициализируем используемые параметры в теле кода - в данном случае, пару списков (в одном "Text_List", будем держать текстовые значения меток; а в другом "Points_List" - строковое представление координат. Здесь я намеренно делаю второй список строковым чтобы показать пример обработки строковых значений координат в числа в рамках операции добавления Точки привязки текста (объекта GesignScript.Geometry.Point)
  3. Вспомогательная функция GetOneCoordStr - возвращает строковое представление числа; по правилам математики, если число меньше 10, то оно состоит из 1 цифры - но нам для использования необходимо чтобы в этом случае первой цифрой был "0" - что и реализуется в функции. Функция обозначается конструкцией def. Подробнее о функциях можно почитать здесь.
  4. Вторая вспомогательная функция GetStrCoordFromNum - по большому счету, она могла бы быть реализована и в теле основного метода. Она возвращает строку от двух чисел - то самое текстовое содержимое, которое мы будем впоследствии размещать
  5. Основной цикл for (подробнее о циклах можно прочитать тут); здесь происходит последовательный перебор числового промежутка от "0" до размера сетки планшетов. В теле цикла происходит 2 операции помимо перехода к следующему квадрату (+=1): это добавление в список "Text_List" значения, которое будет иметь метка, и координаты позиционирования в список "Points_List" в качестве строки, разделенной запятой
  6. В конце мы формируем новый список "ToExport", куда вкладываем 2 сформированных списка, получая так называемый двухсвязный список (подробнее см. на этой странице).
  7. OUT = ToExport - выход Python скрипта - это наш список с парой вложенных списков
Теперь подаем первый воженный список на text в нод MText.Create. Разложили мы список при помощи простой операции через CodeBlock
Теперь подаем первый воженный список на text в нод MText.Create. Разложили мы список при помощи простой операции через CodeBlock
Формируем заготовку для следующего скрипта - преобразование строки в набор чисел (координат) для подачи как элемента типа GesignScript.Geometry.Point
Формируем заготовку для следующего скрипта - преобразование строки в набор чисел (координат) для подачи как элемента типа GesignScript.Geometry.Point
Наш составленный скрипт. Дадим ему объяснение далее:
Наш составленный скрипт. Дадим ему объяснение далее:
  1. Первым действием мы подключаем "пространство имен" clr (так как мы используем не чистый Python, а его гибрид - IronPython, то здесь мы подключаем .NET пространство - для подключения к .NET-библиотекам, составляющим Dynamo API и Autodesk API (API для Revit, Civil 3D и пр.). В данном случае, мы подключаем библиотеку ProtoGeometry для использования геометрии Dynamo. Нас интересует только один объект - Point, поэтому только его мы и "импортируем" в чертеж [здесь логика похожа на С++, где мы подключаем через #<lib_name> все методы N-ной библиотеки]
  2. Инициализируем список "Points_List", в который будем вносить элемент GesignScript.Geometry.Point
  3. Основной цикл for; здесь мы перебираем построчно входной список, формируя на базе каждой строки новый массив с разделителем "," и преобразуя каждое строчное значение в число типа float (подробнее о типизации в Python смотри тут), после чего заносим в значение координат точки эти числа и "упаковываем" Point в наш ранее объявленный список "Points_List"
  4. OUT = Points_List - в качестве выходного параметра выдаем список с элементами GesignScript.Geometry.Point
Финальный вид скрипта
Финальный вид скрипта
По окончании работы скрипта вручную меняем высоту текста на нужное значение
По окончании работы скрипта вручную меняем высоту текста на нужное значение

4. Некоторые дополнительные действия

Чтобы сделать скрипт более информативным, особенно при его потенциальном использовании другими Пользователями следует методически сопровождать скрипт пояснениями.

Данная опция, либо комбинация клавиш
Данная опция, либо комбинация клавиш
Оставляю пояснение
Оставляю пояснение

Также размещаю данный скрипт в своем репозитории по ссылке и вношу ее в комментарий (чтобы Пользователь мог скачать последнюю актуальную версию скрипта и прочесть на GitHub какие обновления в него были внесены).

Также меняем логику подачи элементов для возможности инициировать их как "Входные" параметры - для редактирования в Проигрывателе Dynamo
Также меняем логику подачи элементов для возможности инициировать их как "Входные" параметры - для редактирования в Проигрывателе Dynamo
Прокликиваем параметры для всех значений
Прокликиваем параметры для всех значений
Также вносим в группу начальных параметров целевой слой, где будут размещаться элементы (по умолчанию, нулевой слой)
Также вносим в группу начальных параметров целевой слой, где будут размещаться элементы (по умолчанию, нулевой слой)
Законченный вид скрипта в среде Dynamo
Законченный вид скрипта в среде Dynamo
Вид скрипта
Вид скрипта
Скрипт отработал (ошибки - это превышение диапазона координат)
Скрипт отработал (ошибки - это превышение диапазона координат)
Конечный результат (на фоне блок-заготовка для прямоугольного массива)
Конечный результат (на фоне блок-заготовка для прямоугольного массива)

5. Заключение

В данной статье мы рассмотрели пример создания простого Dynamo-скрипта для Civil 3D с использованием ряда Python [IronPython] функций, заменяя "лапшу" стандартных нодов. Провели описание всех действий и выложили скрипт на GitHub для возможности загрузки пользователями.

Далее я продолжу писать в таком же ключе; буду благодарен за идеи, примеры реализации чего рассмотреть - пишите об этом в комментариях, либо в telegram-группе Dynamo for Civil 3D.

#autodesk #dynamo #ironpython #pyton #civil 3d #autocad #bim #script #python script #dynamo for civil 3d

Не пропускайте публикации, подписывайтесь на Telegram-канал с тизерами статей.