为了在 BimRv SDK 中过滤和收集元素,开发人员可以使用 OdBmElementCollector 类来收集符合一组条件的元素。OdBmIterator 类也可以与谓词或过滤规则配合使用。
- OdBmElementCollector — 收集通过一组条件传递的数据库中的元素。定义在 Database/BmElementCollector.h 中。
常用方法:- OdBmElementCollector& wherePasses(const OdBmFilterRulePtr& pRule) — 将元素过滤器应用于收集器。
- OdBmElementPtrArray collect() const — 返回通过过滤器的元素集。
- OdBmElementCollector& ofCategory(OdBm::BuiltInCategory::Enum category) — 将 ElementCategoryFilter 应用于收集器。
- OdBmElementCollector& 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< T > 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 文档(需要登录)。