@faicad/faijs 0.19.0 → 0.22.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 (140) hide show
  1. package/dist/api/brep-mirror/joinery-brep.d.ts.map +1 -1
  2. package/dist/api/brep-mirror/joinery-brep.js +3 -1
  3. package/dist/api/brep-mirror/joinery-brep.js.map +1 -1
  4. package/dist/api/generated/script-face-manifest.d.ts +4 -0
  5. package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
  6. package/dist/api/generated/script-face-manifest.js.map +1 -1
  7. package/dist/api/knurl.d.ts.map +1 -1
  8. package/dist/api/knurl.js +1 -0
  9. package/dist/api/knurl.js.map +1 -1
  10. package/dist/api/primitives.d.ts +4 -3
  11. package/dist/api/primitives.d.ts.map +1 -1
  12. package/dist/api/primitives.js +9 -3
  13. package/dist/api/primitives.js.map +1 -1
  14. package/dist/api/profile.d.ts +34 -5
  15. package/dist/api/profile.d.ts.map +1 -1
  16. package/dist/api/profile.js +60 -9
  17. package/dist/api/profile.js.map +1 -1
  18. package/dist/api/punch-hole.d.ts +3 -0
  19. package/dist/api/punch-hole.d.ts.map +1 -1
  20. package/dist/api/punch-hole.js.map +1 -1
  21. package/dist/api/sketch-on-plane.d.ts +12 -6
  22. package/dist/api/sketch-on-plane.d.ts.map +1 -1
  23. package/dist/api/sketch-on-plane.js +11 -8
  24. package/dist/api/sketch-on-plane.js.map +1 -1
  25. package/dist/api/surface/arg-spec.d.ts +8 -0
  26. package/dist/api/surface/arg-spec.d.ts.map +1 -1
  27. package/dist/api/surface/arg-spec.js.map +1 -1
  28. package/dist/api/transform.d.ts +5 -5
  29. package/dist/api/transform.d.ts.map +1 -1
  30. package/dist/api/transform.js +12 -10
  31. package/dist/api/transform.js.map +1 -1
  32. package/dist/api/xml-dom.d.ts +27 -0
  33. package/dist/api/xml-dom.d.ts.map +1 -0
  34. package/dist/api/xml-dom.js +45 -0
  35. package/dist/api/xml-dom.js.map +1 -0
  36. package/dist/brep/brep-ops.d.ts +4 -4
  37. package/dist/brep/brep-ops.d.ts.map +1 -1
  38. package/dist/brep/brep-ops.js +8 -6
  39. package/dist/brep/brep-ops.js.map +1 -1
  40. package/dist/brep/brep-topology.d.ts.map +1 -1
  41. package/dist/brep/brep-topology.js +3 -1
  42. package/dist/brep/brep-topology.js.map +1 -1
  43. package/dist/brep/export/export-model.d.ts +79 -0
  44. package/dist/brep/export/export-model.d.ts.map +1 -0
  45. package/dist/brep/export/export-model.js +335 -0
  46. package/dist/brep/export/export-model.js.map +1 -0
  47. package/dist/brep/primitives-brep.d.ts.map +1 -1
  48. package/dist/brep/primitives-brep.js +3 -1
  49. package/dist/brep/primitives-brep.js.map +1 -1
  50. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  51. package/dist/brepkit-kernel/brepkitKernel.js +4 -2
  52. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  53. package/dist/cad-runtime/direct-executor.d.ts +4 -0
  54. package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
  55. package/dist/cad-runtime/direct-executor.js +17 -1
  56. package/dist/cad-runtime/direct-executor.js.map +1 -1
  57. package/dist/cad-runtime/runtime.d.ts +24 -1
  58. package/dist/cad-runtime/runtime.d.ts.map +1 -1
  59. package/dist/cad-runtime/runtime.js +53 -3
  60. package/dist/cad-runtime/runtime.js.map +1 -1
  61. package/dist/define-op.d.ts +22 -0
  62. package/dist/define-op.d.ts.map +1 -1
  63. package/dist/define-op.js +15 -0
  64. package/dist/define-op.js.map +1 -1
  65. package/dist/env-agnostic.d.ts +7 -7
  66. package/dist/env-agnostic.d.ts.map +1 -1
  67. package/dist/env-agnostic.js +3 -3
  68. package/dist/env-agnostic.js.map +1 -1
  69. package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -1
  70. package/dist/geometry2d/bridge/lift-on-plane.js +6 -0
  71. package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -1
  72. package/dist/geometry2d/pen-sketcher.d.ts +25 -0
  73. package/dist/geometry2d/pen-sketcher.d.ts.map +1 -1
  74. package/dist/geometry2d/pen-sketcher.js +43 -0
  75. package/dist/geometry2d/pen-sketcher.js.map +1 -1
  76. package/dist/lang/code-to-args.d.ts +29 -3
  77. package/dist/lang/code-to-args.d.ts.map +1 -1
  78. package/dist/lang/code-to-args.js +41 -2
  79. package/dist/lang/code-to-args.js.map +1 -1
  80. package/dist/lang/codegen.d.ts +45 -1
  81. package/dist/lang/codegen.d.ts.map +1 -1
  82. package/dist/lang/codegen.js +135 -6
  83. package/dist/lang/codegen.js.map +1 -1
  84. package/dist/lang/host-arg.d.ts +6 -0
  85. package/dist/lang/host-arg.d.ts.map +1 -1
  86. package/dist/lang/host-arg.js.map +1 -1
  87. package/dist/lang/metadata-extractor.d.ts +25 -0
  88. package/dist/lang/metadata-extractor.d.ts.map +1 -1
  89. package/dist/lang/metadata-extractor.js +289 -25
  90. package/dist/lang/metadata-extractor.js.map +1 -1
  91. package/dist/lang/parse-error.d.ts +7 -1
  92. package/dist/lang/parse-error.d.ts.map +1 -1
  93. package/dist/lang/parse-error.js.map +1 -1
  94. package/dist/lang/security-scanner.d.ts +9 -1
  95. package/dist/lang/security-scanner.d.ts.map +1 -1
  96. package/dist/lang/security-scanner.js +38 -1
  97. package/dist/lang/security-scanner.js.map +1 -1
  98. package/dist/mesh/io.d.ts +62 -9
  99. package/dist/mesh/io.d.ts.map +1 -1
  100. package/dist/mesh/io.js +124 -17
  101. package/dist/mesh/io.js.map +1 -1
  102. package/dist/mesh/threemf-loader.d.ts +15 -0
  103. package/dist/mesh/threemf-loader.d.ts.map +1 -0
  104. package/dist/mesh/threemf-loader.js +163 -0
  105. package/dist/mesh/threemf-loader.js.map +1 -0
  106. package/dist/mesh/transform.d.ts +2 -2
  107. package/dist/mesh/transform.d.ts.map +1 -1
  108. package/dist/mesh/transform.js +3 -3
  109. package/dist/mesh/transform.js.map +1 -1
  110. package/dist/mesh/types.d.ts +1 -1
  111. package/dist/mesh/types.d.ts.map +1 -1
  112. package/dist/mesh/types.js.map +1 -1
  113. package/dist/node-host/cli.d.ts.map +1 -1
  114. package/dist/node-host/cli.js +53 -26
  115. package/dist/node-host/cli.js.map +1 -1
  116. package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
  117. package/dist/occt-kernel/occtKernel.js +4 -2
  118. package/dist/occt-kernel/occtKernel.js.map +1 -1
  119. package/dist/occt-kernel/topologyExt.d.ts.map +1 -1
  120. package/dist/occt-kernel/topologyExt.js +4 -1
  121. package/dist/occt-kernel/topologyExt.js.map +1 -1
  122. package/dist/runtime-state.d.ts +18 -0
  123. package/dist/runtime-state.d.ts.map +1 -1
  124. package/dist/runtime-state.js +23 -0
  125. package/dist/runtime-state.js.map +1 -1
  126. package/dist/sdk.d.ts +1 -1
  127. package/dist/sdk.d.ts.map +1 -1
  128. package/dist/sdk.js +1 -1
  129. package/dist/sdk.js.map +1 -1
  130. package/dist/tolerance.d.ts +38 -0
  131. package/dist/tolerance.d.ts.map +1 -0
  132. package/dist/tolerance.js +40 -0
  133. package/dist/tolerance.js.map +1 -0
  134. package/dist/topology/naming/score.js +3 -3
  135. package/dist/topology/naming/score.js.map +1 -1
  136. package/dist/units.d.ts +248 -0
  137. package/dist/units.d.ts.map +1 -0
  138. package/dist/units.js +397 -0
  139. package/dist/units.js.map +1 -0
  140. package/package.json +11 -2
@@ -321,4 +321,22 @@ export declare function keep(...shapes: unknown[]): void;
321
321
  * @param shapes - the shapes whose corresponding variables should be kept hidden.
322
322
  */
323
323
  export declare function keepHidden(...shapes: unknown[]): void;
324
+ /** Per-part declared file units (key = PartName; null-never — absent key = unknown). */
325
+ export type DetectedUnits = Map<PartName, string>;
326
+ /**
327
+ * Register a part's declared file unit (called from the load op body; the unit
328
+ * is metadata only — coordinates are already base-unit, never re-scaled).
329
+ *
330
+ * @param partName - the variable name the loaded shape will be bound to.
331
+ * @param unit - the file's own declared unit (faijs UnitName).
332
+ */
333
+ export declare function setPendingDetectedUnit(partName: PartName, unit: string): void;
334
+ /**
335
+ * Take all pending detected units and clear them (engine, after each statement;
336
+ * consumed exactly once).
337
+ *
338
+ * @returns a fresh Map of part name → declared unit, copied from the pending
339
+ * store and cleared so it is consumed exactly once.
340
+ */
341
+ export declare function takePendingDetectedUnits(): DetectedUnits;
324
342
  //# sourceMappingURL=runtime-state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-state.d.ts","sourceRoot":"","sources":["../src/runtime-state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime-state.d.ts","sourceRoot":"","sources":["../src/runtime-state.ts"],"names":[],"mappings":"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"}
@@ -321,4 +321,27 @@ function registerKeep(shapes, hidden) {
321
321
  return;
322
322
  keepSink(String(stmt.id), names, hidden);
323
323
  }
