原文链接:
Graphically Display Area Boundary Loops
我最近研究了一个关于检测区域边界是否闭合的问题,方法是在 RevitLookup 中查看相关的坐标值。但是我想人脑很难分析这么多的数据,所以靠谱的方式你懂的,还是创建一个外部命令(DisplayBoundary)来自动化地完成。该命令遍历选中区域(或是模型中的所有区域)的边界片段,然后创建一个曲线来代表每个片段。
命令运行之后,新创建的曲线就可以独立地图形化显示了。
区域边界片段获取设置
因为 Revit 墙体的 Location 属性是定义于其中心线的,所以应该使用 SpatialElementBoundaryLocation 属性来从边界片段结果中获取闭合线。
它的锯齿状边界来源于位于该区域的房间的门窗洞。
我最近研究了一个关于检测区域边界是否闭合的问题,方法是在 RevitLookup 中查看相关的坐标值。但是我想人脑很难分析这么多的数据,所以靠谱的方式你懂的,还是创建一个外部命令(DisplayBoundary)来自动化地完成。该命令遍历选中区域(或是模型中的所有区域)的边界片段,然后创建一个曲线来代表每个片段。
命令运行之后,新创建的曲线就可以独立地图形化显示了。
区域边界片段获取设置
Area.GetBoundarySegments() 方法需要一个 SpatialElementBoundaryOptions 对象作为参数,SpatialElementBoundaryOptions 对象提供两个属性来定义如何获取边界片段:
1. StoreFreeBoundaryFaces (bool)
在结果中是否包含自由边界面(空间元素表面的与其轮廓表面不重合的部分)
2. SpatialElementBoundaryLocation (enum)
Finish - 空间元素的轮廓面
Center - 空间元素中心线面因为 Revit 墙体的 Location 属性是定义于其中心线的,所以应该使用 SpatialElementBoundaryLocation 属性来从边界片段结果中获取闭合线。
例子
下图是我用来测试的 Revit 文件。
它的锯齿状边界来源于位于该区域的房间的门窗洞。
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 = "Please select some area alements "
+ " before running his command, or nothing "
+ "at all to process all of them.";
return Result.Failed;
}
// 注意从逻辑上讲是不需要调用 WhereElementIsNotElementType() 方法的。
// 但是 Revit API 有个小缺陷,如果不调用则在对 col 进行过滤操作时会抛出一个异常。
col = new FilteredElementCollector( doc, ids ).WhereElementIsNotElementType();
}
else
{
// 注意我们不能使用 Area 作为 OfClass() 方法的参数,因为 Area 不是 Revit 的本地对象。
// 应该先使用 Area 的基类 SpatialElement 作为 OfClass() 方法的参数,然后在结果中将类型转换成 Area。
col = new FilteredElementCollector( doc ).OfClass( typeof( SpatialElement ) );
}
// 定义边界设置
SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions();
opt.StoreFreeBoundaryFaces = true;
opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center; // 闭合线
//opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish; // 非闭合线
using( Transaction tx = new Transaction( doc ) )
{
tx.Start( "Convert Area Loops To Model Curves" );
foreach( SpatialElement e in col )
{
Area area = e as Area;
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