Найти в Дзене

Работа с DWG и автоматическое создание элементов по DWG-подложке

Оглавление

Всем привет! Сегодня рассмотрим несколько интересных вещей из Revit API: поиск DWG-импортов (и связей), работа с геометрией, создание труб (многие линейные элементы и перекрытия создаются аналогично) и создание новых элементов.

Спойлер: рассматривайте эту статью как сборную солянку: я рассказываю вам интересные штуки про Revit API, а вы используете только то, что надо вам. Категорически не рекомендую чертить подложку в DWG и переносить её в Revit, даже с помощью плагинов.

Задача

Дан DWG-файл с полилиниями. Часть из них имеет слой "Pipes". Необходимо получить эти полилинии и построить трубы по оси входящих в них линий. Каждую пару смежных труб — соединить отводом.

Решение

1. Получение DWG

Загрузим DWG в модель (лучше связью), выделим и нажмём Snoop Selection в Revit Lookup (что за Lookup, где взять?). Видим, что этот элемент относится к классу ImportInstance (причём неважно, связь это или импорт):

Определяем класс выбранного элемента через Lookup
Определяем класс выбранного элемента через Lookup

Ну а дальше просто используем FilteredElementCollector:

-2

Обратите внимание, что я вынес Document в отдельное поле класса. Это нужно для того, чтобы использовать его во всех методах и не передавать лишний раз.

Также я взял первый экземпляр импорта просто методом .First();. Он выдаст исключение, если последовательность пустая. Если у вас много импортов DWG, то тогда записывайте их в список и делайте то, что нужно вам (удаляйте).

2. Получение полилиний

На этом этапе нужно будет внимательно поработать с Revit Lookup. В вашем случае там могут быть не полилинии, а отрезки, или что угодно ещё. Получение геометрии родных элементов Ревита будет происходить точно также.

Итак, нам нужно пройти по пути GeometryGeometryInstanceGetInstanceGeometry. Звучит просто, если знать как, в коде чуть-чуть сложнее.

Итак, пошагово в Lookup:

1. Переходим в геометрию элемента, из неё в GeometryInstance при настройке ActiveView
1. Переходим в геометрию элемента, из неё в GeometryInstance при настройке ActiveView
2. На GeometryInstance вызываем GetInstanceGeometry
2. На GeometryInstance вызываем GetInstanceGeometry
3. И вот теперь видим наши полилинии
3. И вот теперь видим наши полилинии

Но это ещё не всё — надо понять, какие из них лежат на слое Pipes. Идём в GraphicStyleId:

4. Находим значение в свойстве GraphicsStyleCategory
4. Находим значение в свойстве GraphicsStyleCategory
-7

Принцип при поиске решения задачи для будущего плагина довольно часто именно такой: находим решение в Lookup, потом реализуем в коде. Посмотрим код:

Давайте разбираться:

1. Свойство Geometry нельзя получить на прямую, синтаксис такой:

element.get_Geometry(options);

В строках 25-27 создаём экземпляр Options. В 31 строке получаем с их помощью геометрию.

А дальше немного непонятный финт. В чём дело:
Свойство
Geometry возвращает нам GeometryElement, который является списком GeometryObject. И нам нужно получить (в данном случае) первый такой объект. Для этого мы заводим переменную для него (строка 30), и проходимся циклом, чтобы записать в неё значение.

Если вдруг у вас получилось добиться аналогичного результата проще, пожалуйста, напишите в комментарии со ссылкой на гитхаб или со скринами кода.

Дальше всё просто: в строке 44 получаем список полилиний через GetInstanceGeometry(), и просто проходимся по ним циклом. Я решил обернуть всё это в группу транзакций, потому что в методе CreatePipes создаются транзакции.

Далее осталось проверить слой полилинии. Мы берём стиль на 48 строке и проверяем его имя. Не забываем привести к типу GraphicsStyle.

Итак, полилиния найдена, осталось создать трубы.

Создание труб

Поскольку полилиния представляет собой последовательность линий, я выбрал такой алгоритм: последовательно построить все трубы, записать их в список, а потом последовательно построить отводы для каждой пары труб.

Создать трубы нам поможет статический метод Pipe.Create. Ему нужно передать тип системы, тип трубы и уровень. В данном случае в демонстрационных целях я возьму всё методом First(). Но в настоящих плагинах так, скорее всего, не получится — надо будет писать логику по определению типа системы и типа трубы.

Получаем из документа необходимые переменные
Получаем из документа необходимые переменные

Рассмотрим итоговый код создания трубы:

-9

На строке 63 получаем все точки полилинии. Создаём список для новых труб на 73 строке и начинаем работу:

Запускаем цикл for на 77 строке (мой обзор на циклы C#). Начинаем с единицы, чтобы мы могли взять предыдущую точку из списка точек. Ну и, собственно, создаём трубу на 82 строке.

На 83 строке я назначаю трубе диаметром 10 мм (тут пишу, почему я делаю это именно так). Это необязательно: по умолчанию будет 152,4 мм.

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

В этом нам поможет класс Document (но другой — из Autodesk.Revit.Creation). Метод NewElbowFitting — создаёт отводы. Вообще, этот класс создаёт все точечные элементы (чьё местоположение определяется точкой и углом поворота), и некоторые другие.

Метод принимает 2 коннектора, поэтому я написал метод, который у 2 труб находит 2 лежащих рядом коннектора:

-10

Создаём отвод:

Продолжение метода CreatePipes
Продолжение метода CreatePipes

Задача решена.

Организация проекта

Я создал в своём репозитории https://github.com/SergeyNefyodov/Revit-API-Blog новую папку DwgMepCurveCreator, и в ней один новый класс Command. Я не добавлял ничего в addin-файл, поэтому код из репозитория будет работать только в Addin-manager. (Не забывайте ставить звезду моему репозиторию, это аналог лайка на GitHub).

Тут можно прочитать, как запускать и отлаживать плагины через Addin Manager.

А тут — как подключить внешнюю команду к Revit

Здесь — как превратить команду в кнопку на панели "Надстройки" (или на новой панели).

Посмотрим, что получилось (первый раз пробую с гифкой, если знаете удобные инструменты записи экрана — пишите в комментарии)

Это GIF, если она неподвижна, подождите, пока прогрузится
Это GIF, если она неподвижна, подождите, пока прогрузится

А на этом всё! В следующей статье начнём создавать оконные приложения с помощью WPF. Обязательно подписывайтесь на мой телеграм-канал, это центральная часть блога, где я аккумулирую весь контент. До новых встреч!

-13