05过滤
Filtering 过滤
Revit API提供了一种过滤和迭代Revit文档中图元的机制。这是获取一组相关元素(如文档中的所有墙或门)的最佳方法。过滤器也可以用来找到一个非常具体的元素集,如所有特定大小的梁。
获取通过指定过滤器的元素的基本步骤如下:
- 创建新的FilteredElementCollector
- 对它应用一个或多个过滤器
- 获取过滤后的元素或元素ID(使用以下几种方法之一)
下面的示例涵盖了在文档中筛选和迭代元素的基本步骤。
代码区域6-1:使用元素过滤获取文档中的所有墙实例
1 | // Find all Wall instances in the document by using category filter |
Pages in this section 本节中的页面
- 创建FilteredElementCollector
- 应用过滤器
- 获取筛选的元素或元素ID
- LINQ查询
- 边界框过滤器
- 元素交叉过滤器
创建FilteredElementCollector
用于元素迭代和筛选的主类称为FilteredElementCollector。它以三种方式之一构建:
- 从文档-将搜索和筛选文档中的元素集
- 从一个文档和一组ElementId-将搜索和筛选一组指定的元素
- 从文档和视图-将搜索和过滤视图中的可见元素
注意:使用静态FilteredElementCollector.IsViewValidForElementIteration()过滤指定视图中的元素时,请始终检查视图是否对元素迭代有效。
首次创建对象时,没有应用任何过滤器。此类要求在尝试访问元素之前至少设置一个条件,否则将引发异常。
应用过滤器
可以使用ElementFilters将筛选器应用于FilteredElementCollector。ElementFilter是一个类,它检查元素以查看它是否满足特定条件。ElementFilter基类有三个派生类,它们将元素筛选器分为三个类别。
- ElementQuickFilter-快速过滤器仅在ElementRecord上操作,ElementRecord是一个低内存类,它具有有限的读取元素属性的接口。被快速筛选器拒绝的元素将不会在内存中展开。
- ElementSlowFilter-慢过滤器要求首先获取元素并在内存中展开。因此,最好将慢速过滤器与至少一个ElementQuickFilter耦合,这应该最小化扩展的元素数量,以便根据该过滤器设置的标准进行评估。
- ElementLogicalFilter-逻辑筛选器将联合收割机两个或多个筛选器逻辑组合。Revit可能会对构件过滤器重新排序,以使最快作用的过滤器首先被评估。
大多数过滤器可以使用重载构造函数来反转,该重载构造函数接受指示反转过滤器的布尔参数,以便通常被过滤器接受的元素将被拒绝,而通常被拒绝的元素将被接受。不能反转的过滤器在下面的相应部分中注明。
有一组预定义的过滤器可用于常见用途。这些内置过滤器中的许多都为上面的FilteredElementCollector部分中提到的FilteredElementCollector快捷方法提供了基础。接下来的三个部分提供了有关内置过滤器的更多信息。
创建筛选器后,需要将其应用于FilteredElementCollector。泛型方法WherePasses()用于将单个ElementFilter应用于FilteredElementCollector。
还可以使用FilteredElementCollector提供的许多快捷方法应用筛选器。有些应用一个特定的过滤器而不需要进一步的输入,比如WhereElementIsCurveDriven(),而其他应用一个特定的过滤器而只需要一个简单的输入,比如OfCategory()方法,它将BuiltInCategory作为一个参数。最后,还有一些方法,如UnionWith(),可以将过滤器连接在一起。所有这些方法都返回相同的收集器,从而可以轻松地将过滤器链接在一起。
Quick filters 快速筛选器
快速过滤器只在ElementRecord上操作,ElementRecord是一个低内存类,它具有有限的读取元素属性的接口。被快速筛选器拒绝的元素将不会在内存中展开。下表总结了内置的快速过滤器,下面是一些过滤器的示例。
Table 13: Built-in Quick Filters
表13:内置快速过滤器
Built-in Filter 内置过滤器 | What it passes 它所经过的 | Shortcut Method(s) 快捷方法 |
---|---|---|
BoundingBoxContainsPointFilter | 具有包含给定点的边界框的元素 | None |
BoundingBoxIntersectsFilter | 具有与给定轮廓相交的边界框的元素 | None |
BoundingBoxIsInsideFilter | 在给定轮廓内有边界框的元素 | None |
ElementCategoryFilter | id 与输入类别id匹配的元素 | OfCategoryId() |
ElementClassFilter | 与输入运行时类(或派生类)匹配的元素 | OfClass() |
ElementDesignOptionFilter | 特定设计选项中的图元 | ContainedInDesignOption() |
ElementIsCurveDrivenFilter | 曲线驱动的元素 | WhereElementIsCurveDriven() |
ElementIsElementTypeFilter | 属于“元素类型”的元素 | WhereElementIsNotElementType() |
ElementMulticategoryFilter | 与给定类别集中的任何一个相匹配的元素 | None |
ElementMulticlassFilter | 与给定的类(或派生类)集匹配的元素 | None |
ElementOwnerViewFilter | 视图专有的图元 | OwnedByView() WhereElementIsViewIndependent() |
ElementStructuralTypeFilter | 与给定结构类型匹配的元素 | None |
ExclusionFilter | 除元素id之外的所有元素都输入到过滤器 | Excluding() |
FamilySymbolFilter | 特定族的Symbol |
注意:FamilySymbolFilter不能反转。
注意:边界框过滤器排除所有从View派生的对象和从ElementType派生的对象。 下面的示例在文档中创建一个大纲,然后使用BoundingBoxIntersectsFilter查找文档中具有与该大纲相交的边界框的元素。然后,它展示了如何使用反向过滤器来查找边界框不与给定轮廓相交的所有墙。请注意,使用OfClass()方法也会将ElementClassFilter应用于集合。
代码区域6-2:BoundingBoxIntersectsFilter示例
1 | // Use BoundingBoxIntersects filter to find elements with a bounding box that intersects the |
下一个示例使用排除过滤器查找文档中当前未选定的所有墙。
代码区域6-3:创建排除过滤器
1 | // Find all walls that are not currently selected, |
注意:ElementClassFilter将匹配其类与输入类完全匹配的元素,或其类派生自输入类的元素。下面的示例使用ElementClassFilter获取文档中的所有加载。
代码区域6-4:使用ElementClassFilter获取负载
1 | // Use ElementClassFilter to find all loads in the document |
API中有一小部分元素子类不受元素类过滤器支持。这些类型存在于API中,但不存在于Revit的本机对象模型中,这意味着此过滤器不支持这些类型。为了使用类过滤器来查找这些类型的元素,需要使用更高级别的类,然后进一步处理结果以查找仅匹配子类型的元素。
注:其中一些类型存在专用过滤器。 以下类型受此限制影响:
Type 类型 | Dedicated Filter 专用过滤器 |
---|---|
Autodesk.Revit.DB.Material的子类 | None |
Autodesk.Revit.DB.CurveElement的子类 | CurveElementFilter |
Autodesk.Revit.DB.ConnectorElement的子类 | None |
Autodesk.Revit.DB.HostedSweep的子类 | None |
Autodesk.Revit.DB.Architecture.Room | RoomFilter |
Autodesk.Revit.DB.Mechanical.Space | SpaceFilter |
Autodesk.Revit.DB.Area | AreaFilter |
Autodesk.Revit.DB.Architecture.RoomTag | RoomTagFilter |
Autodesk.Revit.DB.Mechanical.SpaceTag | SpaceTagFilter |
Autodesk.Revit.DB.AreaTag | AreaTagFilter |
Autodesk.Revit.DB.CombinableElement | None |
Autodesk.Revit.DB.Mullion | None |
Autodesk.Revit.DB.Panel | None |
Autodesk.Revit.DB.AnnotationSymbol | None |
Autodesk.Revit.DB.Structure.AreaReinforcementType | None |
Autodesk.Revit.DB.Structure.PathReinforcementType | None |
Autodesk.Revit.DB.AnnotationSymbolType | None |
Autodesk.Revit.DB.Architecture.RoomTagType | None |
Autodesk.Revit.DB.Mechanical.SpaceTagType | None |
Autodesk.Revit.DB.AreaTagType | None |
Autodesk.Revit.DB.Structure.TrussType | None |
Slow Filters 慢过滤器
慢过滤器要求首先获得元素并在内存中展开。因此,最好将慢速过滤器与至少一个ElementQuickFilter耦合,这应该最小化扩展的元素数量,以便根据该过滤器设置的标准进行评估。下表总结了内置的慢速过滤器,下面的几个示例提供了对某些过滤器的深入了解。
表14:内置慢速过滤器
Built-in Filter 内置过滤器 | What it passes 它所经过的 | Shortcut Method(s) 快捷方法 |
---|---|---|
AreaFilter | Areas 区域 | None |
AreaTagFilter | Area tags 面积标记 | None |
CurveElementFilter | CurveElements 曲线元素 | None |
ElementLevelFilter | 与给定级别ID关联的元素 | None |
ElementParameterFilter | 元素传递一个或多个参数筛选规则 | None |
ElementPhaseStatusFilter | 给定阶段上具有给定阶段状态的元素 | None |
FamilyInstanceFilter | 一个特定的族实例 | None |
FamilyStructuralMaterialTypeFilter | 给定结构材料类型的族元素 | None |
PrimaryDesignOptionMemberFilter | 任何主设计选项所拥有的图元 | None |
RoomFilter | 房间 | None |
RoomTagFilter | 房间标记 | None |
SpaceFilter | 空间 | None |
SpaceTagFilter | 空间标签 | None |
StructuralInstanceUsageFilter | 给定结构用途的族 | None |
StructuralMaterialTypeFilter | 给定结构材料类型的族 | None |
StructuralWallUsageFilter | 指定结构墙用途的墙 | None |
Element Intersection Filters | 与给定图元的实体几何相交的图元 | None |
Element Intersection Filters | 与给定实体几何相交的元素 | None |
以下慢速过滤器不能反转: RoomFilter RoomTagFilter AreaFilter AreaTagFilter SpaceFilter *
FamilyInstanceFilter 如快速过滤器一节所述,有些类不能与ElementClassFilter一起使用。其中一些类,如Room和RoomTag有自己的专用过滤器。
代码区域6-5:使用房间过滤器
1 | // Use a RoomFilter to find all room elements in the document. It is necessary to use the |
ElementParameterFilter是一个功能强大的过滤器,可以根据元素可能具有的参数值查找元素。它可以查找参数值与特定值匹配或大于或小于某个值的元素。ElementParameterFilter还可用于查找支持特定共享参数的元素。 下面的示例使用ElementParameterFilter查找大小超过100平方英尺的房间和小于100平方英尺的房间。
代码区域6-6:使用参数过滤器
1 | // Creates an ElementParameter filter to find rooms whose area is |
下面的示例显示如何使用FamilyStructuralMaterialTypeFilter查找材质类型为木材的所有族。它还说明了如何使用反向过滤器来查找材质类型不是木材的所有族。
代码区域6-7:查找所有使用木质材料的家庭
1 | // Use FamilyStructuralMaterialType filter to find families whose material type is Wood |
最后两个慢过滤器派生自ElementIntersectsFilter,后者是用于匹配与几何体相交的元素的过滤器的基类。有关此类过滤器的使用示例,请参见几何工具类一节中的代码区域:查找附近的墙。#逻辑过滤器逻辑过滤器联合收割机将两个或多个过滤器逻辑组合。下表总结了内置的逻辑筛选器。表15:内置逻辑过滤器
Built-in Filter 内置过滤器 | What it passes 它所经过的 | Shortcut Method(s) 快捷方法 |
---|---|---|
LogicalAndFilter | 通过2个或更多过滤器的元素 | WherePasses()-添加一个额外的过滤器IntersectWith()-连接两组独立的过滤器 |
LogicalOrFilter | 至少通过2个或多个过滤器之一的元素 | UnionWith()-连接两组独立的过滤器 |
在下面的示例中,使用逻辑过滤器组合了两个快速过滤器,以获取文档中的所有door FamilyInstance元素。
代码区域6-8:使用LogicalAndFilter查找所有门实例
1 | // Find all door instances in the project by finding all elements that both belong to the |
获取筛选的元素或元素ID
将一个或多个过滤器应用于FilteredElementCollector后,可以通过以下三种方式之一来检索已过滤的元素集:
- 获取Elements或ElementId的集合。
- ToElements()-返回通过所有应用的过滤器的所有元素
- ToElementIds()-返回通过所有应用过滤器的所有元素的ElementIds
- 获取与筛选器匹配的第一个Element或ElementId。
- FirstElement()-返回第一个元素以通过所有应用的过滤器
- FirstElementId()-返回第一个元素的id,以通过所有应用的过滤器
- 获取ElementId或Element迭代器。
- GetElementIdIterator()-将FilteredElementIdIterator返回到通过过滤器的元素id
- GetElementIterator()-将FilteredElementIterator返回给通过过滤器的元素
- GetEnumerator()-返回一个IEnumerator,它遍历传递元素的集合
一次只能使用这些组中的一个方法;如果调用另一个方法来提取元素,收集器将重置。因此,如果您之前已经获得了一个迭代器,那么当您调用另一个方法来提取元素时,它将停止并且不再遍历任何元素。
哪种方法最好取决于应用。如果只需要一个匹配元素,那么FirstElement()或FirstElementId()是最佳选择。如果需要所有匹配的元素,请使用ToElements()。如果需要一个变量,使用迭代器。
如果应用程序将删除元素或对过滤列表中的元素进行重大更改,ToElementIds()或元素id迭代器是最佳选择。这是因为删除元素或对元素进行重大更改会使元素句柄无效。对于元素id,对具有ElementId的Document.GetElement()的调用将始终返回有效的Element(如果元素已被删除,则返回空引用)。
使用ToElements()方法将筛选结果作为元素集合获取,允许使用foreach检查集合中的每个元素,如下所示:
代码区域6-9:使用ToElements()获取筛选结果
1 | // Use ElementClassFilter to find all loads in the document |
当只需要一个传递元素时,使用FirstElement():
代码区域6-10:获取第一个通过的元素
1 | // Create a filter to find all columns |
在某些情况下,FirstElement()是不够的。下一个示例显示如何使用扩展方法获取第一个非模板3D视图(这对于ReferenceIntersector构造函数的输入很有用)。
代码区域6-11:使用扩展方法获取第一个传递元素
1 | // Use filter to find a non-template 3D view |
The following example demonstrates the use of the FirstElementId() method to get one passing element (a 3d view in this case) and the use of ToElementIds() to get the filter results as a collection of element ids (in order to delete a set of elements in this case).
下面的示例演示了使用FirstElementId()方法获取一个传递元素(本例中为3D视图),以及使用ToElementIds()获取作为元素ID集合的过滤结果(本例中为删除一组元素)。
代码区域6-12:使用得到过滤器结果作为元素id
1 | FilteredElementCollector collector = new FilteredElementCollector(document); |
在下面的示例中使用了GetElementIterator()方法,该方法循环访问已筛选的元素以检查某些管道的流状态。
代码区域6-13:以元素迭代器的形式获取结果
1 | FilteredElementCollector collector = new FilteredElementCollector(document); |
或者,过滤结果可以作为元素id迭代器返回:
代码区域6-14:以元素id迭代器的形式获取结果
1 | // Use a RoomFilter to find all room elements in the document. |
在某些情况下,针对给定的过滤器测试单个元素,而不是获取通过过滤器的所有元素,可能会很有用。ElementFilter.PassesFilter()有两个重载,它们根据筛选器测试给定的Element或ElementId,如果元素通过筛选器,则返回true。
LINQ查询
在.NET中,FilteredElementCollector类支持Elements的IEEETM接口。您可以将此类与LINQ查询和操作一起使用来处理元素列表。请注意,由于此类提供的ElementFilters和快捷方法在生成托管包装之前处理本机代码中的元素,因此在尝试使用LINQ查询处理结果之前,在收集器上使用尽可能多的本机筛选器将获得更好的性能。
The following example uses an ElementClassFilter to get all FamilyInstance elements in the document, and then uses a LINQ query to narrow down the results to those FamilyInstances with a specific name.
下面的示例使用ElementClassFilter获取文档中的所有FamilyInstance元素,然后使用LINQ查询将结果范围缩小到具有特定名称的FamilyInstance。
代码区域6-15:使用LINQ查询
1 | // Use ElementClassFilter to find family instances whose name is 60" x 30" Student |
边界框过滤器
BoundingBox过滤器:
- BoundingBoxIsInsideFilter
- BoundingBoxIntersectsFilter
- BoundingBoxContainsPointFilter
帮助您查找其边界框满足特定条件的元素。您可以检查每个元素的边界框是否在给定体积内,是否与给定体积相交,或者是否包含给定点。也可以反向执行此检查,以查找不与体积相交或不包含给定点的元素。
BoundingBox过滤器使用Outline作为其输入。Outline是一个表示直角棱柱的类,其轴与Revit世界坐标系对齐。
这些过滤器最适合于实际几何形状与其边界框的几何形状紧密匹配的形状。示例可能包括曲线与X或Y方向对齐的线性墙、由此类墙形成的矩形房间、与此类墙对齐的楼板或屋顶,或者合理的矩形族。否则,可能会出现误报,因为元素的边界框可能比实际几何形状大得多。(在这些情况下,您可以使用实际图元的几何图形来确定图元是否真正满足条件)。
元素交叉过滤器
元素过滤器:
- ElementIntersectsElementFilter
- ElementIntersectsSolidFilter
其实际三维几何体与目标对象的三维几何体相交的过程元素。
使用ElementIntersectsElementFilter,目标对象是另一个元素。交点的确定与Revit在生成冲突报告期间确定是否存在冲突时使用的逻辑相同。(意味着某些图元组合永远不会通过此过滤器,例如在相交处自动连接的混凝土构件,或也从干涉检查中排除的场地图元)。此外,没有实心几何图形的图元(如钢筋)也不会通过此过滤器。
使用ElementIntersectsSolidFilter,目标对象是任何实体。该实体可以从现有图元中获得,使用GeometryCreationUtilities中的例程从头开始创建,或者是布尔运算等二次运算的结果。与ElementIntersectsElementFilter类似,此过滤器不会传递缺少实心几何图形的元素。
两个过滤器都可以反转以匹配目标对象体积之外的元素。
这两个过滤器都是慢速过滤器,因此最好与一个或多个快速过滤器(如类或类别过滤器)组合使用。
代码区域:使用ElementIntersectsSolidFilter匹配阻止禁用出口到门的元素
1 | /// |