@faicad/faijs 0.19.0 → 0.29.3

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 (510) hide show
  1. package/LICENSE +202 -28
  2. package/dist/api/api-namespace.d.ts +5 -5
  3. package/dist/api/api-namespace.d.ts.map +1 -1
  4. package/dist/api/api-namespace.js +4 -4
  5. package/dist/api/api-namespace.js.map +1 -1
  6. package/dist/api/assert.d.ts +2 -2
  7. package/dist/api/assert.js +8 -8
  8. package/dist/api/assert.js.map +1 -1
  9. package/dist/api/asset.d.ts +1 -1
  10. package/dist/api/asset.js +2 -2
  11. package/dist/api/asset.js.map +1 -1
  12. package/dist/api/boolean.d.ts +1 -1
  13. package/dist/api/boolean.d.ts.map +1 -1
  14. package/dist/api/boolean.js +128 -16
  15. package/dist/api/boolean.js.map +1 -1
  16. package/dist/api/brep-mirror/joinery-brep.d.ts.map +1 -1
  17. package/dist/api/brep-mirror/joinery-brep.js +3 -1
  18. package/dist/api/brep-mirror/joinery-brep.js.map +1 -1
  19. package/dist/api/cadquery-selectors/borrow-bridge.d.ts +14 -0
  20. package/dist/api/cadquery-selectors/borrow-bridge.d.ts.map +1 -0
  21. package/dist/api/cadquery-selectors/borrow-bridge.js +52 -0
  22. package/dist/api/cadquery-selectors/borrow-bridge.js.map +1 -0
  23. package/dist/api/cadquery-selectors/edge.d.ts +40 -0
  24. package/dist/api/cadquery-selectors/edge.d.ts.map +1 -0
  25. package/dist/api/cadquery-selectors/edge.js +70 -0
  26. package/dist/api/cadquery-selectors/edge.js.map +1 -0
  27. package/dist/api/cadquery-selectors/entity.d.ts +121 -0
  28. package/dist/api/cadquery-selectors/entity.d.ts.map +1 -0
  29. package/dist/api/cadquery-selectors/entity.js +167 -0
  30. package/dist/api/cadquery-selectors/entity.js.map +1 -0
  31. package/dist/api/cadquery-selectors/face.d.ts +33 -0
  32. package/dist/api/cadquery-selectors/face.d.ts.map +1 -0
  33. package/dist/api/cadquery-selectors/face.js +353 -0
  34. package/dist/api/cadquery-selectors/face.js.map +1 -0
  35. package/dist/api/cadquery-selectors/grammar.d.ts +50 -0
  36. package/dist/api/cadquery-selectors/grammar.d.ts.map +1 -0
  37. package/dist/api/cadquery-selectors/grammar.js +345 -0
  38. package/dist/api/cadquery-selectors/grammar.js.map +1 -0
  39. package/dist/api/cadquery-selectors/index.d.ts +18 -0
  40. package/dist/api/cadquery-selectors/index.d.ts.map +1 -0
  41. package/dist/api/cadquery-selectors/index.js +17 -0
  42. package/dist/api/cadquery-selectors/index.js.map +1 -0
  43. package/dist/api/cadquery-selectors/predicates.d.ts +76 -0
  44. package/dist/api/cadquery-selectors/predicates.d.ts.map +1 -0
  45. package/dist/api/cadquery-selectors/predicates.js +85 -0
  46. package/dist/api/cadquery-selectors/predicates.js.map +1 -0
  47. package/dist/api/cadquery-selectors/resolve.d.ts +41 -0
  48. package/dist/api/cadquery-selectors/resolve.d.ts.map +1 -0
  49. package/dist/api/cadquery-selectors/resolve.js +243 -0
  50. package/dist/api/cadquery-selectors/resolve.js.map +1 -0
  51. package/dist/api/cadquery-selectors/types.d.ts +96 -0
  52. package/dist/api/cadquery-selectors/types.d.ts.map +1 -0
  53. package/dist/api/cadquery-selectors/types.js +11 -0
  54. package/dist/api/cadquery-selectors/types.js.map +1 -0
  55. package/dist/api/chamfer.d.ts +13 -5
  56. package/dist/api/chamfer.d.ts.map +1 -1
  57. package/dist/api/chamfer.js +63 -7
  58. package/dist/api/chamfer.js.map +1 -1
  59. package/dist/api/compound-geom.d.ts +1 -1
  60. package/dist/api/compound-geom.js +1 -1
  61. package/dist/api/compound-geom.js.map +1 -1
  62. package/dist/api/draft.d.ts +1 -1
  63. package/dist/api/draft.js +1 -1
  64. package/dist/api/draft.js.map +1 -1
  65. package/dist/api/edge-ref.d.ts +1 -1
  66. package/dist/api/edge-ref.d.ts.map +1 -1
  67. package/dist/api/edge-ref.js +11 -3
  68. package/dist/api/edge-ref.js.map +1 -1
  69. package/dist/api/engrave.d.ts +1 -1
  70. package/dist/api/engrave.js +7 -7
  71. package/dist/api/engrave.js.map +1 -1
  72. package/dist/api/extrude.d.ts +6 -1
  73. package/dist/api/extrude.d.ts.map +1 -1
  74. package/dist/api/extrude.js +59 -5
  75. package/dist/api/extrude.js.map +1 -1
  76. package/dist/api/face-ref.d.ts +1 -1
  77. package/dist/api/face-ref.js +1 -1
  78. package/dist/api/face-ref.js.map +1 -1
  79. package/dist/api/feature-repair.d.ts +1 -1
  80. package/dist/api/feature-repair.js +1 -1
  81. package/dist/api/feature-repair.js.map +1 -1
  82. package/dist/api/fillet-variable.d.ts +1 -1
  83. package/dist/api/fillet-variable.js +1 -1
  84. package/dist/api/fillet-variable.js.map +1 -1
  85. package/dist/api/fillet.d.ts +28 -8
  86. package/dist/api/fillet.d.ts.map +1 -1
  87. package/dist/api/fillet.js +64 -9
  88. package/dist/api/fillet.js.map +1 -1
  89. package/dist/api/generated/script-face-manifest.d.ts +4 -0
  90. package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
  91. package/dist/api/generated/script-face-manifest.js.map +1 -1
  92. package/dist/api/geom.d.ts +1 -1
  93. package/dist/api/geom.js +1 -1
  94. package/dist/api/geom.js.map +1 -1
  95. package/dist/api/helix.d.ts +1 -1
  96. package/dist/api/helix.js +1 -1
  97. package/dist/api/helix.js.map +1 -1
  98. package/dist/api/import-brep.d.ts +20 -2
  99. package/dist/api/import-brep.d.ts.map +1 -1
  100. package/dist/api/import-brep.js +28 -3
  101. package/dist/api/import-brep.js.map +1 -1
  102. package/dist/api/import-step.d.ts +17 -2
  103. package/dist/api/import-step.d.ts.map +1 -1
  104. package/dist/api/import-step.js +23 -3
  105. package/dist/api/import-step.js.map +1 -1
  106. package/dist/api/index.d.ts +2 -1
  107. package/dist/api/index.d.ts.map +1 -1
  108. package/dist/api/index.js +5 -2
  109. package/dist/api/index.js.map +1 -1
  110. package/dist/api/internal/compat-op.js +1 -1
  111. package/dist/api/internal/compat-op.js.map +1 -1
  112. package/dist/api/internal/mesh-solid-op.d.ts +236 -0
  113. package/dist/api/internal/mesh-solid-op.d.ts.map +1 -0
  114. package/dist/api/internal/mesh-solid-op.js +352 -0
  115. package/dist/api/internal/mesh-solid-op.js.map +1 -0
  116. package/dist/api/internal/svg-asset-resolver.d.ts +1 -1
  117. package/dist/api/internal/svg-asset-resolver.js +1 -1
  118. package/dist/api/internal/svg-asset-resolver.js.map +1 -1
  119. package/dist/api/knurl.d.ts +1 -1
  120. package/dist/api/knurl.d.ts.map +1 -1
  121. package/dist/api/knurl.js +3 -2
  122. package/dist/api/knurl.js.map +1 -1
  123. package/dist/api/loft.d.ts +1 -1
  124. package/dist/api/loft.js +1 -1
  125. package/dist/api/loft.js.map +1 -1
  126. package/dist/api/measurement/index.d.ts +9 -5
  127. package/dist/api/measurement/index.d.ts.map +1 -1
  128. package/dist/api/measurement/index.js +47 -20
  129. package/dist/api/measurement/index.js.map +1 -1
  130. package/dist/api/pattern.d.ts +5 -3
  131. package/dist/api/pattern.d.ts.map +1 -1
  132. package/dist/api/pattern.js +32 -4
  133. package/dist/api/pattern.js.map +1 -1
  134. package/dist/api/place.d.ts +1 -1
  135. package/dist/api/place.js +1 -1
  136. package/dist/api/place.js.map +1 -1
  137. package/dist/api/primitives.d.ts +5 -4
  138. package/dist/api/primitives.d.ts.map +1 -1
  139. package/dist/api/primitives.js +11 -5
  140. package/dist/api/primitives.js.map +1 -1
  141. package/dist/api/profile.d.ts +64 -8
  142. package/dist/api/profile.d.ts.map +1 -1
  143. package/dist/api/profile.js +61 -10
  144. package/dist/api/profile.js.map +1 -1
  145. package/dist/api/punch-hole.d.ts +3 -0
  146. package/dist/api/punch-hole.d.ts.map +1 -1
  147. package/dist/api/punch-hole.js.map +1 -1
  148. package/dist/api/reconcile.d.ts +1 -1
  149. package/dist/api/reconcile.js +1 -1
  150. package/dist/api/reconcile.js.map +1 -1
  151. package/dist/api/replicate.d.ts.map +1 -1
  152. package/dist/api/replicate.js +122 -1
  153. package/dist/api/replicate.js.map +1 -1
  154. package/dist/api/screw.d.ts +1 -1
  155. package/dist/api/screw.js +3 -3
  156. package/dist/api/screw.js.map +1 -1
  157. package/dist/api/sdf.d.ts +1 -1
  158. package/dist/api/sdf.js +2 -2
  159. package/dist/api/sdf.js.map +1 -1
  160. package/dist/api/section-by-plane.d.ts +1 -1
  161. package/dist/api/section-by-plane.d.ts.map +1 -1
  162. package/dist/api/section-by-plane.js +2 -1
  163. package/dist/api/section-by-plane.js.map +1 -1
  164. package/dist/api/shell.d.ts +11 -4
  165. package/dist/api/shell.d.ts.map +1 -1
  166. package/dist/api/shell.js +53 -7
  167. package/dist/api/shell.js.map +1 -1
  168. package/dist/api/sketch-on-face.d.ts +41 -0
  169. package/dist/api/sketch-on-face.d.ts.map +1 -1
  170. package/dist/api/sketch-on-face.js +100 -1
  171. package/dist/api/sketch-on-face.js.map +1 -1
  172. package/dist/api/sketch-on-plane.d.ts +17 -9
  173. package/dist/api/sketch-on-plane.d.ts.map +1 -1
  174. package/dist/api/sketch-on-plane.js +12 -10
  175. package/dist/api/sketch-on-plane.js.map +1 -1
  176. package/dist/api/split-by-plane.d.ts +1 -1
  177. package/dist/api/split-by-plane.d.ts.map +1 -1
  178. package/dist/api/split-by-plane.js +2 -1
  179. package/dist/api/split-by-plane.js.map +1 -1
  180. package/dist/api/split.d.ts +1 -1
  181. package/dist/api/split.js +2 -2
  182. package/dist/api/split.js.map +1 -1
  183. package/dist/api/surface/arg-spec.d.ts +8 -0
  184. package/dist/api/surface/arg-spec.d.ts.map +1 -1
  185. package/dist/api/surface/arg-spec.js.map +1 -1
  186. package/dist/api/sweep.d.ts +1 -1
  187. package/dist/api/sweep.js +1 -1
  188. package/dist/api/sweep.js.map +1 -1
  189. package/dist/api/thicken.d.ts +1 -1
  190. package/dist/api/thicken.js +1 -1
  191. package/dist/api/thicken.js.map +1 -1
  192. package/dist/api/topo-resolve.d.ts +74 -1
  193. package/dist/api/topo-resolve.d.ts.map +1 -1
  194. package/dist/api/topo-resolve.js +180 -2
  195. package/dist/api/topo-resolve.js.map +1 -1
  196. package/dist/api/transform.d.ts +10 -6
  197. package/dist/api/transform.d.ts.map +1 -1
  198. package/dist/api/transform.js +74 -21
  199. package/dist/api/transform.js.map +1 -1
  200. package/dist/api/wire.d.ts +1 -1
  201. package/dist/api/wire.js +1 -1
  202. package/dist/api/wire.js.map +1 -1
  203. package/dist/api/xml-dom.d.ts +27 -0
  204. package/dist/api/xml-dom.d.ts.map +1 -0
  205. package/dist/api/xml-dom.js +45 -0
  206. package/dist/api/xml-dom.js.map +1 -0
  207. package/dist/brep/brep-ops.d.ts +13 -11
  208. package/dist/brep/brep-ops.d.ts.map +1 -1
  209. package/dist/brep/brep-ops.js +31 -30
  210. package/dist/brep/brep-ops.js.map +1 -1
  211. package/dist/brep/brep-topology.d.ts +5 -4
  212. package/dist/brep/brep-topology.d.ts.map +1 -1
  213. package/dist/brep/brep-topology.js +9 -6
  214. package/dist/brep/brep-topology.js.map +1 -1
  215. package/dist/brep/effective-deflection.d.ts +35 -0
  216. package/dist/brep/effective-deflection.d.ts.map +1 -0
  217. package/dist/brep/effective-deflection.js +49 -0
  218. package/dist/brep/effective-deflection.js.map +1 -0
  219. package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
  220. package/dist/brep/engine/adapters/brep-mock.js +27 -0
  221. package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
  222. package/dist/brep/engine/adapters/brepkit.d.ts +18 -0
  223. package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
  224. package/dist/brep/engine/adapters/brepkit.js +46 -1
  225. package/dist/brep/engine/adapters/brepkit.js.map +1 -1
  226. package/dist/brep/engine/adapters/occt.d.ts +1 -1
  227. package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
  228. package/dist/brep/engine/adapters/occt.js +3 -1
  229. package/dist/brep/engine/adapters/occt.js.map +1 -1
  230. package/dist/brep/engine/primitives.d.ts +29 -7
  231. package/dist/brep/engine/primitives.d.ts.map +1 -1
  232. package/dist/brep/engine/primitives.js.map +1 -1
  233. package/dist/brep/engine/registry.d.ts +24 -1
  234. package/dist/brep/engine/registry.d.ts.map +1 -1
  235. package/dist/brep/engine/registry.js +24 -0
  236. package/dist/brep/engine/registry.js.map +1 -1
  237. package/dist/brep/engine/types.d.ts +54 -3
  238. package/dist/brep/engine/types.d.ts.map +1 -1
  239. package/dist/brep/engine/types.js +10 -0
  240. package/dist/brep/engine/types.js.map +1 -1
  241. package/dist/brep/export/export-model.d.ts +79 -0
  242. package/dist/brep/export/export-model.d.ts.map +1 -0
  243. package/dist/brep/export/export-model.js +336 -0
  244. package/dist/brep/export/export-model.js.map +1 -0
  245. package/dist/brep/face-evolution.d.ts +1 -1
  246. package/dist/brep/face-evolution.d.ts.map +1 -1
  247. package/dist/brep/face-evolution.js +20 -1
  248. package/dist/brep/face-evolution.js.map +1 -1
  249. package/dist/brep/handle-bridge.d.ts +1 -1
  250. package/dist/brep/handle-bridge.js +1 -1
  251. package/dist/brep/handle-bridge.js.map +1 -1
  252. package/dist/brep/mesh-solid.d.ts +218 -0
  253. package/dist/brep/mesh-solid.d.ts.map +1 -0
  254. package/dist/brep/mesh-solid.js +229 -0
  255. package/dist/brep/mesh-solid.js.map +1 -0
  256. package/dist/brep/primitives-brep.d.ts.map +1 -1
  257. package/dist/brep/primitives-brep.js +3 -1
  258. package/dist/brep/primitives-brep.js.map +1 -1
  259. package/dist/brep/text/fontRegistry.d.ts +32 -1
  260. package/dist/brep/text/fontRegistry.d.ts.map +1 -1
  261. package/dist/brep/text/fontRegistry.js +51 -1
  262. package/dist/brep/text/fontRegistry.js.map +1 -1
  263. package/dist/brep/text/text-to-solid.d.ts.map +1 -1
  264. package/dist/brep/text/text-to-solid.js +8 -3
  265. package/dist/brep/text/text-to-solid.js.map +1 -1
  266. package/dist/brepkit-kernel/brepkitKernel.d.ts +18 -2
  267. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  268. package/dist/brepkit-kernel/brepkitKernel.js +453 -125
  269. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  270. package/dist/brepkit-kernel/brepkitWasm.d.ts +8 -0
  271. package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
  272. package/dist/brepkit-kernel/brepkitWasm.js +10 -0
  273. package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
  274. package/dist/browser-host/browser-font-provider.d.ts +12 -0
  275. package/dist/browser-host/browser-font-provider.d.ts.map +1 -1
  276. package/dist/browser-host/browser-font-provider.js +25 -0
  277. package/dist/browser-host/browser-font-provider.js.map +1 -1
  278. package/dist/browser.d.ts +6 -3
  279. package/dist/browser.d.ts.map +1 -1
  280. package/dist/browser.js +10 -3
  281. package/dist/browser.js.map +1 -1
  282. package/dist/cad-runtime/backend-dispatch.d.ts +28 -3
  283. package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
  284. package/dist/cad-runtime/backend-dispatch.js +119 -4
  285. package/dist/cad-runtime/backend-dispatch.js.map +1 -1
  286. package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
  287. package/dist/cad-runtime/direct-executor.d.ts +19 -3
  288. package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
  289. package/dist/cad-runtime/direct-executor.js +49 -1
  290. package/dist/cad-runtime/direct-executor.js.map +1 -1
  291. package/dist/cad-runtime/ports.d.ts +3 -3
  292. package/dist/cad-runtime/ports.d.ts.map +1 -1
  293. package/dist/cad-runtime/ports.js.map +1 -1
  294. package/dist/cad-runtime/preview-exec.d.ts +4 -4
  295. package/dist/cad-runtime/preview-exec.js +2 -2
  296. package/dist/cad-runtime/preview-exec.js.map +1 -1
  297. package/dist/cad-runtime/runtime.d.ts +66 -8
  298. package/dist/cad-runtime/runtime.d.ts.map +1 -1
  299. package/dist/cad-runtime/runtime.js +121 -8
  300. package/dist/cad-runtime/runtime.js.map +1 -1
  301. package/dist/define-op.d.ts +37 -1
  302. package/dist/define-op.d.ts.map +1 -1
  303. package/dist/define-op.js +25 -1
  304. package/dist/define-op.js.map +1 -1
  305. package/dist/env-agnostic.d.ts +7 -7
  306. package/dist/env-agnostic.d.ts.map +1 -1
  307. package/dist/env-agnostic.js +3 -3
  308. package/dist/env-agnostic.js.map +1 -1
  309. package/dist/geometry2d/adapt.d.ts +39 -4
  310. package/dist/geometry2d/adapt.d.ts.map +1 -1
  311. package/dist/geometry2d/adapt.js +14 -3
  312. package/dist/geometry2d/adapt.js.map +1 -1
  313. package/dist/geometry2d/blueprint.d.ts +2 -2
  314. package/dist/geometry2d/blueprint.js +2 -2
  315. package/dist/geometry2d/blueprint.js.map +1 -1
  316. package/dist/geometry2d/bridge/lift-on-plane.d.ts +18 -8
  317. package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -1
  318. package/dist/geometry2d/bridge/lift-on-plane.js +71 -12
  319. package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -1
  320. package/dist/geometry2d/bridge/plane.d.ts +17 -0
  321. package/dist/geometry2d/bridge/plane.d.ts.map +1 -1
  322. package/dist/geometry2d/bridge/plane.js +22 -0
  323. package/dist/geometry2d/bridge/plane.js.map +1 -1
  324. package/dist/geometry2d/curve2d.d.ts +25 -0
  325. package/dist/geometry2d/curve2d.d.ts.map +1 -1
  326. package/dist/geometry2d/curve2d.js +41 -5
  327. package/dist/geometry2d/curve2d.js.map +1 -1
  328. package/dist/geometry2d/pen-sketcher.d.ts +25 -0
  329. package/dist/geometry2d/pen-sketcher.d.ts.map +1 -1
  330. package/dist/geometry2d/pen-sketcher.js +43 -0
  331. package/dist/geometry2d/pen-sketcher.js.map +1 -1
  332. package/dist/index.d.ts +6 -2
  333. package/dist/index.d.ts.map +1 -1
  334. package/dist/index.js +10 -3
  335. package/dist/index.js.map +1 -1
  336. package/dist/io/bytes-node.d.ts +11 -0
  337. package/dist/io/bytes-node.d.ts.map +1 -0
  338. package/dist/io/bytes-node.js +28 -0
  339. package/dist/io/bytes-node.js.map +1 -0
  340. package/dist/io/bytes.d.ts +33 -0
  341. package/dist/io/bytes.d.ts.map +1 -0
  342. package/dist/io/bytes.js +41 -0
  343. package/dist/io/bytes.js.map +1 -0
  344. package/dist/io/fai-zip/container-read.d.ts +102 -0
  345. package/dist/io/fai-zip/container-read.d.ts.map +1 -0
  346. package/dist/io/fai-zip/container-read.js +305 -0
  347. package/dist/io/fai-zip/container-read.js.map +1 -0
  348. package/dist/io/fai-zip/container-write.d.ts +70 -0
  349. package/dist/io/fai-zip/container-write.d.ts.map +1 -0
  350. package/dist/io/fai-zip/container-write.js +186 -0
  351. package/dist/io/fai-zip/container-write.js.map +1 -0
  352. package/dist/io/fai-zip/container.d.ts +107 -0
  353. package/dist/io/fai-zip/container.d.ts.map +1 -0
  354. package/dist/io/fai-zip/container.js +89 -0
  355. package/dist/io/fai-zip/container.js.map +1 -0
  356. package/dist/io/fai-zip/index.d.ts +18 -0
  357. package/dist/io/fai-zip/index.d.ts.map +1 -0
  358. package/dist/io/fai-zip/index.js +4 -0
  359. package/dist/io/fai-zip/index.js.map +1 -0
  360. package/dist/io/index.d.ts +10 -0
  361. package/dist/io/index.d.ts.map +1 -0
  362. package/dist/io/index.js +13 -0
  363. package/dist/io/index.js.map +1 -0
  364. package/dist/io/zip.d.ts +68 -0
  365. package/dist/io/zip.d.ts.map +1 -0
  366. package/dist/io/zip.js +147 -0
  367. package/dist/io/zip.js.map +1 -0
  368. package/dist/lang/code-to-args.d.ts +30 -4
  369. package/dist/lang/code-to-args.d.ts.map +1 -1
  370. package/dist/lang/code-to-args.js +42 -3
  371. package/dist/lang/code-to-args.js.map +1 -1
  372. package/dist/lang/codegen.d.ts +45 -1
  373. package/dist/lang/codegen.d.ts.map +1 -1
  374. package/dist/lang/codegen.js +135 -6
  375. package/dist/lang/codegen.js.map +1 -1
  376. package/dist/lang/host-arg.d.ts +6 -0
  377. package/dist/lang/host-arg.d.ts.map +1 -1
  378. package/dist/lang/host-arg.js.map +1 -1
  379. package/dist/lang/metadata-extractor.d.ts +25 -0
  380. package/dist/lang/metadata-extractor.d.ts.map +1 -1
  381. package/dist/lang/metadata-extractor.js +289 -25
  382. package/dist/lang/metadata-extractor.js.map +1 -1
  383. package/dist/lang/parse-error.d.ts +7 -1
  384. package/dist/lang/parse-error.d.ts.map +1 -1
  385. package/dist/lang/parse-error.js.map +1 -1
  386. package/dist/lang/security-scanner.d.ts +9 -1
  387. package/dist/lang/security-scanner.d.ts.map +1 -1
  388. package/dist/lang/security-scanner.js +38 -1
  389. package/dist/lang/security-scanner.js.map +1 -1
  390. package/dist/lang/statement-summary.d.ts +1 -1
  391. package/dist/lang/statement-summary.js +1 -1
  392. package/dist/lang/statement-summary.js.map +1 -1
  393. package/dist/lang/types.d.ts +1 -1
  394. package/dist/lang/types.js +1 -1
  395. package/dist/lang/types.js.map +1 -1
  396. package/dist/mesh/index.d.ts +2 -1
  397. package/dist/mesh/index.d.ts.map +1 -1
  398. package/dist/mesh/index.js +2 -1
  399. package/dist/mesh/index.js.map +1 -1
  400. package/dist/mesh/io.d.ts +69 -9
  401. package/dist/mesh/io.d.ts.map +1 -1
  402. package/dist/mesh/io.js +121 -17
  403. package/dist/mesh/io.js.map +1 -1
  404. package/dist/mesh/reconcile.d.ts +1 -1
  405. package/dist/mesh/reconcile.js +1 -1
  406. package/dist/mesh/reconcile.js.map +1 -1
  407. package/dist/mesh/rigid-transform.d.ts +3 -3
  408. package/dist/mesh/rigid-transform.js +3 -3
  409. package/dist/mesh/rigid-transform.js.map +1 -1
  410. package/dist/mesh/stl-unit.d.ts +24 -0
  411. package/dist/mesh/stl-unit.d.ts.map +1 -0
  412. package/dist/mesh/stl-unit.js +17 -0
  413. package/dist/mesh/stl-unit.js.map +1 -0
  414. package/dist/mesh/threemf-bambu.d.ts +142 -0
  415. package/dist/mesh/threemf-bambu.d.ts.map +1 -0
  416. package/dist/mesh/threemf-bambu.js +334 -0
  417. package/dist/mesh/threemf-bambu.js.map +1 -0
  418. package/dist/mesh/threemf-loader.d.ts +50 -0
  419. package/dist/mesh/threemf-loader.d.ts.map +1 -0
  420. package/dist/mesh/threemf-loader.js +628 -0
  421. package/dist/mesh/threemf-loader.js.map +1 -0
  422. package/dist/mesh/threemf-view.d.ts +71 -0
  423. package/dist/mesh/threemf-view.d.ts.map +1 -0
  424. package/dist/mesh/threemf-view.js +100 -0
  425. package/dist/mesh/threemf-view.js.map +1 -0
  426. package/dist/mesh/transform.d.ts +2 -2
  427. package/dist/mesh/transform.d.ts.map +1 -1
  428. package/dist/mesh/transform.js +3 -3
  429. package/dist/mesh/transform.js.map +1 -1
  430. package/dist/mesh/types.d.ts +1 -1
  431. package/dist/mesh/types.d.ts.map +1 -1
  432. package/dist/mesh/types.js.map +1 -1
  433. package/dist/node-host/cli.d.ts +44 -6
  434. package/dist/node-host/cli.d.ts.map +1 -1
  435. package/dist/node-host/cli.js +127 -50
  436. package/dist/node-host/cli.js.map +1 -1
  437. package/dist/node-host/font-family-index.d.ts +93 -0
  438. package/dist/node-host/font-family-index.d.ts.map +1 -0
  439. package/dist/node-host/font-family-index.js +273 -0
  440. package/dist/node-host/font-family-index.js.map +1 -0
  441. package/dist/node-host/fs-asset-resolver.d.ts +8 -3
  442. package/dist/node-host/fs-asset-resolver.d.ts.map +1 -1
  443. package/dist/node-host/fs-asset-resolver.js +13 -5
  444. package/dist/node-host/fs-asset-resolver.js.map +1 -1
  445. package/dist/node-host/index.d.ts +8 -0
  446. package/dist/node-host/index.d.ts.map +1 -1
  447. package/dist/node-host/index.js +1 -0
  448. package/dist/node-host/index.js.map +1 -1
  449. package/dist/node-host/node-font-provider.d.ts +28 -0
  450. package/dist/node-host/node-font-provider.d.ts.map +1 -1
  451. package/dist/node-host/node-font-provider.js +49 -0
  452. package/dist/node-host/node-font-provider.js.map +1 -1
  453. package/dist/node.d.ts +1 -0
  454. package/dist/node.d.ts.map +1 -1
  455. package/dist/node.js +1 -0
  456. package/dist/node.js.map +1 -1
  457. package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
  458. package/dist/occt-kernel/occt-primitives.js +35 -2
  459. package/dist/occt-kernel/occt-primitives.js.map +1 -1
  460. package/dist/occt-kernel/occtKernel.d.ts +18 -13
  461. package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
  462. package/dist/occt-kernel/occtKernel.js +20 -31
  463. package/dist/occt-kernel/occtKernel.js.map +1 -1
  464. package/dist/occt-kernel/stepColorParser.d.ts +18 -0
  465. package/dist/occt-kernel/stepColorParser.d.ts.map +1 -1
  466. package/dist/occt-kernel/stepColorParser.js +38 -0
  467. package/dist/occt-kernel/stepColorParser.js.map +1 -1
  468. package/dist/occt-kernel/topologyExt.d.ts +1 -1
  469. package/dist/occt-kernel/topologyExt.d.ts.map +1 -1
  470. package/dist/occt-kernel/topologyExt.js +8 -6
  471. package/dist/occt-kernel/topologyExt.js.map +1 -1
  472. package/dist/primitives/text/cjk-font.d.ts +2 -15
  473. package/dist/primitives/text/cjk-font.d.ts.map +1 -1
  474. package/dist/primitives/text/cjk-font.js +13 -1
  475. package/dist/primitives/text/cjk-font.js.map +1 -1
  476. package/dist/runtime-state.d.ts +103 -9
  477. package/dist/runtime-state.d.ts.map +1 -1
  478. package/dist/runtime-state.js +95 -2
  479. package/dist/runtime-state.js.map +1 -1
  480. package/dist/sdk.d.ts +4 -4
  481. package/dist/sdk.d.ts.map +1 -1
  482. package/dist/sdk.js +6 -6
  483. package/dist/sdk.js.map +1 -1
  484. package/dist/shape.d.ts +97 -2
  485. package/dist/shape.d.ts.map +1 -1
  486. package/dist/shape.js +126 -1
  487. package/dist/shape.js.map +1 -1
  488. package/dist/tolerance.d.ts +38 -0
  489. package/dist/tolerance.d.ts.map +1 -0
  490. package/dist/tolerance.js +40 -0
  491. package/dist/tolerance.js.map +1 -0
  492. package/dist/topology/naming/lineage.d.ts +6 -0
  493. package/dist/topology/naming/lineage.d.ts.map +1 -1
  494. package/dist/topology/naming/lineage.js +8 -0
  495. package/dist/topology/naming/lineage.js.map +1 -1
  496. package/dist/topology/naming/resolve-edge.d.ts +20 -1
  497. package/dist/topology/naming/resolve-edge.d.ts.map +1 -1
  498. package/dist/topology/naming/resolve-edge.js +54 -20
  499. package/dist/topology/naming/resolve-edge.js.map +1 -1
  500. package/dist/topology/naming/score.js +3 -3
  501. package/dist/topology/naming/score.js.map +1 -1
  502. package/dist/units.d.ts +248 -0
  503. package/dist/units.d.ts.map +1 -0
  504. package/dist/units.js +397 -0
  505. package/dist/units.js.map +1 -0
  506. package/dist/weapp.d.ts +6 -2
  507. package/dist/weapp.d.ts.map +1 -1
  508. package/dist/weapp.js +7 -1
  509. package/dist/weapp.js.map +1 -1
  510. package/package.json +28 -3
