/////////////////////////////////////////////////////////////////////////////// // 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 "RxInit.h" #include "StaticRxObject.h" #include "RxDynamicModule.h" #include "OdPerfTimer.h" #include "ExPrintConsole.h" #include "diagnostics.h" #include #include "../Extensions/ExServices/ExStepHostAppServices.h" #include "StepCore.h" #include "StepAPFile.h" #include "Common/daiModuleNames.h" #include "StepModuleNames.h" #include "daiHeaderSection.h" #include "daiRepository.h" #include "daiModel.h" #include "daiApplicationInstance.h" #include "daiUtils/daiUtils.h" #include "Common/examples/daiSimpleProgramOptions.h" #include "Common/examples/daiErrorEventListOutput.h" // // Define module map for statically linked modules: // #if !defined(_TOOLKIT_IN_DLL_) ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT(OdRxThreadPoolService); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT(OdSDAIModule); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT(OdStepCoreModule); ODRX_BEGIN_STATIC_MODULE_MAP() ODRX_DEFINE_STATIC_APPMODULE(OdThreadPoolModuleName, OdRxThreadPoolService) ODRX_DEFINE_STATIC_APPMODULE(OdSDAIModuleName, OdSDAIModule) ODRX_DEFINE_STATIC_APPMODULE(OdStepCoreModuleName, OdStepCoreModule) ODRX_END_STATIC_MODULE_MAP() #endif // Define a Custom Services class. // // Combines the platform dependent functionality of // OdRxSystemServices and OdDbBaseHostAppServices // class MyServices : public ExSystemServices, public OdExStepHostAppServices { protected: ODRX_USING_HEAP_OPERATORS(ExSystemServices); OdGsDevicePtr gsBitmapDevice(OdRxObject* /*pViewObj*/ = nullptr, OdDbBaseDatabase* /*pDb*/ = nullptr, OdUInt32 /*flags*/ = 0) { try { OdGsModulePtr pGsModule = ::odrxDynamicLinker()->loadModule(OdWinBitmapModuleName); return pGsModule->createBitmapDevice(); } catch (const OdError&) { } return OdGsDevicePtr(); } OdString m_pathToExecutable; public: void setPathToExecutable(const OdString &pathToExecutable) { m_pathToExecutable = pathToExecutable; } virtual OdString findFile( const OdString& fileName, OdDbBaseDatabase* pDb, FindFileHint hint) { if (fileName.find(L".exp") >= 0) { if (odrxSystemServices()->accessFile(fileName, Oda::kFileRead)) return fileName; OdString schemasFileName = OD_T("./Schemas/") + fileName; if (odrxSystemServices()->accessFile(schemasFileName, Oda::kFileRead)) return schemasFileName; OdString expFileName = m_pathToExecutable + "Schemas/" + fileName; if (odrxSystemServices()->accessFile(expFileName, Oda::kFileRead)) return expFileName; } return fileName; } virtual const OdString program() { return OdString::kEmpty; } virtual const OdString product() { return OD_T("ODA STEP SDK"); } virtual const OdString companyName() { return OD_T("Open Design Alliance"); } virtual bool ttfFileNameByDescriptor( const OdTtfDescriptor& description, OdString& filename) { return false; } virtual OdString getAlternateFontName() const { return OdString::kEmpty; } virtual OdString getFontMapFileName() const { return OdString::kEmpty; } virtual OdString getPreferableFont( const OdString& fontName, OdFontType fontType) { return OdString::kEmpty; } virtual OdString getSubstituteFont( const OdString& fontName, OdFontType fontType) { return OdString::kEmpty; } }; // // Prints a dump of loaded model // void dumpModel(OdDAI::ModelPtr model, bool dumpInverse) { odPrintConsoleString(L"Schema: %hs\n\n", model->underlyingSchemaName().c_str()); OdDAI::InstanceIteratorPtr it = model->newIterator(); for (; !it->done(); it->step()) { OdDAIObjectId id = it->id(); if (id.isValid()) { OdDAI::ApplicationInstancePtr inst = id.openObject(); OdAnsiString stepLine = OdDAI::Utils::getStepLine(inst); odPrintConsoleString(L"%hs\n", stepLine.c_str()); if (dumpInverse) { OdDAI::Entity *entity = inst->getInstanceType(); const OdArray &inverseAttributes = entity->inverseAttributes(); for (const auto &inverseAttribute : inverseAttributes) { OdAnsiString inverseAttributeContent("$"); if (inverseAttribute->isAggregate()) { OdDAI::Aggr *ids = nullptr; inst->getAttr(inverseAttribute->name()) >> ids; if (!ids->isNil()) { bool first = true; OdDAI::ConstIteratorPtr it = ids->createConstIterator(); for (it->beginning(); it->next();) { OdDAIObjectId id; it->getCurrentMember() >> id; if (first == false) inverseAttributeContent += OdAnsiString().format(", #%llu", (OdUInt64)id.getHandle()); else inverseAttributeContent = OdAnsiString().format("#%llu", (OdUInt64)id.getHandle()); first = false; } } } else { OdDAIObjectId id; inst->getAttr(inverseAttribute->name()) >> id; if (!id.isNull()) { inverseAttributeContent.format("#%llu", (OdUInt64)id.getHandle()); } } odPrintConsoleString(L" %hs: %hs\n", inverseAttribute->originalName().c_str(), inverseAttributeContent.c_str()); } } } } } // // Prints statistics for entity extent // void statistics(OdDAI::ModelPtr model, const OdAnsiString &entityName) { const OdDAI::SetOfOdDAIObjectId *extent = model->getEntityExtent(entityName.c_str()); if (extent && !extent->isNil()) { int extentSize = extent->getMemberCount(); odPrintConsoleString(L"\n%hs.extent size = %d\n", entityName.c_str(), extentSize); auto it = extent->createConstIterator(); for (it->beginning(); it->next();) { OdDAIObjectId id; if (it->getCurrentMember() >> id && id.isValid()) { OdDAI::ApplicationInstancePtr inst = id.openObject(); const char *name = nullptr; if (inst->getAttr("name") >> name) { odPrintConsoleString(L"\n#%llu=%hs.name is '%hs'", (OdUInt64)id.getHandle(), inst->typeName().c_str(), name); } } } } } // // Access to 2D aggregates example (b_spline_surface_with_knots) // void aggr2D_Access(OdDAI::ModelPtr model) { const OdDAI::SetOfOdDAIObjectId *extent = model->getEntityExtent("B_SPLINE_SURFACE_WITH_KNOTS"); if (extent && !extent->isNil()) { int extentSize = extent->getMemberCount(); odPrintConsoleString(L"\n%b_spline_surface_with_knots.extent size = %d\n", extentSize); auto it = extent->createConstIterator(); for (it->beginning(); it->next();) { OdDAIObjectId id; if (it->getCurrentMember() >> id && id.isValid()) { OdDAI::ApplicationInstancePtr inst = id.openObject(); odPrintConsoleString(L"\n#%llu.control_points_list = (", (OdUInt64)id.getHandle()); OdDAI::Aggr *control_points_list = nullptr; if ((inst->getAttr("control_points_list") >> control_points_list) && !control_points_list->isNil()) { OdDAI::IteratorPtr itNestedAggr = control_points_list->createIterator(); for (itNestedAggr->beginning(); itNestedAggr->next();) { odPrintConsoleString(L" ("); OdDAI::Aggr *aggrIds = nullptr; if ((itNestedAggr->getCurrentMember() >> aggrIds) && !aggrIds->isNil()) { OdDAI::IteratorPtr itId = aggrIds->createIterator(); for (itId->beginning(); itId->next();) { OdDAIObjectId id; if ((itId->getCurrentMember() >> id) && id.isValid()) { odPrintConsoleString(L" #%llu ", (OdUInt64)id.getHandle()); } } } odPrintConsoleString(L" )"); } } odPrintConsoleString(L" )\n"); } } } } void customAssertFunc(const char* expression, const char* fileName, int nLineNo) { OdString message; message.format(L"\n!!! Assertion failed: \"%ls\"\n file: %ls, line %d\n", OdString(expression).c_str(), OdString(fileName).c_str(), nLineNo); odPrintConsoleString(message); } namespace { void initExecutable(OdString pathToExecutable, MyServices* service) { int slashPos = -1; #ifdef ODA_WINDOWS slashPos = pathToExecutable.reverseFind('\\'); if (slashPos > 0) pathToExecutable = pathToExecutable.left(slashPos + 1); #endif slashPos = pathToExecutable.reverseFind('/'); if (slashPos > 0) pathToExecutable = pathToExecutable.left(slashPos + 1); service->setPathToExecutable(pathToExecutable); } } // // Main // #if defined(OD_USE_WMAIN) int wmain(int argc, wchar_t* argv[]) #else int main(int argc, char* argv[]) #endif { #if defined(TARGET_OS_MAC) && !defined(__MACH__) argc = ccommand(&argv); #endif // // Set current user locale (not OD_T("C")), for strftime // setlocale(LC_TIME, ""); // // Set custom assert function // ::odSetAssertFunc(customAssertFunc); OdString inFileName; OdString outFileName; bool readErrorLogOn = false; bool noWait = false; bool isDebugMode = false; bool noProgress = false; using namespace OdDAI::utils; argv_parser commandLineParser("ExStepReadFile"); commandLineParser.add_param(std::make_shared>(inFileName, "-inFile", "input .stp/.step/.stpz file.", false)); commandLineParser.add_param(std::make_shared>(outFileName, "-outFile", "output .stp/.step/.stpz file.", true)); commandLineParser.add_param(std::make_shared(readErrorLogOn, "-readErrorLogIsOn", "turn on error log during file reading.")); commandLineParser.add_param(std::make_shared(noWait, "-noWait", "-disable \"press any key\" on finish.")); commandLineParser.add_param(std::make_shared(isDebugMode, "-isDebug", "Waiting press any key on start process.")); commandLineParser.add_param(std::make_shared(noProgress, "-noProgress", "Disable progress meter output.")); // // Create a Services object // OdStaticRxObject svcs; // // Display the Product and Version that created the executable // odPrintConsoleString(L"\nExStepReadFile developed using %ls ver %ls\n", svcs.product().c_str(), svcs.versionString().c_str()); std::vector argumentList(argv + 1, argv + argc); std::stringstream executionStream; if (commandLineParser.parse(argumentList, executionStream) != OdDAI::utils::ParseResult::succeed) { odPrintConsoleString(OdString(executionStream.str().c_str())); return Utils::res_INVALID_ARGUMENTS.first; } if (isDebugMode == true) { odPrintConsoleString(L"\nDebug mode: Attach to process and then press ENTER to continue.\n"); int removeWarn = getchar(); } if (noProgress) { svcs.disableProgressMeterOutput(true); } // // Initialize example module input parameters // initExecutable(argv[0], &svcs); #if !defined(_TOOLKIT_IN_DLL_) ODRX_INIT_STATIC_MODULE_MAP(); #endif // // Initialize ODA SDK // odrxInitialize(&svcs); odStepInitialize(false, false); // // Result code // int nRes = Utils::res_OK.first; try { // // Create SDAI session // OdDAI::SessionPtr session = oddaiCreateSession(); if (session.isNull()) { throw Utils::res_CAN_NOT_CREATE_SESSION; } // // Error logger initialization // OdDAI::List* errorsList = nullptr; if (readErrorLogOn) { odPrintConsoleString(L"\n%s - error events recording is active: \n", Utils::actionNameEventParamRead.c_str()); session->startEventRecording(); odPrintConsoleString(L"%s - is turned on \n", Utils::actionNameSessionEventRec.c_str()); if (session->getAttrCaseInsensitive("errors") >> errorsList && errorsList) { odPrintConsoleString(L"%s - the list was get successfuly. Lets check this list on errors before read.\n", Utils::actionNameErrorEventList.c_str()); Utils::errorEventListOutput(errorsList); } else { odPrintConsoleString(L"%s - cant get list. Error events recording is not available.\n", Utils::actionNameErrorEventList.c_str()); } } OdPerfTimerWrapper timerWrapper; timerWrapper.getTimer()->start(); OdAPFilePtr apFile = svcs.readFile(inFileName); timerWrapper.getTimer()->stop(); OdResult readFileRes = apFile ? eOk : eFileInternalErr; // // File opening statistics // if (readFileRes == eOk) { odPrintConsoleString(L"File opened successfully.\n"); } else { odPrintConsoleString(L"File open error.\n"); } odPrintConsoleString(L"Opening time: %d msec\n\n", timerWrapper.getTimer()->countedMSec()); if (errorsList) { odPrintConsoleString(L"%s - the file reading was finished. Events list output:\n", Utils::actionNameErrorEventList.c_str()); Utils::errorEventListOutput(errorsList); } // // Dump opened model // if (readFileRes == eOk) { // // Access default model in read-only mode // OdDAI::ModelPtr model = apFile->getModel(); if (model == nullptr) { odPrintConsoleString(L"\nModel is null."); throw Utils::res_UNEXPECTED_ERROR; } dumpModel(model, true); //statistics(model, "representation_item"); //aggr2D_Access(model); // // Read-write access, entities can be instantiated and changed within model // //model->promoteModelToReadWrite(); //OdDAI::ApplicationInstancePtr inst = model->createEntityInstance(...); //OdDAIObjectId id = model->appendEntityInstance(inst); //... // // Write model back in file. // if (!outFileName.isEmpty()) { OdPerfTimerWrapper timerWrapper; timerWrapper.getTimer()->start(); //OdResult writeFileRes = repository->writeFile(outFileName); OdResult writeFileRes = apFile->writeFile(outFileName); timerWrapper.getTimer()->stop(); if (writeFileRes == eOk) { odPrintConsoleString(L"\nFile written successfully."); } else { odPrintConsoleString(L"\nFile writing error."); } odPrintConsoleString(L"\nWriting time: %d msec", timerWrapper.getTimer()->countedMSec()); } } // // Close repository. Model will be deleted. // //session->closeRepo(repository); if (noWait == false) { odPrintConsoleString(L"\nPress ENTER to continue.\n"); int removeWarn = getchar(); } } catch(OdError& e) { odPrintConsoleString(L"\n\nInternal error: %ls", e.description().c_str()); nRes = Utils::res_ERROR.first; } catch (Utils::ResultPair& e) { odPrintConsoleString(L"\n\nExecutable error: %hs.", e.second.c_str()); nRes = e.first; } catch(...) { odPrintConsoleString(L"\n\n%hs.", Utils::res_UNEXPECTED_ERROR.second.c_str()); nRes = Utils::res_UNEXPECTED_ERROR.first; } // // Close current SDAI session // oddaiCloseCurrentSession(); // // Make sure all OdSmartPtr instances are released before ODA SDK uninitialization! // // // Uninitialize ODA SDK in appropriate order // odStepUninitialize(); odrxUninitialize(); return nRes; }