324
+ const pendingDetectedUnits = new Map();
325
+ /**
326
+ * Register a part's declared file unit (called from the load op body; the unit
327
+ * is metadata only — coordinates are already base-unit, never re-scaled).
328
+ *
329
+ * @param partName - the variable name the loaded shape will be bound to.
330
+ * @param unit - the file's own declared unit (faijs UnitName).
331
+ */
332
+ export function setPendingDetectedUnit(partName, unit) {
333
+ pendingDetectedUnits.set(partName, unit);
334
+ }
335
+ /**
336
+ * Take all pending detected units and clear them (engine, after each statement;
337
+ * consumed exactly once).
338
+ *
339
+ * @returns a fresh Map of part name → declared unit, copied from the pending
340
+ * store and cleared so it is consumed exactly once.
341
+ */
342
+ export function takePendingDetectedUnits() {
343
+ const out = new Map(pendingDetectedUnits);
344
+ pendingDetectedUnits.clear();
345
+ return out;
346
+ }
324
347
  //# sourceMappingURL=runtime-state.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-state.js","sourceRoot":"","sources":["../src/runtime-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * runtime-state — 全局运行时状态锚点(零依赖层)\n *\n *\n * 本模块位于 L0+(零运行时依赖),是 L3 API 面(core/src/api,原 stdlib)与\n * cad-runtime(L2)之间唯一的共享状态。**放在这一层是为了避免循环依赖**:\n * api/ 不能 import cad-runtime(cad-runtime/api-namespace.ts 已经 import 了 api/)。\n *\n * 承载三类状态:\n * 1. Backends —— 宿主注入的环境资源(内核 / 端口 / 模式 / 标准库命名空间)\n * 2. 当前执行语句 —— keep() 归属用(引擎在语句 fn 之前设置)\n * 3. Shape 身份表 —— 构造器登记(isShape 依据)与 Shape→PartName 反查\n *\n * ⚠️ 依赖方向红线:本文件不得 import 任何 src/ 下的模块(只可 import type)。\n */\n\nimport type { PartName, StmtId } from './identity'\n\n/**\n * Lightweight execution anchor — carries only the fields consumed by\n * library functions via getCurrentStmt(): `id` (StmtId), `outputs` (PartName[]),\n * `callee`, and `hasAssignment`. The DirectExecutor creates these from\n * line-number + writes.\n */\nexport interface ExecutionAnchor {\n readonly id: string\n readonly outputs: PartName[]\n readonly callee?: string\n readonly hasAssignment?: boolean\n}\n\n// ── 后端配置(宿主注入的环境资源)──\n\n/**\n * 执行模式(与 src/cad-runtime/ports.ts 的 ExecutionMode 保持一致)。\n *\n * 此处重复定义是为了保持本模块零依赖。一致性由 `cad-runtime/runtime.ts:460`\n * (`mode: this.mode`,`ExecutionMode` → 本类型的赋值)在编译期间接钉住:\n * 只给 `ExecutionMode` 加成员而不加到这里 → 该行 tsc 报错。\n * (2026-09-22 核实:无独立守卫测试。)\n */\nexport type RuntimeExecutionMode = 'auto' | 'brep' | 'mesh'\n\n/** 宿主注入的环境资源。字段类型用宽松结构,避免本模块依赖具体实现。 */\nexport interface Backends {\n /** 契约版本(装配期校验,不兼容即抛错) */\n readonly contractVersion: number\n /** 执行配置(可变对象,宿主可在运行期切换) */\n readonly config: {\n mode: RuntimeExecutionMode\n /** 当前 BREP 引擎 id(注册表首个注册者;未注册为 null)。能力路由读(§8.4)。 */\n brepEngineId?: string | null\n /**\n * 当前引擎能力声明(宽松结构,零依赖)。能力路由读(§8.4)。\n *\n * `evolution` = 本引擎**实际提供**的 `*WithHistory` 核函数名名单\n * (`brep/engine/types.ts` 的 `BrepEvolutionKind`)。**不是**族级布尔——\n * 族级布尔会多报能力、使静态判定失效(Phase 0.2)。\n * 本模块须零依赖,故此处只写 `readonly string[]`;权威类型见\n * `BrepCapabilities`,消费侧由 `backend-dispatch.engineCapabilitySet` 归一化。\n */\n brepCapabilities?: {\n evolution?: readonly string[]\n /**\n * 非演化内核方法名(D5):本引擎**实际提供**的 L1 中立方法名\n * (`getBoundingBox` / `getVolume` / `getSurfaceArea` / `getLength` /\n * `getCenterOfMass` 等)。2026-09-24 narrowing plan §2.4:与\n * `backend-dispatch.EngineCapabilitiesLike` 对齐(该类型有 `methods`,\n * 运行时配置镜像此前缺失——非字面量赋值不做 excess property 检查,\n * `methods` 判定\"能用但没被契约钉住\")。\n */\n methods?: readonly string[]\n heal?: boolean\n directEdit?: boolean\n advSurface?: boolean\n assembly?: boolean\n meshLift?: boolean\n }\n partTransform?: { position: [number, number, number]; scale?: [number, number, number] }\n }\n /** 几何后端。brep 引擎异步初始化 → 用 getter。 */\n readonly kernel: {\n readonly brep: unknown | null\n readonly csg: unknown | undefined\n readonly sdf: unknown | undefined\n }\n /** 宿主端口(透传 HostPorts) */\n readonly fonts: unknown\n readonly texture: unknown\n readonly assets: unknown\n readonly events: unknown\n /** faijs 自带标准库命名空间(引擎不区分它与第三方库——都是库函数;P5 起由宿主注入,core 不默认装配) */\n readonly cad?: StdlibNamespace\n}\n\n/**\n * 契约版本。破坏性变更 +1。加载第三方库时校验,不兼容即抛错。\n *\n * v3(P23,§5.2 / D11):`defineOp` 的实现边界统一为 Result 语义——实现可返回\n * `Result`(边界 unwrap,`err` → 抛错)、可抛错(归一为带 op 名的错误),\n * 也可照旧返回裸产物(透传);并新增 D11 `positional` 位置形态声明。\n * v2 → v3 是破坏性变更:按 v2 契约构建的库必须重新构建。\n */\nexport const CONTRACT_VERSION = 3\n\n/** 库函数签名(引擎视角:任意参数的普通函数,信息均匀化,不按名字分支)。 */\nexport type StdlibFn = (...args: any[]) => unknown\n\n/** 库命名空间:函数名 → 库函数(faijs 自带标准库与第三方库同构)。 */\nexport interface StdlibNamespace {\n [name: string]: StdlibFn\n}\n\n/**\n * 契约版本校验(P7 第三方库通道):加载时校验,不兼容即抛错(不静默降级)。\n * 第三方库模块若带 contractVersion 字段(与 CONTRACT_VERSION 对齐),必须匹配。\n *\n * @param lib - the library module whose contractVersion field is validated.\n */\nexport function assertContractVersion(lib: { contractVersion?: unknown }): void {\n if (lib.contractVersion !== undefined && lib.contractVersion !== CONTRACT_VERSION) {\n throw new Error(\n `[faijs] library contract version mismatch: got ${String(lib.contractVersion)}, expected ${CONTRACT_VERSION}`,\n )\n }\n}\n\n/**\n * brep 强制模式下的不支持错误(mesh-only 函数 / 输入不在 BREP 链)。\n *\n * 由分派路径抛出,CadRuntime 捕获后转换为 ExecutionResult.failedAt\n * (与旧解释器\"brep 模式立即返回 E_BREP_UNSUPPORTED,不静默回退 mesh\"的语义一致)。\n * P2 起定义在本层(零依赖),L3 API 命名空间与引擎共享同一类(instanceof 判定)。\n */\nexport class BrepUnsupportedError extends Error {\n /** The statement that triggered the unsupported operation, when available. */\n readonly stmt?: ExecutionAnchor\n constructor(message: string, stmt?: ExecutionAnchor) {\n super(message)\n this.name = 'BrepUnsupportedError'\n this.stmt = stmt\n }\n}\n\n/**\n * Unsupported error for mesh-forced mode (brep-only functions, or auto-mode\n * brep-only functions with a broken input chain).\n *\n * Symmetric to BrepUnsupportedError: thrown statically by the dispatch path,\n * caught by CadRuntime and converted into ExecutionResult.failedAt. A brep-only\n * function being unavailable in mesh mode is expected behavior (mode ×\n * implementation-set mismatch), not a bug fallback — the static-dispatch red\n * line (no try-catch, no runtime fallback) is unchanged.\n */\nexport class MeshUnsupportedError extends Error {\n /** The statement that triggered the unsupported operation, when available. */\n readonly stmt?: ExecutionAnchor\n constructor(message: string, stmt?: ExecutionAnchor) {\n super(message)\n this.name = 'MeshUnsupportedError'\n this.stmt = stmt\n }\n}\n\n// ── 状态容器 ──\n\n/**\n * The global runtime state singleton: backend configuration, the currently\n * executing statement, and the Shape identity tables (constructor registry,\n * identity slots, and Shape → PartName reverse lookup).\n */\nexport interface FaijsRuntimeState {\n readonly stateVersion: number\n /** 后端配置(configureBackends 写入) */\n backends: Backends | undefined\n /** 当前执行语句锚点(引擎在语句 fn 之前设置) */\n currentStmt: ExecutionAnchor | undefined\n /** Shape 构造器登记(isShape 的唯一依据) */\n readonly created: WeakSet<object>\n /** Shape 身份槽 */\n readonly slots: WeakMap<object, ShapeSlot>\n /** Shape → PartName 反查(keep 与 dependentsOf 用) */\n readonly shapeToName: WeakMap<object, PartName>\n /** 同语句 lineage 去重标记(define-op 写入;语句边界 setCurrentStmt 重置)。 */\n registeredStmtId: StmtId | undefined\n}\n\n// ── 函数 BREP 域(控制流放松方案 §5.6 / D13) ──\n// 本机函数体内的瞬态 BREP 句柄:进入函数时开启登记域,op 输出句柄写入时经\n// registerFunctionBrep 登记;函数返回后引擎取走域、释放除返回值可到达句柄外的全部\n// (对齐「调用方负责句柄生命周期」brep-ops.ts 与 meshesToStep 的 finally 模式)。\n// 全局计数与 DirectExecutor.userFunctionDepth 同步(单 runtime 场景,与 setCurrentStmt 同构)。\n\nlet functionBrepDepth = 0\nconst functionBrepDomain: unknown[] = []\n\n/** 进入函数 BREP 域(DirectExecutor 执行 local 语句 fn 之前调用)。 */\nexport function enterFunctionBrep(): void {\n if (functionBrepDepth === 0) functionBrepDomain.length = 0\n functionBrepDepth++\n}\n\n/** 退出函数 BREP 域(fn 结束后调用)。 */\nexport function exitFunctionBrep(): void {\n functionBrepDepth = Math.max(0, functionBrepDepth - 1)\n}\n\n/**\n * 登记函数域内新产生的 BREP 句柄(hook 点在 op 输出 shape 槽位写入处——fromBrep)。\n * 非函数域(depth = 0)时 no-op(零开销,现状路径不变)。\n * @param solid - 新产生的 OCCT 句柄。\n */\nexport function registerFunctionBrep(solid: unknown): void {\n if (functionBrepDepth > 0) functionBrepDomain.push(solid)\n}\n\n/**\n * 取走当前函数域的句柄登记表并清空(引擎在 fn 结束后调用,随后释放非返回值句柄)。\n * @returns 当前函数域的句柄登记表快照。\n */\nexport function takeFunctionBrepDomain(): unknown[] {\n const domain = [...functionBrepDomain]\n functionBrepDomain.length = 0\n return domain\n}\n\n/** Shape 身份槽(OCCT 句柄 + 面演化 + 拓扑命名 + 装配行为)。 */\nexport interface ShapeSlot {\n solid?: unknown\n faceEvolution?: Map<number, number[]>\n // 1.10 前置③:roleTable 槽字段已删除——权威落点在血缘图旁挂\n // (topology/naming/lineage.ts 的 recordOutput / tableOfPart),\n // 解析缓存 miss 由回走重算恢复(api/topo-resolve.ts)。\n /** mesh/primitive 面 hint 快照(§3.6 setTopology 注入时由 runtime 提炼写入,解析兜底用)。 */\n faceHints?: unknown\n behavior?: unknown\n}\n\n/**\n * 装配变换(引擎应用):求解在库(solveTransforms),应用与下游失效在引擎(P6)。\n * index = 成员下标(compound.children 内)。\n */\nexport interface AssemblyTransform {\n index: number\n quaternion: [number, number, number, number]\n pivot: [number, number, number]\n translation: [number, number, number]\n rotationMatrix: number[]\n}\n\n/**\n * do_assemble 的待应用变换登记(P6:求解 ≠ 传播)。\n * 库只把求解结果写到这里;引擎在语句执行后取走并应用 + 失效下游。\n */\nconst pendingAssemblyKeys = new Set<object>()\nconst pendingAssemblyTransforms = new WeakMap<object, AssemblyTransform[]>()\n\n/**\n * Register a compound's pending assembly transforms (called from the\n * do_assemble method body; accumulates across calls).\n *\n * @param c - the compound object that owns the transforms.\n * @param ts - the assembly transforms to append.\n */\nexport function setPendingAssemblyTransforms(c: object, ts: AssemblyTransform[]): void {\n if (ts.length === 0) return\n pendingAssemblyKeys.add(c)\n const existing = pendingAssemblyTransforms.get(c) ?? []\n pendingAssemblyTransforms.set(c, [...existing, ...ts])\n}\n\n/**\n * Take all pending assembly transforms and clear them (called by the engine's\n * afterStatement hook; consumed exactly once).\n *\n * @returns the list of compounds with their accumulated transforms.\n */\nexport function takePendingAssemblyTransforms(): Array<{ compound: object; transforms: AssemblyTransform[] }> {\n const out: Array<{ compound: object; transforms: AssemblyTransform[] }> = []\n for (const c of pendingAssemblyKeys) {\n const ts = pendingAssemblyTransforms.get(c)\n if (ts && ts.length > 0) out.push({ compound: c, transforms: ts })\n pendingAssemblyTransforms.delete(c)\n }\n pendingAssemblyKeys.clear()\n return out\n}\n\n// ── P3:运动副位姿登记(ExecutionResult.kinematics)──\n// 与 pendingAssemblyTransforms 同模式:库只把 solveKinematics 的 per-member 位姿\n// 写到这里,引擎在语句执行后取走并放入 ExecutionResult.kinematics(宿主动画/导出\n// 从 ExecutionResult 读取,不新增返回值消费语义)。\n\n/** 单个成员的位姿(position + faijs [x,y,z,w] rotation;与 api/assembly/joints 的 KinematicsPose 结构一致)。 */\nexport interface AssemblyKinematicsPose {\n position: [number, number, number]\n rotation: [number, number, number, number]\n}\n\n/** 位姿键:成员名 → AssemblyKinematicsPose(含恒等链根;键 = PartName)。 */\nexport type AssemblyKinematics = Record<string, AssemblyKinematicsPose>\n\nconst pendingKinematicsKeys = new Set<object>()\nconst pendingAssemblyKinematics = new WeakMap<object, AssemblyKinematics>()\n\n/**\n * Register a compound's pending assembly kinematics (P3; called from the\n * do_assemble/solve method body; accumulates across calls).\n *\n * @param c - the compound object that owns the kinematics.\n * @param kin - per-member poses keyed by member name (all members, incl. identity).\n */\nexport function setPendingAssemblyKinematics(c: object, kin: AssemblyKinematics): void {\n pendingKinematicsKeys.add(c)\n pendingAssemblyKinematics.set(c, kin)\n}\n\n/**\n * Take all pending assembly kinematics and clear them (called by the engine after\n * an assembly statement; consumed exactly once).\n *\n * @returns the list of compounds with their per-member kinematics.\n */\nexport function takePendingAssemblyKinematics(): Array<{ compound: object; kinematics: AssemblyKinematics }> {\n const out: Array<{ compound: object; kinematics: AssemblyKinematics }> = []\n for (const c of pendingKinematicsKeys) {\n const kin = pendingAssemblyKinematics.get(c)\n if (kin) out.push({ compound: c, kinematics: kin })\n pendingAssemblyKinematics.delete(c)\n }\n pendingKinematicsKeys.clear()\n return out\n}\n\nconst STATE_VERSION = 1\nconst KEY = '__FAICAD_FAIJS_RUNTIME__'\n\n/**\n * 获取全局状态(单例)。\n *\n * 挂在 globalThis 上是为了让\"两份 faijs 代码\"(宿主 bundle 一份、第三方库\n * 打进一份)共享同一份状态——两份 WeakSet 会导致 Shape 身份不通(几何孤岛)。\n * 构建期去重(external)是主手段,这里是兜底。\n *\n * @returns the shared global runtime state singleton.\n */\nexport function getRuntimeState(): FaijsRuntimeState {\n const g = globalThis as unknown as Record<string, unknown>\n const existing = g[KEY] as FaijsRuntimeState | undefined\n if (existing) {\n if (existing.stateVersion !== STATE_VERSION) {\n throw new Error(\n `[faijs] runtime state version mismatch: loaded=${existing.stateVersion}, expected=${STATE_VERSION}`,\n )\n }\n return existing\n }\n const created: FaijsRuntimeState = {\n stateVersion: STATE_VERSION,\n backends: undefined,\n currentStmt: undefined,\n created: new WeakSet<object>(),\n slots: new WeakMap<object, ShapeSlot>(),\n shapeToName: new WeakMap<object, PartName>(),\n registeredStmtId: undefined,\n }\n g[KEY] = created\n return created\n}\n\n// ── 后端配置读写 ──\n\n/**\n * 宿主在启动时调用一次,注入环境资源。\n *\n * @param backends - the host-injected environment resources.\n */\nexport function configureBackends(backends: Backends): void {\n getRuntimeState().backends = backends\n}\n\n/**\n * 读取后端配置。库函数通过它获取内核与宿主端口。\n *\n * 未配置时抛错——不要返回默认值兜底(配置是宿主的责任,缺失必须暴露)。\n *\n * @returns the configured backend resources.\n */\nexport function getBackends(): Backends {\n const b = getRuntimeState().backends\n if (!b) {\n throw new Error('[faijs] backends not configured: call configureBackends() before executing')\n }\n return b\n}\n\n// ── 当前执行语句(引擎内部状态)──\n\n/**\n * 引擎在语句 fn 之前调用(替换现状的 exec.currentStmt = source)。\n *\n * @param stmt - the statement currently being executed.\n */\nexport function setCurrentStmt(stmt: ExecutionAnchor | undefined): void {\n const s = getRuntimeState()\n // 语句边界:锚点变化(含语句结束置 undefined)时解除同语句 lineage 去重标记,\n // 使下一条语句(或同 id 复跑)重新获得注册资格;同一条语句内 TS 库函数\n // (如 cq-compat Workplane op)连续调用多个 defineOp 时共享锚点,标记保持\n // 生效,嵌套调用正确跳过注册(见 define-op 的 isOuter 判定)。\n if (s.currentStmt?.id !== stmt?.id) s.registeredStmtId = undefined\n s.currentStmt = stmt\n}\n\n/**\n * 读取当前执行语句。库函数不应调用它(F1)。\n *\n * @returns the currently executing statement, or undefined if none.\n */\nexport function getCurrentStmt(): ExecutionAnchor | undefined {\n return getRuntimeState().currentStmt\n}\n\n// ── Shape 身份表 ──\n\n/**\n * Shape → 变量名反查(keep 与 dependentsOf 依赖)。\n *\n * @param shape - the shape to look up.\n * @returns the part name registered for the shape, or undefined.\n */\nexport function nameOf(shape: object): PartName | undefined {\n return getRuntimeState().shapeToName.get(shape)\n}\n\n/**\n * 登记 Shape → 变量名映射。\n *\n * @param shape - the shape to register.\n * @param name - the part name to associate with the shape.\n */\nexport function setName(shape: object, name: PartName): void {\n getRuntimeState().shapeToName.set(shape, name)\n}\n\n// ── keep 声明(库函数体调用)──\n\n/**\n * 登记回调类型。由 DirectExecutor 在装配时注入(保持 runtime-state 零依赖)。\n */\nexport type KeepSink = (stmtId: string, names: PartName[], hidden: boolean) => void\n\nlet keepSink: KeepSink | undefined\n\n/**\n * 引擎装配 keep 的落地目标(DirectExecutor.registerKeep)。\n *\n * @param sink - the keep callback registered by the engine, or undefined to clear.\n */\nexport function setKeepSink(sink: KeepSink | undefined): void {\n keepSink = sink\n}\n\n/**\n * 函数体 keep 声明:声明保留这些 Shape 对应的变量(可见)。\n *\n * 库作者在库函数体内调用:\n * ```ts\n * import { keep } from '@faicad/faijs'\n * export function group(params) {\n * keep(...params.members)\n * return compound(params.members)\n * }\n * ```\n *\n * 归属到\"当前正在执行的语句\"(引擎在 fn 之前 setCurrentStmt)。\n * 未登记在 shapeToName 的对象(库内部的自定义对象)被忽略——这是刻意的静默。\n *\n * @param shapes - the shapes whose corresponding variables should be kept.\n */\nexport function keep(...shapes: unknown[]): void {\n registerKeep(shapes, false)\n}\n\n/**\n * 函数体 keep 声明:保留但 canvas 不渲染(布尔系函数的源)。\n *\n * @param shapes - the shapes whose corresponding variables should be kept hidden.\n */\nexport function keepHidden(...shapes: unknown[]): void {\n registerKeep(shapes, true)\n}\n\nfunction registerKeep(shapes: unknown[], hidden: boolean): void {\n const stmt = getRuntimeState().currentStmt\n if (!stmt || !keepSink) return\n const names: PartName[] = []\n for (const s of shapes) {\n if (s === null || typeof s !== 'object') continue\n const n = nameOf(s)\n if (n !== undefined) names.push(n)\n }\n if (names.length === 0) return\n keepSink(String(stmt.id), names, hidden)\n}\n"]}
