Предыдущая статья про Renga API называлась Непоследний обзор Renga API и, хотя с момента её выпуска прошло значительное время, он действительно оказался непоследним!
За это время мы выпустили еще 40 версий API. Какие-то из них были более насыщенными, какие-то менее. Основные моменты, которые стало возможным выполнить через API:
создавать, удалять и редактировать объекты модели здания, сборки и чертежа;
создавать, удалять и редактировать стили, материалы, профили, чертежи и многое другое;
получать и изменять параметры и свойства стилей объектов;
задавать выражение и признак экспорта в CSV для назначенного свойства;
управлять информацией о проекте;
экспортировать модель в формате IFC с учетом файлов сопоставления и настроек геометрического представления;
получать данные для расчётов инженерных систем;
создавать связи между объектами инженерных систем;
получать список категорий объектов инженерных систем в проекте;
добавлять шаблоны стилей, о которых читайте в статьях о Renga STDL.
Сегодня мы разберем один из ключевых сценариев автоматизации в Renga - создание объектов в модели через API. Благодаря этой автоматизации открыты все двери для генерации планировок по заданным параметрам, конструктивных элементов по расчетам, создания уникальных фитингов в модели по требованиям технологов и так далее.
Все дальнейшие примеры кода в статье будут на языке C#, однако описанные подходы применимы для С++ и других COM-совместимых языков. Python-разработчики также могут использовать API через библиотеки для работы с COM.
Немного про версии API
В статье рассматривается API версии 2.47, что соответствует Renga версии 9.0. Мы сохраняем бинарную совместимость плагинов, т.е. если вы собрали плагин на API версии 2.7, что соответствует Renga 4.1, то он запустится на Renga 9.0 и выше. При этом от версии к версии некоторые методы или константы в API могут быть переименованы, для перехода на новую новую версию рекомендуется ознакомиться с Migration Guide нужной версии на странице changelog в справке.
В этой статье мы пропустим этапы создания и подключения плагина и сосредоточимся на работе с API. Подробности по этим этапам можно найти в первую очередь в справке и предыдущих статьях.
Метод CreateObject
В Renga API создание любого объекта модели происходит через вызов метода CreateObject из интерфейса IModel, представляющего модель.
IModelObject CreateObject(INewEntityArgs args);
Метод принимает единственный параметр – интерфейс INewEntityArgs, содержащий аргументы для создания объекта, и возвращает интерфейс IModelObject, представляющий созданный объект модели.
Если с возвратом функции всё достаточно прозрачно, то с INewEntityArgs разберемся поподробнее. Данный интерфейс содержит полный набор аргументов для создания объекта любого типа, но для каждого типа объекта используется только часть из них – заполнять все поля не требуется. Создать экземпляр такого интерфейса можно через метод IModel.CreateNewEntityArgs. Рассмотрим каждый аргумент подробнее:
Аргумент |
Описание |
|---|---|
TypeId |
Тип объекта (стена, колонна, дверь и т.д.). Константа из класса |
HostObjectId |
ID объекта-хоста (обязателен для некоторых объектов, например, для окна в стене) |
Placement3D |
Позиция и ориентация объекта в модели здания и сборке. По умолчанию равен |
Placement2D |
Позиция и ориентация объекта на чертеже. По умолчанию равен |
StyleId |
ID стиля объекта (обязателен для некоторых объектов, например для оборудования) |
FilePath |
Путь к файлу (используется для создания связей или стилей элементов) |
CategoryId |
ID категории (используется для создания стилей, чертежей и т.д., к созданию объектов не имеет отношения) |
Любые изменения проекта в Renga API выполняются только в контексте открытой операции. Создание объекта - не исключение, поэтому вызов
CreateObjectобязан быть заключен между вызовамиIOperation.StartиIOperation.Apply. Во всех примерах ниже эти вызовы опущены для краткости, но подразумеваются.
Создание объектов в модели здания
Доступ к модели здания осуществляется через свойство IProject.Model:
// app - объект типа Renga.IApplication Renga.IProject project = app.Project; Renga.IModel model = project.Model;
Создание объектов на уровне
Напишем минимальный код для создания объекта колонна и будем на каждом шаге добавлять аргументы, усложняя сценарий.
Для создания колонны достаточно задать аргумент TypeId. Таким образом, колонна будет создана в точке (0, 0, 0) на текущем активном уровне:
var args1 = model.CreateNewEntityArgs(); args1.TypeId = Renga.EntityTypes.Column; // Задали тип объекта как константу из класса Renga.EntityTypes Renga.IModelObject column1 = model.CreateObject(args1);
Теперь укажем уровень, на котором будет размещена колонна, для этого аргумент HostObjectId приравняем к идентификатору желаемого уровня (например, не активного):
var args2 = model.CreateNewEntityArgs(); int anyLevelId = ...; // получили ID желаемого уровня args2.HostObjectId = anyLevelId; args2.TypeId = Renga.EntityTypes.Column; Renga.IModelObject column2 = model.CreateObject(args2);
Далее зададим точку размещения колонны, например (1000, 1000, 0) и оси, отвечающие за ее поворот в пространстве. Для этого необходимо создать и заполнить структуру Renga.Placement3D:
var args3 = model.CreateNewEntityArgs(); var placement1 = new Renga.Placement3D { Origin = new Renga.Point3D { X = 1000, Y = 1000, Z = 0 }, xAxis = new Renga.Vector3D { X = 1, Y = 0, Z = 0 }, zAxis = new Renga.Vector3D { X = 0, Y = 0, Z = 1 }, }; args3.Placement3D = placement1; args3.TypeId = Renga.EntityTypes.Column; Renga.IModelObject column3 = model.CreateObject(args3);
И в конце зададим еще одну точку размещения и желаемый стиль колонны, для этого аргумент StyleId приравняем к ID желаемого стиля:
var args4 = model.CreateNewEntityArgs(); int anyColumnStyleId = ...; // Получили желаемый стиль колонны из IProject.ColumnStyles args4.StyleId = anyColumnStyleId; var placement2 = new Renga.Placement3D { Origin = new Renga.Point3D { X = 2000, Y = 2000, Z = 0 }, xAxis = new Renga.Vector3D { X = 1, Y = 0, Z = 0 }, zAxis = new Renga.Vector3D { X = 0, Y = 0, Z = 1 }, }; args4.Placement3D = placement2; args4.TypeId = Renga.EntityTypes.Column; Renga.IModelObject column4 = model.CreateObject(args4);
После выполнения всех действий в Renga мы увидим примерно следующую картину:

