读书人

Building Coder(Revit 二次开发)- 应

发布时间: 2012-10-20 14:12:47 作者: rapoo

Building Coder(Revit 二次开发)- 使用“实体相交(Solid Intersection)”机制过滤有接触的梁
原文链接:Filter for Touching Beams Using Solid Intersection

几何创建工具创建的临时实体(Solid)可以用于几何特征过滤器。

问题


我想通过编程方式获取全部有接触的梁,不考虑它们之间的连接状态。用户首先选中一根梁,然后程序自动将所有有递归接触的梁(即级联方式接触)选中。


Jeremy


首先让我们讨论这些梁是处于连接状态的情况:你可以使用 Beam.LocationCurve.ElementsAtJoin 属性获取在一根梁的指定端点连接的所有梁。然后再遍历得到的梁的集合,对每根梁继续使用 Beam.LocationCurve.ElementsAtJoin 属性获取级联模式下新的连接梁的集合。你可以在 SDK 例程 TraverseSystem 中找到类似的处理机制,这个例程展示了在管道系统中如何使用 MEP 连接管理器(Connection Manager)来遍历所有处于连接状态的元素。


然后回到你的需求:这些梁不是处于连接状态,而只是相互接触的。我们可以使用 ElementIntersectsSolidFilter,在一个由实体定义的空间区域中检测所有与该区域相交的元素。这个实体可以来自实际的 BIM 模型,也可以是临时创建的且只存在于内存中。

为了获取所有级联方式接触的梁,我们必须为每根梁都创建一个实体和 ElementIntersectsSolidFilter。如果你需求中的接触是指在任意位置(即不是在梁的两个端点),那么应该按照当前梁的形状创建一个形状拉伸实体,然后检测与该形状拉伸实体有任何空间相交或是足够接近的梁。如果你只关心有端点接触的梁,那可以简单地在当前梁的端点处创建一个球体。

这个操作应该递归地应用到所有找到的梁。当然,你必须将已经处理过的梁排除在外,否则会导致死循环。

以下是我考虑的实现流程:

1. 维护三个梁列表

- 已经处理过的梁(已处理梁表)
- 正在被处理的梁(当前梁表)
- 与正在被处理的梁相邻的梁(相邻梁表)

2. 选中一根梁添加到当前梁表

3. 如果当前梁表非空,则重复如下处理

- 将当前梁添加到已处理梁表
- 清空相邻梁表
- 将与当前梁有接触的所有梁添加到相邻梁表
- 将在上一步中找到的相邻梁表作为新的当前梁表

在下面的代码中,检测与指定梁接触的所有梁的代码在方法 AddConnectedElements() 中。该方法首先在梁的两个端点分别创建一个球体,然后创建一个与基于球体的空间相邻检测器,并将其应用到一个 ElementIntersectsSolidFilter 中。执行过滤器,并从过滤结果中删除已经处理过的梁,和已经找到的相邻梁,然后将最后结果添加到相邻梁表。

public Result Execute(  ExternalCommandData commandData,  ref string message,  ElementSet elements ){  UIApplication uiapp = commandData.Application;  UIDocument uidoc = uiapp.ActiveUIDocument;  Application app = uiapp.Application;  CreationApp creapp = app.Create;  Document doc = uidoc.Document;  Selection sel = uidoc.Selection;  Reference r = null;   try  {    r = sel.PickObject( ObjectType.Element, "Please select a beam" );  }  catch( RvtOperationCanceledException )  {    return Result.Cancelled;  }   // 初始梁  Element start = doc.GetElement( r );   // 当前梁表(我们需要查找它们的相邻梁)  List<ElementId> current = new List<ElementId>();   current.Add( start.Id );   // 已处理梁表  List<ElementId> visited = new List<ElementId>();   // 相邻梁表  List<ElementId> neighbours = new List<ElementId>();   // 递归调用  while( 0 < current.Count )  {    // 记录已处理梁表    visited.AddRange( current );     neighbours.Clear();     // 查找当前梁表的相邻梁表(未处理)    foreach( ElementId id in current )    {      Element e = doc.GetElement( id );      AddConnectedElements( neighbours, e, visited );    }     // 当前梁表处理完毕,找到相邻梁表成为下一次操作的当前梁表    // newly found become the next current ones     current.Clear();    current.AddRange( neighbours );  }   foreach( ElementId id in visited )  {    uidoc.Selection.Elements.Add( doc.GetElement( id ) );  }  return Result.Succeeded;}

注意这个解决方案适用于所有基于曲线的元素。可以用于查找所有接触墙体、管线、管道等等场景。


完整的代码可以从这里下载:SelectTouchingBeams.zip

读书人网 >其他相关

热点推荐