@faicad/faijs 0.32.3 → 0.33.1

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 (195) 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.map +1 -1
  182. package/dist/node-host/cli.js +3 -2
  183. package/dist/node-host/cli.js.map +1 -1
  184. package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
  185. package/dist/occt-kernel/occt-primitives.js +2 -0
  186. package/dist/occt-kernel/occt-primitives.js.map +1 -1
  187. package/dist/primitives/svg/svg-path.d.ts +192 -0
  188. package/dist/primitives/svg/svg-path.d.ts.map +1 -0
  189. package/dist/primitives/svg/svg-path.js +776 -0
  190. package/dist/primitives/svg/svg-path.js.map +1 -0
  191. package/dist/third-party/earcut.d.ts +19 -0
  192. package/dist/third-party/earcut.d.ts.map +1 -0
  193. package/dist/third-party/earcut.js +575 -0
  194. package/dist/third-party/earcut.js.map +1 -0
  195. package/package.json +10 -3
@@ -117,7 +117,7 @@ function transformBrep(op, input, params) {
117
117
  // L1 面:translateBrep/rotateBrep/scaleBrep/identityHashEvolution 只用 L1(D12)。
118
118
  const kernel = getBrepApi();
119
119
  const inputSolid = brepOf(input);
120
- if (!inputSolid)
120
+ if (inputSolid === undefined)
121
121
  throw new Error('[api/transform] input is not BREP');
122
122
  // 静态双轨(无运行时 try-catch 回退——按引擎事实在执行前定轨):
123
123
  // - occt(原生有 *WithHistory)→ 权威历史路径(产内核面映射 + roleTable)。
@@ -1 +1 @@
1
- {"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/api/transform.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api transform — 变换对象库函数(translate/rotate_euler/scale/scale3d)\n *\n * 平台分层(narrowing plan Phase 5,D11 + 2026-09-28 D 批降级):\n * - `translate` / `scale`:**中立 op**(不再声明 `engines:['occt']`)。BREP 路径按引擎\n * 事实**静态定轨**(读 `hasNativeHistory`——引擎身份是唯一判据,非运行时探测):\n * - occt(原生有 `translateWithHistory` / `scaleWithHistory`)→ 走 face-evolution.ts 的\n * `translateWithHashEvolution` / `scaleWithHashEvolution` 权威面演化(历史路径),\n * 产 hash 面映射并传播 roleTable;\n * - brepkit(无该二核函数,但裸 `kernel.translate` / `kernel.scale` 是真实现)→\n * L1 `translateBrep` / `scaleBrep`:几何精确,**另加 identityHashEvolution**。\n * 变换不改变面数/顺序,恒等映射真实成立(非伪造)——挂恒等面演化并传播 roleTable,\n * 选面/命名在降级路径不丢(区别于 boolean/chamfer 这种毁面重造、严禁伪造的情形)。\n * - `rotate_euler` / `scale3d`:**中立 op**——内核无单次 WithHistory 可表达\n * (任意欧拉+pivot / 非等比),走 `rotateBrep` / `scaleBrep` + identity 面演化\n * (只用 L1,跨引擎一致,不声明 engines)。\n *\n * dispatchPath 静态判定 brep/mesh,\n * BREP 路径用 brepOf(input) 取输入实体、fromBrep 登记输出实体。\n *\n * 网格链(方案 2026-10-01 §4 Phase 4 / B3 批):`mesh:` 实现分两支——**网格实体**\n * 走网格后端内核变换句柄(保持网格零件身份与近似拓扑),**裸网格**维持既有的顶点\n * 烘焙(manifold 链,无身份可言)。两支靠 `hasMeshSolid` 区分,不靠\"能不能跑\"试错。\n */\n\nimport type { Shape, Vec3 } from '../mesh/types'\n// B3 correction (2026-10-06): no library-face cad aggregate — import the impl from its own module.\nimport * as meshTransform from '../mesh/transform'\nimport { translateBrep, rotateBrep, scaleBrep, solidToShape } from '../brep/brep-ops'\nimport {\n identityEvolution,\n identityHashEvolution,\n rotateWithHashEvolution,\n scaleWithHashEvolution,\n translateWithHashEvolution,\n} from '../brep/face-evolution'\nimport type { HashEvolution } from '../brep/face-evolution'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { hasNativeHistory } from '../brep/engine/native-history'\nimport { fromBrep, brepOf, inputRoleTable, hasMeshSolid } from '../shape'\nimport { propagateAllOrigins } from '../topology/naming/roles'\nimport type { RoleTable } from '../topology/naming/types'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { defineOp } from '../sdk'\nimport { assertVec3, assertPositiveNumber } from './assert'\nimport { meshSolidBasicEntry, meshSolidProduct } from './internal/mesh-solid-op'\nimport type { BrepHandle } from '../brep/engine/types'\n\n/**\n * Validate translate parameters: `offset` must be a vec3.\n * @param params - the raw translate operation parameters.\n */\nexport function assertTranslateParams(params: Record<string, unknown>): void {\n assertVec3(params.offset, 'translate.offset')\n}\n\n/**\n * Validate rotate_euler parameters: `angles` must be a vec3, and `pivot`\n * (if provided) must also be a vec3.\n * @param params - the raw rotate_euler operation parameters.\n */\nexport function assertRotateParams(params: Record<string, unknown>): void {\n assertVec3(params.angles, 'rotate_euler.angles')\n if (params.pivot !== undefined && params.pivot !== null) {\n assertVec3(params.pivot, 'rotate_euler.pivot')\n }\n}\n\n/**\n * Validate scale parameters (brepjs contract, §4.6 裁决 2): `factor` must be a\n * positive number (uniform). The non-uniform array form belongs to `scale3d` —\n * any `scale(p, { factor: [x,y,z] })` call throws an explicit `E_ARGS_FORM`\n * error pointing at `scale3d` (error hint ≠ compatibility).\n * @param params - the raw scale operation parameters.\n */\nexport function assertScaleParams(params: Record<string, unknown>): void {\n if (Array.isArray(params.factor)) {\n throw new Error(\n '[faijs/args] scale: E_ARGS_FORM: uniform scaling takes a single number ' +\n '(scale(p, s, { center? })). Non-uniform scaling uses scale3d(p, [x,y,z]).',\n )\n }\n assertPositiveNumber(params.factor, 'scale.factor')\n}\n\n/**\n * Validate scale3d parameters (P6: factor locked to Vec3): `factor` must be a\n * vec3. The uniform scalar form belongs to `scale` — any `scale3d(p, 2)` call\n * throws an explicit `E_ARGS_FORM` error pointing at `scale` (§4.6 裁决 2).\n * @param params - the raw scale3d operation parameters.\n */\nexport function assertScale3dParams(params: Record<string, unknown>): void {\n if (typeof params.factor === 'number') {\n throw new Error(\n '[faijs/args] scale3d: E_ARGS_FORM: factor must be a vec3 [x, y, z]. ' +\n 'Uniform scaling now uses scale(p, 2) (§4.6 裁决 2).',\n )\n }\n assertVec3(params.factor, 'scale3d.factor')\n}\n\n/**\n * BREP 路径:变换 solid + 面演化 + roleTable 传播 + 三角化 + fromBrep 登记。\n *\n * 静态双轨:\n * - 引擎声明 `translateWithHistory` / `scaleWithHistory`(occt)→ 权威历史路径\n * (`translateWithHashEvolution` / `scaleWithHashEvolution`),产内核给出的面映射 + roleTable。\n * - 引擎只声明裸方法(brepkit:裸 `translate`/`scale` 是真实现,但无 `*WithHistory`)→\n * L1 裸调用 + identityHashEvolution。变换是刚体变换、面数/顺序保持不变,恒等映射\n * **真实成立**(非伪造;由 brep/face-evolution.ordering.test.ts 钉住)——因此 brepkit\n * 降级路径保留恒等面演化与 roleTable 传播,选面/命名不因降级而丢失。\n * `rotate_euler` / `scale3d` 走 `rotateBrep` / `scaleBrep` + identity 面演化(既有语义,跨引擎中性)。\n * @param op - the transform operation name.\n * @param input - the input geometry.\n * @param params - the operation parameters.\n * @returns the transformed Shape.\n */\n/**\n * 返回欧拉角中唯一非零分量的轴索引(0=X / 1=Y / 2=Z);多轴同时非零或全零返回 -1。\n *\n * 单轴欧拉角可等价映射到内核单轴 `rotateWithHistory`(绕该轴、以 pivot 为轴上一点),\n * 从而拿到内核权威面演化;多轴欧拉角内核无单次 API 可表达,退回 identity。\n * @param angles - the euler angles in degrees (XYZ order).\n * @returns the single non-zero axis index, or -1.\n */\nfunction singleNonZeroAxis(angles: Vec3): 0 | 1 | 2 | -1 {\n let idx = -1\n for (let i = 0; i < 3; i++) {\n if (Math.abs(angles[i]) > 1e-12) {\n if (idx !== -1) return -1\n idx = i\n }\n }\n return idx as 0 | 1 | 2 | -1\n}\n\nfunction transformBrep(op: string, input: Shape, params: Record<string, unknown>): Shape {\n // L1 面:translateBrep/rotateBrep/scaleBrep/identityHashEvolution 只用 L1(D12)。\n const kernel = getBrepApi()\n const inputSolid = brepOf(input) as BrepHandle | undefined\n if (!inputSolid) throw new Error('[api/transform] input is not BREP')\n\n // 静态双轨(无运行时 try-catch 回退——按引擎事实在执行前定轨):\n // - occt(原生有 *WithHistory)→ 权威历史路径(产内核面映射 + roleTable)。\n // - brepkit(裸 translate/scale 是真实现,无 *WithHistory)→ L1 裸调用 + identityHashEvolution。\n // 变换不改变面数/顺序,恒等映射真实成立(非伪造),故仍挂恒等面演化与 roleTable 传播。\n const hasTranslateHistory = hasNativeHistory('translateWithHistory')\n const hasScaleHistory = hasNativeHistory('scaleWithHistory')\n const hasRotateHistory = hasNativeHistory('rotateWithHistory')\n\n let resultSolid: BrepHandle\n // 面演化(hash 键):权威路径用内核映射,降级/中立路径用 identity 恒等映射。\n let historyEvolution: HashEvolution\n\n if (op === 'translate') {\n if (hasTranslateHistory) {\n // 权威映射:内核 translateWithHistory(1:1 全覆盖,实测见 evolution-bindings.test.ts)\n const r = translateWithHashEvolution(kernel, inputSolid, params.offset as Vec3)\n resultSolid = r.result\n historyEvolution = r.evolution\n } else {\n // brepkit 降级:L1 裸 translate(几何精确)+ identity(变换保面序,真实正确)。\n resultSolid = translateBrep(kernel, inputSolid, params.offset as Vec3)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n } else if (op === 'scale') {\n if (hasScaleHistory) {\n // 权威映射:内核 scaleWithHistory(仅均匀 —— assertScaleParams 已保证 factor 是 number)\n const r = scaleWithHashEvolution(\n kernel,\n inputSolid,\n (params.center as Vec3 | undefined) ?? [0, 0, 0],\n params.factor as number,\n )\n resultSolid = r.result\n historyEvolution = r.evolution\n } else {\n // brepkit 降级:L1 裸 scale(几何精确)+ identity(变换保面序,真实正确)。\n const center = (params.center as Vec3 | undefined) ?? [0, 0, 0]\n resultSolid = scaleBrep(kernel, inputSolid, params.factor as number, center)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n } else if (op === 'rotate_euler') {\n // 单轴欧拉角可映射到内核单轴 rotateWithHistory → 权威面演化;\n // 多轴欧拉角内核无对应 API → L1 rotate + identity(ordering.test.ts 钉住)。\n const angles = params.angles as Vec3\n const axisIdx = singleNonZeroAxis(angles)\n if (hasRotateHistory && axisIdx !== -1) {\n const axis: Vec3 = axisIdx === 0 ? [1, 0, 0] : axisIdx === 1 ? [0, 1, 0] : [0, 0, 1]\n const pivot = (params.pivot as Vec3 | undefined) ?? [0, 0, 0]\n const r = rotateWithHashEvolution(kernel, inputSolid, pivot, axis, (angles[axisIdx] * Math.PI) / 180)\n resultSolid = r.result\n historyEvolution = r.evolution\n } else {\n resultSolid = rotateBrep(kernel, inputSolid, angles, params.pivot as Vec3 | undefined)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n } else {\n // scale3d(非等比):内核无单次 WithHistory 可表达 →\n // L1 scale + identity 面演化(face-evolution.ordering.test.ts 钉住)。\n resultSolid = scaleBrep(kernel, inputSolid, params.factor as number | Vec3, params.center as Vec3 | undefined)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n\n // 变换面 1:1 保留——沿演化传播 roleTable(所有 origin),跨引擎一致(含 brepkit 降级路径)。\n const inputTable = inputRoleTable(input) as RoleTable | undefined\n let roleTable: RoleTable | undefined\n if (inputTable && inputTable.size > 0) {\n roleTable = propagateAllOrigins(inputTable, historyEvolution)\n }\n\n return fromBrep(solidToShape(kernel, resultSolid), {\n solid: resultSolid,\n // 变换维护拓扑,面 ordinal 不变 → 挂 identity 面演化(供显示/选面,跨引擎一致)。\n faceEvolution: identityEvolution(kernel, resultSolid),\n roleTable,\n })\n}\n\n/**\n * 网格实体路径:把同一个变换应用到网格实体的**句柄**上(方案 2026-10-01 §4 Phase 4 / B3 批)。\n *\n * 为什么不复用 `cad.translate` 那套顶点烘焙:那套只动 `positions`、不碰身份槽——\n * 对一个网格零件用它,等于把\"网格实体 + 近似拓扑\"静默降级成\"裸网格\"(下游每一个\n * 网格 op 都会因此失去选面/选边的能力)。网格链的正确姿势与 BREP 侧完全一致:\n * **变换句柄**(内核 `translate`/`transform` 带 kind tag 返回新实体),再由\n * `meshSolidProduct` 重新三角化 + 重建近似拓扑。\n *\n * 面演化在这里**如实缺席**:变换按定义 1:1 保面序,但没有 hash 演化可言(近似拓扑\n * 没有内核 hash)——不造恒等映射,也不传播 roleTable(网格链上没有 roleTable)。\n *\n * @param op - the transform operation name.\n * @param input - the mesh-solid input.\n * @param params - the validated operation parameters.\n * @returns the transformed mesh solid as a new mesh part.\n */\nfunction transformMeshSolid(op: string, input: Shape, params: Record<string, unknown>): Shape {\n const entry = meshSolidBasicEntry(input, op)\n let result: BrepHandle\n if (op === 'translate') {\n result = translateBrep(entry.kernel, entry.solid, params.offset as Vec3)\n } else if (op === 'rotate_euler') {\n result = rotateBrep(entry.kernel, entry.solid, params.angles as Vec3, params.pivot as Vec3 | undefined)\n } else if (op === 'scale') {\n result = scaleBrep(entry.kernel, entry.solid, params.factor as number, params.center as Vec3 | undefined)\n } else {\n result = scaleBrep(entry.kernel, entry.solid, params.factor as Vec3, params.center as Vec3 | undefined)\n }\n return meshSolidProduct(entry, result)\n}\n\n/**\n * 平移几何体。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name translate\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 平移后的几何,装配的相对位置靠成员的变换语句表达。\n * @param input - 目标几何。type:Shape required:true\n * @param params.offset - 平移向量(mm)。type:[x,y,z] required:true\n * @example\n * const p1 = cad.translate(part0, { offset: [10, 0, 0] })\n */\nexport const translate = defineOp({\n name: 'translate',\n meshEngines: ['brepkit'],\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/translate] no input geometry')\n assertTranslateParams(params)\n if (hasMeshSolid(input)) return transformMeshSolid('translate', input, params)\n return meshTransform.translate(input, params.offset as Vec3)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/translate] no input geometry')\n assertTranslateParams(params)\n return transformBrep('translate', input, params)\n },\n // D11: `translate(p, 10, 0, 0)` == `translate(p, { offset: [10, 0, 0] })`;\n // `offset` is a vec3 slot sitting after the single leading Shape argument.\n slotMap: { keys: ['offset'], vec3Keys: ['offset'], shapeArity: 1 },\n paramDims: { offset: 'length' },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 绕轴旋转几何体。angles 为欧拉角(度,XYZ 顺序)。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name rotate_euler\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 旋转后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.angles - 欧拉角(度,XYZ 顺序)。type:[x,y,z] required:true\n * @param params.pivot - 旋转中心。type:[x,y,z] 默认 原点\n * @example\n * const p2 = cad.rotate_euler(part0, { angles: [0, 0, 45] })\n * const p3 = cad.rotate_euler(part0, { angles: [0, 0, 45], pivot: [0,0,0] })\n */\nexport const rotate_euler = defineOp({\n name: 'rotate_euler',\n meshEngines: ['brepkit'],\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/rotate_euler] no input geometry')\n assertRotateParams(params)\n if (hasMeshSolid(input)) return transformMeshSolid('rotate_euler', input, params)\n return meshTransform.rotate_euler(input, params.angles as Vec3, params.pivot as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/rotate_euler] no input geometry')\n assertRotateParams(params)\n return transformBrep('rotate_euler', input, params)\n },\n // D11: `rotate_euler(p, 0, 0, 45)` == `rotate_euler(p, { angles: [0, 0, 45] })`.\n slotMap: { keys: ['angles'], vec3Keys: ['angles'], shapeArity: 1 },\n paramDims: { angles: 'angle', pivot: 'length' },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 等比缩放几何体(brepjs 契约,§4.6 裁决 2)。factor 只收 number;不动点默认\n * 原点(与旧 `scale(shape, factor, { center? })` 一致),`center` 可选。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name scale\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 缩放后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.factor - 等比缩放系数(> 0)。type:number required:true\n * @param params.center - 缩放不动点(p 保持不动)。type:[x,y,z] 默认 [0,0,0](原点)\n * @example\n * const p4 = cad.scale(part0, 2)\n * const p5 = cad.scale(part0, { factor: 2, center: [10, 0, 0] })\n */\nexport const scale = defineOp({\n name: 'scale',\n meshEngines: ['brepkit'],\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/scale] no input geometry')\n assertScaleParams(params)\n if (hasMeshSolid(input)) return transformMeshSolid('scale', input, params)\n return meshTransform.scale(input, params.factor as number, params.center as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/scale] no input geometry')\n assertScaleParams(params)\n return transformBrep('scale', input, params)\n },\n // L3 schema: factor/center for codegen/UI panels.\n schema: { factor: 'number', center: 'vec3?' },\n // D11(§4.6):`scale(p, 2)` == `scale(p, { factor: 2 })`(标量槽);尾参 options\n // ({center})经 dual-form-args 尾参合并并入。\n slotMap: { keys: ['factor'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n\n/**\n * 非等比缩放几何体(faijs 语义,§1.4.4 裁决 2)。factor 定死 vec3 — 等比缩放请用\n * `scale(p, s)`,`scale3d(p, [x,y,z])` 才可非等比。`center` 为不动点(默认原点)。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name scale3d\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 缩放后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.factor - 三轴缩放系数(均 > 0)。type:[x,y,z] required:true\n * @param params.center - 缩放不动点。type:[x,y,z] 默认 [0,0,0](原点)\n * @example\n * const p4 = cad.scale3d(part0, { factor: [2, 1, 1] })\n * const p5 = cad.scale3d(part0, [2, 1, 1], { center: [10, 0, 0] })\n */\nexport const scale3d = defineOp({\n name: 'scale3d',\n meshEngines: ['brepkit'],\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/scale3d] no input geometry')\n assertScale3dParams(params)\n if (hasMeshSolid(input)) return transformMeshSolid('scale3d', input, params)\n return meshTransform.scale3d(input, params.factor as Vec3, params.center as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/scale3d] no input geometry')\n assertScale3dParams(params)\n return transformBrep('scale3d', input, params)\n },\n // L3 schema: factor/center for codegen/UI panels.\n schema: { factor: 'vec3', center: 'vec3?' },\n // D11(裁决 2):`scale3d(p, [1,2,3])` == `scale3d(p, { factor: [1,2,3] })`;\n // 标量 factor(如 `scale(p, 2)`)由 assertScale3dParams 拒绝并提示 `scale`。\n slotMap: { keys: ['factor'], vec3Keys: ['factor'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n"]}
1
+ {"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/api/transform.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api transform — 变换对象库函数(translate/rotate_euler/scale/scale3d)\n *\n * 平台分层(narrowing plan Phase 5,D11 + 2026-09-28 D 批降级):\n * - `translate` / `scale`:**中立 op**(不再声明 `engines:['occt']`)。BREP 路径按引擎\n * 事实**静态定轨**(读 `hasNativeHistory`——引擎身份是唯一判据,非运行时探测):\n * - occt(原生有 `translateWithHistory` / `scaleWithHistory`)→ 走 face-evolution.ts 的\n * `translateWithHashEvolution` / `scaleWithHashEvolution` 权威面演化(历史路径),\n * 产 hash 面映射并传播 roleTable;\n * - brepkit(无该二核函数,但裸 `kernel.translate` / `kernel.scale` 是真实现)→\n * L1 `translateBrep` / `scaleBrep`:几何精确,**另加 identityHashEvolution**。\n * 变换不改变面数/顺序,恒等映射真实成立(非伪造)——挂恒等面演化并传播 roleTable,\n * 选面/命名在降级路径不丢(区别于 boolean/chamfer 这种毁面重造、严禁伪造的情形)。\n * - `rotate_euler` / `scale3d`:**中立 op**——内核无单次 WithHistory 可表达\n * (任意欧拉+pivot / 非等比),走 `rotateBrep` / `scaleBrep` + identity 面演化\n * (只用 L1,跨引擎一致,不声明 engines)。\n *\n * dispatchPath 静态判定 brep/mesh,\n * BREP 路径用 brepOf(input) 取输入实体、fromBrep 登记输出实体。\n *\n * 网格链(方案 2026-10-01 §4 Phase 4 / B3 批):`mesh:` 实现分两支——**网格实体**\n * 走网格后端内核变换句柄(保持网格零件身份与近似拓扑),**裸网格**维持既有的顶点\n * 烘焙(manifold 链,无身份可言)。两支靠 `hasMeshSolid` 区分,不靠\"能不能跑\"试错。\n */\n\nimport type { Shape, Vec3 } from '../mesh/types'\n// B3 correction (2026-10-06): no library-face cad aggregate — import the impl from its own module.\nimport * as meshTransform from '../mesh/transform'\nimport { translateBrep, rotateBrep, scaleBrep, solidToShape } from '../brep/brep-ops'\nimport {\n identityEvolution,\n identityHashEvolution,\n rotateWithHashEvolution,\n scaleWithHashEvolution,\n translateWithHashEvolution,\n} from '../brep/face-evolution'\nimport type { HashEvolution } from '../brep/face-evolution'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { hasNativeHistory } from '../brep/engine/native-history'\nimport { fromBrep, brepOf, inputRoleTable, hasMeshSolid } from '../shape'\nimport { propagateAllOrigins } from '../topology/naming/roles'\nimport type { RoleTable } from '../topology/naming/types'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { defineOp } from '../sdk'\nimport { assertVec3, assertPositiveNumber } from './assert'\nimport { meshSolidBasicEntry, meshSolidProduct } from './internal/mesh-solid-op'\nimport type { BrepHandle } from '../brep/engine/types'\n\n/**\n * Validate translate parameters: `offset` must be a vec3.\n * @param params - the raw translate operation parameters.\n */\nexport function assertTranslateParams(params: Record<string, unknown>): void {\n assertVec3(params.offset, 'translate.offset')\n}\n\n/**\n * Validate rotate_euler parameters: `angles` must be a vec3, and `pivot`\n * (if provided) must also be a vec3.\n * @param params - the raw rotate_euler operation parameters.\n */\nexport function assertRotateParams(params: Record<string, unknown>): void {\n assertVec3(params.angles, 'rotate_euler.angles')\n if (params.pivot !== undefined && params.pivot !== null) {\n assertVec3(params.pivot, 'rotate_euler.pivot')\n }\n}\n\n/**\n * Validate scale parameters (brepjs contract, §4.6 裁决 2): `factor` must be a\n * positive number (uniform). The non-uniform array form belongs to `scale3d` —\n * any `scale(p, { factor: [x,y,z] })` call throws an explicit `E_ARGS_FORM`\n * error pointing at `scale3d` (error hint ≠ compatibility).\n * @param params - the raw scale operation parameters.\n */\nexport function assertScaleParams(params: Record<string, unknown>): void {\n if (Array.isArray(params.factor)) {\n throw new Error(\n '[faijs/args] scale: E_ARGS_FORM: uniform scaling takes a single number ' +\n '(scale(p, s, { center? })). Non-uniform scaling uses scale3d(p, [x,y,z]).',\n )\n }\n assertPositiveNumber(params.factor, 'scale.factor')\n}\n\n/**\n * Validate scale3d parameters (P6: factor locked to Vec3): `factor` must be a\n * vec3. The uniform scalar form belongs to `scale` — any `scale3d(p, 2)` call\n * throws an explicit `E_ARGS_FORM` error pointing at `scale` (§4.6 裁决 2).\n * @param params - the raw scale3d operation parameters.\n */\nexport function assertScale3dParams(params: Record<string, unknown>): void {\n if (typeof params.factor === 'number') {\n throw new Error(\n '[faijs/args] scale3d: E_ARGS_FORM: factor must be a vec3 [x, y, z]. ' +\n 'Uniform scaling now uses scale(p, 2) (§4.6 裁决 2).',\n )\n }\n assertVec3(params.factor, 'scale3d.factor')\n}\n\n/**\n * BREP 路径:变换 solid + 面演化 + roleTable 传播 + 三角化 + fromBrep 登记。\n *\n * 静态双轨:\n * - 引擎声明 `translateWithHistory` / `scaleWithHistory`(occt)→ 权威历史路径\n * (`translateWithHashEvolution` / `scaleWithHashEvolution`),产内核给出的面映射 + roleTable。\n * - 引擎只声明裸方法(brepkit:裸 `translate`/`scale` 是真实现,但无 `*WithHistory`)→\n * L1 裸调用 + identityHashEvolution。变换是刚体变换、面数/顺序保持不变,恒等映射\n * **真实成立**(非伪造;由 brep/face-evolution.ordering.test.ts 钉住)——因此 brepkit\n * 降级路径保留恒等面演化与 roleTable 传播,选面/命名不因降级而丢失。\n * `rotate_euler` / `scale3d` 走 `rotateBrep` / `scaleBrep` + identity 面演化(既有语义,跨引擎中性)。\n * @param op - the transform operation name.\n * @param input - the input geometry.\n * @param params - the operation parameters.\n * @returns the transformed Shape.\n */\n/**\n * 返回欧拉角中唯一非零分量的轴索引(0=X / 1=Y / 2=Z);多轴同时非零或全零返回 -1。\n *\n * 单轴欧拉角可等价映射到内核单轴 `rotateWithHistory`(绕该轴、以 pivot 为轴上一点),\n * 从而拿到内核权威面演化;多轴欧拉角内核无单次 API 可表达,退回 identity。\n * @param angles - the euler angles in degrees (XYZ order).\n * @returns the single non-zero axis index, or -1.\n */\nfunction singleNonZeroAxis(angles: Vec3): 0 | 1 | 2 | -1 {\n let idx = -1\n for (let i = 0; i < 3; i++) {\n if (Math.abs(angles[i]) > 1e-12) {\n if (idx !== -1) return -1\n idx = i\n }\n }\n return idx as 0 | 1 | 2 | -1\n}\n\nfunction transformBrep(op: string, input: Shape, params: Record<string, unknown>): Shape {\n // L1 面:translateBrep/rotateBrep/scaleBrep/identityHashEvolution 只用 L1(D12)。\n const kernel = getBrepApi()\n const inputSolid = brepOf(input) as BrepHandle | undefined\n if (inputSolid === undefined) throw new Error('[api/transform] input is not BREP')\n\n // 静态双轨(无运行时 try-catch 回退——按引擎事实在执行前定轨):\n // - occt(原生有 *WithHistory)→ 权威历史路径(产内核面映射 + roleTable)。\n // - brepkit(裸 translate/scale 是真实现,无 *WithHistory)→ L1 裸调用 + identityHashEvolution。\n // 变换不改变面数/顺序,恒等映射真实成立(非伪造),故仍挂恒等面演化与 roleTable 传播。\n const hasTranslateHistory = hasNativeHistory('translateWithHistory')\n const hasScaleHistory = hasNativeHistory('scaleWithHistory')\n const hasRotateHistory = hasNativeHistory('rotateWithHistory')\n\n let resultSolid: BrepHandle\n // 面演化(hash 键):权威路径用内核映射,降级/中立路径用 identity 恒等映射。\n let historyEvolution: HashEvolution\n\n if (op === 'translate') {\n if (hasTranslateHistory) {\n // 权威映射:内核 translateWithHistory(1:1 全覆盖,实测见 evolution-bindings.test.ts)\n const r = translateWithHashEvolution(kernel, inputSolid, params.offset as Vec3)\n resultSolid = r.result\n historyEvolution = r.evolution\n } else {\n // brepkit 降级:L1 裸 translate(几何精确)+ identity(变换保面序,真实正确)。\n resultSolid = translateBrep(kernel, inputSolid, params.offset as Vec3)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n } else if (op === 'scale') {\n if (hasScaleHistory) {\n // 权威映射:内核 scaleWithHistory(仅均匀 —— assertScaleParams 已保证 factor 是 number)\n const r = scaleWithHashEvolution(\n kernel,\n inputSolid,\n (params.center as Vec3 | undefined) ?? [0, 0, 0],\n params.factor as number,\n )\n resultSolid = r.result\n historyEvolution = r.evolution\n } else {\n // brepkit 降级:L1 裸 scale(几何精确)+ identity(变换保面序,真实正确)。\n const center = (params.center as Vec3 | undefined) ?? [0, 0, 0]\n resultSolid = scaleBrep(kernel, inputSolid, params.factor as number, center)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n } else if (op === 'rotate_euler') {\n // 单轴欧拉角可映射到内核单轴 rotateWithHistory → 权威面演化;\n // 多轴欧拉角内核无对应 API → L1 rotate + identity(ordering.test.ts 钉住)。\n const angles = params.angles as Vec3\n const axisIdx = singleNonZeroAxis(angles)\n if (hasRotateHistory && axisIdx !== -1) {\n const axis: Vec3 = axisIdx === 0 ? [1, 0, 0] : axisIdx === 1 ? [0, 1, 0] : [0, 0, 1]\n const pivot = (params.pivot as Vec3 | undefined) ?? [0, 0, 0]\n const r = rotateWithHashEvolution(kernel, inputSolid, pivot, axis, (angles[axisIdx] * Math.PI) / 180)\n resultSolid = r.result\n historyEvolution = r.evolution\n } else {\n resultSolid = rotateBrep(kernel, inputSolid, angles, params.pivot as Vec3 | undefined)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n } else {\n // scale3d(非等比):内核无单次 WithHistory 可表达 →\n // L1 scale + identity 面演化(face-evolution.ordering.test.ts 钉住)。\n resultSolid = scaleBrep(kernel, inputSolid, params.factor as number | Vec3, params.center as Vec3 | undefined)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n\n // 变换面 1:1 保留——沿演化传播 roleTable(所有 origin),跨引擎一致(含 brepkit 降级路径)。\n const inputTable = inputRoleTable(input) as RoleTable | undefined\n let roleTable: RoleTable | undefined\n if (inputTable && inputTable.size > 0) {\n roleTable = propagateAllOrigins(inputTable, historyEvolution)\n }\n\n return fromBrep(solidToShape(kernel, resultSolid), {\n solid: resultSolid,\n // 变换维护拓扑,面 ordinal 不变 → 挂 identity 面演化(供显示/选面,跨引擎一致)。\n faceEvolution: identityEvolution(kernel, resultSolid),\n roleTable,\n })\n}\n\n/**\n * 网格实体路径:把同一个变换应用到网格实体的**句柄**上(方案 2026-10-01 §4 Phase 4 / B3 批)。\n *\n * 为什么不复用 `cad.translate` 那套顶点烘焙:那套只动 `positions`、不碰身份槽——\n * 对一个网格零件用它,等于把\"网格实体 + 近似拓扑\"静默降级成\"裸网格\"(下游每一个\n * 网格 op 都会因此失去选面/选边的能力)。网格链的正确姿势与 BREP 侧完全一致:\n * **变换句柄**(内核 `translate`/`transform` 带 kind tag 返回新实体),再由\n * `meshSolidProduct` 重新三角化 + 重建近似拓扑。\n *\n * 面演化在这里**如实缺席**:变换按定义 1:1 保面序,但没有 hash 演化可言(近似拓扑\n * 没有内核 hash)——不造恒等映射,也不传播 roleTable(网格链上没有 roleTable)。\n *\n * @param op - the transform operation name.\n * @param input - the mesh-solid input.\n * @param params - the validated operation parameters.\n * @returns the transformed mesh solid as a new mesh part.\n */\nfunction transformMeshSolid(op: string, input: Shape, params: Record<string, unknown>): Shape {\n const entry = meshSolidBasicEntry(input, op)\n let result: BrepHandle\n if (op === 'translate') {\n result = translateBrep(entry.kernel, entry.solid, params.offset as Vec3)\n } else if (op === 'rotate_euler') {\n result = rotateBrep(entry.kernel, entry.solid, params.angles as Vec3, params.pivot as Vec3 | undefined)\n } else if (op === 'scale') {\n result = scaleBrep(entry.kernel, entry.solid, params.factor as number, params.center as Vec3 | undefined)\n } else {\n result = scaleBrep(entry.kernel, entry.solid, params.factor as Vec3, params.center as Vec3 | undefined)\n }\n return meshSolidProduct(entry, result)\n}\n\n/**\n * 平移几何体。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name translate\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 平移后的几何,装配的相对位置靠成员的变换语句表达。\n * @param input - 目标几何。type:Shape required:true\n * @param params.offset - 平移向量(mm)。type:[x,y,z] required:true\n * @example\n * const p1 = cad.translate(part0, { offset: [10, 0, 0] })\n */\nexport const translate = defineOp({\n name: 'translate',\n meshEngines: ['brepkit'],\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/translate] no input geometry')\n assertTranslateParams(params)\n if (hasMeshSolid(input)) return transformMeshSolid('translate', input, params)\n return meshTransform.translate(input, params.offset as Vec3)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/translate] no input geometry')\n assertTranslateParams(params)\n return transformBrep('translate', input, params)\n },\n // D11: `translate(p, 10, 0, 0)` == `translate(p, { offset: [10, 0, 0] })`;\n // `offset` is a vec3 slot sitting after the single leading Shape argument.\n slotMap: { keys: ['offset'], vec3Keys: ['offset'], shapeArity: 1 },\n paramDims: { offset: 'length' },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 绕轴旋转几何体。angles 为欧拉角(度,XYZ 顺序)。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name rotate_euler\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 旋转后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.angles - 欧拉角(度,XYZ 顺序)。type:[x,y,z] required:true\n * @param params.pivot - 旋转中心。type:[x,y,z] 默认 原点\n * @example\n * const p2 = cad.rotate_euler(part0, { angles: [0, 0, 45] })\n * const p3 = cad.rotate_euler(part0, { angles: [0, 0, 45], pivot: [0,0,0] })\n */\nexport const rotate_euler = defineOp({\n name: 'rotate_euler',\n meshEngines: ['brepkit'],\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/rotate_euler] no input geometry')\n assertRotateParams(params)\n if (hasMeshSolid(input)) return transformMeshSolid('rotate_euler', input, params)\n return meshTransform.rotate_euler(input, params.angles as Vec3, params.pivot as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/rotate_euler] no input geometry')\n assertRotateParams(params)\n return transformBrep('rotate_euler', input, params)\n },\n // D11: `rotate_euler(p, 0, 0, 45)` == `rotate_euler(p, { angles: [0, 0, 45] })`.\n slotMap: { keys: ['angles'], vec3Keys: ['angles'], shapeArity: 1 },\n paramDims: { angles: 'angle', pivot: 'length' },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 等比缩放几何体(brepjs 契约,§4.6 裁决 2)。factor 只收 number;不动点默认\n * 原点(与旧 `scale(shape, factor, { center? })` 一致),`center` 可选。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name scale\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 缩放后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.factor - 等比缩放系数(> 0)。type:number required:true\n * @param params.center - 缩放不动点(p 保持不动)。type:[x,y,z] 默认 [0,0,0](原点)\n * @example\n * const p4 = cad.scale(part0, 2)\n * const p5 = cad.scale(part0, { factor: 2, center: [10, 0, 0] })\n */\nexport const scale = defineOp({\n name: 'scale',\n meshEngines: ['brepkit'],\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/scale] no input geometry')\n assertScaleParams(params)\n if (hasMeshSolid(input)) return transformMeshSolid('scale', input, params)\n return meshTransform.scale(input, params.factor as number, params.center as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/scale] no input geometry')\n assertScaleParams(params)\n return transformBrep('scale', input, params)\n },\n // L3 schema: factor/center for codegen/UI panels.\n schema: { factor: 'number', center: 'vec3?' },\n // D11(§4.6):`scale(p, 2)` == `scale(p, { factor: 2 })`(标量槽);尾参 options\n // ({center})经 dual-form-args 尾参合并并入。\n slotMap: { keys: ['factor'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n\n/**\n * 非等比缩放几何体(faijs 语义,§1.4.4 裁决 2)。factor 定死 vec3 — 等比缩放请用\n * `scale(p, s)`,`scale3d(p, [x,y,z])` 才可非等比。`center` 为不动点(默认原点)。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name scale3d\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 缩放后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.factor - 三轴缩放系数(均 > 0)。type:[x,y,z] required:true\n * @param params.center - 缩放不动点。type:[x,y,z] 默认 [0,0,0](原点)\n * @example\n * const p4 = cad.scale3d(part0, { factor: [2, 1, 1] })\n * const p5 = cad.scale3d(part0, [2, 1, 1], { center: [10, 0, 0] })\n */\nexport const scale3d = defineOp({\n name: 'scale3d',\n meshEngines: ['brepkit'],\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/scale3d] no input geometry')\n assertScale3dParams(params)\n if (hasMeshSolid(input)) return transformMeshSolid('scale3d', input, params)\n return meshTransform.scale3d(input, params.factor as Vec3, params.center as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[api/scale3d] no input geometry')\n assertScale3dParams(params)\n return transformBrep('scale3d', input, params)\n },\n // L3 schema: factor/center for codegen/UI panels.\n schema: { factor: 'vec3', center: 'vec3?' },\n // D11(裁决 2):`scale3d(p, [1,2,3])` == `scale3d(p, { factor: [1,2,3] })`;\n // 标量 factor(如 `scale(p, 2)`)由 assertScale3dParams 拒绝并提示 `scale`。\n slotMap: { keys: ['factor'], vec3Keys: ['factor'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n"]}
@@ -15,6 +15,14 @@
15
15
  * 2026-09-25 core-decouple wrapup(§3.1 A 案):不再依赖 brepjs 的 HLR+2D
