You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何快速检索指定Room内的ElevationMarker及相关视图?

针对Room内ElevationMarker查找的高效解决方案

核心问题解答

Revit API里没有直接对应ElementIntersectsSolidFilter、专门用于匹配Room内ElevationMarker的过滤器,但可以通过空间几何判断+高效过滤逻辑替代你当前的低效实现,同时兼容所有现有模型,不用依赖ExtensibleStorage。

现有代码的性能瓶颈

你当前的实现有两个关键性能问题:

  • 创建临时视图本身会产生额外开销,而且通过视图ID收集元素相当于遍历视图内所有元素,模型大时这个范围太广
  • 对每个标记逐个调用get_BoundingBox和GetRoomAtPoint,这类几何操作的单次开销不低,批量调用时会被放大

优化后的实现思路

直接基于Room的几何范围过滤全局的ElevationMarker,步骤如下:

  1. 获取目标Room的几何边界(Solid)或边界框,先做粗筛
  2. 全局收集所有ElevationMarker(跳过类型),用几何过滤器缩小范围
  3. 对筛选后的标记做精确判断,确认是否属于目标Room

优化代码示例

using Autodesk.Revit.DB;

public List<ElevationMarker> GetElevationMarkersInRoom(Room targetRoom, Document doc)
{
    List<ElevationMarker> markersInRoom = new List<ElevationMarker>();
    Phase roomPhase = targetRoom.Phase;

    // 1. 获取Room的Solid边界(用于精确相交判断)
    Solid roomSolid = null;
    IList<IList<BoundarySegment>> boundarySegments = targetRoom.GetBoundarySegments(new SpatialElementBoundaryOptions());
    if (boundarySegments != null && boundarySegments.Count > 0)
    {
        List<CurveLoop> curveLoops = new List<CurveLoop>();
        foreach (var segmentList in boundarySegments)
        {
            CurveLoop loop = new CurveLoop();
            foreach (BoundarySegment seg in segmentList)
            {
                loop.Append(seg.GetCurve());
            }
            curveLoops.Add(loop);
        }
        roomSolid = GeometryCreationUtilities.CreateExtrusionGeometry(curveLoops, XYZ.BasisZ, targetRoom.UnboundedHeight);
    }

    if (roomSolid == null)
    {
        // 如果无法获取Solid,退而求其次用Room的BoundingBox做初步过滤
        BoundingBoxXYZ roomBB = targetRoom.get_BoundingBox(null);
        Outline roomOutline = new Outline(roomBB.Min, roomBB.Max);
        BoundingBoxIntersectsFilter bbFilter = new BoundingBoxIntersectsFilter(roomOutline);

        var candidateMarkers = new FilteredElementCollector(doc)
            .OfClass(typeof(ElevationMarker))
            .WhereElementIsNotElementType()
            .WherePasses(bbFilter)
            .Cast<ElevationMarker>()
            .Where(e => e.HasElevations());

        foreach (var marker in candidateMarkers)
        {
            // 获取ElevationMarker的插入点
            XYZ markerLocation = marker.GetTransform().Origin;
            Room markerRoom = doc.GetRoomAtPoint(markerLocation, roomPhase);
            if (markerRoom != null && markerRoom.Id == targetRoom.Id)
            {
                markersInRoom.Add(marker);
            }
        }
    }
    else
    {
        // 用Solid相交过滤器做精确筛选
        ElementIntersectsSolidFilter solidFilter = new ElementIntersectsSolidFilter(roomSolid);

        markersInRoom = new FilteredElementCollector(doc)
            .OfClass(typeof(ElevationMarker))
            .WhereElementIsNotElementType()
            .WherePasses(solidFilter)
            .Cast<ElevationMarker>()
            .Where(e => e.HasElevations())
            .ToList();

        // 额外校验:避免Solid相交判断的误判(比如标记边界刚好触碰到Room)
        markersInRoom = markersInRoom.Where(m => 
        {
            XYZ loc = m.GetTransform().Origin;
            Room r = doc.GetRoomAtPoint(loc, roomPhase);
            return r != null && r.Id == targetRoom.Id;
        }).ToList();
    }

    return markersInRoom;
}

额外说明

  • 找到ElevationMarker后,可以通过marker.GetAllElevations()获取关联的立面视图ID,再通过doc.GetElement(viewId)拿到视图对象进行重命名
  • 若Room的Solid创建失败(比如复杂形状的Room),代码会自动降级到边界框过滤+点校验的逻辑,保证兼容性
  • 相比你原来的实现,这个方案省去了临时视图的创建,且用过滤器先粗筛元素,大幅减少了后续需要做精确判断的元素数量,性能提升明显

内容的提问来源于stack exchange,提问作者Anthony Tiefenbach

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:31:17