Filtering 过滤

Revit API提供了一种过滤和迭代Revit文档中图元的机制。这是获取一组相关元素(如文档中的所有墙或门)的最佳方法。过滤器也可以用来找到一个非常具体的元素集,如所有特定大小的梁。

获取通过指定过滤器的元素的基本步骤如下:

  1. 创建新的FilteredElementCollector
  2. 对它应用一个或多个过滤器
  3. 获取过滤后的元素或元素ID(使用以下几种方法之一)

下面的示例涵盖了在文档中筛选和迭代元素的基本步骤。

代码区域6-1:使用元素过滤获取文档中的所有墙实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Find all Wall instances in the document by using category filter
ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_Walls);

// Apply the filter to the elements in the active document
// Use shortcut WhereElementIsNotElementType() to find wall instances only
FilteredElementCollector collector = new FilteredElementCollector(document);
IList walls =
collector.WherePasses(filter).WhereElementIsNotElementType().ToElements();
String prompt = "The walls in the current document are:\n";
foreach (Element e in walls)
{
prompt += e.Name + "\n";
}
TaskDialog.Show("Revit", prompt);

Pages in this section 本节中的页面

  • 创建FilteredElementCollector
  • 应用过滤器
  • 获取筛选的元素或元素ID
  • LINQ查询
  • 边界框过滤器
  • 元素交叉过滤器

创建FilteredElementCollector

用于元素迭代和筛选的主类称为FilteredElementCollector。它以三种方式之一构建:

  1. 从文档-将搜索和筛选文档中的元素集
  2. 从一个文档和一组ElementId-将搜索和筛选一组指定的元素
  3. 从文档和视图-将搜索和过滤视图中的可见元素

注意:使用静态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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Use BoundingBoxIntersects filter to find elements with a bounding box that intersects the 
// given Outline in the document.

// Create a Outline, uses a minimum and maximum XYZ point to initialize the outline.
Outline myOutLn = new Outline(new XYZ(0, 0, 0), new XYZ(100, 100, 100));

// Create a BoundingBoxIntersects filter with this Outline
BoundingBoxIntersectsFilter filter = new BoundingBoxIntersectsFilter(myOutLn);

// Apply the filter to the elements in the active document
// This filter excludes all objects derived from View and objects derived from ElementType
FilteredElementCollector collector = new FilteredElementCollector(document);
IList elements = collector.WherePasses(filter).ToElements();

// Find all walls which don't intersect with BoundingBox: use an inverted filter
// to match elements
// Use shortcut command OfClass() to find walls only
BoundingBoxIntersectsFilter invertFilter = new BoundingBoxIntersectsFilter(myOutLn, true);
collector = new FilteredElementCollector(document);
IList notIntersectWalls = collector.OfClass(typeof(Wall)).WherePasses(invertFilter).ToElements();

下一个示例使用排除过滤器查找文档中当前未选定的所有墙。

代码区域6-3:创建排除过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Find all walls that are not currently selected, 
// Get all element ids which are current selected by users, exclude these ids when filtering
ICollection selectedIds = uiDocument.Selection.GetElementIds();

// Use the selection to instantiate an exclusion filter
ExclusionFilter filter = new ExclusionFilter(selectedIds);
// For the sake of simplicity we do not test here whether the selection is empty or not,
// but in production code a proper validation would have to be done to avoid an argument
// exception from the filter's consructor.

// Apply the filter to the elements in the active document,
// Use shortcut method OfClass() to find Walls only
FilteredElementCollector collector = new FilteredElementCollector(uiDocument.Document);
IList walls = collector.WherePasses(filter).OfClass(typeof(Wall)).ToElements();

注意:ElementClassFilter将匹配其类与输入类完全匹配的元素,或其类派生自输入类的元素。下面的示例使用ElementClassFilter获取文档中的所有加载。

代码区域6-4:使用ElementClassFilter获取负载

1
2
3
4
5
6
7
// Use ElementClassFilter to find all loads in the document
// Using typeof(LoadBase) will yield all AreaLoad, LineLoad and PointLoad
ElementClassFilter filter = new ElementClassFilter(typeof(LoadBase));

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
ICollection allLoads = collector.WherePasses(filter).ToElements();

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
2
3
4
5
6
7
8
// Use a RoomFilter to find all room elements in the document. It is necessary to use the 
// RoomFilter and not an ElementClassFilter or the shortcut method OfClass() because the Room
// class is not supported by those methods.
RoomFilter filter = new RoomFilter();

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
IList rooms = collector.WherePasses(filter).ToElements();

