Расскажу, как стандартными нодами найти пересечения элементов.
Это нужно не столько ради проверки модели на правильность построений, сколько на определение принадлежности элементов. Например, когда нужно определить, к какому помещению относится оборудование или воздухораспределители.
Концепция
Общая идея простая: берём геометрические объекты и смотрим, что с чем пересекается.
В Динамо можно преобразовать элементы в геометрию, то есть получить с семейства набор твёрдых тел — солидов — и кривых линий. Затем можно их преобразовать в 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». Подписывайтесь и приглашайте коллег. Можно обсудить статью и задать вопросы в специальном чате канала.
Читайте методичку для проектировщиков: полезный материал, в котором последовательно рассказываю, как создавать модель.
Бесплатные обзоры ваших моделей
Периодически провожу «Ревит-линчи» — разбираю файлы семейств и проектов пользователей и отвечаю на вопросы по Ревиту и БИМ-технологиям. Дату и ссылку на Ревит-линч публикую в Телеграм-канале. Приходите, там интересно.
Отблагодарить автора
Я много времени уделяю блогу и разработке семейств. Если хотите отблагодарить меня, то можете сделать небольшой подарок (именно подарок, такой перевод не облагается налогом).