Building Coder(Revit 二次开发)- 创建球体用于AVF和过滤
原文链接:Sphere Creation for AVF and Filtering
Revit 2012 API 新引入了 GeometryCreationUtilities 类来帮助创建实体。然而它没有提供直接的球体创建方法,而是提供了以下五个根据输入曲线创建几何实体的辅助方法:
CreateBlendGeometry 融合CreateExtrusionGeometry 拉伸CreateRevolvedGeometry 旋转CreateSweptGeometry 放样CreateSweptBlendGeometry 放样融合创建之后的几何结果并不会作为元素添加到文档中。不过你可以使用创建的实体、实体的面和边做如下操作:
- 作为Analysis Visualization Framework(AVF)方法的面输入参数
例如:SpatialFieldManager.AddSpatialFieldPrimitive
- 作为确定三维元素空间相交情况的实体输入参数
- 作为布尔操作的输入参数
- 作为几何计算的输入参数
例如:面投影(Face.Project)、面相交(Face.Intersect)、和其它有关面、实体、边的几何方法
既然这种方式创建的实体只存在于内存中,无法添加到 Revit 文件数据库与文件一起保存,那它们有什么作用呢?
正如我们上面提到的,你可以使用这些实体通过AVF来可视化地显示一些结果;或者在搜索相交元素时(ElementIntersectsFilter)将范围限定在一个空间区域。
创建球体
我们可以使用 CreateRevolvedGeometry() 方法:首先创建一个表示半圆的闭合曲线,包括180度的圆弧和连接圆弧两个端点的直线(即经过圆心的直径线)。然后将半圆面以直径线为轴旋转360度就可以了。
这里我们首先需要创建一个 Revit 称之为 Frame 的对象。为了使我的代码能允许在任意位置创建球体,我还需要将球心和球半径作为输入参数。我可以使用球心来定义 Frame 的位置。起初我以为既然半圆面的闭合曲线是针对全局坐标系的,那么 Frame 应该会自动将半圆面的其它几何数据转换为全局坐标系。但是当我使用以球心为原点的局部坐标系定义圆弧和直径线时,CreateRevolvedGeometry() 方法会抛出异常:闭合曲线必须位于Z轴的右侧(X坐标 >= 0)。
所以我们必须在创建圆弧和直径线时,就使用已经转换到全局坐标系的坐标值。
void PaintSolids( Document doc, Solid solid, int level ) { Application app = doc.Application; View view = doc.ActiveView; if( view.AnalysisDisplayStyleId == ElementId.InvalidElementId ) { CreateAvfDisplayStyle( doc, view ); } SpatialFieldManager sfm = SpatialFieldManager.GetSpatialFieldManager( view ); if( null == sfm ) { sfm = SpatialFieldManager.CreateSpatialFieldManager( view, 1 ); } if( _schemaId != -1 ) { IList<int> results = sfm.GetRegisteredResults(); if( !results.Contains( _schemaId ) ) { _schemaId = -1; } } if( _schemaId == -1 ) { AnalysisResultSchema resultSchema = new AnalysisResultSchema( "PaintedSolids", "Description" ); _schemaId = sfm.RegisterResult( resultSchema ); } FaceArray faces = solid.Faces;Transform trf = Transform.Identity;foreach( Face face in faces ){int idx = sfm.AddSpatialFieldPrimitive( face, trf );IList<UV> uvPts = new List<UV>( 1 );uvPts.Add( face.GetBoundingBox().Min );FieldDomainPointsByUV pnts = new FieldDomainPointsByUV( uvPts );List<double> doubleList = new List<double>( 1 );doubleList.Add( level );IList<ValueAtPoint> valList = new List<ValueAtPoint>( 1 );valList.Add( new ValueAtPoint( doubleList ) );FieldValues vals = new FieldValues( valList );sfm.UpdateSpatialFieldPrimitive( idx, pnts, vals, _schemaId );} }