ElementParameterFilter是一个功能强大的过滤器,可以根据元素可能具有的参数值查找元素。它可以查找参数值与特定值匹配或大于或小于某个值的元素。ElementParameterFilter还可用于查找支持特定共享参数的元素。 下面的示例使用ElementParameterFilter查找大小超过100平方英尺的房间和小于100平方英尺的房间。

代码区域6-6:使用参数过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Creates an ElementParameter filter to find rooms whose area is 
// greater than specified value
// Create filter by provider and evaluator
BuiltInParameter areaParam = BuiltInParameter.ROOM_AREA;
// provider
ParameterValueProvider pvp = new ParameterValueProvider(new ElementId((int)areaParam));
// evaluator
FilterNumericRuleEvaluator fnrv = new FilterNumericGreater();
// rule value
double ruleValue = 100.0f; // filter room whose area is greater than 100 SF
// rule
FilterRule fRule = new FilterDoubleRule(pvp, fnrv, ruleValue, 1E-6);

// Create an ElementParameter filter
ElementParameterFilter filter = new ElementParameterFilter(fRule);

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
IList rooms = collector.WherePasses(filter).ToElements();

// Find rooms whose area is less than or equal to 100:
// Use inverted filter to match elements
ElementParameterFilter lessOrEqualFilter = new ElementParameterFilter(fRule, true);
collector = new FilteredElementCollector(document);
IList lessOrEqualFounds = collector.WherePasses(lessOrEqualFilter).ToElements();

下面的示例显示如何使用FamilyStructuralMaterialTypeFilter查找材质类型为木材的所有族。它还说明了如何使用反向过滤器来查找材质类型不是木材的所有族。

代码区域6-7:查找所有使用木质材料的家庭

1
2
3
4
5
6
7
8
9
10
11
12
// Use FamilyStructuralMaterialType filter to find families whose material type is Wood
FamilyStructuralMaterialTypeFilter filter = new FamilyStructuralMaterialTypeFilter(StructuralMaterialType.Wood);

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
ICollection woodFamiles = collector.WherePasses(filter).ToElements();

// Find families are not Wood: Use inverted filter to match families
FamilyStructuralMaterialTypeFilter notWoodFilter =
new FamilyStructuralMaterialTypeFilter(StructuralMaterialType.Wood, true);
collector = new FilteredElementCollector(document);
ICollection notWoodFamilies = collector.WherePasses(notWoodFilter).ToElements();

最后两个慢过滤器派生自ElementIntersectsFilter,后者是用于匹配与几何体相交的元素的过滤器的基类。有关此类过滤器的使用示例,请参见几何工具类一节中的代码区域:查找附近的墙。#逻辑过滤器逻辑过滤器联合收割机将两个或多个过滤器逻辑组合。下表总结了内置的逻辑筛选器。表15:内置逻辑过滤器

Built-in Filter 内置过滤器 What it passes 它所经过的 Shortcut Method(s) 快捷方法
LogicalAndFilter 通过2个或更多过滤器的元素 WherePasses()-添加一个额外的过滤器IntersectWith()-连接两组独立的过滤器
LogicalOrFilter 至少通过2个或多个过滤器之一的元素 UnionWith()-连接两组独立的过滤器

在下面的示例中,使用逻辑过滤器组合了两个快速过滤器,以获取文档中的所有door FamilyInstance元素。

代码区域6-8:使用LogicalAndFilter查找所有门实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Find all door instances in the project by finding all elements that both belong to the
// door category and are family instances.
ElementClassFilter familyInstanceFilter = new ElementClassFilter(typeof(FamilyInstance));

// Create a category filter for Doors
ElementCategoryFilter doorsCategoryfilter =
new ElementCategoryFilter(BuiltInCategory.OST_Doors);

// Create a logic And filter for all Door FamilyInstances
LogicalAndFilter doorInstancesFilter = new LogicalAndFilter(familyInstanceFilter,
doorsCategoryfilter);

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
IList doors = collector.WherePasses(doorInstancesFilter).ToElements();

获取筛选的元素或元素ID

