我们知道,通过过滤器ElementIntersectsElementFilter可以获取到与某构件相交的构件,但是不能获取到与其接触但未相交的元素。比如下图,两面墙都与中间的柱子相交,
var column = _document.CollectAll<FamilyInstance>(BuiltInCategory.OST_StructuralColumns)
.FirstOrDefault();
var co = new FilteredElementCollector(_document);
var elemsFilter = new ElementIntersectsElementFilter(column, false);
var elems = co.WherePasses(elemsFilter).ToElements();
通过上面的方法,就可以获取到与柱子相交的两面墙。
如果想获取到与其只是接触的构件,可以利用ElementIntersectsSolidFilter。
比如下面的情况:两面墙刚好画到柱子的边缘,只是接触,而未相交。
思路就是首先获取到柱子的solid和对应的faces,然后通过faces,创建额外的solid,利用新创建的solid,去过滤与其相交的构件
var column = _document.CollectAll<FamilyInstance>(BuiltInCategory.OST_StructuralColumns)
.FirstOrDefault();
var solidElem = GetElementSolid(column);
var faces = GetFacesFromSolid(solidElem);
foreach (var face in faces)
{
var planarFace = face as PlanarFace;
//忽略掉顶面和底面
if (planarFace.FaceNormal.IsAlmostEqualTo(new XYZ(0, 0, 1))
|| planarFace.FaceNormal.IsAlmostEqualTo(new XYZ(0, 0, -1)))
{
continue;
}
//由face转变为拉伸所需要的截面profile
var profiles = planarFace.GetEdgesAsCurveLoops();
//生成拉伸体solid
var solid = GeometryCreationUtilities
.CreateExtrusionGeometry(profiles, planarFace.FaceNormal, 1);
using (var ts = new Transaction(_document, "创建"))
{
ts.Start();
var ds = DirectShape.CreateElement(_document, new ElementId(-2000151));
ds.AppendShape(new List<GeometryObject> { solid });
ts.Commit();
}
var collector = new FilteredElementCollector(_document).OfClass(typeof(Wall));
var solidFilter = new ElementIntersectsSolidFilter(solid);
collector.WherePasses(solidFilter);
var ids = collector.ToElementIds();
TaskDialog.Show("Tips", ids.Count.ToString());
}
获取元素solid
/// <summary>
/// 获取元素的solid
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
private Solid GetElementSolid(Element element)
{
Solid solid = null;
var option = _commandData.Application.Application.Create.NewGeometryOptions();
option.IncludeNonVisibleObjects = false;
option.DetailLevel = ViewDetailLevel.Medium;
var geometryElement = element.get_Geometry(option);
foreach (var geoOb in geometryElement)
{
if (geoOb is Solid)
{
var s = geoOb as Solid;
if (s != null && s.Volume > 0)
{
solid = s;
}
}
else if (geoOb is GeometryInstance)
{
var gIn = geoOb as GeometryInstance;
if (gIn != null)
{
//获取当前实例的几何信息
var ge = gIn.GetInstanceGeometry();
//获取族类型的几何信息
//var ge = gIn.GetSymbolGeometry();
foreach (var go in ge)
{
var s = go as Solid;
if (s != null && s.Volume > 0)
{
solid = s;
}
}
}
}
}
return solid;
}
获取solid的faces
/// <summary>
/// 获取solid的面faces
/// </summary>
/// <param name="solid"></param>
/// <returns></returns>
private List<Face> GetFacesFromSolid(Solid solid)
{
var faces = new List<Face>();
foreach (Face face in solid.Faces)
{
faces.Add(face);
}
return faces;
}
下面这段代码可以让创建的solid转化为对应的实体构件,只是为了肉眼可以看到实际的solid到底创建在了哪里:
var ds = DirectShape.CreateElement(_document, new ElementId(-2000151));
ds.AppendShape(new List<GeometryObject> { solid });
运行程序,效果如下:高亮部分即新创建的solid,被转换成了其他肉眼可见的模型。
最终得出结果,与solid相交的构件分别为两面墙。