Дисклеймер: правовая сторона вопроса до конца не ясна, публикую как есть без некоторых частей (см. концовку).
Autodesk Dynamo в общем случае является OpenSource решением со своим Community, разработанный (?) под эгидой Autodesk. Dynamo поставляется как так называемая Core версия (open-source часть) и Core+"Internal" версия (под ряд продуктов Autodesk).
Здесь же ссылки на последующие части
«Renga API & Dynamo Core. Часть 2 - интерфейсы, константы, свойства, чтение свойств; выборка объектов модели и их свойства».
«Renga API & Dynamo Core. Часть 3 - создание новых свойств, присвоение объектам, транзакции».
«Renga API & Dynamo Core. Часть 4 - объекты, уровни, стили отображения и COM-типизация данных».
«Renga API & Dynamo Core. Часть 5 - геометрия объектов, общие выводы»
Примечание: "Internal" - это сугубо моё название, в реальности оно называется как-то по другому.
К чему я веду? К возможности подключения Core-версий к иным САПР, не на платформе Autodesk. Собственно говоря, Core-версия ни к какой САПР не привязана, это самостоятельное приложение.
Всё, что нам нужно - это подключить к Dynamo библиотеку, которая будет инициализировать API конкретной САПР. При этом реализация процесса будет состоять из двух важных частей:
- инициация подключения к САПР из-под Dynamo, в основном, как к COM-объекту (выстраивание логики процесса САПР, пространств модели и пр.);
- написание отдельных методов, позволяющих получать свойства/создавать что либо в пространстве модели данной САПР.
Как правило, самый *** - это понять как "дружить" Dynamo и процесс САПР с поправкой на то, что Dynamo не воспринимает интерфейсы и некоторые синтаксические конструкции языка типа ref, out и пр. Тут же он не любит, чтобы методы имели значения по умолчанию нестандартных типов (отличных от базовых типов .NET).
Ах да, совсем забыл - Dynamo написан на .NET (C# ), поэтому мы будем говорить только по .NET API. Не уверен насколько у него (Dynamo) налажена интероперабельность с C++ в части пользовательских библиотек (пока не пробовал), но в теории можно будет попробовать все методы писать на C++, а на C# делать лишь "обертку" их заголовков.
1. Загрузка и установка Dynamo Core
Здесь всё просто до безобразия -- качаем скомпилированную Core-версию с данного раздела, распаковываем и по сути сборка Core у нас готова.
Стоит упомянуть разве что про зависимость конкретной версии Dynamo-Core от версии .NET Framework. Так как Renga (к которой я и собираюсь "прикручивать" сборку имеет примеры API на .NET Framework 4.8, то я и качаю Core 2.12 (текущая предпоследняя стабильная). Вообще говоря, 4.8 начался вроде с Core 2.8 ... но тут я следовал принципу "последняя актуальная стабильная",
2. Настройка проекта библиотеки классов
Наш проект мы будем собирать также под .NET Framework 4.8 (как и Dynamo Core). Нигде в API Renga не регламентировано это, к слову.
Логику сборки делаю классической - пустое решение (VS) + библиотека классов на .NET Framework 4.8 и консольное приложение также на .NET Framework 4.8, через которое я запускаю внешнюю программу - DynamoSandbox.exe, куда уже импортирована локальная скомпилированная библиотека классов.
Сложным является вопрос хранения внешних зависимостей. В процессе программирования под Renga используется по-существу, единственная "COM-библиотека" RengaCOMAPI.tlb. В свойствах проекта в VS её нельзя настроить на копирование локально, а проект Dynamo будучи установленным не будет знать где она лежит.
Здесь я вынужденно ввожу первое условие: по абсолютному файловому пути C:\Work\RengaCOMAPI.tlb. должна лежать эта библиотека. К слову, распространять её в составе пакета (онлайн-публикация) я также не имею формального права от Разработчиков программы.
Безусловно, можно распространять пакет нодов под Renga не как стандартный пакет, а как полноценный установщик, который найдет директорию с установленной Renga и положит туда нужные файл, но я так делать во первых не умею, во вторых не буду. Пока что.
3. Подключение к проекту Renga
Верхний уровень любого API в отношении десктопной программы занимает инициация документа/модели. Поэтому с него мы и начнем, а именно, с инициации Application.
Может быть по крайней мере 3 ситуации:
- Программа не запущена вообще
- Программа запущена, но не на том проекте/на стартовом виде
- Проект уже запущен в одном из процессов программы
Для случая 1 есть пример в справке здесь. Сложней с 2 и 3 - когда надо перехватить запущенный процесс Renga и открыть/перейти к нужному проекту. Процесс обращения к активному процессу Renga описан здесь.
Окей, с API понятно, а как это воплотить в Dynamo? Хах, а вот тут начинается уже интересное. В явном виде передавать интерфейсы (а объекты класса Application, Project, Model и пр. являются именно интерфейсами) в нодах Dynamo не получится. Следовательно, необходимо инициализировать во внутренних методах объекты проекта/модели и обращаться к ним при выполнении соответствующих методов позже.
Я реализовал это в виде класса DynDocument, где расположил объекты интерфейса - приложение и проект.
Примечание: конструкция private DynDocument() { } только лишь для того, чтобы в Dynamo оно не светилось как нод*
Здесь присутствует структура для Application и IApplication. Первое -- это создание нового процесса Renga (запуск приложения и открытие проекта). Второе - это перебор открытых процессов как IApplication.
Вообще говоря, если запущенную Renga обозвать просто Application никаких ошибок не будет ... возможно это вскроется позже, но сейчас я не использую IApplication вообще.
Другой вопрос, что явно открыть конкретный проект среди ряда открытых я не пробовал ... пусть пользователь это сделает сам. В конце концов это не сложно ... чем вот это мучиться с интерфейсом Application.
4. О последовательности выполнения операций. Искусственное направление
Стоит сказать про критическую важность явного задания последовательности выполняемых операций. В силу того, что передавать сущности проекта/модели мы не можем - то наши ноды фактически возвращают void (действие). Для того, чтобы управлять последовательностью выполнения нодов - у меня тип всех изменен с void на int (возвращается "0"). Так я могу управлять очередностью нодов.
5. Пакетные операции на файлах IFC
Рассмотрим вариант пакетной обработки файлов. К примеру, конвертации ряда проектов Renga в IFC. Для этого нам потребуется список файлов и метод API по открытию проекта по файловому пути, экспорту в IFC и закрытию, а также для красоты - настройки экспорта в эти форматы (из коих есть только для ifc -- IIfcExportSettings).
Сколь я не мучился пытаясь передать эти настройки как сущность (com_объект) у меня не вышло - ругалось на "несопоставление типов", поэтому я решил сохранять эти настройки в файле, а потом вызывать их снова из другого метода.
Набор файлов для формирования IFC возьмем простые - из числа примеров поставляемых вместе с программой из директории RengaSoftware\Samples\.
Помня, что Dynamo не умеет работать с пакетной обработкой (ждать завершения части скрипта) даже с искусственно тормозящимся потоком (Thread.Sleep()), я сделаю экспортер в виде большого нода (чтобы в его теле происходило переключение между документами).
Первая зеленая группа - это сопоставление трех файлов маппинга параметров (для слоев, типов и значений).
Изюминкой реализации этих параметров является нестандартное задание путям к файлам. Вместо классических "\\" там используется "/" и что прикольно в режиме отладки оно вообще перескакивало через IIfcExportSettings с такими путями и не исполняло процесс!. Возвращалась очень информативная ошибка:
Так как по оговоренной причине, Dynamo не особо любит отдельные нестандартные типы заданные по умолчанию, я сделал возможность их выбора пользователем (выше).
6. Пакетные операции на чертежах модели
Здесь примерно такая же логика, как в случае с IFC, только если IFC для проекта мог быть один -- то здесь в файле может быть несколько чертежей.
Реализуем скрипты для одного файла и пакетное для нескольких (там, правда, будет иметь место необходимость пред-настройки параметров листов - но оставим это на совести пользователя).
В качестве демо файлов также возьмем ранние примеры - какой-то набор листов там есть (нам важно лишь их наличие, а не содержимое).
Перед тем, как запустить саму процедуру экспорта обратим внимание на понимание чертежей в среде Renga - это не только чертежи (drawings), но и Уровни (Levels), сборки (), разрезы (), фасады () и спецификации. Только чертежи обозначаются как IProject.Drawings, тогда как всё в целом -- как IProject.Drawings2.
Честно говоря, создание двух методов вместо одного но с перегрузкой операторов выглядит странно ... ну да ладно, не будем это комментировать.
7. Завершаем первую часть?
Итак, данная статья несет в себе главный посыл:
Работать с API любой САПР через Dynamo Core возможно, если есть API к данной САПР и COM-интерфейс для САПР.
Что мы сделали по отношении к Renga - инициализировали сущности (интерфейсы) процесса, проекта; научились производить пакетные операции над файлами в части формирования IFC и вывода чертежей.
Следующая часть (2) будет посвящена вопросу обращения к свойствам параметров проекта, к свойствам отдельных элементов.
Сам пакет я выкладываю на GitHub (репозиторий здесь). Также публикую набор кода как Dynamo-package под именем "RengaDyn". Ввиду сложности подключения библиотеки "RengaCOMAPI.tlb" к проекту сделайте это сами разместив её по файловому пути
C:\Work\RengaCOMAPI.tlb.
Позже, когда получу разрешение на публикацию её в составе основного кода - выложу и там.
Файл "RengaCOMAPI.tlb" находится в составе этого пакета.
Упоминаемые в статей скрипты (4 шт) также находятся в репозитории на GitHub.
Не пропускайте публикации, подписывайтесь на Telegram-канал с тизерами статей.
#dynamo core #renga #renga api #rengabim #dynamo