@faicad/faijs 0.33.2 → 0.35.8
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/entities.js +14 -4
- package/dist/api/assembly/entities.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 +54 -26
- 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 +92 -12
- package/dist/api/fillet.js.map +1 -1
- package/dist/api/generated/script-face-manifest.js +1 -1
- package/dist/api/generated/script-face-manifest.js.map +1 -1
- package/dist/api/generated/topology.js +1 -1
- package/dist/api/generated/topology.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/primitives.d.ts +3 -2
- package/dist/api/primitives.d.ts.map +1 -1
- package/dist/api/primitives.js +3 -2
- package/dist/api/primitives.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/surface/arg-spec.d.ts.map +1 -1
- package/dist/api/surface/arg-spec.js +5 -6
- package/dist/api/surface/arg-spec.js.map +1 -1
- package/dist/api/topo-resolve.d.ts.map +1 -1
- package/dist/api/topo-resolve.js +24 -5
- package/dist/api/topo-resolve.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 +328 -38
- package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.d.ts +3 -1
- package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.js +13 -9
- 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 +252 -20
- 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 +423 -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 +7 -5
- package/dist/mesh/primitives.d.ts.map +1 -1
- package/dist/mesh/primitives.js +16 -9
- package/dist/mesh/primitives.js.map +1 -1
- package/dist/mesh/types.d.ts +4 -3
- package/dist/mesh/types.d.ts.map +1 -1
- package/dist/mesh/types.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/primitives/brep-primitives.d.ts.map +1 -1
- package/dist/primitives/brep-primitives.js +39 -12
- package/dist/primitives/brep-primitives.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/topology/naming/geom-hint.d.ts +12 -0
- package/dist/topology/naming/geom-hint.d.ts.map +1 -1
- package/dist/topology/naming/geom-hint.js +1 -1
- package/dist/topology/naming/geom-hint.js.map +1 -1
- package/dist/topology/naming/lineage.d.ts +1 -0
- package/dist/topology/naming/lineage.d.ts.map +1 -1
- package/dist/topology/naming/lineage.js +37 -1
- package/dist/topology/naming/lineage.js.map +1 -1
- package/dist/topology/naming/resolve-face.d.ts +13 -2
- package/dist/topology/naming/resolve-face.d.ts.map +1 -1
- package/dist/topology/naming/resolve-face.js +18 -2
- package/dist/topology/naming/resolve-face.js.map +1 -1
- 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
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* faijs-extra load — 加载库函数(统一 load 函数)
|
|
3
|
+
*
|
|
4
|
+
* file 指定资产名(用户上传文件名,不含路径、含后缀),经宿主资产解析器按名解析;
|
|
5
|
+
* 格式由 file 后缀白名单自判(不依赖宿主 format 参数),isCadFormat 静态判定 brep/mesh,
|
|
6
|
+
* 产物经 solid()/fromBrep() 构造器创建。
|
|
7
|
+
*
|
|
8
|
+
* @platform occt — 本文件 import `occt-kernel/occtKernel`(BREP 路径的 XCAF /
|
|
9
|
+
* `importBrepToMesh` 平台面)。mesh 路径(STL/3MF)不依赖平台模块;本 op 无
|
|
10
|
+
* `engines` 声明(不按 op 整体做引擎门,运行时按引擎能力静态分派,见下方注释)。
|
|
11
|
+
*/
|
|
12
|
+
import { importFile, detectStepUnit } from '../../mesh/io.js';
|
|
13
|
+
import { isCadFormat } from '../../brep/brep-chain.js';
|
|
14
|
+
import { loadBrepAssembly, loadBrepAssemblyNative, solidToShape, } from '../../brep/brep-ops.js';
|
|
15
|
+
import { weldToleranceFor } from '../../brep/mesh-solid.js';
|
|
16
|
+
import { importBrepToMesh } from '../../occt-kernel/occtKernel.js';
|
|
17
|
+
import { reconstructSolidFromMesh } from '../../occt-kernel/meshReconstruct.js';
|
|
18
|
+
import { parseStl } from '../../mesh/stl-loader.js';
|
|
19
|
+
import { OCCT_BREP_ENGINE_ID } from '../../brep/engine/adapters/occt.js';
|
|
20
|
+
import { OpError } from '../../api/internal/result-unwrap.js';
|
|
21
|
+
import { getBackends, BrepUnsupportedError, getCurrentStmt, setPendingDetectedUnit, setPendingImportModel, setPendingMeshSolid, setPendingMeshTopology, } from '../../runtime-state.js';
|
|
22
|
+
import { solid, compound, fromBrep, fromMeshSolid } from '../../shape.js';
|
|
23
|
+
import { UNIT_DIM } from '../../units.js';
|
|
24
|
+
import { runtimeLineage } from '../../topology/naming/lineage.js';
|
|
25
|
+
import { asStmtId } from '../../identity.js';
|
|
26
|
+
import { HASH_UPPER_BOUND } from '../../brep/face-evolution.js';
|
|
27
|
+
/**
|
|
28
|
+
* 执行加载操作(统一 load 函数)
|
|
29
|
+
*
|
|
30
|
+
* 按 params.file(资产名)从宿主资产库解析 buffer。
|
|
31
|
+
*
|
|
32
|
+
* 静态分派:
|
|
33
|
+
* - CAD 源 + kernel + 非 mesh 模式 → BREP 路径(loadBrep 异常 = 未预期错误,冒泡上报)
|
|
34
|
+
* - 非 CAD 源 / 无 kernel / mesh 模式 → mesh 路径
|
|
35
|
+
* - brep 模式且将走 mesh 路径 → 调用前抛 BrepUnsupportedError(不静默回退)
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* 加载几何资产。`file` 指定资产名(用户上传文件名,不含路径、含后缀),内容经宿主资产解析器按名解析,**引用而非拷贝**。
|
|
39
|
+
* @group 创建
|
|
40
|
+
* @inputs 0
|
|
41
|
+
* @async true
|
|
42
|
+
* @qual ok
|
|
43
|
+
* @name load
|
|
44
|
+
* @note 语言正常化后 loadFile/loadUrl/loadByKey 别名已删除(A4),统一为 `load` 一个函数。
|
|
45
|
+
* @returns Shape 加载的几何,永远是 part 的第一条语句,后面可接特征链。
|
|
46
|
+
* @param params.file - 资产文件名(用户上传名,不含路径、含后缀,如 'vise.3mf');内容按名从宿主资产库取。type:string
|
|
47
|
+
* @param params.unit - **强制设置模型的源单位**:仅对无内部单位声明的 mesh 格式
|
|
48
|
+
* (STL/3MF)有效——提供即覆盖/忽略模型内部记录的单位(3MF `<model unit>`),
|
|
49
|
+
* 按指定单位折算坐标;只有调用方确实知道单位时才提供(用户手写脚本)。未提供
|
|
50
|
+
* 时:STL faijs 启发式(guessStlUnit)、3MF 文件声明。**STEP/BREP 不支持**——
|
|
51
|
+
* 走 OCCT 链、单位由文件内部声明决定(读取时折算),提供 unit 直接报错。type:string
|
|
52
|
+
* @note 格式由 `file` 后缀白名单自判:stl/3mf → mesh 路径;step/stp/stpz/brep → BREP 路径。宿主不再传 `format`。
|
|
53
|
+
* @note 后缀白名单未命中 → 报错(不猜格式);3MF 后缀会做 zip 魔数 sanity(后缀与内容明显不符时报错)。
|
|
54
|
+
* @note 本 op 要求导入物含实体(历史契约)。非实体(wire/face/shell)的导入是平台 `cad.import_brep` 的一等能力,不由本 op 承担。
|
|
55
|
+
* @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用的「文件导入 Feature」提供——`file` 读的是应用侧资产库(按用户上传文件名注册),产物语句位置与命名都是画布语义。不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。2026-10-06 起多零件文件不再单零件收敛——全量以 compound + `ExecutionResult.importModels` 返回;宿主按 `importModel.parts` 身份批量建 part。
|
|
56
|
+
* @example
|
|
57
|
+
* const p = await cad.load({ file: 'box.stl' })
|
|
58
|
+
* const p = await cad.load({ file: 'box.3mf' })
|
|
59
|
+
* const p = await cad.load({ file: 'model.step' })
|
|
60
|
+
*/
|
|
61
|
+
export async function load(params) {
|
|
62
|
+
const assets = getBackends().assets;
|
|
63
|
+
if (!assets) {
|
|
64
|
+
throw new OpError('load', 'E_OP_FAILED', '[extra/load] assets is required for load op');
|
|
65
|
+
}
|
|
66
|
+
// P8:参数面收敛为 file(资产名,不含路径、含后缀)。key/path/url/format 三键已删除。
|
|
67
|
+
const file = params.file;
|
|
68
|
+
if (typeof file !== 'string' || file === '') {
|
|
69
|
+
throw new OpError('load', 'E_ARGS_FORM', '[extra/load] load op requires a non-empty file (asset file name, no path)');
|
|
70
|
+
}
|
|
71
|
+
if (file.includes('/') || file.includes('\\')) {
|
|
72
|
+
throw new OpError('load', 'E_ARGS_FORM', `[extra/load] file must not contain path separators: ${JSON.stringify(file)}`);
|
|
73
|
+
}
|
|
74
|
+
// 格式自判:file 后缀白名单 → 归一化格式;未命中即报错(不猜格式)。
|
|
75
|
+
const fmt = formatFromFile(file);
|
|
76
|
+
if (!fmt) {
|
|
77
|
+
throw new OpError('load', 'E_ARGS_FORM', `[extra/load] unsupported file extension in: ${JSON.stringify(file)}`);
|
|
78
|
+
}
|
|
79
|
+
const buffer = (await assets.resolveByKey(file)).bytes;
|
|
80
|
+
assertFileMagic(fmt, buffer, file);
|
|
81
|
+
// 静态判定路径:mesh 模式 / 无 kernel / 非 CAD 源 → mesh 路径;否则 BREP 路径
|
|
82
|
+
// STL 特例(2026-10-17):brepkit/occt 的 L1 面都有 importStl——STL 可以在内核里
|
|
83
|
+
// 直接构造成**真 BREP 实体**(带面-边邻接),而不是走 importIndexedMesh→weld 的
|
|
84
|
+
// 网格路径。网格路径的产物在 brepkit 下无任何特征操作能力(边无邻接面、钻孔/分割
|
|
85
|
+
// 无实现);BREP 路径则圆角可选边、钻孔/分割走内核布尔,全链可用。**3MF 仍走 mesh
|
|
86
|
+
// 路径**(内核无 import3mf,三角网格只能 importIndexedMesh)。
|
|
87
|
+
const { config, kernel: kernels } = getBackends();
|
|
88
|
+
const kernel = kernels.brep;
|
|
89
|
+
const useBrep = config.mode !== 'mesh' && !!kernel &&
|
|
90
|
+
(isCadFormat({ format: fmt }, true) || fmt === 'stl');
|
|
91
|
+
// brep 模式且将走 mesh-only 路径 → 调用前抛错,不静默回退
|
|
92
|
+
if (!useBrep && config.mode === 'brep') {
|
|
93
|
+
throw new BrepUnsupportedError('E_BREP_UNSUPPORTED: load op has no BREP implementation for this source');
|
|
94
|
+
}
|
|
95
|
+
// mesh 路径:importFile 返回 { shape, parts, unit, importModel? } — unit 是文件
|
|
96
|
+
// 源单位(必然有值;faijs 单一真源;元数据;坐标已是基准值)。opts.unit 强制
|
|
97
|
+
// 设置源单位(mesh 格式:STL 直接折算;3MF 覆盖 `<model unit>` 声明);未提供
|
|
98
|
+
// 时 STL 走 guessStlUnit 猜测、3MF 走文件声明。P0(方案 §5.4):多零件 mesh
|
|
99
|
+
// (多 object 3MF)不再折叠——全量 parts 以 compound 返回 + importModel 登记;
|
|
100
|
+
// 单零件保持现状(buildMeshPart)。
|
|
101
|
+
if (!useBrep) {
|
|
102
|
+
const opts = buildImportOpts(params.unit);
|
|
103
|
+
const { shape, parts, unit, importModel } = await importFile(buffer, fmt, opts);
|
|
104
|
+
registerDetectedUnit(unit);
|
|
105
|
+
if (importModel)
|
|
106
|
+
registerImportModel(importModel);
|
|
107
|
+
if (parts.length > 1) {
|
|
108
|
+
// 多零件:compound 全量返回(children 序 = parts.index = importModel.parts.index)。
|
|
109
|
+
// 多零件的网格实体/近似拓扑登记属 P2(宿主按 compound.children 建 part 时处理)。
|
|
110
|
+
return compound(parts);
|
|
111
|
+
}
|
|
112
|
+
return buildMeshPart(shape, file);
|
|
113
|
+
}
|
|
114
|
+
// BREP 路径(直接执行,不包 try-catch!异常 = 未预期错误,冒泡上报)
|
|
115
|
+
// P2:brepChain(meshShapeCache)归引擎侧,loadBrepAssembly 不传。
|
|
116
|
+
// P0(方案 §5.3):多 solid 文件经 XCAF 装配树全量导入——多零件返回 compound
|
|
117
|
+
// (children 序 = parts.index),单零件返回单一 Shape(行为与现状一致)。
|
|
118
|
+
// **不再接收/使用 partIndex**(取件点唯一,宿主不再拆)。
|
|
119
|
+
// 单位(unit-system §5.2):STEP/.brep 走 OCCT 链——OCCT 读取时按文件内部
|
|
120
|
+
// 单位声明折算(XCAF / fromBREP 均如此),**不支持用户强制设置单位**。因此
|
|
121
|
+
// BREP 路径**拒绝 params.unit**:用户显式提供 unit → 明确报错(不缩放、不
|
|
122
|
+
// workaround——缩放+重三角化会改变几何精度语义,且与文件声明矛盾)。
|
|
123
|
+
// STL/3MF(mesh 路径,importFile)支持 opts.unit 强制折算(坐标可直接缩放)。
|
|
124
|
+
const forcedUnit = buildImportOpts(params.unit)?.unit;
|
|
125
|
+
if (forcedUnit) {
|
|
126
|
+
throw new OpError('load', 'E_ARGS_FORM', `[extra/load] ${JSON.stringify(file)}: unit 参数不支持 ${fmt}(STEP/BREP 走 OCCT 链,` +
|
|
127
|
+
'单位由文件内部声明决定、读取时折算,OCCT 不支持强制设置单位);' +
|
|
128
|
+
'unit 仅支持无内部单位声明的 mesh 格式(STL/3MF)。');
|
|
129
|
+
}
|
|
130
|
+
const text = new TextDecoder().decode(new Uint8Array(buffer));
|
|
131
|
+
const declared = detectStepUnit(text) ?? 'mm';
|
|
132
|
+
const hash = await contentHash(buffer);
|
|
133
|
+
// key 带引擎 id(见 loadCache 注释):缓存值持有该内核的 BREP 句柄。
|
|
134
|
+
const cacheKey = hash ? `${config.brepEngineId ?? '<none>'}:${hash}` : null;
|
|
135
|
+
// 装配读取通道(**静态**按引擎分派,无运行时回退):
|
|
136
|
+
// - XCAF(`STEPCAFControl_Reader`)是 occt 内核的装配读取器 → 装配树 + 零件名/颜色;
|
|
137
|
+
// - 其余引擎(brepkit)没有 XCAF → 走 L1 契约面的原生通道
|
|
138
|
+
// `loadBrepAssemblyNative`(importStep/fromBREP + getSubShapes 枚举实体)。
|
|
139
|
+
// 代价是零件身份只有 `imported:<i>`、无装配层级——引擎能力事实,非降级回退。
|
|
140
|
+
const hasXcafChannel = config.brepEngineId === OCCT_BREP_ENGINE_ID;
|
|
141
|
+
/** 装配读取(无缓存):XCAF 通道产装配层级,原生通道无层级(引擎能力事实)。 */
|
|
142
|
+
const readBrepParts = async () => {
|
|
143
|
+
if (!hasXcafChannel)
|
|
144
|
+
return loadBrepAssemblyNative(kernel, buffer);
|
|
145
|
+
const r = await loadBrepAssembly(kernel, buffer);
|
|
146
|
+
return { parts: r.parts, ...(r.assembly ? { assembly: r.assembly } : {}) };
|
|
147
|
+
};
|
|
148
|
+
let brepParts;
|
|
149
|
+
let assembly;
|
|
150
|
+
if (fmt === 'stl') {
|
|
151
|
+
// STL 原生 BREP 通道:kernel.importStl → 单实体(无装配层级;成员名 imported:0)。
|
|
152
|
+
// 与 loadBrepAssemblyNative 同一 L1 契约面;STL 无内部单位声明 → 默认 mm
|
|
153
|
+
// (detectStepUnit 对 STL 文本必然返回 null,registerDetectedUnit 落到 'mm')。
|
|
154
|
+
//
|
|
155
|
+
// importStl 的实体**逐面独立、边不共享**——直接用它,edge naming 没有邻接面
|
|
156
|
+
// (圆角选不了边)。缝合方式按内核分派(mesh 后端与 brep 引擎**同内核**才可用
|
|
157
|
+
// 其私有 weld 原语,句柄域必须一致):
|
|
158
|
+
// · brepkit(weapp):importStl → weld(缝共享边)→ unify(合并共面)——与
|
|
159
|
+
// mesh 路径 normalizeMeshSolid 同一规范化管线;
|
|
160
|
+
// · occt(web):网格 → OCCT 愈合管线 reconstructSolidFromMesh(importStl →
|
|
161
|
+
// fixShape → healSolid → unifySameDomain,见 occt-kernel/meshReconstruct.ts)——
|
|
162
|
+
// brepkit 的 weld 吃 brepkit 句柄,不能处理 occt 句柄。
|
|
163
|
+
const meshBackend = getBackends().kernel.meshSolid;
|
|
164
|
+
const canWeld = meshBackend !== undefined && meshBackend.kernel === kernel;
|
|
165
|
+
let solid;
|
|
166
|
+
if (canWeld) {
|
|
167
|
+
const imported = kernel.importStl(buffer);
|
|
168
|
+
const faces = kernel.getSubShapes(imported, 'face');
|
|
169
|
+
solid = meshBackend.ops.weld(faces, weldToleranceFor(kernel, imported));
|
|
170
|
+
meshBackend.ops.unify(solid);
|
|
171
|
+
kernel.release(imported);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
const parsed = parseStl(buffer);
|
|
175
|
+
solid = reconstructSolidFromMesh(kernel, parsed.positions, parsed.indices);
|
|
176
|
+
}
|
|
177
|
+
brepParts = [{ index: 0, name: file, shape: solidToShape(kernel, solid), solid, color: null }];
|
|
178
|
+
}
|
|
179
|
+
else if (fmt === 'brep' && hasXcafChannel) {
|
|
180
|
+
// CASCADE BREP 文本(单 solid,无装配树):XCAF(STEPCAFControl_Reader)
|
|
181
|
+
// 读不了 BREP 语法——occt 下唯一读取实现是 kernel.fromBREP(importBrepToMesh)。
|
|
182
|
+
// 非 occt 引擎走下方 `loadBrepAssemblyNative`(同一 kernel.fromBREP,走契约面)。
|
|
183
|
+
// 产物与 STEP 单零件同构(fromBrep + solid 句柄,句柄归 brepChain 管理)。
|
|
184
|
+
const imported = await importBrepToMesh(text);
|
|
185
|
+
const handle = imported.shapeHandle;
|
|
186
|
+
brepParts = [{ index: 0, name: file, shape: solidToShape(kernel, handle), solid: handle, color: null }];
|
|
187
|
+
}
|
|
188
|
+
else if (cacheKey) {
|
|
189
|
+
const cached = loadCache.get(cacheKey);
|
|
190
|
+
if (cached) {
|
|
191
|
+
brepParts = cached.parts;
|
|
192
|
+
assembly = cached.assembly;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
const r = await readBrepParts();
|
|
196
|
+
brepParts = r.parts;
|
|
197
|
+
assembly = r.assembly;
|
|
198
|
+
loadCache.set(cacheKey, { parts: brepParts, assembly });
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const r = await readBrepParts();
|
|
203
|
+
brepParts = r.parts;
|
|
204
|
+
assembly = r.assembly;
|
|
205
|
+
}
|
|
206
|
+
// BREP 路径的源单位:文件声明(文本探测,无声明 → 'mm',与 OCCT 约定一致)。
|
|
207
|
+
// unit 必然有值(faijs 单一真源),registerDetectedUnit 总是登记。
|
|
208
|
+
registerDetectedUnit(declared);
|
|
209
|
+
const importModel = {
|
|
210
|
+
format: fmt === 'brep' ? 'brep' : 'step',
|
|
211
|
+
unit: declared,
|
|
212
|
+
parts: brepParts.map((p) => ({
|
|
213
|
+
index: p.index,
|
|
214
|
+
name: p.name,
|
|
215
|
+
...(p.color ? { color: p.color } : {}),
|
|
216
|
+
})),
|
|
217
|
+
...(assembly ? { assembly } : {}),
|
|
218
|
+
};
|
|
219
|
+
registerImportModel(importModel);
|
|
220
|
+
if (brepParts.length === 1) {
|
|
221
|
+
const p = brepParts[0];
|
|
222
|
+
return buildBrepPart(kernel, p, getCurrentStmt()?.outputs[0]);
|
|
223
|
+
}
|
|
224
|
+
// 多零件:每个 child 带自己的 BREP solid(宿主经 brepOf(child) 读取)+
|
|
225
|
+
// 逐成员 roleTable;终端合并表按同一 StmtId 落 statement 键 + part 键。
|
|
226
|
+
const stmtId = String(getCurrentStmt()?.id ?? '');
|
|
227
|
+
const mergedRoles = new Map();
|
|
228
|
+
const children = brepParts.map((p, idx) => {
|
|
229
|
+
const memberRoles = buildImportedRoles(kernel, p.solid, idx);
|
|
230
|
+
for (const [role, hashes] of memberRoles)
|
|
231
|
+
mergedRoles.set(role, hashes);
|
|
232
|
+
return fromBrep(p.shape, {
|
|
233
|
+
solid: p.solid,
|
|
234
|
+
roleTable: new Map([[stmtId, memberRoles]]),
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
const out = compound(children);
|
|
238
|
+
if (stmtId) {
|
|
239
|
+
const part = getCurrentStmt()?.outputs[0];
|
|
240
|
+
// load 是裸 async 函数(不经 defineOp 包装),part 键 roleTable 不会由
|
|
241
|
+
// 包装层登记(import-step.ts GOTCHA 注释)——必须手动落 part 键,否则
|
|
242
|
+
// 下游 edgeRef/chamfer 报 "input shape has no role table (nameless shape)"。
|
|
243
|
+
runtimeLineage.recordOutput(asStmtId(stmtId), new Map([[stmtId, mergedRoles]]), undefined, part);
|
|
244
|
+
}
|
|
245
|
+
return out;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* 单零件 BREP 链根:fromBrep + roleTable,statement 键与 part 键同时登记。
|
|
249
|
+
*
|
|
250
|
+
* 与 `import-step.ts:74-80` 同构(方案 2026-09-18 §5.1:链根建 roleTable——
|
|
251
|
+
* 导入文件的面没有语义名,按枚举序命名 `imported:<i>`,同一文件重复导入
|
|
252
|
+
* 枚举序稳定,role 名跨次导入保持一致)。与 import_step 的差异:load 是裸
|
|
253
|
+
* async 函数(不经 defineOp),part 键 roleTable(outputTablesByPart)不会
|
|
254
|
+
* 由包装层登记,必须在此手动 `runtimeLineage.recordOutput(..., part)` 落
|
|
255
|
+
* part 键——否则 `buildNamingInput` 的 roleTableCache 为空、`edgeRef` 的
|
|
256
|
+
* `tableOfPart` 为空,STEP 导入件所有边 faces===null(倒角/圆角被禁用)。
|
|
257
|
+
*/
|
|
258
|
+
function buildBrepPart(kernel, p, part) {
|
|
259
|
+
const stmtId = String(getCurrentStmt()?.id ?? '');
|
|
260
|
+
const roles = buildImportedRoles(kernel, p.solid);
|
|
261
|
+
// recordOutput 的 roleTable 形参外层键是 string(宽松 map),不声明成
|
|
262
|
+
// RoleTable(外层键 StmtId)——避免空 stmt 时 '' 键触发类型不符。
|
|
263
|
+
const table = new Map([[stmtId, roles]]);
|
|
264
|
+
const shape = fromBrep(p.shape, { solid: p.solid, roleTable: table });
|
|
265
|
+
if (stmtId) {
|
|
266
|
+
runtimeLineage.recordOutput(asStmtId(stmtId), table, p.solid, part);
|
|
267
|
+
}
|
|
268
|
+
return shape;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* 导入面按枚举序命名(E3 / H12,与 import-step.ts 同构)。
|
|
272
|
+
*
|
|
273
|
+
* - 单零件:`imported:<i>`(i = 内核面枚举序,0 起);
|
|
274
|
+
* - 多零件 compound 成员:`imported:<memberIdx>:<i>`——同一 StmtId 下
|
|
275
|
+
* 逐成员 role 键唯一(方案 2026-09-18 §7.5 的 origin 撞名红线 / 评审
|
|
276
|
+
* P0-2):几何相同的成员(如装配中两个同型件)面 hash 会相同,若都用
|
|
277
|
+
* 裸 `imported:<i>` 会在合并表的 `roleOfOrdinal` 里撞名。
|
|
278
|
+
*/
|
|
279
|
+
function buildImportedRoles(kernel, solid, memberIdx) {
|
|
280
|
+
const hashes = kernel.subShapeHashes(solid, 'face', HASH_UPPER_BOUND);
|
|
281
|
+
const prefix = memberIdx === undefined ? '' : `${memberIdx}:`;
|
|
282
|
+
const roles = new Map();
|
|
283
|
+
for (let i = 0; i < hashes.length; i++) {
|
|
284
|
+
roles.set(`imported:${prefix}${i}`, [hashes[i]]);
|
|
285
|
+
}
|
|
286
|
+
return roles;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* mesh 路径产物构造:装了网格后端则产出**网格实体 + 近似拓扑**,否则退回裸网格。
|
|
290
|
+
*
|
|
291
|
+
* 两条分支的边界(方案 2026-10-01 §3.3):
|
|
292
|
+
* - **未装配网格后端**(`kernel.meshSolid` 缺失)→ `solid(shape)`。这是宿主的装配
|
|
293
|
+
* 事实(如小程序构建不装 brepkit),不是静默降级:该 part 本来就没有网格内核可用。
|
|
294
|
+
* - **装配了但规范化失败**(开放/非流形/自交网格)→ **抛错**,绝不退化成"无拓扑的
|
|
295
|
+
* 裸网格"——那会让所有下游 mesh op 失去选择能力,属于"报错好于掩盖"。
|
|
296
|
+
*
|
|
297
|
+
* 显示 mesh 用**网格实体的三角化**而不是原始 STL 顶点数组:规则 1(拓扑 faceRuns
|
|
298
|
+
* 所索引的三角形必须就是用户看到的三角形)。用原始 STL 数组 + 实体重新三角化会让
|
|
299
|
+
* 两者三角形数/序错位,faceRuns 直接失效。
|
|
300
|
+
*
|
|
301
|
+
* @param shape - the parsed mesh payload (base-unit coordinates).
|
|
302
|
+
* @param file - the source file name (error messages).
|
|
303
|
+
* @returns the constructed shape (mesh solid when a backend is assembled).
|
|
304
|
+
*/
|
|
305
|
+
function buildMeshPart(shape, file) {
|
|
306
|
+
const backend = getBackends().kernel.meshSolid;
|
|
307
|
+
if (!backend)
|
|
308
|
+
return solid(shape);
|
|
309
|
+
const part = getCurrentStmt()?.outputs[0];
|
|
310
|
+
let result;
|
|
311
|
+
try {
|
|
312
|
+
result = backend.normalize({ positions: shape.positions, indices: shape.indices });
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
316
|
+
throw new OpError('load', 'E_MESH_SOLID_UNWELDABLE', `E_MESH_SOLID_UNWELDABLE: [extra/load] ${JSON.stringify(file)} could not be normalized into a mesh solid` +
|
|
317
|
+
`${part ? ` (part "${part}")` : ''}: ${reason}`, { cause: err });
|
|
318
|
+
}
|
|
319
|
+
// 句柄 + 近似拓扑登记:load op 拿不到 CadRuntime 实例,故走 pending 通道
|
|
320
|
+
// (与 detectedUnit / multiPartCount 同模式),引擎在语句执行后收编。
|
|
321
|
+
if (part) {
|
|
322
|
+
setPendingMeshSolid(part, result.solid);
|
|
323
|
+
setPendingMeshTopology(part, backend.buildTopologyData(result));
|
|
324
|
+
}
|
|
325
|
+
return fromMeshSolid({ positions: result.mesh.positions, indices: result.mesh.indices }, { meshSolid: result.solid });
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* 文件级解析缓存(P2,2026-10-06):按文件内容 SHA-256 缓存解析产物。
|
|
329
|
+
*
|
|
330
|
+
* 背景:execute 全量重放时同一文件会被反复解析(e2e 重放序列 3 次 execute × 2 条
|
|
331
|
+
* load 语句 = 6 次 XCAF 解析)。occt-wasm 在 Web Worker 环境下每次 XCAF 解析都会
|
|
332
|
+
* 累积 OCCT 资源,约第 6 次解析后 BOP(common/cut)整体挂死(node 环境不复现,
|
|
333
|
+
* 内存充足)。缓存命中后同一文件全量重放只解析一次,既根治 worker BOP 挂死,
|
|
334
|
+
* 也消除重复解析/三角化的成本。
|
|
335
|
+
*
|
|
336
|
+
* 缓存 key = **引擎 id + 内容 SHA-256**(不按文件名——同名文件内容可不同,内容指纹
|
|
337
|
+
* 才可靠)。带上引擎 id 是因为缓存值持有**该内核的** BREP 句柄:换引擎(或换内核
|
|
338
|
+
* 版本)后旧句柄对新内核无效,仅按内容指纹做 key 会把 A 引擎的句柄交给 B 引擎。
|
|
339
|
+
* 缓存持有解析产物(compound 的 BREP solid 句柄等),与 statementCache 同生命周期
|
|
340
|
+
* (runtime 级;worker 重建时模块重载自然清空)。缓存只是优化:digest 计算失败时
|
|
341
|
+
* 跳过缓存(功能等价,不静默降级语义)。
|
|
342
|
+
*/
|
|
343
|
+
const loadCache = new Map();
|
|
344
|
+
async function contentHash(buffer) {
|
|
345
|
+
try {
|
|
346
|
+
const digest = await globalThis.crypto.subtle.digest('SHA-256', buffer);
|
|
347
|
+
return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
return null; // 无 WebCrypto(罕见环境):跳过缓存,功能等价
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* 文件加载白名单(P8 §4.2/§4.3,与 3d_editor config/file-formats 的 CAD 模型扩展名对齐):
|
|
355
|
+
* mesh 路径 stl/3mf;BREP 路径 step/stp/stpz/brep。
|
|
356
|
+
* iges/igs 刻意不在白名单——occt-wasm 未链接 TKDEIGES(brep-chain CAD_FORMATS 注释),
|
|
357
|
+
* 走 BREP 路径必然失败;报「不支持的扩展名」比报内核错误更清晰。宿主 iges 现状路径保留。
|
|
358
|
+
* 返回归一化格式:stp/stpz → 'step',其余原样;白名单未命中返回 undefined。
|
|
359
|
+
*/
|
|
360
|
+
const LOAD_EXTENSION_WHITELIST = {
|
|
361
|
+
stl: 'stl',
|
|
362
|
+
'3mf': '3mf',
|
|
363
|
+
step: 'step',
|
|
364
|
+
stp: 'step',
|
|
365
|
+
stpz: 'step',
|
|
366
|
+
brep: 'brep',
|
|
367
|
+
};
|
|
368
|
+
function formatFromFile(file) {
|
|
369
|
+
const ext = file.split('.').pop()?.toLowerCase() ?? '';
|
|
370
|
+
return LOAD_EXTENSION_WHITELIST[ext];
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* 魔数 sanity(P8 §4.3):后缀定格式后用文件头校验,后缀与内容明显不符时报错。
|
|
374
|
+
* 仅 3MF 做显式魔数(zip 头 PK\x03\x04 / PK\x05\x06,可靠且歧义小);
|
|
375
|
+
* STL(文本/二进制歧义)、STEP/IGES/BREP(文本格式)不做魔数,由各解析器内部消歧/报错——
|
|
376
|
+
* 遵循「解析外部数据必须宽容」红线:只有可靠判据才拒绝,不误伤正常文件。
|
|
377
|
+
*/
|
|
378
|
+
function assertFileMagic(fmt, buffer, file) {
|
|
379
|
+
if (fmt !== '3mf')
|
|
380
|
+
return;
|
|
381
|
+
const bytes = new Uint8Array(buffer.slice(0, 4));
|
|
382
|
+
const isZip = bytes[0] === 0x50 && bytes[1] === 0x4b && (bytes[2] === 0x03 || bytes[2] === 0x05);
|
|
383
|
+
if (!isZip) {
|
|
384
|
+
throw new OpError('load', 'E_ARGS_FORM', `[extra/load] file ${JSON.stringify(file)} has .3mf extension but content is not a 3MF archive`);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* params.unit(UnitName 字符串,固化在脚本行里)→ importFile 的 opts.unit。
|
|
389
|
+
* 契约(unit-system §5.2):提供即**强制设置模型的源单位**——只对无内部单位
|
|
390
|
+
* 声明、坐标可直接折算的 mesh 格式(STL/3MF)有效;STEP/BREP 走 OCCT 链
|
|
391
|
+
* (单位由文件内部声明决定),unit 参数由 load op 在 BREP 路径**明确报错**,
|
|
392
|
+
* 不在此处拦截(保持 importFile 对 mesh 格式的单一职责)。非法/非长度单位
|
|
393
|
+
* 直接报错。
|
|
394
|
+
*/
|
|
395
|
+
function buildImportOpts(unitParam) {
|
|
396
|
+
if (typeof unitParam !== 'string' || unitParam === '')
|
|
397
|
+
return undefined;
|
|
398
|
+
if (UNIT_DIM[unitParam] !== 'length') {
|
|
399
|
+
throw new OpError('load', 'E_ARGS_FORM', `[extra/load] unknown or non-length unit: ${JSON.stringify(unitParam)}`);
|
|
400
|
+
}
|
|
401
|
+
return { unit: unitParam };
|
|
402
|
+
}
|
|
403
|
+
/** Register the file's source unit for the current statement's output part. */
|
|
404
|
+
function registerDetectedUnit(unit) {
|
|
405
|
+
const stmt = getCurrentStmt();
|
|
406
|
+
const part = stmt?.outputs[0];
|
|
407
|
+
if (part)
|
|
408
|
+
setPendingDetectedUnit(part, unit);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Register the current statement's output part's import model (P0,方案
|
|
412
|
+
* 2026-10-06-step-3mf-multipart-import-plan.md §5.5): the structure data
|
|
413
|
+
* (parts identity table + STEP assembly + Bambu views) of a `cad.load`.
|
|
414
|
+
* 单/多零件均登记(单零件 parts 长度 1)。引擎在语句执行后收编进
|
|
415
|
+
* ExecutionResult.importModels,宿主据此批量建 part,不再自行解析文件。
|
|
416
|
+
*/
|
|
417
|
+
function registerImportModel(model) {
|
|
418
|
+
const stmt = getCurrentStmt();
|
|
419
|
+
const part = stmt?.outputs[0];
|
|
420
|
+
if (part)
|
|
421
|
+
setPendingImportModel(part, model);
|
|
422
|
+
}
|
|
423
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../../src/extra/ops/load.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * faijs-extra load — 加载库函数(统一 load 函数)\n *\n * file 指定资产名(用户上传文件名,不含路径、含后缀),经宿主资产解析器按名解析;\n * 格式由 file 后缀白名单自判(不依赖宿主 format 参数),isCadFormat 静态判定 brep/mesh,\n * 产物经 solid()/fromBrep() 构造器创建。\n *\n * @platform occt — 本文件 import `occt-kernel/occtKernel`(BREP 路径的 XCAF /\n * `importBrepToMesh` 平台面)。mesh 路径(STL/3MF)不依赖平台模块;本 op 无\n * `engines` 声明(不按 op 整体做引擎门,运行时按引擎能力静态分派,见下方注释)。\n */\n\nimport type { Shape } from '../../mesh/types'\nimport type { CompoundShape } from '../../shape'\nimport type { ImportModel, ImportAssemblyNode } from '../../mesh/import-model'\nimport { importFile, detectStepUnit } from '../../mesh/io'\nimport { isCadFormat } from '../../brep/brep-chain'\nimport {\n loadBrepAssembly, loadBrepAssemblyNative, solidToShape, type LoadBrepAssemblyPart,\n} from '../../brep/brep-ops'\nimport { weldToleranceFor } from '../../brep/mesh-solid'\nimport { importBrepToMesh } from '../../occt-kernel/occtKernel'\nimport { reconstructSolidFromMesh } from '../../occt-kernel/meshReconstruct'\nimport { parseStl } from '../../mesh/stl-loader'\nimport { OCCT_BREP_ENGINE_ID } from '../../brep/engine/adapters/occt'\nimport type { BrepHandle } from '../../brep/engine/types'\nimport { OpError } from '../../api/internal/result-unwrap'\nimport {\n getBackends, BrepUnsupportedError, getCurrentStmt,\n setPendingDetectedUnit, setPendingImportModel,\n setPendingMeshSolid, setPendingMeshTopology,\n} from '../../runtime-state'\nimport { solid, compound, fromBrep, fromMeshSolid } from '../../shape'\nimport { UNIT_DIM, type UnitName } from '../../units'\nimport type { BrepEngineApi } from '../../brep/engine/primitives'\nimport { runtimeLineage } from '../../topology/naming/lineage'\nimport { asStmtId, type PartName } from '../../identity'\nimport { HASH_UPPER_BOUND } from '../../brep/face-evolution'\n// 只取**类型**:后端实现的运行时依赖(内核、拓扑构建器)留在 core,不进扩展库。\nimport type { MeshSolidBackend } from '../../brep/mesh-solid'\n\n/**\n * 执行加载操作(统一 load 函数)\n *\n * 按 params.file(资产名)从宿主资产库解析 buffer。\n *\n * 静态分派:\n * - CAD 源 + kernel + 非 mesh 模式 → BREP 路径(loadBrep 异常 = 未预期错误,冒泡上报)\n * - 非 CAD 源 / 无 kernel / mesh 模式 → mesh 路径\n * - brep 模式且将走 mesh 路径 → 调用前抛 BrepUnsupportedError(不静默回退)\n */\n/**\n * 加载几何资产。`file` 指定资产名(用户上传文件名,不含路径、含后缀),内容经宿主资产解析器按名解析,**引用而非拷贝**。\n * @group 创建\n * @inputs 0\n * @async true\n * @qual ok\n * @name load\n * @note 语言正常化后 loadFile/loadUrl/loadByKey 别名已删除(A4),统一为 `load` 一个函数。\n * @returns Shape 加载的几何,永远是 part 的第一条语句,后面可接特征链。\n * @param params.file - 资产文件名(用户上传名,不含路径、含后缀,如 'vise.3mf');内容按名从宿主资产库取。type:string\n * @param params.unit - **强制设置模型的源单位**:仅对无内部单位声明的 mesh 格式\n * (STL/3MF)有效——提供即覆盖/忽略模型内部记录的单位(3MF `<model unit>`),\n * 按指定单位折算坐标;只有调用方确实知道单位时才提供(用户手写脚本)。未提供\n * 时:STL faijs 启发式(guessStlUnit)、3MF 文件声明。**STEP/BREP 不支持**——\n * 走 OCCT 链、单位由文件内部声明决定(读取时折算),提供 unit 直接报错。type:string\n * @note 格式由 `file` 后缀白名单自判:stl/3mf → mesh 路径;step/stp/stpz/brep → BREP 路径。宿主不再传 `format`。\n * @note 后缀白名单未命中 → 报错(不猜格式);3MF 后缀会做 zip 魔数 sanity(后缀与内容明显不符时报错)。\n * @note 本 op 要求导入物含实体(历史契约)。非实体(wire/face/shell)的导入是平台 `cad.import_brep` 的一等能力,不由本 op 承担。\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用的「文件导入 Feature」提供——`file` 读的是应用侧资产库(按用户上传文件名注册),产物语句位置与命名都是画布语义。不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。2026-10-06 起多零件文件不再单零件收敛——全量以 compound + `ExecutionResult.importModels` 返回;宿主按 `importModel.parts` 身份批量建 part。\n * @example\n * const p = await cad.load({ file: 'box.stl' })\n * const p = await cad.load({ file: 'box.3mf' })\n * const p = await cad.load({ file: 'model.step' })\n */\nexport async function load(params: Record<string, unknown>): Promise<Shape | CompoundShape> {\n const assets = getBackends().assets as {\n resolveByKey(key: string): Promise<{ bytes: ArrayBuffer }>\n } | undefined\n if (!assets) {\n throw new OpError('load', 'E_OP_FAILED', '[extra/load] assets is required for load op')\n }\n\n // P8:参数面收敛为 file(资产名,不含路径、含后缀)。key/path/url/format 三键已删除。\n const file = params.file\n if (typeof file !== 'string' || file === '') {\n throw new OpError('load', 'E_ARGS_FORM', '[extra/load] load op requires a non-empty file (asset file name, no path)')\n }\n if (file.includes('/') || file.includes('\\\\')) {\n throw new OpError('load', 'E_ARGS_FORM', `[extra/load] file must not contain path separators: ${JSON.stringify(file)}`)\n }\n\n // 格式自判:file 后缀白名单 → 归一化格式;未命中即报错(不猜格式)。\n const fmt = formatFromFile(file)\n if (!fmt) {\n throw new OpError('load', 'E_ARGS_FORM', `[extra/load] unsupported file extension in: ${JSON.stringify(file)}`)\n }\n\n const buffer = (await assets.resolveByKey(file)).bytes\n assertFileMagic(fmt, buffer, file)\n\n // 静态判定路径:mesh 模式 / 无 kernel / 非 CAD 源 → mesh 路径;否则 BREP 路径\n // STL 特例(2026-10-17):brepkit/occt 的 L1 面都有 importStl——STL 可以在内核里\n // 直接构造成**真 BREP 实体**(带面-边邻接),而不是走 importIndexedMesh→weld 的\n // 网格路径。网格路径的产物在 brepkit 下无任何特征操作能力(边无邻接面、钻孔/分割\n // 无实现);BREP 路径则圆角可选边、钻孔/分割走内核布尔,全链可用。**3MF 仍走 mesh\n // 路径**(内核无 import3mf,三角网格只能 importIndexedMesh)。\n const { config, kernel: kernels } = getBackends()\n const kernel = kernels.brep as BrepEngineApi | null\n const useBrep =\n config.mode !== 'mesh' && !!kernel &&\n (isCadFormat({ format: fmt }, true) || fmt === 'stl')\n\n // brep 模式且将走 mesh-only 路径 → 调用前抛错,不静默回退\n if (!useBrep && config.mode === 'brep') {\n throw new BrepUnsupportedError('E_BREP_UNSUPPORTED: load op has no BREP implementation for this source')\n }\n\n // mesh 路径:importFile 返回 { shape, parts, unit, importModel? } — unit 是文件\n // 源单位(必然有值;faijs 单一真源;元数据;坐标已是基准值)。opts.unit 强制\n // 设置源单位(mesh 格式:STL 直接折算;3MF 覆盖 `<model unit>` 声明);未提供\n // 时 STL 走 guessStlUnit 猜测、3MF 走文件声明。P0(方案 §5.4):多零件 mesh\n // (多 object 3MF)不再折叠——全量 parts 以 compound 返回 + importModel 登记;\n // 单零件保持现状(buildMeshPart)。\n if (!useBrep) {\n const opts = buildImportOpts(params.unit)\n const { shape, parts, unit, importModel } = await importFile(buffer, fmt, opts)\n registerDetectedUnit(unit)\n if (importModel) registerImportModel(importModel)\n if (parts.length > 1) {\n // 多零件:compound 全量返回(children 序 = parts.index = importModel.parts.index)。\n // 多零件的网格实体/近似拓扑登记属 P2(宿主按 compound.children 建 part 时处理)。\n return compound(parts)\n }\n return buildMeshPart(shape, file)\n }\n\n // BREP 路径(直接执行,不包 try-catch!异常 = 未预期错误,冒泡上报)\n // P2:brepChain(meshShapeCache)归引擎侧,loadBrepAssembly 不传。\n // P0(方案 §5.3):多 solid 文件经 XCAF 装配树全量导入——多零件返回 compound\n // (children 序 = parts.index),单零件返回单一 Shape(行为与现状一致)。\n // **不再接收/使用 partIndex**(取件点唯一,宿主不再拆)。\n // 单位(unit-system §5.2):STEP/.brep 走 OCCT 链——OCCT 读取时按文件内部\n // 单位声明折算(XCAF / fromBREP 均如此),**不支持用户强制设置单位**。因此\n // BREP 路径**拒绝 params.unit**:用户显式提供 unit → 明确报错(不缩放、不\n // workaround——缩放+重三角化会改变几何精度语义,且与文件声明矛盾)。\n // STL/3MF(mesh 路径,importFile)支持 opts.unit 强制折算(坐标可直接缩放)。\n const forcedUnit = buildImportOpts(params.unit)?.unit\n if (forcedUnit) {\n throw new OpError(\n 'load',\n 'E_ARGS_FORM',\n `[extra/load] ${JSON.stringify(file)}: unit 参数不支持 ${fmt}(STEP/BREP 走 OCCT 链,` +\n '单位由文件内部声明决定、读取时折算,OCCT 不支持强制设置单位);' +\n 'unit 仅支持无内部单位声明的 mesh 格式(STL/3MF)。',\n )\n }\n const text = new TextDecoder().decode(new Uint8Array(buffer))\n const declared = detectStepUnit(text) ?? 'mm'\n const hash = await contentHash(buffer)\n // key 带引擎 id(见 loadCache 注释):缓存值持有该内核的 BREP 句柄。\n const cacheKey = hash ? `${config.brepEngineId ?? '<none>'}:${hash}` : null\n // 装配读取通道(**静态**按引擎分派,无运行时回退):\n // - XCAF(`STEPCAFControl_Reader`)是 occt 内核的装配读取器 → 装配树 + 零件名/颜色;\n // - 其余引擎(brepkit)没有 XCAF → 走 L1 契约面的原生通道\n // `loadBrepAssemblyNative`(importStep/fromBREP + getSubShapes 枚举实体)。\n // 代价是零件身份只有 `imported:<i>`、无装配层级——引擎能力事实,非降级回退。\n const hasXcafChannel = config.brepEngineId === OCCT_BREP_ENGINE_ID\n /** 装配读取(无缓存):XCAF 通道产装配层级,原生通道无层级(引擎能力事实)。 */\n const readBrepParts = async (): Promise<{\n parts: LoadBrepAssemblyPart[]\n assembly?: ImportAssemblyNode\n }> => {\n if (!hasXcafChannel) return loadBrepAssemblyNative(kernel!, buffer)\n const r = await loadBrepAssembly(kernel!, buffer)\n return { parts: r.parts, ...(r.assembly ? { assembly: r.assembly } : {}) }\n }\n let brepParts: LoadBrepAssemblyPart[]\n let assembly: ImportAssemblyNode | undefined\n if (fmt === 'stl') {\n // STL 原生 BREP 通道:kernel.importStl → 单实体(无装配层级;成员名 imported:0)。\n // 与 loadBrepAssemblyNative 同一 L1 契约面;STL 无内部单位声明 → 默认 mm\n // (detectStepUnit 对 STL 文本必然返回 null,registerDetectedUnit 落到 'mm')。\n //\n // importStl 的实体**逐面独立、边不共享**——直接用它,edge naming 没有邻接面\n // (圆角选不了边)。缝合方式按内核分派(mesh 后端与 brep 引擎**同内核**才可用\n // 其私有 weld 原语,句柄域必须一致):\n // · brepkit(weapp):importStl → weld(缝共享边)→ unify(合并共面)——与\n // mesh 路径 normalizeMeshSolid 同一规范化管线;\n // · occt(web):网格 → OCCT 愈合管线 reconstructSolidFromMesh(importStl →\n // fixShape → healSolid → unifySameDomain,见 occt-kernel/meshReconstruct.ts)——\n // brepkit 的 weld 吃 brepkit 句柄,不能处理 occt 句柄。\n const meshBackend = getBackends().kernel.meshSolid as MeshSolidBackend | undefined\n const canWeld = meshBackend !== undefined && meshBackend.kernel === kernel\n let solid: BrepHandle\n if (canWeld) {\n const imported = kernel!.importStl(buffer)\n const faces = kernel!.getSubShapes(imported, 'face')\n solid = meshBackend!.ops.weld(faces, weldToleranceFor(kernel!, imported))\n meshBackend!.ops.unify(solid)\n kernel!.release(imported)\n } else {\n const parsed = parseStl(buffer)\n solid = reconstructSolidFromMesh(kernel!, parsed.positions, parsed.indices)\n }\n brepParts = [{ index: 0, name: file, shape: solidToShape(kernel!, solid), solid, color: null }]\n } else if (fmt === 'brep' && hasXcafChannel) {\n // CASCADE BREP 文本(单 solid,无装配树):XCAF(STEPCAFControl_Reader)\n // 读不了 BREP 语法——occt 下唯一读取实现是 kernel.fromBREP(importBrepToMesh)。\n // 非 occt 引擎走下方 `loadBrepAssemblyNative`(同一 kernel.fromBREP,走契约面)。\n // 产物与 STEP 单零件同构(fromBrep + solid 句柄,句柄归 brepChain 管理)。\n const imported = await importBrepToMesh(text)\n const handle = imported.shapeHandle as unknown as BrepHandle\n brepParts = [{ index: 0, name: file, shape: solidToShape(kernel!, handle), solid: handle, color: null }]\n } else if (cacheKey) {\n const cached = loadCache.get(cacheKey)\n if (cached) {\n brepParts = cached.parts\n assembly = cached.assembly\n } else {\n const r = await readBrepParts()\n brepParts = r.parts\n assembly = r.assembly\n loadCache.set(cacheKey, { parts: brepParts, assembly })\n }\n } else {\n const r = await readBrepParts()\n brepParts = r.parts\n assembly = r.assembly\n }\n // BREP 路径的源单位:文件声明(文本探测,无声明 → 'mm',与 OCCT 约定一致)。\n // unit 必然有值(faijs 单一真源),registerDetectedUnit 总是登记。\n registerDetectedUnit(declared)\n const importModel: ImportModel = {\n format: fmt === 'brep' ? 'brep' : 'step',\n unit: declared,\n parts: brepParts.map((p) => ({\n index: p.index,\n name: p.name,\n ...(p.color ? { color: p.color } : {}),\n })),\n ...(assembly ? { assembly } : {}),\n }\n registerImportModel(importModel)\n if (brepParts.length === 1) {\n const p = brepParts[0]\n return buildBrepPart(kernel, p, getCurrentStmt()?.outputs[0])\n }\n // 多零件:每个 child 带自己的 BREP solid(宿主经 brepOf(child) 读取)+\n // 逐成员 roleTable;终端合并表按同一 StmtId 落 statement 键 + part 键。\n const stmtId = String(getCurrentStmt()?.id ?? '')\n const mergedRoles = new Map<string, number[]>()\n const children = brepParts.map((p, idx) => {\n const memberRoles = buildImportedRoles(kernel, p.solid, idx)\n for (const [role, hashes] of memberRoles) mergedRoles.set(role, hashes)\n return fromBrep(p.shape, {\n solid: p.solid,\n roleTable: new Map([[stmtId, memberRoles]]),\n })\n })\n const out = compound(children)\n if (stmtId) {\n const part = getCurrentStmt()?.outputs[0]\n // load 是裸 async 函数(不经 defineOp 包装),part 键 roleTable 不会由\n // 包装层登记(import-step.ts GOTCHA 注释)——必须手动落 part 键,否则\n // 下游 edgeRef/chamfer 报 \"input shape has no role table (nameless shape)\"。\n runtimeLineage.recordOutput(asStmtId(stmtId), new Map([[stmtId, mergedRoles]]), undefined, part)\n }\n return out\n}\n\n/**\n * 单零件 BREP 链根:fromBrep + roleTable,statement 键与 part 键同时登记。\n *\n * 与 `import-step.ts:74-80` 同构(方案 2026-09-18 §5.1:链根建 roleTable——\n * 导入文件的面没有语义名,按枚举序命名 `imported:<i>`,同一文件重复导入\n * 枚举序稳定,role 名跨次导入保持一致)。与 import_step 的差异:load 是裸\n * async 函数(不经 defineOp),part 键 roleTable(outputTablesByPart)不会\n * 由包装层登记,必须在此手动 `runtimeLineage.recordOutput(..., part)` 落\n * part 键——否则 `buildNamingInput` 的 roleTableCache 为空、`edgeRef` 的\n * `tableOfPart` 为空,STEP 导入件所有边 faces===null(倒角/圆角被禁用)。\n */\nfunction buildBrepPart(\n kernel: BrepEngineApi,\n p: LoadBrepAssemblyPart,\n part: PartName | undefined,\n): Shape {\n const stmtId = String(getCurrentStmt()?.id ?? '')\n const roles = buildImportedRoles(kernel, p.solid)\n // recordOutput 的 roleTable 形参外层键是 string(宽松 map),不声明成\n // RoleTable(外层键 StmtId)——避免空 stmt 时 '' 键触发类型不符。\n const table = new Map<string, Map<string, number[]>>([[stmtId, roles]])\n const shape = fromBrep(p.shape, { solid: p.solid, roleTable: table })\n if (stmtId) {\n runtimeLineage.recordOutput(asStmtId(stmtId), table, p.solid, part)\n }\n return shape\n}\n\n/**\n * 导入面按枚举序命名(E3 / H12,与 import-step.ts 同构)。\n *\n * - 单零件:`imported:<i>`(i = 内核面枚举序,0 起);\n * - 多零件 compound 成员:`imported:<memberIdx>:<i>`——同一 StmtId 下\n * 逐成员 role 键唯一(方案 2026-09-18 §7.5 的 origin 撞名红线 / 评审\n * P0-2):几何相同的成员(如装配中两个同型件)面 hash 会相同,若都用\n * 裸 `imported:<i>` 会在合并表的 `roleOfOrdinal` 里撞名。\n */\nfunction buildImportedRoles(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n memberIdx?: number,\n): Map<string, number[]> {\n const hashes = kernel.subShapeHashes(solid, 'face', HASH_UPPER_BOUND)\n const prefix = memberIdx === undefined ? '' : `${memberIdx}:`\n const roles = new Map<string, number[]>()\n for (let i = 0; i < hashes.length; i++) {\n roles.set(`imported:${prefix}${i}`, [hashes[i]!])\n }\n return roles\n}\n\n/**\n * mesh 路径产物构造:装了网格后端则产出**网格实体 + 近似拓扑**,否则退回裸网格。\n *\n * 两条分支的边界(方案 2026-10-01 §3.3):\n * - **未装配网格后端**(`kernel.meshSolid` 缺失)→ `solid(shape)`。这是宿主的装配\n * 事实(如小程序构建不装 brepkit),不是静默降级:该 part 本来就没有网格内核可用。\n * - **装配了但规范化失败**(开放/非流形/自交网格)→ **抛错**,绝不退化成\"无拓扑的\n * 裸网格\"——那会让所有下游 mesh op 失去选择能力,属于\"报错好于掩盖\"。\n *\n * 显示 mesh 用**网格实体的三角化**而不是原始 STL 顶点数组:规则 1(拓扑 faceRuns\n * 所索引的三角形必须就是用户看到的三角形)。用原始 STL 数组 + 实体重新三角化会让\n * 两者三角形数/序错位,faceRuns 直接失效。\n *\n * @param shape - the parsed mesh payload (base-unit coordinates).\n * @param file - the source file name (error messages).\n * @returns the constructed shape (mesh solid when a backend is assembled).\n */\nfunction buildMeshPart(shape: Shape, file: string): Shape {\n const backend = getBackends().kernel.meshSolid as MeshSolidBackend | undefined\n if (!backend) return solid(shape)\n\n const part = getCurrentStmt()?.outputs[0]\n let result: ReturnType<MeshSolidBackend['normalize']>\n try {\n result = backend.normalize({ positions: shape.positions, indices: shape.indices })\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err)\n throw new OpError(\n 'load',\n 'E_MESH_SOLID_UNWELDABLE',\n `E_MESH_SOLID_UNWELDABLE: [extra/load] ${JSON.stringify(file)} could not be normalized into a mesh solid` +\n `${part ? ` (part \"${part}\")` : ''}: ${reason}`,\n { cause: err },\n )\n }\n\n // 句柄 + 近似拓扑登记:load op 拿不到 CadRuntime 实例,故走 pending 通道\n // (与 detectedUnit / multiPartCount 同模式),引擎在语句执行后收编。\n if (part) {\n setPendingMeshSolid(part, result.solid)\n setPendingMeshTopology(part, backend.buildTopologyData(result))\n }\n return fromMeshSolid(\n { positions: result.mesh.positions, indices: result.mesh.indices },\n { meshSolid: result.solid },\n )\n}\n\n/**\n * 文件级解析缓存(P2,2026-10-06):按文件内容 SHA-256 缓存解析产物。\n *\n * 背景:execute 全量重放时同一文件会被反复解析(e2e 重放序列 3 次 execute × 2 条\n * load 语句 = 6 次 XCAF 解析)。occt-wasm 在 Web Worker 环境下每次 XCAF 解析都会\n * 累积 OCCT 资源,约第 6 次解析后 BOP(common/cut)整体挂死(node 环境不复现,\n * 内存充足)。缓存命中后同一文件全量重放只解析一次,既根治 worker BOP 挂死,\n * 也消除重复解析/三角化的成本。\n *\n * 缓存 key = **引擎 id + 内容 SHA-256**(不按文件名——同名文件内容可不同,内容指纹\n * 才可靠)。带上引擎 id 是因为缓存值持有**该内核的** BREP 句柄:换引擎(或换内核\n * 版本)后旧句柄对新内核无效,仅按内容指纹做 key 会把 A 引擎的句柄交给 B 引擎。\n * 缓存持有解析产物(compound 的 BREP solid 句柄等),与 statementCache 同生命周期\n * (runtime 级;worker 重建时模块重载自然清空)。缓存只是优化:digest 计算失败时\n * 跳过缓存(功能等价,不静默降级语义)。\n */\nconst loadCache = new Map<string, { parts: LoadBrepAssemblyPart[]; assembly?: ImportAssemblyNode }>()\n\nasync function contentHash(buffer: ArrayBuffer): Promise<string | null> {\n try {\n const digest = await globalThis.crypto.subtle.digest('SHA-256', buffer)\n return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, '0')).join('')\n } catch {\n return null // 无 WebCrypto(罕见环境):跳过缓存,功能等价\n }\n}\n\n/**\n * 文件加载白名单(P8 §4.2/§4.3,与 3d_editor config/file-formats 的 CAD 模型扩展名对齐):\n * mesh 路径 stl/3mf;BREP 路径 step/stp/stpz/brep。\n * iges/igs 刻意不在白名单——occt-wasm 未链接 TKDEIGES(brep-chain CAD_FORMATS 注释),\n * 走 BREP 路径必然失败;报「不支持的扩展名」比报内核错误更清晰。宿主 iges 现状路径保留。\n * 返回归一化格式:stp/stpz → 'step',其余原样;白名单未命中返回 undefined。\n */\nconst LOAD_EXTENSION_WHITELIST: Record<string, string> = {\n stl: 'stl',\n '3mf': '3mf',\n step: 'step',\n stp: 'step',\n stpz: 'step',\n brep: 'brep',\n}\n\nfunction formatFromFile(file: string): string | undefined {\n const ext = file.split('.').pop()?.toLowerCase() ?? ''\n return LOAD_EXTENSION_WHITELIST[ext]\n}\n\n/**\n * 魔数 sanity(P8 §4.3):后缀定格式后用文件头校验,后缀与内容明显不符时报错。\n * 仅 3MF 做显式魔数(zip 头 PK\\x03\\x04 / PK\\x05\\x06,可靠且歧义小);\n * STL(文本/二进制歧义)、STEP/IGES/BREP(文本格式)不做魔数,由各解析器内部消歧/报错——\n * 遵循「解析外部数据必须宽容」红线:只有可靠判据才拒绝,不误伤正常文件。\n */\nfunction assertFileMagic(fmt: string, buffer: ArrayBuffer, file: string): void {\n if (fmt !== '3mf') return\n const bytes = new Uint8Array(buffer.slice(0, 4))\n const isZip = bytes[0] === 0x50 && bytes[1] === 0x4b && (bytes[2] === 0x03 || bytes[2] === 0x05)\n if (!isZip) {\n throw new OpError(\n 'load',\n 'E_ARGS_FORM',\n `[extra/load] file ${JSON.stringify(file)} has .3mf extension but content is not a 3MF archive`,\n )\n }\n}\n\n/**\n * params.unit(UnitName 字符串,固化在脚本行里)→ importFile 的 opts.unit。\n * 契约(unit-system §5.2):提供即**强制设置模型的源单位**——只对无内部单位\n * 声明、坐标可直接折算的 mesh 格式(STL/3MF)有效;STEP/BREP 走 OCCT 链\n * (单位由文件内部声明决定),unit 参数由 load op 在 BREP 路径**明确报错**,\n * 不在此处拦截(保持 importFile 对 mesh 格式的单一职责)。非法/非长度单位\n * 直接报错。\n */\nfunction buildImportOpts(unitParam: unknown): { unit: UnitName } | undefined {\n if (typeof unitParam !== 'string' || unitParam === '') return undefined\n if (UNIT_DIM[unitParam as UnitName] !== 'length') {\n throw new OpError('load', 'E_ARGS_FORM', `[extra/load] unknown or non-length unit: ${JSON.stringify(unitParam)}`)\n }\n return { unit: unitParam as UnitName }\n}\n\n/** Register the file's source unit for the current statement's output part. */\nfunction registerDetectedUnit(unit: UnitName): void {\n const stmt = getCurrentStmt()\n const part = stmt?.outputs[0]\n if (part) setPendingDetectedUnit(part, unit)\n}\n\n/**\n * Register the current statement's output part's import model (P0,方案\n * 2026-10-06-step-3mf-multipart-import-plan.md §5.5): the structure data\n * (parts identity table + STEP assembly + Bambu views) of a `cad.load`.\n * 单/多零件均登记(单零件 parts 长度 1)。引擎在语句执行后收编进\n * ExecutionResult.importModels,宿主据此批量建 part,不再自行解析文件。\n */\nfunction registerImportModel(model: ImportModel): void {\n const stmt = getCurrentStmt()\n const part = stmt?.outputs[0]\n if (part) setPendingImportModel(part, model)\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* faijs-extra svgExtrude — SVG 挤出创建库函数(creator 函数,无输入)
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
* dispatchPath 静态判定 brep/mesh,产物经 solid()/fromBrep() 构造器创建。
|
|
6
|
+
*/
|
|
7
|
+
import type { Shape } from '../../mesh/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Validate svgExtrude parameters: `svg` is required and `depth` must be a
|
|
10
|
+
* positive number.
|
|
11
|
+
* @param params - the raw svgExtrude operation parameters.
|
|
12
|
+
*/
|
|
13
|
+
export declare function assertSvgExtrudeParams(params: Record<string, unknown>): void;
|
|
14
|
+
/**
|
|
15
|
+
* 从二维 SVG 轮廓挤出零件(拓扑操作)。
|
|
16
|
+
* @group 创建
|
|
17
|
+
* @inputs 0
|
|
18
|
+
* @async true
|
|
19
|
+
* @qual warn
|
|
20
|
+
* @name svgExtrude
|
|
21
|
+
* @note SVG 是外部资产,应优先用资产引用(`cad.asset(key)` 经 CallRefIR)而非整份 XML 内联拷贝。自然尺寸(viewBox)与缩放已显式成参数(mesh/BREP 两条路径都解析 viewBox 并传递 naturalWidth/naturalHeight),尺寸语义不再依赖两套实现各自推导。
|
|
22
|
+
* @returns Shape SVG 挤出几何,生成独立零件。
|
|
23
|
+
* @param params.svg - SVG 内容:资产 key(推荐)或整份 SVG 文本(兼容)。type:string required:true
|
|
24
|
+
* @param params.depth - 挤出深度(mm)。type:number required:true
|
|
25
|
+
* @param params.targetLongSide - 长边目标尺寸(mm)。type:number 默认 20
|
|
26
|
+
* @example
|
|
27
|
+
* const s = await cad.svgExtrude({ svg: 'logo.svg', depth: 5, targetLongSide: 20 })
|
|
28
|
+
*/
|
|
29
|
+
export declare const svgExtrude: ((params: Record<string, unknown>) => Promise<Shape>) & {
|
|
30
|
+
__faijs__dualOp?: import("../../define-op.js").DualOpMeta;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=svg-extrude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg-extrude.d.ts","sourceRoot":"","sources":["../../../src/extra/ops/svg-extrude.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAc7C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAK5E;AAcD;;;;;;;;;;;;;;IAcI;AACJ,eAAO,MAAM,UAAU;;CAsBrB,CAAA"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* faijs-extra svgExtrude — SVG 挤出创建库函数(creator 函数,无输入)
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
* dispatchPath 静态判定 brep/mesh,产物经 solid()/fromBrep() 构造器创建。
|
|
6
|
+
*/
|
|
7
|
+
import { svgExtrude as meshSvgExtrude } from '../mesh/primitives.js';
|
|
8
|
+
import { parseSvgNaturalSize } from '../../primitives/parse-svg-size.js';
|
|
9
|
+
import { svgToSolid } from '../../brep/svg/svg-to-solid.js';
|
|
10
|
+
import { solidToShape } from '../../brep/brep-ops.js';
|
|
11
|
+
import { getBrepApi } from '../../brep/handle-bridge.js';
|
|
12
|
+
import { resolveSvgArg } from '../../api/internal/svg-asset-resolver.js';
|
|
13
|
+
import { getBackends } from '../../runtime-state.js';
|
|
14
|
+
import { fromBrep } from '../../shape.js';
|
|
15
|
+
import { defineOp } from '../../sdk.js';
|
|
16
|
+
import { assertPositiveNumber } from '../../api/assert.js';
|
|
17
|
+
/**
|
|
18
|
+
* Validate svgExtrude parameters: `svg` is required and `depth` must be a
|
|
19
|
+
* positive number.
|
|
20
|
+
* @param params - the raw svgExtrude operation parameters.
|
|
21
|
+
*/
|
|
22
|
+
export function assertSvgExtrudeParams(params) {
|
|
23
|
+
if (params.svg === undefined || params.svg === null || params.svg === '') {
|
|
24
|
+
throw new Error(`[extra/svgExtrude] svg is required, got ${JSON.stringify(params.svg)}`);
|
|
25
|
+
}
|
|
26
|
+
assertPositiveNumber(params.depth, 'svgExtrude.depth');
|
|
27
|
+
}
|
|
28
|
+
/** BREP 路径:SVG path 解析 → OCCT wire/face → extrude + fromBrep 登记。 */
|
|
29
|
+
function svgExtrudeBrep(params, svgText) {
|
|
30
|
+
const kernel = getBrepApi();
|
|
31
|
+
const solidHandle = svgToSolid(kernel, svgText, {
|
|
32
|
+
depth: params.depth,
|
|
33
|
+
targetLongSide: params.targetLongSide ?? 20,
|
|
34
|
+
});
|
|
35
|
+
return fromBrep(solidToShape(kernel, solidHandle), { solid: solidHandle });
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 从二维 SVG 轮廓挤出零件(拓扑操作)。
|
|
39
|
+
* @group 创建
|
|
40
|
+
* @inputs 0
|
|
41
|
+
* @async true
|
|
42
|
+
* @qual warn
|
|
43
|
+
* @name svgExtrude
|
|
44
|
+
* @note SVG 是外部资产,应优先用资产引用(`cad.asset(key)` 经 CallRefIR)而非整份 XML 内联拷贝。自然尺寸(viewBox)与缩放已显式成参数(mesh/BREP 两条路径都解析 viewBox 并传递 naturalWidth/naturalHeight),尺寸语义不再依赖两套实现各自推导。
|
|
45
|
+
* @returns Shape SVG 挤出几何,生成独立零件。
|
|
46
|
+
* @param params.svg - SVG 内容:资产 key(推荐)或整份 SVG 文本(兼容)。type:string required:true
|
|
47
|
+
* @param params.depth - 挤出深度(mm)。type:number required:true
|
|
48
|
+
* @param params.targetLongSide - 长边目标尺寸(mm)。type:number 默认 20
|
|
49
|
+
* @example
|
|
50
|
+
* const s = await cad.svgExtrude({ svg: 'logo.svg', depth: 5, targetLongSide: 20 })
|
|
51
|
+
*/
|
|
52
|
+
export const svgExtrude = defineOp({
|
|
53
|
+
mesh: async (params) => {
|
|
54
|
+
assertSvgExtrudeParams(params);
|
|
55
|
+
const svgText = await resolveSvgArg(params.svg, { assets: getBackends().assets });
|
|
56
|
+
// mesh 路径:与 BREP 路径一致,内部解析 SVG 自然尺寸后缩放
|
|
57
|
+
const { naturalWidth, naturalHeight } = parseSvgNaturalSize(svgText);
|
|
58
|
+
return meshSvgExtrude({
|
|
59
|
+
svg: svgText,
|
|
60
|
+
depth: params.depth,
|
|
61
|
+
targetLongSide: params.targetLongSide ?? 20,
|
|
62
|
+
naturalWidth,
|
|
63
|
+
naturalHeight,
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
brep: async (params) => {
|
|
67
|
+
assertSvgExtrudeParams(params);
|
|
68
|
+
const svgText = await resolveSvgArg(params.svg, { assets: getBackends().assets });
|
|
69
|
+
return svgExtrudeBrep(params, svgText);
|
|
70
|
+
},
|
|
71
|
+
naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } },
|
|
72
|
+
paramDims: {},
|
|
73
|
+
});
|
|
74
|
+
//# sourceMappingURL=svg-extrude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg-extrude.js","sourceRoot":"","sources":["../../../src/extra/ops/svg-extrude.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAA;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEvD;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA+B;IACpE,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,IAAI,MAAM,CAAC,GAAG,KAAK,EAAE,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC1F,CAAC;IACD,oBAAoB,CAAC,MAAM,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAA;AACxD,CAAC;AAED,oEAAoE;AACpE,SAAS,cAAc,CAAC,MAA+B,EAAE,OAAe;IACtE,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAE3B,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;QAC9C,KAAK,EAAE,MAAM,CAAC,KAAe;QAC7B,cAAc,EAAG,MAAM,CAAC,cAAqC,IAAI,EAAE;KACpE,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;AAC5E,CAAC;AAED;;;;;;;;;;;;;;IAcI;AACJ,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC;IACjC,IAAI,EAAE,KAAK,EAAE,MAA+B,EAAE,EAAE;QAC9C,sBAAsB,CAAC,MAAM,CAAC,CAAA;QAC9B,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,MAAmC,EAAE,CAAC,CAAA;QAC9G,uCAAuC;QACvC,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAA;QACpE,OAAO,cAAc,CAAC;YACpB,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,MAAM,CAAC,KAAe;YAC7B,cAAc,EAAG,MAAM,CAAC,cAAqC,IAAI,EAAE;YACnE,YAAY;YACZ,aAAa;SACd,CAAC,CAAA;IACJ,CAAC;IACD,IAAI,EAAE,KAAK,EAAE,MAA+B,EAAE,EAAE;QAC9C,sBAAsB,CAAC,MAAM,CAAC,CAAA;QAC9B,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,MAAmC,EAAE,CAAC,CAAA;QAC9G,OAAO,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,CAAC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,EAAgB;IAErF,SAAS,EAAE,EAAE;CACd,CAAC,CAAA","sourcesContent":["/**\n * faijs-extra svgExtrude — SVG 挤出创建库函数(creator 函数,无输入)\n *\n *\n * dispatchPath 静态判定 brep/mesh,产物经 solid()/fromBrep() 构造器创建。\n */\n\nimport type { Shape } from '../../mesh/types'\nimport type { AssetResolver } from '../../cad-runtime/ports'\nimport { svgExtrude as meshSvgExtrude } from '../mesh/primitives'\nimport { parseSvgNaturalSize } from '../../primitives/parse-svg-size'\nimport { svgToSolid } from '../../brep/svg/svg-to-solid'\nimport { solidToShape } from '../../brep/brep-ops'\nimport { getBrepApi } from '../../brep/handle-bridge'\nimport { resolveSvgArg } from '../../api/internal/svg-asset-resolver'\nimport { getBackends } from '../../runtime-state'\nimport { fromBrep } from '../../shape'\nimport { defineOp } from '../../sdk'\nimport type { Provenance } from '../../topology/naming/lineage'\nimport { assertPositiveNumber } from '../../api/assert'\n\n/**\n * Validate svgExtrude parameters: `svg` is required and `depth` must be a\n * positive number.\n * @param params - the raw svgExtrude operation parameters.\n */\nexport function assertSvgExtrudeParams(params: Record<string, unknown>): void {\n if (params.svg === undefined || params.svg === null || params.svg === '') {\n throw new Error(`[extra/svgExtrude] svg is required, got ${JSON.stringify(params.svg)}`)\n }\n assertPositiveNumber(params.depth, 'svgExtrude.depth')\n}\n\n/** BREP 路径:SVG path 解析 → OCCT wire/face → extrude + fromBrep 登记。 */\nfunction svgExtrudeBrep(params: Record<string, unknown>, svgText: string): Shape {\n const kernel = getBrepApi()\n\n const solidHandle = svgToSolid(kernel, svgText, {\n depth: params.depth as number,\n targetLongSide: (params.targetLongSide as number | undefined) ?? 20,\n })\n\n return fromBrep(solidToShape(kernel, solidHandle), { solid: solidHandle })\n}\n\n/**\n * 从二维 SVG 轮廓挤出零件(拓扑操作)。\n * @group 创建\n * @inputs 0\n * @async true\n * @qual warn\n * @name svgExtrude\n * @note SVG 是外部资产,应优先用资产引用(`cad.asset(key)` 经 CallRefIR)而非整份 XML 内联拷贝。自然尺寸(viewBox)与缩放已显式成参数(mesh/BREP 两条路径都解析 viewBox 并传递 naturalWidth/naturalHeight),尺寸语义不再依赖两套实现各自推导。\n * @returns Shape SVG 挤出几何,生成独立零件。\n * @param params.svg - SVG 内容:资产 key(推荐)或整份 SVG 文本(兼容)。type:string required:true\n * @param params.depth - 挤出深度(mm)。type:number required:true\n * @param params.targetLongSide - 长边目标尺寸(mm)。type:number 默认 20\n * @example\n * const s = await cad.svgExtrude({ svg: 'logo.svg', depth: 5, targetLongSide: 20 })\n */\nexport const svgExtrude = defineOp({\n mesh: async (params: Record<string, unknown>) => {\n assertSvgExtrudeParams(params)\n const svgText = await resolveSvgArg(params.svg, { assets: getBackends().assets as AssetResolver | undefined })\n // mesh 路径:与 BREP 路径一致,内部解析 SVG 自然尺寸后缩放\n const { naturalWidth, naturalHeight } = parseSvgNaturalSize(svgText)\n return meshSvgExtrude({\n svg: svgText,\n depth: params.depth as number,\n targetLongSide: (params.targetLongSide as number | undefined) ?? 20,\n naturalWidth,\n naturalHeight,\n })\n },\n brep: async (params: Record<string, unknown>) => {\n assertSvgExtrudeParams(params)\n const svgText = await resolveSvgArg(params.svg, { assets: getBackends().assets as AssetResolver | undefined })\n return svgExtrudeBrep(params, svgText)\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } } as Provenance,\n\n paramDims: {},\n})\n"]}
|