13. Revit API: Filter(过滤器)
前言
在讲Selection
之前,还是有必要先了解一下的过滤器的。
对了,关于查找一些比较偏的功能或者API的用法,可以这样查找
关键词 site:https://thebuildingcoder.typepad.com/
site
是高级搜索指令,表示从目标网址查找,不同的浏览器都有各自的指令,但部分是通用的。
网站thebuildingcoder
里有许多关于Revit的有用的信息。
回到主题,这篇来讲一讲Filter
。
一、Filter是什么
如其意,Filter
就是过滤器,用来过滤/查找我们需要的元素,满足条件的留下,就和用筛子筛豆子一样。当然我们可以遍历检索,但效率低。为了解决效率问题,Revit内置了一些Filter,我们可以直接使用。
在Revit中,Filter相关的类,可以划分为3块
- 收集器(
Collector
),用来执行过滤器,返回过滤结果,且内部封装有过滤器的简单调用方法。 - 过滤器(
xxFilter
),具体的过滤器,按特定的规则进行过滤。 - 过滤规则(
FilterRule
),一些规则,可以有限的影响过滤操作。
下面分别对这3块内容进行讲解。
更具体的类图如下。FilteredWorksetCollector
此篇不涉及,我目前还不知道Workset
是个什么东西。
二、ElementFilter
先看ElementFilter
,它是一众过滤器的基类,并直接派生出3种过滤器。
按照其功能或特性,分别为
- ElementLogicalFilter:逻辑过滤器,用来对多种过滤器进行组合
- ElementQuickFilter:快过滤器,采用一个叫
ElementRecord
的低内存类进行检索,相当于一个包含少量的必要的信息的记录/映射。 - ElementSlowFilter:慢过滤器,慢是相对于快过滤器的,作用于已展开的Element上,也就是读的信息更多,可以执行更细致的过滤。在使用时,通常会先使用快过滤器缩小范围,以提高效率。
先看看基类ElementFilter吧。
类成员 | 描述 |
---|---|
Inverted { get; } | 表示是否反转过滤,True则改为保留不满足条件的。 反转过滤需要在构造函数上传参确定。 |
PassesFilter(..) | 验证给定元素是否可以通过验证 |
2.1. ElementLogicalFilter(逻辑过滤器)
逻辑过滤器(ElementLogicalFilter
)是用来组合一系列具体的过滤器的。
它本身未公开构造函数,只能通过其派生出的2个子类来构建。
子类名称很直观:
- 逻辑与(
LogicalAndFilter
):完成全部过滤器验证,才能保留下来 - 逻辑或(
LogicalOrFilter
):完成任意过滤器验证,就可以保留下来
下面的例子,使用了类型过滤器检测地板类型,和类过滤器检测Wall类。并使用收集器执行与结果输出。
private List<ElementId> TestLogicalFilter(Document document)
{// 1.collectorFilteredElementCollector collector = new FilteredElementCollector(document);// 2.FilterElementCategoryFilter categoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_Floors);ElementClassFilter classFilter = new ElementClassFilter(typeof(Wall));// logical ANDLogicalAndFilter logicalAndFilter = new LogicalAndFilter(categoryFilter, classFilter);// logical ORLogicalOrFilter logicalOrFilter = new LogicalOrFilter(categoryFilter, categoryFilter);// 3.wherePassescollector.WherePasses(logicalAndFilter);//collector.WherePasses(logicalOrFilter);// 4.collectreturn collector.ToElementIds().ToList();
}
3.2. ElementQuickFilter(快过滤器)
快过滤器(ElementQuickFilter
)由于只拿到Element的一点点信息,所以其子类的过滤规则都比较简单。
都过滤些什么呢?类、类型、包围盒之类的基本是。具体就不列了,看上面的图片,或者翻看文档都可以。
有几个特别的,简单提一下。
ElementMulti...Filter
:一次塞入多个类/类型ExclusionFilter
:排除过滤器,比如进行“查找所有未选中的墙体”这个操作。ExtensibleStorageFilter
:扩展存储过滤器,如果用了扩展存储,那这个就很有用。
至于使用上,就按照上面的示例代码那样:
- 创一个收集器
- New一些过滤器
- 让收集器
WherePasses
过滤器 - 从收集器上拿到元素(ID)集合。
对于包围盒过滤器存在的问题,看Revit获取元素Solid和计算包围盒。
简单来说就是Element.BoundingBox的问题,它会将非几何结构也计入到元素范围中,这当然是合理的,但是“反直觉”。
3.3. ElementSlowFilter(慢过滤器)
慢过滤器(ElementSlowFilter
)检索了更多的元素信息,相较于快过滤器慢一些,相对的,慢过滤器上的规则就更多样。
同样的,不一一列出各个过滤器。比较常用的,就FamilyInstanceFilter
吧。
还有一个最特殊的,元素参数过滤器(ElementParameterFilter
),因为这是唯一用到FilterRule
的过滤器了。这在后面过滤器规则那段一起讲。
三、FilteredElementCollector
看到这儿,我们已经对收集器(FilteredElementCollector
)有所了解。
先创建收集器,再创建过滤器,然后进行运用,最后拿到结果。
流程很丝滑,但不够简洁。对此,收集器本身封装了常用过滤器的创建方法,并可采用链式结构调用,这样就极大的简化了过滤操作。
同样的,对于上面的代码示例,我们可以这样进行简写。
FilteredElementCollector collector = new FilteredElementCollector(document);
var ids = collector.OfCategory(BuiltInCategory.OST_Floors).OfClass(typeof(Wall)).ToElementIds().ToList();
通过这种方式,就能将一些单条件的过滤器快速运用到收集器上。
构造函数:
Constructors | Description |
---|---|
FilteredElementCollector(Document) | 目标元素为整个文档 |
FilteredElementCollector(Document, ViewId) | 目标元素为指定视图种可见的元素 |
FilteredElementCollector(Document, List) | 目标元素为传入的元素 |
方法:
Methods | Description |
---|---|
ToElementIds ToElements | 获取过滤后的元素ID集合 获取过滤后的元素集合 |
WherePasses | 应用过滤器 |
UnionWith | 和另一个收集器的结果合并 |
OfClass OfCategory(/Id) | 应用类过滤器(ElementClassFilter) 应用类型过滤器(ElementCategoryFilter) |
OwnedByView | 应用当前视图过滤器(ElementOwnerViewFilter) |
Excluding | 应用排除过滤器(ExclusionFilter) |
WhereElementIsCurveDriven WhereElementIs(/Not)ElementType WhereElementIsViewIndependent | 应用曲线驱动验证过滤器(ElementIsCurveDrivenFilter) 应用元素验证过滤器(ElementIsElementTypeFilter) 应用(ElementOwnerViewFilter) |
ContainedInDesignOption | 应用(ElementDesignOptionFilter) |
四、FilterRule
过滤规则(FilterRule
)允许开发者自定义一些过滤条件。
前面也说了,元素参数过滤器(ElementParameterFilter
)是唯一和FilterRule够上的过滤器,它是一个慢过滤器,毕竟涉及到元素的参数信息了,它的构造函数要求传入FilterRule。
但元素参数过滤器并不是RevitAPI种唯一使用过滤规则的类,还有一个非常有迷惑性的类,叫ParameterFilterElement
(参数过滤器元素)。
ParameterFilterElement:一个类似Collector的东西,里面封装了并提供了一些过滤规则相关的方法。
4.1. FilterRule的派生类
看下图(最上方大图的一部分)
- FilterCategoryRule:定义类型过滤规则,相当于一个慢速的类型过滤器
- FilterInverseRule:定义反转过滤规则,效果用反转过滤器
- FilterValueRule:定义值过滤规则。
- SharedParameterApplicableRule:定义共享参数过滤规则
这里有个叫FilterCategoryRule
的规则,效果上完全就是一个慢速版的类型过滤器。
关于这部分运用,主要是在 值过滤规则 上,我们来看看。
4.2. FilterValueRule(值过滤规则)
要定义值过滤规则,需要有两个东西:
- 值的来源(
ParameterValueProvider
) - 值的验证比较方式(
RuleEvaluator
)
4.2.1. ParameterValueProvider(值提供者)
我们先来看看值的获取。
好吧,看文档有点迷惑,直接看例子:
// 获取元素的“面积”参数
ElementId areaParamId = new ElementId(BuiltInParameter.HOST_AREA_COMPUTED);
ParameterValueProvider doubleValueProvider = new ParameterValueProvider(areaParamId);
4.2.2. RuleEvaluator(验证器)
不同类型的值,有不同的比较方式。
a) 字符串:FilterStringRuleEvaluator
- FilterStringBeginsWith:开始于
- FilterStringEndsWith:结束于
- FilterStringContains:包含
- FilterStringGreater(/OrEqual):排序在后(或等于)
- FilterStringLess(/OrEqual):排序在前(或等于)
b) 数字:FilterNumericRuleEvaluator
- FilterNumericEquals:等于
- FilterNumericGreater(/OrEqual):大于(或等于)
- FilterNumericLess(/OrEqual):小于(或等于)
4.2.3. 代码示例
结合一个代码示例来看看吧。
以下代码:检索结构用途为“非承重”、面积大于等于1000平方英尺的墙体。
private List<ElementId> TestParameterFilter(Document document)
{// 1. collectorFilteredElementCollector collector = new FilteredElementCollector(document);// 2. rule// 2.1. category ruleFilterCategoryRule filterCategoryRule = new FilterCategoryRule([new ElementId(BuiltInCategory.OST_Walls)]); // 墙// 2.2. value rule => stringParameterValueProvider stringValueProvider = new ParameterValueProvider(new ElementId(BuiltInParameter.WALL_STRUCTURAL_USAGE_PARAM)); // 结构用途FilterStringRuleEvaluator stringEvaluator = new FilterStringEquals(); // 等于FilterStringRule stringRule = new FilterStringRule(stringValueProvider, stringEvaluator, "非承重", false);// 2.3. value rule => number => doubleElementId areaParamId = new ElementId(BuiltInParameter.HOST_AREA_COMPUTED);ParameterValueProvider doubleValueProvider = new ParameterValueProvider(areaParamId); FilterNumericRuleEvaluator doubleEvaluator = new FilterNumericGreaterOrEqual(); // 大于等于FilterDoubleRule doubleRule = new FilterDoubleRule(doubleValueProvider, doubleEvaluator, 1000, 10e-3);// 3. filterElementParameterFilter elementParameterFilter = new ElementParameterFilter([filterCategoryRule, stringRule, doubleRule]);// 4. resultreturn collector.WherePasses(elementParameterFilter).ToElementIds().ToList();
}
使用Revit自带的项目“Technical_school-current_m.rvt
”进行验证。
将上面检索到的墙体放入选择列表中,效果如下图:
总结
这篇讲解了过滤器相关的API以及使用方法,我觉得还是比较全面的😺。
这篇又提到了哪些本篇范围外的呢,参数(Parameter
),平方英尺/单位(Unit
),放入选择列表(Selection
)。
下一篇,就写Selection
命名空间下的那几个了。