Создание зависимых объектов
Создание зависимых объектов особенно тем, что такие объекты не могут создаваться сами на уровне, они всегда создаются на другом объекте-хосте, поэтому заполнение аргумента HostObjectId в этом случае обязательно.
Ознакомиться с соответствием зависимых объектов к их хостам можно в документации к свойству
HostObjectId.
Кроме того, аргумент Placement3D для таких объектов используется иначе, чем для обычных: точка размещения не берётся напрямую из плейсмента, а проецируется на объект-хост. Оси при этом могут выполнять дополнительную роль в зависимости от типа объекта.
Рассмотрим пример создания окна в стене и воздуховода на трассе:
// Создаём окно var windowArgs = model.CreateNewEntityArgs(); // получили ID нужного стиля окна из IProject.WindowStyles и задали StyleId int windowStyleId = ...; windowArgs.StyleId = windowStyleId; // получили ID нужной стены и задали HostObjectId int wallId = ...; windowArgs.HostObjectId = wallId; // задали точку, которая будет проецироваться на стену windowArgs.Placement3D = new Placement3D{ Origin = new Renga.Point3D { X = 3000, Y = 0, Z = 0 }, xAxis = new Renga.Vector3D { X = 1, Y = 0, Z = 0 }, zAxis = new Renga.Vector3D { X = 0, Y = 0, Z = 1 }, }; windowArgs.TypeId = Renga.EntityTypes.Window; Renga.IModelObject window = model.CreateObject(windowArgs); // Создаём воздуховод var ductArgs = model.CreateNewEntityArgs(); // получили ID нужного стиля воздуховода из IProject.DuctStyles и задали StyleId int ductStyleId = ...; ductArgs.StyleId = ductStyleId; // получили ID нужной трассы и задали HostObjectId int routeId = ...; ductArgs.HostObjectId = routeId; // задали точку, которая будет проецироваться на трассу ductArgs.Placement3D = new Placement3D{ Origin = new Renga.Point3D { X = 8000, Y = 0, Z = 0 }, xAxis = new Renga.Vector3D { X = 1, Y = 0, Z = 0 }, zAxis = new Renga.Vector3D { X = 0, Y = 0, Z = 1 }, }; ductArgs.TypeId = Renga.EntityTypes.Duct; Renga.IModelObject duct = model.CreateObject(ductArgs);
После выполнения кода увидим следующее:

