[返回博客](/cn/blog) # 熟悉视图中的元素过滤

Artur Vakhramov 十月 25, 2018 [\#rvt](/cn/blog/tag/rvt) [\#rfa](/cn/blog/tag/rfa) [\#Example](/cn/blog/tag/example)

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

#### 引言

我们发现视图不包含所有图形元素的特殊列表。在渲染过程中，会根据规则从公共数据库中选择必要的元素。本文将阐述基本规则，展示如何开始构建自定义图形查看器。

启动视图

我们发现文件打开会启动对要渲染的视图的搜索。这是通过 DBDrawingInfo 管理器完成的，该管理器包含 DBDrawing 元素列表和指向活动 DBDrawing 元素的指针。下面是 DBDrawingInfo 管理器的转储：

OdBmDBDrawingInfoPtr Item\[6\]: . . . . . . . address is not Null  
RxObjectWeakPtr ADocument . . . . . . . . 52  
VariantArray DBDrawingsIndex. . . . . . . Size: 6  
Handle Item\[0\]. . . . . . . . . . . . . 1109  
Handle Item\[1\]. . . . . . . . . . . . . 1499  
Handle Item\[2\]. . . . . . . . . . . . . 1509  
Handle Item\[3\]. . . . . . . . . . . . . 1518  
Handle Item\[4\]. . . . . . . . . . . . . 1892  
Handle Item\[5\]. . . . . . . . . . . . . 2320  
VariantArray OpenWindowStates . . . . . . Size: 1  
OdBmWindowStatePtr Item\[0\]: . . . . . . address is not Null  
GePoint3d ProjLeftBottom. . . . . . . \[-1.1; -0.5; 0.0\]  
GePoint3d ProjRightTop. . . . . . . . \[0.9; 0.3; 0.0\]  
Handle DBDrawingId. . . . . . . . . . 2320  
int ShowState . . . . . . . . . . . . 2  
int ScreenWidth . . . . . . . . . . . 1676  
int ScreenHeight. . . . . . . . . . . 718  
int ScreenLeft. . . . . . . . . . . . -6  
int ScreenRight . . . . . . . . . . . -6  
int ScreenTop . . . . . . . . . . . . -25  
int ScreenBottom. . . . . . . . . . . -6  
int HorizontalRes . . . . . . . . . . . . 1920  
int VerticalRes . . . . . . . . . . . . . 952

此管理器包含一个 ID 数组——DBDrawingIndex，用于所有可用的 DBDrawing 元素。它还包含带有活动 DBDrawing 元素的启动窗口设置。如果未设置启动窗口设置，则使用第一个 DBDrawing 元素。

代码示例，演示如何获取活动的 DBDrawing：

```
OdBmDBDrawingInfoPtr pDBDrawingInfo = pDatabase->getAppInfo(OdBm::ManagerType::DBDrawingInfo);
OdBmDBDrawingPtr pDBDrawing = pDBDrawingInfo->getActiveDBDrawingId().safeOpenObject();

```

我们还可以获取有关主视口和主视图的信息：

```
OdBmViewportPtr pBaseViewport = pDBDrawing->getBaseViewportId().safeOpenObject();
OdBmDBViewPtr pView = pBaseViewport->getDbViewId().safeOpenObject();

```

因此，我们获取用于渲染的起始视图。您可以使用 DBDrawingInfo 管理器中提供的有关 DBDrawing 元素的信息，以相同的方式获取任何其他视图。

注意：有关获取活动视图的信息可在此处找到 [https://docs.opendesign.com/tbim/tbim\_views.html](https://docs.opendesign.com/tbim/tbim_views.html)

#### 视图元素选择

每个视图都可以提供可用于渲染的元素列表。可以使用以下函数来完成此操作：

```
/** \details
Returns the list of the annotated elements of the view.
		
\param  arr [out] Output list of drawable elements.
*/
void getFrontDrawableElements(OdBmObjectIdArray& arr);

/** \details
Returns the list of the non-annotated of the view.
		
\param  arr [out] Output list of drawable elements.
*/
void getDrawableElements(OdBmObjectIdArray& arr);

```

这些函数执行：

- 根据文件类型（.rvt/.rfa）选择可用于渲染的元素；
- 从元素头中选择信息；
- 将元素分为两组：在前面渲染的元素和“普通”元素。

#### 元素过滤

如果元素可用于渲染，这并不意味着它必须强制渲染。元素可能有自己的自定义渲染规则，应予以考虑。

unplacedOwnerId 是禁止元素渲染的规则之一：

```
if (! pElement->getUnplacedOwnerId().isNull() ) {/*skip vectorization*/}

```

此外，每个视图都有自己的一套规则和过滤器，在渲染时需要考虑。

#### 设计过滤

每个视图元素都可能属于特定的设计（element-&gt;getDesignOptionId()）。以下是针对一个设计“主模型”的元素渲染实现示例

```
bool OdBmDBViewImpl::isElementDesignOptionVisible(const OdBmObjectId& designOptionId) const
{
  if (!designOptionId.isValid() ||
    !OdBmObjectId::isRegularHandle(designOptionId.getHandle())) { // element is from Main model, so it is always visible
    return true;
  }
  
  const OdBmDesignOptionPtr pElementDesignOption = designOptionId.safeOpenObject();
  const OdBmDesignOptionViewSettingsPtr& pDOVS = getDesignOptionViewSettings();
  
  if (!pElementDesignOption.isNull() && !pDOVS.isNull()) {

    const OdBmObjectId elementDesignOptionSetId = pElementDesignOption->getDesignOptionSetId();
  
    OdBmMap<OdBmObjectId, OdBmObjectId> mapSettingsOptions;
    pDOVS->getOverridingOptions2(mapSettingsOptions);
  
    OdBmMap<OdBmObjectId, OdBmObjectId>::const_iterator it = mapSettingsOptions.find(elementDesignOptionSetId);
    if (it != mapSettingsOptions.end()) {
      if (designOptionId != it->second) {
        return false;
      }
    }
    else {
      const OdBmDesignOptionSetPtr pElementDesignOptionSet = elementDesignOptionSetId.safeOpenObject();
      if (pElementDesignOptionSet->getMainDesignOption() != designOptionId) {
        return false;
      }
    }
  }

  return true;
}

```

#### 类别过滤

每个元素都可以有一个类别（element-&gt;getCategroryId()）。可以使用类别作为过滤选项。以下是类别过滤的示例：

```
bool OdBmDBViewImpl::isElementCategoryVisible(const OdBmObjectId& categoryId) const
{
  if (categoryId.isNull())
    return true;

  // check IckyExcludedCategoriesSetPtrWrapper
  OdBmObjectIdArray aExcludedCategoryIds;
  const OdBmDrawFilterPtrArray& aDrawFilters = getDrawFilters();
  OdBmDrawFilterPtrArray::const_iterator itEnd = aDrawFilters.end();
  for (OdBmDrawFilterPtrArray::const_iterator it = aDrawFilters.begin(); it != itEnd; ++it)
  {
    if ((*it)->isA() == OdBmIckyExcludedCategoriesSetPtrWrapper::desc())
    {
      OdBmIckyExcludedCategoriesSetPtrWrapperPtr pExclSet = *it;

      // check excluded categories
      pExclSet->getCategoryIds(aExcludedCategoryIds);
      if (aExcludedCategoryIds.contains(categoryId))
        return false;

      // get category data
      const OdBmCategoryElemPtr pCategoryElem = categoryId.safeOpenObject();
      const OdBmCategoryPtr category = pCategoryElem->getCategory();

      OdInt32 categoryType(OdBm::CategoryType::Invalid);
      OdBmObjectId::handle_type parentId;

      if (category.get()) {
        categoryType = category->getCategoryType();
        parentId = category->getParentCategoryId();
      }

      // check excluded category types
      switch (categoryType) {
        //case OdBm::CategoryType::Invalid:
        //  // do nothing
        //  break;
      case OdBm::CategoryType::Model:
        if (pExclSet->getModelsExcluded()) return false;
        break;
      case OdBm::CategoryType::Annotation:
        if (pExclSet->getAnnotationsExcluded()) return false;
        break;
        //case OdBm::CategoryType::Internal:
        //  // do nothing
        //  break;
      case OdBm::CategoryType::AnalyticalModel:
        if (pExclSet->getAnalyticalModelsExcluded()) return false;
        break;
      }

      //TODO if (pExclSet->getMassShellExcluded()) {} //do smth
      //TODO if (pExclSet->getImportsExcluded()) {} // do smth

      // check excluded parent categories
      if (parentId != OdBmObjectId::kNullHandle)
      {
        for (OdBmObjectIdArray::const_iterator it = aExcludedCategoryIds.begin();
          it != aExcludedCategoryIds.end(); ++it) {
          if ((*it).getHandle() == parentId)
            return false;
        }
      }

      break;
    } // if ((*it)->isA() == OdBmIckyExcludedCategoriesSetPtrWrapper::desc())
  } // for (OdBmObjectPtrArray::const_iterator it = m_DrawFilters.begin(); it != m_DrawFilters.end(); ++it)

  return true;
}

```

请注意，在上面的示例中，类别过滤选项是从所需视图中获取的。类别类型和父类别也一并考虑。

#### 元素过滤

视图可以有一个隐藏的元素列表。以下是基于隐藏元素列表的元素过滤示例：

```
// check element filter
{
  OdBmObjectIdArray aExcludedElementIds;
  const OdBmHiddenElementsViewSettingsPtr& pHiddenElemSettings = getHiddenElementsViewSettings();
  pHiddenElemSettings->getHiddenElements(aExcludedElementIds);

  if (aExcludedElementIds.contains(element->objectId()))
    return false;
}

```

#### 元素参数过滤

视图可以有一个隐藏的元素参数列表。以下是基于隐藏元素参数的过滤示例：

```
// check element parameter filter
{
  OdBmObjectPtrArray aParameterFilters;
  const OdBmFilterOverridesPtr& pFilterOverrides = getFilterOverrides();
  OdBmObjectPtrArray aFilterSettings;
  pFilterOverrides->getSettings(aFilterSettings);
  OdBmObjectPtrArray::const_iterator itFSEnd = aFilterSettings.end();
  for (OdBmObjectPtrArray::const_iterator it = aFilterSettings.begin(); it != itFSEnd; ++it)
  {
    if ((*it)->isA() == OdBmFilterGraphicSettings::desc())
    {
      OdBmFilterGraphicSettingsPtr pFilterGraphicsSettings = (*it);
      if (!pFilterGraphicsSettings->getVisibilityFlag())
      {
        OdBmParameterFilterElementPtr pFilterElem = pFilterGraphicsSettings->getFilterElemId().safeOpenObject();
        aParameterFilters.push_back(pFilterElem);
      }
    }
  }

  OdBmObjectPtrArray::const_iterator itPFEnd = aParameterFilters.end();
  for (OdBmObjectPtrArray::const_iterator it = aParameterFilters.begin(); it != itPFEnd; ++it)
  {
    OdBmParameterFilterElementPtr pFilterElem = (*it);
    OdBmObjectIdArray aCategories;
    pFilterElem->getCategoryRule()->getCategories(aCategories);
    if (!aCategories.contains(element->getCategroryId()))
      return false;

    // check rules
    OdBmObjectPtrArray aRules;
    pFilterElem->getRules(aRules);
    for (OdBmObjectPtrArray::const_iterator it = aRules.begin(); it != aRules.end(); ++it)
    {
      OdBmFilterRulePtr pFilterRule = (*it);
      if (!pFilterRule->elementPasses(element))
        return false;
    }
  }
}

```

注意：过滤时使用 OdBmFilerRule ([https://docs.opendesign.com/tbim/frames.html?frmname=topic&amp;frmfile=tbim\_filtering.html](https://docs.opendesign.com/tbim/frames.html?frmname=topic&frmfile=tbim_filtering.html))

#### 总结

过滤完成后，可以开始渲染。渲染时可以使用几何体缓存（element-&gt;getGeometry()）。

有时，一个元素可能被认为是可见的，但不会被渲染。例如，如果元素没有几何体缓存，就可能发生这种情况。元素可能是一个过渡元素，需要处理另一个元素（例如，FamilyInstance 包含 FamilySymbol 几何体的变换矩阵——在渲染 FamilySymbol 几何体时应考虑此矩阵）。

元素几何体可以具有不同的属性/选项，这些属性/选项会影响元素是否被渲染。GFiler 对象或 GInfo 标志就是此类选项的示例。

## 今天就开始行动

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

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