1
+ {"version":3,"file":"runtime-state.js","sourceRoot":"","sources":["../src/runtime-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * runtime-state — 全局运行时状态锚点(零依赖层)\n *\n *\n * 本模块位于 L0+(零运行时依赖),是 L3 API 面(core/src/api,原 stdlib)与\n * cad-runtime(L2)之间唯一的共享状态。**放在这一层是为了避免循环依赖**:\n * api/ 不能 import cad-runtime(cad-runtime/api-namespace.ts 已经 import 了 api/)。\n *\n * 承载三类状态:\n * 1. Backends —— 宿主注入的环境资源(内核 / 端口 / 模式 / 标准库命名空间)\n * 2. 当前执行语句 —— keep() 归属用(引擎在语句 fn 之前设置)\n * 3. Shape 身份表 —— 构造器登记(isShape 依据)与 Shape→PartName 反查\n *\n * ⚠️ 依赖方向红线:本文件不得 import 任何 src/ 下的模块(只可 import type)。\n */\n\nimport type { PartName, StmtId } from './identity'\n\n/**\n * Lightweight execution anchor — carries only the fields consumed by\n * library functions via getCurrentStmt(): `id` (StmtId), `outputs` (PartName[]),\n * `callee`, and `hasAssignment`. The DirectExecutor creates these from\n * line-number + writes.\n */\nexport interface ExecutionAnchor {\n readonly id: string\n readonly outputs: PartName[]\n readonly callee?: string\n readonly hasAssignment?: boolean\n}\n\n// ── 后端配置(宿主注入的环境资源)──\n\n/**\n * 执行模式(与 src/cad-runtime/ports.ts 的 ExecutionMode 保持一致)。\n *\n * 此处重复定义是为了保持本模块零依赖。一致性由 `cad-runtime/runtime.ts:460`\n * (`mode: this.mode`,`ExecutionMode` → 本类型的赋值)在编译期间接钉住:\n * 只给 `ExecutionMode` 加成员而不加到这里 → 该行 tsc 报错。\n * (2026-09-22 核实:无独立守卫测试。)\n */\nexport type RuntimeExecutionMode = 'auto' | 'brep' | 'mesh'\n\n/** 宿主注入的环境资源。字段类型用宽松结构,避免本模块依赖具体实现。 */\nexport interface Backends {\n /** 契约版本(装配期校验,不兼容即抛错) */\n readonly contractVersion: number\n /** 执行配置(可变对象,宿主可在运行期切换) */\n readonly config: {\n mode: RuntimeExecutionMode\n /** 当前 BREP 引擎 id(注册表首个注册者;未注册为 null)。能力路由读(§8.4)。 */\n brepEngineId?: string | null\n /**\n * 当前引擎能力声明(宽松结构,零依赖)。能力路由读(§8.4)。\n *\n * `evolution` = 本引擎**实际提供**的 `*WithHistory` 核函数名名单\n * (`brep/engine/types.ts` 的 `BrepEvolutionKind`)。**不是**族级布尔——\n * 族级布尔会多报能力、使静态判定失效(Phase 0.2)。\n * 本模块须零依赖,故此处只写 `readonly string[]`;权威类型见\n * `BrepCapabilities`,消费侧由 `backend-dispatch.engineCapabilitySet` 归一化。\n */\n brepCapabilities?: {\n evolution?: readonly string[]\n /**\n * 非演化内核方法名(D5):本引擎**实际提供**的 L1 中立方法名\n * (`getBoundingBox` / `getVolume` / `getSurfaceArea` / `getLength` /\n * `getCenterOfMass` 等)。2026-09-24 narrowing plan §2.4:与\n * `backend-dispatch.EngineCapabilitiesLike` 对齐(该类型有 `methods`,\n * 运行时配置镜像此前缺失——非字面量赋值不做 excess property 检查,\n * `methods` 判定\"能用但没被契约钉住\")。\n */\n methods?: readonly string[]\n heal?: boolean\n directEdit?: boolean\n advSurface?: boolean\n assembly?: boolean\n meshLift?: boolean\n }\n partTransform?: { position: [number, number, number]; scale?: [number, number, number] }\n }\n /** 几何后端。brep 引擎异步初始化 → 用 getter。 */\n readonly kernel: {\n readonly brep: unknown | null\n readonly csg: unknown | undefined\n readonly sdf: unknown | undefined\n }\n /** 宿主端口(透传 HostPorts) */\n readonly fonts: unknown\n readonly texture: unknown\n readonly assets: unknown\n readonly events: unknown\n /** faijs 自带标准库命名空间(引擎不区分它与第三方库——都是库函数;P5 起由宿主注入,core 不默认装配) */\n readonly cad?: StdlibNamespace\n}\n\n/**\n * 契约版本。破坏性变更 +1。加载第三方库时校验,不兼容即抛错。\n *\n * v3(P23,§5.2 / D11):`defineOp` 的实现边界统一为 Result 语义——实现可返回\n * `Result`(边界 unwrap,`err` → 抛错)、可抛错(归一为带 op 名的错误),\n * 也可照旧返回裸产物(透传);并新增 D11 `positional` 位置形态声明。\n * v2 → v3 是破坏性变更:按 v2 契约构建的库必须重新构建。\n */\nexport const CONTRACT_VERSION = 3\n\n/** 库函数签名(引擎视角:任意参数的普通函数,信息均匀化,不按名字分支)。 */\nexport type StdlibFn = (...args: any[]) => unknown\n\n/** 库命名空间:函数名 → 库函数(faijs 自带标准库与第三方库同构)。 */\nexport interface StdlibNamespace {\n [name: string]: StdlibFn\n}\n\n/**\n * 契约版本校验(P7 第三方库通道):加载时校验,不兼容即抛错(不静默降级)。\n * 第三方库模块若带 contractVersion 字段(与 CONTRACT_VERSION 对齐),必须匹配。\n *\n * @param lib - the library module whose contractVersion field is validated.\n */\nexport function assertContractVersion(lib: { contractVersion?: unknown }): void {\n if (lib.contractVersion !== undefined && lib.contractVersion !== CONTRACT_VERSION) {\n throw new Error(\n `[faijs] library contract version mismatch: got ${String(lib.contractVersion)}, expected ${CONTRACT_VERSION}`,\n )\n }\n}\n\n/**\n * brep 强制模式下的不支持错误(mesh-only 函数 / 输入不在 BREP 链)。\n *\n * 由分派路径抛出,CadRuntime 捕获后转换为 ExecutionResult.failedAt\n * (与旧解释器\"brep 模式立即返回 E_BREP_UNSUPPORTED,不静默回退 mesh\"的语义一致)。\n * P2 起定义在本层(零依赖),L3 API 命名空间与引擎共享同一类(instanceof 判定)。\n */\nexport class BrepUnsupportedError extends Error {\n /** The statement that triggered the unsupported operation, when available. */\n readonly stmt?: ExecutionAnchor\n constructor(message: string, stmt?: ExecutionAnchor) {\n super(message)\n this.name = 'BrepUnsupportedError'\n this.stmt = stmt\n }\n}\n\n/**\n * Unsupported error for mesh-forced mode (brep-only functions, or auto-mode\n * brep-only functions with a broken input chain).\n *\n * Symmetric to BrepUnsupportedError: thrown statically by the dispatch path,\n * caught by CadRuntime and converted into ExecutionResult.failedAt. A brep-only\n * function being unavailable in mesh mode is expected behavior (mode ×\n * implementation-set mismatch), not a bug fallback — the static-dispatch red\n * line (no try-catch, no runtime fallback) is unchanged.\n */\nexport class MeshUnsupportedError extends Error {\n /** The statement that triggered the unsupported operation, when available. */\n readonly stmt?: ExecutionAnchor\n constructor(message: string, stmt?: ExecutionAnchor) {\n super(message)\n this.name = 'MeshUnsupportedError'\n this.stmt = stmt\n }\n}\n\n// ── 状态容器 ──\n\n/**\n * The global runtime state singleton: backend configuration, the currently\n * executing statement, and the Shape identity tables (constructor registry,\n * identity slots, and Shape → PartName reverse lookup).\n */\nexport interface FaijsRuntimeState {\n readonly stateVersion: number\n /** 后端配置(configureBackends 写入) */\n backends: Backends | undefined\n /** 当前执行语句锚点(引擎在语句 fn 之前设置) */\n currentStmt: ExecutionAnchor | undefined\n /** Shape 构造器登记(isShape 的唯一依据) */\n readonly created: WeakSet<object>\n /** Shape 身份槽 */\n readonly slots: WeakMap<object, ShapeSlot>\n /** Shape → PartName 反查(keep 与 dependentsOf 用) */\n readonly shapeToName: WeakMap<object, PartName>\n /** 同语句 lineage 去重标记(define-op 写入;语句边界 setCurrentStmt 重置)。 */\n registeredStmtId: StmtId | undefined\n}\n\n// ── 函数 BREP 域(控制流放松方案 §5.6 / D13) ──\n// 本机函数体内的瞬态 BREP 句柄:进入函数时开启登记域,op 输出句柄写入时经\n// registerFunctionBrep 登记;函数返回后引擎取走域、释放除返回值可到达句柄外的全部\n// (对齐「调用方负责句柄生命周期」brep-ops.ts 与 meshesToStep 的 finally 模式)。\n// 全局计数与 DirectExecutor.userFunctionDepth 同步(单 runtime 场景,与 setCurrentStmt 同构)。\n\nlet functionBrepDepth = 0\nconst functionBrepDomain: unknown[] = []\n\n/** 进入函数 BREP 域(DirectExecutor 执行 local 语句 fn 之前调用)。 */\nexport function enterFunctionBrep(): void {\n if (functionBrepDepth === 0) functionBrepDomain.length = 0\n functionBrepDepth++\n}\n\n/** 退出函数 BREP 域(fn 结束后调用)。 */\nexport function exitFunctionBrep(): void {\n functionBrepDepth = Math.max(0, functionBrepDepth - 1)\n}\n\n/**\n * 登记函数域内新产生的 BREP 句柄(hook 点在 op 输出 shape 槽位写入处——fromBrep)。\n * 非函数域(depth = 0)时 no-op(零开销,现状路径不变)。\n * @param solid - 新产生的 OCCT 句柄。\n */\nexport function registerFunctionBrep(solid: unknown): void {\n if (functionBrepDepth > 0) functionBrepDomain.push(solid)\n}\n\n/**\n * 取走当前函数域的句柄登记表并清空(引擎在 fn 结束后调用,随后释放非返回值句柄)。\n * @returns 当前函数域的句柄登记表快照。\n */\nexport function takeFunctionBrepDomain(): unknown[] {\n const domain = [...functionBrepDomain]\n functionBrepDomain.length = 0\n return domain\n}\n\n/** Shape 身份槽(OCCT 句柄 + 面演化 + 拓扑命名 + 装配行为)。 */\nexport interface ShapeSlot {\n solid?: unknown\n faceEvolution?: Map<number, number[]>\n // 1.10 前置③:roleTable 槽字段已删除——权威落点在血缘图旁挂\n // (topology/naming/lineage.ts 的 recordOutput / tableOfPart),\n // 解析缓存 miss 由回走重算恢复(api/topo-resolve.ts)。\n /** mesh/primitive 面 hint 快照(§3.6 setTopology 注入时由 runtime 提炼写入,解析兜底用)。 */\n faceHints?: unknown\n behavior?: unknown\n}\n\n/**\n * 装配变换(引擎应用):求解在库(solveTransforms),应用与下游失效在引擎(P6)。\n * index = 成员下标(compound.children 内)。\n */\nexport interface AssemblyTransform {\n index: number\n quaternion: [number, number, number, number]\n pivot: [number, number, number]\n translation: [number, number, number]\n rotationMatrix: number[]\n}\n\n/**\n * do_assemble 的待应用变换登记(P6:求解 ≠ 传播)。\n * 库只把求解结果写到这里;引擎在语句执行后取走并应用 + 失效下游。\n */\nconst pendingAssemblyKeys = new Set<object>()\nconst pendingAssemblyTransforms = new WeakMap<object, AssemblyTransform[]>()\n\n/**\n * Register a compound's pending assembly transforms (called from the\n * do_assemble method body; accumulates across calls).\n *\n * @param c - the compound object that owns the transforms.\n * @param ts - the assembly transforms to append.\n */\nexport function setPendingAssemblyTransforms(c: object, ts: AssemblyTransform[]): void {\n if (ts.length === 0) return\n pendingAssemblyKeys.add(c)\n const existing = pendingAssemblyTransforms.get(c) ?? []\n pendingAssemblyTransforms.set(c, [...existing, ...ts])\n}\n\n/**\n * Take all pending assembly transforms and clear them (called by the engine's\n * afterStatement hook; consumed exactly once).\n *\n * @returns the list of compounds with their accumulated transforms.\n */\nexport function takePendingAssemblyTransforms(): Array<{ compound: object; transforms: AssemblyTransform[] }> {\n const out: Array<{ compound: object; transforms: AssemblyTransform[] }> = []\n for (const c of pendingAssemblyKeys) {\n const ts = pendingAssemblyTransforms.get(c)\n if (ts && ts.length > 0) out.push({ compound: c, transforms: ts })\n pendingAssemblyTransforms.delete(c)\n }\n pendingAssemblyKeys.clear()\n return out\n}\n\n// ── P3:运动副位姿登记(ExecutionResult.kinematics)──\n// 与 pendingAssemblyTransforms 同模式:库只把 solveKinematics 的 per-member 位姿\n// 写到这里,引擎在语句执行后取走并放入 ExecutionResult.kinematics(宿主动画/导出\n// 从 ExecutionResult 读取,不新增返回值消费语义)。\n\n/** 单个成员的位姿(position + faijs [x,y,z,w] rotation;与 api/assembly/joints 的 KinematicsPose 结构一致)。 */\nexport interface AssemblyKinematicsPose {\n position: [number, number, number]\n rotation: [number, number, number, number]\n}\n\n/** 位姿键:成员名 → AssemblyKinematicsPose(含恒等链根;键 = PartName)。 */\nexport type AssemblyKinematics = Record<string, AssemblyKinematicsPose>\n\nconst pendingKinematicsKeys = new Set<object>()\nconst pendingAssemblyKinematics = new WeakMap<object, AssemblyKinematics>()\n\n/**\n * Register a compound's pending assembly kinematics (P3; called from the\n * do_assemble/solve method body; accumulates across calls).\n *\n * @param c - the compound object that owns the kinematics.\n * @param kin - per-member poses keyed by member name (all members, incl. identity).\n */\nexport function setPendingAssemblyKinematics(c: object, kin: AssemblyKinematics): void {\n pendingKinematicsKeys.add(c)\n pendingAssemblyKinematics.set(c, kin)\n}\n\n/**\n * Take all pending assembly kinematics and clear them (called by the engine after\n * an assembly statement; consumed exactly once).\n *\n * @returns the list of compounds with their per-member kinematics.\n */\nexport function takePendingAssemblyKinematics(): Array<{ compound: object; kinematics: AssemblyKinematics }> {\n const out: Array<{ compound: object; kinematics: AssemblyKinematics }> = []\n for (const c of pendingKinematicsKeys) {\n const kin = pendingAssemblyKinematics.get(c)\n if (kin) out.push({ compound: c, kinematics: kin })\n pendingAssemblyKinematics.delete(c)\n }\n pendingKinematicsKeys.clear()\n return out\n}\n\nconst STATE_VERSION = 1\nconst KEY = '__FAICAD_FAIJS_RUNTIME__'\n\n/**\n * 获取全局状态(单例)。\n *\n * 挂在 globalThis 上是为了让\"两份 faijs 代码\"(宿主 bundle 一份、第三方库\n * 打进一份)共享同一份状态——两份 WeakSet 会导致 Shape 身份不通(几何孤岛)。\n * 构建期去重(external)是主手段,这里是兜底。\n *\n * @returns the shared global runtime state singleton.\n */\nexport function getRuntimeState(): FaijsRuntimeState {\n const g = globalThis as unknown as Record<string, unknown>\n const existing = g[KEY] as FaijsRuntimeState | undefined\n if (existing) {\n if (existing.stateVersion !== STATE_VERSION) {\n throw new Error(\n `[faijs] runtime state version mismatch: loaded=${existing.stateVersion}, expected=${STATE_VERSION}`,\n )\n }\n return existing\n }\n const created: FaijsRuntimeState = {\n stateVersion: STATE_VERSION,\n backends: undefined,\n currentStmt: undefined,\n created: new WeakSet<object>(),\n slots: new WeakMap<object, ShapeSlot>(),\n shapeToName: new WeakMap<object, PartName>(),\n registeredStmtId: undefined,\n }\n g[KEY] = created\n return created\n}\n\n// ── 后端配置读写 ──\n\n/**\n * 宿主在启动时调用一次,注入环境资源。\n *\n * @param backends - the host-injected environment resources.\n */\nexport function configureBackends(backends: Backends): void {\n getRuntimeState().backends = backends\n}\n\n/**\n * 读取后端配置。库函数通过它获取内核与宿主端口。\n *\n * 未配置时抛错——不要返回默认值兜底(配置是宿主的责任,缺失必须暴露)。\n *\n * @returns the configured backend resources.\n */\nexport function getBackends(): Backends {\n const b = getRuntimeState().backends\n if (!b) {\n throw new Error('[faijs] backends not configured: call configureBackends() before executing')\n }\n return b\n}\n\n// ── 当前执行语句(引擎内部状态)──\n\n/**\n * 引擎在语句 fn 之前调用(替换现状的 exec.currentStmt = source)。\n *\n * @param stmt - the statement currently being executed.\n */\nexport function setCurrentStmt(stmt: ExecutionAnchor | undefined): void {\n const s = getRuntimeState()\n // 语句边界:锚点变化(含语句结束置 undefined)时解除同语句 lineage 去重标记,\n // 使下一条语句(或同 id 复跑)重新获得注册资格;同一条语句内 TS 库函数\n // (如 cq-compat Workplane op)连续调用多个 defineOp 时共享锚点,标记保持\n // 生效,嵌套调用正确跳过注册(见 define-op 的 isOuter 判定)。\n if (s.currentStmt?.id !== stmt?.id) s.registeredStmtId = undefined\n s.currentStmt = stmt\n}\n\n/**\n * 读取当前执行语句。库函数不应调用它(F1)。\n *\n * @returns the currently executing statement, or undefined if none.\n */\nexport function getCurrentStmt(): ExecutionAnchor | undefined {\n return getRuntimeState().currentStmt\n}\n\n// ── Shape 身份表 ──\n\n/**\n * Shape → 变量名反查(keep 与 dependentsOf 依赖)。\n *\n * @param shape - the shape to look up.\n * @returns the part name registered for the shape, or undefined.\n */\nexport function nameOf(shape: object): PartName | undefined {\n return getRuntimeState().shapeToName.get(shape)\n}\n\n/**\n * 登记 Shape → 变量名映射。\n *\n * @param shape - the shape to register.\n * @param name - the part name to associate with the shape.\n */\nexport function setName(shape: object, name: PartName): void {\n getRuntimeState().shapeToName.set(shape, name)\n}\n\n// ── keep 声明(库函数体调用)──\n\n/**\n * 登记回调类型。由 DirectExecutor 在装配时注入(保持 runtime-state 零依赖)。\n */\nexport type KeepSink = (stmtId: string, names: PartName[], hidden: boolean) => void\n\nlet keepSink: KeepSink | undefined\n\n/**\n * 引擎装配 keep 的落地目标(DirectExecutor.registerKeep)。\n *\n * @param sink - the keep callback registered by the engine, or undefined to clear.\n */\nexport function setKeepSink(sink: KeepSink | undefined): void {\n keepSink = sink\n}\n\n/**\n * 函数体 keep 声明:声明保留这些 Shape 对应的变量(可见)。\n *\n * 库作者在库函数体内调用:\n * ```ts\n * import { keep } from '@faicad/faijs'\n * export function group(params) {\n * keep(...params.members)\n * return compound(params.members)\n * }\n * ```\n *\n * 归属到\"当前正在执行的语句\"(引擎在 fn 之前 setCurrentStmt)。\n * 未登记在 shapeToName 的对象(库内部的自定义对象)被忽略——这是刻意的静默。\n *\n * @param shapes - the shapes whose corresponding variables should be kept.\n */\nexport function keep(...shapes: unknown[]): void {\n registerKeep(shapes, false)\n}\n\n/**\n * 函数体 keep 声明:保留但 canvas 不渲染(布尔系函数的源)。\n *\n * @param shapes - the shapes whose corresponding variables should be kept hidden.\n */\nexport function keepHidden(...shapes: unknown[]): void {\n registerKeep(shapes, true)\n}\n\nfunction registerKeep(shapes: unknown[], hidden: boolean): void {\n const stmt = getRuntimeState().currentStmt\n if (!stmt || !keepSink) return\n const names: PartName[] = []\n for (const s of shapes) {\n if (s === null || typeof s !== 'object') continue\n const n = nameOf(s)\n if (n !== undefined) names.push(n)\n }\n if (names.length === 0) return\n keepSink(String(stmt.id), names, hidden)\n}\n\n// ── 文件单位登记(unit-system §10.6:load op 的 detectedUnit 回传)──\n// 与 pendingAssemblyTransforms 同模式:load op 把读出的文件声明单位写到这里,\n// 引擎在语句执行后取走并按 part 名放进 ExecutionResult.detectedUnits(宿主写进\n// LoadedFileModel.sourceUnit,不新增返回值消费语义)。\n\n/** Per-part declared file units (key = PartName; null-never — absent key = unknown). */\nexport type DetectedUnits = Map<PartName, string>\n\nconst pendingDetectedUnits = new Map<PartName, string>()\n\n/**\n * Register a part's declared file unit (called from the load op body; the unit\n * is metadata only — coordinates are already base-unit, never re-scaled).\n *\n * @param partName - the variable name the loaded shape will be bound to.\n * @param unit - the file's own declared unit (faijs UnitName).\n */\nexport function setPendingDetectedUnit(partName: PartName, unit: string): void {\n pendingDetectedUnits.set(partName, unit)\n}\n\n/**\n * Take all pending detected units and clear them (engine, after each statement;\n * consumed exactly once).\n *\n * @returns a fresh Map of part name → declared unit, copied from the pending\n * store and cleared so it is consumed exactly once.\n */\nexport function takePendingDetectedUnits(): DetectedUnits {\n const out = new Map(pendingDetectedUnits)\n pendingDetectedUnits.clear()\n return out\n}\n"]}
package/dist/sdk.d.ts CHANGED
@@ -26,7 +26,7 @@ export { getKernel, getBrepApi, meshHandle, fromHandle } from './brep/handle-bri
26
26
  export type { MeshHandleOptions } from './brep/handle-bridge.js';
