我想通过编程方式获取全部有接触的梁,不考虑它们之间的连接状态。用户首先选中一根梁,然后程序自动将所有有递归接触的梁(即级联方式接触)选中。
Jeremy
首先让我们讨论这些梁是处于连接状态的情况:你可以使用 Beam.LocationCurve.ElementsAtJoin 属性获取在一根梁的指定端点连接的所有梁。然后再遍历得到的梁的集合,对每根梁继续使用 Beam.LocationCurve.ElementsAtJoin 属性获取级联模式下新的连接梁的集合。你可以在 SDK 例程 TraverseSystem 中找到类似的处理机制,这个例程展示了在管道系统中如何使用 MEP 连接管理器(Connection Manager)来遍历所有处于连接状态的元素。
1. 维护三个梁列表
- 已经处理过的梁(已处理梁表)2. 选中一根梁添加到当前梁表
3. 如果当前梁表非空,则重复如下处理
- 将当前梁添加到已处理梁表 ///
/// 获取所有与元素“e”相邻的元素(排除已处理过的元素)
///
void AddElementsIntersectingSphereAt(
List neighbours,
XYZ p,
List visited,
Document doc )
{
Solid sphere = CreateSphereAt( doc.Application.Create, p, _sphere_radius );
ElementIntersectsSolidFilter intersectSphere = new ElementIntersectsSolidFilter( sphere );
FilteredElementCollector collector = new FilteredElementCollector( doc )
.WhereElementIsCurveDriven() // 可以处理任意 Location 为 LocationCurve 的元素
.OfCategory( _bic )
.Excluding( visited.Union( neighbours ).ToList() )
.WherePasses( intersectSphere );
neighbours.AddRange( collector.ToElementIds() );
}
///
/// Determine all neighbouring elements close to
/// the two ends of the current element 'e',
/// skipping all previously visited ones.
///
void AddConnectedElements(
List neighbours,
Element e,
List visited )
{
Location loc = e.Location;
Debug.Print( string.Format( "current element {0} has location {1}",
ElementDescription( e ),
null == loc ? "" : loc.GetType().Name ) );
LocationCurve lc = loc as LocationCurve;
if( null != lc )
{
Document doc = e.Document;
Curve c = lc.Curve;
XYZ p = c.get_EndPoint( 0 );
XYZ q = c.get_EndPoint( 1 );
AddElementsIntersectingSphereAt( neighbours, p, visited, doc );
AddElementsIntersectingSphereAt( neighbours, q, visited, doc );
}
}
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 current = new List();
current.Add( start.Id );
// 已处理梁表
List visited = new List();
// 相邻梁表
List neighbours = new List();
// 递归调用
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;
}
注意这个解决方案适用于所有基于曲线的元素。可以用于查找所有接触墙体、管线、管道等等场景。