@faicad/faijs 0.22.2 → 0.29.5

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 (488) 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/appearance.d.ts +138 -0
  7. package/dist/api/appearance.d.ts.map +1 -0
  8. package/dist/api/appearance.js +230 -0
  9. package/dist/api/appearance.js.map +1 -0
  10. package/dist/api/assert.d.ts +2 -2
  11. package/dist/api/assert.js +8 -8
  12. package/dist/api/assert.js.map +1 -1
  13. package/dist/api/asset.d.ts +1 -1
  14. package/dist/api/asset.js +2 -2
  15. package/dist/api/asset.js.map +1 -1
  16. package/dist/api/boolean.d.ts +1 -1
  17. package/dist/api/boolean.d.ts.map +1 -1
  18. package/dist/api/boolean.js +128 -16
  19. package/dist/api/boolean.js.map +1 -1
  20. package/dist/api/cadquery-selectors/borrow-bridge.d.ts +14 -0
  21. package/dist/api/cadquery-selectors/borrow-bridge.d.ts.map +1 -0
  22. package/dist/api/cadquery-selectors/borrow-bridge.js +52 -0
  23. package/dist/api/cadquery-selectors/borrow-bridge.js.map +1 -0
  24. package/dist/api/cadquery-selectors/edge.d.ts +40 -0
  25. package/dist/api/cadquery-selectors/edge.d.ts.map +1 -0
  26. package/dist/api/cadquery-selectors/edge.js +70 -0
  27. package/dist/api/cadquery-selectors/edge.js.map +1 -0
  28. package/dist/api/cadquery-selectors/entity.d.ts +121 -0
  29. package/dist/api/cadquery-selectors/entity.d.ts.map +1 -0
  30. package/dist/api/cadquery-selectors/entity.js +167 -0
  31. package/dist/api/cadquery-selectors/entity.js.map +1 -0
  32. package/dist/api/cadquery-selectors/face.d.ts +33 -0
  33. package/dist/api/cadquery-selectors/face.d.ts.map +1 -0
  34. package/dist/api/cadquery-selectors/face.js +353 -0
  35. package/dist/api/cadquery-selectors/face.js.map +1 -0
  36. package/dist/api/cadquery-selectors/grammar.d.ts +50 -0
  37. package/dist/api/cadquery-selectors/grammar.d.ts.map +1 -0
  38. package/dist/api/cadquery-selectors/grammar.js +345 -0
  39. package/dist/api/cadquery-selectors/grammar.js.map +1 -0
  40. package/dist/api/cadquery-selectors/index.d.ts +18 -0
  41. package/dist/api/cadquery-selectors/index.d.ts.map +1 -0
  42. package/dist/api/cadquery-selectors/index.js +17 -0
  43. package/dist/api/cadquery-selectors/index.js.map +1 -0
  44. package/dist/api/cadquery-selectors/predicates.d.ts +76 -0
  45. package/dist/api/cadquery-selectors/predicates.d.ts.map +1 -0
  46. package/dist/api/cadquery-selectors/predicates.js +85 -0
  47. package/dist/api/cadquery-selectors/predicates.js.map +1 -0
  48. package/dist/api/cadquery-selectors/resolve.d.ts +41 -0
  49. package/dist/api/cadquery-selectors/resolve.d.ts.map +1 -0
  50. package/dist/api/cadquery-selectors/resolve.js +243 -0
  51. package/dist/api/cadquery-selectors/resolve.js.map +1 -0
  52. package/dist/api/cadquery-selectors/types.d.ts +96 -0
  53. package/dist/api/cadquery-selectors/types.d.ts.map +1 -0
  54. package/dist/api/cadquery-selectors/types.js +11 -0
  55. package/dist/api/cadquery-selectors/types.js.map +1 -0
  56. package/dist/api/chamfer.d.ts +13 -5
  57. package/dist/api/chamfer.d.ts.map +1 -1
  58. package/dist/api/chamfer.js +63 -7
  59. package/dist/api/chamfer.js.map +1 -1
  60. package/dist/api/compound-geom.d.ts +1 -1
  61. package/dist/api/compound-geom.js +1 -1
  62. package/dist/api/compound-geom.js.map +1 -1
  63. package/dist/api/draft.d.ts +1 -1
  64. package/dist/api/draft.js +1 -1
  65. package/dist/api/draft.js.map +1 -1
  66. package/dist/api/edge-ref.d.ts +1 -1
  67. package/dist/api/edge-ref.d.ts.map +1 -1
  68. package/dist/api/edge-ref.js +11 -3
  69. package/dist/api/edge-ref.js.map +1 -1
  70. package/dist/api/engrave.d.ts +1 -1
  71. package/dist/api/engrave.js +7 -7
  72. package/dist/api/engrave.js.map +1 -1
  73. package/dist/api/extrude.d.ts +6 -1
  74. package/dist/api/extrude.d.ts.map +1 -1
  75. package/dist/api/extrude.js +59 -5
  76. package/dist/api/extrude.js.map +1 -1
  77. package/dist/api/face-ref.d.ts +1 -1
  78. package/dist/api/face-ref.js +1 -1
  79. package/dist/api/face-ref.js.map +1 -1
  80. package/dist/api/feature-repair.d.ts +1 -1
  81. package/dist/api/feature-repair.js +1 -1
  82. package/dist/api/feature-repair.js.map +1 -1
  83. package/dist/api/fillet-variable.d.ts +1 -1
  84. package/dist/api/fillet-variable.js +1 -1
  85. package/dist/api/fillet-variable.js.map +1 -1
  86. package/dist/api/fillet.d.ts +28 -8
  87. package/dist/api/fillet.d.ts.map +1 -1
  88. package/dist/api/fillet.js +64 -9
  89. package/dist/api/fillet.js.map +1 -1
  90. package/dist/api/geom.d.ts +1 -1
  91. package/dist/api/geom.js +1 -1
  92. package/dist/api/geom.js.map +1 -1
  93. package/dist/api/helix.d.ts +1 -1
  94. package/dist/api/helix.js +1 -1
  95. package/dist/api/helix.js.map +1 -1
  96. package/dist/api/import-brep.d.ts +20 -2
  97. package/dist/api/import-brep.d.ts.map +1 -1
  98. package/dist/api/import-brep.js +28 -3
  99. package/dist/api/import-brep.js.map +1 -1
  100. package/dist/api/import-step.d.ts +17 -2
  101. package/dist/api/import-step.d.ts.map +1 -1
  102. package/dist/api/import-step.js +51 -3
  103. package/dist/api/import-step.js.map +1 -1
  104. package/dist/api/index.d.ts +6 -1
  105. package/dist/api/index.d.ts.map +1 -1
  106. package/dist/api/index.js +7 -2
  107. package/dist/api/index.js.map +1 -1
  108. package/dist/api/internal/compat-op.js +1 -1
  109. package/dist/api/internal/compat-op.js.map +1 -1
  110. package/dist/api/internal/mesh-solid-op.d.ts +236 -0
  111. package/dist/api/internal/mesh-solid-op.d.ts.map +1 -0
  112. package/dist/api/internal/mesh-solid-op.js +352 -0
  113. package/dist/api/internal/mesh-solid-op.js.map +1 -0
  114. package/dist/api/internal/svg-asset-resolver.d.ts +1 -1
  115. package/dist/api/internal/svg-asset-resolver.js +1 -1
  116. package/dist/api/internal/svg-asset-resolver.js.map +1 -1
  117. package/dist/api/knurl.d.ts +1 -1
  118. package/dist/api/knurl.js +2 -2
  119. package/dist/api/knurl.js.map +1 -1
  120. package/dist/api/loft.d.ts +1 -1
  121. package/dist/api/loft.js +1 -1
  122. package/dist/api/loft.js.map +1 -1
  123. package/dist/api/measurement/index.d.ts +9 -5
  124. package/dist/api/measurement/index.d.ts.map +1 -1
  125. package/dist/api/measurement/index.js +47 -20
  126. package/dist/api/measurement/index.js.map +1 -1
  127. package/dist/api/meta.d.ts +93 -0
  128. package/dist/api/meta.d.ts.map +1 -0
  129. package/dist/api/meta.js +99 -0
  130. package/dist/api/meta.js.map +1 -0
  131. package/dist/api/pattern.d.ts +5 -3
  132. package/dist/api/pattern.d.ts.map +1 -1
  133. package/dist/api/pattern.js +32 -4
  134. package/dist/api/pattern.js.map +1 -1
  135. package/dist/api/place.d.ts +1 -1
  136. package/dist/api/place.js +1 -1
  137. package/dist/api/place.js.map +1 -1
  138. package/dist/api/primitives.d.ts +1 -1
  139. package/dist/api/primitives.d.ts.map +1 -1
  140. package/dist/api/primitives.js +119 -4
  141. package/dist/api/primitives.js.map +1 -1
  142. package/dist/api/profile.d.ts +39 -12
  143. package/dist/api/profile.d.ts.map +1 -1
  144. package/dist/api/profile.js +4 -4
  145. package/dist/api/profile.js.map +1 -1
  146. package/dist/api/reconcile.d.ts +1 -1
  147. package/dist/api/reconcile.js +1 -1
  148. package/dist/api/reconcile.js.map +1 -1
  149. package/dist/api/replicate.d.ts.map +1 -1
  150. package/dist/api/replicate.js +122 -1
  151. package/dist/api/replicate.js.map +1 -1
  152. package/dist/api/screw.d.ts +1 -1
  153. package/dist/api/screw.js +3 -3
  154. package/dist/api/screw.js.map +1 -1
  155. package/dist/api/sdf.d.ts +1 -1
  156. package/dist/api/sdf.js +2 -2
  157. package/dist/api/sdf.js.map +1 -1
  158. package/dist/api/section-by-plane.d.ts +1 -1
  159. package/dist/api/section-by-plane.d.ts.map +1 -1
  160. package/dist/api/section-by-plane.js +2 -1
  161. package/dist/api/section-by-plane.js.map +1 -1
  162. package/dist/api/shell.d.ts +11 -4
  163. package/dist/api/shell.d.ts.map +1 -1
  164. package/dist/api/shell.js +53 -7
  165. package/dist/api/shell.js.map +1 -1
  166. package/dist/api/sketch-on-face.d.ts +41 -0
  167. package/dist/api/sketch-on-face.d.ts.map +1 -1
  168. package/dist/api/sketch-on-face.js +100 -1
  169. package/dist/api/sketch-on-face.js.map +1 -1
  170. package/dist/api/sketch-on-plane.d.ts +7 -5
  171. package/dist/api/sketch-on-plane.d.ts.map +1 -1
  172. package/dist/api/sketch-on-plane.js +6 -7
  173. package/dist/api/sketch-on-plane.js.map +1 -1
  174. package/dist/api/split-by-plane.d.ts +1 -1
  175. package/dist/api/split-by-plane.d.ts.map +1 -1
  176. package/dist/api/split-by-plane.js +2 -1
  177. package/dist/api/split-by-plane.js.map +1 -1
  178. package/dist/api/split.d.ts +1 -1
  179. package/dist/api/split.js +2 -2
  180. package/dist/api/split.js.map +1 -1
  181. package/dist/api/sweep.d.ts +1 -1
  182. package/dist/api/sweep.js +1 -1
  183. package/dist/api/sweep.js.map +1 -1
  184. package/dist/api/thicken.d.ts +1 -1
  185. package/dist/api/thicken.js +1 -1
  186. package/dist/api/thicken.js.map +1 -1
  187. package/dist/api/topo-resolve.d.ts +74 -1
  188. package/dist/api/topo-resolve.d.ts.map +1 -1
  189. package/dist/api/topo-resolve.js +180 -2
  190. package/dist/api/topo-resolve.js.map +1 -1
  191. package/dist/api/transform.d.ts +5 -1
  192. package/dist/api/transform.d.ts.map +1 -1
  193. package/dist/api/transform.js +62 -11
  194. package/dist/api/transform.js.map +1 -1
  195. package/dist/api/wire.d.ts +1 -1
  196. package/dist/api/wire.js +1 -1
  197. package/dist/api/wire.js.map +1 -1
  198. package/dist/brep/brep-ops.d.ts +9 -7
  199. package/dist/brep/brep-ops.d.ts.map +1 -1
  200. package/dist/brep/brep-ops.js +50 -26
  201. package/dist/brep/brep-ops.js.map +1 -1
  202. package/dist/brep/brep-topology.d.ts +5 -4
  203. package/dist/brep/brep-topology.d.ts.map +1 -1
  204. package/dist/brep/brep-topology.js +6 -5
  205. package/dist/brep/brep-topology.js.map +1 -1
  206. package/dist/brep/effective-deflection.d.ts +35 -0
  207. package/dist/brep/effective-deflection.d.ts.map +1 -0
  208. package/dist/brep/effective-deflection.js +49 -0
  209. package/dist/brep/effective-deflection.js.map +1 -0
  210. package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
  211. package/dist/brep/engine/adapters/brep-mock.js +27 -0
  212. package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
  213. package/dist/brep/engine/adapters/brepkit.d.ts +18 -0
  214. package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
  215. package/dist/brep/engine/adapters/brepkit.js +46 -1
  216. package/dist/brep/engine/adapters/brepkit.js.map +1 -1
  217. package/dist/brep/engine/adapters/occt.d.ts +1 -1
  218. package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
  219. package/dist/brep/engine/adapters/occt.js +4 -2
  220. package/dist/brep/engine/adapters/occt.js.map +1 -1
  221. package/dist/brep/engine/primitives.d.ts +29 -7
  222. package/dist/brep/engine/primitives.d.ts.map +1 -1
  223. package/dist/brep/engine/primitives.js.map +1 -1
  224. package/dist/brep/engine/registry.d.ts +24 -1
  225. package/dist/brep/engine/registry.d.ts.map +1 -1
  226. package/dist/brep/engine/registry.js +24 -0
  227. package/dist/brep/engine/registry.js.map +1 -1
  228. package/dist/brep/engine/types.d.ts +54 -3
  229. package/dist/brep/engine/types.d.ts.map +1 -1
  230. package/dist/brep/engine/types.js +10 -0
  231. package/dist/brep/engine/types.js.map +1 -1
  232. package/dist/brep/export/export-model.d.ts +40 -0
  233. package/dist/brep/export/export-model.d.ts.map +1 -1
  234. package/dist/brep/export/export-model.js +274 -30
  235. package/dist/brep/export/export-model.js.map +1 -1
  236. package/dist/brep/export/step-meta-header.d.ts +102 -0
  237. package/dist/brep/export/step-meta-header.d.ts.map +1 -0
  238. package/dist/brep/export/step-meta-header.js +225 -0
  239. package/dist/brep/export/step-meta-header.js.map +1 -0
  240. package/dist/brep/export/step.d.ts +5 -1
  241. package/dist/brep/export/step.d.ts.map +1 -1
  242. package/dist/brep/export/step.js +11 -2
  243. package/dist/brep/export/step.js.map +1 -1
  244. package/dist/brep/face-evolution.d.ts +1 -1
  245. package/dist/brep/face-evolution.d.ts.map +1 -1
  246. package/dist/brep/face-evolution.js +20 -1
  247. package/dist/brep/face-evolution.js.map +1 -1
  248. package/dist/brep/handle-bridge.d.ts +1 -1
  249. package/dist/brep/handle-bridge.js +1 -1
  250. package/dist/brep/handle-bridge.js.map +1 -1
  251. package/dist/brep/mesh-solid.d.ts +218 -0
  252. package/dist/brep/mesh-solid.d.ts.map +1 -0
  253. package/dist/brep/mesh-solid.js +229 -0
  254. package/dist/brep/mesh-solid.js.map +1 -0
  255. package/dist/brep/text/fontRegistry.d.ts +32 -1
  256. package/dist/brep/text/fontRegistry.d.ts.map +1 -1
  257. package/dist/brep/text/fontRegistry.js +51 -1
  258. package/dist/brep/text/fontRegistry.js.map +1 -1
  259. package/dist/brep/text/text-to-solid.d.ts.map +1 -1
  260. package/dist/brep/text/text-to-solid.js +8 -3
  261. package/dist/brep/text/text-to-solid.js.map +1 -1
  262. package/dist/brepkit-kernel/brepkitKernel.d.ts +18 -2
  263. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  264. package/dist/brepkit-kernel/brepkitKernel.js +449 -123
  265. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  266. package/dist/brepkit-kernel/brepkitWasm.d.ts +8 -0
  267. package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
  268. package/dist/brepkit-kernel/brepkitWasm.js +10 -0
  269. package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
  270. package/dist/browser-host/browser-font-provider.d.ts +12 -0
  271. package/dist/browser-host/browser-font-provider.d.ts.map +1 -1
  272. package/dist/browser-host/browser-font-provider.js +25 -0
  273. package/dist/browser-host/browser-font-provider.js.map +1 -1
  274. package/dist/browser.d.ts +6 -3
  275. package/dist/browser.d.ts.map +1 -1
  276. package/dist/browser.js +10 -3
  277. package/dist/browser.js.map +1 -1
  278. package/dist/cad-runtime/backend-dispatch.d.ts +28 -3
  279. package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
  280. package/dist/cad-runtime/backend-dispatch.js +119 -4
  281. package/dist/cad-runtime/backend-dispatch.js.map +1 -1
  282. package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
  283. package/dist/cad-runtime/direct-executor.d.ts +15 -3
  284. package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
  285. package/dist/cad-runtime/direct-executor.js +33 -1
  286. package/dist/cad-runtime/direct-executor.js.map +1 -1
  287. package/dist/cad-runtime/ports.d.ts +3 -3
  288. package/dist/cad-runtime/ports.d.ts.map +1 -1
  289. package/dist/cad-runtime/ports.js.map +1 -1
  290. package/dist/cad-runtime/preview-exec.d.ts +4 -4
  291. package/dist/cad-runtime/preview-exec.js +2 -2
  292. package/dist/cad-runtime/preview-exec.js.map +1 -1
  293. package/dist/cad-runtime/runtime.d.ts +42 -7
  294. package/dist/cad-runtime/runtime.d.ts.map +1 -1
  295. package/dist/cad-runtime/runtime.js +68 -5
  296. package/dist/cad-runtime/runtime.js.map +1 -1
  297. package/dist/define-op.d.ts +15 -1
  298. package/dist/define-op.d.ts.map +1 -1
  299. package/dist/define-op.js +73 -2
  300. package/dist/define-op.js.map +1 -1
  301. package/dist/env-agnostic.d.ts +2 -2
  302. package/dist/env-agnostic.d.ts.map +1 -1
  303. package/dist/env-agnostic.js +1 -1
  304. package/dist/env-agnostic.js.map +1 -1
  305. package/dist/geometry2d/adapt.d.ts +39 -4
  306. package/dist/geometry2d/adapt.d.ts.map +1 -1
  307. package/dist/geometry2d/adapt.js +14 -3
  308. package/dist/geometry2d/adapt.js.map +1 -1
  309. package/dist/geometry2d/blueprint.d.ts +2 -2
  310. package/dist/geometry2d/blueprint.js +2 -2
  311. package/dist/geometry2d/blueprint.js.map +1 -1
  312. package/dist/geometry2d/bridge/lift-on-plane.d.ts +18 -8
  313. package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -1
  314. package/dist/geometry2d/bridge/lift-on-plane.js +65 -12
  315. package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -1
  316. package/dist/geometry2d/bridge/plane.d.ts +17 -0
  317. package/dist/geometry2d/bridge/plane.d.ts.map +1 -1
  318. package/dist/geometry2d/bridge/plane.js +22 -0
  319. package/dist/geometry2d/bridge/plane.js.map +1 -1
  320. package/dist/geometry2d/curve2d.d.ts +25 -0
  321. package/dist/geometry2d/curve2d.d.ts.map +1 -1
  322. package/dist/geometry2d/curve2d.js +41 -5
  323. package/dist/geometry2d/curve2d.js.map +1 -1
  324. package/dist/index.d.ts +6 -2
  325. package/dist/index.d.ts.map +1 -1
  326. package/dist/index.js +10 -3
  327. package/dist/index.js.map +1 -1
  328. package/dist/io/bytes-node.d.ts +11 -0
  329. package/dist/io/bytes-node.d.ts.map +1 -0
  330. package/dist/io/bytes-node.js +28 -0
  331. package/dist/io/bytes-node.js.map +1 -0
  332. package/dist/io/bytes.d.ts +33 -0
  333. package/dist/io/bytes.d.ts.map +1 -0
  334. package/dist/io/bytes.js +41 -0
  335. package/dist/io/bytes.js.map +1 -0
  336. package/dist/io/fai-zip/container-read.d.ts +102 -0
  337. package/dist/io/fai-zip/container-read.d.ts.map +1 -0
  338. package/dist/io/fai-zip/container-read.js +305 -0
  339. package/dist/io/fai-zip/container-read.js.map +1 -0
  340. package/dist/io/fai-zip/container-write.d.ts +70 -0
  341. package/dist/io/fai-zip/container-write.d.ts.map +1 -0
  342. package/dist/io/fai-zip/container-write.js +186 -0
  343. package/dist/io/fai-zip/container-write.js.map +1 -0
  344. package/dist/io/fai-zip/container.d.ts +107 -0
  345. package/dist/io/fai-zip/container.d.ts.map +1 -0
  346. package/dist/io/fai-zip/container.js +89 -0
  347. package/dist/io/fai-zip/container.js.map +1 -0
  348. package/dist/io/fai-zip/index.d.ts +18 -0
  349. package/dist/io/fai-zip/index.d.ts.map +1 -0
  350. package/dist/io/fai-zip/index.js +4 -0
  351. package/dist/io/fai-zip/index.js.map +1 -0
  352. package/dist/io/index.d.ts +10 -0
  353. package/dist/io/index.d.ts.map +1 -0
  354. package/dist/io/index.js +13 -0
  355. package/dist/io/index.js.map +1 -0
  356. package/dist/io/zip.d.ts +68 -0
  357. package/dist/io/zip.d.ts.map +1 -0
  358. package/dist/io/zip.js +147 -0
  359. package/dist/io/zip.js.map +1 -0
  360. package/dist/lang/code-to-args.d.ts +1 -1
  361. package/dist/lang/code-to-args.js +1 -1
  362. package/dist/lang/code-to-args.js.map +1 -1
  363. package/dist/lang/metadata-extractor.d.ts.map +1 -1
  364. package/dist/lang/metadata-extractor.js +2 -21
  365. package/dist/lang/metadata-extractor.js.map +1 -1
  366. package/dist/lang/statement-summary.d.ts +1 -1
  367. package/dist/lang/statement-summary.js +1 -1
  368. package/dist/lang/statement-summary.js.map +1 -1
  369. package/dist/lang/types.d.ts +6 -7
  370. package/dist/lang/types.d.ts.map +1 -1
  371. package/dist/lang/types.js +1 -1
  372. package/dist/lang/types.js.map +1 -1
  373. package/dist/mesh/index.d.ts +2 -1
  374. package/dist/mesh/index.d.ts.map +1 -1
  375. package/dist/mesh/index.js +2 -1
  376. package/dist/mesh/index.js.map +1 -1
  377. package/dist/mesh/io.d.ts +13 -0
  378. package/dist/mesh/io.d.ts.map +1 -1
  379. package/dist/mesh/io.js +38 -17
  380. package/dist/mesh/io.js.map +1 -1
  381. package/dist/mesh/primitives.d.ts.map +1 -1
  382. package/dist/mesh/primitives.js +41 -6
  383. package/dist/mesh/primitives.js.map +1 -1
  384. package/dist/mesh/reconcile.d.ts +1 -1
  385. package/dist/mesh/reconcile.js +1 -1
  386. package/dist/mesh/reconcile.js.map +1 -1
  387. package/dist/mesh/rigid-transform.d.ts +3 -3
  388. package/dist/mesh/rigid-transform.js +3 -3
  389. package/dist/mesh/rigid-transform.js.map +1 -1
  390. package/dist/mesh/stl-unit.d.ts +24 -0
  391. package/dist/mesh/stl-unit.d.ts.map +1 -0
  392. package/dist/mesh/stl-unit.js +17 -0
  393. package/dist/mesh/stl-unit.js.map +1 -0
  394. package/dist/mesh/threemf-bambu.d.ts +142 -0
  395. package/dist/mesh/threemf-bambu.d.ts.map +1 -0
  396. package/dist/mesh/threemf-bambu.js +334 -0
  397. package/dist/mesh/threemf-bambu.js.map +1 -0
  398. package/dist/mesh/threemf-loader.d.ts +65 -7
  399. package/dist/mesh/threemf-loader.d.ts.map +1 -1
  400. package/dist/mesh/threemf-loader.js +738 -99
  401. package/dist/mesh/threemf-loader.js.map +1 -1
  402. package/dist/mesh/threemf-view.d.ts +71 -0
  403. package/dist/mesh/threemf-view.d.ts.map +1 -0
  404. package/dist/mesh/threemf-view.js +100 -0
  405. package/dist/mesh/threemf-view.js.map +1 -0
  406. package/dist/mesh/types.d.ts +38 -0
  407. package/dist/mesh/types.d.ts.map +1 -1
  408. package/dist/mesh/types.js.map +1 -1
  409. package/dist/node-host/cli.d.ts +44 -6
  410. package/dist/node-host/cli.d.ts.map +1 -1
  411. package/dist/node-host/cli.js +76 -26
  412. package/dist/node-host/cli.js.map +1 -1
  413. package/dist/node-host/font-family-index.d.ts +93 -0
  414. package/dist/node-host/font-family-index.d.ts.map +1 -0
  415. package/dist/node-host/font-family-index.js +273 -0
  416. package/dist/node-host/font-family-index.js.map +1 -0
  417. package/dist/node-host/fs-asset-resolver.d.ts +8 -3
  418. package/dist/node-host/fs-asset-resolver.d.ts.map +1 -1
  419. package/dist/node-host/fs-asset-resolver.js +13 -5
  420. package/dist/node-host/fs-asset-resolver.js.map +1 -1
  421. package/dist/node-host/index.d.ts +8 -0
  422. package/dist/node-host/index.d.ts.map +1 -1
  423. package/dist/node-host/index.js +1 -0
  424. package/dist/node-host/index.js.map +1 -1
  425. package/dist/node-host/node-font-provider.d.ts +28 -0
  426. package/dist/node-host/node-font-provider.d.ts.map +1 -1
  427. package/dist/node-host/node-font-provider.js +49 -0
  428. package/dist/node-host/node-font-provider.js.map +1 -1
  429. package/dist/node.d.ts +1 -0
  430. package/dist/node.d.ts.map +1 -1
  431. package/dist/node.js +1 -0
  432. package/dist/node.js.map +1 -1
  433. package/dist/occt-kernel/highLevelApi.d.ts +4 -1
  434. package/dist/occt-kernel/highLevelApi.d.ts.map +1 -1
  435. package/dist/occt-kernel/highLevelApi.js +4 -2
  436. package/dist/occt-kernel/highLevelApi.js.map +1 -1
  437. package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
  438. package/dist/occt-kernel/occt-primitives.js +36 -3
  439. package/dist/occt-kernel/occt-primitives.js.map +1 -1
  440. package/dist/occt-kernel/occtKernel.d.ts +19 -14
  441. package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
  442. package/dist/occt-kernel/occtKernel.js +19 -32
  443. package/dist/occt-kernel/occtKernel.js.map +1 -1
  444. package/dist/occt-kernel/stepColorParser.d.ts +18 -0
  445. package/dist/occt-kernel/stepColorParser.d.ts.map +1 -1
  446. package/dist/occt-kernel/stepColorParser.js +38 -0
  447. package/dist/occt-kernel/stepColorParser.js.map +1 -1
  448. package/dist/occt-kernel/stepMetaParser.d.ts +44 -0
  449. package/dist/occt-kernel/stepMetaParser.d.ts.map +1 -0
  450. package/dist/occt-kernel/stepMetaParser.js +166 -0
  451. package/dist/occt-kernel/stepMetaParser.js.map +1 -0
  452. package/dist/occt-kernel/topologyExt.d.ts +1 -1
  453. package/dist/occt-kernel/topologyExt.d.ts.map +1 -1
  454. package/dist/occt-kernel/topologyExt.js +4 -5
  455. package/dist/occt-kernel/topologyExt.js.map +1 -1
  456. package/dist/primitives/text/cjk-font.d.ts +2 -15
  457. package/dist/primitives/text/cjk-font.d.ts.map +1 -1
  458. package/dist/primitives/text/cjk-font.js +13 -1
  459. package/dist/primitives/text/cjk-font.js.map +1 -1
  460. package/dist/runtime-state.d.ts +85 -9
  461. package/dist/runtime-state.d.ts.map +1 -1
  462. package/dist/runtime-state.js +72 -2
  463. package/dist/runtime-state.js.map +1 -1
  464. package/dist/sdk.d.ts +3 -3
  465. package/dist/sdk.d.ts.map +1 -1
  466. package/dist/sdk.js +5 -5
  467. package/dist/sdk.js.map +1 -1
  468. package/dist/shape.d.ts +108 -5
  469. package/dist/shape.d.ts.map +1 -1
  470. package/dist/shape.js +130 -3
  471. package/dist/shape.js.map +1 -1
  472. package/dist/step/stepMetaParser.d.ts +55 -0
  473. package/dist/step/stepMetaParser.d.ts.map +1 -0
  474. package/dist/step/stepMetaParser.js +177 -0
  475. package/dist/step/stepMetaParser.js.map +1 -0
  476. package/dist/topology/naming/lineage.d.ts +6 -0
  477. package/dist/topology/naming/lineage.d.ts.map +1 -1
  478. package/dist/topology/naming/lineage.js +8 -0
  479. package/dist/topology/naming/lineage.js.map +1 -1
  480. package/dist/topology/naming/resolve-edge.d.ts +20 -1
  481. package/dist/topology/naming/resolve-edge.d.ts.map +1 -1
  482. package/dist/topology/naming/resolve-edge.js +54 -20
  483. package/dist/topology/naming/resolve-edge.js.map +1 -1
  484. package/dist/weapp.d.ts +6 -2
  485. package/dist/weapp.d.ts.map +1 -1
  486. package/dist/weapp.js +7 -1
  487. package/dist/weapp.js.map +1 -1
  488. package/package.json +19 -3
