@faicad/faijs 0.16.0 → 0.17.0

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 (490) hide show
  1. package/LICENSE +4 -5
  2. package/NOTICE +5 -6
  3. package/dist/api/api-namespace.d.ts.map +1 -1
  4. package/dist/api/api-namespace.js +19 -1
  5. package/dist/api/api-namespace.js.map +1 -1
  6. package/dist/api/assembly/entities.d.ts +1 -1
  7. package/dist/api/assembly/entities.d.ts.map +1 -1
  8. package/dist/api/assembly/entities.js.map +1 -1
  9. package/dist/api/assembly/joints.d.ts +2 -2
  10. package/dist/api/assembly/joints.d.ts.map +1 -1
  11. package/dist/api/assembly/joints.js +2 -2
  12. package/dist/api/assembly/joints.js.map +1 -1
  13. package/dist/api/assembly/lower.d.ts +1 -1
  14. package/dist/api/assembly/lower.d.ts.map +1 -1
  15. package/dist/api/assembly/lower.js.map +1 -1
  16. package/dist/api/assembly/pose.d.ts +3 -3
  17. package/dist/api/assembly/pose.d.ts.map +1 -1
  18. package/dist/api/assembly/pose.js +1 -1
  19. package/dist/api/assembly/pose.js.map +1 -1
  20. package/dist/api/assembly/preview.d.ts +1 -1
  21. package/dist/api/assembly/preview.d.ts.map +1 -1
  22. package/dist/api/assembly/preview.js +1 -1
  23. package/dist/api/assembly/preview.js.map +1 -1
  24. package/dist/api/assembly/solve.d.ts.map +1 -1
  25. package/dist/api/assembly/solve.js +3 -3
  26. package/dist/api/assembly/solve.js.map +1 -1
  27. package/dist/api/assembly/solvers/assembly-tree.d.ts +98 -0
  28. package/dist/api/assembly/solvers/assembly-tree.d.ts.map +1 -0
  29. package/dist/api/assembly/solvers/assembly-tree.js +130 -0
  30. package/dist/api/assembly/solvers/assembly-tree.js.map +1 -0
  31. package/dist/api/assembly/solvers/chain-solver.d.ts +27 -0
  32. package/dist/api/assembly/solvers/chain-solver.d.ts.map +1 -0
  33. package/dist/api/assembly/solvers/chain-solver.js +330 -0
  34. package/dist/api/assembly/solvers/chain-solver.js.map +1 -0
  35. package/dist/api/assembly/solvers/global-solver.js +2 -2
  36. package/dist/api/assembly/solvers/global-solver.js.map +1 -1
  37. package/dist/api/assembly/solvers/joints-kinematics.d.ts +308 -0
  38. package/dist/api/assembly/solvers/joints-kinematics.d.ts.map +1 -0
  39. package/dist/api/assembly/solvers/joints-kinematics.js +643 -0
  40. package/dist/api/assembly/solvers/joints-kinematics.js.map +1 -0
  41. package/dist/api/assembly/solvers/quat.d.ts +35 -0
  42. package/dist/api/assembly/solvers/quat.d.ts.map +1 -0
  43. package/dist/api/assembly/solvers/quat.js +84 -0
  44. package/dist/api/assembly/solvers/quat.js.map +1 -0
  45. package/dist/api/assembly/solvers/types.d.ts +33 -0
  46. package/dist/api/assembly/solvers/types.d.ts.map +1 -1
  47. package/dist/api/assembly/solvers/types.js.map +1 -1
  48. package/dist/api/boolean.d.ts.map +1 -1
  49. package/dist/api/boolean.js +3 -4
  50. package/dist/api/boolean.js.map +1 -1
  51. package/dist/api/brep-mirror/booleanFns.d.ts +40 -0
  52. package/dist/api/brep-mirror/booleanFns.d.ts.map +1 -0
  53. package/dist/api/brep-mirror/booleanFns.js +99 -0
  54. package/dist/api/brep-mirror/booleanFns.js.map +1 -0
  55. package/dist/api/brep-mirror/brepHelpers.d.ts +55 -0
  56. package/dist/api/brep-mirror/brepHelpers.d.ts.map +1 -0
  57. package/dist/api/brep-mirror/brepHelpers.js +131 -0
  58. package/dist/api/brep-mirror/brepHelpers.js.map +1 -0
  59. package/dist/api/brep-mirror/compoundFns.d.ts +47 -0
  60. package/dist/api/brep-mirror/compoundFns.d.ts.map +1 -0
  61. package/dist/api/brep-mirror/compoundFns.js +300 -0
  62. package/dist/api/brep-mirror/compoundFns.js.map +1 -0
  63. package/dist/api/brep-mirror/healingFns.d.ts +78 -0
  64. package/dist/api/brep-mirror/healingFns.d.ts.map +1 -0
  65. package/dist/api/brep-mirror/healingFns.js +294 -0
  66. package/dist/api/brep-mirror/healingFns.js.map +1 -0
  67. package/dist/api/brep-mirror/hullFns.d.ts +20 -0
  68. package/dist/api/brep-mirror/hullFns.d.ts.map +1 -0
  69. package/dist/api/brep-mirror/hullFns.js +46 -0
  70. package/dist/api/brep-mirror/hullFns.js.map +1 -0
  71. package/dist/api/brep-mirror/patternFns.d.ts +43 -0
  72. package/dist/api/brep-mirror/patternFns.d.ts.map +1 -0
  73. package/dist/api/brep-mirror/patternFns.js +178 -0
  74. package/dist/api/brep-mirror/patternFns.js.map +1 -0
  75. package/dist/api/brep-mirror/primitiveFns.d.ts +42 -0
  76. package/dist/api/brep-mirror/primitiveFns.d.ts.map +1 -0
  77. package/dist/api/brep-mirror/primitiveFns.js +104 -0
  78. package/dist/api/brep-mirror/primitiveFns.js.map +1 -0
  79. package/dist/api/brep-mirror/roofFns.d.ts +24 -0
  80. package/dist/api/brep-mirror/roofFns.d.ts.map +1 -0
  81. package/dist/api/brep-mirror/roofFns.js +229 -0
  82. package/dist/api/brep-mirror/roofFns.js.map +1 -0
  83. package/dist/api/brep-mirror/straightSkeleton.d.ts +36 -0
  84. package/dist/api/brep-mirror/straightSkeleton.d.ts.map +1 -0
  85. package/dist/api/brep-mirror/straightSkeleton.js +443 -0
  86. package/dist/api/brep-mirror/straightSkeleton.js.map +1 -0
  87. package/dist/api/brep-mirror/sweepFns.d.ts +55 -0
  88. package/dist/api/brep-mirror/sweepFns.d.ts.map +1 -0
  89. package/dist/api/brep-mirror/sweepFns.js +200 -0
  90. package/dist/api/brep-mirror/sweepFns.js.map +1 -0
  91. package/dist/api/brep-mirror/threadFns.d.ts +15 -0
  92. package/dist/api/brep-mirror/threadFns.d.ts.map +1 -1
  93. package/dist/api/brep-mirror/threadFns.js +37 -2
  94. package/dist/api/brep-mirror/threadFns.js.map +1 -1
  95. package/dist/api/brep-mirror/topologyFns.d.ts +74 -0
  96. package/dist/api/brep-mirror/topologyFns.d.ts.map +1 -0
  97. package/dist/api/brep-mirror/topologyFns.js +273 -0
  98. package/dist/api/brep-mirror/topologyFns.js.map +1 -0
  99. package/dist/api/brep-topology.d.ts +190 -0
  100. package/dist/api/brep-topology.d.ts.map +1 -0
  101. package/dist/api/brep-topology.js +337 -0
  102. package/dist/api/brep-topology.js.map +1 -0
  103. package/dist/api/brepjs-compat/constants.d.ts +11 -0
  104. package/dist/api/brepjs-compat/constants.d.ts.map +1 -0
  105. package/dist/api/brepjs-compat/constants.js +11 -0
  106. package/dist/api/brepjs-compat/constants.js.map +1 -0
  107. package/dist/api/brepjs-compat/index.d.ts +19 -232
  108. package/dist/api/brepjs-compat/index.d.ts.map +1 -1
  109. package/dist/api/brepjs-compat/index.js +19 -286
  110. package/dist/api/brepjs-compat/index.js.map +1 -1
  111. package/dist/api/brepjs-compat/planeOps.d.ts +98 -0
  112. package/dist/api/brepjs-compat/planeOps.d.ts.map +1 -0
  113. package/dist/api/brepjs-compat/planeOps.js +170 -0
  114. package/dist/api/brepjs-compat/planeOps.js.map +1 -0
  115. package/dist/api/brepjs-compat/planeTypes.d.ts +24 -0
  116. package/dist/api/brepjs-compat/planeTypes.d.ts.map +1 -0
  117. package/dist/api/brepjs-compat/planeTypes.js +8 -0
  118. package/dist/api/brepjs-compat/planeTypes.js.map +1 -0
  119. package/dist/api/brepjs-compat/types.d.ts +64 -0
  120. package/dist/api/brepjs-compat/types.d.ts.map +1 -0
  121. package/dist/api/brepjs-compat/types.js +48 -0
  122. package/dist/api/brepjs-compat/types.js.map +1 -0
  123. package/dist/api/brepjs-compat/vecOps.d.ts +124 -0
  124. package/dist/api/brepjs-compat/vecOps.d.ts.map +1 -0
  125. package/dist/api/brepjs-compat/vecOps.js +202 -0
  126. package/dist/api/brepjs-compat/vecOps.js.map +1 -0
  127. package/dist/api/chamfer.d.ts +5 -0
  128. package/dist/api/chamfer.d.ts.map +1 -1
  129. package/dist/api/chamfer.js +13 -8
  130. package/dist/api/chamfer.js.map +1 -1
  131. package/dist/api/compound-geom.d.ts.map +1 -1
  132. package/dist/api/compound-geom.js +8 -2
  133. package/dist/api/compound-geom.js.map +1 -1
  134. package/dist/api/draft.d.ts +69 -0
  135. package/dist/api/draft.d.ts.map +1 -0
  136. package/dist/api/draft.js +109 -0
  137. package/dist/api/draft.js.map +1 -0
  138. package/dist/api/edge-ref.d.ts.map +1 -1
  139. package/dist/api/edge-ref.js +2 -2
  140. package/dist/api/edge-ref.js.map +1 -1
  141. package/dist/api/engrave.d.ts.map +1 -1
  142. package/dist/api/engrave.js +2 -3
  143. package/dist/api/engrave.js.map +1 -1
  144. package/dist/api/extrude.d.ts.map +1 -1
  145. package/dist/api/extrude.js +28 -13
  146. package/dist/api/extrude.js.map +1 -1
  147. package/dist/api/face-ref.d.ts.map +1 -1
  148. package/dist/api/face-ref.js +2 -2
  149. package/dist/api/face-ref.js.map +1 -1
  150. package/dist/api/feature-repair.d.ts +137 -0
  151. package/dist/api/feature-repair.d.ts.map +1 -0
  152. package/dist/api/feature-repair.js +221 -0
  153. package/dist/api/feature-repair.js.map +1 -0
  154. package/dist/api/fillet-variable.d.ts +35 -0
  155. package/dist/api/fillet-variable.d.ts.map +1 -0
  156. package/dist/api/fillet-variable.js +71 -0
  157. package/dist/api/fillet-variable.js.map +1 -0
  158. package/dist/api/fillet.d.ts +3 -0
  159. package/dist/api/fillet.d.ts.map +1 -1
  160. package/dist/api/fillet.js +7 -4
  161. package/dist/api/fillet.js.map +1 -1
  162. package/dist/api/generated/2d.d.ts +1 -13
  163. package/dist/api/generated/2d.d.ts.map +1 -1
  164. package/dist/api/generated/2d.js +6 -1
  165. package/dist/api/generated/2d.js.map +1 -1
  166. package/dist/api/generated/brepjs/index.d.ts +298 -298
  167. package/dist/api/generated/brepjs/index.d.ts.map +1 -1
  168. package/dist/api/generated/brepjs/index.js +183 -183
  169. package/dist/api/generated/brepjs/index.js.map +1 -1
  170. package/dist/api/generated/core.d.ts +3 -123
  171. package/dist/api/generated/core.d.ts.map +1 -1
  172. package/dist/api/generated/core.js +2 -81
  173. package/dist/api/generated/core.js.map +1 -1
  174. package/dist/api/generated/gear.d.ts +1 -15
  175. package/dist/api/generated/gear.d.ts.map +1 -1
  176. package/dist/api/generated/gear.js +6 -3
  177. package/dist/api/generated/gear.js.map +1 -1
  178. package/dist/api/generated/io.d.ts +1 -13
  179. package/dist/api/generated/io.d.ts.map +1 -1
  180. package/dist/api/generated/io.js +6 -1
  181. package/dist/api/generated/io.js.map +1 -1
  182. package/dist/api/generated/kernel.d.ts +1 -39
  183. package/dist/api/generated/kernel.d.ts.map +1 -1
  184. package/dist/api/generated/kernel.js +6 -4
  185. package/dist/api/generated/kernel.js.map +1 -1
  186. package/dist/api/generated/measurement.d.ts +53 -97
  187. package/dist/api/generated/measurement.d.ts.map +1 -1
  188. package/dist/api/generated/measurement.js +48 -143
  189. package/dist/api/generated/measurement.js.map +1 -1
  190. package/dist/api/generated/ns.d.ts +1 -10
  191. package/dist/api/generated/ns.d.ts.map +1 -1
  192. package/dist/api/generated/ns.js +2 -10
  193. package/dist/api/generated/ns.js.map +1 -1
  194. package/dist/api/generated/operations.d.ts +65 -110
  195. package/dist/api/generated/operations.d.ts.map +1 -1
  196. package/dist/api/generated/operations.js +132 -80
  197. package/dist/api/generated/operations.js.map +1 -1
  198. package/dist/api/generated/projection.d.ts +1 -8
  199. package/dist/api/generated/projection.d.ts.map +1 -1
  200. package/dist/api/generated/projection.js +6 -4
  201. package/dist/api/generated/projection.js.map +1 -1
  202. package/dist/api/generated/query.d.ts +1 -9
  203. package/dist/api/generated/query.d.ts.map +1 -1
  204. package/dist/api/generated/query.js +6 -1
  205. package/dist/api/generated/query.js.map +1 -1
  206. package/dist/api/generated/script-face-manifest.d.ts +2 -0
  207. package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
  208. package/dist/api/generated/script-face-manifest.js +34 -22
  209. package/dist/api/generated/script-face-manifest.js.map +1 -1
  210. package/dist/api/generated/script-face.d.ts +52 -27
  211. package/dist/api/generated/script-face.d.ts.map +1 -1
  212. package/dist/api/generated/script-face.js +18 -4
  213. package/dist/api/generated/script-face.js.map +1 -1
  214. package/dist/api/generated/sketching.d.ts +4 -7
  215. package/dist/api/generated/sketching.d.ts.map +1 -1
  216. package/dist/api/generated/sketching.js +10 -8
  217. package/dist/api/generated/sketching.js.map +1 -1
  218. package/dist/api/generated/text.d.ts +1 -6
  219. package/dist/api/generated/text.d.ts.map +1 -1
  220. package/dist/api/generated/text.js +6 -3
  221. package/dist/api/generated/text.js.map +1 -1
  222. package/dist/api/generated/topology.d.ts +77 -175
  223. package/dist/api/generated/topology.d.ts.map +1 -1
  224. package/dist/api/generated/topology.js +172 -131
  225. package/dist/api/generated/topology.js.map +1 -1
  226. package/dist/api/geom.d.ts.map +1 -1
  227. package/dist/api/geom.js +2 -2
  228. package/dist/api/geom.js.map +1 -1
  229. package/dist/api/helix.d.ts +51 -0
  230. package/dist/api/helix.d.ts.map +1 -0
  231. package/dist/api/helix.js +63 -0
  232. package/dist/api/helix.js.map +1 -0
  233. package/dist/api/import-step.d.ts.map +1 -1
  234. package/dist/api/import-step.js +6 -2
  235. package/dist/api/import-step.js.map +1 -1
  236. package/dist/api/index.d.ts +18 -5
  237. package/dist/api/index.d.ts.map +1 -1
  238. package/dist/api/index.js +29 -12
  239. package/dist/api/index.js.map +1 -1
  240. package/dist/api/internal/compat-op.d.ts +10 -0
  241. package/dist/api/internal/compat-op.d.ts.map +1 -1
  242. package/dist/api/internal/compat-op.js +9 -3
  243. package/dist/api/internal/compat-op.js.map +1 -1
  244. package/dist/api/internal/compat-projection.d.ts +4 -4
  245. package/dist/api/internal/compat-projection.js +7 -7
  246. package/dist/api/internal/compat-projection.js.map +1 -1
  247. package/dist/api/internal/l3-bridge.d.ts +75 -42
  248. package/dist/api/internal/l3-bridge.d.ts.map +1 -1
  249. package/dist/api/internal/l3-bridge.js +105 -50
  250. package/dist/api/internal/l3-bridge.js.map +1 -1
  251. package/dist/api/internal/profile-wire.d.ts +31 -0
  252. package/dist/api/internal/profile-wire.d.ts.map +1 -0
  253. package/dist/api/internal/profile-wire.js +37 -0
  254. package/dist/api/internal/profile-wire.js.map +1 -0
  255. package/dist/api/internal/replica-role-table.js +2 -2
  256. package/dist/api/internal/replica-role-table.js.map +1 -1
  257. package/dist/api/loft.d.ts +66 -0
  258. package/dist/api/loft.d.ts.map +1 -0
  259. package/dist/api/loft.js +111 -0
  260. package/dist/api/loft.js.map +1 -0
  261. package/dist/api/measurement/index.d.ts +51 -0
  262. package/dist/api/measurement/index.d.ts.map +1 -0
  263. package/dist/api/measurement/index.js +71 -0
  264. package/dist/api/measurement/index.js.map +1 -0
  265. package/dist/api/occt-kernel-bridge.d.ts +5 -8
  266. package/dist/api/occt-kernel-bridge.d.ts.map +1 -1
  267. package/dist/api/occt-kernel-bridge.js +18 -14
  268. package/dist/api/occt-kernel-bridge.js.map +1 -1
  269. package/dist/api/pattern.d.ts.map +1 -1
  270. package/dist/api/pattern.js +3 -4
  271. package/dist/api/pattern.js.map +1 -1
  272. package/dist/api/place.d.ts.map +1 -1
  273. package/dist/api/place.js +2 -4
  274. package/dist/api/place.js.map +1 -1
  275. package/dist/api/primitives.d.ts.map +1 -1
  276. package/dist/api/primitives.js +3 -4
  277. package/dist/api/primitives.js.map +1 -1
  278. package/dist/api/replicate.d.ts +28 -1
  279. package/dist/api/replicate.d.ts.map +1 -1
  280. package/dist/api/replicate.js +29 -19
  281. package/dist/api/replicate.js.map +1 -1
  282. package/dist/api/result.d.ts +6 -11
  283. package/dist/api/result.d.ts.map +1 -1
  284. package/dist/api/result.js +6 -11
  285. package/dist/api/result.js.map +1 -1
  286. package/dist/api/revolve.d.ts.map +1 -1
  287. package/dist/api/revolve.js +15 -14
  288. package/dist/api/revolve.js.map +1 -1
  289. package/dist/api/screw.d.ts +3 -0
  290. package/dist/api/screw.d.ts.map +1 -1
  291. package/dist/api/screw.js +9 -4
  292. package/dist/api/screw.js.map +1 -1
  293. package/dist/api/sdf.d.ts +1 -1
  294. package/dist/api/section-by-plane.d.ts +42 -0
  295. package/dist/api/section-by-plane.d.ts.map +1 -0
  296. package/dist/api/section-by-plane.js +61 -0
  297. package/dist/api/section-by-plane.js.map +1 -0
  298. package/dist/api/shell.d.ts +45 -0
  299. package/dist/api/shell.d.ts.map +1 -0
  300. package/dist/api/shell.js +73 -0
  301. package/dist/api/shell.js.map +1 -0
  302. package/dist/api/sketch.d.ts +8 -1
  303. package/dist/api/sketch.d.ts.map +1 -1
  304. package/dist/api/sketch.js +12 -7
  305. package/dist/api/sketch.js.map +1 -1
  306. package/dist/api/split-by-plane.d.ts +41 -0
  307. package/dist/api/split-by-plane.d.ts.map +1 -0
  308. package/dist/api/split-by-plane.js +60 -0
  309. package/dist/api/split-by-plane.js.map +1 -0
  310. package/dist/api/split.d.ts +6 -1
  311. package/dist/api/split.d.ts.map +1 -1
  312. package/dist/api/split.js +23 -9
  313. package/dist/api/split.js.map +1 -1
  314. package/dist/api/surface/arg-spec.d.ts +22 -0
  315. package/dist/api/surface/arg-spec.d.ts.map +1 -1
  316. package/dist/api/surface/arg-spec.js +723 -476
  317. package/dist/api/surface/arg-spec.js.map +1 -1
  318. package/dist/api/sweep.d.ts +55 -0
  319. package/dist/api/sweep.d.ts.map +1 -0
  320. package/dist/api/sweep.js +86 -0
  321. package/dist/api/sweep.js.map +1 -0
  322. package/dist/api/thicken.d.ts +36 -0
  323. package/dist/api/thicken.d.ts.map +1 -0
  324. package/dist/api/thicken.js +55 -0
  325. package/dist/api/thicken.js.map +1 -0
  326. package/dist/api/transform.d.ts +8 -0
  327. package/dist/api/transform.d.ts.map +1 -1
  328. package/dist/api/transform.js +15 -4
  329. package/dist/api/transform.js.map +1 -1
  330. package/dist/api/view/cameraFns.d.ts +48 -0
  331. package/dist/api/view/cameraFns.d.ts.map +1 -0
  332. package/dist/api/view/cameraFns.js +75 -0
  333. package/dist/api/view/cameraFns.js.map +1 -0
  334. package/dist/api/view/projectionPlanes.d.ts +25 -0
  335. package/dist/api/view/projectionPlanes.d.ts.map +1 -0
  336. package/dist/api/view/projectionPlanes.js +30 -0
  337. package/dist/api/view/projectionPlanes.js.map +1 -0
  338. package/dist/api/view/view-camera.d.ts +2 -2
  339. package/dist/api/view/view-camera.d.ts.map +1 -1
  340. package/dist/api/view/view-camera.js +3 -3
  341. package/dist/api/view/view-camera.js.map +1 -1
  342. package/dist/api/view/view-projection.d.ts +9 -6
  343. package/dist/api/view/view-projection.d.ts.map +1 -1
  344. package/dist/api/view/view-projection.js +132 -65
  345. package/dist/api/view/view-projection.js.map +1 -1
  346. package/dist/api/wire.d.ts +45 -0
  347. package/dist/api/wire.d.ts.map +1 -0
  348. package/dist/api/wire.js +96 -0
  349. package/dist/api/wire.js.map +1 -0
  350. package/dist/boolean/creased-normals.d.ts +50 -0
  351. package/dist/boolean/creased-normals.d.ts.map +1 -0
  352. package/dist/boolean/creased-normals.js +114 -0
  353. package/dist/boolean/creased-normals.js.map +1 -0
  354. package/dist/boolean/deriveNormals.d.ts +4 -1
  355. package/dist/boolean/deriveNormals.d.ts.map +1 -1
  356. package/dist/boolean/deriveNormals.js +5 -2
  357. package/dist/boolean/deriveNormals.js.map +1 -1
  358. package/dist/brep/brep-ops.d.ts +6 -0
  359. package/dist/brep/brep-ops.d.ts.map +1 -1
  360. package/dist/brep/brep-ops.js +11 -2
  361. package/dist/brep/brep-ops.js.map +1 -1
  362. package/dist/brep/brep-topology.d.ts +4 -0
  363. package/dist/brep/brep-topology.d.ts.map +1 -1
  364. package/dist/brep/brep-topology.js +4 -0
  365. package/dist/brep/brep-topology.js.map +1 -1
  366. package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
  367. package/dist/brep/engine/adapters/brep-mock.js +79 -59
  368. package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
  369. package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
  370. package/dist/brep/engine/adapters/brepkit.js +7 -1
  371. package/dist/brep/engine/adapters/brepkit.js.map +1 -1
  372. package/dist/brep/engine/adapters/occt.d.ts +15 -7
  373. package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
  374. package/dist/brep/engine/adapters/occt.js +52 -167
  375. package/dist/brep/engine/adapters/occt.js.map +1 -1
  376. package/dist/brep/engine/primitives.d.ts +93 -130
  377. package/dist/brep/engine/primitives.d.ts.map +1 -1
  378. package/dist/brep/engine/primitives.js +9 -7
  379. package/dist/brep/engine/primitives.js.map +1 -1
  380. package/dist/brep/engine/types.d.ts +14 -1
  381. package/dist/brep/engine/types.d.ts.map +1 -1
  382. package/dist/brep/engine/types.js +11 -1
  383. package/dist/brep/engine/types.js.map +1 -1
  384. package/dist/brep/export/step.d.ts +3 -0
  385. package/dist/brep/export/step.d.ts.map +1 -1
  386. package/dist/brep/export/step.js +7 -1
  387. package/dist/brep/export/step.js.map +1 -1
  388. package/dist/brep/face-evolution.d.ts +8 -0
  389. package/dist/brep/face-evolution.d.ts.map +1 -1
  390. package/dist/brep/face-evolution.js +15 -3
  391. package/dist/brep/face-evolution.js.map +1 -1
  392. package/dist/brep/handle-bridge.d.ts +20 -2
  393. package/dist/brep/handle-bridge.d.ts.map +1 -1
  394. package/dist/brep/handle-bridge.js +25 -2
  395. package/dist/brep/handle-bridge.js.map +1 -1
  396. package/dist/brepkit-kernel/brepkitKernel.d.ts +25 -5
  397. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  398. package/dist/brepkit-kernel/brepkitKernel.js +336 -144
  399. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  400. package/dist/cad-runtime/admit-compat-lib.d.ts +6 -1
  401. package/dist/cad-runtime/admit-compat-lib.d.ts.map +1 -1
  402. package/dist/cad-runtime/admit-compat-lib.js +5 -1
  403. package/dist/cad-runtime/admit-compat-lib.js.map +1 -1
  404. package/dist/cad-runtime/backend-dispatch.d.ts +9 -3
  405. package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
  406. package/dist/cad-runtime/backend-dispatch.js +32 -2
  407. package/dist/cad-runtime/backend-dispatch.js.map +1 -1
  408. package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
  409. package/dist/cad-runtime/direct-executor.js +8 -2
  410. package/dist/cad-runtime/direct-executor.js.map +1 -1
  411. package/dist/cad-runtime/runtime.d.ts +3 -0
  412. package/dist/cad-runtime/runtime.d.ts.map +1 -1
  413. package/dist/cad-runtime/runtime.js +3 -1
  414. package/dist/cad-runtime/runtime.js.map +1 -1
  415. package/dist/define-op.d.ts +18 -2
  416. package/dist/define-op.d.ts.map +1 -1
  417. package/dist/define-op.js +29 -1
  418. package/dist/define-op.js.map +1 -1
  419. package/dist/env-agnostic.d.ts +3 -0
  420. package/dist/env-agnostic.d.ts.map +1 -1
  421. package/dist/env-agnostic.js +7 -0
  422. package/dist/env-agnostic.js.map +1 -1
  423. package/dist/index.d.ts.map +1 -1
  424. package/dist/index.js +3 -4
  425. package/dist/index.js.map +1 -1
  426. package/dist/lang/symbol-table.generated.d.ts +28 -0
  427. package/dist/lang/symbol-table.generated.d.ts.map +1 -1
  428. package/dist/lang/symbol-table.generated.js +29 -1
  429. package/dist/lang/symbol-table.generated.js.map +1 -1
  430. package/dist/occt-kernel/highLevelApi.d.ts.map +1 -1
  431. package/dist/occt-kernel/highLevelApi.js +6 -3
  432. package/dist/occt-kernel/highLevelApi.js.map +1 -1
  433. package/dist/occt-kernel/hullGeometry.d.ts +31 -0
  434. package/dist/occt-kernel/hullGeometry.d.ts.map +1 -0
  435. package/dist/occt-kernel/hullGeometry.js +319 -0
  436. package/dist/occt-kernel/hullGeometry.js.map +1 -0
  437. package/dist/occt-kernel/hullOps.d.ts +24 -0
  438. package/dist/occt-kernel/hullOps.d.ts.map +1 -0
  439. package/dist/occt-kernel/hullOps.js +52 -0
  440. package/dist/occt-kernel/hullOps.js.map +1 -0
  441. package/dist/occt-kernel/occt-primitives.d.ts +14 -0
  442. package/dist/occt-kernel/occt-primitives.d.ts.map +1 -0
  443. package/dist/occt-kernel/occt-primitives.js +351 -0
  444. package/dist/occt-kernel/occt-primitives.js.map +1 -0
  445. package/dist/occt-kernel/occtKernel.d.ts +14 -6
  446. package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
  447. package/dist/occt-kernel/occtKernel.js +11 -3
  448. package/dist/occt-kernel/occtKernel.js.map +1 -1
  449. package/dist/occt-kernel/topologyExt.js +2 -2
  450. package/dist/occt-kernel/topologyExt.js.map +1 -1
  451. package/dist/primitives/brep-primitives.d.ts +4 -0
  452. package/dist/primitives/brep-primitives.d.ts.map +1 -1
  453. package/dist/primitives/brep-primitives.js +4 -0
  454. package/dist/primitives/brep-primitives.js.map +1 -1
  455. package/dist/result/bug.d.ts +22 -0
  456. package/dist/result/bug.d.ts.map +1 -0
  457. package/dist/result/bug.js +28 -0
  458. package/dist/result/bug.js.map +1 -0
  459. package/dist/result/errors.d.ts +270 -0
  460. package/dist/result/errors.d.ts.map +1 -0
  461. package/dist/result/errors.js +317 -0
  462. package/dist/result/errors.js.map +1 -0
  463. package/dist/result/kernelErrorTranslation.d.ts +21 -0
  464. package/dist/result/kernelErrorTranslation.d.ts.map +1 -0
  465. package/dist/result/kernelErrorTranslation.js +102 -0
  466. package/dist/result/kernelErrorTranslation.js.map +1 -0
  467. package/dist/result/result.d.ts +213 -0
  468. package/dist/result/result.d.ts.map +1 -0
  469. package/dist/result/result.js +336 -0
  470. package/dist/result/result.js.map +1 -0
  471. package/dist/result/vec3.d.ts +12 -0
  472. package/dist/result/vec3.d.ts.map +1 -0
  473. package/dist/result/vec3.js +14 -0
  474. package/dist/result/vec3.js.map +1 -0
  475. package/dist/runtime-state.d.ts +9 -0
  476. package/dist/runtime-state.d.ts.map +1 -1
  477. package/dist/runtime-state.js.map +1 -1
  478. package/dist/sdk.d.ts +3 -1
  479. package/dist/sdk.d.ts.map +1 -1
  480. package/dist/sdk.js +2 -1
  481. package/dist/sdk.js.map +1 -1
  482. package/dist/shape.d.ts +43 -1
  483. package/dist/shape.d.ts.map +1 -1
  484. package/dist/shape.js +57 -1
  485. package/dist/shape.js.map +1 -1
  486. package/dist/topology/naming/geom-hint.js +1 -1
  487. package/dist/topology/naming/geom-hint.js.map +1 -1
  488. package/dist/topology/naming/score.js +1 -1
  489. package/dist/topology/naming/score.js.map +1 -1
  490. package/package.json +6 -16
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/brep/engine/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG","sourcesContent":["/**\n * engine/types — BREP 引擎中立类型(零具体实现依赖,不 import 任何内核包)\n *\n *\n * 契约(对应 brepjs 的 KernelShape 约定):\n * - L1 及以上代码永远不对句柄调用任何方法,只把它传回产生它的那个引擎;\n * - 句柄不得跨引擎传递——跨引擎必须先经 mesh 层(§8.3 的结构保证)。\n * - OCCT 适配器的句柄运行时就是 number,加 brand 是零成本的类型层转换。\n */\n\ndeclare const BrepHandleBrand: unique symbol\n\n/**\n * BREP 实体句柄——不透明值。\n *\n * 与 occt-wasm 的 ShapeHandle 同构(number & brand)。OCCT 适配器\n * (occt-kernel/)内部以 `as unknown as` 双向转换,跨适配器边界零运行时成本。\n */\nexport type BrepHandle = number & { readonly [BrepHandleBrand]: never }\n\n/** 三维点/向量(与内核无关的中立形态)。 */\nexport interface BrepVec3 {\n x: number\n y: number\n z: number\n}\n\n/** 轴对齐包围盒。 */\nexport interface BrepBoundingBox {\n xmin: number\n ymin: number\n zmin: number\n xmax: number\n ymax: number\n zmax: number\n}\n\n/** BRepMesh 三角化输出(镜像 occt-wasm Mesh 的中立形态)。 */\nexport interface BrepMeshResult {\n /** XYZ 交错顶点坐标,长度 = vertexCount * 3 */\n positions: Float32Array\n /** XYZ 交错顶点法线,长度 = vertexCount * 3 */\n normals: Float32Array\n /** 三角形索引 */\n indices: Uint32Array\n /** 顶点数(positions.length / 3) */\n vertexCount: number\n /** 三角形数(indices.length / 3) */\n triangleCount: number\n /** 面组:[triStart, triCount, faceHash] 三元组(meshShape 时存在) */\n faceGroups?: Int32Array\n /** 面组数(meshShape 时存在) */\n faceCount?: number\n}\n\n/** 三角化精度选项。 */\nexport interface BrepTessellateOptions {\n /** 最大弦偏差(mm),默认 0.1 */\n linearDeflection?: number\n /** 最大角偏差(弧度),默认 0.5 */\n angularDeflection?: number\n /** 按每条边长度相对解释 linearDeflection */\n relative?: boolean\n}\n\n/** 边折线数据(wireframe 输出)。 */\nexport interface BrepEdgeData {\n /** XYZ 交错边采样点 */\n points: Float32Array\n /** 每边分组:[pointStart, pointCount, edgeHash] 三元组 */\n edgeGroups: Int32Array\n /** points 中的浮点数总数(= XYZ 坐标数) */\n pointCount: number\n /** 不同边的数量 */\n edgeCount: number\n}\n\n/**\n * *WithHistory 面演化数据(modified/generated/deleted 用面 hash 编码)。\n *\n * ⚠️ **三个字段的编码不同,实测于 2026-09-22(`brep/engine/phase0-kernel-probes.test.ts`),\n * 与 occt-wasm 自己的文档(`dist/types.d.ts:227-231`)不符**:\n *\n * | 字段 | 实际编码 | 键/值语义 |\n * |---|---|---|\n * | `modified` | **分段** `[inHash, count, outHash…] × N` | 键 = 输入面 hash;值 = 该输入面在结果里的**后继**(可 1→N) |\n * | `generated` | **同构分段**,**键集与 `modified` 相同** | 值 = 该输入面派生出的**中间形**(实测结果里 0 存活) |\n * | `deleted` | **扁平** hash 数组 | 输入面中已不存在的面 |\n *\n * 「扁平数组」的读法会把 `generated` 的 count 字段当成 hash——\n * 实测 `cut` 的 `generated` 里真的含 `2`(一个 count),故该误读不会自己暴露。\n *\n * ⚠️ **未受影响的面有两种上报形态,两种都表示\"未变\"**:自映射(`i -> [i]`)。\n * 或者**整个不上报**(`fillet` 实测两者并存)。⇒ 读法必须是\n * `modified.get(h) ?? [h]`,不能只看\"是否出现在 `modified` 里\"。\n *\n * ⇒ 结果面的三种命运(判据见 `phase0-kernel-probes.test.ts`):\n * **原样幸存**(hash ∈ 输入 hash 集合,hash 逐字不变)/ **改型幸存**(在 `modified` 输出里)/\n * **新造**(两者皆非——这才是真正需要派生词汇命名的面,如 `fillet` 的过渡面)。\n */\nexport interface BrepEvolutionData {\n /** 结果句柄 */\n result: BrepHandle\n /** 分段:`[inHash, count, outHash…] × N`;值 = 该输入面的结果后继 */\n modified: number[]\n /** 分段(键集同 `modified`):该输入面派生的中间形 hash,实测结果里 0 存活 */\n generated: number[]\n /** 扁平:输入面中已不存在的面 hash */\n deleted: number[]\n}\n\n/** 曲线参数区间(与内核 curveParameters 返回同构:first/last)。 */\nexport interface BrepCurveParameters {\n first: number\n last: number\n}\n\n/** 曲面 UV 边界。 */\nexport interface BrepUvBounds {\n uMin: number\n uMax: number\n vMin: number\n vMax: number\n}\n\n/** 子形状类型(getSubShapes / subShapeHashes 等)。 */\nexport type BrepSubShapeType = 'vertex' | 'edge' | 'wire' | 'face' | 'shell' | 'solid'\n\n/**\n * XCAF 装配文档句柄(可选能力槽 AssemblyCapability 的文档形态)。\n *\n * 形态来自 occt-wasm XCAFDocumentImpl 的被调用子集(step.ts / occt-kernel 装配链)。\n */\nexport interface BrepXcafDocument {\n addShape(shape: BrepHandle, opts?: { name?: string; color?: [number, number, number] }): void\n exportSTEP(): string\n close(): void\n}\n\n/**\n * 曲面细分精度控制模型(与 brepjs KernelCapabilities.tessellationModel 同构的中立镜像,\n * P7 并入;faijs 侧零内核依赖,不 import vendored 树——D8 反向只允许发生在 api/)。\n *\n * - `'build-time'` — 网格在实体构造时固定(如 manifold 全局分段设置);质量参数须在构造前应用。\n * - `'extract-time'`— 形状是精确的,按需以每调用 deflection 细分(如 OCCT);质量是\n * `mesh()`/导出时的默认 deflection。\n * - `'none'` — 无细分控制(或非网格内核)。\n */\nexport type BrepTessellationModel = 'build-time' | 'extract-time' | 'none'\n\n/**\n * 面演化(`*WithHistory`)核函数名——与内核方法同名,**逐核函数**声明。\n *\n * ⚠️ **为什么不能是一个布尔位**(2026-09-22 Phase 0.2):`evolution: true` 是**族级**声明。\n * 而「本内核提供面演化」这句话在建面上不成立——每个 `*WithHistory` 是一个独立核函数,\n * 内核可以只提供其中一部分。`brepkit` 就是活例:它提供 `fuse`/`cut`/`fillet`,\n * `chamfer`/`intersect`/`translate`/… 一律 `unsupported(...)`\n * (`brepkit-kernel/brepkitKernel.ts:220-537`)。\n *\n * 族级布尔的后果不是\"少报\"而是**多报**:`cad.intersect` 声明需要 `evolution`,\n * 在 `evolution: true` 下通过静态判定 → 落到运行时才撞 `unsupported('intersectWithHistory')`。\n * 这直接违反 AGENTS.md 红线「BREP 路径能否走由静态规则判定,禁止运行时回退」——\n * 静态判定之所以能成立,前提是引擎的能力声明**说的是逐核函数的实话**。\n *\n * ⇒ 引擎声明\"我提供哪几个\"(`BrepCapabilities.evolution`),op 声明\"我要哪一个\"\n * (`defineOp.capabilities`),两者**按名字求交集**(`cad-runtime/backend-dispatch.ts`)。\n */\nexport type BrepEvolutionKind =\n // 布尔族\n | 'fuseWithHistory'\n | 'cutWithHistory'\n | 'intersectWithHistory'\n // 倒圆/倒角族\n | 'filletWithHistory'\n | 'chamferWithHistory'\n // 刚体变换族\n | 'translateWithHistory'\n | 'rotateWithHistory'\n | 'mirrorWithHistory'\n | 'scaleWithHistory'\n // 抽壳/偏置/加厚族\n | 'shellWithHistory'\n | 'offsetWithHistory'\n | 'thickenWithHistory'\n\n/**\n * 非演化内核方法真名(`*WithHistory` 之外的 `BrepEngineApi` 方法)。\n *\n * 与 `BrepEvolutionKind` 分名(P3 冲突消除):`'mirror'` 一个字符串不能同时表示\n * \"提供 `mirrorWithHistory`\"与\"提供 `mirror`\",两族必须互不共用字符串。\n * 语义与 evolution 相同——**逐核函数**声明:声明 = 实现(诚实原则),\n * 缺省/空 = 一个都不提供。\n *\n * 初始全集 = Phase 0 能力映射表(`api/surface/capability-map.json`)盘点的\n * compat op 依赖内核方法 + 方案初始项;Phase 3 全量收敛时按映射表滚动补全。\n */\nexport type BrepMethodKind =\n // pattern 族\n | 'linearPattern'\n | 'circularPattern'\n | 'gridPattern'\n | 'rectangularPattern'\n // 基础方法族(裸方法,无历史)\n | 'mirror'\n | 'rotate'\n | 'translate'\n | 'scale'\n // 倒角/圆角基础方法(directEdit 族下的逐核真名,Phase 2:chamfer op 能力声明\n // 精确到内核方法——brepkit 无 chamfer/chamferDistAngle,静态判定执行前报错)\n | 'chamfer'\n | 'chamferDistAngle'\n | 'fillet'\n | 'filletVariable'\n // 构形/拉伸/放样族\n | 'makeRectangle'\n | 'shell'\n | 'extrude'\n | 'loft'\n | 'loftAdvanced'\n | 'section'\n | 'sweepPipeShell'\n | 'simplePipe'\n | 'revolveVec'\n | 'buildExtrusionLaw'\n // 布尔/装配辅助(裸方法)\n | 'fuse'\n | 'cut'\n | 'intersect'\n | 'fuseAll'\n // 构造方法族\n | 'makeArcEdge'\n | 'makeBezierEdge'\n | 'makeCylinder'\n | 'makeEllipsoid'\n | 'makeFace'\n | 'makeFaceOnSurface'\n | 'makeLineEdge'\n | 'makeTorus'\n | 'makeVertex'\n | 'makeWireFromMixed'\n | 'buildEdgeOnSurface'\n | 'addHolesInFace'\n | 'buildTriFace'\n | 'sew'\n | 'sewAndSolidify'\n // 修复/校验族\n | 'healFace'\n | 'healSolid'\n | 'healWire'\n | 'fixShape'\n | 'fixSelfIntersection'\n | 'isValid'\n | 'removeDegenerateEdges'\n | 'simplify'\n | 'split'\n // 查询/测量族\n | 'boundingBox'\n | 'curveParameters'\n | 'curvePointAtParam'\n | 'curveTangent'\n | 'hullFromPoints'\n | 'isNull'\n | 'iterShapes'\n | 'locate'\n | 'shapeType'\n | 'surfaceCenterOfMass'\n | 'surfaceNormal'\n | 'surfaceType'\n | 'uvBounds'\n // 变换族(非演化真名)\n | 'composeTransform'\n | 'applyComposedTransformWithHistory'\n | 'generalTransformNonOrthogonal'\n | 'generalTransformWithHistory'\n // 交换/导入族\n | 'importStl'\n | 'createXCAFDocument'\n | 'importXCAFFromSTEP'\n // 生命周期辅助\n | 'copyShape'\n | 'dispose'\n | 'downcast'\n | 'hashCode'\n\n/**\n * 可选能力槽声明(§7.5,Phase 1 钉死成员)。\n *\n * 缺失的能力 → 依赖它的功能静态降级走 mesh(§8.4),绝不伪造。\n *\n * P7 并入(D4):移植 brepjs `KernelCapabilities` 的数据字段(exact/brepExport/\n * exactMeasurement/tessellationModel)进本模型,由适配器在注册时如实声明;分派逻辑\n * (backend-dispatch 的 BrepCapabilityName 路由)不改——新字段是引擎本质描述,不是\n * 逐 op 路由键。\n *\n * 未并入 `disposalModel`(D5 决策,与 vendored port 一致):faijs 的句柄释放由\n * `cad-runtime` 顶替释放统一编排(增量失败回滚前提),brepjs 的 DisposalScope/arena\n * 语义不强制统一,故不作为能力位记录。\n */\nexport interface BrepCapabilities {\n /**\n * 面演化族:本引擎**实际提供**的 `*WithHistory` 核函数名(不是族级布尔,见\n * `BrepEvolutionKind`)。空数组 / 缺省 = 一个都不提供。\n */\n evolution?: readonly BrepEvolutionKind[]\n /**\n * 非演化内核方法族:本引擎**实际提供**的 `BrepEngineApi` 方法真名\n * (逐核声明,与 `evolution` 同语义;空数组 / 缺省 = 一个都不提供)。\n */\n methods?: readonly BrepMethodKind[]\n /** 修复族(healSolid/fixShape/fixFaceOrientations/...) */\n heal?: boolean\n /** 直接编辑族(C1:moveFace/replaceFace/...) */\n directEdit?: boolean\n /** 高级曲面族(C1:boundarySurface/fillSurface/...) */\n advSurface?: boolean\n /** XCAF 装配族 */\n assembly?: boolean\n /** mesh→BREP 提升(buildTriFace/sewAndSolidify) */\n meshLift?: boolean\n /** 精确 B-rep 几何(vs mesh 近似)——brepjs KernelCapabilities.exact 并入 */\n exact?: boolean\n /** 可序列化为 B-rep 交换格式(BREP/STEP)——brepjs brepExport 并入 */\n brepExport?: boolean\n /** 体积/面积/长度匹配解析值(vs mesh 近似)——brepjs exactMeasurement 并入 */\n exactMeasurement?: boolean\n /** 细分精度控制模型——brepjs tessellationModel 并入 */\n tessellationModel?: BrepTessellationModel\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/brep/engine/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAU,CAAA","sourcesContent":["/**\n * engine/types — BREP 引擎中立类型(零具体实现依赖,不 import 任何内核包)\n *\n *\n * 契约(对应 brepjs 的 KernelShape 约定):\n * - L1 及以上代码永远不对句柄调用任何方法,只把它传回产生它的那个引擎;\n * - 句柄不得跨引擎传递——跨引擎必须先经 mesh 层(§8.3 的结构保证)。\n * - OCCT 适配器的句柄运行时就是 number,加 brand 是零成本的类型层转换。\n */\n\n/**\n * BREP 引擎身份(D11-1,2026-09-24 narrowing plan)。\n *\n * 三个值来自三个已存在的引擎 id 常量(`OCCT_BREP_ENGINE_ID` / `BREPKIT_BREP_ENGINE_ID`\n * / `BREP_MOCK_ENGINE_ID`,各自适配器导出);本类型由常量数组推导,禁止裸 `string`。\n * 适配器常量用 `satisfies BrepEngineId` 收窄(typecheck 钉住集合一致)。\n *\n * 消费点:`defineOp` 的 `engines` 声明(平台 op 自证身份)、`dispatchPath` 的平台\n * 身份分支(D11-2)、`script-face-manifest` 的平台 op 标注(§3.8)。\n */\nexport const BREP_ENGINE_IDS = ['occt', 'brepkit', 'brep_mock'] as const\n\n/** BREP 引擎身份(固定三值联合;由 {@link BREP_ENGINE_IDS} 推导)。 */\nexport type BrepEngineId = (typeof BREP_ENGINE_IDS)[number]\n\ndeclare const BrepHandleBrand: unique symbol\n\n/**\n * BREP 实体句柄——不透明值。\n *\n * 与 occt-wasm 的 ShapeHandle 同构(number & brand)。OCCT 适配器\n * (occt-kernel/)内部以 `as unknown as` 双向转换,跨适配器边界零运行时成本。\n */\nexport type BrepHandle = number & { readonly [BrepHandleBrand]: never }\n\n/** 三维点/向量(与内核无关的中立形态)。 */\nexport interface BrepVec3 {\n x: number\n y: number\n z: number\n}\n\n/** 轴对齐包围盒。 */\nexport interface BrepBoundingBox {\n xmin: number\n ymin: number\n zmin: number\n xmax: number\n ymax: number\n zmax: number\n}\n\n/** BRepMesh 三角化输出(镜像 occt-wasm Mesh 的中立形态)。 */\nexport interface BrepMeshResult {\n /** XYZ 交错顶点坐标,长度 = vertexCount * 3 */\n positions: Float32Array\n /** XYZ 交错顶点法线,长度 = vertexCount * 3 */\n normals: Float32Array\n /** 三角形索引 */\n indices: Uint32Array\n /** 顶点数(positions.length / 3) */\n vertexCount: number\n /** 三角形数(indices.length / 3) */\n triangleCount: number\n /** 面组:[triStart, triCount, faceHash] 三元组(meshShape 时存在) */\n faceGroups?: Int32Array\n /** 面组数(meshShape 时存在) */\n faceCount?: number\n}\n\n/** 三角化精度选项。 */\nexport interface BrepTessellateOptions {\n /** 最大弦偏差(mm),默认 0.1 */\n linearDeflection?: number\n /** 最大角偏差(弧度),默认 0.5 */\n angularDeflection?: number\n /** 按每条边长度相对解释 linearDeflection */\n relative?: boolean\n}\n\n/** 边折线数据(wireframe 输出)。 */\nexport interface BrepEdgeData {\n /** XYZ 交错边采样点 */\n points: Float32Array\n /** 每边分组:[pointStart, pointCount, edgeHash] 三元组 */\n edgeGroups: Int32Array\n /** points 中的浮点数总数(= XYZ 坐标数) */\n pointCount: number\n /** 不同边的数量 */\n edgeCount: number\n}\n\n/**\n * *WithHistory 面演化数据(modified/generated/deleted 用面 hash 编码)。\n *\n * ⚠️ **三个字段的编码不同,实测于 2026-09-22(`brep/engine/phase0-kernel-probes.test.ts`),\n * 与 occt-wasm 自己的文档(`dist/types.d.ts:227-231`)不符**:\n *\n * | 字段 | 实际编码 | 键/值语义 |\n * |---|---|---|\n * | `modified` | **分段** `[inHash, count, outHash…] × N` | 键 = 输入面 hash;值 = 该输入面在结果里的**后继**(可 1→N) |\n * | `generated` | **同构分段**,**键集与 `modified` 相同** | 值 = 该输入面派生出的**中间形**(实测结果里 0 存活) |\n * | `deleted` | **扁平** hash 数组 | 输入面中已不存在的面 |\n *\n * 「扁平数组」的读法会把 `generated` 的 count 字段当成 hash——\n * 实测 `cut` 的 `generated` 里真的含 `2`(一个 count),故该误读不会自己暴露。\n *\n * ⚠️ **未受影响的面有两种上报形态,两种都表示\"未变\"**:自映射(`i -> [i]`)。\n * 或者**整个不上报**(`fillet` 实测两者并存)。⇒ 读法必须是\n * `modified.get(h) ?? [h]`,不能只看\"是否出现在 `modified` 里\"。\n *\n * ⇒ 结果面的三种命运(判据见 `phase0-kernel-probes.test.ts`):\n * **原样幸存**(hash ∈ 输入 hash 集合,hash 逐字不变)/ **改型幸存**(在 `modified` 输出里)/\n * **新造**(两者皆非——这才是真正需要派生词汇命名的面,如 `fillet` 的过渡面)。\n */\nexport interface BrepEvolutionData {\n /** 结果句柄 */\n result: BrepHandle\n /** 分段:`[inHash, count, outHash…] × N`;值 = 该输入面的结果后继 */\n modified: number[]\n /** 分段(键集同 `modified`):该输入面派生的中间形 hash,实测结果里 0 存活 */\n generated: number[]\n /** 扁平:输入面中已不存在的面 hash */\n deleted: number[]\n}\n\n/** 曲线参数区间(与内核 curveParameters 返回同构:first/last)。 */\nexport interface BrepCurveParameters {\n first: number\n last: number\n}\n\n/** 曲面 UV 边界。 */\nexport interface BrepUvBounds {\n uMin: number\n uMax: number\n vMin: number\n vMax: number\n}\n\n/** 子形状类型(getSubShapes / subShapeHashes 等)。 */\nexport type BrepSubShapeType = 'vertex' | 'edge' | 'wire' | 'face' | 'shell' | 'solid'\n\n/**\n * XCAF 装配文档句柄(可选能力槽 AssemblyCapability 的文档形态)。\n *\n * 形态来自 occt-wasm XCAFDocumentImpl 的被调用子集(step.ts / occt-kernel 装配链)。\n */\nexport interface BrepXcafDocument {\n addShape(shape: BrepHandle, opts?: { name?: string; color?: [number, number, number] }): void\n exportSTEP(): string\n close(): void\n}\n\n/**\n * 曲面细分精度控制模型(与 brepjs KernelCapabilities.tessellationModel 同构的中立镜像,\n * P7 并入;faijs 侧零内核依赖,不 import vendored 树——D8 反向只允许发生在 api/)。\n *\n * - `'build-time'` — 网格在实体构造时固定(如 manifold 全局分段设置);质量参数须在构造前应用。\n * - `'extract-time'`— 形状是精确的,按需以每调用 deflection 细分(如 OCCT);质量是\n * `mesh()`/导出时的默认 deflection。\n * - `'none'` — 无细分控制(或非网格内核)。\n */\nexport type BrepTessellationModel = 'build-time' | 'extract-time' | 'none'\n\n/**\n * 面演化(`*WithHistory`)核函数名——与内核方法同名,**逐核函数**声明。\n *\n * ⚠️ **为什么不能是一个布尔位**(2026-09-22 Phase 0.2):`evolution: true` 是**族级**声明。\n * 而「本内核提供面演化」这句话在建面上不成立——每个 `*WithHistory` 是一个独立核函数,\n * 内核可以只提供其中一部分。`brepkit` 就是活例:它提供 `fuse`/`cut`/`fillet`,\n * `chamfer`/`intersect`/`translate`/… 一律 `unsupported(...)`\n * (`brepkit-kernel/brepkitKernel.ts:220-537`)。\n *\n * 族级布尔的后果不是\"少报\"而是**多报**:`cad.intersect` 声明需要 `evolution`,\n * 在 `evolution: true` 下通过静态判定 → 落到运行时才撞 `unsupported('intersectWithHistory')`。\n * 这直接违反 AGENTS.md 红线「BREP 路径能否走由静态规则判定,禁止运行时回退」——\n * 静态判定之所以能成立,前提是引擎的能力声明**说的是逐核函数的实话**。\n *\n * ⇒ 引擎声明\"我提供哪几个\"(`BrepCapabilities.evolution`),op 声明\"我要哪一个\"\n * (`defineOp.capabilities`),两者**按名字求交集**(`cad-runtime/backend-dispatch.ts`)。\n */\nexport type BrepEvolutionKind =\n // 布尔族\n | 'fuseWithHistory'\n | 'cutWithHistory'\n | 'intersectWithHistory'\n // 倒圆/倒角族\n | 'filletWithHistory'\n | 'chamferWithHistory'\n // 刚体变换族\n | 'translateWithHistory'\n | 'rotateWithHistory'\n | 'mirrorWithHistory'\n | 'scaleWithHistory'\n // 抽壳/偏置/加厚族\n | 'shellWithHistory'\n | 'offsetWithHistory'\n | 'thickenWithHistory'\n\n/**\n * 非演化内核方法真名(`*WithHistory` 之外的 `BrepEngineApi` 方法)。\n *\n * 与 `BrepEvolutionKind` 分名(P3 冲突消除):`'mirror'` 一个字符串不能同时表示\n * \"提供 `mirrorWithHistory`\"与\"提供 `mirror`\",两族必须互不共用字符串。\n * 语义与 evolution 相同——**逐核函数**声明:声明 = 实现(诚实原则),\n * 缺省/空 = 一个都不提供。\n *\n * 初始全集 = Phase 0 能力映射表(`api/surface/capability-map.json`)盘点的\n * compat op 依赖内核方法 + 方案初始项;Phase 3 全量收敛时按映射表滚动补全。\n */\nexport type BrepMethodKind =\n // pattern 族\n | 'linearPattern'\n | 'circularPattern'\n | 'gridPattern'\n | 'rectangularPattern'\n // 基础方法族(裸方法,无历史)\n | 'mirror'\n | 'rotate'\n | 'translate'\n | 'scale'\n // 倒角/圆角基础方法(directEdit 族下的逐核真名,Phase 2:chamfer op 能力声明\n // 精确到内核方法——brepkit 无 chamfer/chamferDistAngle,静态判定执行前报错)\n | 'chamfer'\n | 'chamferDistAngle'\n | 'fillet'\n | 'filletVariable'\n // 构形/拉伸/放样族\n | 'makeRectangle'\n | 'shell'\n | 'extrude'\n | 'loft'\n | 'loftAdvanced'\n | 'section'\n | 'sweepPipeShell'\n | 'simplePipe'\n | 'revolveVec'\n | 'buildExtrusionLaw'\n // 布尔/装配辅助(裸方法)\n | 'fuse'\n | 'cut'\n | 'intersect'\n | 'fuseAll'\n // 构造方法族\n | 'makeArcEdge'\n | 'makeBezierEdge'\n | 'makeCylinder'\n | 'makeEllipsoid'\n | 'makeFace'\n | 'makeFaceOnSurface'\n | 'makeLineEdge'\n | 'makeTorus'\n | 'makeVertex'\n | 'makeWireFromMixed'\n | 'buildEdgeOnSurface'\n | 'addHolesInFace'\n | 'buildTriFace'\n | 'sew'\n | 'sewAndSolidify'\n // 修复/校验族\n | 'healFace'\n | 'healSolid'\n | 'healWire'\n | 'fixShape'\n | 'fixSelfIntersection'\n | 'isValid'\n | 'removeDegenerateEdges'\n | 'simplify'\n | 'split'\n // 查询/测量族\n // ⚠️ 测量族能力名用 L1 中立名(D5,narrowing plan):`getBoundingBox` / `getVolume`\n // / `getSurfaceArea` / `getLength` / `getCenterOfMass` ——能力名 == BrepEngineApi 接口名,\n // 守卫「能力声明诚实」据此逐名断言适配器是 function。vendored 面自己的原生名\n // (boundingBox/volume/area/length)按其自身命名,\n // 不是能力名空间成员。\n | 'getBoundingBox'\n | 'getVolume'\n | 'getSurfaceArea'\n | 'getLength'\n | 'getCenterOfMass'\n | 'curveParameters'\n | 'curvePointAtParam'\n | 'curveTangent'\n | 'hullFromPoints'\n | 'isNull'\n | 'iterShapes'\n | 'locate'\n | 'shapeType'\n | 'surfaceCenterOfMass'\n | 'surfaceNormal'\n | 'surfaceType'\n | 'uvBounds'\n // 变换族(非演化真名)\n | 'composeTransform'\n | 'applyComposedTransformWithHistory'\n | 'generalTransformNonOrthogonal'\n | 'generalTransformWithHistory'\n // 交换/导入族\n | 'importStl'\n | 'createXCAFDocument'\n | 'importXCAFFromSTEP'\n // 生命周期辅助\n | 'copyShape'\n | 'dispose'\n | 'downcast'\n | 'hashCode'\n\n/**\n * 可选能力槽声明(§7.5,Phase 1 钉死成员)。\n *\n * 缺失的能力 → 依赖它的功能静态降级走 mesh(§8.4),绝不伪造。\n *\n * P7 并入(D4):移植 brepjs `KernelCapabilities` 的数据字段(exact/brepExport/\n * exactMeasurement/tessellationModel)进本模型,由适配器在注册时如实声明;分派逻辑\n * (backend-dispatch 的 BrepCapabilityName 路由)不改——新字段是引擎本质描述,不是\n * 逐 op 路由键。\n *\n * 未并入 `disposalModel`(D5 决策,与 vendored port 一致):faijs 的句柄释放由\n * `cad-runtime` 顶替释放统一编排(增量失败回滚前提),brepjs 的 DisposalScope/arena\n * 语义不强制统一,故不作为能力位记录。\n */\nexport interface BrepCapabilities {\n /**\n * 面演化族:本引擎**实际提供**的 `*WithHistory` 核函数名(不是族级布尔,见\n * `BrepEvolutionKind`)。空数组 / 缺省 = 一个都不提供。\n */\n evolution?: readonly BrepEvolutionKind[]\n /**\n * 非演化内核方法族:本引擎**实际提供**的 `BrepEngineApi` 方法真名\n * (逐核声明,与 `evolution` 同语义;空数组 / 缺省 = 一个都不提供)。\n */\n methods?: readonly BrepMethodKind[]\n /** 修复族(healSolid/fixShape/fixFaceOrientations/...) */\n heal?: boolean\n /** 直接编辑族(C1:moveFace/replaceFace/...) */\n directEdit?: boolean\n /** 高级曲面族(C1:boundarySurface/fillSurface/...) */\n advSurface?: boolean\n /** XCAF 装配族 */\n assembly?: boolean\n /** mesh→BREP 提升(buildTriFace/sewAndSolidify) */\n meshLift?: boolean\n /** 精确 B-rep 几何(vs mesh 近似)——brepjs KernelCapabilities.exact 并入 */\n exact?: boolean\n /** 可序列化为 B-rep 交换格式(BREP/STEP)——brepjs brepExport 并入 */\n brepExport?: boolean\n /** 体积/面积/长度匹配解析值(vs mesh 近似)——brepjs exactMeasurement 并入 */\n exactMeasurement?: boolean\n /** 细分精度控制模型——brepjs tessellationModel 并入 */\n tessellationModel?: BrepTessellationModel\n}\n"]}
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * exportStepFromSolids — L1 STEP 导出(从 OCCT solid 句柄,多实体、零 fuse)
3
3
  *
