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

25/12/2016

Графическое отображение границ зоны

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

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

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

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

Метод Area.GetBoundarySegments принимает в качестве аргумента объект класса SpatialElementBoundaryOptions, который позволяет задать два свойства – StoreFreeBoundaryFaces и SpatialElementBoundaryLocation.

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

Последний может быть установлен в Finish, чтобы получить поверхность зоны по финишной поверхности граничащего элемента, или в Center – по центральной линии.

Пример

Вот пример зоны, на которой будем производить тестирование:

 

Тут мы видим сложные края, составленные из стен, проемов в них и соответствующих помещений:

 

Выбрав зоны и запустив команду, мы построим лини модели по каждому сегменту границы помещения. Изолировав линии модели мы увидим контур границы зоны:

 

Код

Код довольно прост и понятен. Однако он не был тщательно протестирован:

Код - C#: [Выделить]
  1. public Result Execute(
  2.   ExternalCommandData commandData,
  3.   ref string message,
  4.   ElementSet elements )
  5. {
  6.   UIApplication uiapp = commandData.Application;
  7.   UIDocument uidoc = uiapp.ActiveUIDocument;
  8.   Application app = uiapp.Application;
  9.   Document doc = uidoc.Document;
  10.  
  11.   FilteredElementCollector col = null;
  12.  
  13.   // Доступ к текущим выделенным элементам
  14.  
  15.   ElementSet set = uidoc.Selection.Elements;
  16.  
  17.   int n = set.Size;
  18.  
  19.   if( 0 < n )
  20.   {
  21.     List<ElementId> ids
  22.       = new List<ElementId>( set
  23.         .OfType<Area>()
  24.         .Select<Area,ElementId>( e => e.Id ) );
  25.  
  26.  
  27.     if( 0 == ids.Count )
  28.     {
  29.       message = "Выберите зоны "
  30.         + " Перед запускам команды или не выбирайти ничего"
  31.         + "для обработки всех зон.";
  32.  
  33.       return Result.Failed;
  34.     }
  35.  
  36.  
  37.     col = new FilteredElementCollector( doc, ids )
  38.       .WhereElementIsNotElementType();
  39.   }
  40.   else
  41.   {
  42.     // Извлекаем все зоны из базы данныэх
  43.  
  44.     col = new FilteredElementCollector( doc )
  45.       .OfClass( typeof( Area ) );
  46.   }
  47.  
  48.   // Задаем опции для определения границ
  49.  
  50.   SpatialElementBoundaryOptions opt
  51.     = new SpatialElementBoundaryOptions();
  52.  
  53.   opt.StoreFreeBoundaryFaces = true;
  54.  
  55.   opt.SpatialElementBoundaryLocation =
  56.     SpatialElementBoundaryLocation.Center; // контур замкнут
  57.     //SpatialElementBoundaryLocation.Finish; // Контур не замкнут
  58.  
  59.   using( Transaction tx = new Transaction( doc ) )
  60.   {
  61.     tx.Start( "Конвертация границы зоны в линии модели" );
  62.  
  63.     // проходим по всем зонам
  64.  
  65.     foreach( Area area in col )
  66.     {
  67.       Debug.Print( area.Name );
  68.  
  69.       double z = area.Level.Elevation;
  70.  
  71.       Plane levelPlane = app.Create.NewPlane(
  72.         XYZ.BasisZ, new XYZ( 0, 0, z ) );
  73.  
  74.       SketchPlane sketchPlane
  75.         = doc.Create.NewSketchPlane( levelPlane );
  76.  
  77.       IList<IList<BoundarySegment>> loops
  78.         = area.GetBoundarySegments( opt );
  79.  
  80.       foreach( IList<BoundarySegment> loop in loops )
  81.       {
  82.         foreach( BoundarySegment seg in loop )
  83.         {
  84.           doc.Create.NewModelCurve(
  85.             seg.Curve, sketchPlane );
  86.         }
  87.       }
  88.     }
  89.  
  90.     tx.Commit();
  91.   }
  92.   return Result.Succeeded;
  93. }

В архиве DisplayBoundary.zip содержится полный код команды с проектом для Visual Studio.

Источник: http://thebuildingcoder.typepad.com/blog/2012/08/graphically-display-area-boundary-loops.html

Примечание. Этот способ также подойдет и для отображения границ помещения, так как методы, применяемые для определения границ, находятся в базовом классе SpatialElement.Наследуемыми классами являются класс Room и Area

Автор перевода: Виктор Чекалин

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

Опубликовано 25.12.2016