Создание связей
API предоставляет возможности для создания любого вида связи: с изображением, чертежом, 3D- и IFC-моделью. При создании связи необходимо заполнить аргумент FilePath - абсолютный путь до файла на диске.
Следующий код демонстрирует создание связи с растровым изображением cat.jpg:
var imageArgs = model.CreateNewEntityArgs(); imageArgs.FilePath = "D:\\cat.jpg"; imageArgs.TypeId = Renga.EntityTypes.Image; Renga.IModelObject image = model.CreateObject(imageArgs);
Выполнив код, получим вот такого котика в модели:

Создание объектов в других моделях
В Renga через пользовательский интерфейс можно создавать объекты не только в модели здания, но и в стилях сборки и в чертежах.
И API не отстает! И предоставляет возможность автоматизировать и эти сценарии.
Раз в стиле сборки и в чертеже можно взаимодействовать с объектами, значит, они тоже являются моделями, а значит, получив соответствующую сущность, достаточно привести её к уже знакомому интерфейсу IModel:
// получаем модель стиля сборки Renga.IEntity assembly = project.Assemblies.GetByIndex(0); var assemblyModel = assembly as Renga.IModel; // получаем модель чертежа Renga.IEntity drawing = project.Drawings2.GetByIndex(0); var drawingModel = drawing as Renga.IModel;
После получения assemblyModel или drawingModel создание объектов выполняется точно так же, как и в модели здания, отличается лишь набор доступных для создания объектов.
Теперь в стиле сборки создадим колонну:
var columnArgs = assemblyModel.CreateNewEntityArgs(); columnArgs.StyleId = ...; // задали ID нужного стиля columnArgs.TypeId = Renga.EntityTypes.Column; Renga.IModelObject column = assemblyModel.CreateObject(columnArgs);
А в чертеже создадим линию чертежа:
var drawingLineArgs = drawingModel.CreateNewEntityArgs(); drawingLineArgs.TypeId = Renga.EntityTypes.DrawingLine; Renga.IModelObject drawingLine = drawingModel.CreateObject(drawingLineArgs);
После выполнения этого кода в чертеже и стиле сборки увидим следующее:

Как узнать, какие объекты я могу создать в конкретной модели?
Ознакомиться с перечнем всех типов объектов, которые можно создать с помощью API, и с моделями, допускающими их создание, можно в таблице в документации метода CreateObject.
Итоги
Текущие возможности API по созданию объектов позволяют реализовать множество сценариев автоматизации: создание конструктивных элементов, создание чертежей и сборок, создание и редактирование инженерных систем в зависимости от результатов расчетов, создание произвольных элементов оформления на чертеже и многое другое!
Если у вас есть вопросы или предложения по развитию API, оставляйте запрос в ServiceDesk. Мы всегда рады вопросам и готовы помочь!
На что стоит обратить внимание
В завершение перечислим несколько моментов, которые могут сэкономить время при знакомстве с созданием объектов через Renga API:
Вызов
IModel.CreateObjectдолжен всегда выполняться внутри начатой операции, между вызовамиStartиApplyинтерфейсаIOperationНабор обязательных аргументов для создания зависит от типа создаваемого объекта
Если создание объекта не происходит и вызов
CreateObjectвозвращаетnull, то через свойствоIApplication.LastErrorможно получить детальный текст ошибки
Полезные материалы
How-to в официальной справке
Сэмплы плагинов из SDK, в частности, плагин
ObjectCreationДля тех, кому интересно, как использовать Renga API в связке с ИИ - отличная статья

Новиков Владислав
Инженер-программист, Renga Software