[返回博客](/cn/blog) # BimRv SDK：使用过滤规则收集元素

Evgeniy Tikhonov 一月 09, 2020 [\#rfa](/cn/blog/tag/rfa) [\#rvt](/cn/blog/tag/rvt) [\#filter](/cn/blog/tag/filter)

<a class="a2a_button_facebook"></a><a class="a2a_button_twitter"></a><a class="a2a_button_linkedin"></a>

为了在 BimRv SDK 中过滤和收集元素，开发人员可以使用 OdBmElementCollector 类来收集符合一组条件的元素。OdBmIterator 类也可以与谓词或过滤规则配合使用。

- OdBmElementCollector — 收集通过一组条件传递的数据库中的元素。定义在 Database/BmElementCollector.h 中。  
     常用方法：
    - OdBmElementCollector&amp; wherePasses(const OdBmFilterRulePtr&amp; pRule) — 将元素过滤器应用于收集器。
    - OdBmElementPtrArray collect() const — 返回通过过滤器的元素集。
    - OdBmElementCollector&amp; ofCategory(OdBm::BuiltInCategory::Enum category) — 将 ElementCategoryFilter 应用于收集器。
    - OdBmElementCollector&amp; ofClass(const OdTfClass\* pClass) — 将 ElementClassFilter 应用于收集器。
    - OdBmElementCollector::iterator\_type getElementIterator() const — 返回收集到的元素的元素迭代器 (OdBmElementIterator)。
- OdBmIterator — 一个类模板，定义了类型 T 对象的迭代器。定义在 Common/BmIterator.h 中。迭代器的常用方法：
    - T object() — 返回迭代器指向的对象。
    - bool done() — 如果没有更多对象可迭代，则返回 true。
    - bool next() — 返回数组中的下一个元素。
    - OdBmIterator::pointer\_type clone() — 返回迭代器的克隆。
    - OdArray&lt; T &gt; collect() — 返回迭代对象的数组。
    - OdBmIterator::pointer\_type filter() — 创建迭代器的克隆，并将过滤条件应用于克隆中的每个对象。
- OdBmElementIterator — 此迭代器用于迭代数据库中的元素。定义在 Database/Entities/BmElemTable.h 中。
- OdBmElemTableIterator — OdBmElementIterator 的公共派生类。定义在 Database/Entities/BmElemTable.h 中。

要创建 OdBmElemTableIterator，请使用 OdBmDatabase::newElemTableIterator() 方法。

OdBmElementCollector 和 OdBmIterator 类之间的主要区别在于，OdBmIterator 在设计上是无状态的，并且 collect() 方法会结束迭代器（请参阅下面的示例）。OdBmElementCollector 会保留其数据。

要多次使用迭代器，只需在调用 collect() 或 next() 方法之前克隆它：

```
OdBmElementIteratorPtr pElementsIt = pDb->newElemTableIterator()->filter(pCategoryRule);
OdBmElementIteratorPtr pElementsItClone = pElementsIt->clone();
```

下一个示例演示了在数据库中迭代和过滤元素的过程。

示例文件包含七条风管曲线，但其中只有一条在注释中包含“foo”。

要为元素类别构建过滤规则：

```
OdBmDatabasePtr pDb = app->readFile(L"sample_file.rvt");
// Create filter rule based on OST_DuctCurves category
OdBmFilterCategoryRulePtr pCategoryRule = OdBmFilterCategoryRule::createObject();
pCategoryRule->addCategory(pDb->getObjectId(OdBm::BuiltInCategory::OST_DuctCurves, true));
// Collect elements using category rule
{
  // Create new ElemTable iterator and call filter method to get iterator of Elements that pass the filter rule
  OdBmElementIteratorPtr pElementsIt = pDb->newElemTableIterator()->filter(pCategoryRule);
  // Collect filtered elements into array
  OdBmElementPtrArray elements = pElementsIt->collect();
  // Please notice that the elements1 array will be empty, because iterator is stateless by design
  OdBmElementPtrArray elements1 = pElementsIt->collect();
}
```

要为元素的注释属性构建字符串规则：

```
// Create Parameter value provider
OdBmParameterValueProviderPtr pParamEvalProvider = OdBmParameterValueProvider::createObject();
// Set flags and properties
pParamEvalProvider->setElemOrSymbol(1);
pParamEvalProvider->setParameter(OdBmParameterId(pDb->getObjectId(OdBm::BuiltInParameter::ALL_MODEL_INSTANCE_COMMENTS, true)));
// Create string rule with Equal evaluator
OdBmFilterStringRulePtr pStringRule = OdBmFilterStringRule::createObject();
pStringRule->setValueProvider(pParamEvalProvider);
OdBmFilterStringEqualsPtr pEvaluator = OdBmFilterStringEquals::createObject();
pStringRule->setEvaluator(pEvaluator);
pStringRule->setRuleString(L"foo");
```

要使用类别和字符串规则过滤元素：

```
OdBmElementIteratorPtr pElementsIt = pDb->newElemTableIterator()->filter(pCategoryRule)->filter(pStringRule);
OdBmElementPtrArray elements = pElementsIt->collect();
```

要使用 OdBmElementCollector 收集元素：

```
OdBmDatabasePtr pDb_ = app->readFile(L"rooms.rvt");

// Create a filter rule for anything with ROOM_NAME that isn't "CLOSET"
OdBmParameterValueProviderPtr pParamEvalProvider = OdBmParameterValueProvider::createObject();
pParamEvalProvider->setElemOrSymbol(1);
pParamEvalProvider->setParameter(OdBmParameterId(pDb_->getObjectId(OdBm::BuiltInParameter::ROOM_NAME, true)));
OdBmFilterStringRuleEvaluatorPtr pEvaluator = OdBmFilterStringEquals::createObject();
OdBmFilterStringRulePtr pStringRule = OdBmFilterStringRule::createObject();
pStringRule->setValueProvider(pParamEvalProvider);
pStringRule->setEvaluator(pEvaluator);
pStringRule->setRuleString("CLOSET");
OdBmFilterInverseRulePtr pInverter = OdBmFilterInverseRule::createObject();
pInverter->setInnerRule(pStringRule);

// Get elements without a ROOM_NAME of "CLOSET"
OdBmElementCollector pFilterTest5 = OdBmElementCollector(pDb_).wherePasses(pInverter);
OdBmElementPtrArray arr5 = pFilterTest5.collect();

// Create a rule to filter out all rooms
OdBmFilterCategoryRulePtr pCategoryRule = OdBmFilterCategoryRule::createObject();
pCategoryRule->addCategory(pDb_->getObjectId(OdBm::BuiltInCategory::OST_Rooms, true));

// Get only rooms without a ROOM_NAME of "CLOSET"
OdBmElementCollector pFilterTest6 = pFilterTest5.wherePasses(pCategoryRule);

// Do the same by combining calls of wherePasses()
OdBmElementCollector pFilterTest7 = OdBmElementCollector(pDb_).wherePasses(pInverter).wherePasses(pCategoryRule);

// Get all elements of OdBm::BuiltInCategory::OST_Rooms category
OdBmElementCollector pFilterTest8 = OdBmElementCollector(pDb_).ofCategory(OdBm::BuiltInCategory::OST_Rooms);

// Get all elements of OdBmRoomElem class
OdBmElementCollector pFilterTest9 = OdBmElementCollector(pDb_).ofClass(OdBmRoomElem::desc());
```

#### 使用 OdBmIterator 和谓词收集元素

您还可以将谓词与迭代器配合使用，例如：

```
struct c_elemHandle : std::unary_function<OdBmElementPtr, bool> {
  c_elemHandle(OdBm::BuiltInCategory::Enum category) 
    : m_hndl(OdDbHandle(category)) {}
  bool operator()(const OdBmElementPtr& pObj) const {
    return m_hndl == pObj->getCategroryId().getHandle();
  }
private:
  OdDbHandle m_hndl;
};

OdBmElementIteratorPtr pElementsIt = 
pDb->newElemTableIterator()->filter(c_elemHandle(OdBm::BuiltInCategory::OST_Rooms));
```

有关类和方法（包括用于创建过滤规则的评估器）的更多详细信息，请参阅 [BimRv 文档](https://docs.opendesign.com/tbim/)（需要登录）。

## 今天就开始行动

**免费试用 ODA 软件 60 天。  
无风险，无需信用卡。**

[免费试用](https://www.opendesign.com/cn/free-trial)