将一个或多个过滤器应用于FilteredElementCollector后,可以通过以下三种方式之一来检索已过滤的元素集:

  1. 获取Elements或ElementId的集合。
    • ToElements()-返回通过所有应用的过滤器的所有元素
    • ToElementIds()-返回通过所有应用过滤器的所有元素的ElementIds
  2. 获取与筛选器匹配的第一个Element或ElementId。
    • FirstElement()-返回第一个元素以通过所有应用的过滤器
    • FirstElementId()-返回第一个元素的id,以通过所有应用的过滤器
  3. 获取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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Use ElementClassFilter to find all loads in the document
// Using typeof(LoadBase) will yield all AreaLoad, LineLoad and PointLoad
ElementClassFilter filter = new ElementClassFilter(typeof(LoadBase));

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.WherePasses(filter);
ICollection allLoads = collector.ToElements();

String prompt = "The loads in the current document are:\n";
foreach (Element loadElem in allLoads)
{
LoadBase load = loadElem as LoadBase;
prompt += load.GetType().Name + ": " +
load.Name + "\n";
}

TaskDialog.Show("Revit", prompt);

当只需要一个传递元素时,使用FirstElement():

代码区域6-10:获取第一个通过的元素

1
2
3
4
5
6
7
8
9
10
11
// Create a filter to find all columns
StructuralInstanceUsageFilter columnFilter =
new StructuralInstanceUsageFilter(StructuralInstanceUsage.Column);

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.WherePasses(columnFilter);

// Get the first column from the filtered results
// Element will be a FamilyInstance
FamilyInstance column = collector.FirstElement() as FamilyInstance;

在某些情况下,FirstElement()是不够的。下一个示例显示如何使用扩展方法获取第一个非模板3D视图(这对于ReferenceIntersector构造函数的输入很有用)。

代码区域6-11:使用扩展方法获取第一个传递元素

1
2
3
4
5
6
7
8
9
10
// Use filter to find a non-template 3D view
// This example does not use FirstElement() since first filterd view3D might be a template
FilteredElementCollector collector = new FilteredElementCollector(document);
Func<View3D, bool> isNotTemplate = v3 => !(v3.IsTemplate);

// apply ElementClassFilter
collector.OfClass(typeof(View3D));

// use extension methods to get first non-template View3D
View3D view3D = collector.Cast().First(isNotTemplate);

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FilteredElementCollector collector = new FilteredElementCollector(document);

// Use shortcut OfClass to get View elements
collector.OfClass(typeof(View3D));

// Get the Id of the first view
ElementId viewId = collector.FirstElementId();

// Test if the view is valid for element filtering
if (FilteredElementCollector.IsViewValidForElementIteration(document, viewId))
{
FilteredElementCollector viewCollector = new FilteredElementCollector(document, viewId);

// Get all FamilyInstance items in the view
viewCollector.OfClass(typeof(FamilyInstance));
ICollection familyInstanceIds = viewCollector.ToElementIds();

document.Delete(familyInstanceIds);
}

在下面的示例中使用了GetElementIterator()方法,该方法循环访问已筛选的元素以检查某些管道的流状态。

代码区域6-13:以元素迭代器的形式获取结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FilteredElementCollector collector = new FilteredElementCollector(document);

// Apply a filter to get all pipes in the document
collector.OfClass(typeof(Autodesk.Revit.DB.Plumbing.Pipe));

// Get results as an element iterator and look for a pipe with
// a specific flow state
FilteredElementIterator elemItr = collector.GetElementIterator();
elemItr.Reset();
while (elemItr.MoveNext())
{
Pipe pipe = elemItr.Current as Pipe;
if (pipe.FlowState == PipeFlowState.LaminarState)
{
TaskDialog.Show("Revit", "Model has at least one pipe with Laminar flow state.");
break;
}
}

或者,过滤结果可以作为元素id迭代器返回:

代码区域6-14:以元素id迭代器的形式获取结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Use a RoomFilter to find all room elements in the document. 
RoomFilter filter = new RoomFilter();

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.WherePasses(filter);

// Get results as ElementId iterator
FilteredElementIdIterator roomIdItr = collector.GetElementIdIterator();
roomIdItr.Reset();
while (roomIdItr.MoveNext())
{
ElementId roomId = roomIdItr.Current;
// Warn rooms smaller than 50 SF
Room room = document.GetElement(roomId) as Room;
if (room.Area < 50.0)
{
String prompt = "Room is too small: id = " + roomId.ToString();
TaskDialog.Show("Revit", prompt);
break;
}
}

