/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #include "OdaCommon.h" #include #include "ExIgesTutorial_03.h" #include "RxValue.h" #include "Core/IgesInit.h" #include "Core/IgesFile.h" #include "IgesExamplesCommon.h" #include #include using namespace OdDAI; class AbstractNotifier { public: virtual ~AbstractNotifier() {}; virtual void onLevelBegin(const OdRxObject* inst) = 0; virtual void onLevelEnd(const OdRxObject* inst) = 0; virtual void onHierarchyAttributeFound(const OdRxObject* inst, OdRxMember* member) = 0; virtual void onHasRepresentation(const OdRxObject* inst, const OdRxObject* reprInst) = 0; virtual void onAttribute(const OdRxMember* member, const OdRxValue& rxVal, const OdRxObject* inst) = 0; }; class LevelSaver { int& m_level; public: LevelSaver(int& level) : m_level(level) { ++m_level; } ~LevelSaver() { --m_level; } }; class CDATreePrinter : public AbstractNotifier { int m_level; public: CDATreePrinter() : m_level(0) { } virtual void onLevelBegin(const OdRxObject* inst) { ++m_level; odPrintConsoleString(OD_T("%sHierarchy level: %d\n"), tabulation(m_level).c_str(), m_level); const OdString& className = inst->isA()->name(); odPrintConsoleString(OD_T("%sClass: %s\n"), tabulation(m_level).c_str(), className.c_str()); OdString entityName; OdRxPropertyPtr propName = OdRxMemberQueryEngine::theEngine()->find(inst, OD_T("Name")); if (!propName.isNull()) { OdRxValue valName; (eOk == propName->getValue(inst, valName)) && (valName >> entityName); } odPrintConsoleString(OD_T("%sName: `%s`\n"), tabulation(m_level).c_str(), entityName.c_str()); } virtual void onLevelEnd(const OdRxObject* inst) { --m_level; } virtual void onHierarchyAttributeFound(const OdRxObject* inst, OdRxMember* member) { const OdString& propName = member->name(); odPrintConsoleString(OD_T("%sHierarchy property name: %s\n"), tabulation(m_level).c_str(), propName.c_str()); } virtual void onHasRepresentation(const OdRxObject* inst, const OdRxObject* reprInst) { const OdString& reprClassName = reprInst->isA()->name(); odPrintConsoleString(OD_T("%sCan be vectorized here (Representation: %s)\n"), tabulation(m_level).c_str(), reprClassName.c_str()); // vectorize(inst); // not reprInst, inst should be casted appropriately to OdGiDrawable/OdIfcInstance } virtual void onAttribute(const OdRxMember* member, const OdRxValue& rxVal, const OdRxObject* inst) { OdString memberName = member->name(); odPrintConsoleString(OD_T("\n%s%s: "), tabulation(m_level).c_str(), memberName.c_str()); const OdRxValueType& vt = rxVal.type(); if (vt == OdRxValueType::Desc::value()) { OdDAIObjectId idVal = *rxvalue_cast(&rxVal); odPrintConsoleString(OD_T("#%llu"), (OdUInt64)idVal.getHandle()); } else if (vt == OdRxValueType::Desc::value()) { OdAnsiString strVal = *rxvalue_cast(&rxVal); odPrintConsoleString(OD_T("'%hs'"), strVal.c_str()); } else if (vt == OdRxValueType::Desc::value()) { OdString strVal = *rxvalue_cast(&rxVal); odPrintConsoleString(OD_T("'%s'"), strVal.c_str()); } else if (vt == OdRxValueType::Desc::value()) { double dblVal = *rxvalue_cast(&rxVal); odPrintConsoleString(OD_T("%.4f"), dblVal); } else if (vt == OdRxValueType::Desc::value()) { int intVal = *rxvalue_cast(&rxVal); odPrintConsoleString(OD_T("%d"), intVal); } else if (vt == OdRxValueType::Desc::value()) { OdDAI::Boolean boolVal = *rxvalue_cast(&rxVal); odPrintConsoleString(OD_T("%hs"), boolVal.toStr().c_str()); } if (vt.isEnum()) { OdAnsiString strVal; rxVal >> strVal; odPrintConsoleString(OD_T("'%hs'"), strVal.c_str()); } // ... // Children attributes processing const OdArray* children = member->children(); if (member->children() && children->size()) { odPrintConsoleString(OD_T(", child attributes:")); LevelSaver saveLevel(m_level); if (rxVal.type() == OdRxValueType::Desc::value()) { OdDAIObjectId idVal = *rxvalue_cast(&rxVal); OdDAI::ApplicationInstancePtr instParentSet = idVal.openObject(); ODA_ASSERT_ONCE(instParentSet); for (const OdRxMemberPtr& childAttribute : *children) { if (childAttribute->isKindOf(OdRxProperty::desc())) { const OdRxPropertyPtr rxProperty = OdRxProperty::cast(childAttribute); OdRxValue childValue; if (eOk == rxProperty->getValue(instParentSet, childValue)) { onAttribute(childAttribute, childValue, instParentSet); } else { odPrintConsoleString(OD_T("\n%s%s: Can not get value."), tabulation(m_level).c_str(), childAttribute->name().c_str()); } } else if (childAttribute->isKindOf(OdRxCollectionProperty::desc())) { // // Process collection // const OdRxCollectionProperty* collection = dynamic_cast(childAttribute.get()); // Haven't seen before } } } else { for (const OdRxMemberPtr& childAttribute : *children) { if (childAttribute->isKindOf(OdRxProperty::desc())) { OdRxProperty* childProp = OdRxProperty::cast(childAttribute); OdRxValue childRxVal; if (eOk == childProp->getValue(inst, childRxVal)) { onAttribute(childProp, childRxVal, inst); } } else { // Haven't seen before } } } } } protected: OdString tabulation(int tab) { if (tab < 0) tab = 0; OdString res; while (tab > 0) { res += OD_T(" "); --tab; } return res; } }; class CDAWalker { AbstractNotifier* m_pNotifier; public: CDAWalker(AbstractNotifier* notifier) : m_pNotifier(notifier) { } ~CDAWalker() { delete m_pNotifier; } void run(const OdRxObject* inst) { return walkCDA(inst); } protected: void walkAttributes(const OdRxObject* inst) { OdRxMemberIteratorPtr memberIterator = OdRxMemberQueryEngine::theEngine()->newMemberIterator(inst); if (memberIterator) { OdUInt64 memberCount = memberIterator->size(); for (; !memberIterator->done(); memberIterator->next()) { OdRxMember* member = memberIterator->current(); if (member->isKindOf(OdRxProperty::desc())) { // // Process single property // OdRxProperty* prop = OdRxProperty::cast(member); // dynamic_cast(member); OdRxValue rxVal; if (eOk == prop->getValue(inst, rxVal)) { m_pNotifier->onAttribute(member, rxVal, inst); } } else if (member->isKindOf(OdRxCollectionProperty::desc())) { // // Process collection // OdRxCollectionProperty* collection = dynamic_cast(member); OdRxValueIteratorPtr itValues = collection->newValueIterator(inst); if (!itValues.isNull()) { for (; !itValues->done(); itValues->next()) { OdRxValue rxVal = itValues->current(); // Typed values extraction } } } } } } void walkCDA(const OdRxObject* inst) { if (m_pNotifier) m_pNotifier->onLevelBegin(inst); // // Uncomment to get OdRx class name. // //OdString rxClassName = inst->isA()->name(); // // Uncomment this line for dump attributes/properties of an instance // walkAttributes(inst); // // Try to find attribute called Representation, if it isn't null, the instance can be vectorized. // OdRxMember* memRepr = OdRxMemberQueryEngine::theEngine()->find(inst, OD_T("Representation")); if (memRepr) { if (memRepr->isKindOf(OdRxProperty::desc())) { OdRxProperty* propRepr = OdRxProperty::cast(memRepr); OdRxValue idRepresentation; if (eOk == propRepr->getValue(inst, idRepresentation)) { const IOdRxReferenceType* reference = idRepresentation.type().reference(); if (reference) { OdRxObjectPtr reprInst = reference->dereference(idRepresentation, IOdRxReferenceType::kForRead); if (!reprInst.isNull()) { if (m_pNotifier) m_pNotifier->onHasRepresentation(inst, reprInst); } } } } } // // Walk along all Rx Properties of instance and try to find Hierarchy Attribute // OdRxMemberIteratorPtr it = OdRxMemberQueryEngine::theEngine()->newMemberIterator(inst); for (; !it->done(); it->next()) { OdRxMember* member = it->current(); OdRxAttributeCollection& attrs = member->attributes(); int numAttrs = attrs.count(); for (int i = 0; i < numAttrs; ++i) { OdRxAttribute* attr = attrs.getAt(i); OdRxClass* pRx = attr->isA(); if (pRx->isDerivedFrom(OdRxHierarchyLevelAttribute::desc())) { if (m_pNotifier) m_pNotifier->onHierarchyAttributeFound(inst, member); if (member->isKindOf(OdRxProperty::desc())) { OdRxProperty* prop = dynamic_cast(member); OdRxValue idHierarchy; if (eOk == prop->getValue(inst, idHierarchy)) { const IOdRxReferenceType* reference = idHierarchy.type().reference(); if (reference) { OdGiDrawablePtr pInst = reference->dereference(idHierarchy, IOdRxReferenceType::kForRead); if (pInst) walkCDA(pInst); } } } else if (member->isKindOf(OdRxCollectionProperty::desc())) { OdRxCollectionProperty* collection = dynamic_cast(member); OdRxValueIteratorPtr itValues = collection->newValueIterator(inst); if (!itValues.isNull()) for (; !itValues->done(); itValues->next()) { OdRxValue treeNodeId = itValues->current(); const IOdRxReferenceType* reference = treeNodeId.type().reference(); if (reference) { OdGiDrawablePtr pInst = reference->dereference(treeNodeId, IOdRxReferenceType::kForRead); walkCDA(pInst); } } } } } } if (m_pNotifier) m_pNotifier->onLevelEnd(inst); } }; Tutorial_03::Tutorial_03(const OdString& applicationName) : BaseIgesTutorial(applicationName) { m_tutorialArgsParser .add_param( std::make_shared>(m_igesFileName, "filename", "input .igs or .iges file")); m_tutorialArgsParser .add_param( std::make_shared(m_noWait, "-NoWait", "disable \"press any key\" on finish.")); } int Tutorial_03::run(MyServices& svcs, const std::vector& argv, std::ostream& resultStream) { auto parseResult = BaseIgesTutorial::run(svcs, argv, resultStream); if (parseResult != 0) { return parseResult; } IgesFilePtr igesFile = svcs.readFile(m_igesFileName); if (igesFile) { odPrintConsoleString(OD_T("\nFile opened successfully.")); odPrintConsoleString(OD_T("\n")); CDAWalker walker(new CDATreePrinter); walker.run(igesFile); } return eOk; }