27
27
  export { BREP_ENGINE_IDS, type BrepEngineId, type BrepHandle } from './brep/engine/types.js';
28
28
  export type { BrepEngineApi } from './brep/engine/primitives.js';
29
- export { defineOp, assertLibConforms, hasDualOp, DUAL_OP_META } from './define-op.js';
29
+ export { defineOp, assertLibConforms, hasDualOp, dualOpMetaOf, DUAL_OP_META } from './define-op.js';
30
30
  export type { DualOpMeta, DualOpOptions, DualOpImpls, MeshImpl, BrepImpl, MeshData, BrepResult, } from './define-op.js';
31
31
  export type { BrepCapabilityName } from './cad-runtime/backend-dispatch.js';
32
32
  //# sourceMappingURL=sdk.d.ts.map
package/dist/sdk.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,EACV,OAAO,EACP,MAAM,EACN,YAAY,EACZ,OAAO,EACP,UAAU,GACX,MAAM,SAAS,CAAA;AAChB,YAAY,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,QAAQ,EACR,UAAU,GACX,MAAM,SAAS,CAAA;AAChB,YAAY,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAIzC,OAAO,EACL,IAAI,EACJ,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,QAAQ,EACR,oBAAoB,EACpB,QAAQ,EACR,eAAe,EACf,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAA;AAMxB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACpF,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACzF,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAQ7D,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAClF,YAAY,EACV,UAAU,EACV,aAAa,EACb,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,UAAU,GACX,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA"}
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,EACV,OAAO,EACP,MAAM,EACN,YAAY,EACZ,OAAO,EACP,UAAU,GACX,MAAM,SAAS,CAAA;AAChB,YAAY,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,QAAQ,EACR,UAAU,GACX,MAAM,SAAS,CAAA;AAChB,YAAY,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAIzC,OAAO,EACL,IAAI,EACJ,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,QAAQ,EACR,oBAAoB,EACpB,QAAQ,EACR,eAAe,EACf,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAA;AAMxB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACpF,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACzF,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAQ7D,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAChG,YAAY,EACV,UAAU,EACV,aAAa,EACb,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,UAAU,GACX,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA"}
package/dist/sdk.js CHANGED
@@ -31,5 +31,5 @@ export { BREP_ENGINE_IDS } from './brep/engine/types.js';
31
31
  // 与 type-only mesh、brep 类型——零 heavy 依赖,dist/sdk.js 守卫继续通过。
