#include "stdafx.h" #include "geassign.h" #include "acutmem.h" #include "AecDbObjXDataMap.h" #include "AecDbObjXDataMapObj.h" #include #include "comdef.h" #include "Base64.h" #include "BIMEntity.h" #include "shJson.h" #include "Base64.h" #include "EarThwormDef.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #define MAP_BLOCK_BEGIN _T("TDBXDATAMAP_BLOCK_BEGIN_") #define MAP_BLOCK_END _T("TDBXDATAMAP_BLOCK_END_") #define DIF_VT_PT _T("$vector3d") // 设置向量是在键值pszkey后增加字符串"$vector3d",与点进行区分 #define BIM_REC_LEN _T("_`!@#$^&*BIM_REC_LEN*&^$#@!`_") #define MAX_BINARYCHUNK 127 #define BINARY_CHUNKBLOCKS "binarychunkblocks" #define BINARY_CHUNKBLOCKS1 "binarychunkblocks:" #ifndef _ttof #define _ttof(pszVal) _tcstod((pszVal), NULL) #endif // 文件头版本号(魔数 'AEC' + 版本),仅用于区分「有版本头 / 无版本头(老格式带 Base64 块标记)」。 const int AecDbObjXDataMap::g_nVersion = 0x41454301; // 'AEC' + 0x01 // 矩阵二进制块结构:[int 魔数][16个double],共 4+128=132 字节。 // 魔数写在块头,读取时先读一个 int:等于魔数即为新的二进制结构,否则是旧的字符串结构。 // (pData 与 pszVal 是同一个 union,不能靠它们区分,故用块头魔数) static const int kMatrixMagic = 0x4D5458A5; // 'M''T''X' + 0xA5(非可打印,不会与字符串首字符冲突) static const int kMatrixBinBytes = (int)(sizeof(int) + 16 * sizeof(double)); // 132 // 数组二进制块结构:[int 容器魔数][int 元素类型][int 元素个数][元素数据...]。 // 用"一个容器魔数 + 元素类型字段"来表达数组,而不是"每种元素类型一个魔数/类型标签": // 新增元素类型(如 int/string 数组)时,只需扩展元素的编解码,无需新增魔数或类型标签。 // 元素类型沿用 AecXData::EType 的值(如 kTypeDouble / kTypePoint)。 // 数组沿用 kTypeBinary 保存(而非新增类型标签),这样可直接复用各处对 kTypeBinary 的 // 序列化处理(XData/DXF/DWG/JSON/CFile 等),无需逐个 switch 增加分支。 // 另外:XData/DXF 的二进制块本身不携带自定义标签(见 Resbuf2XDMap,二进制块统一还原为 // kTypeBinary),所以"自描述的块头"对数组是必要的,单靠 nVt 标签并不可靠。 static const int kArrayMagic = 0x41525259; // 'A''R''R''Y' using namespace SHJson; namespace { WValue& toJson(const AcGePoint3d &pt, WValue &v) { v.SetObject(); addMember(v, _T("x"), pt.x); addMember(v, _T("y"), pt.y); addMember(v, _T("z"), pt.z); return v; } bool byJson(const WValue &v, AcGePoint3d &pt) { if (v.HasMember(_T("x")) && v.HasMember(_T("y")) && v.HasMember(_T("z"))) { pt.x = v[_T("x")].GetDouble(); pt.y = v[_T("y")].GetDouble(); pt.z = v[_T("z")].GetDouble(); return true; } return false; } WValue& toJson(const AcGeVector3d &vt, WValue &v) { return toJson(AcGePoint3d(vt.x, vt.y, vt.z), v); } bool byJson(const WValue &v, AcGeVector3d &vt) { AcGePoint3d pt; if (byJson(v, pt)) { vt.x = pt.x; vt.y = pt.y; vt.z = pt.z; } return false; } WValue& toJson(const AcGeMatrix3d &mat, WValue &m) { m.SetObject(); AcGeVector3d x, y, z; AcGePoint3d o; mat.getCoordSystem(o, x, y, z); WValue jX, jY, jZ, jO; toJson(x, jX); toJson(y, jY); toJson(z, jZ); toJson(o, jO); addMember(m, _T("x"), jX); addMember(m, _T("y"), jY); addMember(m, _T("z"), jZ); addMember(m, _T("o"), jO); return m; } bool byJson(const WValue &v, AcGeMatrix3d &mat) { MCIt itX(v.FindMember(_T("x"))); MCIt itY(v.FindMember(_T("y"))); MCIt itZ(v.FindMember(_T("z"))); MCIt itO(v.FindMember(_T("o"))); if (itX != v.MemberEnd() && itY != v.MemberEnd() && itZ != v.MemberEnd() && itO != v.MemberEnd()) { AcGeVector3d x, y, z; AcGePoint3d o; byJson(itX->value, x); byJson(itY->value, y); byJson(itZ->value, z); byJson(itO->value, o); mat.setCoordSystem(o, x, y, z); } return false; } // 矩阵内部以 [魔数][16个double] 的二进制块保存(pData, npszLen=132)。 // 只能保存文本的通道(XData/DXF/DWG/JSON等)仍按逗号分隔文本读写,用下面的函数转换。 // 判断矩阵是否为二进制块:看块头魔数; // 注意 pData 与 pszVal 是同一个 union,不能靠它们区分,故把魔数写进块头。 bool IsMatrixBinary(const AecXData &xdata) { if (xdata.nVt != AecXData::kTypeMatrix || xdata.pData == NULL) return false; if (xdata.npszLen < (LONG_PTR)sizeof(int)) return false; return *(const int *)xdata.pData == kMatrixMagic; } void MatrixToText(const AecXData &xdata, CString &sText) { sText.Empty(); if (xdata.nVt != AecXData::kTypeMatrix) return; if (IsMatrixBinary(xdata)) { // 二进制块:[魔数][16个double] → 逗号分隔文本 const double *p = (const double *)((const int *)xdata.pData + 1); CString sTemp; for (int i = 0; i < 16; i++) { sTemp.Format(_T("%.9f"), p[i]); if (i > 0) sText += _T(","); sText += sTemp; } } else if (xdata.pszVal != NULL) { // 旧的字符串形式:原样返回 sText = xdata.pszVal; } } BOOL Script2StringArray(const CString &sScript, TCHAR tSpace, CStringArray &arTexts) { //x,y,z,d,a int nPos = -1, nStart = 0; CString sText; while (TRUE) { nPos = sScript.Find(tSpace, nStart); if (nPos != -1) { sText = sScript.Mid(nStart, nPos - nStart); arTexts.Add(sText); nStart = nPos + 1; } else { if (nStart <= sScript.GetLength() - 1) { sText = sScript.Mid(nStart); arTexts.Add(sText); } break; } } return arTexts.GetSize() > 0; } bool TextToMatrix(const TCHAR *pszText, double *pOut) { if (pszText == NULL || pOut == NULL) return false; CString sText(pszText); CStringArray arTexts; Script2StringArray(sText, _T(','), arTexts); if (arTexts.GetSize() != 16) return false; for (int i = 0; i < 16; i++) pOut[i] = _ttof(arTexts.GetAt(i)); return true; } // 把 16 个 double 打包成矩阵二进制块 [魔数][16个double](调用方需保证 xdata 已清零) void SetMatrixData(AecXData &xdata, const double *p) { xdata.nVt = AecXData::kTypeMatrix; xdata.npszLen = kMatrixBinBytes; xdata.pData = new byte[kMatrixBinBytes]; *(int *)xdata.pData = kMatrixMagic; memcpy((int *)xdata.pData + 1, p, 16 * sizeof(double)); } // 从 AecXData 取出 16 个 double(兼容旧的字符串形式) bool GetMatrixData(const AecXData &xdata, double *pOut) { if (xdata.nVt != AecXData::kTypeMatrix || pOut == NULL) return false; if (IsMatrixBinary(xdata)) { memcpy(pOut, (const int *)xdata.pData + 1, 16 * sizeof(double)); return true; } // 兼容旧格式:逗号分隔字符串 if (xdata.pszVal != NULL) return TextToMatrix(xdata.pszVal, pOut); return false; } // 判断 kTypeBinary 数据块是否以指定魔数开头(用于区分普通二进制与数组二进制) bool IsBinaryWithMagic(const AecXData &xdata, int nMagic) { if (xdata.nVt != AecXData::kTypeBinary || xdata.pData == NULL) return false; if (xdata.npszLen < (LONG_PTR)sizeof(int)) return false; return *(const int *)xdata.pData == nMagic; } // 读取数组块头 [魔数][元素类型][元素个数],非数组块返回 false bool GetArrayHeader(const AecXData &xdata, int &nElemVt, int &nCount) { if (!IsBinaryWithMagic(xdata, kArrayMagic)) return false; if (xdata.npszLen < (LONG_PTR)(3 * sizeof(int))) return false; const int *p = (const int *)xdata.pData; nElemVt = p[1]; nCount = p[2]; return (nCount >= 0); } // 写入数组块头(调用方需保证 xdata 已清零),返回元素数据起始地址 double *SetArrayData(AecXData &xdata, int nElemVt, int nCount, int nElemBytes) { LONG_PTR nBytes = (LONG_PTR)3 * sizeof(int) + (LONG_PTR)nCount * nElemBytes; xdata.nVt = AecXData::kTypeBinary; xdata.npszLen = nBytes; xdata.pData = new byte[nBytes]; int *p = (int *)xdata.pData; p[0] = kArrayMagic; p[1] = nElemVt; p[2] = nCount; return (double *)(p + 3); } // 数组元素数据起始地址(块头之后) const double *ArrayElemPtr(const AecXData &xdata) { return (const double *)((const int *)xdata.pData + 3); } // double 数组 → 元素类型 kTypeDouble 的数组块 void SetDoubleArrayData(AecXData &xdata, const AcGeDoubleArray &arVal) { int nCount = arVal.length(); double *pd = SetArrayData(xdata, AecXData::kTypeDouble, nCount, (int)sizeof(double)); for (int i = 0; i < nCount; i++) pd[i] = arVal[i]; } // 从数组块取出 double 数组 bool GetDoubleArrayData(const AecXData &xdata, AcGeDoubleArray &arVal) { int nElemVt = 0, nCount = 0; if (!GetArrayHeader(xdata, nElemVt, nCount)) return false; if (nElemVt != AecXData::kTypeDouble) return false; const double *pd = ArrayElemPtr(xdata); arVal.setLogicalLength(0); for (int i = 0; i < nCount; i++) arVal.append(pd[i]); return true; } // 点数组 → 元素类型 kTypePoint 的数组块(每个点3个double) void SetPoint3dArrayData(AecXData &xdata, const AcGePoint3dArray &arPt) { int nCount = arPt.length(); double *pd = SetArrayData(xdata, AecXData::kTypePoint, nCount, (int)(3 * sizeof(double))); for (int i = 0; i < nCount; i++) { pd[i * 3 + 0] = arPt[i].x; pd[i * 3 + 1] = arPt[i].y; pd[i * 3 + 2] = arPt[i].z; } } // 从数组块取出点数组 bool GetPoint3dArrayData(const AecXData &xdata, AcGePoint3dArray &arPt) { int nElemVt = 0, nCount = 0; if (!GetArrayHeader(xdata, nElemVt, nCount)) return false; if (nElemVt != AecXData::kTypePoint) return false; const double *pd = ArrayElemPtr(xdata); arPt.setLogicalLength(0); for (int i = 0; i < nCount; i++) arPt.append(AcGePoint3d(pd[i * 3 + 0], pd[i * 3 + 1], pd[i * 3 + 2])); return true; } } AecDbObjXDataMap::AecDbObjXDataMap() { } AecDbObjXDataMap::AecDbObjXDataMap(const AecDbObjXDataMap& datamap) { //map 互相复制(CopyFrom 内部会先 Empty 再深拷贝) CopyFrom(&datamap); } AecDbObjXDataMap::~AecDbObjXDataMap() { Empty(); } // 把 xdata 以 pszKey 存入(已存在则先 Free 再覆盖),并接管 xdata 的所有权: // 存入后把源置空,避免源再次 Free 造成重复释放。 void AecDbObjXDataMap::SetXData(LPCTSTR pszKey, AecXData &xdata) { It it = m_xData.find(pszKey); if (it != m_xData.end()) { it->second.Free(); it->second = xdata; } else { m_xData.insert(std::pair(pszKey, xdata)); } xdata.nVt = 0; xdata.npszLen = 0; xdata.nVal = 0; } BOOL AecDbObjXDataMap::SetAt( LPCTSTR pszKey, const int &nVal ) { if (pszKey != NULL) { AecXData xdata; xdata.nVt = AecXData::kTypeInt; xdata.nVal = nVal; SetXData(pszKey, xdata); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey, const Adesk::Int16 &nVal) { if (pszKey != NULL) { AecXData xdata; xdata.nVt = AecXData::kTypeShort; xdata.nVal = nVal; SetXData(pszKey, xdata); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey, const DWORD &dw) { if (pszKey != NULL) { AecXData xdata; xdata.nVt = AecXData::kTypeInt; xdata.nVal = dw; SetXData(pszKey, xdata); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey, const double &dVal) { if (pszKey != NULL) { AecXData xdata; xdata.nVt = AecXData::kTypeDouble; xdata.dVal[0] = dVal; SetXData(pszKey, xdata); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,const AcGeDoubleArray& arVal) { // 整个数组保存为一个 [魔数][个数][double...] 的二进制块,避免精度丢失 if (pszKey == NULL) return FALSE; AecXData xdata; SetDoubleArrayData(xdata, arVal); SetXData(pszKey, xdata); return TRUE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,const AcGeVector3d& vt,BOOL bTransformBy) { /* 设置向量是在键值pszkey后增加字符串"$vector3d",与点进行区分 bTransformBy标识向量是否随cad实体所变化 */ if (pszKey != NULL) { CString sTmpKey = pszKey; sTmpKey += DIF_VT_PT; AecXData xdata; xdata.nVt = AecXData::kTypeVector; if(bTransformBy) { // 向量随cad实体变化而改变 xdata.nVt = AecXData::kTypeVectorWorld; } xdata.dVal[0] = vt.x; xdata.dVal[1] = vt.y; xdata.dVal[2] = vt.z; SetXData(sTmpKey, xdata); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,const AcGePoint3d& ptGe,BOOL bTransformBy) { /* bTransformBy标识点是否随cad实体所变化 */ if (pszKey != NULL) { AecXData xdata; xdata.nVt = AecXData::kTypePoint; if (bTransformBy) { // 点随cad实体变化而改变 xdata.nVt = AecXData::kTypePointWorld; } xdata.dVal[0] = ptGe.x; xdata.dVal[1] = ptGe.y; xdata.dVal[2] = ptGe.z; SetXData(pszKey, xdata); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,const AcGePoint3dArray& arPt,BOOL bTransformBy) { // 整个点数组保存为一个 [魔数][个数][x,y,z...] 的二进制块,避免精度丢失 if (pszKey == NULL) return FALSE; AecXData xdata; SetPoint3dArrayData(xdata, arPt); SetXData(pszKey, xdata); return TRUE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,const AcGeMatrix3d& xform) { if (pszKey != NULL) { double ar[16]; int k = 0; for (int i = 0;i < 4;i++) { for (int j = 0;j < 4;j++) { ar[k++] = xform.entry[i][j]; } } AecXData xdata; SetMatrixData(xdata, ar); // 打包成 [魔数][16个double] 的二进制块 SetXData(pszKey, xdata); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,void* pData,int nSize) { if (pszKey != NULL && nSize > 0 && pData != NULL) { AecXData xdata; xdata.nVt = AecXData::kTypeBinary; xdata.npszLen = nSize; xdata.pData = new byte[nSize]; memcpy(xdata.pData,pData,nSize); SetXData(pszKey, xdata); return TRUE; } return FALSE; } CString AecDbObjXDataMap::MatrixToString(const AecXData& xdata) { CString sText; MatrixToText(xdata, sText); return sText; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,AcGeMatrix3d& xform) const { if (pszKey != NULL) { CIt it; if ((it = m_xData.find(pszKey)) != m_xData.end()) { double ar[16]; if (GetMatrixData((*it).second, ar)) { int k = 0; for (int i = 0;i < 4;i++) for (int j = 0;j < 4;j++) xform.entry[i][j] = ar[k++]; return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,LPCTSTR pszValue) { if (pszKey != NULL) { AecXData xdata; xdata.nVt = AecXData::kTypeString; xdata.npszLen = _tcslen(pszValue) + 1; xdata.pszVal = new TCHAR[xdata.npszLen]; memset(xdata.pszVal, 0, xdata.npszLen * sizeof(TCHAR)); _tcsncpy_s(xdata.pszVal, xdata.npszLen, pszValue, xdata.npszLen - 1); SetXData(pszKey, xdata); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,int iIndex,LPCTSTR pszValue) { if (pszKey != NULL) { CString sKey; sKey.Format(_T("%s_%d"),pszKey,iIndex); return SetAt(sKey,pszValue); } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,int iIndex,CString &sValue) const { if (pszKey != NULL) { CString sKey; sKey.Format(_T("%s_%d"),pszKey,iIndex); return GetAt(sKey,sValue); } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,int iIndex,const AecDbObjXDataMap& xDataMap) { //{key | type | inf}个隔开 CString sKey,sType,sInfo,sRecord,sText; sText = _T(""); AecXData xdata; memset(&xdata,0,sizeof(AecXData)); for (CIt it = xDataMap.m_xData.begin(); it != xDataMap.m_xData.end(); ++it) { xdata = (*it).second; sKey = (*it).first; sType = _T(""); sInfo = _T(""); switch (xdata.nVt) { case AecXData::kTypeShort: { sType.Format(_T("%d"), AecXData::kTypeShort); sInfo.Format(_T("%d"), xdata.iVal); sRecord.Format(_T("{%s|%s|%s}"), sKey, sType, sInfo); sText += sRecord; break; } case AecXData::kTypeInt: // 整型 { sType.Format(_T("%d"),AecXData::kTypeInt); sInfo.Format(_T("%d"),xdata.nVal); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } case AecXData::kTypeSoftId: { sType.Format(_T("%d"),AecXData::kTypeSoftId); sInfo.Format(_T("%d"),xdata.nVal); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } case AecXData::kTypeHardId: { sType.Format(_T("%d"),AecXData::kTypeHardId); sInfo.Format(_T("%d"),xdata.nVal); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } case AecXData::kTypeDouble: // 浮点 { sType.Format(_T("%d"),AecXData::kTypeDouble); sInfo.Format(_T("%.9f"),xdata.dVal[0]); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } case AecXData::kTypePoint: // 点 { sType.Format(_T("%d"),AecXData::kTypePoint); sInfo.Format(_T("%.4f,%.4f,%.4f"),xdata.dVal[0],xdata.dVal[1],xdata.dVal[2]); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } case AecXData::kTypePointWorld: // cad变化点 { sType.Format(_T("%d"),AecXData::kTypePointWorld); sInfo.Format(_T("%.9f,%.9f,%.9f"),xdata.dVal[0],xdata.dVal[1],xdata.dVal[2]); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } case AecXData::kTypeVector: // 向量 { sType.Format(_T("%d"),AecXData::kTypeVector); sInfo.Format(_T("%.9f,%.9f,%.9f"),xdata.dVal[0],xdata.dVal[1],xdata.dVal[2]); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } case AecXData::kTypeVectorWorld: // 变化向量 { sType.Format(_T("%d"),AecXData::kTypeVectorWorld); sInfo.Format(_T("%.9f,%.9f,%.9f"),xdata.dVal[0],xdata.dVal[1],xdata.dVal[2]); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } case AecXData::kTypeMatrix: // 矩阵 { sType.Format(_T("%d"),AecXData::kTypeMatrix); MatrixToText(xdata, sInfo); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } case AecXData::kTypeBinary: // binary data { break; } case AecXData::kTypeString: // 字符串 { sType.Format(_T("%d"),AecXData::kTypeString); sInfo.Format(_T("%s"),xdata.pszVal); sRecord.Format(_T("{%s|%s|%s}"),sKey,sType,sInfo); sText += sRecord; break; } break; default: break; } } if (!sText.IsEmpty()) return SetAt(pszKey,iIndex,sText); return FALSE; } BOOL AecDbObjXDataMap::ParseToRecords(CString& sText,CStringArray& arRecords) const { CString sRecord; int nFr = 0,nTo = 0; //{Key|Type|Info}... while(TRUE) { nFr = sText.Find(_T("{"),0); nTo = sText.Find(_T("}"),0); if (nFr == 0 && nTo > 0) { sRecord = sText.Mid(nFr,nTo + 1); sRecord.TrimLeft(_T("{")); sRecord.TrimRight(_T("}")); arRecords.Add(sRecord); if (nTo + 1 < sText.GetLength()) { sRecord = sText.Mid(nTo + 1); sText = sRecord; } else { break; } } else { break; } } return arRecords.GetSize() > 0; } BOOL AecDbObjXDataMap::ExtractRecord(CString& sRecord,CString& sKey,CString& sType,CString& sInfo) const { //Key|int|Info int nFr = sRecord.Find(_T("|"),0); if (nFr != -1) { CString sTemp; sKey = sRecord.Mid(0,nFr); if (nFr + 1 < sRecord.GetLength()) { sTemp = sRecord.Mid(nFr + 1); sRecord = sTemp; nFr = sRecord.Find(_T("|"),0); if (nFr != -1) { sType = sRecord.Mid(0,nFr); if (nFr + 1 < sRecord.GetLength()) { sInfo = sRecord.Mid(nFr + 1); return TRUE; } } } } return FALSE; } BOOL AecDbObjXDataMap::StringToAcGePoint3d(CString& sText,AcGePoint3d& ptGe) const { //x,y,z CString sX,sY,sZ; int nFr = sText.Find(_T(","),0); if (nFr != -1) { CString sTemp; sX = sText.Mid(0,nFr); if (nFr + 1 < sText.GetLength()) { sTemp = sText.Mid(nFr + 1); sText = sTemp; nFr = sText.Find(_T(","),0); if (nFr != -1) { sY = sText.Mid(0,nFr); if (nFr + 1 < sText.GetLength()) { sZ = sText.Mid(nFr + 1); ptGe.set(_ttof(sX),_ttof(sY),_ttof(sZ)); return TRUE; } } } } return FALSE; } BOOL AecDbObjXDataMap::StringToAcGeVector3d(CString& sText,AcGeVector3d& vt) const { //x,y,z AcGePoint3d ptGe; if (StringToAcGePoint3d(sText,ptGe)) { vt = ptGe.asVector(); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,int iIndex,AecDbObjXDataMap& xDataMap) const { CString sKey,sType,sInfo,sText,sRecord; AcGePoint3d ptGe; AcGeVector3d vt; BOOL bSuccess = FALSE; AcDbObjectId id; if (GetAt(pszKey,iIndex,sText)) { sText.TrimLeft(); sText.TrimRight(); if (sText.GetLength() > 1) { CStringArray arRecords; bSuccess = ParseToRecords(sText,arRecords); for (int i = 0;i < arRecords.GetSize();i++) { sRecord = arRecords.GetAt(i); if (ExtractRecord(sRecord,sKey,sType,sInfo)) { int nVt = _ttoi(sType); switch (nVt) { case AecXData::kTypeShort: { xDataMap.SetAt(sKey, (short)_ttoi(sInfo)); break; } case AecXData::kTypeInt: // 整型 { xDataMap.SetAt(sKey,_ttoi(sInfo)); break; } case AecXData::kTypeSoftId: { id.setFromOldId((INT_PTR)_ttoi(sInfo)); xDataMap.SetAt(sKey,id); break; } case AecXData::kTypeHardId: { id.setFromOldId((INT_PTR)_ttoi(sInfo)); xDataMap.SetAt(sKey,id,FALSE); break; } case AecXData::kTypeDouble: // 浮点 { xDataMap.SetAt(sKey,_ttof(sInfo)); break; } case AecXData::kTypePoint: // 点 { if (StringToAcGePoint3d(sInfo,ptGe)) { xDataMap.SetAt(sKey,ptGe); } break; } case AecXData::kTypePointWorld: // cad变化点 { if (StringToAcGePoint3d(sInfo,ptGe)) { xDataMap.SetAt(sKey,ptGe,TRUE); } break; } case AecXData::kTypeVector: // 向量 { if (StringToAcGeVector3d(sInfo,vt)) { sKey.Replace(DIF_VT_PT,_T(" ")); sKey.TrimRight(); xDataMap.SetAt(sKey,vt); } break; } case AecXData::kTypeVectorWorld: // 变化向量 { if (StringToAcGeVector3d(sInfo,vt)) { sKey.Replace(DIF_VT_PT,_T(" ")); sKey.TrimRight(); xDataMap.SetAt(sKey,vt,TRUE); } break; } case AecXData::kTypeMatrix: //矩阵 { double ar[16]; if (TextToMatrix(sInfo, ar)) { AcGeMatrix3d xf; int k = 0; for (int i = 0;i < 4;i++) for (int j = 0;j < 4;j++) xf.entry[i][j] = ar[k++]; xDataMap.SetAt(sKey, xf); } break; } case AecXData::kTypeBinary: //binary data { break; } case AecXData::kTypeString: // 字符串 { xDataMap.SetAt(sKey,sInfo); break; } break; default: break; } } else { //按照常规处理 xDataMap.SetAt(pszKey,iIndex,sText); bSuccess = TRUE; } } } else { //按照常规处理 xDataMap.SetAt(pszKey,iIndex,sText); bSuccess = TRUE; } } return bSuccess; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey, const AecDbObjXDataMap& xDataMap) { // 把整个子 map 按二进制格式序列化,作为单个二进制块(kTypeBinary)保存, // 这样矩阵/数组等二进制数据也能无损地随子 map 一起保存。 if (pszKey == NULL) return FALSE; CMemFile mf; if (!xDataMap.Write(&mf, FALSE)) return FALSE; UINT nLen = (UINT)mf.GetLength(); if (nLen == 0) return FALSE; byte *pBuf = new byte[nLen]; mf.SeekToBegin(); mf.Read(pBuf, nLen); BOOL bOk = SetAt(pszKey, pBuf, (int)nLen); delete[] pBuf; return bOk; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey, AecDbObjXDataMap& xDataMap) { // 取出二进制块并按二进制格式反序列化回子 map void *pData = NULL; int nSize = 0; if (!GetAt(pszKey, pData, nSize)) return FALSE; CMemFile mf((BYTE *)pData, (UINT)nSize); mf.SeekToBegin(); BOOL bOk = xDataMap.Read(&mf, FALSE); delete[] (byte *)pData; return bOk; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,const AcDbObjectId& id,BOOL bIsSoft) { if (pszKey != NULL) { AecXData xdata; xdata.nVt = AecXData::kTypeSoftId; if (!bIsSoft) xdata.nVt = AecXData::kTypeHardId; xdata.nVal = id.asOldId(); SetXData(pszKey, xdata); return TRUE; } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,const AcDbHandle& handle) { if (pszKey != NULL) { TCHAR szHandleStr[19]; memset(szHandleStr,0,sizeof(szHandleStr) ); handle.getIntoAsciiBuffer(szHandleStr); LPCTSTR pszVal = szHandleStr; return SetAt(pszKey,pszVal); } return FALSE; } BOOL AecDbObjXDataMap::SetAt(LPCTSTR pszKey,const AecXData& XData) { if (pszKey == NULL) return FALSE; It it = m_xData.find(pszKey); if (it != m_xData.end()) //找到 { // 已存在:原地深拷贝覆盖(释放旧资源,允许类型变化) return it->second.CopyFrom(XData) ? TRUE : FALSE; } // 未找到:先深拷贝再插入,避免与源共享字符串/二进制缓冲 AecXData xdata; xdata.CopyFrom(XData); std::pair pa(pszKey,xdata); m_xData.insert(pa); return TRUE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,AecXData& XData) const { if (pszKey != NULL) { CIt it; if ((it = m_xData.find(pszKey)) != m_xData.end()) { XData = (*it).second; return TRUE; } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,void*& pData,int& nSize) const { if (pszKey != NULL) { AecXData XData; CIt it; if ((it = m_xData.find(pszKey)) != m_xData.end()) { XData = (*it).second; if (XData.nVt == AecXData::kTypeBinary ) { if (XData.npszLen > 0) { pData = new byte[XData.npszLen]; memcpy(pData,XData.pData,XData.npszLen); nSize = XData.npszLen; return TRUE; } } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey, DWORD & dw) const { if (pszKey != NULL) { CIt it; if ((it = m_xData.find(pszKey)) != m_xData.end()) { AecXData xdata = (*it).second; if (xdata.nVt == AecXData::kTypeInt) { dw = (int)xdata.nVal; return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,int& nVal) const { if (pszKey != NULL) { CIt it; if ((it = m_xData.find(pszKey)) != m_xData.end()) { AecXData xdata = (*it).second; if (xdata.nVt == AecXData::kTypeInt) { nVal = (int)xdata.nVal; return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey, short &nVal) const { if (pszKey != NULL) { CIt it; if ((it = m_xData.find(pszKey)) != m_xData.end()) { AecXData xdata = (*it).second; if (xdata.nVt == AecXData::kTypeShort)//优先 { nVal = (short)xdata.iVal; return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,double& dVal) const { if (pszKey != NULL) { CIt it; if ((it = m_xData.find(pszKey)) != m_xData.end()) { AecXData xdata = (*it).second; if (xdata.nVt == AecXData::kTypeDouble) { dVal = xdata.dVal[0]; return TRUE; } else if (xdata.nVt == AecXData::kTypeInt) { dVal = 1.0 * xdata.nVal; return TRUE; } else if (xdata.nVt == AecXData::kTypeShort)//优先 { dVal = 1.0 * xdata.iVal; return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,AcGeDoubleArray& arVal) const { arVal.setLogicalLength(0); if (pszKey == NULL) return FALSE; // 新格式:单个二进制块([魔数][个数][double...]) CIt it = m_xData.find(pszKey); if (it != m_xData.end() && GetDoubleArrayData((*it).second, arVal)) return (arVal.length() > 0); // 兼容旧格式:pszKey0, pszKey1, ... CString sSubKey; double dVal; int nIndex = 0; sSubKey.Format(_T("%s%d"),pszKey,nIndex++); while(GetAt(sSubKey,dVal)) { arVal.append(dVal); sSubKey.Format(_T("%s%d"),pszKey,nIndex++); } return (arVal.length() > 0); } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,AcGeVector3d& vt) const { /* 由于设置向量是将键值pszkey后增加字符串"$vector3d", 故获取向量时在键值pszkey后增加字符串"$vector3d" */ if (pszKey != NULL) { CString sTmpKey = pszKey; sTmpKey += DIF_VT_PT; CIt it; if ((it = m_xData.find(sTmpKey)) != m_xData.end()) { AecXData xdata = (*it).second; if ((xdata.nVt == AecXData::kTypeVector) || (xdata.nVt == (AecXData::kTypeVectorWorld))) { vt.x = xdata.dVal[0]; vt.y = xdata.dVal[1]; vt.z = xdata.dVal[2]; return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,AcGePoint3d& ptGe) const { if (pszKey != NULL) { CIt it; if ((it = m_xData.find(pszKey)) != m_xData.end()) { AecXData xdata = (*it).second; if ( (xdata.nVt == AecXData::kTypePoint) || (xdata.nVt == AecXData::kTypePointWorld)) { ptGe.x = xdata.dVal[0]; ptGe.y = xdata.dVal[1]; ptGe.z = xdata.dVal[2]; return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,AcGePoint3dArray& arPt) const { arPt.setLogicalLength(0); if (pszKey == NULL) return FALSE; // 新格式:单个二进制块([魔数][个数][x,y,z...]) CIt it = m_xData.find(pszKey); if (it != m_xData.end() && GetPoint3dArrayData((*it).second, arPt)) return (arPt.length() > 0); // 兼容旧格式:pszKey0, pszKey1, ... CString sSubKey; AcGePoint3d pt; int nIndex = 0; sSubKey.Format(_T("%s%d"),pszKey,nIndex++); while(GetAt(sSubKey,pt)) { arPt.append(pt); sSubKey.Format(_T("%s%d"),pszKey,nIndex++); } return (arPt.length() > 0); } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,CString &sValue) const { if (pszKey != NULL) { CIt it; if ((it = m_xData.find(pszKey)) != m_xData.end()) { AecXData xdata = (*it).second; if (xdata.nVt == AecXData::kTypeString) { sValue = xdata.pszVal; return TRUE; } else if (xdata.nVt == AecXData::kTypeMatrix) { MatrixToText(xdata, sValue); return TRUE; } else if (xdata.nVt == AecXData::kTypeInt || xdata.nVt == AecXData::kTypeInt64) { sValue.Format(_T("%d"), xdata.nVal); return TRUE; } else if (xdata.nVt == AecXData::kTypeShort) { sValue.Format(_T("%d"), xdata.iVal); return TRUE; } else if (xdata.nVt == AecXData::kTypeDouble) { sValue.Format(_T("%.9f"), xdata.dVal[0]); sValue.TrimRight(_T('0')); return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,AcDbObjectId& id) const { if (pszKey != NULL) { CIt it; if ((it = m_xData.find(pszKey) ) != m_xData.end()) { AecXData xdata = (*it).second; if (xdata.nVt == AecXData::kTypeSoftId || xdata.nVt == AecXData::kTypeHardId) { id.setFromOldId(xdata.nVal); return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey,AcDbHandle& handle,AcDbDatabase* pDb/* = NULL*/) const { CString sVal; if (GetAt(pszKey,sVal)) { AcDbHandle handleT((LPCTSTR)sVal); if (pDb == NULL) pDb = acdbCurDwg(); if (pDb != NULL) { AcDbObjectId id; if ( Acad::eOk == pDb->getAcDbObjectId(id,false,handleT) ) { handle = handleT; return TRUE; } } } return FALSE; } BOOL AecDbObjXDataMap::GetAt(LPCTSTR pszKey, TCHAR * psz, const int & len) const { CString str(_T("")); if (GetAt(pszKey, str)) { if (str.GetLength() < len && psz) { ::memset(psz, 0, len * sizeof(TCHAR)); _tcsncpy_s(psz, len, str, len-1); return TRUE; } } return FALSE; } BOOL AecDbObjXDataMap::HasKey(LPCTSTR pszKey,int& nVt) const { if (pszKey != NULL) { CString sTmpKey = pszKey; sTmpKey += DIF_VT_PT; CIt it; it = m_xData.find(pszKey); if (it != m_xData.end()) { AecXData xdata = it->second;//m_xData[pszKey]; nVt = xdata.nVt; return TRUE; } it = m_xData.find(sTmpKey); if( it != m_xData.end()) { AecXData xdata = it->second;//m_xData[sTmpKey]; nVt = xdata.nVt; return TRUE; } else { return FALSE; } } return FALSE; } void AecDbObjXDataMap::Empty() { for (It it = m_xData.begin(); it != m_xData.end(); ++it) it->second.Free(); m_xData.clear(); } BOOL AecDbObjXDataMap::RemoveAt(LPCTSTR pszKey) { if (!pszKey) return FALSE; CString sTmpKey = pszKey; sTmpKey += DIF_VT_PT; It it = m_xData.find(pszKey); It it1 = m_xData.find(sTmpKey); BOOL bRemoved = FALSE; if (it != m_xData.end()) { it->second.Free(); // 释放内存 m_xData.erase(it); bRemoved = TRUE; } if (it1 != m_xData.end()) { it1->second.Free(); // 释放内存 m_xData.erase(it1); bRemoved = TRUE; } return bRemoved; } BOOL AecDbObjXDataMap::RemoveAt(LPCTSTR pszKey,int nIndex) { if (pszKey != NULL) { CString sKey; sKey.Format(_T("%s_%d"),pszKey,nIndex); return RemoveAt(sKey); } return FALSE; } AecDbObjXDataMap& AecDbObjXDataMap::operator = (const AecDbObjXDataMap& srcMap) { //map 互相复制(CopyFrom 内部已处理 this == &srcMap 与 Empty) CopyFrom(&srcMap); return *this; } BOOL AecDbObjXDataMap::CopyFrom(const AecDbObjXDataMap* pSrc) { if (pSrc == NULL || this == pSrc) return FALSE; //map 互相复制:SetAt 内部走 AecXData::CopyFrom 深拷贝, //字符串/矩阵/二进制都会重新分配,不与源共享缓冲 Empty(); for (CIt it = pSrc->m_xData.begin();it != pSrc->m_xData.end();it++) { SetAt((*it).first,(*it).second); } return TRUE; } BOOL AecDbObjXDataMap::AppendFrom(const AecDbObjXDataMap* pSrc) { if (pSrc == NULL || this == pSrc) return FALSE; //合并:同名键以 pSrc 的值覆盖(SetAt 语义) for (CIt it = pSrc->m_xData.begin();it != pSrc->m_xData.end();it++) { SetAt((*it).first,(*it).second); } return TRUE; } AecDbObjXDataMap::It AecDbObjXDataMap::Begin() { return m_xData.begin(); } BOOL AecDbObjXDataMap::GetNext(It& it,CString& sKey,AecXData& xData) { if (it != m_xData.end()) { if ((*it).second.nVt == AecXData::kTypeString) { if ((*it).second.npszLen > 0 && (*it).second.pszVal != NULL) { memset(&xData, 0, sizeof(AecXData)); xData.nVt = AecXData::kTypeString; xData.npszLen = (*it).second.npszLen;//!!! xData.pszVal = new TCHAR[xData.npszLen];//!!! _tcsncpy_s(xData.pszVal, xData.npszLen, (*it).second.pszVal, xData.npszLen - 1);//!!! } else { //异常-->AecXData::kTypeInt 0 代替 memset(&xData, 0, sizeof(AecXData)); xData.nVt = AecXData::kTypeInt; } } else { xData = (*it).second; sKey = (*it).first; } ++it; return TRUE; } return FALSE; } AecDbObjXDataMap::It AecDbObjXDataMap::End() { return m_xData.end(); } void AecDbObjXDataMap::List() const { AecXData xdata; int nVt = -1; AcGePoint3d ptVal; AcGeVector3d vt; AcDbObjectId id; for (CIt it = m_xData.begin(); it != m_xData.end(); ++it) { xdata = (*it).second; nVt = xdata.nVt; acutPrintf(_T("\n%s:"),(const TCHAR *)(*it).first); switch (nVt) { case AecXData::kTypeShort: acutPrintf(_T("%d : VT_I2"), (int)xdata.iVal); break; case AecXData::kTypeInt: // 整型 acutPrintf(_T("%d : VT_I4"),(int)xdata.nVal); break; case AecXData::kTypeSoftId: //s id #ifndef _WIN64 acutPrintf(_T("%ld : VT_UI4"),xdata.nVal); #else acutPrintf(_T("%d : VT_UI4"),xdata.nVal); #endif break; case AecXData::kTypeHardId: //h id #ifndef _WIN64 acutPrintf(_T("%ld : VT_UI4"),xdata.nVal); #else acutPrintf(_T("%d : VT_UI4"),xdata.nVal); #endif break; case AecXData::kTypeDouble: // 浮点 acutPrintf(_T("%.9f : VT_R8"),xdata.dVal[0]); break; case AecXData::kTypePoint: // 点 acutPrintf(_T("%.9f,%.9f,%.9f : Point3d"),xdata.dVal[0],xdata.dVal[1],xdata.dVal[2]); break; case AecXData::kTypePointWorld: // cad变化点 acutPrintf(_T("%.9f,%.9f,%.9f : Point3d"),xdata.dVal[0],xdata.dVal[1],xdata.dVal[2]); break; case AecXData::kTypeVector: // 向量 acutPrintf(_T("%.9f,%.9f,%.9f : Vector3d"),xdata.dVal[0],xdata.dVal[1],xdata.dVal[2]); break; case AecXData::kTypeVectorWorld: // 变化向量 acutPrintf(_T("%.9f,%.9f,%.9f : Vector3d"),xdata.dVal[0],xdata.dVal[1],xdata.dVal[2]); break; case AecXData::kTypeMatrix: // 矩阵 { CString sMat; MatrixToText(xdata, sMat); acutPrintf(_T("%s : Matrix3d"),(LPCTSTR)sMat); } break; case AecXData::kTypeBinary: // binarydata acutPrintf(_T("%p:%d bytes : Binary data"),xdata.pData,xdata.npszLen); break; case AecXData::kTypeString: // 字符串 acutPrintf(_T("%s : String"),xdata.pszVal); break; default: break; } } } void AecDbObjXDataMap::List(std::vector& pList) const { AecXData xdata; int nVt = -1; TCHAR szData[MAX_PATH * 4]; for (CIt it = m_xData.begin(); it != m_xData.end(); ++it) { xdata = (*it).second; nVt = xdata.nVt; memset(szData, 0, sizeof(szData)); switch (nVt) { case AecXData::kTypeShort: swprintf(szData, _T("%d : VT_I4"), xdata.iVal); break; case AecXData::kTypeInt: // 整型 swprintf(szData,_T("%d : VT_I4"), (int)xdata.nVal); break; case AecXData::kTypeSoftId: //s id #ifndef _WIN64 swprintf(szData, _T("%ld : VT_UI4"), xdata.nVal); #else swprintf(szData, _T("%d : VT_UI4"), (int)xdata.nVal); #endif break; case AecXData::kTypeHardId: //h id #ifndef _WIN64 swprintf(szData, _T("%ld : VT_UI4"), xdata.nVal); #else swprintf(szData, _T("%d : VT_UI4"), (int)xdata.nVal); #endif break; case AecXData::kTypeDouble: // 浮点 swprintf(szData, _T("%.3f : VT_R8"), xdata.dVal[0]); break; case AecXData::kTypePoint: // 点 swprintf(szData, _T("(%.3f,%.3f,%.3f) : Point3d"), xdata.dVal[0], xdata.dVal[1], xdata.dVal[2]); break; case AecXData::kTypePointWorld: // cad变化点 swprintf(szData, _T("(%.3f,%.3f,%.3f) : Point3d"), xdata.dVal[0], xdata.dVal[1], xdata.dVal[2]); break; case AecXData::kTypeVector: // 向量 swprintf(szData, _T("(%.3f,%.3f,%.3f) : Vector3d"), xdata.dVal[0], xdata.dVal[1], xdata.dVal[2]); break; case AecXData::kTypeVectorWorld: // 变化向量 swprintf(szData, _T("(%.3f,%.3f,%.3f) : Vector3d"), xdata.dVal[0], xdata.dVal[1], xdata.dVal[2]); break; case AecXData::kTypeMatrix: // 矩阵 { CString sMat; MatrixToText(xdata, sMat); swprintf(szData, _T("%s : Matrix3d"), (LPCTSTR)sMat); } break; case AecXData::kTypeBinary: // binarydata swprintf(szData, _T("%p:%d bytes : Binary data"), xdata.pData, (int)xdata.npszLen); break; case AecXData::kTypeString: // 字符串 { //太长...多余的截掉 if (xdata.npszLen > MAX_PATH * 4) { wcsncpy(szData, xdata.pszVal, MAX_PATH * 4-4); _tcscat(szData, _T("...")); } else { swprintf(szData, _T("%s : String"), xdata.pszVal); } break; } default: break; } // 每个元素占两项:先 key(名称),后 value(数据)。 pList.push_back((*it).first); pList.push_back(szData); } } static bool XDataEqu(const AecXData& xdata1,const AecXData& xdata2) { if (xdata1.nVt != xdata2.nVt) return false; switch (xdata1.nVt) { case AecXData::kTypeShort: if (xdata1.iVal != xdata2.iVal) return false; case AecXData::kTypeInt: // 整型 case AecXData::kTypeSoftId: //s id case AecXData::kTypeHardId: //h id if (xdata1.nVal != xdata2.nVal) return false; break; case AecXData::kTypeDouble: // 浮点 if ( fabs(xdata1.dVal[0] - xdata2.dVal[0]) > 1.e-3) return false; break; case AecXData::kTypePoint: // 点 case AecXData::kTypePointWorld: // cad变化点 case AecXData::kTypeVector: // 向量 case AecXData::kTypeVectorWorld: // 变化向量 if ( fabs(xdata1.dVal[0] - xdata2.dVal[0]) > 1.e-3) return false; if ( fabs(xdata1.dVal[1] - xdata2.dVal[1]) > 1.e-3) return false; if ( fabs(xdata1.dVal[2] - xdata2.dVal[2]) > 1.e-3) return false; break; case AecXData::kTypeMatrix: // 矩阵 if (xdata1.npszLen != xdata2.npszLen) return false; if (xdata1.pData == NULL || xdata2.pData == NULL) return false; if (memcmp(xdata1.pData,xdata2.pData,(size_t)xdata1.npszLen) != 0) return false; break; case AecXData::kTypeBinary: // binarydata if (xdata1.npszLen != xdata2.npszLen) return false; break; case AecXData::kTypeString: // 字符串 if (_tcscmp(xdata1.pszVal,xdata2.pszVal) != 0) return false; break; default: break; } return true; } int AecDbObjXDataMap::ComparedTo(const AecDbObjXDataMap* pXDataMap) const { if (pXDataMap == NULL) return 1; if (m_xData.size() != pXDataMap->m_xData.size()) return 1; for (CIt it1 = m_xData.begin(); it1 != m_xData.end(); ++it1) { CIt it2 = pXDataMap->m_xData.find(it1->first); if (it2 == pXDataMap->m_xData.end()) { return 1; } else { if ( !XDataEqu(it1->second,it2->second)) { return 1; } } } return 0; } Acad::ErrorStatus AecDbObjXDataMap::dxfOutFields(AcDbDxfFiler* pFiler) const { if (pFiler == NULL) return Acad::eInvalidInput; AecXData xdata; int nVt = -1; AcGePoint3d ptVal; AcGeVector3d vt; AcDbObjectId id; pFiler->writeString(AcDb::kDxfXTextString, MAP_BLOCK_BEGIN); for (CIt it = m_xData.begin(); it != m_xData.end(); ++it) { xdata = (*it).second; nVt = xdata.nVt; pFiler->writeString(AcDb::kDxfXdAsciiString, (const TCHAR *)(*it).first); pFiler->writeInt32(AcDb::kDxfXdInteger32, nVt); switch (nVt) { case AecXData::kTypeShort: pFiler->writeInt16(AcDb::kDxfXdInteger16, xdata.iVal); break; case AecXData::kTypeInt: // 整型 pFiler->writeInt32(AcDb::kDxfXdInteger32, (int)xdata.nVal); break; case AecXData::kTypeSoftId: //s id id.setFromOldId(xdata.nVal); pFiler->writeObjectId(AcDb::kDxfSoftPointerId,id); break; case AecXData::kTypeHardId: //h id id.setFromOldId(xdata.nVal); pFiler->writeObjectId(AcDb::kDxfHardPointerId,id); break; case AecXData::kTypeDouble: // 浮点 pFiler->writeDouble(AcDb::kDxfXdReal, xdata.dVal[0]); break; case AecXData::kTypePoint: // 点 ptVal.x = xdata.dVal[0]; ptVal.y = xdata.dVal[1]; ptVal.z = xdata.dVal[2]; pFiler->writePoint3d(AcDb::kDxfXdXCoord, ptVal); break; case AecXData::kTypePointWorld: // cad变化点 ptVal.x = xdata.dVal[0]; ptVal.y = xdata.dVal[1]; ptVal.z = xdata.dVal[2]; pFiler->writePoint3d(AcDb::kDxfXdWorldXCoord, ptVal); break; case AecXData::kTypeVector: // 向量 vt.x = xdata.dVal[0]; vt.y = xdata.dVal[1]; vt.z = xdata.dVal[2]; pFiler->writeVector3d(AcDb::kDxfXdXCoord, vt); break; case AecXData::kTypeVectorWorld: // 变化向量 vt.x = xdata.dVal[0]; vt.y = xdata.dVal[1]; vt.z = xdata.dVal[2]; pFiler->writeVector3d(AcDb::kDxfXdWorldXDir, vt); break; case AecXData::kTypeMatrix: // 矩阵 { CString sMat; MatrixToText(xdata, sMat); pFiler->writeString(AcDb::kDxfXdAsciiString, (LPCTSTR)sMat); } break; case AecXData::kTypeBinary: // binary data { ads_binary binary; binary.clen = xdata.npszLen; binary.buf = (char*)xdata.pData; pFiler->writeBChunk(AcDb::kDxfXdBinaryChunk,binary); } break; case AecXData::kTypeString: // 字符串 pFiler->writeString(AcDb::kDxfXdAsciiString, xdata.pszVal); break; default: break; } } pFiler->writeString(AcDb::kDxfXTextString, MAP_BLOCK_END); return Acad::eOk; } Acad::ErrorStatus AecDbObjXDataMap::dxfInFields(AcDbDxfFiler* pFiler) { if (pFiler == NULL) return Acad::eInvalidInput; BOOL bFinded = FALSE; long nVt = 0; TCHAR* pszKey = NULL; TCHAR* pszVal = NULL; AcGePoint3d ptVal; AcGeVector3d vt; CString sKey,sTag; struct resbuf rb; while ((pFiler->readItem(&rb)) == Acad::eOk) { if(rb.restype == AcDb::kDxfXdAsciiString) { sTag = rb.resval.rstring; if (sTag.CompareNoCase(MAP_BLOCK_BEGIN) == 0) { bFinded = TRUE; break; } } } if (!bFinded) return Acad::eOk; int nMapUnitIndex = 0; AcDbObjectId id; while ((pFiler->readItem(&rb)) == Acad::eOk) { nMapUnitIndex++; if(nMapUnitIndex == 1) { if(rb.restype == AcDb::kDxfXdAsciiString) { sKey = rb.resval.rstring; continue; } } else { nMapUnitIndex = 0; } nVt = rb.restype; switch (nVt) { case AecXData::kTypeShort: SetAt(sKey, rb.resval.rint); break; case AecXData::kTypeInt: // 整型 SetAt(sKey,rb.resval.rlong); break; case AecXData::kTypeSoftId: //s id #ifdef _WIN64 id.setFromOldId(rb.resval.mnInt64); #else id.setFromOldId(rb.resval.rlong); #endif SetAt(sKey,id); break; case AecXData::kTypeHardId: //h id #ifdef _WIN64 id.setFromOldId(rb.resval.mnInt64); #else id.setFromOldId(rb.resval.rlong); #endif SetAt(sKey,id,FALSE); break; case AecXData::kTypeDouble: // 浮点 SetAt(sKey,rb.resval.rreal); break; case AecXData::kTypePoint: // 点 SetAt(sKey, asPnt3d(rb.resval.rpoint)); break; case AecXData::kTypePointWorld: // 变化点 SetAt(sKey, asPnt3d(rb.resval.rpoint),TRUE); break; case AecXData::kTypeVector: // 向量 sKey.Replace(DIF_VT_PT,_T(" ")); sKey.TrimRight(); SetAt(sKey, asPnt3d(rb.resval.rpoint)); break; case AecXData::kTypeVectorWorld: // cad变化向量 sKey.Replace(DIF_VT_PT,_T(" ")); sKey.TrimRight(); SetAt(sKey, asPnt3d(rb.resval.rpoint),TRUE); break; case AecXData::kTypeMatrix: //矩阵 { double ar[16]; if (TextToMatrix(rb.resval.rstring, ar)) { AcGeMatrix3d xf; int k = 0; for (int i = 0;i < 4;i++) for (int j = 0;j < 4;j++) xf.entry[i][j] = ar[k++]; SetAt(sKey, xf); } } break; case AecXData::kTypeBinary: //binary data SetAt(sKey,rb.resval.rbinary.buf,rb.resval.rbinary.clen); break; case AecXData::kTypeString: // 字符串 SetAt(sKey, rb.resval.rstring); break; default: break; } } return Acad::eOk; } // 增加 clone 的 xdatamap 的关系复制维护 void AecDbObjXDataMap::BeginCloneXlation(AecDbObjXDataMap* pMapClone,AcDbIdMapping& idMap) const { assert(pMapClone != NULL); AcDbObjectId id; AecXData xdata; AcDbIdPair idpair; for (CIt it = m_xData.begin();it != m_xData.end();it++) { xdata = (*it).second; switch (xdata.nVt) { case AecXData::kTypeSoftId: { id.setFromOldId(xdata.nVal); idpair.setKey(id); if ( idMap.compute(idpair) ) { pMapClone->SetAt((*it).first,idpair.value(),TRUE); } } break; case AecXData::kTypeHardId: { id.setFromOldId(xdata.nVal); idpair.setKey(id); if ( idMap.compute(idpair) ) { pMapClone->SetAt((*it).first,idpair.value(),FALSE); } } break; default: break; } } } Acad::ErrorStatus AecDbObjXDataMap::dwgOutFields(AcDbDwgFiler* pFiler) const { if (pFiler != NULL) { AecXData xdata; int nVt = -1; AcGePoint3d ptVal; AcGeVector3d vt; AcDbSoftPointerId id; pFiler->writeString(MAP_BLOCK_BEGIN); for (CIt it = m_xData.begin(); it != m_xData.end(); ++it) { xdata = (*it).second; nVt = xdata.nVt; pFiler->writeString((const TCHAR *)(*it).first); pFiler->writeInt32(nVt); switch (nVt) { case AecXData::kTypeShort: pFiler->writeInt16(xdata.iVal); break; case AecXData::kTypeInt: // 整型 pFiler->writeInt32((int)xdata.nVal); break; case AecXData::kTypeSoftId: id.setFromOldId(xdata.nVal); pFiler->writeSoftPointerId(id); break; case AecXData::kTypeHardId: id.setFromOldId(xdata.nVal); pFiler->writeHardPointerId(id); break; case AecXData::kTypeDouble: // 浮点 pFiler->writeDouble(xdata.dVal[0]); break; case AecXData::kTypePoint: // 点 case AecXData::kTypePointWorld: ptVal.x = xdata.dVal[0]; ptVal.y = xdata.dVal[1]; ptVal.z = xdata.dVal[2]; pFiler->writePoint3d(ptVal); break; case AecXData::kTypeVector: // 向量 case AecXData::kTypeVectorWorld: vt.x = xdata.dVal[0]; vt.y = xdata.dVal[1]; vt.z = xdata.dVal[2]; pFiler->writeVector3d(vt); break; case AecXData::kTypeMatrix: //矩阵 { CString sMat; MatrixToText(xdata, sMat); pFiler->writeString((LPCTSTR)sMat); } break; case AecXData::kTypeBinary: //binary data { pFiler->writeInt32(xdata.npszLen); pFiler->writeBytes(xdata.pData,xdata.npszLen); break; } break; case AecXData::kTypeString: // 字符串 pFiler->writeString(xdata.pszVal); break; default: break; } } pFiler->writeString(MAP_BLOCK_END); return Acad::eOk; } return Acad::eInvalidInput; } Acad::ErrorStatus AecDbObjXDataMap::dwgInFields(AcDbDwgFiler* pFiler) { if (pFiler == NULL) return Acad::eInvalidInput; BOOL bFinded = FALSE; Adesk::Int32 nVt = 0; Adesk::Int16 iVal = 0; AecXData xdata; TCHAR* pszKey = NULL; TCHAR* pszVal = NULL; AcGePoint3d ptVal; AcGeVector3d vt; AcGeMatrix3d xform; CString sKey,sTag; CString sText; CStringArray arTexts; Empty(); while ((pFiler->readString(&pszVal)) == Acad::eOk) { sTag = pszVal; if (pszVal != NULL) acutDelString(pszVal); if (sTag.CompareNoCase(MAP_BLOCK_BEGIN) == 0) { bFinded = TRUE; break; } } if (!bFinded) return Acad::eOk; while ((pFiler->readString(&pszKey)) == Acad::eOk) { sKey = pszKey; if (pszKey != NULL) acutDelString(pszKey); if (sKey.CompareNoCase(MAP_BLOCK_END) == 0) { break; } pFiler->readInt32(&nVt); xdata.nVt = (int)nVt; AcDbSoftPointerId id; AcDbHardPointerId idh; switch (nVt) { case AecXData::kTypeShort: pFiler->readInt16(&iVal); xdata.iVal = iVal; SetAt(sKey, xdata.iVal); break; case AecXData::kTypeInt: // 整型 pFiler->readInt32(&nVt); xdata.nVal = (int)nVt; SetAt(sKey, (int)xdata.nVal); break; case AecXData::kTypeSoftId: pFiler->readSoftPointerId(&id); SetAt(sKey,id); break; case AecXData::kTypeHardId: pFiler->readHardPointerId(&idh); SetAt(sKey,idh,FALSE); break; case AecXData::kTypeDouble: // 浮点 pFiler->readDouble(&xdata.dVal[0]); SetAt(sKey, xdata.dVal[0]); break; case AecXData::kTypePoint: // 点 pFiler->readPoint3d(&ptVal); SetAt(sKey, ptVal); break; case AecXData::kTypePointWorld: // cad变化点 pFiler->readPoint3d(&ptVal); SetAt(sKey, ptVal, TRUE); break; case AecXData::kTypeVector: // 向量 pFiler->readVector3d(&vt); sKey.Replace(DIF_VT_PT,_T(" ")); sKey.TrimRight(); SetAt(sKey, vt); break; case AecXData::kTypeVectorWorld: // cad变化向量 pFiler->readVector3d(&vt); sKey.Replace(DIF_VT_PT,_T(" ")); sKey.TrimRight(); SetAt(sKey, vt, TRUE); break; case AecXData::kTypeMatrix: //矩阵 pszVal = NULL; pFiler->readString(&pszVal); sText = pszVal; arTexts.RemoveAll(); Script2StringArray(sText,_T(','),arTexts); if (arTexts.GetSize() == 16) { for (int i = 0;i < 4;i++) { for (int j = 0;j < 4;j++) { xform.entry[i][j] = _ttof(arTexts.GetAt(i * 4 + j)); } } } SetAt(sKey, xform); if (pszVal != NULL) acutDelString(pszVal); break; case AecXData::kTypeBinary: //binary data { Adesk::Int32 nSize = 0; pFiler->readInt32(&nSize); if (nSize > 0) { void* pData = new byte[nSize]; pFiler->readBytes(pData,nSize); SetAt(sKey,pData,nSize); } break; } case AecXData::kTypeString: // 字符串 pszVal = NULL; pFiler->readString(&pszVal); SetAt(sKey, pszVal); if (pszVal != NULL) acutDelString(pszVal); break; default: break; } } return Acad::eOk; } //分区链块 static struct resbuf *PartitionBlocks(AecDbObjXDataMap::CIt iter, struct resbuf *&pTemp) { //最大65535 blocks int nBlocks = iter->second.npszLen / 127 + ((iter->second.npszLen % 127 > 0) ? 1 : 0); //head const char *pszBlocks = BINARY_CHUNKBLOCKS; struct resbuf *pTempNext = acutNewRb(AcDb::kDxfXdBinaryChunk); pTempNext->resval.rbinary.clen = 66; char *pBlocks = new char[66];//binarychunkblocks memset(pBlocks, 0, 66); pTempNext->resval.rbinary.buf = pBlocks; sprintf(pBlocks, "%s:%d:%d", pszBlocks,nBlocks, (int)iter->second.npszLen); pTemp->rbnext = pTempNext; pTemp = pTempNext; LONG_PTR nCut = iter->second.npszLen; char *pData = (char *)iter->second.pData; while (nCut > 127) { pTempNext = acutNewRb(AcDb::kDxfXdBinaryChunk); pTempNext->resval.rbinary.clen = (nCut > 127) ? 127 : nCut; pTempNext->resval.rbinary.buf = new char[pTempNext->resval.rbinary.clen]; memcpy(pTempNext->resval.rbinary.buf, pData, pTempNext->resval.rbinary.clen); pTemp->rbnext = pTempNext; pTemp = pTempNext; //下一段 pData += 127; nCut -= 127; if (nCut < 127 && nCut > 0)//最后一段 { pTempNext = acutNewRb(AcDb::kDxfXdBinaryChunk); pTempNext->resval.rbinary.clen = nCut; pTempNext->resval.rbinary.buf = new char[pTempNext->resval.rbinary.clen]; memcpy(pTempNext->resval.rbinary.buf, pData, pTempNext->resval.rbinary.clen); pTemp->rbnext = pTempNext; pTemp = pTempNext; } } return pTempNext; } // bXRecord = fase 操作扩展数据 bXRecord = true 操作扩展词典 BOOL AecDbObjXDataMap::XDMap2Resbuf(LPCTSTR pszApp, struct resbuf*& pRb,BOOL bXRecord,BOOL bOnlyWriteSecond) const { if(pszApp == NULL || m_xData.empty()) return FALSE; struct resbuf* pTemp = NULL; // 链表头 if (!bXRecord) { // 扩展数据需要链表头 pTemp = acutNewRb(AcDb::kDxfRegAppName); acutNewString(pszApp,pTemp->resval.rstring); pRb = pTemp; } AcDbObjectId id; ads_name adsName; struct resbuf* pTempNext = NULL; // 遍历map for(CIt iter = m_xData.begin(); iter != m_xData.end(); iter++) { if (!bOnlyWriteSecond)//如果不写key { pTempNext = acutNewRb(AcDb::kDxfXdAsciiString); acutNewString(iter->first, pTempNext->resval.rstring); if (pRb == NULL) { pRb = pTempNext; } else { pTemp->rbnext = pTempNext; } pTemp = pTempNext; } pTempNext = NULL; switch (iter->second.nVt) { case AecXData::kTypeShort: { pTempNext = acutNewRb(AcDb::kDxfXdInteger16); pTempNext->resval.rint = (short)iter->second.iVal; pTemp->rbnext = pTempNext; break; } case AecXData::kTypeInt: // 整型 pTempNext = acutNewRb(AcDb::kDxfXdInteger32); pTempNext->resval.rlong = (long)iter->second.nVal; pTemp->rbnext = pTempNext; break; /*--------------------------------------------------------------------------------------- Extended data (xdata) is created by applications written with ObjectARX? or AutoLISP? and can be added to any object. Xdata consists of a linked list of resbufs used by the application. (AutoCAD maintains the information but doesn't use it.) The data is associated with a DXF group code in the range of 1000 to 1071. */ /* so someguy want save id to an entity xdata ,must save as kDxfXdHandle kDxfXdHandle is same as string; */ case AecXData::kTypeSoftId: //s id id.setFromOldId(iter->second.nVal); acdbGetAdsName(adsName,id); if(bXRecord) pTempNext = acutBuildList(AcDb::kDxfSoftPointerId, adsName, 0); else { pTempNext = acutNewRb(AcDb::kDxfXdHandle); TCHAR szHandleStr[19]; memset(szHandleStr,0,sizeof(szHandleStr) ); id.handle().getIntoAsciiBuffer(szHandleStr); #if ARX < 17 acutNewString(szHandleStr, pTempNext->resval.rstring); #else acutNewString(pTempNext->resval.rstring, (int)(_tcslen(szHandleStr) + 1)); _tcsncpy_s(pTempNext->resval.rstring, _tcslen(szHandleStr) + 1, szHandleStr, _tcslen(szHandleStr)); #endif } pTemp->rbnext = pTempNext; break; case AecXData::kTypeHardId: //h id not support xdata id.setFromOldId(iter->second.nVal); acdbGetAdsName(adsName,id); if(bXRecord) pTempNext = acutBuildList(AcDb::kDxfHardPointerId, adsName, 0); else { pTempNext = acutNewRb(AcDb::kDxfXdHandle); TCHAR szHandleStr[19]; memset(szHandleStr,0,sizeof(szHandleStr) ); id.handle().getIntoAsciiBuffer(szHandleStr); #if ARX < 17 acutNewString(szHandleStr, pTempNext->resval.rstring); #else acutNewString(pTempNext->resval.rstring, (int)(_tcslen(szHandleStr) + 1)); _tcsncpy_s(pTempNext->resval.rstring, (int)(_tcslen(szHandleStr) + 1), szHandleStr, _tcslen(szHandleStr)); #endif } pTemp->rbnext = pTempNext; break; case AecXData::kTypeString: // 字符串 pTempNext = acutNewRb(AcDb::kDxfXdAsciiString); acutNewString(iter->second.pszVal, pTempNext->resval.rstring); pTemp->rbnext = pTempNext; break; case AecXData::kTypeDouble: // 浮点型 pTempNext = acutNewRb(AcDb::kDxfXdReal); pTempNext->resval.rreal = iter->second.dVal[0]; pTemp->rbnext = pTempNext; break; case AecXData::kTypePoint: // 点 pTempNext = acutNewRb(AcDb::kDxfXdXCoord); pTempNext->resval.rpoint[0] = iter->second.dVal[0]; pTempNext->resval.rpoint[1] = iter->second.dVal[1]; pTempNext->resval.rpoint[2] = iter->second.dVal[2]; pTemp->rbnext = pTempNext; break; case AecXData::kTypePointWorld: // 随cad实体变化的点 pTempNext = acutNewRb(AcDb::kDxfXdWorldXCoord); pTempNext->resval.rpoint[0] = iter->second.dVal[0]; pTempNext->resval.rpoint[1] = iter->second.dVal[1]; pTempNext->resval.rpoint[2] = iter->second.dVal[2]; pTemp->rbnext = pTempNext; break; case AecXData::kTypeVector: // 向量 pTempNext = acutNewRb(AcDb::kDxfXdXCoord); pTempNext->resval.rpoint[0] = iter->second.dVal[0]; pTempNext->resval.rpoint[1] = iter->second.dVal[1]; pTempNext->resval.rpoint[2] = iter->second.dVal[2]; pTemp->rbnext = pTempNext; break; case AecXData::kTypeVectorWorld: // 随cad实体变化的向量 pTempNext = acutNewRb(AcDb::kDxfXdWorldXDir); pTempNext->resval.rpoint[0] = iter->second.dVal[0]; pTempNext->resval.rpoint[1] = iter->second.dVal[1]; pTempNext->resval.rpoint[2] = iter->second.dVal[2]; pTemp->rbnext = pTempNext; break; case AecXData::kTypeMatrix: // 矩阵 { CString sMat; MatrixToText(iter->second, sMat); pTempNext = acutNewRb(AcDb::kDxfXdAsciiString); acutNewString(sMat, pTempNext->resval.rstring); pTemp->rbnext = pTempNext; } break; case AecXData::kTypeBinary: /*pTempNext = acutNewRb(AcDb::kDxfXdBinaryChunk); pTempNext->resval.rbinary.clen = iter->second.npszLen; pTempNext->resval.rbinary.buf = new char[iter->second.npszLen]; memcpy(pTempNext->resval.rbinary.buf,iter->second.pData,iter->second.npszLen); pTemp->rbnext = pTempNext; if (pTempNext->resval.rbinary.clen > 127) acutPrintf(_T("\nBinaryChunk Data overflow!!!"));*/ if (iter->second.npszLen > MAX_BINARYCHUNK) { pTempNext = PartitionBlocks(iter, pTemp); } else { pTempNext = acutNewRb(AcDb::kDxfXdBinaryChunk); pTempNext->resval.rbinary.clen = iter->second.npszLen; pTempNext->resval.rbinary.buf = new char[iter->second.npszLen]; memcpy(pTempNext->resval.rbinary.buf, iter->second.pData, iter->second.npszLen); pTemp->rbnext = pTempNext; } break; default: continue; } pTemp = pTempNext; pTempNext = NULL; } return (pRb != NULL); } void AecDbObjXDataMap::SecondAsKey(CString& sTemp,AecXData& xData) { switch (xData.nVt) { case AecXData::kTypeShort: sTemp.Format(_T("%d"), xData.iVal); break; case AecXData::kTypeInt: // 整型 sTemp.Format(_T("%d"),xData.nVal); break; case AecXData::kTypeSoftId: sTemp.Format(_T("%d"),xData.nVal); break; case AecXData::kTypeHardId: sTemp.Format(_T("%d"),xData.nVal); break; case AecXData::kTypeDouble: // 浮点 sTemp.Format(_T("%.9f"),xData.dVal[0]); break; case AecXData::kTypePoint: // 点 case AecXData::kTypePointWorld: case AecXData::kTypeVector: // 向量 case AecXData::kTypeVectorWorld: sTemp.Format(_T("%.9f,%.9f,%.9f"),xData.dVal[0],xData.dVal[1],xData.dVal[2]); break; case AecXData::kTypeMatrix: //矩阵 { MatrixToText(xData, sTemp); break; } case AecXData::kTypeString: // 字符串 { sTemp = xData.pszVal; break; } case AecXData::kTypeBinary: //binary data { CTime tNow = CTime::GetCurrentTime(); sTemp = tNow.Format(" %Y-%m-%d %H.%M.%S"); break; } default: break; } } //合并区链块 static bool MergeBlocks(AecXData &xData, struct resbuf*& pTemp) { if (pTemp == NULL) return false; char *pszBlocks = (char *)xData.pData; if (NULL != strstr(pszBlocks, BINARY_CHUNKBLOCKS1)) { //AAAA:5:635 //AAAA: char *pszId = strstr(pszBlocks, BINARY_CHUNKBLOCKS1); //5:635 char *pszNm = pszId; pszNm += strlen(BINARY_CHUNKBLOCKS1); int nBlocks = atoi(pszNm); //:635 char *pszSz = strstr(pszNm, ":"); pszSz += 1; //635 xData.npszLen = atoi(pszSz); if (xData.npszLen == 0) return false; xData.pData = new char[xData.npszLen]; memset(xData.pData, 0, xData.npszLen); struct resbuf *pLast = pTemp; char *pPos = (char*)xData.pData; pTemp = pTemp->rbnext; for (int i = 0; i < nBlocks; i++) { assert(pTemp->restype == AcDb::kDxfXdBinaryChunk);//must memcpy(pPos, pTemp->resval.rbinary.buf, pTemp->resval.rbinary.clen); pPos += pTemp->resval.rbinary.clen; pLast = pTemp; pTemp = pTemp->rbnext; } //待后续下移一段,确保当前指向正读取数据段 pTemp = pLast; return true; } return false; } // bXRecord = fase 操作扩展数据 bXRecord = true 操作扩展词典 BOOL AecDbObjXDataMap::Resbuf2XDMap(struct resbuf* pRb,BOOL bXRecord,AcDbDatabase* pDb,BOOL bKeyAsSecond/* = FALSE*/) { if(pRb == NULL) return FALSE; Empty(); struct resbuf* pTemp = pRb; // 跳过扩展数据头 扩展数据 if (!bXRecord) { pTemp = pRb->rbnext; } AcDbObjectId id; int nMapUnitIndex = 1; AecXData xData; CString sTemp; while (pTemp != NULL) { if (nMapUnitIndex == 1 && !bKeyAsSecond) { // skey键值 if (pTemp->restype == AcDb::kDxfXdAsciiString) { sTemp = pTemp->resval.rstring; nMapUnitIndex++; } } else { // value switch (pTemp->restype) { case AcDb::kDxfXdAsciiString: // 字符串 xData.nVt = AecXData::kTypeString; xData.npszLen = _tcslen(pTemp->resval.rstring) + 1; xData.pszVal = new TCHAR[xData.npszLen]; _tcsncpy_s(xData.pszVal, xData.npszLen, pTemp->resval.rstring, xData.npszLen - 1); nMapUnitIndex++; break; case AcDb::kDxfXdInteger16: xData.nVt = AecXData::kTypeShort; xData.iVal = pTemp->resval.rint; nMapUnitIndex++; break; case AcDb::kDxfXdInteger32: // 整型 xData.nVt = AecXData::kTypeInt; xData.nVal = pTemp->resval.rlong; nMapUnitIndex++; break; /*--------------------------------------------------------------------------------------- Extended data (xdata) is created by applications written with ObjectARX? or AutoLISP? and can be added to any object. Xdata consists of a linked list of resbufs used by the application. (AutoCAD maintains the information but doesn't use it.) The data is associated with a DXF group code in the range of 1000 to 1071. */ case AcDb::kDxfSoftPointerId: //s id not support xdata acdbGetObjectId(id, pTemp->resval.rlname); xData.nVt = AecXData::kTypeSoftId; xData.nVal = id.asOldId(); nMapUnitIndex++; break; case AcDb::kDxfHardPointerId: //h id not support xdata acdbGetObjectId(id, pTemp->resval.rlname); xData.nVt = AecXData::kTypeHardId; xData.nVal = id.asOldId(); nMapUnitIndex++; break; //-------------------------------------------------------------------------------------- case AcDb::kDxfXdHandle: //handle for xdata { AcDbHandle handle(pTemp->resval.rstring); if (pDb == NULL) pDb = acdbCurDwg(); if (pDb != NULL) { if ( Acad::eOk == pDb->getAcDbObjectId(id,false,handle) ) { xData.nVt = AecXData::kTypeSoftId; xData.nVal = id.asOldId(); nMapUnitIndex++; } } } break; case AcDb::kDxfXdReal: // 浮点型 xData.nVt = AecXData::kTypeDouble; xData.dVal[0] = pTemp->resval.rreal; nMapUnitIndex++; break; case AcDb::kDxfXdXCoord: // 点 向量 xData.nVt = AecXData::kTypePoint; xData.dVal[0] = pTemp->resval.rpoint[0]; xData.dVal[1] = pTemp->resval.rpoint[1]; xData.dVal[2] = pTemp->resval.rpoint[2]; nMapUnitIndex++; if(sTemp.Find(DIF_VT_PT) >= 0) { // 向量 xData.nVt = AecXData::kTypeVector; } break; case AcDb::kDxfXdWorldXCoord: {// 随cad实体变化的点 xData.nVt = AecXData::kTypePointWorld; xData.dVal[0] = pTemp->resval.rpoint[0]; xData.dVal[1] = pTemp->resval.rpoint[1]; xData.dVal[2] = pTemp->resval.rpoint[2]; nMapUnitIndex++; break; } case AcDb::kDxfXdWorldXDir: // 随cad实体变化的向量 { xData.nVt = AecXData::kTypeVectorWorld; xData.dVal[0] = pTemp->resval.rpoint[0]; xData.dVal[1] = pTemp->resval.rpoint[1]; xData.dVal[2] = pTemp->resval.rpoint[2]; nMapUnitIndex++; break; } case AcDb::kDxfXdBinaryChunk: { xData.nVt = AecXData::kTypeBinary; xData.npszLen = pTemp->resval.rbinary.clen; xData.pData = pTemp->resval.rbinary.buf; char* pszBlocks = (char *)xData.pData; if (NULL != strstr(pszBlocks, BINARY_CHUNKBLOCKS) && NULL != strstr(pszBlocks, BINARY_CHUNKBLOCKS1) ) { //aaaa:10:3333 MergeBlocks(xData, pTemp); } else { //... } nMapUnitIndex++; break; } default: break; } } if (bKeyAsSecond) { SecondAsKey(sTemp,xData); nMapUnitIndex++;//3 } if(nMapUnitIndex > 2) { // 插入一套 skey value std::pair pa(sTemp,xData); m_xData.insert(pa); nMapUnitIndex = 1; } //移向下一段 pTemp = pTemp->rbnext; } return !m_xData.empty(); } //支持扩展数据的4个方法 // 根据实体指针插入链表 bXRecord = fase 操作扩展数据 bXRecord = true 操作扩展词典 BOOL AecDbObjXDataMap::Write(AcDbObject* pEnt, LPCTSTR pszApp, BOOL bXRecord,BOOL bAppend,BOOL bOnlyWriteSecond) const { if (pEnt == NULL || pszApp == NULL) return FALSE; // 根据map生成链表 struct resbuf* pRb = NULL; if (!XDMap2Resbuf(pszApp ,pRb ,bXRecord,bOnlyWriteSecond)) return FALSE; Acad::ErrorStatus eStat = Acad::eOutOfMemory; if (!bXRecord) { // 扩展数据 struct resbuf* pTmpRb = pEnt->xData(pszApp); if (pTmpRb != NULL) { if (!bAppend) { // 存在清空 struct resbuf* pTmp = acutNewRb(AcDb::kDxfRegAppName); acutNewString(pszApp,pTmp->resval.rstring); pEnt->setXData(pTmp); acutRelRb(pTmpRb); acutRelRb(pTmp); } else//追加 { struct resbuf* pTmpRbNext = pTmpRb->rbnext; struct resbuf* pTemp = pRb; while(pTemp != NULL) { if (pTemp->rbnext == NULL) { pTemp->rbnext = pTmpRbNext; break; } pTemp = pTemp->rbnext; } // 存在清空 struct resbuf* pTmp = acutNewRb(AcDb::kDxfRegAppName); acutNewString(pszApp,pTmp->resval.rstring); pEnt->setXData(pTmp); acutRelRb(pTmp); } } // 注册扩展数据链表 int nRes = acdbRegApp(pszApp); eStat = pEnt->setXData(pRb); acutRelRb(pRb); return (eStat == Acad::eOk); } // 扩展词典 AcDbObjectId dictObjId, xrecObjId; pEnt->createExtensionDictionary(); dictObjId = pEnt->extensionDictionary(); // 打开扩展词典指针 AcDbDictionary* pDict = NULL; if (Acad::eOk != acdbOpenObject(pDict, dictObjId, AcDb::kForWrite)) { if (pRb != NULL) acutRelRb(pRb); return FALSE; } AcDbXrecord* pXrec = NULL; if (pDict->has(pszApp)) { // 存在此扩展词典 获取扩展词典指针 AcDbObject* pObj = NULL; pDict->getAt(pszApp,pObj,AcDb::kForWrite); if(pObj != NULL) { pXrec = AcDbXrecord::cast(pObj); if(pXrec != NULL) { // 重新设置扩展词典 eStat = pXrec->setFromRbChain(*pRb); } pObj->close(); } pDict->close(); } else { // 不存在此扩展词典 pXrec = new AcDbXrecord; eStat = pXrec->setFromRbChain(*pRb); eStat = pDict->setAt(pszApp,pXrec,xrecObjId); pXrec->close(); pDict->close(); } acutRelRb(pRb); return (eStat == Acad::eOk); } // 根据实体id插入链表 bXRecord = fase 操作扩展数据 bXRecord = true 操作扩展词典 BOOL AecDbObjXDataMap::Write(const AcDbObjectId& id,LPCTSTR pszApp,BOOL bXRecord,BOOL bAppend,BOOL bOnlyWriteSecond) const { if(pszApp == NULL) return FALSE; AcDbObject * pEnt = NULL; BOOL bWriteIdXData = FALSE; if(Acad::eOk == acdbOpenObject(pEnt, id, AcDb::kForWrite)) { // 根据实体指针设置链表 bWriteIdXData = Write(pEnt,pszApp,bXRecord,bAppend,bOnlyWriteSecond); pEnt->close(); } return bWriteIdXData; } BOOL AecDbObjXDataMap::WriteExDic(AcDbObject* pObj,LPCTSTR pszApp) const { if (pObj == NULL || pszApp == NULL) return FALSE; BOOL bWriteIdXData = FALSE; pObj->createExtensionDictionary(); AcDbObjectId idDic = pObj->extensionDictionary(); AcDbObject* pDicObj = NULL; if ( Acad::eOk == acdbOpenObject(pDicObj,idDic,AcDb::kForWrite)) { AcDbDictionary* pDic = AcDbDictionary::cast(pDicObj); if (pDic != NULL) { Acad::ErrorStatus es; AcDbObjectId idXdata; //先删除 es = pDic->getAt(pszApp,idXdata); if (es == Acad::eOk) { AcDbObject* pXDataObj = NULL; if ( Acad::eOk == acdbOpenObject(pXDataObj,idXdata,AcDb::kForWrite)) { pXDataObj->erase(); pXDataObj->close(); } } //再加入 AecDbObjXDataMapObj* pXDataMapObj = new AecDbObjXDataMapObj; pXDataMapObj->SetXDataMap(*this,false); AcDbObjectId idMap; Acad::ErrorStatus eRes = pDic->setAt(pszApp,pXDataMapObj,idMap); pXDataMapObj->close(); bWriteIdXData = (eRes == Acad::eOk) ? TRUE : FALSE; } pDicObj->close(); } return bWriteIdXData; } BOOL AecDbObjXDataMap::WriteExDic(const AcDbObjectId& id,LPCTSTR pszApp) const { if(pszApp == NULL) return FALSE; AcDbObject * pObj = NULL; BOOL bWriteIdXData = FALSE; if(Acad::eOk == acdbOpenObject(pObj, id, AcDb::kForWrite)) { bWriteIdXData = WriteExDic(pObj,pszApp); pObj->close(); } return bWriteIdXData; } BOOL AecDbObjXDataMap::ReadExDic(AcDbObject* pObj,LPCTSTR pszApp) { if (pObj == NULL || pszApp == NULL) return FALSE; BOOL bSuccess = FALSE; AcDbObjectId idDic = pObj->extensionDictionary(); AcDbObject* pDicObj = NULL; if ( Acad::eOk == acdbOpenObject(pDicObj,idDic,AcDb::kForRead)) { AcDbDictionary* pDic = AcDbDictionary::cast(pDicObj); if (pDic != NULL) { AcDbObject* pXDataObj = NULL; if ( Acad::eOk == pDic->getAt(pszApp,pXDataObj,AcDb::kForRead) ) { AecDbObjXDataMapObj* pXDataMapObj = AecDbObjXDataMapObj::cast(pXDataObj); if (pXDataMapObj != NULL) { bSuccess = pXDataMapObj->GetXDataMap(*this) ? TRUE : FALSE; } pXDataObj->close(); } } pDicObj->close(); } return bSuccess; } BOOL AecDbObjXDataMap::ReadExDic(const AcDbObjectId& id,LPCTSTR pszApp) { if(pszApp == NULL) return FALSE; AcDbObject * pObj = NULL; BOOL bSuccess = FALSE; if(Acad::eOk == acdbOpenObject(pObj, id, AcDb::kForRead)) { bSuccess = ReadExDic(pObj,pszApp); pObj->close(); } return bSuccess; } BOOL AecDbObjXDataMap::Write(CFile* pFileOut,BOOL bWriteUserData) const { // 1. 永远在最开头写入文件头魔数版本号 int nVersion = g_nVersion; pFileOut->Write(&nVersion, sizeof(int)); AecXData xdata; int nVt = -1; AcGePoint3d ptVal; AcGeVector3d vt; AcDbSoftPointerId id; int nSize = 0; CString sText,sVal; if (bWriteUserData) { int count(0); GetAt(BIM_REC_LEN, count); CMapStringToString mapStr2Str; for (int i = 0; i < count; i++) //1000条用户数据 { sText.Format(_T("user%d"), i); if (GetAt(sText, sVal)) { mapStr2Str.SetAt(sText, sVal); } } nSize = mapStr2Str.GetCount(); pFileOut->Write(&nSize, sizeof(int)); for (POSITION ps = mapStr2Str.GetStartPosition(); ps != NULL;) { mapStr2Str.GetNextAssoc(ps,sText,sVal); // 【修复】彻底摒弃 _bstr_t,使用原生 TCHAR 直接序列化 nSize = sText.GetLength(); pFileOut->Write(&nSize, sizeof(int)); pFileOut->Write((LPCTSTR)sText, nSize * sizeof(TCHAR)); nVt = AecXData::kTypeString; pFileOut->Write(&nVt, sizeof(int)); nSize = sVal.GetLength(); pFileOut->Write(&nSize, sizeof(int)); pFileOut->Write((LPCTSTR)sVal, nSize * sizeof(TCHAR)); } } else { //多少个 nSize = m_xData.size(); pFileOut->Write(&nSize,sizeof(int)); for (CIt it = m_xData.begin(); it != m_xData.end(); ++it) { xdata = (*it).second; nVt = xdata.nVt; sText = (*it).first; //key nSize = it->first.GetLength(); pFileOut->Write(&nSize,sizeof(int)); pFileOut->Write((LPCTSTR)it->first, nSize * sizeof(TCHAR)); //vt pFileOut->Write(&nVt,sizeof(int)); switch (nVt) { case AecXData::kTypeShort: pFileOut->Write(&xdata.iVal,sizeof(short)); break; case AecXData::kTypeInt: // 整型 pFileOut->Write(&xdata.nVal,sizeof(int)); break; case AecXData::kTypeSoftId: pFileOut->Write(&xdata.nVal,sizeof(int)); break; case AecXData::kTypeHardId: pFileOut->Write(&xdata.nVal,sizeof(int)); break; case AecXData::kTypeDouble: // 浮点 pFileOut->Write(&xdata.dVal[0],sizeof(double)); break; case AecXData::kTypePoint: // 点 case AecXData::kTypePointWorld: case AecXData::kTypeVector: // 向量 case AecXData::kTypeVectorWorld: pFileOut->Write(xdata.dVal,sizeof(double) * 3); break; case AecXData::kTypeMatrix: //矩阵:二进制块([魔数][16个double]),自描述 { double ar[16]; if (GetMatrixData(xdata, ar)) { byte buf[kMatrixBinBytes]; int nMagic = kMatrixMagic; memcpy(buf, &nMagic, sizeof(int)); memcpy(buf + sizeof(int), ar, 16 * sizeof(double)); pFileOut->Write(buf, kMatrixBinBytes); } } break; case AecXData::kTypeString: // 字符串 { nSize = _tcsclen(xdata.pszVal); pFileOut->Write(&nSize,sizeof(int)); pFileOut->Write(xdata.pszVal, nSize * sizeof(TCHAR)); } break; case AecXData::kTypeBinary: { pFileOut->Write(&xdata.npszLen,sizeof(int)); pFileOut->Write(xdata.pData, xdata.npszLen); } break; default: break; } } } return TRUE; } BOOL AecDbObjXDataMap::Write(CString &strOut, BOOL bWriteUserData) const { CMemFile mf; if (Write(&mf, bWriteUserData)) { mf.SeekToBegin(); strOut = Base64::EncodeF2W(&mf).c_str(); return 1; } return 0; } // bXRecord = fase 操作扩展数据 bXRecord = true 操作扩展词典 BOOL AecDbObjXDataMap::Read(AcDbObject* pEnt,LPCTSTR pszApp,BOOL bXRecord,BOOL bKeyAsSecond/* = FALSE*/) { if(pEnt == NULL || pszApp == NULL) return FALSE; struct resbuf* pRb = NULL; BOOL bResbuf2XDmap = FALSE; if (!bXRecord) { // 扩展数据 pRb = pEnt->xData(pszApp); if(pRb == NULL) return FALSE; bResbuf2XDmap = Resbuf2XDMap(pRb,bXRecord,pEnt->database(),bKeyAsSecond); acutRelRb(pRb); return bResbuf2XDmap; } // 获取扩展数据(词典)id AcDbObjectId dictObjId, xrecObjId; dictObjId = pEnt->extensionDictionary(); if (dictObjId.isNull()) { // 没有扩展数据 return FALSE; } // 打开扩展词典实体 AcDbDictionary* pDict = NULL; if (Acad::eOk != acdbOpenObject(pDict, dictObjId, AcDb::kForRead)) { return FALSE; } AcDbXrecord *pXrec = NULL; AcDbObject* pObj = NULL; // 获取扩展数据链表 if (Acad::eOk == pDict->getAt(pszApp,pObj,AcDb::kForRead)) { pXrec = AcDbXrecord::cast(pObj); if (pXrec != NULL) { pXrec->rbChain(&pRb); if (pRb != NULL) { bResbuf2XDmap = Resbuf2XDMap(pRb,bXRecord,pEnt->database(),bKeyAsSecond); acutRelRb(pRb); } } pObj->close(); } else { // 获取链表失败 pDict->close(); return FALSE; } pDict->close(); return bResbuf2XDmap; } // bXRecord = fase 操作扩展数据 bXRecord = true 操作扩展词典 BOOL AecDbObjXDataMap::Read(const AcDbObjectId& id,LPCTSTR pszApp,BOOL bXRecord,BOOL bKeyAsSecond/* = FALSE*/) { AcDbObject * pEnt = NULL; BOOL bReadIdXData = FALSE; if(Acad::eOk == acdbOpenObject(pEnt, id, AcDb::kForRead)) { bReadIdXData = Read(pEnt,pszApp,bXRecord,bKeyAsSecond); pEnt->close(); } return bReadIdXData; } BOOL AecDbObjXDataMap::Read(CFile *pFileOut, BOOL bWriteUserData) { Empty(); int nMarker = 0; ULONGLONG startPos = pFileOut->GetPosition(); pFileOut->Read(&nMarker, sizeof(int)); BOOL bIsOldVersion = FALSE; // 无版本头(老格式,文件以 Base64 块标记开头) if (nMarker != g_nVersion) { // 无版本头:回退跳过 Base64(MAP_BLOCK_BEGIN) 前缀 bIsOldVersion = TRUE; pFileOut->Seek(startPos, CFile::begin); CString sTemp = MAP_BLOCK_BEGIN; _bstr_t bst((LPCTSTR)sTemp); std::string str; str.append((const char *)bst); std::string str2 = Base64::Encode(str); char *pszBuf = new char[str2.length() + 1]; memset(pszBuf, 0, str2.length() + 1); pFileOut->Read(pszBuf, (UINT)str2.length()); delete[] pszBuf; } int nCount = 0; pFileOut->Read(&nCount, sizeof(int)); AecXData xdata; int nLen = 0; for (int i = 0; i < nCount; i++) { ::memset(&xdata, 0, sizeof(xdata)); pFileOut->Read(&nLen, sizeof(int)); TCHAR *pszKey = new TCHAR[nLen + 1]; ::memset(pszKey, 0, (nLen + 1) * sizeof(TCHAR)); pFileOut->Read(pszKey, nLen * sizeof(TCHAR)); pFileOut->Read(&xdata.nVt, sizeof(int)); switch (xdata.nVt) { case AecXData::kTypeShort: { short sTemp = 0; pFileOut->Read(&sTemp, sizeof(short)); xdata.iVal = sTemp; break; } case AecXData::kTypeInt: { int nTemp = 0; pFileOut->Read(&nTemp, sizeof(int)); xdata.nVal = nTemp; break; } case AecXData::kTypeSoftId: case AecXData::kTypeHardId: { unsigned int uTemp = 0; pFileOut->Read(&uTemp, sizeof(int)); xdata.nVal = uTemp; break; } case AecXData::kTypeDouble: pFileOut->Read(&xdata.dVal[0], sizeof(double)); break; case AecXData::kTypePoint: case AecXData::kTypePointWorld: case AecXData::kTypeVector: case AecXData::kTypeVectorWorld: pFileOut->Read(xdata.dVal, sizeof(double) * 3); break; case AecXData::kTypeString: { int nCharCount = 0; pFileOut->Read(&nCharCount, sizeof(int)); // 读到字符数 xdata.npszLen = nCharCount + 1; // 修正:内部长度需包含 \0 xdata.pszVal = new TCHAR[xdata.npszLen]; ::memset(xdata.pszVal, 0, sizeof(TCHAR) * xdata.npszLen); pFileOut->Read(xdata.pszVal, sizeof(TCHAR) * nCharCount); break; } case AecXData::kTypeMatrix: { // 先读一个 int:等于魔数即为新的二进制块,否则是旧的字符串结构(该 int 是字符数) int nHead = 0; pFileOut->Read(&nHead, sizeof(int)); if (nHead == kMatrixMagic) { // 新格式:紧接 16 个 double double ar[16]; pFileOut->Read(ar, sizeof(ar)); SetMatrixData(xdata, ar); } else { // 旧格式:nHead 为字符数,读字符串后解析成二进制块 TCHAR* pszText = new TCHAR[nHead + 1]; ::memset(pszText, 0, sizeof(TCHAR) * (nHead + 1)); pFileOut->Read(pszText, sizeof(TCHAR) * nHead); double ar[16]; if (TextToMatrix(pszText, ar)) SetMatrixData(xdata, ar); delete[] pszText; } break; } case AecXData::kTypeBinary: { pFileOut->Read(&xdata.npszLen, sizeof(int)); xdata.pData = new byte[xdata.npszLen]; ::memset(xdata.pData, 0, xdata.npszLen); // 修正:使用 pData 统一语义 pFileOut->Read(xdata.pData, (UINT)xdata.npszLen); break; } default: delete[] pszKey; continue; } It it = m_xData.find(pszKey); if (it != m_xData.end()) { it->second.Free(); it->second = xdata; } else { m_xData.insert(std::make_pair(pszKey, xdata)); } delete[] pszKey; } // 修正:吃掉旧版本留在文件尾部的 MAP_BLOCK_END,防止污染文件流 if (bIsOldVersion) { CString sTemp = MAP_BLOCK_END; _bstr_t bst((LPCTSTR)sTemp); std::string str; str.append((const char *)bst); std::string str2 = Base64::Encode(str); char *pszBuf = new char[str2.length() + 1]; memset(pszBuf, 0, str2.length() + 1); pFileOut->Read(pszBuf, (UINT)str2.length()); delete[] pszBuf; } return TRUE; } BOOL AecDbObjXDataMap::Read(LPCTSTR pszIn, BOOL bWriteUserData) { if (!pszIn) return 0; CMemFile mf; Base64::DecodeW2F(pszIn, &mf); mf.SeekToBegin(); return Read(&mf, bWriteUserData); } SHJson::WValue& AecDbObjXDataMap::ToJson() const { AecXData xdata; AcGePoint3d ptVal; AcGeVector3d vt; AcDbSoftPointerId id; int type(-1); std::wstring name(_T("")); WValue node; m_json.SetArray(); node.SetObject(); for (CIt it = m_xData.begin(); it != m_xData.end(); ++it) { xdata = (*it).second; node.SetNull(); node.SetObject(); WValue value, name; value.SetObject(); type = xdata.nVt; addMember(node, _T("name"), it->first); addMember(node, _T("type"), type); switch (type) { case AecXData::kTypeShort: addMember(node, _T("value"), xdata.iVal); case AecXData::kTypeInt: // 整型 addMember(node, _T("value"), xdata.nVal); break; case AecXData::kTypeSoftId: case AecXData::kTypeHardId: addMember(node, _T("value"), xdata.nVal); break; case AecXData::kTypeDouble: // 浮点 addMember(node, _T("value"), xdata.dVal[0]); break; case AecXData::kTypePoint: // 点 case AecXData::kTypePointWorld: toJson(AcGePoint3d(xdata.dVal[0], xdata.dVal[1], xdata.dVal[2]), value); addMember(node, _T("value"), value); break; case AecXData::kTypeVector: // 向量 case AecXData::kTypeVectorWorld: toJson(AcGeVector3d(xdata.dVal[0], xdata.dVal[1], xdata.dVal[2]), value); addMember(node, _T("value"), value); break; case AecXData::kTypeMatrix: //矩阵 { double ar[16]; if (GetMatrixData(xdata, ar)) { AcGeMatrix3d xform; int k = 0; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) xform.entry[i][j] = ar[k++]; toJson(xform, value); addMember(node, _T("value"), value); } break; } case AecXData::kTypeBinary: //binary data { char *p = new char[xdata.npszLen]; LONG_PTR len(sizeof(char) * xdata.npszLen); ::memset(p, 0, len); ::memcpy(p, xdata.pData, len); std::wstring ws(_T("")); value.SetObject(); addMember(value, _T("len"), len); if (len) { std::string s = Base64::Encode(p, len); ws = Base64::ansii2Unicode(s.c_str(), CP_UTF8); } addMember(value, _T("data"), ws.c_str()); addMember(node, _T("value"), value); DELETE_ARR_(p); break; } break; case AecXData::kTypeString: // 字符串 addMember(node, _T("value"), xdata.pszVal); break; default: break; } pushBack(m_json, node); } return m_json; } bool AecDbObjXDataMap::ByJson(const WValue &v) { if (!v.IsArray()) return false; int type(-1); std::wstring name(_T("")); for (VCIt it = v.Begin(); it != v.End(); ++it) { WCValue &vv(*it); if (!vv.IsObject()) continue; if (!vv.HasMember(_T("type")) || !vv.HasMember(_T("name")) || !vv.HasMember(_T("value"))) continue; type = vv[_T("type")].GetInt(); name = vv[_T("name")].GetString(); WCValue &va(vv[_T("value")]); switch (type) { case AecXData::kTypeShort: SetAt(name.c_str(), va.GetInt()); //?? return true; case AecXData::kTypeInt: // 整型 SetAt(name.c_str(), va.GetInt()); return true; case AecXData::kTypeSoftId: SetAt(name.c_str(), (DWORD)va.GetUint()); return true; case AecXData::kTypeHardId: SetAt(name.c_str(), (DWORD)va.GetUint64()); return true; case AecXData::kTypeDouble: // 浮点 SetAt(name.c_str(), va.GetDouble()); return true; case AecXData::kTypePoint: // 点 case AecXData::kTypePointWorld: { AcGePoint3d pt; if (!byJson(va, pt)) return false; SetAt(name.c_str(), pt); return true; } case AecXData::kTypeVector: // 向量 case AecXData::kTypeVectorWorld: { AcGeVector3d vt; if (!byJson(va, vt)) return false; SetAt(name.c_str(), vt); return true; } case AecXData::kTypeMatrix: //矩阵 { AcGeMatrix3d m; if (byJson(va, m)) return false; SetAt(name.c_str(), m); return true; } case AecXData::kTypeBinary: //binary data { char *pBuffer(NULL); if (va.IsObject()) { MCIt itLen = va.FindMember(_T("len")); MCIt itData = va.FindMember(_T("data")); if (itLen != va.MemberEnd() && itData != va.MemberEnd()) { LONG_PTR len = itLen->value.GetInt64(); std::wstring ws = itData->value.GetString(); std::string s = Base64::unicode2Ansii(ws.c_str(), CP_UTF8); // 这么写的原因是 decode() 函数有问题,反回的长度会大于原有长度,其内存会用0补齐 // 所以,这里直接用原有长度,并不会影响内存的释放。 if (Base64::Decode(s, pBuffer) >= len) { SetAt(name.c_str(), pBuffer, len); } } } DELETE_ARR_(pBuffer); return true; } case AecXData::kTypeString: // 字符串 SetAt(name.c_str(), va.GetString()); return true; default: break; } } return false; } bool AecDbObjXDataMap::getBimDatas(const AecDbObjXDataMap & XData, SH_BIM_BLOCK & bim) { int count(0); if (!XData.GetAt(BIM_REC_LEN, count)) return false; bim.clear(); int idx(-1); CString key, value, n, v; for (int i = 0; i < count; ++i) { key.Format(_T("user%d"), i); if (!XData.GetAt(key, value)) continue; idx = value.Find(_T(":")); if (idx == -1) continue; n = value.Left(idx); v = value.Right(value.GetLength() - idx - 1); bim.push_back(std::make_pair(n, v)); } return !bim.empty(); } bool AecDbObjXDataMap::setBimDatas(AecDbObjXDataMap & XData, const SH_BIM_BLOCK & bim) { int count(0); XData.GetAt(BIM_REC_LEN, count); CString name, value; for (int i = 0; i < count; ++i) { name.Format(_T("user%d"), i); XData.RemoveAt(name); } if (XData.SetAt(BIM_REC_LEN, (int)bim.size())) { for (int i = 0; i < bim.size(); ++i) { const SH_BIM_REC &rec(bim[i]); name.Format(_T("user%d"), i); value.Format(_T("%s:%s"), rec.first, rec.second); XData.SetAt(name, value); } return true; } return false; } bool AecDbObjXDataMap::findBimData(const AecDbObjXDataMap &XData , LPCTSTR pszKey , CString &strValue , CString &strUserKey) { int count(0); if (!XData.GetAt(BIM_REC_LEN, count)) return false; int idx(-1); CString key, value, n, v;; for (int i = 0; i < count; ++i) { key.Format(_T("user%d"), i); if (!XData.GetAt(key, value)) continue; idx = value.Find(_T(":")); if (idx == -1) continue; n = value.Left(idx); if (n == pszKey) { strUserKey = key; strValue = value.Right(value.GetLength() - idx - 1); return true; } } return false; } bool AecDbObjXDataMap::getBimData(const AecDbObjXDataMap & XData, LPCTSTR pszKey, CString & strValue) { if (!pszKey) return false; CString strUserKey; if (!findBimData(XData, pszKey, strValue, strUserKey)) return false; return true; } bool AecDbObjXDataMap::setBimData(AecDbObjXDataMap & XData, LPCTSTR pszKey, LPCTSTR pszValue) { if (!pszKey || !pszValue) return false; CString strUserKey, strValue; if (findBimData(XData, pszKey, strValue, strUserKey)) { return XData.SetAt(strUserKey, CString(pszKey) + _T(":") + pszValue) ? true : false; } else { int count(0); XData.GetAt(BIM_REC_LEN, count); CString userKey(_T("")); userKey.Format(_T("user%d"), count); XData.SetAt(BIM_REC_LEN, count + 1); return XData.SetAt(userKey, CString(pszKey) + _T(":") + pszValue) ? true : false; } return false; } bool AecDbObjXDataMap::delBimData(AecDbObjXDataMap & XData, LPCTSTR pszKey) { if (!pszKey) return false; CString strUserKey, strValue; if (!findBimData(XData, pszKey, strValue, strUserKey)) return false; if (XData.RemoveAt(strUserKey)) { int count(0); XData.GetAt(BIM_REC_LEN, count); if (count > 0) XData.SetAt(BIM_REC_LEN, count - 1); return true; } return false; } size_t AecDbObjXDataMap::Count() const { return m_xData.size(); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// AecXData::AecXData() { nVt = 0; npszLen = 0; nVal = 0; // 清零 union,防止野指针 } bool AecXData::CopyFrom(const AecXData& src) { if (this == &src) return true; Free(); nVt = src.nVt; npszLen = src.npszLen; // 先整体复制 union(POD 类型一次到位),字符串/二进制随后重新分配覆盖 memcpy(dVal, src.dVal, sizeof(dVal)); if (src.nVt == AecXData::kTypeString) { // 字符串 pszVal = NULL; if (src.pszVal != NULL && src.npszLen > 0) { pszVal = new TCHAR[src.npszLen]; _tcsncpy_s(pszVal, src.npszLen, src.pszVal, src.npszLen - 1); } else { npszLen = 0; } } else if (src.nVt == AecXData::kTypeMatrix) { // 统一规范化为 [魔数][16个double] 的二进制块 double ar[16]; if (GetMatrixData(src, ar)) SetMatrixData(*this, ar); else { nVt = 0; npszLen = 0; nVal = 0; } } else if (src.nVt == AecXData::kTypeBinary) { // 二进制数据块 pData = NULL; if (src.pData != NULL && src.npszLen > 0) { pData = new byte[src.npszLen]; memcpy(pData, src.pData, src.npszLen); } else { npszLen = 0; } } return true; } void AecXData::Free() { // 字符串类型(用 pszVal 保存) if (nVt == kTypeString) { if (pszVal != NULL && npszLen > 0) { delete[] pszVal; pszVal = NULL; } } // 二进制数据块类型(矩阵也以16个double的二进制块保存,同为 pData) else if (nVt == kTypeBinary || nVt == kTypeMatrix) { if (pData != NULL && npszLen > 0) { // 必须强制转换 void* 为 byte* 才能触发 C++ 正确的数组析构逻辑 delete[] (byte*)pData; pData = NULL; } } // 重置状态 npszLen = 0; nVt = 0; nVal = 0; }