在某些情况下,针对给定的过滤器测试单个元素,而不是获取通过过滤器的所有元素,可能会很有用。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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Use ElementClassFilter to find family instances whose name is 60" x 30" Student 
ElementClassFilter filter = new ElementClassFilter(typeof(FamilyInstance));

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.WherePasses(filter);

// Use Linq query to find family instances whose name is 60" x 30" Student
var query = from element in collector
where element.Name == "60\" x 30\" Student"
select element;

// Cast found elements to family instances,
// this cast to FamilyInstance is safe because ElementClassFilter for FamilyInstance was used
List familyInstances = query.Cast().ToList();

边界框过滤器

BoundingBox过滤器:

  • BoundingBoxIsInsideFilter
  • BoundingBoxIntersectsFilter
  • BoundingBoxContainsPointFilter

帮助您查找其边界框满足特定条件的元素。您可以检查每个元素的边界框是否在给定体积内,是否与给定体积相交,或者是否包含给定点。也可以反向执行此检查,以查找不与体积相交或不包含给定点的元素。

BoundingBox过滤器使用Outline作为其输入。Outline是一个表示直角棱柱的类,其轴与Revit世界坐标系对齐。

这些过滤器最适合于实际几何形状与其边界框的几何形状紧密匹配的形状。示例可能包括曲线与X或Y方向对齐的线性墙、由此类墙形成的矩形房间、与此类墙对齐的楼板或屋顶,或者合理的矩形族。否则,可能会出现误报,因为元素的边界框可能比实际几何形状大得多。(在这些情况下,您可以使用实际图元的几何图形来确定图元是否真正满足条件)。

元素交叉过滤器

元素过滤器:

  • ElementIntersectsElementFilter
  • ElementIntersectsSolidFilter

其实际三维几何体与目标对象的三维几何体相交的过程元素。

使用ElementIntersectsElementFilter,目标对象是另一个元素。交点的确定与Revit在生成冲突报告期间确定是否存在冲突时使用的逻辑相同。(意味着某些图元组合永远不会通过此过滤器,例如在相交处自动连接的混凝土构件,或也从干涉检查中排除的场地图元)。此外,没有实心几何图形的图元(如钢筋)也不会通过此过滤器。

使用ElementIntersectsSolidFilter,目标对象是任何实体。该实体可以从现有图元中获得,使用GeometryCreationUtilities中的例程从头开始创建,或者是布尔运算等二次运算的结果。与ElementIntersectsElementFilter类似,此过滤器不会传递缺少实心几何图形的元素。

两个过滤器都可以反转以匹配目标对象体积之外的元素。

这两个过滤器都是慢速过滤器,因此最好与一个或多个快速过滤器(如类或类别过滤器)组合使用。

代码区域:使用ElementIntersectsSolidFilter匹配阻止禁用出口到门的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/// 
/// Finds any Revit physical elements which interfere with the target
/// solid region surrounding a door.
/// This routine is useful for detecting interferences which are
/// violations of the Americans with Disabilities Act or other local disabled
/// access codes.
/// The door instance.
/// The accessibility region calculated
/// to surround the approach of the door.
/// Because the geometric parameters of this region are code- and
/// door-specific, calculation of the geometry of the region is not
/// demonstrated in this example.
/// A collection of interfering element ids.
private ICollection FindElementsInterferingWithDoor(FamilyInstance doorInstance, Solid doorAccessibilityRegion)
{
// Setup the filtered element collector for all document elements.
FilteredElementCollector interferingCollector =
new FilteredElementCollector(doorInstance.Document);

// Only accept element instances
interferingCollector.WhereElementIsNotElementType();

// Exclude intersections with the door itself or the host wall for the door.
List excludedElements = new List();
excludedElements.Add(doorInstance.Id);
excludedElements.Add(doorInstance.Host.Id);
ExclusionFilter exclusionFilter = new ExclusionFilter(excludedElements);
interferingCollector.WherePasses(exclusionFilter);

// Set up a filter which matches elements whose solid geometry intersects
// with the accessibility region
ElementIntersectsSolidFilter intersectionFilter =
new ElementIntersectsSolidFilter(doorAccessibilityRegion);
interferingCollector.WherePasses(intersectionFilter);

// Return all elements passing the collector
return interferingCollector.ToElementIds();
}

注:翻译自Revit API Developers Guide