Files
Hoops_Exchange/exchange/exchangesource/NetWrapper/Translation.cpp
2025-12-15 22:06:49 +08:00

584 lines
21 KiB
C++

/***********************************************************************************************************************
*
* 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 <string>
#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>
#include <hoops_license.h>
#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<Byte> ^chars = Encoding::ASCII->GetBytes(text);
pin_ptr<Byte> charsPointer = &(chars[0]);
char *nativeCharsPointer = reinterpret_cast<char *>(static_cast<unsigned char *>(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<String^,
String^>^ 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<String^,String^> 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<Char>^chars = {'[',']'};
array<String^>^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<Char>^chars = {'[',']'};
array<String^>^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<String^,
String^>^ 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<String^,String^> 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<String^,String^> 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();
}
}
}