4
+ * @platform occt — 本文件 import occt-kernel(createXCAFDocument/XCAF label 写入是
5
+ * occt-only 平台面,D3)。文件级标注满足守卫①(平台 import 自证身份)。
6
+ *
4
7
  * 每个 entry 作为 STEP 中一个独立实体(独立 XCAF label / PRODUCT)导出,
5
8
  * 保留名称与颜色。多实体之间绝不 fuse —— 这是硬性约定:
6
9
  * fuse 只允许作为用户脚本里的几何布尔运算,禁止作为导出时的实体合并手段。
@@ -1 +1 @@
1
- {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../../src/brep/export/step.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAGzD,8CAA8C;AAC9C,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,0DAA0D;IAC1D,IAAI,CAAC,EAAE;QAAE,SAAS,EAAE,YAAY,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAA;IACxD,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,eAAe,EAAE,GACzB,WAAW,CA4Eb;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,aAAa,GACpB,WAAW,CAEb"}
1
+ {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../../src/brep/export/step.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAIzD,8CAA8C;AAC9C,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,0DAA0D;IAC1D,IAAI,CAAC,EAAE;QAAE,SAAS,EAAE,YAAY,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAA;IACxD,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,eAAe,EAAE,GACzB,WAAW,CA8Eb;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,aAAa,GACpB,WAAW,CAEb"}
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * exportStepFromSolids — L1 STEP 导出(从 OCCT solid 句柄,多实体、零 fuse)
3
3
  *
4
+ * @platform occt — 本文件 import occt-kernel(createXCAFDocument/XCAF label 写入是
5
+ * occt-only 平台面,D3)。文件级标注满足守卫①(平台 import 自证身份)。
6
+ *
4
7
  * 每个 entry 作为 STEP 中一个独立实体(独立 XCAF label / PRODUCT)导出,
5
8
  * 保留名称与颜色。多实体之间绝不 fuse —— 这是硬性约定:
6
9
  * fuse 只允许作为用户脚本里的几何布尔运算,禁止作为导出时的实体合并手段。
@@ -10,6 +13,7 @@
10
13
  * `name [n]`,与本节点的展平命名规则一致。
11
14
  */
12
15
  import { reconstructSolidFromMesh } from '../../occt-kernel/meshReconstruct.js';
16
+ import { getOcctKernel } from '../../occt-kernel/occtKernel.js';
13
17
  /**
14
18
  * sRGB → linear 转换。
15
19
  *
@@ -36,7 +40,7 @@ export function exportStepFromSolids(kernel, entries) {
36
40
  if (entries.length === 0) {
37
41
  throw new Error('No exportable geometry');
38
42
  }
39
- const doc = kernel.createXCAFDocument();
43
+ const doc = getOcctKernel().createXCAFDocument();
40
44
  // 本函数创建的句柄(展平出的子 solid + mesh 重建的 solid),导出后释放。
41
45
  // 缓存里的原 solid(entry.solid)绝不释放,归调用方/缓存所有。
42
46
  const ownedHandles = [];
@@ -88,6 +92,8 @@ export function exportStepFromSolids(kernel, entries) {
88
92
  const color = entry.color
89
93
  ? [srgbToLinear(entry.color[0]), srgbToLinear(entry.color[1]), srgbToLinear(entry.color[2])]
90
94
  : undefined;
95
+ // 平台面(D3):XCAF label 写入是 occt-only。BrepHandle ↔ ShapeHandle
96
+ // 运行时同构,品牌转换只发生在平台边界。
91
97
  doc.addShape(sub, { name, color });
92
98
  }
93
99
  }
@@ -1 +1 @@
1
- {"version":3,"file":"step.js","sourceRoot":"","sources":["../../../src/brep/export/step.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * exportStepFromSolids — L1 STEP 导出(从 OCCT solid 句柄,多实体、零 fuse)\n *\n * 每个 entry 作为 STEP 中一个独立实体(独立 XCAF label / PRODUCT)导出,\n * 保留名称与颜色。多实体之间绝不 fuse —— 这是硬性约定:\n * fuse 只允许作为用户脚本里的几何布尔运算,禁止作为导出时的实体合并手段。\n *\n * 导出 → 再导入身份闭环:导入侧 importAssemblyFromStep(XCAF)会把\n * 多实体 STEP 还原为多个 part;多 solid compound 拆分出的子节点命名为\n * `name [n]`,与本节点的展平命名规则一致。\n */\n\nimport type { BrepHandle } from '../engine/types'\nimport type { BrepEngineApi } from '../engine/primitives'\nimport { reconstructSolidFromMesh } from '../../occt-kernel/meshReconstruct'\n\n/** STEP 导出条目:一个 part(精确 BREP 形状或三角网格,二选一)。 */\nexport interface StepExportEntry {\n /** 精确 BREP 形状(solid/shell/face/compound,来自宿主导出缓存)。与 mesh 二选一,solid 优先。 */\n solid?: BrepHandle\n /** 三角网格(世界坐标、已按单位缩放),经 reconstructSolidFromMesh 重建为实体。 */\n mesh?: { positions: Float32Array; indices: Uint32Array }\n /** 实体名称(写入 label name,导出为 PRODUCT 名称)。 */\n name?: string\n /** RGB 0..1 颜色(sRGB 编码,如宿主材质 base color)。写入前转 linear。 */\n color?: [number, number, number]\n}\n\n/**\n * sRGB → linear 转换。\n *\n * OCCT XCAF 内部按 linear RGB 存储颜色,STEP writer(xcafExportSTEP)\n * 导出时做 linear→sRGB 编码写 COLOUR_RGB。为了让\"宿主传入的 sRGB 颜色 ==\n * STEP 文件中的 COLOUR_RGB == 回读颜色\",写入前必须先转 linear。\n *\n * @param c sRGB 编码值(0..1)\n * @returns linear 值(0..1)\n */\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)\n}\n\n/**\n * Export multiple BREP solids (and/or triangle meshes) to STEP, one\n * independent entity per entry — no fuse, no string splicing.\n *\n * @param kernel OCCT kernel (must match the one that created the solids)\n * @param entries parts to export; each becomes its own XCAF label\n * @returns STEP file content as ArrayBuffer\n * @throws if entries is empty, or a mesh entry fails to reconstruct\n */\nexport function exportStepFromSolids(\n kernel: BrepEngineApi,\n entries: StepExportEntry[],\n): ArrayBuffer {\n if (entries.length === 0) {\n throw new Error('No exportable geometry')\n }\n\n const doc = kernel.createXCAFDocument()\n // 本函数创建的句柄(展平出的子 solid + mesh 重建的 solid),导出后释放。\n // 缓存里的原 solid(entry.solid)绝不释放,归调用方/缓存所有。\n const ownedHandles: BrepHandle[] = []\n\n try {\n for (const entry of entries) {\n // 1. 解析 solid:优先用精确 solid;无则从三角网格重建\n let solid = entry.solid\n if (!solid) {\n if (!entry.mesh) {\n throw new Error('StepExportEntry must provide either solid or mesh')\n }\n solid = reconstructSolidFromMesh(kernel, entry.mesh.positions, entry.mesh.indices)\n ownedHandles.push(solid)\n }\n\n // 2. 展平 Compound(多 solid 导入的 part 其 solid 是 Compound);\n // 纯 solid 时 getSubShapes('solid') 返回 [自身]。\n // 形状类型分派:solid → shell → face → edge。ref 侧(cadquery\n // Shape.exportStep)可导出任意类型的形状,面/壳/边 compound(如\n // Shape.faces('>Z') / shape.edges('>Z') 的结果)同样要能写进\n // STEP(U22,2026-09-09)。\n let subs = kernel.getSubShapes(solid, 'solid')\n if (subs.length === 0) {\n subs = kernel.getSubShapes(solid, 'shell')\n }\n if (subs.length === 0) {\n subs = kernel.getSubShapes(solid, 'face')\n }\n if (subs.length === 0) {\n subs = kernel.getSubShapes(solid, 'edge')\n }\n if (subs.length === 0) {\n // wasm getSubShapes 不展开 compound 层(TopExp_Explorer 默认跳过),\n // 纯面/壳/边 compound(如 Shape.siblings / faces('>Z') 结果)在这里\n // 拿不到子形状。把 compound 整体作为单个 XCAF label 写入(STEP\n // writer 支持 compound 形状,与 ref 侧 cadquery Shape.exportStep\n // 对 faces/edges compound 的行为一致)。\n subs = [solid]\n }\n for (let si = 0; si < subs.length; si++) {\n const sub = subs[si]\n // 展平出的子句柄若不属于调用方缓存,记入 ownedHandles\n if (solid !== sub) ownedHandles.push(sub)\n const name = subs.length > 1\n ? `${entry.name ?? 'part'} [${si + 1}]`\n : entry.name\n // sRGB → linear:XCAF 按 linear 存储,STEP writer 输出时线性→sRGB,\n // 转换后 STEP 文件里的 COLOUR_RGB 才是宿主传入的原始 sRGB 值。\n const color: [number, number, number] | undefined = entry.color\n ? [srgbToLinear(entry.color[0]), srgbToLinear(entry.color[1]), srgbToLinear(entry.color[2])]\n : undefined\n doc.addShape(sub, { name, color })\n }\n }\n\n // 3. 导出(每个 label 一个独立 PRODUCT,保留名称/颜色)\n const stepText = doc.exportSTEP()\n return new TextEncoder().encode(stepText).buffer\n } finally {\n // 4. 释放顺序:先关文档,再释放本函数创建的句柄\n doc.close()\n for (const h of ownedHandles) {\n try {\n kernel.release(h)\n } catch {\n // already released\n }\n }\n }\n}\n\n/**\n * Export a BREP solid (OCCT native) to STEP format.\n *\n * 单实体导出 = exportStepFromSolids 的单条目特例(同一实现,无第二真源)。\n *\n * @param solid OCCT solid handle\n * @param kernel OCCT kernel (must match the one that created the solid)\n * @returns STEP file content as ArrayBuffer\n */\nexport function exportStepFromSolid(\n solid: BrepHandle,\n kernel: BrepEngineApi,\n): ArrayBuffer {\n return exportStepFromSolids(kernel, [{ solid }])\n}"]}
1
+ {"version":3,"file":"step.js","sourceRoot":"","sources":["../../../src/brep/export/step.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * exportStepFromSolids — L1 STEP 导出(从 OCCT solid 句柄,多实体、零 fuse)\n *\n * @platform occt — 本文件 import occt-kernel(createXCAFDocument/XCAF label 写入是\n * occt-only 平台面,D3)。文件级标注满足守卫①(平台 import 自证身份)。\n *\n * 每个 entry 作为 STEP 中一个独立实体(独立 XCAF label / PRODUCT)导出,\n * 保留名称与颜色。多实体之间绝不 fuse —— 这是硬性约定:\n * fuse 只允许作为用户脚本里的几何布尔运算,禁止作为导出时的实体合并手段。\n *\n * 导出 → 再导入身份闭环:导入侧 importAssemblyFromStep(XCAF)会把\n * 多实体 STEP 还原为多个 part;多 solid compound 拆分出的子节点命名为\n * `name [n]`,与本节点的展平命名规则一致。\n */\n\nimport type { BrepHandle } from '../engine/types'\nimport type { BrepEngineApi } from '../engine/primitives'\nimport { reconstructSolidFromMesh } from '../../occt-kernel/meshReconstruct'\nimport { getOcctKernel, type ShapeHandle } from '../../occt-kernel/occtKernel'\n\n/** STEP 导出条目:一个 part(精确 BREP 形状或三角网格,二选一)。 */\nexport interface StepExportEntry {\n /** 精确 BREP 形状(solid/shell/face/compound,来自宿主导出缓存)。与 mesh 二选一,solid 优先。 */\n solid?: BrepHandle\n /** 三角网格(世界坐标、已按单位缩放),经 reconstructSolidFromMesh 重建为实体。 */\n mesh?: { positions: Float32Array; indices: Uint32Array }\n /** 实体名称(写入 label name,导出为 PRODUCT 名称)。 */\n name?: string\n /** RGB 0..1 颜色(sRGB 编码,如宿主材质 base color)。写入前转 linear。 */\n color?: [number, number, number]\n}\n\n/**\n * sRGB → linear 转换。\n *\n * OCCT XCAF 内部按 linear RGB 存储颜色,STEP writer(xcafExportSTEP)\n * 导出时做 linear→sRGB 编码写 COLOUR_RGB。为了让\"宿主传入的 sRGB 颜色 ==\n * STEP 文件中的 COLOUR_RGB == 回读颜色\",写入前必须先转 linear。\n *\n * @param c sRGB 编码值(0..1)\n * @returns linear 值(0..1)\n */\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)\n}\n\n/**\n * Export multiple BREP solids (and/or triangle meshes) to STEP, one\n * independent entity per entry — no fuse, no string splicing.\n *\n * @param kernel OCCT kernel (must match the one that created the solids)\n * @param entries parts to export; each becomes its own XCAF label\n * @returns STEP file content as ArrayBuffer\n * @throws if entries is empty, or a mesh entry fails to reconstruct\n */\nexport function exportStepFromSolids(\n kernel: BrepEngineApi,\n entries: StepExportEntry[],\n): ArrayBuffer {\n if (entries.length === 0) {\n throw new Error('No exportable geometry')\n }\n\n const doc = getOcctKernel().createXCAFDocument()\n // 本函数创建的句柄(展平出的子 solid + mesh 重建的 solid),导出后释放。\n // 缓存里的原 solid(entry.solid)绝不释放,归调用方/缓存所有。\n const ownedHandles: BrepHandle[] = []\n\n try {\n for (const entry of entries) {\n // 1. 解析 solid:优先用精确 solid;无则从三角网格重建\n let solid = entry.solid\n if (!solid) {\n if (!entry.mesh) {\n throw new Error('StepExportEntry must provide either solid or mesh')\n }\n solid = reconstructSolidFromMesh(kernel, entry.mesh.positions, entry.mesh.indices)\n ownedHandles.push(solid)\n }\n\n // 2. 展平 Compound(多 solid 导入的 part 其 solid 是 Compound);\n // 纯 solid 时 getSubShapes('solid') 返回 [自身]。\n // 形状类型分派:solid → shell → face → edge。ref 侧(cadquery\n // Shape.exportStep)可导出任意类型的形状,面/壳/边 compound(如\n // Shape.faces('>Z') / shape.edges('>Z') 的结果)同样要能写进\n // STEP(U22,2026-09-09)。\n let subs = kernel.getSubShapes(solid, 'solid')\n if (subs.length === 0) {\n subs = kernel.getSubShapes(solid, 'shell')\n }\n if (subs.length === 0) {\n subs = kernel.getSubShapes(solid, 'face')\n }\n if (subs.length === 0) {\n subs = kernel.getSubShapes(solid, 'edge')\n }\n if (subs.length === 0) {\n // wasm getSubShapes 不展开 compound 层(TopExp_Explorer 默认跳过),\n // 纯面/壳/边 compound(如 Shape.siblings / faces('>Z') 结果)在这里\n // 拿不到子形状。把 compound 整体作为单个 XCAF label 写入(STEP\n // writer 支持 compound 形状,与 ref 侧 cadquery Shape.exportStep\n // 对 faces/edges compound 的行为一致)。\n subs = [solid]\n }\n for (let si = 0; si < subs.length; si++) {\n const sub = subs[si]\n // 展平出的子句柄若不属于调用方缓存,记入 ownedHandles\n if (solid !== sub) ownedHandles.push(sub)\n const name = subs.length > 1\n ? `${entry.name ?? 'part'} [${si + 1}]`\n : entry.name\n // sRGB → linear:XCAF 按 linear 存储,STEP writer 输出时线性→sRGB,\n // 转换后 STEP 文件里的 COLOUR_RGB 才是宿主传入的原始 sRGB 值。\n const color: [number, number, number] | undefined = entry.color\n ? [srgbToLinear(entry.color[0]), srgbToLinear(entry.color[1]), srgbToLinear(entry.color[2])]\n : undefined\n // 平台面(D3):XCAF label 写入是 occt-only。BrepHandle ↔ ShapeHandle\n // 运行时同构,品牌转换只发生在平台边界。\n doc.addShape(sub as unknown as ShapeHandle, { name, color })\n }\n }\n\n // 3. 导出(每个 label 一个独立 PRODUCT,保留名称/颜色)\n const stepText = doc.exportSTEP()\n return new TextEncoder().encode(stepText).buffer\n } finally {\n // 4. 释放顺序:先关文档,再释放本函数创建的句柄\n doc.close()\n for (const h of ownedHandles) {\n try {\n kernel.release(h)\n } catch {\n // already released\n }\n }\n }\n}\n\n/**\n * Export a BREP solid (OCCT native) to STEP format.\n *\n * 单实体导出 = exportStepFromSolids 的单条目特例(同一实现,无第二真源)。\n *\n * @param solid OCCT solid handle\n * @param kernel OCCT kernel (must match the one that created the solid)\n * @returns STEP file content as ArrayBuffer\n */\nexport function exportStepFromSolid(\n solid: BrepHandle,\n kernel: BrepEngineApi,\n): ArrayBuffer {\n return exportStepFromSolids(kernel, [{ solid }])\n}"]}
@@ -1,6 +1,14 @@
1
1
  /**
2
2
  * 面演化(face evolution)工具:hash 映射 ↔ ordinal 映射转换
3
3
  *
4
+ * @platform occt — 本文件 import occt-kernel(translateWithHashEvolution /
5
+ * scaleWithHashEvolution / directEditWithRoleTable(chamfer 分支) 走 occt-only
6
+ * `*WithHistory` 原生面,D3)。文件级标注满足守卫①(平台 import 自证身份);
7
+ * 文件内的**中立函数**(getFaceHashes/decodeEvolution/booleanWithRoleTable/
8
+ * identityHashEvolution 等只用 L1 BrepEngineApi)不因标注改变函数级中立性——
9
+ * 调用它们的**中立 op**(rotate_euler/scale3d/fillet/boolean 等)不声明 engines,
10
+ * 运行时不拦截(与 replicate.ts 同口径)。
11
+ *
4
12
  * See docs/api-contract.md §11 (topology contract) for face evolution context.
5
13
  *
6
14
  * occt-wasm 的 *WithHistory API 返回 BrepEvolutionData,其中 modified/generated
@@ -1 +1 @@
1
- {"version":3,"file":"face-evolution.d.ts","sourceRoot":"","sources":["../../src/brep/face-evolution.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"face-evolution.d.ts","sourceRoot":"","sources":["../../src/brep/face-evolution.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,14 @@
1
1
  /**
2
2
  * 面演化(face evolution)工具:hash 映射 ↔ ordinal 映射转换
3
3
  *
4
+ * @platform occt — 本文件 import occt-kernel(translateWithHashEvolution /
5
+ * scaleWithHashEvolution / directEditWithRoleTable(chamfer 分支) 走 occt-only
6
+ * `*WithHistory` 原生面,D3)。文件级标注满足守卫①(平台 import 自证身份);
7
+ * 文件内的**中立函数**(getFaceHashes/decodeEvolution/booleanWithRoleTable/
8
+ * identityHashEvolution 等只用 L1 BrepEngineApi)不因标注改变函数级中立性——
9
+ * 调用它们的**中立 op**(rotate_euler/scale3d/fillet/boolean 等)不声明 engines,
10
+ * 运行时不拦截(与 replicate.ts 同口径)。
11
+ *
4
12
  * See docs/api-contract.md §11 (topology contract) for face evolution context.
5
13
  *
6
14
  * occt-wasm 的 *WithHistory API 返回 BrepEvolutionData,其中 modified/generated
@@ -11,6 +19,7 @@
11
19
  * getSubShapes(shape,'face')[i] ↔ subShapeHashes(shape,'face',B)[i] 一一对应
12
20
  * 因此可以把 hash 映射无损转换为 ordinal 映射。
13
21
  */
22
+ import { getOcctKernel } from '../occt-kernel/occtKernel.js';
14
23
  /** hash 上界(与 occt-wasm kernel.cpp 一致:`% 2147483647`) */
15
24
  export const HASH_UPPER_BOUND = 2147483647;
16
25
  /**
@@ -200,7 +209,7 @@ export function identityHashEvolution(kernel, inputShape, resultShape) {
200
209
  */
201
210
  export function translateWithHashEvolution(kernel, shape, d) {
202
211
  const inputHashes = getFaceHashes(kernel, shape);
203
- const evo = kernel.translateWithHistory(shape, d[0], d[1], d[2], inputHashes, HASH_UPPER_BOUND);
212
+ const evo = getOcctKernel().translateWithHistory(shape, d[0], d[1], d[2], inputHashes, HASH_UPPER_BOUND);
204
213
  return { result: evo.result, evolution: decodeHashEvolution(evo) };
205
214
  }
206
215
  /**
@@ -218,7 +227,7 @@ export function translateWithHashEvolution(kernel, shape, d) {
218
227
  */
219
228
  export function scaleWithHashEvolution(kernel, shape, center, factor) {
220
229
  const inputHashes = getFaceHashes(kernel, shape);
221
- const evo = kernel.scaleWithHistory(shape, { x: center[0], y: center[1], z: center[2] }, factor, inputHashes, HASH_UPPER_BOUND);
230
+ const evo = getOcctKernel().scaleWithHistory(shape, { x: center[0], y: center[1], z: center[2] }, factor, inputHashes, HASH_UPPER_BOUND);
222
231
  return { result: evo.result, evolution: decodeHashEvolution(evo) };
223
232
  }
224
233
  /**
@@ -416,7 +425,10 @@ export function directEditWithRoleTable(kernel, op, solid, edgeHandles, radius,
416
425
  evo = kernel.filletWithHistory(solid, edgeHandles, radius, inputHashes, HASH_UPPER_BOUND);
417
426
  }
418
427
  else {
419
- evo = kernel.chamferWithHistory(solid, edgeHandles, radius, inputHashes, HASH_UPPER_BOUND);
428
+ // chamferWithHistory 是 occt-only(L1 无)→ 平台面 getOcctKernel(D3)。
429
+ // BrepHandle(branded number)与 occt-wasm ShapeHandle 运行时同构,品牌转换
430
+ // 只发生在平台边界。
431
+ evo = getOcctKernel().chamferWithHistory(solid, edgeHandles, radius, inputHashes, HASH_UPPER_BOUND);
420
432
  }
421
433
  const faceEvolution = decodeEvolution(kernel, evo, solid, evo.result);
422
434
  const hashEvo = decodeHashEvolution(evo);
@@ -1 +1 @@
1
- {"version":3,"file":"face-evolution.js","sourceRoot":"","sources":["../../src/brep/face-evolution.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 面演化(face evolution)工具:hash 映射 ↔ ordinal 映射转换\n *\n * See docs/api-contract.md §11 (topology contract) for face evolution context.\n *\n * occt-wasm 的 *WithHistory API 返回 BrepEvolutionData,其中 modified/generated\n * 用面 hash(内存指针哈希)编码。本模块将其解码为 ordinal 映射(面枚举序号),\n * 可安全持久化进 faijs 文本。\n *\n * 核心原理(分析文档 §4.4):\n * getSubShapes(shape,'face')[i] ↔ subShapeHashes(shape,'face',B)[i] 一一对应\n * 因此可以把 hash 映射无损转换为 ordinal 映射。\n */\n\nimport type { BrepHandle, BrepEvolutionData } from './engine/types'\nimport type { BrepEngineApi } from './engine/primitives'\n\n/** hash 上界(与 occt-wasm kernel.cpp 一致:`% 2147483647`) */\nexport const HASH_UPPER_BOUND = 2147483647\n\n/**\n * 面演化映射:输入面 ordinal → 输出面 ordinal 列表\n *\n * - 1→1:面被修改但未被切割(如面带孔仍是单面)\n * - 1→N:面被切割成多个面\n * - 不在 map 中:面未被修改或被删除\n */\nexport type FaceEvolution = Map<number, number[]>\n\n/**\n * Collect the hash list of all faces of a shape (via subShapeHashes; efficient, no handles allocated).\n * @param kernel - the OCCT kernel.\n * @param shape - the shape whose face hashes to collect.\n * @returns the array of face hashes.\n */\nexport function getFaceHashes(kernel: BrepEngineApi, shape: BrepHandle): number[] {\n return Array.from(kernel.subShapeHashes(shape, 'face', HASH_UPPER_BOUND))\n}\n\n/**\n * Collect the union of face hashes of two shapes (for WithHistory calls of binary boolean operations).\n *\n * Analysis doc §4.2: fuse/cut/intersect must pass subShapeHashes(A) ∪ subShapeHashes(B)\n * to track both inputs' face evolution.\n * @param kernel - the OCCT kernel.\n * @param shapeA - the first input shape.\n * @param shapeB - the second input shape.\n * @returns the union of the two shapes' face hashes.\n */\nexport function getUnionFaceHashes(\n kernel: BrepEngineApi,\n shapeA: BrepHandle,\n shapeB: BrepHandle,\n): number[] {\n const hashesA = getFaceHashes(kernel, shapeA)\n const hashesB = getFaceHashes(kernel, shapeB)\n return [...new Set([...hashesA, ...hashesB])]\n}\n\n/**\n * 解码 BrepEvolutionData 的 modified 数组为 ordinal 映射。\n *\n * modified 分段编码格式:[inputHash, count, outHash1, outHash2, ...] × N\n *\n * @param kernel the OCCT kernel.\n * @param evo the BrepEvolutionData (from a *WithHistory API).\n * @param inputShape the input shape (for the input face hash → ordinal mapping).\n * @param resultShape the result shape (for the output face hash → ordinal mapping).\n * @returns the FaceEvolution: inOrdinal → outOrdinal[].\n */\nexport function decodeEvolution(\n kernel: BrepEngineApi,\n evo: BrepEvolutionData,\n inputShape: BrepHandle,\n resultShape: BrepHandle,\n): FaceEvolution {\n const inputHashes = getFaceHashes(kernel, inputShape)\n const resultHashes = getFaceHashes(kernel, resultShape)\n\n // 构建 hash → ordinal 查找表\n const resultHashToOrdinal = new Map<number, number>()\n for (let i = 0; i < resultHashes.length; i++) {\n resultHashToOrdinal.set(resultHashes[i], i)\n }\n const inputHashToOrdinal = new Map<number, number>()\n for (let i = 0; i < inputHashes.length; i++) {\n inputHashToOrdinal.set(inputHashes[i], i)\n }\n\n // 解码 modified 数组\n const evolution: FaceEvolution = new Map()\n const modified = evo.modified\n let idx = 0\n while (idx < modified.length) {\n const inHash = modified[idx]\n const count = modified[idx + 1]\n const outOrdinals: number[] = []\n for (let j = 0; j < count; j++) {\n const outHash = modified[idx + 2 + j]\n const outOrdinal = resultHashToOrdinal.get(outHash)\n if (outOrdinal !== undefined) {\n outOrdinals.push(outOrdinal)\n }\n }\n const inOrdinal = inputHashToOrdinal.get(inHash)\n if (inOrdinal !== undefined) {\n evolution.set(inOrdinal, outOrdinals)\n }\n idx += 2 + count\n }\n\n return evolution\n}\n\n\n/**\n * Hash 键面演化:输入面 hash → 输出面 hash 列表(1→多分裂时多个)。\n *\n * 与序号键 FaceEvolution 并列、同源(同一次 *WithHistory 打包结果解出),\n * 一个供 role 传播(hash 键)、一个供选择器/文本(序号键),零额外 wasm 调用。\n */\nexport interface HashEvolution {\n /** 输入面 hash → 输出面 hash 列表(1→多分裂时多个)。 */\n readonly modified: ReadonlyMap<number, readonly number[]>\n /** 输入面中已不存在的面 hash。 */\n readonly deleted: ReadonlySet<number>\n}\n\n/**\n * 把 BrepEvolutionData 解码为 hash 键演化(§2.4)。\n *\n * modified 分段编码格式:[inHash, count, outHash1, ...] × N —— 本身就是\n * hash→hash[] 的 1→多映射,直接按同一格式解出 hash 键版本,不需要\n * getSubShapes 逐句柄 hashCode,也不分配任何句柄。\n *\n * generated 刻意不进 role 传播。**实测依据(2026-09-22,`brep/engine/phase0-kernel-probes.test.ts`)**:\n * `generated` 与 `modified` **同构分段、键集相同**,其值是各输入面派生出的**中间形**——\n * `cut` 实测 12 个 hash、结果里 **0 个存活**(`fillet`/`fuse` 里整个桶为空)。\n * ⇒ 新造面**不能**由 `generated` 定位,只能由\"三类命运\"的补集判定\n * (既不在输入 hash 集合、也不在任何 `modified` 输出里),再交 `construct`/派生词汇命名。\n *\n * @param evo - the BrepEvolutionData (from a *WithHistory API).\n * @returns the hash-keyed evolution.\n */\nexport function decodeHashEvolution(evo: BrepEvolutionData): HashEvolution {\n const modified = new Map<number, number[]>()\n const m = evo.modified\n let idx = 0\n while (idx < m.length) {\n const inHash = m[idx]\n const count = m[idx + 1]\n const outHashes: number[] = []\n for (let j = 0; j < count; j++) {\n outHashes.push(m[idx + 2 + j])\n }\n modified.set(inHash, outHashes)\n idx += 2 + count\n }\n return { modified, deleted: new Set(evo.deleted) }\n}\n\n/**\n * 把一次双输入布尔(cut/fuse/intersect)的打包演化按「inHash 属于 A 还是 B」\n * 拆成 A、B 两张 hash 演化(§3.4 布尔合流,faijs 对 brepjs 的必要扩展)。\n *\n * 现有 *WithHistoryBrep 包装只用 getUnionFaceHashes 传入 A∪B 两边 hash、且只对\n * 基体 a 解码序号演化。本函数对同一份 evo 零额外内核调用:用 subShapeHashes(a)\n * / subShapeHashes(b) 两个集合判定每个 inHash 的归属,各自传播各自的 role 表。\n *\n * @param evo - the BrepEvolutionData (from a binary boolean *WithHistory API).\n * @param hashesA - the face hashes of input A (target), via subShapeHashes.\n * @param hashesB - the face hashes of input B (tool), via subShapeHashes.\n * @returns the A/B split hash evolutions (faces from neither input are dropped).\n */\nexport function splitHashEvolutionByOrigin(\n evo: BrepEvolutionData,\n hashesA: readonly number[],\n hashesB: readonly number[],\n): { a: HashEvolution; b: HashEvolution } {\n const raw = decodeHashEvolution(evo)\n const setA = new Set(hashesA)\n const setB = new Set(hashesB)\n\n const aModified = new Map<number, number[]>()\n const bModified = new Map<number, number[]>()\n for (const [inHash, outs] of raw.modified) {\n if (setA.has(inHash)) aModified.set(inHash, [...outs])\n else if (setB.has(inHash)) bModified.set(inHash, [...outs])\n }\n\n const aDeleted = new Set<number>()\n const bDeleted = new Set<number>()\n for (const h of raw.deleted) {\n if (setA.has(h)) aDeleted.add(h)\n else if (setB.has(h)) bDeleted.add(h)\n }\n\n return { a: { modified: aModified, deleted: aDeleted }, b: { modified: bModified, deleted: bDeleted } }\n}\n\n/**\n * 构造 hash 键恒等演化:输入第 i 面 hash → 输出第 i 面 hash(按枚举序号对齐)。\n *\n * ⚠️ **Phase 0.3 后本函数只用于「内核无 `*WithHistory` 可表达」的 4 个 op**:\n *\n * | op | 为什么不能走权威映射 |\n * |---|---|\n * | `rotate_euler` | 任意欧拉角 + pivot;内核只有**单轴** `rotateWithHistory` |\n * | `scale3d` | 非等比;`generalTransform` 无历史(`scaleWithHistory` 只收均匀 factor) |\n * | `copy` | 深拷贝;内核无 `copyWithHistory` |\n * | `place` | 任意矩阵 `located`;内核无对应历史 API |\n *\n * `translate` / `scale`(均匀)已改走权威映射(`translateWithHashEvolution` /\n * `scaleWithHashEvolution`),不再经过本函数。\n *\n * ⚠️ **本函数的正确性依赖一个曾经未被验证的假设**:刚体变换/深拷贝保持 OCCT 的\n * 面枚举序号。该假设现由 `brep/face-evolution.ordering.test.ts` 实测钉住。\n * 若该测试变红 ⇒ 本函数在这 4 个 op 上会产出**错误的身份映射**,\n * 必须为它们找别的权威来源,**不是**调松测试。\n *\n * @param kernel - the OCCT kernel.\n * @param inputShape - the input shape.\n * @param resultShape - the transformed/copied output shape.\n * @returns the hash identity evolution (modified: in[i] → [out[i]]).\n */\nexport function identityHashEvolution(\n kernel: BrepEngineApi,\n inputShape: BrepHandle,\n resultShape: BrepHandle,\n): HashEvolution {\n const inputHashes = getFaceHashes(kernel, inputShape)\n const resultHashes = getFaceHashes(kernel, resultShape)\n const count = Math.min(inputHashes.length, resultHashes.length)\n const modified = new Map<number, number[]>()\n for (let i = 0; i < count; i++) {\n modified.set(inputHashes[i], [resultHashes[i]])\n }\n return { modified, deleted: new Set() }\n}\n\n/**\n * 平移 + **权威**面演化(Phase 0.3):走内核 `translateWithHistory`。\n *\n * 与 `identityHashEvolution` 的区别:这里的 `inHash → outHash[]` 是 OCCT 自己给的,\n * **不依赖**\"枚举序号在变换后保持\"这个此前从未验证的假设(分析文档 §7 第 6 项)。\n * 实测(`brep/engine/evolution-bindings.test.ts`):刚体变换的权威映射为\n * 1:1 全覆盖(`coveredInputs === 面数`、`deleted` 空、`generated` 空)。\n *\n * @param kernel - the OCCT kernel.\n * @param shape - the input shape.\n * @param d - the translation vector as [dx, dy, dz].\n * @returns the translated handle plus the authority hash evolution.\n */\nexport function translateWithHashEvolution(\n kernel: BrepEngineApi,\n shape: BrepHandle,\n d: readonly [number, number, number],\n): { result: BrepHandle; evolution: HashEvolution } {\n const inputHashes = getFaceHashes(kernel, shape)\n const evo = kernel.translateWithHistory(shape, d[0], d[1], d[2], inputHashes, HASH_UPPER_BOUND)\n return { result: evo.result, evolution: decodeHashEvolution(evo) }\n}\n\n/**\n * 均匀缩放 + **权威**面演化(Phase 0.3):走内核 `scaleWithHistory`。\n *\n * ⚠️ **仅均匀缩放**。非均匀缩放内核无 `*WithHistory`(`generalTransform` 无历史),\n * 故 `scale3d` 无法走本函数——它退回 `identityHashEvolution`,其\"面序保持\"假设\n * 由 `brep/face-evolution.ordering.test.ts` 钉住。\n *\n * @param kernel - the OCCT kernel.\n * @param shape - the input shape.\n * @param center - the fixed point of the scaling (not scaled).\n * @param factor - the uniform scale factor.\n * @returns the scaled handle plus the authority hash evolution.\n */\nexport function scaleWithHashEvolution(\n kernel: BrepEngineApi,\n shape: BrepHandle,\n center: readonly [number, number, number],\n factor: number,\n): { result: BrepHandle; evolution: HashEvolution } {\n const inputHashes = getFaceHashes(kernel, shape)\n const evo = kernel.scaleWithHistory(\n shape,\n { x: center[0], y: center[1], z: center[2] },\n factor,\n inputHashes,\n HASH_UPPER_BOUND,\n )\n return { result: evo.result, evolution: decodeHashEvolution(evo) }\n}\n\n/**\n * 双输入布尔 + roleTable 合流组合封装(§3.4,stdlib boolean 链式调用用)。\n *\n * 一次 *WithHistory 内核调用同时产出:\n * - result:结果实体\n * - faceEvolution:序号键演化(进 faceEvolutionCache,服务选择器/可视化)\n * - roleTable:A/B 两侧 role 表各自传播后合并(进 roleTableCache,服务命名)\n *\n * 缝面(generated)刻意不进 role 传播(§1.3/R2:generated hash 指向中间形、\n * 实测 0 存活)。新 origin 一律是**本次语句的 StmtId**(Phase 1.6:不再用 LHS\n * 变量名——PartName 会被改名/复用,StmtId 全局唯一)。\n *\n * @param kernel - the OCCT kernel.\n * @param op - the boolean operation ('fuse' | 'cut' | 'intersect').\n * @param a - the target shape.\n * @param b - the tool shape.\n * @param tableA - the target's role table.\n * @param tableB - the tool's role table.\n * @param outStmt - the boolean statement's StmtId (串形;新 origin for seam faces).\n * @returns the result handle, ordinal evolution and merged role table.\n */\nexport function booleanWithRoleTable(\n kernel: BrepEngineApi,\n op: 'fuse' | 'cut' | 'intersect',\n a: BrepHandle,\n b: BrepHandle,\n tableA: ReadonlyMap<unknown, unknown>,\n tableB: ReadonlyMap<unknown, unknown>,\n outStmt: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n const inputHashes = getUnionFaceHashes(kernel, a, b)\n let evo: BrepEvolutionData\n if (op === 'fuse') evo = kernel.fuseWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n else if (op === 'cut') evo = kernel.cutWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n else evo = kernel.intersectWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n\n const faceEvolution = decodeEvolution(kernel, evo, a, evo.result)\n\n // A/B 拆流 → 各自传播 → 合表(§3.4)\n const hashesA = getFaceHashes(kernel, a)\n const hashesB = getFaceHashes(kernel, b)\n const { a: evoA, b: evoB } = splitHashEvolutionByOrigin(evo, hashesA, hashesB)\n const merged = mergeRoleTablesLocal(tableA, evoA, tableB, evoB, outStmt)\n\n return { result: evo.result, faceEvolution, roleTable: merged }\n}\n\n/** 合表(避免 naming/roles 循环依赖:本文件不 import naming,用结构等价实现)。 */\nfunction mergeRoleTablesLocal(\n tableA: ReadonlyMap<unknown, unknown>,\n evoA: HashEvolution,\n tableB: ReadonlyMap<unknown, unknown>,\n evoB: HashEvolution,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- retained for future boolean generated-face naming\n outPart: string,\n): ReadonlyMap<unknown, unknown> {\n const result = new Map<unknown, unknown>()\n for (const [origin, roles] of tableA) {\n result.set(origin, propagateOriginRoles(roles as ReadonlyMap<string, readonly number[]>, evoA))\n }\n for (const [origin, roles] of tableB) {\n const existing = result.get(origin) as ReadonlyMap<string, readonly number[]> | undefined\n const advanced = propagateOriginRoles(roles as ReadonlyMap<string, readonly number[]>, evoB)\n if (existing) {\n const merged = new Map<string, number[]>()\n for (const [role, hs] of existing) merged.set(role, [...hs])\n for (const [role, hs] of advanced) {\n const prev = merged.get(role)\n merged.set(role, prev ? [...new Set([...prev, ...hs])] : [...hs])\n }\n result.set(origin, merged)\n } else {\n result.set(origin, advanced)\n }\n }\n // 3.6: void outPart removed — boolean seam faces are handled by the \"three fates\"\n // analysis (§4.4): cut has 0 new faces (§7 item 7), fuse seam faces are a Phase 4+ concern.\n // outPart retained for future kernel/byAdjacency on boolean generated faces.\n return result\n}\n\n/** 单 origin 传播(结构等价于 naming/roles.propagateRoles,避免循环依赖)。 */\nfunction propagateOriginRoles(\n roles: ReadonlyMap<string, readonly number[]>,\n evolution: HashEvolution,\n): ReadonlyMap<string, readonly number[]> {\n const updated = new Map<string, number[]>()\n for (const [role, hashes] of roles) {\n const successors: number[] = []\n for (const hash of hashes) {\n if (evolution.deleted.has(hash)) continue\n const modified = evolution.modified.get(hash)\n const targets = modified !== undefined && modified.length > 0 ? modified : [hash]\n for (const h of targets) if (!successors.includes(h)) successors.push(h)\n }\n if (successors.length > 0) updated.set(role, successors)\n }\n return updated\n}\n\n/**\n * Decode a BrepEvolutionData deleted array into the ordinal list of deleted faces.\n * @param kernel - the OCCT kernel.\n * @param evo - the BrepEvolutionData (from a *WithHistory API).\n * @param inputShape - the input shape (for the hash → ordinal mapping).\n * @returns the array of deleted face ordinals.\n */\nexport function decodeDeleted(\n kernel: BrepEngineApi,\n evo: BrepEvolutionData,\n inputShape: BrepHandle,\n): number[] {\n const inputHashes = getFaceHashes(kernel, inputShape)\n const inputHashToOrdinal = new Map<number, number>()\n for (let i = 0; i < inputHashes.length; i++) {\n inputHashToOrdinal.set(inputHashes[i], i)\n }\n\n const deletedOrdinals: number[] = []\n for (const hash of evo.deleted) {\n const ordinal = inputHashToOrdinal.get(hash)\n if (ordinal !== undefined) {\n deletedOrdinals.push(ordinal)\n }\n }\n return deletedOrdinals\n}\n\n// ─── WithHistory 封装函数 ───\n\n/**\n * cutWithHistory 封装:执行切割并返回结果 + 面演化映射。\n *\n * @param kernel OCCT 内核\n * @param a 基体\n * @param b 工具(从基体中减去)\n * @returns { result: 结果 BrepHandle, faceEvolution: 面演化映射 }\n */\nexport function cutWithHistoryBrep(\n kernel: BrepEngineApi,\n a: BrepHandle,\n b: BrepHandle,\n): { result: BrepHandle; faceEvolution: FaceEvolution } {\n const inputHashes = getUnionFaceHashes(kernel, a, b)\n const evo = kernel.cutWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n const faceEvolution = decodeEvolution(kernel, evo, a, evo.result)\n return { result: evo.result, faceEvolution }\n}\n\n/**\n * fuseWithHistory wrapper: performs the fuse and returns the result plus the face evolution mapping.\n * @param kernel - the OCCT kernel.\n * @param a - the base shape.\n * @param b - the tool shape to fuse into the base.\n * @returns the result BrepHandle plus the face evolution mapping.\n */\nexport function fuseWithHistoryBrep(\n kernel: BrepEngineApi,\n a: BrepHandle,\n b: BrepHandle,\n): { result: BrepHandle; faceEvolution: FaceEvolution } {\n const inputHashes = getUnionFaceHashes(kernel, a, b)\n const evo = kernel.fuseWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n const faceEvolution = decodeEvolution(kernel, evo, a, evo.result)\n return { result: evo.result, faceEvolution }\n}\n\n/**\n * intersectWithHistory wrapper: performs the intersection and returns the result plus the face evolution mapping.\n * @param kernel - the OCCT kernel.\n * @param a - the first input shape.\n * @param b - the second input shape.\n * @returns the result BrepHandle plus the face evolution mapping.\n */\nexport function intersectWithHistoryBrep(\n kernel: BrepEngineApi,\n a: BrepHandle,\n b: BrepHandle,\n): { result: BrepHandle; faceEvolution: FaceEvolution } {\n const inputHashes = getUnionFaceHashes(kernel, a, b)\n const evo = kernel.intersectWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n const faceEvolution = decodeEvolution(kernel, evo, a, evo.result)\n return { result: evo.result, faceEvolution }\n}\n\n// ─── 变换操作面演化 ───\n\n/**\n * 构造恒等面演化映射(用于 translate/rotate/scale 等不改变拓扑的操作)。\n *\n * 变换操作不改变面的数量和顺序,每个面 ordinal i → [i]。\n * 避免调用 *WithHistory API(rotate/scale 的 WithHistory 签名与现有 Euler/Vec3 参数不兼容)。\n *\n * @param kernel OCCT 内核\n * @param shape 输入形状(用于获取面数量)\n * @returns 恒等 FaceEvolution\n */\nexport function identityEvolution(\n kernel: BrepEngineApi,\n shape: BrepHandle,\n): FaceEvolution {\n const faceCount = getFaceHashes(kernel, shape).length\n const evolution: FaceEvolution = new Map()\n for (let i = 0; i < faceCount; i++) {\n evolution.set(i, [i])\n }\n return evolution\n}\n\n// ─── directEdit WithHistory 封装(fillet / chamfer:单输入) ───\n\n/**\n * 单输入 directEdit(fillet/chamfer)+ roleTable 传播封装。\n *\n * 与 `booleanWithRoleTable`(双输入)对应:单输入只有一张输入 role 表,\n * 一次 `*WithHistory` 内核调用产出结果 + 面演化,沿 hash 演化推进所有 origin。\n *\n * generated 刻意不进 role 传播(§1.3 事实:generated hash 指向中间形,\n * 实测 0 存活),过渡面的命名由 DerivedFaceTopoRef 在 M2 处理。\n *\n * @param kernel - the OCCT kernel.\n * @param op - the directEdit operation ('fillet' | 'chamfer').\n * @param solid - the input solid (single input, unlike boolean's a/b).\n * @param edgeHandles - the resolved Edge handles to fillet/chamfer.\n * @param radius - the fillet radius or chamfer distance (uniform only).\n * @param inputRoleTable - the input's role table.\n * @param outPart - the statement's LHS variable name (for new origin allocation).\n * @returns the result handle, ordinal evolution and propagated role table.\n */\nexport function directEditWithRoleTable(\n kernel: BrepEngineApi,\n op: 'fillet' | 'chamfer',\n solid: BrepHandle,\n edgeHandles: BrepHandle[],\n radius: number,\n inputRoleTable: ReadonlyMap<unknown, unknown>,\n outPart: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n const inputHashes = getFaceHashes(kernel, solid)\n let evo: BrepEvolutionData\n if (op === 'fillet') {\n evo = kernel.filletWithHistory(solid, edgeHandles, radius, inputHashes, HASH_UPPER_BOUND)\n } else {\n evo = kernel.chamferWithHistory(solid, edgeHandles, radius, inputHashes, HASH_UPPER_BOUND)\n }\n\n const faceEvolution = decodeEvolution(kernel, evo, solid, evo.result)\n const hashEvo = decodeHashEvolution(evo)\n const propagated = propagateAllOriginsLocal(inputRoleTable, hashEvo)\n\n // 3.4: generated face naming — transition faces are neither input faces nor\n // modified outputs (§4.4 \"三类命运\": 原样幸存 / 改型幸存 / 新造).\n // Role format: `gen:<op>:<i>` (i = enumeration order among generated faces).\n // String formatted directly (no import of role-name.ts — avoids circular dep).\n const resultHashes = getFaceHashes(kernel, evo.result)\n const inputHashSet = new Set(inputHashes)\n const modifiedOutputHashes = new Set<number>()\n for (const outs of hashEvo.modified.values()) {\n for (const h of outs) modifiedOutputHashes.add(h)\n }\n const generatedHashes = resultHashes.filter(\n (h) => !inputHashSet.has(h) && !modifiedOutputHashes.has(h),\n )\n\n if (generatedHashes.length > 0) {\n const genRoles = new Map<string, number[]>()\n for (let i = 0; i < generatedHashes.length; i++) {\n genRoles.set(`gen:${op}:${i}`, [generatedHashes[i]!])\n }\n const roleTable = new Map(propagated)\n roleTable.set(outPart, genRoles)\n return { result: evo.result, faceEvolution, roleTable }\n }\n\n return { result: evo.result, faceEvolution, roleTable: propagated }\n}\n\n/**\n * 单输入 directEdit 的便捷别名:fillet。\n *\n * @param kernel - the OCCT kernel.\n * @param solid - the input solid.\n * @param edgeHandles - the resolved Edge handles.\n * @param radius - the fillet radius (uniform).\n * @param inputRoleTable - the input's role table.\n * @param outPart - the statement's LHS variable name.\n * @returns the result handle, ordinal evolution and propagated role table.\n */\nexport function filletWithRoleTable(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n edgeHandles: BrepHandle[],\n radius: number,\n inputRoleTable: ReadonlyMap<unknown, unknown>,\n outPart: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n return directEditWithRoleTable(kernel, 'fillet', solid, edgeHandles, radius, inputRoleTable, outPart)\n}\n\n/**\n * 单输入 directEdit 的便捷别名:chamfer。\n *\n * @param kernel - the OCCT kernel.\n * @param solid - the input solid.\n * @param edgeHandles - the resolved Edge handles.\n * @param distance - the chamfer distance (uniform).\n * @param inputRoleTable - the input's role table.\n * @param outPart - the statement's LHS variable name.\n * @returns the result handle, ordinal evolution and propagated role table.\n */\nexport function chamferWithRoleTable(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n edgeHandles: BrepHandle[],\n distance: number,\n inputRoleTable: ReadonlyMap<unknown, unknown>,\n outPart: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n return directEditWithRoleTable(kernel, 'chamfer', solid, edgeHandles, distance, inputRoleTable, outPart)\n}\n\n/**\n * 钻孔 roleTable 传播:底孔(圆柱 cut)产生的新造面 = 孔壁,挂**消费它的那条语句**\n * 的 origin(§7.1:drill 的工具体是 op 内部临时件,无其他用户可见坐标可继承)。\n * 角色形态 `hole:<j>`(j = 新造面枚举序)。沿用 `directEditWithRoleTable` 的\n * 三类命运判定(原样幸存 / 改型幸存 / 新造),新造面才派生命名。\n *\n * @param kernel - the OCCT kernel.\n * @param solid - the input solid (the drilled part).\n * @param toolSolid - the drill-bit tool solid (caller-built; released by caller).\n * @param inputRoleTable - the input's role table.\n * @param outStmt - the drilling statement's StmtId (origin for new faces).\n * @returns the result handle, ordinal evolution and role table with `hole:<j>`.\n */\nexport function drillBrepWithRoleTable(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n toolSolid: BrepHandle,\n inputRoleTable: ReadonlyMap<unknown, unknown>,\n outStmt: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n const inputHashes = getFaceHashes(kernel, solid)\n const evo = kernel.cutWithHistory(solid, toolSolid, inputHashes, HASH_UPPER_BOUND)\n const faceEvolution = decodeEvolution(kernel, evo, solid, evo.result)\n const hashEvo = decodeHashEvolution(evo)\n const propagated = propagateAllOriginsLocal(inputRoleTable, hashEvo)\n\n // 三类命运判定:新造面 = 结果 − 输入 − 改型后继(§4.4)。\n const resultHashes = getFaceHashes(kernel, evo.result)\n const inputHashSet = new Set(inputHashes)\n const modifiedOutputHashes = new Set<number>()\n for (const outs of hashEvo.modified.values()) {\n for (const h of outs) modifiedOutputHashes.add(h)\n }\n const generatedHashes = resultHashes.filter(\n (h) => !inputHashSet.has(h) && !modifiedOutputHashes.has(h),\n )\n\n const roleTable = new Map(propagated)\n if (generatedHashes.length > 0) {\n const genRoles = new Map<string, number[]>()\n for (let i = 0; i < generatedHashes.length; i++) {\n genRoles.set(`hole:${i}`, [generatedHashes[i]!])\n }\n roleTable.set(outStmt, genRoles)\n }\n return { result: evo.result, faceEvolution, roleTable }\n}\n\n/** 单输入 roleTable 传播(结构等价于 naming/roles.propagateAllOrigins,避免循环依赖)。 */\nfunction propagateAllOriginsLocal(\n roles: ReadonlyMap<unknown, unknown>,\n evolution: HashEvolution,\n): ReadonlyMap<unknown, unknown> {\n const result = new Map<unknown, unknown>()\n for (const [origin, originRoles] of roles) {\n result.set(origin, propagateOriginRoles(originRoles as ReadonlyMap<string, readonly number[]>, evolution))\n }\n return result\n}\n"]}
1
+ {"version":3,"file":"face-evolution.js","sourceRoot":"","sources":["../../src/brep/face-evolution.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 面演化(face evolution)工具:hash 映射 ↔ ordinal 映射转换\n *\n * @platform occt — 本文件 import occt-kernel(translateWithHashEvolution /\n * scaleWithHashEvolution / directEditWithRoleTable(chamfer 分支) 走 occt-only\n * `*WithHistory` 原生面,D3)。文件级标注满足守卫①(平台 import 自证身份);\n * 文件内的**中立函数**(getFaceHashes/decodeEvolution/booleanWithRoleTable/\n * identityHashEvolution 等只用 L1 BrepEngineApi)不因标注改变函数级中立性——\n * 调用它们的**中立 op**(rotate_euler/scale3d/fillet/boolean 等)不声明 engines,\n * 运行时不拦截(与 replicate.ts 同口径)。\n *\n * See docs/api-contract.md §11 (topology contract) for face evolution context.\n *\n * occt-wasm 的 *WithHistory API 返回 BrepEvolutionData,其中 modified/generated\n * 用面 hash(内存指针哈希)编码。本模块将其解码为 ordinal 映射(面枚举序号),\n * 可安全持久化进 faijs 文本。\n *\n * 核心原理(分析文档 §4.4):\n * getSubShapes(shape,'face')[i] ↔ subShapeHashes(shape,'face',B)[i] 一一对应\n * 因此可以把 hash 映射无损转换为 ordinal 映射。\n */\n\nimport type { BrepHandle, BrepEvolutionData } from './engine/types'\nimport type { BrepEngineApi } from './engine/primitives'\nimport { getOcctKernel, type ShapeHandle } from '../occt-kernel/occtKernel'\n\n/** hash 上界(与 occt-wasm kernel.cpp 一致:`% 2147483647`) */\nexport const HASH_UPPER_BOUND = 2147483647\n\n/**\n * 面演化映射:输入面 ordinal → 输出面 ordinal 列表\n *\n * - 1→1:面被修改但未被切割(如面带孔仍是单面)\n * - 1→N:面被切割成多个面\n * - 不在 map 中:面未被修改或被删除\n */\nexport type FaceEvolution = Map<number, number[]>\n\n/**\n * Collect the hash list of all faces of a shape (via subShapeHashes; efficient, no handles allocated).\n * @param kernel - the OCCT kernel.\n * @param shape - the shape whose face hashes to collect.\n * @returns the array of face hashes.\n */\nexport function getFaceHashes(kernel: BrepEngineApi, shape: BrepHandle): number[] {\n return Array.from(kernel.subShapeHashes(shape, 'face', HASH_UPPER_BOUND))\n}\n\n/**\n * Collect the union of face hashes of two shapes (for WithHistory calls of binary boolean operations).\n *\n * Analysis doc §4.2: fuse/cut/intersect must pass subShapeHashes(A) ∪ subShapeHashes(B)\n * to track both inputs' face evolution.\n * @param kernel - the OCCT kernel.\n * @param shapeA - the first input shape.\n * @param shapeB - the second input shape.\n * @returns the union of the two shapes' face hashes.\n */\nexport function getUnionFaceHashes(\n kernel: BrepEngineApi,\n shapeA: BrepHandle,\n shapeB: BrepHandle,\n): number[] {\n const hashesA = getFaceHashes(kernel, shapeA)\n const hashesB = getFaceHashes(kernel, shapeB)\n return [...new Set([...hashesA, ...hashesB])]\n}\n\n/**\n * 解码 BrepEvolutionData 的 modified 数组为 ordinal 映射。\n *\n * modified 分段编码格式:[inputHash, count, outHash1, outHash2, ...] × N\n *\n * @param kernel the OCCT kernel.\n * @param evo the BrepEvolutionData (from a *WithHistory API).\n * @param inputShape the input shape (for the input face hash → ordinal mapping).\n * @param resultShape the result shape (for the output face hash → ordinal mapping).\n * @returns the FaceEvolution: inOrdinal → outOrdinal[].\n */\nexport function decodeEvolution(\n kernel: BrepEngineApi,\n evo: BrepEvolutionData,\n inputShape: BrepHandle,\n resultShape: BrepHandle,\n): FaceEvolution {\n const inputHashes = getFaceHashes(kernel, inputShape)\n const resultHashes = getFaceHashes(kernel, resultShape)\n\n // 构建 hash → ordinal 查找表\n const resultHashToOrdinal = new Map<number, number>()\n for (let i = 0; i < resultHashes.length; i++) {\n resultHashToOrdinal.set(resultHashes[i], i)\n }\n const inputHashToOrdinal = new Map<number, number>()\n for (let i = 0; i < inputHashes.length; i++) {\n inputHashToOrdinal.set(inputHashes[i], i)\n }\n\n // 解码 modified 数组\n const evolution: FaceEvolution = new Map()\n const modified = evo.modified\n let idx = 0\n while (idx < modified.length) {\n const inHash = modified[idx]\n const count = modified[idx + 1]\n const outOrdinals: number[] = []\n for (let j = 0; j < count; j++) {\n const outHash = modified[idx + 2 + j]\n const outOrdinal = resultHashToOrdinal.get(outHash)\n if (outOrdinal !== undefined) {\n outOrdinals.push(outOrdinal)\n }\n }\n const inOrdinal = inputHashToOrdinal.get(inHash)\n if (inOrdinal !== undefined) {\n evolution.set(inOrdinal, outOrdinals)\n }\n idx += 2 + count\n }\n\n return evolution\n}\n\n\n/**\n * Hash 键面演化:输入面 hash → 输出面 hash 列表(1→多分裂时多个)。\n *\n * 与序号键 FaceEvolution 并列、同源(同一次 *WithHistory 打包结果解出),\n * 一个供 role 传播(hash 键)、一个供选择器/文本(序号键),零额外 wasm 调用。\n */\nexport interface HashEvolution {\n /** 输入面 hash → 输出面 hash 列表(1→多分裂时多个)。 */\n readonly modified: ReadonlyMap<number, readonly number[]>\n /** 输入面中已不存在的面 hash。 */\n readonly deleted: ReadonlySet<number>\n}\n\n/**\n * 把 BrepEvolutionData 解码为 hash 键演化(§2.4)。\n *\n * modified 分段编码格式:[inHash, count, outHash1, ...] × N —— 本身就是\n * hash→hash[] 的 1→多映射,直接按同一格式解出 hash 键版本,不需要\n * getSubShapes 逐句柄 hashCode,也不分配任何句柄。\n *\n * generated 刻意不进 role 传播。**实测依据(2026-09-22,`brep/engine/phase0-kernel-probes.test.ts`)**:\n * `generated` 与 `modified` **同构分段、键集相同**,其值是各输入面派生出的**中间形**——\n * `cut` 实测 12 个 hash、结果里 **0 个存活**(`fillet`/`fuse` 里整个桶为空)。\n * ⇒ 新造面**不能**由 `generated` 定位,只能由\"三类命运\"的补集判定\n * (既不在输入 hash 集合、也不在任何 `modified` 输出里),再交 `construct`/派生词汇命名。\n *\n * @param evo - the BrepEvolutionData (from a *WithHistory API).\n * @returns the hash-keyed evolution.\n */\nexport function decodeHashEvolution(evo: BrepEvolutionData): HashEvolution {\n const modified = new Map<number, number[]>()\n const m = evo.modified\n let idx = 0\n while (idx < m.length) {\n const inHash = m[idx]\n const count = m[idx + 1]\n const outHashes: number[] = []\n for (let j = 0; j < count; j++) {\n outHashes.push(m[idx + 2 + j])\n }\n modified.set(inHash, outHashes)\n idx += 2 + count\n }\n return { modified, deleted: new Set(evo.deleted) }\n}\n\n/**\n * 把一次双输入布尔(cut/fuse/intersect)的打包演化按「inHash 属于 A 还是 B」\n * 拆成 A、B 两张 hash 演化(§3.4 布尔合流,faijs 对 brepjs 的必要扩展)。\n *\n * 现有 *WithHistoryBrep 包装只用 getUnionFaceHashes 传入 A∪B 两边 hash、且只对\n * 基体 a 解码序号演化。本函数对同一份 evo 零额外内核调用:用 subShapeHashes(a)\n * / subShapeHashes(b) 两个集合判定每个 inHash 的归属,各自传播各自的 role 表。\n *\n * @param evo - the BrepEvolutionData (from a binary boolean *WithHistory API).\n * @param hashesA - the face hashes of input A (target), via subShapeHashes.\n * @param hashesB - the face hashes of input B (tool), via subShapeHashes.\n * @returns the A/B split hash evolutions (faces from neither input are dropped).\n */\nexport function splitHashEvolutionByOrigin(\n evo: BrepEvolutionData,\n hashesA: readonly number[],\n hashesB: readonly number[],\n): { a: HashEvolution; b: HashEvolution } {\n const raw = decodeHashEvolution(evo)\n const setA = new Set(hashesA)\n const setB = new Set(hashesB)\n\n const aModified = new Map<number, number[]>()\n const bModified = new Map<number, number[]>()\n for (const [inHash, outs] of raw.modified) {\n if (setA.has(inHash)) aModified.set(inHash, [...outs])\n else if (setB.has(inHash)) bModified.set(inHash, [...outs])\n }\n\n const aDeleted = new Set<number>()\n const bDeleted = new Set<number>()\n for (const h of raw.deleted) {\n if (setA.has(h)) aDeleted.add(h)\n else if (setB.has(h)) bDeleted.add(h)\n }\n\n return { a: { modified: aModified, deleted: aDeleted }, b: { modified: bModified, deleted: bDeleted } }\n}\n\n/**\n * 构造 hash 键恒等演化:输入第 i 面 hash → 输出第 i 面 hash(按枚举序号对齐)。\n *\n * ⚠️ **Phase 0.3 后本函数只用于「内核无 `*WithHistory` 可表达」的 4 个 op**:\n *\n * | op | 为什么不能走权威映射 |\n * |---|---|\n * | `rotate_euler` | 任意欧拉角 + pivot;内核只有**单轴** `rotateWithHistory` |\n * | `scale3d` | 非等比;`generalTransform` 无历史(`scaleWithHistory` 只收均匀 factor) |\n * | `copy` | 深拷贝;内核无 `copyWithHistory` |\n * | `place` | 任意矩阵 `located`;内核无对应历史 API |\n *\n * `translate` / `scale`(均匀)已改走权威映射(`translateWithHashEvolution` /\n * `scaleWithHashEvolution`),不再经过本函数。\n *\n * ⚠️ **本函数的正确性依赖一个曾经未被验证的假设**:刚体变换/深拷贝保持 OCCT 的\n * 面枚举序号。该假设现由 `brep/face-evolution.ordering.test.ts` 实测钉住。\n * 若该测试变红 ⇒ 本函数在这 4 个 op 上会产出**错误的身份映射**,\n * 必须为它们找别的权威来源,**不是**调松测试。\n *\n * @param kernel - the OCCT kernel.\n * @param inputShape - the input shape.\n * @param resultShape - the transformed/copied output shape.\n * @returns the hash identity evolution (modified: in[i] → [out[i]]).\n */\nexport function identityHashEvolution(\n kernel: BrepEngineApi,\n inputShape: BrepHandle,\n resultShape: BrepHandle,\n): HashEvolution {\n const inputHashes = getFaceHashes(kernel, inputShape)\n const resultHashes = getFaceHashes(kernel, resultShape)\n const count = Math.min(inputHashes.length, resultHashes.length)\n const modified = new Map<number, number[]>()\n for (let i = 0; i < count; i++) {\n modified.set(inputHashes[i], [resultHashes[i]])\n }\n return { modified, deleted: new Set() }\n}\n\n/**\n * 平移 + **权威**面演化(Phase 0.3):走内核 `translateWithHistory`。\n *\n * 与 `identityHashEvolution` 的区别:这里的 `inHash → outHash[]` 是 OCCT 自己给的,\n * **不依赖**\"枚举序号在变换后保持\"这个此前从未验证的假设(分析文档 §7 第 6 项)。\n * 实测(`brep/engine/evolution-bindings.test.ts`):刚体变换的权威映射为\n * 1:1 全覆盖(`coveredInputs === 面数`、`deleted` 空、`generated` 空)。\n *\n * @param kernel - the OCCT kernel.\n * @param shape - the input shape.\n * @param d - the translation vector as [dx, dy, dz].\n * @returns the translated handle plus the authority hash evolution.\n */\nexport function translateWithHashEvolution(\n kernel: BrepEngineApi,\n shape: BrepHandle,\n d: readonly [number, number, number],\n): { result: BrepHandle; evolution: HashEvolution } {\n const inputHashes = getFaceHashes(kernel, shape)\n const evo = getOcctKernel().translateWithHistory(shape as unknown as ShapeHandle, d[0], d[1], d[2], inputHashes, HASH_UPPER_BOUND) as unknown as BrepEvolutionData\n return { result: evo.result, evolution: decodeHashEvolution(evo) }\n}\n\n/**\n * 均匀缩放 + **权威**面演化(Phase 0.3):走内核 `scaleWithHistory`。\n *\n * ⚠️ **仅均匀缩放**。非均匀缩放内核无 `*WithHistory`(`generalTransform` 无历史),\n * 故 `scale3d` 无法走本函数——它退回 `identityHashEvolution`,其\"面序保持\"假设\n * 由 `brep/face-evolution.ordering.test.ts` 钉住。\n *\n * @param kernel - the OCCT kernel.\n * @param shape - the input shape.\n * @param center - the fixed point of the scaling (not scaled).\n * @param factor - the uniform scale factor.\n * @returns the scaled handle plus the authority hash evolution.\n */\nexport function scaleWithHashEvolution(\n kernel: BrepEngineApi,\n shape: BrepHandle,\n center: readonly [number, number, number],\n factor: number,\n): { result: BrepHandle; evolution: HashEvolution } {\n const inputHashes = getFaceHashes(kernel, shape)\n const evo = getOcctKernel().scaleWithHistory(\n shape as unknown as ShapeHandle,\n { x: center[0], y: center[1], z: center[2] },\n factor,\n inputHashes,\n HASH_UPPER_BOUND,\n ) as unknown as BrepEvolutionData\n return { result: evo.result, evolution: decodeHashEvolution(evo) }\n}\n\n/**\n * 双输入布尔 + roleTable 合流组合封装(§3.4,stdlib boolean 链式调用用)。\n *\n * 一次 *WithHistory 内核调用同时产出:\n * - result:结果实体\n * - faceEvolution:序号键演化(进 faceEvolutionCache,服务选择器/可视化)\n * - roleTable:A/B 两侧 role 表各自传播后合并(进 roleTableCache,服务命名)\n *\n * 缝面(generated)刻意不进 role 传播(§1.3/R2:generated hash 指向中间形、\n * 实测 0 存活)。新 origin 一律是**本次语句的 StmtId**(Phase 1.6:不再用 LHS\n * 变量名——PartName 会被改名/复用,StmtId 全局唯一)。\n *\n * @param kernel - the OCCT kernel.\n * @param op - the boolean operation ('fuse' | 'cut' | 'intersect').\n * @param a - the target shape.\n * @param b - the tool shape.\n * @param tableA - the target's role table.\n * @param tableB - the tool's role table.\n * @param outStmt - the boolean statement's StmtId (串形;新 origin for seam faces).\n * @returns the result handle, ordinal evolution and merged role table.\n */\nexport function booleanWithRoleTable(\n kernel: BrepEngineApi,\n op: 'fuse' | 'cut' | 'intersect',\n a: BrepHandle,\n b: BrepHandle,\n tableA: ReadonlyMap<unknown, unknown>,\n tableB: ReadonlyMap<unknown, unknown>,\n outStmt: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n const inputHashes = getUnionFaceHashes(kernel, a, b)\n let evo: BrepEvolutionData\n if (op === 'fuse') evo = kernel.fuseWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n else if (op === 'cut') evo = kernel.cutWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n else evo = kernel.intersectWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n\n const faceEvolution = decodeEvolution(kernel, evo, a, evo.result)\n\n // A/B 拆流 → 各自传播 → 合表(§3.4)\n const hashesA = getFaceHashes(kernel, a)\n const hashesB = getFaceHashes(kernel, b)\n const { a: evoA, b: evoB } = splitHashEvolutionByOrigin(evo, hashesA, hashesB)\n const merged = mergeRoleTablesLocal(tableA, evoA, tableB, evoB, outStmt)\n\n return { result: evo.result, faceEvolution, roleTable: merged }\n}\n\n/** 合表(避免 naming/roles 循环依赖:本文件不 import naming,用结构等价实现)。 */\nfunction mergeRoleTablesLocal(\n tableA: ReadonlyMap<unknown, unknown>,\n evoA: HashEvolution,\n tableB: ReadonlyMap<unknown, unknown>,\n evoB: HashEvolution,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- retained for future boolean generated-face naming\n outPart: string,\n): ReadonlyMap<unknown, unknown> {\n const result = new Map<unknown, unknown>()\n for (const [origin, roles] of tableA) {\n result.set(origin, propagateOriginRoles(roles as ReadonlyMap<string, readonly number[]>, evoA))\n }\n for (const [origin, roles] of tableB) {\n const existing = result.get(origin) as ReadonlyMap<string, readonly number[]> | undefined\n const advanced = propagateOriginRoles(roles as ReadonlyMap<string, readonly number[]>, evoB)\n if (existing) {\n const merged = new Map<string, number[]>()\n for (const [role, hs] of existing) merged.set(role, [...hs])\n for (const [role, hs] of advanced) {\n const prev = merged.get(role)\n merged.set(role, prev ? [...new Set([...prev, ...hs])] : [...hs])\n }\n result.set(origin, merged)\n } else {\n result.set(origin, advanced)\n }\n }\n // 3.6: void outPart removed — boolean seam faces are handled by the \"three fates\"\n // analysis (§4.4): cut has 0 new faces (§7 item 7), fuse seam faces are a Phase 4+ concern.\n // outPart retained for future kernel/byAdjacency on boolean generated faces.\n return result\n}\n\n/** 单 origin 传播(结构等价于 naming/roles.propagateRoles,避免循环依赖)。 */\nfunction propagateOriginRoles(\n roles: ReadonlyMap<string, readonly number[]>,\n evolution: HashEvolution,\n): ReadonlyMap<string, readonly number[]> {\n const updated = new Map<string, number[]>()\n for (const [role, hashes] of roles) {\n const successors: number[] = []\n for (const hash of hashes) {\n if (evolution.deleted.has(hash)) continue\n const modified = evolution.modified.get(hash)\n const targets = modified !== undefined && modified.length > 0 ? modified : [hash]\n for (const h of targets) if (!successors.includes(h)) successors.push(h)\n }\n if (successors.length > 0) updated.set(role, successors)\n }\n return updated\n}\n\n/**\n * Decode a BrepEvolutionData deleted array into the ordinal list of deleted faces.\n * @param kernel - the OCCT kernel.\n * @param evo - the BrepEvolutionData (from a *WithHistory API).\n * @param inputShape - the input shape (for the hash → ordinal mapping).\n * @returns the array of deleted face ordinals.\n */\nexport function decodeDeleted(\n kernel: BrepEngineApi,\n evo: BrepEvolutionData,\n inputShape: BrepHandle,\n): number[] {\n const inputHashes = getFaceHashes(kernel, inputShape)\n const inputHashToOrdinal = new Map<number, number>()\n for (let i = 0; i < inputHashes.length; i++) {\n inputHashToOrdinal.set(inputHashes[i], i)\n }\n\n const deletedOrdinals: number[] = []\n for (const hash of evo.deleted) {\n const ordinal = inputHashToOrdinal.get(hash)\n if (ordinal !== undefined) {\n deletedOrdinals.push(ordinal)\n }\n }\n return deletedOrdinals\n}\n\n// ─── WithHistory 封装函数 ───\n\n/**\n * cutWithHistory 封装:执行切割并返回结果 + 面演化映射。\n *\n * @param kernel OCCT 内核\n * @param a 基体\n * @param b 工具(从基体中减去)\n * @returns { result: 结果 BrepHandle, faceEvolution: 面演化映射 }\n */\nexport function cutWithHistoryBrep(\n kernel: BrepEngineApi,\n a: BrepHandle,\n b: BrepHandle,\n): { result: BrepHandle; faceEvolution: FaceEvolution } {\n const inputHashes = getUnionFaceHashes(kernel, a, b)\n const evo = kernel.cutWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n const faceEvolution = decodeEvolution(kernel, evo, a, evo.result)\n return { result: evo.result, faceEvolution }\n}\n\n/**\n * fuseWithHistory wrapper: performs the fuse and returns the result plus the face evolution mapping.\n * @param kernel - the OCCT kernel.\n * @param a - the base shape.\n * @param b - the tool shape to fuse into the base.\n * @returns the result BrepHandle plus the face evolution mapping.\n */\nexport function fuseWithHistoryBrep(\n kernel: BrepEngineApi,\n a: BrepHandle,\n b: BrepHandle,\n): { result: BrepHandle; faceEvolution: FaceEvolution } {\n const inputHashes = getUnionFaceHashes(kernel, a, b)\n const evo = kernel.fuseWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n const faceEvolution = decodeEvolution(kernel, evo, a, evo.result)\n return { result: evo.result, faceEvolution }\n}\n\n/**\n * intersectWithHistory wrapper: performs the intersection and returns the result plus the face evolution mapping.\n * @param kernel - the OCCT kernel.\n * @param a - the first input shape.\n * @param b - the second input shape.\n * @returns the result BrepHandle plus the face evolution mapping.\n */\nexport function intersectWithHistoryBrep(\n kernel: BrepEngineApi,\n a: BrepHandle,\n b: BrepHandle,\n): { result: BrepHandle; faceEvolution: FaceEvolution } {\n const inputHashes = getUnionFaceHashes(kernel, a, b)\n const evo = kernel.intersectWithHistory(a, b, inputHashes, HASH_UPPER_BOUND)\n const faceEvolution = decodeEvolution(kernel, evo, a, evo.result)\n return { result: evo.result, faceEvolution }\n}\n\n// ─── 变换操作面演化 ───\n\n/**\n * 构造恒等面演化映射(用于 translate/rotate/scale 等不改变拓扑的操作)。\n *\n * 变换操作不改变面的数量和顺序,每个面 ordinal i → [i]。\n * 避免调用 *WithHistory API(rotate/scale 的 WithHistory 签名与现有 Euler/Vec3 参数不兼容)。\n *\n * @param kernel OCCT 内核\n * @param shape 输入形状(用于获取面数量)\n * @returns 恒等 FaceEvolution\n */\nexport function identityEvolution(\n kernel: BrepEngineApi,\n shape: BrepHandle,\n): FaceEvolution {\n const faceCount = getFaceHashes(kernel, shape).length\n const evolution: FaceEvolution = new Map()\n for (let i = 0; i < faceCount; i++) {\n evolution.set(i, [i])\n }\n return evolution\n}\n\n// ─── directEdit WithHistory 封装(fillet / chamfer:单输入) ───\n\n/**\n * 单输入 directEdit(fillet/chamfer)+ roleTable 传播封装。\n *\n * 与 `booleanWithRoleTable`(双输入)对应:单输入只有一张输入 role 表,\n * 一次 `*WithHistory` 内核调用产出结果 + 面演化,沿 hash 演化推进所有 origin。\n *\n * generated 刻意不进 role 传播(§1.3 事实:generated hash 指向中间形,\n * 实测 0 存活),过渡面的命名由 DerivedFaceTopoRef 在 M2 处理。\n *\n * @param kernel - the OCCT kernel.\n * @param op - the directEdit operation ('fillet' | 'chamfer').\n * @param solid - the input solid (single input, unlike boolean's a/b).\n * @param edgeHandles - the resolved Edge handles to fillet/chamfer.\n * @param radius - the fillet radius or chamfer distance (uniform only).\n * @param inputRoleTable - the input's role table.\n * @param outPart - the statement's LHS variable name (for new origin allocation).\n * @returns the result handle, ordinal evolution and propagated role table.\n */\nexport function directEditWithRoleTable(\n kernel: BrepEngineApi,\n op: 'fillet' | 'chamfer',\n solid: BrepHandle,\n edgeHandles: BrepHandle[],\n radius: number,\n inputRoleTable: ReadonlyMap<unknown, unknown>,\n outPart: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n const inputHashes = getFaceHashes(kernel, solid)\n let evo: BrepEvolutionData\n if (op === 'fillet') {\n evo = kernel.filletWithHistory(solid, edgeHandles, radius, inputHashes, HASH_UPPER_BOUND)\n } else {\n // chamferWithHistory 是 occt-only(L1 无)→ 平台面 getOcctKernel(D3)。\n // BrepHandle(branded number)与 occt-wasm ShapeHandle 运行时同构,品牌转换\n // 只发生在平台边界。\n evo = getOcctKernel().chamferWithHistory(\n solid as unknown as ShapeHandle,\n edgeHandles as unknown as ShapeHandle[],\n radius,\n inputHashes,\n HASH_UPPER_BOUND,\n ) as unknown as BrepEvolutionData\n }\n\n const faceEvolution = decodeEvolution(kernel, evo, solid, evo.result)\n const hashEvo = decodeHashEvolution(evo)\n const propagated = propagateAllOriginsLocal(inputRoleTable, hashEvo)\n\n // 3.4: generated face naming — transition faces are neither input faces nor\n // modified outputs (§4.4 \"三类命运\": 原样幸存 / 改型幸存 / 新造).\n // Role format: `gen:<op>:<i>` (i = enumeration order among generated faces).\n // String formatted directly (no import of role-name.ts — avoids circular dep).\n const resultHashes = getFaceHashes(kernel, evo.result)\n const inputHashSet = new Set(inputHashes)\n const modifiedOutputHashes = new Set<number>()\n for (const outs of hashEvo.modified.values()) {\n for (const h of outs) modifiedOutputHashes.add(h)\n }\n const generatedHashes = resultHashes.filter(\n (h) => !inputHashSet.has(h) && !modifiedOutputHashes.has(h),\n )\n\n if (generatedHashes.length > 0) {\n const genRoles = new Map<string, number[]>()\n for (let i = 0; i < generatedHashes.length; i++) {\n genRoles.set(`gen:${op}:${i}`, [generatedHashes[i]!])\n }\n const roleTable = new Map(propagated)\n roleTable.set(outPart, genRoles)\n return { result: evo.result, faceEvolution, roleTable }\n }\n\n return { result: evo.result, faceEvolution, roleTable: propagated }\n}\n\n/**\n * 单输入 directEdit 的便捷别名:fillet。\n *\n * @param kernel - the OCCT kernel.\n * @param solid - the input solid.\n * @param edgeHandles - the resolved Edge handles.\n * @param radius - the fillet radius (uniform).\n * @param inputRoleTable - the input's role table.\n * @param outPart - the statement's LHS variable name.\n * @returns the result handle, ordinal evolution and propagated role table.\n */\nexport function filletWithRoleTable(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n edgeHandles: BrepHandle[],\n radius: number,\n inputRoleTable: ReadonlyMap<unknown, unknown>,\n outPart: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n return directEditWithRoleTable(kernel, 'fillet', solid, edgeHandles, radius, inputRoleTable, outPart)\n}\n\n/**\n * 单输入 directEdit 的便捷别名:chamfer。\n *\n * @param kernel - the OCCT kernel.\n * @param solid - the input solid.\n * @param edgeHandles - the resolved Edge handles.\n * @param distance - the chamfer distance (uniform).\n * @param inputRoleTable - the input's role table.\n * @param outPart - the statement's LHS variable name.\n * @returns the result handle, ordinal evolution and propagated role table.\n */\nexport function chamferWithRoleTable(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n edgeHandles: BrepHandle[],\n distance: number,\n inputRoleTable: ReadonlyMap<unknown, unknown>,\n outPart: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n return directEditWithRoleTable(kernel, 'chamfer', solid, edgeHandles, distance, inputRoleTable, outPart)\n}\n\n/**\n * 钻孔 roleTable 传播:底孔(圆柱 cut)产生的新造面 = 孔壁,挂**消费它的那条语句**\n * 的 origin(§7.1:drill 的工具体是 op 内部临时件,无其他用户可见坐标可继承)。\n * 角色形态 `hole:<j>`(j = 新造面枚举序)。沿用 `directEditWithRoleTable` 的\n * 三类命运判定(原样幸存 / 改型幸存 / 新造),新造面才派生命名。\n *\n * @param kernel - the OCCT kernel.\n * @param solid - the input solid (the drilled part).\n * @param toolSolid - the drill-bit tool solid (caller-built; released by caller).\n * @param inputRoleTable - the input's role table.\n * @param outStmt - the drilling statement's StmtId (origin for new faces).\n * @returns the result handle, ordinal evolution and role table with `hole:<j>`.\n */\nexport function drillBrepWithRoleTable(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n toolSolid: BrepHandle,\n inputRoleTable: ReadonlyMap<unknown, unknown>,\n outStmt: string,\n): { result: BrepHandle; faceEvolution: FaceEvolution; roleTable: ReadonlyMap<unknown, unknown> } {\n const inputHashes = getFaceHashes(kernel, solid)\n const evo = kernel.cutWithHistory(solid, toolSolid, inputHashes, HASH_UPPER_BOUND)\n const faceEvolution = decodeEvolution(kernel, evo, solid, evo.result)\n const hashEvo = decodeHashEvolution(evo)\n const propagated = propagateAllOriginsLocal(inputRoleTable, hashEvo)\n\n // 三类命运判定:新造面 = 结果 − 输入 − 改型后继(§4.4)。\n const resultHashes = getFaceHashes(kernel, evo.result)\n const inputHashSet = new Set(inputHashes)\n const modifiedOutputHashes = new Set<number>()\n for (const outs of hashEvo.modified.values()) {\n for (const h of outs) modifiedOutputHashes.add(h)\n }\n const generatedHashes = resultHashes.filter(\n (h) => !inputHashSet.has(h) && !modifiedOutputHashes.has(h),\n )\n\n const roleTable = new Map(propagated)\n if (generatedHashes.length > 0) {\n const genRoles = new Map<string, number[]>()\n for (let i = 0; i < generatedHashes.length; i++) {\n genRoles.set(`hole:${i}`, [generatedHashes[i]!])\n }\n roleTable.set(outStmt, genRoles)\n }\n return { result: evo.result, faceEvolution, roleTable }\n}\n\n/** 单输入 roleTable 传播(结构等价于 naming/roles.propagateAllOrigins,避免循环依赖)。 */\nfunction propagateAllOriginsLocal(\n roles: ReadonlyMap<unknown, unknown>,\n evolution: HashEvolution,\n): ReadonlyMap<unknown, unknown> {\n const result = new Map<unknown, unknown>()\n for (const [origin, originRoles] of roles) {\n result.set(origin, propagateOriginRoles(originRoles as ReadonlyMap<string, readonly number[]>, evolution))\n }\n return result\n}\n"]}
@@ -12,12 +12,30 @@
12
12
  */
13
13
  import type { Shape } from '../mesh/types.js';
14
14
  import { fromBrep } from '../shape.js';
15
+ import type { BrepEngineApi } from './engine/primitives.js';
15
16
  /**
16
- * Get the OCCT kernel instance faijs is currently using.
17
- * @returns the current OCCT kernel.
17
+ * Get the currently injected BREP kernel instance (untyped escape hatch).
18
+ * @deprecated D12: this exit predates the engine-neutral L1 surface and its name
19
+ * ("OCCT kernel") no longer matches what it returns — the current engine's raw
20
+ * kernel, whatever engine that is. Prefer `getBrepApi()` (typed, engine-neutral,
21
+ * same file) for neutral ops; platform-only code (L2 face) should use
22
+ * `getOcctKernel()` (D3). Kept for vendored-face bridging and existing tests.
23
+ * @returns the current BREP engine's kernel instance.
18
24
  * @throws when the kernel is not ready (mesh mode or uninitialized) — never silently returns null.
19
25
  */
20
26
  export declare function getKernel(): unknown;
27
+ /**
28
+ * Get the current BREP engine as the **L1 core surface** (`BrepEngineApi`).
29
+ *
30
+ * 2026-09-24 narrowing plan(D12):中立 op 的取内核唯一出口——取代
31
+ * `getBackends().kernel.brep as BrepEngineApi` 的逐点断言。本文件是 L1 契约
32
+ * 的注册点(`registerBrepEngine` 注入的就是 `BrepEngineApi` 实例),此处断言
33
+ * 诚实;平台面(L1 之外的 occt 独有能力)仍走 `getOcctKernel()`(D3)。
34
+ *
35
+ * @returns the current engine's L1 contract surface (`BrepEngineApi`) — typed, engine-neutral.
36
+ * @throws when no BREP engine is registered (uninitialized) — never silently returns null.
37
+ */
38
+ export declare function getBrepApi(): BrepEngineApi;
21
39
  /**
22
40
  * Options controlling how a handle is tessellated.
23
41
  */
@@ -1 +1 @@
1
- {"version":3,"file":"handle-bridge.d.ts","sourceRoot":"","sources":["../../src/brep/handle-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAUnC;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAMnC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAEhD;AAyBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAW3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAGjG"}
1
+ {"version":3,"file":"handle-bridge.d.ts","sourceRoot":"","sources":["../../src/brep/handle-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAUxD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAMnC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAQ1C;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAEhD;AAyBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAW3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAGjG"}
@@ -13,8 +13,13 @@
13
13
  import { getBackends } from '../runtime-state.js';
14
14
  import { fromBrep } from '../shape.js';
15
15
  /**
16
- * Get the OCCT kernel instance faijs is currently using.
17
- * @returns the current OCCT kernel.
16
+ * Get the currently injected BREP kernel instance (untyped escape hatch).
17
+ * @deprecated D12: this exit predates the engine-neutral L1 surface and its name
18
+ * ("OCCT kernel") no longer matches what it returns — the current engine's raw
19
+ * kernel, whatever engine that is. Prefer `getBrepApi()` (typed, engine-neutral,
20
+ * same file) for neutral ops; platform-only code (L2 face) should use
21
+ * `getOcctKernel()` (D3). Kept for vendored-face bridging and existing tests.
22
+ * @returns the current BREP engine's kernel instance.
18
23
  * @throws when the kernel is not ready (mesh mode or uninitialized) — never silently returns null.
19
24
  */
20
25
  export function getKernel() {
@@ -24,6 +29,24 @@ export function getKernel() {
24
29
  }
25
30
  return kernel;
26
31
  }
32
+ /**
33
+ * Get the current BREP engine as the **L1 core surface** (`BrepEngineApi`).
34
+ *
35
+ * 2026-09-24 narrowing plan(D12):中立 op 的取内核唯一出口——取代
36
+ * `getBackends().kernel.brep as BrepEngineApi` 的逐点断言。本文件是 L1 契约
37
+ * 的注册点(`registerBrepEngine` 注入的就是 `BrepEngineApi` 实例),此处断言
38
+ * 诚实;平台面(L1 之外的 occt 独有能力)仍走 `getOcctKernel()`(D3)。
39
+ *
40
+ * @returns the current engine's L1 contract surface (`BrepEngineApi`) — typed, engine-neutral.
41
+ * @throws when no BREP engine is registered (uninitialized) — never silently returns null.
42
+ */
43
+ export function getBrepApi() {
44
+ const kernel = getBackends().kernel.brep;
45
+ if (!kernel) {
46
+ throw new Error('[faijs/bridge] BREP engine API not available: BREP operations require an initialized engine');
47
+ }
48
+ return kernel;
49
+ }
27
50
  /**
28
51
  * OCC 句柄身份契约判别(单一真源)。
29
52
  *
@@ -1 +1 @@
1
- {"version":3,"file":"handle-bridge.js","sourceRoot":"","sources":["../../src/brep/handle-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAUnC;;;;GAIG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAA;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAA;IAC5G,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAYD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,CAAU;IACrC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAK,CAA8B,CAAC,UAAU,KAAK,IAAI,CAAA;AACnG,CAAC;AAED;0CAC0C;AAC1C,SAAS,YAAY,CAAC,CAAU;IAC9B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,YAAY,CAAC,CAAC,CAAC,CAAA;AACjD,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,MAAe,EAAE,MAAc;IACpD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,yDAAyD;YAC/E,kCAAkC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,IAAI;YAC9E,wDAAwD,CAC3D,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAe,EAAE,IAAwB;IAClE,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACnC,MAAM,MAAM,GAAG,SAAS,EAAoB,CAAA;IAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;QACpC,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,IAAI,GAAG;QAC/C,iBAAiB,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;KACrE,CAAC,CAAA;IACF,OAAO;QACL,SAAS,EAAE,IAAI,YAAY,CAAC,IAAI,CAAC,SAA8B,CAAC;QAChE,OAAO,EAAE,IAAI,WAAW,CAAC,IAAI,CAAC,OAA4B,CAAC;KAC5D,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,MAAe,EAAE,IAAwB;IAClE,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACnC,OAAO,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;AAC9D,CAAC","sourcesContent":["/**\n * handle-bridge — OCCT 句柄 → faijs Shape 的 SDK 桥接(B1)\n *\n *\n * 第三方库要造 BREP 产物,需要\"OCCT handle → mesh\"。`src/brep/brep-ops.ts:17`\n * 有 `import * as THREE from 'three'`,SDK 绝不能 import 它(会把 three 拉进\n * SDK bundle,违反 `src/sdk.test.ts` 的零 heavy 依赖守卫)。本文件在**新建的\n * 零依赖模块**中实现,直接调运行时注入的 `kernel.meshShape`。\n *\n * 依赖约束(硬性):只允许 import `runtime-state`、`stdlib/shape`、type-only\n * `mesh/types`——任何新增依赖必须保持 dist/sdk.js 零 heavy 依赖守卫通过。\n */\n\nimport type { Shape } from '../mesh/types'\nimport { getBackends } from '../runtime-state'\nimport { fromBrep } from '../shape'\n\n/** 结构化内核接口(不 import occt-wasm,只做结构匹配,避免 heavy 依赖) */\ninterface MeshableKernel {\n meshShape(\n handle: unknown,\n opts: { linearDeflection: number; angularDeflection: number },\n ): { positions: ArrayLike<number>; indices: ArrayLike<number> }\n}\n\n/**\n * Get the OCCT kernel instance faijs is currently using.\n * @returns the current OCCT kernel.\n * @throws when the kernel is not ready (mesh mode or uninitialized) — never silently returns null.\n */\nexport function getKernel(): unknown {\n const kernel = getBackends().kernel.brep\n if (!kernel) {\n throw new Error('[faijs/bridge] OCCT kernel not available: BREP operations require an initialized kernel')\n }\n return kernel\n}\n\n/**\n * Options controlling how a handle is tessellated.\n */\nexport interface MeshHandleOptions {\n /** linear deflection (mm), default 0.1 — matches the built-in ops (src/brep/brep-ops.ts:27). */\n linearDeflection?: number\n /** angular segment count, default 32 — angularDeflection = 2π / segments. */\n segments?: number\n}\n\n/**\n * OCC 句柄身份契约判别(单一真源)。\n *\n * occt-wasm 的 `handle()` 工厂(vendored occtWasm helpers.ts:25)构造的句柄对象\n * 统一携带 `__occtWasm: true`。本叶子是 faijs 侧唯一允许的判据:\n * define-op 的 `wrapBrepOne` 用它区分\"几何句柄\"与\"纯数据记录\",本文件\n * `fromHandle`/`meshHandle` 入口用它做形态断言。禁止在其他文件硬编码\n * `'__occtWasm' in v` 字符串直查——句柄/数据判定的任何新消费点都必须引用本叶子。\n * @param v - 待判别的值。\n * @returns `true` 当且仅当 `v` 是携带 `__occtWasm: true` 标记的句柄对象。\n */\nexport function isOcctHandle(v: unknown): boolean {\n return typeof v === 'object' && v !== null && (v as { __occtWasm?: unknown }).__occtWasm === true\n}\n\n/** 合法句柄输入:branded numeric id(occt-wasm 的 `ShapeHandle` 运行时形态)或\n * `__occtWasm` 标记对象(`handle()` 工厂产物)。 */\nfunction isHandleLike(v: unknown): boolean {\n return typeof v === 'number' || isOcctHandle(v)\n}\n\n/**\n * 入口形态断言:拒绝把纯数据记录当句柄三角化。\n * 纯数据记录(无 `__occtWasm` 标记的 plain object,如 sheetmetal part 数据)\n * 必须在 SDK 边界被显式拒绝(E_BAD_HANDLE),而不是在 kernel 深处以\n * `OcctError: meshShape: Invalid shape ID 0` 崩溃——define-op 的 wrapBrepOne\n * 已在第一道透传过滤,本断言是第二道防线(防未来未带标记的新句柄形态漏网)。\n */\nfunction requireHandle(handle: unknown, caller: string): void {\n if (!isHandleLike(handle)) {\n throw new Error(\n `[faijs/bridge] ${caller}: E_BAD_HANDLE: expected an OCCT handle (numeric id or ` +\n `__occtWasm-tagged object); got ${handle === null ? 'null' : typeof handle}. ` +\n `Plain data records must not be tessellated as handles.`,\n )\n }\n}\n\n/**\n * Tessellate an OCCT handle into a Shape (without registering a BREP slot).\n * @param handle - the OCCT solid handle to tessellate (numeric id or `__occtWasm`-tagged object).\n * @param opts - optional tessellation options.\n * @returns the tessellated Shape.\n */\nexport function meshHandle(handle: unknown, opts?: MeshHandleOptions): Shape {\n requireHandle(handle, 'meshHandle')\n const kernel = getKernel() as MeshableKernel\n const mesh = kernel.meshShape(handle, {\n linearDeflection: opts?.linearDeflection ?? 0.1,\n angularDeflection: (2 * Math.PI) / Math.max(3, opts?.segments ?? 32),\n })\n return {\n positions: new Float32Array(mesh.positions as ArrayLike<number>),\n indices: new Uint32Array(mesh.indices as ArrayLike<number>),\n }\n}\n\n/**\n * Default path (recommended): tessellate + register the BREP slot in one step.\n * Equivalent to meshHandle(h) + fromBrep(sh, { solid: h }).\n * Library authors only fall back to the meshHandle + fromBrep combination when\n * they need custom tessellation precision.\n * @param handle - the OCCT solid handle to bridge (numeric id or `__occtWasm`-tagged object).\n * @param opts - optional tessellation options.\n * @returns the registered Shape, as returned by fromBrep.\n */\nexport function fromHandle(handle: unknown, opts?: MeshHandleOptions): ReturnType<typeof fromBrep> {\n requireHandle(handle, 'fromHandle')\n return fromBrep(meshHandle(handle, opts), { solid: handle })\n}\n"]}
1
+ {"version":3,"file":"handle-bridge.js","sourceRoot":"","sources":["../../src/brep/handle-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAWnC;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAA;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAA;IAC5G,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAA;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAA;IACH,CAAC;IACD,OAAO,MAAuB,CAAA;AAChC,CAAC;AAYD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,CAAU;IACrC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAK,CAA8B,CAAC,UAAU,KAAK,IAAI,CAAA;AACnG,CAAC;AAED;0CAC0C;AAC1C,SAAS,YAAY,CAAC,CAAU;IAC9B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,YAAY,CAAC,CAAC,CAAC,CAAA;AACjD,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,MAAe,EAAE,MAAc;IACpD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,yDAAyD;YAC/E,kCAAkC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,IAAI;YAC9E,wDAAwD,CAC3D,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAe,EAAE,IAAwB;IAClE,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACnC,MAAM,MAAM,GAAG,SAAS,EAAoB,CAAA;IAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;QACpC,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,IAAI,GAAG;QAC/C,iBAAiB,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;KACrE,CAAC,CAAA;IACF,OAAO;QACL,SAAS,EAAE,IAAI,YAAY,CAAC,IAAI,CAAC,SAA8B,CAAC;QAChE,OAAO,EAAE,IAAI,WAAW,CAAC,IAAI,CAAC,OAA4B,CAAC;KAC5D,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,MAAe,EAAE,IAAwB;IAClE,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACnC,OAAO,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;AAC9D,CAAC","sourcesContent":["/**\n * handle-bridge — OCCT 句柄 → faijs Shape 的 SDK 桥接(B1)\n *\n *\n * 第三方库要造 BREP 产物,需要\"OCCT handle → mesh\"。`src/brep/brep-ops.ts:17`\n * 有 `import * as THREE from 'three'`,SDK 绝不能 import 它(会把 three 拉进\n * SDK bundle,违反 `src/sdk.test.ts` 的零 heavy 依赖守卫)。本文件在**新建的\n * 零依赖模块**中实现,直接调运行时注入的 `kernel.meshShape`。\n *\n * 依赖约束(硬性):只允许 import `runtime-state`、`stdlib/shape`、type-only\n * `mesh/types`——任何新增依赖必须保持 dist/sdk.js 零 heavy 依赖守卫通过。\n */\n\nimport type { Shape } from '../mesh/types'\nimport { getBackends } from '../runtime-state'\nimport { fromBrep } from '../shape'\nimport type { BrepEngineApi } from './engine/primitives'\n\n/** 结构化内核接口(不 import occt-wasm,只做结构匹配,避免 heavy 依赖) */\ninterface MeshableKernel {\n meshShape(\n handle: unknown,\n opts: { linearDeflection: number; angularDeflection: number },\n ): { positions: ArrayLike<number>; indices: ArrayLike<number> }\n}\n\n/**\n * Get the currently injected BREP kernel instance (untyped escape hatch).\n * @deprecated D12: this exit predates the engine-neutral L1 surface and its name\n * (\"OCCT kernel\") no longer matches what it returns — the current engine's raw\n * kernel, whatever engine that is. Prefer `getBrepApi()` (typed, engine-neutral,\n * same file) for neutral ops; platform-only code (L2 face) should use\n * `getOcctKernel()` (D3). Kept for vendored-face bridging and existing tests.\n * @returns the current BREP engine's kernel instance.\n * @throws when the kernel is not ready (mesh mode or uninitialized) — never silently returns null.\n */\nexport function getKernel(): unknown {\n const kernel = getBackends().kernel.brep\n if (!kernel) {\n throw new Error('[faijs/bridge] OCCT kernel not available: BREP operations require an initialized kernel')\n }\n return kernel\n}\n\n/**\n * Get the current BREP engine as the **L1 core surface** (`BrepEngineApi`).\n *\n * 2026-09-24 narrowing plan(D12):中立 op 的取内核唯一出口——取代\n * `getBackends().kernel.brep as BrepEngineApi` 的逐点断言。本文件是 L1 契约\n * 的注册点(`registerBrepEngine` 注入的就是 `BrepEngineApi` 实例),此处断言\n * 诚实;平台面(L1 之外的 occt 独有能力)仍走 `getOcctKernel()`(D3)。\n *\n * @returns the current engine's L1 contract surface (`BrepEngineApi`) — typed, engine-neutral.\n * @throws when no BREP engine is registered (uninitialized) — never silently returns null.\n */\nexport function getBrepApi(): BrepEngineApi {\n const kernel = getBackends().kernel.brep\n if (!kernel) {\n throw new Error(\n '[faijs/bridge] BREP engine API not available: BREP operations require an initialized engine',\n )\n }\n return kernel as BrepEngineApi\n}\n\n/**\n * Options controlling how a handle is tessellated.\n */\nexport interface MeshHandleOptions {\n /** linear deflection (mm), default 0.1 — matches the built-in ops (src/brep/brep-ops.ts:27). */\n linearDeflection?: number\n /** angular segment count, default 32 — angularDeflection = 2π / segments. */\n segments?: number\n}\n\n/**\n * OCC 句柄身份契约判别(单一真源)。\n *\n * occt-wasm 的 `handle()` 工厂(vendored occtWasm helpers.ts:25)构造的句柄对象\n * 统一携带 `__occtWasm: true`。本叶子是 faijs 侧唯一允许的判据:\n * define-op 的 `wrapBrepOne` 用它区分\"几何句柄\"与\"纯数据记录\",本文件\n * `fromHandle`/`meshHandle` 入口用它做形态断言。禁止在其他文件硬编码\n * `'__occtWasm' in v` 字符串直查——句柄/数据判定的任何新消费点都必须引用本叶子。\n * @param v - 待判别的值。\n * @returns `true` 当且仅当 `v` 是携带 `__occtWasm: true` 标记的句柄对象。\n */\nexport function isOcctHandle(v: unknown): boolean {\n return typeof v === 'object' && v !== null && (v as { __occtWasm?: unknown }).__occtWasm === true\n}\n\n/** 合法句柄输入:branded numeric id(occt-wasm 的 `ShapeHandle` 运行时形态)或\n * `__occtWasm` 标记对象(`handle()` 工厂产物)。 */\nfunction isHandleLike(v: unknown): boolean {\n return typeof v === 'number' || isOcctHandle(v)\n}\n\n/**\n * 入口形态断言:拒绝把纯数据记录当句柄三角化。\n * 纯数据记录(无 `__occtWasm` 标记的 plain object,如 sheetmetal part 数据)\n * 必须在 SDK 边界被显式拒绝(E_BAD_HANDLE),而不是在 kernel 深处以\n * `OcctError: meshShape: Invalid shape ID 0` 崩溃——define-op 的 wrapBrepOne\n * 已在第一道透传过滤,本断言是第二道防线(防未来未带标记的新句柄形态漏网)。\n */\nfunction requireHandle(handle: unknown, caller: string): void {\n if (!isHandleLike(handle)) {\n throw new Error(\n `[faijs/bridge] ${caller}: E_BAD_HANDLE: expected an OCCT handle (numeric id or ` +\n `__occtWasm-tagged object); got ${handle === null ? 'null' : typeof handle}. ` +\n `Plain data records must not be tessellated as handles.`,\n )\n }\n}\n\n/**\n * Tessellate an OCCT handle into a Shape (without registering a BREP slot).\n * @param handle - the OCCT solid handle to tessellate (numeric id or `__occtWasm`-tagged object).\n * @param opts - optional tessellation options.\n * @returns the tessellated Shape.\n */\nexport function meshHandle(handle: unknown, opts?: MeshHandleOptions): Shape {\n requireHandle(handle, 'meshHandle')\n const kernel = getKernel() as MeshableKernel\n const mesh = kernel.meshShape(handle, {\n linearDeflection: opts?.linearDeflection ?? 0.1,\n angularDeflection: (2 * Math.PI) / Math.max(3, opts?.segments ?? 32),\n })\n return {\n positions: new Float32Array(mesh.positions as ArrayLike<number>),\n indices: new Uint32Array(mesh.indices as ArrayLike<number>),\n }\n}\n\n/**\n * Default path (recommended): tessellate + register the BREP slot in one step.\n * Equivalent to meshHandle(h) + fromBrep(sh, { solid: h }).\n * Library authors only fall back to the meshHandle + fromBrep combination when\n * they need custom tessellation precision.\n * @param handle - the OCCT solid handle to bridge (numeric id or `__occtWasm`-tagged object).\n * @param opts - optional tessellation options.\n * @returns the registered Shape, as returned by fromBrep.\n */\nexport function fromHandle(handle: unknown, opts?: MeshHandleOptions): ReturnType<typeof fromBrep> {\n requireHandle(handle, 'fromHandle')\n return fromBrep(meshHandle(handle, opts), { solid: handle })\n}\n"]}