@@ -0,0 +1,41 @@
1
+ import type { EntityKind, SelStep } from './types.js';
2
+ import type { EntityGeom, ShapeHandle } from './entity.js';
3
+ /** A set of candidate entities with their owning shape (for normal orientation). */
4
+ export interface Selection {
5
+ owner: ShapeHandle | null;
6
+ items: EntityGeom[];
7
+ }
8
+ /** A fully-resolved narrowing chain: the surviving kind and kernel handles. */
9
+ export interface ChainResult {
10
+ kind: EntityKind;
11
+ handles: ShapeHandle[];
12
+ }
13
+ /**
14
+ * Multi-step `{kind, sel}` narrowing (plan §4.5). Each step collects the `kind`
15
+ * sub-entities of every currently-held object, dedups by kernel identity, then
16
+ * filters by the parsed selector. An empty `sel` collects without filtering
17
+ * (CadQuery `.vertices()` / `.edges()`, whose `_filter` is a no-op).
18
+ *
19
+ * resolveSelection(shape, [{face,'+Z'},{vertex,'<XY'}])
20
+ * → the +Z face's vertices with the smallest x+y, in the order they appear.
21
+ *
22
+ * @param owner - The owning shape handle to start from (or `null` for empty).
23
+ * @param chain - The ordered per-kind narrowing steps to apply.
24
+ * @returns The final kind and the surviving kernel handles at that kind.
25
+ */
26
+ export declare function resolveSelection(owner: ShapeHandle | null, chain: SelStep[]): ChainResult;
27
+ /**
28
+ * Narrow a single step and return the surviving kernel handles. Backs the
29
+ * `resolveEdgeSelection` / `resolveVertexSelector` / `resolveFaceEdgeSelection`
30
+ * projections.
31
+ *
32
+ * @param owner - The owning shape handle to start from (or `null` for empty).
33
+ * @param kind - The topological kind of the step.
34
+ * @param sel - The CadQuery selector string for the step (may be empty).
35
+ * @returns The surviving kernel handles after the single-step narrowing.
36
+ */
37
+ export declare function resolveStepHandles(owner: ShapeHandle | null, kind: EntityKind, sel: string): ShapeHandle[];
38
+ /** ValueError-equivalent for an empty input to a N-th selector. */
39
+ export declare class EmptyNthError extends Error {
40
+ }
41
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/api/cadquery-selectors/resolve.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAY,UAAU,EAAgB,OAAO,EAAQ,MAAM,SAAS,CAAA;AAChF,OAAO,KAAK,EAAE,UAAU,EAAM,WAAW,EAAE,MAAM,UAAU,CAAA;AAa3D,oFAAoF;AACpF,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACzB,KAAK,EAAE,UAAU,EAAE,CAAA;CACpB;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,WAAW,EAAE,CAAA;CACvB;AASD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,WAAW,CAoBzF;AAiBD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,WAAW,GAAG,IAAI,EACzB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,MAAM,GACV,WAAW,EAAE,CAEf;AAoDD,mEAAmE;AACnE,qBAAa,aAAc,SAAQ,KAAK;CAAG"}
@@ -0,0 +1,243 @@
1
+ /**
2
+ * cadquery-selectors/resolve — evaluate a parsed `SelectorExpr` against a set
3
+ * of candidate entities (plan §4.5). Clean-room re-encoding of
4
+ * `cadquery/selectors.py`:
5
+ *
6
+ * · `_SimpleStringSyntaxSelector._chooseSelector` — atom → selector object
7
+ * · `_NthSelector.cluster`/`filter` — center-projection sort + cluster
8
+ * · `BaseDirSelector.filter` — linear edges / planar faces only, else drop
9
+ * · `BinarySelector` set algebra (`AndSelector`/`SumSelector`/
10
+ * `SubtractSelector`/`InverseSelector`) from the expression grammar.
11
+ *
12
+ * Every child of a set operation is applied to the SAME full input list and its
13
+ * results combined (upstream `BinarySelector.filter`), so operands do not chain
14
+ * into each other.
15
+ *
16
+ * Validated against the LOCKED cadquery 2.8.0 probe (C:\cqenv\sel_probe.py)
17
+ * — cube_off ground truth recorded in plan §5.2.
18
+ *
19
+ * @platform occt — narrowing evaluates kernel `ShapeHandle`s through the
20
+ * native occt-kernel (`getKernel()`: isSame identity dedup etc.), so this
21
+ * module is occt-coupled by nature.
22
+ */
23
+ import { getKernel } from '../../occt-kernel/occtKernel.js';
24
+ import { faceGeom, edgeGeom, vertexGeom, subShapeHandles } from './entity.js';
25
+ import { parseSelector } from './grammar.js';
26
+ import { NTH_TOLERANCE, isAligned, isDirectionCandidate, isParallel, isPerpendicular, typeMatches, entityDirection, } from './predicates.js';
27
+ /** Project a kernel handle of the given kind into its `EntityGeom`. */
28
+ function project(handle, kind) {
29
+ if (kind === 'face')
30
+ return faceGeom(handle);
31
+ if (kind === 'edge')
32
+ return edgeGeom(handle);
33
+ return vertexGeom(handle);
34
+ }
35
+ /**
36
+ * Multi-step `{kind, sel}` narrowing (plan §4.5). Each step collects the `kind`
37
+ * sub-entities of every currently-held object, dedups by kernel identity, then
38
+ * filters by the parsed selector. An empty `sel` collects without filtering
39
+ * (CadQuery `.vertices()` / `.edges()`, whose `_filter` is a no-op).
40
+ *
41
+ * resolveSelection(shape, [{face,'+Z'},{vertex,'<XY'}])
42
+ * → the +Z face's vertices with the smallest x+y, in the order they appear.
43
+ *
44
+ * @param owner - The owning shape handle to start from (or `null` for empty).
45
+ * @param chain - The ordered per-kind narrowing steps to apply.
46
+ * @returns The final kind and the surviving kernel handles at that kind.
47
+ */
48
+ export function resolveSelection(owner, chain) {
49
+ if (chain.length === 0) {
50
+ return { kind: 'face', handles: owner ? subShapeHandles(owner, 'face') : [] };
51
+ }
52
+ let candidates = owner ? [owner] : [];
53
+ let kind = chain[0].kind;
54
+ for (const step of chain) {
55
+ // ① collect: sub-entities of each candidate, union/ordered, dedup by identity.
56
+ const gathered = dedupByIsSame(candidates.flatMap((o) => subShapeHandles(o, step.kind)));
57
+ // ② filter: resolve the selector over the gathered views.
58
+ const items = gathered.map((h) => project(h, step.kind));
59
+ candidates =
60
+ step.sel.trim() === ''
61
+ ? gathered
62
+ : evalExpr({ owner, items }, parseSelector(step.sel)).map((g) => g._handle);
63
+ kind = step.kind;
64
+ }
65
+ return { kind, handles: candidates };
66
+ }
67
+ /** Deduplicate kernel handles by KERNEL identity (isSame), preserving order. */
68
+ function dedupByIsSame(handles) {
69
+ const out = [];
70
+ for (const h of handles) {
71
+ if (!out.some((o) => kernOf().isSame(o, h)))
72
+ out.push(h);
73
+ }
74
+ return out;
75
+ }
76
+ function kernOf() {
77
+ return getKernel();
78
+ }
79
+ // ─── single-kind conveniences (plan §4.6) ────────────────────────────────
80
+ /**
81
+ * Narrow a single step and return the surviving kernel handles. Backs the
82
+ * `resolveEdgeSelection` / `resolveVertexSelector` / `resolveFaceEdgeSelection`
83
+ * projections.
84
+ *
85
+ * @param owner - The owning shape handle to start from (or `null` for empty).
86
+ * @param kind - The topological kind of the step.
87
+ * @param sel - The CadQuery selector string for the step (may be empty).
88
+ * @returns The surviving kernel handles after the single-step narrowing.
89
+ */
90
+ export function resolveStepHandles(owner, kind, sel) {
91
+ return resolveSelection(owner, [{ kind, sel }]).handles;
92
+ }
93
+ /** Center dot direction — the ordering key for the N-th selectors. */
94
+ function projKey(g, axis) {
95
+ const c = g.center();
96
+ return c.x * axis.x + c.y * axis.y + c.z * axis.z;
97
+ }
98
+ /**
99
+ * `_NthSelector.cluster` + `filter`: sort by key, cluster consecutive items
100
+ * within `NTH_TOLERANCE`, then return the cluster at index `n` of the list
101
+ * reversed when `max` is false. An empty input raises (upstream
102
+ * `_NthSelector.filter` ValueError); an out-of-range `n` raises IndexError.
103
+ */
104
+ function nthCluster(items, axis, max, n) {
105
+ if (items.length === 0) {
106
+ throw new EmptyNthError('Can not return the Nth element of an empty list');
107
+ }
108
+ const keyed = items
109
+ .map((g) => ({ g, key: projKey(g, axis) }))
110
+ .sort((a, b) => a.key - b.key);
111
+ const clusters = [];
112
+ let cur = [keyed[0].g];
113
+ let start = keyed[0].key;
114
+ for (let i = 1; i < keyed.length; i++) {
115
+ const { g, key } = keyed[i];
116
+ if (Math.abs(key - start) <= NTH_TOLERANCE) {
117
+ cur.push(g);
118
+ }
119
+ else {
120
+ clusters.push(cur);
121
+ cur = [g];
122
+ start = key;
123
+ }
124
+ }
125
+ clusters.push(cur);
126
+ // `_NthSelector.filter`: descending requires reversing the cluster list first.
127
+ if (!max)
128
+ clusters.reverse();
129
+ // Python-style negative index (e.g. `>Z[-2]` ⇔ `clusters[-2]`).
130
+ const idx = n < 0 ? clusters.length + n : n;
131
+ const out = clusters[idx];
132
+ if (out === undefined) {
133
+ throw new RangeError(`Attempted to access index ${n} of a list with length ${clusters.length}`);
134
+ }
135
+ return out;
136
+ }
137
+ /** ValueError-equivalent for an empty input to a N-th selector. */
138
+ export class EmptyNthError extends Error {
139
+ }
140
+ // ── set operations (BinarySelector) ────────────────────────────────────────
141
+ /** `AndSelector`: intersection by kernel identity. */
142
+ function intersect(a, b) {
143
+ const bs = new Set(b.map((g) => g.hash()));
144
+ return a.filter((g) => bs.has(g.hash()));
145
+ }
146
+ /** `SumSelector`: union (no duplicates) by kernel identity. */
147
+ function union(a, b) {
148
+ const seen = new Set();
149
+ const out = [];
150
+ for (const g of a.concat(b)) {
151
+ const h = g.hash();
152
+ if (!seen.has(h)) {
153
+ seen.add(h);
154
+ out.push(g);
155
+ }
156
+ }
157
+ return out;
158
+ }
159
+ /** `SubtractSelector`: set difference by kernel identity. */
160
+ function subtract(a, b) {
161
+ const bs = new Set(b.map((g) => g.hash()));
162
+ return a.filter((g) => !bs.has(g.hash()));
163
+ }
164
+ // ── atom application ──────────────────────────────────────────────────────
165
+ /** BaseDirSelector filter: the direction test over allowed entity kinds. */
166
+ function filterByTest(items, owner, test) {
167
+ const out = [];
168
+ for (const g of items) {
169
+ if (!isDirectionCandidate(g))
170
+ continue;
171
+ const d = entityDirection(g, owner ?? undefined);
172
+ if (d !== null && test(d))
173
+ out.push(g);
174
+ }
175
+ return out;
176
+ }
177
+ /** Apply one atom to the full candidate list, mirroring each selector.filter. */
178
+ function applyAtom(items, owner, desc) {
179
+ switch (desc.kind) {
180
+ case 'dir':
181
+ // `DirectionSelector` (bare `X` or `(x,y,z)`): angle≈0, signed — same as
182
+ // the `+` operator (upstream `only_dir` maps to DirectionSelector).
183
+ return filterByTest(items, owner, (d) => isAligned(d, desc.vec, 1));
184
+ case 'signed':
185
+ return filterByTest(items, owner, (d) => isAligned(d, desc.vec, desc.sign));
186
+ case 'parallel':
187
+ return filterByTest(items, owner, (d) => isParallel(d, desc.vec));
188
+ case 'perpendicular':
189
+ return filterByTest(items, owner, (d) => isPerpendicular(d, desc.vec));
190
+ case 'type':
191
+ return items.filter((g) => typeMatches(g, desc.name));
192
+ case 'minmax':
193
+ // `DirectionMinMaxSelector` = CenterNthSelector(n=-1, max) — no pre-filter.
194
+ return nthCluster(items, desc.vec, desc.max, -1);
195
+ case 'minmaxNth': {
196
+ // `DirectionNthSelector`: parallel pre-filter, then Nth cluster.
197
+ const parallel = filterByTest(items, owner, (d) => isParallel(d, desc.vec));
198
+ return nthCluster(parallel, desc.vec, desc.max, desc.n);
199
+ }
200
+ case 'centerNth': {
201
+ // `CenterNthSelector`: no pre-filter, arbitrary index (n=-1 when absent).
202
+ const n = desc.n ?? -1;
203
+ return nthCluster(items, desc.vec, desc.max, n);
204
+ }
205
+ }
206
+ }
207
+ // ── expression evaluation ─────────────────────────────────────────────────
208
+ /** Evaluate an expression over the candidate list (upstream `Selector.filter`). */
209
+ function evalExpr(sel, expr) {
210
+ const { items, owner } = sel;
211
+ switch (expr.op) {
212
+ case 'atom':
213
+ return applyAtom(items, owner, expr.desc);
214
+ case 'and': {
215
+ let acc = null;
216
+ for (const t of expr.terms) {
217
+ const r = evalExpr({ items, owner }, t);
218
+ acc = acc === null ? r : intersect(acc, r);
219
+ }
220
+ return acc ?? [];
221
+ }
222
+ case 'or': {
223
+ let acc = [];
224
+ for (const t of expr.terms) {
225
+ acc = union(acc, evalExpr({ items, owner }, t));
226
+ }
227
+ return acc;
228
+ }
229
+ case 'exc': {
230
+ let acc = evalExpr({ items, owner }, expr.terms[0]);
231
+ for (let i = 1; i < expr.terms.length; i++) {
232
+ acc = subtract(acc, evalExpr({ items, owner }, expr.terms[i]));
233
+ }
234
+ return acc;
235
+ }
236
+ case 'not': {
237
+ // `InverseSelector`: complement of the operand within the full list.
238
+ const r = evalExpr({ items, owner }, expr.term);
239
+ return subtract(items, r);
240
+ }
241
+ }
242
+ }
243
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/api/cadquery-selectors/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * cadquery-selectors/resolve — evaluate a parsed `SelectorExpr` against a set\n * of candidate entities (plan §4.5). Clean-room re-encoding of\n * `cadquery/selectors.py`:\n *\n * · `_SimpleStringSyntaxSelector._chooseSelector` — atom → selector object\n * · `_NthSelector.cluster`/`filter` — center-projection sort + cluster\n * · `BaseDirSelector.filter` — linear edges / planar faces only, else drop\n * · `BinarySelector` set algebra (`AndSelector`/`SumSelector`/\n * `SubtractSelector`/`InverseSelector`) from the expression grammar.\n *\n * Every child of a set operation is applied to the SAME full input list and its\n * results combined (upstream `BinarySelector.filter`), so operands do not chain\n * into each other.\n *\n * Validated against the LOCKED cadquery 2.8.0 probe (C:\\cqenv\\sel_probe.py)\n * — cube_off ground truth recorded in plan §5.2.\n *\n * @platform occt — narrowing evaluates kernel `ShapeHandle`s through the\n * native occt-kernel (`getKernel()`: isSame identity dedup etc.), so this\n * module is occt-coupled by nature.\n */\nimport { getKernel } from '../../occt-kernel/occtKernel'\nimport type { OcctKernel } from 'occt-wasm'\nimport type { AtomDesc, EntityKind, SelectorExpr, SelStep, Vec3 } from './types'\nimport type { EntityGeom, P3, ShapeHandle } from './entity'\nimport { faceGeom, edgeGeom, vertexGeom, subShapeHandles } from './entity'\nimport { parseSelector } from './grammar'\nimport {\n NTH_TOLERANCE,\n isAligned,\n isDirectionCandidate,\n isParallel,\n isPerpendicular,\n typeMatches,\n entityDirection,\n} from './predicates'\n\n/** A set of candidate entities with their owning shape (for normal orientation). */\nexport interface Selection {\n owner: ShapeHandle | null\n items: EntityGeom[]\n}\n\n/** A fully-resolved narrowing chain: the surviving kind and kernel handles. */\nexport interface ChainResult {\n kind: EntityKind\n handles: ShapeHandle[]\n}\n\n/** Project a kernel handle of the given kind into its `EntityGeom`. */\nfunction project(handle: ShapeHandle, kind: EntityKind): EntityGeom {\n if (kind === 'face') return faceGeom(handle)\n if (kind === 'edge') return edgeGeom(handle)\n return vertexGeom(handle)\n}\n\n/**\n * Multi-step `{kind, sel}` narrowing (plan §4.5). Each step collects the `kind`\n * sub-entities of every currently-held object, dedups by kernel identity, then\n * filters by the parsed selector. An empty `sel` collects without filtering\n * (CadQuery `.vertices()` / `.edges()`, whose `_filter` is a no-op).\n *\n * resolveSelection(shape, [{face,'+Z'},{vertex,'<XY'}])\n * → the +Z face's vertices with the smallest x+y, in the order they appear.\n *\n * @param owner - The owning shape handle to start from (or `null` for empty).\n * @param chain - The ordered per-kind narrowing steps to apply.\n * @returns The final kind and the surviving kernel handles at that kind.\n */\nexport function resolveSelection(owner: ShapeHandle | null, chain: SelStep[]): ChainResult {\n if (chain.length === 0) {\n return { kind: 'face', handles: owner ? subShapeHandles(owner, 'face') : [] }\n }\n let candidates: ShapeHandle[] = owner ? [owner] : []\n let kind: EntityKind = chain[0].kind\n for (const step of chain) {\n // ① collect: sub-entities of each candidate, union/ordered, dedup by identity.\n const gathered: ShapeHandle[] = dedupByIsSame(\n candidates.flatMap((o) => subShapeHandles(o, step.kind)),\n )\n // ② filter: resolve the selector over the gathered views.\n const items = gathered.map((h) => project(h, step.kind))\n candidates =\n step.sel.trim() === ''\n ? gathered\n : evalExpr({ owner, items }, parseSelector(step.sel)).map((g) => g._handle)\n kind = step.kind\n }\n return { kind, handles: candidates }\n}\n\n/** Deduplicate kernel handles by KERNEL identity (isSame), preserving order. */\nfunction dedupByIsSame(handles: ShapeHandle[]): ShapeHandle[] {\n const out: ShapeHandle[] = []\n for (const h of handles) {\n if (!out.some((o) => kernOf().isSame(o as never, h as never))) out.push(h)\n }\n return out\n}\n\nfunction kernOf(): OcctKernel {\n return getKernel() as unknown as OcctKernel\n}\n\n// ─── single-kind conveniences (plan §4.6) ────────────────────────────────\n\n/**\n * Narrow a single step and return the surviving kernel handles. Backs the\n * `resolveEdgeSelection` / `resolveVertexSelector` / `resolveFaceEdgeSelection`\n * projections.\n *\n * @param owner - The owning shape handle to start from (or `null` for empty).\n * @param kind - The topological kind of the step.\n * @param sel - The CadQuery selector string for the step (may be empty).\n * @returns The surviving kernel handles after the single-step narrowing.\n */\nexport function resolveStepHandles(\n owner: ShapeHandle | null,\n kind: EntityKind,\n sel: string,\n): ShapeHandle[] {\n return resolveSelection(owner, [{ kind, sel }]).handles\n}\n\n/** Center dot direction — the ordering key for the N-th selectors. */\nfunction projKey(g: EntityGeom, axis: Vec3): number {\n const c = g.center()\n return c.x * axis.x + c.y * axis.y + c.z * axis.z\n}\n\n/**\n * `_NthSelector.cluster` + `filter`: sort by key, cluster consecutive items\n * within `NTH_TOLERANCE`, then return the cluster at index `n` of the list\n * reversed when `max` is false. An empty input raises (upstream\n * `_NthSelector.filter` ValueError); an out-of-range `n` raises IndexError.\n */\nfunction nthCluster(items: EntityGeom[], axis: Vec3, max: boolean, n: number): EntityGeom[] {\n if (items.length === 0) {\n throw new EmptyNthError('Can not return the Nth element of an empty list')\n }\n\n const keyed = items\n .map((g) => ({ g, key: projKey(g, axis) }))\n .sort((a, b) => a.key - b.key)\n\n const clusters: EntityGeom[][] = []\n let cur = [keyed[0].g]\n let start = keyed[0].key\n for (let i = 1; i < keyed.length; i++) {\n const { g, key } = keyed[i]\n if (Math.abs(key - start) <= NTH_TOLERANCE) {\n cur.push(g)\n } else {\n clusters.push(cur)\n cur = [g]\n start = key\n }\n }\n clusters.push(cur)\n\n // `_NthSelector.filter`: descending requires reversing the cluster list first.\n if (!max) clusters.reverse()\n\n // Python-style negative index (e.g. `>Z[-2]` ⇔ `clusters[-2]`).\n const idx = n < 0 ? clusters.length + n : n\n const out = clusters[idx]\n if (out === undefined) {\n throw new RangeError(\n `Attempted to access index ${n} of a list with length ${clusters.length}`,\n )\n }\n return out\n}\n\n/** ValueError-equivalent for an empty input to a N-th selector. */\nexport class EmptyNthError extends Error {}\n\n// ── set operations (BinarySelector) ────────────────────────────────────────\n\n/** `AndSelector`: intersection by kernel identity. */\nfunction intersect(a: EntityGeom[], b: EntityGeom[]): EntityGeom[] {\n const bs = new Set(b.map((g) => g.hash()))\n return a.filter((g) => bs.has(g.hash()))\n}\n\n/** `SumSelector`: union (no duplicates) by kernel identity. */\nfunction union(a: EntityGeom[], b: EntityGeom[]): EntityGeom[] {\n const seen = new Set<number>()\n const out: EntityGeom[] = []\n for (const g of a.concat(b)) {\n const h = g.hash()\n if (!seen.has(h)) {\n seen.add(h)\n out.push(g)\n }\n }\n return out\n}\n\n/** `SubtractSelector`: set difference by kernel identity. */\nfunction subtract(a: EntityGeom[], b: EntityGeom[]): EntityGeom[] {\n const bs = new Set(b.map((g) => g.hash()))\n return a.filter((g) => !bs.has(g.hash()))\n}\n\n// ── atom application ──────────────────────────────────────────────────────\n\n/** BaseDirSelector filter: the direction test over allowed entity kinds. */\nfunction filterByTest(\n items: EntityGeom[],\n owner: ShapeHandle | null,\n test: (d: P3) => boolean,\n): EntityGeom[] {\n const out: EntityGeom[] = []\n for (const g of items) {\n if (!isDirectionCandidate(g)) continue\n const d = entityDirection(g, owner ?? undefined)\n if (d !== null && test(d)) out.push(g)\n }\n return out\n}\n\n/** Apply one atom to the full candidate list, mirroring each selector.filter. */\nfunction applyAtom(items: EntityGeom[], owner: ShapeHandle | null, desc: AtomDesc): EntityGeom[] {\n switch (desc.kind) {\n case 'dir':\n // `DirectionSelector` (bare `X` or `(x,y,z)`): angle≈0, signed — same as\n // the `+` operator (upstream `only_dir` maps to DirectionSelector).\n return filterByTest(items, owner, (d) => isAligned(d, desc.vec, 1))\n case 'signed':\n return filterByTest(items, owner, (d) => isAligned(d, desc.vec, desc.sign))\n case 'parallel':\n return filterByTest(items, owner, (d) => isParallel(d, desc.vec))\n case 'perpendicular':\n return filterByTest(items, owner, (d) => isPerpendicular(d, desc.vec))\n case 'type':\n return items.filter((g) => typeMatches(g, desc.name))\n case 'minmax':\n // `DirectionMinMaxSelector` = CenterNthSelector(n=-1, max) — no pre-filter.\n return nthCluster(items, desc.vec, desc.max, -1)\n case 'minmaxNth': {\n // `DirectionNthSelector`: parallel pre-filter, then Nth cluster.\n const parallel = filterByTest(items, owner, (d) => isParallel(d, desc.vec))\n return nthCluster(parallel, desc.vec, desc.max, desc.n)\n }\n case 'centerNth': {\n // `CenterNthSelector`: no pre-filter, arbitrary index (n=-1 when absent).\n const n = desc.n ?? -1\n return nthCluster(items, desc.vec, desc.max, n)\n }\n }\n}\n\n// ── expression evaluation ─────────────────────────────────────────────────\n\n/** Evaluate an expression over the candidate list (upstream `Selector.filter`). */\nfunction evalExpr(sel: Selection, expr: SelectorExpr): EntityGeom[] {\n const { items, owner } = sel\n switch (expr.op) {\n case 'atom':\n return applyAtom(items, owner, expr.desc)\n case 'and': {\n let acc: EntityGeom[] | null = null\n for (const t of expr.terms) {\n const r = evalExpr({ items, owner }, t)\n acc = acc === null ? r : intersect(acc, r)\n }\n return acc ?? []\n }\n case 'or': {\n let acc: EntityGeom[] = []\n for (const t of expr.terms) {\n acc = union(acc, evalExpr({ items, owner }, t))\n }\n return acc\n }\n case 'exc': {\n let acc: EntityGeom[] = evalExpr({ items, owner }, expr.terms[0])\n for (let i = 1; i < expr.terms.length; i++) {\n acc = subtract(acc, evalExpr({ items, owner }, expr.terms[i]))\n }\n return acc\n }\n case 'not': {\n // `InverseSelector`: complement of the operand within the full list.\n const r = evalExpr({ items, owner }, expr.term)\n return subtract(items, r)\n }\n }\n}"]}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * cadquery-selectors/types — shared types for the CadQuery selector subsystem.
3
+ *
4
+ * Companion to `2026-10-02-cadquery-selector-parity-plan.md`. These types are
5
+ * the machine-readable description of the CadQuery string-syntax selector
6
+ * grammar (upstream `cadquery/selectors.py` `_makeGrammar` /
7
+ * `_makeExpressionGrammar`), so faijs' string selectors can be *verified*
8
+ * against the reference implementation rather than approximated.
9
+ */
10
+ /** A topological entity kind that selectors can target. */
11
+ export type EntityKind = 'face' | 'edge' | 'vertex';
12
+ /** A single narrowing step: pick `kind` sub-entities, then filter by `sel`. */
13
+ export interface SelStep {
14
+ kind: EntityKind;
15
+ sel: string;
16
+ }
17
+ /** A 3-D vector (component-wise, arbitrary scale). Kept non-normalised to
18
+ * mirror CadQuery's `axes` table which stores `(1,1,0)` for `XY` etc. */
19
+ export interface Vec3 {
20
+ x: number;
21
+ y: number;
22
+ z: number;
23
+ }
24
+ /**
25
+ * A parse atom. Every string-syntax atom maps to exactly one descriptor,
26
+ * mirroring upstream `_SimpleStringSyntaxSelector._chooseSelector`.
27
+ */
28
+ export type AtomDesc = {
29
+ kind: 'dir';
30
+ vec: Vec3;
31
+ } | {
32
+ kind: 'parallel';
33
+ vec: Vec3;
34
+ } | {
35
+ kind: 'perpendicular';
36
+ vec: Vec3;
37
+ } | {
38
+ kind: 'signed';
39
+ vec: Vec3;
40
+ sign: 1 | -1;
41
+ } | {
42
+ kind: 'minmax';
43
+ vec: Vec3;
44
+ max: boolean;
45
+ } | {
46
+ kind: 'minmaxNth';
47
+ vec: Vec3;
48
+ max: boolean;
49
+ n: number;
50
+ } | {
51
+ kind: 'centerNth';
52
+ vec: Vec3;
53
+ max: boolean;
54
+ n: number | null;
55
+ } | {
56
+ kind: 'type';
57
+ name: string;
58
+ };
59
+ /**
60
+ * Abstract syntax tree produced by the string grammar. Mirrors the pyparsing
61
+ * `infix_notation` node shape: `and`/`or`/`exc` are n-ary left folds of their
62
+ * (odd-indexed) operands; `not` is unary, right-associative, highest precedence.
63
+ */
64
+ export type SelectorExpr = {
65
+ op: 'atom';
66
+ desc: AtomDesc;
67
+ } | {
68
+ op: 'and' | 'or' | 'exc';
69
+ terms: SelectorExpr[];
70
+ } | {
71
+ op: 'not';
72
+ term: SelectorExpr;
73
+ };
74
+ /**
75
+ * The geometry quantities a lifted entity exposes to predicates. Projected
76
+ * lazily (each field is a function so a predicate only pays for what it reads).
77
+ * `center` mirrors CadQuery's `Shape.Center()` — for faces this is the
78
+ * area-weighted surface center of mass, NOT the bounding-box center.
79
+ */
80
+ export interface EntityProj {
81
+ /** Stable identity for de-dup / set keys (kernel hashCode). */
82
+ hash: number;
83
+ /** CadQuery `Shape.Center()`: vertex point / linear COM / surface COM. */
84
+ center: Vec3;
85
+ /** `Face.Center()` normal — oriented outward via owning solid. Null for non-faces. */
86
+ surfaceNormal?: Vec3;
87
+ /** `Edge.tangentAt(0.5)` — oriented along the edge's parameter direction. */
88
+ tangent?: Vec3;
89
+ /** `Face/Edge.geomType()` upcased, e.g. 'PLANE' / 'LINE' / 'CIRCLE'. */
90
+ geomType?: string;
91
+ /** Only used for edge `%type` ordering of LUT (results present when edge). */
92
+ isEdge: boolean;
93
+ isFace: boolean;
94
+ isVertex: boolean;
95
+ }
96
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/api/cadquery-selectors/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,2DAA2D;AAC3D,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEnD,+EAA+E;AAC/E,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,UAAU,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED;yEACyE;AACzE,MAAM,WAAW,IAAI;IACnB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAElC;;;;GAIG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;IAAC,KAAK,EAAE,YAAY,EAAE,CAAA;CAAE,GACnD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,CAAA;AAErC;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAA;IACZ,0EAA0E;IAC1E,MAAM,EAAE,IAAI,CAAA;IACZ,sFAAsF;IACtF,aAAa,CAAC,EAAE,IAAI,CAAA;IACpB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;CAClB"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * cadquery-selectors/types — shared types for the CadQuery selector subsystem.
3
+ *
4
+ * Companion to `2026-10-02-cadquery-selector-parity-plan.md`. These types are
5
+ * the machine-readable description of the CadQuery string-syntax selector
6
+ * grammar (upstream `cadquery/selectors.py` `_makeGrammar` /
7
+ * `_makeExpressionGrammar`), so faijs' string selectors can be *verified*
8
+ * against the reference implementation rather than approximated.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/api/cadquery-selectors/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG","sourcesContent":["/**\n * cadquery-selectors/types — shared types for the CadQuery selector subsystem.\n *\n * Companion to `2026-10-02-cadquery-selector-parity-plan.md`. These types are\n * the machine-readable description of the CadQuery string-syntax selector\n * grammar (upstream `cadquery/selectors.py` `_makeGrammar` /\n * `_makeExpressionGrammar`), so faijs' string selectors can be *verified*\n * against the reference implementation rather than approximated.\n */\n\n/** A topological entity kind that selectors can target. */\nexport type EntityKind = 'face' | 'edge' | 'vertex'\n\n/** A single narrowing step: pick `kind` sub-entities, then filter by `sel`. */\nexport interface SelStep {\n kind: EntityKind\n sel: string\n}\n\n/** A 3-D vector (component-wise, arbitrary scale). Kept non-normalised to\n * mirror CadQuery's `axes` table which stores `(1,1,0)` for `XY` etc. */\nexport interface Vec3 {\n x: number\n y: number\n z: number\n}\n\n/**\n * A parse atom. Every string-syntax atom maps to exactly one descriptor,\n * mirroring upstream `_SimpleStringSyntaxSelector._chooseSelector`.\n */\nexport type AtomDesc =\n | { kind: 'dir'; vec: Vec3 } // bare axis `X` / `(x,y,z)` — DirectionSelector\n | { kind: 'parallel'; vec: Vec3 } // `|A` — ParallelDirSelector\n | { kind: 'perpendicular'; vec: Vec3 } // `#A` — PerpendicularDirSelector\n | { kind: 'signed'; vec: Vec3; sign: 1 | -1 } // `+A` / `-A` — DirectionSelector\n | { kind: 'minmax'; vec: Vec3; max: boolean } // `>A` / `<A` — DirectionMinMaxSelector\n | { kind: 'minmaxNth'; vec: Vec3; max: boolean; n: number } // `>A[k]` — DirectionNthSelector\n | { kind: 'centerNth'; vec: Vec3; max: boolean; n: number | null } // `>>A` / `<<A[k]` — CenterNthSelector\n | { kind: 'type'; name: string } // `%TYPE` — TypeSelector (name already upper-cased)\n\n/**\n * Abstract syntax tree produced by the string grammar. Mirrors the pyparsing\n * `infix_notation` node shape: `and`/`or`/`exc` are n-ary left folds of their\n * (odd-indexed) operands; `not` is unary, right-associative, highest precedence.\n */\nexport type SelectorExpr =\n | { op: 'atom'; desc: AtomDesc }\n | { op: 'and' | 'or' | 'exc'; terms: SelectorExpr[] }\n | { op: 'not'; term: SelectorExpr }\n\n/**\n * The geometry quantities a lifted entity exposes to predicates. Projected\n * lazily (each field is a function so a predicate only pays for what it reads).\n * `center` mirrors CadQuery's `Shape.Center()` — for faces this is the\n * area-weighted surface center of mass, NOT the bounding-box center.\n */\nexport interface EntityProj {\n /** Stable identity for de-dup / set keys (kernel hashCode). */\n hash: number\n /** CadQuery `Shape.Center()`: vertex point / linear COM / surface COM. */\n center: Vec3\n /** `Face.Center()` normal — oriented outward via owning solid. Null for non-faces. */\n surfaceNormal?: Vec3\n /** `Edge.tangentAt(0.5)` — oriented along the edge's parameter direction. */\n tangent?: Vec3\n /** `Face/Edge.geomType()` upcased, e.g. 'PLANE' / 'LINE' / 'CIRCLE'. */\n geomType?: string\n /** Only used for edge `%type` ordering of LUT (results present when edge). */\n isEdge: boolean\n isFace: boolean\n isVertex: boolean\n}"]}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * stdlib chamfer — chamfer 倒角库函数(BREP-only,directEdit 能力)
2
+ * api chamfer — chamfer 倒角库函数(BREP-only,directEdit 能力)
3
3
  *
4
4
  * 平台分层(2026-09-26 B 批降级):**中立 op**(不再声明 `engines:['occt']`)。
5
5
  * equal 分支按引擎能力**静态定轨**(与 intersect 同构,读 `dispatchPath` 同源的能力集):
@@ -26,10 +26,15 @@ import type { BrepEngineApi } from '../brep/engine/primitives.js';
26
26
  import type { ResolutionContext } from '../topology/naming/index.js';
27
27
  /**
28
28
  * Validate chamfer parameters: `edges` must be a non-empty array of EdgeTopoRef,
29
- * each with kind key "edge" and a two-entry faces pair.
29
+ * each with kind key "edge" and a two-entry faces pair — or of 1-based ordinals
30
+ * when `opts.allowOrdinals` (the mesh chain, which has no role layer to match
31
+ * edges against).
30
32
  * @param params the raw chamfer operation parameters.
33
+ * @param opts the selector-form options (mesh chain allows ordinals).
31
34
  */
32
- export declare function assertChamferParams(params: Record<string, unknown>): void;
35
+ export declare function assertChamferParams(params: Record<string, unknown>, opts?: {
36
+ readonly allowOrdinals?: boolean;
37
+ }): void;
33
38
  /**
34
39
  * twoDistances 单边换算:width1/width2 + β(§3.5)→ (dF, θ) 供一次 chamferDistAngle。
35
40
  * 参考面由内核自选(refOrdinal 的面);width1 对应 faces[0] 侧、width2 对应 faces[1] 侧。
@@ -48,13 +53,15 @@ export declare function twoDistParams(kernel: BrepEngineApi, ctx: ResolutionCont
48
53
  angleDeg: number;
49
54
  };
50
55
  /**
51
- * 在几何体上倒角(等距 / 双距 / 距角)。仅 BREP 可用。
56
+ * 在几何体上倒角(等距 / 双距 / 距角)。
52
57
  * @group 特征
53
58
  * @inputs 1
54
59
  * @async true
55
60
  * @qual ok
56
61
  * @name chamfer
57
- * @note 倒角是 BREP-only:非 BREP 输入抛 E_MESH_UNSUPPORTED。参考面由内核自选,`width1` 沿 faces[0] 侧、`width2` 沿 faces[1] 侧。
62
+ * @note BREP 输入走完整三形态;**网格实体**输入只支持 `equal` / `distanceAngle`
63
+ * (`twoDistances` 需要 role 可解析的邻面,近似拓扑没有 role)。
64
+ * `width1` 沿 faces[0] 侧、`width2` 沿 faces[1] 侧(BREP 路径)。
58
65
  * @returns Shape 倒角后的几何。
59
66
  * @param input - 目标几何。type:Shape required:true
60
67
  * @param params.edges - 参与倒角的边(EdgeTopoRef[],条目为相邻两面的 role 线路)。type:EdgeTopoRef[] required:true
@@ -65,6 +72,7 @@ export declare function twoDistParams(kernel: BrepEngineApi, ctx: ResolutionCont
65
72
  * @param params.angle - type=distanceAngle: 与参考面夹角(度,(0,90))。type:number
66
73
  * @example
67
74
  * const p = await cad.chamfer(part0, { edges: [{ kind:'edge', faces:[{ origin:'box', role:'box:top' }, { origin:'box', role:'box:front' }], hint:{ kind:'edge' } }], type:'equal', width:1 })
75
+ * const q = await cad.chamfer(meshPart, { edges: [3], type:'equal', width:1 })
68
76
  */
69
77
  export declare const chamfer: ((input: Shape, params: Record<string, unknown>) => Promise<Shape>) & {
70
78
  __faijs__dualOp?: import("../define-op.js").DualOpMeta;
@@ -1 +1 @@
1
- {"version":3,"file":"chamfer.d.ts","sourceRoot":"","sources":["../../src/api/chamfer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAQ1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAE9D,OAAO,KAAK,EAAe,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAQxE;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAuCzE;AAyCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,iBAAiB,EACtB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAgBxC;AAwHD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,OAAO;;CAQlB,CAAA"}
1
+ {"version":3,"file":"chamfer.d.ts","sourceRoot":"","sources":["../../src/api/chamfer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAQ1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAE9D,OAAO,KAAK,EAAe,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAUxE;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1C,IAAI,CA6CN;AAyCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,iBAAiB,EACtB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAgBxC;AAsKD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,OAAO;;CAclB,CAAA"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * stdlib chamfer — chamfer 倒角库函数(BREP-only,directEdit 能力)
2
+ * api chamfer — chamfer 倒角库函数(BREP-only,directEdit 能力)
3
3
  *
4
4
  * 平台分层(2026-09-26 B 批降级):**中立 op**(不再声明 `engines:['occt']`)。
5
5
  * equal 分支按引擎能力**静态定轨**(与 intersect 同构,读 `dispatchPath` 同源的能力集):
@@ -30,19 +30,30 @@ import { fromBrep, brepOf, inputRoleTable } from '../shape.js';
30
30
  import { defineOp } from '../sdk.js';
31
31
  import { resolveTopoRef, facesForQualifier, TopoRefError } from '../topology/naming/index.js';
32
32
  import { buildEdgeResolutionContext, buildEdgeContextFromSolid } from './topo-resolve.js';
33
+ import { OpError } from './internal/result-unwrap.js';
34
+ import { meshKernelFailure, meshSolidEntry, meshSolidProduct, resolveMeshEdges } from './internal/mesh-solid-op.js';
33
35
  import { angleBetweenNormals, materialDihedralFromNormalAngle, chamferAngleFromDistances } from './chamfer-math.js';
34
- // ── 参数自校验(stdlib 被直接 import 时的防御层)──
36
+ // ── 参数自校验(api 层被直接 import 时的防御层)──
35
37
  /**
36
38
  * Validate chamfer parameters: `edges` must be a non-empty array of EdgeTopoRef,
37
- * each with kind key "edge" and a two-entry faces pair.
39
+ * each with kind key "edge" and a two-entry faces pair — or of 1-based ordinals
40
+ * when `opts.allowOrdinals` (the mesh chain, which has no role layer to match
41
+ * edges against).
38
42
  * @param params the raw chamfer operation parameters.
43
+ * @param opts the selector-form options (mesh chain allows ordinals).
39
44
  */
40
- export function assertChamferParams(params) {
45
+ export function assertChamferParams(params, opts) {
41
46
  const edges = params.edges;
42
47
  if (!Array.isArray(edges) || edges.length === 0) {
43
48
  throw new Error('E_CHAMFER_NO_EDGES: chamfer requires at least one edge');
44
49
  }
45
50
  for (const e of edges) {
51
+ if (opts?.allowOrdinals && typeof e === 'number') {
52
+ if (!Number.isInteger(e) || e < 1) {
53
+ throw new Error('E_CHAMFER_BAD_EDGE_REF: an edge ordinal must be a positive integer (1-based)');
54
+ }
55
+ continue;
56
+ }
46
57
  if (!e || typeof e !== 'object' || e.kind !== 'edge') {
47
58
  throw new Error('E_CHAMFER_BAD_EDGE_REF: every edge entry must be an EdgeTopoRef with kind:"edge"');
48
59
  }
@@ -177,7 +188,7 @@ function chamferBrep(input, params) {
177
188
  const kernel = getBrepApi();
178
189
  const solid = brepOf(input);
179
190
  if (!solid)
180
- throw new Error('[stdlib/chamfer] E_CHAMFER_NO_BREP: input is not BREP');
191
+ throw new Error('[api/chamfer] E_CHAMFER_NO_BREP: input is not BREP');
181
192
  const edges = params.edges ?? [];
182
193
  const type = params.type;
183
194
  const ctx = buildEdgeResolutionContext(kernel, input);
@@ -242,13 +253,51 @@ function chamferBrep(input, params) {
242
253
  return fromBrep(solidToShape(kernel, resultSolid), faceEvolution ? { solid: resultSolid, faceEvolution, roleTable } : { solid: resultSolid, roleTable });
243
254
  }
244
255
  /**
245
- * 在几何体上倒角(等距 / 双距 / 距角)。仅 BREP 可用。
256
+ * 网格实体路径:对近似拓扑里识别出的边倒角(方案 2026-10-01 §3.5 三明治)。
257
+ *
258
+ * 支持的形态与 BREP 路径的差异:
259
+ * - `equal` → L1 裸 `kernel.chamfer`;`distanceAngle` → `kernel.chamferDistAngle`;
260
+ * - `twoDistances` **不支持**:它要把 `faces[0]/faces[1]` 两个 role 限定符解析到面,
261
+ * 再由内核选中的参考面决定 width1/width2 各归哪一侧。近似拓扑没有 role 层,
262
+ * 这两个限定符无从解析——如实拒绝,不猜一个参考面(猜错 = 倒角落在错误的一侧)。
263
+ *
264
+ * 与 fillet 同一条 GOTCHA:一次请求里的全部边交给内核会在共面边链上被整体拒绝,
265
+ * 本实现如实失败,不自动拆成逐边重试。
266
+ *
267
+ * @param input - the mesh-solid input.
268
+ * @param params - the validated chamfer parameters.
269
+ * @returns the chamfered mesh solid as a new mesh part.
270
+ */
271
+ function chamferMeshSolid(input, params) {
272
+ const type = params.type;
273
+ const edges = params.edges ?? [];
274
+ if (type === 'twoDistances') {
275
+ throw new OpError('chamfer', 'E_MESH_SOLID_UNSUPPORTED', '[api/chamfer] twoDistances needs role-resolvable adjacent faces to decide which side ' +
276
+ 'carries width1/width2; a mesh solid has no role layer — use type:"equal" or "distanceAngle"');
277
+ }
278
+ const entry = meshSolidEntry(input, 'chamfer');
279
+ const edgeHandles = resolveMeshEdges(entry, edges, 'chamfer');
280
+ let result;
281
+ try {
282
+ result = type === 'distanceAngle'
283
+ ? entry.kernel.chamferDistAngle(entry.solid, edgeHandles, params.width, params.angle)
284
+ : entry.kernel.chamfer(entry.solid, edgeHandles, params.width);
285
+ }
286
+ catch (cause) {
287
+ throw meshKernelFailure('chamfer', 'E_CHAMFER_FAILED', `chamfer(type=${type}) on ${edgeHandles.length} edge(s)`, cause);
288
+ }
289
+ return meshSolidProduct(entry, result);
290
+ }
291
+ /**
292
+ * 在几何体上倒角(等距 / 双距 / 距角)。
246
293
  * @group 特征
247
294
  * @inputs 1
248
295
  * @async true
249
296
  * @qual ok
250
297
  * @name chamfer
251
- * @note 倒角是 BREP-only:非 BREP 输入抛 E_MESH_UNSUPPORTED。参考面由内核自选,`width1` 沿 faces[0] 侧、`width2` 沿 faces[1] 侧。
298
+ * @note BREP 输入走完整三形态;**网格实体**输入只支持 `equal` / `distanceAngle`
299
+ * (`twoDistances` 需要 role 可解析的邻面,近似拓扑没有 role)。
300
+ * `width1` 沿 faces[0] 侧、`width2` 沿 faces[1] 侧(BREP 路径)。
252
301
  * @returns Shape 倒角后的几何。
253
302
  * @param input - 目标几何。type:Shape required:true
254
303
  * @param params.edges - 参与倒角的边(EdgeTopoRef[],条目为相邻两面的 role 线路)。type:EdgeTopoRef[] required:true
@@ -259,10 +308,17 @@ function chamferBrep(input, params) {
259
308
  * @param params.angle - type=distanceAngle: 与参考面夹角(度,(0,90))。type:number
260
309
  * @example
261
310
  * const p = await cad.chamfer(part0, { edges: [{ kind:'edge', faces:[{ origin:'box', role:'box:top' }, { origin:'box', role:'box:front' }], hint:{ kind:'edge' } }], type:'equal', width:1 })
311
+ * const q = await cad.chamfer(meshPart, { edges: [3], type:'equal', width:1 })
262
312
  */
263
313
  export const chamfer = defineOp({
264
314
  // 中立 op(2026-09-26 B 批):不再声明 engines——equal 路径按引擎能力静态分派
265
315
  // (occt→chamferWithHistory 历史路径;brepkit→裸 kernel.chamfer 无演化降级)。
316
+ // meshEngines:网格实体路径由 brepkit 网格后端提供(方案 2026-10-01 §3.4)。
317
+ meshEngines: ['brepkit'],
318
+ mesh(input, params) {
319
+ assertChamferParams(params, { allowOrdinals: true });
320
+ return chamferMeshSolid(input, params);
321
+ },
266
322
  brep(input, params) {
267
323
  assertChamferParams(params);
268
324
  return chamferBrep(input, params);