构建一个长方体,过滤出与之碰撞的元素,当长方体的截面很小时,可以把它视为一条直线,那么就是过滤出与直线碰撞的元素。
/// <summary>
/// 使用实体相交的方法过滤出碰撞元素
/// </summary>
/// <param name="document"></param>
/// <param name="line">线在拉伸体的中间位置</param>
/// <param name="xDir">碰撞体截面X方向</param>
/// <param name="xLength">X长度</param>
/// <param name="yLength">Y长度</param>
/// <returns></returns>
public static IEnumerable<Element> GetCollisionElement(this Document document, Line line, XYZ xDir, double xLength = 0, double yLength = 0)
{
System.Diagnostics.Debug.Assert(line != null);
System.Diagnostics.Debug.Assert(GeometryHelper.IsVertical(line.Direction, xDir));
xLength = xLength == 0 ? UnitHelper.MM2Feet(1) : xLength;
yLength = yLength == 0 ? UnitHelper.MM2Feet(1) : yLength;
var solid = BuildSolid(line.GetEndPoint(0), xDir, line.Direction, xLength, yLength, line.ApproximateLength);
#if DEBUG
foreach (Edge edge in solid.Edges)
document.CreateLine(edge.AsCurve() as Line, new Autodesk.Revit.DB.Color(200, 60, 60));
#endif
var filter = new ElementIntersectsSolidFilter(solid);
var collector = new FilteredElementCollector(document);
return collector.WherePasses(filter);
}
/// <summary>
/// 构建Solid结构
/// ____________
/// | |
/// | |
/// | | width
/// |____________|
/// length
/// </summary>
/// <param name="document"></param>
/// <param name="point">矩形截面的中心位置</param>
/// <param name="xDir">截面X轴方向</param>
/// <param name="zDir">截面法相</param>
/// <param name="length">x方向长度</param>
/// <param name="width">y方向长度</param>
/// <param name="extrusionHeight"></param>
/// <returns></returns>
public static Solid BuildSolid(XYZ point, XYZ xDir, XYZ zDir, double length, double width, double extrusionHeight)
{
System.Diagnostics.Debug.Assert(DoubleEqualComparer.Instance.Equals(xDir.DotProduct(zDir), 0));
System.Diagnostics.Debug.Assert(extrusionHeight > 0 && length > 0 && width > 0);
var transform = TransformUtils.CreateTransform(point, xDir, zDir);
var halfLength = length / 2;
var halfWidth = width / 2;
var A = transform.OfPoint(new XYZ(-halfLength, -halfWidth, 0));
var B = transform.OfPoint(new XYZ(halfLength, -halfWidth, 0));
var C = transform.OfPoint(new XYZ(halfLength, halfWidth, 0));
var D = transform.OfPoint(new XYZ(-halfLength, halfWidth, 0));
var a = transform.OfPoint(new XYZ(-halfLength, -halfWidth, extrusionHeight));
var b = transform.OfPoint(new XYZ(halfLength, -halfWidth, extrusionHeight));
var c = transform.OfPoint(new XYZ(halfLength, halfWidth, extrusionHeight));
var d = transform.OfPoint(new XYZ(-halfLength, halfWidth, extrusionHeight));
var profileLoops = new List<CurveLoop>();
var loop = new CurveLoop();
loop.Append(Line.CreateBound(A, B));
loop.Append(Line.CreateBound(B, C));
loop.Append(Line.CreateBound(C, D));
loop.Append(Line.CreateBound(D, A));
profileLoops.Add(loop);
return GeometryCreationUtilities.CreateExtrusionGeometry(profileLoops, transform.BasisZ, extrusionHeight);
}
代码说明:逻辑挺简单的,为了构建出一个长方体,需要条件:
1、截面位置:截面上一点和法相(line),xDir,xLength,yLength
2、拉伸体长度(line的长度)
使用ElementIntersectsFilter碰撞过滤器时,最优的处理方式是:先取对象的boundingbox,然后使用快速过滤器BoundingBoxIntersectsFilter或BoundingBoxIsInsideFilter(具体看需求)初步筛选出元素,最后再使用碰撞过滤器处理上一步过滤出来的元素。