company-desktop
|
d671000269
|
fix: AecRxBase 里的 3D 缓存块去掉对 CoreLibrary 的依赖
修 rebase 后暴露的编译/链接问题(AecRxBase 不链接 CoreLibrary):
- 去掉 SectionPerf 计数器(SectionPerfCounter 的实现只在 CoreLibrary 里,
AecRxBase 用的是自己那份静态副本,打不进同一份报告,本来也没有意义);
- 去掉 CMFCDbDwgFiler 判断(CMFCDbDwgFiler 也定义在 CoreLibrary),
内存 filer 走同一条存取路径即可。
|
2026-10-30 08:47:58 +08:00 |
|
company-desktop
|
9088c47bee
|
feat: 通用 3D 缓存块存取(AecDbEntityCommon)+ 先挂在管件上
按"缓存挂在母体实体的 3dbuffer 上"的思路,把上一轮在 AecDbX3dPartEntity 里写的存取逻辑
提成通用能力:
- AecDbEntityCommon::Write3DBufferBlock() / Read3DBufferBlock():
只能在最派生类的 dwgOut/dwgInFields 末尾调用;缓存里**全是 brep 才写**,
有一个非 brep(中心线/箭头等)就整条不写(用户定的语义);
读不到 magic / 校验失败 → 保持空缓存,照旧重建;不动版本号;内存 filer 不参与。
- AecDbEwFitting 上先挂了两个 hook(管件是全库 Add3DBuffer 用得最多的类,96 处)。
- 开关 AEC_3D_DWG_CACHE,默认关(=1 才写/读),Release 与正常存盘零影响。
- AEC_HAS_MODELER_FILER 对中望也打开(沿用上一轮的 cmake 改动)。
实测结论(big1.dwg,MOVE 弄脏 + REGENALL + QSAVE):
- 存盘后的 DWG 里 magic A3DB 出现 0 次 —— 一个块都没写出去;
- 同一次存盘里 EwPipe::RegionAcisout 3011 次,说明"弄脏+重序列化"这条路本身是通的。
原因(两堵墙互相顶):改过的实体在 AssertWriteEnabled 里就被清空了 3D 缓存
(而且 REGENALL 只重建视口可见的对象);没改过的实体增量存盘按字节拷贝、根本不调
dwgOutFields。所以"缓存有效"和"实体是脏的"在存盘那一刻基本不同时成立 ——
"塞进实体自己的流"这条路机制上不成立,不是值不值的问题。
分析写进 3d-cache-dwg-verdict.md §9,并给出唯一自洽的方向:缓存与实体序列化解耦
(隐藏块/字典里的 Xrecord 旁挂 + 命令结束/空闲时写入 + 按 handle 失效)。
这一版的两个函数就是那个方向的 modeler 存取基础,留着复用。
|
2026-10-30 08:39:35 +08:00 |
|
company-desktop
|
47d7b96cad
|
perf: 给基础体构造加计时,定位到 DrawPipe/DrawCone/DrawLoft 共占 33%
继续追"剩余效率问题"。上一轮已确认 Parasolid 的 93.4% 发生在我们的视口绘制里,
本轮机位下一层:给 GiDrawUtility 的基础体构造函数加计时。
新增 inc/PerfCounterLite.h:header-only 的轻量计数器。
AecRxBase.arx 不链接 CoreLibrary(静态库只被 CoreCommand 链接),拿不到 SectionPerf
的符号,所以单独做一份;只在 Debug + AEC_PERF_COUNTER=1 时生效,Release 零开销。
统计写 %TEMP%\aec_prim_perf.txt(独立文件,避免提前写出 aec_section_perf.txt
让自动化脚本误判"开图完成")。
接入 GiDrawUtility:DrawPipe 三个重载、DrawLoft 两个重载、DrawCone、DrawCylinder。
实测(big1.dwg,93 s 开图 / 81 s CPU):
DrawPipe(region) 7201 次 13.2 s 平均 1837us 最长 130ms
DrawLoft(reg) 883 次 5.27 s 平均 5969us
DrawLoft(curve) 883 次 5.90 s 平均 6679us
DrawCone 811 次 4.64 s 平均 5717us
DrawPipe(pts)/Cylinder 2411 次 4.07 s 平均 1688us
去重后约 27 s,占 81 s CPU 的 33%。
结论(详见 perf-primitive-cost.md):
- 7201 次管道构建 vs 约 2260 个管类实体 = 3.2 次/实体,护栏/爬梯/设备细节也在造管道
- 单次成本差一个量级:圆柱 1.7ms 最便宜(已是优化过的快路径),圆锥 5.7ms、放样 6.0~6.7ms 最贵
- 长尾明显:DrawPipe 最长 130ms(平均的 70 倍),存在个别大件
- 都在"首次构建"路径上,没有重复重建,所以只能少建 / 建得更便宜 / 跨实体复用同参数几何
验证:R230 Debug 编译通过,tools/run_acad_perf.ps1 自动开图取数;
截面缓存与回写仍为正常/0(未受本次插桩影响)。
|
2026-10-28 23:32:22 +08:00 |
|
company-desktop
|
7038a98441
|
diag: 用 PDB 解析栈帧,定位到 AecDbEwPipeBase::copyFrom 里的多余序列化
上一版只给了"模块+RVA"的栈,我据此先后推断成
AecDbCurveBase::subGetTransformedCopy 和 AecDbEntityCommon::base_DeepClone,两者都是错的
(用户在那里下断点不命中;新加的 PerfTraceMark 打点也没有触发)。本次用符号解析定死。
本次改动:
- 新增 inc/PerfTraceMark.h:inline 的"某函数被调用过"打点,Debug 且 AEC_WRITEBACK_TRACE=1
才生效。AecRxBase.arx 不链接 CoreLibrary(静态库只被 CoreCommand 链接),拿不到 SectionPerf,
所以做成 header-only。
- 在 5 个候选入口打点:AecDbCurveBase::subGetTransformedCopy / subDeepClone、
AecDbEntityBase::subDeepClone、AecDbEntityCommon::base_DeepClone、CKTCadUtility::CloneObject。
跑一次开图,5 个都没触发 —— 这些候选被排除。
- 新增 tools/resolve_rva.ps1:用 dbghelp 的 SymLoadModuleEx / SymFromAddr 配本地 PDB,
把"模块+RVA"解析成函数名。Windows 没有自带 symbolizer,这个脚本很轻,可反复用。
解析结果(CoreCommand.arx):
0x58f051 AecDbEwPipeBase::copyFrom+0x41
0x7e1300 AecDbZLineStair::DrawGuarBar3d+0x2c0
0x7e09d0 AecDbZLineStair::DrawSteep3d+0xbe0
0x7ddcef AecDbZLineStair::Draw3d+0x34f
真实成因:Z 型楼梯画护栏(DrawGuarBar3d)时 copyFrom 一份管道实体,
而 AecDbEwPipeBase::copyFrom 用通用的 CopyObject(inc/AecDbEntityCommon.h:331)
做"整实体 dwgOutFields/dwgInFields 往返"来拷字段,于是截面被写成临时 SAT 文件再读回来。
而且这次序列化是多余的:copyFrom 随后把所有字段又用内存级方式拷了一遍
(曲线 clone/copyFrom、截面 clone/copyFrom、XData CopyFrom、m_arUserInfs append、
标志位/图层/线型/Breaks 逐项赋值),WriteUserInterface 写的也只是 m_arUserInfs。
所以最小修改是把那句 CopyObject 去掉,并补上源为 NULL 时清空目标的分支
(目前这个"清空"是 CopyObject 顺带完成的)。
本次只做定位与记录(分析写进 pipe-section-region-performance-plan.md 并纠正了上一版的误判),
不改 copyFrom 的行为——它影响所有管系实体的复制粘贴/块内拷贝,需要单独验证。
|
2026-10-28 21:28:00 +08:00 |
|
gjm
|
86bb3b778a
|
优化 transfromRegion:旋转与平移合成一次 region 变换(E3)
原来对 AcDbRegion 连做两次 transformBy(先转到平面、再平移),
region 是 ACIS body,每次变换都要重建拓扑,而该函数在
DrawPipe(pCurve, pRegion, ptCenInRgn) 里每个管件都会调用。
改为先算出 ptOnRegion 变换后的落点,把平移量用 preMultBy 合成进
同一个矩阵,region 只做一次 ACIS 变换;顺带删掉 plan.get(pt0,pt1,pt2)
这三个未使用的局部变量。
|
2026-10-25 19:16:43 +08:00 |
|
gjm
|
74730f2c91
|
修复 GiDrawUtility 参数校验与规范问题 B7、B9、S1
- B7: DrawPipe(pCurve, dR) 检查 getStartPoint 返回值,避免未定义点传给 getFirstDeriv。
- B9: 补充参数校验:
DrawDish 大直径为 0 时 2*dH/dD 除零;
DrawCirTorus / DrawRectTorus 小半径不小于大半径时截面半径为负(RectTorus 另校验高度);
DrawPipe(ptFrom, ptTo, ...) 零长度路径无法扫掠;
DrawPipe(pCurve, dR) 半径非正。
- S1: spliteCurve、deleteContainerOfArx 由文件级 static 移入已有的匿名 namespace。
|
2026-10-25 19:07:16 +08:00 |
|
gjm
|
14d3ff43c9
|
修复 GiDrawUtility 逻辑缺陷 L7、B2-B5
- L7: 新增 TakeFirstRegion,createFromCurves 返回多个 region 时只取第一个并释放其余,
createRegion(AcDbEntity*)、DrawDish、DrawPipe(curve,dR) 三处统一走此路径;
DrawDish 同时在 DrawRevolve 失败时释放 region。
- B2: RotateAndMove 的零向量防护原为 "*= 1" 空操作,改为显式判零并退化为 Z 轴。
- B3: DrawTydf 的 tfdy 分支截面各自平移后未更新引导线,改为重设端点到变换后的截面中心。
- B4: DrawMesh 增加入参校验(pVertexList 非空、rows>=2、columns>=3),避免越界读与空截面。
- B5: DrawRevolve 建 region 失败时不再往模型空间塞红色曲线,改为直接释放克隆对象。
|
2026-10-25 18:46:19 +08:00 |
|
gjm
|
938edc0204
|
修复 RotateAndMove 平移项缺失旋转分量导致落点错位
平移量应为 ptDist - R*ptOrig,原实现写成 ptDist - ptOrig,
仅在 ptOrig 位于旋转轴上(含原点)时才成立。
DrawTydf 台体分支传入的 ptBottom 非原点,vtMove 倾斜时
实体整体偏移 |R*ptOrig - ptOrig|,本次一并修正。
|
2026-10-25 18:35:41 +08:00 |
|
gjm
|
4de7c883a6
|
fix: 修复 GiDrawUtility 失败路径内存泄漏(L3-L6)
- L3: DrawLoft(曲线版) createRegion 失败时清理三个 clone 及已成功的 region
- L4: DrawBox/DrawSphere 创建失败时释放 pSolid
- L5: DrawMesh loft 失败时释放 pSection 数组与 vecPLs 中各 polyline
- L6: DrawPipe(曲线,半径) ARX 扫掠分支补 DELETE_PTR(pReg),与 ZWCAD/extrude 分支对齐
|
2026-10-25 18:05:51 +08:00 |
|
gjm
|
7c9d849348
|
fix: 修复 GiDrawUtility::DrawPipe 每次画管泄漏 region
- 删除重复调用且丢弃结果的 createRegion(L1:每次调用必漏一个 AcDbRegion)
- 内圆 region 创建失败时释放 pBig(L2a)
- booleanOper 成功后释放第二个操作数 pSml(L2b,与 AecDbEwPipeBase/AecDbEwFitting 惯例一致)
|
2026-10-25 17:59:42 +08:00 |
|
gjm
|
c84bc78869
|
重构底层
重构AecDbEntityBase,AecDbCurveBase
|
2026-10-19 09:19:05 +08:00 |
|
company-desktop
|
199abb989c
|
重构: AecDbObjXDataMap 解耦 UI,并统一 SetAt/数组实现
- AecXData 的 ctor/Free/CopyFrom 由头部 inline 移入 .cpp,结构体加
AECDLLIMPEXP 导出,修复其它模块构造 AecXData 时的 LNK2019。
- 抽出私有 SetXData(pszKey, xdata) 助手,替换各 SetAt 中重复的
find/Free+覆盖/insert 逻辑,并接管 xdata 所有权。
- 数组二进制块统一为 [kArrayMagic][元素类型][元素个数][数据...],元素类型
复用 AecXData::EType;新增元素类型无需再加魔数或类型标签。
- 矩阵/数组魔数集中到 .cpp 顶部常量,便于维护。
- List(CListCtrl*, int) 改为 List(std::vector<CString>&):去掉 MFC 控件与
nImage 依赖,每个元素输出 key/value 两项;CCKSXDlg::ListXDataMap 相应改为
构造 vector 后填充两列列表。
|
2026-10-13 15:28:19 +08:00 |
|
company-desktop
|
0467086e65
|
重构: AecXData 类型标签改用枚举 AecXData::EType
- 在 AecXData 内新增 enum EType,取值直接采用 wtypes.h 的 VARENUM(VT_*),
与原实现逐位一致(nVt 会序列化进 DWG/DXF/XData,数值必须保持不变)。
- 各模块共 303 处 nVt 判断由裸 VT_* 改为 AecXData::kTypeXxx,涉及 18 个文件;
仅调试打印用的字符串字面量保持原样。
- AecDbObjXDataMap.h 增加 #include <wtypes.h>(EType 引用 VT_*)。
|
2026-10-13 09:55:42 +08:00 |
|
gjm
|
164968b62e
|
chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
|
2026-10-04 00:04:20 +08:00 |
|
gjm
|
8ac3fe9197
|
移除旧的 Visual Studio 工程文件,统一使用 CMake 构建
删除 527 个 *.vcxproj、1 个 *.vcxproj.filters、2 个旧版 *.vcproj
以及 8 个 shs_image*.sln 解决方案文件(保留 StartApp C# 工程)。
|
2026-09-28 15:53:36 +08:00 |
|
gjm
|
345044cb46
|
初始化提交
|
2026-09-28 15:28:50 +08:00 |
|