Files
2026-07-22 13:48:46 +08:00

30 KiB
Raw Permalink Blame History

SimpleCADAPI 2.0 重构设计文档

文档目的

本文档用于汇总并冻结 SimpleCADAPI 2.0 的重构方向。核心目标不是继续围绕 OCP 做包装,而是把系统重构为一个以 OCP 为底层内核、以参数/表达式/操作图/拓扑历史为事实来源的建模系统。

本文档覆盖:

  • 2.0 的目标、边界和兼容性要求
  • 现状评估与为何必须重构
  • 目标架构与核心数据模型
  • 参数表达式图方案
  • 几何值模型、拓扑追踪与序列化方案;装配约束属于后续重做范围
  • 分阶段迁移计划、测试计划与风险控制

本文档是架构设计稿,不是实现说明书。命名、模块拆分和阶段顺序可以在落地时微调,但本文档中的设计原则和兼容性约束应视为 2.0 的硬边界。

配套执行文档见:docs/core/rearchitecture_2_0_requirements.md

当前实现审计(2026-04-14

已完成

  • 表达式基础层已落地:Var/Const/ExprExpressionGraph、参数 canonicalization 已可用。
  • GraphSession 已升级为双图 session:同时维护 OperationGraphExpressionGraph
  • Sketch 已作为一等对象引入,但没有替代 Vertex/Edge/Wire/Face/Solid 主线。
  • Vertex/Edge/Wire/Face/Solid 已能接受 raw OCC wrapped shapewrapped 已开始成为核心存储。
  • extrude/revolve/fillet/chamfer/shell/cut/union/intersection 等核心操作已经接入了不同程度的表达式或历史记录能力。
  • model.json 已具备 graph + expression 的初步导出能力;旧 assembly / constraint 支持面已暂时移除。

仍未完成

  • model.json 仍不是完整 canonical IR:缺少稳定的 geometry_registrysemantic_delta_logtopology_delta_log 等核心结构。
  • graph JSON roundtrip 还没有稳定保留 SemanticDelta / TopoDelta,会导致 replay 之外的历史信息丢失。
  • 自动生成的 SemanticDelta 仍存在 pending 风格引用,占位语义没有被绑定成稳定的 graph/node 引用。
  • Phase 1 曲线/轮廓入口尚未完全表达式化,仍有 primitive/profile API 只能接受纯数值。
  • OCP-native evaluator 迁移仍未完成,很多实现仍在直接调用 cadquery 构造层。
  • shell 等操作的可靠拓扑历史仍然不完整,当前更多是“记录结果”而不是“稳定双层 delta”。

本轮收敛 TODO

  • TODO-IR-001:为 OperationGraph 的 JSON roundtrip 补齐 SemanticDelta / TopoDelta 序列化。
  • TODO-IR-002:为 model.json 补齐 geometry_registrysemantic_delta_logtopology_delta_log
  • TODO-HIST-001:把自动生成的 SemanticDeltapending 占位绑定到真实 graph_id/node_id
  • TODO-OPS-001:补齐 Phase 1 剩余 primitive/profile API 的表达式入口,至少覆盖 pointlinerectanglepolyline

仍待后续轮次完成的大项

  • TODO-KERNEL-001:继续把 evaluator 从 cadquery 构造路径迁移到 OCP-native builder 路径。
  • TODO-HIST-002:为 shell 等尚未完整追踪的操作补齐稳定 TopoDelta
  • TODO-IR-003:继续扩展 canonical model.json,补齐更完整的 geometry/sketch/stable-ref registryassembly registry 等待新装配契约后再设计。
  • TODO-FRAME-001:补齐文档中要求的显式 frame / placement 基础设施,而不是只保留当前 workplane 上下文模型。

剩余 TODO 审计(本轮整理)

本轮可完成

  • TODO-HIST-003revolve 仍未走 tracked history,需补齐稳定 TopoDelta 与 graph roundtrip 保留。
  • TODO-IR-004model.json 仍缺 sketch/profile registry
  • TODO-IR-005:移除旧 assembly_registry / constraint_registry 与嵌套 assembly payload,避免在新装配契约前冻结半成品 schema。
  • TODO-DOC-001:把“已完成 / 可完成 / 结构性大项”在审计段落中明确区分,避免 TODO 状态失真。

结构性大项

  • TODO-KERNEL-002loft/sweep/helical_sweep 仍主要依赖 CQ 构造层。
  • TODO-KERNEL-003line/arc/spline/helix 等 curve evaluator 仍主要依赖 CQ 构造层。
  • TODO-SEM-001SemanticDelta 仍以 ShapeOutput 为主,尚未升级为更清晰的 feature/body/sketch 语义实体。
  • TODO-FRAME-002:缺少独立的 frame.py / placement graph,当前空间语义仍主要依附 workplane 上下文。

注:helical_sweep 已按组合操作处理,不再作为基础核心 IR 节点记录;图中记录为 make_helix_wire + sweep

新一轮剩余深化项

  • TODO-HIST-004:为 loft/sweep/helical_sweep 补更完整的 tracked TopoDelta,目前已完成 OCP-native evaluator 替换,但历史记录仍未达到 extrude/revolve/shell 同等细度。
  • TODO-FRAME-003:保留建模 session frame snapshot;旧 assembly / instance pose 接入已撤回,等待新装配契约。
  • TODO-SEM-002:继续把语义实体从 Point/Profile/Body 扩展到更明确的 Sketch/Feature 级别;AssemblyConstraint 暂不导出。

注:helical_sweep 作为组合宏,通过 make_helix_wire + sweep 继承同等级 history 记录,而不是单独维护基础特征节点。

本轮最终状态冻结(2026-04-15)

本轮将 2.0 的“继续推进”收束为一个必须由代码、导出 payload 和测试共同满足的最终状态,而不是停留在设计描述:

  • model.json 是 canonical export,并可独立 replay。
  • graph 是唯一真相源,并且必须直接是 canonical low-level graph。
  • leaf_ids 是多输出场景的显式结果集,不允许默认依赖 graph.leaf_nodes() 猜测最终输出。
  • canonical graph 必须收敛到冻结的基础 op set;任何 convenience op 或 macro-only op 若未 lower,不得进入 graph
  • helical_sweep 必须始终作为组合宏对待,而不是基础 canonical 节点。
  • detail feature 的 canonical 事实来源必须是 geo select nodes / explicit selected refs,而不是 selection_query 文本。
  • QL selector 运行时结果会编译成 make_select_* 节点;每个节点用 tag-free geo_selector 固定到被选中对象的几何事实。
  • selection_queryselector_hint 继续保留,但只作为回放与映射的 fallback 信息。
  • replay_model_json() 必须直接依赖 graph,并对 detail feature 按以下顺序解析选择:
    • geo select nodes
    • selection query fallback
    • explicit topo refs
    • stable indices
    • selector hint

为避免该冻结状态重新退化,本轮同时引入:

  • model.json.canonical_contract 机器可读合约
  • canonical low-level op set 的导出期校验
  • 围绕最终状态的专门测试

背景与问题定义

当前 SimpleCADAPI 已经具备以下基础能力:

  • 纯函数风格的几何 API
  • Vertex -> Edge -> Wire -> Face -> Solid 的几何对象主线
  • 操作图记录、序列化与 replay 雏形
  • 针对部分 OCP builder 的拓扑历史追踪
  • 旧装配姿态约束系统已从 public/support 面移除,等待重新设计

但当前系统的事实来源仍然主要是即时构建出的 OCP/BRep 对象,而不是统一的参数化模型 IR。这样会导致几个根本问题:

  1. 模型结果主要是最终几何,而不是参数化语义对象。
  2. 大量核心类型直接持有 cadquery 对象,导致内核层与 OCP 强耦合。
  3. 虽然已经有 graph/history,但还没有覆盖完整的参数、表达式与对象空间描述;装配约束需要单独重做契约。
  4. 拓扑历史目前只覆盖部分操作,且很多 API 仍然是“算完即得 shape”。
  5. 当前不再冻结旧装配系统语义,新装配系统需要从统一参数图/表达式图/重建图重新接入。

因此,2.0 的核心任务不是“继续增强现有 CQ 包装层”,而是把系统的中心从“几何结果”切换到“参数化模型”。

2.0 总目标

SimpleCADAPI 2.0 的目标是构建一个:

  • OCP 为主要几何内核
  • 保留当前纯函数、shape-first 用户体验
  • 具备统一参数表达式图
  • 具备统一操作图与拓扑历史图
  • 具备统一空间描述,并为后续装配约束图预留契约空间
  • 可序列化、可重放、可增量更新
  • 能输出最终 mesh/BRep,也能输出完整参数化中间表示

换句话说,2.0 中:

  • mesh / brep / step / stl 只是导出结果
  • TopoDS_Shape 是求值缓存和内核结果
  • 真正的事实来源是模型 IR:表达式、变量、几何值、特征、拓扑变化;装配和约束需在新契约中重新纳入

兼容性约束

以下要求已经明确,应作为 2.0 的硬约束:

  1. 保留纯函数风格 API。
  2. 保留 Vertex -> Edge -> Wire -> Face -> Solid 作为公开几何对象主线。
  3. 保留现有命名风格,尤其是 *_rvertex*_redge*_rwire*_rface*_rsolid
  4. 尽量让现有脚本在小改动下迁移到 2.0。
  5. 2.0 第一阶段全部按无单位标量处理,不引入单位系统。

这意味着:

  • 2.0 不能把公开 API 改造成 scene graph 风格对象系统。
  • 2.0 不能要求用户把所有常量都显式包成 wrapper。
  • 2.0 不能把表达式系统设计成破坏现有调用习惯的 DSL。

现状评估

当前已有的可复用基础

以下模块和设计思路可以直接复用或吸收:

  • src/simplecadapi/graph.py
    • 已有操作 DAG 记录机制
    • 已有 output lineage 附着机制
  • src/simplecadapi/topology.py
    • 已有 OperationGraphOperationNodeTopoRefTopoDelta
  • src/simplecadapi/serializer.py
    • 已有 graph JSON 导出/导入/replay 思路
  • src/simplecadapi/tracking.py
    • 已有基于 OCP builder 的 Modified / Generated / IsDeleted 历史查询

当前必须重构的核心问题

以下模块当前与 2.0 目标存在结构性冲突:

  • src/simplecadapi/core.py
    • Vertex/Edge/Wire/Face/Solid 直接持有 cq_* 对象
    • 类型层与 OCP 强绑定
  • src/simplecadapi/operations.py
    • 大量公开 API 直接调用 cq.*
    • 操作定义和求值逻辑、记录逻辑、标签逻辑混杂
  • src/simplecadapi/serializer.py
    • replay 仍围绕现有 CQ 风格操作重建
  • 旧装配/约束实现
    • 已从 public/support 面移除;新实现需要先定义与主 graph/表达式系统一致的契约

当前的关键判断

  1. 现有 shape-first API 是资产,不是包袱。
  2. 当前 graph/history 雏形是资产,但 schema 和覆盖范围不够。
  3. tracking.py 说明直接面向 OCP builder 的方向是可行的。
  4. 2.0 的问题不是“要不要表达式”,而是“如何在不破坏纯函数 API 的前提下记录表达式”。

2.0 设计原则

1. 保留 shape-first 与纯函数风格

2.0 对外仍然以几何值为中心:

  • make_line_redge(...) -> Edge
  • make_circle_rface(...) -> Face
  • extrude_rsolid(face, ...) -> Solid
  • fillet_rsolid(solid, ...) -> Solid

不引入公开的 scene node 概念来替代几何值对象。

2. 表达式与历史是横切能力,不替换几何返回类型

表达式图、历史图、拓扑图、装配约束图都应是内部模型层能力。它们增强几何对象,但不改变“函数输入几何,函数返回几何”的用户体验。

3. OCP 是 2.0 的主内核

OCP 不再是核心几何实现层。2.0 目标是:

  • 几何构造、特征、布尔、变换、查询尽量直接通过 OCP
  • OCP 不再是核心 runtime 依赖
  • 如需保留 CQ,只能作为开发辅助或过渡期兼容工具,而不是内核前提

4. 模型 IR 是事实来源,BRep 是求值产物

2.0 中真正需要持久化和导出的核心数据是:

  • variables
  • expressions
  • frames
  • sketches
  • feature chain
  • assembly instances
  • constraints
  • semantic delta
  • topology delta

5. 只把基础操作做成核心语义

2.0 第一阶段只把以下操作作为核心建模语义:

  • line
  • arc
  • bspline
  • sketch
  • extrude
  • revolve
  • fillet
  • chamfer
  • shell
  • cut
  • union
  • intersection
  • assembly constraints

其他复杂宏、特例建模函数、evolve case、不稳定脚本能力不作为 2.0 核心 IR 的第一阶段内容。

2.0 目标架构

总体分层

建议的 2.0 架构分为 6 层:

  1. Expression Layer
  2. Geometry Value Layer
  3. Feature and Operation Layer
  4. OCP Evaluation Layer
  5. History and Topology Layer
  6. Assembly and Serialization Layer

Layer 1: Expression Layer

负责变量、常量、表达式 DAG、参数求值与 dirty propagation。

输出:

  • 标量表达式节点
  • 向量/点参数的逐项表达式引用
  • 装配约束参数表达式

Layer 2: Geometry Value Layer

负责对外暴露的几何值对象:

  • Vertex
  • Edge
  • Wire
  • Face
  • Solid
  • Sketch(新增)

这些对象继续作为公开 API 的主线,不被 scene graph 替代。

Layer 3: Feature and Operation Layer

负责把基础操作定义成稳定的语义节点:

  • primitive/profile ops
  • feature ops
  • boolean ops
  • transform/placement ops

Layer 4: OCP Evaluation Layer

负责:

  • 用 OCP 对语义节点求值
  • 产出 TopoDS_Shape 结果
  • 获取 builder 历史信息

Layer 5: History and Topology Layer

负责:

  • operation graph
  • semantic delta
  • topology delta
  • stable refs
  • replay

Layer 6: Assembly and Serialization Layer

负责:

  • assembly instances
  • anchors
  • constraints
  • solve
  • JSON IR 导入导出
  • 下游导出适配器

几何值模型

公开几何对象不变

2.0 继续保留以下公开类型:

  • Vertex
  • Edge
  • Wire
  • Face
  • Solid

新增但不替代主线的对象:

  • Sketch

内部语义:Placement Ownership

2.0 需要一个内部概念来统一空间描述,但这个概念不应演化为公开类型分裂。

定义如下:

  • 所有公开几何对象都是一等值对象
  • 每个对象都可以回答自己的空间信息
  • 但对象的空间信息来源有两种:
    • 自身直接拥有的 frame/placement
    • 从上游 owner、feature 或 assembly instance 推导出的 placement

这只是内部 runtime/IR 约束,不作为用户层公开分类。

为什么需要这个内部概念

原因只有两个:

  1. 装配约束必须知道姿态是谁在负责。
  2. 子拓扑对象的世界位置必须有稳定来源,而不是每个 face/edge 都假装是独立场景节点。

统一空间描述

2.0 应提供统一空间描述能力,至少支持:

  • 本地 frame
  • 世界 frame
  • 几何中心/法向/包围盒
  • owner/instance 来源

建议通过内部 frame graph 维护,而不是通过隐式全局 workplane 状态维护。

SimpleWorkplane 的公开用法可以继续保留,但其实现应逐步切换为显式 frame 组合,而不是只依赖 ambient context。

参数与表达式系统

目标

参数系统必须满足:

  • 对用户尽量无感
  • 保留现有纯函数 API
  • 可序列化
  • 可 replay
  • 可做依赖分析和局部重建
  • 同时可服务几何参数和装配约束参数

选型结论

2.0 采用以下方案:

  • Variable 显式创建
  • 普通常量自动提升为 Const
  • 只要表达式中出现变量,后续算术运算自动形成 Expr DAG
  • 所有公开 API 在入口统一进行参数 canonicalization

这是 2.0 第一阶段推荐的表达式图方案。

为什么不采用更“魔法”的方案

以下方案不作为 2.0 核心机制:

  1. 源码 AST 捕获
    • inspect.getsource()、notebook、REPL、skill 环境都不稳定
  2. float 子类伪装透明数值
    • numpy、OCP、C 扩展交互容易静默退化
  3. 强制所有参数都手写 wrapper
    • 会破坏当前 API 的简洁性
  4. 直接以 SymPy 为核心
    • 过重,不适合作为第一阶段内核

推荐 API 形态

推荐新增:

r = scad.var("r", 10.0)
h = scad.var("h", 20.0)

base = scad.make_circle_rface(center=(0, 0, 0), radius=r)
body = scad.extrude_rsolid(base, direction=(0, 0, 1), distance=h)
body2 = scad.fillet_rsolid(body, edges=..., radius=r * 0.1)

同时保留原有脚本:

box = scad.make_box_rsolid(10, 20, 30)

这时旧脚本里的参数会被当作常量节点处理。

核心数据模型

建议定义:

  • Var(name: str, default: float)
  • Const(value: float)
  • Expr(op: str, args: tuple[ExprLike, ...])

Phase 1 的 Expr 支持:

  • +
  • -
  • *
  • /
  • **
  • unary -
  • abs
  • min
  • max
  • sin
  • cos
  • tan
  • sqrt

第一阶段全部按无单位标量处理。

参数 canonicalization

所有公开 API 在入口统一完成:

  • float/int -> Const
  • Var -> Var
  • Expr -> Expr
  • tuple/list -> 逐项 lift

canonicalization 结果至少需要包含:

  • 表达式引用
  • 当前数值快照

这样:

  • OCP evaluator 使用数值快照执行建模
  • graph/serializer 使用表达式引用保存依赖关系

表达式图与操作图的关系

建议维护两张图:

  1. ExpressionGraph
  2. OperationGraph

它们的关系:

  • OperationNode.params 不直接重复内嵌完整表达式树
  • 参数通过 expr_idexpr_ref 指向表达式图节点
  • 序列化时,表达式图和操作图共同构成完整模型 IR

好处:

  • 变量可在多个特征与约束中复用
  • 修改单个变量时,可做精确 dirty rebuild
  • graph 更清晰,不会在多个节点中重复复制整棵表达式树

Sketch 模型

为什么必须新增 Sketch

当前系统虽然有 line/arc/spline/wire/face,但缺少一等 Sketch 对象。这会导致:

  • profile 来源不明确
  • 2D 语义缺失
  • 参数化导出和 replay 时难以表达草图层级

因此 2.0 需要引入 Sketch,但 Sketch 是增强对象,不替代 Vertex/Edge/Wire/Face/Solid 主线。

One-Way Rule

同一建模意图应只有一种推荐实现方式:当目标是构建 sketch/profile 时,必须使用 sketch API,例如 make_sketch_rsketch(...)add_line_rsketch(...)constrain_parallel_rsketch(...)make_face_from_sketch_rface(...)make_line_redge(...)make_wire_from_edges_rwire(...) 等 concrete geometry API 只用于 path、纯几何对象、或 sketch lowering 的内部/底层结果,不作为手写草图的推荐方式。

Phase 1 的 Sketch 范围

第一阶段 Sketch 只负责:

  • 容纳 named point / line / circle entities
  • 承载声明式约束:coincident、horizontal、vertical、parallel、perpendicular、collinear、tangent、concentric、midpoint、symmetric、equal length/radius、distance、distance-x/y、length、angle、radius、diameter、fix
  • 求解 constrained sketch 并输出 diagnostics / DOF / residual
  • 生成闭合 loop/profile
  • 参与 extrude/revolve 等特征输入
  • 承载表达式参数与 curve identity

Phase 1 明确不做

第一阶段不做 assembly constraint solverassembly 仍等待新的 assembly graph / constraint graph 契约。

基础操作模型

核心基础操作集

2.0 核心操作集如下:

  • curve/profile:
    • line
    • arc
    • bspline
    • sketch
  • solid feature:
    • extrude
    • revolve
    • fillet
    • chamfer
    • shell
  • boolean:
    • cut
    • union
    • intersection
  • assembly:
    • rigid constraints and instances

变换操作的定位

translaterotatemirror 等操作仍应保留为公开 API,但在 2.0 中建议区别对待:

  • 对 body/instance,它们优先被建模为 placement/rigid transform 操作
  • 对 topology history,它们通常不是创建新特征语义,而是改变对象姿态或结果映射

因此它们应作为支持性核心操作存在,但不抢占“实体特征链”的主轴。

OCP 内核与求值模型

设计目标

2.0 的 evaluator 应做到:

  • 输入稳定语义节点
  • 输出 OCP shape 结果
  • 保留 builder
  • 获取拓扑历史
  • 产出 semantic delta + topology delta

OCP-native Wrapper

2.0 的 Vertex/Edge/Wire/Face/Solid 应从当前 OCP wrapper 切换为 OCP thin wrapper

  • 内部持有 TopoDS_*
  • 自己实现必要的几何查询
  • 尽量避免依赖 cadquery.Shape 提供的方法

当前可复用方向

tracking.py 已经说明以下路径可行:

  • 直接保留 OCC builder
  • 调用 Modified / Generated / IsDeleted
  • 构建 TopoDelta

2.0 应把这条路径从“局部实验能力”提升为“核心 evaluator 规范”。

历史、语义变化与拓扑变化

为什么需要双层 delta

只记录最终 shape 不够,只记录 topology delta 也不够。2.0 需要两层变化信息:

  1. 语义变化
  2. 拓扑变化

语义变化

语义变化描述模型层对象发生了什么:

  • 新建了哪些对象
  • 删除了哪些对象
  • 修改了哪些对象

例如:

  • 创建一个新 Sketch
  • 创建一个新 FeatureNode
  • 替换一个 Body 的当前结果

拓扑变化

拓扑变化描述 OCP 几何层发生了什么:

  • created
  • preserved
  • modified
  • deleted

并记录:

  • parent_refs
  • origin_role
  • 可选 raw_event

2.0 中每次操作的最小产物

每个基础操作应至少返回或附带以下信息:

  • 语义输出对象
  • 几何结果对象
  • semantic delta
  • topology delta
  • 输入对象引用
  • 参数表达式引用
  • 当前参数值快照

需要强覆盖的操作

2.0 第一阶段目标是至少让以下操作具备可靠历史:

  • extrude
  • revolve
  • fillet
  • chamfer
  • shell
  • cut
  • union
  • intersection

如果某个 OCP builder 无法直接给出完整历史,则 evaluator 必须:

  • 明确声明追踪能力等级
  • 或通过辅助 diff 机制补全
  • 不能悄悄退化成“只有结果 shape,没有变化记录”

对象引用与可追踪选择

目标

2.0 要求所有重要几何对象都有:

  • 可追踪引用
  • 可查询空间信息
  • 可关联参数来源

建议引用体系

建议同时维护两类引用:

  1. SemanticRef
    • 面向模型对象
    • 用于 feature、sketch、assembly、constraint 级别引用
  2. TopoRef
    • 面向具体拓扑子形体
    • 用于面/边/顶点级追踪

选择策略

延续现有系统中较好的做法:

  • shape ref
  • selector hint
  • selection query
  • index fallback

但 2.0 应把它们正式化为稳定 schema,而不是零散 metadata。

装配与约束模型

当前判断

constraints.py assembly 系统已从当前 public/support 面移除。2.0 需要先定义新的 assembly IR / constraint graph 契约,再把装配能力重新纳入统一模型 IR。

2.0 装配目标

2.0 中装配层应负责:

  • part definition
  • part instance
  • instance frame
  • anchors
  • constraints
  • solve result
  • 表达式依赖

约束参数也使用同一表达式系统

装配约束涉及:

  • distance
  • offset
  • angle-like parameters
  • frame origin/rotation inputs

这些都应复用同一套 Var/Const/Expr 系统,而不是单独发明一套 assembly 参数机制。

装配层边界

2.0 第一阶段装配约束仍聚焦:

  • rigid body pose solving
  • 不直接修改 part definition 内部拓扑

也就是说:

  • part 的参数变化仍由 feature chain 驱动
  • assembly solve 主要改变 instance pose

序列化与导出

新的 canonical export

2.0 的主导出格式不应是 STEP/STL,而应是模型 IR。

建议采用:

  • model.json
  • 可选 brep_cache/
  • 可选 replay snapshot

model.json 至少应包含

  • schema version
  • producer version
  • expression graph
  • operation graph
  • geometry object registry
  • sketch/profile registry
  • assembly registry
  • constraint registry
  • semantic delta log
  • topology delta log
  • optional display/query hints

STEP/STL/BRep 的定位

这些格式继续保留,但只作为:

  • 最终几何导出
  • 与外部 CAD/CAE/渲染工具交换最终形状

不作为 2.0 的参数化事实来源。

建议的模块重组

以下是建议的 2.0 模块拆分方向:

参数与表达式

  • src/simplecadapi/expr.py
  • src/simplecadapi/eval.py

几何值与 frame

  • src/simplecadapi/geometry.py
  • src/simplecadapi/frame.py
  • src/simplecadapi/sketch.py

OCP 内核适配

  • src/simplecadapi/kernel/ocp_shapes.py
  • src/simplecadapi/kernel/ocp_query.py
  • src/simplecadapi/kernel/ocp_builders.py

基础操作

  • src/simplecadapi/ops/primitives.py
  • src/simplecadapi/ops/curves.py
  • src/simplecadapi/ops/features.py
  • src/simplecadapi/ops/booleans.py
  • src/simplecadapi/ops/transforms.py

历史与拓扑

  • src/simplecadapi/history/op_graph.py
  • src/simplecadapi/history/topology.py
  • src/simplecadapi/history/tracking.py

装配与约束

  • src/simplecadapi/assembly/model.py
  • src/simplecadapi/assembly/anchors.py
  • src/simplecadapi/assembly/constraints.py
  • src/simplecadapi/assembly/solver.py

IO 与 replay

  • src/simplecadapi/io/model_json.py
  • src/simplecadapi/io/replay.py
  • src/simplecadapi/io/exporters.py

兼容外壳

  • src/simplecadapi/__init__.py
  • src/simplecadapi/compat/

兼容外壳负责保留既有 API 名称、签名风格和 import 入口。

迁移策略

总原则

不建议直接在现有 CQ 内核上“原地爆破式重写”。更稳妥的策略是:

  • 在仓库中并行引入 2.0 内核
  • 先做新模块和新测试
  • 等核心操作链跑通后,再把公开 API 切换到底层新引擎

推荐分期

Phase 0: 设计冻结

目标:

  • 冻结 2.0 设计边界
  • 冻结兼容性原则
  • 冻结核心 IR schema 草案

交付:

  • 本文档
  • schema 草案
  • 基础类型命名草案

Phase 1: 表达式与 frame 基础层

目标:

  • 实现 Var/Const/Expr
  • 实现参数 canonicalization
  • 建立 ExpressionGraph
  • 建立 Frame 基础设施
  • 支持变量驱动的数值求值与 dirty propagation

交付:

  • var() API
  • 表达式序列化
  • 参数快照求值器

Phase 2: OCP-native 几何值层

目标:

  • Vertex/Edge/Wire/Face/Solid 建立 OCP-native wrapper
  • 替换当前 core.pycq_* 主依赖
  • 提供面积、体积、法向、bbox、中心等基础查询

交付:

  • OCP thin wrapper
  • 与现有 API 对应的 geometry query 基线测试

Phase 3: Sketch 与基础特征链

目标:

  • 引入 Sketch
  • 支持 line/arc/bspline/sketch
  • 支持 extrude/revolve
  • 支持基于表达式参数求值

交付:

  • Sketch 数据模型
  • extrude/revolve 的 OCP evaluator
  • expression graph 与 operation graph 打通

Phase 4: Boolean 与细节特征的完整追踪

目标:

  • 支持 cut/union/intersection
  • 支持 fillet/chamfer/shell
  • 为这些操作产出可靠 TopoDelta
  • 引入 SemanticDelta

交付:

  • 双层 delta 体系
  • 稳定引用体系
  • 选择与 selector schema

Phase 5: Assembly 与约束图整合

目标:

  • 将 assembly 从独立模块整合为统一 IR 的一部分
  • 约束参数表达式化
  • solve 结果可重放、可序列化

交付:

  • assembly graph
  • constraint graph
  • solve snapshot

Phase 6: 兼容层切换与导出适配器

目标:

  • 用兼容外壳把公开 API 指向新引擎
  • 保留旧命名和主要调用方式
  • 提供新的 canonical JSON export
  • 保留 STEP/STL/BRep 导出

交付:

  • 公开 API 迁移
  • replay 验证
  • 文档与案例迁移

测试策略

2.0 必须从一开始就建立测试矩阵,而不是等功能完成后再补。

1. 兼容性测试

确保以下内容不被破坏:

  • 现有 make_**_rsolid 等函数名
  • 现有返回类型主线
  • 常量参数脚本可以继续运行

2. 表达式测试

至少覆盖:

  • Var/Const/Expr 构图
  • 表达式序列化/反序列化
  • 运算符重载正确性
  • dirty propagation

3. 几何求值测试

至少覆盖:

  • line
  • arc
  • bspline
  • extrude
  • revolve
  • cut/union/intersection
  • fillet/chamfer/shell

4. 拓扑历史测试

至少覆盖:

  • created/preserved/modified/deleted
  • origin_role
  • parent_refs
  • selector 回放稳定性

5. 装配测试

至少覆盖:

  • rigid pose solve
  • constraint expression propagation
  • solve snapshot replay
  • 局部参数变化后的局部重建

6. 全链路测试

至少覆盖:

  • script -> model.json -> replay -> geometry equivalence
  • script -> model.json -> assembly solve -> export

风险与控制策略

风险 1: 试图一步做太多

控制策略:

  • 第一阶段只做基础操作集
  • 完整 sketch solver 暂不进入 Phase 1
  • 复杂宏与特殊 case 暂不进入核心 IR

风险 2: 兼容性被新架构吞掉

控制策略:

  • 公开 API 与兼容层分离
  • 新内核并行实现
  • 迁移期间保留 shape-first 设计不动摇

风险 3: 拓扑命名与稳定引用不稳定

控制策略:

  • 同时维护 SemanticRefTopoRef
  • 不只依赖索引
  • 利用 selector hint、selection query、角色语义和参数来源共同定位

风险 4: 表达式系统过于“魔法”导致难维护

控制策略:

  • 变量显式
  • 常量自动提升
  • 不做源码 AST 捕获
  • 不做 float 伪装继承

非目标

以下内容不属于 2.0 第一阶段目标:

  • 单位系统
  • 通用 CAS 级符号推导
  • 完整 2D sketch constraint solver
  • 所有历史 CAD 格式的原生参数兼容导出
  • 把所有宏函数都纳入核心 IR

结论

SimpleCADAPI 2.0 的本质不是简单地“把 cadquery 换成 OCP”,而是把系统从一个以最终几何为中心的 CQ 包装层,重构成一个以:

  • 几何值对象
  • 参数表达式图
  • 基础特征链
  • 拓扑变化记录
  • 装配约束图

为中心的参数化建模平台。

同时,2.0 不能丢失 SimpleCADAPI 当前最重要的设计资产:

  • 纯函数风格
  • shape-first 用户心智
  • Vertex -> Edge -> Wire -> Face -> Solid 主线
  • 清晰直观的命名和调用方式

因此,2.0 的正确重构路线是:

  • 在内部重建核心模型
  • 在外部保持 API 风格延续
  • 用显式变量、自动表达式提升和 API 边界记录来实现低侵入参数化
  • 用 OCP-native evaluator 和双层 delta 来实现可靠历史追踪

这是一个 2.0 级重构,但它的目标不是抛弃已有设计,而是在保留其用户体验的前提下,把它变成一个真正完整的参数化 CAD 系统。