16
16
  * drawing 链——HLR 由 core 引擎原生提供(occt-wasm projectEdges),2D SVG
17
17
  * 序列化为本地实现(曲线边以采样折线近似)。
18
+ *
19
+ * 2026-10-11 双方言通道(方案 docs/plans/2026-10-11-brepkit-svg-view.md,与
20
+ * STEP 引擎中立化同基调:按引擎 id 静态分派通道,无门禁、无 engines 声明、
21
+ * 不因内核缺特性报错):
22
+ * - occt:HLR compound 句柄 → getSubShapes → 3D 曲线采样 → 相机平面投影;
23
+ * - brepkit:内核原生 `projectEdges` 直接返回已投影 2D 折线 JSON
24
+ * `{"visible":[[x,y,…],…],"hidden":[…]}`(每条折线 = 扁平 x,y 点对数组;
25
+ * y 轴 = x_axis × view,与 occt 输出坐标约定同构),解析后直接序列化。
18
26
  */
19
27
  import type { Shape } from '../../mesh/types.js';
20
28
  import { type ViewSpec } from './view-camera.js';
@@ -1 +1 @@
1
- {"version":3,"file":"view-projection.d.ts","sourceRoot":"","sources":["../../../src/api/view/view-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAI7C,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AAU5D,0BAA0B;AAC1B,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sBAAsB;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,oCAAoC;AACpC,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAA;IACf,8BAA8B;IAC9B,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC9C,eAAe;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAyID;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAE,kBAAuB,GAAG,aAAa,CA2BzG;AAED;;;;;;;;;;;;;;;;;;;IAmBI;AACJ,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAE3F"}
1
+ {"version":3,"file":"view-projection.d.ts","sourceRoot":"","sources":["../../../src/api/view/view-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAK7C,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AAU5D,0BAA0B;AAC1B,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sBAAsB;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,oCAAoC;AACpC,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAA;IACf,8BAA8B;IAC9B,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC9C,eAAe;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AA8MD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAE,kBAAuB,GAAG,aAAa,CA2BzG;AAED;;;;;;;;;;;;;;;;;;;IAmBI;AACJ,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAE3F"}
@@ -15,9 +15,18 @@
15
15
  * 2026-09-25 core-decouple wrapup(§3.1 A 案):不再依赖 brepjs 的 HLR+2D
16
16
  * drawing 链——HLR 由 core 引擎原生提供(occt-wasm projectEdges),2D SVG
17
17
  * 序列化为本地实现(曲线边以采样折线近似)。
18
+ *
19
+ * 2026-10-11 双方言通道(方案 docs/plans/2026-10-11-brepkit-svg-view.md,与
20
+ * STEP 引擎中立化同基调:按引擎 id 静态分派通道,无门禁、无 engines 声明、
21
+ * 不因内核缺特性报错):
22
+ * - occt:HLR compound 句柄 → getSubShapes → 3D 曲线采样 → 相机平面投影;
23
+ * - brepkit:内核原生 `projectEdges` 直接返回已投影 2D 折线 JSON
24
+ * `{"visible":[[x,y,…],…],"hidden":[…]}`(每条折线 = 扁平 x,y 点对数组;
25
+ * y 轴 = x_axis × view,与 occt 输出坐标约定同构),解析后直接序列化。
18
26
  */
19
27
  import { brepOf } from '../../shape.js';
20
28
  import { getBrepApi } from '../../brep/handle-bridge.js';
29
+ import { getBackends } from '../../runtime-state.js';
21
30
  import { resolveCamera } from './view-camera.js';
22
31
  /** 每条边的 3D 采样点数(直线 2 点;曲线分段近似)。 */
23
32
  const EDGE_SAMPLES = 5;
@@ -41,7 +50,10 @@ const COMPOUND_KEYS = [
41
50
  ];
42
51
  /**
43
52
  * HLR 投影 shape → 可见/隐藏 2D 折线(SVG d 串)。
44
- * 全部句柄在本函数内释放(compound + 边;输入 shape 不消费)。
53
+ * 按引擎 id 静态分派方言通道(见文件头 2026-10-11 注):
54
+ * - brepkit → 内核原生折线 JSON 通道;
55
+ * - 其余(含 occt)→ compound 句柄采样通道(现状)。
56
+ * 无引擎门禁:分派只选通道,不因内核缺特性报错。
45
57
  */
46
58
  function projectPolylines(shape, view) {
47
59
  const solid = brepOf(shape);
@@ -51,7 +63,66 @@ function projectPolylines(shape, view) {
51
63
  }
52
64
  const api = getBrepApi();
53
65
  const cam = resolveCamera(view);
54
- const r = api.projectEdges(solid, { x: cam.position[0], y: cam.position[1], z: cam.position[2] }, { x: cam.direction[0], y: cam.direction[1], z: cam.direction[2] }, { x: cam.xAxis[0], y: cam.xAxis[1], z: cam.xAxis[2] }, true, 0.1);
66
+ const engineId = getBackends().config.brepEngineId;
67
+ if (engineId === 'brepkit') {
68
+ return projectPolylinesNative(api, solid, cam);
69
+ }
70
+ return projectPolylinesCompound(api, solid, cam);
71
+ }
72
+ /** projectEdges 的公共调用参数(两方言同构,签名见 brep/engine/primitives.ts)。 */
73
+ function projectEdgesArgs(cam) {
74
+ return [
75
+ { x: cam.position[0], y: cam.position[1], z: cam.position[2] },
76
+ { x: cam.direction[0], y: cam.direction[1], z: cam.direction[2] },
77
+ { x: cam.xAxis[0], y: cam.xAxis[1], z: cam.xAxis[2] },
78
+ true,
79
+ 0.1,
80
+ ];
81
+ }
82
+ /**
83
+ * brepkit 原生通道:内核 projectEdges 返回 JSON 字符串
84
+ * `{"visible":[[x,y,…],…],"hidden":[…]}`(每条折线 = 扁平 x,y 点对数组,已是
85
+ * 相机平面 2D 坐标),解析后直接转 SVG path d 串。内核返回非法 JSON 属实现
86
+ * 缺陷,直接抛错暴露(非"缺特性",不受无门禁基调豁免)。
87
+ */
88
+ function projectPolylinesNative(api, solid, cam) {
89
+ const [origin, direction, xAxis] = projectEdgesArgs(cam);
90
+ const raw = api.projectEdges(solid, origin, direction, xAxis, true, 0.1);
91
+ const parsed = parseNativeProjection(raw);
92
+ return {
93
+ visible: parsed.visible.map(polylineToPath),
94
+ hidden: parsed.hidden.map(polylineToPath),
95
+ };
96
+ }
97
+ /** 解析 brepkit projectEdges 的折线 JSON(结构错误一律抛错暴露)。 */
98
+ function parseNativeProjection(raw) {
99
+ if (typeof raw !== 'string') {
100
+ throw new Error(`[faijs/view-projection] E_PROJECTION_DIALECT: native projectEdges returned ${typeof raw}, expected JSON string`);
101
+ }
102
+ const obj = JSON.parse(raw);
103
+ const flat = (v) => {
104
+ if (!Array.isArray(v))
105
+ throw new Error('[faijs/view-projection] E_PROJECTION_DIALECT: malformed native projection JSON');
106
+ return v.filter((p) => Array.isArray(p) && p.length >= 4);
107
+ };
108
+ return { visible: flat(obj.visible), hidden: flat(obj.hidden) };
109
+ }
110
+ /** 扁平 x,y 点对数组 → SVG path d 串(M + L 序列)。 */
111
+ function polylineToPath(poly) {
112
+ let d = `M ${poly[0].toFixed(4)} ${poly[1].toFixed(4)}`;
113
+ for (let i = 2; i + 1 < poly.length; i += 2) {
114
+ d += ` L ${poly[i].toFixed(4)} ${poly[i + 1].toFixed(4)}`;
115
+ }
116
+ return d;
117
+ }
118
+ /**
119
+ * occt compound 通道(现状,逐字节不变):HLR 输出 6 组 compound 的 arena id,
120
+ * 逐 compound 取边 → 3D 曲线采样 → 相机平面投影。
121
+ * 全部句柄在本函数内释放(compound + 边;输入 shape 不消费)。
122
+ */
123
+ function projectPolylinesCompound(api, solid, cam) {
124
+ const [origin, direction, xAxis] = projectEdgesArgs(cam);
125
+ const r = api.projectEdges(solid, origin, direction, xAxis, true, 0.1);
55
126
  const out = { visible: [], hidden: [] };
56
127
  const toHandle = (id) => id;
57
128
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"view-projection.js","sourceRoot":"","sources":["../../../src/api/view/view-projection.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * view-projection — 单视图投影 → SVG 线稿(faijs 视图投影能力,路径 A)\n *\n * projectView(shape, view, opts?) 返回**纯数据 SVG 字符串**(非 Shape):\n * - 直连 core 引擎的 HLR 投影(`BrepEngineApi.projectEdges`,OCCT\n * HLRBRep 隐线消除):可见 / 隐藏两组边(sharp/smooth/outline compound);\n * - 每组边 → 3D 曲线采样折线(`curveParameters` + `curvePointAtParam`)→\n * 投影到相机平面(正交投影,坐标 = 相对 camera.origin 在 xAxis/yAxis 上的分量);\n * - 序列化为一个完整 SVG:可见轮廓实线 + 隐藏线虚线(stroke-dasharray)。\n *\n * 返回字符串绕开 arg-spec 对 projectEdges/makeProjectedEdges 的 skip 障碍\n * (Edge 句柄数组 + compound 生命周期无法静态收养——本 op 只在内部消费,\n * 产物是 2D 纯文本,无收养问题)。\n *\n * 2026-09-25 core-decouple wrapup(§3.1 A 案):不再依赖 brepjs 的 HLR+2D\n * drawing 链——HLR 由 core 引擎原生提供(occt-wasm projectEdges),2D SVG\n * 序列化为本地实现(曲线边以采样折线近似)。\n */\n\nimport type { Shape } from '../../mesh/types'\nimport { brepOf } from '../../shape'\nimport { getBrepApi } from '../../brep/handle-bridge'\nimport type { BrepHandle } from '../../brep/engine/types'\nimport { resolveCamera, type ViewSpec } from './view-camera'\n\n/** 投影相机(与 view-camera 输出同构)。 */\ninterface Camera {\n readonly position: [number, number, number]\n readonly direction: [number, number, number]\n readonly xAxis: [number, number, number]\n readonly yAxis: [number, number, number]\n}\n\n/** projectView 的序列化选项。 */\nexport interface ProjectViewOptions {\n /** viewBox 四周留白(单位 = 投影平面坐标单位;缺省 1)。 */\n margin?: number\n /** 可见/隐藏线 stroke-width(像素;缺省 1)。 */\n strokeWidth?: number\n /** 隐藏线虚线样式(SVG stroke-dasharray;缺省 '4,4')。 */\n dash?: string\n /** 隐藏线透明度(缺省 0.6)。 */\n hiddenOpacity?: number\n /** 输出 SVG 宽度(缺省 = viewBox 宽度)。 */\n width?: number\n /** 输出 SVG 高度(缺省 = viewBox 高度)。 */\n height?: number\n}\n\n/** 单视图投影的结构化结果(projectSheet 复用)。 */\nexport interface ProjectionSvg {\n /** 完整 SVG 字符串。 */\n svg: string\n /** viewBox 属性值('minX minY w h';可见 ∪ 隐藏线并集 + margin)。 */\n viewBox: string\n /** 各 path d 串:可见实线 / 隐藏虚线。 */\n paths: { visible: string[]; hidden: string[] }\n /** 输出宽度/高度。 */\n width: number\n height: number\n}\n\n/** 每条边的 3D 采样点数(直线 2 点;曲线分段近似)。 */\nconst EDGE_SAMPLES = 5\n\ntype Vec3 = readonly [number, number, number]\n\n/** 3D 点 → 相机平面 2D 坐标。\n *\n * GOTCHA: occt-wasm 的 HLR projectEdges 已把边投影到相机平面,输出坐标 =\n * (沿 xAxis 的水平分量, 沿 cross(direction, xAxis) 的垂直分量, 沿 direction\n * 的深度分量≈0)——不是世界坐标。因此 2D 坐标直接取输出的前两分量,不再做\n * dot 二次投影(否则会把垂直信息读丢——垂直在 p.y 而非 p.z)。\n */\nfunction projectTo2D(p: Vec3, _cam: Camera): [number, number] {\n return [p[0], p[1]]\n}\n\n/** 引擎 projectEdges 的返回结构(occt-wasm:6 组 compound 的 arena id)。 */\ninterface ProjectEdgesResult {\n visibleSharp: number\n visibleSmooth: number\n visibleOutline: number\n hiddenSharp: number\n hiddenSmooth: number\n hiddenOutline: number\n}\n\nconst COMPOUND_KEYS = [\n ['visibleSharp', 'visible'],\n ['visibleSmooth', 'visible'],\n ['visibleOutline', 'visible'],\n ['hiddenSharp', 'hidden'],\n ['hiddenSmooth', 'hidden'],\n ['hiddenOutline', 'hidden'],\n] as const\n\n/**\n * HLR 投影 shape → 可见/隐藏 2D 折线(SVG d 串)。\n * 全部句柄在本函数内释放(compound + 边;输入 shape 不消费)。\n */\nfunction projectPolylines(shape: Shape, view: ViewSpec): { visible: string[]; hidden: string[] } {\n const solid = brepOf(shape) as BrepHandle | undefined\n if (solid === undefined) {\n throw new Error(\n '[faijs/view-projection] E_BREP_ONLY_INPUT: operation requires a BREP-backed shape ' +\n '(mesh-only input cannot be projected)',\n )\n }\n const api = getBrepApi()\n const cam = resolveCamera(view) as unknown as Camera\n const r = api.projectEdges(\n solid,\n { x: cam.position[0], y: cam.position[1], z: cam.position[2] },\n { x: cam.direction[0], y: cam.direction[1], z: cam.direction[2] },\n { x: cam.xAxis[0], y: cam.xAxis[1], z: cam.xAxis[2] },\n true,\n 0.1,\n ) as ProjectEdgesResult\n\n const out: { visible: string[]; hidden: string[] } = { visible: [], hidden: [] }\n const toHandle = (id: number): BrepHandle => id as BrepHandle\n try {\n for (const [key, group] of COMPOUND_KEYS) {\n const compoundId = r[key]\n if (typeof compoundId !== 'number' || compoundId === 0) continue\n const edges = api.getSubShapes(toHandle(compoundId), 'edge')\n for (const edge of edges) {\n const d = edgeToPath(api, edge, cam)\n if (d !== null) out[group].push(d)\n }\n // 释放 compound slot(幂等)\n try {\n api.release(toHandle(compoundId))\n } catch {\n // already released\n }\n }\n } finally {\n void 0\n }\n return out\n}\n\n/** 单条边 → SVG path d 串(3D 曲线采样折线投影到相机平面)。 */\nfunction edgeToPath(api: ReturnType<typeof getBrepApi>, edge: BrepHandle, cam: Camera): string | null {\n let cp\n try {\n cp = api.curveParameters(edge)\n } catch {\n return null // 退化边(如孤立顶点线)无曲线参数\n }\n const { first, last } = cp\n const span = last - first\n const pts: [number, number][] = []\n for (let i = 0; i < EDGE_SAMPLES; i += 1) {\n const t = first + (span * i) / (EDGE_SAMPLES - 1)\n const p = api.curvePointAtParam(edge, t)\n pts.push(projectTo2D([p.x, p.y, p.z], cam))\n }\n if (pts.length < 2) return null\n let d = `M ${pts[0][0].toFixed(4)} ${pts[0][1].toFixed(4)}`\n for (let i = 1; i < pts.length; i += 1) {\n d += ` L ${pts[i][0].toFixed(4)} ${pts[i][1].toFixed(4)}`\n }\n return d\n}\n\n/** 解析 'minX minY w h' 为数值数组。 */\nfunction parseViewBox(vb: string): [number, number, number, number] | undefined {\n const parts = vb.trim().split(/\\s+/).map(Number)\n if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n))) return undefined\n return [parts[0], parts[1], parts[2], parts[3]]\n}\n\n/** 折线点集 bbox → viewBox(统一坐标系;margin 再外扩)。 */\nfunction viewBoxOfPaths(paths: string[], margin: number): string {\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n for (const d of paths) {\n const nums = d.match(/[-+]?\\d*\\.?\\d+(?:[eE][-+]?\\d+)?/g) ?? []\n for (let i = 0; i + 1 < nums.length; i += 2) {\n const x = Number(nums[i])\n const y = Number(nums[i + 1])\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue\n minX = Math.min(minX, x)\n minY = Math.min(minY, y)\n maxX = Math.max(maxX, x)\n maxY = Math.max(maxY, y)\n }\n }\n if (!Number.isFinite(minX)) return '0 0 0 0' // 空投影(如空 shape)\n return `${minX - margin} ${minY - margin} ${maxX - minX + 2 * margin} ${maxY - minY + 2 * margin}`\n}\n\n/**\n * 单视图投影(结构化结果)。\n *\n * @param shape - 待投影的 faijs Shape(必须带 BREP 槽;mesh-only 输入抛 E_BREP_ONLY_INPUT)。\n * @param view - 视图规格(标准视图 / iso / 轴对平面 / 方向对象)。\n * @param opts - 序列化选项。\n * @returns 结构化投影结果(svg/viewBox/paths/尺寸)。\n */\nexport function projectViewSvg(shape: Shape, view: ViewSpec, opts: ProjectViewOptions = {}): ProjectionSvg {\n const { visible: visiblePaths, hidden: hiddenPaths } = projectPolylines(shape, view)\n const margin = opts.margin ?? 1\n const viewBox = viewBoxOfPaths([...visiblePaths, ...hiddenPaths], margin)\n const parsed = parseViewBox(viewBox) ?? [0, 0, 0, 0]\n const width = opts.width ?? parsed[2]\n const height = opts.height ?? parsed[3]\n const strokeWidth = opts.strokeWidth ?? 1\n const dash = opts.dash ?? '4,4'\n const hiddenOpacity = opts.hiddenOpacity ?? 0.6\n const visibleMarkup = visiblePaths\n .map((d) => `<path d=\"${d}\" fill=\"none\" stroke=\"#000\" stroke-width=\"${strokeWidth}\" />`)\n .join('\\n ')\n const hiddenMarkup = hiddenPaths\n .map(\n (d) =>\n `<path d=\"${d}\" fill=\"none\" stroke=\"#000\" stroke-width=\"${strokeWidth}\" stroke-dasharray=\"${dash}\" opacity=\"${hiddenOpacity}\" />`,\n )\n .join('\\n ')\n const svg = [\n `<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${viewBox}\" width=\"${width}\" height=\"${height}\" fill=\"none\" stroke=\"black\" stroke-width=\"0.6%\" vector-effect=\"non-scaling-stroke\">`,\n ` <g stroke=\"#000\" fill=\"none\">`,\n ` ${visibleMarkup}${hiddenMarkup === '' ? '' : `\\n ${hiddenMarkup}`}`,\n ` </g>`,\n `</svg>`,\n ].join('\\n')\n return { svg, viewBox, paths: { visible: visiblePaths, hidden: hiddenPaths }, width, height }\n}\n\n/**\n * 单视图投影 → SVG 线稿字符串(纯数据,不消费/修改 shape;规则 1 下裸调用不消费输入)。\n * @group 查询\n * @inputs 1\n * @async false\n * @qual ok\n * @name projectView\n * @returns SVG 字符串(<svg viewBox=\"…\"> + 可见实线 <path> + 隐藏虚线 <path>)。裸调用 cad.projectView(part0, 'front') 不消费 part0(规则 1),part 仍留在 canvas。\n * @param shape - 目标几何(必须有 BREP 槽;mesh-only 抛 E_BREP_ONLY_INPUT)。type:Shape required:true\n * @param view - 视图规格(同 viewCamera:标准视图名 / iso / 轴对平面 / 方向对象)。type:string|{dir,xAxis?} required:true\n * @param opts.strokeWidth - 可见线宽(stroke-width)。type:number 默认 1\n * @param opts.dash - 隐藏线虚线样式(stroke-dasharray)。type:string 默认 '4,4'\n * @param opts.hiddenOpacity - 隐藏线透明度。type:number 默认 0.6\n * @param opts.margin - viewBox 外扩边距。type:number 默认 1\n * @param opts.width - 输出宽度(缺省 = viewBox 宽度)。type:number\n * @param opts.height - 输出高度(缺省 = viewBox 高度)。type:number\n * @example\n * const svg = cad.projectView(part0, 'front')\n * const svg = cad.projectView(part0, 'iso', { strokeWidth: 1, dash: '4,4', hiddenOpacity: 0.6 })\n */\nexport function projectView(shape: Shape, view: ViewSpec, opts?: ProjectViewOptions): string {\n return projectViewSvg(shape, view, opts).svg\n}\n"]}
1
+ {"version":3,"file":"view-projection.js","sourceRoot":"","sources":["../../../src/api/view/view-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAiB,MAAM,eAAe,CAAA;AAuC5D,mCAAmC;AACnC,MAAM,YAAY,GAAG,CAAC,CAAA;AAItB;;;;;;GAMG;AACH,SAAS,WAAW,CAAC,CAAO,EAAE,IAAY;IACxC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACrB,CAAC;AAYD,MAAM,aAAa,GAAG;IACpB,CAAC,cAAc,EAAE,SAAS,CAAC;IAC3B,CAAC,eAAe,EAAE,SAAS,CAAC;IAC5B,CAAC,gBAAgB,EAAE,SAAS,CAAC;IAC7B,CAAC,aAAa,EAAE,QAAQ,CAAC;IACzB,CAAC,cAAc,EAAE,QAAQ,CAAC;IAC1B,CAAC,eAAe,EAAE,QAAQ,CAAC;CACnB,CAAA;AAEV;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,KAAY,EAAE,IAAc;IACpD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAA2B,CAAA;IACrD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,oFAAoF;YAClF,uCAAuC,CAC1C,CAAA;IACH,CAAC;IACD,MAAM,GAAG,GAAG,UAAU,EAAE,CAAA;IACxB,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAsB,CAAA;IACpD,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAA;IAClD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,sBAAsB,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;IAChD,CAAC;IACD,OAAO,wBAAwB,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;AAClD,CAAC;AAED,iEAAiE;AACjE,SAAS,gBAAgB,CAAC,GAAW;IACnC,OAAO;QACL,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;QAC9D,EAAE,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;QACjE,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;QACrD,IAAI;QACJ,GAAG;KACK,CAAA;AACZ,CAAC;AAED;;;;;GAKG;AACH,SAAS,sBAAsB,CAC7B,GAAkC,EAClC,KAAiB,EACjB,GAAW;IAEX,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAA;IACxD,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;IACxE,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAA;IACzC,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;KAC1C,CAAA;AACH,CAAC;AAED,oDAAoD;AACpD,SAAS,qBAAqB,CAAC,GAAY;IACzC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,8EAA8E,OAAO,GAAG,wBAAwB,CACjH,CAAA;IACH,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4C,CAAA;IACtE,MAAM,IAAI,GAAG,CAAC,CAAU,EAAc,EAAE;QACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAA;QACxH,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAiB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;IAC1E,CAAC,CAAA;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAA;AACjE,CAAC;AAED,4CAA4C;AAC5C,SAAS,cAAc,CAAC,IAAc;IACpC,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;IACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3D,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED;;;;GAIG;AACH,SAAS,wBAAwB,CAC/B,GAAkC,EAClC,KAAiB,EACjB,GAAW;IAEX,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAA;IACxD,MAAM,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAuB,CAAA;IAE5F,MAAM,GAAG,GAA4C,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;IAChF,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAc,EAAE,CAAC,EAAgB,CAAA;IAC7D,IAAI,CAAC;QACH,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,aAAa,EAAE,CAAC;YACzC,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;YACzB,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,CAAC;gBAAE,SAAQ;YAChE,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAA;YAC5D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;gBACpC,IAAI,CAAC,KAAK,IAAI;oBAAE,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACpC,CAAC;YACD,uBAAuB;YACvB,IAAI,CAAC;gBACH,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAA;YACnC,CAAC;YAAC,MAAM,CAAC;gBACP,mBAAmB;YACrB,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,CAAA;IACR,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,4CAA4C;AAC5C,SAAS,UAAU,CAAC,GAAkC,EAAE,IAAgB,EAAE,GAAW;IACnF,IAAI,EAAE,CAAA;IACN,IAAI,CAAC;QACH,EAAE,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA,CAAC,mBAAmB;IACjC,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,CAAA;IAC1B,MAAM,IAAI,GAAG,IAAI,GAAG,KAAK,CAAA;IACzB,MAAM,GAAG,GAAuB,EAAE,CAAA;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,CAAA;QACjD,MAAM,CAAC,GAAG,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QACxC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;IAC7C,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IAC/B,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3D,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED,gCAAgC;AAChC,SAAS,YAAY,CAAC,EAAU;IAC9B,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAChD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAClF,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AACjD,CAAC;AAED,6CAA6C;AAC7C,SAAS,cAAc,CAAC,KAAe,EAAE,MAAc;IACrD,IAAI,IAAI,GAAG,QAAQ,CAAA;IACnB,IAAI,IAAI,GAAG,QAAQ,CAAA;IACnB,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAA;IACpB,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAA;IACpB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,kCAAkC,CAAC,IAAI,EAAE,CAAA;QAC9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;YACzB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAQ;YACxD,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YACxB,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YACxB,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YACxB,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAA,CAAC,gBAAgB;IAC7D,OAAO,GAAG,IAAI,GAAG,MAAM,IAAI,IAAI,GAAG,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,MAAM,EAAE,CAAA;AACpG,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,IAAc,EAAE,OAA2B,EAAE;IACxF,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IACpF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAA;IAC/B,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,GAAG,YAAY,EAAE,GAAG,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;IACzE,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;IACvC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,CAAA;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAA;IAC/B,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,GAAG,CAAA;IAC/C,MAAM,aAAa,GAAG,YAAY;SAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,6CAA6C,WAAW,MAAM,CAAC;SACvF,IAAI,CAAC,QAAQ,CAAC,CAAA;IACjB,MAAM,YAAY,GAAG,WAAW;SAC7B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,YAAY,CAAC,6CAA6C,WAAW,uBAAuB,IAAI,cAAc,aAAa,MAAM,CACpI;SACA,IAAI,CAAC,QAAQ,CAAC,CAAA;IACjB,MAAM,GAAG,GAAG;QACV,kEAAkE,OAAO,YAAY,KAAK,aAAa,MAAM,sFAAsF;QACnM,iCAAiC;QACjC,OAAO,aAAa,GAAG,YAAY,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,YAAY,EAAE,EAAE;QAC3E,QAAQ;QACR,QAAQ;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACZ,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;AAC/F,CAAC;AAED;;;;;;;;;;;;;;;;;;;IAmBI;AACJ,MAAM,UAAU,WAAW,CAAC,KAAY,EAAE,IAAc,EAAE,IAAyB;IACjF,OAAO,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,GAAG,CAAA;AAC9C,CAAC","sourcesContent":["/**\n * view-projection — 单视图投影 → SVG 线稿(faijs 视图投影能力,路径 A)\n *\n * projectView(shape, view, opts?) 返回**纯数据 SVG 字符串**(非 Shape):\n * - 直连 core 引擎的 HLR 投影(`BrepEngineApi.projectEdges`,OCCT\n * HLRBRep 隐线消除):可见 / 隐藏两组边(sharp/smooth/outline compound);\n * - 每组边 → 3D 曲线采样折线(`curveParameters` + `curvePointAtParam`)→\n * 投影到相机平面(正交投影,坐标 = 相对 camera.origin 在 xAxis/yAxis 上的分量);\n * - 序列化为一个完整 SVG:可见轮廓实线 + 隐藏线虚线(stroke-dasharray)。\n *\n * 返回字符串绕开 arg-spec 对 projectEdges/makeProjectedEdges 的 skip 障碍\n * (Edge 句柄数组 + compound 生命周期无法静态收养——本 op 只在内部消费,\n * 产物是 2D 纯文本,无收养问题)。\n *\n * 2026-09-25 core-decouple wrapup(§3.1 A 案):不再依赖 brepjs 的 HLR+2D\n * drawing 链——HLR 由 core 引擎原生提供(occt-wasm projectEdges),2D SVG\n * 序列化为本地实现(曲线边以采样折线近似)。\n *\n * 2026-10-11 双方言通道(方案 docs/plans/2026-10-11-brepkit-svg-view.md,与\n * STEP 引擎中立化同基调:按引擎 id 静态分派通道,无门禁、无 engines 声明、\n * 不因内核缺特性报错):\n * - occt:HLR compound 句柄 → getSubShapes → 3D 曲线采样 → 相机平面投影;\n * - brepkit:内核原生 `projectEdges` 直接返回已投影 2D 折线 JSON\n * `{\"visible\":[[x,y,…],…],\"hidden\":[…]}`(每条折线 = 扁平 x,y 点对数组;\n * y 轴 = x_axis × view,与 occt 输出坐标约定同构),解析后直接序列化。\n */\n\nimport type { Shape } from '../../mesh/types'\nimport { brepOf } from '../../shape'\nimport { getBrepApi } from '../../brep/handle-bridge'\nimport type { BrepHandle } from '../../brep/engine/types'\nimport { getBackends } from '../../runtime-state'\nimport { resolveCamera, type ViewSpec } from './view-camera'\n\n/** 投影相机(与 view-camera 输出同构)。 */\ninterface Camera {\n readonly position: [number, number, number]\n readonly direction: [number, number, number]\n readonly xAxis: [number, number, number]\n readonly yAxis: [number, number, number]\n}\n\n/** projectView 的序列化选项。 */\nexport interface ProjectViewOptions {\n /** viewBox 四周留白(单位 = 投影平面坐标单位;缺省 1)。 */\n margin?: number\n /** 可见/隐藏线 stroke-width(像素;缺省 1)。 */\n strokeWidth?: number\n /** 隐藏线虚线样式(SVG stroke-dasharray;缺省 '4,4')。 */\n dash?: string\n /** 隐藏线透明度(缺省 0.6)。 */\n hiddenOpacity?: number\n /** 输出 SVG 宽度(缺省 = viewBox 宽度)。 */\n width?: number\n /** 输出 SVG 高度(缺省 = viewBox 高度)。 */\n height?: number\n}\n\n/** 单视图投影的结构化结果(projectSheet 复用)。 */\nexport interface ProjectionSvg {\n /** 完整 SVG 字符串。 */\n svg: string\n /** viewBox 属性值('minX minY w h';可见 ∪ 隐藏线并集 + margin)。 */\n viewBox: string\n /** 各 path d 串:可见实线 / 隐藏虚线。 */\n paths: { visible: string[]; hidden: string[] }\n /** 输出宽度/高度。 */\n width: number\n height: number\n}\n\n/** 每条边的 3D 采样点数(直线 2 点;曲线分段近似)。 */\nconst EDGE_SAMPLES = 5\n\ntype Vec3 = readonly [number, number, number]\n\n/** 3D 点 → 相机平面 2D 坐标。\n *\n * GOTCHA: occt-wasm 的 HLR projectEdges 已把边投影到相机平面,输出坐标 =\n * (沿 xAxis 的水平分量, 沿 cross(direction, xAxis) 的垂直分量, 沿 direction\n * 的深度分量≈0)——不是世界坐标。因此 2D 坐标直接取输出的前两分量,不再做\n * dot 二次投影(否则会把垂直信息读丢——垂直在 p.y 而非 p.z)。\n */\nfunction projectTo2D(p: Vec3, _cam: Camera): [number, number] {\n return [p[0], p[1]]\n}\n\n/** 引擎 projectEdges 的返回结构(occt-wasm:6 组 compound 的 arena id)。 */\ninterface ProjectEdgesResult {\n visibleSharp: number\n visibleSmooth: number\n visibleOutline: number\n hiddenSharp: number\n hiddenSmooth: number\n hiddenOutline: number\n}\n\nconst COMPOUND_KEYS = [\n ['visibleSharp', 'visible'],\n ['visibleSmooth', 'visible'],\n ['visibleOutline', 'visible'],\n ['hiddenSharp', 'hidden'],\n ['hiddenSmooth', 'hidden'],\n ['hiddenOutline', 'hidden'],\n] as const\n\n/**\n * HLR 投影 shape → 可见/隐藏 2D 折线(SVG d 串)。\n * 按引擎 id 静态分派方言通道(见文件头 2026-10-11 注):\n * - brepkit → 内核原生折线 JSON 通道;\n * - 其余(含 occt)→ compound 句柄采样通道(现状)。\n * 无引擎门禁:分派只选通道,不因内核缺特性报错。\n */\nfunction projectPolylines(shape: Shape, view: ViewSpec): { visible: string[]; hidden: string[] } {\n const solid = brepOf(shape) as BrepHandle | undefined\n if (solid === undefined) {\n throw new Error(\n '[faijs/view-projection] E_BREP_ONLY_INPUT: operation requires a BREP-backed shape ' +\n '(mesh-only input cannot be projected)',\n )\n }\n const api = getBrepApi()\n const cam = resolveCamera(view) as unknown as Camera\n const engineId = getBackends().config.brepEngineId\n if (engineId === 'brepkit') {\n return projectPolylinesNative(api, solid, cam)\n }\n return projectPolylinesCompound(api, solid, cam)\n}\n\n/** projectEdges 的公共调用参数(两方言同构,签名见 brep/engine/primitives.ts)。 */\nfunction projectEdgesArgs(cam: Camera) {\n return [\n { x: cam.position[0], y: cam.position[1], z: cam.position[2] },\n { x: cam.direction[0], y: cam.direction[1], z: cam.direction[2] },\n { x: cam.xAxis[0], y: cam.xAxis[1], z: cam.xAxis[2] },\n true,\n 0.1,\n ] as const\n}\n\n/**\n * brepkit 原生通道:内核 projectEdges 返回 JSON 字符串\n * `{\"visible\":[[x,y,…],…],\"hidden\":[…]}`(每条折线 = 扁平 x,y 点对数组,已是\n * 相机平面 2D 坐标),解析后直接转 SVG path d 串。内核返回非法 JSON 属实现\n * 缺陷,直接抛错暴露(非\"缺特性\",不受无门禁基调豁免)。\n */\nfunction projectPolylinesNative(\n api: ReturnType<typeof getBrepApi>,\n solid: BrepHandle,\n cam: Camera,\n): { visible: string[]; hidden: string[] } {\n const [origin, direction, xAxis] = projectEdgesArgs(cam)\n const raw = api.projectEdges(solid, origin, direction, xAxis, true, 0.1)\n const parsed = parseNativeProjection(raw)\n return {\n visible: parsed.visible.map(polylineToPath),\n hidden: parsed.hidden.map(polylineToPath),\n }\n}\n\n/** 解析 brepkit projectEdges 的折线 JSON(结构错误一律抛错暴露)。 */\nfunction parseNativeProjection(raw: unknown): { visible: number[][]; hidden: number[][] } {\n if (typeof raw !== 'string') {\n throw new Error(\n `[faijs/view-projection] E_PROJECTION_DIALECT: native projectEdges returned ${typeof raw}, expected JSON string`,\n )\n }\n const obj = JSON.parse(raw) as { visible?: unknown; hidden?: unknown }\n const flat = (v: unknown): number[][] => {\n if (!Array.isArray(v)) throw new Error('[faijs/view-projection] E_PROJECTION_DIALECT: malformed native projection JSON')\n return v.filter((p): p is number[] => Array.isArray(p) && p.length >= 4)\n }\n return { visible: flat(obj.visible), hidden: flat(obj.hidden) }\n}\n\n/** 扁平 x,y 点对数组 → SVG path d 串(M + L 序列)。 */\nfunction polylineToPath(poly: number[]): string {\n let d = `M ${poly[0].toFixed(4)} ${poly[1].toFixed(4)}`\n for (let i = 2; i + 1 < poly.length; i += 2) {\n d += ` L ${poly[i].toFixed(4)} ${poly[i + 1].toFixed(4)}`\n }\n return d\n}\n\n/**\n * occt compound 通道(现状,逐字节不变):HLR 输出 6 组 compound 的 arena id,\n * 逐 compound 取边 → 3D 曲线采样 → 相机平面投影。\n * 全部句柄在本函数内释放(compound + 边;输入 shape 不消费)。\n */\nfunction projectPolylinesCompound(\n api: ReturnType<typeof getBrepApi>,\n solid: BrepHandle,\n cam: Camera,\n): { visible: string[]; hidden: string[] } {\n const [origin, direction, xAxis] = projectEdgesArgs(cam)\n const r = api.projectEdges(solid, origin, direction, xAxis, true, 0.1) as ProjectEdgesResult\n\n const out: { visible: string[]; hidden: string[] } = { visible: [], hidden: [] }\n const toHandle = (id: number): BrepHandle => id as BrepHandle\n try {\n for (const [key, group] of COMPOUND_KEYS) {\n const compoundId = r[key]\n if (typeof compoundId !== 'number' || compoundId === 0) continue\n const edges = api.getSubShapes(toHandle(compoundId), 'edge')\n for (const edge of edges) {\n const d = edgeToPath(api, edge, cam)\n if (d !== null) out[group].push(d)\n }\n // 释放 compound slot(幂等)\n try {\n api.release(toHandle(compoundId))\n } catch {\n // already released\n }\n }\n } finally {\n void 0\n }\n return out\n}\n\n/** 单条边 → SVG path d 串(3D 曲线采样折线投影到相机平面)。 */\nfunction edgeToPath(api: ReturnType<typeof getBrepApi>, edge: BrepHandle, cam: Camera): string | null {\n let cp\n try {\n cp = api.curveParameters(edge)\n } catch {\n return null // 退化边(如孤立顶点线)无曲线参数\n }\n const { first, last } = cp\n const span = last - first\n const pts: [number, number][] = []\n for (let i = 0; i < EDGE_SAMPLES; i += 1) {\n const t = first + (span * i) / (EDGE_SAMPLES - 1)\n const p = api.curvePointAtParam(edge, t)\n pts.push(projectTo2D([p.x, p.y, p.z], cam))\n }\n if (pts.length < 2) return null\n let d = `M ${pts[0][0].toFixed(4)} ${pts[0][1].toFixed(4)}`\n for (let i = 1; i < pts.length; i += 1) {\n d += ` L ${pts[i][0].toFixed(4)} ${pts[i][1].toFixed(4)}`\n }\n return d\n}\n\n/** 解析 'minX minY w h' 为数值数组。 */\nfunction parseViewBox(vb: string): [number, number, number, number] | undefined {\n const parts = vb.trim().split(/\\s+/).map(Number)\n if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n))) return undefined\n return [parts[0], parts[1], parts[2], parts[3]]\n}\n\n/** 折线点集 bbox → viewBox(统一坐标系;margin 再外扩)。 */\nfunction viewBoxOfPaths(paths: string[], margin: number): string {\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n for (const d of paths) {\n const nums = d.match(/[-+]?\\d*\\.?\\d+(?:[eE][-+]?\\d+)?/g) ?? []\n for (let i = 0; i + 1 < nums.length; i += 2) {\n const x = Number(nums[i])\n const y = Number(nums[i + 1])\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue\n minX = Math.min(minX, x)\n minY = Math.min(minY, y)\n maxX = Math.max(maxX, x)\n maxY = Math.max(maxY, y)\n }\n }\n if (!Number.isFinite(minX)) return '0 0 0 0' // 空投影(如空 shape)\n return `${minX - margin} ${minY - margin} ${maxX - minX + 2 * margin} ${maxY - minY + 2 * margin}`\n}\n\n/**\n * 单视图投影(结构化结果)。\n *\n * @param shape - 待投影的 faijs Shape(必须带 BREP 槽;mesh-only 输入抛 E_BREP_ONLY_INPUT)。\n * @param view - 视图规格(标准视图 / iso / 轴对平面 / 方向对象)。\n * @param opts - 序列化选项。\n * @returns 结构化投影结果(svg/viewBox/paths/尺寸)。\n */\nexport function projectViewSvg(shape: Shape, view: ViewSpec, opts: ProjectViewOptions = {}): ProjectionSvg {\n const { visible: visiblePaths, hidden: hiddenPaths } = projectPolylines(shape, view)\n const margin = opts.margin ?? 1\n const viewBox = viewBoxOfPaths([...visiblePaths, ...hiddenPaths], margin)\n const parsed = parseViewBox(viewBox) ?? [0, 0, 0, 0]\n const width = opts.width ?? parsed[2]\n const height = opts.height ?? parsed[3]\n const strokeWidth = opts.strokeWidth ?? 1\n const dash = opts.dash ?? '4,4'\n const hiddenOpacity = opts.hiddenOpacity ?? 0.6\n const visibleMarkup = visiblePaths\n .map((d) => `<path d=\"${d}\" fill=\"none\" stroke=\"#000\" stroke-width=\"${strokeWidth}\" />`)\n .join('\\n ')\n const hiddenMarkup = hiddenPaths\n .map(\n (d) =>\n `<path d=\"${d}\" fill=\"none\" stroke=\"#000\" stroke-width=\"${strokeWidth}\" stroke-dasharray=\"${dash}\" opacity=\"${hiddenOpacity}\" />`,\n )\n .join('\\n ')\n const svg = [\n `<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${viewBox}\" width=\"${width}\" height=\"${height}\" fill=\"none\" stroke=\"black\" stroke-width=\"0.6%\" vector-effect=\"non-scaling-stroke\">`,\n ` <g stroke=\"#000\" fill=\"none\">`,\n ` ${visibleMarkup}${hiddenMarkup === '' ? '' : `\\n ${hiddenMarkup}`}`,\n ` </g>`,\n `</svg>`,\n ].join('\\n')\n return { svg, viewBox, paths: { visible: visiblePaths, hidden: hiddenPaths }, width, height }\n}\n\n/**\n * 单视图投影 → SVG 线稿字符串(纯数据,不消费/修改 shape;规则 1 下裸调用不消费输入)。\n * @group 查询\n * @inputs 1\n * @async false\n * @qual ok\n * @name projectView\n * @returns SVG 字符串(<svg viewBox=\"…\"> + 可见实线 <path> + 隐藏虚线 <path>)。裸调用 cad.projectView(part0, 'front') 不消费 part0(规则 1),part 仍留在 canvas。\n * @param shape - 目标几何(必须有 BREP 槽;mesh-only 抛 E_BREP_ONLY_INPUT)。type:Shape required:true\n * @param view - 视图规格(同 viewCamera:标准视图名 / iso / 轴对平面 / 方向对象)。type:string|{dir,xAxis?} required:true\n * @param opts.strokeWidth - 可见线宽(stroke-width)。type:number 默认 1\n * @param opts.dash - 隐藏线虚线样式(stroke-dasharray)。type:string 默认 '4,4'\n * @param opts.hiddenOpacity - 隐藏线透明度。type:number 默认 0.6\n * @param opts.margin - viewBox 外扩边距。type:number 默认 1\n * @param opts.width - 输出宽度(缺省 = viewBox 宽度)。type:number\n * @param opts.height - 输出高度(缺省 = viewBox 高度)。type:number\n * @example\n * const svg = cad.projectView(part0, 'front')\n * const svg = cad.projectView(part0, 'iso', { strokeWidth: 1, dash: '4,4', hiddenOpacity: 0.6 })\n */\nexport function projectView(shape: Shape, view: ViewSpec, opts?: ProjectViewOptions): string {\n return projectViewSvg(shape, view, opts).svg\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"cross-section.d.ts","sourceRoot":"","sources":["../../src/boolean/cross-section.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,IAAI,IAAI,KAAK,EAAQ,KAAK,EAAE,MAAM,WAAW,CAAA;AAEtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAE1C;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,KAAK,EAAE,WAAW,EAAE,CAAA;IACpB,kBAAkB;IAClB,MAAM,EAAE,KAAK,EAAE,EAAE,CAAA;IACjB,gCAAgC;IAChC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;IACpB,gCAAgC;IAChC,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB;IAChB,YAAY,EAAE,MAAM,CAAA;CACrB;AAiDD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,aAAa,CAuL3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,KAAK,EACb,MAAM,EAAE,MAAM,EACd,KAAK,SAAI,GACR;IAAE,SAAS,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAoDnD"}
1
+ {"version":3,"file":"cross-section.d.ts","sourceRoot":"","sources":["../../src/boolean/cross-section.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,IAAI,IAAI,KAAK,EAAQ,KAAK,EAAE,MAAM,WAAW,CAAA;AAItD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAE1C;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,KAAK,EAAE,WAAW,EAAE,CAAA;IACpB,kBAAkB;IAClB,MAAM,EAAE,KAAK,EAAE,EAAE,CAAA;IACjB,gCAAgC;IAChC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;IACpB,gCAAgC;IAChC,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB;IAChB,YAAY,EAAE,MAAM,CAAA;CACrB;AAiDD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,aAAa,CAuL3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,KAAK,EACb,MAAM,EAAE,MAAM,EACd,KAAK,SAAI,GACR;IAAE,SAAS,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAoDnD"}
@@ -15,7 +15,9 @@
15
15
  * - 输出的 cap 顶点为局部空间,预览期经 matrixWorld 渲染到世界空间。
16
16
  */
17
17
  import { Vec3 as Vec3C, Vec2 } from '../math3d/index.js';
18
- import earcut from 'earcut';
18
+ // earcut 上游仅提供 CJS,浏览器/Vite 直接 serve 无法 default import;vendored
19
+ // ESM(`../third-party/earcut`,算法与 npm earcut@2.2.4 逐字节一致,ISC)。
20
+ import earcut from '../third-party/earcut.js';
19
21
  const EPS_SURFACE = 1e-6;
20
22
  /** 线段端点量化容差(平面 2D 坐标),用于缝合相邻线段。 */
21
23
  const STITCH_TOL = 1e-4;
@@ -1 +1 @@
1
- {"version":3,"file":"cross-section.js","sourceRoot":"","sources":["../../src/boolean/cross-section.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 截面求解器(无 CSG / 无 Manifold.simplify)\n *\n * 给定源网格(THREE.BufferGeometry)和一个局部空间平面,直接求「平面与网格的\n * 交线」,缝合成闭合环(外环 + 孔环),并三角化出截面 cap。这是「拉伸预览无\n * split 方案」的唯一 CPU 几何成本。\n *\n * 为什么不用 Manifold.split:\n * - split 是整模型布尔运算(焊接 + 全分辨率 CSG),168 万三角面 4~8s/次;\n * - 本方案只做三角形–平面求交(纯算术),O(n),且后续可叠加 BVH 降到 O(log n + k)。\n *\n * 设计契约(与 ExtrudeRenderer 现有代码对齐):\n * - 输入平面为「局部空间」THREE.Plane(调用方负责把世界平面经 matrixWorld 逆变换得到)。\n * - computeSection 直接读 geometry.attributes,不拷贝整份顶点缓冲。\n * - 输出的 cap 顶点为局部空间,预览期经 matrixWorld 渲染到世界空间。\n */\nimport { Vec3 as Vec3C, Vec2, Plane } from '../math3d'\nimport earcut from 'earcut'\nimport type { Shape } from '../mesh/types'\n\n/**\n * A single closed loop (3D, local space, lying on the section plane).\n * `isHole=false` marks the outer boundary, `true` marks a hole.\n */\nexport interface SectionRing {\n points: Vec3C[]\n isHole: boolean\n}\n\n/**\n * Result of computing a section: the stitched loops and diagnostic counters.\n */\nexport interface SectionResult {\n /** All stitched loops (already classified by area into isHole). */\n rings: SectionRing[]\n /** 外环列表(3D 点)。 */\n outers: Vec3C[][]\n /** 每个外环对应的孔环列表(与 outers 同序)。 */\n holesOf: Vec3C[][][]\n /** 实际参与求交、跨越/贴合平面的三角形数(诊断用)。 */\n hitTriangleCount: number\n /** 收集到的交线段数。 */\n segmentCount: number\n}\n\nconst EPS_SURFACE = 1e-6\n/** 线段端点量化容差(平面 2D 坐标),用于缝合相邻线段。 */\nconst STITCH_TOL = 1e-4\n\nfunction triangulateWithEarcut(contour: Vec2[], holes: Vec2[][]): number[][] {\n const data: number[] = []\n const holeIndices: number[] = []\n let vertexCount = 0\n for (const p of contour) { data.push(p.x, p.y); vertexCount++ }\n for (const hole of holes) {\n holeIndices.push(vertexCount)\n for (const p of hole) { data.push(p.x, p.y); vertexCount++ }\n }\n const flat = earcut(data, holeIndices.length > 0 ? holeIndices : undefined, 2)\n const tris: number[][] = []\n for (let i = 0; i < flat.length; i += 3) tris.push([flat[i], flat[i + 1], flat[i + 2]])\n return tris\n}\n\n/** 平面正交基 (u, v),用于把 3D 截面点投影到 2D 以做缝合/面积/三角化。 */\nfunction planeBasis(normal: Vec3C): { u: Vec3C; v: Vec3C } {\n const n = normal.clone().normalize()\n const t = Math.abs(n.x) < 0.9 ? new Vec3C(1, 0, 0) : new Vec3C(0, 1, 0)\n const u = new Vec3C().crossVectors(t, n).normalize()\n const v = new Vec3C().crossVectors(n, u).normalize()\n return { u, v }\n}\n\nfunction project2D(p: Vec3C, u: Vec3C, v: Vec3C): Vec2 {\n return new Vec2(p.dot(u), p.dot(v))\n}\n\n/**\n * 端点量化到 STITCH_TOL 网格上作为缝合 key。\n * 用 Math.round 而非 toFixed:避免 -0.00001 → \"-0.0000\" 与 0 → \"0.0000\" 被当成两个点。\n */\nfunction key2D(p: Vec2): string {\n return `${Math.round(p.x / STITCH_TOL)},${Math.round(p.y / STITCH_TOL)}`\n}\n\n/** 三角形三个顶点索引(索引几何)或顺次顶点(非索引几何)。 */\ninterface TriRef {\n a: number\n b: number\n c: number\n}\n\n/**\n * Compute the section of a mesh cut by a plane.\n * @param geometry Source mesh (local space), supports indexed and non-indexed.\n * @param plane Local-space cutting plane (THREE.Plane semantics: normal·p + constant = 0).\n * @returns The stitched section rings, outers, holes, and diagnostic counters.\n */\nexport function computeSection(geometry: Shape, plane: Plane): SectionResult {\n const pos = geometry.positions\n const index = geometry.indices\n const triCount = index.length / 3\n\n const refs: TriRef[] = []\n for (let t = 0; t < triCount; t++) {\n refs.push({ a: index[t * 3], b: index[t * 3 + 1], c: index[t * 3 + 2] })\n }\n\n const at = (i: number, out: Vec3C) => out.set(pos[i * 3], pos[i * 3 + 1], pos[i * 3 + 2])\n\n const n = plane.normal\n const va = new Vec3C()\n const vb = new Vec3C()\n const vc = new Vec3C()\n\n // 收集交线段(每条 2 个 3D 端点,均在截面上)\n const segments: [Vec3C, Vec3C][] = []\n let hitTriangleCount = 0\n\n for (const r of refs) {\n at(r.a, va); at(r.b, vb); at(r.c, vc)\n const da = n.dot(va) + plane.constant\n const db = n.dot(vb) + plane.constant\n const dc = n.dot(vc) + plane.constant\n\n const above = (d: number) => d > EPS_SURFACE\n const below = (d: number) => d < -EPS_SURFACE\n const onSurf = (d: number) => !above(d) && !below(d)\n\n // 交点插值:在 a、b 边上按距离比例\n const lerp = (ia: number, ib: number, daa: number, dbb: number): Vec3C => {\n const pa = ia === r.a ? va : ia === r.b ? vb : vc\n const pb = ib === r.a ? va : ib === r.b ? vb : vc\n const t = daa / (daa - dbb)\n return new Vec3C().lerpVectors(pa, pb, t)\n }\n\n const crossings: Vec3C[] = []\n if (onSurf(da) && (above(db) !== above(dc) || below(db) !== below(dc))) {\n crossings.push(va.clone())\n }\n if (onSurf(db) && (above(da) !== above(dc) || below(da) !== below(dc))) {\n crossings.push(vb.clone())\n }\n if (onSurf(dc) && (above(da) !== above(db) || below(da) !== below(db))) {\n crossings.push(vc.clone())\n }\n // 纯跨越:异侧顶点两两组合产生 2 个交点\n const verts = [\n { i: r.a, d: da, p: va },\n { i: r.b, d: db, p: vb },\n { i: r.c, d: dc, p: vc },\n ]\n const pos_ = verts.filter((x) => above(x.d) || onSurf(x.d))\n const neg_ = verts.filter((x) => below(x.d) || onSurf(x.d))\n // 标准 straddle:恰好 1 顶点在一侧、2 在另一侧 → 两条跨边各一个交点\n if (pos_.length === 1 && neg_.length === 2) {\n const p = pos_[0]\n const [q1, q2] = neg_\n crossings.push(lerp(p.i, q1.i, p.d, q1.d))\n crossings.push(lerp(p.i, q2.i, p.d, q2.d))\n } else if (neg_.length === 1 && pos_.length === 2) {\n const p = neg_[0]\n const [q1, q2] = pos_\n crossings.push(lerp(p.i, q1.i, p.d, q1.d))\n crossings.push(lerp(p.i, q2.i, p.d, q2.d))\n }\n // 去重(同一三角形内重复端点)\n const uniq: Vec3C[] = []\n for (const c of crossings) {\n if (!uniq.some((u) => u.distanceToSquared(c) < 1e-12)) uniq.push(c)\n }\n if (uniq.length >= 2) {\n hitTriangleCount++\n for (let k = 0; k + 1 < uniq.length; k += 2) {\n segments.push([uniq[k], uniq[k + 1]])\n }\n }\n }\n\n const { u, v } = planeBasis(n)\n\n // 缝合:按量化端点建邻接,沿共享端点 walk 出闭合环\n const endpoints = new Map<string, Array<{ seg: number; end: 0 | 1 }>>()\n segments.forEach((seg, si) => {\n const ka = key2D(project2D(seg[0], u, v))\n const kb = key2D(project2D(seg[1], u, v))\n if (!endpoints.has(ka)) endpoints.set(ka, [])\n if (!endpoints.has(kb)) endpoints.set(kb, [])\n endpoints.get(ka)!.push({ seg: si, end: 0 })\n endpoints.get(kb)!.push({ seg: si, end: 1 })\n })\n\n const visited = new Set<number>()\n const loops: Vec3C[][] = []\n for (let si = 0; si < segments.length; si++) {\n if (visited.has(si)) continue\n const loop: Vec3C[] = []\n const start = segments[si][0]\n loop.push(start)\n visited.add(si)\n let curKey = key2D(project2D(segments[si][1], u, v))\n const startKey = key2D(project2D(start, u, v))\n // 防止无限循环\n let guard = 0\n const maxSteps = segments.length * 2 + 4\n while (guard++ < maxSteps) {\n const cands = endpoints.get(curKey)?.filter((c) => !visited.has(c.seg)) ?? []\n if (cands.length === 0) break\n const c = cands[0]\n const otherEnd = c.end === 0 ? segments[c.seg][1] : segments[c.seg][0]\n loop.push(otherEnd)\n visited.add(c.seg)\n const nk = key2D(project2D(otherEnd, u, v))\n if (nk === startKey) break\n curKey = nk\n }\n loops.push(loop)\n }\n\n // 分类外环/孔环。\n // 关键:不能单纯按「面积<0 即孔」判断,因为缝合出的环绕序不固定(可能整体 CW)。\n // 正确做法:以「绝对面积最大的环」为外环基准,其有向面积符号 outerSign 定义外环方向;\n // 与之同号者为外环、异号者为孔环。这样即使所有环都 CW,最大面积环仍被正确认作外环。\n const signedArea = (loop: Vec3C[]): number => {\n let area = 0\n for (let i = 0; i < loop.length; i++) {\n const p = project2D(loop[i], u, v)\n const q = project2D(loop[(i + 1) % loop.length], u, v)\n area += p.x * q.y - q.x * p.y\n }\n return area / 2\n }\n\n const areas = loops.map((pts) => signedArea(pts))\n let maxIdx = 0\n for (let i = 1; i < areas.length; i++) {\n if (Math.abs(areas[i]) > Math.abs(areas[maxIdx])) maxIdx = i\n }\n const outerSign = areas.length > 0 ? Math.sign(areas[maxIdx]) || 1 : 1\n\n const rings: SectionRing[] = loops.map((pts, i) => {\n const isHole = Math.sign(areas[i]) !== outerSign\n // 统一:外环取 outerSign(CCW),孔环取 -outerSign(CW)\n const wantSign = isHole ? -outerSign : outerSign\n const oriented = Math.sign(areas[i]) !== wantSign ? [...pts].reverse() : pts\n return { points: oriented, isHole }\n })\n\n const outers = rings.filter((r) => !r.isHole).map((r) => r.points)\n const holes = rings.filter((r) => r.isHole).map((r) => r.points)\n\n // 把孔分给包含其重心的外环\n const holesOf: Vec3C[][][] = outers.map(() => [])\n const centroid = (loop: Vec3C[]): Vec2 => {\n const c = new Vec2()\n for (const p of loop) c.add(project2D(p, u, v))\n return c.multiplyScalar(1 / Math.max(1, loop.length))\n }\n const pointInLoop = (pt: Vec2, loop: Vec3C[]): boolean => {\n let inside = false\n for (let i = 0, j = loop.length - 1; i < loop.length; j = i++) {\n const a = project2D(loop[i], u, v)\n const b = project2D(loop[j], u, v)\n if (a.y > pt.y !== b.y > pt.y && pt.x < ((b.x - a.x) * (pt.y - a.y)) / (b.y - a.y) + a.x) {\n inside = !inside\n }\n }\n return inside\n }\n holes.forEach((h) => {\n const hc = centroid(h)\n let assigned = -1\n for (let oi = 0; oi < outers.length; oi++) {\n if (pointInLoop(hc, outers[oi])) { assigned = oi; break }\n }\n if (assigned < 0) assigned = 0\n holesOf[assigned].push(h)\n })\n\n return { rings, outers, holesOf, hitTriangleCount, segmentCount: segments.length }\n}\n\n/**\n * Build a prism geometry by extruding the section rings along the normal for\n * `length`, starting at `start` (in local space). The output contains the cap\n * triangulation (top/bottom faces) plus the side walls of every boundary loop.\n * It can be fed directly to a THREE.BufferGeometry or converted to ManifoldMeshData.\n *\n * @param section computeSection result\n * @param normal Extrusion direction (local space, unit vector)\n * @param length Extrusion length\n * @param start Start offset along the normal (centered mode passes offsetBack so the prism spans [offsetBack, offsetFront])\n * @returns Filled position and index buffers describing the extruded prism.\n */\nexport function buildExtrudedProfile(\n section: SectionResult,\n normal: Vec3C,\n length: number,\n start = 0,\n): { positions: Float32Array; indices: Uint32Array } {\n const positions: number[] = []\n const indices: number[] = []\n const dx = normal.x * length\n const dy = normal.y * length\n const dz = normal.z * length\n const sx = normal.x * start\n const sy = normal.y * start\n const sz = normal.z * start\n\n section.outers.forEach((outer, oi) => {\n const holeLoops = section.holesOf[oi]\n // 本组所有边界环(外环在前,孔环随后),顺序即 pts3D 顺序,也是 triangulateShape 的顶点顺序\n const allLoops: Vec3C[][] = [outer, ...holeLoops]\n const offsets: number[] = []\n const pts3D: Vec3C[] = []\n for (const loop of allLoops) {\n offsets.push(pts3D.length)\n pts3D.push(...loop)\n }\n const basis = planeBasis(normal)\n const to2D = (p: Vec3C) => project2D(p, basis.u, basis.v)\n const tris = triangulateWithEarcut(\n outer.map(to2D),\n holeLoops.map((h) => h.map(to2D)),\n )\n if (!tris || tris.length === 0) return\n\n const base = positions.length / 3\n const vCount = pts3D.length\n // bottom cap(含 start 偏移)\n for (const p of pts3D) positions.push(p.x + sx, p.y + sy, p.z + sz)\n for (const t of tris) indices.push(base + t[0], base + t[1], base + t[2])\n // top cap(reversed winding)\n const topBase = base + vCount\n for (const p of pts3D) positions.push(p.x + sx + dx, p.y + sy + dy, p.z + sz + dz)\n for (const t of tris) indices.push(topBase + t[0], topBase + t[2], topBase + t[1])\n\n // 侧壁:每个边界环的相邻顶点构成竖直 quad(用环内偏移,避免引用查找)\n allLoops.forEach((loop, li) => {\n const off = offsets[li]\n const len = loop.length\n for (let k = 0; k < len; k++) {\n const a = off + k\n const b = off + ((k + 1) % len)\n indices.push(base + a, base + b, topBase + b)\n indices.push(base + a, topBase + b, topBase + a)\n }\n })\n })\n\n return { positions: new Float32Array(positions), indices: new Uint32Array(indices) }\n}\n"]}
1
+ {"version":3,"file":"cross-section.js","sourceRoot":"","sources":["../../src/boolean/cross-section.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 截面求解器(无 CSG / 无 Manifold.simplify)\n *\n * 给定源网格(THREE.BufferGeometry)和一个局部空间平面,直接求「平面与网格的\n * 交线」,缝合成闭合环(外环 + 孔环),并三角化出截面 cap。这是「拉伸预览无\n * split 方案」的唯一 CPU 几何成本。\n *\n * 为什么不用 Manifold.split:\n * - split 是整模型布尔运算(焊接 + 全分辨率 CSG),168 万三角面 4~8s/次;\n * - 本方案只做三角形–平面求交(纯算术),O(n),且后续可叠加 BVH 降到 O(log n + k)。\n *\n * 设计契约(与 ExtrudeRenderer 现有代码对齐):\n * - 输入平面为「局部空间」THREE.Plane(调用方负责把世界平面经 matrixWorld 逆变换得到)。\n * - computeSection 直接读 geometry.attributes,不拷贝整份顶点缓冲。\n * - 输出的 cap 顶点为局部空间,预览期经 matrixWorld 渲染到世界空间。\n */\nimport { Vec3 as Vec3C, Vec2, Plane } from '../math3d'\n// earcut 上游仅提供 CJS,浏览器/Vite 直接 serve 无法 default import;vendored\n// ESM(`../third-party/earcut`,算法与 npm earcut@2.2.4 逐字节一致,ISC)。\nimport earcut from '../third-party/earcut'\nimport type { Shape } from '../mesh/types'\n\n/**\n * A single closed loop (3D, local space, lying on the section plane).\n * `isHole=false` marks the outer boundary, `true` marks a hole.\n */\nexport interface SectionRing {\n points: Vec3C[]\n isHole: boolean\n}\n\n/**\n * Result of computing a section: the stitched loops and diagnostic counters.\n */\nexport interface SectionResult {\n /** All stitched loops (already classified by area into isHole). */\n rings: SectionRing[]\n /** 外环列表(3D 点)。 */\n outers: Vec3C[][]\n /** 每个外环对应的孔环列表(与 outers 同序)。 */\n holesOf: Vec3C[][][]\n /** 实际参与求交、跨越/贴合平面的三角形数(诊断用)。 */\n hitTriangleCount: number\n /** 收集到的交线段数。 */\n segmentCount: number\n}\n\nconst EPS_SURFACE = 1e-6\n/** 线段端点量化容差(平面 2D 坐标),用于缝合相邻线段。 */\nconst STITCH_TOL = 1e-4\n\nfunction triangulateWithEarcut(contour: Vec2[], holes: Vec2[][]): number[][] {\n const data: number[] = []\n const holeIndices: number[] = []\n let vertexCount = 0\n for (const p of contour) { data.push(p.x, p.y); vertexCount++ }\n for (const hole of holes) {\n holeIndices.push(vertexCount)\n for (const p of hole) { data.push(p.x, p.y); vertexCount++ }\n }\n const flat = earcut(data, holeIndices.length > 0 ? holeIndices : undefined, 2)\n const tris: number[][] = []\n for (let i = 0; i < flat.length; i += 3) tris.push([flat[i], flat[i + 1], flat[i + 2]])\n return tris\n}\n\n/** 平面正交基 (u, v),用于把 3D 截面点投影到 2D 以做缝合/面积/三角化。 */\nfunction planeBasis(normal: Vec3C): { u: Vec3C; v: Vec3C } {\n const n = normal.clone().normalize()\n const t = Math.abs(n.x) < 0.9 ? new Vec3C(1, 0, 0) : new Vec3C(0, 1, 0)\n const u = new Vec3C().crossVectors(t, n).normalize()\n const v = new Vec3C().crossVectors(n, u).normalize()\n return { u, v }\n}\n\nfunction project2D(p: Vec3C, u: Vec3C, v: Vec3C): Vec2 {\n return new Vec2(p.dot(u), p.dot(v))\n}\n\n/**\n * 端点量化到 STITCH_TOL 网格上作为缝合 key。\n * 用 Math.round 而非 toFixed:避免 -0.00001 → \"-0.0000\" 与 0 → \"0.0000\" 被当成两个点。\n */\nfunction key2D(p: Vec2): string {\n return `${Math.round(p.x / STITCH_TOL)},${Math.round(p.y / STITCH_TOL)}`\n}\n\n/** 三角形三个顶点索引(索引几何)或顺次顶点(非索引几何)。 */\ninterface TriRef {\n a: number\n b: number\n c: number\n}\n\n/**\n * Compute the section of a mesh cut by a plane.\n * @param geometry Source mesh (local space), supports indexed and non-indexed.\n * @param plane Local-space cutting plane (THREE.Plane semantics: normal·p + constant = 0).\n * @returns The stitched section rings, outers, holes, and diagnostic counters.\n */\nexport function computeSection(geometry: Shape, plane: Plane): SectionResult {\n const pos = geometry.positions\n const index = geometry.indices\n const triCount = index.length / 3\n\n const refs: TriRef[] = []\n for (let t = 0; t < triCount; t++) {\n refs.push({ a: index[t * 3], b: index[t * 3 + 1], c: index[t * 3 + 2] })\n }\n\n const at = (i: number, out: Vec3C) => out.set(pos[i * 3], pos[i * 3 + 1], pos[i * 3 + 2])\n\n const n = plane.normal\n const va = new Vec3C()\n const vb = new Vec3C()\n const vc = new Vec3C()\n\n // 收集交线段(每条 2 个 3D 端点,均在截面上)\n const segments: [Vec3C, Vec3C][] = []\n let hitTriangleCount = 0\n\n for (const r of refs) {\n at(r.a, va); at(r.b, vb); at(r.c, vc)\n const da = n.dot(va) + plane.constant\n const db = n.dot(vb) + plane.constant\n const dc = n.dot(vc) + plane.constant\n\n const above = (d: number) => d > EPS_SURFACE\n const below = (d: number) => d < -EPS_SURFACE\n const onSurf = (d: number) => !above(d) && !below(d)\n\n // 交点插值:在 a、b 边上按距离比例\n const lerp = (ia: number, ib: number, daa: number, dbb: number): Vec3C => {\n const pa = ia === r.a ? va : ia === r.b ? vb : vc\n const pb = ib === r.a ? va : ib === r.b ? vb : vc\n const t = daa / (daa - dbb)\n return new Vec3C().lerpVectors(pa, pb, t)\n }\n\n const crossings: Vec3C[] = []\n if (onSurf(da) && (above(db) !== above(dc) || below(db) !== below(dc))) {\n crossings.push(va.clone())\n }\n if (onSurf(db) && (above(da) !== above(dc) || below(da) !== below(dc))) {\n crossings.push(vb.clone())\n }\n if (onSurf(dc) && (above(da) !== above(db) || below(da) !== below(db))) {\n crossings.push(vc.clone())\n }\n // 纯跨越:异侧顶点两两组合产生 2 个交点\n const verts = [\n { i: r.a, d: da, p: va },\n { i: r.b, d: db, p: vb },\n { i: r.c, d: dc, p: vc },\n ]\n const pos_ = verts.filter((x) => above(x.d) || onSurf(x.d))\n const neg_ = verts.filter((x) => below(x.d) || onSurf(x.d))\n // 标准 straddle:恰好 1 顶点在一侧、2 在另一侧 → 两条跨边各一个交点\n if (pos_.length === 1 && neg_.length === 2) {\n const p = pos_[0]\n const [q1, q2] = neg_\n crossings.push(lerp(p.i, q1.i, p.d, q1.d))\n crossings.push(lerp(p.i, q2.i, p.d, q2.d))\n } else if (neg_.length === 1 && pos_.length === 2) {\n const p = neg_[0]\n const [q1, q2] = pos_\n crossings.push(lerp(p.i, q1.i, p.d, q1.d))\n crossings.push(lerp(p.i, q2.i, p.d, q2.d))\n }\n // 去重(同一三角形内重复端点)\n const uniq: Vec3C[] = []\n for (const c of crossings) {\n if (!uniq.some((u) => u.distanceToSquared(c) < 1e-12)) uniq.push(c)\n }\n if (uniq.length >= 2) {\n hitTriangleCount++\n for (let k = 0; k + 1 < uniq.length; k += 2) {\n segments.push([uniq[k], uniq[k + 1]])\n }\n }\n }\n\n const { u, v } = planeBasis(n)\n\n // 缝合:按量化端点建邻接,沿共享端点 walk 出闭合环\n const endpoints = new Map<string, Array<{ seg: number; end: 0 | 1 }>>()\n segments.forEach((seg, si) => {\n const ka = key2D(project2D(seg[0], u, v))\n const kb = key2D(project2D(seg[1], u, v))\n if (!endpoints.has(ka)) endpoints.set(ka, [])\n if (!endpoints.has(kb)) endpoints.set(kb, [])\n endpoints.get(ka)!.push({ seg: si, end: 0 })\n endpoints.get(kb)!.push({ seg: si, end: 1 })\n })\n\n const visited = new Set<number>()\n const loops: Vec3C[][] = []\n for (let si = 0; si < segments.length; si++) {\n if (visited.has(si)) continue\n const loop: Vec3C[] = []\n const start = segments[si][0]\n loop.push(start)\n visited.add(si)\n let curKey = key2D(project2D(segments[si][1], u, v))\n const startKey = key2D(project2D(start, u, v))\n // 防止无限循环\n let guard = 0\n const maxSteps = segments.length * 2 + 4\n while (guard++ < maxSteps) {\n const cands = endpoints.get(curKey)?.filter((c) => !visited.has(c.seg)) ?? []\n if (cands.length === 0) break\n const c = cands[0]\n const otherEnd = c.end === 0 ? segments[c.seg][1] : segments[c.seg][0]\n loop.push(otherEnd)\n visited.add(c.seg)\n const nk = key2D(project2D(otherEnd, u, v))\n if (nk === startKey) break\n curKey = nk\n }\n loops.push(loop)\n }\n\n // 分类外环/孔环。\n // 关键:不能单纯按「面积<0 即孔」判断,因为缝合出的环绕序不固定(可能整体 CW)。\n // 正确做法:以「绝对面积最大的环」为外环基准,其有向面积符号 outerSign 定义外环方向;\n // 与之同号者为外环、异号者为孔环。这样即使所有环都 CW,最大面积环仍被正确认作外环。\n const signedArea = (loop: Vec3C[]): number => {\n let area = 0\n for (let i = 0; i < loop.length; i++) {\n const p = project2D(loop[i], u, v)\n const q = project2D(loop[(i + 1) % loop.length], u, v)\n area += p.x * q.y - q.x * p.y\n }\n return area / 2\n }\n\n const areas = loops.map((pts) => signedArea(pts))\n let maxIdx = 0\n for (let i = 1; i < areas.length; i++) {\n if (Math.abs(areas[i]) > Math.abs(areas[maxIdx])) maxIdx = i\n }\n const outerSign = areas.length > 0 ? Math.sign(areas[maxIdx]) || 1 : 1\n\n const rings: SectionRing[] = loops.map((pts, i) => {\n const isHole = Math.sign(areas[i]) !== outerSign\n // 统一:外环取 outerSign(CCW),孔环取 -outerSign(CW)\n const wantSign = isHole ? -outerSign : outerSign\n const oriented = Math.sign(areas[i]) !== wantSign ? [...pts].reverse() : pts\n return { points: oriented, isHole }\n })\n\n const outers = rings.filter((r) => !r.isHole).map((r) => r.points)\n const holes = rings.filter((r) => r.isHole).map((r) => r.points)\n\n // 把孔分给包含其重心的外环\n const holesOf: Vec3C[][][] = outers.map(() => [])\n const centroid = (loop: Vec3C[]): Vec2 => {\n const c = new Vec2()\n for (const p of loop) c.add(project2D(p, u, v))\n return c.multiplyScalar(1 / Math.max(1, loop.length))\n }\n const pointInLoop = (pt: Vec2, loop: Vec3C[]): boolean => {\n let inside = false\n for (let i = 0, j = loop.length - 1; i < loop.length; j = i++) {\n const a = project2D(loop[i], u, v)\n const b = project2D(loop[j], u, v)\n if (a.y > pt.y !== b.y > pt.y && pt.x < ((b.x - a.x) * (pt.y - a.y)) / (b.y - a.y) + a.x) {\n inside = !inside\n }\n }\n return inside\n }\n holes.forEach((h) => {\n const hc = centroid(h)\n let assigned = -1\n for (let oi = 0; oi < outers.length; oi++) {\n if (pointInLoop(hc, outers[oi])) { assigned = oi; break }\n }\n if (assigned < 0) assigned = 0\n holesOf[assigned].push(h)\n })\n\n return { rings, outers, holesOf, hitTriangleCount, segmentCount: segments.length }\n}\n\n/**\n * Build a prism geometry by extruding the section rings along the normal for\n * `length`, starting at `start` (in local space). The output contains the cap\n * triangulation (top/bottom faces) plus the side walls of every boundary loop.\n * It can be fed directly to a THREE.BufferGeometry or converted to ManifoldMeshData.\n *\n * @param section computeSection result\n * @param normal Extrusion direction (local space, unit vector)\n * @param length Extrusion length\n * @param start Start offset along the normal (centered mode passes offsetBack so the prism spans [offsetBack, offsetFront])\n * @returns Filled position and index buffers describing the extruded prism.\n */\nexport function buildExtrudedProfile(\n section: SectionResult,\n normal: Vec3C,\n length: number,\n start = 0,\n): { positions: Float32Array; indices: Uint32Array } {\n const positions: number[] = []\n const indices: number[] = []\n const dx = normal.x * length\n const dy = normal.y * length\n const dz = normal.z * length\n const sx = normal.x * start\n const sy = normal.y * start\n const sz = normal.z * start\n\n section.outers.forEach((outer, oi) => {\n const holeLoops = section.holesOf[oi]\n // 本组所有边界环(外环在前,孔环随后),顺序即 pts3D 顺序,也是 triangulateShape 的顶点顺序\n const allLoops: Vec3C[][] = [outer, ...holeLoops]\n const offsets: number[] = []\n const pts3D: Vec3C[] = []\n for (const loop of allLoops) {\n offsets.push(pts3D.length)\n pts3D.push(...loop)\n }\n const basis = planeBasis(normal)\n const to2D = (p: Vec3C) => project2D(p, basis.u, basis.v)\n const tris = triangulateWithEarcut(\n outer.map(to2D),\n holeLoops.map((h) => h.map(to2D)),\n )\n if (!tris || tris.length === 0) return\n\n const base = positions.length / 3\n const vCount = pts3D.length\n // bottom cap(含 start 偏移)\n for (const p of pts3D) positions.push(p.x + sx, p.y + sy, p.z + sz)\n for (const t of tris) indices.push(base + t[0], base + t[1], base + t[2])\n // top cap(reversed winding)\n const topBase = base + vCount\n for (const p of pts3D) positions.push(p.x + sx + dx, p.y + sy + dy, p.z + sz + dz)\n for (const t of tris) indices.push(topBase + t[0], topBase + t[2], topBase + t[1])\n\n // 侧壁:每个边界环的相邻顶点构成竖直 quad(用环内偏移,避免引用查找)\n allLoops.forEach((loop, li) => {\n const off = offsets[li]\n const len = loop.length\n for (let k = 0; k < len; k++) {\n const a = off + k\n const b = off + ((k + 1) % len)\n indices.push(base + a, base + b, topBase + b)\n indices.push(base + a, topBase + b, topBase + a)\n }\n })\n })\n\n return { positions: new Float32Array(positions), indices: new Uint32Array(indices) }\n}\n"]}
@@ -385,6 +385,32 @@ export declare function loadBrepAssembly(kernel: BrepEngineApi, buffer: ArrayBuf
385
385
  assembly?: ImportAssemblyNode;
386
386
  multiSolidCount?: number;
387
387
  }>;
388
+ /**
389
+ * BREP-native 多零件 STEP 导入 —— **无 XCAF 的引擎**的装配读取通道。
390
+ *
391
+ * 与 `loadBrepAssembly`(XCAF 装配树,occt-only)对照:本函数只用 L1 契约面
392
+ * (`kernel.importStep` / `kernel.fromBREP` / `kernel.getSubShapes`),因此对任何
393
+ * 实现了这两个方法的引擎成立(brepkit 即此路径)。代价是拿不到 XCAF 的零件名 /
394
+ * 颜色 / 装配层级——零件身份退回 `imported:<index>`,`assembly` 不产出。这是
395
+ * **引擎能力事实**,不是静默降级(调用方按引擎 id 静态分派,见下)。
396
+ *
397
+ * 分派规则(静态,无运行时回退):XCAF(`STEPCAFControl_Reader`)是 occt 内核的
398
+ * 装配读取器,brepkit 没有;调用方按当前引擎 id 选择本函数还是 XCAF 版本
399
+ * (`cad.load` 见 `packages/faijs-extra/src/ops/load.ts`),不靠 try-catch 探测。
400
+ *
401
+ * 句柄归属:返回的每个 `part.solid` 即内核枚举出的实体本身(生命周期交给调用方,
402
+ * `fromBrep` 绑定后归 brepChain)。顶层包装句柄在本函数内释放——但**若顶层句柄
403
+ * 就是枚举出的那个实体**(brepkit 的 `getSubShapes(solid,'solid')` 对单实体返回
404
+ * 自身,见 brepkitKernel 的 `catch { list = [s] }`)则不释放,否则返回件被释放。
405
+ *
406
+ * @param kernel - the initialized BREP kernel (L1 contract face).
407
+ * @param buffer - the raw STEP (or CASCADE BREP text) file bytes.
408
+ * @returns 全部实体零件(内核枚举序,index 连续)+ 实体数(>1 时)。
409
+ */
410
+ export declare function loadBrepAssemblyNative(kernel: BrepEngineApi, buffer: ArrayBuffer): {
411
+ parts: LoadBrepAssemblyPart[];
412
+ multiSolidCount?: number;
413
+ };
388
414
  /**
389
415
  * Convert a Mat4 into the 3x4 row-major array (12 doubles) the OCCT
390
416
  * transform expects.