32
32
  // 第三方库作者用 defineOp 声明实现集合;dispatchPath 不再直接导出——
33
33
  // 分派由 defineOp 包装器内部调用(规则仍是引擎 backend-dispatch.ts 单点)。
34
- export { defineOp, assertLibConforms, hasDualOp, DUAL_OP_META } from './define-op.js';
34
+ export { defineOp, assertLibConforms, hasDualOp, dualOpMetaOf, DUAL_OP_META } from './define-op.js';
35
35
  //# sourceMappingURL=sdk.js.map
package/dist/sdk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,iDAAiD;AAEjD,OAAO,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,EACV,OAAO,EACP,MAAM,EACN,YAAY,EACZ,OAAO,EACP,UAAU,GACX,MAAM,SAAS,CAAA;AAUhB,oDAAoD;AAEpD,OAAO,EACL,IAAI,EACJ,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAA;AAUxB,wCAAwC;AACxC,8EAA8E;AAC9E,oCAAoC;AAEpC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEpF,OAAO,EAAE,eAAe,EAAsC,MAAM,qBAAqB,CAAA;AAGzF,8CAA8C;AAC9C,gFAAgF;AAChF,2DAA2D;AAC3D,gDAAgD;AAChD,uDAAuD;AAEvD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA","sourcesContent":["/**\n * sdk — 第三方库开发面(F3 / roadmap V2.2)\n *\n *\n * 第三方库模块(`import * as gear from 'my-lib'` 的目标)用它开发:\n * ```ts\n * import { solid, fromBrep, isShape, keep, getBackends, CONTRACT_VERSION } from '@faicad/faijs/sdk'\n * export const contractVersion = CONTRACT_VERSION\n * export function makeSpurGear(params) { ... }\n * ```\n *\n * 本入口**零 heavy 运行时依赖**:只 re-export runtime-state(L0+ 零依赖锚点层)\n * 与 stdlib/shape(构造器 + 身份表,仅 type-import mesh 类型)。\n * 值导入闭包不含 three / occt-wasm / manifold / node:*——由守卫测试保证\n * (dist/sdk.js 静态 import 扫描)。\n *\n * 与主入口的关系:sdk 是主入口的**子集 + 极薄 re-export**,供库作者按需导入;\n * 主入口 / browser / stdlib 不受影响(additive)。\n */\n\n// ── 构造器与身份表(stdlib/shape:类型化构造器 + BREP 句柄登记) ──\n\nexport {\n solid,\n fromBrep,\n compound,\n isShape,\n isCompound,\n hasBrep,\n brepOf,\n nameOfShapes,\n getSlot,\n ensureSlot,\n} from './shape'\nexport type {\n SolidShape,\n CompoundShape,\n ShapeKind,\n StdShape,\n BrepHolder,\n} from './shape'\nexport type { Shape } from './mesh/types'\n\n// ── 运行时状态锚点(零依赖层:keep / backends / 契约版本 / 错误类型) ──\n\nexport {\n keep,\n keepHidden,\n getBackends,\n configureBackends,\n assertContractVersion,\n CONTRACT_VERSION,\n BrepUnsupportedError,\n MeshUnsupportedError,\n} from './runtime-state'\nexport type {\n Backends,\n RuntimeExecutionMode,\n StdlibFn,\n StdlibNamespace,\n ShapeSlot,\n KeepSink,\n} from './runtime-state'\n\n// ── BREP 桥接(B1:第三方库造 BREP 产物的三角化入口) ──\n// handle-bridge 只 import runtime-state / stdlib/shape / type-only mesh/types,\n// 零 heavy 依赖——dist/sdk.js 守卫测试继续通过。\n\nexport { getKernel, getBrepApi, meshHandle, fromHandle } from './brep/handle-bridge'\nexport type { MeshHandleOptions } from './brep/handle-bridge'\nexport { BREP_ENGINE_IDS, type BrepEngineId, type BrepHandle } from './brep/engine/types'\nexport type { BrepEngineApi } from './brep/engine/primitives'\n\n// ── 双路径实现声明(D 面契约:mesh 必选、BREP 可选;几何函数专用) ──\n// define-op 只依赖 runtime-state / stdlib/shape / handle-bridge / backend-dispatch\n// 与 type-only mesh、brep 类型——零 heavy 依赖,dist/sdk.js 守卫继续通过。\n// 第三方库作者用 defineOp 声明实现集合;dispatchPath 不再直接导出——\n// 分派由 defineOp 包装器内部调用(规则仍是引擎 backend-dispatch.ts 单点)。\n\nexport { defineOp, assertLibConforms, hasDualOp, DUAL_OP_META } from './define-op'\nexport type {\n DualOpMeta,\n DualOpOptions,\n DualOpImpls,\n MeshImpl,\n BrepImpl,\n MeshData,\n BrepResult,\n} from './define-op'\nexport type { BrepCapabilityName } from './cad-runtime/backend-dispatch'\n"]}
1
+ {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,iDAAiD;AAEjD,OAAO,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,EACV,OAAO,EACP,MAAM,EACN,YAAY,EACZ,OAAO,EACP,UAAU,GACX,MAAM,SAAS,CAAA;AAUhB,oDAAoD;AAEpD,OAAO,EACL,IAAI,EACJ,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAA;AAUxB,wCAAwC;AACxC,8EAA8E;AAC9E,oCAAoC;AAEpC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEpF,OAAO,EAAE,eAAe,EAAsC,MAAM,qBAAqB,CAAA;AAGzF,8CAA8C;AAC9C,gFAAgF;AAChF,2DAA2D;AAC3D,gDAAgD;AAChD,uDAAuD;AAEvD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA","sourcesContent":["/**\n * sdk — 第三方库开发面(F3 / roadmap V2.2)\n *\n *\n * 第三方库模块(`import * as gear from 'my-lib'` 的目标)用它开发:\n * ```ts\n * import { solid, fromBrep, isShape, keep, getBackends, CONTRACT_VERSION } from '@faicad/faijs/sdk'\n * export const contractVersion = CONTRACT_VERSION\n * export function makeSpurGear(params) { ... }\n * ```\n *\n * 本入口**零 heavy 运行时依赖**:只 re-export runtime-state(L0+ 零依赖锚点层)\n * 与 stdlib/shape(构造器 + 身份表,仅 type-import mesh 类型)。\n * 值导入闭包不含 three / occt-wasm / manifold / node:*——由守卫测试保证\n * (dist/sdk.js 静态 import 扫描)。\n *\n * 与主入口的关系:sdk 是主入口的**子集 + 极薄 re-export**,供库作者按需导入;\n * 主入口 / browser / stdlib 不受影响(additive)。\n */\n\n// ── 构造器与身份表(stdlib/shape:类型化构造器 + BREP 句柄登记) ──\n\nexport {\n solid,\n fromBrep,\n compound,\n isShape,\n isCompound,\n hasBrep,\n brepOf,\n nameOfShapes,\n getSlot,\n ensureSlot,\n} from './shape'\nexport type {\n SolidShape,\n CompoundShape,\n ShapeKind,\n StdShape,\n BrepHolder,\n} from './shape'\nexport type { Shape } from './mesh/types'\n\n// ── 运行时状态锚点(零依赖层:keep / backends / 契约版本 / 错误类型) ──\n\nexport {\n keep,\n keepHidden,\n getBackends,\n configureBackends,\n assertContractVersion,\n CONTRACT_VERSION,\n BrepUnsupportedError,\n MeshUnsupportedError,\n} from './runtime-state'\nexport type {\n Backends,\n RuntimeExecutionMode,\n StdlibFn,\n StdlibNamespace,\n ShapeSlot,\n KeepSink,\n} from './runtime-state'\n\n// ── BREP 桥接(B1:第三方库造 BREP 产物的三角化入口) ──\n// handle-bridge 只 import runtime-state / stdlib/shape / type-only mesh/types,\n// 零 heavy 依赖——dist/sdk.js 守卫测试继续通过。\n\nexport { getKernel, getBrepApi, meshHandle, fromHandle } from './brep/handle-bridge'\nexport type { MeshHandleOptions } from './brep/handle-bridge'\nexport { BREP_ENGINE_IDS, type BrepEngineId, type BrepHandle } from './brep/engine/types'\nexport type { BrepEngineApi } from './brep/engine/primitives'\n\n// ── 双路径实现声明(D 面契约:mesh 必选、BREP 可选;几何函数专用) ──\n// define-op 只依赖 runtime-state / stdlib/shape / handle-bridge / backend-dispatch\n// 与 type-only mesh、brep 类型——零 heavy 依赖,dist/sdk.js 守卫继续通过。\n// 第三方库作者用 defineOp 声明实现集合;dispatchPath 不再直接导出——\n// 分派由 defineOp 包装器内部调用(规则仍是引擎 backend-dispatch.ts 单点)。\n\nexport { defineOp, assertLibConforms, hasDualOp, dualOpMetaOf, DUAL_OP_META } from './define-op'\nexport type {\n DualOpMeta,\n DualOpOptions,\n DualOpImpls,\n MeshImpl,\n BrepImpl,\n MeshData,\n BrepResult,\n} from './define-op'\nexport type { BrepCapabilityName } from './cad-runtime/backend-dispatch'\n"]}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * tolerance.ts — dimensioned threshold / tolerance constants (D6).
3
+ *
4
+ * These are the magnitude thresholds that were previously bare magic numbers
5
+ * with an implicit "mm" assumption. Each is defined once with an explicit unit,
6
+ * then consumed via `.as(mm)` where a bare float must cross into a numeric
7
+ * kernel (manifold-3d / occt-wasm). This keeps the mm basis readable without
8
+ * hiding it in the runtime value.
9
+ *
10
+ * Not all §2.2 thresholds collapse into one constant — they are not one kind of
11
+ * thing:
12
+ * - `CENTROID_DIST_SQ_MAX_MM2` is a SQUARED magnitude (mm²), so it stays a bare
13
+ * number with the unit spelled out in its name (D6 hard constraint 1).
14
+ * - `angularDeflection`'s default 0.5 is in radians and is intentionally NOT
15
+ * part of the length tolerance family (D6 hard constraint 2).
16
+ */
17
+ import { type ValueWithUnits } from './units.js';
18
+ /** Zero-length gate: a length at or below this is treated as zero. Independent of OCCT's tolerance. */
19
+ export declare const ZERO_LENGTH: ValueWithUnits;
20
+ /** Mesh → STEP sewing tolerance (occtKernel.ts `meshesToStep`). */
21
+ export declare const SEWING_TOLERANCE: ValueWithUnits;
22
+ /** Default chord-error (linear deflection) for tessellation (multiple op sites). */
23
+ export declare const DEFAULT_LINEAR_DEFLECTION: ValueWithUnits;
24
+ /** Fallback bounding box half-extent when a shape has no real bounds (topologyExt). */
25
+ export declare const OCTREE_BBOX_FALLBACK: ValueWithUnits;
26
+ /**
27
+ * Centroid-distance² upper bound used by topology naming (mm²). This is a
28
+ * SQUARED magnitude — it must stay a bare number; writing `(10*mm)^2` would
29
+ * drop the dimension and fail for non-length dimensions (D6 hard constraint 1).
30
+ */
31
+ export declare const CENTROID_DIST_SQ_MAX_MM2 = 100;
32
+ /**
33
+ * Convenience: extract a tolerance's base-unit float (mm) for numeric kernels.
34
+ * @param v - a dimensioned tolerance value.
35
+ * @returns the magnitude in mm (base-unit float).
36
+ */
37
+ export declare function asMm(v: ValueWithUnits): number;
38
+ //# sourceMappingURL=tolerance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tolerance.d.ts","sourceRoot":"","sources":["../src/tolerance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAM,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AAEjD,uGAAuG;AACvG,eAAO,MAAM,WAAW,EAAE,cAA+B,CAAA;AAEzD,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,EAAE,cAA6B,CAAA;AAE5D,oFAAoF;AACpF,eAAO,MAAM,yBAAyB,EAAE,cAA4B,CAAA;AAEpE,uFAAuF;AACvF,eAAO,MAAM,oBAAoB,EAAE,cAA4B,CAAA;AAE/D;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAE3C;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAE9C"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * tolerance.ts — dimensioned threshold / tolerance constants (D6).
3
+ *
4
+ * These are the magnitude thresholds that were previously bare magic numbers
5
+ * with an implicit "mm" assumption. Each is defined once with an explicit unit,
6
+ * then consumed via `.as(mm)` where a bare float must cross into a numeric
7
+ * kernel (manifold-3d / occt-wasm). This keeps the mm basis readable without
8
+ * hiding it in the runtime value.
9
+ *
10
+ * Not all §2.2 thresholds collapse into one constant — they are not one kind of
11
+ * thing:
12
+ * - `CENTROID_DIST_SQ_MAX_MM2` is a SQUARED magnitude (mm²), so it stays a bare
13
+ * number with the unit spelled out in its name (D6 hard constraint 1).
14
+ * - `angularDeflection`'s default 0.5 is in radians and is intentionally NOT
15
+ * part of the length tolerance family (D6 hard constraint 2).
16
+ */
17
+ import { mm } from './units.js';
18
+ /** Zero-length gate: a length at or below this is treated as zero. Independent of OCCT's tolerance. */
19
+ export const ZERO_LENGTH = mm.mul(0.1e-9);
20
+ /** Mesh → STEP sewing tolerance (occtKernel.ts `meshesToStep`). */
21
+ export const SEWING_TOLERANCE = mm.mul(0.01);
22
+ /** Default chord-error (linear deflection) for tessellation (multiple op sites). */
23
+ export const DEFAULT_LINEAR_DEFLECTION = mm.mul(0.1);
24
+ /** Fallback bounding box half-extent when a shape has no real bounds (topologyExt). */
25
+ export const OCTREE_BBOX_FALLBACK = mm.mul(100);
26
+ /**
27
+ * Centroid-distance² upper bound used by topology naming (mm²). This is a
28
+ * SQUARED magnitude — it must stay a bare number; writing `(10*mm)^2` would
29
+ * drop the dimension and fail for non-length dimensions (D6 hard constraint 1).
30
+ */
31
+ export const CENTROID_DIST_SQ_MAX_MM2 = 100;
32
+ /**
33
+ * Convenience: extract a tolerance's base-unit float (mm) for numeric kernels.
34
+ * @param v - a dimensioned tolerance value.
35
+ * @returns the magnitude in mm (base-unit float).
36
+ */
37
+ export function asMm(v) {
38
+ return v.as(mm);
39
+ }
40
+ //# sourceMappingURL=tolerance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tolerance.js","sourceRoot":"","sources":["../src/tolerance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,EAAE,EAAuB,MAAM,SAAS,CAAA;AAEjD,uGAAuG;AACvG,MAAM,CAAC,MAAM,WAAW,GAAmB,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AAEzD,mEAAmE;AACnE,MAAM,CAAC,MAAM,gBAAgB,GAAmB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AAE5D,oFAAoF;AACpF,MAAM,CAAC,MAAM,yBAAyB,GAAmB,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAEpE,uFAAuF;AACvF,MAAM,CAAC,MAAM,oBAAoB,GAAmB,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAE/D;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AAE3C;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAC,CAAiB;IACpC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;AACjB,CAAC","sourcesContent":["/**\n * tolerance.ts — dimensioned threshold / tolerance constants (D6).\n *\n * These are the magnitude thresholds that were previously bare magic numbers\n * with an implicit \"mm\" assumption. Each is defined once with an explicit unit,\n * then consumed via `.as(mm)` where a bare float must cross into a numeric\n * kernel (manifold-3d / occt-wasm). This keeps the mm basis readable without\n * hiding it in the runtime value.\n *\n * Not all §2.2 thresholds collapse into one constant — they are not one kind of\n * thing:\n * - `CENTROID_DIST_SQ_MAX_MM2` is a SQUARED magnitude (mm²), so it stays a bare\n * number with the unit spelled out in its name (D6 hard constraint 1).\n * - `angularDeflection`'s default 0.5 is in radians and is intentionally NOT\n * part of the length tolerance family (D6 hard constraint 2).\n */\nimport { mm, type ValueWithUnits } from './units'\n\n/** Zero-length gate: a length at or below this is treated as zero. Independent of OCCT's tolerance. */\nexport const ZERO_LENGTH: ValueWithUnits = mm.mul(0.1e-9)\n\n/** Mesh → STEP sewing tolerance (occtKernel.ts `meshesToStep`). */\nexport const SEWING_TOLERANCE: ValueWithUnits = mm.mul(0.01)\n\n/** Default chord-error (linear deflection) for tessellation (multiple op sites). */\nexport const DEFAULT_LINEAR_DEFLECTION: ValueWithUnits = mm.mul(0.1)\n\n/** Fallback bounding box half-extent when a shape has no real bounds (topologyExt). */\nexport const OCTREE_BBOX_FALLBACK: ValueWithUnits = mm.mul(100)\n\n/**\n * Centroid-distance² upper bound used by topology naming (mm²). This is a\n * SQUARED magnitude — it must stay a bare number; writing `(10*mm)^2` would\n * drop the dimension and fail for non-length dimensions (D6 hard constraint 1).\n */\nexport const CENTROID_DIST_SQ_MAX_MM2 = 100\n\n/**\n * Convenience: extract a tolerance's base-unit float (mm) for numeric kernels.\n * @param v - a dimensioned tolerance value.\n * @returns the magnitude in mm (base-unit float).\n */\nexport function asMm(v: ValueWithUnits): number {\n return v.as(mm)\n}"]}
@@ -11,8 +11,8 @@
11
11
  const TYPE_MISMATCH = -Infinity;
12
12
  /** 法向点积下限(拒绝阈值)。 */
13
13
  const NORMAL_DOT_MIN = 0.707;
14
- /** 质心距²上限(mm²;拒绝阈值)。 */
15
- const CENTROID_DIST_SQ_MAX = 100;
14
+ /** 质心距²上限(mm²;平方量级,保持裸数字,见 tolerance.ts)。 */
15
+ const CENTROID_DIST_SQ_MAX_MM2 = 100;
16
16
  /** 面积 |log 比| 超此值扣分。 */
17
17
  const AREA_LOG_RATIO_MAX = 1.0;
18
18
  /** 几何兜底接受的最小分。 */
@@ -86,7 +86,7 @@ export function scoreCandidate(kernel, hint, candidate) {
86
86
  const dy = hint.center[1] - g.center[1];
87
87
  const dz = hint.center[2] - g.center[2];
88
88
  const distSq = dx * dx + dy * dy + dz * dz;
89
- if (distSq > CENTROID_DIST_SQ_MAX)
89
+ if (distSq > CENTROID_DIST_SQ_MAX_MM2)
90
90
  return TYPE_MISMATCH;
91
91
  score -= distSq / 100;
92
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"score.js","sourceRoot":"","sources":["../../../src/topology/naming/score.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * score.ts — 面候选打分器(移植 brepjs src/topology/shapeRef/scoring.ts)\n *\n * 两套实现,口径一致、结果可比(§3.5):\n * - `defaultFaceScorer`:BREP 现场几何(kernel 计算 surfaceType/normal/center/area)\n * - `scoreFaceRow`:mesh/primitive 面行快照(FaceRow 或命名槽 FaceHint)\n *\n * 阈值常量化并写明 mm 单位假设——faijs 契约就是 mm,可直接沿用 brepjs 阈值。\n */\n\nimport type { BrepEngineApi } from '../../brep/engine/primitives'\nimport type { BrepHandle } from '../../brep/engine/types'\nimport type { FaceHint } from './types'\n\n/** 打分函数:分越高越匹配;-Infinity 直接拒绝。 */\nexport type FaceScorer = (hint: FaceHint, candidate: FaceCandidate) => number\n\n/** 打分候选:BREP 现场句柄 或 mesh/primitive 面行快照,二选一。 */\nexport interface FaceCandidate {\n /** BREP 现场面句柄(走 kernel 现场几何)。 */\n readonly handle?: BrepHandle\n /** 面行快照(mesh/primitive;与 handle 二选一)。 */\n readonly row?: Readonly<{\n surfaceType?: string\n normal?: readonly number[]\n center?: readonly number[]\n area?: number\n }>\n}\n\n/** 曲面类型不符直接拒绝(硬门)。 */\nconst TYPE_MISMATCH = -Infinity\n/** 法向点积下限(拒绝阈值)。 */\nconst NORMAL_DOT_MIN = 0.707\n/** 质心距²上限(mm²;拒绝阈值)。 */\nconst CENTROID_DIST_SQ_MAX = 100\n/** 面积 |log 比| 超此值扣分。 */\nconst AREA_LOG_RATIO_MAX = 1.0\n/** 几何兜底接受的最小分。 */\nexport const MIN_SCORE = 0.5\n/** 并列模糊带:两候选分差小于此值视为并列(→ ambiguous)。 */\nexport const AMBIGUITY_THRESHOLD = 0.1\n\n/** 从候选读取几何量的统一入口(handle 优先,row 兜底)。 */\nfunction candidateGeometry(\n kernel: BrepEngineApi | null,\n candidate: FaceCandidate,\n): { surfaceType?: string; normal?: readonly number[]; center?: readonly number[]; area?: number } {\n if (candidate.handle !== undefined && kernel) {\n const center = kernel.surfaceCenterOfMass(candidate.handle)\n const uv = kernel.uvBounds(candidate.handle)\n const u = (uv.uMin + uv.uMax) / 2\n const v = (uv.vMin + uv.vMax) / 2\n const normal = kernel.surfaceNormal(candidate.handle, u, v)\n return {\n surfaceType: kernel.surfaceType(candidate.handle),\n normal: [normal.x, normal.y, normal.z],\n center: [center.x, center.y, center.z],\n area: faceAreaOf(kernel, candidate.handle),\n }\n }\n return candidate.row ?? {}\n}\n\n/** 面面积:BREP 现场无直接 API,用包围盒近似不可靠——退化为 undefined(不打分)。 */\nfunction faceAreaOf(_kernel: BrepEngineApi, _face: BrepHandle): number | undefined {\n // occt-wasm 无公开 face area API(queryBatch 仅测试用、返回 {area} 但生产路径零调用)。\n // hint 携带的 area 仍参与面积比扣分(见 scorerArea),此处返回 undefined 表示「现场未知」。\n return undefined\n}\n\n/** 面积比扣分(hint.area 已知且 >0 时)。 */\nfunction scorerArea(hint: FaceHint, area: number | undefined): number {\n if (hint.area === undefined || hint.area <= 0) return 0\n if (area === undefined || area <= 0) return 0\n const logRatio = Math.abs(Math.log(hint.area / area))\n return logRatio > AREA_LOG_RATIO_MAX ? -logRatio : 0\n}\n\n/**\n * 打分一条候选(共用于 BREP 现场与面行快照两路)。\n *\n * @param kernel - OCCT 内核(candidate.handle 路径需要;row 路径可传 null)。\n * @param hint - 被解析 TopoRef 携带的面 hint。\n * @param candidate - 候选(句柄或面行)。\n * @returns 综合分;-Infinity 表示硬性不匹配。\n */\nexport function scoreCandidate(\n kernel: BrepEngineApi | null,\n hint: FaceHint,\n candidate: FaceCandidate,\n): number {\n let score = 0\n const g = candidateGeometry(kernel, candidate)\n\n // 曲面类型硬门\n if (hint.surfaceType !== undefined) {\n if (g.surfaceType === hint.surfaceType) {\n score += 1.0\n } else {\n return TYPE_MISMATCH\n }\n }\n\n // 法向点积\n if (hint.normal !== undefined && g.normal !== undefined) {\n const dot =\n hint.normal[0] * g.normal[0] +\n hint.normal[1] * g.normal[1] +\n hint.normal[2] * g.normal[2]\n if (dot < NORMAL_DOT_MIN) return TYPE_MISMATCH\n score += dot\n }\n\n // 质心距²惩罚\n if (hint.center !== undefined && g.center !== undefined) {\n const dx = hint.center[0] - g.center[0]\n const dy = hint.center[1] - g.center[1]\n const dz = hint.center[2] - g.center[2]\n const distSq = dx * dx + dy * dy + dz * dz\n if (distSq > CENTROID_DIST_SQ_MAX) return TYPE_MISMATCH\n score -= distSq / 100\n }\n\n // 面积比扣分\n score += scorerArea(hint, g.area)\n\n return score\n}\n\n/**\n * BREP 现场打分器(§3.5 defaultFaceScorer 移植):候选是活句柄,几何现场算。\n * 保持与 scoreFaceRow 同一套权重,保证两路结果可比。\n */\n/**\n * Build a scorer that computes geometry live from a BREP kernel handle.\n *\n * @param kernel - the OCCT kernel used to evaluate candidate face geometry.\n * @returns a FaceScorer scoring live face handles against a FaceHint.\n */\nexport function defaultFaceScorer(kernel: BrepEngineApi): FaceScorer {\n return (hint, candidate) => scoreCandidate(kernel, hint, candidate)\n}\n\n/**\n * 面行/命名槽快照打分器(§3.5 scoreFaceRow):候选是 FaceRow/hint 快照,\n * 用于 mesh/primitive(无 kernel 现场几何)。\n *\n * @param hint - the FaceHint carried by the TopoRef being resolved.\n * @param row - the candidate face-row snapshot (surfaceType/normal/center/area).\n * @returns the combined score; -Infinity rejects the candidate outright.\n */\nexport function scoreFaceRow(hint: FaceHint, row: FaceCandidate['row']): number {\n return scoreCandidate(null, hint, { row })\n}\n"]}
1
+ {"version":3,"file":"score.js","sourceRoot":"","sources":["../../../src/topology/naming/score.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsBH,sBAAsB;AACtB,MAAM,aAAa,GAAG,CAAC,QAAQ,CAAA;AAC/B,oBAAoB;AACpB,MAAM,cAAc,GAAG,KAAK,CAAA;AAC5B,6CAA6C;AAC7C,MAAM,wBAAwB,GAAG,GAAG,CAAA;AACpC,wBAAwB;AACxB,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAC9B,kBAAkB;AAClB,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,CAAA;AAC5B,wCAAwC;AACxC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAA;AAEtC,uCAAuC;AACvC,SAAS,iBAAiB,CACxB,MAA4B,EAC5B,SAAwB;IAExB,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QAC3D,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QAC5C,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QAC3D,OAAO;YACL,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC;YACjD,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YACtC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YACtC,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC;SAC3C,CAAA;IACH,CAAC;IACD,OAAO,SAAS,CAAC,GAAG,IAAI,EAAE,CAAA;AAC5B,CAAC;AAED,wDAAwD;AACxD,SAAS,UAAU,CAAC,OAAsB,EAAE,KAAiB;IAC3D,mEAAmE;IACnE,gEAAgE;IAChE,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,iCAAiC;AACjC,SAAS,UAAU,CAAC,IAAc,EAAE,IAAwB;IAC1D,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IACvD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAA;IACrD,OAAO,QAAQ,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;AACtD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,MAA4B,EAC5B,IAAc,EACd,SAAwB;IAExB,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,MAAM,CAAC,GAAG,iBAAiB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAE9C,SAAS;IACT,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YACvC,KAAK,IAAI,GAAG,CAAA;QACd,CAAC;aAAM,CAAC;YACN,OAAO,aAAa,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO;IACP,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACxD,MAAM,GAAG,GACP,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC9B,IAAI,GAAG,GAAG,cAAc;YAAE,OAAO,aAAa,CAAA;QAC9C,KAAK,IAAI,GAAG,CAAA;IACd,CAAC;IAED,SAAS;IACT,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACxD,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QAC1C,IAAI,MAAM,GAAG,wBAAwB;YAAE,OAAO,aAAa,CAAA;QAC3D,KAAK,IAAI,MAAM,GAAG,GAAG,CAAA;IACvB,CAAC;IAED,QAAQ;IACR,KAAK,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;IAEjC,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;GAGG;AACH;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAqB;IACrD,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;AACrE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,IAAc,EAAE,GAAyB;IACpE,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;AAC5C,CAAC","sourcesContent":["/**\n * score.ts — 面候选打分器(移植 brepjs src/topology/shapeRef/scoring.ts)\n *\n * 两套实现,口径一致、结果可比(§3.5):\n * - `defaultFaceScorer`:BREP 现场几何(kernel 计算 surfaceType/normal/center/area)\n * - `scoreFaceRow`:mesh/primitive 面行快照(FaceRow 或命名槽 FaceHint)\n *\n * 阈值常量化并写明 mm 单位假设——faijs 契约就是 mm,可直接沿用 brepjs 阈值。\n */\n\nimport type { BrepEngineApi } from '../../brep/engine/primitives'\nimport type { BrepHandle } from '../../brep/engine/types'\nimport type { FaceHint } from './types'\n\n/** 打分函数:分越高越匹配;-Infinity 直接拒绝。 */\nexport type FaceScorer = (hint: FaceHint, candidate: FaceCandidate) => number\n\n/** 打分候选:BREP 现场句柄 或 mesh/primitive 面行快照,二选一。 */\nexport interface FaceCandidate {\n /** BREP 现场面句柄(走 kernel 现场几何)。 */\n readonly handle?: BrepHandle\n /** 面行快照(mesh/primitive;与 handle 二选一)。 */\n readonly row?: Readonly<{\n surfaceType?: string\n normal?: readonly number[]\n center?: readonly number[]\n area?: number\n }>\n}\n\n/** 曲面类型不符直接拒绝(硬门)。 */\nconst TYPE_MISMATCH = -Infinity\n/** 法向点积下限(拒绝阈值)。 */\nconst NORMAL_DOT_MIN = 0.707\n/** 质心距²上限(mm²;平方量级,保持裸数字,见 tolerance.ts)。 */\nconst CENTROID_DIST_SQ_MAX_MM2 = 100\n/** 面积 |log 比| 超此值扣分。 */\nconst AREA_LOG_RATIO_MAX = 1.0\n/** 几何兜底接受的最小分。 */\nexport const MIN_SCORE = 0.5\n/** 并列模糊带:两候选分差小于此值视为并列(→ ambiguous)。 */\nexport const AMBIGUITY_THRESHOLD = 0.1\n\n/** 从候选读取几何量的统一入口(handle 优先,row 兜底)。 */\nfunction candidateGeometry(\n kernel: BrepEngineApi | null,\n candidate: FaceCandidate,\n): { surfaceType?: string; normal?: readonly number[]; center?: readonly number[]; area?: number } {\n if (candidate.handle !== undefined && kernel) {\n const center = kernel.surfaceCenterOfMass(candidate.handle)\n const uv = kernel.uvBounds(candidate.handle)\n const u = (uv.uMin + uv.uMax) / 2\n const v = (uv.vMin + uv.vMax) / 2\n const normal = kernel.surfaceNormal(candidate.handle, u, v)\n return {\n surfaceType: kernel.surfaceType(candidate.handle),\n normal: [normal.x, normal.y, normal.z],\n center: [center.x, center.y, center.z],\n area: faceAreaOf(kernel, candidate.handle),\n }\n }\n return candidate.row ?? {}\n}\n\n/** 面面积:BREP 现场无直接 API,用包围盒近似不可靠——退化为 undefined(不打分)。 */\nfunction faceAreaOf(_kernel: BrepEngineApi, _face: BrepHandle): number | undefined {\n // occt-wasm 无公开 face area API(queryBatch 仅测试用、返回 {area} 但生产路径零调用)。\n // hint 携带的 area 仍参与面积比扣分(见 scorerArea),此处返回 undefined 表示「现场未知」。\n return undefined\n}\n\n/** 面积比扣分(hint.area 已知且 >0 时)。 */\nfunction scorerArea(hint: FaceHint, area: number | undefined): number {\n if (hint.area === undefined || hint.area <= 0) return 0\n if (area === undefined || area <= 0) return 0\n const logRatio = Math.abs(Math.log(hint.area / area))\n return logRatio > AREA_LOG_RATIO_MAX ? -logRatio : 0\n}\n\n/**\n * 打分一条候选(共用于 BREP 现场与面行快照两路)。\n *\n * @param kernel - OCCT 内核(candidate.handle 路径需要;row 路径可传 null)。\n * @param hint - 被解析 TopoRef 携带的面 hint。\n * @param candidate - 候选(句柄或面行)。\n * @returns 综合分;-Infinity 表示硬性不匹配。\n */\nexport function scoreCandidate(\n kernel: BrepEngineApi | null,\n hint: FaceHint,\n candidate: FaceCandidate,\n): number {\n let score = 0\n const g = candidateGeometry(kernel, candidate)\n\n // 曲面类型硬门\n if (hint.surfaceType !== undefined) {\n if (g.surfaceType === hint.surfaceType) {\n score += 1.0\n } else {\n return TYPE_MISMATCH\n }\n }\n\n // 法向点积\n if (hint.normal !== undefined && g.normal !== undefined) {\n const dot =\n hint.normal[0] * g.normal[0] +\n hint.normal[1] * g.normal[1] +\n hint.normal[2] * g.normal[2]\n if (dot < NORMAL_DOT_MIN) return TYPE_MISMATCH\n score += dot\n }\n\n // 质心距²惩罚\n if (hint.center !== undefined && g.center !== undefined) {\n const dx = hint.center[0] - g.center[0]\n const dy = hint.center[1] - g.center[1]\n const dz = hint.center[2] - g.center[2]\n const distSq = dx * dx + dy * dy + dz * dz\n if (distSq > CENTROID_DIST_SQ_MAX_MM2) return TYPE_MISMATCH\n score -= distSq / 100\n }\n\n // 面积比扣分\n score += scorerArea(hint, g.area)\n\n return score\n}\n\n/**\n * BREP 现场打分器(§3.5 defaultFaceScorer 移植):候选是活句柄,几何现场算。\n * 保持与 scoreFaceRow 同一套权重,保证两路结果可比。\n */\n/**\n * Build a scorer that computes geometry live from a BREP kernel handle.\n *\n * @param kernel - the OCCT kernel used to evaluate candidate face geometry.\n * @returns a FaceScorer scoring live face handles against a FaceHint.\n */\nexport function defaultFaceScorer(kernel: BrepEngineApi): FaceScorer {\n return (hint, candidate) => scoreCandidate(kernel, hint, candidate)\n}\n\n/**\n * 面行/命名槽快照打分器(§3.5 scoreFaceRow):候选是 FaceRow/hint 快照,\n * 用于 mesh/primitive(无 kernel 现场几何)。\n *\n * @param hint - the FaceHint carried by the TopoRef being resolved.\n * @param row - the candidate face-row snapshot (surfaceType/normal/center/area).\n * @returns the combined score; -Infinity rejects the candidate outright.\n */\nexport function scoreFaceRow(hint: FaceHint, row: FaceCandidate['row']): number {\n return scoreCandidate(null, hint, { row })\n}\n"]}