@faicad/faijs 0.33.2 → 0.35.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/api-namespace.d.ts +14 -14
- package/dist/api/api-namespace.d.ts.map +1 -1
- package/dist/api/api-namespace.js +40 -14
- package/dist/api/api-namespace.js.map +1 -1
- package/dist/api/appearance.d.ts +47 -6
- package/dist/api/appearance.d.ts.map +1 -1
- package/dist/api/appearance.js.map +1 -1
- package/dist/api/assembly/solve-tree.d.ts +1 -0
- package/dist/api/assembly/solve-tree.d.ts.map +1 -1
- package/dist/api/assembly/solve-tree.js +42 -17
- package/dist/api/assembly/solve-tree.js.map +1 -1
- package/dist/api/assembly/solve.d.ts +1 -0
- package/dist/api/assembly/solve.d.ts.map +1 -1
- package/dist/api/assembly/solve.js.map +1 -1
- package/dist/api/assembly/solvers/global-solver.d.ts.map +1 -1
- package/dist/api/assembly/solvers/global-solver.js +130 -23
- package/dist/api/assembly/solvers/global-solver.js.map +1 -1
- package/dist/api/assembly/solvers/pose-from-delta.d.ts +9 -0
- package/dist/api/assembly/solvers/pose-from-delta.d.ts.map +1 -1
- package/dist/api/assembly/solvers/pose-from-delta.js +23 -0
- package/dist/api/assembly/solvers/pose-from-delta.js.map +1 -1
- package/dist/api/assembly/solvers/types.d.ts +20 -2
- package/dist/api/assembly/solvers/types.d.ts.map +1 -1
- package/dist/api/assembly/solvers/types.js.map +1 -1
- package/dist/api/chamfer.d.ts +7 -4
- package/dist/api/chamfer.d.ts.map +1 -1
- package/dist/api/chamfer.js +57 -13
- package/dist/api/chamfer.js.map +1 -1
- package/dist/api/draft.d.ts +7 -4
- package/dist/api/draft.d.ts.map +1 -1
- package/dist/api/draft.js +11 -6
- package/dist/api/draft.js.map +1 -1
- package/dist/api/edge-ref.d.ts +4 -4
- package/dist/api/edge-ref.js +4 -4
- package/dist/api/edge-ref.js.map +1 -1
- package/dist/api/extrude.d.ts +10 -6
- package/dist/api/extrude.d.ts.map +1 -1
- package/dist/api/extrude.js +50 -25
- package/dist/api/extrude.js.map +1 -1
- package/dist/api/face-ref.d.ts +4 -4
- package/dist/api/face-ref.js +4 -4
- package/dist/api/face-ref.js.map +1 -1
- package/dist/api/feature-repair.d.ts +6 -3
- package/dist/api/feature-repair.d.ts.map +1 -1
- package/dist/api/feature-repair.js +12 -7
- package/dist/api/feature-repair.js.map +1 -1
- package/dist/api/fillet-variable.d.ts +6 -2
- package/dist/api/fillet-variable.d.ts.map +1 -1
- package/dist/api/fillet-variable.js +24 -6
- package/dist/api/fillet-variable.js.map +1 -1
- package/dist/api/fillet.d.ts +7 -4
- package/dist/api/fillet.d.ts.map +1 -1
- package/dist/api/fillet.js +45 -12
- package/dist/api/fillet.js.map +1 -1
- package/dist/api/helix.d.ts +13 -13
- package/dist/api/helix.d.ts.map +1 -1
- package/dist/api/helix.js +19 -24
- package/dist/api/helix.js.map +1 -1
- package/dist/api/import-brep.d.ts +10 -18
- package/dist/api/import-brep.d.ts.map +1 -1
- package/dist/api/import-brep.js +17 -25
- package/dist/api/import-brep.js.map +1 -1
- package/dist/api/import-step.d.ts +10 -15
- package/dist/api/import-step.d.ts.map +1 -1
- package/dist/api/import-step.js +24 -29
- package/dist/api/import-step.js.map +1 -1
- package/dist/api/index.js +2 -2
- package/dist/api/index.js.map +1 -1
- package/dist/api/internal/export-members.js.map +1 -1
- package/dist/api/loft-advanced.d.ts +4 -0
- package/dist/api/loft-advanced.d.ts.map +1 -1
- package/dist/api/loft-advanced.js +4 -0
- package/dist/api/loft-advanced.js.map +1 -1
- package/dist/api/loft.d.ts +5 -3
- package/dist/api/loft.d.ts.map +1 -1
- package/dist/api/loft.js +5 -3
- package/dist/api/loft.js.map +1 -1
- package/dist/api/meta.d.ts +42 -6
- package/dist/api/meta.d.ts.map +1 -1
- package/dist/api/meta.js.map +1 -1
- package/dist/api/punch-hole.d.ts +5 -2
- package/dist/api/punch-hole.d.ts.map +1 -1
- package/dist/api/punch-hole.js +4 -1
- package/dist/api/punch-hole.js.map +1 -1
- package/dist/api/replicate.d.ts +4 -5
- package/dist/api/replicate.d.ts.map +1 -1
- package/dist/api/replicate.js +4 -5
- package/dist/api/replicate.js.map +1 -1
- package/dist/api/selectors-to-refs.d.ts +83 -0
- package/dist/api/selectors-to-refs.d.ts.map +1 -0
- package/dist/api/selectors-to-refs.js +211 -0
- package/dist/api/selectors-to-refs.js.map +1 -0
- package/dist/api/shell.d.ts +17 -8
- package/dist/api/shell.d.ts.map +1 -1
- package/dist/api/shell.js +45 -15
- package/dist/api/shell.js.map +1 -1
- package/dist/api/sketch-on-face.d.ts +12 -6
- package/dist/api/sketch-on-face.d.ts.map +1 -1
- package/dist/api/sketch-on-face.js +31 -4
- package/dist/api/sketch-on-face.js.map +1 -1
- package/dist/api/sketch-on-plane.d.ts +3 -0
- package/dist/api/sketch-on-plane.d.ts.map +1 -1
- package/dist/api/sketch-on-plane.js +3 -0
- package/dist/api/sketch-on-plane.js.map +1 -1
- package/dist/api/sketch-on-surface.d.ts +4 -1
- package/dist/api/sketch-on-surface.d.ts.map +1 -1
- package/dist/api/sketch-on-surface.js +4 -1
- package/dist/api/sketch-on-surface.js.map +1 -1
- package/dist/api/view/view-projection.d.ts.map +1 -1
- package/dist/api/view/view-projection.js +9 -2
- package/dist/api/view/view-projection.js.map +1 -1
- package/dist/brep/brep-chain.js +2 -2
- package/dist/brep/brep-chain.js.map +1 -1
- package/dist/brep/brep-ops.d.ts +1 -1
- package/dist/brep/brep-ops.js +1 -1
- package/dist/brep/brep-ops.js.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.js +45 -0
- package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
- package/dist/brep/engine/primitives.d.ts +87 -3
- package/dist/brep/engine/primitives.d.ts.map +1 -1
- package/dist/brep/engine/primitives.js +1 -1
- package/dist/brep/engine/primitives.js.map +1 -1
- package/dist/brep/engine/registry.d.ts +33 -7
- package/dist/brep/engine/registry.d.ts.map +1 -1
- package/dist/brep/engine/registry.js +47 -16
- package/dist/brep/engine/registry.js.map +1 -1
- package/dist/brep/handle-bridge.d.ts +14 -15
- package/dist/brep/handle-bridge.d.ts.map +1 -1
- package/dist/brep/handle-bridge.js +35 -15
- package/dist/brep/handle-bridge.js.map +1 -1
- package/dist/brep/primitives-brep.js +2 -2
- package/dist/brep/primitives-brep.js.map +1 -1
- package/dist/brep/text/text-to-solid.d.ts +40 -3
- package/dist/brep/text/text-to-solid.d.ts.map +1 -1
- package/dist/brep/text/text-to-solid.js +104 -24
- package/dist/brep/text/text-to-solid.js.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.d.ts +2 -2
- package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.js +315 -36
- package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.js +7 -7
- package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
- package/dist/brepkit-kernel/multi-version-test.d.ts +2 -2
- package/dist/brepkit-kernel/multi-version-test.d.ts.map +1 -1
- package/dist/brepkit-kernel/multi-version-test.js +6 -6
- package/dist/brepkit-kernel/multi-version-test.js.map +1 -1
- package/dist/browser.d.ts +2 -3
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +1 -2
- package/dist/browser.js.map +1 -1
- package/dist/cad-runtime/admit-compat-lib.d.ts +9 -1
- package/dist/cad-runtime/admit-compat-lib.d.ts.map +1 -1
- package/dist/cad-runtime/admit-compat-lib.js +11 -1
- package/dist/cad-runtime/admit-compat-lib.js.map +1 -1
- package/dist/cad-runtime/browser-lib-loader.d.ts +16 -11
- package/dist/cad-runtime/browser-lib-loader.d.ts.map +1 -1
- package/dist/cad-runtime/browser-lib-loader.js +16 -8
- package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
- package/dist/cad-runtime/direct-executor.d.ts +62 -5
- package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
- package/dist/cad-runtime/direct-executor.js +617 -42
- package/dist/cad-runtime/direct-executor.js.map +1 -1
- package/dist/cad-runtime/interp/closure.d.ts +3 -2
- package/dist/cad-runtime/interp/closure.d.ts.map +1 -1
- package/dist/cad-runtime/interp/closure.js.map +1 -1
- package/dist/cad-runtime/interp/env.d.ts +9 -6
- package/dist/cad-runtime/interp/env.d.ts.map +1 -1
- package/dist/cad-runtime/interp/env.js +4 -2
- package/dist/cad-runtime/interp/env.js.map +1 -1
- package/dist/cad-runtime/lib-decl.d.ts +121 -0
- package/dist/cad-runtime/lib-decl.d.ts.map +1 -0
- package/dist/cad-runtime/lib-decl.js +100 -0
- package/dist/cad-runtime/lib-decl.js.map +1 -0
- package/dist/cad-runtime/ports.d.ts +12 -0
- package/dist/cad-runtime/ports.d.ts.map +1 -1
- package/dist/cad-runtime/ports.js.map +1 -1
- package/dist/cad-runtime/runtime.d.ts +59 -5
- package/dist/cad-runtime/runtime.d.ts.map +1 -1
- package/dist/cad-runtime/runtime.js +237 -18
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/extra/browser.d.ts +9 -0
- package/dist/extra/browser.d.ts.map +1 -0
- package/dist/extra/browser.js +9 -0
- package/dist/extra/browser.js.map +1 -0
- package/dist/extra/editor-ops.d.ts +22 -0
- package/dist/extra/editor-ops.d.ts.map +1 -0
- package/dist/extra/editor-ops.js +21 -0
- package/dist/extra/editor-ops.js.map +1 -0
- package/dist/extra/extras/svg-extrude.d.ts +45 -0
- package/dist/extra/extras/svg-extrude.d.ts.map +1 -0
- package/dist/extra/extras/svg-extrude.js +110 -0
- package/dist/extra/extras/svg-extrude.js.map +1 -0
- package/dist/extra/extras/text-cjk.d.ts +36 -0
- package/dist/extra/extras/text-cjk.d.ts.map +1 -0
- package/dist/extra/extras/text-cjk.js +86 -0
- package/dist/extra/extras/text-cjk.js.map +1 -0
- package/dist/extra/extras/text-geometry.d.ts +69 -0
- package/dist/extra/extras/text-geometry.d.ts.map +1 -0
- package/dist/extra/extras/text-geometry.js +188 -0
- package/dist/extra/extras/text-geometry.js.map +1 -0
- package/dist/extra/index.d.ts +40 -0
- package/dist/extra/index.d.ts.map +1 -0
- package/dist/extra/index.js +40 -0
- package/dist/extra/index.js.map +1 -0
- package/dist/extra/mesh/drill-hole/DrillHoleCore.d.ts +94 -0
- package/dist/extra/mesh/drill-hole/DrillHoleCore.d.ts.map +1 -0
- package/dist/extra/mesh/drill-hole/DrillHoleCore.js +282 -0
- package/dist/extra/mesh/drill-hole/DrillHoleCore.js.map +1 -0
- package/dist/extra/mesh/drill-hole/drill-types.d.ts +34 -0
- package/dist/extra/mesh/drill-hole/drill-types.d.ts.map +1 -0
- package/dist/extra/mesh/drill-hole/drill-types.js +7 -0
- package/dist/extra/mesh/drill-hole/drill-types.js.map +1 -0
- package/dist/extra/mesh/engrave-decoration.d.ts +42 -0
- package/dist/extra/mesh/engrave-decoration.d.ts.map +1 -0
- package/dist/extra/mesh/engrave-decoration.js +39 -0
- package/dist/extra/mesh/engrave-decoration.js.map +1 -0
- package/dist/extra/mesh/fai_drill.d.ts +21 -0
- package/dist/extra/mesh/fai_drill.d.ts.map +1 -0
- package/dist/extra/mesh/fai_drill.js +89 -0
- package/dist/extra/mesh/fai_drill.js.map +1 -0
- package/dist/extra/mesh/fai_extrude.d.ts +24 -0
- package/dist/extra/mesh/fai_extrude.d.ts.map +1 -0
- package/dist/extra/mesh/fai_extrude.js +42 -0
- package/dist/extra/mesh/fai_extrude.js.map +1 -0
- package/dist/extra/mesh/fai_split.d.ts +164 -0
- package/dist/extra/mesh/fai_split.d.ts.map +1 -0
- package/dist/extra/mesh/fai_split.js +269 -0
- package/dist/extra/mesh/fai_split.js.map +1 -0
- package/dist/extra/mesh/primitives.d.ts +29 -0
- package/dist/extra/mesh/primitives.d.ts.map +1 -0
- package/dist/extra/mesh/primitives.js +41 -0
- package/dist/extra/mesh/primitives.js.map +1 -0
- package/dist/extra/op-names.d.ts +37 -0
- package/dist/extra/op-names.d.ts.map +1 -0
- package/dist/extra/op-names.js +46 -0
- package/dist/extra/op-names.js.map +1 -0
- package/dist/extra/ops/compound.d.ts +140 -0
- package/dist/extra/ops/compound.d.ts.map +1 -0
- package/dist/extra/ops/compound.js +167 -0
- package/dist/extra/ops/compound.js.map +1 -0
- package/dist/extra/ops/copy.d.ts +40 -0
- package/dist/extra/ops/copy.d.ts.map +1 -0
- package/dist/extra/ops/copy.js +83 -0
- package/dist/extra/ops/copy.js.map +1 -0
- package/dist/extra/ops/fai_drill.d.ts +51 -0
- package/dist/extra/ops/fai_drill.d.ts.map +1 -0
- package/dist/extra/ops/fai_drill.js +233 -0
- package/dist/extra/ops/fai_drill.js.map +1 -0
- package/dist/extra/ops/fai_extrude.d.ts +36 -0
- package/dist/extra/ops/fai_extrude.d.ts.map +1 -0
- package/dist/extra/ops/fai_extrude.js +84 -0
- package/dist/extra/ops/fai_extrude.js.map +1 -0
- package/dist/extra/ops/fai_split.d.ts +46 -0
- package/dist/extra/ops/fai_split.d.ts.map +1 -0
- package/dist/extra/ops/fai_split.js +235 -0
- package/dist/extra/ops/fai_split.js.map +1 -0
- package/dist/extra/ops/load.d.ts +49 -0
- package/dist/extra/ops/load.d.ts.map +1 -0
- package/dist/extra/ops/load.js +385 -0
- package/dist/extra/ops/load.js.map +1 -0
- package/dist/extra/ops/svg-extrude.d.ts +32 -0
- package/dist/extra/ops/svg-extrude.d.ts.map +1 -0
- package/dist/extra/ops/svg-extrude.js +74 -0
- package/dist/extra/ops/svg-extrude.js.map +1 -0
- package/dist/extra/ops/text.d.ts +34 -0
- package/dist/extra/ops/text.d.ts.map +1 -0
- package/dist/extra/ops/text.js +100 -0
- package/dist/extra/ops/text.js.map +1 -0
- package/dist/geometry2d/bridge/lift-on-plane.d.ts +8 -5
- package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -1
- package/dist/geometry2d/bridge/lift-on-plane.js +8 -5
- package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/lang/symbol-table.d.ts +3 -3
- package/dist/lang/symbol-table.generated.d.ts +10 -0
- package/dist/lang/symbol-table.generated.d.ts.map +1 -1
- package/dist/lang/symbol-table.generated.js +10 -0
- package/dist/lang/symbol-table.generated.js.map +1 -1
- package/dist/lang/symbol-table.js +3 -3
- package/dist/lang/symbol-table.js.map +1 -1
- package/dist/math3d/index.d.ts +1 -1
- package/dist/math3d/index.js +1 -1
- package/dist/math3d/index.js.map +1 -1
- package/dist/mesh/engrave.d.ts +2 -3
- package/dist/mesh/engrave.d.ts.map +1 -1
- package/dist/mesh/engrave.js +4 -11
- package/dist/mesh/engrave.js.map +1 -1
- package/dist/mesh/index.d.ts +0 -2
- package/dist/mesh/index.d.ts.map +1 -1
- package/dist/mesh/index.js +0 -2
- package/dist/mesh/index.js.map +1 -1
- package/dist/mesh/primitives.d.ts +1 -1
- package/dist/mesh/primitives.js +1 -1
- package/dist/mesh/primitives.js.map +1 -1
- package/dist/node-host/cli.d.ts +11 -4
- package/dist/node-host/cli.d.ts.map +1 -1
- package/dist/node-host/cli.js +53 -28
- package/dist/node-host/cli.js.map +1 -1
- package/dist/node-host/execute-script.d.ts.map +1 -1
- package/dist/node-host/execute-script.js +3 -4
- package/dist/node-host/execute-script.js.map +1 -1
- package/dist/node-host/lib-package-json.d.ts +36 -0
- package/dist/node-host/lib-package-json.d.ts.map +1 -0
- package/dist/node-host/lib-package-json.js +73 -0
- package/dist/node-host/lib-package-json.js.map +1 -0
- package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
- package/dist/occt-kernel/occt-primitives.js +41 -0
- package/dist/occt-kernel/occt-primitives.js.map +1 -1
- package/dist/occt-kernel/occtKernel.d.ts +1 -1
- package/dist/occt-kernel/occtKernel.js +1 -1
- package/dist/occt-kernel/occtKernel.js.map +1 -1
- package/dist/runtime-state.d.ts +28 -1
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +14 -1
- package/dist/runtime-state.js.map +1 -1
- package/dist/sdk.d.ts +2 -2
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +11 -2
- package/dist/sdk.js.map +1 -1
- package/dist/sketch/bspline.d.ts +58 -0
- package/dist/sketch/bspline.d.ts.map +1 -0
- package/dist/sketch/bspline.js +104 -0
- package/dist/sketch/bspline.js.map +1 -0
- package/dist/sketch/canonical.d.ts +239 -0
- package/dist/sketch/canonical.d.ts.map +1 -0
- package/dist/sketch/canonical.js +17 -0
- package/dist/sketch/canonical.js.map +1 -0
- package/dist/sketch/contour.d.ts +43 -0
- package/dist/sketch/contour.d.ts.map +1 -0
- package/dist/sketch/contour.js +202 -0
- package/dist/sketch/contour.js.map +1 -0
- package/dist/sketch/dim-spec.d.ts +32 -0
- package/dist/sketch/dim-spec.d.ts.map +1 -0
- package/dist/sketch/dim-spec.js +112 -0
- package/dist/sketch/dim-spec.js.map +1 -0
- package/dist/sketch/faces.d.ts +45 -0
- package/dist/sketch/faces.d.ts.map +1 -0
- package/dist/sketch/faces.js +108 -0
- package/dist/sketch/faces.js.map +1 -0
- package/dist/sketch/fcstd-types.d.ts +194 -0
- package/dist/sketch/fcstd-types.d.ts.map +1 -0
- package/dist/sketch/fcstd-types.js +67 -0
- package/dist/sketch/fcstd-types.js.map +1 -0
- package/dist/sketch/index.d.ts +46 -0
- package/dist/sketch/index.d.ts.map +1 -0
- package/dist/sketch/index.js +39 -0
- package/dist/sketch/index.js.map +1 -0
- package/dist/sketch/node.d.ts +14 -0
- package/dist/sketch/node.d.ts.map +1 -0
- package/dist/sketch/node.js +43 -0
- package/dist/sketch/node.js.map +1 -0
- package/dist/sketch/op.d.ts +111 -0
- package/dist/sketch/op.d.ts.map +1 -0
- package/dist/sketch/op.js +185 -0
- package/dist/sketch/op.js.map +1 -0
- package/dist/sketch/planegcs-backend.d.ts +69 -0
- package/dist/sketch/planegcs-backend.d.ts.map +1 -0
- package/dist/sketch/planegcs-backend.js +812 -0
- package/dist/sketch/planegcs-backend.js.map +1 -0
- package/dist/sketch/project.d.ts +176 -0
- package/dist/sketch/project.d.ts.map +1 -0
- package/dist/sketch/project.js +656 -0
- package/dist/sketch/project.js.map +1 -0
- package/dist/sketch/shapes.d.ts +370 -0
- package/dist/sketch/shapes.d.ts.map +1 -0
- package/dist/sketch/shapes.js +959 -0
- package/dist/sketch/shapes.js.map +1 -0
- package/dist/sketch/solve.d.ts +21 -0
- package/dist/sketch/solve.d.ts.map +1 -0
- package/dist/sketch/solve.js +144 -0
- package/dist/sketch/solve.js.map +1 -0
- package/dist/sketch/solver-loader.d.ts +47 -0
- package/dist/sketch/solver-loader.d.ts.map +1 -0
- package/dist/sketch/solver-loader.js +77 -0
- package/dist/sketch/solver-loader.js.map +1 -0
- package/dist/sketch/solver.d.ts +63 -0
- package/dist/sketch/solver.d.ts.map +1 -0
- package/dist/sketch/solver.js +28 -0
- package/dist/sketch/solver.js.map +1 -0
- package/dist/sketch/verify.d.ts +53 -0
- package/dist/sketch/verify.d.ts.map +1 -0
- package/dist/sketch/verify.js +71 -0
- package/dist/sketch/verify.js.map +1 -0
- package/dist/weapp.d.ts +1 -1
- package/dist/weapp.d.ts.map +1 -1
- package/dist/weapp.js +1 -1
- package/dist/weapp.js.map +1 -1
- package/package.json +43 -11
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import type { Shape } from '../mesh/types.js';
|
|
13
13
|
import type { EdgeTopoRef } from '../topology/naming/index.js';
|
|
14
|
+
/** 单边选择:EdgeTopoRef(UI 拾取产物)或 CadQuery 边选择器字符串(AI 生成)。 */
|
|
15
|
+
export type FilletVariableEdge = EdgeTopoRef | string;
|
|
14
16
|
/**
|
|
15
17
|
* 变半径圆角:对单条边施加从起点到终点的线性变半径圆角。
|
|
16
18
|
* @group 特征
|
|
@@ -23,13 +25,15 @@ import type { EdgeTopoRef } from '../topology/naming/index.js';
|
|
|
23
25
|
* 仅 BREP 可用。
|
|
24
26
|
* @returns Shape 变半径圆角后的几何。
|
|
25
27
|
* @param input - 目标几何。type:Shape required:true
|
|
26
|
-
* @param edge -
|
|
28
|
+
* @param edge - 目标边:EdgeTopoRef(同 cad.fillet 的 edges 条目,UI 拾取产物)或 CadQuery 边选择器字符串(如 "|Z",AI 生成;多边命中抛错)。type:EdgeTopoRef|string required:true
|
|
27
29
|
* @param r1 - 起点半径(mm,>0)。type:number required:true
|
|
28
30
|
* @param r2 - 终点半径(mm,>0)。type:number required:true
|
|
29
31
|
* @example
|
|
30
32
|
* const v = await cad.filletVariable(part0, partEdges[0], 1, 4)
|
|
33
|
+
* // AI 生成可写 CadQuery 边选择器字符串
|
|
34
|
+
* const v2 = await cad.filletVariable(part0, "|Z", 1, 4)
|
|
31
35
|
*/
|
|
32
|
-
export declare const filletVariable: ((input: Shape, edge:
|
|
36
|
+
export declare const filletVariable: ((input: Shape, edge: FilletVariableEdge, r1: number, r2: number) => Promise<Shape>) & {
|
|
33
37
|
__faijs__dualOp?: import("../define-op.js").DualOpMeta;
|
|
34
38
|
};
|
|
35
39
|
//# sourceMappingURL=fillet-variable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fillet-variable.d.ts","sourceRoot":"","sources":["../../src/api/fillet-variable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAM1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"fillet-variable.d.ts","sourceRoot":"","sources":["../../src/api/fillet-variable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAM1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAMrD,0DAA0D;AAC1D,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,MAAM,CAAA;AAiDrD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,cAAc;;CAOzB,CAAA"}
|
|
@@ -15,12 +15,28 @@ import { brepOf, fromBrep } from '../shape.js';
|
|
|
15
15
|
import { defineOp } from '../sdk.js';
|
|
16
16
|
import { resolveTopoRef, TopoRefError } from '../topology/naming/index.js';
|
|
17
17
|
import { buildEdgeResolutionContext } from './topo-resolve.js';
|
|
18
|
+
import { resolveSelectorToEdgeRefs } from './selectors-to-refs.js';
|
|
18
19
|
/** BREP 路径:解析边引用 → L1 filletVariable → 收养。 */
|
|
19
20
|
function filletVariableBrep(input, edge, startRadius, endRadius) {
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
let edgeRef;
|
|
22
|
+
if (typeof edge === 'string') {
|
|
23
|
+
// 选择器字符串 → 解析;单边参数多命中 → 抛错(R3:不静默取第一个)。
|
|
24
|
+
const refs = resolveSelectorToEdgeRefs(input, edge);
|
|
25
|
+
if (refs.length === 0) {
|
|
26
|
+
throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `filletVariable: selector "${edge}" matched no edge`);
|
|
27
|
+
}
|
|
28
|
+
if (refs.length > 1) {
|
|
29
|
+
throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `filletVariable: selector "${edge}" matched ${refs.length} edges; filletVariable takes exactly one edge`);
|
|
30
|
+
}
|
|
31
|
+
edgeRef = refs[0];
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
edgeRef = edge;
|
|
35
|
+
}
|
|
36
|
+
if (!edgeRef || edgeRef.kind !== 'edge') {
|
|
37
|
+
throw new Error('E_FILLETVAR_BAD_EDGE_REF: edge must be an EdgeTopoRef (as consumed by cad.fillet) or a selector string');
|
|
22
38
|
}
|
|
23
|
-
const faces =
|
|
39
|
+
const faces = edgeRef.faces;
|
|
24
40
|
if (!Array.isArray(faces) || faces.length !== 2) {
|
|
25
41
|
throw new Error('E_FILLETVAR_BAD_EDGE_REF: EdgeTopoRef.faces must be a two-entry RoleQualifier pair');
|
|
26
42
|
}
|
|
@@ -36,9 +52,9 @@ function filletVariableBrep(input, edge, startRadius, endRadius) {
|
|
|
36
52
|
const ctx = buildEdgeResolutionContext(kernel, input);
|
|
37
53
|
if (!ctx)
|
|
38
54
|
throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', 'filletVariable: input has no BREP naming context');
|
|
39
|
-
const r = resolveTopoRef(
|
|
55
|
+
const r = resolveTopoRef(edgeRef, ctx);
|
|
40
56
|
if (r.handle === undefined) {
|
|
41
|
-
throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `filletVariable: edge resolved without handle (${
|
|
57
|
+
throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `filletVariable: edge resolved without handle (${edgeRef.faces[0].role}/${edgeRef.faces[1].role})`);
|
|
42
58
|
}
|
|
43
59
|
const result = kernel.filletVariable(solid, r.handle, startRadius, endRadius);
|
|
44
60
|
return fromBrep(solidToShape(kernel, result), { solid: result });
|
|
@@ -55,11 +71,13 @@ function filletVariableBrep(input, edge, startRadius, endRadius) {
|
|
|
55
71
|
* 仅 BREP 可用。
|
|
56
72
|
* @returns Shape 变半径圆角后的几何。
|
|
57
73
|
* @param input - 目标几何。type:Shape required:true
|
|
58
|
-
* @param edge -
|
|
74
|
+
* @param edge - 目标边:EdgeTopoRef(同 cad.fillet 的 edges 条目,UI 拾取产物)或 CadQuery 边选择器字符串(如 "|Z",AI 生成;多边命中抛错)。type:EdgeTopoRef|string required:true
|
|
59
75
|
* @param r1 - 起点半径(mm,>0)。type:number required:true
|
|
60
76
|
* @param r2 - 终点半径(mm,>0)。type:number required:true
|
|
61
77
|
* @example
|
|
62
78
|
* const v = await cad.filletVariable(part0, partEdges[0], 1, 4)
|
|
79
|
+
* // AI 生成可写 CadQuery 边选择器字符串
|
|
80
|
+
* const v2 = await cad.filletVariable(part0, "|Z", 1, 4)
|
|
63
81
|
*/
|
|
64
82
|
export const filletVariable = defineOp({
|
|
65
83
|
brep(input, edge, r1, r2) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fillet-variable.js","sourceRoot":"","sources":["../../src/api/fillet-variable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"fillet-variable.js","sourceRoot":"","sources":["../../src/api/fillet-variable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAA;AAK/D,8CAA8C;AAC9C,SAAS,kBAAkB,CAAC,KAAY,EAAE,IAAwB,EAAE,WAAmB,EAAE,SAAiB;IACxG,IAAI,OAAoB,CAAA;IACxB,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,wCAAwC;QACxC,MAAM,IAAI,GAAG,yBAAyB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACnD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,6BAA6B,IAAI,mBAAmB,CAAC,CAAA;QAC1G,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,YAAY,CACpB,kBAAkB,EAClB,MAAM,EACN,6BAA6B,IAAI,aAAa,IAAI,CAAC,MAAM,+CAA+C,CACzG,CAAA;QACH,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,IAAI,CAAA;IAChB,CAAC;IACD,IAAI,CAAC,OAAO,IAAK,OAA8B,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,wGAAwG,CAAC,CAAA;IAC3H,CAAC;IACD,MAAM,KAAK,GAAI,OAA+B,CAAC,KAAK,CAAA;IACpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC,CAAA;IACvG,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAA;QAC7F,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAA2B,CAAA;IACrD,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;IAEjG,MAAM,GAAG,GAAG,0BAA0B,CAAC,MAAM,EAAE,KAAe,CAAC,CAAA;IAC/D,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,kDAAkD,CAAC,CAAA;IAChH,MAAM,CAAC,GAAG,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IACtC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,iDAAiD,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAA;IACxJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,MAAoB,EAAE,WAAW,EAAE,SAAS,CAAC,CAAA;IAC3F,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;IACrC,IAAI,CAAC,KAAY,EAAE,IAAwB,EAAE,EAAU,EAAE,EAAU;QACjE,OAAO,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;IAChD,CAAC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE,EAAgB;IAE1E,SAAS,EAAE,EAAE;CACd,CAAC,CAAA","sourcesContent":["/**\n * api fillet-variable — 变半径圆角:单边起止半径(手写中立 op,Phase 5)\n *\n * 中立 op:L1 `filletVariable(solid, edge, startRadius, endRadius)` 在 occt 与\n * brepkit 两侧均有真实现(engine-method-map 实测 `dialect`)⇒ 走 `getBrepApi()`\n * (D12),不声明 engines(中立 op:实现只经 L1 契约面)。\n *\n * 这是 faijs 简化形态(单边 + 起止半径);旧版的 per-edge 回调形态\n * (`variableFillet`)维持 skip(状态化回调不可静态建模)。\n * 选边口径与 `fillet` 一致(EdgeTopoRef,faces 两面 role 线路)。\n */\n\nimport type { Shape } from '../mesh/types'\nimport type { BrepHandle } from '../brep/engine/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { brepOf, fromBrep } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { EdgeTopoRef } from '../topology/naming'\nimport { resolveTopoRef, TopoRefError } from '../topology/naming'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { buildEdgeResolutionContext } from './topo-resolve'\nimport { resolveSelectorToEdgeRefs } from './selectors-to-refs'\n\n/** 单边选择:EdgeTopoRef(UI 拾取产物)或 CadQuery 边选择器字符串(AI 生成)。 */\nexport type FilletVariableEdge = EdgeTopoRef | string\n\n/** BREP 路径:解析边引用 → L1 filletVariable → 收养。 */\nfunction filletVariableBrep(input: Shape, edge: FilletVariableEdge, startRadius: number, endRadius: number): Shape {\n let edgeRef: EdgeTopoRef\n if (typeof edge === 'string') {\n // 选择器字符串 → 解析;单边参数多命中 → 抛错(R3:不静默取第一个)。\n const refs = resolveSelectorToEdgeRefs(input, edge)\n if (refs.length === 0) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `filletVariable: selector \"${edge}\" matched no edge`)\n }\n if (refs.length > 1) {\n throw new TopoRefError(\n 'E_TOPO_NOT_FOUND',\n 'edge',\n `filletVariable: selector \"${edge}\" matched ${refs.length} edges; filletVariable takes exactly one edge`,\n )\n }\n edgeRef = refs[0]\n } else {\n edgeRef = edge\n }\n if (!edgeRef || (edgeRef as { kind?: unknown }).kind !== 'edge') {\n throw new Error('E_FILLETVAR_BAD_EDGE_REF: edge must be an EdgeTopoRef (as consumed by cad.fillet) or a selector string')\n }\n const faces = (edgeRef as { faces?: unknown }).faces\n if (!Array.isArray(faces) || faces.length !== 2) {\n throw new Error('E_FILLETVAR_BAD_EDGE_REF: EdgeTopoRef.faces must be a two-entry RoleQualifier pair')\n }\n for (const r of [startRadius, endRadius]) {\n if (typeof r !== 'number' || !Number.isFinite(r) || r <= 0) {\n throw new Error('E_FILLETVAR_BAD_RADIUS: startRadius / endRadius must be positive numbers')\n }\n }\n const kernel = getBrepApi()\n const solid = brepOf(input) as BrepHandle | undefined\n if (solid === undefined) throw new Error('E_FILLETVAR_NO_BREP: filletVariable input is not BREP')\n\n const ctx = buildEdgeResolutionContext(kernel, input as object)\n if (!ctx) throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', 'filletVariable: input has no BREP naming context')\n const r = resolveTopoRef(edgeRef, ctx)\n if (r.handle === undefined) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `filletVariable: edge resolved without handle (${edgeRef.faces[0].role}/${edgeRef.faces[1].role})`)\n }\n\n const result = kernel.filletVariable(solid, r.handle as BrepHandle, startRadius, endRadius)\n return fromBrep(solidToShape(kernel, result), { solid: result })\n}\n\n/**\n * 变半径圆角:对单条边施加从起点到终点的线性变半径圆角。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name filletVariable\n * @note 中立 op:L1 filletVariable 两引擎同实现。`r1 == r2` 时与 cad.fillet 等半径\n * 结果等价。旧版的 per-edge 回调变半径(variableFillet)不上脚本面。\n * 仅 BREP 可用。\n * @returns Shape 变半径圆角后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param edge - 目标边:EdgeTopoRef(同 cad.fillet 的 edges 条目,UI 拾取产物)或 CadQuery 边选择器字符串(如 \"|Z\",AI 生成;多边命中抛错)。type:EdgeTopoRef|string required:true\n * @param r1 - 起点半径(mm,>0)。type:number required:true\n * @param r2 - 终点半径(mm,>0)。type:number required:true\n * @example\n * const v = await cad.filletVariable(part0, partEdges[0], 1, 4)\n * // AI 生成可写 CadQuery 边选择器字符串\n * const v2 = await cad.filletVariable(part0, \"|Z\", 1, 4)\n */\nexport const filletVariable = defineOp({\n brep(input: Shape, edge: FilletVariableEdge, r1: number, r2: number) {\n return filletVariableBrep(input, edge, r1, r2)\n },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n"]}
|
package/dist/api/fillet.d.ts
CHANGED
|
@@ -31,9 +31,10 @@ export interface EdgeSelectorCheckOptions {
|
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Validate fillet parameters: `edges` must be a non-empty array of EdgeTopoRef
|
|
34
|
-
* (each with kind key "edge" and a two-entry faces pair)
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
* (each with kind key "edge" and a two-entry faces pair) or of selector strings
|
|
35
|
+
* (`"|Z"` etc., precision chain) — or of 1-based ordinals when
|
|
36
|
+
* `opts.allowOrdinals` (the mesh chain); a top-level selector string is also
|
|
37
|
+
* accepted. `radius` must be a positive number (M1: uniform radius only).
|
|
37
38
|
* @param params the raw fillet operation parameters.
|
|
38
39
|
* @param opts the selector-form options (mesh chain allows ordinals).
|
|
39
40
|
*/
|
|
@@ -55,10 +56,12 @@ export declare function assertFilletParams(params: Record<string, unknown>, opts
|
|
|
55
56
|
* 序号(近似拓扑 `edges` 数组下标 + 1)指认。
|
|
56
57
|
* @returns Shape 圆角后的几何。
|
|
57
58
|
* @param input - 目标几何。type:Shape required:true
|
|
58
|
-
* @param params.edges -
|
|
59
|
+
* @param params.edges - 参与圆角的边:CadQuery 边选择器字符串(如 "|Z",AI 生成)或相邻两面的 role 线路(EdgeTopoRef[],UI 拾取产物);网格链上也可用 1 起序号。type:EdgeTopoRef[]|string required:true
|
|
59
60
|
* @param params.radius - 圆角半径(mm,>0)。type:number required:true
|
|
60
61
|
* @example
|
|
61
62
|
* const p = await cad.fillet(part0, { edges: [{ kind:'edge', faces:[{ origin:'box', role:'box:top' }, { origin:'box', role:'box:front' }], hint:{ kind:'edge' } }], radius:2 })
|
|
63
|
+
* // AI 生成可写 CadQuery 边选择器字符串("|Z" 切线平行 Z 的边)
|
|
64
|
+
* const p2 = await cad.fillet(part0, { edges: "|Z", radius: 2 })
|
|
62
65
|
* const q = await cad.fillet(meshPart, { edges: [3], radius: 1 })
|
|
63
66
|
*/
|
|
64
67
|
export declare const fillet: ((input: Shape, params: Record<string, unknown>) => Promise<Shape>) & {
|
package/dist/api/fillet.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fillet.d.ts","sourceRoot":"","sources":["../../src/api/fillet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"fillet.d.ts","sourceRoot":"","sources":["../../src/api/fillet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAiB1C,gBAAgB;AAChB,MAAM,WAAW,wBAAwB;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CACjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,CAAC,EAAE,wBAAwB,GAC9B,IAAI,CA+BN;AAgID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,MAAM;;CAmBjB,CAAA"}
|
package/dist/api/fillet.js
CHANGED
|
@@ -20,32 +20,41 @@
|
|
|
20
20
|
import { solidToShape } from '../brep/brep-ops.js';
|
|
21
21
|
import { filletWithRoleTable } from '../brep/face-evolution.js';
|
|
22
22
|
import { getBrepApi } from '../brep/handle-bridge.js';
|
|
23
|
-
import { getCurrentStmt } from '../runtime-state.js';
|
|
24
|
-
import { fromBrep, brepOf, inputRoleTable } from '../shape.js';
|
|
23
|
+
import { getCurrentStmt, nameOf, setName } from '../runtime-state.js';
|
|
24
|
+
import { fromBrep, brepOf, inputRoleTable, resolveCompoundMember, replaceCompoundMember } from '../shape.js';
|
|
25
25
|
import { defineOp } from '../sdk.js';
|
|
26
26
|
import { resolveTopoRef, TopoRefError } from '../topology/naming/index.js';
|
|
27
27
|
import { buildEdgeResolutionContext } from './topo-resolve.js';
|
|
28
|
+
import { expandEdgeSelectorRefs } from './selectors-to-refs.js';
|
|
28
29
|
import { meshKernelFailure, meshSolidEntry, meshSolidProduct, resolveMeshEdges } from './internal/mesh-solid-op.js';
|
|
29
30
|
/**
|
|
30
31
|
* Validate fillet parameters: `edges` must be a non-empty array of EdgeTopoRef
|
|
31
|
-
* (each with kind key "edge" and a two-entry faces pair)
|
|
32
|
-
*
|
|
33
|
-
*
|
|
32
|
+
* (each with kind key "edge" and a two-entry faces pair) or of selector strings
|
|
33
|
+
* (`"|Z"` etc., precision chain) — or of 1-based ordinals when
|
|
34
|
+
* `opts.allowOrdinals` (the mesh chain); a top-level selector string is also
|
|
35
|
+
* accepted. `radius` must be a positive number (M1: uniform radius only).
|
|
34
36
|
* @param params the raw fillet operation parameters.
|
|
35
37
|
* @param opts the selector-form options (mesh chain allows ordinals).
|
|
36
38
|
*/
|
|
37
39
|
export function assertFilletParams(params, opts) {
|
|
38
40
|
const edges = params.edges;
|
|
39
|
-
|
|
41
|
+
const list = typeof edges === 'string' ? [edges] : edges;
|
|
42
|
+
if (typeof edges !== 'string' && (!Array.isArray(edges) || list.length === 0)) {
|
|
40
43
|
throw new Error('E_FILLET_NO_EDGES: fillet requires at least one edge');
|
|
41
44
|
}
|
|
42
|
-
for (const e of
|
|
45
|
+
for (const e of list) {
|
|
43
46
|
if (opts?.allowOrdinals && typeof e === 'number') {
|
|
44
47
|
if (!Number.isInteger(e) || e < 1) {
|
|
45
48
|
throw new Error('E_FILLET_BAD_EDGE_REF: an edge ordinal must be a positive integer (1-based)');
|
|
46
49
|
}
|
|
47
50
|
continue;
|
|
48
51
|
}
|
|
52
|
+
if (typeof e === 'string') {
|
|
53
|
+
if (e.trim() === '') {
|
|
54
|
+
throw new Error('E_FILLET_BAD_EDGE_REF: an edge selector string must not be empty');
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
49
58
|
if (!e || typeof e !== 'object' || e.kind !== 'edge') {
|
|
50
59
|
throw new Error('E_FILLET_BAD_EDGE_REF: every edge entry must be an EdgeTopoRef with kind:"edge"');
|
|
51
60
|
}
|
|
@@ -91,8 +100,8 @@ function filletBrep(input, params) {
|
|
|
91
100
|
const ctx = buildEdgeResolutionContext(kernel, input);
|
|
92
101
|
if (!ctx)
|
|
93
102
|
throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', 'fillet: input has no edge naming context');
|
|
94
|
-
//
|
|
95
|
-
const edgeHandles = edges.map((e) => resolveEdge(ctx, e));
|
|
103
|
+
// 展开选择器字符串 → EdgeTopoRef[],再解析所有 EdgeTopoRef → Edge 句柄
|
|
104
|
+
const edgeHandles = expandEdgeSelectorRefs(input, edges).map((e) => resolveEdge(ctx, e));
|
|
96
105
|
// 输入 roleTable + outStmt(与 boolean.ts 同构)。Phase 1.6:origin=本次语句 StmtId。
|
|
97
106
|
const inputTable = inputRoleTable(input);
|
|
98
107
|
const outStmt = String(getCurrentStmt()?.id ?? '');
|
|
@@ -135,6 +144,10 @@ function filletMeshSolid(input, params) {
|
|
|
135
144
|
const edges = params.edges;
|
|
136
145
|
const radius = params.radius;
|
|
137
146
|
const entry = meshSolidEntry(input, 'fillet');
|
|
147
|
+
// 选择器字符串只服务精度链(网格零件无 role 层);网格链用 1 起序号。
|
|
148
|
+
if (typeof edges === 'string' || edges.some((e) => typeof e === 'string')) {
|
|
149
|
+
throw new TopoRefError('E_TOPO_MESH_UNSUPPORTED', 'edge', 'fillet: selector strings are precision-chain only — mesh solids have no role layer (use 1-based edge ordinals)');
|
|
150
|
+
}
|
|
138
151
|
const edgeHandles = resolveMeshEdges(entry, edges, 'fillet');
|
|
139
152
|
let result;
|
|
140
153
|
try {
|
|
@@ -145,6 +158,18 @@ function filletMeshSolid(input, params) {
|
|
|
145
158
|
}
|
|
146
159
|
return meshSolidProduct(entry, result);
|
|
147
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* 多零件 compound 成员是匿名 Shape:其面 role 记录在父 compound 的 part 键合并表里。
|
|
163
|
+
* 解包后让 target 继承父 part 名,buildEdgeResolutionContext/inputRoleTable 才能按
|
|
164
|
+
* part 名查到表(与 chamfer 同构)。单零件路径 input===target 已命名,守卫使其空转。
|
|
165
|
+
*/
|
|
166
|
+
function adoptParentPartName(input, target) {
|
|
167
|
+
if (target === input)
|
|
168
|
+
return;
|
|
169
|
+
const parentName = nameOf(input);
|
|
170
|
+
if (parentName && !nameOf(target))
|
|
171
|
+
setName(target, parentName);
|
|
172
|
+
}
|
|
148
173
|
/**
|
|
149
174
|
* 在几何体上做圆角(等半径)。
|
|
150
175
|
*
|
|
@@ -162,21 +187,29 @@ function filletMeshSolid(input, params) {
|
|
|
162
187
|
* 序号(近似拓扑 `edges` 数组下标 + 1)指认。
|
|
163
188
|
* @returns Shape 圆角后的几何。
|
|
164
189
|
* @param input - 目标几何。type:Shape required:true
|
|
165
|
-
* @param params.edges -
|
|
190
|
+
* @param params.edges - 参与圆角的边:CadQuery 边选择器字符串(如 "|Z",AI 生成)或相邻两面的 role 线路(EdgeTopoRef[],UI 拾取产物);网格链上也可用 1 起序号。type:EdgeTopoRef[]|string required:true
|
|
166
191
|
* @param params.radius - 圆角半径(mm,>0)。type:number required:true
|
|
167
192
|
* @example
|
|
168
193
|
* const p = await cad.fillet(part0, { edges: [{ kind:'edge', faces:[{ origin:'box', role:'box:top' }, { origin:'box', role:'box:front' }], hint:{ kind:'edge' } }], radius:2 })
|
|
194
|
+
* // AI 生成可写 CadQuery 边选择器字符串("|Z" 切线平行 Z 的边)
|
|
195
|
+
* const p2 = await cad.fillet(part0, { edges: "|Z", radius: 2 })
|
|
169
196
|
* const q = await cad.fillet(meshPart, { edges: [3], radius: 1 })
|
|
170
197
|
*/
|
|
171
198
|
export const fillet = defineOp({
|
|
172
199
|
meshEngines: ['brepkit'],
|
|
173
200
|
mesh(input, params) {
|
|
174
201
|
assertFilletParams(params, { allowOrdinals: true });
|
|
175
|
-
|
|
202
|
+
// P2:多零件 load 输入是 compound——按 partIndex 取目标成员,结果替换回原 compound。
|
|
203
|
+
const target = resolveCompoundMember(input, params.partIndex, 'fillet');
|
|
204
|
+
const result = filletMeshSolid(target, params);
|
|
205
|
+
return replaceCompoundMember(input, params.partIndex, result);
|
|
176
206
|
},
|
|
177
207
|
brep(input, params) {
|
|
178
208
|
assertFilletParams(params);
|
|
179
|
-
|
|
209
|
+
const target = resolveCompoundMember(input, params.partIndex, 'fillet');
|
|
210
|
+
adoptParentPartName(input, target);
|
|
211
|
+
const result = filletBrep(target, params);
|
|
212
|
+
return replaceCompoundMember(input, params.partIndex, result);
|
|
180
213
|
},
|
|
181
214
|
naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
|
|
182
215
|
paramDims: {},
|
package/dist/api/fillet.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fillet.js","sourceRoot":"","sources":["../../src/api/fillet.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api fillet — fillet 圆角库函数(BREP-only)\n *\n * 平台分层(narrowing plan Phase 5,D11):**中立 op**——`filletWithHistory` 是\n * L1 核心面(brepkit 亦实现),实现全程走 L1(getBrepApi,D12),不声明 engines。\n * 实现体内不分支:两引擎都走 `filletWithRoleTable` 历史轨(见 `filletBrep`)。\n *\n * 与 chamfer 的差异:fillet 用 filletWithHistory 走面演化 + roleTable 传播\n * (chamfer 在 P5 同步改造)。M1 只支持等半径;M2 计划支持变半径与几何限定符。\n *\n * M1:\n * - 等半径(number):kernel.filletWithHistory(solid, edges, radius, hashes, bound)\n * - 走 filletWithRoleTable 传播 roleTable\n * - BREP-only:mesh 输入 → E_MESH_UNSUPPORTED(backend-dispatch 静态判定)\n *\n * M2(未实施):\n * - 变半径 [r1, r2]:filletVariable + 单边 + 不产 roleTable(降级)\n * - 几何限定符字符串选边(§4)\n */\n\nimport type { Shape } from '../mesh/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { filletWithRoleTable } from '../brep/face-evolution'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { getCurrentStmt } from '../runtime-state'\nimport { fromBrep, brepOf, inputRoleTable } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { BrepHandle } from '../brep/engine/types'\nimport type { EdgeTopoRef, ResolutionContext } from '../topology/naming'\nimport { resolveTopoRef, TopoRefError } from '../topology/naming'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { buildEdgeResolutionContext } from './topo-resolve'\nimport { meshKernelFailure, meshSolidEntry, meshSolidProduct, resolveMeshEdges } from './internal/mesh-solid-op'\n\n// ── 参数自校验(api 层被直接 import 时的防御层)──\n\n/** 边选择器校验选项。 */\nexport interface EdgeSelectorCheckOptions {\n /**\n * 允许 1 起序号作为边选择器(**仅网格链**;见 `resolveMeshEdges`)。\n *\n * 精度链不开这个口子:BREP 的边身份是 role 线路(两个相邻面的 `(origin, role)`),\n * 序号只是内核枚举序,跨特征会漂移——让精度链接受序号等于把\"可重放的引用\"降级成\n * \"这次跑出来的下标\"。近似链相反:没有 role 层,序号是唯一无歧义的指认方式。\n */\n readonly allowOrdinals?: boolean\n}\n\n/**\n * Validate fillet parameters: `edges` must be a non-empty array of EdgeTopoRef\n * (each with kind key \"edge\" and a two-entry faces pair) — or of 1-based\n * ordinals when `opts.allowOrdinals` (the mesh chain); `radius` must be a\n * positive number (M1: uniform radius only).\n * @param params the raw fillet operation parameters.\n * @param opts the selector-form options (mesh chain allows ordinals).\n */\nexport function assertFilletParams(\n params: Record<string, unknown>,\n opts?: EdgeSelectorCheckOptions,\n): void {\n const edges = params.edges\n if (!Array.isArray(edges) || edges.length === 0) {\n throw new Error('E_FILLET_NO_EDGES: fillet requires at least one edge')\n }\n for (const e of edges) {\n if (opts?.allowOrdinals && typeof e === 'number') {\n if (!Number.isInteger(e) || e < 1) {\n throw new Error('E_FILLET_BAD_EDGE_REF: an edge ordinal must be a positive integer (1-based)')\n }\n continue\n }\n if (!e || typeof e !== 'object' || (e as { kind?: unknown }).kind !== 'edge') {\n throw new Error('E_FILLET_BAD_EDGE_REF: every edge entry must be an EdgeTopoRef with kind:\"edge\"')\n }\n const faces = (e as { faces?: unknown }).faces\n if (!Array.isArray(faces) || faces.length !== 2) {\n throw new Error('E_FILLET_BAD_EDGE_REF: EdgeTopoRef.faces must be a two-entry RoleQualifier pair')\n }\n }\n const radius = params.radius\n if (typeof radius !== 'number' || !Number.isFinite(radius) || radius <= 0) {\n throw new Error('E_FILLET_BAD_RADIUS: fillet.radius must be a positive number')\n }\n}\n\n/** 解析一条 EdgeTopoRef → handle;失败抛命名层 TopoRefError。 */\nfunction resolveEdge(ctx: ResolutionContext, ref: EdgeTopoRef): BrepHandle {\n const r = resolveTopoRef(ref, ctx)\n if (r.handle === undefined) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `fillet: edge resolved without handle (${ref.faces[0].role}/${ref.faces[1].role})`)\n }\n return r.handle as BrepHandle\n}\n\n/**\n * 把内核 OcctError 回译成 E_FILLET_RADIUS_TOO_LARGE。\n *\n * OCCT 在半径超过邻面尺寸、三面交汇处、凹边处都可能失败。\n * 绝不可静默返回未圆角的原形状(§9 风险)。\n */\nfunction translateOcctError(err: unknown): Error {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('E_FILLET') || msg.includes('E_TOPO')) return err as Error\n return new Error(`E_FILLET_RADIUS_TOO_LARGE: OCCT fillet failed — ${msg}`)\n}\n\n/** BREP-only 主入口(M1 等半径 flow)。 */\nfunction filletBrep(input: Shape, params: Record<string, unknown>): Shape {\n // L1 面(D12):filletWithHistory 是 L1,全链路中立。\n const kernel = getBrepApi()\n const solid = brepOf(input) as BrepHandle | undefined\n if (solid === undefined) throw new Error('E_FILLET_NO_BREP: fillet input is not BREP')\n\n const edges = params.edges as EdgeTopoRef[]\n const radius = params.radius as number\n const ctx = buildEdgeResolutionContext(kernel, input as object)\n if (!ctx) throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', 'fillet: input has no edge naming context')\n\n // 解析所有 EdgeTopoRef → Edge 句柄\n const edgeHandles = edges.map((e) => resolveEdge(ctx, e))\n\n // 输入 roleTable + outStmt(与 boolean.ts 同构)。Phase 1.6:origin=本次语句 StmtId。\n const inputTable = inputRoleTable(input) as ReadonlyMap<unknown, unknown> | undefined\n const outStmt = String(getCurrentStmt()?.id ?? '')\n\n let resultSolid: BrepHandle\n let faceEvolution: Map<number, number[]> | undefined\n let roleTable: ReadonlyMap<unknown, unknown> | undefined\n\n try {\n const r = filletWithRoleTable(\n kernel,\n solid,\n edgeHandles,\n radius,\n inputTable ?? new Map(),\n outStmt,\n )\n resultSolid = r.result\n faceEvolution = r.faceEvolution\n roleTable = r.roleTable\n } catch (err) {\n throw translateOcctError(err)\n }\n\n return fromBrep(\n solidToShape(kernel, resultSolid),\n { solid: resultSolid, faceEvolution, roleTable },\n )\n}\n\n/**\n * 网格实体路径:对近似拓扑里识别出的边倒圆角(方案 2026-10-01 §3.5 三明治)。\n *\n * 与 BREP 路径的三处实质差异,都是\"网格零件没有精度链、没有 role 层\"的直接后果:\n * - 边**按几何或序号**解析:`EdgeTopoRef` 走长度/中点匹配;**1 起序号**直接取自近似\n * 拓扑的 `edges` 数组下标 + 1(等长边靠几何分不开,序号是唯一无歧义的指认方式);\n * - 内核调用走 L1 裸 `kernel.fillet`(`filletWithHistory` 是精度链的面演化能力,\n * 近似拓扑没有 hash 演化可言,故**不产生** faceEvolution / roleTable,如实缺席\n * 而不是造一张恒等映射);\n * - 产物句柄写回后由 `meshSolidProduct` 重新三角化并重建近似拓扑。\n *\n * GOTCHA(2026-10-01 实测,见 `brepkit-kernel/mesh-solid-topology.test.ts`):\n * 一次请求里的**全部**边交给内核,会在共面边链(如圆柱端盖的 64 条边)上被整体\n * 拒绝——不是单条边不可倒,而是\"一次性磨圆会自交\"。故本实现**如实失败**,不自动\n * 拆成逐边重试(运行时换策略会掩盖几何事实)。要给共面边链倒角,请分多次调用,\n * 每次一组几何上互不相邻的边。\n *\n * @param input - the mesh-solid input.\n * @param params - the validated fillet parameters.\n * @returns the filleted mesh solid as a new mesh part.\n */\nfunction filletMeshSolid(input: Shape, params: Record<string, unknown>): Shape {\n const edges = params.edges as (number | EdgeTopoRef)[]\n const radius = params.radius as number\n const entry = meshSolidEntry(input, 'fillet')\n const edgeHandles = resolveMeshEdges(entry, edges, 'fillet')\n\n let result: BrepHandle\n try {\n result = entry.kernel.fillet(entry.solid, edgeHandles, radius)\n } catch (cause) {\n throw meshKernelFailure(\n 'fillet',\n 'E_FILLET_RADIUS_TOO_LARGE',\n `fillet(r=${radius}) on ${edgeHandles.length} edge(s)`,\n cause,\n )\n }\n return meshSolidProduct(entry, result)\n}\n\n/**\n * 在几何体上做圆角(等半径)。\n *\n * 两条路径都以 `meshEngines: ['brepkit']` 之外的事实为界:BREP 输入走\n * `filletWithHistory`(带面演化与 roleTable 传播);**网格实体**输入走网格后端\n * (近似拓扑无 role,边按几何或序号解析,无面演化)。非 BREP 的**裸网格**输入仍抛\n * `E_MESH_SOLID_UNSUPPORTED`——裸网格没有近似拓扑,没有边可选。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name fillet\n * @note `radius` 为正数(mm)。BREP 路径圆角后 roleTable 经 filletWithHistory 传播,\n * 后续特征仍可按 role 选面/选边;网格实体路径没有 role 层,边只能按几何或\n * 序号(近似拓扑 `edges` 数组下标 + 1)指认。\n * @returns Shape 圆角后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.edges - 参与圆角的边:相邻两面的 role 线路(EdgeTopoRef[]);网格链上也可用 1 起序号。type:EdgeTopoRef[] required:true\n * @param params.radius - 圆角半径(mm,>0)。type:number required:true\n * @example\n * const p = await cad.fillet(part0, { edges: [{ kind:'edge', faces:[{ origin:'box', role:'box:top' }, { origin:'box', role:'box:front' }], hint:{ kind:'edge' } }], radius:2 })\n * const q = await cad.fillet(meshPart, { edges: [3], radius: 1 })\n */\nexport const fillet = defineOp({\n meshEngines: ['brepkit'],\n mesh(input: Shape, params: Record<string, unknown>) {\n assertFilletParams(params, { allowOrdinals: true })\n return filletMeshSolid(input, params)\n },\n brep(input: Shape, params: Record<string, unknown>) {\n assertFilletParams(params)\n return filletBrep(input, params)\n },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n"]}
|
|
1
|
+
{"version":3,"file":"fillet.js","sourceRoot":"","sources":["../../src/api/fillet.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api fillet — fillet 圆角库函数(BREP-only)\n *\n * 平台分层(narrowing plan Phase 5,D11):**中立 op**——`filletWithHistory` 是\n * L1 核心面(brepkit 亦实现),实现全程走 L1(getBrepApi,D12),不声明 engines。\n * 实现体内不分支:两引擎都走 `filletWithRoleTable` 历史轨(见 `filletBrep`)。\n *\n * 与 chamfer 的差异:fillet 用 filletWithHistory 走面演化 + roleTable 传播\n * (chamfer 在 P5 同步改造)。M1 只支持等半径;M2 计划支持变半径与几何限定符。\n *\n * M1:\n * - 等半径(number):kernel.filletWithHistory(solid, edges, radius, hashes, bound)\n * - 走 filletWithRoleTable 传播 roleTable\n * - BREP-only:mesh 输入 → E_MESH_UNSUPPORTED(backend-dispatch 静态判定)\n *\n * M2(未实施):\n * - 变半径 [r1, r2]:filletVariable + 单边 + 不产 roleTable(降级)\n * - 几何限定符字符串选边(§4)\n */\n\nimport type { Shape } from '../mesh/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { filletWithRoleTable } from '../brep/face-evolution'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { getCurrentStmt, nameOf, setName } from '../runtime-state'\nimport { fromBrep, brepOf, inputRoleTable, resolveCompoundMember, replaceCompoundMember } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { BrepHandle } from '../brep/engine/types'\nimport type { EdgeTopoRef, ResolutionContext } from '../topology/naming'\nimport { resolveTopoRef, TopoRefError } from '../topology/naming'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { buildEdgeResolutionContext } from './topo-resolve'\nimport { expandEdgeSelectorRefs } from './selectors-to-refs'\nimport { meshKernelFailure, meshSolidEntry, meshSolidProduct, resolveMeshEdges } from './internal/mesh-solid-op'\n\n// ── 参数自校验(api 层被直接 import 时的防御层)──\n\n/** 边选择器校验选项。 */\nexport interface EdgeSelectorCheckOptions {\n /**\n * 允许 1 起序号作为边选择器(**仅网格链**;见 `resolveMeshEdges`)。\n *\n * 精度链不开这个口子:BREP 的边身份是 role 线路(两个相邻面的 `(origin, role)`),\n * 序号只是内核枚举序,跨特征会漂移——让精度链接受序号等于把\"可重放的引用\"降级成\n * \"这次跑出来的下标\"。近似链相反:没有 role 层,序号是唯一无歧义的指认方式。\n */\n readonly allowOrdinals?: boolean\n}\n\n/**\n * Validate fillet parameters: `edges` must be a non-empty array of EdgeTopoRef\n * (each with kind key \"edge\" and a two-entry faces pair) or of selector strings\n * (`\"|Z\"` etc., precision chain) — or of 1-based ordinals when\n * `opts.allowOrdinals` (the mesh chain); a top-level selector string is also\n * accepted. `radius` must be a positive number (M1: uniform radius only).\n * @param params the raw fillet operation parameters.\n * @param opts the selector-form options (mesh chain allows ordinals).\n */\nexport function assertFilletParams(\n params: Record<string, unknown>,\n opts?: EdgeSelectorCheckOptions,\n): void {\n const edges = params.edges\n const list = typeof edges === 'string' ? [edges] : (edges as unknown[])\n if (typeof edges !== 'string' && (!Array.isArray(edges) || list.length === 0)) {\n throw new Error('E_FILLET_NO_EDGES: fillet requires at least one edge')\n }\n for (const e of list) {\n if (opts?.allowOrdinals && typeof e === 'number') {\n if (!Number.isInteger(e) || e < 1) {\n throw new Error('E_FILLET_BAD_EDGE_REF: an edge ordinal must be a positive integer (1-based)')\n }\n continue\n }\n if (typeof e === 'string') {\n if (e.trim() === '') {\n throw new Error('E_FILLET_BAD_EDGE_REF: an edge selector string must not be empty')\n }\n continue\n }\n if (!e || typeof e !== 'object' || (e as { kind?: unknown }).kind !== 'edge') {\n throw new Error('E_FILLET_BAD_EDGE_REF: every edge entry must be an EdgeTopoRef with kind:\"edge\"')\n }\n const faces = (e as { faces?: unknown }).faces\n if (!Array.isArray(faces) || faces.length !== 2) {\n throw new Error('E_FILLET_BAD_EDGE_REF: EdgeTopoRef.faces must be a two-entry RoleQualifier pair')\n }\n }\n const radius = params.radius\n if (typeof radius !== 'number' || !Number.isFinite(radius) || radius <= 0) {\n throw new Error('E_FILLET_BAD_RADIUS: fillet.radius must be a positive number')\n }\n}\n\n/** 解析一条 EdgeTopoRef → handle;失败抛命名层 TopoRefError。 */\nfunction resolveEdge(ctx: ResolutionContext, ref: EdgeTopoRef): BrepHandle {\n const r = resolveTopoRef(ref, ctx)\n if (r.handle === undefined) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `fillet: edge resolved without handle (${ref.faces[0].role}/${ref.faces[1].role})`)\n }\n return r.handle as BrepHandle\n}\n\n/**\n * 把内核 OcctError 回译成 E_FILLET_RADIUS_TOO_LARGE。\n *\n * OCCT 在半径超过邻面尺寸、三面交汇处、凹边处都可能失败。\n * 绝不可静默返回未圆角的原形状(§9 风险)。\n */\nfunction translateOcctError(err: unknown): Error {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('E_FILLET') || msg.includes('E_TOPO')) return err as Error\n return new Error(`E_FILLET_RADIUS_TOO_LARGE: OCCT fillet failed — ${msg}`)\n}\n\n/** BREP-only 主入口(M1 等半径 flow)。 */\nfunction filletBrep(input: Shape, params: Record<string, unknown>): Shape {\n // L1 面(D12):filletWithHistory 是 L1,全链路中立。\n const kernel = getBrepApi()\n const solid = brepOf(input) as BrepHandle | undefined\n if (solid === undefined) throw new Error('E_FILLET_NO_BREP: fillet input is not BREP')\n\n const edges = params.edges as EdgeTopoRef[] | string\n const radius = params.radius as number\n const ctx = buildEdgeResolutionContext(kernel, input as object)\n if (!ctx) throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', 'fillet: input has no edge naming context')\n\n // 展开选择器字符串 → EdgeTopoRef[],再解析所有 EdgeTopoRef → Edge 句柄\n const edgeHandles = expandEdgeSelectorRefs(input, edges).map((e) => resolveEdge(ctx, e))\n\n // 输入 roleTable + outStmt(与 boolean.ts 同构)。Phase 1.6:origin=本次语句 StmtId。\n const inputTable = inputRoleTable(input) as ReadonlyMap<unknown, unknown> | undefined\n const outStmt = String(getCurrentStmt()?.id ?? '')\n\n let resultSolid: BrepHandle\n let faceEvolution: Map<number, number[]> | undefined\n let roleTable: ReadonlyMap<unknown, unknown> | undefined\n\n try {\n const r = filletWithRoleTable(\n kernel,\n solid,\n edgeHandles,\n radius,\n inputTable ?? new Map(),\n outStmt,\n )\n resultSolid = r.result\n faceEvolution = r.faceEvolution\n roleTable = r.roleTable\n } catch (err) {\n throw translateOcctError(err)\n }\n\n return fromBrep(\n solidToShape(kernel, resultSolid),\n { solid: resultSolid, faceEvolution, roleTable },\n )\n}\n\n/**\n * 网格实体路径:对近似拓扑里识别出的边倒圆角(方案 2026-10-01 §3.5 三明治)。\n *\n * 与 BREP 路径的三处实质差异,都是\"网格零件没有精度链、没有 role 层\"的直接后果:\n * - 边**按几何或序号**解析:`EdgeTopoRef` 走长度/中点匹配;**1 起序号**直接取自近似\n * 拓扑的 `edges` 数组下标 + 1(等长边靠几何分不开,序号是唯一无歧义的指认方式);\n * - 内核调用走 L1 裸 `kernel.fillet`(`filletWithHistory` 是精度链的面演化能力,\n * 近似拓扑没有 hash 演化可言,故**不产生** faceEvolution / roleTable,如实缺席\n * 而不是造一张恒等映射);\n * - 产物句柄写回后由 `meshSolidProduct` 重新三角化并重建近似拓扑。\n *\n * GOTCHA(2026-10-01 实测,见 `brepkit-kernel/mesh-solid-topology.test.ts`):\n * 一次请求里的**全部**边交给内核,会在共面边链(如圆柱端盖的 64 条边)上被整体\n * 拒绝——不是单条边不可倒,而是\"一次性磨圆会自交\"。故本实现**如实失败**,不自动\n * 拆成逐边重试(运行时换策略会掩盖几何事实)。要给共面边链倒角,请分多次调用,\n * 每次一组几何上互不相邻的边。\n *\n * @param input - the mesh-solid input.\n * @param params - the validated fillet parameters.\n * @returns the filleted mesh solid as a new mesh part.\n */\nfunction filletMeshSolid(input: Shape, params: Record<string, unknown>): Shape {\n const edges = params.edges as (number | string | EdgeTopoRef)[] | string\n const radius = params.radius as number\n const entry = meshSolidEntry(input, 'fillet')\n // 选择器字符串只服务精度链(网格零件无 role 层);网格链用 1 起序号。\n if (typeof edges === 'string' || edges.some((e) => typeof e === 'string')) {\n throw new TopoRefError(\n 'E_TOPO_MESH_UNSUPPORTED',\n 'edge',\n 'fillet: selector strings are precision-chain only — mesh solids have no role layer (use 1-based edge ordinals)',\n )\n }\n const edgeHandles = resolveMeshEdges(entry, edges as (number | EdgeTopoRef)[], 'fillet')\n\n let result: BrepHandle\n try {\n result = entry.kernel.fillet(entry.solid, edgeHandles, radius)\n } catch (cause) {\n throw meshKernelFailure(\n 'fillet',\n 'E_FILLET_RADIUS_TOO_LARGE',\n `fillet(r=${radius}) on ${edgeHandles.length} edge(s)`,\n cause,\n )\n }\n return meshSolidProduct(entry, result)\n}\n\n/**\n * 多零件 compound 成员是匿名 Shape:其面 role 记录在父 compound 的 part 键合并表里。\n * 解包后让 target 继承父 part 名,buildEdgeResolutionContext/inputRoleTable 才能按\n * part 名查到表(与 chamfer 同构)。单零件路径 input===target 已命名,守卫使其空转。\n */\nfunction adoptParentPartName(input: Shape, target: Shape): void {\n if (target === input) return\n const parentName = nameOf(input)\n if (parentName && !nameOf(target)) setName(target, parentName)\n}\n\n/**\n * 在几何体上做圆角(等半径)。\n *\n * 两条路径都以 `meshEngines: ['brepkit']` 之外的事实为界:BREP 输入走\n * `filletWithHistory`(带面演化与 roleTable 传播);**网格实体**输入走网格后端\n * (近似拓扑无 role,边按几何或序号解析,无面演化)。非 BREP 的**裸网格**输入仍抛\n * `E_MESH_SOLID_UNSUPPORTED`——裸网格没有近似拓扑,没有边可选。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name fillet\n * @note `radius` 为正数(mm)。BREP 路径圆角后 roleTable 经 filletWithHistory 传播,\n * 后续特征仍可按 role 选面/选边;网格实体路径没有 role 层,边只能按几何或\n * 序号(近似拓扑 `edges` 数组下标 + 1)指认。\n * @returns Shape 圆角后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.edges - 参与圆角的边:CadQuery 边选择器字符串(如 \"|Z\",AI 生成)或相邻两面的 role 线路(EdgeTopoRef[],UI 拾取产物);网格链上也可用 1 起序号。type:EdgeTopoRef[]|string required:true\n * @param params.radius - 圆角半径(mm,>0)。type:number required:true\n * @example\n * const p = await cad.fillet(part0, { edges: [{ kind:'edge', faces:[{ origin:'box', role:'box:top' }, { origin:'box', role:'box:front' }], hint:{ kind:'edge' } }], radius:2 })\n * // AI 生成可写 CadQuery 边选择器字符串(\"|Z\" 切线平行 Z 的边)\n * const p2 = await cad.fillet(part0, { edges: \"|Z\", radius: 2 })\n * const q = await cad.fillet(meshPart, { edges: [3], radius: 1 })\n */\nexport const fillet = defineOp({\n meshEngines: ['brepkit'],\n mesh(input: Shape, params: Record<string, unknown>) {\n assertFilletParams(params, { allowOrdinals: true })\n // P2:多零件 load 输入是 compound——按 partIndex 取目标成员,结果替换回原 compound。\n const target = resolveCompoundMember(input, params.partIndex, 'fillet')\n const result = filletMeshSolid(target, params)\n return replaceCompoundMember(input, params.partIndex, result)\n },\n brep(input: Shape, params: Record<string, unknown>) {\n assertFilletParams(params)\n const target = resolveCompoundMember(input, params.partIndex, 'fillet')\n adoptParentPartName(input, target)\n const result = filletBrep(target, params)\n return replaceCompoundMember(input, params.partIndex, result)\n },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n"]}
|
package/dist/api/helix.d.ts
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* api helix — 螺旋线(1D
|
|
2
|
+
* api helix — 螺旋线(1D 曲线,全平台中立 op)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `engines: ['occt']` 由守卫 ② 校验。
|
|
4
|
+
* 2026-10-13:`makeHelixWire` 已进 L1 中立面(`BrepEngineApi`),本 op 由
|
|
5
|
+
* 「occt 平台 op」升为**全平台中立 op** —— 不再声明 `engines: ['occt']`。
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
12
|
-
*
|
|
7
|
+
* 手性是 `makeHelixWire` 的**形参**(`leftHanded`),由引擎适配器消化,本文件只看 L1:
|
|
8
|
+
* - 右手(默认 `'right'`):两引擎都可建。brepkit 侧是采样拟合近似
|
|
9
|
+
* (无 1D 螺旋原语),偏差已钉 band。
|
|
10
|
+
* - 左手(`handed: 'left'`):occt 侧走原生带手性入口(`makeHelixWireHanded`);
|
|
11
|
+
* brepkit 无带手性原语 → 适配器**显式失败**,不做镜像兜底
|
|
12
|
+
* (静默换算法比报错更危险)。故本文件不 import 平台模块、也不按 op 声明
|
|
13
|
+
* `engines: ['occt']`——那会把右手一并拒掉。
|
|
13
14
|
* - 1D 产物:经 fromBrepCurve 登记,kind='curve'。
|
|
14
|
-
* - 非 occt 引擎(brepkit)→ 执行前 BrepUnsupportedError(D11-4);brep_mock 受 D11-3
|
|
15
|
-
* 豁免不拦截(且 getOcctKernel 为全局 occt 实例,brep_mock 下仍可真实出线)。
|
|
16
15
|
*/
|
|
17
16
|
import type { Shape } from '../mesh/types.js';
|
|
18
17
|
/** 螺旋手性:`'right'`(右手,逆时针上旋)或 `'left'`(左手,顺时针上旋)。 */
|
|
@@ -31,7 +30,8 @@ export interface HelixOptions {
|
|
|
31
30
|
origin?: [number, number, number];
|
|
32
31
|
/**
|
|
33
32
|
* 手性(默认 `'right'`)。同 pitch/height/radius 下左右旋互为镜像。
|
|
34
|
-
*
|
|
33
|
+
* 经 L1 `makeHelixWire(..., leftHanded)` 送达引擎适配器:occt 两侧都原生支持;
|
|
34
|
+
* brepkit 只有右手(左手显式失败,不镜像)。
|
|
35
35
|
*/
|
|
36
36
|
handed?: HelixHanded;
|
|
37
37
|
}
|
|
@@ -42,7 +42,7 @@ export interface HelixOptions {
|
|
|
42
42
|
* @async false
|
|
43
43
|
* @qual ok
|
|
44
44
|
* @name helix
|
|
45
|
-
* @note
|
|
45
|
+
* @note 全平台中立 op:手性是 L1 `makeHelixWire` 的形参(`leftHanded`)——右手两引擎都可建(brepkit 侧为采样拟合近似);左手仅 occt 原生支持,brepkit 适配器显式失败(不镜像兜底)。
|
|
46
46
|
* @returns Shape 1D 螺旋线(kind:'curve')。
|
|
47
47
|
* @param options.radius - 螺旋半径(mm,>0)。type:number required:true
|
|
48
48
|
* @param options.pitch - 螺距(mm,≠0)。type:number required:true
|
package/dist/api/helix.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helix.d.ts","sourceRoot":"","sources":["../../src/api/helix.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"helix.d.ts","sourceRoot":"","sources":["../../src/api/helix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAO1C,oDAAoD;AACpD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAA;AAE1C,sBAAsB;AACtB,MAAM,WAAW,YAAY;IAC3B,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,cAAc;IACd,KAAK,EAAE,MAAM,CAAA;IACb,yBAAyB;IACzB,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,gBAAgB;IAChB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAwBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,KAAK;;CAYhB,CAAA"}
|
package/dist/api/helix.js
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* api helix — 螺旋线(1D
|
|
2
|
+
* api helix — 螺旋线(1D 曲线,全平台中立 op)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `engines: ['occt']` 由守卫 ② 校验。
|
|
4
|
+
* 2026-10-13:`makeHelixWire` 已进 L1 中立面(`BrepEngineApi`),本 op 由
|
|
5
|
+
* 「occt 平台 op」升为**全平台中立 op** —— 不再声明 `engines: ['occt']`。
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
12
|
-
*
|
|
7
|
+
* 手性是 `makeHelixWire` 的**形参**(`leftHanded`),由引擎适配器消化,本文件只看 L1:
|
|
8
|
+
* - 右手(默认 `'right'`):两引擎都可建。brepkit 侧是采样拟合近似
|
|
9
|
+
* (无 1D 螺旋原语),偏差已钉 band。
|
|
10
|
+
* - 左手(`handed: 'left'`):occt 侧走原生带手性入口(`makeHelixWireHanded`);
|
|
11
|
+
* brepkit 无带手性原语 → 适配器**显式失败**,不做镜像兜底
|
|
12
|
+
* (静默换算法比报错更危险)。故本文件不 import 平台模块、也不按 op 声明
|
|
13
|
+
* `engines: ['occt']`——那会把右手一并拒掉。
|
|
13
14
|
* - 1D 产物:经 fromBrepCurve 登记,kind='curve'。
|
|
14
|
-
* - 非 occt 引擎(brepkit)→ 执行前 BrepUnsupportedError(D11-4);brep_mock 受 D11-3
|
|
15
|
-
* 豁免不拦截(且 getOcctKernel 为全局 occt 实例,brep_mock 下仍可真实出线)。
|
|
16
15
|
*/
|
|
17
16
|
import { solidToShape } from '../brep/brep-ops.js';
|
|
18
17
|
import { getBrepApi } from '../brep/handle-bridge.js';
|
|
19
18
|
import { fromBrepCurve } from '../shape.js';
|
|
20
19
|
import { defineOp } from '../sdk.js';
|
|
21
|
-
|
|
22
|
-
/** BREP 路径:用 occt 原生 makeHelixWire / makeHelixWireHanded 构造螺旋线,登记 1D 句柄。 */
|
|
20
|
+
/** BREP 路径:经 L1 `makeHelixWire` 构造螺旋线(手性作为形参),登记 1D 句柄。 */
|
|
23
21
|
function helixBrep(opts) {
|
|
24
22
|
const { radius, pitch, turns } = opts;
|
|
25
23
|
if (!(radius > 0))
|
|
@@ -36,13 +34,11 @@ function helixBrep(opts) {
|
|
|
36
34
|
const origin = opts.origin ?? [0, 0, 0];
|
|
37
35
|
const height = pitch * turns;
|
|
38
36
|
const kernel = getBrepApi();
|
|
39
|
-
const occt = getOcctKernel();
|
|
40
37
|
const o = { x: origin[0], y: origin[1], z: origin[2] };
|
|
41
38
|
const a = { x: axis[0], y: axis[1], z: axis[2] };
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
: occt.makeHelixWire(o, a, pitch, height, radius));
|
|
39
|
+
// 手性是 L1 形参:occt 侧左右手都是原生路径;brepkit 侧右手采样拟合、左手由
|
|
40
|
+
// 适配器显式拒绝(无镜像兜底)。本文件因此不需要任何平台 import。
|
|
41
|
+
const handle = kernel.makeHelixWire(o, a, pitch, height, radius, handed === 'left');
|
|
46
42
|
return fromBrepCurve(solidToShape(kernel, handle), { solid: handle });
|
|
47
43
|
}
|
|
48
44
|
/**
|
|
@@ -52,7 +48,7 @@ function helixBrep(opts) {
|
|
|
52
48
|
* @async false
|
|
53
49
|
* @qual ok
|
|
54
50
|
* @name helix
|
|
55
|
-
* @note
|
|
51
|
+
* @note 全平台中立 op:手性是 L1 `makeHelixWire` 的形参(`leftHanded`)——右手两引擎都可建(brepkit 侧为采样拟合近似);左手仅 occt 原生支持,brepkit 适配器显式失败(不镜像兜底)。
|
|
56
52
|
* @returns Shape 1D 螺旋线(kind:'curve')。
|
|
57
53
|
* @param options.radius - 螺旋半径(mm,>0)。type:number required:true
|
|
58
54
|
* @param options.pitch - 螺距(mm,≠0)。type:number required:true
|
|
@@ -65,15 +61,14 @@ function helixBrep(opts) {
|
|
|
65
61
|
* const lh = cad.helix({ radius: 5, pitch: 2, turns: 3, handed: 'left' })
|
|
66
62
|
*/
|
|
67
63
|
export const helix = defineOp({
|
|
68
|
-
// name
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
64
|
+
// name 必填:occt op 覆盖率扫描器的 op 全集只收
|
|
65
|
+
// `export const X = defineOp({ name: '…' })`——缺 name 的 op 在报告里不可见。
|
|
66
|
+
// (本 op 无平台直调:左手经 L1 形参送达,原生 makeHelixWireHanded 由契约实现层
|
|
67
|
+
// 直调,见 occt-kernel/occt-primitives.ts。)
|
|
72
68
|
name: 'helix',
|
|
73
69
|
brep(opts) {
|
|
74
70
|
return helixBrep(opts);
|
|
75
71
|
},
|
|
76
|
-
engines: ['occt'],
|
|
77
72
|
naming: { kind: 'unmodeled', reason: 'construct vocabulary pending Phase 3' },
|
|
78
73
|
paramDims: {},
|
|
79
74
|
});
|
package/dist/api/helix.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helix.js","sourceRoot":"","sources":["../../src/api/helix.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"helix.js","sourceRoot":"","sources":["../../src/api/helix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AA0BjC,2DAA2D;AAC3D,SAAS,SAAS,CAAC,IAAkB;IACnC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,CAAA;IACrC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAA;IAC5E,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAChF,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IACzE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAA;IACrC,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,8DAA8D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACnG,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACvC,MAAM,MAAM,GAAG,KAAK,GAAG,KAAK,CAAA;IAC5B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;IACtD,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;IAChD,gDAAgD;IAChD,sCAAsC;IACtC,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,CAAA;IACnF,OAAO,aAAa,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;AACvE,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,CAAC;IAC5B,kCAAkC;IAClC,mEAAmE;IACnE,wDAAwD;IACxD,0CAA0C;IAC1C,IAAI,EAAE,OAAO;IACb,IAAI,CAAC,IAAkB;QACrB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,sCAAsC,EAAgB;IAE3F,SAAS,EAAE,EAAE;CACd,CAAC,CAAA","sourcesContent":["/**\n * api helix — 螺旋线(1D 曲线,全平台中立 op)\n *\n * 2026-10-13:`makeHelixWire` 已进 L1 中立面(`BrepEngineApi`),本 op 由\n * 「occt 平台 op」升为**全平台中立 op** —— 不再声明 `engines: ['occt']`。\n *\n * 手性是 `makeHelixWire` 的**形参**(`leftHanded`),由引擎适配器消化,本文件只看 L1:\n * - 右手(默认 `'right'`):两引擎都可建。brepkit 侧是采样拟合近似\n * (无 1D 螺旋原语),偏差已钉 band。\n * - 左手(`handed: 'left'`):occt 侧走原生带手性入口(`makeHelixWireHanded`);\n * brepkit 无带手性原语 → 适配器**显式失败**,不做镜像兜底\n * (静默换算法比报错更危险)。故本文件不 import 平台模块、也不按 op 声明\n * `engines: ['occt']`——那会把右手一并拒掉。\n * - 1D 产物:经 fromBrepCurve 登记,kind='curve'。\n */\n\nimport type { Shape } from '../mesh/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { fromBrepCurve } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\n\n/** 螺旋手性:`'right'`(右手,逆时针上旋)或 `'left'`(左手,顺时针上旋)。 */\nexport type HelixHanded = 'right' | 'left'\n\n/** `cad.helix` 参数。 */\nexport interface HelixOptions {\n /** 螺旋半径(mm,>0)。 */\n radius: number\n /** 螺距(mm,每圈沿轴的推进量,≠0)。 */\n pitch: number\n /** 圈数(>0)。 */\n turns: number\n /** 螺旋轴方向(单位向量,默认 +Z)。 */\n axis?: [number, number, number]\n /** 起点(默认原点)。 */\n origin?: [number, number, number]\n /**\n * 手性(默认 `'right'`)。同 pitch/height/radius 下左右旋互为镜像。\n * 经 L1 `makeHelixWire(..., leftHanded)` 送达引擎适配器:occt 两侧都原生支持;\n * brepkit 只有右手(左手显式失败,不镜像)。\n */\n handed?: HelixHanded\n}\n\n/** BREP 路径:经 L1 `makeHelixWire` 构造螺旋线(手性作为形参),登记 1D 句柄。 */\nfunction helixBrep(opts: HelixOptions): Shape {\n const { radius, pitch, turns } = opts\n if (!(radius > 0)) throw new Error('E_HELIX_BAD_RADIUS: radius must be > 0')\n if (!(pitch !== 0)) throw new Error('E_HELIX_BAD_PITCH: pitch must be non-zero')\n if (!(turns > 0)) throw new Error('E_HELIX_BAD_TURNS: turns must be > 0')\n const handed = opts.handed ?? 'right'\n if (handed !== 'right' && handed !== 'left') {\n throw new Error(`E_HELIX_BAD_HANDED: handed must be 'right' or 'left' (got '${String(handed)}')`)\n }\n const axis = opts.axis ?? [0, 0, 1]\n const origin = opts.origin ?? [0, 0, 0]\n const height = pitch * turns\n const kernel = getBrepApi()\n const o = { x: origin[0], y: origin[1], z: origin[2] }\n const a = { x: axis[0], y: axis[1], z: axis[2] }\n // 手性是 L1 形参:occt 侧左右手都是原生路径;brepkit 侧右手采样拟合、左手由\n // 适配器显式拒绝(无镜像兜底)。本文件因此不需要任何平台 import。\n const handle = kernel.makeHelixWire(o, a, pitch, height, radius, handed === 'left')\n return fromBrepCurve(solidToShape(kernel, handle), { solid: handle })\n}\n\n/**\n * 构造螺旋线(1D 曲线)。\n * @group 创建\n * @inputs 0\n * @async false\n * @qual ok\n * @name helix\n * @note 全平台中立 op:手性是 L1 `makeHelixWire` 的形参(`leftHanded`)——右手两引擎都可建(brepkit 侧为采样拟合近似);左手仅 occt 原生支持,brepkit 适配器显式失败(不镜像兜底)。\n * @returns Shape 1D 螺旋线(kind:'curve')。\n * @param options.radius - 螺旋半径(mm,>0)。type:number required:true\n * @param options.pitch - 螺距(mm,≠0)。type:number required:true\n * @param options.turns - 圈数(>0)。type:number required:true\n * @param options.axis - 螺旋轴方向(默认 +Z)。type:Vec3 required:false\n * @param options.origin - 起点(默认原点)。type:Vec3 required:false\n * @param options.handed - 手性:'right'(默认)或 'left'。type:HelixHanded required:false\n * @example\n * const h = cad.helix({ radius: 5, pitch: 2, turns: 3 })\n * const lh = cad.helix({ radius: 5, pitch: 2, turns: 3, handed: 'left' })\n */\nexport const helix = defineOp({\n // name 必填:occt op 覆盖率扫描器的 op 全集只收\n // `export const X = defineOp({ name: '…' })`——缺 name 的 op 在报告里不可见。\n // (本 op 无平台直调:左手经 L1 形参送达,原生 makeHelixWireHanded 由契约实现层\n // 直调,见 occt-kernel/occt-primitives.ts。)\n name: 'helix',\n brep(opts: HelixOptions) {\n return helixBrep(opts)\n },\n naming: { kind: 'unmodeled', reason: 'construct vocabulary pending Phase 3' } as Provenance,\n\n paramDims: {},\n})\n"]}
|
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
* BREP 专属:`.brp` 无 mesh 解析器;mesh / 无内核模式抛 E_BREP_UNSUPPORTED。
|
|
15
15
|
*/
|
|
16
16
|
import type { Shape } from '../mesh/types.js';
|
|
17
|
+
/**
|
|
18
|
+
* 裸实现:契约层测试直调(不经 defineOp 的 dispatch 拦截)。
|
|
19
|
+
*
|
|
20
|
+
* @param params - op 参数对象;`asset` 为容器资产名(去扩展名)。
|
|
21
|
+
* @returns 持 OCCT 句柄的几何(非实体亦可)。
|
|
22
|
+
*/
|
|
23
|
+
export declare function importBrepImpl(params: Record<string, unknown>): Promise<Shape>;
|
|
17
24
|
/**
|
|
18
25
|
* 平台 BREP 资产导入:把容器 `assets/` 里的冻结 BREP 载体装成持 OCCT 句柄的 Shape。
|
|
19
26
|
*
|
|
@@ -26,27 +33,12 @@ import type { Shape } from '../mesh/types.js';
|
|
|
26
33
|
* @qual ok
|
|
27
34
|
* @name import_brep
|
|
28
35
|
* @param params.asset - 容器资产名(去扩展名)。type:string required:true
|
|
29
|
-
* @note 非实体一等(C6):wire/face/shell 一律可导入,本 op 不设 `allowNonSolid` 一类开关。需要实体的 op(布尔、up-to 目标面)在**使用点**报错,而不是在导入点拒绝。
|
|
30
|
-
* @note 这是**平台**资产导入 op。编辑器 `cad.load` 是 `../3d_editor` 的「文件导入 Feature」(key/path/url 三键分流 + 画布语句位置语义),平台侧不要复用它(C7)。
|
|
31
36
|
* @returns Promise<Shape> 持 OCCT 句柄的几何(非实体亦可)。
|
|
32
37
|
* @example
|
|
33
38
|
* const a = await cad.import_brep({ asset: 'Array001.Shape' })
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* @param params - op 参数对象;`asset` 为容器资产名(去扩展名)。
|
|
39
|
-
* @returns 持 OCCT 句柄的几何(非实体亦可)。
|
|
40
|
-
*/
|
|
41
|
-
export declare function importBrepImpl(params: Record<string, unknown>): Promise<Shape>;
|
|
42
|
-
/**
|
|
43
|
-
* GOTCHA(2026-09-30):import_brep / import_step 必须经 defineOp 包装进入 cad
|
|
44
|
-
* 命名空间,不能是裸 async 函数。part 键 roleTable(outputTablesByPart)只在
|
|
45
|
-
* define-op.ts 包装层的 brep 分支登记(shape.ts attachBrep 只落语句键表,因为
|
|
46
|
-
* fromBrep 时刻 shape 还没被 executor 命名)。裸函数产物没有 part 键表 → 下游
|
|
47
|
-
* place 的 inputRoleTable(tableOfPart)拿到 undefined → place 产物 roleTable
|
|
48
|
-
* 断流 → edgeRef 报 "input shape has no role table (nameless shape)"
|
|
49
|
-
* (fcstd 语料 43 例,如 ISO4032_Hex_Nut_M10 的 chamfer(Pocket001__place))。
|
|
39
|
+
* @note 非实体一等(C6):wire/face/shell 一律可导入,本 op 不设 `allowNonSolid` 一类开关。需要实体的 op(布尔、up-to 目标面)在**使用点**报错,而不是在导入点拒绝。
|
|
40
|
+
* @note 这是**平台**资产导入 op。编辑器 `cad.load` 是 `../3d_editor` 的「文件导入 Feature」(key/path/url 三键分流 + 画布语句位置语义),平台侧不要复用它(C7)。
|
|
41
|
+
* @note GOTCHA(2026-09-30):必须经 defineOp 包装进入 cad 命名空间,不能是裸 async 函数。part 键 roleTable(outputTablesByPart)只在 define-op.ts 包装层的 brep 分支登记(shape.ts attachBrep 只落语句键表,因为 fromBrep 时刻 shape 还没被 executor 命名)。裸函数产物没有 part 键表 → 下游 place 的 inputRoleTable(tableOfPart)拿到 undefined → place 产物 roleTable 断流 → edgeRef 报 "input shape has no role table (nameless shape)"(fcstd 语料 43 例,如 ISO4032_Hex_Nut_M10 的 chamfer(Pocket001__place))。
|
|
50
42
|
*/
|
|
51
43
|
export declare const import_brep: ((params: Record<string, unknown>) => Promise<Shape>) & {
|
|
52
44
|
__faijs__dualOp?: import("../define-op.js").DualOpMeta;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-brep.d.ts","sourceRoot":"","sources":["../../src/api/import-brep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAU1C
|
|
1
|
+
{"version":3,"file":"import-brep.d.ts","sourceRoot":"","sources":["../../src/api/import-brep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAU1C;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CA2CpF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW;;CAUtB,CAAA"}
|