Расскажу, как стандартными нодами найти пересечения элементов.

Это нужно не столько ради проверки модели на правильность построений, сколько на определение принадлежности элементов. Например, когда нужно определить, к какому помещению относится оборудование или воздухораспределители.

Концепция

Общая идея простая: берём геометрические объекты и смотрим, что с чем пересекается.

В Динамо можно преобразовать элементы в геометрию, то есть получить с семейства набор твёрдых тел — солидов — и кривых линий. Затем можно их преобразовать в bounding box — габаритный параллелепипед, грубо говоря кубик, который построится по максимальным размерам семейства.

Грубо — потому что не кубик, а параллелепипед, но я замучаюсь писать это слово, поэтому далее по тексту кубик — это параллелепипед.

После стандартными нодами можно проверить, какие кубики пересекаются и получить список true-false. Обработав такой список мы получим нужные нам данные. Вот такой концепт.

Реализация

Давайте сразу посмотрим на примере. Есть модель АР с помещениями, модель ОВ с пространствами и в инженерном файле расставлены диффузоры.

Модель АР и диффузоры
Модель АР и диффузоры

Задача — нужно определить, в каких пространствах находятся диффузоры и записать эту информацию в выбранный параметр.

Сам Ревит знает, где находятся диффузоры, потому что показывает в диспетчере инженерных систем, к каким пространствам они относятся. Подробнее про диспетчер можете прочитать в отдельном материале. Про пространства также есть дотошная статья. Тем не менее автоматически вывести эту информацию прямо в диффузоры не получится, придётся использовать Динамо.

Для начала нужно выбрать, какие элементы будем пересекать. Пользуюсь обычными нодами для выбора элементов в модели.

Получаю все элементы в модели
Получаю все элементы в модели

Теперь нужно преобразовать элементы в геометрию. Для этого есть нод Element.Geometry. Все объёмные тела, которые были в семействе, он превратит в солиды, а линии оставит линиями. При этом текущая детализация не будет влиять на отображение, нод покажет всё. Например, диффузор будет выглядеть так:

Преобразовываю элемент в геометрию
Преобразовываю элемент в геометрию

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

Делать такое придётся у всех нодов, чью геометрию хотите скрыть
Делать такое придётся у всех нодов, чью геометрию хотите скрыть

Если обратите внимание на раскрытый список у нода Element.Geometry, то увидите, из чего состоит один диффузор: 13 линий и всего одно твёрдое тело, один солид.

Потому что геометрия диффузора — одно тело вращения, остальное — линии условного графического обозначения. 4 треугольника по 3 линии и окружность в центре, которую сейчас не видно. Вот и получается 13 линий и 1 солид.

Далее я подал геометрию на нод BoundingBox.ByGeometry. Он берёт все линии и солиды, находит две максимально удалённые друг от друга точки и строит кубик. Если раскрыть список у нода, то увидим вот такую запись для каждого диффузора (числа будут разными, но форма записи одинаковая):

BoundingBox(MinPoint = Point(X = 5023.910, Y = 8077.303, Z = 6484.000), MaPoint = Point(X = 6030.128, Y = 9083.521, Z = 6560.000))

Текст целиком не влезает — давняя беда Динамо
Текст целиком не влезает — давняя беда Динамо

В этой записи зашифрованы координаты минимальной и максимальной точки кубика. Минимальная — та, которая ближе всего к внутреннему началу, а максимальная — та, что дальше. Внутреннее начало — это начало локальной системы координат файла, его нельзя передвинуть или изменить.

Обычно, если вы разместите базовую точку проекта в нулях, то увидите это самое внутреннее начало. С версии 2020.2 у него появилось своё обозначение в виде трёх осей координат.

Если хотите посмотреть, как Динамо воспринимает баундин бокс, то подайте нод с ним на другой стандартный нод BoundingBox.ToCuboid. Получите вот такую картину:

Серый кубики — визуализация баундин боксов
Серый кубики — визуализация баундин боксов

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

Для этого есть нод BoundingBox.Intersects. Поскольку у нас есть список диффузоров и пространств и нам нужно проверить пересечение каждого диффузора с каждым пространством, то нужно включить векторное переплетение списков. Подробнее об этом читайте в статье про списки.

Подаю баундин боксы диффузоров и пространств на нод для проверки пересечений
Подаю баундин боксы диффузоров и пространств на нод для проверки пересечений

Поскольку нужно получить на выходе список пространств, которые соответствуют списку диффузоров, то лучше подавать на вход boundingBox список диффузоров, а на вход other — пространств. Так итоговая информация будет удобнее для обработки.

Теперь у нас есть список true-false. Там, где true — пересечение, диффузор находится в пространстве. Значит, нужно получить список пространств, чтобы он соответствовал списку диффузоров. Использую нод List.AllIndicesOf для получения индексов true-позиций, а потом выдёргиваю нодом List.GetItemAtIndex нужные пространства.

Получаю пространства
Получаю пространства

В ноде BoundingBox.Intersects я получаю список пересечений. В каждом подсписке со значением true «сидит» пространство, в котором находится диффузор. Получал индекс для true, то есть его порядковый номер в подсписке, а потом из списка всех пространств получаю искомое.

Теперь нужно просто получить имя и номер пространства и записать их в диффузоры.

Получаю имена и номера пространств, формирую список
Получаю имена и номера пространств, формирую список
Записываю информацию в диффузоры в параметр «Комментарии»
Записываю информацию в диффузоры в параметр «Комментарии»

Готово. Если составить спецификацию на диффузоры и вывести столбец со значениями параметра «Комментарии», то получаю всю информацию:

Проверил в модели — всё правильно
Проверил в модели — всё правильно

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

Скрипт на пересечение диффузоров и пространств
Скрипт на пересечение диффузоров и пространств

По той же схеме вы можете пересекать любые элементы с пространствами: мебель, оборудование, электроприборы и так далее. Нужны пересечения стен и воздуховодов или колонн и трубопроводов? Способ тоже подходит, он универсальный. Главное, следите за своими баундин боксами.

В данном примере я пересекал баундин боксы, но можно было работать и напрямую с геометрией. Например, если взять баундин бокс с трубы, то это будет вытянутый кубик, а не цилиндр, что может привести к ложным пересечкам.

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

Когда нужна более высокая точность, преобразовывайте элементы в геометрию и используйте нод Geometry.DoesIntersect. Вы так же получите список true-false, однако следите за тем, что подаёте на нод. Лучше предварительно очистить геометрию от ненужных линий. В остальном всё работает аналогично.

Обновления статей удобно получать в Телеграм-канале «Блог Муратова про Revit MEP». Подписывайтесь и приглашайте коллег. Можно обсудить статью и задать вопросы в специальном чате канала.

Читайте методичку для проектировщиков: полезный материал, в котором последовательно рассказываю, как создавать модель.

Бесплатные обзоры ваших моделей

Периодически провожу «Ревит-линчи» — разбираю файлы семейств и проектов пользователей и отвечаю на вопросы по Ревиту и БИМ-технологиям. Дату и ссылку на Ревит-линч публикую в Телеграм-канале. Приходите, там интересно.

Отблагодарить автора

Я много времени уделяю блогу и разработке семейств. Если хотите отблагодарить меня, то можете сделать небольшой подарок (именно подарок, такой перевод не облагается налогом).