Найти в Дзене

Управление координатами в Revit API. Класс Transform

Оглавление

Всем привет! Сегодня поговорим о разных системах координат и как от одной перейти к другой с наименьшими потерями и без особых проблем.

Введение

Представим ситуацию: нам надо написать плагин, который по элементам связанного файла расставляет некоторые другие элементы. Вы написали плагин, протестировали, всё работает. А потом его запускает инженер, и у него (неё) тоже всё срабатывает, но элементы встают красивым контуром здания со смещением метров на 200 в сторону. Вы начинаете разбираться в причинах, замечаете, что ещё и базовые точки совпадают. Что делать?

Общая система координат файла

Обычно принято считать, что в Ревите есть 2 точки для определения координат объекта: базовая точка и точка съёмки. Подробнее об этом можно почитать тут. И как правило, этих знаний хватает для корректной настройки совместной работы и общих координат. Но, когда мы начинаем писать плагины, то в некоторых случаях могут начаться проблемы.

Дело в том, что на самом деле у файла есть 3 точки отсчёта: базовая точка, точка съёмки и внутреннее начало. И они могут находиться в разных местах и показывать разные вещи.

Точка съёмки показывает нахождение файла в общей системе координат нескольких файлов. Базовая точка — это условное "начало проекта" для пользователя. А внутреннее начало — точка, от которой Ревит считает все координаты.

Мы можем менять положение точки съёмки и базовой точки проекта, но положение внутреннего начала мы менять не можем. Поэтому при работе со связанным файлом может возникнуть ситуация, что координаты мы взяли из него по его внутреннему началу, а вставили в текущий файл по его внутреннему началу совсем в другое место (да и по другому направлению). Как этого избежать?

1. Мы можем получить базовую точку любого документа через статический метод BasePoint.GetProjectBasePoint(document). Внутреннее начало: через InternalOrigin.Get(document). Далее, прибавляя или вычитая её Position или SharedPosition к точкам, координаты которых мы нашли в связанном документе, мы получим координаты точек в текущем документе без смещения:

-2

Этот метод работает, но что делать с поворотом? Так просто мы его не получим. Однако, разумеется у нас есть другой способ. Рассмотрим его подробно и издалека.

Задача

Выбрать элемент в связанном файле, выбрать экземпляр семейства в текущем файле, на месте размещения элемента в связи разместить ещё одно такое же семейство (сейчас не будем рассматривать, что у разных элементов разные способы размещения, я буду выбирать только FamilyInstance и брать его Location). Связь смещена и повёрнута относительно текущего документа.

Решение

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

Вот такой код получился:

-3

Обратите внимание:

  • У Reference ref1 свойство ElementId отвечает за Id связанного файла, а LinkedElementId — за Id элемента из связи.
  • Элемент из связи мы берём из связанного документа, получив его на строке 48.

Остальное, думаю, понятно (а если нет, то подписывайтесь на блог, изучайте другие статьи и обучайтесь Revit API, если для вас это актуально. Но подписывайтесь и ставьте лайки в любом случае).

Смотрим результат:

Что я выбрал (окно в связи и фитинг в текущем файле):

-4

Получил висящий в воздухе фитинг:

-5

Теперь попробуем применить класс Transform. У класса Instance есть метод GetTransform. Наследники Instance — RevitLinkInstance и FamilyInstance. Вот у RevitLinkInstance мы и возьмём Transform.

Кажется то, что нужно
Кажется то, что нужно

Добавим 2 строчки в код:

-7

Что тут произошло: мы получили Transform, который по сути показывает, как система координат связанного файла смещена относительно системы координат текущего файла. А затем мы применили эту трансформацию к координате, полученной из связанного файла, и получили значение координаты в текущем файле, совпадающей с координатой в связи.

На картинке так (фитинг влез в окно, но его видно):

-8

В общем-то, так и работает Transform. Получив координаты в одной системе координат, и применив Transform этой же системы к полученной координате, мы получаем координаты в основной системе. Для обратного преобразования мы можем использовать свойство Inverse того же Transform.

Заключение

Transform есть у всех элементов, являющихся FamilyInstance. Так же он есть у видов (точнее, у их свойства CropBox). Часто с его помощью можно упростить поиск координаты размещения семейства.

Вообще, тема с управлением координатами с помощью Transform довольно сложная, и я уверен, что раскрыл её не полностью. Если у вас есть интересные кейсы, делитесь ими в комментарии.

А также не забывайте подписываться на мой телеграм-канал о Revit API. До новых встреч!

-9