@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
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { Vec3, Mat4, Quat, Box3 } from '../../../math3d/index.js';
|
|
2
|
+
import { makeScrew } from '../../../primitives/screw/screw.js';
|
|
3
|
+
import { getScrewSpec } from '../../../primitives/screw/screw-db.js';
|
|
4
|
+
import { computeBoolean, geoToManifoldMesh, manifoldMeshToGeo, } from '../../../boolean/csg-backend.js';
|
|
5
|
+
import { deriveNormals } from '../../../boolean/deriveNormals.js';
|
|
6
|
+
import { cylinderGeometry } from '../../../mesh/meshdata/parametric.js';
|
|
7
|
+
import { transformShape, translateShape } from '../../../mesh/meshdata/ops.js';
|
|
8
|
+
/** Rotation matrix: +90° around X — converts Y-up vertex data to Z-up. */
|
|
9
|
+
const ROT_Y_TO_Z = new Mat4().makeRotationX(Math.PI / 2);
|
|
10
|
+
/**
|
|
11
|
+
* Build a Z-up hole geometry centered on the origin, with the axial direction
|
|
12
|
+
* along Z.
|
|
13
|
+
*
|
|
14
|
+
* - simple: CylinderGeometry rotated to Z-up
|
|
15
|
+
* - screw: makeScrew() already returns Z-up
|
|
16
|
+
*
|
|
17
|
+
* Tolerance is applied as a radial expansion (tolerance/2 on radius).
|
|
18
|
+
*
|
|
19
|
+
* @param params - drill-hole parameters (type, diameter, screw details, tolerance).
|
|
20
|
+
* @param height - axial length of the hole in millimeters.
|
|
21
|
+
* @returns the hole geometry as a Z-up Shape.
|
|
22
|
+
*/
|
|
23
|
+
export function buildHoleGeometry(params, height) {
|
|
24
|
+
const toleranceRadius = params.tolerance / 2;
|
|
25
|
+
// ── simple: CylinderGeometry → rotate to Z-up ──
|
|
26
|
+
if (params.holeType === 'simple') {
|
|
27
|
+
const r = params.diameter / 2 + toleranceRadius;
|
|
28
|
+
const geo = cylinderGeometry(r, r, height, 32);
|
|
29
|
+
return transformShape(geo, ROT_Y_TO_Z);
|
|
30
|
+
}
|
|
31
|
+
// ── screw: makeScrew() already returns Z-up ──
|
|
32
|
+
if (params.holeType === 'screw') {
|
|
33
|
+
let geo = makeScrew({
|
|
34
|
+
system: params.screwSystem,
|
|
35
|
+
specIdx: params.screwSpecIdx,
|
|
36
|
+
thread: params.screwThread,
|
|
37
|
+
pitchCustom: 0,
|
|
38
|
+
length: height,
|
|
39
|
+
head: params.screwHead,
|
|
40
|
+
nRad: 32,
|
|
41
|
+
});
|
|
42
|
+
// Center the screw on origin. makeScrew extends from Z=0 to Z=height
|
|
43
|
+
// for the body, plus headHeight = spec.dia for the head (if present).
|
|
44
|
+
// The total length = height + headHeight, so center by half that.
|
|
45
|
+
const spec = getScrewSpec(params.screwSystem, params.screwSpecIdx);
|
|
46
|
+
const headHeight = params.screwHead !== 'none' ? spec.dia : 0;
|
|
47
|
+
const totalLength = height + headHeight;
|
|
48
|
+
geo = translateShape(geo, 0, 0, -totalLength / 2);
|
|
49
|
+
// For screw with head: makeScrew places the head at the +Z end (top of
|
|
50
|
+
// the screw), but for a drill hole the head must be at the -Z end — the
|
|
51
|
+
// entry point at the surface. Reflect Z to put the head at the entry side,
|
|
52
|
+
// and reverse triangle winding to maintain correct normals.
|
|
53
|
+
if (params.screwHead !== 'none') {
|
|
54
|
+
const pos = geo.positions;
|
|
55
|
+
for (let i = 2; i < pos.length; i += 3) {
|
|
56
|
+
pos[i] = -pos[i];
|
|
57
|
+
}
|
|
58
|
+
// Fix winding order: reflection flips triangle orientation
|
|
59
|
+
const arr = geo.indices;
|
|
60
|
+
for (let i = 0; i < arr.length; i += 3) {
|
|
61
|
+
const tmp = arr[i + 1];
|
|
62
|
+
arr[i + 1] = arr[i + 2];
|
|
63
|
+
arr[i + 2] = tmp;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Apply tolerance: scale radially (X and Y in Z-up space)
|
|
67
|
+
const baseRadius = spec.dia / 2;
|
|
68
|
+
if (toleranceRadius > 0 && baseRadius > 0) {
|
|
69
|
+
const scale = 1 + toleranceRadius / baseRadius;
|
|
70
|
+
const scaleMatrix = new Mat4().makeScale(scale, scale, 1);
|
|
71
|
+
geo = transformShape(geo, scaleMatrix);
|
|
72
|
+
}
|
|
73
|
+
return geo;
|
|
74
|
+
}
|
|
75
|
+
// Fallback (should not reach)
|
|
76
|
+
const geo = cylinderGeometry(params.diameter / 2, params.diameter / 2, height, 32);
|
|
77
|
+
return transformShape(geo, ROT_Y_TO_Z);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Compute the through-hole height by raycasting against the target mesh's
|
|
81
|
+
* bounding box. Returns { height, center } so the cylinder exactly spans the
|
|
82
|
+
* model thickness along the drill direction, without extending outside.
|
|
83
|
+
*
|
|
84
|
+
* @param position - world-space position of the hole entry point.
|
|
85
|
+
* @param direction - the drill direction (normalized internally).
|
|
86
|
+
* @param bbox - world-space bounding box of the target mesh.
|
|
87
|
+
* @returns the height and world-space center of the through hole.
|
|
88
|
+
*/
|
|
89
|
+
export function computeThroughHoleDimensions(position, direction, bbox) {
|
|
90
|
+
const dir = direction.clone().normalize();
|
|
91
|
+
// Manual slab-method intersection: compute distances along dir to bbox entry/exit.
|
|
92
|
+
// This handles edge cases where position is exactly on the bbox boundary
|
|
93
|
+
// (Ray.intersectBox returns null in those cases).
|
|
94
|
+
const p = position;
|
|
95
|
+
const d = dir;
|
|
96
|
+
let tNear = -Infinity;
|
|
97
|
+
let tFar = Infinity;
|
|
98
|
+
// X slab
|
|
99
|
+
if (Math.abs(d.x) > 1e-12) {
|
|
100
|
+
const t1 = (bbox.min.x - p.x) / d.x;
|
|
101
|
+
const t2 = (bbox.max.x - p.x) / d.x;
|
|
102
|
+
tNear = Math.max(tNear, Math.min(t1, t2));
|
|
103
|
+
tFar = Math.min(tFar, Math.max(t1, t2));
|
|
104
|
+
}
|
|
105
|
+
else if (p.x < bbox.min.x || p.x > bbox.max.x) {
|
|
106
|
+
// Parallel to X slab and outside — no intersection
|
|
107
|
+
return { height: 0, center: position.clone() };
|
|
108
|
+
}
|
|
109
|
+
// Y slab
|
|
110
|
+
if (Math.abs(d.y) > 1e-12) {
|
|
111
|
+
const t1 = (bbox.min.y - p.y) / d.y;
|
|
112
|
+
const t2 = (bbox.max.y - p.y) / d.y;
|
|
113
|
+
tNear = Math.max(tNear, Math.min(t1, t2));
|
|
114
|
+
tFar = Math.min(tFar, Math.max(t1, t2));
|
|
115
|
+
}
|
|
116
|
+
else if (p.y < bbox.min.y || p.y > bbox.max.y) {
|
|
117
|
+
return { height: 0, center: position.clone() };
|
|
118
|
+
}
|
|
119
|
+
// Z slab
|
|
120
|
+
if (Math.abs(d.z) > 1e-12) {
|
|
121
|
+
const t1 = (bbox.min.z - p.z) / d.z;
|
|
122
|
+
const t2 = (bbox.max.z - p.z) / d.z;
|
|
123
|
+
tNear = Math.max(tNear, Math.min(t1, t2));
|
|
124
|
+
tFar = Math.min(tFar, Math.max(t1, t2));
|
|
125
|
+
}
|
|
126
|
+
else if (p.z < bbox.min.z || p.z > bbox.max.z) {
|
|
127
|
+
return { height: 0, center: position.clone() };
|
|
128
|
+
}
|
|
129
|
+
// Clamp: if position is inside or on boundary, tNear <= 0 <= tFar
|
|
130
|
+
// Forward distance = tFar (exit point along +dir)
|
|
131
|
+
// Backward distance = -tNear (exit point along -dir, i.e. behind us)
|
|
132
|
+
const forwardDist = tFar > 0 ? tFar : 0;
|
|
133
|
+
const backwardDist = tNear < 0 ? -tNear : 0;
|
|
134
|
+
const height = forwardDist + backwardDist;
|
|
135
|
+
const center = position.clone()
|
|
136
|
+
.add(dir.clone().multiplyScalar((forwardDist - backwardDist) / 2));
|
|
137
|
+
return { height, center };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Compute the blind-hole center: the hole entry is at the click point,
|
|
141
|
+
* the hole extends inward by `depth`. The cylinder center is at
|
|
142
|
+
* position + direction * (depth / 2).
|
|
143
|
+
*
|
|
144
|
+
* @param position - world-space hole entry point.
|
|
145
|
+
* @param direction - the drill direction (normalized internally).
|
|
146
|
+
* @param depth - blind-hole depth in millimeters.
|
|
147
|
+
* @returns the world-space cylinder center.
|
|
148
|
+
*/
|
|
149
|
+
export function computeBlindHoleCenter(position, direction, depth) {
|
|
150
|
+
return position.clone().add(direction.clone().normalize().multiplyScalar(depth / 2));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Orient and position a Z-up hole geometry (axial along Z) to world space.
|
|
154
|
+
* Returns a new geometry with the transform baked in.
|
|
155
|
+
*
|
|
156
|
+
* @param geo - Z-up hole geometry centered on the origin.
|
|
157
|
+
* @param direction - world-space axis the hole should point along.
|
|
158
|
+
* @param center - world-space position of the hole center.
|
|
159
|
+
* @returns a transformed clone of the input geometry.
|
|
160
|
+
*/
|
|
161
|
+
export function positionHoleGeometry(geo, direction, center) {
|
|
162
|
+
// Rotate Z axis to direction
|
|
163
|
+
const quat = new Quat().setFromUnitVectors(new Vec3(0, 0, 1), direction.clone().normalize());
|
|
164
|
+
const rotMatrix = new Mat4().makeRotationFromQuaternion(quat);
|
|
165
|
+
let result = transformShape(geo, rotMatrix);
|
|
166
|
+
// Translate to center
|
|
167
|
+
result = translateShape(result, center.x, center.y, center.z);
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Resolve the drill direction based on params.direction and the face normal.
|
|
172
|
+
*
|
|
173
|
+
* - 'normal': inward direction = negated face normal
|
|
174
|
+
* - 'x'/'y'/'z': axis-aligned, flipped to point INTO the material
|
|
175
|
+
* (i.e. opposite to the face normal)
|
|
176
|
+
*
|
|
177
|
+
* @param direction - requested drill-direction reference.
|
|
178
|
+
* @param faceNormal - face normal at the drill position.
|
|
179
|
+
* @returns the resolved unit drill direction.
|
|
180
|
+
*/
|
|
181
|
+
export function resolveDrillDirection(direction, faceNormal) {
|
|
182
|
+
if (direction === 'normal') {
|
|
183
|
+
return faceNormal.clone().negate().normalize();
|
|
184
|
+
}
|
|
185
|
+
// Axis-aligned direction
|
|
186
|
+
const axisDir = new Vec3(direction === 'x' ? 1 : 0, direction === 'y' ? 1 : 0, direction === 'z' ? 1 : 0);
|
|
187
|
+
// Flip to point INTO the material (opposite to face normal)
|
|
188
|
+
if (axisDir.dot(faceNormal) > 0) {
|
|
189
|
+
axisDir.negate();
|
|
190
|
+
}
|
|
191
|
+
return axisDir;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Drill a hole into a mesh in world space, returning the resulting
|
|
195
|
+
* geometry in the mesh's local space.
|
|
196
|
+
*
|
|
197
|
+
* @param target - the target mesh-like object with geometry and world matrix.
|
|
198
|
+
* @param params - drill-hole parameters.
|
|
199
|
+
* @param position - world-space hole entry point.
|
|
200
|
+
* @param faceNormal - world-space normal of the face at the entry point.
|
|
201
|
+
* @returns the drilled geometry in mesh-local space.
|
|
202
|
+
*/
|
|
203
|
+
export async function executeDrillHole(target, params, position, faceNormal) {
|
|
204
|
+
return executeDrillHoleOnGeometry(target.geometry, target.matrixWorld, params, position, faceNormal);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Core drill computation that accepts geometry + world matrix directly.
|
|
208
|
+
*
|
|
209
|
+
* This avoids the need to temporarily swap mesh.geometry when the mesh
|
|
210
|
+
* currently has a preview geometry on it. Callers that have the G0 geometry
|
|
211
|
+
* in a separate Shape can use this directly.
|
|
212
|
+
*
|
|
213
|
+
* @param sourceGeometry - the base geometry to drill (mesh-local space).
|
|
214
|
+
* @param worldMatrix - world transform of the source geometry.
|
|
215
|
+
* @param params - drill-hole parameters.
|
|
216
|
+
* @param position - world-space hole entry point.
|
|
217
|
+
* @param faceNormal - world-space face normal at the entry point.
|
|
218
|
+
* @returns the drilled geometry, transformed back into mesh-local space.
|
|
219
|
+
*/
|
|
220
|
+
export async function executeDrillHoleOnGeometry(sourceGeometry, worldMatrix, params, position, faceNormal) {
|
|
221
|
+
// 1. Compute drill direction based on params.direction
|
|
222
|
+
const direction = resolveDrillDirection(params.direction, faceNormal);
|
|
223
|
+
// 2. Compute bbox from the source geometry (in world space)
|
|
224
|
+
const bbox = new Box3();
|
|
225
|
+
const v = new Vec3();
|
|
226
|
+
for (let i = 0; i < sourceGeometry.positions.length; i += 3) {
|
|
227
|
+
v.set(sourceGeometry.positions[i], sourceGeometry.positions[i + 1], sourceGeometry.positions[i + 2]);
|
|
228
|
+
v.applyMatrix4(worldMatrix);
|
|
229
|
+
bbox.expandByPoint(v);
|
|
230
|
+
}
|
|
231
|
+
const bboxSize = bbox.getSize(new Vec3());
|
|
232
|
+
const bboxMax = Math.max(bboxSize.x, bboxSize.y, bboxSize.z);
|
|
233
|
+
// 3. Clamp depth to valid range: [0, bboxMax]
|
|
234
|
+
const safeDepth = Math.max(0, Math.min(params.depth, bboxMax));
|
|
235
|
+
// 4. Compute hole height and center
|
|
236
|
+
let holeHeight;
|
|
237
|
+
let holeCenter;
|
|
238
|
+
if (safeDepth === 0) {
|
|
239
|
+
// Through hole: clip to bbox
|
|
240
|
+
const dims = computeThroughHoleDimensions(position, direction, bbox);
|
|
241
|
+
// Add epsilon on both ends for clean CSG cut
|
|
242
|
+
holeHeight = dims.height + 0.2; // 0.1mm each side
|
|
243
|
+
holeCenter = dims.center;
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
// Blind hole
|
|
247
|
+
holeHeight = safeDepth;
|
|
248
|
+
holeCenter = computeBlindHoleCenter(position, direction, safeDepth);
|
|
249
|
+
// For screw with head: the geometry is centered at (height + headHeight)/2,
|
|
250
|
+
// so the entry (-totalLength/2) must map to position. Adjust holeCenter
|
|
251
|
+
// by direction * headHeight/2 to compensate.
|
|
252
|
+
if (params.holeType === 'screw' && params.screwHead !== 'none') {
|
|
253
|
+
const spec = getScrewSpec(params.screwSystem, params.screwSpecIdx);
|
|
254
|
+
const headHeight = spec.dia;
|
|
255
|
+
holeCenter.add(direction.clone().normalize().multiplyScalar(headHeight / 2));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// 5. Build hole geometry (Z-up, centered on origin)
|
|
259
|
+
const holeGeo = buildHoleGeometry(params, holeHeight);
|
|
260
|
+
// 6. Position hole geometry to world space
|
|
261
|
+
const holeGeoWorld = positionHoleGeometry(holeGeo, direction, holeCenter);
|
|
262
|
+
// 7. Transform source geometry to world space
|
|
263
|
+
const targetGeo = transformShape(sourceGeometry, worldMatrix);
|
|
264
|
+
// 8. Convert to ManifoldMeshData
|
|
265
|
+
const targetManifold = geoToManifoldMesh(targetGeo);
|
|
266
|
+
const holeManifold = geoToManifoldMesh(holeGeoWorld);
|
|
267
|
+
// 9. Execute CSG subtract
|
|
268
|
+
const result = await computeBoolean([targetManifold, holeManifold], 'subtract');
|
|
269
|
+
// 10. Convert back to Shape
|
|
270
|
+
const resultGeo = manifoldMeshToGeo(result);
|
|
271
|
+
// 11. Transform back to mesh local space
|
|
272
|
+
const invMatrix = new Mat4().copy(worldMatrix).invert();
|
|
273
|
+
const transformedGeo = transformShape(resultGeo, invMatrix);
|
|
274
|
+
// Derive creased normals on the committed result so sharp edges stay sharp
|
|
275
|
+
// (the old computeVertexNormals() averaged on the welded shared-vertex
|
|
276
|
+
// topology and rounded them off). toCreasedNormals transforms correctly with
|
|
277
|
+
// applyMatrix4 above, but we re-derive to guarantee the final geometry uses
|
|
278
|
+
// the unified creased-normal logic regardless of the manifold output topology.
|
|
279
|
+
const finalGeo = deriveNormals(transformedGeo);
|
|
280
|
+
return finalGeo;
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=DrillHoleCore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DrillHoleCore.js","sourceRoot":"","sources":["../../../../src/extra/mesh/drill-hole/DrillHoleCore.ts"],"names":[],"mappings":"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","sourcesContent":["import { Vec3, Mat4, Quat, Box3 } from '../../../math3d'\nimport type { Shape } from '../../../mesh/types'\nimport { makeScrew } from '../../../primitives/screw/screw'\nimport { getScrewSpec } from '../../../primitives/screw/screw-db'\nimport {\n computeBoolean,\n geoToManifoldMesh,\n manifoldMeshToGeo,\n} from '../../../boolean/csg-backend'\nimport { deriveNormals } from '../../../boolean/deriveNormals'\nimport type { ManifoldMeshData } from '../../../boolean/csg-backend'\nimport { cylinderGeometry } from '../../../mesh/meshdata/parametric'\nimport { transformShape, translateShape } from '../../../mesh/meshdata/ops'\nimport type { DrillDirection, DrillHoleParams } from './drill-types'\n\n/** Rotation matrix: +90° around X — converts Y-up vertex data to Z-up. */\nconst ROT_Y_TO_Z = new Mat4().makeRotationX(Math.PI / 2)\n\n/**\n * Build a Z-up hole geometry centered on the origin, with the axial direction\n * along Z.\n *\n * - simple: CylinderGeometry rotated to Z-up\n * - screw: makeScrew() already returns Z-up\n *\n * Tolerance is applied as a radial expansion (tolerance/2 on radius).\n *\n * @param params - drill-hole parameters (type, diameter, screw details, tolerance).\n * @param height - axial length of the hole in millimeters.\n * @returns the hole geometry as a Z-up Shape.\n */\nexport function buildHoleGeometry(\n params: DrillHoleParams,\n height: number,\n): Shape {\n const toleranceRadius = params.tolerance / 2\n\n // ── simple: CylinderGeometry → rotate to Z-up ──\n if (params.holeType === 'simple') {\n const r = params.diameter / 2 + toleranceRadius\n const geo = cylinderGeometry(r, r, height, 32)\n return transformShape(geo, ROT_Y_TO_Z)\n }\n\n // ── screw: makeScrew() already returns Z-up ──\n if (params.holeType === 'screw') {\n let geo: Shape = makeScrew({\n system: params.screwSystem,\n specIdx: params.screwSpecIdx,\n thread: params.screwThread,\n pitchCustom: 0,\n length: height,\n head: params.screwHead,\n nRad: 32,\n })\n\n // Center the screw on origin. makeScrew extends from Z=0 to Z=height\n // for the body, plus headHeight = spec.dia for the head (if present).\n // The total length = height + headHeight, so center by half that.\n const spec = getScrewSpec(params.screwSystem, params.screwSpecIdx)\n const headHeight = params.screwHead !== 'none' ? spec.dia : 0\n const totalLength = height + headHeight\n geo = translateShape(geo, 0, 0, -totalLength / 2)\n\n // For screw with head: makeScrew places the head at the +Z end (top of\n // the screw), but for a drill hole the head must be at the -Z end — the\n // entry point at the surface. Reflect Z to put the head at the entry side,\n // and reverse triangle winding to maintain correct normals.\n if (params.screwHead !== 'none') {\n const pos = geo.positions\n for (let i = 2; i < pos.length; i += 3) {\n pos[i] = -pos[i]\n }\n\n // Fix winding order: reflection flips triangle orientation\n const arr = geo.indices\n for (let i = 0; i < arr.length; i += 3) {\n const tmp = arr[i + 1]\n arr[i + 1] = arr[i + 2]\n arr[i + 2] = tmp\n }\n }\n\n // Apply tolerance: scale radially (X and Y in Z-up space)\n const baseRadius = spec.dia / 2\n if (toleranceRadius > 0 && baseRadius > 0) {\n const scale = 1 + toleranceRadius / baseRadius\n const scaleMatrix = new Mat4().makeScale(scale, scale, 1)\n geo = transformShape(geo, scaleMatrix)\n }\n return geo\n }\n\n // Fallback (should not reach)\n const geo = cylinderGeometry(params.diameter / 2, params.diameter / 2, height, 32)\n return transformShape(geo, ROT_Y_TO_Z)\n}\n\n/**\n * Compute the through-hole height by raycasting against the target mesh's\n * bounding box. Returns { height, center } so the cylinder exactly spans the\n * model thickness along the drill direction, without extending outside.\n *\n * @param position - world-space position of the hole entry point.\n * @param direction - the drill direction (normalized internally).\n * @param bbox - world-space bounding box of the target mesh.\n * @returns the height and world-space center of the through hole.\n */\nexport function computeThroughHoleDimensions(\n position: Vec3,\n direction: Vec3,\n bbox: Box3,\n): { height: number; center: Vec3 } {\n const dir = direction.clone().normalize()\n\n // Manual slab-method intersection: compute distances along dir to bbox entry/exit.\n // This handles edge cases where position is exactly on the bbox boundary\n // (Ray.intersectBox returns null in those cases).\n const p = position\n const d = dir\n let tNear = -Infinity\n let tFar = Infinity\n\n // X slab\n if (Math.abs(d.x) > 1e-12) {\n const t1 = (bbox.min.x - p.x) / d.x\n const t2 = (bbox.max.x - p.x) / d.x\n tNear = Math.max(tNear, Math.min(t1, t2))\n tFar = Math.min(tFar, Math.max(t1, t2))\n } else if (p.x < bbox.min.x || p.x > bbox.max.x) {\n // Parallel to X slab and outside — no intersection\n return { height: 0, center: position.clone() }\n }\n\n // Y slab\n if (Math.abs(d.y) > 1e-12) {\n const t1 = (bbox.min.y - p.y) / d.y\n const t2 = (bbox.max.y - p.y) / d.y\n tNear = Math.max(tNear, Math.min(t1, t2))\n tFar = Math.min(tFar, Math.max(t1, t2))\n } else if (p.y < bbox.min.y || p.y > bbox.max.y) {\n return { height: 0, center: position.clone() }\n }\n\n // Z slab\n if (Math.abs(d.z) > 1e-12) {\n const t1 = (bbox.min.z - p.z) / d.z\n const t2 = (bbox.max.z - p.z) / d.z\n tNear = Math.max(tNear, Math.min(t1, t2))\n tFar = Math.min(tFar, Math.max(t1, t2))\n } else if (p.z < bbox.min.z || p.z > bbox.max.z) {\n return { height: 0, center: position.clone() }\n }\n\n // Clamp: if position is inside or on boundary, tNear <= 0 <= tFar\n // Forward distance = tFar (exit point along +dir)\n // Backward distance = -tNear (exit point along -dir, i.e. behind us)\n const forwardDist = tFar > 0 ? tFar : 0\n const backwardDist = tNear < 0 ? -tNear : 0\n\n const height = forwardDist + backwardDist\n const center = position.clone()\n .add(dir.clone().multiplyScalar((forwardDist - backwardDist) / 2))\n\n return { height, center }\n}\n\n/**\n * Compute the blind-hole center: the hole entry is at the click point,\n * the hole extends inward by `depth`. The cylinder center is at\n * position + direction * (depth / 2).\n *\n * @param position - world-space hole entry point.\n * @param direction - the drill direction (normalized internally).\n * @param depth - blind-hole depth in millimeters.\n * @returns the world-space cylinder center.\n */\nexport function computeBlindHoleCenter(\n position: Vec3,\n direction: Vec3,\n depth: number,\n): Vec3 {\n return position.clone().add(direction.clone().normalize().multiplyScalar(depth / 2))\n}\n\n/**\n * Orient and position a Z-up hole geometry (axial along Z) to world space.\n * Returns a new geometry with the transform baked in.\n *\n * @param geo - Z-up hole geometry centered on the origin.\n * @param direction - world-space axis the hole should point along.\n * @param center - world-space position of the hole center.\n * @returns a transformed clone of the input geometry.\n */\nexport function positionHoleGeometry(\n geo: Shape,\n direction: Vec3,\n center: Vec3,\n): Shape {\n // Rotate Z axis to direction\n const quat = new Quat().setFromUnitVectors(\n new Vec3(0, 0, 1),\n direction.clone().normalize(),\n )\n const rotMatrix = new Mat4().makeRotationFromQuaternion(quat)\n let result = transformShape(geo, rotMatrix)\n // Translate to center\n result = translateShape(result, center.x, center.y, center.z)\n return result\n}\n\n/**\n * Resolve the drill direction based on params.direction and the face normal.\n *\n * - 'normal': inward direction = negated face normal\n * - 'x'/'y'/'z': axis-aligned, flipped to point INTO the material\n * (i.e. opposite to the face normal)\n *\n * @param direction - requested drill-direction reference.\n * @param faceNormal - face normal at the drill position.\n * @returns the resolved unit drill direction.\n */\nexport function resolveDrillDirection(\n direction: DrillDirection,\n faceNormal: Vec3,\n): Vec3 {\n if (direction === 'normal') {\n return faceNormal.clone().negate().normalize()\n }\n\n // Axis-aligned direction\n const axisDir = new Vec3(\n direction === 'x' ? 1 : 0,\n direction === 'y' ? 1 : 0,\n direction === 'z' ? 1 : 0,\n )\n\n // Flip to point INTO the material (opposite to face normal)\n if (axisDir.dot(faceNormal) > 0) {\n axisDir.negate()\n }\n return axisDir\n}\n\n/**\n * Drill a hole into a mesh in world space, returning the resulting\n * geometry in the mesh's local space.\n *\n * @param target - the target mesh-like object with geometry and world matrix.\n * @param params - drill-hole parameters.\n * @param position - world-space hole entry point.\n * @param faceNormal - world-space normal of the face at the entry point.\n * @returns the drilled geometry in mesh-local space.\n */\nexport async function executeDrillHole(\n target: { geometry: Shape; matrixWorld: Mat4 },\n params: DrillHoleParams,\n position: Vec3,\n faceNormal: Vec3,\n): Promise<Shape> {\n return executeDrillHoleOnGeometry(\n target.geometry,\n target.matrixWorld,\n params,\n position,\n faceNormal,\n )\n}\n\n/**\n * Core drill computation that accepts geometry + world matrix directly.\n *\n * This avoids the need to temporarily swap mesh.geometry when the mesh\n * currently has a preview geometry on it. Callers that have the G0 geometry\n * in a separate Shape can use this directly.\n *\n * @param sourceGeometry - the base geometry to drill (mesh-local space).\n * @param worldMatrix - world transform of the source geometry.\n * @param params - drill-hole parameters.\n * @param position - world-space hole entry point.\n * @param faceNormal - world-space face normal at the entry point.\n * @returns the drilled geometry, transformed back into mesh-local space.\n */\nexport async function executeDrillHoleOnGeometry(\n sourceGeometry: Shape,\n worldMatrix: Mat4,\n params: DrillHoleParams,\n position: Vec3,\n faceNormal: Vec3,\n): Promise<Shape> {\n // 1. Compute drill direction based on params.direction\n const direction = resolveDrillDirection(params.direction, faceNormal)\n\n // 2. Compute bbox from the source geometry (in world space)\n const bbox = new Box3()\n const v = new Vec3()\n for (let i = 0; i < sourceGeometry.positions.length; i += 3) {\n v.set(sourceGeometry.positions[i], sourceGeometry.positions[i + 1], sourceGeometry.positions[i + 2])\n v.applyMatrix4(worldMatrix)\n bbox.expandByPoint(v)\n }\n const bboxSize = bbox.getSize(new Vec3())\n const bboxMax = Math.max(bboxSize.x, bboxSize.y, bboxSize.z)\n\n // 3. Clamp depth to valid range: [0, bboxMax]\n const safeDepth = Math.max(0, Math.min(params.depth, bboxMax))\n\n // 4. Compute hole height and center\n let holeHeight: number\n let holeCenter: Vec3\n\n if (safeDepth === 0) {\n // Through hole: clip to bbox\n const dims = computeThroughHoleDimensions(position, direction, bbox)\n // Add epsilon on both ends for clean CSG cut\n holeHeight = dims.height + 0.2 // 0.1mm each side\n holeCenter = dims.center\n } else {\n // Blind hole\n holeHeight = safeDepth\n holeCenter = computeBlindHoleCenter(position, direction, safeDepth)\n\n // For screw with head: the geometry is centered at (height + headHeight)/2,\n // so the entry (-totalLength/2) must map to position. Adjust holeCenter\n // by direction * headHeight/2 to compensate.\n if (params.holeType === 'screw' && params.screwHead !== 'none') {\n const spec = getScrewSpec(params.screwSystem, params.screwSpecIdx)\n const headHeight = spec.dia\n holeCenter.add(direction.clone().normalize().multiplyScalar(headHeight / 2))\n }\n }\n\n // 5. Build hole geometry (Z-up, centered on origin)\n const holeGeo = buildHoleGeometry(params, holeHeight)\n\n // 6. Position hole geometry to world space\n const holeGeoWorld = positionHoleGeometry(holeGeo, direction, holeCenter)\n\n // 7. Transform source geometry to world space\n const targetGeo = transformShape(sourceGeometry, worldMatrix)\n\n // 8. Convert to ManifoldMeshData\n const targetManifold: ManifoldMeshData = geoToManifoldMesh(targetGeo)\n const holeManifold: ManifoldMeshData = geoToManifoldMesh(holeGeoWorld)\n\n // 9. Execute CSG subtract\n const result = await computeBoolean([targetManifold, holeManifold], 'subtract')\n\n // 10. Convert back to Shape\n const resultGeo = manifoldMeshToGeo(result)\n\n // 11. Transform back to mesh local space\n const invMatrix = new Mat4().copy(worldMatrix).invert()\n const transformedGeo = transformShape(resultGeo, invMatrix)\n\n // Derive creased normals on the committed result so sharp edges stay sharp\n // (the old computeVertexNormals() averaged on the welded shared-vertex\n // topology and rounded them off). toCreasedNormals transforms correctly with\n // applyMatrix4 above, but we re-derive to guarantee the final geometry uses\n // the unified creased-normal logic regardless of the manifold output topology.\n const finalGeo = deriveNormals(transformedGeo)\n\n return finalGeo\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* drill-types — 钻孔相关类型定义
|
|
3
|
+
*
|
|
4
|
+
* 从 stores/drill-store.ts 提取的纯类型,供 DrillHoleCore 使用。
|
|
5
|
+
*/
|
|
6
|
+
export type DrillHoleType = 'simple' | 'screw';
|
|
7
|
+
/** Reference axis for the drill direction: along the face normal or an axis-aligned direction. */
|
|
8
|
+
export type DrillDirection = 'normal' | 'x' | 'y' | 'z';
|
|
9
|
+
/** Thread standard used to dimension screw holes: metric or imperial. */
|
|
10
|
+
export type ScrewSystem = 'metric' | 'imperial';
|
|
11
|
+
/** Thread pitch variant for a screw hole. */
|
|
12
|
+
export type ScrewThread = 'coarse' | 'fine' | 'none';
|
|
13
|
+
/** Head (countersink) style for a screw hole. */
|
|
14
|
+
export type ScrewHead = 'none' | 'hex' | 'chc';
|
|
15
|
+
/**
|
|
16
|
+
* Full parameter set describing a drill-hole operation, including the hole
|
|
17
|
+
* type (simple or screw), geometry, depth, direction, tolerance, and the
|
|
18
|
+
* screw-specific fields used by the screw variant.
|
|
19
|
+
*/
|
|
20
|
+
export interface DrillHoleParams {
|
|
21
|
+
diameter: number;
|
|
22
|
+
depth: number;
|
|
23
|
+
holeType: DrillHoleType;
|
|
24
|
+
direction: DrillDirection;
|
|
25
|
+
tolerance: number;
|
|
26
|
+
snapEnabled: boolean;
|
|
27
|
+
screwSystem: ScrewSystem;
|
|
28
|
+
screwSpecIdx: number;
|
|
29
|
+
screwThread: ScrewThread;
|
|
30
|
+
screwPitchCustom: number;
|
|
31
|
+
screwLength: number;
|
|
32
|
+
screwHead: ScrewHead;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=drill-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drill-types.d.ts","sourceRoot":"","sources":["../../../../src/extra/mesh/drill-hole/drill-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,CAAA;AAC9C,kGAAkG;AAClG,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAEvD,yEAAyE;AACzE,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAA;AAE/C,6CAA6C;AAC7C,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAA;AAEpD,iDAAiD;AACjD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAA;AAE9C;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,aAAa,CAAA;IACvB,SAAS,EAAE,cAAc,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,OAAO,CAAA;IACpB,WAAW,EAAE,WAAW,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,WAAW,CAAA;IACxB,gBAAgB,EAAE,MAAM,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,SAAS,CAAA;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drill-types.js","sourceRoot":"","sources":["../../../../src/extra/mesh/drill-hole/drill-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG","sourcesContent":["/**\n * drill-types — 钻孔相关类型定义\n *\n * 从 stores/drill-store.ts 提取的纯类型,供 DrillHoleCore 使用。\n */\n\nexport type DrillHoleType = 'simple' | 'screw'\n/** Reference axis for the drill direction: along the face normal or an axis-aligned direction. */\nexport type DrillDirection = 'normal' | 'x' | 'y' | 'z'\n\n/** Thread standard used to dimension screw holes: metric or imperial. */\nexport type ScrewSystem = 'metric' | 'imperial'\n\n/** Thread pitch variant for a screw hole. */\nexport type ScrewThread = 'coarse' | 'fine' | 'none'\n\n/** Head (countersink) style for a screw hole. */\nexport type ScrewHead = 'none' | 'hex' | 'chc'\n\n/**\n * Full parameter set describing a drill-hole operation, including the hole\n * type (simple or screw), geometry, depth, direction, tolerance, and the\n * screw-specific fields used by the screw variant.\n */\nexport interface DrillHoleParams {\n diameter: number\n depth: number\n holeType: DrillHoleType\n direction: DrillDirection\n tolerance: number\n snapEnabled: boolean\n screwSystem: ScrewSystem\n screwSpecIdx: number\n screwThread: ScrewThread\n screwPitchCustom: number\n screwLength: number\n screwHead: ScrewHead\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* engrave-decoration — the mesh decoration geometry for `cad.engrave`.
|
|
3
|
+
*
|
|
4
|
+
* Core's `mesh/engrave.ts` calls this directly (the old host-injection
|
|
5
|
+
* port `decoration-provider.ts` was deleted when faijs-extra was absorbed
|
|
6
|
+
* into core — the text/SVG geometry chain is now an internal implementation).
|
|
7
|
+
*/
|
|
8
|
+
import type { Shape } from '../../mesh/types.js';
|
|
9
|
+
/** Decoration inputs `cad.engrave` passes to the provider. */
|
|
10
|
+
export interface EngraveDecorationParams {
|
|
11
|
+
/** Text to engrave (mutually exclusive with `svg`). */
|
|
12
|
+
text?: string;
|
|
13
|
+
/** Text size in mm. */
|
|
14
|
+
textSize?: number;
|
|
15
|
+
/** SVG source text (mutually exclusive with `text`). */
|
|
16
|
+
svg?: string;
|
|
17
|
+
/** SVG long-side target size in mm. */
|
|
18
|
+
svgSize?: number;
|
|
19
|
+
/** SVG logical width, used for the scale factor. */
|
|
20
|
+
svgNaturalWidth?: number;
|
|
21
|
+
/** SVG logical height, used for the scale factor. */
|
|
22
|
+
svgNaturalHeight?: number;
|
|
23
|
+
/** Extrusion depth in mm. */
|
|
24
|
+
depth: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Produces the decoration geometry (local space, `+Z` = extrusion direction) for
|
|
28
|
+
* `cad.engrave`'s mesh path.
|
|
29
|
+
*/
|
|
30
|
+
export type EngraveDecorationProvider = (params: EngraveDecorationParams) => Promise<Shape>;
|
|
31
|
+
/**
|
|
32
|
+
* Build the text/SVG decoration provider for `cad.engrave`'s mesh path.
|
|
33
|
+
*
|
|
34
|
+
* Semantics match the pre-split implementation inside core: the CJK branch uses
|
|
35
|
+
* the system CJK font when the Local Font Access API yields one, otherwise the
|
|
36
|
+
* registered default font (whose missing glyphs then raise the documented
|
|
37
|
+
* `[text-geometry] Character … not found in font` error).
|
|
38
|
+
*
|
|
39
|
+
* @returns the provider, ready to hand to `setEngraveDecorationProvider()`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createEngraveDecorationProvider(): EngraveDecorationProvider;
|
|
42
|
+
//# sourceMappingURL=engrave-decoration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engrave-decoration.d.ts","sourceRoot":"","sources":["../../../src/extra/mesh/engrave-decoration.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAM7C,8DAA8D;AAC9D,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oDAAoD;IACpD,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,MAAM,EAAE,uBAAuB,KAC5B,OAAO,CAAC,KAAK,CAAC,CAAA;AAEnB;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,IAAI,yBAAyB,CAuB3E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { containsCjk, loadSystemCjkFont } from '../../primitives/text/cjk-font.js';
|
|
2
|
+
import { svgToExtrudedGeometry } from '../extras/svg-extrude.js';
|
|
3
|
+
import { createTextGeometry, getOpentypeFont } from '../extras/text-geometry.js';
|
|
4
|
+
import { createMixedTextGeometry } from '../extras/text-cjk.js';
|
|
5
|
+
/**
|
|
6
|
+
* Build the text/SVG decoration provider for `cad.engrave`'s mesh path.
|
|
7
|
+
*
|
|
8
|
+
* Semantics match the pre-split implementation inside core: the CJK branch uses
|
|
9
|
+
* the system CJK font when the Local Font Access API yields one, otherwise the
|
|
10
|
+
* registered default font (whose missing glyphs then raise the documented
|
|
11
|
+
* `[text-geometry] Character … not found in font` error).
|
|
12
|
+
*
|
|
13
|
+
* @returns the provider, ready to hand to `setEngraveDecorationProvider()`.
|
|
14
|
+
*/
|
|
15
|
+
export function createEngraveDecorationProvider() {
|
|
16
|
+
return async (params) => {
|
|
17
|
+
if (params.text) {
|
|
18
|
+
const size = params.textSize ?? 10;
|
|
19
|
+
const font = await getOpentypeFont();
|
|
20
|
+
if (containsCjk(params.text)) {
|
|
21
|
+
const cjkFont = await loadSystemCjkFont();
|
|
22
|
+
if (cjkFont) {
|
|
23
|
+
return createMixedTextGeometry(params.text, size, params.depth, cjkFont.font, font);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return createTextGeometry(params.text, size, params.depth, font);
|
|
27
|
+
}
|
|
28
|
+
if (params.svg) {
|
|
29
|
+
return svgToExtrudedGeometry(params.svg, {
|
|
30
|
+
depth: params.depth,
|
|
31
|
+
targetLongSide: params.svgSize,
|
|
32
|
+
naturalWidth: params.svgNaturalWidth ?? 0,
|
|
33
|
+
naturalHeight: params.svgNaturalHeight ?? 0,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
throw new Error('[faijs-extra] engrave decoration requires either text or svg');
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=engrave-decoration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engrave-decoration.js","sourceRoot":"","sources":["../../../src/extra/mesh/engrave-decoration.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AA4B5D;;;;;;;;;GASG;AACH,MAAM,UAAU,+BAA+B;IAC7C,OAAO,KAAK,EAAE,MAAM,EAAkB,EAAE;QACtC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAA;YAClC,MAAM,IAAI,GAAG,MAAM,eAAe,EAAE,CAAA;YACpC,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,MAAM,OAAO,GAAG,MAAM,iBAAiB,EAAE,CAAA;gBACzC,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,uBAAuB,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;gBACrF,CAAC;YACH,CAAC;YACD,OAAO,kBAAkB,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAClE,CAAC;QACD,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;YACf,OAAO,qBAAqB,CAAC,MAAM,CAAC,GAAG,EAAE;gBACvC,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,cAAc,EAAE,MAAM,CAAC,OAAO;gBAC9B,YAAY,EAAE,MAAM,CAAC,eAAe,IAAI,CAAC;gBACzC,aAAa,EAAE,MAAM,CAAC,gBAAgB,IAAI,CAAC;aAC5C,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAA;IACjF,CAAC,CAAA;AACH,CAAC","sourcesContent":["/**\n * engrave-decoration — the mesh decoration geometry for `cad.engrave`.\n *\n * Core's `mesh/engrave.ts` calls this directly (the old host-injection\n * port `decoration-provider.ts` was deleted when faijs-extra was absorbed\n * into core — the text/SVG geometry chain is now an internal implementation).\n */\nimport type { Shape } from '../../mesh/types'\nimport { containsCjk, loadSystemCjkFont } from '../../primitives/text/cjk-font'\nimport { svgToExtrudedGeometry } from '../extras/svg-extrude'\nimport { createTextGeometry, getOpentypeFont } from '../extras/text-geometry'\nimport { createMixedTextGeometry } from '../extras/text-cjk'\n\n/** Decoration inputs `cad.engrave` passes to the provider. */\nexport interface EngraveDecorationParams {\n /** Text to engrave (mutually exclusive with `svg`). */\n text?: string\n /** Text size in mm. */\n textSize?: number\n /** SVG source text (mutually exclusive with `text`). */\n svg?: string\n /** SVG long-side target size in mm. */\n svgSize?: number\n /** SVG logical width, used for the scale factor. */\n svgNaturalWidth?: number\n /** SVG logical height, used for the scale factor. */\n svgNaturalHeight?: number\n /** Extrusion depth in mm. */\n depth: number\n}\n\n/**\n * Produces the decoration geometry (local space, `+Z` = extrusion direction) for\n * `cad.engrave`'s mesh path.\n */\nexport type EngraveDecorationProvider = (\n params: EngraveDecorationParams,\n) => Promise<Shape>\n\n/**\n * Build the text/SVG decoration provider for `cad.engrave`'s mesh path.\n *\n * Semantics match the pre-split implementation inside core: the CJK branch uses\n * the system CJK font when the Local Font Access API yields one, otherwise the\n * registered default font (whose missing glyphs then raise the documented\n * `[text-geometry] Character … not found in font` error).\n *\n * @returns the provider, ready to hand to `setEngraveDecorationProvider()`.\n */\nexport function createEngraveDecorationProvider(): EngraveDecorationProvider {\n return async (params): Promise<Shape> => {\n if (params.text) {\n const size = params.textSize ?? 10\n const font = await getOpentypeFont()\n if (containsCjk(params.text)) {\n const cjkFont = await loadSystemCjkFont()\n if (cjkFont) {\n return createMixedTextGeometry(params.text, size, params.depth, cjkFont.font, font)\n }\n }\n return createTextGeometry(params.text, size, params.depth, font)\n }\n if (params.svg) {\n return svgToExtrudedGeometry(params.svg, {\n depth: params.depth,\n targetLongSide: params.svgSize,\n naturalWidth: params.svgNaturalWidth ?? 0,\n naturalHeight: params.svgNaturalHeight ?? 0,\n })\n }\n throw new Error('[faijs-extra] engrave decoration requires either text or svg')\n }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mesh 钻孔 API
|
|
3
|
+
*
|
|
4
|
+
* 提取来源:
|
|
5
|
+
* - engine/components/drill-hole/DrillHoleCore.ts (executeDrillHoleOnGeometry)
|
|
6
|
+
* - engine/version-store/executors/DrillCommandExecutor.ts (executeDrillOnGeometryData)
|
|
7
|
+
*
|
|
8
|
+
* DrillCommandExecutor 已是最纯的入口(typed arrays 输入输出),
|
|
9
|
+
* mesh 直接复用其几何计算逻辑。
|
|
10
|
+
*/
|
|
11
|
+
import type { Shape, DrillParams } from '../../mesh/types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Drill a hole into a world-space shape, cutting the hole geometry out with a
|
|
14
|
+
* CSG subtract.
|
|
15
|
+
*
|
|
16
|
+
* @param shape - the world-space shape to drill into.
|
|
17
|
+
* @param params - drill parameters (position, direction, depth, hole type, screw details).
|
|
18
|
+
* @returns the drilled shape in world space.
|
|
19
|
+
*/
|
|
20
|
+
export declare function drill(shape: Shape, params: DrillParams): Promise<Shape>;
|
|
21
|
+
//# sourceMappingURL=fai_drill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fai_drill.d.ts","sourceRoot":"","sources":["../../../src/extra/mesh/fai_drill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE1D;;;;;;;GAOG;AACH,wBAAsB,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CA2E7E"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mesh 钻孔 API
|
|
3
|
+
*
|
|
4
|
+
* 提取来源:
|
|
5
|
+
* - engine/components/drill-hole/DrillHoleCore.ts (executeDrillHoleOnGeometry)
|
|
6
|
+
* - engine/version-store/executors/DrillCommandExecutor.ts (executeDrillOnGeometryData)
|
|
7
|
+
*
|
|
8
|
+
* DrillCommandExecutor 已是最纯的入口(typed arrays 输入输出),
|
|
9
|
+
* mesh 直接复用其几何计算逻辑。
|
|
10
|
+
*/
|
|
11
|
+
import { Vec3, Box3 } from '../../math3d/index.js';
|
|
12
|
+
import { buildHoleGeometry, computeThroughHoleDimensions, computeBlindHoleCenter, positionHoleGeometry, } from './drill-hole/DrillHoleCore.js';
|
|
13
|
+
import { computeBoolean, geoToManifoldMesh, } from '../../boolean/csg-backend.js';
|
|
14
|
+
import { getScrewSpec } from '../../primitives/screw/screw-db.js';
|
|
15
|
+
/**
|
|
16
|
+
* Drill a hole into a world-space shape, cutting the hole geometry out with a
|
|
17
|
+
* CSG subtract.
|
|
18
|
+
*
|
|
19
|
+
* @param shape - the world-space shape to drill into.
|
|
20
|
+
* @param params - drill parameters (position, direction, depth, hole type, screw details).
|
|
21
|
+
* @returns the drilled shape in world space.
|
|
22
|
+
*/
|
|
23
|
+
export async function drill(shape, params) {
|
|
24
|
+
const position = new Vec3(...params.position);
|
|
25
|
+
const faceNormal = new Vec3(...params.faceNormal);
|
|
26
|
+
// 1. 计算钻孔方向:direction 是 Vec3,确保朝向材料内部
|
|
27
|
+
const direction = new Vec3(...params.direction).normalize();
|
|
28
|
+
if (direction.dot(faceNormal) > 0) {
|
|
29
|
+
direction.negate();
|
|
30
|
+
}
|
|
31
|
+
// 2. 从输入几何计算 bbox(世界空间)
|
|
32
|
+
const bbox = new Box3();
|
|
33
|
+
const posVec = new Vec3();
|
|
34
|
+
for (let i = 0; i < shape.positions.length; i += 3) {
|
|
35
|
+
posVec.set(shape.positions[i], shape.positions[i + 1], shape.positions[i + 2]);
|
|
36
|
+
bbox.expandByPoint(posVec);
|
|
37
|
+
}
|
|
38
|
+
const bboxSize = bbox.getSize(new Vec3());
|
|
39
|
+
const bboxMax = Math.max(bboxSize.x, bboxSize.y, bboxSize.z);
|
|
40
|
+
// 3. 钳制深度
|
|
41
|
+
const depth = params.depth ?? 0;
|
|
42
|
+
const safeDepth = Math.max(0, Math.min(depth, bboxMax));
|
|
43
|
+
// 4. 计算孔高和中心
|
|
44
|
+
let holeHeight;
|
|
45
|
+
let holeCenter;
|
|
46
|
+
if (safeDepth === 0) {
|
|
47
|
+
// 通孔:按 bbox 裁剪
|
|
48
|
+
const dims = computeThroughHoleDimensions(position, direction, bbox);
|
|
49
|
+
holeHeight = dims.height + 0.2; // 0.1mm each side
|
|
50
|
+
holeCenter = dims.center;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// 盲孔
|
|
54
|
+
holeHeight = safeDepth;
|
|
55
|
+
holeCenter = computeBlindHoleCenter(position, direction, safeDepth);
|
|
56
|
+
// 螺丝孔带头部时调整中心
|
|
57
|
+
if (params.holeType === 'screw' && params.screwHead && params.screwHead !== 'none') {
|
|
58
|
+
const system = params.screwSystem ?? 'metric';
|
|
59
|
+
const specIdx = params.screwSpecIdx ?? 4;
|
|
60
|
+
const spec = getScrewSpec(system, specIdx);
|
|
61
|
+
const headHeight = spec.dia;
|
|
62
|
+
holeCenter.add(direction.clone().normalize().multiplyScalar(headHeight / 2));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// 5. 构建孔几何(Z-up,居中于原点)
|
|
66
|
+
const drillHoleParams = {
|
|
67
|
+
diameter: params.diameter,
|
|
68
|
+
depth: depth,
|
|
69
|
+
holeType: params.holeType ?? 'simple',
|
|
70
|
+
direction: 'normal',
|
|
71
|
+
tolerance: params.tolerance ?? 0.3,
|
|
72
|
+
snapEnabled: true,
|
|
73
|
+
screwSystem: params.screwSystem ?? 'metric',
|
|
74
|
+
screwSpecIdx: params.screwSpecIdx ?? 4,
|
|
75
|
+
screwThread: params.screwThread ?? 'coarse',
|
|
76
|
+
screwHead: params.screwHead ?? 'none',
|
|
77
|
+
screwPitchCustom: 0,
|
|
78
|
+
screwLength: 0,
|
|
79
|
+
};
|
|
80
|
+
const holeGeo = buildHoleGeometry(drillHoleParams, holeHeight);
|
|
81
|
+
// 6. 定位孔几何到世界空间
|
|
82
|
+
const holeGeoWorld = positionHoleGeometry(holeGeo, direction, holeCenter);
|
|
83
|
+
// 7. 转换为 ManifoldMeshData
|
|
84
|
+
const holeManifold = geoToManifoldMesh(holeGeoWorld);
|
|
85
|
+
// 8. CSG subtract
|
|
86
|
+
const result = await computeBoolean([shape, holeManifold], 'subtract');
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=fai_drill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fai_drill.js","sourceRoot":"","sources":["../../../src/extra/mesh/fai_drill.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mesh 钻孔 API\n *\n * 提取来源:\n * - engine/components/drill-hole/DrillHoleCore.ts (executeDrillHoleOnGeometry)\n * - engine/version-store/executors/DrillCommandExecutor.ts (executeDrillOnGeometryData)\n *\n * DrillCommandExecutor 已是最纯的入口(typed arrays 输入输出),\n * mesh 直接复用其几何计算逻辑。\n */\n\nimport { Vec3, Box3 } from '../../math3d'\nimport {\n buildHoleGeometry,\n computeThroughHoleDimensions,\n computeBlindHoleCenter,\n positionHoleGeometry,\n} from './drill-hole/DrillHoleCore'\nimport {\n computeBoolean,\n geoToManifoldMesh,\n} from '../../boolean/csg-backend'\nimport { getScrewSpec } from '../../primitives/screw/screw-db'\nimport type { Shape, DrillParams } from '../../mesh/types'\n\n/**\n * Drill a hole into a world-space shape, cutting the hole geometry out with a\n * CSG subtract.\n *\n * @param shape - the world-space shape to drill into.\n * @param params - drill parameters (position, direction, depth, hole type, screw details).\n * @returns the drilled shape in world space.\n */\nexport async function drill(shape: Shape, params: DrillParams): Promise<Shape> {\n const position = new Vec3(...params.position)\n const faceNormal = new Vec3(...params.faceNormal)\n\n // 1. 计算钻孔方向:direction 是 Vec3,确保朝向材料内部\n const direction = new Vec3(...params.direction).normalize()\n if (direction.dot(faceNormal) > 0) {\n direction.negate()\n }\n\n // 2. 从输入几何计算 bbox(世界空间)\n const bbox = new Box3()\n const posVec = new Vec3()\n for (let i = 0; i < shape.positions.length; i += 3) {\n posVec.set(shape.positions[i], shape.positions[i + 1], shape.positions[i + 2])\n bbox.expandByPoint(posVec)\n }\n const bboxSize = bbox.getSize(new Vec3())\n const bboxMax = Math.max(bboxSize.x, bboxSize.y, bboxSize.z)\n\n // 3. 钳制深度\n const depth = params.depth ?? 0\n const safeDepth = Math.max(0, Math.min(depth, bboxMax))\n\n // 4. 计算孔高和中心\n let holeHeight: number\n let holeCenter: Vec3\n\n if (safeDepth === 0) {\n // 通孔:按 bbox 裁剪\n const dims = computeThroughHoleDimensions(position, direction, bbox)\n holeHeight = dims.height + 0.2 // 0.1mm each side\n holeCenter = dims.center\n } else {\n // 盲孔\n holeHeight = safeDepth\n holeCenter = computeBlindHoleCenter(position, direction, safeDepth)\n\n // 螺丝孔带头部时调整中心\n if (params.holeType === 'screw' && params.screwHead && params.screwHead !== 'none') {\n const system = (params.screwSystem as 'metric' | 'imperial') ?? 'metric'\n const specIdx = params.screwSpecIdx ?? 4\n const spec = getScrewSpec(system, specIdx)\n const headHeight = spec.dia\n holeCenter.add(direction.clone().normalize().multiplyScalar(headHeight / 2))\n }\n }\n\n // 5. 构建孔几何(Z-up,居中于原点)\n const drillHoleParams = {\n diameter: params.diameter,\n depth: depth,\n holeType: params.holeType ?? 'simple',\n direction: 'normal' as const,\n tolerance: params.tolerance ?? 0.3,\n snapEnabled: true,\n screwSystem: (params.screwSystem as 'metric' | 'imperial') ?? 'metric',\n screwSpecIdx: params.screwSpecIdx ?? 4,\n screwThread: (params.screwThread as 'coarse' | 'fine' | 'none') ?? 'coarse',\n screwHead: (params.screwHead as 'hex' | 'chc' | 'none') ?? 'none',\n screwPitchCustom: 0,\n screwLength: 0,\n }\n const holeGeo = buildHoleGeometry(drillHoleParams, holeHeight)\n\n // 6. 定位孔几何到世界空间\n const holeGeoWorld = positionHoleGeometry(holeGeo, direction, holeCenter)\n\n // 7. 转换为 ManifoldMeshData\n const holeManifold = geoToManifoldMesh(holeGeoWorld)\n\n // 8. CSG subtract\n const result = await computeBoolean([shape, holeManifold], 'subtract')\n\n return result\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mesh 拉伸 API
|
|
3
|
+
*
|
|
4
|
+
* 提取来源:engine/boolean/extrude-helpers.ts (buildExtrudeParts)
|
|
5
|
+
* 已是纯数据函数(ManifoldMeshData 输入输出),直接包装。
|
|
6
|
+
*
|
|
7
|
+
* 拉伸语义(三段模型):
|
|
8
|
+
* - back(下半):沿法线 N 平移 offsetBack
|
|
9
|
+
* - middle(中段):平面处的截面沿 N 挤出 L
|
|
10
|
+
* - front(上半):沿法线 N 平移 offsetFront
|
|
11
|
+
* 其中 offsetFront - offsetBack === length 恒成立。
|
|
12
|
+
*/
|
|
13
|
+
import type { Shape, ExtrudeParams } from '../../mesh/types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Execute a face extrude: cut the model at the cutting plane and extrude the
|
|
16
|
+
* middle section by `length` along the plane normal, then union the three
|
|
17
|
+
* segments back into a single solid.
|
|
18
|
+
*
|
|
19
|
+
* @param shape - the world-space shape to extrude.
|
|
20
|
+
* @param params - extrude parameters (normal, planeDistance, length, mode).
|
|
21
|
+
* @returns the extruded shape in world space.
|
|
22
|
+
*/
|
|
23
|
+
export declare function extrude(shape: Shape, params: ExtrudeParams): Promise<Shape>;
|
|
24
|
+
//# sourceMappingURL=fai_extrude.d.ts.map
|