ビューでの要素フィルタリングに慣れる

はじめに

ビューには、すべてのグラフィック要素を含む特別なリストが含まれていないことが明らかになりました。レンダリング手順中、必要な要素は共通データベースからルールに従って選択されます。この記事では、カスタムグラフィックビューアを始めるための基本的なルールを説明します。

開始ビュー

ファイルを開くと、レンダリングされるビューの検索が開始されることが明らかになりました。これは、DBDrawing要素リストとアクティブなDBDrawing要素へのポインタを含むDBDrawingInfoマネージャーを使用して行われます。以下は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

このマネージャーには、利用可能なすべてのDBDrawing要素のIDの配列(DBDrawingIndex)が含まれています。また、アクティブな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

ビュー要素の選択

各ビューは、レンダリングに利用可能な要素のリストを提供できます。以下の関数を使用してこれを行うことができます。

/** \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)に基づいてレンダリング可能な要素の選択。
  • 要素のヘッダーからの情報の選択。
  • 要素を2つのグループに分割:前面にレンダリングされるものと「共通」のもの。

要素のフィルタリング

要素がレンダリング可能であるからといって、必ずレンダリングされるべきであるとは限りません。要素には独自のカスタムレンダリングルールがあり、それを考慮する必要があります。

unplacedOwnerIdは、要素のレンダリングを禁止するルールの1つです。

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

さらに、すべてのビューには、レンダリング中に考慮すべき独自のルールとフィルターのセットがあります。

デザインフィルタリング

すべてのビュー要素は特定のデザインに属することができます (element->getDesignOptionId())。1つのデザイン「メインモデル」の要素に対するレンダリング実装例。

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->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&frmfile=tbim_filtering.html)

結論

フィルタリングが実行された後、レンダリングを開始できます。レンダリング中にジオメトリキャッシュを使用することが可能です (element->getGeometry())。

要素が可視と見なされても、レンダリングされない場合があります。例えば、要素にジオメトリキャッシュがない場合に発生する可能性があります。要素が推移的な要素である場合、別の要素に対処する必要があります(例えば、FamilyInstanceにはFamilySymbolジオメトリの変換行列が含まれており、この行列はFamilySymbolジオメトリをレンダリングする際に考慮されるべきです)。

要素のジオメトリには、要素がレンダリングされるかどうかに影響を与えるさまざまな属性/オプションがあります。GFilerオブジェクトやGInfoフラグがそのようなオプションの例です。

今すぐ始める

ODAソフトウェアを60日間無料でお試しください。
リスクなし、クレジットカード不要。

無料で試す