Графическое отображение границ зоны
Недавно я работал над проблемой одного разработчика, у которого были трудности с границами зоны и попыткой определить, является ли граница замкнутой или нет, с помощью значений координат в RevitLookup.
Очевидно, что это не самый легкий способ, попытаться проанализировать кучу чисел.
Поэтому я реализовал небольшую команду DisplayBoundary для отображения границы. В ней перебираются все сегменты границы выбранных зон или всех зон в модели и с помощью линий модели рисуется каждый сегмент.
После выполнения, линии модели могут быть изолированы, для отображения результата.
Метод Area.GetBoundarySegments принимает в качестве аргумента объект класса SpatialElementBoundaryOptions, который позволяет задать два свойства – StoreFreeBoundaryFaces и SpatialElementBoundaryLocation.
Первый отвечает за то, включать ли «свободные» поверхности в результат. Т.е. такие поверхности, которые не связаны с поверхностями элемента, являющегося границей зоны.
Последний может быть установлен в Finish, чтобы получить поверхность зоны по финишной поверхности граничащего элемента, или в Center – по центральной линии.
Пример
Вот пример зоны, на которой будем производить тестирование:
Тут мы видим сложные края, составленные из стен, проемов в них и соответствующих помещений:
Выбрав зоны и запустив команду, мы построим лини модели по каждому сегменту границы помещения. Изолировав линии модели мы увидим контур границы зоны:
Код
Код довольно прост и понятен. Однако он не был тщательно протестирован:
- public Result Execute(
- ExternalCommandData commandData,
- ref string message,
- ElementSet elements )
- {
- UIApplication uiapp = commandData.Application;
- UIDocument uidoc = uiapp.ActiveUIDocument;
- Application app = uiapp.Application;
- Document doc = uidoc.Document;
- FilteredElementCollector col = null;
- // Доступ к текущим выделенным элементам
- ElementSet set = uidoc.Selection.Elements;
- int n = set.Size;
- if( 0 < n )
- {
- List<ElementId> ids
- = new List<ElementId>( set
- .OfType<Area>()
- .Select<Area,ElementId>( e => e.Id ) );
- if( 0 == ids.Count )
- {
- message = "Выберите зоны "
- + " Перед запускам команды или не выбирайти ничего"
- + "для обработки всех зон.";
- return Result.Failed;
- }
- col = new FilteredElementCollector( doc, ids )
- .WhereElementIsNotElementType();
- }
- else
- {
- // Извлекаем все зоны из базы данныэх
- col = new FilteredElementCollector( doc )
- .OfClass( typeof( Area ) );
- }
- // Задаем опции для определения границ
- SpatialElementBoundaryOptions opt
- = new SpatialElementBoundaryOptions();
- opt.StoreFreeBoundaryFaces = true;
- opt.SpatialElementBoundaryLocation =
- SpatialElementBoundaryLocation.Center; // контур замкнут
- //SpatialElementBoundaryLocation.Finish; // Контур не замкнут
- using( Transaction tx = new Transaction( doc ) )
- {
- tx.Start( "Конвертация границы зоны в линии модели" );
- // проходим по всем зонам
- foreach( Area area in col )
- {
- Debug.Print( area.Name );
- double z = area.Level.Elevation;
- Plane levelPlane = app.Create.NewPlane(
- XYZ.BasisZ, new XYZ( 0, 0, z ) );
- SketchPlane sketchPlane
- = doc.Create.NewSketchPlane( levelPlane );
- IList<IList<BoundarySegment>> loops
- = area.GetBoundarySegments( opt );
- foreach( IList<BoundarySegment> loop in loops )
- {
- foreach( BoundarySegment seg in loop )
- {
- doc.Create.NewModelCurve(
- seg.Curve, sketchPlane );
- }
- }
- }
- tx.Commit();
- }
- return Result.Succeeded;
- }
В архиве 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