...
Workbench project preparation
Refer How-Toto: Traverse PRC model file using Visitor pattern for rapid prototyping article and create a workbench project (form [Workbench project preparation] to [Implement tree traverse function])
...
Create a derived class of A3DTreeVisitor including
visitEnter
method forA3DPartConnector
Code Block language cpp ... static MY_CHAR acLogFileName[_MAX_PATH * 2]; class bodyOperationVisitor: public A3DTreeVisitor { public: bodyOperationVisitor(A3DVisitorContainer* psContainer = NULL) : A3DTreeVisitor(psContainer) {}; ~bodyOperationVisitor() {}; public: virtual A3DStatus visitEnter(const A3DPartConnector& sConnector) override { A3DStatus iRet = A3DTreeVisitor::visitEnter(sConnector); // My processes return iRet; } }; void traverseModelFile(A3DAsmModelFile* pModelFile) ...
Use the derived
bodyOperationVisitor
class instead ofA3DTessVisitor
in thetraverseModelFile
functionCode Block language cpp ... // Prepare body operation visitor and set to the container bodyOperationVisitor *pBodyOpVisitor = new bodyOperationVisitor(&sA3DVisitorContainer); sA3DVisitorContainer.push(pBodyOpVisitor); ...
Build the project
Create break points in the
bodyOperaitonVisitor
bodyOperationVisitor
class and verify that the class is called during run time
...
Code Block | ||
---|---|---|
| ||
/*********************************************************************************************************************** * * Copyright (c) 2017 by Tech Soft 3D, LLC. * The information contained herein is confidential and proprietary to Tech Soft 3D, LLC., and considered a trade secret * as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event * of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized * employees of Tech Soft 3D, LLC. is granted only under a written non-disclosure agreement, expressly prescribing the * scope and manner of such use. * ***********************************************************************************************************************/ /* * This sample demonstrates how to load a model and export it as a model file of a different format. The chosen * format is determined by the file extension of the output file name. */ #define INITIALIZE_A3D_API #include <A3DSDKIncludes.h> #include "common.hpp" #include <sstream> #include <vector> #include "visitor/VisitorContainer.h" #include "visitor/VisitorTree.h" static MY_CHAR acSrcFileName[_MAX_PATH * 2]; static MY_CHAR acDstFileName[_MAX_PATH * 2]; static MY_CHAR acLogFileName[_MAX_PATH * 2]; static A3DAsmModelFile *s_pNewModelFile = NULL; class bodyOperationVisitor : public A3DTreeVisitor { public: bodyOperationVisitor(A3DVisitorContainer* psContainer = NULL) : A3DTreeVisitor(psContainer) {}; ~bodyOperationVisitor() {}; private: int m_iBodyCnt; A3DAsmPartDefinition** m_ppPart; A3DAsmProductOccurrence* m_pAssyPO = NULL; struct SplitPart { const A3DAsmProductOccurrence *parentPO; A3DAsmProductOccurrence *oldPartPO; A3DAsmProductOccurrence *newAssyPO; A3DAsmProductOccurrence *protoPO; A3DMiscTransformation *instanceTransform; A3DRootBaseData instanceBaseData; }; std::vector<SplitPart> m_aSplitPart; public: virtual A3DStatus visitEnter(const A3DPartConnector& sConnector) override { A3DStatus iRet = A3DTreeVisitor::visitEnter(sConnector); // Get the PartDefiniiton data A3DAsmPartDefinitionData sData = sConnector.m_sPartData; // Detect multi body part m_iBodyCnt = 0; if (1 < sData.m_uiRepItemsSize) { m_iBodyCnt = sData.m_uiRepItemsSize; // Create new Parts for each body m_ppPart = new A3DAsmPartDefinition*[m_iBodyCnt]; for (A3DUns32 ui = 0; ui < m_iBodyCnt; ui++) { // Create a new part and set body A3DAsmPartDefinitionData sNewPartData; A3D_INITIALIZE_DATA(A3DAsmPartDefinitionData, sNewPartData); sNewPartData.m_uiRepItemsSize = 1; sNewPartData.m_ppRepItems = &sData.m_ppRepItems[ui]; iRet = A3DAsmPartDefinitionCreate(&sNewPartData, &m_ppPart[ui]); } } return iRet; } virtual A3DStatus visitLeave(const A3DProductOccurrenceConnector& sConnector) override { A3DStatus iRet = A3D_SUCCESS; // Get the ProductOccurrence (PO) const A3DEntity* pEntity = sConnector.GetA3DEntity(); A3DAsmProductOccurrence* pPO = (A3DAsmProductOccurrence*)pEntity; // Get PO data A3DAsmProductOccurrenceData sData = sConnector.m_sProductOccurrenceData; // Get RootBaseData of the PO A3DRootBaseData sRootBaseData; A3D_INITIALIZE_DATA(A3DRootBaseData, sRootBaseData); A3DRootBaseGet(pPO, &sRootBaseData); // If multi body part if (m_iBodyCnt) { // Get prototype A3DAsmProductOccurrence *pProtoPO = sData.m_pPrototype; A3DAsmProductOccurrenceData sProtoData; A3DRootBaseData sProtoBaseData; if (NULL != pProtoPO) { A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sProtoData); iRet = A3DAsmProductOccurrenceGet(pProtoPO, &sProtoData); A3D_INITIALIZE_DATA(A3DRootBaseData, sProtoBaseData); iRet = A3DRootBaseGet(pProtoPO, &sProtoBaseData); // Chenck whether the same part is detected for (int i = 0; i < m_aSplitPart.size(); i++) { if (pProtoPO == m_aSplitPart[i].protoPO) { // Keep the target POs SplitPart splitPart; splitPart.parentPO = sConnector.GetProductOccurrenceFather(); splitPart.oldPartPO = pPO; splitPart.newAssyPO = m_aSplitPart[i].newAssyPO; splitPart.instanceTransform = sData.m_pLocation; splitPart.instanceBaseData = sRootBaseData; m_aSplitPart.push_back(splitPart); return iRet; } } } // Create new POs of the new parts A3DAsmProductOccurrence **ppPO; ppPO = new A3DAsmProductOccurrence*[m_iBodyCnt]; for (A3DUns32 ui = 0; ui < m_iBodyCnt; ui++) { // Create new PO A3DAsmProductOccurrenceData sPOData; A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sPOData); sPOData.m_dUnit = sData.m_dUnit; sPOData.m_pPart = m_ppPart[ui]; iRet = A3DAsmProductOccurrenceCreate(&sPOData, &ppPO[ui]); // Set part name (org name - id) char name[1024]; sprintf_s(name, sizeof(name), "%s - %d", sRootBaseData.m_pcName, ui + 1); A3DRootBaseData sNewBaseData; A3D_INITIALIZE_DATA(A3DRootBaseData, sNewBaseData); sNewBaseData.m_pcName = name; iRet = A3DRootBaseSet(ppPO[ui], &sNewBaseData); } // Create a new assembly PO for split parts A3DAsmProductOccurrenceData sNewPOData; A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sNewPOData); sNewPOData.m_uiPOccurrencesSize = m_iBodyCnt; sNewPOData.m_dUnit = sData.m_dUnit; sNewPOData.m_ppPOccurrences = ppPO; // sNewPOData.m_pLocation = sData.m_pLocation; iRet = A3DAsmProductOccurrenceCreate(&sNewPOData, &m_pAssyPO); iRet = A3DRootBaseSet(m_pAssyPO, &sRootBaseData); // Access father PO const A3DAsmProductOccurrence *pParentPO = sConnector.GetProductOccurrenceFather(); // If father PO isn't null, it is assembly model file if (NULL != pParentPO) { if (NULL != pProtoPO) { // Set prototype's RootBaseData iRet = A3DRootBaseSet(m_pAssyPO, &sProtoBaseData); } // Keep the target POs SplitPart splitPart; splitPart.parentPO = sConnector.GetProductOccurrenceFather(); splitPart.oldPartPO = pPO; splitPart.newAssyPO = m_pAssyPO; splitPart.protoPO = pProtoPO; splitPart.instanceTransform = sData.m_pLocation; splitPart.instanceBaseData = sRootBaseData; m_aSplitPart.push_back(splitPart); m_pAssyPO = NULL; } // No father PO maens that it is part model file } else { // Check whether current PO is in a targets for (int i = 0; i < m_aSplitPart.size(); i++) { SplitPart splitPart = m_aSplitPart[i]; if (pPO == splitPart.parentPO) { // Find target multi body part PO and replace to assembly PO for (A3DUns32 ui = 0; ui < sData.m_uiPOccurrencesSize; ui++) { if (sData.m_ppPOccurrences[ui] == splitPart.oldPartPO) { // Create new sub-assembly instance A3DAsmProductOccurrenceData sAssyInstData; A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sAssyInstData); sAssyInstData.m_pLocation = splitPart.instanceTransform; sAssyInstData.m_pPrototype = splitPart.newAssyPO; A3DAsmProductOccurrence *pAssyInstPO; iRet = A3DAsmProductOccurrenceCreate(&sAssyInstData, &pAssyInstPO); // Set RootBaseData of the instance iRet = A3DRootBaseSet(pAssyInstPO, &splitPart.instanceBaseData); // Replace part instance to sub-assembly instance sData.m_ppPOccurrences[ui] = pAssyInstPO; break; } } iRet = A3DAsmProductOccurrenceEdit(&sData, pPO); } } } iRet = A3DTreeVisitor::visitLeave(sConnector); return iRet; } virtual A3DStatus visitLeave(const A3DModelFileConnector& sConnector) override { A3DStatus iRet = A3D_SUCCESS; const A3DEntity* pEntity = sConnector.GetA3DEntity(); A3DAsmModelFile* pModelFile = (A3DAsmModelFile*)pEntity; A3DAsmModelFileData sData = sConnector.m_sModelFileData; A3DRootBaseData sRootBaseData; A3D_INITIALIZE_DATA(A3DRootBaseData, sRootBaseData); A3DRootBaseGet(pModelFile, &sRootBaseData); if (m_pAssyPO) { // Create assemly pModelFile A3DAsmModelFileData sModelFileData = sConnector.m_sModelFileData; sModelFileData.m_bUnitFromCAD = sData.m_bUnitFromCAD; sModelFileData.m_dUnit = sData.m_dUnit; sModelFileData.m_eModellerType = kA3DModellerPrc; sModelFileData.m_uiPOccurrencesSize = 1; sModelFileData.m_ppPOccurrences = &m_pAssyPO; iRet = A3DAsmModelFileCreate(&sModelFileData, &s_pNewModelFile); // Set root made data of original model file iRet = A3DRootBaseSet(s_pNewModelFile, &sRootBaseData); m_pAssyPO = NULL; } return iRet; } }; void traverseModelFile(A3DAsmModelFile* pModelFile) { // Prepare Visitor container A3DVisitorContainer sA3DVisitorContainer(CONNECT_TRANSFO); sA3DVisitorContainer.SetTraverseInstance(true); // Prepare Tree traverse visitor and set to the container bodyOperationVisitor *pBodyOpVisitor = new bodyOperationVisitor(&sA3DVisitorContainer); sA3DVisitorContainer.push(pBodyOpVisitor); // Prepare model file connector and call Traverse A3DModelFileConnector sModelFileConnector(pModelFile); A3DStatus sStatus = sModelFileConnector.Traverse(&sA3DVisitorContainer); } //###################################################################################################################### #ifdef _MSC_VER int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv) #else int main(A3DInt32 iArgc, A3DUTF8Char** ppcArgv) #endif { // // ### COMMAND LINE ARGUMENTS // if (iArgc < 2) { MY_PRINTF2("Usage:\n %s [input CAD file] [output CAD file] [output LOG file]\n", ppcArgv[0]); MY_PRINTF(" Default output CAD file is [input CAD file].prc\n"); MY_PRINTF(" Default output LOG file is [output CAD file]_Log.txt\n\n"); return A3D_ERROR; } if (iArgc > 1) MY_STRCPY(acSrcFileName, ppcArgv[1]); else MY_STRCPY(acSrcFileName, DEFAULT_INPUT_CAD); if (iArgc > 2) MY_STRCPY(acDstFileName, ppcArgv[2]); else MY_SPRINTF(acDstFileName, "%s.prc", acSrcFileName); if (iArgc > 3) MY_STRCPY(acLogFileName, ppcArgv[3]); else MY_SPRINTF(acLogFileName, "%s_Log.txt", acDstFileName); GetLogFile(acLogFileName); // Initialize log file // // ### INITIALIZE HOOPS EXCHANGE // std::wstringstream bin_dir; #ifdef _DEBUG std::wstring buffer; buffer.resize(_MAX_PATH * 2); if (GetEnvironmentVariable(L"HEXCHANGE_INSTALL_DIR", &buffer[0], static_cast<DWORD>(buffer.size()))) { bin_dir << buffer.data() << L"/bin/win64\0"; } #else bin_dir << L""; #endif A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(bin_dir.str().data()); CHECK_RET(sHoopsExchangeLoader.m_eSDKStatus); // Uncomment these lines to track memory leaks //CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree)); CHECK_RET(A3DDllSetCallbacksReport(PrintLogMessage, PrintLogWarning, PrintLogError)); // // ### PROCESS SAMPLE CODE // // specify input file A3DImport sImport(acSrcFileName); // see A3DSDKInternalConvert.hxx for import and export detailed parameters // specify output file A3DExport sExport(acDstFileName); // see A3DSDKInternalConvert.hxx for import and export detailed parameters // perform conversion CHECK_RET(sHoopsExchangeLoader.Import(sImport)); traverseModelFile(sHoopsExchangeLoader.m_psModelFile); if (NULL != s_pNewModelFile) { A3DStatus iRet = A3DAsmModelFileDelete(sHoopsExchangeLoader.m_psModelFile); sHoopsExchangeLoader.m_psModelFile = s_pNewModelFile; s_pNewModelFile = NULL; } CHECK_RET(sHoopsExchangeLoader.Export(sExport)); // // ### TERMINATE HOOPS EXCHANGE // // Check memory allocations //if (siCheckMallocCounter != 0) // fprintf(GetLogFile(), "stiMallocCounter=%d", siCheckMallocCounter); return A3D_SUCCESS; } |
Related articles
How-Toto: Traverse PRC model file using Visitor pattern for rapid prototyping
...