ADN Open CIS
Сообщество программистов Autodesk в СНГ

10/12/2013

Как получить экземпляры семейств в заданном помещении

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

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

Как и всегда, для доступа к элементам из базы данных Revit воспользуемся классом FilteredElementCollector.

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

Таким образом, мне нужно применить следующие фильтры по порядку:

  • Не является типоразмером (NotElementType)
  • На зависит от вида (View Independent)
  • Является экземпляром семейства (Family Instance)
  • Элемент пересекается с границами комнаты

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

Для выполнения последней проверки, я сначала определю прямоугольник, ограничивающий комнату (BoundingBox) и преобразую его в объект Outline. Затем использую полученный объект в фильтре BoundingBoxIntersectsFilter. Возможно существует более изящный способ чтобы реализовать что-то подобное, так же можно воспользоваться фильтром BoundingBoxContainsPointFilter.

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

Все вышеперечисленные действия используют быстрые фильтры.

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

 

Я решил просто использовать свойство FamilyInstance.Room и проверить, является ли значение этого свойства выбранным мной помещением. Подобную проверку кстати тоже можно выполнить с помощью фильтра. Например, используя ElementParameterFilter, что может значительно увеличить производительность, так как фильтрация будет происходить на уровне базы данных Revit, а не в коде, что является более эффективным. О том как правильно использовать это свойство, смотрите ниже.

Пока же метод выглядит следующим образом:

Код - C#: [Выделить]
  1. /// <summary>
  2. /// Возвращает идентификаторы экземпляров семейств
  3. /// находящихся в заданном помещении
  4. /// </summary>
  5. List<Element> GetFurniture( Room room )
  6. {
  7.   BoundingBoxXYZ bb = room.get_BoundingBox( null );
  8.  
  9.   Outline outline = new Outline( bb.Min, bb.Max );
  10.  
  11.   BoundingBoxIntersectsFilter filter
  12.     = new BoundingBoxIntersectsFilter( outline );
  13.  
  14.   Document doc = room.Document;
  15.  
  16.   // Todo: Добавить ограничение по категории
  17.   // и по другим свойствам при необходимости.
  18.  
  19.   FilteredElementCollector collector
  20.     = new FilteredElementCollector( doc )
  21.       .WhereElementIsNotElementType()
  22.       .WhereElementIsViewIndependent()
  23.       .OfClass( typeof( FamilyInstance ) )
  24.       .WherePasses( filter );
  25.  
  26.   int roomid = room.Id.IntegerValue;
  27.  
  28.   List<Element> a = new List<Element>();
  29.  
  30.   foreach( FamilyInstance fi in collector )
  31.   {
  32.     if( fi.Room.Id.IntegerValue.Equals( roomid ) )
  33.     {
  34.       a.Add( fi );
  35.     }
  36.   }
  37.   return a;
  38. }

В конце метода я лишь проверяю, соответствует ли свойство Room заданному помещению.

Но я боюсь что могут быть проблемы, связанные с этим свойством и его зависимостью от стадии. Патрик Розендаль (Patrick Rosendahl) реализовал более надежный способ, для определения помещения для заданного элемента. В сложных моделях возможно лучше применять его.

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

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

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

Источник: http://thebuildingcoder.typepad.com/blog/2013/03/filter-for-family-instances-in-a-room.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=389

Опубликовано 10.12.2013
Отредактировано 10.12.2013 в 08:29:27