/*********************************************************************************************************************** * * 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 TranslateToPkParts.cpp This file demonstrates how to load a CAD file and import the data into a Parasolid session. - Load a CAD file with HOOPS Exchange - Call the A3DSDKHOOPSExchangeLoader::Export() function - Export to Parasolid with PK_PART_transmit (Parasolid API) In order to compile, you need to: 1. On Windows - Set up the PARASOLID_INSTALL_DIR and PARASOLID_INSTALL_DIR_64 environment variables to your Parasolid folder using the property sheet PARASOLID with the "User macros" field; - Save the property sheet. - Then you can build it. 2. On Linux - Set up the PARASOLID_INSTALL_DIR environment variable to your Parasolid folder in the makefile - Then you can build it. In order to run, you need to: Common: - Set up the P_SCHEMA environment variable to your Parasolid schema folder (ending with \base\schema); - Copy pskernel.dll or libpskernel.so to your working directory (the HOOPS Exchange library binary folder). Windows-specific: - Provide the correct working directory, i.e. the HOOPS Exchange binary folder (i.e. ..\..\..\..\bin\win32); this setting is located in Project Properties --> Configuration Properties --> Debugging --> Working Directory; - Set up the command line - Then you can run it. Linux-specific: - Set up the LD_LIBRARY_PATH=$PARASOLID_INSTALL_DIR/shared_object:../../../../bin/linux32|linux64 - Then you can run it. ***********************************************************************************************************************/ #if defined(_MSC_VER) && !defined(PARASOLID_INSTALL_DIR) # error PARASOLID_INSTALL_DIR environment variable required #endif #include #ifndef _MSC_VER # include #endif #define INITIALIZE_A3D_API #include #include "../common.hpp" //###################################################################################################################### extern "C" { extern void FSTART(int*); extern void FABORT(int*); extern void FSTOP(int*); extern void FMALLO(int*, char**, int*); extern void FMFREE(int*, char**, int*); extern void GOSGMT(const int*, const int*, const int*, const int*, const double*, const int*, const int*, int*); extern void GOOPSG(const int*, const int*, const int*, const int*, const double*, const int*, const int*, int*); extern void GOCLSG(const int*, const int*, const int*, const int*, const double*, const int*, const int*, int*); extern void GOPIXL(const int*, const double*, const int*, const int*, int*); extern void GOOPPX(const int*, const double*, const int*, const int*, int*); extern void GOCLPX(const int*, const double*, const int*, const int*, int*); extern void FFOPRD(const int*, const int*, const char*, const int*, const int*, int*, int*); extern void FFOPWR(const int*, const int*, const char*, const int*, const char*, const int*, int*, int*); extern void FFCLOS(const int*, const int*, const int*, int*); extern void FFREAD(const int*, const int*, const int*, char*, int*, int*); extern void FFWRIT(const int*, const int*, const int*, const char*, int*); extern void FFOPRB(const int*, const int*, const int*, int*, int*, int*); extern void FFSEEK(const int*, const int*, const int*, int*); extern void FFTELL(const int*, const int*, int*, int*); extern PK_ERROR_code_t FRU_delta_open_for_write(PK_PMARK_t, PK_DELTA_t*); extern PK_ERROR_code_t FRU_delta_open_for_read(PK_DELTA_t); extern PK_ERROR_code_t FRU_delta_write(PK_DELTA_t, unsigned, const char*); extern PK_ERROR_code_t FRU_delta_read(PK_DELTA_t, unsigned, char*); extern PK_ERROR_code_t FRU_delta_delete(PK_DELTA_t); extern PK_ERROR_code_t FRU_delta_close(PK_DELTA_t); extern int FRU__delta_init(int action); } //###################################################################################################################### bool ParasolidInitialize() { PK_ERROR_code_t pk_error; PK_SESSION_frustrum_t ps_file_handlers; PK_MEMORY_frustrum_t ps_memory_handlers; PK_SESSION_frustrum_o_m(ps_file_handlers); ps_file_handlers.fstart = FSTART; ps_file_handlers.fabort = FABORT; ps_file_handlers.fstop = FSTOP; ps_file_handlers.fmallo = FMALLO; ps_file_handlers.fmfree = FMFREE; ps_file_handlers.gosgmt = GOSGMT; ps_file_handlers.goopsg = GOOPSG; ps_file_handlers.goclsg = GOCLSG; ps_file_handlers.gopixl = GOPIXL; ps_file_handlers.gooppx = GOOPPX; ps_file_handlers.goclpx = GOCLPX; ps_file_handlers.ffoprd = FFOPRD; ps_file_handlers.ffopwr = FFOPWR; ps_file_handlers.ffclos = FFCLOS; ps_file_handlers.ffread = FFREAD; ps_file_handlers.ffwrit = FFWRIT; ps_file_handlers.ffoprb = FFOPRB; ps_file_handlers.ffseek = FFSEEK; ps_file_handlers.fftell = FFTELL; pk_error = PK_SESSION_register_frustrum(&ps_file_handlers); if (pk_error != PK_ERROR_no_errors) return false; ps_memory_handlers.alloc_fn = malloc; ps_memory_handlers.free_fn = free; pk_error = PK_MEMORY_register_callbacks(ps_memory_handlers); if (pk_error != PK_ERROR_no_errors) return false; PK_DELTA_frustrum_t deltaFrustrum; deltaFrustrum.open_for_write_fn = FRU_delta_open_for_write; deltaFrustrum.open_for_read_fn = FRU_delta_open_for_read; deltaFrustrum.close_fn = FRU_delta_close; deltaFrustrum.write_fn = FRU_delta_write; deltaFrustrum.read_fn = FRU_delta_read; deltaFrustrum.delete_fn = FRU_delta_delete; pk_error = PK_DELTA_register_callbacks(deltaFrustrum); if (pk_error != PK_ERROR_no_errors) return false; FRU__delta_init(1); PK_SESSION_start_o_t session_options; PK_SESSION_start_o_m(session_options); session_options.user_field = 0; session_options.journal_file = NULL; pk_error = PK_SESSION_start(&session_options); return pk_error == PK_ERROR_no_errors; } //###################################################################################################################### void ParasolidTerminate() { FRU__delta_init(2); PK_SESSION_stop(); } #ifdef _MSC_VER # include #elif defined (__linux__) && !defined(__APPLE__) # include #elif defined (__APPLE__) # include # include #else #error TSystem not implemented on this platform #endif static int getLogicalProcessor() { #ifdef _MSC_VER SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); return sysinfo.dwNumberOfProcessors; #elif defined (__APPLE__) int nm[2]; size_t len = 4; uint32_t count; nm[0] = CTL_HW; nm[1] = HW_AVAILCPU; sysctl(nm, 2, &count, &len, NULL, 0); if (count < 1) { nm[1] = HW_NCPU; sysctl(nm, 2, &count, &len, NULL, 0); if (count < 1) { count = 1; } } return count; #elif defined (__linux__) && !defined (__APPLE__) return sysconf(_SC_NPROCESSORS_ONLN); #else return 1; #endif } static MY_CHAR acSrcFileName[_MAX_PATH * 2]; static MY_CHAR acDstFileName[_MAX_PATH * 2]; static MY_CHAR acLogFileName[_MAX_PATH * 2]; //###################################################################################################################### // Main function #ifdef _MSC_VER int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv) #else int main(A3DInt32 iArgc, A3DUTF8Char** ppcArgv) #endif { // // ### COMMAND LINE ARGUMENTS // for (int iArg = 0; iArg < iArgc; iArg++) MY_PRINTF2("%s ", ppcArgv[iArg]); MY_PRINTF("\n"); if (iArgc < 2) { MY_PRINTF2("Usage:\n %s [options]\n", ppcArgv[0]); MY_PRINTF(" Default output Parasolid file is [input CAD file].xmt_txt\n\n"); MY_PRINTF(" Default output LOG file is [output Parasolid file].xmt_txt_Log.txt\n\n"); MY_PRINTF(" options:\n"); MY_PRINTF(" -log filename : file to dump messages into. Default is _Log.txt\n"); MY_PRINTF(" -healing 0|1|2 : healing mode (it activates the Parasolid healing); 0 = off (by default), 1 = on all the time, 2 = on only for data not coming from Parasolid\n"); MY_PRINTF(" -accurate 0|1|2 : accurate mode (it replaces tolerant edges by accurate ones if possible); 0 = off (by default), 1 = on all the time, 2 = on only for data not coming from Parasolid \n"); MY_PRINTF(" -simplify 0|1|2 : simplify mode (it replaces curves and surfaces by simplified geometry if possible); 0 = off (by default), 1 = on all the time, 2 = on only for data not coming from Parasolid \n"); MY_PRINTF(" -merge 0|1|2 : merge mode (it merges geomerties and topologies if possible); 0 = off (by default), 1 = on all the time, 2 = on only for data not coming from Parasolid \n"); MY_PRINTF(" -disjoin 0|1 : disjoin mode (it removes some faces from the bodies to avoid PK_FACE_state_bad_face_face_c errors); 0 = off (by default), 1 = on\n"); MY_PRINTF(" -sew 0|1 : sew mode (it sews bodies together if possible); 0 = off, 1 = on (by default)\n"); MY_PRINTF(" -sewexchange 0|1 : sew mode (it sews bodies together if possible); 0 = off, 1 = on (by default) Only applied to non parasolid based formats \n"); MY_PRINTF(" -sewingtolerance real: sewing tolerance for sew mode (1e-4 millimeters by default)\n"); MY_PRINTF(" -iges 0|1 : export to iges file format 0 = off (by default), 1 = on\n"); MY_PRINTF(" -step 0|1 : export to step file format 0 = off (by default), 1 = on\n"); return A3D_ERROR; } int iNbPkParts = 0; PK_PART_t* pPkParts = 0; A3DExport sExport(&iNbPkParts, &pPkParts); // see A3DSDKInternalConvert.hxx for import and export detailed parameters sExport.m_sTranslateToPkPartsData.m_eHealing = kA3DE_HEALING_NO; // Use healing if needed, and on-demand if possible sExport.m_sTranslateToPkPartsData.m_eComputeAccurateEdges = kA3DE_ACCURATE_NO; sExport.m_sTranslateToPkPartsData.m_eSimplifyGeometry = kA3DE_SIMPLIFY_NO; sExport.m_sTranslateToPkPartsData.m_eMergeEntities = kA3DE_MERGE_NO; sExport.m_sTranslateToPkPartsData.m_bDisjoinIfFaceFaceError = false; sExport.m_sTranslateToPkPartsData.m_bSew = true; sExport.m_sTranslateToPkPartsData.m_dSewingTolerance = 1e-4; sExport.m_sTranslateToPkPartsData.m_pcPSBodyShopPath = ""; sExport.m_sTranslateToPkPartsData.m_bUseColour2Attribute = true; sExport.m_sTranslateToPkPartsData.m_uiNbProc = 0; //getLogicalProcessor(); sExport.m_sExportParasolidData.m_bBStrictAssemblyStructure = true; bool bStep = false; bool bIges = false; bool bSewExchange = true; double dSewTolerance = 0.1; MY_CHAR* _pSrcFileName = NULL; MY_CHAR* _pDstFileName = NULL; MY_CHAR* _pLogFileName = NULL; for (int iArg = 1; iArg < iArgc; iArg++) { if (ppcArgv[iArg] != NULL && ppcArgv[iArg][0] == '-') { if (!MY_STRCMP(ppcArgv[iArg], "-log") && iArg + 1 < iArgc) { _pLogFileName = ppcArgv[iArg + 1]; iArg++; } else if (!MY_STRCMP(ppcArgv[iArg], "-healing")) switch (MY_ATOI(ppcArgv[++iArg])) { case 0: sExport.m_sTranslateToPkPartsData.m_eHealing = kA3DE_HEALING_NO; break; case 1: sExport.m_sTranslateToPkPartsData.m_eHealing = kA3DE_HEALING_YES; break; case 2: sExport.m_sTranslateToPkPartsData.m_eHealing = kA3DE_HEALING_ONLY_IF_NOT_PARASOLID; break; } else if (!MY_STRCMP(ppcArgv[iArg], "-accurate")) switch (MY_ATOI(ppcArgv[++iArg])) { case 0: sExport.m_sTranslateToPkPartsData.m_eComputeAccurateEdges = kA3DE_ACCURATE_NO; break; case 1: sExport.m_sTranslateToPkPartsData.m_eComputeAccurateEdges = kA3DE_ACCURATE_YES; break; case 2: sExport.m_sTranslateToPkPartsData.m_eComputeAccurateEdges = kA3DE_ACCURATE_ONLY_IF_NOT_PARASOLID; break; } else if (!MY_STRCMP(ppcArgv[iArg], "-simplify")) switch (MY_ATOI(ppcArgv[++iArg])) { case 0: sExport.m_sTranslateToPkPartsData.m_eSimplifyGeometry = kA3DE_SIMPLIFY_NO; break; case 1: sExport.m_sTranslateToPkPartsData.m_eSimplifyGeometry = kA3DE_SIMPLIFY_YES; break; case 2: sExport.m_sTranslateToPkPartsData.m_eSimplifyGeometry = kA3DE_SIMPLIFY_ONLY_IF_NOT_PARASOLID; break; } else if (!MY_STRCMP(ppcArgv[iArg], "-merge")) switch (MY_ATOI(ppcArgv[++iArg])) { case 0: sExport.m_sTranslateToPkPartsData.m_eMergeEntities = kA3DE_MERGE_NO; break; case 1: sExport.m_sTranslateToPkPartsData.m_eMergeEntities = kA3DE_MERGE_YES; break; case 2: sExport.m_sTranslateToPkPartsData.m_eMergeEntities = kA3DE_MERGE_ONLY_IF_NOT_PARASOLID; break; } else if (!MY_STRCMP(ppcArgv[iArg], "-disjoin")) switch (MY_ATOI(ppcArgv[++iArg])) { case 0: sExport.m_sTranslateToPkPartsData.m_bDisjoinIfFaceFaceError = false; break; case 1: sExport.m_sTranslateToPkPartsData.m_bDisjoinIfFaceFaceError = true; break; } else if (!MY_STRCMP(ppcArgv[iArg], "-sew")) switch (MY_ATOI(ppcArgv[++iArg])) { case 0: sExport.m_sTranslateToPkPartsData.m_bSew = false; break; case 1: sExport.m_sTranslateToPkPartsData.m_bSew = true; break; } else if (!MY_STRCMP(ppcArgv[iArg], "-sewingtolerance")) { dSewTolerance = (MY_ATOF(ppcArgv[++iArg])); sExport.m_sTranslateToPkPartsData.m_dSewingTolerance = dSewTolerance * 0.001; } else if (!MY_STRCMP(ppcArgv[iArg], "-bodyshop")) { if ((MY_ATOI(ppcArgv[++iArg])) == 0) sExport.m_sTranslateToPkPartsData.m_pcPSBodyShopPath = NULL; } else if (!MY_STRCMP(ppcArgv[iArg], "-step")) switch (MY_ATOI(ppcArgv[++iArg])) { case 1: bStep = true; break; } else if (!MY_STRCMP(ppcArgv[iArg], "-iges")) switch (MY_ATOI(ppcArgv[++iArg])) { case 1: bIges = true; break; } else if (!MY_STRCMP(ppcArgv[iArg], "-sewexchange")) switch (MY_ATOI(ppcArgv[++iArg])) { case 0: bSewExchange = false; break; case 1: bSewExchange = true; break; } } else { if (_pSrcFileName == NULL) _pSrcFileName = ppcArgv[iArg]; else if (_pDstFileName == NULL) _pDstFileName = ppcArgv[iArg]; else if (_pLogFileName == NULL) _pLogFileName = ppcArgv[iArg]; } } // if (_pSrcFileName == NULL) MY_STRCPY(acSrcFileName, DEFAULT_INPUT_CAD); else MY_STRCPY(acSrcFileName, _pSrcFileName); if (_pDstFileName == NULL) MY_STRCPY(acDstFileName, acSrcFileName); // The extension .xmt_txt will be added by the API else MY_STRCPY(acDstFileName, _pDstFileName); if (_pLogFileName == NULL) MY_SPRINTF(acLogFileName, "%s.xmt_txt_Log.txt", acDstFileName); else MY_STRCPY(acLogFileName, _pLogFileName); GetLogFile(acLogFileName); // Initialize log file // // ### INITIALIZE HOOPS EXCHANGE // #ifdef _MSC_VER const TCHAR* pcLibPath = _T(""); // As Documented, working directory must be install directory. #else const char* pcLibPath = ""; #endif A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(pcLibPath); CHECK_RET(sHoopsExchangeLoader.m_eSDKStatus); CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree)); CHECK_RET(A3DDllSetCallbacksReport(PrintLogMessage, PrintLogWarning, PrintLogError)); //Check Parsolid Schema path char *workbuff = getenv("P_SCHEMA"); if (workbuff) { PrintLogMessage("P_SCHEMA="); PrintLogMessage(workbuff); PrintLogMessage("\n"); } else PrintLogMessage("P_SCHEMA= missing\n"); // initialize Parasolid PrintLogMessage("Initializing Parasolid...\n"); if (!ParasolidInitialize()) { PrintLogError(0, "Parasolid initialization failure\n"); return A3D_ERROR; } const struct ParasolidCleaner { ~ParasolidCleaner() { ParasolidTerminate(); } } sParasolidCleaner; // // ### PROCESS SAMPLE CODE // // Import Input CAD file A3DImport sImport(acSrcFileName); // see A3DSDKInternalConvert.hxx for import and export detailed parameters if (bStep || bIges) { // direct export to Iges or Step #ifdef _MSC_VER A3DUniChar sDirectOutputPath[_MAX_PATH]; swprintf(sDirectOutputPath, _MAX_PATH, (bIges) ? _T("%s.igs") : _T("%s.stp"), acDstFileName); #else A3DUTF8Char sDirectOutputPath[_MAX_PATH]; sprintf(sDirectOutputPath, (bIges) ? "%s.igs" : "%s.stp", acDstFileName); #endif A3DExport sDirectExport(sDirectOutputPath); PrintLogMessage("Conversion...\n"); CHECK_RET(sHoopsExchangeLoader.Convert(sImport, sDirectExport)); return A3D_SUCCESS; } // ---------------------------------------------------------------------------- // export to parasolid with the bridge sImport.m_sLoadData.m_sSpecifics.m_sParasolid.m_bKeepParsedEntities = true; sImport.m_sLoadData.m_sSpecifics.m_sStep.m_bHealOrientations = true; sImport.m_sLoadData.m_sGeneral.m_eReadGeomTessMode = kA3DReadGeomAndTess; sImport.m_sLoadData.m_sTessellation.m_eTessellationLevelOfDetail = kA3DTessLODMedium; PrintLogMessage("TranslateToPkParts...\n"); A3DStatus iRet = sHoopsExchangeLoader.Import(sImport); if (iRet != A3D_SUCCESS && iRet != A3D_LOAD_MISSING_COMPONENTS) CHECK_RET(iRet); if (bSewExchange) { A3DAsmModelFileData sModelFileData; A3D_INITIALIZE_DATA(A3DAsmModelFileData, sModelFileData); CHECK_RET(A3DAsmModelFileGet(sHoopsExchangeLoader.m_psModelFile, &sModelFileData)); A3DSewOptionsData sSewData; A3D_INITIALIZE_DATA(A3DSewOptionsData, sSewData); if (sModelFileData.m_eModellerType != kA3DModellerJt && sModelFileData.m_eModellerType != kA3DModellerSlw && sModelFileData.m_eModellerType != kA3DModellerUnigraphics && sModelFileData.m_eModellerType != kA3DModellerParasolid && sModelFileData.m_eModellerType != kA3DModellerSE) CHECK_RET(A3DAsmModelFileSew(&sHoopsExchangeLoader.m_psModelFile, dSewTolerance, &sSewData)); CHECK_RET(A3DAsmModelFileGet(nullptr, &sModelFileData)); } // ---------------------------------------------------------------------------- switch (sHoopsExchangeLoader.Export(sExport)) { case A3D_SUCCESS: break; case A3D_HEPB_MISSING: PrintLogError(0, "Can't load HEPB library"); return A3D_ERROR; case A3D_PARASOLID_ERROR_970: PrintLogError(0, "Can't access Parasolid schema"); return A3D_ERROR; case A3D_BODYSHOP_MISSING: PrintLogError(0, "Can't load BodyShop library"); return A3D_ERROR; case A3D_WRITE_KEEPPARSEDENTITIES_DISABLED: PrintLogError(0, "KeepParsedEntities reading option must be enabled when using TranslateToPkParts"); return A3D_ERROR; default: PrintLogError(0, "TranslateToPkParts Failure"); return A3D_ERROR; } A3DUTF8Char acOutPutKeyUTF8[_MAX_PATH]; #ifdef _MSC_VER A3DMiscUTF16ToUTF8(acDstFileName, acOutPutKeyUTF8); #else MY_STRCPY(acOutPutKeyUTF8, acDstFileName); #endif if (!iNbPkParts) { PrintLogError(0, "No part to transmit\n"); return A3D_SUCCESS; } PrintLogMessage("PK_PART_transmit...\n"); PK_PART_transmit_o_t sTransmitOptions; PK_PART_transmit_o_m(sTransmitOptions); sTransmitOptions.transmit_format = PK_transmit_format_text_c; // in order to use PK_PART_transmit_u (for Unicode names), an Unicode frustrum must be defined PK_ERROR_code_t eTransmitStatus = PK_PART_transmit(iNbPkParts, pPkParts, acOutPutKeyUTF8, &sTransmitOptions); // Free Parasolid table (user has to free this pointer) PK_MEMORY_free(pPkParts); if (eTransmitStatus) return eTransmitStatus; // // ### TERMINATE HOOPS EXCHANGE // // Check memory allocations return (int)ListLeaks(); }