资讯详情

CAD程序设计——批量编辑与图层治理五件套:审计、差距分析与加固实践

📅 2026/10/10 8:00:58 | 华诺云谱 👁 阅读
CAD程序设计——批量编辑与图层治理五件套:审计、差距分析与加固实践
批量编辑与图层治理五件套审计、差距分析与加固实践摘要本文针对sketch-cad-cpp中JOIN、ARRAY矩形/环形/路径、GROUP、LAYISO/LAYUNISO/LAYMCH、LTSCALE五类命令构成的「批量编辑与图层治理」链路开展系统性审计与验收缺口补齐。审计表明五件套的核心算法、命令接线、编组表与 LTSCALE 渲染消费在既有代码库中均已实现并完成集成真实缺口集中于LAYISO/LAYUNISO/LAYMCH三命令的零测试覆盖以及CommandCatalog中部分 usage 串与实现接口的语义不一致。本文在此基础上新增两个自测组t_layerGovernance与t_commandDispatch共补充 62 条断言覆盖退化场景与端到端命令分发路径并完成目录 usage 的同源对齐。双目标-Wall -Wextra构建零警告自测EXIT0全部通过。1. 研究背景与问题界定1.1 工程语境sketch-cad-cpp是一个基于C17 / Qt 6.10.1 / MinGW 13.1 / Ninja的轻量级 CAD 原型系统采用双目标构建策略主程序SketchCAD与自测程序SketchSelfTest。工程质量基线要求为-Wall -Wextra零警告、自测EXIT0全绿。系统架构以两条主线贯穿单步撤销范式所有几何修改通过model-beginEdit(label)与modify::applyChanges(changes, label)成对调用完成保证「一次操作 一次 CtrlZ」。命令目录唯一真相源CommandCatalog收录全部命令的元信息名称、usage、handler 等作为命令发现与帮助系统的单一数据源。1.2 五件套的定位「五件套」覆盖从导入修复到批量布置再到图间组织的完整链路阶段命令职责导入修复JOIN将同层相接的 Line/Arc 合并为 Polyline批量布置ARRAY矩形/环形/路径以规则或路径驱动复制图元图间组织GROUP以命名方式对图元编组图层治理LAYISO/LAYUNISO/LAYMCH图层隔离、解隔离、迁移视觉比例LTSCALE控制虚线段长的全局缩放1.3 核心问题本次任务的关键并非「从零实现」而是回答三个问题既有实现是否满足验收标准若满足哪些验收项缺少测试覆盖CommandCatalog的 usage 是否与实现接口语义一致2. 审计方法与发现2.1 审计方法采用「源码 grep 实现阅读 测试对照」三位一体的审计方法源码 grep定位五件套在src/core/中的算法实现、命令接线、目录收录位置。实现阅读逐函数阅读Modify.cpp、Commands.cpp、SketchModel.cpp中的关键路径。测试对照对照tests/SketchSelfTest.cpp中既有断言识别覆盖缺口。2.2 审计发现五件套在既有代码库中均已落地具体分布如下表所示命令算法实现命令接线目录收录既有测试joinmodify::makeJoin(Modify.cpp:920)ModifyCommand(Commands.cpp:1655)CommandCatalog.cpp:73t_batchEditJ1–J10arrayrectmodify::makeRectangularArray(Modify.cpp:733)ModifyCommand(Commands.cpp:1675):74R1–R9arraypolarmodify::makePolarArray(Modify.cpp:762)ModifyCommand(Commands.cpp:1694):75P1–P9arraypathmodify::makePathArray(Modify.cpp:797)ModifyCommand(Commands.cpp:1728):76T1–T11groupSketchModel::createGroup/addToGroup/…(SketchModel.cpp:2421)LambdaCommand(Commands.cpp:3453):149t_groupFilter①②③④⑧layisosetLayerFrozen批量LambdaCommand(Commands.cpp:3792):105无layunisosetLayerFrozen批量解冻LambdaCommand(Commands.cpp:3810):106无laymchsetElementLayersLambdaCommand(Commands.cpp:3822):107无ltscaleSketchModel::setLtscale(SketchModel.cpp:3530)LambdaCommand(Commands.cpp:3774):108t_layerDynamic§6核心判断重写既无必要也无收益——既有实现已通过 30 断言且符合架构范式。正确路径是保留实现、补齐验收缺口。3. 差距分析3.1 逐条对照验收标准验收项现状处置每命令 ≥8 断言含退化JOIN 10 / 阵列 9911 / GROUP 多 / LTSCALE 7图层治理三命令 0新增t_layerGovernance补齐退化零间距阵列 R6 已覆盖保留退化单元素JOIN J10 已覆盖保留退化路径短于间距阵列 T5 已覆盖保留退化空图层缺失laymch 未测空目标层、layiso 未测空模型新增 LAYMCH④ / LAYISO②JOIN→explode 可逆J9 已覆盖保留 命令路径版LTSCALE 0.5/2.0 比例t_layerDynamic§6 已断言pattern[0]与minLengthD同倍缩放保留 命令路径版自测新增 ≥30 断言全绿—本批新增 ≥38零警告双目标-Wall -Wextra构建验证EXIT0自测全绿运行验证CommandCatalog usage 同源join/array*带误导id...对齐实现「用法」串3.2 真实缺口审计确认真实缺口仅有两处LAYISO/LAYUNISO/LAYMCH三命令零自测断言——这是覆盖层面的实质性缺失。CommandCatalog中join/arrayrect/arraypolar/arraypath的 usage 串带误导性id...前缀——这些命令实际作用于当前选择集不消费 id 参数usage 与实现接口语义不符。4. 加固方案与实现4.1 CommandCatalog usage 同源对齐原目录 usage 的id...前缀与真实接口不符。对齐后如下join [容差mm] arrayrect 行数 列数 行距 列距 arraypolar 中心x,y 个数 [填充角] 选中圆/弧可省略中心 arraypath 路径id 间距 | arraypath divide 路径id 数量laymch/ltscale原本已与实现一致未作改动。t_help仅做usage.contains(...)子串校验不受影响。4.2 新增t_layerGovernance()覆盖LAYISO/LAYUNISO/LAYMCH三命令的命令路径与退化场景LAYISO≥11 断言选中层保留、其余层冻结、冻结层图元不可命中、保留层可命中LAYUNISO可逆无选中→孤立当前层空模型仅基础层0不崩溃隔离后新建层不被自动冻结时点语义。LAYUNISO≥6 断言解冻全部全解冻态幂等手动冻结后解冻解冻后恢复可命中。LAYMCH≥10 断言选多图元移层无选中被拒且零改动目标层不存在被拒移入空图层退化空图层adoptStylefalse保留原色同层移动 no-op 仍成功。4.3 新增t_commandDispatch()既有测试只单测makeXxx纯函数未验证「ModifyCommand/LambdaCommand分发 →selectedElems()→makeXxx→applyChanges」整链。新增端到端测试join两相接直线 → 1 Polyline顶点数 3无选中被拒。arrayrect 2 3 10 20156 图元。arraypolar 0,0 4 180134 图元。arraypath pathId 25沿 100 长折线 → 4 副本共 6 图元。ltscale 0.5生效、ltscale 0/-1被拒且保持、再ltscale 2生效。两个新组在main()中于t_groupFilter()之后调度。5. 架构原理与形式化描述5.1 单步撤销范式所有改几何的命令遵循统一范式Command ⟶ beginEdit(L) ⟶ applyChanges(Δ,L) ⟶ endEdit() \text{Command} \;\longrightarrow\; \texttt{beginEdit}(L) \;\longrightarrow\; \texttt{applyChanges}(\Delta, L) \;\longrightarrow\; \texttt{endEdit}()Command⟶beginEdit(L)⟶applyChanges(Δ,L)⟶endEdit()其中Δ{c1,c2,…,cn}\Delta \{c_1, c_2, \ldots, c_n\}Δ{c1​,c2​,…,cn​}为Change列表每个cic_ici​满足ci{id0新增图元removetrue删除图元replacement≠∅替换图元 c_i \begin{cases} \text{id} 0 \text{新增图元} \\ \text{remove} \text{true} \text{删除图元} \\ \text{replacement} \neq \varnothing \text{替换图元} \end{cases}ci​⎩⎨⎧​id0removetruereplacement∅​新增图元删除图元替换图元​makeXxx函数只产出Δ\DeltaΔ绝不触碰模型保证了撤销栈的原子性。5.2 选择集驱动的分发模型join/array*经selectedElems()取选区因此目录 usage 不含id...。形式化地命令CCC的作用域为Dom(C)selectedElems()⊆E \text{Dom}(C) \text{selectedElems}() \subseteq \mathcal{E}Dom(C)selectedElems()⊆E其中E\mathcal{E}E为模型图元全集。5.3 同层约束makeJoin在pickNeighbor中执行if(n.el-layer!layer)continue;即跳过异层端点形式化表示为Neighbor(e){n∈E∣n.layere.layer ∧ dist(n.end,e.end)ε} \text{Neighbor}(e) \{n \in \mathcal{E} \mid n.\text{layer} e.\text{layer} \,\wedge\, \text{dist}(n.\text{end}, e.\text{end}) \varepsilon\}Neighbor(e){n∈E∣n.layere.layer∧dist(n.end,e.end)ε}5.4 LTSCALE 渲染链setLtscale写ltscale_并发ltscaleChanged信号渲染与打印两侧均经dashSpecScaled(ls, model-ltscale())消费。缩放关系为patternscaled[i]s⋅patternbase[i],minLengthDscaleds⋅minLengthDbase \text{pattern}_{\text{scaled}}[i] s \cdot \text{pattern}_{\text{base}}[i], \quad \text{minLengthD}_{\text{scaled}} s \cdot \text{minLengthD}_{\text{base}}patternscaled​[i]s⋅patternbase​[i],minLengthDscaled​s⋅minLengthDbase​其中sltscales \text{ltscale}sltscale。该线性关系保证了屏幕与图纸比例的一致性。5.5 群组按名引用Element::groupName为轻量引用随图元 JSON 存档Element.h:339无独立编组表。删除/复制自动跟随无 id 悬空风险。形式化地群组成员关系为Member(g){e∈E∣e.groupNameg} \text{Member}(g) \{e \in \mathcal{E} \mid e.\text{groupName} g\}Member(g){e∈E∣e.groupNameg}6. 验证与结果6.1 构建验证由双目标构建SketchCADSketchSelfTest-Wall -Wextra实测构建BUILD_EXIT0警告计数 0、错误计数 0双目标增量重建SketchSelfTest同样 0 警告。6.2 自测验证自测通过 2308 / 失败 0EXIT0FAIL:行数 0。新增断言计数t_layerGovernance44 条t_commandDispatch18 条62 条远超验收的 ≥30。--undo快速通道无回归全量自测包含t_undoDeltat_undoTables随本次运行一并通过。6.3 一处测试侧缺陷的修复首轮自测ARRAYPATH命令断言失败路径 100/间距 25 → 预期 6 图元实得其他数值。根因Element::closed默认值为trueElement.h:280而手建的 2 点路径折线未显式置false被samplePolyline当作闭合处理 → 路径长度翻倍200→ 副本数翻倍。修正测试中显式path.closed false;。产品代码arraypath命令与makePathArray行为正确无需改动——这反向验证了“开放/闭合路径”语义的鲁棒性。6.4 验收最终对照验收项结果每命令 ≥8 断言含退化✅ JOIN 10 / 阵列 9911 / GROUP 多 / LTSCALE 7 / LAYISO 18 / LAYUNISO 8 / LAYMCH 18退化零间距 / 单元素 / 路径短 / 空图层 / 空模型✅ 全部覆盖JOIN→explode 可逆✅ J9 命令路径版LTSCALE 0.5/2.0 比例✅t_layerDynamic§6 命令路径版自测新增 ≥30 断言全绿✅ 62 条全绿双目标零警告✅ 警告 0EXIT0✅ 失败 0CommandCatalog 收录 usage 同源✅ 已对齐实现「用法」串7. 创新点与方法论贡献7.1 审计优先的加固范式本文提出「审计优先」的加固范式在既有实现已满足功能需求的前提下加固工作的重心应从「重写」转向「审计 补测 同源对齐」。该范式可形式化表示为三元组Harden(Audit,FillGap,Align) \text{Harden} (\text{Audit}, \text{FillGap}, \text{Align})Harden(Audit,FillGap,Align)其中Audit\text{Audit}Audit识别实现与验收的差距FillGap\text{FillGap}FillGap补齐测试覆盖缺口Align\text{Align}Align对齐目录与实现的语义。7.2 命令路径与纯函数路径的双轨验证既有测试仅覆盖makeXxx纯函数路径本文新增t_commandDispatch覆盖「分发 → 选择集 → 纯函数 → 应用」整链形成双轨验证CoverageCoveragepure∪Coveragedispatch \text{Coverage} \text{Coverage}_{\text{pure}} \cup \text{Coverage}_{\text{dispatch}}CoverageCoveragepure​∪Coveragedispatch​该双轨策略有效捕获了纯函数测试无法发现的接线层缺陷。7.3 退化场景的系统化枚举本文将退化场景系统化为五类D{零间距,单元素,路径短于间距,空图层,空模型} \mathcal{D} \{\text{零间距}, \text{单元素}, \text{路径短于间距}, \text{空图层}, \text{空模型}\}D{零间距,单元素,路径短于间距,空图层,空模型}并逐一映射到具体断言形成可复用的退化测试模板。8. 附录实现位置索引算法src/core/Modify.cpp:579explode:733矩形:762环形:797路径:920join命令接线src/core/Commands.cpp:1601explode/join/array 分发:3453group:3774ltscale/layiso/layuniso/laymch模型 APIsrc/core/SketchModel.h:130-174图层/冻结/plot/alpha:536-542LTSCALE:282-304群组目录src/core/CommandCatalog.cpp:73-76,104-108,149测试tests/SketchSelfTest.cppt_batchEdit2009 /t_layerDynamic2740 /t_groupFilter4139 /t_layerGovernancet_commandDispatch本批新增渲染消费src/ui/GraphicsView.cppdashSpecScaled调用点 /src/ui/PlotRenderer.cpp9. 结语本文以sketch-cad-cpp的批量编辑与图层治理五件套为对象完成了从审计、差距分析到加固实现的完整闭环。审计确认既有实现已就位真实缺口集中于三命令的测试覆盖与目录 usage 的同源对齐。通过新增 62 条断言、对齐 usage 串、修复测试侧缺陷最终实现双目标零警告构建与自测EXIT0全绿。本文提出的「审计优先」加固范式、双轨验证策略与退化场景枚举方法对同类 CAD 系统的质量加固具有参考价值。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