refactor: 管道截面统一存 SAT,曲线写路径退役 #29

Merged
gjm merged 2 commits from company-desktop-computer/refactor/ewpipebase-region-sat AGit into main 2026-10-21 23:05:00 +08:00
2 changed files with 126 additions and 125 deletions
Showing only changes of commit 8941246b16 - Show all commits

No files matched your search

@@ -658,6 +658,40 @@ namespace
return es != Acad::eOk; return es != Acad::eOk;
} }
// 读端只接受纯文件名:DWG 里存的名字不可信,去掉路径成分防止写到临时目录之外
CString SanitizeRegionTempName(const CString& sFileName)
{
CString sName = sFileName;
int nSlash = sName.ReverseFind(_T('\\'));
int nSlash2 = sName.ReverseFind(_T('/'));
if (nSlash2 > nSlash)
nSlash = nSlash2;
if (nSlash >= 0)
sName = sName.Mid(nSlash + 1);
// 空名、上跳目录、盘符一律丢弃,退回固定名
if (sName.IsEmpty() || sName.Find(_T("..")) >= 0 || sName.Find(_T(':')) >= 0)
sName = _T("region_tmp.dat");
return sName;
}
// acisOut 不可用时的兜底:写 errorfile 标记,再让 region 自己写原生数据
Acad::ErrorStatus WriteRegionNativeFallback(AcDbDwgFiler* pFiler, AcDbRegion* pRegion)
{
pFiler->writeString(_T("errorfile"));
char pszTxt[7];
::memset(pszTxt, 0, sizeof(pszTxt));
pFiler->writeUInt32(7);
pFiler->writeBytes(pszTxt, 7);
return pRegion->dwgOutFields(pFiler);
}
} }
AcDbRegion *AecDbEwPipeBase::RegionFromCurvesDwgInFields(AcDbDwgFiler *pFiler, Adesk::UInt32 nLen) AcDbRegion *AecDbEwPipeBase::RegionFromCurvesDwgInFields(AcDbDwgFiler *pFiler, Adesk::UInt32 nLen)
@@ -760,9 +794,12 @@ AcDbRegion* AecDbEwPipeBase::RegionAcisInDwgInFields(AcDbDwgFiler* pFiler)
//高版本acis方式 //高版本acis方式
CString sFileName; CString sFileName;
TCHAR* pszFileName = NULL; TCHAR* pszFileName = NULL;
pFiler->readString(&pszFileName); if (pFiler->readString(&pszFileName) != Acad::eOk || pszFileName == NULL)
if (pszFileName != NULL)
{ {
acutPrintf(_T("\nAecDbEwPipeBase: 截面读文件名失败。"));
return NULL;
}
//Region_%s.dat //Region_%s.dat
sFileName = pszFileName; sFileName = pszFileName;
acutDelString(pszFileName); acutDelString(pszFileName);
@@ -770,56 +807,79 @@ AcDbRegion* AecDbEwPipeBase::RegionAcisInDwgInFields(AcDbDwgFiler* pFiler)
Adesk::UInt32 nLen = 0; Adesk::UInt32 nLen = 0;
pFiler->readUInt32(&nLen); pFiler->readUInt32(&nLen);
if (nLen > 0) if (nLen == 0)
{ return NULL;
char* pszTxt = new char[nLen];
char* pszTxt = new char[nLen + 1];
::memset(pszTxt, 0, nLen + 1);
pFiler->readBytes(pszTxt,nLen); pFiler->readBytes(pszTxt,nLen);
if (sFileName.CompareNoCase(_T("errorfile")) == 0) if (sFileName.CompareNoCase(_T("errorfile")) == 0)
{ {
//原生写法 //原生写法
AcDbRegion* pRegion = (AcDbRegion*)AcDbRegion::desc()->create(); delete[] pszTxt;
Acad::ErrorStatus es = pRegion->dwgInFields(pFiler);
AcDbRegion* pRegion = (AcDbRegion*)AcDbRegion::desc()->create();
if (pRegion == NULL)
{
acutPrintf(_T("\nAecDbEwPipeBase: 截面原生读取时创建 region 失败。"));
return NULL;
}
Acad::ErrorStatus es = pRegion->dwgInFields(pFiler);
if (es != Acad::eOk)
{
acutPrintf(_T("\nAecDbEwPipeBase: 截面原生 dwgInFields 失败,err=%d。"),es);
delete pRegion;
return NULL;
}
return pRegion; return pRegion;
} }
else
{
CString sFullPath = FilePath::getSystemTemporaryFolder(); CString sFullPath = FilePath::getSystemTemporaryFolder();
sFullPath += _T("\\"); sFullPath += _T("\\");
sFullPath += sFileName; sFullPath += SanitizeRegionTempName(sFileName);
CFile file; CFile file;
if (file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite)) if (!file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite))
{ {
acutPrintf(_T("\nAecDbEwPipeBase: 截面临时文件创建失败:%s"),(LPCTSTR)sFullPath);
delete[] pszTxt;
return NULL;
}
file.Write(pszTxt,nLen); file.Write(pszTxt,nLen);
file.Close(); file.Close();
delete[] pszTxt;
AcDbVoidPtrArray arBodyPtrs; AcDbVoidPtrArray arBodyPtrs;
Acad::ErrorStatus es; Acad::ErrorStatus es = AcDbBody::acisIn(sFullPath,arBodyPtrs);
if ( Acad::eOk == (es = AcDbBody::acisIn(sFullPath,arBodyPtrs) ) ) if (es != Acad::eOk)
{
if (arBodyPtrs.length() > 0)
{
AcDbEntity* pEnt = (AcDbEntity*)arBodyPtrs.first();
AcDbRegion* pRegion = AcDbRegion::cast(pEnt);
if (pRegion != NULL)
{ {
acutPrintf(_T("\nAecDbEwPipeBase: 截面 acisIn 失败,len=%u,err=%d。"),nLen,es);
::DeleteFile(sFullPath); ::DeleteFile(sFullPath);
delete[] pszTxt;
return pRegion;
}
//可能其他的合成或boolsubstract...
}
}
::DeleteFile(sFullPath);
}
}
delete[] pszTxt;
}
}
return NULL; return NULL;
}
// acisIn 返回的实体未入库,由调用方负责释放;只留第一个 region,其余丢弃
AcDbRegion* pRegion = NULL;
for (int i = 0;i < arBodyPtrs.length();i++)
{
AcDbEntity* pEnt = (AcDbEntity*)arBodyPtrs.at(i);
if (pRegion == NULL)
{
pRegion = AcDbRegion::cast(pEnt);
if (pRegion != NULL)
continue;
}
delete pEnt;
}
if (pRegion == NULL)
acutPrintf(_T("\nAecDbEwPipeBase: 截面 acisIn 未返回 region,len=%u。"),nLen);
::DeleteFile(sFullPath);
return pRegion;
} }
AcDbRegion* AecDbEwPipeBase::SectionRegionDwgInFields(AcDbDwgFiler* pFiler,int nVer) AcDbRegion* AecDbEwPipeBase::SectionRegionDwgInFields(AcDbDwgFiler* pFiler,int nVer)
@@ -1132,34 +1192,19 @@ Acad::ErrorStatus AecDbEwPipeBase::BaseCurveDwgOutFields(AcDbCurve* pBaseCurve,A
return Acad::eOk; return Acad::eOk;
} }
Acad::ErrorStatus AecDbEwPipeBase::RegionExplodeDwgOutFields(AcDbDwgFiler* pFiler,AcDbVoidPtrArray& arCurPtrs) const
{
Adesk::UInt32 nCurs = arCurPtrs.length();
pFiler->writeUInt32(nCurs);
AcDbCurve* pCurve = NULL;
for (int i = 0;i < arCurPtrs.length();i++)
{
pCurve = (AcDbCurve*)arCurPtrs.at(i);
BaseCurveDwgOutFields(pCurve,pFiler);
delete pCurve;
}
return Acad::eOk;
}
Acad::ErrorStatus AecDbEwPipeBase::RegionAcisoutDwgOutFields(AcDbDwgFiler* pFiler) const Acad::ErrorStatus AecDbEwPipeBase::RegionAcisoutDwgOutFields(AcDbDwgFiler* pFiler) const
{ {
if (m_pRegion == NULL) if (m_pRegion == NULL)
return Acad::eInvalidInput; return Acad::eInvalidInput;
//开始写acis方式 //开始写acis方式
//避免多文档crash //避免多文档crash:文件名带进程号,同一张图在两个 CAD 实例里同时打开不会互相覆盖
TCHAR szHandleStr[19]; TCHAR szHandleStr[19];
memset(szHandleStr,0,sizeof(szHandleStr) ); memset(szHandleStr,0,sizeof(szHandleStr) );
objectId().handle().getIntoAsciiBuffer(szHandleStr); objectId().handle().getIntoAsciiBuffer(szHandleStr);
CString sFileName; CString sFileName;
sFileName.Format(_T("Region_%s.dat"),szHandleStr); sFileName.Format(_T("Region_%lu_%s.dat"),(unsigned long)::GetCurrentProcessId(),szHandleStr);
CString sFullPath = FilePath::getSystemTemporaryFolder(); CString sFullPath = FilePath::getSystemTemporaryFolder();
sFullPath += _T("\\"); sFullPath += _T("\\");
@@ -1168,21 +1213,43 @@ Acad::ErrorStatus AecDbEwPipeBase::RegionAcisoutDwgOutFields(AcDbDwgFiler* pFile
AcDbVoidPtrArray arBodyPtrs; AcDbVoidPtrArray arBodyPtrs;
arBodyPtrs.append(m_pRegion); arBodyPtrs.append(m_pRegion);
Acad::ErrorStatus es; Acad::ErrorStatus es = AcDbBody::acisOut(sFullPath, arBodyPtrs);
if (Acad::eOk == (es = AcDbBody::acisOut(sFullPath, arBodyPtrs))) if (Acad::eOk != es)
{ {
acutPrintf(_T("\nAecDbEwPipeBase: 截面 acisOut 失败,handle=%s,err=%d,改用原生写法。"),szHandleStr,es);
::DeleteFile(sFullPath);
return WriteRegionNativeFallback(pFiler, m_pRegion);
}
CFile file; CFile file;
if (file.Open(sFullPath, CFile::modeRead)) if (!file.Open(sFullPath, CFile::modeRead))
{ {
acutPrintf(_T("\nAecDbEwPipeBase: 截面临时文件打开失败,handle=%s,改用原生写法。"),szHandleStr);
::DeleteFile(sFullPath);
return WriteRegionNativeFallback(pFiler, m_pRegion);
}
//确认REGION不会超过32位数量级字节 //确认REGION不会超过32位数量级字节
//强制转换兼容可能的07-09CAD //强制转换兼容可能的07-09CAD
ULONGLONG dwFileLength = file.GetLength(); ULONGLONG dwFileLength = file.GetLength();
Adesk::UInt32 nLen = (Adesk::UInt32)dwFileLength; Adesk::UInt32 nLen = (Adesk::UInt32)dwFileLength;
char* pszTxt = new char[nLen]; char* pszTxt = new char[nLen + 1];
file.Read(pszTxt, nLen); ::memset(pszTxt, 0, nLen + 1);
UINT nRead = file.Read(pszTxt, nLen);
file.Close(); file.Close();
if (nLen == 0 || nRead != nLen)
{
// 空文件或短读:尾部是未初始化内存,不能写进 DWG
acutPrintf(_T("\nAecDbEwPipeBase: 截面临时文件异常,handle=%s,期望%u字节实读%u字节,改用原生写法。")
,szHandleStr,nLen,nRead);
::DeleteFile(sFullPath);
delete[] pszTxt;
return WriteRegionNativeFallback(pFiler, m_pRegion);
}
pFiler->writeString((LPCTSTR)sFileName); pFiler->writeString((LPCTSTR)sFileName);
pFiler->writeUInt32(nLen); pFiler->writeUInt32(nLen);
pFiler->writeBytes(pszTxt,nLen); pFiler->writeBytes(pszTxt,nLen);
@@ -1190,88 +1257,23 @@ Acad::ErrorStatus AecDbEwPipeBase::RegionAcisoutDwgOutFields(AcDbDwgFiler* pFile
::DeleteFile(sFullPath); ::DeleteFile(sFullPath);
delete[] pszTxt; delete[] pszTxt;
return Acad::eOk; return Acad::eOk;
}
else
{
pFiler->writeString(_T("errorfile"));
char* pszTxt = new char[7];
memset(pszTxt,0,7);
pFiler->writeUInt32(7);
pFiler->writeBytes(pszTxt,7);
//原生写法
es = m_pRegion->dwgOutFields(pFiler);
return es;
}
}
else
{
pFiler->writeString(_T("errorfile"));
char* pszTxt = new char[7];
memset(pszTxt,0,7);
pFiler->writeUInt32(7);
pFiler->writeBytes(pszTxt,7);
//原生写法
es = m_pRegion->dwgOutFields(pFiler);
return es;
}
return Acad::eOutOfMemory;
} }
Acad::ErrorStatus AecDbEwPipeBase::SectionRegionDwgOutFields(AcDbDwgFiler* pFiler,int nVer) const Acad::ErrorStatus AecDbEwPipeBase::SectionRegionDwgOutFields(AcDbDwgFiler* pFiler,int nVer) const
{ {
assertReadEnabled(); assertReadEnabled();
if (m_pRegion != NULL) UNREFERENCED_PARAMETER(nVer);
{
if (nVer < 4)//旧版本,保持原样,有错误漏洞
{
AcDbVoidPtrArray arCurPtrs;
m_pRegion->explode(arCurPtrs);
if (!arCurPtrs.isEmpty()) if (m_pRegion == NULL)
{ return Acad::eOk;
return RegionExplodeDwgOutFields(pFiler,arCurPtrs);
}
else
{
//旧版本错误漏洞
//旧版本不考虑 nVer已经升级
//...
}
}
else
{
AcDbVoidPtrArray arCurPtrs;
m_pRegion->explode(arCurPtrs);
//如果炸碎成功 // 统一写 SAT:nLen = 0 是读取端识别 SAT 通道的标志,旧版本插件同样识别。
if (!arCurPtrs.isEmpty()) // 曲线通道只用于读老图纸,写路径已退役,不再按截面类型分流
{
//轻量化写法
return RegionExplodeDwgOutFields(pFiler,arCurPtrs);
}
else
{
//补救措施,重量化写法
//写入长度0 旧版本<4 情况不考虑 nVer已经升级
Adesk::UInt32 nCurs = 0; Adesk::UInt32 nCurs = 0;
pFiler->writeUInt32(nCurs); pFiler->writeUInt32(nCurs);
return RegionAcisoutDwgOutFields(pFiler); return RegionAcisoutDwgOutFields(pFiler);
}
}
}
return Acad::eOk;
} }
Acad::ErrorStatus AecDbEwPipeBase::DefaultNo() Acad::ErrorStatus AecDbEwPipeBase::DefaultNo()
@@ -149,7 +149,6 @@ protected:
Acad::ErrorStatus BaseCurveDwgOutFields(AcDbCurve* pBaseCurve,AcDbDwgFiler* pFiler) const; Acad::ErrorStatus BaseCurveDwgOutFields(AcDbCurve* pBaseCurve,AcDbDwgFiler* pFiler) const;
Acad::ErrorStatus RegionAcisoutDwgOutFields(AcDbDwgFiler* pFiler) const; Acad::ErrorStatus RegionAcisoutDwgOutFields(AcDbDwgFiler* pFiler) const;
Acad::ErrorStatus RegionExplodeDwgOutFields(AcDbDwgFiler* pFiler,AcDbVoidPtrArray& arCurPtrs) const;
Acad::ErrorStatus SectionRegionDwgOutFields(AcDbDwgFiler* pFiler,int nVer) const; Acad::ErrorStatus SectionRegionDwgOutFields(AcDbDwgFiler* pFiler,int nVer) const;
Acad::ErrorStatus AddDimPoints(AcDbGripDataPtrArray& grips,const AcGeVector3d& curViewDir, Acad::ErrorStatus AddDimPoints(AcDbGripDataPtrArray& grips,const AcGeVector3d& curViewDir,