@faicad/faijs 0.32.3 → 0.33.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/dist/api/api-namespace.js +3 -3
  2. package/dist/api/api-namespace.js.map +1 -1
  3. package/dist/api/assembly/index.d.ts +1 -0
  4. package/dist/api/assembly/index.d.ts.map +1 -1
  5. package/dist/api/assembly/index.js +1 -0
  6. package/dist/api/assembly/index.js.map +1 -1
  7. package/dist/api/assembly/lower.d.ts.map +1 -1
  8. package/dist/api/assembly/lower.js +7 -0
  9. package/dist/api/assembly/lower.js.map +1 -1
  10. package/dist/api/assembly/normalize.d.ts.map +1 -1
  11. package/dist/api/assembly/normalize.js +2 -1
  12. package/dist/api/assembly/normalize.js.map +1 -1
  13. package/dist/api/assembly/solve-tree.d.ts +46 -0
  14. package/dist/api/assembly/solve-tree.d.ts.map +1 -0
  15. package/dist/api/assembly/solve-tree.js +135 -0
  16. package/dist/api/assembly/solve-tree.js.map +1 -0
  17. package/dist/api/assembly/solve.d.ts +7 -0
  18. package/dist/api/assembly/solve.d.ts.map +1 -1
  19. package/dist/api/assembly/solve.js.map +1 -1
  20. package/dist/api/assembly/solvers/assembly-tree.d.ts +4 -0
  21. package/dist/api/assembly/solvers/assembly-tree.d.ts.map +1 -1
  22. package/dist/api/assembly/solvers/assembly-tree.js +1 -0
  23. package/dist/api/assembly/solvers/assembly-tree.js.map +1 -1
  24. package/dist/api/assembly/solvers/global-solver.d.ts.map +1 -1
  25. package/dist/api/assembly/solvers/global-solver.js +210 -3
  26. package/dist/api/assembly/solvers/global-solver.js.map +1 -1
  27. package/dist/api/assembly/solvers/types.d.ts +8 -0
  28. package/dist/api/assembly/solvers/types.d.ts.map +1 -1
  29. package/dist/api/assembly/solvers/types.js.map +1 -1
  30. package/dist/api/assembly/types.d.ts +32 -1
  31. package/dist/api/assembly/types.d.ts.map +1 -1
  32. package/dist/api/assembly/types.js.map +1 -1
  33. package/dist/api/assembly/validate.d.ts +2 -2
  34. package/dist/api/assembly/validate.d.ts.map +1 -1
  35. package/dist/api/assembly/validate.js +24 -2
  36. package/dist/api/assembly/validate.js.map +1 -1
  37. package/dist/api/cadquery-selectors/edge.js +1 -1
  38. package/dist/api/cadquery-selectors/edge.js.map +1 -1
  39. package/dist/api/cadquery-selectors/entity.d.ts +29 -20
  40. package/dist/api/cadquery-selectors/entity.d.ts.map +1 -1
  41. package/dist/api/cadquery-selectors/entity.js +26 -20
  42. package/dist/api/cadquery-selectors/entity.js.map +1 -1
  43. package/dist/api/cadquery-selectors/face.d.ts +4 -2
  44. package/dist/api/cadquery-selectors/face.d.ts.map +1 -1
  45. package/dist/api/cadquery-selectors/face.js +8 -7
  46. package/dist/api/cadquery-selectors/face.js.map +1 -1
  47. package/dist/api/cadquery-selectors/resolve.d.ts +7 -6
  48. package/dist/api/cadquery-selectors/resolve.d.ts.map +1 -1
  49. package/dist/api/cadquery-selectors/resolve.js +13 -11
  50. package/dist/api/cadquery-selectors/resolve.js.map +1 -1
  51. package/dist/api/chamfer.js +1 -1
  52. package/dist/api/chamfer.js.map +1 -1
  53. package/dist/api/draft.js +1 -1
  54. package/dist/api/draft.js.map +1 -1
  55. package/dist/api/edge-ref.js +2 -2
  56. package/dist/api/edge-ref.js.map +1 -1
  57. package/dist/api/engrave.js +1 -1
  58. package/dist/api/engrave.js.map +1 -1
  59. package/dist/api/export-3mf.js +1 -1
  60. package/dist/api/export-3mf.js.map +1 -1
  61. package/dist/api/export-brep.js +1 -1
  62. package/dist/api/export-brep.js.map +1 -1
  63. package/dist/api/export-step.d.ts +12 -13
  64. package/dist/api/export-step.d.ts.map +1 -1
  65. package/dist/api/export-step.js +19 -17
  66. package/dist/api/export-step.js.map +1 -1
  67. package/dist/api/extrude.js +3 -3
  68. package/dist/api/extrude.js.map +1 -1
  69. package/dist/api/face-ref.js +2 -2
  70. package/dist/api/face-ref.js.map +1 -1
  71. package/dist/api/feature-repair.js +2 -2
  72. package/dist/api/feature-repair.js.map +1 -1
  73. package/dist/api/fillet-variable.js +1 -1
  74. package/dist/api/fillet-variable.js.map +1 -1
  75. package/dist/api/fillet.js +1 -1
  76. package/dist/api/fillet.js.map +1 -1
  77. package/dist/api/geom.js +1 -1
  78. package/dist/api/geom.js.map +1 -1
  79. package/dist/api/import-step.d.ts.map +1 -1
  80. package/dist/api/import-step.js +4 -2
  81. package/dist/api/import-step.js.map +1 -1
  82. package/dist/api/pattern.js +1 -1
  83. package/dist/api/pattern.js.map +1 -1
  84. package/dist/api/place.js +1 -1
  85. package/dist/api/place.js.map +1 -1
  86. package/dist/api/punch-hole.js +1 -1
  87. package/dist/api/punch-hole.js.map +1 -1
  88. package/dist/api/replicate.js +1 -1
  89. package/dist/api/replicate.js.map +1 -1
  90. package/dist/api/revolve.js +1 -1
  91. package/dist/api/revolve.js.map +1 -1
  92. package/dist/api/section-by-plane.js +1 -1
  93. package/dist/api/section-by-plane.js.map +1 -1
  94. package/dist/api/shell.js +1 -1
  95. package/dist/api/shell.js.map +1 -1
  96. package/dist/api/sketch-on-face.js +1 -1
  97. package/dist/api/sketch-on-face.js.map +1 -1
  98. package/dist/api/split-by-plane.js +1 -1
  99. package/dist/api/split-by-plane.js.map +1 -1
  100. package/dist/api/split.js +1 -1
  101. package/dist/api/split.js.map +1 -1
  102. package/dist/api/thicken.js +1 -1
  103. package/dist/api/thicken.js.map +1 -1
  104. package/dist/api/topo-resolve.js +4 -4
  105. package/dist/api/topo-resolve.js.map +1 -1
  106. package/dist/api/transform.js +1 -1
  107. package/dist/api/transform.js.map +1 -1
  108. package/dist/api/view/view-projection.d.ts +8 -0
  109. package/dist/api/view/view-projection.d.ts.map +1 -1
  110. package/dist/api/view/view-projection.js +73 -2
  111. package/dist/api/view/view-projection.js.map +1 -1
  112. package/dist/boolean/cross-section.d.ts.map +1 -1
  113. package/dist/boolean/cross-section.js +3 -1
  114. package/dist/boolean/cross-section.js.map +1 -1
  115. package/dist/brep/brep-ops.d.ts +26 -0
  116. package/dist/brep/brep-ops.d.ts.map +1 -1
  117. package/dist/brep/brep-ops.js +45 -0
  118. package/dist/brep/brep-ops.js.map +1 -1
  119. package/dist/brep/brep-topology.js +1 -1
  120. package/dist/brep/brep-topology.js.map +1 -1
  121. package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
  122. package/dist/brep/engine/adapters/brep-mock.js +2 -0
  123. package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
  124. package/dist/brep/engine/primitives.d.ts +17 -0
  125. package/dist/brep/engine/primitives.d.ts.map +1 -1
  126. package/dist/brep/engine/primitives.js.map +1 -1
  127. package/dist/brep/export/export-model.d.ts.map +1 -1
  128. package/dist/brep/export/export-model.js +36 -11
  129. package/dist/brep/export/export-model.js.map +1 -1
  130. package/dist/brep/export/step-flat.d.ts +35 -0
  131. package/dist/brep/export/step-flat.d.ts.map +1 -0
  132. package/dist/brep/export/step-flat.js +94 -0
  133. package/dist/brep/export/step-flat.js.map +1 -0
  134. package/dist/brep/export/step.d.ts.map +1 -1
  135. package/dist/brep/export/step.js +42 -21
  136. package/dist/brep/export/step.js.map +1 -1
  137. package/dist/brep/handle-bridge.d.ts +4 -4
  138. package/dist/brep/handle-bridge.js +4 -4
  139. package/dist/brep/handle-bridge.js.map +1 -1
  140. package/dist/brep/svg/svg-to-solid.d.ts +3 -17
  141. package/dist/brep/svg/svg-to-solid.d.ts.map +1 -1
  142. package/dist/brep/svg/svg-to-solid.js +16 -317
  143. package/dist/brep/svg/svg-to-solid.js.map +1 -1
  144. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  145. package/dist/brepkit-kernel/brepkitKernel.js +10 -0
  146. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  147. package/dist/brepkit-kernel/brepkitWasm.d.ts +1 -1
  148. package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
  149. package/dist/brepkit-kernel/brepkitWasm.js +7 -6
  150. package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
  151. package/dist/brepkit-kernel/multi-version-test.d.ts +7 -7
  152. package/dist/brepkit-kernel/multi-version-test.d.ts.map +1 -1
  153. package/dist/brepkit-kernel/multi-version-test.js +10 -10
  154. package/dist/brepkit-kernel/multi-version-test.js.map +1 -1
  155. package/dist/cad-runtime/direct-executor.js +2 -2
  156. package/dist/cad-runtime/direct-executor.js.map +1 -1
  157. package/dist/cad-runtime/runtime.js +5 -5
  158. package/dist/cad-runtime/runtime.js.map +1 -1
  159. package/dist/geometry2d/curve2d.js +42 -1
  160. package/dist/geometry2d/curve2d.js.map +1 -1
  161. package/dist/math3d/Box3.js.map +1 -1
  162. package/dist/math3d/Euler.js.map +1 -1
  163. package/dist/math3d/Mat4.js.map +1 -1
  164. package/dist/math3d/Plane.js.map +1 -1
  165. package/dist/math3d/Quat.js.map +1 -1
  166. package/dist/math3d/Vec2.js.map +1 -1
  167. package/dist/math3d/Vec3.js.map +1 -1
  168. package/dist/math3d/index.js.map +1 -1
  169. package/dist/mesh/meshdata/contour.d.ts +34 -0
  170. package/dist/mesh/meshdata/contour.d.ts.map +1 -0
  171. package/dist/mesh/meshdata/contour.js +39 -0
  172. package/dist/mesh/meshdata/contour.js.map +1 -0
  173. package/dist/mesh/meshdata/extrude.d.ts +25 -0
  174. package/dist/mesh/meshdata/extrude.d.ts.map +1 -0
  175. package/dist/mesh/meshdata/extrude.js +198 -0
  176. package/dist/mesh/meshdata/extrude.js.map +1 -0
  177. package/dist/mesh/meshdata/index.js.map +1 -1
  178. package/dist/mesh/meshdata/ops.js.map +1 -1
  179. package/dist/mesh/meshdata/parametric.js.map +1 -1
  180. package/dist/mesh/meshdata/weld.js.map +1 -1
  181. package/dist/node-host/cli.d.ts +9 -0
  182. package/dist/node-host/cli.d.ts.map +1 -1
  183. package/dist/node-host/cli.js +34 -9
  184. package/dist/node-host/cli.js.map +1 -1
  185. package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
  186. package/dist/occt-kernel/occt-primitives.js +2 -0
  187. package/dist/occt-kernel/occt-primitives.js.map +1 -1
  188. package/dist/primitives/svg/svg-path.d.ts +192 -0
  189. package/dist/primitives/svg/svg-path.d.ts.map +1 -0
  190. package/dist/primitives/svg/svg-path.js +776 -0
  191. package/dist/primitives/svg/svg-path.js.map +1 -0
  192. package/dist/third-party/earcut.d.ts +19 -0
  193. package/dist/third-party/earcut.d.ts.map +1 -0
  194. package/dist/third-party/earcut.js +575 -0
  195. package/dist/third-party/earcut.js.map +1 -0
  196. package/package.json +10 -3
@@ -40,9 +40,9 @@ import { halfSpace } from './half-space.js';
40
40
  import { exportStl } from './export-stl.js';
41
41
  import { exportBrep } from './export-brep.js';
42
42
  // 2026-10-08(方案 §2.6 / DEC-3):脚本面 step / 3mf 出口。两者都是薄壳:宿主门
43
- // (+ exportStep 的 occt 引擎门)之后把入参转成 ExportEntry[],序列化一律交库面
44
- // exportModelSync(单一真源),故与库面逐字节同源。只进脚本面(本字面量 + check()
45
- // 符号表),**不平铺 api/index.ts**(§2.7 / DEC-6)。
43
+ // (引擎通道无门禁——库面按当前引擎分派,见 export-step.ts)之后把入参转成 ExportEntry[],
44
+ // 序列化一律交库面 exportModelSync(单一真源),故与库面逐字节同源。只进脚本面
45
+ // (本字面量 + check() 符号表),**不平铺 api/index.ts**(§2.7 / DEC-6)。
46
46
  import { exportStep } from './export-step.js';
47
47
  import { export3mf } from './export-3mf.js';
48
48
  // S4(occt-wasm op 接入):类型判定谓词族(平台 op engines:['occt'],普通函数形态)。