@@ -1,5 +1,5 @@
1
1
  /**
2
- * stdlib profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。
2
+ * api profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。
3
3
  *
4
4
  * 用途:faijs 此前没有「从 2D 轮廓构造 planar face」的能力,导致草图轮廓无法喂给
5
5
  * extrude/revolve。本 op 接收 2D 轮廓(线段 + 圆弧),在 z=0 平面用 OCCT 构面:
@@ -15,6 +15,7 @@
15
15
  * 在轮廓坐标里预先变换,或由下游特征的 Placement 承担。
16
16
  */
17
17
  import type { Shape } from '../mesh/types.js';
18
+ import { Blueprint } from '../geometry2d/blueprint.js';
18
19
  /** 直线段(2D,z=0;端点为绝对坐标)。 */
19
20
  export interface ProfileLineSeg {
20
21
  kind: 'line';
@@ -39,15 +40,59 @@ export interface ProfileArcSeg {
39
40
  x2: number;
40
41
  y2: number;
41
42
  }
42
- /** 一条有序 2D 轮廓段(直线或圆弧)。 */
43
- export type ProfileSeg = ProfileLineSeg | ProfileArcSeg;
43
+ /**
44
+ * 参数曲线段(NURBS 控制数据;`kind:'spline'` 同时承载 Bézier 与 B 样条 ——
45
+ * Bézier 就是一条两端重节点钳制的 B 样条,两者同一份数据形态)。
46
+ *
47
+ * 存在的意义:源几何真是一条参数曲线时(Draft 文字轮廓的 Bézier、投影出的
48
+ * B 样条),本段让它以曲线身份进到 wire,而不是先被采样成折线。
49
+ * `first`/`last` 是该边在**基曲线参数轴**上的裁剪区间;省略即整条曲线。
50
+ */
51
+ export interface ProfileSplineSeg {
52
+ kind: 'spline';
53
+ /** 多项式次数 */
54
+ degree: number;
55
+ /** 扁平控制点 `[x, y, x, y, …]` */
56
+ poles: number[];
57
+ /** 去重后的节点值(与 `multiplicities` 平行) */
58
+ knots: number[];
59
+ /** 各节点的重数 */
60
+ multiplicities: number[];
61
+ /** 周期(闭合回绕)曲线 */
62
+ periodic?: boolean;
63
+ /** 每个控制点的权;非有理曲线省略 */
64
+ weights?: number[];
65
+ /** 裁剪起点(基曲线参数轴) */
66
+ first?: number;
67
+ /** 裁剪终点(基曲线参数轴) */
68
+ last?: number;
69
+ }
70
+ /** 一条有序 2D 轮廓段(直线、圆弧或参数曲线)。 */
71
+ export type ProfileSeg = ProfileLineSeg | ProfileArcSeg | ProfileSplineSeg;
44
72
  /** 单个轮廓环:有序段序列(首尾相接)。 */
45
73
  export interface ProfileLoop {
46
74
  segments: ProfileSeg[];
47
75
  }
76
+ /**
77
+ * A 2D contour that is already DRAWN — a pure-data `Blueprint`, or an array of
78
+ * them (one per contour).
79
+ *
80
+ * Why the 2D entries accept this: a drawn contour carries no OCCT handle, and
81
+ * without this path NO op can turn it into a Shape. Measured 2026-09-28 —
82
+ * feeding a drawn `Blueprint` straight to `cad.extrude` fails with
83
+ * `E_BREP_INPUT: argument carries no BREP handle`, and to `cad.sweep` with
84
+ * `INVALID_SHAPE_ID`. The "draw → `sketchOnPlane` → `extrude`" pipeline
85
+ * therefore needs this bridge; `cad.profile` takes it too, because both entries
86
+ * share {@link toContourBlueprints} and a split acceptance rule would be a trap.
87
+ */
88
+ export type DrawnContours = Blueprint | Blueprint[];
48
89
  /** `cad.profile` 参数:轮廓环集合。语义见 {@link buildProfileShape}(嵌套=孔,不相交=独立岛)。 */
49
90
  export interface ProfileParams {
50
- contours: ProfileLoop[];
91
+ /**
92
+ * 轮廓来源,两种等价形态:段环数据(`{segments: […]}`)或已绘制轮廓
93
+ * (`Blueprint` / 其数组)。
94
+ */
95
+ contours: ProfileLoop[] | DrawnContours;
51
96
  /**
52
97
  * 产物形态:'face'(默认)构面;'wire' 只交出不带面的最大岛外环 wire(1D 曲线),
53
98
  * 供扫掠族(sweep/loft/…)直接作 spine。'wire' 形态丢弃孔环(扫掠脊柱为单闭合轮廓)。
@@ -55,8 +100,19 @@ export interface ProfileParams {
55
100
  as?: 'face' | 'wire';
56
101
  }
57
102
  /**
58
- * Validate profile parameters: `contours` must be a non-empty array of loops,
59
- * each with at least one segment.
103
+ * Normalize a `contours` argument to `Blueprint[]`.
104
+ *
105
+ * Accepts the segment-loop data form, a single drawn contour, or an array of
106
+ * drawn contours. The two forms are never mixed — a mixed array is a caller bug
107
+ * and is rejected rather than half-interpreted.
108
+ *
109
+ * @param contours - the raw `contours` argument (`ProfileLoop[]` | `Blueprint` | `Blueprint[]`).
110
+ * @returns one `Blueprint` per contour, in input order.
111
+ */
112
+ export declare function toContourBlueprints(contours: unknown): Blueprint[];
113
+ /**
114
+ * Validate profile parameters: `contours` must be a non-empty contour set —
115
+ * either segment loops (each with at least one segment) or drawn contours.
60
116
  * @param params the raw profile operation parameters.
61
117
  */
62
118
  export declare function assertProfileParams(params: Record<string, unknown>): void;
@@ -69,7 +125,7 @@ export declare function assertProfileParams(params: Record<string, unknown>): vo
69
125
  * (7 面、volume 0)。多岛产物 = compound(每岛一面、各带自己的孔),下游
70
126
  * `cad.extrude` 对 compound 输入逐面挤出(kernel MakePrism 收复合形状)。
71
127
  *
72
- * @param params - 轮廓环集合与产物形态。
128
+ * @param params - 轮廓来源(段环数据或已绘制轮廓)与产物形态。
73
129
  * @returns Shape(单岛为 face;多岛为 face 的 compound;`as:'wire'` 为 1D 曲线)。
74
130
  */
75
131
  export declare function buildProfileShape(params: ProfileParams): Shape;
@@ -81,7 +137,7 @@ export declare function buildProfileShape(params: ProfileParams): Shape;
81
137
  * @qual ok
82
138
  * @name profile
83
139
  * @returns Shape 平面几何(mesh 三角化 + BREP 句柄);`as:'wire'` 时返回 1D 曲线(kind:'curve')。
84
- * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔)。type:ProfileLoop[] required:true
140
+ * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔),或已绘制轮廓(单个 Blueprint 或其数组)。type:ProfileLoop[]|Blueprint|Blueprint[] required:true
85
141
  * @param params.as - 产物形态:'face'(默认)构面;'wire' 只交外环 wire(1D 曲线)。type:'face'|'wire' required:false
