Найти тему

Работа с помещениями. Создание пола по контуру помещения

Оглавление

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

Введение

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

Я давно не писал статьи с полным описанием всех подробностей, и мои читатели могли пропустить что-либо среди других статей, поэтому сейчас некоторые вещи могут повторяться. Там, где я пропускаю что-либо, буду приводить ссылки на свои другие статьи.

Создание проекта

Итак, ещё раз — для старта я использую проект на шаблоне Nice3Point, подготовленный для размещения нескольких команд согласно этой статье.

Жмём правой кнопкой мыши на решение — Добавить — Создать проект.

Выбираем шаблон Revit Addin Module:

-2

Не забываем указать папку source:

-3

В данном случае я выберу модальный UI без инъекции зависимостей:

-4

Проект создан:

-5

Создание окна WPF

Подробности о создании WPF-приложений смотрите в подборке о WPF. Я же сейчас реализую обычное окно: там будет выпадающий список для выбора типа пола, текст, показывающий, сколько помещений выбрано, и 2 кнопки: выбрать помещения и создать полы.

Вот так выглядит код окна (до добавления привязок):

-6

А само окно вот так:

-7

Создание ViewModel

Создадим простую ViewModel, даже без дескрипторов для описания типов пола. У нас будут следующие свойства:

  • Список типов полов
  • Выбранный тип пола
  • Список выбранных помещений

Мы выводим на экран так же ещё и число выбранных помещений, но для этого нам не нужны отдельные свойства. Мы можем привязаться к списку помещений и использовать конвертёр, либо привязаться непосредственно к свойству Length массива помещений. Я сделаю массив, то есть неизменяемый объект — при попытке выбрать помещения, они будут не добавляться к выбору, а сбрасываться.

Получилась вот такая ViewModel:

-8

О том, что такое RelayCommand и как работает ObservableProperty, я пишу здесь.

Ещё я использую события во ViewModel, чтобы управлять видимостью окна:

-9

Чуть более подробно я раскрываю это здесь. Не забывайте добавлять обработчик в файле команды (напомню в конце статьи)

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

Теперь давайте добавим ISelectionFilter, чтобы пользователь мог выбирать только комнаты:

-10

Не забудьте добавить его в команду выбора элементов пользователем:

-11

Настройка привязок

Отлично, ViewModel готова. Давайте настроим привязки во View с учётом этого:

-12

Благодаря тому, что в строке 9 xaml указан контекст данных, я могу настраивать привязки со всплывающими подсказками и не переживать о том, что я допустил опечатку

d:DataContext="{d:DesignInstance viewModel:FloorCreatorExampleViewModel}"


Давайте посмотрим, что получилось, в окне Revit:

-13

Я выбрал 2 комнаты — я вижу 2 комнаты.

-14

Список типов тоже на месте. Нужно поправить только размеры окна, и можно писать код по созданию пола.

Создание пола

Я решил создать статический класс с одним методом: он будет принимать на вход тип пола и список помещений, создавать полы, выделять их в модели, и ничего не возвращать. Не вижу тут смысла в создании объекта, поэтому делаю класс статическим. Код тут довольно простой, но и ситуацию я обрабатываю простую:

-15

На что тут нужно обратить внимание:

  • Строка 14: SpatialElementBoundaryOptions: вы можете поэкспериментировать с его настройками под ваши нужды
  • Строка 24: GetBoundarySegments возвращает список списков сегментов. Как правило, в итоге нам нужен первый, по идее, в помещении могут быть внутренне контуры, так что будьте с этим внимательны: в примере я беру только первый, но он может не сработать в 100% случаев
  • Строка 25: Линии в CurveLoop должны идти друг за другом, иначе на 31 строке код не выполнится.
  • Проверить, корректный ли у вас контур пола, можно с помощью класса BoundaryValidation, чтоб не ловить исключения
  • В случае, если у вас не получается создать пол, рисуйте линии по контуру вашего CurveLoop через NewDetailCurve, и ищите разрывы в них.
  • Данный код не заводит полы в проёмы. Это довольно сложная задача, которую нельзя решить в несколько строк для всех возможных случаев (но решить её, разумеется, можно), поэтому я здесь и не привожу своих решений. Я решал такую задачу для конкретных случаев, с учётом стадий и корректировкой по именам семейств. Если у вас есть общее или хоть чуть-чуть обобщённое решение задачи по заведению пола в проёмы, можете написать мне. Возможно, я его опубликую.

В конце удалим комментарий с команды создания полов и передадим её аргументы:

-16

Как видите, полы создадутся и без создания объекта FloorCreator, при этом статический метод CreateFloors отработает как чистая функция: выполнит действия, не меняя состояния других объектов нашего приложения.

Результат

Полы созданы (тут перекрылись с существующими):

-17

И выделены в модели:

-18

Заключение

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

-19