@@ -1 +1 @@
1
- {"version":3,"file":"api-namespace.js","sourceRoot":"","sources":["../../src/api/api-namespace.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api-namespace — 把 L3 API 面(api/ 层的 fp操作)装配为 cad 命名空间(统一 ABI,B2 消灭)\n *\n *\n * 库函数签名 = .fai.js 源码形态(无隐式参数);本文件无任何 per-函数逻辑。\n *\n * 归属(monorepo P5/E-a-1):本文件随 core 出包,是 faijs 默认库函数\n * (cad 命名空间)的装配点。K5(引擎零函数知识)的准确含义是:parser / compile /\n * runtime 不按函数名分支、不区分函数类别,函数信息统一以 defineOp 元数据(均匀数据)\n * 承载。把 cad 这套库数据内置进引擎,与第三方库走完全相同的 registerLib 路径,\n * 引擎并未对 cad 特判,因此不构成 K5 违反。cad 在 core 的 createRuntime 包装中\n * 被注册为 default 命名空间(见 cad-runtime/runtime.ts 的 createRuntime)。\n *\n * D1(2026-09-23 扩展库拆分):本命名空间只装配**平台面**。编辑器专属 op\n * (`fai_*` / `group` / `assembly` / `copy` / `load`)与两个非基础 three 链的创建 op\n * (`text` / `svgExtrude`)已迁到 `@faicad/faijs-extra`,由宿主经\n * `mergeEditorNamespace()` 合并后注册——键名与拆分前完全一致,存量 `.fai.js` 零迁移。\n * 四个 transform op(translate/rotate_euler/scale/scale3d)按 D1 选项 C 留在此处:\n * `translate` 是通用几何变换,且是小程序端唯一在用的 transform op。\n */\n\nimport { box, sphere, cylinder, cone, wedge } from './primitives'\nimport { translate, rotate_euler, scale, scale3d } from './transform'\n// cad.extrude 是平台手写 op(承载 upTo;长度形态委托 generated/operations 的投影),\n// 见 api/extrude.ts 的分层说明——up-to 不落在 fai_extrude(后者已随扩展库迁出)。\nimport { extrude } from './extrude'\nimport { knurl } from './knurl'\nimport { sdf } from './sdf'\nimport { screw } from './screw'\nimport { profile } from './profile'\nimport { sketchOnPlane } from './sketch-on-plane'\nimport { sketchOnFace } from './sketch-on-face'\nimport { sketchOnSurface } from './sketch-on-surface'\nimport { punchHole } from './punch-hole'\nimport { wire } from './wire'\nimport { helix } from './helix'\nimport { surface } from './surface'\nimport { offset2d } from './offset2d'\nimport { solidFromFaces } from './solid-from-faces'\nimport { halfSpace } from './half-space'\nimport { exportStl } from './export-stl'\nimport { exportBrep } from './export-brep'\n// 2026-10-08(方案 §2.6 / DEC-3):脚本面 step / 3mf 出口。两者都是薄壳:宿主门\n// (+ exportStep 的 occt 引擎门)之后把入参转成 ExportEntry[],序列化一律交库面\n// exportModelSync(单一真源),故与库面逐字节同源。只进脚本面(本字面量 + check()\n// 符号表),**不平铺 api/index.ts**(§2.7 / DEC-6)。\nimport { exportStep } from './export-step'\nimport { export3mf } from './export-3mf'\n// S4(occt-wasm op 接入):类型判定谓词族(平台 op engines:['occt'],普通函数形态)。\n// 直调 occt 原生 isEdge/isFace/isShell/isVertex/isWire/isCompound/isCompSolid/isEqual\n// (不在 L1 契约,方案 §3.4.6 校正注);布尔返回,走 export-brep 同口径。\nimport {\n isEdge, isFace, isShell, isVertex, isWire, isCompound, isCompSolid, isEqual,\n} from './shape-type'\n// S4(occt-wasm op 接入):视图与导出族(平台 op engines:['occt'],普通函数形态)。\n// 直调 occt 原生 toSVG/toMultiviewSVG/toPNG/toMultiviewPNG(不在 L1 契约,方案 §3.4.7 校正注);\n// 字符串/Uint8Array 返回,走 export-brep / shape-type 同口径。\nimport { toSVG, toMultiviewSVG, toPNG, toMultiviewPNG } from './view-export'\n// S4(occt-wasm op 接入):曲线与草图构造族(平台 op engines:['occt'],方案 §3.4.1)。\n// 直调 occt 原生 makeEdge/makeCircleArc/makeEllipseEdge/makeEllipseArc/makeTangentArc/\n// approximatePoints/interpolatePointsWithTangents/curveDegreeElevate/curveKnotInsert/\n// curveKnotRemove/curveIsPeriodic(不在 L1 契约);curveIsPeriodic 布尔返回,普通函数。\nimport {\n edge, circleArc, ellipseEdge, ellipseArc, tangentArc,\n approximatePoints, interpolateWithTangents,\n curveDegreeElevate, curveKnotInsert, curveKnotRemove, curveIsPeriodic,\n} from './curve-sketch'\n// S4(occt-wasm op 接入):曲面与面构造族(平台 op engines:['occt'],方案 §3.4.2)。\n// 直调 occt 原生 makeFaceOnSurface/makeNonPlanarFace/makeSolid/reverseSurfaceU/outerWire\n// (不在 L1 契约;bsplineSurface 已由 S3 的 surface op 覆盖)。\nimport { faceOnSurface, nonPlanarFace, makeSolid, reverseSurfaceU, outerWire } from './surface-face'\n// S4(occt-wasm op 接入):实体与偏置族剩余(平台 op engines:['occt'],方案 §3.4.4)。\n// 直调 occt 原生 draftPrism/pipe(不在 L1 契约;offsetWire2D/buildSolidFromFaces/\n// halfSpace 已由 S3 落地)。\nimport { draftPrism, pipe } from './solid-offset'\n// S4(occt-wasm op 接入):测量与查询族(平台 op engines:['occt'],方案 §3.4.6)。\n// 13 个原生方法不在 L1 契约:containsPoint/distanceBetween/getInertia/\n// getLinearCenterOfMass/projectPointOnEdge/projectPointOnFace/classifyPointOnFace/\n// uvFromPoint/vertexPosition/subShapeCount/iterShapes 返回非 Shape,\n// 走 export-brep / shape-type 同口径的普通函数;liftCurve2d / commonCells\n// 返回 Shape,走 defineOp。\nimport {\n containsPoint, distanceBetween, inertia, linearCenterOfMass,\n projectPointOnEdge, projectPointOnFace, classifyPointOnFace,\n uvFromPoint, vertexPosition, subShapeCount, iterShapes,\n liftCurve2d, commonCells,\n} from './measure-query'\n// S4(occt-wasm op 接入):通用布尔族(平台 op engines:['occt'],方案 §3.4.5)——\n// 原生 booleanOp:带 glue/fuzzy/simplify 选项的通用形态,不在 L1 契约。\nimport { boolean as booleanWithOptions } from './boolean-op'\n// S4(occt-wasm op 接入):包围盒对齐族(平台 op engines:['occt'],方案 §3.4.9)——\n// 原生 alignX/alignY/alignZ 三轴并为一个脚本符号 alignTo。\nimport { alignTo } from './align'\nimport { union, subtract, intersect, cut } from './boolean'\nimport { split } from './split'\nimport { sweep } from './sweep'\nimport { sweepAdvanced } from './sweep-advanced'\nimport { loft } from './loft'\nimport { loftAdvanced } from './loft-advanced'\nimport { linearPattern } from './pattern'\nimport { circularPattern, gridPattern, rectangularPattern, mirrorJoin, mirror, clone } from './replicate'\nimport { engrave } from './engrave'\nimport { chamfer } from './chamfer'\nimport { fillet } from './fillet'\nimport { shell } from './shell'\nimport { draft } from './draft'\nimport { thicken } from './thicken'\nimport { defeature, reverseShape, unifySameDomain, sew, sewAndSolidify, removeHolesFromFace } from './feature-repair'\nimport { filletVariable } from './fillet-variable'\nimport { splitByPlane } from './split-by-plane'\nimport { sectionByPlane } from './section-by-plane'\nimport { faceNormal, bboxCenter, bboxMin, bboxMax } from './geom'\nimport { edgeRef } from './edge-ref'\nimport { faceRef } from './face-ref'\nimport { jointTrajectory, inverseKinematics, mechanismDOF } from './assembly'\nimport { asset } from './asset'\nimport { import_brep } from './import-brep'\nimport { import_step } from './import-step'\nimport { compound as geometricCompound } from './compound-geom'\nimport { place } from './place'\nimport { scriptFaceOps } from './generated/script-face'\nimport { revolve } from './revolve'\nimport { CONTRACT_VERSION } from '../runtime-state'\nimport type { LibNamespace } from '../runtime-state'\n\n/**\n * Assemble api functions into the cad namespace.\n *\n * P23(§4.2 ②,B1):cad 面 = faijs 特有 dual op(下方字面量)+\n * 生成脚本面 op(`scriptFaceOps`——`api/generated/script-face.ts` 按 arg-spec\n * 的 `scriptFace: true` 条目生成,`defineOp({ brep: __own_* })` 直连的\n * brep-only 语句级 op)。`check()` 符号表(`gen-symbol-table.ts`)取自同一份清单。\n * 2026-10-08(§2.7 / DEC-6、DEC-7):本命名空间**不再**要求被 `api/index.ts`\n * 平铺——库面只保留有库作者消费者的名字,其余脚本 op 只走 `cad.*` 与子路径。\n *\n * @returns the assembled LibNamespace ready for runtime injection.\n */\nexport function createApiNamespace(): LibNamespace {\n // D-4 strict assembly check: the cad namespace now exports dual-op functions\n // (defineOp), so registerLib requires a matching contractVersion. Cast is\n // needed because LibNamespace is an index-signature type.\n return {\n contractVersion: CONTRACT_VERSION,\n box, sphere, cylinder, cone, wedge,\n screw, profile, sketchOnPlane, sketchOnFace, sketchOnSurface, punchHole, wire, helix, sdf,\n // D1 选项 C:四个 transform op 全留核心(translate 小程序端在用,同族不拆散)。\n translate, rotate_euler, scale, scale3d,\n engrave, chamfer, fillet, knurl,\n // Phase 5:按面/边选的特征族 + 修复薄包装(shell/draft 中立;thicken 平台 occt)。\n shell, draft, thicken, filletVariable, splitByPlane, sectionByPlane,\n defeature, reverseShape, unifySameDomain, sew, sewAndSolidify, removeHolesFromFace,\n union, subtract, intersect,\n extrude, revolve,\n // Phase 4:手写扫掠 / 放样。**基础 op 两内核都支持**(进 L1 中立名\n // BrepEngineApi#sweep / #loft);只有 occt 能做的完整控制面拆成独立平台 op\n // (engines:['occt']):sweepAdvanced(transition/auxSpine/support/law/…)、\n // loftAdvanced(startPoint/tolerance)。\n // arg-spec 里 sweep 保留 brep-op(引擎记录)/ loft 为 skip,两者均不投脚本面,\n // 所以这里不是 override 而是唯一实现(同 extrude / revolve 口径)。\n sweep, sweepAdvanced, loft, loftAdvanced,\n // S3(occt-wasm op 接入):控制点阵 → B 样条面(平台 op engines:['occt'])。\n surface,\n // S3(occt-wasm op 接入):2D 轮廓偏置(平台 op engines:['occt'],原生 offsetWire2D)。\n offset2d,\n // S3(occt-wasm op 接入):面集一次成型为实体(平台 op engines:['occt'],原生 buildSolidFromFaces)。\n solidFromFaces,\n // S3(occt-wasm op 接入):无限半空间实体(平台 op engines:['occt'],原生 halfSpace;\n // 无界布尔工具的来源,产物 mesh 为空——单独渲染无意义,只作 cut/common/split 的工具位)。\n halfSpace,\n // S3(occt-wasm op 接入):导出族。exportStl 中立(只序列化 Shape 自带三角载荷,\n // 无内核调用);exportBrep 平台(原生 toBREP,L1 只有 fromBREP 导入侧)。\n exportStl,\n exportBrep,\n // 方案 §2.6:step(occt 必需——装配层级走 XCAF)/ 3mf(引擎中立,纯 XML + ZIP)。\n exportStep,\n export3mf,\n // S4(occt-wasm op 接入):类型判定谓词族(平台 op engines:['occt'],布尔返回)。\n isEdge, isFace, isShell, isVertex, isWire, isCompound, isCompSolid, isEqual,\n // S4(occt-wasm op 接入):视图与导出族(平台 op engines:['occt'],字符串/Uint8Array 返回)。\n toSVG, toMultiviewSVG, toPNG, toMultiviewPNG,\n // S4(occt-wasm op 接入):曲线与草图构造族(平台 op engines:['occt'],方案 §3.4.1)。\n edge, circleArc, ellipseEdge, ellipseArc, tangentArc,\n approximatePoints, interpolateWithTangents,\n curveDegreeElevate, curveKnotInsert, curveKnotRemove, curveIsPeriodic,\n // S4(occt-wasm op 接入):曲面与面构造族(平台 op engines:['occt'],方案 §3.4.2)。\n faceOnSurface, nonPlanarFace, makeSolid, reverseSurfaceU, outerWire,\n // S4(occt-wasm op 接入):实体与偏置族剩余(平台 op engines:['occt'],方案 §3.4.4)。\n draftPrism, pipe,\n // S4(occt-wasm op 接入):测量与查询族(平台 op engines:['occt'],方案 §3.4.6)。\n containsPoint, distanceBetween, inertia, linearCenterOfMass,\n projectPointOnEdge, projectPointOnFace, classifyPointOnFace,\n uvFromPoint, vertexPosition, subShapeCount, iterShapes,\n liftCurve2d, commonCells,\n // S4(occt-wasm op 接入):通用布尔族 booleanOp(方案 §3.4.5)+ 包围盒对齐族\n // alignX/Y/Z → alignTo(方案 §3.4.9),平台 op engines:['occt']。\n boolean: booleanWithOptions,\n alignTo,\n faceNormal, bboxCenter, bboxMin, bboxMax,\n edgeRef,\n faceRef,\n jointTrajectory, inverseKinematics, mechanismDOF,\n asset,\n // 平台几何 op(H11,方案 §4):FCStd 迁移自此不再借用编辑器 op\n // (group/translate/rotate_euler);这几个与 ../3d_editor 无关系。\n import_brep,\n import_step,\n compound: geometricCompound,\n place,\n ...scriptFaceOps,\n // Phase 3: override generated cut (compatOp, no roleTable propagation) with\n // handwritten cut from boolean.ts (does roleTable propagation via booleanBrep).\n cut,\n // Phase 3: override generated split / linearPattern (compatOp, no roleTable\n // propagation) with handwritten versions that build replica[k] / splinter(#j)\n // role tables (L3 / L4 抗重放词汇). Spread after scriptFaceOps so they win.\n split,\n linearPattern,\n // 覆盖生成版:4 个多副本 pattern 提拔手写(keep + replica[*] 角色表);\n // 2 个单副本(mirror/clone)加 keep 薄 override。transformCopy 不再是脚本面\n // op(arg-spec skip:ComposedTransform 在 .fai.js 不可构造),仅保留 TS 库导出。\n // Spread after scriptFaceOps so they win.\n circularPattern,\n gridPattern,\n rectangularPattern,\n mirrorJoin,\n mirror,\n clone,\n } as unknown as LibNamespace\n}\n"]}
1
+ {"version":3,"file":"api-namespace.js","sourceRoot":"","sources":["../../src/api/api-namespace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACjE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACrE,iEAAiE;AACjE,4DAA4D;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,2DAA2D;AAC3D,8DAA8D;AAC9D,iDAAiD;AACjD,2DAA2D;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,8DAA8D;AAC9D,kFAAkF;AAClF,mDAAmD;AACnD,OAAO,EACL,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,GAC5E,MAAM,cAAc,CAAA;AACrB,6DAA6D;AAC7D,gFAAgF;AAChF,oDAAoD;AACpD,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC5E,kEAAkE;AAClE,mFAAmF;AACnF,sFAAsF;AACtF,uEAAuE;AACvE,OAAO,EACL,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EACpD,iBAAiB,EAAE,uBAAuB,EAC1C,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,GACtE,MAAM,gBAAgB,CAAA;AACvB,iEAAiE;AACjE,qFAAqF;AACrF,mDAAmD;AACnD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AACpG,kEAAkE;AAClE,wEAAwE;AACxE,uBAAuB;AACvB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AACjD,gEAAgE;AAChE,6DAA6D;AAC7D,mFAAmF;AACnF,iEAAiE;AACjE,gEAAgE;AAChE,uBAAuB;AACvB,OAAO,EACL,aAAa,EAAE,eAAe,EAAE,OAAO,EAAE,kBAAkB,EAC3D,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAC3D,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EACtD,WAAW,EAAE,WAAW,GACzB,MAAM,iBAAiB,CAAA;AACxB,gEAAgE;AAChE,uDAAuD;AACvD,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAC5D,iEAAiE;AACjE,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACzG,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACrH,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC7E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAGnD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB;IAChC,6EAA6E;IAC7E,0EAA0E;IAC1E,0DAA0D;IAC1D,OAAO;QACL,eAAe,EAAE,gBAAgB;QACjC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK;QAClC,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG;QACzF,wDAAwD;QACxD,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO;QACvC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK;QAC/B,6DAA6D;QAC7D,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc;QACnE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,mBAAmB;QAClF,KAAK,EAAE,QAAQ,EAAE,SAAS;QAC1B,OAAO,EAAE,OAAO;QAChB,8CAA8C;QAC9C,yDAAyD;QACzD,uEAAuE;QACvE,sCAAsC;QACtC,2DAA2D;QAC3D,kDAAkD;QAClD,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY;QACxC,4DAA4D;QAC5D,OAAO;QACP,uEAAuE;QACvE,QAAQ;QACR,gFAAgF;QAChF,cAAc;QACd,mEAAmE;QACnE,2DAA2D;QAC3D,SAAS;QACT,0DAA0D;QAC1D,sDAAsD;QACtD,SAAS;QACT,UAAU;QACV,4DAA4D;QAC5D,UAAU;QACV,SAAS;QACT,4DAA4D;QAC5D,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO;QAC3E,wEAAwE;QACxE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc;QAC5C,kEAAkE;QAClE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU;QACpD,iBAAiB,EAAE,uBAAuB;QAC1C,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe;QACrE,iEAAiE;QACjE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS;QACnE,kEAAkE;QAClE,UAAU,EAAE,IAAI;QAChB,gEAAgE;QAChE,aAAa,EAAE,eAAe,EAAE,OAAO,EAAE,kBAAkB;QAC3D,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB;QAC3D,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU;QACtD,WAAW,EAAE,WAAW;QACxB,yDAAyD;QACzD,0DAA0D;QAC1D,OAAO,EAAE,kBAAkB;QAC3B,OAAO;QACP,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO;QACxC,OAAO;QACP,OAAO;QACP,eAAe,EAAE,iBAAiB,EAAE,YAAY;QAChD,KAAK;QACL,0CAA0C;QAC1C,wDAAwD;QACxD,WAAW;QACX,WAAW;QACX,QAAQ,EAAE,iBAAiB;QAC3B,KAAK;QACL,GAAG,aAAa;QAChB,4EAA4E;QAC5E,gFAAgF;QAChF,GAAG;QACH,4EAA4E;QAC5E,8EAA8E;QAC9E,uEAAuE;QACvE,KAAK;QACL,aAAa;QACb,oDAAoD;QACpD,6DAA6D;QAC7D,iEAAiE;QACjE,0CAA0C;QAC1C,eAAe;QACf,WAAW;QACX,kBAAkB;QAClB,UAAU;QACV,MAAM;QACN,KAAK;KACqB,CAAA;AAC9B,CAAC","sourcesContent":["/**\n * api-namespace — 把 L3 API 面(api/ 层的 fp操作)装配为 cad 命名空间(统一 ABI,B2 消灭)\n *\n *\n * 库函数签名 = .fai.js 源码形态(无隐式参数);本文件无任何 per-函数逻辑。\n *\n * 归属(monorepo P5/E-a-1):本文件随 core 出包,是 faijs 默认库函数\n * (cad 命名空间)的装配点。K5(引擎零函数知识)的准确含义是:parser / compile /\n * runtime 不按函数名分支、不区分函数类别,函数信息统一以 defineOp 元数据(均匀数据)\n * 承载。把 cad 这套库数据内置进引擎,与第三方库走完全相同的 registerLib 路径,\n * 引擎并未对 cad 特判,因此不构成 K5 违反。cad 在 core 的 createRuntime 包装中\n * 被注册为 default 命名空间(见 cad-runtime/runtime.ts 的 createRuntime)。\n *\n * D1(2026-09-23 扩展库拆分):本命名空间只装配**平台面**。编辑器专属 op\n * (`fai_*` / `group` / `assembly` / `copy` / `load`)与两个非基础 three 链的创建 op\n * (`text` / `svgExtrude`)已迁到 `@faicad/faijs-extra`,由宿主经\n * `mergeEditorNamespace()` 合并后注册——键名与拆分前完全一致,存量 `.fai.js` 零迁移。\n * 四个 transform op(translate/rotate_euler/scale/scale3d)按 D1 选项 C 留在此处:\n * `translate` 是通用几何变换,且是小程序端唯一在用的 transform op。\n */\n\nimport { box, sphere, cylinder, cone, wedge } from './primitives'\nimport { translate, rotate_euler, scale, scale3d } from './transform'\n// cad.extrude 是平台手写 op(承载 upTo;长度形态委托 generated/operations 的投影),\n// 见 api/extrude.ts 的分层说明——up-to 不落在 fai_extrude(后者已随扩展库迁出)。\nimport { extrude } from './extrude'\nimport { knurl } from './knurl'\nimport { sdf } from './sdf'\nimport { screw } from './screw'\nimport { profile } from './profile'\nimport { sketchOnPlane } from './sketch-on-plane'\nimport { sketchOnFace } from './sketch-on-face'\nimport { sketchOnSurface } from './sketch-on-surface'\nimport { punchHole } from './punch-hole'\nimport { wire } from './wire'\nimport { helix } from './helix'\nimport { surface } from './surface'\nimport { offset2d } from './offset2d'\nimport { solidFromFaces } from './solid-from-faces'\nimport { halfSpace } from './half-space'\nimport { exportStl } from './export-stl'\nimport { exportBrep } from './export-brep'\n// 2026-10-08(方案 §2.6 / DEC-3):脚本面 step / 3mf 出口。两者都是薄壳:宿主门\n// (引擎通道无门禁——库面按当前引擎分派,见 export-step.ts)之后把入参转成 ExportEntry[],\n// 序列化一律交库面 exportModelSync(单一真源),故与库面逐字节同源。只进脚本面\n// (本字面量 + check() 符号表),**不平铺 api/index.ts**(§2.7 / DEC-6)。\nimport { exportStep } from './export-step'\nimport { export3mf } from './export-3mf'\n// S4(occt-wasm op 接入):类型判定谓词族(平台 op engines:['occt'],普通函数形态)。\n// 直调 occt 原生 isEdge/isFace/isShell/isVertex/isWire/isCompound/isCompSolid/isEqual\n// (不在 L1 契约,方案 §3.4.6 校正注);布尔返回,走 export-brep 同口径。\nimport {\n isEdge, isFace, isShell, isVertex, isWire, isCompound, isCompSolid, isEqual,\n} from './shape-type'\n// S4(occt-wasm op 接入):视图与导出族(平台 op engines:['occt'],普通函数形态)。\n// 直调 occt 原生 toSVG/toMultiviewSVG/toPNG/toMultiviewPNG(不在 L1 契约,方案 §3.4.7 校正注);\n// 字符串/Uint8Array 返回,走 export-brep / shape-type 同口径。\nimport { toSVG, toMultiviewSVG, toPNG, toMultiviewPNG } from './view-export'\n// S4(occt-wasm op 接入):曲线与草图构造族(平台 op engines:['occt'],方案 §3.4.1)。\n// 直调 occt 原生 makeEdge/makeCircleArc/makeEllipseEdge/makeEllipseArc/makeTangentArc/\n// approximatePoints/interpolatePointsWithTangents/curveDegreeElevate/curveKnotInsert/\n// curveKnotRemove/curveIsPeriodic(不在 L1 契约);curveIsPeriodic 布尔返回,普通函数。\nimport {\n edge, circleArc, ellipseEdge, ellipseArc, tangentArc,\n approximatePoints, interpolateWithTangents,\n curveDegreeElevate, curveKnotInsert, curveKnotRemove, curveIsPeriodic,\n} from './curve-sketch'\n// S4(occt-wasm op 接入):曲面与面构造族(平台 op engines:['occt'],方案 §3.4.2)。\n// 直调 occt 原生 makeFaceOnSurface/makeNonPlanarFace/makeSolid/reverseSurfaceU/outerWire\n// (不在 L1 契约;bsplineSurface 已由 S3 的 surface op 覆盖)。\nimport { faceOnSurface, nonPlanarFace, makeSolid, reverseSurfaceU, outerWire } from './surface-face'\n// S4(occt-wasm op 接入):实体与偏置族剩余(平台 op engines:['occt'],方案 §3.4.4)。\n// 直调 occt 原生 draftPrism/pipe(不在 L1 契约;offsetWire2D/buildSolidFromFaces/\n// halfSpace 已由 S3 落地)。\nimport { draftPrism, pipe } from './solid-offset'\n// S4(occt-wasm op 接入):测量与查询族(平台 op engines:['occt'],方案 §3.4.6)。\n// 13 个原生方法不在 L1 契约:containsPoint/distanceBetween/getInertia/\n// getLinearCenterOfMass/projectPointOnEdge/projectPointOnFace/classifyPointOnFace/\n// uvFromPoint/vertexPosition/subShapeCount/iterShapes 返回非 Shape,\n// 走 export-brep / shape-type 同口径的普通函数;liftCurve2d / commonCells\n// 返回 Shape,走 defineOp。\nimport {\n containsPoint, distanceBetween, inertia, linearCenterOfMass,\n projectPointOnEdge, projectPointOnFace, classifyPointOnFace,\n uvFromPoint, vertexPosition, subShapeCount, iterShapes,\n liftCurve2d, commonCells,\n} from './measure-query'\n// S4(occt-wasm op 接入):通用布尔族(平台 op engines:['occt'],方案 §3.4.5)——\n// 原生 booleanOp:带 glue/fuzzy/simplify 选项的通用形态,不在 L1 契约。\nimport { boolean as booleanWithOptions } from './boolean-op'\n// S4(occt-wasm op 接入):包围盒对齐族(平台 op engines:['occt'],方案 §3.4.9)——\n// 原生 alignX/alignY/alignZ 三轴并为一个脚本符号 alignTo。\nimport { alignTo } from './align'\nimport { union, subtract, intersect, cut } from './boolean'\nimport { split } from './split'\nimport { sweep } from './sweep'\nimport { sweepAdvanced } from './sweep-advanced'\nimport { loft } from './loft'\nimport { loftAdvanced } from './loft-advanced'\nimport { linearPattern } from './pattern'\nimport { circularPattern, gridPattern, rectangularPattern, mirrorJoin, mirror, clone } from './replicate'\nimport { engrave } from './engrave'\nimport { chamfer } from './chamfer'\nimport { fillet } from './fillet'\nimport { shell } from './shell'\nimport { draft } from './draft'\nimport { thicken } from './thicken'\nimport { defeature, reverseShape, unifySameDomain, sew, sewAndSolidify, removeHolesFromFace } from './feature-repair'\nimport { filletVariable } from './fillet-variable'\nimport { splitByPlane } from './split-by-plane'\nimport { sectionByPlane } from './section-by-plane'\nimport { faceNormal, bboxCenter, bboxMin, bboxMax } from './geom'\nimport { edgeRef } from './edge-ref'\nimport { faceRef } from './face-ref'\nimport { jointTrajectory, inverseKinematics, mechanismDOF } from './assembly'\nimport { asset } from './asset'\nimport { import_brep } from './import-brep'\nimport { import_step } from './import-step'\nimport { compound as geometricCompound } from './compound-geom'\nimport { place } from './place'\nimport { scriptFaceOps } from './generated/script-face'\nimport { revolve } from './revolve'\nimport { CONTRACT_VERSION } from '../runtime-state'\nimport type { LibNamespace } from '../runtime-state'\n\n/**\n * Assemble api functions into the cad namespace.\n *\n * P23(§4.2 ②,B1):cad 面 = faijs 特有 dual op(下方字面量)+\n * 生成脚本面 op(`scriptFaceOps`——`api/generated/script-face.ts` 按 arg-spec\n * 的 `scriptFace: true` 条目生成,`defineOp({ brep: __own_* })` 直连的\n * brep-only 语句级 op)。`check()` 符号表(`gen-symbol-table.ts`)取自同一份清单。\n * 2026-10-08(§2.7 / DEC-6、DEC-7):本命名空间**不再**要求被 `api/index.ts`\n * 平铺——库面只保留有库作者消费者的名字,其余脚本 op 只走 `cad.*` 与子路径。\n *\n * @returns the assembled LibNamespace ready for runtime injection.\n */\nexport function createApiNamespace(): LibNamespace {\n // D-4 strict assembly check: the cad namespace now exports dual-op functions\n // (defineOp), so registerLib requires a matching contractVersion. Cast is\n // needed because LibNamespace is an index-signature type.\n return {\n contractVersion: CONTRACT_VERSION,\n box, sphere, cylinder, cone, wedge,\n screw, profile, sketchOnPlane, sketchOnFace, sketchOnSurface, punchHole, wire, helix, sdf,\n // D1 选项 C:四个 transform op 全留核心(translate 小程序端在用,同族不拆散)。\n translate, rotate_euler, scale, scale3d,\n engrave, chamfer, fillet, knurl,\n // Phase 5:按面/边选的特征族 + 修复薄包装(shell/draft 中立;thicken 平台 occt)。\n shell, draft, thicken, filletVariable, splitByPlane, sectionByPlane,\n defeature, reverseShape, unifySameDomain, sew, sewAndSolidify, removeHolesFromFace,\n union, subtract, intersect,\n extrude, revolve,\n // Phase 4:手写扫掠 / 放样。**基础 op 两内核都支持**(进 L1 中立名\n // BrepEngineApi#sweep / #loft);只有 occt 能做的完整控制面拆成独立平台 op\n // (engines:['occt']):sweepAdvanced(transition/auxSpine/support/law/…)、\n // loftAdvanced(startPoint/tolerance)。\n // arg-spec 里 sweep 保留 brep-op(引擎记录)/ loft 为 skip,两者均不投脚本面,\n // 所以这里不是 override 而是唯一实现(同 extrude / revolve 口径)。\n sweep, sweepAdvanced, loft, loftAdvanced,\n // S3(occt-wasm op 接入):控制点阵 → B 样条面(平台 op engines:['occt'])。\n surface,\n // S3(occt-wasm op 接入):2D 轮廓偏置(平台 op engines:['occt'],原生 offsetWire2D)。\n offset2d,\n // S3(occt-wasm op 接入):面集一次成型为实体(平台 op engines:['occt'],原生 buildSolidFromFaces)。\n solidFromFaces,\n // S3(occt-wasm op 接入):无限半空间实体(平台 op engines:['occt'],原生 halfSpace;\n // 无界布尔工具的来源,产物 mesh 为空——单独渲染无意义,只作 cut/common/split 的工具位)。\n halfSpace,\n // S3(occt-wasm op 接入):导出族。exportStl 中立(只序列化 Shape 自带三角载荷,\n // 无内核调用);exportBrep 平台(原生 toBREP,L1 只有 fromBREP 导入侧)。\n exportStl,\n exportBrep,\n // 方案 §2.6:step(occt 必需——装配层级走 XCAF)/ 3mf(引擎中立,纯 XML + ZIP)。\n exportStep,\n export3mf,\n // S4(occt-wasm op 接入):类型判定谓词族(平台 op engines:['occt'],布尔返回)。\n isEdge, isFace, isShell, isVertex, isWire, isCompound, isCompSolid, isEqual,\n // S4(occt-wasm op 接入):视图与导出族(平台 op engines:['occt'],字符串/Uint8Array 返回)。\n toSVG, toMultiviewSVG, toPNG, toMultiviewPNG,\n // S4(occt-wasm op 接入):曲线与草图构造族(平台 op engines:['occt'],方案 §3.4.1)。\n edge, circleArc, ellipseEdge, ellipseArc, tangentArc,\n approximatePoints, interpolateWithTangents,\n curveDegreeElevate, curveKnotInsert, curveKnotRemove, curveIsPeriodic,\n // S4(occt-wasm op 接入):曲面与面构造族(平台 op engines:['occt'],方案 §3.4.2)。\n faceOnSurface, nonPlanarFace, makeSolid, reverseSurfaceU, outerWire,\n // S4(occt-wasm op 接入):实体与偏置族剩余(平台 op engines:['occt'],方案 §3.4.4)。\n draftPrism, pipe,\n // S4(occt-wasm op 接入):测量与查询族(平台 op engines:['occt'],方案 §3.4.6)。\n containsPoint, distanceBetween, inertia, linearCenterOfMass,\n projectPointOnEdge, projectPointOnFace, classifyPointOnFace,\n uvFromPoint, vertexPosition, subShapeCount, iterShapes,\n liftCurve2d, commonCells,\n // S4(occt-wasm op 接入):通用布尔族 booleanOp(方案 §3.4.5)+ 包围盒对齐族\n // alignX/Y/Z → alignTo(方案 §3.4.9),平台 op engines:['occt']。\n boolean: booleanWithOptions,\n alignTo,\n faceNormal, bboxCenter, bboxMin, bboxMax,\n edgeRef,\n faceRef,\n jointTrajectory, inverseKinematics, mechanismDOF,\n asset,\n // 平台几何 op(H11,方案 §4):FCStd 迁移自此不再借用编辑器 op\n // (group/translate/rotate_euler);这几个与 ../3d_editor 无关系。\n import_brep,\n import_step,\n compound: geometricCompound,\n place,\n ...scriptFaceOps,\n // Phase 3: override generated cut (compatOp, no roleTable propagation) with\n // handwritten cut from boolean.ts (does roleTable propagation via booleanBrep).\n cut,\n // Phase 3: override generated split / linearPattern (compatOp, no roleTable\n // propagation) with handwritten versions that build replica[k] / splinter(#j)\n // role tables (L3 / L4 抗重放词汇). Spread after scriptFaceOps so they win.\n split,\n linearPattern,\n // 覆盖生成版:4 个多副本 pattern 提拔手写(keep + replica[*] 角色表);\n // 2 个单副本(mirror/clone)加 keep 薄 override。transformCopy 不再是脚本面\n // op(arg-spec skip:ComposedTransform 在 .fai.js 不可构造),仅保留 TS 库导出。\n // Spread after scriptFaceOps so they win.\n circularPattern,\n gridPattern,\n rectangularPattern,\n mirrorJoin,\n mirror,\n clone,\n } as unknown as LibNamespace\n}\n"]}
@@ -11,6 +11,7 @@ export * from './entities.js';
11
11
  export * from './lower.js';
12
12
  export * from './pose.js';
13
13
  export * from './solve.js';
14
+ export * from './solve-tree.js';
14
15
  export * from './preview.js';
15
16
  export * from './joints.js';
16
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/assembly/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/assembly/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA"}
@@ -11,6 +11,7 @@ export * from './entities.js';
11
11
  export * from './lower.js';
12
12
  export * from './pose.js';
13
13
  export * from './solve.js';
14
+ export * from './solve-tree.js';
14
15
  export * from './preview.js';
15
16
  export * from './joints.js';
16
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/assembly/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA","sourcesContent":["/**\n * api/assembly — 装配约束求解层(P1)\n *\n * 分层(方案 §4.1):normalize(规范化 + face_mate 兼容)→ lower(直译降级,\n * mate/align 寄生在 concentric 上)→ entities(TopoRef → SolverEntity,双链路)\n * → solve(core 自持 solveConstraints)→ pose(位姿转换契约)。\n */\n\nexport * from './types'\nexport * from './normalize'\nexport * from './entities'\nexport * from './lower'\nexport * from './pose'\nexport * from './solve'\nexport * from './preview'\nexport * from './joints'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/assembly/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA","sourcesContent":["/**\n * api/assembly — 装配约束求解层(P1)\n *\n * 分层(方案 §4.1):normalize(规范化 + face_mate 兼容)→ lower(直译降级,\n * mate/align 寄生在 concentric 上)→ entities(TopoRef → SolverEntity,双链路)\n * → solve(core 自持 solveConstraints)→ pose(位姿转换契约)。\n */\n\nexport * from './types'\nexport * from './normalize'\nexport * from './entities'\nexport * from './lower'\nexport * from './pose'\nexport * from './solve'\nexport * from './solve-tree'\nexport * from './preview'\nexport * from './joints'\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"lower.d.ts","sourceRoot":"","sources":["../../../src/api/assembly/lower.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAa,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAC5E,OAAO,EAAiD,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAEpG;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,oBAAoB,EAAE,IAAI,EAAE,OAAO,GAAG,YAAY,CAOjF;AAED,gFAAgF;AAChF,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,gBAAgB,CAAA;IAC5B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,YAAY,CAAA;CACzB;AAUD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,EAC3E,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,EACzC,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,EACzC,KAAK,CAAC,EAAE,MAAM,GACb,iBAAiB,CA+CnB;AAeD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,oBAAoB,EAAE,GAAG,EAAE,mBAAmB,GAAG,iBAAiB,CAmC9G"}
1
+ {"version":3,"file":"lower.d.ts","sourceRoot":"","sources":["../../../src/api/assembly/lower.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAa,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAC5E,OAAO,EAAiD,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAEpG;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,oBAAoB,EAAE,IAAI,EAAE,OAAO,GAAG,YAAY,CAOjF;AAED,gFAAgF;AAChF,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,gBAAgB,CAAA;IAC5B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,YAAY,CAAA;CACzB;AAUD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,EAC3E,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,EACzC,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,EACzC,KAAK,CAAC,EAAE,MAAM,GACb,iBAAiB,CA+CnB;AAeD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,oBAAoB,EAAE,GAAG,EAAE,mBAAmB,GAAG,iBAAiB,CA4C9G"}
@@ -140,6 +140,13 @@ export function lowerStructuralConstraint(c, env) {
140
140
  case 'distance':
141
141
  case 'angle':
142
142
  return lowerPair(c, env);
143
+ case 'fixedPoint':
144
+ case 'fixedAxis':
145
+ case 'fixedRotation':
146
+ // 世界锚定 unary 无 brepjs chain 等效(chain 无「子实体 ↔ 世界字面系」概念)。
147
+ // 主路径是 solver:'global'(global-solver 原生处理这三类);chain 上明确报错,
148
+ // 绝不静默降级为错误的定位语义。
149
+ throw new Error(`[assembly:lower] ${c.type} is only supported by the 'global' solver; set { solver: 'global' }`);
143
150
  }
144
151
  }
145
152
  //# sourceMappingURL=lower.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lower.js","sourceRoot":"","sources":["../../../src/api/assembly/lower.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api/assembly/lower — faijs 约束 → brepjs SolverConstraint 降级(P1,方案 §3.7.2 / §4.2)\n *\n * 关键简化(方案 §3.7.3):不自写合成器、不自写拓扑调度——\n * - mate → concentric + dep 侧 axis 编码取反法向(flip 是贴合语义的正解:\n * A 的外法向 = B 的内法向);\n * - align → concentric + 两侧 axis 编码不取反;\n * - coincident/concentric/distance/angle → 直译;\n * - parallel/perpendicular → angle 0°/90° 语法糖。\n *\n * 禁止把复合语义拆成多条 SolverConstraint——每节点只被定位一次(方案 §3.7.1)。\n */\n\nimport type { SolverConstraint, SolverEntity } from './solvers/types'\nimport type { ResolvedFaceGeometry } from '../topo-resolve'\nimport type { AssemblyVec3, EntityRef, StructuralConstraint } from './types'\nimport { resolveFaceGeometryOfRef, resolveSolverEntity, type EntityResolutionEnv } from './entities'\n\n/**\n * 面 → 有向轴实体(§3.7.2 轴编码)。flip=true 取内法向(贴合语义)。\n * origin = 面中心:dep 侧是本地坐标,ref 侧由 brepjs transformEntity 转世界。\n *\n * @param f - the resolved face geometry (center + normal).\n * @param flip - when true, negate the normal (mate encoding on the dependent side).\n * @returns the directed axis entity.\n */\nexport function axisFromFace(f: ResolvedFaceGeometry, flip: boolean): SolverEntity {\n const n = f.normal\n return {\n type: 'axis',\n origin: f.center,\n direction: flip ? ([-n[0], -n[1], -n[2]] as AssemblyVec3) : n,\n }\n}\n\n/** 降级产物:SolverConstraint + dependent 实体 origin(作 AssemblyTransform 的 pivot)。 */\nexport interface LoweredConstraint {\n constraint: SolverConstraint\n /** dependent 侧实体 origin(本地坐标);fixed 约束无。 */\n depOrigin?: AssemblyVec3\n}\n\n/** 直译定位约束的形状(a/b 必有,value 可选)。 */\ninterface PairSpec {\n type: 'coincident' | 'concentric' | 'distance' | 'angle'\n value?: number\n a: EntityRef\n b: EntityRef\n}\n\n/**\n * 纯实体降级(P2-f3):两侧 SolverEntity 已知(预览路径 / 宿主已持有几何)。\n * 与 lowerStructuralConstraint 共用 axisFromFace 的编码规则,不另写数学。\n *\n * mate/align 要求两侧都是 `plane` 实体(贴合语义只接受平面)——把 plane 还原成\n * {center, normal} 再走 axisFromFace 编码;与执行路径(lowerStructuralConstraint\n * 的 mate/align 分支)逐位一致。非 plane 输入直接抛错(绝不静默)。\n *\n * @param type - the constraint type(parallel/perpendicular 请显式用 angle 0/90)。\n * @param a - the reference-side entity (node + solver entity).\n * @param b - the dependent-side entity (node + solver entity).\n * @param value - distance/angle 用(其它类型忽略)。\n * @returns the lowered solver constraint with the dependent origin.\n */\nexport function lowerEntities(\n type: 'mate' | 'align' | 'coincident' | 'concentric' | 'distance' | 'angle',\n a: { node: string; entity: SolverEntity },\n b: { node: string; entity: SolverEntity },\n value?: number,\n): LoweredConstraint {\n switch (type) {\n case 'mate':\n case 'align': {\n const kindA = a.entity.type\n const kindB = b.entity.type\n if (kindA !== 'plane' || kindB !== 'plane') {\n throw new Error(\n `[assembly:lower] ${type} requires plane entities on both sides, got ${kindA}/${kindB}`,\n )\n }\n // SolverEntity.origin/normal 是 readonly Vec3;拷贝成可变 AssemblyVec3 再传给\n // axisFromFace(避免类型断言覆盖 readonly→mutable 的契约警告)。\n // SolverEntity 是扁平 interface(type 联合非 tagged union),kind 检查后字段必然存在。\n const normalA = a.entity.normal as readonly [number, number, number]\n const normalB = b.entity.normal as readonly [number, number, number]\n const pa = { origin: [...a.entity.origin] as AssemblyVec3, normal: [...normalA] as AssemblyVec3 }\n const pb = { origin: [...b.entity.origin] as AssemblyVec3, normal: [...normalB] as AssemblyVec3 }\n const flip = type === 'mate'\n return {\n constraint: {\n type: 'concentric',\n entityA: { node: a.node, entity: axisFromFace({ center: pa.origin, normal: pa.normal }, false) },\n entityB: { node: b.node, entity: axisFromFace({ center: pb.origin, normal: pb.normal }, flip) },\n },\n depOrigin: pb.origin,\n }\n }\n case 'coincident':\n case 'concentric':\n case 'distance':\n case 'angle': {\n const constraint: SolverConstraint = {\n type,\n entityA: { node: a.node, entity: a.entity },\n entityB: { node: b.node, entity: b.entity },\n }\n if (value !== undefined) constraint.value = value\n return { constraint, depOrigin: [b.entity.origin[0], b.entity.origin[1], b.entity.origin[2]] }\n }\n default:\n // TS 穷尽分支防御:JS 调用方可能传越界字符串(fixed/parallel/perpendicular/其他)\n throw new Error(\n `[assembly:lower] unsupported constraint type for lowerEntities: ${String(type)} ` +\n `(fixed has no displacement semantics; parallel/perpendicular use 'angle' 0/90)`,\n )\n }\n}\n\n/** 直译定位约束:解析两侧实体后原样翻译。 */\nfunction lowerPair(c: PairSpec, env: EntityResolutionEnv): LoweredConstraint {\n const entityA = resolveSolverEntity(c.a, env)\n const entityB = resolveSolverEntity(c.b, env)\n const constraint: SolverConstraint = {\n type: c.type,\n entityA: { node: c.a.part, entity: entityA },\n entityB: { node: c.b.part, entity: entityB },\n }\n if (c.value !== undefined) constraint.value = c.value\n return { constraint, depOrigin: [entityB.origin[0], entityB.origin[1], entityB.origin[2]] }\n}\n\n/**\n * 把一条规范化约束降级为 brepjs SolverConstraint(§4.2 步骤 3)。\n *\n * @param c - the normalized structural constraint.\n * @param env - the entity resolution environment (kernel + member lookup).\n * @returns the lowered solver constraint with the dependent origin.\n */\nexport function lowerStructuralConstraint(c: StructuralConstraint, env: EntityResolutionEnv): LoweredConstraint {\n switch (c.type) {\n case 'mate':\n case 'align': {\n // 贴合/对齐:两侧都必须是面引用;轴编码进 concentric(§3.7.2)\n const geomA = resolveFaceGeometryOfRef(c.a, env)\n const geomB = resolveFaceGeometryOfRef(c.b, env)\n const flip = c.type === 'mate'\n return {\n constraint: {\n type: 'concentric',\n entityA: { node: c.a.part, entity: axisFromFace(geomA, false) },\n entityB: { node: c.b.part, entity: axisFromFace(geomB, flip) },\n },\n depOrigin: geomB.center,\n }\n }\n case 'parallel':\n return lowerPair({ type: 'angle', value: 0, a: c.a, b: c.b }, env)\n case 'perpendicular':\n return lowerPair({ type: 'angle', value: 90, a: c.a, b: c.b }, env)\n case 'fixed':\n // solver 对 fixed 只读 entityA.node;entity 占位满足 SolverConstraint 形状\n return {\n constraint: {\n type: 'fixed',\n entityA: { node: c.part, entity: { type: 'point', origin: [0, 0, 0] } },\n },\n }\n case 'coincident':\n case 'concentric':\n case 'distance':\n case 'angle':\n return lowerPair(c, env)\n }\n}\n"]}
1
+ {"version":3,"file":"lower.js","sourceRoot":"","sources":["../../../src/api/assembly/lower.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api/assembly/lower — faijs 约束 → brepjs SolverConstraint 降级(P1,方案 §3.7.2 / §4.2)\n *\n * 关键简化(方案 §3.7.3):不自写合成器、不自写拓扑调度——\n * - mate → concentric + dep 侧 axis 编码取反法向(flip 是贴合语义的正解:\n * A 的外法向 = B 的内法向);\n * - align → concentric + 两侧 axis 编码不取反;\n * - coincident/concentric/distance/angle → 直译;\n * - parallel/perpendicular → angle 0°/90° 语法糖。\n *\n * 禁止把复合语义拆成多条 SolverConstraint——每节点只被定位一次(方案 §3.7.1)。\n */\n\nimport type { SolverConstraint, SolverEntity } from './solvers/types'\nimport type { ResolvedFaceGeometry } from '../topo-resolve'\nimport type { AssemblyVec3, EntityRef, StructuralConstraint } from './types'\nimport { resolveFaceGeometryOfRef, resolveSolverEntity, type EntityResolutionEnv } from './entities'\n\n/**\n * 面 → 有向轴实体(§3.7.2 轴编码)。flip=true 取内法向(贴合语义)。\n * origin = 面中心:dep 侧是本地坐标,ref 侧由 brepjs transformEntity 转世界。\n *\n * @param f - the resolved face geometry (center + normal).\n * @param flip - when true, negate the normal (mate encoding on the dependent side).\n * @returns the directed axis entity.\n */\nexport function axisFromFace(f: ResolvedFaceGeometry, flip: boolean): SolverEntity {\n const n = f.normal\n return {\n type: 'axis',\n origin: f.center,\n direction: flip ? ([-n[0], -n[1], -n[2]] as AssemblyVec3) : n,\n }\n}\n\n/** 降级产物:SolverConstraint + dependent 实体 origin(作 AssemblyTransform 的 pivot)。 */\nexport interface LoweredConstraint {\n constraint: SolverConstraint\n /** dependent 侧实体 origin(本地坐标);fixed 约束无。 */\n depOrigin?: AssemblyVec3\n}\n\n/** 直译定位约束的形状(a/b 必有,value 可选)。 */\ninterface PairSpec {\n type: 'coincident' | 'concentric' | 'distance' | 'angle'\n value?: number\n a: EntityRef\n b: EntityRef\n}\n\n/**\n * 纯实体降级(P2-f3):两侧 SolverEntity 已知(预览路径 / 宿主已持有几何)。\n * 与 lowerStructuralConstraint 共用 axisFromFace 的编码规则,不另写数学。\n *\n * mate/align 要求两侧都是 `plane` 实体(贴合语义只接受平面)——把 plane 还原成\n * {center, normal} 再走 axisFromFace 编码;与执行路径(lowerStructuralConstraint\n * 的 mate/align 分支)逐位一致。非 plane 输入直接抛错(绝不静默)。\n *\n * @param type - the constraint type(parallel/perpendicular 请显式用 angle 0/90)。\n * @param a - the reference-side entity (node + solver entity).\n * @param b - the dependent-side entity (node + solver entity).\n * @param value - distance/angle 用(其它类型忽略)。\n * @returns the lowered solver constraint with the dependent origin.\n */\nexport function lowerEntities(\n type: 'mate' | 'align' | 'coincident' | 'concentric' | 'distance' | 'angle',\n a: { node: string; entity: SolverEntity },\n b: { node: string; entity: SolverEntity },\n value?: number,\n): LoweredConstraint {\n switch (type) {\n case 'mate':\n case 'align': {\n const kindA = a.entity.type\n const kindB = b.entity.type\n if (kindA !== 'plane' || kindB !== 'plane') {\n throw new Error(\n `[assembly:lower] ${type} requires plane entities on both sides, got ${kindA}/${kindB}`,\n )\n }\n // SolverEntity.origin/normal 是 readonly Vec3;拷贝成可变 AssemblyVec3 再传给\n // axisFromFace(避免类型断言覆盖 readonly→mutable 的契约警告)。\n // SolverEntity 是扁平 interface(type 联合非 tagged union),kind 检查后字段必然存在。\n const normalA = a.entity.normal as readonly [number, number, number]\n const normalB = b.entity.normal as readonly [number, number, number]\n const pa = { origin: [...a.entity.origin] as AssemblyVec3, normal: [...normalA] as AssemblyVec3 }\n const pb = { origin: [...b.entity.origin] as AssemblyVec3, normal: [...normalB] as AssemblyVec3 }\n const flip = type === 'mate'\n return {\n constraint: {\n type: 'concentric',\n entityA: { node: a.node, entity: axisFromFace({ center: pa.origin, normal: pa.normal }, false) },\n entityB: { node: b.node, entity: axisFromFace({ center: pb.origin, normal: pb.normal }, flip) },\n },\n depOrigin: pb.origin,\n }\n }\n case 'coincident':\n case 'concentric':\n case 'distance':\n case 'angle': {\n const constraint: SolverConstraint = {\n type,\n entityA: { node: a.node, entity: a.entity },\n entityB: { node: b.node, entity: b.entity },\n }\n if (value !== undefined) constraint.value = value\n return { constraint, depOrigin: [b.entity.origin[0], b.entity.origin[1], b.entity.origin[2]] }\n }\n default:\n // TS 穷尽分支防御:JS 调用方可能传越界字符串(fixed/parallel/perpendicular/其他)\n throw new Error(\n `[assembly:lower] unsupported constraint type for lowerEntities: ${String(type)} ` +\n `(fixed has no displacement semantics; parallel/perpendicular use 'angle' 0/90)`,\n )\n }\n}\n\n/** 直译定位约束:解析两侧实体后原样翻译。 */\nfunction lowerPair(c: PairSpec, env: EntityResolutionEnv): LoweredConstraint {\n const entityA = resolveSolverEntity(c.a, env)\n const entityB = resolveSolverEntity(c.b, env)\n const constraint: SolverConstraint = {\n type: c.type,\n entityA: { node: c.a.part, entity: entityA },\n entityB: { node: c.b.part, entity: entityB },\n }\n if (c.value !== undefined) constraint.value = c.value\n return { constraint, depOrigin: [entityB.origin[0], entityB.origin[1], entityB.origin[2]] }\n}\n\n/**\n * 把一条规范化约束降级为 brepjs SolverConstraint(§4.2 步骤 3)。\n *\n * @param c - the normalized structural constraint.\n * @param env - the entity resolution environment (kernel + member lookup).\n * @returns the lowered solver constraint with the dependent origin.\n */\nexport function lowerStructuralConstraint(c: StructuralConstraint, env: EntityResolutionEnv): LoweredConstraint {\n switch (c.type) {\n case 'mate':\n case 'align': {\n // 贴合/对齐:两侧都必须是面引用;轴编码进 concentric(§3.7.2)\n const geomA = resolveFaceGeometryOfRef(c.a, env)\n const geomB = resolveFaceGeometryOfRef(c.b, env)\n const flip = c.type === 'mate'\n return {\n constraint: {\n type: 'concentric',\n entityA: { node: c.a.part, entity: axisFromFace(geomA, false) },\n entityB: { node: c.b.part, entity: axisFromFace(geomB, flip) },\n },\n depOrigin: geomB.center,\n }\n }\n case 'parallel':\n return lowerPair({ type: 'angle', value: 0, a: c.a, b: c.b }, env)\n case 'perpendicular':\n return lowerPair({ type: 'angle', value: 90, a: c.a, b: c.b }, env)\n case 'fixed':\n // solver 对 fixed 只读 entityA.node;entity 占位满足 SolverConstraint 形状\n return {\n constraint: {\n type: 'fixed',\n entityA: { node: c.part, entity: { type: 'point', origin: [0, 0, 0] } },\n },\n }\n case 'coincident':\n case 'concentric':\n case 'distance':\n case 'angle':\n return lowerPair(c, env)\n case 'fixedPoint':\n case 'fixedAxis':\n case 'fixedRotation':\n // 世界锚定 unary 无 brepjs chain 等效(chain 无「子实体 ↔ 世界字面系」概念)。\n // 主路径是 solver:'global'(global-solver 原生处理这三类);chain 上明确报错,\n // 绝不静默降级为错误的定位语义。\n throw new Error(\n `[assembly:lower] ${c.type} is only supported by the 'global' solver; set { solver: 'global' }`,\n )\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/api/assembly/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEvE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,kBAAkB,GAAG,oBAAoB,CAgB/E"}
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/api/assembly/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEvE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,kBAAkB,GAAG,oBAAoB,CAiB/E"}
@@ -24,7 +24,8 @@ export function normalizeConstraint(c) {
24
24
  }
25
25
  if (c.type === 'mate' || c.type === 'align' || c.type === 'coincident' ||
26
26
  c.type === 'concentric' || c.type === 'distance' || c.type === 'angle' ||
27
- c.type === 'parallel' || c.type === 'perpendicular' || c.type === 'fixed') {
27
+ c.type === 'parallel' || c.type === 'perpendicular' || c.type === 'fixed' ||
28
+ c.type === 'fixedPoint' || c.type === 'fixedAxis' || c.type === 'fixedRotation') {
28
29
  return c;
29
30
  }
30
31
  throw new Error(`[assembly] unknown constraint type: ${c.type}`);
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../../src/api/assembly/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,CAAqB;IACvD,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC3B,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE;YAC/C,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU,EAAE;SAClD,CAAA;IACH,CAAC;IACD,IACE,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY;QAClE,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;QACtE,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EACzE,CAAC;QACD,OAAO,CAAC,CAAA;IACV,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uCAAwC,CAAwB,CAAC,IAAI,EAAE,CAAC,CAAA;AAC1F,CAAC","sourcesContent":["/**\n * api/assembly/normalize — 约束规范化(P1,方案 §4.1 / §5.3)\n *\n * 唯一职责:把 `cad.assembly({ constraints })` 的各种输入形态归一为\n * {@link StructuralConstraint}:\n * - 遗留 `face_mate` → `mate`(字段重排:fixedPartName/fixedFace → a,movingPartName/movingFace → b);\n * - 新形态直通(引用同一对象,不拷贝)。\n *\n * 未知类型在此抛错(fail-fast),不在求解深处静默跳过。\n */\n\nimport type { AssemblyConstraint, StructuralConstraint } from './types'\n\n/**\n * Normalize one assembly constraint to the structural form.\n * @param c - the raw constraint from script args.\n * @returns the normalized structural constraint.\n * @throws Error when the constraint type is unknown.\n */\nexport function normalizeConstraint(c: AssemblyConstraint): StructuralConstraint {\n if (c.type === 'face_mate') {\n return {\n type: 'mate',\n a: { part: c.fixedPartName, face: c.fixedFace },\n b: { part: c.movingPartName, face: c.movingFace },\n }\n }\n if (\n c.type === 'mate' || c.type === 'align' || c.type === 'coincident' ||\n c.type === 'concentric' || c.type === 'distance' || c.type === 'angle' ||\n c.type === 'parallel' || c.type === 'perpendicular' || c.type === 'fixed'\n ) {\n return c\n }\n throw new Error(`[assembly] unknown constraint type: ${(c as { type?: unknown }).type}`)\n}\n"]}
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../../src/api/assembly/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,CAAqB;IACvD,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC3B,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE;YAC/C,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU,EAAE;SAClD,CAAA;IACH,CAAC;IACD,IACE,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY;QAClE,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;QACtE,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;QACzE,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe,EAC/E,CAAC;QACD,OAAO,CAAC,CAAA;IACV,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uCAAwC,CAAwB,CAAC,IAAI,EAAE,CAAC,CAAA;AAC1F,CAAC","sourcesContent":["/**\n * api/assembly/normalize — 约束规范化(P1,方案 §4.1 / §5.3)\n *\n * 唯一职责:把 `cad.assembly({ constraints })` 的各种输入形态归一为\n * {@link StructuralConstraint}:\n * - 遗留 `face_mate` → `mate`(字段重排:fixedPartName/fixedFace → a,movingPartName/movingFace → b);\n * - 新形态直通(引用同一对象,不拷贝)。\n *\n * 未知类型在此抛错(fail-fast),不在求解深处静默跳过。\n */\n\nimport type { AssemblyConstraint, StructuralConstraint } from './types'\n\n/**\n * Normalize one assembly constraint to the structural form.\n * @param c - the raw constraint from script args.\n * @returns the normalized structural constraint.\n * @throws Error when the constraint type is unknown.\n */\nexport function normalizeConstraint(c: AssemblyConstraint): StructuralConstraint {\n if (c.type === 'face_mate') {\n return {\n type: 'mate',\n a: { part: c.fixedPartName, face: c.fixedFace },\n b: { part: c.movingPartName, face: c.movingFace },\n }\n }\n if (\n c.type === 'mate' || c.type === 'align' || c.type === 'coincident' ||\n c.type === 'concentric' || c.type === 'distance' || c.type === 'angle' ||\n c.type === 'parallel' || c.type === 'perpendicular' || c.type === 'fixed' ||\n c.type === 'fixedPoint' || c.type === 'fixedAxis' || c.type === 'fixedRotation'\n ) {\n return c\n }\n throw new Error(`[assembly] unknown constraint type: ${(c as { type?: unknown }).type}`)\n}\n"]}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * api/assembly/solve-tree — 嵌套子装配求解(P4,方案 §4.2)
3
+ *
4
+ * flatten → solveGlobal → recompose:
5
+ * 1. flatten:walkAssembly 收集叶 shape + qualified member name(如 `subassy.part`),
6
+ * 构建扁平 members/memberNames;约束从各层收集(part 名用 qualified name,可跨层引用)。
7
+ * 2. solve:调 solveGlobal 求解扁平问题。
8
+ * 3. recompose:自顶向下将父变换(AssemblyNode.translate/rotate)与 solver 变换复合
9
+ * (parentTransform ∘ childLocalTransform),得到每个叶节点的世界变换。
10
+ *
11
+ * 语义对齐 CQ `Assembly.solve()`:每个对象的 `loc` 累积合成世界变换。
12
+ * faijs Shape 不携带 placement → 求解器从 identity 初值求解;父变换在 recompose 阶段复合。
13
+ */
14
+ import type { AssemblyTransform } from '../../runtime-state.js';
15
+ import type { SolveOptions } from './solvers/types.js';
16
+ import type { AssemblyNode } from './solvers/assembly-tree.js';
17
+ /** 嵌套子装配求解结果:per-leaf 世界变换 + 诊断量。 */
18
+ export interface AssemblyTreeSolveResult {
19
+ /** 每个叶节点的世界变换(键 = qualified name)。 */
20
+ transforms: Record<string, AssemblyTransform>;
21
+ /** 是否全部约束可解。 */
22
+ converged: boolean;
23
+ /** 无法求解的约束明细。 */
24
+ unsupported: string[];
25
+ /** 逐约束最终残差。 */
26
+ residuals: number[];
27
+ /** 残差超阈值的约束逐条写入。 */
28
+ warnings?: string[];
29
+ /**
30
+ * P7/D1-3:欠定自由度诊断(透传自 solveGlobal)。dof > 0 = 约束集欠定,
31
+ * 终态位姿依赖优化器轨迹、无唯一「正确解」——判等方应走规范判等通道而非逐位比对。
32
+ */
33
+ underdetermined?: {
34
+ dof: number;
35
+ };
36
+ }
37
+ /**
38
+ * 求解嵌套子装配树:flatten → solveGlobal → recompose。
39
+ *
40
+ * @param root - 装配树根节点(root 的 shape 被忽略,仅作容器)。
41
+ * @param opts - 求解选项(透传给 solveGlobal;默认 solver:'global')。
42
+ * @returns 每个叶节点的世界变换 + 诊断量。
43
+ * @throws Error on empty members, unknown constraint parts, or non-convergence.
44
+ */
45
+ export declare function solveAssemblyTree(root: AssemblyNode, opts?: SolveOptions): AssemblyTreeSolveResult;
46
+ //# sourceMappingURL=solve-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solve-tree.d.ts","sourceRoot":"","sources":["../../../src/api/assembly/solve-tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAO3D,qCAAqC;AACrC,MAAM,WAAW,uBAAuB;IACtC,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;IAC7C,gBAAgB;IAChB,SAAS,EAAE,OAAO,CAAA;IAClB,iBAAiB;IACjB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,eAAe;IACf,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB;;;OAGG;IACH,eAAe,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAClC;AAkFD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,YAAY,EAClB,IAAI,CAAC,EAAE,YAAY,GAClB,uBAAuB,CAkDzB"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * api/assembly/solve-tree — 嵌套子装配求解(P4,方案 §4.2)
3
+ *
4
+ * flatten → solveGlobal → recompose:
5
+ * 1. flatten:walkAssembly 收集叶 shape + qualified member name(如 `subassy.part`),
6
+ * 构建扁平 members/memberNames;约束从各层收集(part 名用 qualified name,可跨层引用)。
7
+ * 2. solve:调 solveGlobal 求解扁平问题。
8
+ * 3. recompose:自顶向下将父变换(AssemblyNode.translate/rotate)与 solver 变换复合
9
+ * (parentTransform ∘ childLocalTransform),得到每个叶节点的世界变换。
10
+ *
11
+ * 语义对齐 CQ `Assembly.solve()`:每个对象的 `loc` 累积合成世界变换。
12
+ * faijs Shape 不携带 placement → 求解器从 identity 初值求解;父变换在 recompose 阶段复合。
13
+ */
14
+ import { solveGlobal } from './solvers/global-solver.js';
15
+ import { poseToAssemblyTransform, toBrepjsQuat, isIdentityPose } from './pose.js';
16
+ import { quatFromAxisAngle, quatRotate, quatMultiply } from './solvers/quat.js';
17
+ const DEG2RAD = Math.PI / 180;
18
+ /** 把 AssemblyNode 的 translate/rotate 转为 SolverPose(brepjs [w,x,y,z] 旋转)。 */
19
+ function nodeToPose(node) {
20
+ const position = node.translate
21
+ ? [node.translate[0], node.translate[1], node.translate[2]]
22
+ : [0, 0, 0];
23
+ let rotation = [1, 0, 0, 0];
24
+ if (node.rotate) {
25
+ const axis = node.rotate.axis
26
+ ? [node.rotate.axis[0], node.rotate.axis[1], node.rotate.axis[2]]
27
+ : [0, 0, 1];
28
+ rotation = quatFromAxisAngle(axis, node.rotate.angle * DEG2RAD);
29
+ }
30
+ return { position, rotation };
31
+ }
32
+ /** 复合两个 pose:先应用 child,再应用 parent(p' = R_p·(R_c·p + T_c) + T_p)。 */
33
+ function composePose(parent, child) {
34
+ const rotatedT = quatRotate(parent.rotation, child.position);
35
+ return {
36
+ position: [
37
+ parent.position[0] + rotatedT[0],
38
+ parent.position[1] + rotatedT[1],
39
+ parent.position[2] + rotatedT[2],
40
+ ],
41
+ rotation: quatMultiply(parent.rotation, child.rotation),
42
+ };
43
+ }
44
+ /**
45
+ * flatten:递归遍历装配树,收集叶 shape + qualified name + 约束 + 累积父 pose。
46
+ *
47
+ * qualified name = 从 root 的子节点到叶的 dot-separated 路径(如 `subassy.partB`)。
48
+ * 约束从各层收集 as-is——约束中的 part 名应为 qualified name(可跨层引用)。
49
+ */
50
+ function flattenTree(root) {
51
+ const members = [];
52
+ const memberNames = [];
53
+ const constraints = [];
54
+ const parentPoses = new Map();
55
+ if (root.constraints) {
56
+ for (const c of root.constraints)
57
+ constraints.push(c);
58
+ }
59
+ function walk(node, prefix, accumulated) {
60
+ for (const child of node.children) {
61
+ const qName = prefix ? `${prefix}.${child.name}` : child.name;
62
+ const childPose = nodeToPose(child);
63
+ const childAccumulated = composePose(accumulated, childPose);
64
+ if (child.shape) {
65
+ members.push(child.shape);
66
+ memberNames.push(qName);
67
+ parentPoses.set(qName, childAccumulated);
68
+ }
69
+ if (child.constraints) {
70
+ for (const c of child.constraints)
71
+ constraints.push(c);
72
+ }
73
+ if (child.children.length > 0) {
74
+ walk(child, qName, childAccumulated);
75
+ }
76
+ }
77
+ }
78
+ const rootPose = nodeToPose(root);
79
+ walk(root, '', rootPose);
80
+ return { members, memberNames, constraints, parentPoses };
81
+ }
82
+ /**
83
+ * 求解嵌套子装配树:flatten → solveGlobal → recompose。
84
+ *
85
+ * @param root - 装配树根节点(root 的 shape 被忽略,仅作容器)。
86
+ * @param opts - 求解选项(透传给 solveGlobal;默认 solver:'global')。
87
+ * @returns 每个叶节点的世界变换 + 诊断量。
88
+ * @throws Error on empty members, unknown constraint parts, or non-convergence.
89
+ */
90
+ export function solveAssemblyTree(root, opts) {
91
+ const flat = flattenTree(root);
92
+ if (flat.members.length === 0) {
93
+ return { transforms: {}, converged: true, unsupported: [], residuals: [] };
94
+ }
95
+ const solveOpts = { solver: 'global', ...opts };
96
+ const result = solveGlobal(flat.members, flat.memberNames, flat.constraints, solveOpts);
97
+ if (!result.converged) {
98
+ throw new Error('[assembly:tree] constraint solve did not converge; unsupported: ' +
99
+ (result.unsupported.length > 0 ? result.unsupported.join(', ') : '(no detail)'));
100
+ }
101
+ const transforms = {};
102
+ for (let i = 0; i < flat.memberNames.length; i++) {
103
+ const name = flat.memberNames[i];
104
+ const parentPose = flat.parentPoses.get(name);
105
+ if (parentPose && !isIdentityPose(parentPose)) {
106
+ transforms[name] = poseToAssemblyTransform(parentPose, [0, 0, 0], i);
107
+ }
108
+ }
109
+ for (const t of result.transforms) {
110
+ const name = flat.memberNames[t.index];
111
+ if (!name)
112
+ continue;
113
+ const parentPose = flat.parentPoses.get(name);
114
+ if (!parentPose || isIdentityPose(parentPose)) {
115
+ transforms[name] = t;
116
+ continue;
117
+ }
118
+ const solverPose = {
119
+ position: [t.translation[0], t.translation[1], t.translation[2]],
120
+ rotation: toBrepjsQuat(t.quaternion),
121
+ };
122
+ const composed = composePose(parentPose, solverPose);
123
+ transforms[name] = poseToAssemblyTransform(composed, [0, 0, 0], t.index);
124
+ }
125
+ return {
126
+ transforms,
127
+ converged: result.converged,
128
+ unsupported: result.unsupported,
129
+ residuals: result.residuals,
130
+ warnings: result.warnings,
131
+ // P7/D1-3:显式透传(此处是重建对象,spread 不会带上)。
132
+ underdetermined: result.underdetermined,
133
+ };
134
+ }
135
+ //# sourceMappingURL=solve-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solve-tree.js","sourceRoot":"","sources":["../../../src/api/assembly/solve-tree.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api/assembly/solve-tree — 嵌套子装配求解(P4,方案 §4.2)\n *\n * flatten → solveGlobal → recompose:\n * 1. flatten:walkAssembly 收集叶 shape + qualified member name(如 `subassy.part`),\n * 构建扁平 members/memberNames;约束从各层收集(part 名用 qualified name,可跨层引用)。\n * 2. solve:调 solveGlobal 求解扁平问题。\n * 3. recompose:自顶向下将父变换(AssemblyNode.translate/rotate)与 solver 变换复合\n * (parentTransform ∘ childLocalTransform),得到每个叶节点的世界变换。\n *\n * 语义对齐 CQ `Assembly.solve()`:每个对象的 `loc` 累积合成世界变换。\n * faijs Shape 不携带 placement → 求解器从 identity 初值求解;父变换在 recompose 阶段复合。\n */\n\nimport type { Shape } from '../../mesh/types'\nimport type { AssemblyTransform } from '../../runtime-state'\nimport type { AssemblyConstraint } from './types'\nimport type { SolveOptions } from './solvers/types'\nimport type { AssemblyNode } from './solvers/assembly-tree'\nimport { solveGlobal } from './solvers/global-solver'\nimport { poseToAssemblyTransform, toBrepjsQuat, isIdentityPose, type SolverPose } from './pose'\nimport { quatFromAxisAngle, quatRotate, quatMultiply } from './solvers/quat'\n\nconst DEG2RAD = Math.PI / 180\n\n/** 嵌套子装配求解结果:per-leaf 世界变换 + 诊断量。 */\nexport interface AssemblyTreeSolveResult {\n /** 每个叶节点的世界变换(键 = qualified name)。 */\n transforms: Record<string, AssemblyTransform>\n /** 是否全部约束可解。 */\n converged: boolean\n /** 无法求解的约束明细。 */\n unsupported: string[]\n /** 逐约束最终残差。 */\n residuals: number[]\n /** 残差超阈值的约束逐条写入。 */\n warnings?: string[]\n /**\n * P7/D1-3:欠定自由度诊断(透传自 solveGlobal)。dof > 0 = 约束集欠定,\n * 终态位姿依赖优化器轨迹、无唯一「正确解」——判等方应走规范判等通道而非逐位比对。\n */\n underdetermined?: { dof: number }\n}\n\n\n/** 把 AssemblyNode 的 translate/rotate 转为 SolverPose(brepjs [w,x,y,z] 旋转)。 */\nfunction nodeToPose(node: AssemblyNode): SolverPose {\n const position: [number, number, number] = node.translate\n ? [node.translate[0], node.translate[1], node.translate[2]]\n : [0, 0, 0]\n let rotation: [number, number, number, number] = [1, 0, 0, 0]\n if (node.rotate) {\n const axis: readonly [number, number, number] = node.rotate.axis\n ? [node.rotate.axis[0], node.rotate.axis[1], node.rotate.axis[2]]\n : [0, 0, 1]\n rotation = quatFromAxisAngle(axis, node.rotate.angle * DEG2RAD)\n }\n return { position, rotation }\n}\n\n/** 复合两个 pose:先应用 child,再应用 parent(p' = R_p·(R_c·p + T_c) + T_p)。 */\nfunction composePose(parent: SolverPose, child: SolverPose): SolverPose {\n const rotatedT = quatRotate(parent.rotation, child.position)\n return {\n position: [\n parent.position[0] + rotatedT[0],\n parent.position[1] + rotatedT[1],\n parent.position[2] + rotatedT[2],\n ],\n rotation: quatMultiply(parent.rotation, child.rotation),\n }\n}\n\ninterface FlatAssembly {\n members: Shape[]\n memberNames: string[]\n constraints: AssemblyConstraint[]\n /** 每个叶节点的累积父 pose(从 root 到该叶,含该叶自身 translate/rotate)。 */\n parentPoses: Map<string, SolverPose>\n}\n\n/**\n * flatten:递归遍历装配树,收集叶 shape + qualified name + 约束 + 累积父 pose。\n *\n * qualified name = 从 root 的子节点到叶的 dot-separated 路径(如 `subassy.partB`)。\n * 约束从各层收集 as-is——约束中的 part 名应为 qualified name(可跨层引用)。\n */\nfunction flattenTree(root: AssemblyNode): FlatAssembly {\n const members: Shape[] = []\n const memberNames: string[] = []\n const constraints: AssemblyConstraint[] = []\n const parentPoses = new Map<string, SolverPose>()\n\n if (root.constraints) {\n for (const c of root.constraints) constraints.push(c)\n }\n\n function walk(node: AssemblyNode, prefix: string, accumulated: SolverPose): void {\n for (const child of node.children) {\n const qName = prefix ? `${prefix}.${child.name}` : child.name\n const childPose = nodeToPose(child)\n const childAccumulated = composePose(accumulated, childPose)\n\n if (child.shape) {\n members.push(child.shape)\n memberNames.push(qName)\n parentPoses.set(qName, childAccumulated)\n }\n\n if (child.constraints) {\n for (const c of child.constraints) constraints.push(c)\n }\n\n if (child.children.length > 0) {\n walk(child, qName, childAccumulated)\n }\n }\n }\n\n const rootPose = nodeToPose(root)\n walk(root, '', rootPose)\n return { members, memberNames, constraints, parentPoses }\n}\n\n/**\n * 求解嵌套子装配树:flatten → solveGlobal → recompose。\n *\n * @param root - 装配树根节点(root 的 shape 被忽略,仅作容器)。\n * @param opts - 求解选项(透传给 solveGlobal;默认 solver:'global')。\n * @returns 每个叶节点的世界变换 + 诊断量。\n * @throws Error on empty members, unknown constraint parts, or non-convergence.\n */\nexport function solveAssemblyTree(\n root: AssemblyNode,\n opts?: SolveOptions,\n): AssemblyTreeSolveResult {\n const flat = flattenTree(root)\n if (flat.members.length === 0) {\n return { transforms: {}, converged: true, unsupported: [], residuals: [] }\n }\n\n const solveOpts: SolveOptions = { solver: 'global', ...opts }\n const result = solveGlobal(flat.members, flat.memberNames, flat.constraints, solveOpts)\n if (!result.converged) {\n throw new Error(\n '[assembly:tree] constraint solve did not converge; unsupported: ' +\n (result.unsupported.length > 0 ? result.unsupported.join(', ') : '(no detail)'),\n )\n }\n\n const transforms: Record<string, AssemblyTransform> = {}\n\n for (let i = 0; i < flat.memberNames.length; i++) {\n const name = flat.memberNames[i]\n const parentPose = flat.parentPoses.get(name)\n if (parentPose && !isIdentityPose(parentPose)) {\n transforms[name] = poseToAssemblyTransform(parentPose, [0, 0, 0], i)\n }\n }\n\n for (const t of result.transforms) {\n const name = flat.memberNames[t.index]\n if (!name) continue\n const parentPose = flat.parentPoses.get(name)\n if (!parentPose || isIdentityPose(parentPose)) {\n transforms[name] = t\n continue\n }\n const solverPose: SolverPose = {\n position: [t.translation[0], t.translation[1], t.translation[2]],\n rotation: toBrepjsQuat(t.quaternion as [number, number, number, number]),\n }\n const composed = composePose(parentPose, solverPose)\n transforms[name] = poseToAssemblyTransform(composed, [0, 0, 0], t.index)\n }\n\n return {\n transforms,\n converged: result.converged,\n unsupported: result.unsupported,\n residuals: result.residuals,\n warnings: result.warnings,\n // P7/D1-3:显式透传(此处是重建对象,spread 不会带上)。\n underdetermined: result.underdetermined,\n }\n}"]}
@@ -36,6 +36,13 @@ export interface AssemblySolveResult {
36
36
  * P1(global 求解器):逐约束最终残差(CQ 代价的逐约束平方和)。chain 路径不填。
37
37
  */
38
38
  residuals?: number[];
39
+ /**
40
+ * P7/D1-3:欠定自由度诊断(仅 global 路径透传)。dof > 0 = 约束集欠定,
41
+ * 终态位姿依赖优化器轨迹、无唯一「正确解」——判等方应走规范判等通道而非逐位比对。
42
+ */
43
+ underdetermined?: {
44
+ dof: number;
45
+ };
39
46
  }
40
47
  /**
41
48
  * 求解装配:members + memberNames + constraints → per-member 终态。
@@ -1 +1 @@
1
- {"version":3,"file":"solve.d.ts","sourceRoot":"","sources":["../../../src/api/assembly/solve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAO5D,OAAO,EAAmB,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,SAAS,CAAA;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGnD,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,UAAU,EAAE,iBAAiB,EAAE,CAAA;IAC/B,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,kDAAkD;IAClD,SAAS,EAAE,OAAO,CAAA;IAClB,uCAAuC;IACvC,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC3C;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,KAAK,EAAE,EAChB,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,EAAE,kBAAkB,EAAE,EACjC,IAAI,CAAC,EAAE,YAAY,GAClB,mBAAmB,CA0DrB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,KAAK,EAAE,EAChB,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,EAAE,kBAAkB,EAAE,EACjC,MAAM,GAAE,SAAS,EAAO,EACxB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EACzC,IAAI,CAAC,EAAE,YAAY,GAClB,mBAAmB,CAkCrB"}
1
+ {"version":3,"file":"solve.d.ts","sourceRoot":"","sources":["../../../src/api/assembly/solve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAO5D,OAAO,EAAmB,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,SAAS,CAAA;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGnD,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,UAAU,EAAE,iBAAiB,EAAE,CAAA;IAC/B,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,kDAAkD;IAClD,SAAS,EAAE,OAAO,CAAA;IAClB,uCAAuC;IACvC,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC3C;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,KAAK,EAAE,EAChB,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,EAAE,kBAAkB,EAAE,EACjC,IAAI,CAAC,EAAE,YAAY,GAClB,mBAAmB,CA0DrB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,KAAK,EAAE,EAChB,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,EAAE,kBAAkB,EAAE,EACjC,MAAM,GAAE,SAAS,EAAO,EACxB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EACzC,IAAI,CAAC,EAAE,YAAY,GAClB,mBAAmB,CAkCrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"solve.js","sourceRoot":"","sources":["../../../src/api/assembly/solve.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api/assembly/solve — 装配求解入口(P1,方案 §4.2)\n *\n * 流程:规范化(normalize)→ 降级(lower)→ brepjs solveConstraints\n *(拓扑轮次调度 / DOF / converged 全部由 brepjs 提供,零 brepjs 修改)→\n * per-member 终态 AssemblyTransform(修 L6:不再 per-constraint 增量叠加)。\n *\n * 不收敛 → 抛错(D3,错误信息带 unsupported 明细;对齐「绝不静默」约定)。\n * 恒等位姿的成员(锚定/链根)不输出变换——引擎不做无谓的几何重算。\n */\n\nimport type { Shape } from '../../mesh/types'\nimport type { BrepEngineApi } from '../../brep/engine/primitives'\nimport type { AssemblyTransform } from '../../runtime-state'\nimport { getBrepApi } from '../../brep/handle-bridge'\nimport { solveConstraints } from './solvers/chain-solver'\nimport { normalizeConstraint } from './normalize'\nimport { lowerStructuralConstraint } from './lower'\nimport { type EntityResolutionEnv } from './entities'\nimport { poseToAssemblyTransform, isIdentityPose, type SolverPose } from './pose'\nimport { solveKinematics, type JointSpec, type KinematicsPose } from './joints'\nimport type { AssemblyConstraint, AssemblyVec3 } from './types'\nimport type { SolveOptions } from './solvers/types'\nimport { solveGlobal } from './solvers/global-solver'\n\n/** 求解完整结果:per-member 终态变换 + 诊断量。 */\nexport interface AssemblySolveResult {\n /** 每个被定位成员一条终态变换(index = 成员下标;恒等位姿不输出)。 */\n transforms: AssemblyTransform[]\n /** unsupported 约束的自由度合计(诊断量;收敛时为 0)。 */\n dof: number\n /** 是否全部约束可解(不收敛时 solveAssembly 已抛错,此字段恒 true)。 */\n converged: boolean\n /** 无法求解的约束明细(entity 类型不匹配 / 参考不可达)。 */\n unsupported: string[]\n /**\n * P3:运动副解算的全成员位姿表(键 = 成员名;含恒等链根),\n * 只有该装配声明了 joints 时才存在——宿主从 ExecutionResult.kinematics 消费。\n */\n kinematics?: Record<string, KinematicsPose>\n /**\n * P3:合并诊断(joints 覆盖约束解时各记一条;D-P3-1,不参与 converged 统计)。\n */\n warnings?: string[]\n /**\n * P1(global 求解器):逐约束最终残差(CQ 代价的逐约束平方和)。chain 路径不填。\n */\n residuals?: number[]\n}\n\n/**\n * 求解装配:members + memberNames + constraints → per-member 终态。\n *\n * @param members - member shapes (compound children, aligned with memberNames).\n * @param memberNames - member variable names (R7: empty names throw before solving).\n * @param constraints - raw constraints from `cad.assembly({ constraints })`.\n * @param opts - optional solver options (e.g. `solver: 'global'` selects the global least-squares path).\n * @returns the solve result (transforms + diagnostics).\n * @throws Error on empty member names, unknown constraint parts, or non-convergence.\n */\nexport function solveAssembly(\n members: Shape[],\n memberNames: string[],\n constraints: AssemblyConstraint[],\n opts?: SolveOptions,\n): AssemblySolveResult {\n // P1:global 求解器分派(CadQuery 兼容全局最小二乘;零额外依赖)\n if (opts?.solver === 'global') {\n return solveGlobal(members, memberNames, constraints, opts)\n }\n\n // R7:成员名是 solver 的节点键,空串会让多成员互相覆盖——求解前断言\n memberNames.forEach((name, i) => {\n if (!name) {\n throw new Error(\n `[assembly] member at index ${i} has an empty name — members are referenced by variable name in constraints`,\n )\n }\n })\n\n const memberMap = new Map<string, Shape>()\n members.forEach((m, i) => {\n const name = memberNames[i]\n if (name && !memberMap.has(name)) memberMap.set(name, m)\n })\n // kernel 仅 TopoRef/边引用解析需要;backends 未配置(纯位姿场景/单测)→ null,\n // 此时快照引用仍可解,TopoRef 引用按 E_TOPO_NOT_FOUND 显式报错\n let kernel: BrepEngineApi | null = null\n try {\n kernel = getBrepApi()\n } catch {\n // backends not configured — snapshot-form constraints still solvable\n }\n const env: EntityResolutionEnv = { kernel, memberOf: (p: string) => memberMap.get(p) }\n\n const lowered: ReturnType<typeof lowerStructuralConstraint>['constraint'][] = []\n const depOrigins = new Map<string, AssemblyVec3>()\n for (const raw of constraints) {\n const c = normalizeConstraint(raw)\n const { constraint, depOrigin } = lowerStructuralConstraint(c, env)\n lowered.push(constraint)\n if (depOrigin && constraint.entityB) depOrigins.set(constraint.entityB.node, depOrigin)\n }\n\n const result = solveConstraints([...memberNames], lowered)\n if (!result.converged) {\n throw new Error(\n `[assembly] constraint solve did not converge (dof=${result.dof}); unsupported: ` +\n (result.unsupported.length > 0 ? result.unsupported.join(', ') : '(no detail)'),\n )\n }\n\n // per-member 终态(L6 修复):恒等位姿(锚定/链根)不输出,引擎不重算\n const transforms: AssemblyTransform[] = []\n for (const [node, rawPose] of result.transforms) {\n const pose: SolverPose = rawPose\n if (isIdentityPose(pose)) continue\n const index = memberNames.indexOf(node)\n if (index < 0) continue\n const pivot = depOrigins.get(node) ?? ([0, 0, 0] as AssemblyVec3)\n transforms.push(poseToAssemblyTransform(pose, pivot, index))\n }\n return { transforms, dof: result.dof, converged: result.converged, unsupported: result.unsupported }\n}\n\n/**\n * 求解装配(约束 + 运动副,P3):先跑约束求解得到 per-member 终态,再跑\n * solveKinematics 得到 joints 的 per-member 位姿,以**成员名**为键用 joints 结果\n * 覆盖同名成员的约束解,得到唯一一张表——**在库侧一次合并**,调用方一次性\n * setPendingAssemblyTransforms(禁止引擎侧两次登记)。\n *\n * 诊断不混用:joints 不参与 solveConstraints 的 converged/dof/unsupported 统计;\n * 覆盖发生时在 warnings 里各记一条(D-P3-1)。kinematics 为全成员位姿表(含\n * 恒等链根),供宿主从 ExecutionResult.kinematics 消费。\n *\n * joints 为空 → 退化为基础 solveAssembly 行为(无 kinematics/warnings 字段)。\n *\n * @param members - member shapes (aligned with memberNames).\n * @param memberNames - member variable names (R7: empty names throw).\n * @param constraints - raw constraints (may be empty).\n * @param joints - raw joint declarations (may be empty).\n * @param drive - per-child DOF value overrides (may be undefined).\n * @param opts - optional solver options (forwarded to the base constraint solve).\n * @returns the merged solve result (transforms + diagnostics + kinematics/warnings).\n */\nexport function solveAssemblyAndKinematics(\n members: Shape[],\n memberNames: string[],\n constraints: AssemblyConstraint[],\n joints: JointSpec[] = [],\n drive?: Record<string, number | number[]>,\n opts?: SolveOptions,\n): AssemblySolveResult {\n const base = solveAssembly(members, memberNames, constraints, opts)\n if (joints.length === 0) return base\n\n const kin = solveKinematics(memberNames, joints, drive)\n // 合并:以成员名为键,joints 结果覆盖同名成员的约束解(唯一一张表)\n const merged = new Map<string, AssemblyTransform>()\n for (const t of base.transforms) {\n const name = memberNames[t.index]\n if (name) merged.set(name, t)\n }\n const warnings: string[] = []\n for (const t of kin.transforms) {\n const name = memberNames[t.index]\n if (!name) continue\n if (merged.has(name)) {\n warnings.push(`[assembly] joint '${name}' overrides the constraint solution for member '${name}'`)\n }\n merged.set(name, t)\n }\n // 按成员下标升序输出(与约束解的 Map 遍历序解耦,输出顺序确定)\n const transforms = [...merged.entries()]\n .map(([name, t]) => ({ name, t }))\n .sort((a, b) => memberNames.indexOf(a.name) - memberNames.indexOf(b.name))\n .map(({ t }) => t)\n\n return {\n transforms,\n dof: base.dof,\n converged: base.converged,\n unsupported: base.unsupported,\n kinematics: kin.kinematics,\n warnings: warnings.length > 0 ? warnings : undefined,\n }\n}\n"]}
1
+ {"version":3,"file":"solve.js","sourceRoot":"","sources":["../../../src/api/assembly/solve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAEnD,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAmB,MAAM,QAAQ,CAAA;AACjF,OAAO,EAAE,eAAe,EAAuC,MAAM,UAAU,CAAA;AAG/E,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAgCrD;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAgB,EAChB,WAAqB,EACrB,WAAiC,EACjC,IAAmB;IAEnB,2CAA2C;IAC3C,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,CAAC,CAAA;IAC7D,CAAC;IAED,yCAAyC;IACzC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,8BAA8B,CAAC,6EAA6E,CAC7G,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,SAAS,GAAG,IAAI,GAAG,EAAiB,CAAA;IAC1C,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACvB,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;QAC3B,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;IACF,yDAAyD;IACzD,8CAA8C;IAC9C,IAAI,MAAM,GAAyB,IAAI,CAAA;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,UAAU,EAAE,CAAA;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;IACvE,CAAC;IACD,MAAM,GAAG,GAAwB,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;IAEtF,MAAM,OAAO,GAAiE,EAAE,CAAA;IAChF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAwB,CAAA;IAClD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAA;QAClC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,yBAAyB,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QACnE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACxB,IAAI,SAAS,IAAI,UAAU,CAAC,OAAO;YAAE,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IACzF,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,CAAC,GAAG,WAAW,CAAC,EAAE,OAAO,CAAC,CAAA;IAC1D,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,qDAAqD,MAAM,CAAC,GAAG,kBAAkB;YAC/E,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAClF,CAAA;IACH,CAAC;IAED,4CAA4C;IAC5C,MAAM,UAAU,GAAwB,EAAE,CAAA;IAC1C,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAChD,MAAM,IAAI,GAAe,OAAO,CAAA;QAChC,IAAI,cAAc,CAAC,IAAI,CAAC;YAAE,SAAQ;QAClC,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,KAAK,GAAG,CAAC;YAAE,SAAQ;QACvB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAkB,CAAA;QACjE,UAAU,CAAC,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;IAC9D,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAA;AACtG,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAgB,EAChB,WAAqB,EACrB,WAAiC,EACjC,SAAsB,EAAE,EACxB,KAAyC,EACzC,IAAmB;IAEnB,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,CAAC,CAAA;IACnE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAEpC,MAAM,GAAG,GAAG,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;IACvD,uCAAuC;IACvC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAA;IACnD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QACjC,IAAI,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IAC/B,CAAC;IACD,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QACjC,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,QAAQ,CAAC,IAAI,CAAC,qBAAqB,IAAI,mDAAmD,IAAI,GAAG,CAAC,CAAA;QACpG,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IACrB,CAAC;IACD,oCAAoC;IACpC,MAAM,UAAU,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACrC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;SACjC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SACzE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;IAEpB,OAAO;QACL,UAAU;QACV,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;KACrD,CAAA;AACH,CAAC","sourcesContent":["/**\n * api/assembly/solve — 装配求解入口(P1,方案 §4.2)\n *\n * 流程:规范化(normalize)→ 降级(lower)→ brepjs solveConstraints\n *(拓扑轮次调度 / DOF / converged 全部由 brepjs 提供,零 brepjs 修改)→\n * per-member 终态 AssemblyTransform(修 L6:不再 per-constraint 增量叠加)。\n *\n * 不收敛 → 抛错(D3,错误信息带 unsupported 明细;对齐「绝不静默」约定)。\n * 恒等位姿的成员(锚定/链根)不输出变换——引擎不做无谓的几何重算。\n */\n\nimport type { Shape } from '../../mesh/types'\nimport type { BrepEngineApi } from '../../brep/engine/primitives'\nimport type { AssemblyTransform } from '../../runtime-state'\nimport { getBrepApi } from '../../brep/handle-bridge'\nimport { solveConstraints } from './solvers/chain-solver'\nimport { normalizeConstraint } from './normalize'\nimport { lowerStructuralConstraint } from './lower'\nimport { type EntityResolutionEnv } from './entities'\nimport { poseToAssemblyTransform, isIdentityPose, type SolverPose } from './pose'\nimport { solveKinematics, type JointSpec, type KinematicsPose } from './joints'\nimport type { AssemblyConstraint, AssemblyVec3 } from './types'\nimport type { SolveOptions } from './solvers/types'\nimport { solveGlobal } from './solvers/global-solver'\n\n/** 求解完整结果:per-member 终态变换 + 诊断量。 */\nexport interface AssemblySolveResult {\n /** 每个被定位成员一条终态变换(index = 成员下标;恒等位姿不输出)。 */\n transforms: AssemblyTransform[]\n /** unsupported 约束的自由度合计(诊断量;收敛时为 0)。 */\n dof: number\n /** 是否全部约束可解(不收敛时 solveAssembly 已抛错,此字段恒 true)。 */\n converged: boolean\n /** 无法求解的约束明细(entity 类型不匹配 / 参考不可达)。 */\n unsupported: string[]\n /**\n * P3:运动副解算的全成员位姿表(键 = 成员名;含恒等链根),\n * 只有该装配声明了 joints 时才存在——宿主从 ExecutionResult.kinematics 消费。\n */\n kinematics?: Record<string, KinematicsPose>\n /**\n * P3:合并诊断(joints 覆盖约束解时各记一条;D-P3-1,不参与 converged 统计)。\n */\n warnings?: string[]\n /**\n * P1(global 求解器):逐约束最终残差(CQ 代价的逐约束平方和)。chain 路径不填。\n */\n residuals?: number[]\n /**\n * P7/D1-3:欠定自由度诊断(仅 global 路径透传)。dof > 0 = 约束集欠定,\n * 终态位姿依赖优化器轨迹、无唯一「正确解」——判等方应走规范判等通道而非逐位比对。\n */\n underdetermined?: { dof: number }\n}\n\n/**\n * 求解装配:members + memberNames + constraints → per-member 终态。\n *\n * @param members - member shapes (compound children, aligned with memberNames).\n * @param memberNames - member variable names (R7: empty names throw before solving).\n * @param constraints - raw constraints from `cad.assembly({ constraints })`.\n * @param opts - optional solver options (e.g. `solver: 'global'` selects the global least-squares path).\n * @returns the solve result (transforms + diagnostics).\n * @throws Error on empty member names, unknown constraint parts, or non-convergence.\n */\nexport function solveAssembly(\n members: Shape[],\n memberNames: string[],\n constraints: AssemblyConstraint[],\n opts?: SolveOptions,\n): AssemblySolveResult {\n // P1:global 求解器分派(CadQuery 兼容全局最小二乘;零额外依赖)\n if (opts?.solver === 'global') {\n return solveGlobal(members, memberNames, constraints, opts)\n }\n\n // R7:成员名是 solver 的节点键,空串会让多成员互相覆盖——求解前断言\n memberNames.forEach((name, i) => {\n if (!name) {\n throw new Error(\n `[assembly] member at index ${i} has an empty name — members are referenced by variable name in constraints`,\n )\n }\n })\n\n const memberMap = new Map<string, Shape>()\n members.forEach((m, i) => {\n const name = memberNames[i]\n if (name && !memberMap.has(name)) memberMap.set(name, m)\n })\n // kernel 仅 TopoRef/边引用解析需要;backends 未配置(纯位姿场景/单测)→ null,\n // 此时快照引用仍可解,TopoRef 引用按 E_TOPO_NOT_FOUND 显式报错\n let kernel: BrepEngineApi | null = null\n try {\n kernel = getBrepApi()\n } catch {\n // backends not configured — snapshot-form constraints still solvable\n }\n const env: EntityResolutionEnv = { kernel, memberOf: (p: string) => memberMap.get(p) }\n\n const lowered: ReturnType<typeof lowerStructuralConstraint>['constraint'][] = []\n const depOrigins = new Map<string, AssemblyVec3>()\n for (const raw of constraints) {\n const c = normalizeConstraint(raw)\n const { constraint, depOrigin } = lowerStructuralConstraint(c, env)\n lowered.push(constraint)\n if (depOrigin && constraint.entityB) depOrigins.set(constraint.entityB.node, depOrigin)\n }\n\n const result = solveConstraints([...memberNames], lowered)\n if (!result.converged) {\n throw new Error(\n `[assembly] constraint solve did not converge (dof=${result.dof}); unsupported: ` +\n (result.unsupported.length > 0 ? result.unsupported.join(', ') : '(no detail)'),\n )\n }\n\n // per-member 终态(L6 修复):恒等位姿(锚定/链根)不输出,引擎不重算\n const transforms: AssemblyTransform[] = []\n for (const [node, rawPose] of result.transforms) {\n const pose: SolverPose = rawPose\n if (isIdentityPose(pose)) continue\n const index = memberNames.indexOf(node)\n if (index < 0) continue\n const pivot = depOrigins.get(node) ?? ([0, 0, 0] as AssemblyVec3)\n transforms.push(poseToAssemblyTransform(pose, pivot, index))\n }\n return { transforms, dof: result.dof, converged: result.converged, unsupported: result.unsupported }\n}\n\n/**\n * 求解装配(约束 + 运动副,P3):先跑约束求解得到 per-member 终态,再跑\n * solveKinematics 得到 joints 的 per-member 位姿,以**成员名**为键用 joints 结果\n * 覆盖同名成员的约束解,得到唯一一张表——**在库侧一次合并**,调用方一次性\n * setPendingAssemblyTransforms(禁止引擎侧两次登记)。\n *\n * 诊断不混用:joints 不参与 solveConstraints 的 converged/dof/unsupported 统计;\n * 覆盖发生时在 warnings 里各记一条(D-P3-1)。kinematics 为全成员位姿表(含\n * 恒等链根),供宿主从 ExecutionResult.kinematics 消费。\n *\n * joints 为空 → 退化为基础 solveAssembly 行为(无 kinematics/warnings 字段)。\n *\n * @param members - member shapes (aligned with memberNames).\n * @param memberNames - member variable names (R7: empty names throw).\n * @param constraints - raw constraints (may be empty).\n * @param joints - raw joint declarations (may be empty).\n * @param drive - per-child DOF value overrides (may be undefined).\n * @param opts - optional solver options (forwarded to the base constraint solve).\n * @returns the merged solve result (transforms + diagnostics + kinematics/warnings).\n */\nexport function solveAssemblyAndKinematics(\n members: Shape[],\n memberNames: string[],\n constraints: AssemblyConstraint[],\n joints: JointSpec[] = [],\n drive?: Record<string, number | number[]>,\n opts?: SolveOptions,\n): AssemblySolveResult {\n const base = solveAssembly(members, memberNames, constraints, opts)\n if (joints.length === 0) return base\n\n const kin = solveKinematics(memberNames, joints, drive)\n // 合并:以成员名为键,joints 结果覆盖同名成员的约束解(唯一一张表)\n const merged = new Map<string, AssemblyTransform>()\n for (const t of base.transforms) {\n const name = memberNames[t.index]\n if (name) merged.set(name, t)\n }\n const warnings: string[] = []\n for (const t of kin.transforms) {\n const name = memberNames[t.index]\n if (!name) continue\n if (merged.has(name)) {\n warnings.push(`[assembly] joint '${name}' overrides the constraint solution for member '${name}'`)\n }\n merged.set(name, t)\n }\n // 按成员下标升序输出(与约束解的 Map 遍历序解耦,输出顺序确定)\n const transforms = [...merged.entries()]\n .map(([name, t]) => ({ name, t }))\n .sort((a, b) => memberNames.indexOf(a.name) - memberNames.indexOf(b.name))\n .map(({ t }) => t)\n\n return {\n transforms,\n dof: base.dof,\n converged: base.converged,\n unsupported: base.unsupported,\n kinematics: kin.kinematics,\n warnings: warnings.length > 0 ? warnings : undefined,\n }\n}\n"]}
@@ -11,6 +11,7 @@
11
11
  * |> addChild(_, createAssemblyNode('part-b', { shape: cylShape }));
12
12
  */
13
13
  import type { Shape } from '../../../mesh/types.js';
14
+ import type { AssemblyConstraint } from '../types.js';
14
15
  /** 3D vector(core 本地别名,§5.6 移植)。 */
15
16
  export type Vec3 = readonly [number, number, number];
16
17
  /**
@@ -29,6 +30,8 @@ export interface AssemblyNode {
29
30
  readonly mates?: readonly unknown[];
30
31
  /** Drivable kinematic joints (see jointFns). Typed loosely to avoid a cycle. */
31
32
  readonly joints?: readonly unknown[];
33
+ /** P4: constraints local to this node (part names use qualified names relative to root). */
34
+ readonly constraints?: readonly AssemblyConstraint[];
32
35
  }
33
36
  /** Optional properties for creating or updating an assembly node. */
34
37
  export interface AssemblyNodeOptions {
@@ -39,6 +42,7 @@ export interface AssemblyNodeOptions {
39
42
  axis?: Vec3;
40
43
  };
41
44
  metadata?: Record<string, unknown>;
45
+ constraints?: AssemblyConstraint[];
42
46
  }
43
47
  /**
44
48
  * Create a new assembly node.