86
142
  * @example
87
143
  * const f = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }] })
@@ -1 +1 @@
1
- {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/api/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAe1C,2BAA2B;AAC3B,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAED,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,KAAK,CAAA;IACX,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,cAAc;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,OAAO,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAED,0BAA0B;AAC1B,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,aAAa,CAAA;AAEvD,yBAAyB;AACzB,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,UAAU,EAAE,CAAA;CACvB;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CACrB;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAazE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,KAAK,CAmD9D;AA+ED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,OAAO;;CAOlB,CAAA"}
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/api/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAO1C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAQnD,2BAA2B;AAC3B,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAED,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,KAAK,CAAA;IACX,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,cAAc;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,OAAO,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAA;IACd,YAAY;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,8BAA8B;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,qCAAqC;IACrC,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,aAAa;IACb,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,iBAAiB;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,+BAA+B;AAC/B,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,aAAa,GAAG,gBAAgB,CAAA;AAE1E,yBAAyB;AACzB,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,UAAU,EAAE,CAAA;CACvB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,EAAE,CAAA;AAEnD,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,EAAE,WAAW,EAAE,GAAG,aAAa,CAAA;IACvC;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CACrB;AAeD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,EAAE,CAsBlE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CA2BzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,KAAK,CAiD9D;AA+ED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,OAAO;;CAOlB,CAAA"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * stdlib profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。
2
+ * api profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。
3
3
  *
4
4
  * 用途:faijs 此前没有「从 2D 轮廓构造 planar face」的能力,导致草图轮廓无法喂给
5
5
  * extrude/revolve。本 op 接收 2D 轮廓(线段 + 圆弧),在 z=0 平面用 OCCT 构面:
@@ -25,15 +25,67 @@ import { curveBounds, evaluateCurve2d } from '../geometry2d/curve2d.js';
25
25
  import { profileSegToCurve } from '../geometry2d/adapt.js';
26
26
  // ── 参数自校验 ──
27
27
  /**
28
- * Validate profile parameters: `contours` must be a non-empty array of loops,
29
- * each with at least one segment.
28
+ * True when a `contours` entry is an already-drawn contour rather than a
29
+ * `ProfileLoop` data record. Discriminated on `curves` vs `segments`, so a
30
+ * `ProfileLoop` can never be mistaken for one.
31
+ * @param v - the candidate value.
32
+ * @returns true when `v` is a `Blueprint`-shaped drawn contour.
33
+ */
34
+ function isDrawnContour(v) {
35
+ return !!v && typeof v === 'object' && !Array.isArray(v) && Array.isArray(v.curves);
36
+ }
37
+ /**
38
+ * Normalize a `contours` argument to `Blueprint[]`.
39
+ *
40
+ * Accepts the segment-loop data form, a single drawn contour, or an array of
41
+ * drawn contours. The two forms are never mixed — a mixed array is a caller bug
42
+ * and is rejected rather than half-interpreted.
43
+ *
44
+ * @param contours - the raw `contours` argument (`ProfileLoop[]` | `Blueprint` | `Blueprint[]`).
45
+ * @returns one `Blueprint` per contour, in input order.
46
+ */
47
+ export function toContourBlueprints(contours) {
48
+ if (isDrawnContour(contours))
49
+ return [contours];
50
+ if (!Array.isArray(contours)) {
51
+ throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour');
52
+ }
53
+ if (contours.length === 0) {
54
+ throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour');
55
+ }
56
+ if (isDrawnContour(contours[0])) {
57
+ for (const [i, c] of contours.entries()) {
58
+ if (!isDrawnContour(c)) {
59
+ throw new Error(`E_PROFILE_MIXED_CONTOURS: contour ${i} is a segment loop, not a drawn contour`);
60
+ }
61
+ }
62
+ return contours;
63
+ }
64
+ return contours.map((loop) => new Blueprint((loop?.segments ?? []).map((s) => profileSegToCurve(s))));
65
+ }
66
+ /**
67
+ * Validate profile parameters: `contours` must be a non-empty contour set —
68
+ * either segment loops (each with at least one segment) or drawn contours.
30
69
  * @param params the raw profile operation parameters.
31
70
  */
32
71
  export function assertProfileParams(params) {
33
72
  const contours = params.contours;
73
+ if (isDrawnContour(contours))
74
+ return;
34
75
  if (!Array.isArray(contours) || contours.length === 0) {
35
76
  throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour');
36
77
  }
78
+ // Discriminate the whole array at once so a mixed set names the real defect
79
+ // (E_PROFILE_MIXED_CONTOURS) instead of falling into the loop-shape branch and
80
+ // reporting a drawn contour as a malformed segment loop.
81
+ const drawn = contours.map((c) => isDrawnContour(c));
82
+ if (drawn.some(Boolean)) {
83
+ if (!drawn.every(Boolean)) {
84
+ const bad = drawn.indexOf(false);
85
+ throw new Error(`E_PROFILE_MIXED_CONTOURS: contour ${bad} is a segment loop while contour ${drawn.indexOf(true)} is a drawn contour — the two forms cannot be mixed`);
86
+ }
87
+ return;
88
+ }
37
89
  for (const loop of contours) {
38
90
  if (!loop || typeof loop !== 'object' || !Array.isArray(loop.segments)) {
39
91
  throw new Error('E_PROFILE_BAD_LOOP: each contour must have a segments array');
@@ -52,21 +104,20 @@ export function assertProfileParams(params) {
52
104
  * (7 面、volume 0)。多岛产物 = compound(每岛一面、各带自己的孔),下游
53
105
  * `cad.extrude` 对 compound 输入逐面挤出(kernel MakePrism 收复合形状)。
54
106
  *
55
- * @param params - 轮廓环集合与产物形态。
107
+ * @param params - 轮廓来源(段环数据或已绘制轮廓)与产物形态。
56
108
  * @returns Shape(单岛为 face;多岛为 face 的 compound;`as:'wire'` 为 1D 曲线)。
57
109
  */
58
110
  export function buildProfileShape(params) {
59
111
  const kernel = getBrepApi();
60
112
  const as = params.as ?? 'face';
61
- const loops = params.contours.map((loop) => ({
62
- loop,
63
- curves: loop.segments.map((s) => profileSegToCurve(s)),
64
- }));
65
113
  // F2(2026-09-27):环分类统一到纯 2D 管线 `organiseBlueprints`
66
114
  // (geometry2d/,brepjs 移植)。「嵌套=孔,不相交=独立岛」语义与既有
67
115
  // `profile-multi-island.test.ts` 断言一致;多岛 → 多个顶层,岛+孔 →
68
116
  // CompoundBlueprint([0]=外环,[1..]=孔)。
69
- const organised = organiseBlueprints(loops.map((l) => new Blueprint(l.curves)));
117
+ //
118
+ // 2026-09-28:段环数据与「已绘制轮廓」(`Blueprint`)在此归一 —— 两条
119
+ // 来源只差一次 `toContourBlueprints`,下游分类/构面完全共享。
120
+ const organised = organiseBlueprints(toContourBlueprints(params.contours));
70
121
  // 'wire' 形态:只挑面积最大的岛的外环 wire(1D 曲线),供扫掠族作 spine。
71
122
  if (as === 'wire') {
72
123
  let best = organised.blueprints[0];
@@ -190,7 +241,7 @@ function blueprintArea(entry) {
190
241
  * @qual ok
191
242
  * @name profile
192
243
  * @returns Shape 平面几何(mesh 三角化 + BREP 句柄);`as:'wire'` 时返回 1D 曲线(kind:'curve')。
193
- * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔)。type:ProfileLoop[] required:true
244
+ * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔),或已绘制轮廓(单个 Blueprint 或其数组)。type:ProfileLoop[]|Blueprint|Blueprint[] required:true
194
245
  * @param params.as - 产物形态:'face'(默认)构面;'wire' 只交外环 wire(1D 曲线)。type:'face'|'wire' required:false
195
246
  * @example
196
247
  * const f = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }] })
@@ -1 +1 @@
1
- {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/api/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,iBAAiB,EAAuB,MAAM,qBAAqB,CAAA;AAgD5E,cAAc;AAEd;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA+B;IACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAA;IAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAA;IACjF,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAE,IAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxF,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAA;QAChF,CAAC;QACD,IAAK,IAAoB,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAA;QACnF,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAqB;IACrD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,IAAI,MAAM,CAAA;IAE9B,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC3C,IAAI;QACJ,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAmB,CAAC,CAAC;KACzE,CAAC,CAAC,CAAA;IAEH,oDAAoD;IACpD,8CAA8C;IAC9C,sDAAsD;IACtD,qCAAqC;IACrC,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAE/E,iDAAiD;IACjD,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;QAClB,IAAI,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAE,CAAA;QACnC,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;YACzC,IAAI,aAAa,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC;gBAAE,IAAI,GAAG,KAAK,CAAA;QAC9D,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,YAAY,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QAC9E,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC7C,OAAO,aAAa,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,sBAAsB;IACtB,MAAM,KAAK,GAA4C,EAAE,CAAA;IACzD,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;QACzC,IAAI,KAAK,YAAY,iBAAiB,EAAE,CAAC;YACvC,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC,CAAA;YAC/D,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;YACvC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAA;YAC9E,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBAChD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;gBACpB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACnB,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,CAAA;QACnB,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;IACxD,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,KAAc,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;AACtE,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAC,MAAqB,EAAE,EAAa;IAC3D,MAAM,KAAK,GAAgD,EAAE,CAAA;IAC7D,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAmB,EAAuC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IAC/F,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;QAC1B,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;YACjB,KAAK,MAAM;gBACT,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBACrH,MAAK;YACP,KAAK,QAAQ;gBACX,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;gBACnD,MAAK;YACP,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,iCAAiC;gBACjC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;gBAClI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;gBAClJ,MAAK;YACP,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;oBAChC,sDAAsD;oBACtD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;oBACpH,MAAK;gBACP,CAAC;gBACD,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;gBACxB,MAAM,GAAG,GAA+C,EAAE,CAAA;gBAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7B,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAA;oBACjD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;gBACtC,CAAC;gBACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE;oBAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAE,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,CAAC,CAAA;gBAC9F,MAAK;YACP,CAAC;YACD,KAAK,SAAS,CAAC;YACf,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;gBACxB,MAAM,CAAC,GAAG,EAAE,CAAA;gBACZ,MAAM,GAAG,GAA+C,EAAE,CAAA;gBAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;oBAChD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;gBACtC,CAAC;gBACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE;oBAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAE,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,CAAC,CAAA;gBAC9F,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC/B,CAAC;AAED,8DAA8D;AAC9D,SAAS,aAAa,CAAC,KAAoC;IACzD,MAAM,EAAE,GAAG,KAAK,YAAY,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IAC5E,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACxB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;YACtE,SAAQ;QACV,CAAC;QACD,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;QACxB,MAAM,QAAQ,GAAG,EAAE,CAAA;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAA;YACxD,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAA;YAC9D,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YACvC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YACvC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC;IAC9B,YAAY,EAAE,CAAC,YAAY,CAAC;IAC5B,IAAI,CAAC,MAA+B;QAClC,mBAAmB,CAAC,MAAM,CAAC,CAAA;QAC3B,OAAO,iBAAiB,CAAC,MAAkC,CAAC,CAAA;IAC9D,CAAC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,EAAgB;CACtF,CAAC,CAAA","sourcesContent":["/**\n * stdlib profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。\n *\n * 用途:faijs 此前没有「从 2D 轮廓构造 planar face」的能力,导致草图轮廓无法喂给\n * extrude/revolve。本 op 接收 2D 轮廓(线段 + 圆弧),在 z=0 平面用 OCCT 构面:\n * makeLineEdge/makeArcEdge → makeWire → makeFace(+ addHolesInFace)。\n *\n * 设计:\n * - 输入:{ contours: ProfileLoop[] },每个 loop = 有序 segments(line / arc,z=0)。\n * - 环语义:嵌套 = 孔,不相交 = 独立岛(多岛 → face 的 compound),见 buildProfileShape。\n * - 圆弧:用起点/中点/终点三点的 makeArcEdge;整圆(sweep≈2π)拆成两段弧。\n * - 输出:Shape(mesh 三角化 + 句柄登记)。brep-only(下游 extrude/revolve 亦 brep-only)。\n *\n * 坐标系:输入 2D 点即 (x, y, 0),法向 +Z;草图在 Body 局部系内的定位由调用方(fcstd 端口)\n * 在轮廓坐标里预先变换,或由下游特征的 Placement 承担。\n */\n\nimport type { Shape } from '../mesh/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { solidToShape } from '../brep/brep-ops'\nimport { fromBrep, fromBrepCurve } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { Blueprint } from '../geometry2d/blueprint'\nimport { CompoundBlueprint } from '../geometry2d/compound-blueprint'\nimport { organiseBlueprints } from '../geometry2d/organise'\nimport { curveBounds, evaluateCurve2d } from '../geometry2d/curve2d'\nimport { profileSegToCurve, type ProfileSegLike } from '../geometry2d/adapt'\n\n// ── 参数形状(与 fcstd Contour 结构相同,避免引擎依赖端口层)──\n\n/** 直线段(2D,z=0;端点为绝对坐标)。 */\nexport interface ProfileLineSeg {\n kind: 'line'\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/** 圆弧段(圆心 + 半径 + 起止角,弧度;z=0)。 */\nexport interface ProfileArcSeg {\n kind: 'arc'\n cx: number\n cy: number\n radius: number\n /** 起始角(弧度) */\n startAngle: number\n /** 终止角(弧度) */\n endAngle: number\n ccw: boolean\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/** 一条有序 2D 轮廓段(直线或圆弧)。 */\nexport type ProfileSeg = ProfileLineSeg | ProfileArcSeg\n\n/** 单个轮廓环:有序段序列(首尾相接)。 */\nexport interface ProfileLoop {\n segments: ProfileSeg[]\n}\n\n/** `cad.profile` 参数:轮廓环集合。语义见 {@link buildProfileShape}(嵌套=孔,不相交=独立岛)。 */\nexport interface ProfileParams {\n contours: ProfileLoop[]\n /**\n * 产物形态:'face'(默认)构面;'wire' 只交出不带面的最大岛外环 wire(1D 曲线),\n * 供扫掠族(sweep/loft/…)直接作 spine。'wire' 形态丢弃孔环(扫掠脊柱为单闭合轮廓)。\n */\n as?: 'face' | 'wire'\n}\n\n// ── 参数自校验 ──\n\n/**\n * Validate profile parameters: `contours` must be a non-empty array of loops,\n * each with at least one segment.\n * @param params the raw profile operation parameters.\n */\nexport function assertProfileParams(params: Record<string, unknown>): void {\n const contours = params.contours\n if (!Array.isArray(contours) || contours.length === 0) {\n throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour')\n }\n for (const loop of contours) {\n if (!loop || typeof loop !== 'object' || !Array.isArray((loop as ProfileLoop).segments)) {\n throw new Error('E_PROFILE_BAD_LOOP: each contour must have a segments array')\n }\n if ((loop as ProfileLoop).segments.length === 0) {\n throw new Error('E_PROFILE_EMPTY_LOOP: a contour must have at least one segment')\n }\n }\n}\n\n/**\n * BREP 路径:2D 轮廓集合 → planar face 集合。\n *\n * GOTCHA(2026-09-26,Beds part16/39):环语义是「**嵌套 = 孔,不相交 = 独立岛**」\n * (与 FreeCAD 草图一致),不是「面积最大者当外环、其余全当孔」。旧实现把双岛轮廓的\n * 第二个岛判成「洞外面」→ `addHolesInFace` 收到与外环不相交的 wire → 构面退化\n * (7 面、volume 0)。多岛产物 = compound(每岛一面、各带自己的孔),下游\n * `cad.extrude` 对 compound 输入逐面挤出(kernel MakePrism 收复合形状)。\n *\n * @param params - 轮廓环集合与产物形态。\n * @returns Shape(单岛为 face;多岛为 face 的 compound;`as:'wire'` 为 1D 曲线)。\n */\nexport function buildProfileShape(params: ProfileParams): Shape {\n const kernel = getBrepApi()\n const as = params.as ?? 'face'\n\n const loops = params.contours.map((loop) => ({\n loop,\n curves: loop.segments.map((s) => profileSegToCurve(s as ProfileSegLike)),\n }))\n\n // F2(2026-09-27):环分类统一到纯 2D 管线 `organiseBlueprints`\n // (geometry2d/,brepjs 移植)。「嵌套=孔,不相交=独立岛」语义与既有\n // `profile-multi-island.test.ts` 断言一致;多岛 → 多个顶层,岛+孔 →\n // CompoundBlueprint([0]=外环,[1..]=孔)。\n const organised = organiseBlueprints(loops.map((l) => new Blueprint(l.curves)))\n\n // 'wire' 形态:只挑面积最大的岛的外环 wire(1D 曲线),供扫掠族作 spine。\n if (as === 'wire') {\n let best = organised.blueprints[0]!\n for (const entry of organised.blueprints) {\n if (blueprintArea(entry) > blueprintArea(best)) best = entry\n }\n const outerBp = best instanceof CompoundBlueprint ? best.blueprints[0]! : best\n const wire = blueprintToWire(kernel, outerBp)\n return fromBrepCurve(solidToShape(kernel, wire), { solid: wire })\n }\n\n // 每岛一面(岛的外环 + 直接子环为孔)\n const faces: ReturnType<BrepEngineApi['makeFace']>[] = []\n for (const entry of organised.blueprints) {\n if (entry instanceof CompoundBlueprint) {\n const outerWire = blueprintToWire(kernel, entry.blueprints[0]!)\n const face = kernel.makeFace(outerWire)\n const holes = entry.blueprints.slice(1).map((h) => blueprintToWire(kernel, h))\n if (holes.length > 0) {\n const faced = kernel.addHolesInFace(face, holes)\n kernel.release(face)\n faces.push(faced)\n } else {\n faces.push(face)\n }\n } else {\n faces.push(kernel.makeFace(blueprintToWire(kernel, entry)))\n }\n }\n\n if (faces.length === 1) {\n const f = faces[0]!\n return fromBrep(solidToShape(kernel, f), { solid: f })\n }\n const compound = kernel.makeCompound(faces as never)\n return fromBrep(solidToShape(kernel, compound), { solid: compound })\n}\n\n/**\n * Convert a pure-2D Blueprint to a 3D wire (z=0) for planar face construction.\n * @param kernel - the BREP engine handle-bridge.\n * @param bp - the blueprint whose ordered curves become wire edges.\n * @returns the wire handle.\n */\nfunction blueprintToWire(kernel: BrepEngineApi, bp: Blueprint): ReturnType<BrepEngineApi['makeWire']> {\n const edges: ReturnType<BrepEngineApi['makeLineEdge']>[] = []\n const pt3 = ([x, y]: [number, number]): { x: number; y: number; z: number } => ({ x, y, z: 0 })\n for (const c of bp.curves) {\n switch (c.kind2d) {\n case 'line':\n edges.push(kernel.makeLineEdge({ x: c.ox, y: c.oy, z: 0 }, { x: c.ox + c.dx * c.len, y: c.oy + c.dy * c.len, z: 0 }))\n break\n case 'bezier':\n edges.push(kernel.makeBezierEdge(c.poles.map(pt3)))\n break\n case 'circle': {\n // 完整圆:拆两段半圆 makeArcEdge(避免三点退化)。\n edges.push(kernel.makeArcEdge(pt3(evaluateCurve2d(c, 0)), pt3(evaluateCurve2d(c, Math.PI / 2)), pt3(evaluateCurve2d(c, Math.PI))))\n edges.push(kernel.makeArcEdge(pt3(evaluateCurve2d(c, Math.PI)), pt3(evaluateCurve2d(c, (3 * Math.PI) / 2)), pt3(evaluateCurve2d(c, 2 * Math.PI))))\n break\n }\n case 'trimmed': {\n if (c.basis.kind2d === 'circle') {\n // 圆弧:以 start/mid/end 三点构真实 makeArcEdge(保留光滑柱面,勿拆成折线段)\n edges.push(kernel.makeArcEdge(pt3(evaluateCurve2d(c, 0)), pt3(evaluateCurve2d(c, 0.5)), pt3(evaluateCurve2d(c, 1))))\n break\n }\n const b = curveBounds(c)\n const pts: Array<{ x: number; y: number; z: number }> = []\n for (let k = 0; k <= 32; k++) {\n const t = b.first + ((b.last - b.first) * k) / 32\n pts.push(pt3(evaluateCurve2d(c, t)))\n }\n for (let k = 0; k < pts.length - 1; k++) edges.push(kernel.makeLineEdge(pts[k]!, pts[k + 1]!))\n break\n }\n case 'ellipse':\n case 'bspline': {\n const b = curveBounds(c)\n const n = 32\n const pts: Array<{ x: number; y: number; z: number }> = []\n for (let k = 0; k <= n; k++) {\n const t = b.first + ((b.last - b.first) * k) / n\n pts.push(pt3(evaluateCurve2d(c, t)))\n }\n for (let k = 0; k < pts.length - 1; k++) edges.push(kernel.makeLineEdge(pts[k]!, pts[k + 1]!))\n break\n }\n }\n }\n return kernel.makeWire(edges)\n}\n\n/** 顶层 Blueprint/CompoundBlueprint 的近似有符号面积(用于 wire 最大岛选择)。 */\nfunction blueprintArea(entry: Blueprint | CompoundBlueprint): number {\n const bp = entry instanceof CompoundBlueprint ? entry.blueprints[0]! : entry\n let a = 0\n for (const c of bp.curves) {\n if (c.kind2d === 'line') {\n a += (c.ox * (c.oy + c.dy * c.len) - (c.ox + c.dx * c.len) * c.oy) / 2\n continue\n }\n const b = curveBounds(c)\n const nSamples = 32\n for (let k = 0; k < nSamples; k++) {\n const t0 = b.first + ((b.last - b.first) * k) / nSamples\n const t1 = b.first + ((b.last - b.first) * (k + 1)) / nSamples\n const [x0, y0] = evaluateCurve2d(c, t0)\n const [x1, y1] = evaluateCurve2d(c, t1)\n a += (x0 * y1 - x1 * y0) / 2\n }\n }\n return a\n}\n\n/**\n * 从 2D 轮廓构造平面(creator,无输入)。仅 BREP 可用。\n * @group 创建\n * @inputs 0\n * @async false\n * @qual ok\n * @name profile\n * @returns Shape 平面几何(mesh 三角化 + BREP 句柄);`as:'wire'` 时返回 1D 曲线(kind:'curve')。\n * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔)。type:ProfileLoop[] required:true\n * @param params.as - 产物形态:'face'(默认)构面;'wire' 只交外环 wire(1D 曲线)。type:'face'|'wire' required:false\n * @example\n * const f = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }] })\n * const w = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }], as: 'wire' })\n */\nexport const profile = defineOp({\n capabilities: ['directEdit'],\n brep(params: Record<string, unknown>) {\n assertProfileParams(params)\n return buildProfileShape(params as unknown as ProfileParams)\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } } as Provenance,\n})"]}
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/api/profile.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。\n *\n * 用途:faijs 此前没有「从 2D 轮廓构造 planar face」的能力,导致草图轮廓无法喂给\n * extrude/revolve。本 op 接收 2D 轮廓(线段 + 圆弧),在 z=0 平面用 OCCT 构面:\n * makeLineEdge/makeArcEdge → makeWire → makeFace(+ addHolesInFace)。\n *\n * 设计:\n * - 输入:{ contours: ProfileLoop[] },每个 loop = 有序 segments(line / arc,z=0)。\n * - 环语义:嵌套 = 孔,不相交 = 独立岛(多岛 → face 的 compound),见 buildProfileShape。\n * - 圆弧:用起点/中点/终点三点的 makeArcEdge;整圆(sweep≈2π)拆成两段弧。\n * - 输出:Shape(mesh 三角化 + 句柄登记)。brep-only(下游 extrude/revolve 亦 brep-only)。\n *\n * 坐标系:输入 2D 点即 (x, y, 0),法向 +Z;草图在 Body 局部系内的定位由调用方(fcstd 端口)\n * 在轮廓坐标里预先变换,或由下游特征的 Placement 承担。\n */\n\nimport type { Shape } from '../mesh/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { solidToShape } from '../brep/brep-ops'\nimport { fromBrep, fromBrepCurve } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { Blueprint } from '../geometry2d/blueprint'\nimport { CompoundBlueprint } from '../geometry2d/compound-blueprint'\nimport { organiseBlueprints } from '../geometry2d/organise'\nimport { curveBounds, evaluateCurve2d } from '../geometry2d/curve2d'\nimport { profileSegToCurve, type ProfileSegLike } from '../geometry2d/adapt'\n\n// ── 参数形状(与 fcstd Contour 结构相同,避免引擎依赖端口层)──\n\n/** 直线段(2D,z=0;端点为绝对坐标)。 */\nexport interface ProfileLineSeg {\n kind: 'line'\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/** 圆弧段(圆心 + 半径 + 起止角,弧度;z=0)。 */\nexport interface ProfileArcSeg {\n kind: 'arc'\n cx: number\n cy: number\n radius: number\n /** 起始角(弧度) */\n startAngle: number\n /** 终止角(弧度) */\n endAngle: number\n ccw: boolean\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/**\n * 参数曲线段(NURBS 控制数据;`kind:'spline'` 同时承载 Bézier 与 B 样条 ——\n * Bézier 就是一条两端重节点钳制的 B 样条,两者同一份数据形态)。\n *\n * 存在的意义:源几何真是一条参数曲线时(Draft 文字轮廓的 Bézier、投影出的\n * B 样条),本段让它以曲线身份进到 wire,而不是先被采样成折线。\n * `first`/`last` 是该边在**基曲线参数轴**上的裁剪区间;省略即整条曲线。\n */\nexport interface ProfileSplineSeg {\n kind: 'spline'\n /** 多项式次数 */\n degree: number\n /** 扁平控制点 `[x, y, x, y, …]` */\n poles: number[]\n /** 去重后的节点值(与 `multiplicities` 平行) */\n knots: number[]\n /** 各节点的重数 */\n multiplicities: number[]\n /** 周期(闭合回绕)曲线 */\n periodic?: boolean\n /** 每个控制点的权;非有理曲线省略 */\n weights?: number[]\n /** 裁剪起点(基曲线参数轴) */\n first?: number\n /** 裁剪终点(基曲线参数轴) */\n last?: number\n}\n\n/** 一条有序 2D 轮廓段(直线、圆弧或参数曲线)。 */\nexport type ProfileSeg = ProfileLineSeg | ProfileArcSeg | ProfileSplineSeg\n\n/** 单个轮廓环:有序段序列(首尾相接)。 */\nexport interface ProfileLoop {\n segments: ProfileSeg[]\n}\n\n/**\n * A 2D contour that is already DRAWN — a pure-data `Blueprint`, or an array of\n * them (one per contour).\n *\n * Why the 2D entries accept this: a drawn contour carries no OCCT handle, and\n * without this path NO op can turn it into a Shape. Measured 2026-09-28 —\n * feeding a drawn `Blueprint` straight to `cad.extrude` fails with\n * `E_BREP_INPUT: argument carries no BREP handle`, and to `cad.sweep` with\n * `INVALID_SHAPE_ID`. The \"draw → `sketchOnPlane` → `extrude`\" pipeline\n * therefore needs this bridge; `cad.profile` takes it too, because both entries\n * share {@link toContourBlueprints} and a split acceptance rule would be a trap.\n */\nexport type DrawnContours = Blueprint | Blueprint[]\n\n/** `cad.profile` 参数:轮廓环集合。语义见 {@link buildProfileShape}(嵌套=孔,不相交=独立岛)。 */\nexport interface ProfileParams {\n /**\n * 轮廓来源,两种等价形态:段环数据(`{segments: […]}`)或已绘制轮廓\n * (`Blueprint` / 其数组)。\n */\n contours: ProfileLoop[] | DrawnContours\n /**\n * 产物形态:'face'(默认)构面;'wire' 只交出不带面的最大岛外环 wire(1D 曲线),\n * 供扫掠族(sweep/loft/…)直接作 spine。'wire' 形态丢弃孔环(扫掠脊柱为单闭合轮廓)。\n */\n as?: 'face' | 'wire'\n}\n\n// ── 参数自校验 ──\n\n/**\n * True when a `contours` entry is an already-drawn contour rather than a\n * `ProfileLoop` data record. Discriminated on `curves` vs `segments`, so a\n * `ProfileLoop` can never be mistaken for one.\n * @param v - the candidate value.\n * @returns true when `v` is a `Blueprint`-shaped drawn contour.\n */\nfunction isDrawnContour(v: unknown): v is Blueprint {\n return !!v && typeof v === 'object' && !Array.isArray(v) && Array.isArray((v as Blueprint).curves)\n}\n\n/**\n * Normalize a `contours` argument to `Blueprint[]`.\n *\n * Accepts the segment-loop data form, a single drawn contour, or an array of\n * drawn contours. The two forms are never mixed — a mixed array is a caller bug\n * and is rejected rather than half-interpreted.\n *\n * @param contours - the raw `contours` argument (`ProfileLoop[]` | `Blueprint` | `Blueprint[]`).\n * @returns one `Blueprint` per contour, in input order.\n */\nexport function toContourBlueprints(contours: unknown): Blueprint[] {\n if (isDrawnContour(contours)) return [contours]\n if (!Array.isArray(contours)) {\n throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour')\n }\n if (contours.length === 0) {\n throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour')\n }\n if (isDrawnContour(contours[0])) {\n for (const [i, c] of contours.entries()) {\n if (!isDrawnContour(c)) {\n throw new Error(`E_PROFILE_MIXED_CONTOURS: contour ${i} is a segment loop, not a drawn contour`)\n }\n }\n return contours as Blueprint[]\n }\n return (contours as ProfileLoop[]).map(\n (loop) =>\n new Blueprint(\n (loop?.segments ?? []).map((s) => profileSegToCurve(s as ProfileSegLike)),\n ),\n )\n}\n\n/**\n * Validate profile parameters: `contours` must be a non-empty contour set —\n * either segment loops (each with at least one segment) or drawn contours.\n * @param params the raw profile operation parameters.\n */\nexport function assertProfileParams(params: Record<string, unknown>): void {\n const contours = params.contours\n if (isDrawnContour(contours)) return\n if (!Array.isArray(contours) || contours.length === 0) {\n throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour')\n }\n // Discriminate the whole array at once so a mixed set names the real defect\n // (E_PROFILE_MIXED_CONTOURS) instead of falling into the loop-shape branch and\n // reporting a drawn contour as a malformed segment loop.\n const drawn = contours.map((c) => isDrawnContour(c))\n if (drawn.some(Boolean)) {\n if (!drawn.every(Boolean)) {\n const bad = drawn.indexOf(false)\n throw new Error(\n `E_PROFILE_MIXED_CONTOURS: contour ${bad} is a segment loop while contour ${drawn.indexOf(true)} is a drawn contour — the two forms cannot be mixed`,\n )\n }\n return\n }\n for (const loop of contours) {\n if (!loop || typeof loop !== 'object' || !Array.isArray((loop as ProfileLoop).segments)) {\n throw new Error('E_PROFILE_BAD_LOOP: each contour must have a segments array')\n }\n if ((loop as ProfileLoop).segments.length === 0) {\n throw new Error('E_PROFILE_EMPTY_LOOP: a contour must have at least one segment')\n }\n }\n}\n\n/**\n * BREP 路径:2D 轮廓集合 → planar face 集合。\n *\n * GOTCHA(2026-09-26,Beds part16/39):环语义是「**嵌套 = 孔,不相交 = 独立岛**」\n * (与 FreeCAD 草图一致),不是「面积最大者当外环、其余全当孔」。旧实现把双岛轮廓的\n * 第二个岛判成「洞外面」→ `addHolesInFace` 收到与外环不相交的 wire → 构面退化\n * (7 面、volume 0)。多岛产物 = compound(每岛一面、各带自己的孔),下游\n * `cad.extrude` 对 compound 输入逐面挤出(kernel MakePrism 收复合形状)。\n *\n * @param params - 轮廓来源(段环数据或已绘制轮廓)与产物形态。\n * @returns Shape(单岛为 face;多岛为 face 的 compound;`as:'wire'` 为 1D 曲线)。\n */\nexport function buildProfileShape(params: ProfileParams): Shape {\n const kernel = getBrepApi()\n const as = params.as ?? 'face'\n\n // F2(2026-09-27):环分类统一到纯 2D 管线 `organiseBlueprints`\n // (geometry2d/,brepjs 移植)。「嵌套=孔,不相交=独立岛」语义与既有\n // `profile-multi-island.test.ts` 断言一致;多岛 → 多个顶层,岛+孔 →\n // CompoundBlueprint([0]=外环,[1..]=孔)。\n //\n // 2026-09-28:段环数据与「已绘制轮廓」(`Blueprint`)在此归一 —— 两条\n // 来源只差一次 `toContourBlueprints`,下游分类/构面完全共享。\n const organised = organiseBlueprints(toContourBlueprints(params.contours))\n\n // 'wire' 形态:只挑面积最大的岛的外环 wire(1D 曲线),供扫掠族作 spine。\n if (as === 'wire') {\n let best = organised.blueprints[0]!\n for (const entry of organised.blueprints) {\n if (blueprintArea(entry) > blueprintArea(best)) best = entry\n }\n const outerBp = best instanceof CompoundBlueprint ? best.blueprints[0]! : best\n const wire = blueprintToWire(kernel, outerBp)\n return fromBrepCurve(solidToShape(kernel, wire), { solid: wire })\n }\n\n // 每岛一面(岛的外环 + 直接子环为孔)\n const faces: ReturnType<BrepEngineApi['makeFace']>[] = []\n for (const entry of organised.blueprints) {\n if (entry instanceof CompoundBlueprint) {\n const outerWire = blueprintToWire(kernel, entry.blueprints[0]!)\n const face = kernel.makeFace(outerWire)\n const holes = entry.blueprints.slice(1).map((h) => blueprintToWire(kernel, h))\n if (holes.length > 0) {\n const faced = kernel.addHolesInFace(face, holes)\n kernel.release(face)\n faces.push(faced)\n } else {\n faces.push(face)\n }\n } else {\n faces.push(kernel.makeFace(blueprintToWire(kernel, entry)))\n }\n }\n\n if (faces.length === 1) {\n const f = faces[0]!\n return fromBrep(solidToShape(kernel, f), { solid: f })\n }\n const compound = kernel.makeCompound(faces as never)\n return fromBrep(solidToShape(kernel, compound), { solid: compound })\n}\n\n/**\n * Convert a pure-2D Blueprint to a 3D wire (z=0) for planar face construction.\n * @param kernel - the BREP engine handle-bridge.\n * @param bp - the blueprint whose ordered curves become wire edges.\n * @returns the wire handle.\n */\nfunction blueprintToWire(kernel: BrepEngineApi, bp: Blueprint): ReturnType<BrepEngineApi['makeWire']> {\n const edges: ReturnType<BrepEngineApi['makeLineEdge']>[] = []\n const pt3 = ([x, y]: [number, number]): { x: number; y: number; z: number } => ({ x, y, z: 0 })\n for (const c of bp.curves) {\n switch (c.kind2d) {\n case 'line':\n edges.push(kernel.makeLineEdge({ x: c.ox, y: c.oy, z: 0 }, { x: c.ox + c.dx * c.len, y: c.oy + c.dy * c.len, z: 0 }))\n break\n case 'bezier':\n edges.push(kernel.makeBezierEdge(c.poles.map(pt3)))\n break\n case 'circle': {\n // 完整圆:拆两段半圆 makeArcEdge(避免三点退化)。\n edges.push(kernel.makeArcEdge(pt3(evaluateCurve2d(c, 0)), pt3(evaluateCurve2d(c, Math.PI / 2)), pt3(evaluateCurve2d(c, Math.PI))))\n edges.push(kernel.makeArcEdge(pt3(evaluateCurve2d(c, Math.PI)), pt3(evaluateCurve2d(c, (3 * Math.PI) / 2)), pt3(evaluateCurve2d(c, 2 * Math.PI))))\n break\n }\n case 'trimmed': {\n if (c.basis.kind2d === 'circle') {\n // 圆弧:以 start/mid/end 三点构真实 makeArcEdge(保留光滑柱面,勿拆成折线段)\n edges.push(kernel.makeArcEdge(pt3(evaluateCurve2d(c, 0)), pt3(evaluateCurve2d(c, 0.5)), pt3(evaluateCurve2d(c, 1))))\n break\n }\n const b = curveBounds(c)\n const pts: Array<{ x: number; y: number; z: number }> = []\n for (let k = 0; k <= 32; k++) {\n const t = b.first + ((b.last - b.first) * k) / 32\n pts.push(pt3(evaluateCurve2d(c, t)))\n }\n for (let k = 0; k < pts.length - 1; k++) edges.push(kernel.makeLineEdge(pts[k]!, pts[k + 1]!))\n break\n }\n case 'ellipse':\n case 'bspline': {\n const b = curveBounds(c)\n const n = 32\n const pts: Array<{ x: number; y: number; z: number }> = []\n for (let k = 0; k <= n; k++) {\n const t = b.first + ((b.last - b.first) * k) / n\n pts.push(pt3(evaluateCurve2d(c, t)))\n }\n for (let k = 0; k < pts.length - 1; k++) edges.push(kernel.makeLineEdge(pts[k]!, pts[k + 1]!))\n break\n }\n }\n }\n return kernel.makeWire(edges)\n}\n\n/** 顶层 Blueprint/CompoundBlueprint 的近似有符号面积(用于 wire 最大岛选择)。 */\nfunction blueprintArea(entry: Blueprint | CompoundBlueprint): number {\n const bp = entry instanceof CompoundBlueprint ? entry.blueprints[0]! : entry\n let a = 0\n for (const c of bp.curves) {\n if (c.kind2d === 'line') {\n a += (c.ox * (c.oy + c.dy * c.len) - (c.ox + c.dx * c.len) * c.oy) / 2\n continue\n }\n const b = curveBounds(c)\n const nSamples = 32\n for (let k = 0; k < nSamples; k++) {\n const t0 = b.first + ((b.last - b.first) * k) / nSamples\n const t1 = b.first + ((b.last - b.first) * (k + 1)) / nSamples\n const [x0, y0] = evaluateCurve2d(c, t0)\n const [x1, y1] = evaluateCurve2d(c, t1)\n a += (x0 * y1 - x1 * y0) / 2\n }\n }\n return a\n}\n\n/**\n * 从 2D 轮廓构造平面(creator,无输入)。仅 BREP 可用。\n * @group 创建\n * @inputs 0\n * @async false\n * @qual ok\n * @name profile\n * @returns Shape 平面几何(mesh 三角化 + BREP 句柄);`as:'wire'` 时返回 1D 曲线(kind:'curve')。\n * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔),或已绘制轮廓(单个 Blueprint 或其数组)。type:ProfileLoop[]|Blueprint|Blueprint[] required:true\n * @param params.as - 产物形态:'face'(默认)构面;'wire' 只交外环 wire(1D 曲线)。type:'face'|'wire' required:false\n * @example\n * const f = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }] })\n * const w = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }], as: 'wire' })\n */\nexport const profile = defineOp({\n capabilities: ['directEdit'],\n brep(params: Record<string, unknown>) {\n assertProfileParams(params)\n return buildProfileShape(params as unknown as ProfileParams)\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } } as Provenance,\n})"]}
@@ -1,4 +1,7 @@
1
1
  /**
2
+ * @platform occt — 本文件 import occt-kernel(getOcctKernel:draft-angle punch
3
+ * 的 frustum loft 走原生 occt `loft`,适配器层无此能力)。
4
+ *
2
5
  * `cad.punchHole`: cut a face-placed 2D profile out of a solid (E4 pocket/through
3
6
  * hole with optional taper).
4
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"punch-hole.d.ts","sourceRoot":"","sources":["../../src/api/punch-hole.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAQtD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAIvE,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AAEjE,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,8FAA8F;IAC9F,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,qDAAqD;IACrD,EAAE,EAAE,KAAK,CAAA;IACT,yEAAyE;IACzE,IAAI,EAAE,YAAY,CAAA;IAClB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,sGAAsG;IACtG,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oEAAoE;IACpE,SAAS,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;CAC7C;AAuED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,GAAG,UAAU,CA+F1G;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,GAAG,KAAK,CAOpF;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS;;CAQpB,CAAA"}
1
+ {"version":3,"file":"punch-hole.d.ts","sourceRoot":"","sources":["../../src/api/punch-hole.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAQtD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAIvE,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AAEjE,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,8FAA8F;IAC9F,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,qDAAqD;IACrD,EAAE,EAAE,KAAK,CAAA;IACT,yEAAyE;IACzE,IAAI,EAAE,YAAY,CAAA;IAClB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,sGAAsG;IACtG,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oEAAoE;IACpE,SAAS,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;CAC7C;AAuED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,GAAG,UAAU,CA+F1G;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,GAAG,KAAK,CAOpF;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS;;CAQpB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"punch-hole.js","sourceRoot":"","sources":["../../src/api/punch-hole.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `cad.punchHole`: cut a face-placed 2D profile out of a solid (E4 pocket/through\n * hole with optional taper).\n *\n * The hole profile is a set of closed 2D contours placed on a target face of the\n * solid (the same placement step as `cad.sketchOnFace`). Each placed contour is\n * extruded from the face *into* the part along the face inward normal, and the\n * resulting prism is the \"punch\" tool; a Boolean `cut` removes it from the host —\n * a profile-based pocket (`height` given) or through-hole (`height: null`).\n *\n * v1 scope: the punch is a straight linear prism, or — when `draftAngle > 0` — a\n * **tapered frustum** whose walls recede by `draftAngle` over the punch depth\n * (built as an occt `loft` between a mouth wire in the host plane and an inset\n * end wire at depth `depth·tan(draftAngle)`). The op is a composition over the\n * E3 on-surface placement + `kernel.extrude`/occt `loft` + `kernel.cut` and\n * declares `engines: ['occt']` (surface sampling + Boolean cut + draft loft need\n * the BREP platform).\n * @module\n */\nimport type { Shape } from '../mesh/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport type { BrepHandle } from '../brep/engine/types'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { solidToShape } from '../brep/brep-ops'\nimport { fromBrep, brepOf } from '../shape'\nimport { getOcctKernel } from '../occt-kernel/occtKernel'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { TopoRefError } from '../topology/naming'\nimport { resolveFaceHandle, type FaceSelector } from './sketch-on-face'\nimport { makeUvMap, curves2dBounds, type UvMap } from '../geometry2d/bridge/on-surface'\nimport { evaluateCurve2d } from '../geometry2d/curve2d'\nimport { profileSegToCurve } from '../geometry2d/adapt'\nimport { assertProfileParams, type ProfileLoop } from './profile'\n\n/** Parameters for `cad.punchHole`. */\nexport interface PunchHoleParams {\n /** Ordered 2D closed contour(s) describing the hole profile (same shape as `cad.profile`). */\n contours: ProfileLoop[]\n /** The target solid on which the hole is punched. */\n on: Shape\n /** The host face: a 1-based ordinal or a `cad.faceRef(on, n)` result. */\n face: FaceSelector\n /** Removal depth along the face inward normal. `null`/absent = through hole. */\n height?: number | null\n /** Taper on the hole walls (degrees; default 0 = straight wall). Built as a frustum via occt loft. */\n draftAngle?: number\n /** UV mapping mode for contour placement (default `'original'`). */\n scaleMode?: 'original' | 'bounds' | 'native'\n}\n\n/** Extra length past the host extent so a through-hole clears the opposite side. */\nconst THROUGH_MARGIN = 10\n\n/**\n * Depth of the punch extrusion: the explicit `height`, or the host's bounding-box\n * diagonal (+ margin) for a through hole.\n * @param kernel - the BREP engine surface.\n * @param solid - the host solid handle.\n * @param height - the blind depth, or null for through.\n * @returns the positive extrude length.\n */\nfunction punchDepth(kernel: BrepEngineApi, solid: BrepHandle, height: number | null | undefined): number {\n if (height !== null && height !== undefined) return height\n const box = kernel.getBoundingBox(solid)\n const diag = Math.hypot(box.xmax - box.xmin, box.ymax - box.ymin, box.zmax - box.zmin)\n return diag + THROUGH_MARGIN\n}\n\n/**\n * Map a contour's sampled 2D points onto the host face's UV space, evaluate the\n * surface there, and return a clean, coplanar polygon (sample points projected\n * onto the host's plane through its normal). Rebuilding a straight-edged planar\n * face is deliberate: extruding the on-surface bridge's wire-derived face (a\n * near-coplanar shell, z varies by ~1e-7) collapses its OCCT volume to ~0 — see\n * GOTCHA `punch-hole` (E4).\n * @param kernel - the BREP engine surface.\n * @param host - the host face handle.\n * @param mode - the face scale mode.\n * @param uv - the UV mapping for this contour.\n * @param anchor - an in-plane point of the host face (for the projection plane).\n * @param n - the host face outward normal (unit).\n * @param contour - the 2D contour to punch.\n * @returns a flat polygon of 3D points (each approximately in the host plane).\n */\nfunction buildPolygon3d(\n kernel: BrepEngineApi,\n host: BrepHandle,\n uv: UvMap,\n anchor: { x: number; y: number; z: number },\n n: { x: number; y: number; z: number },\n contour: ProfileLoop,\n): { x: number; y: number; z: number }[] {\n const pts: { x: number; y: number; z: number }[] = []\n // Dedupe consecutive coincident samples across the contour.\n const push = (p: { x: number; y: number; z: number }) => {\n const last = pts[pts.length - 1]\n if (last && Math.abs(last.x - p.x) < 1e-7 && Math.abs(last.y - p.y) < 1e-7 && Math.abs(last.z - p.z) < 1e-7) return\n pts.push(p)\n }\n for (const seg of contour.segments) {\n const c = profileSegToCurve(seg as never)\n for (let k = 0; k <= 12; k++) {\n const [x, y] = evaluateCurve2d(c, k / 12)\n const [u, v] = uv(x, y)\n const raw = kernel.pointOnSurface(host, u, v)\n // Project onto the host face plane (through `anchor` + `n`) for exact coplanarity.\n const d = (raw.x - anchor.x) * n.x + (raw.y - anchor.y) * n.y + (raw.z - anchor.z) * n.z\n push({ x: raw.x - n.x * d, y: raw.y - n.y * d, z: raw.z - n.z * d })\n }\n }\n // Close the loop: drop a trailing point equal to the first.\n if (pts.length > 1) {\n const a = pts[0]!\n const b = pts[pts.length - 1]!\n if (Math.abs(a.x - b.x) < 1e-7 && Math.abs(a.y - b.y) < 1e-7 && Math.abs(a.z - b.z) < 1e-7) pts.pop()\n }\n return pts\n}\n\n/**\n * Build and cut the punch solid for every placed profile on the host face and\n * Boolean-cut it from `solid`, returning the holed solid handle.\n * @param kernel - the BREP engine surface.\n * @param solid - the host solid handle.\n * @param params - the punch parameters.\n * @returns the holed solid handle.\n */\nexport function punchSolidOf(kernel: BrepEngineApi, solid: BrepHandle, params: PunchHoleParams): BrepHandle {\n const host = resolveFaceHandle(kernel, params.on, params.face)\n const mode = params.scaleMode ?? 'original'\n const depth = punchDepth(kernel, solid, params.height ?? null)\n\n const draft = params.draftAngle ?? 0\n const draftRad = (draft * Math.PI) / 180\n\n // Punch inward = opposite the host face outward normal.\n const n0 = kernel.surfaceNormal(host, 0, 0)\n const nlen = Math.hypot(n0.x, n0.y, n0.z) || 1\n const n = { x: n0.x / nlen, y: n0.y / nlen, z: n0.z / nlen }\n\n // In-plane anchor via the host face's UV center.\n const ub = kernel.uvBounds(host)\n const uMid = (ub.uMin + ub.uMax) / 2\n const vMid = (ub.vMin + ub.vMax) / 2\n const anchor = kernel.pointOnSurface(host, uMid, vMid)\n\n const bounds = ub\n let result = solid\n for (const contour of params.contours) {\n const curves = contour.segments.map((s) => profileSegToCurve(s as never))\n const uv = makeUvMap(mode, curves2dBounds(curves), bounds)\n const mouth = buildPolygon3d(kernel, host, uv, anchor, n, contour)\n if (mouth.length < 3) throw new Error('punchHole: contour is degenerate (fewer than 3 distinct points)')\n\n // Mouth wire on the host plane.\n const mouthEdges = [] as BrepHandle[]\n for (let i = 0; i < mouth.length; i++) {\n const a = mouth[i]!\n const b = mouth[(i + 1) % mouth.length]!\n mouthEdges.push(kernel.makeLineEdge(a, b) as never)\n }\n\n let punch: BrepHandle\n if (draft !== 0) {\n // Drafted hole = a tapered frustum: the mouth wire at the host plane and an\n // end wire (recessed by `depth*tan(draftAngle)` toward the contour centre)\n // at the punch depth, lofted together via occt. Verified: occt `loft` of two\n // parallel-planar rect wires reproduces the analytic frustum volume exactly.\n const inset = depth * Math.tan(draftRad)\n // Uniform wall recess: each wall recedes by `inset` = depth·tan(draftAngle)\n // measured *perpendicular* to that wall. For a homothetic scale about the\n // centroid by factor s, the perpendicular recess of an edge at distance h\n // from the centroid is h·(1−s); so choose s = 1 − inset/h̄ with h̄ the mean\n // centroid→edge distance (h̄ = the half-side for a square/rect ⇒ walls land\n // at exactly draftAngle).\n const cx = mouth.reduce((s, p) => s + p.x, 0) / mouth.length\n const cy = mouth.reduce((s, p) => s + p.y, 0) / mouth.length\n const cz = mouth.reduce((s, p) => s + p.z, 0) / mouth.length\n let edgeSum = 0\n for (let i = 0; i < mouth.length; i++) {\n const a = mouth[i]!\n const b = mouth[(i + 1) % mouth.length]!\n // centroid → edge midpoint projection in the host plane\n const mx = (a.x + b.x) / 2 - cx\n const my = (a.y + b.y) / 2 - cy\n const mz = (a.z + b.z) / 2 - cz\n edgeSum += Math.hypot(mx, my, mz)\n }\n const hBar = edgeSum / mouth.length\n if (!Number.isFinite(hBar) || hBar <= 1e-9 || inset >= hBar * 0.999) {\n throw new Error(\n `E_PUNCH_DRAFT_OVER_TAPER: draftAngle ${draft}° inset ${inset.toFixed(3)} must be < half-width ${hBar.toFixed(3)} at depth ${depth}`,\n )\n }\n const s = 1 - inset / hBar\n const endPoints = mouth.map((p) => ({\n x: cx + (p.x - cx) * s - n.x * depth,\n y: cy + (p.y - cy) * s - n.y * depth,\n z: cz + (p.z - cz) * s - n.z * depth,\n }))\n const endEdges = endPoints.map((p, i) => {\n const a = endPoints[i]!\n const b = endPoints[(i + 1) % endPoints.length]!\n return kernel.makeLineEdge(a, b) as never\n }) as BrepHandle[]\n const k = getOcctKernel()\n punch = k.loft(\n [kernel.makeWire(mouthEdges), kernel.makeWire(endEdges)] as unknown as never[],\n true,\n true,\n ) as unknown as BrepHandle\n } else {\n const prismFace = kernel.makeFace(kernel.makeWire(mouthEdges))\n punch = kernel.extrude(prismFace, -n.x * depth, -n.y * depth, -n.z * depth)\n }\n try {\n result = kernel.cut(result, punch)\n } finally {\n kernel.release(punch)\n }\n }\n return result\n}\n\n/**\n * Build a Shape: the host solid with the profile(s) punched out of `params.on`.\n * @param kernel - the BREP engine surface.\n * @param params - the punch parameters.\n * @returns the holed Shape.\n */\nexport function buildPunchHole(kernel: BrepEngineApi, params: PunchHoleParams): Shape {\n const solid = brepOf(params.on) as BrepHandle | undefined\n if (!solid) {\n throw new TopoRefError('E_TOPO_MESH_UNSUPPORTED', 'face', 'punchHole: target `on` has no BREP solid')\n }\n const holed = punchSolidOf(kernel, solid, params)\n return fromBrep(solidToShape(kernel, holed), { solid: holed })\n}\n\n/**\n * `cad.punchHole`: cut a face-placed 2D profile out of a solid.\n * @group 创建\n * @inputs 1\n * @async false\n * @qual ok\n * @name punchHole\n * @returns Shape with the profile punched out of `on`.\n * @param params.contours - ordered 2D closed contours (the hole profile).type:any[] required:true\n * @param params.on - the target solid to punch.type:Shape required:true\n * @param params.face - host face: 1-based ordinal or `cad.faceRef(on, n)`.type:any required:true\n * @param params.height - blind depth along the face inward normal (null/absent = through).type:number|object required:false\n * @param params.draftAngle - wall taper in degrees (default 0 = straight; built as an occt loft frustum).type:number required:false\n * @param params.scaleMode - UV mapping: 'original' | 'bounds' | 'native'.type:string required:false\n */\nexport const punchHole = defineOp({\n capabilities: ['directEdit'],\n engines: ['occt'],\n brep(params: Record<string, unknown>) {\n assertProfileParams(params)\n return buildPunchHole(getBrepApi(), params as unknown as PunchHoleParams)\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } } as Provenance,\n})"]}
1
+ {"version":3,"file":"punch-hole.js","sourceRoot":"","sources":["../../src/api/punch-hole.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @platform occt — 本文件 import occt-kernel(getOcctKernel:draft-angle punch\n * 的 frustum loft 走原生 occt `loft`,适配器层无此能力)。\n *\n * `cad.punchHole`: cut a face-placed 2D profile out of a solid (E4 pocket/through\n * hole with optional taper).\n *\n * The hole profile is a set of closed 2D contours placed on a target face of the\n * solid (the same placement step as `cad.sketchOnFace`). Each placed contour is\n * extruded from the face *into* the part along the face inward normal, and the\n * resulting prism is the \"punch\" tool; a Boolean `cut` removes it from the host —\n * a profile-based pocket (`height` given) or through-hole (`height: null`).\n *\n * v1 scope: the punch is a straight linear prism, or — when `draftAngle > 0` — a\n * **tapered frustum** whose walls recede by `draftAngle` over the punch depth\n * (built as an occt `loft` between a mouth wire in the host plane and an inset\n * end wire at depth `depth·tan(draftAngle)`). The op is a composition over the\n * E3 on-surface placement + `kernel.extrude`/occt `loft` + `kernel.cut` and\n * declares `engines: ['occt']` (surface sampling + Boolean cut + draft loft need\n * the BREP platform).\n * @module\n */\nimport type { Shape } from '../mesh/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport type { BrepHandle } from '../brep/engine/types'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { solidToShape } from '../brep/brep-ops'\nimport { fromBrep, brepOf } from '../shape'\nimport { getOcctKernel } from '../occt-kernel/occtKernel'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { TopoRefError } from '../topology/naming'\nimport { resolveFaceHandle, type FaceSelector } from './sketch-on-face'\nimport { makeUvMap, curves2dBounds, type UvMap } from '../geometry2d/bridge/on-surface'\nimport { evaluateCurve2d } from '../geometry2d/curve2d'\nimport { profileSegToCurve } from '../geometry2d/adapt'\nimport { assertProfileParams, type ProfileLoop } from './profile'\n\n/** Parameters for `cad.punchHole`. */\nexport interface PunchHoleParams {\n /** Ordered 2D closed contour(s) describing the hole profile (same shape as `cad.profile`). */\n contours: ProfileLoop[]\n /** The target solid on which the hole is punched. */\n on: Shape\n /** The host face: a 1-based ordinal or a `cad.faceRef(on, n)` result. */\n face: FaceSelector\n /** Removal depth along the face inward normal. `null`/absent = through hole. */\n height?: number | null\n /** Taper on the hole walls (degrees; default 0 = straight wall). Built as a frustum via occt loft. */\n draftAngle?: number\n /** UV mapping mode for contour placement (default `'original'`). */\n scaleMode?: 'original' | 'bounds' | 'native'\n}\n\n/** Extra length past the host extent so a through-hole clears the opposite side. */\nconst THROUGH_MARGIN = 10\n\n/**\n * Depth of the punch extrusion: the explicit `height`, or the host's bounding-box\n * diagonal (+ margin) for a through hole.\n * @param kernel - the BREP engine surface.\n * @param solid - the host solid handle.\n * @param height - the blind depth, or null for through.\n * @returns the positive extrude length.\n */\nfunction punchDepth(kernel: BrepEngineApi, solid: BrepHandle, height: number | null | undefined): number {\n if (height !== null && height !== undefined) return height\n const box = kernel.getBoundingBox(solid)\n const diag = Math.hypot(box.xmax - box.xmin, box.ymax - box.ymin, box.zmax - box.zmin)\n return diag + THROUGH_MARGIN\n}\n\n/**\n * Map a contour's sampled 2D points onto the host face's UV space, evaluate the\n * surface there, and return a clean, coplanar polygon (sample points projected\n * onto the host's plane through its normal). Rebuilding a straight-edged planar\n * face is deliberate: extruding the on-surface bridge's wire-derived face (a\n * near-coplanar shell, z varies by ~1e-7) collapses its OCCT volume to ~0 — see\n * GOTCHA `punch-hole` (E4).\n * @param kernel - the BREP engine surface.\n * @param host - the host face handle.\n * @param mode - the face scale mode.\n * @param uv - the UV mapping for this contour.\n * @param anchor - an in-plane point of the host face (for the projection plane).\n * @param n - the host face outward normal (unit).\n * @param contour - the 2D contour to punch.\n * @returns a flat polygon of 3D points (each approximately in the host plane).\n */\nfunction buildPolygon3d(\n kernel: BrepEngineApi,\n host: BrepHandle,\n uv: UvMap,\n anchor: { x: number; y: number; z: number },\n n: { x: number; y: number; z: number },\n contour: ProfileLoop,\n): { x: number; y: number; z: number }[] {\n const pts: { x: number; y: number; z: number }[] = []\n // Dedupe consecutive coincident samples across the contour.\n const push = (p: { x: number; y: number; z: number }) => {\n const last = pts[pts.length - 1]\n if (last && Math.abs(last.x - p.x) < 1e-7 && Math.abs(last.y - p.y) < 1e-7 && Math.abs(last.z - p.z) < 1e-7) return\n pts.push(p)\n }\n for (const seg of contour.segments) {\n const c = profileSegToCurve(seg as never)\n for (let k = 0; k <= 12; k++) {\n const [x, y] = evaluateCurve2d(c, k / 12)\n const [u, v] = uv(x, y)\n const raw = kernel.pointOnSurface(host, u, v)\n // Project onto the host face plane (through `anchor` + `n`) for exact coplanarity.\n const d = (raw.x - anchor.x) * n.x + (raw.y - anchor.y) * n.y + (raw.z - anchor.z) * n.z\n push({ x: raw.x - n.x * d, y: raw.y - n.y * d, z: raw.z - n.z * d })\n }\n }\n // Close the loop: drop a trailing point equal to the first.\n if (pts.length > 1) {\n const a = pts[0]!\n const b = pts[pts.length - 1]!\n if (Math.abs(a.x - b.x) < 1e-7 && Math.abs(a.y - b.y) < 1e-7 && Math.abs(a.z - b.z) < 1e-7) pts.pop()\n }\n return pts\n}\n\n/**\n * Build and cut the punch solid for every placed profile on the host face and\n * Boolean-cut it from `solid`, returning the holed solid handle.\n * @param kernel - the BREP engine surface.\n * @param solid - the host solid handle.\n * @param params - the punch parameters.\n * @returns the holed solid handle.\n */\nexport function punchSolidOf(kernel: BrepEngineApi, solid: BrepHandle, params: PunchHoleParams): BrepHandle {\n const host = resolveFaceHandle(kernel, params.on, params.face)\n const mode = params.scaleMode ?? 'original'\n const depth = punchDepth(kernel, solid, params.height ?? null)\n\n const draft = params.draftAngle ?? 0\n const draftRad = (draft * Math.PI) / 180\n\n // Punch inward = opposite the host face outward normal.\n const n0 = kernel.surfaceNormal(host, 0, 0)\n const nlen = Math.hypot(n0.x, n0.y, n0.z) || 1\n const n = { x: n0.x / nlen, y: n0.y / nlen, z: n0.z / nlen }\n\n // In-plane anchor via the host face's UV center.\n const ub = kernel.uvBounds(host)\n const uMid = (ub.uMin + ub.uMax) / 2\n const vMid = (ub.vMin + ub.vMax) / 2\n const anchor = kernel.pointOnSurface(host, uMid, vMid)\n\n const bounds = ub\n let result = solid\n for (const contour of params.contours) {\n const curves = contour.segments.map((s) => profileSegToCurve(s as never))\n const uv = makeUvMap(mode, curves2dBounds(curves), bounds)\n const mouth = buildPolygon3d(kernel, host, uv, anchor, n, contour)\n if (mouth.length < 3) throw new Error('punchHole: contour is degenerate (fewer than 3 distinct points)')\n\n // Mouth wire on the host plane.\n const mouthEdges = [] as BrepHandle[]\n for (let i = 0; i < mouth.length; i++) {\n const a = mouth[i]!\n const b = mouth[(i + 1) % mouth.length]!\n mouthEdges.push(kernel.makeLineEdge(a, b) as never)\n }\n\n let punch: BrepHandle\n if (draft !== 0) {\n // Drafted hole = a tapered frustum: the mouth wire at the host plane and an\n // end wire (recessed by `depth*tan(draftAngle)` toward the contour centre)\n // at the punch depth, lofted together via occt. Verified: occt `loft` of two\n // parallel-planar rect wires reproduces the analytic frustum volume exactly.\n const inset = depth * Math.tan(draftRad)\n // Uniform wall recess: each wall recedes by `inset` = depth·tan(draftAngle)\n // measured *perpendicular* to that wall. For a homothetic scale about the\n // centroid by factor s, the perpendicular recess of an edge at distance h\n // from the centroid is h·(1−s); so choose s = 1 − inset/h̄ with h̄ the mean\n // centroid→edge distance (h̄ = the half-side for a square/rect ⇒ walls land\n // at exactly draftAngle).\n const cx = mouth.reduce((s, p) => s + p.x, 0) / mouth.length\n const cy = mouth.reduce((s, p) => s + p.y, 0) / mouth.length\n const cz = mouth.reduce((s, p) => s + p.z, 0) / mouth.length\n let edgeSum = 0\n for (let i = 0; i < mouth.length; i++) {\n const a = mouth[i]!\n const b = mouth[(i + 1) % mouth.length]!\n // centroid → edge midpoint projection in the host plane\n const mx = (a.x + b.x) / 2 - cx\n const my = (a.y + b.y) / 2 - cy\n const mz = (a.z + b.z) / 2 - cz\n edgeSum += Math.hypot(mx, my, mz)\n }\n const hBar = edgeSum / mouth.length\n if (!Number.isFinite(hBar) || hBar <= 1e-9 || inset >= hBar * 0.999) {\n throw new Error(\n `E_PUNCH_DRAFT_OVER_TAPER: draftAngle ${draft}° inset ${inset.toFixed(3)} must be < half-width ${hBar.toFixed(3)} at depth ${depth}`,\n )\n }\n const s = 1 - inset / hBar\n const endPoints = mouth.map((p) => ({\n x: cx + (p.x - cx) * s - n.x * depth,\n y: cy + (p.y - cy) * s - n.y * depth,\n z: cz + (p.z - cz) * s - n.z * depth,\n }))\n const endEdges = endPoints.map((p, i) => {\n const a = endPoints[i]!\n const b = endPoints[(i + 1) % endPoints.length]!\n return kernel.makeLineEdge(a, b) as never\n }) as BrepHandle[]\n const k = getOcctKernel()\n punch = k.loft(\n [kernel.makeWire(mouthEdges), kernel.makeWire(endEdges)] as unknown as never[],\n true,\n true,\n ) as unknown as BrepHandle\n } else {\n const prismFace = kernel.makeFace(kernel.makeWire(mouthEdges))\n punch = kernel.extrude(prismFace, -n.x * depth, -n.y * depth, -n.z * depth)\n }\n try {\n result = kernel.cut(result, punch)\n } finally {\n kernel.release(punch)\n }\n }\n return result\n}\n\n/**\n * Build a Shape: the host solid with the profile(s) punched out of `params.on`.\n * @param kernel - the BREP engine surface.\n * @param params - the punch parameters.\n * @returns the holed Shape.\n */\nexport function buildPunchHole(kernel: BrepEngineApi, params: PunchHoleParams): Shape {\n const solid = brepOf(params.on) as BrepHandle | undefined\n if (!solid) {\n throw new TopoRefError('E_TOPO_MESH_UNSUPPORTED', 'face', 'punchHole: target `on` has no BREP solid')\n }\n const holed = punchSolidOf(kernel, solid, params)\n return fromBrep(solidToShape(kernel, holed), { solid: holed })\n}\n\n/**\n * `cad.punchHole`: cut a face-placed 2D profile out of a solid.\n * @group 创建\n * @inputs 1\n * @async false\n * @qual ok\n * @name punchHole\n * @returns Shape with the profile punched out of `on`.\n * @param params.contours - ordered 2D closed contours (the hole profile).type:any[] required:true\n * @param params.on - the target solid to punch.type:Shape required:true\n * @param params.face - host face: 1-based ordinal or `cad.faceRef(on, n)`.type:any required:true\n * @param params.height - blind depth along the face inward normal (null/absent = through).type:number|object required:false\n * @param params.draftAngle - wall taper in degrees (default 0 = straight; built as an occt loft frustum).type:number required:false\n * @param params.scaleMode - UV mapping: 'original' | 'bounds' | 'native'.type:string required:false\n */\nexport const punchHole = defineOp({\n capabilities: ['directEdit'],\n engines: ['occt'],\n brep(params: Record<string, unknown>) {\n assertProfileParams(params)\n return buildPunchHole(getBrepApi(), params as unknown as PunchHoleParams)\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } } as Provenance,\n})"]}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * stdlib reconcile — 断链/混合时刻定向归约(P0-1b)
2
+ * api reconcile — 断链/混合时刻定向归约(P0-1b)
3
3
  *
4
4
  *
5
5
  * 用户纠正(2026-08-29):brep→mesh 的归约不只在"mesh 与 brep 做布尔"的时刻发生,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * stdlib reconcile — 断链/混合时刻定向归约(P0-1b)
2
+ * api reconcile — 断链/混合时刻定向归约(P0-1b)
3
3
  *
4
4
  *
5
5
  * 用户纠正(2026-08-29):brep→mesh 的归约不只在"mesh 与 brep 做布尔"的时刻发生,
@@ -1 +1 @@
1
- {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/api/reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAe;IACjD,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACf,WAAW,GAAG,IAAI,CAAA;YAClB,MAAK;QACP,CAAC;IACH,CAAC;IACD,IAAI,CAAC,WAAW;QAAE,OAAO,MAAM,CAAA;IAE/B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACtB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAA;QACzB,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;QAC/C,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAA;IACvD,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["/**\n * stdlib reconcile — 断链/混合时刻定向归约(P0-1b)\n *\n *\n * 用户纠正(2026-08-29):brep→mesh 的归约不只在\"mesh 与 brep 做布尔\"的时刻发生,\n * 而是**任何 BREP 断链时刻**——BREP 输入进入 mesh-only 路径(如 knurl 滚花)即断链,\n * 必须先转 mesh。本文件提供各 mesh 路径入口共用的定向归约:\n *\n * - 触发:本次 op 的输入中既有 `hasBrep(s) === true`、又有 `false`(混合),\n * 或 mesh-only op 收到 BREP 输入(断链)。\n * - 处理对象:**只对 BREP 侧输入**(`brepOf(s)` 有句柄者)做归约(reconcileMesh),\n * 把 OCCT 逐面三角汤归约为合法 2-manifold 网格;mesh 侧输入**原样透传**。\n * - 非混合场景零变化:全 BREP → 走精确布尔,不碰归约;全 mesh → 原样透传。\n * ⇒ 满足用户\"不应该改变现有行为\"的硬约束。\n *\n * 与红线不冲突:归约发生在 dispatchPath 静态判定为 'mesh' **之后**,是输入数据规整,\n * 不是运行时 try-catch 回退。\n */\n\nimport type { Shape } from '../mesh/types'\nimport { reconcileMesh } from '../mesh/reconcile'\nimport { hasBrep } from '../shape'\n\n/**\n * 混合/断链时刻定向归约:仅对 BREP 侧输入做归约,mesh 侧原样透传。\n * 无 BREP 输入时返回原数组引用(零开销、零行为变化)。\n * @param inputs - the input shapes to reconcile.\n * @returns the input array as-is when no BREP input is present, otherwise a\n * new array with BREP-side inputs converted to valid 2-manifold meshes.\n */\nexport function reconcileBrepInputs(inputs: Shape[]): Shape[] {\n let hasBrepSide = false\n for (const s of inputs) {\n if (hasBrep(s)) {\n hasBrepSide = true\n break\n }\n }\n if (!hasBrepSide) return inputs\n\n return inputs.map((s) => {\n if (!hasBrep(s)) return s\n const r = reconcileMesh(s.positions, s.indices)\n return { positions: r.positions, indices: r.indices }\n })\n}\n"]}
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/api/reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAe;IACjD,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACf,WAAW,GAAG,IAAI,CAAA;YAClB,MAAK;QACP,CAAC;IACH,CAAC;IACD,IAAI,CAAC,WAAW;QAAE,OAAO,MAAM,CAAA;IAE/B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACtB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAA;QACzB,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;QAC/C,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAA;IACvD,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["/**\n * api reconcile — 断链/混合时刻定向归约(P0-1b)\n *\n *\n * 用户纠正(2026-08-29):brep→mesh 的归约不只在\"mesh 与 brep 做布尔\"的时刻发生,\n * 而是**任何 BREP 断链时刻**——BREP 输入进入 mesh-only 路径(如 knurl 滚花)即断链,\n * 必须先转 mesh。本文件提供各 mesh 路径入口共用的定向归约:\n *\n * - 触发:本次 op 的输入中既有 `hasBrep(s) === true`、又有 `false`(混合),\n * 或 mesh-only op 收到 BREP 输入(断链)。\n * - 处理对象:**只对 BREP 侧输入**(`brepOf(s)` 有句柄者)做归约(reconcileMesh),\n * 把 OCCT 逐面三角汤归约为合法 2-manifold 网格;mesh 侧输入**原样透传**。\n * - 非混合场景零变化:全 BREP → 走精确布尔,不碰归约;全 mesh → 原样透传。\n * ⇒ 满足用户\"不应该改变现有行为\"的硬约束。\n *\n * 与红线不冲突:归约发生在 dispatchPath 静态判定为 'mesh' **之后**,是输入数据规整,\n * 不是运行时 try-catch 回退。\n */\n\nimport type { Shape } from '../mesh/types'\nimport { reconcileMesh } from '../mesh/reconcile'\nimport { hasBrep } from '../shape'\n\n/**\n * 混合/断链时刻定向归约:仅对 BREP 侧输入做归约,mesh 侧原样透传。\n * 无 BREP 输入时返回原数组引用(零开销、零行为变化)。\n * @param inputs - the input shapes to reconcile.\n * @returns the input array as-is when no BREP input is present, otherwise a\n * new array with BREP-side inputs converted to valid 2-manifold meshes.\n */\nexport function reconcileBrepInputs(inputs: Shape[]): Shape[] {\n let hasBrepSide = false\n for (const s of inputs) {\n if (hasBrep(s)) {\n hasBrepSide = true\n break\n }\n }\n if (!hasBrepSide) return inputs\n\n return inputs.map((s) => {\n if (!hasBrep(s)) return s\n const r = reconcileMesh(s.positions, s.indices)\n return { positions: r.positions, indices: r.indices }\n })\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"replicate.d.ts","sourceRoot":"","sources":["../../src/api/replicate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAiBhD,8DAA8D;AAC9D,UAAU,aAAa;IACrB,wBAAwB;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChF,wBAAwB;IACxB,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7E;AAgDD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe;;CAuC1B,CAAA;AAIF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW;;CAuDtB,CAAA;AAIF,UAAU,yBAAyB;IACjC,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB;;CAqD7B,CAAA;AAIF,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,EAAE,CAAC,EAAE,IAAI,CAAA;CACV;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU;;CA6BrB,CAAA;AAIF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,MAAM;;CAUjB,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK;;CAOhB,CAAA"}
1
+ {"version":3,"file":"replicate.d.ts","sourceRoot":"","sources":["../../src/api/replicate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAuBhD,8DAA8D;AAC9D,UAAU,aAAa;IACrB,wBAAwB;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChF,wBAAwB;IACxB,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7E;AAmED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe;;CAmD1B,CAAA;AAIF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW;;CAyFtB,CAAA;AAIF,UAAU,yBAAyB;IACjC,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB;;CA8E7B,CAAA;AAIF,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,EAAE,CAAC,EAAE,IAAI,CAAA;CACV;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU;;CAkDrB,CAAA;AAIF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,MAAM;;CAwBjB,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK;;CAmBhB,CAAA"}