/*********************************************************************************************************************** * * 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 #include "PRC2XML.h" #include //###################################################################################################################### #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 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; }