/*********************************************************************************************************************** * * Copyright (c) 2010 - 2022 by Tech Soft 3D, Inc. * The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., 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, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the * scope and manner of such use. * ***********************************************************************************************************************/ /** \file MultiplePrc.cpp This file demonstrates how to programmatically create and read multiple PRC files from a CAD assembly using HOOPS Exchange. The input is the CAD assembly file path and a directory. The program generates multiple PRC files from this CAD assembly. This mode is supported for the following format: V4, V5, ProE, UG, SLDW. With other formats, only one PRC file is generated. ***********************************************************************************************************************/ #define _CRT_SECURE_NO_DEPRECATE 1 #include #include #include #include #include #include #define INITIALIZE_A3D_API #include #include //###################################################################################################################### A3DVoid A3DCheckFree(A3DPtr ptr) { free(ptr); } //###################################################################################################################### A3DPtr A3DCheckMalloc(size_t uiToAlloc) { return malloc(uiToAlloc); } //###################################################################################################################### #define CHECK_RET(function_call) {\ iRet = function_call; if(iRet != A3D_SUCCESS) { std::cout << "Error number=" << iRet << std::endl; return iRet; }\ } //###################################################################################################################### std::string ExtractFileName(const A3DUTF8Char* pcIn) { std::string strIn(pcIn); int lastSlash = (int) strIn.rfind("/"); if(lastSlash < 0) lastSlash = (int) strIn.rfind("\\"); std::string tmp = strIn.substr(size_t(lastSlash)+1); return tmp; } //###################################################################################################################### std::string ExtractFilePath(const A3DUTF8Char* pcIn) { std::string strIn(pcIn); int lastSlash = (int) strIn.rfind("/"); if(lastSlash < 0) lastSlash = (int) strIn.rfind("\\"); std::string tmp = strIn.substr(0,size_t(lastSlash)); return tmp; } //###################################################################################################################### std::string ExtractRelativePath(const A3DUTF8Char* pcIn,const A3DUTF8Char* pcDirRoot) { std::string strTotalPath = ExtractFilePath(pcIn); std::string strRootPath(pcDirRoot); std::string strRelativePath; size_t uiTotalPathSize = strTotalPath.size(); size_t uiRootPathSize = strRootPath.size(); if(uiTotalPathSize > uiRootPathSize) { strRelativePath = strTotalPath.substr(uiRootPathSize); } return strRelativePath; } //###################################################################################################################### bool DirExists(const std::string& dirName_in) { DWORD ftyp = GetFileAttributesA(dirName_in.c_str()); if (ftyp == INVALID_FILE_ATTRIBUTES) return false; if (ftyp & FILE_ATTRIBUTE_DIRECTORY) return true; return false; } //###################################################################################################################### std::string ExtractChoreFileName(std::string pcIn) { std::string strIn(pcIn); int lastPoint = (int) strIn.rfind("."); std::string tmp = strIn.substr(0, size_t(lastPoint)); return tmp; } //###################################################################################################################### int TreatFile(A3DSDKHOOPSExchangeLoader &sHoopsExchangeLoader, A3DUTF8Char** ppMappedNativePaths, A3DUTF8Char** ppMappedPRCPaths, unsigned int &idxmap, bool bIsAssembly, char* acUTF8FileName, char* acUTF8InDir, char* acUTF8OutDir) { int iRet; std::string strMainFileName = acUTF8FileName; // --- REREAD the native file without dependencies if(sHoopsExchangeLoader.m_psModelFile != NULL) A3DAsmModelFileDelete(sHoopsExchangeLoader.m_psModelFile); sHoopsExchangeLoader.m_psModelFile = NULL; A3DImport sImport2(strMainFileName.c_str()); sImport2.m_sLoadData.m_sIncremental.m_bLoadNoDependencies = true; iRet = sHoopsExchangeLoader.Import(sImport2); if(iRet != A3D_SUCCESS && iRet != A3D_LOAD_MISSING_COMPONENTS && iRet != A3D_LOAD_MULTI_MODELS_CADFILE) return iRet; // --- EXPORT as PRC std::string strRelativePath = ExtractRelativePath(strMainFileName.c_str(), acUTF8InDir); std::string strChorefilename = ExtractFileName(strMainFileName.c_str()); std::string strOutMainFileName = acUTF8OutDir; strOutMainFileName += strRelativePath; if( DirExists(strOutMainFileName) == false) { #ifdef _MSC_VER _mkdir(strOutMainFileName.c_str()); #else mkdir(strOutMainFileName.c_str()); #endif } strOutMainFileName += "\\__"; strOutMainFileName += strChorefilename; strOutMainFileName += ".prc"; A3DExport sExport(strOutMainFileName.c_str()); CHECK_RET(sHoopsExchangeLoader.Export(sExport)); // update the map NATIVE-PRC std::string strCurrentPRCName = strMainFileName; strCurrentPRCName += ".prc"; ppMappedNativePaths[idxmap] = (A3DUTF8Char*) A3DCheckMalloc(1024 * sizeof(A3DUTF8Char)); strcpy(ppMappedNativePaths[idxmap], strMainFileName.c_str()); //acUTF8FileName if we don't want the path ppMappedPRCPaths[idxmap] = (A3DUTF8Char*) A3DCheckMalloc(1024 * sizeof(A3DUTF8Char)); strcpy(ppMappedPRCPaths[idxmap], strOutMainFileName.c_str()); //strCurrentPRCName.c_str()) if we don't want the path idxmap++; CHECK_RET(A3DAsmModelFileDelete(sHoopsExchangeLoader.m_psModelFile)); sHoopsExchangeLoader.m_psModelFile = NULL; return 0; } //###################################################################################################################### bool SortByExtensionInPath(const std::string& strExtensionAsm, const std::string& strExtensionPrt, const std::string& strTestingPath, const std::string& strPath, std::set& a_rsCollectedAsmFilesPath, std::set& a_rsCollectedPartFilesPath) { char sDrive[256]; char sDir[256]; char sFileName[256]; char sExtension[256]; _splitpath(strTestingPath.c_str(),sDrive,sDir,sFileName,sExtension); std::string szExtension(sExtension); std::transform(szExtension.begin(), szExtension.end(), szExtension.begin(), ::tolower); size_t sAsm = szExtension.find(strExtensionAsm); size_t sPrt = szExtension.find(strExtensionPrt); if(sAsm == std::string::npos && sPrt == std::string::npos) return false; if(sAsm > sPrt) a_rsCollectedAsmFilesPath.insert(strPath); else a_rsCollectedPartFilesPath.insert(strPath); return true; } bool SortFilePath(const A3DEModellerType& eType, const std::string& a_rsPath, std::set& a_rsCollectedAsmFilesPath, std::set& a_rsCollectedPartFilesPath) { switch(eType) { case kA3DModellerProE: { std::string szRealPath = a_rsPath; size_t iDotPos = a_rsPath.find_last_of('.'); if(iDotPos != std::string::npos) szRealPath.erase (szRealPath.begin()+iDotPos, szRealPath.end()); return SortByExtensionInPath("asm", "prt", szRealPath,a_rsPath,a_rsCollectedAsmFilesPath,a_rsCollectedPartFilesPath); } case kA3DModellerSlw: return SortByExtensionInPath("sldasm", "sldprt",a_rsPath, a_rsPath,a_rsCollectedAsmFilesPath,a_rsCollectedPartFilesPath); case kA3DModellerCatiaV5: return SortByExtensionInPath("catproduct", "catpart", a_rsPath,a_rsPath,a_rsCollectedAsmFilesPath,a_rsCollectedPartFilesPath); case kA3DModellerCatia: return SortByExtensionInPath("session", "model", a_rsPath,a_rsPath,a_rsCollectedAsmFilesPath,a_rsCollectedPartFilesPath); case kA3DModellerInventor: return SortByExtensionInPath("iam", "ipt", a_rsPath,a_rsPath,a_rsCollectedAsmFilesPath,a_rsCollectedPartFilesPath); case kA3DModellerSE: return SortByExtensionInPath("asm", "par", a_rsPath,a_rsPath,a_rsCollectedAsmFilesPath,a_rsCollectedPartFilesPath); default : return false; } } //###################################################################################################################### A3DStatus GetAllFileDependenciesFromFilelist(A3DUTF8Char*& a_rpcFilelist, std::set& a_rsCollectedAsmFilesPath, std::set& a_rsCollectedPartFilesPath) { std::ifstream oFile; oFile.open(a_rpcFilelist); while (!oFile.eof()) { std::string szFilePath; getline(oFile,szFilePath); A3DEModellerType eType; A3DStatus iRet = A3DGetFileFormat(szFilePath.c_str(), &eType); if(iRet != A3D_SUCCESS) return iRet; if(!SortFilePath(eType,szFilePath,a_rsCollectedAsmFilesPath, a_rsCollectedPartFilesPath)) return A3D_LOAD_MISSING_COMPONENTS; } oFile.close(); return A3D_SUCCESS; } //###################################################################################################################### A3DStatus GetAllFileDependencies(std::string& a_rszCurFile, A3DSDKHOOPSExchangeLoader& a_rsHoopsExchangeLoader, std::set& a_rsCollectedAsmFilesPath, std::set& a_rsCollectedPartFilesPath) { // Load file A3DImport sImport(a_rszCurFile.c_str()); sImport.m_sLoadData.m_sIncremental.m_bLoadNoDependencies = true; A3DStatus iRet = a_rsHoopsExchangeLoader.Import(sImport); if(iRet != A3D_SUCCESS && iRet != A3D_LOAD_MISSING_COMPONENTS && iRet != A3D_LOAD_MULTI_MODELS_CADFILE) return iRet; // Extract sub-file names A3DUns32 i = 0; A3DUns32 nbPartFiles = 0; A3DUTF8Char** ppPartPaths = NULL; A3DUns32 nbAssemblyFiles = 0; A3DUTF8Char** ppAssemblyPaths = NULL; A3DUns32 uNbMissingFiles = 0; A3DUTF8Char** ppMissingFilesPaths = NULL; CHECK_RET(A3DAsmGetFilesPathFromModelFile(a_rsHoopsExchangeLoader.m_psModelFile, &nbPartFiles, &ppPartPaths, &nbAssemblyFiles, &ppAssemblyPaths, &uNbMissingFiles, &ppMissingFilesPaths)); for(i = 0; i < nbAssemblyFiles; i ++) { a_rsCollectedAsmFilesPath.insert(ppAssemblyPaths[i]); } for(i = 0; i < nbPartFiles; i ++) { a_rsCollectedPartFilesPath.insert(ppPartPaths[i]); a_rsCollectedAsmFilesPath.erase(ppPartPaths[i]); } // Free model file if(a_rsHoopsExchangeLoader.m_psModelFile != NULL) { A3DAsmModelFileDelete(a_rsHoopsExchangeLoader.m_psModelFile); a_rsHoopsExchangeLoader.m_psModelFile = NULL; } // Load Sub assembly files for(i = 0; i < nbAssemblyFiles; i ++) { std::string szSubFileName(ppAssemblyPaths[i]); if(szSubFileName != a_rszCurFile) { GetAllFileDependencies(szSubFileName, a_rsHoopsExchangeLoader, a_rsCollectedAsmFilesPath, a_rsCollectedPartFilesPath); } } // Free filenames intermediate storage CHECK_RET(A3DAsmGetFilesPathFromModelFile(NULL, &nbPartFiles, &ppPartPaths, &nbAssemblyFiles, &ppAssemblyPaths, &uNbMissingFiles, &ppMissingFilesPaths)); return A3D_SUCCESS; } //###################################################################################################################### // Main function #ifdef _MSC_VER int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv) #else int main(int iArgc, A3DUTF8Char** ppcArgv) #endif { if(iArgc != 4 && iArgc != 5) { #ifdef _MSC_VER _tprintf(_T("Usage:\n %s \n"), ppcArgv[0]); #else printf("Usage:\n %s \n", ppcArgv[0]); #endif return A3D_ERROR; } ///////////////////////////////////////////// // 1- Initialize HOOPS Exchange. ///////////////////////////////////////////// #ifdef _MSC_VER # ifdef _WIN64 const TCHAR* pcLibPath = _T("..\\..\\..\\..\\bin\\win64\\"); # else const TCHAR* pcLibPath = _T("..\\..\\..\\..\\bin\\win32\\"); # endif A3DUTF8Char acUTF8FileName[MAX_PATH*4]; A3DUTF8Char acUTF8InDir[MAX_PATH*4]; A3DUTF8Char acUTF8OutDir[MAX_PATH*4]; A3DUTF8Char* acUTF8FileList = NULL; #else # ifdef X32 const A3DUTF8Char* pcLibPath = "../../../../bin/linux32"; # else const A3DUTF8Char* pcLibPath = "../../../../bin/linux64"; # endif A3DUTF8Char* acUTF8FileName = ppcArgv[1]; A3DUTF8Char* acUTF8InDir = ppcArgv[2]; A3DUTF8Char* acUTF8OutDir = ppcArgv[3]; A3DUTF8Char* acUTF8FileList = ppcArgv[4]; #endif A3DInt32 iRet = A3D_SUCCESS; A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(pcLibPath); if (sHoopsExchangeLoader.m_eSDKStatus!=A3D_SUCCESS) return sHoopsExchangeLoader.m_eSDKStatus; #ifdef _MSC_VER A3DMiscUnicodeToUTF8((A3DUTF8Char*) ppcArgv[1], acUTF8FileName); A3DMiscUnicodeToUTF8((A3DUTF8Char*) ppcArgv[2], acUTF8InDir); A3DMiscUnicodeToUTF8((A3DUTF8Char*) ppcArgv[3], acUTF8OutDir); if(ppcArgv[4]) { acUTF8FileList = new A3DUTF8Char[MAX_PATH*4]; A3DMiscUnicodeToUTF8((A3DUTF8Char*) ppcArgv[4], acUTF8FileList); } #endif std::string strMainFileName = ExtractFileName(acUTF8FileName); std::string strInMainFileName = acUTF8FileName; // init map NATIVE-PRC const int MAXFILES = 100; A3DUTF8Char** ppMappedNativePaths = (A3DUTF8Char**) A3DCheckMalloc(MAXFILES * sizeof(A3DUTF8Char*)); A3DUTF8Char** ppMappedPRCPaths = (A3DUTF8Char**) A3DCheckMalloc(MAXFILES * sizeof(A3DUTF8Char*)); unsigned int idxmap = 0; //////////////////////////////////////////////////////////////////////////// // load the model and get the list of files //////////////////////////////////////////////////////////////////////////// // --- EXTRACT file names for sons std::set sAsmFilesPath; std::set sPartFilesPath; if(acUTF8FileList) { iRet = GetAllFileDependenciesFromFilelist(acUTF8FileList, sAsmFilesPath, sPartFilesPath); if(iRet != A3D_SUCCESS) return iRet; } else { iRet = GetAllFileDependencies(strInMainFileName, sHoopsExchangeLoader, sAsmFilesPath, sPartFilesPath); if(iRet != A3D_SUCCESS && iRet != A3D_LOAD_MISSING_COMPONENTS && iRet != A3D_LOAD_MULTI_MODELS_CADFILE) return iRet; } //////////////////////////////////////////////////////////////////////////// // 1- build a PRC for each component in the assembly, // and update the map NATIVE-PRC //////////////////////////////////////////////////////////////////////////// // 1-a Roots if(sAsmFilesPath.find(acUTF8FileName) == sAsmFilesPath.end()) // add root file if it's not already registered in sAsmFilesPath { TreatFile(sHoopsExchangeLoader,ppMappedNativePaths,ppMappedPRCPaths,idxmap , true, acUTF8FileName, acUTF8InDir, acUTF8OutDir); } //1-b Assemblies std::set::iterator itAsmPathCur = sAsmFilesPath.begin(); std::set::iterator itAsmPathEnd = sAsmFilesPath.end(); for(; itAsmPathCur != itAsmPathEnd; itAsmPathCur++) { TreatFile(sHoopsExchangeLoader,ppMappedNativePaths,ppMappedPRCPaths,idxmap , true, (char*) (*itAsmPathCur).c_str(), acUTF8InDir, acUTF8OutDir); } //1-c Part std::set::iterator itPartPathCur = sPartFilesPath.begin(); std::set::iterator itPartPathEnd = sPartFilesPath.end(); for(; itPartPathCur != itPartPathEnd; itPartPathCur++) { TreatFile(sHoopsExchangeLoader,ppMappedNativePaths,ppMappedPRCPaths,idxmap , false, (char*) (*itPartPathCur).c_str(), acUTF8InDir, acUTF8OutDir); } //////////////////////////////////////////////////////////////////////////// // 2- now simulate an assembly reconstruction starting from the root file with all PRC chunks //////////////////////////////////////////////////////////////////////////// std::string strOutMainFileName = acUTF8OutDir; strOutMainFileName += "\\__"; strOutMainFileName += strMainFileName; strOutMainFileName += ".prc"; A3DAsmModelFile* pOutModelFile = NULL; A3DRWParamsLoadData sRPartParam; A3D_INITIALIZE_DATA(A3DRWParamsLoadData, sRPartParam); sRPartParam.m_sGeneral.m_bReadSolids = true; sRPartParam.m_sGeneral.m_bReadSurfaces = true; sRPartParam.m_sGeneral.m_bReadWireframes = true; sRPartParam.m_sGeneral.m_eReadGeomTessMode = kA3DReadGeomAndTess; sRPartParam.m_sGeneral.m_bReadHiddenObjects = true; //sRPartParam.m_sMultiEntries.m_bLoadDefault = true; CHECK_RET(A3DAsmModelFileLoadFromPRCFiles( strOutMainFileName.c_str(), idxmap, (const A3DUTF8Char**)ppMappedPRCPaths, (const A3DUTF8Char**)ppMappedNativePaths, &sRPartParam, &pOutModelFile)); // --- Export the rebuilt assembly to test the result std::string strOut = acUTF8OutDir; strOut += "\\__"; strOut += strMainFileName; strOut += "AllLoaded.prc"; A3DExport sFinalExport(strOut.c_str()); sHoopsExchangeLoader.m_psModelFile = pOutModelFile; CHECK_RET(sHoopsExchangeLoader.Export(sFinalExport)); for(unsigned ui = 0; ui < idxmap; ++ui) { A3DCheckFree(ppMappedPRCPaths[ui]); } A3DCheckFree(ppMappedPRCPaths); delete acUTF8FileList; acUTF8FileList = NULL; return A3D_SUCCESS; }