Files
Hoops_Exchange/exchange/exchangesource/PRC2XML/PRC2XMLTools.cpp
2025-12-15 23:22:33 +08:00

470 lines
16 KiB
C++

/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 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.
*
***********************************************************************************************************************/
#include <A3DSDKIncludes.h>
#include "PRC2XML.h"
#include <map>
//######################################################################################################################
#define READMAXBIGSTRING 65536
A3DUTF8Char gbigstring[READMAXBIGSTRING]; // 64 kB buffer is OK to store big strings like array of doubles
A3DUns32 gnAllocatedStrings = 0;
//######################################################################################################################
void setDoubleAttribute(_TiXmlElement* psElement, const char* name, double val)
{
// max size of one double: "%.15 " 13+1+15+1=30
A3DUTF8Char* pc = gbigstring;
size_t iwritten = sprintf_s(pc,sizeof(gbigstring)-1, "%.15f", val);
for(size_t i = iwritten - 1; i > 0; i--)
{
if((pc)[i] == '0')
(pc)[i] = 0;
else
break;
}
psElement->SetAttribute(name, pc);
}
//######################################################################################################################
const _TiXmlElement* _FirstChildByAttribute(_TiXmlElement* psElement, const A3DUTF8Char* pcAttribName, void* pValue)
{
A3DUTF8Char buffer[64];
sprintf_s(buffer,sizeof(buffer)-1, "%p", pValue);
const _TiXmlElement* child = psElement->FirstChildElement();
for(; child; child = child->NextSiblingElement())
{
const A3DUTF8Char* pcValue = child->Attribute(pcAttribName);
if(pcValue != NULL && strcmp(pcValue, buffer) == 0)
return child;
}
return NULL;
}
//######################################################################################################################
unsigned int getPRC2XMLID(const A3DEntity* pElement)
{
static std::map<const A3DEntity*, unsigned> mapElementIds;
auto itFound = mapElementIds.find(pElement);
if (itFound == mapElementIds.end())
{
// Just use index in export as unique identifier within the xml
unsigned uiUniqueId = (unsigned)mapElementIds.size();
mapElementIds[pElement] = uiUniqueId;
return uiUniqueId;
}
else
return itFound->second;
}
//######################################################################################################################
void setAttributePtr(const A3DUTF8Char* pcAttribName, const A3DEntity* pElement, _TiXmlElement* setting)
{
setting->SetAttribute(pcAttribName, getPRC2XMLID(pElement));
}
//######################################################################################################################
void setAttributePRC2XMLID(const A3DEntity* pElement, _TiXmlElement* setting)
{
setAttributePtr("uiPRC2XML_ID", pElement, setting);
}
//######################################################################################################################
A3DStatus traversePRC2XMLIDs(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DEntity** pp, _TiXmlElement* setting)
{
if (uiSize > 0)
{
A3DUns32 ui = 0;
_TiXmlElement* uints = new _TiXmlElement(name);
uints->SetAttribute("size", (int)uiSize);
// max size of one uint: "%d " 14+1=15
A3DUns32 uiFormat = 15;
A3DUTF8Char* pc = NULL;
if (uiFormat * uiSize > READMAXBIGSTRING)
{
pc = (A3DUTF8Char*)malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
pc[0] = 0;
gnAllocatedStrings++;
}
else
pc = gbigstring;
size_t uiNext = 0;
for (ui = 0; ui < uiSize; ++ui)
{
int iwritten = sprintf(pc + uiNext, "%u ", getPRC2XMLID(pp[ui]));
uiNext += size_t(iwritten);
}
pc[uiNext] = 0;
uints->SetAttribute("data", pc);
setting->LinkEndChild(uints);
if (uiFormat * uiSize > READMAXBIGSTRING)
free(pc);
}
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseDoubles(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DDouble* pd, _TiXmlElement* setting)
{
if(uiSize > 0)
{
A3DUns32 ui = 0;
_TiXmlElement* doubles = new _TiXmlElement(name);
doubles->SetAttribute("size", (int)uiSize);
// max size of one double: "%.15 " 13+1+15+1=30
A3DUns32 uiFormat = 30;
A3DUTF8Char* pc = NULL;
if(uiFormat*uiSize > READMAXBIGSTRING)
{
pc = (A3DUTF8Char*) malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
pc[0] = 0;
gnAllocatedStrings++;
}
else
pc = gbigstring;
size_t uiNext = 0;
for(ui = 0; ui < uiSize; ++ui)
{
int iwritten = sprintf(pc+uiNext, "%.15f", pd[ui]);
size_t i = size_t(iwritten - 1);
for(; i > 0; i--)
{
if((pc+uiNext)[i] == '0')
(pc+uiNext)[i] = 0;
else
break;
}
(pc+uiNext)[i+1] = L' ';
uiNext += i+2;
}
pc[uiNext-1] = 0;
doubles->SetAttribute("data", pc);
setting->LinkEndChild(doubles);
if(uiFormat*uiSize > READMAXBIGSTRING)
free(pc);
}
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseUInts(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DUns32* pui, _TiXmlElement* setting)
{
if(uiSize > 0)
{
A3DUns32 ui = 0;
_TiXmlElement* uints = new _TiXmlElement(name);
uints->SetAttribute("size", (int)uiSize);
// max size of one uint: "%d " 14+1=15
A3DUns32 uiFormat = 15;
A3DUTF8Char* pc = NULL;
if(uiFormat*uiSize > READMAXBIGSTRING)
{
pc = (A3DUTF8Char*) malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
pc[0] = 0;
gnAllocatedStrings++;
}
else
pc = gbigstring;
size_t uiNext = 0;
for(ui = 0; ui < uiSize; ++ui)
{
int iwritten = sprintf(pc+uiNext, "%u ", pui[ui]);
uiNext += size_t(iwritten);
}
pc[uiNext] = 0;
uints->SetAttribute("data", pc);
setting->LinkEndChild(uints);
if(uiFormat*uiSize > READMAXBIGSTRING)
free(pc);
}
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseUChars(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DUns8* pui, _TiXmlElement* setting)
{
if(uiSize > 0)
{
A3DUns32 ui = 0;
_TiXmlElement* uints = new _TiXmlElement(name);
uints->SetAttribute("size", (int)uiSize);
// max size of one uchar: "%d ": 6
A3DUns32 uiFormat = 6;
A3DUTF8Char* pc = NULL;
if(uiFormat*uiSize > READMAXBIGSTRING)
{
pc = (A3DUTF8Char*) malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
pc[0] = 0;
gnAllocatedStrings++;
}
else
pc = gbigstring;
size_t uiNext = 0;
for(ui = 0; ui < uiSize; ++ui)
{
int iwritten = sprintf(pc+uiNext, "%u ", pui[ui]);
uiNext += size_t(iwritten);
}
pc[uiNext] = 0;
uints->SetAttribute("data", pc);
setting->LinkEndChild(uints);
if(uiFormat*uiSize > READMAXBIGSTRING)
free(pc);
}
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseBools(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DBool* pb, _TiXmlElement* setting)
{
if(uiSize > 0)
{
A3DUns32 ui = 0;
_TiXmlElement* bools = new _TiXmlElement(name);
bools->SetAttribute("size", (int) uiSize);
// max size of one bool: 2
A3DUns32 uiFormat = 2;
A3DUTF8Char* pc = NULL;
if(uiFormat*uiSize > READMAXBIGSTRING)
{
pc = (A3DUTF8Char*) malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
pc[0] = 0;
gnAllocatedStrings++;
}
else
pc = gbigstring;
size_t uiNext = 0;
for(ui = 0; ui < uiSize; ++ui)
{
int iwritten = sprintf(pc+uiNext, "%u ", pb[ui] ? 1 : 0);
uiNext += size_t(iwritten);
}
pc[uiNext] = 0;
bools->SetAttribute("data", pc);
setting->LinkEndChild(bools);
if(uiFormat*uiSize > READMAXBIGSTRING)
free(pc);
}
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traversePoint(const A3DUTF8Char* name, const A3DVector3dData& sData, _TiXmlElement* setting)
{
_TiXmlElement* pt = new _TiXmlElement(name);
setDoubleAttribute(pt, "m_dX", sData.m_dX);
setDoubleAttribute(pt, "m_dY", sData.m_dY);
setDoubleAttribute(pt, "m_dZ", sData.m_dZ);
setting->LinkEndChild(pt);
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traversePoint2d(const A3DUTF8Char* name, const A3DVector2dData& sData, _TiXmlElement* setting)
{
_TiXmlElement* pt = new _TiXmlElement(name);
setDoubleAttribute(pt, "m_dX", sData.m_dX);
setDoubleAttribute(pt, "m_dY", sData.m_dY);
setting->LinkEndChild(pt);
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traversePoints(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DVector3dData* pv, _TiXmlElement* setting)
{
if(uiSize > 0)
{
A3DDouble* pd = (A3DDouble*) malloc(size_t(uiSize) * 3 * sizeof(A3DDouble));
if(pd == NULL)
return A3D_ALLOC_FATAL_ERROR;
for(A3DUns32 ui = 0; ui < uiSize; ++ui)
{
pd[3*ui] = pv[ui].m_dX;
pd[3*ui+1] = pv[ui].m_dY;
pd[3*ui+2] = pv[ui].m_dZ;
}
traverseDoubles(name, 3*uiSize, pd, setting);
free(pd);
}
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseInterval(const A3DIntervalData* pData, _TiXmlElement* setting)
{
_TiXmlElement* extent1d = new _TiXmlElement("A3DIntervalData");
setDoubleAttribute(extent1d, "m_dMin", pData->m_dMin);
setDoubleAttribute(extent1d, "m_dMax", pData->m_dMax);
setting->LinkEndChild(extent1d);
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseDomain(const A3DDomainData* pData, _TiXmlElement* setting)
{
_TiXmlElement* extent2d = new _TiXmlElement("A3DDomainData");
setDoubleAttribute(extent2d, "m_sMin.m_dX", pData->m_sMin.m_dX);
setDoubleAttribute(extent2d, "m_sMin.m_dY", pData->m_sMin.m_dY);
setDoubleAttribute(extent2d, "m_sMax.m_dX", pData->m_sMax.m_dX);
setDoubleAttribute(extent2d, "m_sMax.m_dY", pData->m_sMax.m_dY);
setting->LinkEndChild(extent2d);
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseBoundingBox(const A3DBoundingBoxData* pData, _TiXmlElement* setting)
{
_TiXmlElement* extent3d = new _TiXmlElement("A3DBoundingBoxData");
setDoubleAttribute(extent3d, "m_sMin.m_dX", pData->m_sMin.m_dX);
setDoubleAttribute(extent3d, "m_sMin.m_dY", pData->m_sMin.m_dY);
setDoubleAttribute(extent3d, "m_sMin.m_dZ", pData->m_sMin.m_dZ);
setDoubleAttribute(extent3d, "m_sMax.m_dX", pData->m_sMax.m_dX);
setDoubleAttribute(extent3d, "m_sMax.m_dY", pData->m_sMax.m_dY);
setDoubleAttribute(extent3d, "m_sMax.m_dZ", pData->m_sMax.m_dZ);
setting->LinkEndChild(extent3d);
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseParam(const A3DParameterizationData* pData, _TiXmlElement* setting)
{
_TiXmlElement* param = new _TiXmlElement("A3DParameterizationData");
setDoubleAttribute(param, "m_sInterval.m_dMin", pData->m_sInterval.m_dMin);
setDoubleAttribute(param, "m_sInterval.m_dMax", pData->m_sInterval.m_dMax);
setDoubleAttribute(param, "m_dCoeffA", pData->m_dCoeffA);
setDoubleAttribute(param, "m_dCoeffB", pData->m_dCoeffB);
setting->LinkEndChild(param);
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseUVParam(const A3DUVParameterizationData* pData, _TiXmlElement* setting)
{
_TiXmlElement* param = new _TiXmlElement("A3DUVParameterizationData");
traverseDomain(&pData->m_sUVDomain, param);
setDoubleAttribute(param, "m_dUCoeffA", pData->m_dUCoeffA);
setDoubleAttribute(param, "m_dUCoeffB", pData->m_dUCoeffB);
setDoubleAttribute(param, "m_dVCoeffA", pData->m_dVCoeffA);
setDoubleAttribute(param, "m_dVCoeffB", pData->m_dVCoeffB);
setDoubleAttribute(param, "m_bSwapUV", (int)pData->m_bSwapUV);
setting->LinkEndChild(param);
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseCartesianTransformationData(const A3DMiscCartesianTransformationData& oTrsf, _TiXmlElement* setting)
{
_TiXmlElement* trsf = new _TiXmlElement("A3DMiscCartesianTransformationData");
trsf->SetAttribute("m_ucBehaviour", (int)(oTrsf.m_ucBehaviour));
traversePoint("m_sOrigin" , oTrsf.m_sOrigin , trsf);
traversePoint("m_sXVector", oTrsf.m_sXVector, trsf);
traversePoint("m_sYVector", oTrsf.m_sYVector, trsf);
traversePoint("m_sScale" , oTrsf.m_sScale , trsf);
setting->LinkEndChild(trsf);
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseCartesianTransformation(const A3DMiscCartesianTransformation* pTrsf, _TiXmlElement* setting)
{
if (pTrsf)
{
A3DMiscCartesianTransformationData sData;
A3D_INITIALIZE_DATA(A3DMiscCartesianTransformationData, sData);
A3DStatus iRet = A3DMiscCartesianTransformationGet(pTrsf, &sData);
if (iRet == A3D_SUCCESS)
{
traverseCartesianTransformationData(sData, setting);
A3DMiscCartesianTransformationGet(NULL, &sData);
}
else
{
setting->SetAttribute("error", A3DMiscGetErrorMsg(iRet));
}
}
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseGeneralTransformation(const A3DMiscGeneralTransformation* pTrsf, _TiXmlElement* setting)
{
_TiXmlElement* trsf = new _TiXmlElement("A3DMiscGeneralTransformationData");
A3DMiscGeneralTransformationData sData;
A3D_INITIALIZE_DATA(A3DMiscGeneralTransformationData, sData);
A3DStatus iRet = A3DMiscGeneralTransformationGet(pTrsf, &sData);
if (iRet == A3D_SUCCESS)
{
traverseDoubles("m_adCoeff", 16, sData.m_adCoeff, trsf);
A3DMiscGeneralTransformationGet(NULL, &sData);
}
else
{
trsf->SetAttribute("error", A3DMiscGetErrorMsg(iRet));
}
setting->LinkEndChild(trsf);
return A3D_SUCCESS;
}
//######################################################################################################################
A3DStatus traverseTransformation(const A3DMiscTransformation* pTransfo3d, _TiXmlElement* setting)
{
if(pTransfo3d == NULL)
return A3D_SUCCESS;
A3DStatus iRet;
_TiXmlElement* trsf = new _TiXmlElement("A3DMiscTransformation");
traverseSource(pTransfo3d, trsf);
A3DEEntityType eType = kA3DTypeUnknown;
iRet = A3DEntityGetType(pTransfo3d, &eType);
if (eType == kA3DTypeMiscCartesianTransformation)
{
iRet = traverseCartesianTransformation(pTransfo3d, trsf);
}
else if (eType == kA3DTypeMiscGeneralTransformation)
{
iRet = traverseGeneralTransformation(pTransfo3d, trsf);
}
else
{
trsf->SetAttribute("error", A3DMiscGetErrorMsg(iRet));
}
setting->LinkEndChild(trsf);
return iRet;
}