はじめに
ビューには、すべてのグラフィック要素を含む特別なリストが含まれていないことが明らかになりました。レンダリング手順中、必要な要素は共通データベースからルールに従って選択されます。この記事では、カスタムグラフィックビューアを始めるための基本的なルールを説明します。
開始ビュー
ファイルを開くと、レンダリングされるビューの検索が開始されることが明らかになりました。これは、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フラグがそのようなオプションの例です。