面向 AI 原生 3D 建模应用的 SDF、网格与 CAD 内核调研:模型、引用、事务与多内核
主文档与完整目录。本分篇保留原调查日期的依据与实测记录;其中的当前状态、建议和授权仅属于历史快照,不是执行队列。
6. 建议自研:Aira Modeling Intermediate Representation(AMIR)
Section titled “6. 建议自研:Aira Modeling Intermediate Representation(AMIR)”6.1 设计原则
Section titled “6.1 设计原则”AMIR 应是唯一规范模型,表层代码、GUI、AI prompt、插件 API 都只是它的视图或编辑入口。
必须具备:
- 纯数据、无任意代码执行。 模型不能带网络、文件、系统调用,也不能无限循环。
- 强类型的几何域。 Sketch2D、Profile2D、ExactSolid、MeshSolid、Field3D、Assembly、DisplayMesh 不可混用。
- 单位进入类型。 Length、Angle、Area、Volume、Ratio 分离;单位转换显式且可审计。
- 稳定 ID 独立于文本顺序。 node map 以 ID 为键,重排或格式化不改变身份。
- 依赖 DAG 和受限高阶构造。 循环用 bounded pattern/map/reduce 表示,可静态估算成本。
- 每个节点声明权威表示、精度与容差。
- 所有随机性有 seed;所有环境选择有版本。
- 输入、产物、诊断和三角形都可回溯到源节点。
6.2 最小 canonical AST 示例
Section titled “6.2 最小 canonical AST 示例”{ "schema": "aira.model/v0.1", "documentId": "doc.bracket", "units": { "length": "mm", "angle": "deg" }, "tolerance": "0.001 mm", "parameters": { "width": { "type": "Length", "value": "80 mm", "range": ["20 mm", "200 mm"] }, "depth": { "type": "Length", "value": "40 mm", "range": ["10 mm", "120 mm"] }, "thickness": { "type": "Length", "value": "4 mm", "range": ["1 mm", "12 mm"] } }, "nodes": { "sketch.base": { "op": "sketch.rectangle", "target": "Sketch2D", "plane": "XY", "center": ["0 mm", "0 mm"], "size": [{ "param": "width" }, { "param": "depth" }], "outputs": { "profile": "outer_profile" } }, "solid.plate": { "op": "brep.extrude", "target": "ExactSolid", "inputs": { "profile": "sketch.base#outer_profile" }, "distance": { "param": "thickness" }, "outputs": { "body": "plate", "faces": { "start": "bottom", "end": "top", "sides": "walls" } } } }, "assertions": [ { "op": "isValidSolid", "input": "solid.plate#plate" }, { "op": "minThickness", "input": "solid.plate#plate", "gte": "3.9 mm" } ]}这份 JSON 不是建议用户每天手写的最终语法,而是所有工具共享、可版本迁移、可自动验证的 canonical form。
6.3 人类可读的表层语言
Section titled “6.3 人类可读的表层语言”建议做一个很薄的、纯函数式、pipeline 风格 .aira 语言:
model mounting_bracket units mm tolerance 0.001mm
param width: Length = 80mm in 20mm..200mmparam depth: Length = 40mm in 10mm..120mmparam thickness: Length = 4mm in 1mm..12mm
sketch @base on XY { rectangle @outer center [0mm, 0mm] size [width, depth]}
solid @plate: ExactSolid = extrude profile @base.outer distance thickness
assert valid(@plate)assert minThickness(@plate) >= 3.9mm关键不是具体关键字,而是:
- 表层语法与 AST 一一可逆;
- formatter 产生唯一规范格式;
- 任何 GUI 操作都能生成小而稳定的 AST patch,再同步回文本;
- 高级用户可使用自动生成的 TypeScript builder SDK,但 SDK 只生成 AMIR,不能直接操作内核。
实现上建议解析为 lossless CST,再投影到以永久 node ID 为身份的语义 AST;注释、空白和其他文本 trivia 挂到 node ID,printer 只重写受 patch 影响的源码范围。这样既保留 Git 友好文本,也避免 AI 每次改一个参数却重写整份文件。
6.4 为什么不直接选 TypeScript 或 Python 当模型语言
Section titled “6.4 为什么不直接选 TypeScript 或 Python 当模型语言”它们对 LLM 熟悉,但作为唯一 source of truth 有明显代价:
- 任意控制流和副作用让增量重算、沙箱与成本估计困难;
- AST diff 往往退化为脆弱的文本重写;
- 单位、几何类型与表示精度只能靠约定;
- 同一结果可有太多写法,降低训练和评测的一致性;
- 很难保证 GUI 修改后仍生成优雅、可读、可维护的源码;
- 错误栈混合宿主语言、绑定层和几何内核,AI 很难恢复。
因此最优组合不是“不要 TypeScript”,而是:
- TypeScript:应用、插件 SDK、自动化 builder;
- Rust:语言/IR/事务与本地服务;
- C++/WASM:OCCT 与 Manifold;
- AMIR/.aira:AI、人类与 GUI 共同理解的建模语义。
7. 建议自研:稳定几何引用
Section titled “7. 建议自研:稳定几何引用”7.1 禁止的做法
Section titled “7.1 禁止的做法”- face[7]、edge[12];
- “取面积最大的面”后默认选第一个;
- 只保存一次运行中的 OCCT pointer/hash;
- 从 Three.js triangle index 反推长期 CAD 身份;
- 重算歧义时静默换到另一条边。
7.2 SemanticRef
Section titled “7.2 SemanticRef”一个引用应同时包含:
- 来源: 哪个 feature、哪个命名输出产生;
- 角色: startCap、endCap、sideFrom(sketch.lineA)、filletSurface 等;
- 谱系: 经过哪些 Modified / Generated 历史;
- 几何约束: 类型、方向、解析曲面种类、半径/面积区间、邻接关系;
- 基数契约: expect exactly one / N / non-empty;
- 失败策略: 报告 missing、ambiguous 或 changed-kind,不自动猜。
示例:
{ "nodeId": "feature.fillet_outer", "selector": { "scope": "solid.plate#plate", "entity": "Edge", "lineage": { "createdBy": "solid.plate", "fromRole": "walls" }, "where": { "convex": true, "parallelTo": "Z", "adjacentSurfaceTypes": ["Plane", "Plane"] }, "expect": { "count": 4 } }}执行顺序应是:
- 优先使用 feature output 与 OCCT/Manifold 历史映射;
- 再用结构/邻接关系;
- 最后才用几何 predicate;
- 结果不满足 expect 就终止事务并返回候选,而不是选择第一个。
7.3 ArtifactGraph 与 Source Map
Section titled “7.3 ArtifactGraph 与 Source Map”每次内核执行都生成 ArtifactGraph,记录 feature 产物之间的 generated / modified / split / merged / deleted 谱系;在此基础上维护四向映射:
源代码范围 ⇄ AMIR node/port ⇄ kernel artifact/subshape ⇄ render primitive/triangle由此才能实现:
- 点场景中的面,定位到定义它的代码;
- AI 查询某个 feature 实际产生了哪些面;
- 诊断高亮到 3D 视口;
- mesh boolean 后仍追踪材质与大致来源;
- screenshot segmentation 使用稳定 artifact ID,而不是颜色猜测。
8. 建议自研:AI 事务协议
Section titled “8. 建议自研:AI 事务协议”AI 不应拿到“运行任意源码”或一千个 OCCT 方法。推荐一个小型、自描述、可查询的领域工具面:
| 工具 | 作用 |
|---|---|
| catalog.search | 按能力、输入输出类型、精度、成本、失败模式检索操作 |
| model.read | 获取参数、特征图、选区、版本与摘要 |
| model.query | 几何/拓扑/测量/来源查询 |
| model.proposePatch | 对指定 baseRevision 生成领域补丁,静态检查但不提交 |
| model.preview | 在 quality budget 内执行候选图并返回 diff、诊断、图片/分割 |
| model.validate | 运行 exact/mesh/field/制造约束验证 |
| model.commit | 原子提交已验证补丁 |
| model.revert | 按 revision 回退 |
| model.export | 显式选择 STEP、3MF、GLB 等,并报告有损项 |
一个 patch 需要:
{ "baseRevision": "sha256:...", "intent": "把四条外侧竖边做 3 mm 圆角", "operations": [ { "op": "insertNode", "nodeId": "feature.outer_fillet", "after": "solid.plate", "value": { "op": "brep.fillet", "input": "solid.plate#plate", "edges": { "ref": "selection.outer_vertical_edges" }, "radius": "3 mm" } } ], "preconditions": [ { "op": "revisionEquals", "value": "sha256:..." }, { "op": "selectionCount", "ref": "selection.outer_vertical_edges", "equals": 4 } ]}事务语义:
- preview 与 commit 使用相同输入、内核版本、容差和 seed;
- commit 前必须重验 preconditions;
- 失败不产生半修改状态;
- 每次提交保存 prompt/intent、patch、前后 revision、诊断和产物摘要;
- 相同 idempotency key 不得重复应用。
9. Geometry Observatory:让 AI 真正“看懂”模型
Section titled “9. Geometry Observatory:让 AI 真正“看懂”模型”只给截图不够,只给 B-Rep dump 也不够。每次执行建议返回:
- 参数与表达式求值;
- 节点状态:clean / dirty / running / failed / approximated;
- 产物类型与权威表示;
- bounding box、体积、面积、重心、惯量;
- body/face/edge/vertex 数与拓扑摘要;
- surface/curve 类型分布;
- manifold、自相交、空壳、负体积、退化元素;
- 约束自由度、冲突集合、冗余约束;
- selected refs 的解析过程与候选;
- 有损转换记录和误差界;
- 正交六视图、透视图、深度、法线、feature-ID segmentation;
- 执行耗时、峰值内存、三角形数与缓存命中。
这些结果应收敛成可持久化的 Geometry Certificate:记录 exact / approximate / voxelized 等表示等级、kernel 名称与精确版本、input hash、单位/tolerance、采样分辨率、watertight/manifold/self-intersection 状态、来源保留程度、警告与可执行修复建议。它不是“绝对正确证明”,而是让 AI、回归系统和导出流程知道这次结果究竟保证了什么。
错误必须是稳定 code + 结构化 payload:
{ "id": "diag:01K3EXAMPLE00000000000000", "code": "FILLET_RADIUS_TOO_LARGE", "severity": "error", "phase": "kernel", "at": { "nodeId": "feature.outer_fillet", "port": "radius" }, "messageKey": "geometry.fillet.radiusTooLarge", "details": { "entities": ["edge.outer.0", "edge.outer.1"], "requested": { "value": "12", "unit": "mm" }, "safeUpperBoundEstimate": { "value": "4.82", "unit": "mm" } }, "fixes": [ { "kind": "patchTemplate", "action": "reduceRadius", "suggested": { "const": { "type": "Length", "value": "4.5", "unit": "mm" } } }, { "kind": "patchTemplate", "action": "excludeEntity", "entity": "edge.outer.1" } ]}这比异常字符串更能帮助 AI 自我修复,也更容易做自动评测。
10. 多内核调度与转换规则
Section titled “10. 多内核调度与转换规则”10.1 操作路由
Section titled “10.1 操作路由”| 操作 | 默认后端 | 权威输出 |
|---|---|---|
| 约束草图、精确 extrude/revolve/loft/sweep | OCCT | ExactSolid |
| fillet/chamfer/shell/draft、STEP import/export | OCCT | ExactSolid |
| manifold mesh import、mesh boolean、split、打印修整 | Manifold | MeshSolid |
| smooth union、lattice、warp、gyroid | Field compiler | Field3D |
| Field 烘焙 | Manifold LevelSet(首版) | MeshSolid,带误差 |
| 视口三角化 | OCCT tessellator 或 Manifold MeshGL | DisplayMesh |
| 材质、相机、辅助线、选择高亮 | Three.js | SceneView |
10.2 转换必须显式
Section titled “10.2 转换必须显式”允许:
- ExactSolid -> DisplayMesh:tessellate,派生、可重建;
- ExactSolid -> MeshSolid:显式 bake,记录 chordal/angular deflection;
- Field3D -> MeshSolid:显式 bake,记录 bounds/edgeLength/tolerance;
- MeshSolid -> Field3D:显式 voxelize/distance,记录分辨率与 sign 方法。
默认禁止:
- MeshSolid -> ExactSolid 的“自动精确化”;
- Field3D -> ExactSolid 的泛化转换;
- 把导入 STL 当成可无损编辑的 CAD;
- 由 Three.js BufferGeometry 反写设计历史。
同一 feature graph 可以包含多种权威实体,但每个 part/body 的当前权威表示必须唯一。
11. 2D 草图与约束
Section titled “11. 2D 草图与约束”约束对“AI 原生 CAD”不是可选项。ICLR 2022 的 Vitruvion 把参数化草图明确描述为“约束程序”,指出设计意图不仅在几何 primitive 中,也在元素之间的参数关系中。论文
可选路线:
- FreeCAD PlaneGCS 是成熟的 LGPL-2.1-or-later 2D 几何约束求解器。
- planegcs WASM wrapper 提供 TypeScript annotations,并支持 DogLeg、Levenberg-Marquardt、BFGS、SQP 等路径;README 也坦承某些 non-driving 约束和组合仍有使用陷阱。
- SolveSpace 的 libslvs 能力成熟,但 GPLv3 会显著影响闭源集成方式。
- 商业路线可评估 Siemens D-Cubed 2D DCM,但不适合作为开源 MVP 的默认依赖。
建议:
- AMIR 先定义自己的 SketchEntity / Constraint / DOF / ConflictSet,不绑定任何 solver 数据结构。
- 首版对 planegcs WASM 做独立验证,特别测试拖拽、过约束、冗余、初值敏感和大尺度差异。
- 把 solver 的 raw residual、自由度与冲突候选转成稳定诊断。
- 如果闭源分发、体积或行为稳定性不满足需求,再评估自研窄而可解释的 solver;不要一开始重写全部 CAD 约束算法。