From fbb2ca88905bac85258a7999704428c244502b10 Mon Sep 17 00:00:00 2001 From: company-desktop-computer Date: Thu, 22 Oct 2026 10:38:35 +0800 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20=E9=98=B6=E6=AE=B5=E4=B8=89?= =?UTF-8?q?=E6=9A=82=E7=BC=93=EF=BC=8C=E8=A1=A5=E5=85=BC=E5=AE=B9=E5=8F=96?= =?UTF-8?q?=E8=88=8D=E4=B8=8E=E5=B7=B2=E6=A0=B8=E5=AF=B9=E7=9A=84=E6=8A=80?= =?UTF-8?q?=E6=9C=AF=E5=89=8D=E6=8F=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增第 11 节:阶段三暂缓的决定、三个兼容选项的后果、重启前必须先定的事 - 修正过时内容:kCurrentVersionNumber 实际是 4;不需要新增 CoreTools::RegionToBuffer,现有 RegionToString(char*&) 已输出 ASCII 字节 - 写入点、读取点表格按当前 main 行号更新,标注以函数名定位 - 4.3 开头注明阶段一、二已合并,阶段三暂缓 --- AcDbX3dSolid-refactor-plan.md | 116 ++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 34 deletions(-) diff --git a/AcDbX3dSolid-refactor-plan.md b/AcDbX3dSolid-refactor-plan.md index 892437f..5bcaa6c 100644 --- a/AcDbX3dSolid-refactor-plan.md +++ b/AcDbX3dSolid-refactor-plan.md @@ -65,7 +65,7 @@ AcDbRegion* ──RegionToString()──► %TEMP%\Region1.sat ──读文件 `m_pSatBuffer` 的读写通道**已经打通并持久化**: ```cpp -// dwgOutFields :4808-4814 +// dwgOutFields :4822-4829 if (AcDbX3dSolid::kCurrentVersionNumber > 1) { pFiler->writeUInt32(m_nSatLen); if (m_pSatBuffer != NULL) @@ -107,20 +107,28 @@ struct RegionBlobHeader { ### 3.3 编解码 ```cpp -// AcDbX3dSolid.cpp 内部 static -static bool PackRegions(const AcArray& regs, void*& pBuf, Adesk::UInt32& nLen); -static bool UnpackRegions(const void* pBuf, Adesk::UInt32 nLen, AcArray& regs); - -// 单 region 的 SAT 字节(CoreTools 新增,与 RegionToString 共用临时文件逻辑) -bool CoreTools::RegionToBuffer(const AcDbRegion* pReg, void*& pBuf, Adesk::UInt32& nLen); +// AcDbX3dSolid.cpp 匿名 namespace +bool PackRegions(const AcArray& regs, void*& pBuf, Adesk::UInt32& nLen); +bool UnpackRegions(const void* pBuf, Adesk::UInt32 nLen, AcArray& regs); ``` -`UnpackRegions` 内部用**已存在**的 `CoreTools::StringToRegion(Adesk::UInt64 nLen, char* pszReg)`(`CoreTools.cpp:3525`),读端无需新代码。 +单 region 的 SAT 字节**不需要新函数**,直接复用已有的两个重载: + +```cpp +// 输出 SAT 的 ASCII 字节,返回长度,pszTxt 由调用方 delete[] +Adesk::UInt64 CoreTools::RegionToString(const AcDbRegion* pReg, char*& pszTxt); // CoreTools.cpp:3114 +// 从字节重建 region +AcDbRegion* CoreTools::StringToRegion(Adesk::UInt64 nLen, char* pszReg); // CoreTools.cpp:3581 +``` + +`RegionToString(char*&)` 内部已经用 `MakeTempSatPath()` + `DeleteFile`,`StringToRegion` 内部已经过 `fixACISFormat`,阶段一、二落地后这两条链路都是现成的。`PackRegions` 负责把拿到的字节拷进容器并 `delete[]`。 --- ## 4. 改动清单 +> 阶段一、二已合并;阶段三暂缓,取舍与前提见第 11 节。以下保留完整方案,供重启时参考。 + ### 阶段一:临时文件唯一化(纯 bug 修复) **位置**:`CoreCommand/CoreTools.cpp` @@ -178,40 +186,42 @@ void EnsureCreated() { if (m_bNeedCreate) { m_bNeedCreate = false; ReCreate(); } #### 4.3.1 写入点(`RegionToString` → `PackRegions`) -| 行 | 类型 | 现状 | +行号为当前 main(阶段一、二落地后),实施时以函数名定位。 + +| 行 | 类型 / 函数 | 现状 | | --- | --- | --- | -| `:1364` | `kExtrude2` | `RegionToString(pReg, m_sScr)` | -| `:1429-1432` | `kConePipe` | 外/内两个 → `sScr1`/`sScr2` → 拼 `m_sScr` | -| `:2034` | `kSlicePipe` | `RegionToString(pRegion, m_sScr)` | -| `:2120` | `kIntersect` | → `sScr1` → `m_sScr` | -| `:2174` | `kSliceSolid` | → `sSrc1` → `m_sScr` | -| `:2204` | `kRevolve` | → `m_sScr` | -| `:2235` | `kRevolve2` | → `m_sScr` | -| `:5020` | `kLoft` | `strAll`(`@region@` 拼接)→ `m_sScr` | -| `:5073`、`:5087` | `kSweep` | → `m_sScr` | -| `:4868`、`:4881` | `SetSolidData` | `m_sScr = srcRegion` | -| `:5121`、`:5141`、`:5162`、`:5192` | `SetExturd2Data` / `SetRevolve2Data` / `SetSweepData` / `SetLoftData`(`:5192` 所属函数实施时核对) | `m_sScr = sReg` | +| `:1371` | `kExtrude2` | `RegionToString(pReg, m_sScr)` | +| `:1436`、`:1439` | `kConePipe` | 外/内 → `sScr1`/`sScr2` → 拼 `m_sScr` | +| `:2041` | `kSlicePipe` | → `m_sScr` | +| `:2127` | `kIntersect` | → `sScr1` → `m_sScr` | +| `:2181` | `kSliceSolid` | → `sSrc1` → `m_sScr` | +| `:2211` | `kRevolve` | → `m_sScr` | +| `:2242` | `kRevolve2` | → `m_sScr` | +| `:5029` | `kLoft` | `strAll`(`@region@` 拼接)→ `m_sScr` | +| `:5087`、`:5101` | `kSweep` | → `m_sScr` | +| `:4882`、`:4895` | `SetSolidData` | `m_sScr = srcRegion` | +| `:5135`、`:5155`、`:5176`、`:5206` | `SetExturd2Data` / `SetRevolve2Data` / `SetSweepData` / `SetLoftData` | `m_sScr = sReg` | +| `:5516`、`:5528`、`:5542`、`:5562`、`:5589` | `TransformBy` | 变换后重新导出 | #### 4.3.2 读取点(`StringToRegion(m_sScr)` → `UnpackRegions`) -| 行 | 类型 | +| 行 | 类型 / 函数 | | --- | --- | -| `:4364` | `kSlicePipe` | -| `:4376` | `kExtrude2` | -| `:4400` | `kIntersect` | -| `:4438` | `kSliceSolid` | -| `:4466` | `kRevolve` | -| `:4486-4487` | `kConePipe` | -| `:4561` | `kRevolve2` | -| `:4585` | `kLoft` | -| `:4599` | `kSweep` | -| `:5307`、`:5331`、`:5356`、`:5439` | `ToJson` | -| `:5500`、`:5512`、`:5526`、`:5542`、`:5571` | `TransformBy` | -| `:5111`、`:5129`、`:5154` | `GetExturd2Data` / `GetRevolve2Data` / `GetSweepData` | +| `:4366` | `kSlicePipe` | +| `:4378` | `kExtrude2` | +| `:4402` | `kIntersect` | +| `:4440` | `kSliceSolid` | +| `:4468` | `kRevolve` | +| `:4488`、`:4489` | `kConePipe` | +| `:4563` | `kRevolve2` | +| `:4587` | `kLoft`(循环) | +| `:4601` | `kSweep` | +| `:5321`、`:5345`、`:5370`、`:5453` | `ToJson` | +| `:5512`、`:5524`、`:5538`、`:5558`、`:5584` | `TransformBy` | #### 4.3.3 序列化 -**不改**。`m_pSatBuffer` 的 `writeUInt32` + `writeBytes` 已经在 `:4808-4814`,`dwgInFields` 有对称读。 +**不改**。`m_pSatBuffer` 的 `writeUInt32` + `writeBytes` 已经在 `:4822-4829`,`dwgInFields` 有对称读。 只改一件事:region 类型写入时**不再写 `m_sScr`**(保持空字符串),管廊脚本类型不受影响。 @@ -354,3 +364,41 @@ void SetSweepData(const CString& sReg, const AcDbCurve* pCurve); | 1 | `kLoftReducer`(22) 是否纳入统一容器 | **纳入**(4.3.5),老数据回退 `0x00c1` 切分 | | 2 | `kSHEarthWorm`(23) 是否仍在使用 | **已废弃**,但 `m_sScr` 字段本次保留不删,仅停止写入(4.3.6) | | 3 | 公开 `CString` 接口 | **签名不变**,内部转换,外部调用方零改动(第 5 节) | + +--- + +## 11. 阶段三暂缓(2026-10-22) + +**决定:暂不实施。** 阶段一(临时文件唯一化、越界读)、阶段二(懒重建)已合并,主要痛点已经解决;阶段三剩下的收益只有「region 部分 DWG 体积减半」,代价是新图在老版本插件里 region 几何不可见。当前时机未到。 + +### 11.1 核心取舍 + +`m_sScr` 停写后,老版本插件打开新图会走 `StringToRegion("")`,返回 NULL,region 类型建不出几何。数据没有丢——仍在 `m_pSatBuffer` 里,装回新版插件即可恢复。 + +| 选项 | 后果 | 结论 | +| --- | --- | --- | +| 不升版本号,接受老插件缺几何 | 老插件能开图、参数都在,region 几何不显示;换新版可恢复 | 若重启阶段三,选这个 | +| 升到 5,老插件显式 proxy | 不会静默缺几何,但新图在所有老版本上彻底不可编辑,且不可回退 | 不选 | +| 保留双写(`m_sScr` 仍写老格式) | 体积变成 2N + N,比现状更差 | 否决 | + +### 11.2 重启前必须先定的事 + +1. 11.1 的表格选哪一行 +2. `TransformBy`、`ToJson` 是否一起改——这两处在运行时会反复导出/解析 SAT,是阶段三改动量的大头 +3. 老图纸里 region 类型的实际占比——占比低的话体积收益有限,可以永久搁置 + +### 11.3 实施时的技术前提(已核对) + +- `kCurrentVersionNumber` 当前是 **4**。`m_pSatBuffer` 的读写通道在 `dwgOutFields:4822` / `dwgInFields:4754`,版本 > 1 即生效,阶段三不需要动序列化 +- **不需要**新增 `CoreTools::RegionToBuffer`:`RegionToString(const AcDbRegion*, char*&)`(`CoreTools.cpp:3114`)已经输出 SAT 的 ASCII 字节和长度,内部用 `MakeTempSatPath` + `DeleteFile` +- 读端 `StringToRegion(Adesk::UInt64, char*)`(`CoreTools.cpp:3581`)已经过 `fixACISFormat` +- `m_pSatBuffer` 当前有 4 种语义:`kFenceExtrude` 点数组(`:1514`)、`kFrom3JS` SubDMesh(`:1019`/`:1048`)、`kLoftReducer` 宽字符串(`:3132`/`:5405`)、SAT 导入原始字节(`:2872`)。容器头的 magic 是必需的 +- 拷贝构造对 `m_pSatBuffer` 做了深拷贝(`:274-280`),`Clone()` 不会共享指针 + +### 11.4 当前状态 + +| 阶段 | 状态 | PR | +| --- | --- | --- | +| 一:临时文件唯一化 | 已合并 | #22、#26 | +| 二:懒重建 | 已合并 | #25、#27 | +| 三:region 二进制化 | 暂缓 | — | -- 2.54.0 From bed6556adf283143781d46c524a638146b30dbdf Mon Sep 17 00:00:00 2001 From: company-desktop-computer Date: Thu, 22 Oct 2026 10:43:45 +0800 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=E6=98=8E=E7=A1=AE=E9=98=B6?= =?UTF-8?q?=E6=AE=B5=E4=B8=89=E5=8D=95=E5=90=91=E5=85=BC=E5=AE=B9=E2=80=94?= =?UTF-8?q?=E2=80=94=E8=80=81=E7=89=88=E7=9C=8B=E4=B8=8D=E5=88=B0=E6=96=B0?= =?UTF-8?q?=E5=9B=BE=20region=20=E5=87=A0=E4=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 兼容方案定为第一项:不升 kCurrentVersionNumber,新版能完整读旧版图纸, 旧版打开新图时 region 类型的 AcDbX3dSolid 几何不可见。 补充说明 m_pSatBuffer 在旧版也会原样读写,所以旧版另存后回新版仍能恢复; 非 region 类型(点串、SubDMesh、管廊脚本)不受影响。 文档开头的原则、4.3.4 的不升版本理由同步。 --- AcDbX3dSolid-refactor-plan.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/AcDbX3dSolid-refactor-plan.md b/AcDbX3dSolid-refactor-plan.md index 5bcaa6c..5abecac 100644 --- a/AcDbX3dSolid-refactor-plan.md +++ b/AcDbX3dSolid-refactor-plan.md @@ -4,7 +4,7 @@ > > 范围:`SourceCode/Code2026/CoreLibrary/AcDbX3dSolid.cpp`(5596 行)、`inc/AcDbX3dSolid.h`、`CoreCommand/CoreTools.cpp`。 > -> 原则:**老图纸必须能读**;写入统一新格式;不改对象模型(`AcDbX3dSolid` 仍是可平凡复制的数据类)。 +> 原则:**单向兼容——新版必须能读老图纸,老版不保证能显示新图的 region 类型几何**(见 11.1);写入统一新格式;不改对象模型(`AcDbX3dSolid` 仍是可平凡复制的数据类)。 --- @@ -245,7 +245,7 @@ else if (!m_sScr.IsEmpty()) 写入:只写新格式。 -**不升 `kCurrentVersionNumber`**。理由:字段都在,靠"哪个非空"即可判别;升版本会让老版本 CAD 读新图时走 `eMakeMeProxy`。 +**不升 `kCurrentVersionNumber`**。理由:字段都在,靠"哪个非空"即可判别;升版本会让老版本 CAD 读新图时走 `eMakeMeProxy`,新图在所有老版本上彻底不可编辑。代价是老版本看不到 region 类型的几何,这是已定的取舍,见 11.1。 #### 4.3.5 `kLoftReducer` 纳入统一容器 @@ -371,21 +371,22 @@ void SetSweepData(const CString& sReg, const AcDbCurve* pCurve); **决定:暂不实施。** 阶段一(临时文件唯一化、越界读)、阶段二(懒重建)已合并,主要痛点已经解决;阶段三剩下的收益只有「region 部分 DWG 体积减半」,代价是新图在老版本插件里 region 几何不可见。当前时机未到。 -### 11.1 核心取舍 +### 11.1 兼容方向(已定) -`m_sScr` 停写后,老版本插件打开新图会走 `StringToRegion("")`,返回 NULL,region 类型建不出几何。数据没有丢——仍在 `m_pSatBuffer` 里,装回新版插件即可恢复。 +**单向兼容**:新版插件完整读取旧版图纸(`m_sScr` 老路径永久保留);旧版插件打开新图时,region 类型的 `AcDbX3dSolid` 几何不可见。 + +不可见不等于丢数据:`m_pSatBuffer` 老版本也会原样读写(版本 > 1 的通道一直都在),所以旧版打开后另存、再回新版打开,几何仍能恢复。非 region 类型(`m_sszPoint2ds` 点串、SubDMesh、管廊脚本)不受影响。 | 选项 | 后果 | 结论 | | --- | --- | --- | -| 不升版本号,接受老插件缺几何 | 老插件能开图、参数都在,region 几何不显示;换新版可恢复 | 若重启阶段三,选这个 | +| 不升版本号,接受老插件缺几何 | 老插件能开图、参数都在,region 类型几何不显示;换新版可恢复 | **已定,选这个** | | 升到 5,老插件显式 proxy | 不会静默缺几何,但新图在所有老版本上彻底不可编辑,且不可回退 | 不选 | | 保留双写(`m_sScr` 仍写老格式) | 体积变成 2N + N,比现状更差 | 否决 | -### 11.2 重启前必须先定的事 +### 11.2 重启前还要定的事 -1. 11.1 的表格选哪一行 -2. `TransformBy`、`ToJson` 是否一起改——这两处在运行时会反复导出/解析 SAT,是阶段三改动量的大头 -3. 老图纸里 region 类型的实际占比——占比低的话体积收益有限,可以永久搁置 +1. `TransformBy`、`ToJson` 是否一起改——这两处在运行时会反复导出/解析 SAT,是阶段三改动量的大头 +2. 老图纸里 region 类型的实际占比——占比低的话体积收益有限,可以永久搁置 ### 11.3 实施时的技术前提(已核对) -- 2.54.0