/*********************************************************************************************************************** * * 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. * ***********************************************************************************************************************/ /* This sample demonstrates how to use HOOPS Exchange with a .NET wrapper by converting any CAD file to XT. ***********************************************************************************************************************/ #pragma warning(disable: 4505) // "unreferenced local function has been removed" #include #define INITIALIZE_A3D_API #include #include #include "Translation.h" using namespace System; using namespace System::Collections::Generic; using namespace System::Text; using namespace System::Runtime::InteropServices; // If you're seeing three CS0246 errors right below (concerning unknown namespaces), // coupled with a few dozens of MSB3258 and MSB3274 warnings in the ConsoleApplication project, // it's because of a known Visual Studio bug happening when using more recent versions than Visual Studio 2008. // To properly compile, simply go to the Properties of ConsoleApplication, and in the Application tab, // select Target Framework and choose ".NET Framework 4.0". namespace TechSoft3D { namespace HOOPS { static bool stBreakTranslation = false; #define CHECK_CANCEL_OPERATION if(stBreakTranslation) { \ throw (gcnew System::OperationCanceledException()); } \ //############################################################################################################## char* ConvertString(String^ text) { array ^chars = Encoding::ASCII->GetBytes(text); pin_ptr charsPointer = &(chars[0]); char *nativeCharsPointer = reinterpret_cast(static_cast(charsPointer)); std::string ret(nativeCharsPointer, chars->Length); return _strdup(ret.c_str()); } //############################################################################################################## bool ConvertString(A3DUTF8Char* pTextUTF8, String^% sUnicode) { TCHAR pcUnicode[256]; A3DMiscUTF8ToUTF16(pTextUTF8, pcUnicode); StringBuilder^ buf = gcnew StringBuilder(256); //UTF8Encoding^ utf8 = gcnew UTF8Encoding(); size_t i, iCharCount = _tcslen(pcUnicode); for(i = 0; i < iCharCount; ++i) buf->Insert(int(i), pcUnicode[i]); sUnicode = buf->ToString(); return true; } //############################################################################################################## static A3DInt32 stbreak = 0; static bool stbA3DLoaded = false; static FILE* stOut = stdout; static int stiSize = 0; //############################################################################################################## A3DInt32 ReportMessage(A3DUTF8Char* pMsg) { CHECK_CANCEL_OPERATION; String^ sMsg; if (Exchange::stm_pFctReportMessage && ConvertString(pMsg, sMsg)) Exchange::stm_pFctReportMessage(sMsg); if (stOut) return fprintf(stOut, "%s", pMsg); return 0; } //############################################################################################################## A3DInt32 ReportWarning(A3DUTF8Char* pCode, A3DUTF8Char* pMsg) { CHECK_CANCEL_OPERATION; String^ sMsg; String^ sCode; if (Exchange::stm_pFctReportWarning && ConvertString(pCode, sCode) && ConvertString(pMsg, sMsg)) Exchange::stm_pFctReportWarning(sCode, sMsg); if (stOut) return fprintf(stOut, "WARNING(%pCode) %s", pCode, pMsg); else return 0; } //############################################################################################################## A3DInt32 ReportError(A3DUTF8Char* pCode, A3DUTF8Char* pMsg) { CHECK_CANCEL_OPERATION; String^ sMsg; String^ sCode; if (Exchange::stm_pFctReportError && ConvertString(pCode, sCode)&& ConvertString(pMsg, sMsg)) Exchange::stm_pFctReportError(sCode,sMsg); if (stOut) return fprintf(stOut, "ERROR(%pCode) %s", pCode, pMsg); else return 0; } //############################################################################################################## void stStartPrg(A3DInt32 i) { CHECK_CANCEL_OPERATION; if(Exchange::stm_pFCTStart) Exchange::stm_pFCTStart(i); } //############################################################################################################## void stTitlePrg(A3DUTF8Char* pChar) { CHECK_CANCEL_OPERATION; String^ sTitle; if(Exchange::stm_pFCTTitle && ConvertString(pChar, sTitle)) Exchange::stm_pFCTTitle(sTitle); } //############################################################################################################## void stSizePrg(A3DInt32 i) { CHECK_CANCEL_OPERATION; stiSize = i; if(Exchange::stm_pFCTSize) Exchange::stm_pFCTSize(i); } //############################################################################################################## void stIncPrg(A3DInt32 i) { CHECK_CANCEL_OPERATION; if (i > stiSize) i = stiSize; if (Exchange::stm_pFCTIncr) Exchange::stm_pFCTIncr(i); } //############################################################################################################## void stEndPrg() { CHECK_CANCEL_OPERATION; stIncPrg(stiSize); if(Exchange::stm_pFCTEnd) Exchange::stm_pFCTEnd(); } //############################################################################################################## A3DStatus ScaleProductOccurence(A3DAsmProductOccurrence* pPOccurrences, double dScale) { // accessing the ProductOccurence transformation: A3DAsmProductOccurrenceData sPOccurrencesData; A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sPOccurrencesData); A3DAsmProductOccurrenceGet(pPOccurrences, &sPOccurrencesData); A3DStatus iRet = A3D_SUCCESS; if(!sPOccurrencesData.m_pLocation) { A3DMiscGeneralTransformationData sData; A3D_INITIALIZE_DATA(A3DMiscGeneralTransformationData, sData); sData.m_adCoeff[0] = dScale; sData.m_adCoeff[5] = dScale; sData.m_adCoeff[10] = dScale; sData.m_adCoeff[15] = 1.0; A3DMiscCartesianTransformation* pNewScaledTransfo; iRet = A3DMiscGeneralTransformationCreate(&sData,&pNewScaledTransfo); sPOccurrencesData.m_pLocation = pNewScaledTransfo; iRet = A3DAsmProductOccurrenceEdit(&sPOccurrencesData, pPOccurrences); A3DAsmProductOccurrenceGet(NULL, &sPOccurrencesData); return iRet; } A3DEEntityType eType = kA3DTypeUnknown; A3DEntityGetType(sPOccurrencesData.m_pLocation, &eType); // Two types of transformation exist in HOOPS Exchange: CartesianTransformation and GeneralTransformation switch (eType) { case kA3DTypeMiscCartesianTransformation : { // getting the original transformation A3DMiscCartesianTransformationData sData; A3D_INITIALIZE_DATA(A3DMiscCartesianTransformationData, sData); iRet = A3DMiscCartesianTransformationGet(sPOccurrencesData.m_pLocation, &sData); if(iRet != A3D_SUCCESS) return iRet; // creating a new scaled CartesianTransformation from the existing one sData.m_sScale.m_dX *= dScale; sData.m_sScale.m_dY *= dScale; sData.m_sScale.m_dZ *= dScale; A3DMiscCartesianTransformation* pNewScaledTransfo; iRet = A3DMiscCartesianTransformationCreate(&sData, &pNewScaledTransfo); if(iRet!= A3D_SUCCESS) return iRet; iRet = A3DMiscCartesianTransformationGet(NULL, &sData); if(iRet!= A3D_SUCCESS) return iRet; sPOccurrencesData.m_pLocation = pNewScaledTransfo; } break; case kA3DTypeMiscGeneralTransformation : { // getting the original transformation A3DMiscGeneralTransformationData sData; A3D_INITIALIZE_DATA(A3DMiscGeneralTransformationData, sData); iRet = A3DMiscGeneralTransformationGet(sPOccurrencesData.m_pLocation, &sData); if(iRet != A3D_SUCCESS) return iRet; // creating a new scaled CartesianTransformation from the existing one sData.m_adCoeff[0] *= dScale; sData.m_adCoeff[1] *= dScale; sData.m_adCoeff[2] *= dScale; sData.m_adCoeff[4] *= dScale; sData.m_adCoeff[5] *= dScale; sData.m_adCoeff[6] *= dScale; sData.m_adCoeff[8] *= dScale; sData.m_adCoeff[9] *= dScale; sData.m_adCoeff[10] *= dScale; A3DMiscGeneralTransformation* pNewGeneralTransfo; iRet = A3DMiscGeneralTransformationCreate(&sData, &pNewGeneralTransfo); if( iRet!= A3D_SUCCESS) return iRet; iRet = A3DMiscGeneralTransformationGet(NULL, &sData); if( iRet!= A3D_SUCCESS) return iRet; sPOccurrencesData.m_pLocation = pNewGeneralTransfo; } break; default : return A3D_ERROR; } iRet = A3DAsmProductOccurrenceEdit(&sPOccurrencesData, pPOccurrences); A3DAsmProductOccurrenceGet(NULL, &sPOccurrencesData); return A3D_SUCCESS; } //############################################################################################################## bool Exchange::Init() { # ifdef _WIN64 const TCHAR* pcLibPath = _T("..\\..\\..\\..\\..\\..\\bin\\win64_v142\\"); # else const TCHAR* pcLibPath = _T("..\\..\\..\\..\\..\\..\\bin\\win32_v142\\"); # endif if(!A3DSDKLoadLibrary(pcLibPath)) { printf("Cannot load the HOOPS Exchange library\n"); return false; } A3DLicPutUnifiedLicense(HOOPS_LICENSE); A3DInt32 iMajorVersion = 0, iMinorVersion = 0; A3DDllGetVersion(&iMajorVersion, &iMinorVersion); if(A3DDllInitialize(A3D_DLL_MAJORVERSION, A3D_DLL_MINORVERSION) != A3D_SUCCESS) { printf("Cannot initialize the HOOPS Exchange library\n"); A3DSDKUnloadLibrary(); return false; } stbA3DLoaded = true; stbreak = 0; A3DDllSetCallbacksProgress(stStartPrg, stSizePrg, stIncPrg, stEndPrg, stTitlePrg, &stbreak); A3DDllSetCallbacksReport(ReportMessage, ReportWarning, ReportError); return true; } //############################################################################################################## void Exchange::SetLogFile(String^ LogFileName) { if(stOut && stOut != stdout) fclose(stOut); if(fopen_s(&stOut, ConvertString(LogFileName), "w") != 0) stOut = stdout; } //############################################################################################################## void Exchange::SetUnit(double dUnit) { m_dUnit = dUnit; } //############################################################################################################## bool Exchange::IsProEFile(String^ FileName) { A3DEModellerType sModellerType; A3DGetFileFormat(ConvertString(FileName),&sModellerType); return (sModellerType == kA3DModellerProE); } //############################################################################################################## void Exchange::SetLoadParametersOptions(A3DRWParamsLoadData & sLoadParametersData, IDictionary^ sOptions) { #define MACRO_SET_CAT_OPTION_BOOL(CAT,KEY) \ { \ String^ sKey = #CAT+"."+#KEY; \ if(kvp.Key == sKey && kvp.Value == "true") \ sLoadParametersData.m_s##CAT.m_b##KEY = true; \ } #define MACRO_SET_SUBCAT_OPTION_BOOL(CAT,SUBCAT,KEY) \ { \ String^ sKey = #CAT+"."+#SUBCAT+"."+#KEY; \ if(kvp.Key == sKey && kvp.Value == "true") \ sLoadParametersData.m_s##CAT.m_s##SUBCAT.m_b##KEY = true; \ } #define MACRO_SET_SUBCAT_OPTION_STRING(CAT,SUBCAT,KEY) \ { \ String^ sKey = #CAT+"."+#SUBCAT+"."+#KEY; \ if(kvp.Key == sKey) \ sLoadParametersData.m_s##CAT.m_s##SUBCAT.m_pc##KEY = ConvertString(kvp.Value); \ } for each(KeyValuePair kvp in sOptions) { MACRO_SET_CAT_OPTION_BOOL(General, ReadSolids); MACRO_SET_CAT_OPTION_BOOL(General, ReadSurfaces); MACRO_SET_CAT_OPTION_BOOL(General, ReadWireframes); MACRO_SET_CAT_OPTION_BOOL(General, ReadConstructionAndReferences); MACRO_SET_CAT_OPTION_BOOL(General, ReadActiveFilter); MACRO_SET_CAT_OPTION_BOOL(General, ReadAttributes); MACRO_SET_CAT_OPTION_BOOL(Assembly, UseRootDirectory); MACRO_SET_CAT_OPTION_BOOL(Assembly, RootDirRecursive); MACRO_SET_SUBCAT_OPTION_BOOL(Specifics, IGES, SewBrepModels); MACRO_SET_SUBCAT_OPTION_STRING(Specifics, CatiaV4, RootDirLogicalName); MACRO_SET_SUBCAT_OPTION_BOOL(Specifics, CatiaV4, AllowSearchInOtherLogicalNames); MACRO_SET_SUBCAT_OPTION_BOOL(Specifics, Step, PreferProductName); MACRO_SET_SUBCAT_OPTION_BOOL(Specifics, Step, PreferFirstColor); if(kvp.Key->Contains("SearchDir") && kvp.Key->Contains("PhysicalPath")) { String^ Indice = kvp.Key; array^chars = {'[',']'}; array^aIndice = Indice->Split( chars ); int myInt = System::Convert::ToInt32(aIndice[1]); unsigned int uSize = sLoadParametersData.m_sAssembly.m_uiSearchDirectoriesSize; if(uSize == 0) { sLoadParametersData.m_sAssembly.m_ppcSearchDirectories = (A3DRWParamsSearchDirData**) malloc(sizeof(A3DRWParamsSearchDirData*)*(myInt + 1)); sLoadParametersData.m_sAssembly.m_uiSearchDirectoriesSize = myInt + 1; sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[0] = NULL; } else if((unsigned) myInt >= uSize) { sLoadParametersData.m_sAssembly.m_ppcSearchDirectories = (A3DRWParamsSearchDirData**) realloc(sLoadParametersData.m_sAssembly.m_ppcSearchDirectories, sizeof(A3DRWParamsSearchDirData*) * (myInt + 1)); sLoadParametersData.m_sAssembly.m_uiSearchDirectoriesSize = myInt + 1; sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[myInt] = NULL; } if(sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[myInt] == NULL) { sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[myInt] = (A3DRWParamsSearchDirData*) malloc(sizeof(A3DRWParamsSearchDirData)); A3D_INITIALIZE_DATA(A3DRWParamsSearchDirData, *(sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[myInt])); } sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[myInt]->m_pcPhysicalPath = ConvertString(kvp.Value); } if(kvp.Key->Contains("SearchDir") && kvp.Key->Contains("Recursive")) { String^ Indice = kvp.Key; array^chars = {'[',']'}; array^aIndice = Indice->Split(chars); int myInt = System::Convert::ToInt32(aIndice[1]); unsigned int uSize = sLoadParametersData.m_sAssembly.m_uiSearchDirectoriesSize; if(uSize == 0) { sLoadParametersData.m_sAssembly.m_ppcSearchDirectories = (A3DRWParamsSearchDirData**) malloc(sizeof(A3DRWParamsSearchDirData*)*(myInt + 1)); sLoadParametersData.m_sAssembly.m_uiSearchDirectoriesSize = myInt + 1; sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[0] = NULL; } else if((unsigned) myInt >= uSize) { sLoadParametersData.m_sAssembly.m_ppcSearchDirectories = (A3DRWParamsSearchDirData**) realloc(sLoadParametersData.m_sAssembly.m_ppcSearchDirectories, sizeof(A3DRWParamsSearchDirData*) * (myInt + 1)); sLoadParametersData.m_sAssembly.m_uiSearchDirectoriesSize = myInt + 1; sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[0] = NULL; } if(sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[myInt] == NULL) { sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[myInt] = (A3DRWParamsSearchDirData*) malloc(sizeof(A3DRWParamsSearchDirData)); A3D_INITIALIZE_DATA(A3DRWParamsSearchDirData, *(sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[myInt])); } sLoadParametersData.m_sAssembly.m_ppcSearchDirectories[myInt]->m_bRecursive = (kvp.Value == "true"); } } } //############################################################################################################## bool Exchange::ConvertToXT(String^ SourceFileName, String^ DestinationFileName, IDictionary^ sOptions) { A3DAsmModelFile* modelFile = NULL; try { A3DRWParamsLoadData sLoadParametersData; A3D_INITIALIZE_DATA(A3DRWParamsLoadData, sLoadParametersData); // default values sLoadParametersData.m_sGeneral.m_bReadSolids = true; sLoadParametersData.m_sGeneral.m_bReadSurfaces = true; sLoadParametersData.m_sGeneral.m_bReadAttributes = true; sLoadParametersData.m_sGeneral.m_bReadWireframes = true; sLoadParametersData.m_sAssembly.m_bUseRootDirectory = true; // optional values SetLoadParametersOptions(sLoadParametersData,sOptions); // specific syntax for each(KeyValuePair kvp in sOptions) { if(kvp.Key == "WriteBlankedEntities" && kvp.Value == "true") sLoadParametersData.m_sGeneral.m_bReadHiddenObjects = true; } //if(Exchange::stm_pFCTTitle) // Exchange::stm_pFCTTitle("A3DAsmModelFileLoadFromFile"); A3DStatus status = A3DAsmModelFileLoadFromFile(ConvertString(SourceFileName), &sLoadParametersData, &modelFile); if(status == A3D_LOAD_MISSING_COMPONENTS) { printf("HOOPS Exchange CAD file missing components\n"); status = A3D_SUCCESS; } if(status) printf("HOOPS Exchange CAD file loading failure\n"); // changing the unit if(m_dUnit != 1000) // applying a scale { A3DAsmModelFileData sModelFileData; A3D_INITIALIZE_DATA(A3DAsmModelFileData, sModelFileData); A3DAsmModelFileGet(modelFile, &sModelFileData); unsigned int uI; for(uI = 0; uI < sModelFileData.m_uiPOccurrencesSize; uI++) { status = ScaleProductOccurence(sModelFileData.m_ppPOccurrences[uI], 1000 / m_dUnit); if(status) printf("HOOPS Exchange failed to apply the unit\n"); } A3DAsmModelFileGet(NULL, &sModelFileData); } if(status == A3D_SUCCESS) { A3DRWParamsExportParasolidData sExportParameters; A3D_INITIALIZE_DATA(A3DRWParamsExportParasolidData, sExportParameters); // specific syntax for each(KeyValuePair kvp in sOptions) { if(kvp.Key == "WriteBlankedEntities" && kvp.Value == "true") sExportParameters.m_bWriteBlankedEntities = true; } //if(Exchange::stm_pFCTTitle) // Exchange::stm_pFCTTitle("A3DAsmModelFileExportToParasolidFile"); status = A3DAsmModelFileExportToParasolidFile(modelFile, &sExportParameters, ConvertString(DestinationFileName)); if(status) printf("HOOPS Exchange Parasolid export failure\n"); //if(Exchange::stm_pFCTTitle) // Exchange::stm_pFCTTitle("End"); A3DAsmModelFileDelete(modelFile); return status == A3D_SUCCESS; } A3DAsmModelFileDelete(modelFile); stbreak=0; return false; } catch(OperationCanceledException ^) { A3DAsmModelFileDelete(modelFile); stBreakTranslation = m_bBreakTranslation = false; Terminate(); Init(); return false; } } //############################################################################################################## void Exchange::Break() { stBreakTranslation = m_bBreakTranslation = true; } //############################################################################################################## void Exchange::Terminate() { if(stbA3DLoaded) { A3DDllTerminate(); A3DSDKUnloadLibrary(); stbA3DLoaded = false; } } //############################################################################################################## void Exchange::SetCallBackFct(CallbackStart^ pFCTStart, CallbackTitle^ pFCTTitle, CallbackSize^ pFCTSize, CallbackIncrement^ pFCTIncr, CallbackEnd^ pFCTEnd) { stm_pFCTStart = pFCTStart; stm_pFCTTitle = pFCTTitle; stm_pFCTSize = pFCTSize; stm_pFCTIncr = pFCTIncr; stm_pFCTEnd = pFCTEnd; } //############################################################################################################## void Exchange::SetCallBackMessageFct(CallbackReportMessage^ fctReportMessage,CallbackReportWarning^ fctReportWarning, CallbackReportError^ fctReportError) { stm_pFctReportMessage = fctReportMessage; stm_pFctReportWarning = fctReportWarning; stm_pFctReportError = fctReportError; if(stOut == stdout) stOut = 0; } //############################################################################################################## Exchange::Exchange() { m_dUnit = 1000; stBreakTranslation = m_bBreakTranslation = false; } //############################################################################################################## Exchange::!Exchange() { if(stOut && stOut != stdout) fclose(stOut); stOut = stdout; Terminate(); } //############################################################################################################## Exchange::~Exchange() { Terminate(); } } }