@faicad/faijs 0.14.1 → 0.16.0
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 +7 -0
- package/dist/api/api-namespace.d.ts.map +1 -1
- package/dist/api/api-namespace.js +23 -22
- package/dist/api/api-namespace.js.map +1 -1
- package/dist/api/boolean.d.ts.map +1 -1
- package/dist/api/boolean.js +26 -8
- package/dist/api/boolean.js.map +1 -1
- package/dist/api/chamfer.d.ts.map +1 -1
- package/dist/api/chamfer.js +4 -1
- package/dist/api/chamfer.js.map +1 -1
- package/dist/api/generated/cad/script-face.d.ts +1 -1
- package/dist/api/generated/cad/script-face.d.ts.map +1 -1
- package/dist/api/generated/cad/script-face.js +1 -2
- package/dist/api/generated/cad/script-face.js.map +1 -1
- package/dist/api/generated/operations.js +16 -16
- package/dist/api/generated/operations.js.map +1 -1
- package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
- package/dist/api/generated/script-face-manifest.js +0 -1
- package/dist/api/generated/script-face-manifest.js.map +1 -1
- package/dist/api/generated/script-face.d.ts +1 -4
- package/dist/api/generated/script-face.d.ts.map +1 -1
- package/dist/api/generated/script-face.js +2 -3
- package/dist/api/generated/script-face.js.map +1 -1
- package/dist/api/generated/sketching.js +1 -1
- package/dist/api/generated/sketching.js.map +1 -1
- package/dist/api/generated/topology.d.ts +0 -8
- package/dist/api/generated/topology.d.ts.map +1 -1
- package/dist/api/generated/topology.js +19 -26
- package/dist/api/generated/topology.js.map +1 -1
- package/dist/api/index.d.ts +1 -10
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +10 -18
- package/dist/api/index.js.map +1 -1
- package/dist/api/internal/compat-projection.d.ts +3 -1
- package/dist/api/internal/compat-projection.d.ts.map +1 -1
- package/dist/api/internal/compat-projection.js +8 -5
- package/dist/api/internal/compat-projection.js.map +1 -1
- package/dist/api/internal/replica-role-table.d.ts +36 -0
- package/dist/api/internal/replica-role-table.d.ts.map +1 -0
- package/dist/api/internal/replica-role-table.js +73 -0
- package/dist/api/internal/replica-role-table.js.map +1 -0
- package/dist/api/internal/result-unwrap.d.ts +3 -1
- package/dist/api/internal/result-unwrap.d.ts.map +1 -1
- package/dist/api/internal/result-unwrap.js +2 -2
- package/dist/api/internal/result-unwrap.js.map +1 -1
- package/dist/api/occt-kernel-bridge.d.ts +105 -27
- package/dist/api/occt-kernel-bridge.d.ts.map +1 -1
- package/dist/api/occt-kernel-bridge.js +255 -41
- package/dist/api/occt-kernel-bridge.js.map +1 -1
- package/dist/api/pattern.d.ts.map +1 -1
- package/dist/api/pattern.js +25 -61
- package/dist/api/pattern.js.map +1 -1
- package/dist/api/replicate.d.ts +145 -0
- package/dist/api/replicate.d.ts.map +1 -0
- package/dist/api/replicate.js +351 -0
- package/dist/api/replicate.js.map +1 -0
- package/dist/api/revolve.d.ts +36 -0
- package/dist/api/revolve.d.ts.map +1 -0
- package/dist/api/revolve.js +165 -0
- package/dist/api/revolve.js.map +1 -0
- package/dist/api/surface/arg-spec.d.ts +8 -0
- package/dist/api/surface/arg-spec.d.ts.map +1 -1
- package/dist/api/surface/arg-spec.js +37 -36
- package/dist/api/surface/arg-spec.js.map +1 -1
- package/dist/api/surface/projection-overrides.d.ts.map +1 -1
- package/dist/api/surface/projection-overrides.js +6 -0
- package/dist/api/surface/projection-overrides.js.map +1 -1
- package/dist/boolean/deriveNormals.d.ts +5 -4
- package/dist/boolean/deriveNormals.d.ts.map +1 -1
- package/dist/boolean/deriveNormals.js +24 -7
- package/dist/boolean/deriveNormals.js.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.js +58 -0
- package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
- package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brepkit.js +39 -1
- package/dist/brep/engine/adapters/brepkit.js.map +1 -1
- package/dist/brep/engine/adapters/occt.d.ts +1 -5
- package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
- package/dist/brep/engine/adapters/occt.js +232 -18
- package/dist/brep/engine/adapters/occt.js.map +1 -1
- package/dist/brep/engine/primitives.d.ts +79 -0
- package/dist/brep/engine/primitives.d.ts.map +1 -1
- package/dist/brep/engine/primitives.js.map +1 -1
- package/dist/brep/engine/types.d.ts +18 -1
- package/dist/brep/engine/types.d.ts.map +1 -1
- package/dist/brep/engine/types.js.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.js +81 -11
- package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
- package/dist/browser.d.ts +6 -28
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +6 -17
- package/dist/browser.js.map +1 -1
- package/dist/cad-runtime/admit-compat-lib.d.ts +13 -18
- package/dist/cad-runtime/admit-compat-lib.d.ts.map +1 -1
- package/dist/cad-runtime/admit-compat-lib.js +25 -18
- package/dist/cad-runtime/admit-compat-lib.js.map +1 -1
- package/dist/cad-runtime/backend-dispatch.d.ts +4 -2
- package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
- package/dist/cad-runtime/backend-dispatch.js +2 -0
- package/dist/cad-runtime/backend-dispatch.js.map +1 -1
- package/dist/cad-runtime/browser-lib-loader.d.ts +4 -6
- package/dist/cad-runtime/browser-lib-loader.d.ts.map +1 -1
- package/dist/cad-runtime/browser-lib-loader.js +4 -9
- package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
- package/dist/cad-runtime/ports.d.ts +0 -7
- 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 +1 -3
- package/dist/cad-runtime/runtime.d.ts.map +1 -1
- package/dist/cad-runtime/runtime.js +13 -18
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/env-agnostic.d.ts +38 -0
- package/dist/env-agnostic.d.ts.map +1 -0
- package/dist/env-agnostic.js +29 -0
- package/dist/env-agnostic.js.map +1 -0
- package/dist/fcstd/codegen.d.ts.map +1 -1
- package/dist/fcstd/codegen.js +8 -1
- package/dist/fcstd/codegen.js.map +1 -1
- package/dist/fcstd/expressions.d.ts +24 -0
- package/dist/fcstd/expressions.d.ts.map +1 -1
- package/dist/fcstd/expressions.js +91 -0
- package/dist/fcstd/expressions.js.map +1 -1
- package/dist/fcstd/feature-translate.d.ts.map +1 -1
- package/dist/fcstd/feature-translate.js +16 -2
- package/dist/fcstd/feature-translate.js.map +1 -1
- package/dist/fcstd/structural-types.d.ts.map +1 -1
- package/dist/fcstd/structural-types.js +5 -0
- package/dist/fcstd/structural-types.js.map +1 -1
- package/dist/index.d.ts +7 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -16
- package/dist/index.js.map +1 -1
- package/dist/lang/determinism-scanner.d.ts +9 -0
- package/dist/lang/determinism-scanner.d.ts.map +1 -1
- package/dist/lang/determinism-scanner.js +7 -1
- package/dist/lang/determinism-scanner.js.map +1 -1
- package/dist/lang/symbol-table.d.ts +31 -0
- package/dist/lang/symbol-table.d.ts.map +1 -1
- package/dist/lang/symbol-table.generated.d.ts +6 -16
- package/dist/lang/symbol-table.generated.d.ts.map +1 -1
- package/dist/lang/symbol-table.generated.js +6 -16
- package/dist/lang/symbol-table.generated.js.map +1 -1
- package/dist/lang/symbol-table.js +50 -1
- package/dist/lang/symbol-table.js.map +1 -1
- package/dist/mesh/creased-normals.d.ts +50 -0
- package/dist/mesh/creased-normals.d.ts.map +1 -0
- package/dist/mesh/creased-normals.js +114 -0
- package/dist/mesh/creased-normals.js.map +1 -0
- package/dist/mesh/decoration-provider.d.ts +53 -0
- package/dist/mesh/decoration-provider.d.ts.map +1 -0
- package/dist/mesh/decoration-provider.js +21 -0
- package/dist/mesh/decoration-provider.js.map +1 -0
- package/dist/mesh/engrave.d.ts +4 -0
- package/dist/mesh/engrave.d.ts.map +1 -1
- package/dist/mesh/engrave.js +22 -31
- package/dist/mesh/engrave.js.map +1 -1
- package/dist/mesh/index.d.ts +5 -14
- package/dist/mesh/index.d.ts.map +1 -1
- package/dist/mesh/index.js +7 -19
- package/dist/mesh/index.js.map +1 -1
- package/dist/mesh/io.d.ts +2 -1
- package/dist/mesh/io.d.ts.map +1 -1
- package/dist/mesh/io.js +5 -7
- package/dist/mesh/io.js.map +1 -1
- package/dist/mesh/primitives.d.ts +5 -18
- package/dist/mesh/primitives.d.ts.map +1 -1
- package/dist/mesh/primitives.js +4 -48
- package/dist/mesh/primitives.js.map +1 -1
- package/dist/mesh/stl-loader.d.ts +23 -0
- package/dist/mesh/stl-loader.d.ts.map +1 -0
- package/dist/mesh/stl-loader.js +139 -0
- package/dist/mesh/stl-loader.js.map +1 -0
- package/dist/module-resolver/parse-imports.d.ts +37 -0
- package/dist/module-resolver/parse-imports.d.ts.map +1 -0
- package/dist/module-resolver/parse-imports.js +39 -0
- package/dist/module-resolver/parse-imports.js.map +1 -0
- package/dist/module-resolver/resolver.d.ts +1 -1
- package/dist/module-resolver/resolver.js +2 -2
- package/dist/module-resolver/resolver.js.map +1 -1
- package/dist/node-host/cli.d.ts.map +1 -1
- package/dist/node-host/cli.js +1 -22
- package/dist/node-host/cli.js.map +1 -1
- package/dist/primitives/text/cjk-font.d.ts +42 -0
- package/dist/primitives/text/cjk-font.d.ts.map +1 -0
- package/dist/primitives/text/cjk-font.js +86 -0
- package/dist/primitives/text/cjk-font.js.map +1 -0
- package/dist/sdk.d.ts +2 -2
- package/dist/sdk.js +2 -2
- package/dist/sdk.js.map +1 -1
- package/dist/symbol-table.d.ts +15 -0
- package/dist/symbol-table.d.ts.map +1 -0
- package/dist/symbol-table.js +14 -0
- package/dist/symbol-table.js.map +1 -0
- package/dist/topology/naming/lineage-resolve.js +1 -1
- package/dist/topology/naming/lineage-resolve.js.map +1 -1
- package/dist/vendored/brepjs/kernel/index.d.ts +5 -0
- package/dist/vendored/brepjs/kernel/index.d.ts.map +1 -1
- package/dist/vendored/brepjs/kernel/index.js +11 -0
- package/dist/vendored/brepjs/kernel/index.js.map +1 -1
- package/dist/weapp.d.ts +3 -3
- package/dist/weapp.d.ts.map +1 -1
- package/dist/weapp.js +6 -3
- package/dist/weapp.js.map +1 -1
- package/package.json +16 -14
- package/dist/api/compat/index.d.ts +0 -173
- package/dist/api/compat/index.d.ts.map +0 -1
- package/dist/api/compat/index.js +0 -222
- package/dist/api/compat/index.js.map +0 -1
- package/dist/api/compound.d.ts +0 -110
- package/dist/api/compound.d.ts.map +0 -1
- package/dist/api/compound.js +0 -164
- package/dist/api/compound.js.map +0 -1
- package/dist/api/copy.d.ts +0 -40
- package/dist/api/copy.d.ts.map +0 -1
- package/dist/api/copy.js +0 -83
- package/dist/api/copy.js.map +0 -1
- package/dist/api/fai_drill.d.ts +0 -46
- package/dist/api/fai_drill.d.ts.map +0 -1
- package/dist/api/fai_drill.js +0 -243
- package/dist/api/fai_drill.js.map +0 -1
- package/dist/api/fai_extrude.d.ts +0 -36
- package/dist/api/fai_extrude.d.ts.map +0 -1
- package/dist/api/fai_extrude.js +0 -79
- package/dist/api/fai_extrude.js.map +0 -1
- package/dist/api/fai_split.d.ts +0 -46
- package/dist/api/fai_split.d.ts.map +0 -1
- package/dist/api/fai_split.js +0 -254
- package/dist/api/fai_split.js.map +0 -1
- package/dist/api/load.d.ts +0 -41
- package/dist/api/load.d.ts.map +0 -1
- package/dist/api/load.js +0 -84
- package/dist/api/load.js.map +0 -1
- package/dist/api/svgExtrude.d.ts +0 -32
- package/dist/api/svgExtrude.d.ts.map +0 -1
- package/dist/api/svgExtrude.js +0 -74
- package/dist/api/svgExtrude.js.map +0 -1
- package/dist/api/text.d.ts +0 -34
- package/dist/api/text.d.ts.map +0 -1
- package/dist/api/text.js +0 -101
- package/dist/api/text.js.map +0 -1
- package/dist/brep/text/fontTestHelper.d.ts +0 -30
- package/dist/brep/text/fontTestHelper.d.ts.map +0 -1
- package/dist/brep/text/fontTestHelper.js +0 -57
- package/dist/brep/text/fontTestHelper.js.map +0 -1
- package/dist/cad-runtime/module-executor.d.ts +0 -271
- package/dist/cad-runtime/module-executor.d.ts.map +0 -1
- package/dist/cad-runtime/module-executor.js +0 -630
- package/dist/cad-runtime/module-executor.js.map +0 -1
- package/dist/cad-runtime/terminal-dag.d.ts +0 -65
- package/dist/cad-runtime/terminal-dag.d.ts.map +0 -1
- package/dist/cad-runtime/terminal-dag.js +0 -167
- package/dist/cad-runtime/terminal-dag.js.map +0 -1
- package/dist/faqts/browser.d.ts +0 -16
- package/dist/faqts/browser.d.ts.map +0 -1
- package/dist/faqts/browser.js +0 -13
- package/dist/faqts/browser.js.map +0 -1
- package/dist/faqts/exec-blob.d.ts +0 -14
- package/dist/faqts/exec-blob.d.ts.map +0 -1
- package/dist/faqts/exec-blob.js +0 -22
- package/dist/faqts/exec-blob.js.map +0 -1
- package/dist/faqts/exec-node.d.ts +0 -15
- package/dist/faqts/exec-node.d.ts.map +0 -1
- package/dist/faqts/exec-node.js +0 -29
- package/dist/faqts/exec-node.js.map +0 -1
- package/dist/faqts/imports.d.ts +0 -74
- package/dist/faqts/imports.d.ts.map +0 -1
- package/dist/faqts/imports.js +0 -95
- package/dist/faqts/imports.js.map +0 -1
- package/dist/faqts/index.d.ts +0 -22
- package/dist/faqts/index.d.ts.map +0 -1
- package/dist/faqts/index.js +0 -21
- package/dist/faqts/index.js.map +0 -1
- package/dist/faqts/node.d.ts +0 -23
- package/dist/faqts/node.d.ts.map +0 -1
- package/dist/faqts/node.js +0 -23
- package/dist/faqts/node.js.map +0 -1
- package/dist/faqts/run.d.ts +0 -62
- package/dist/faqts/run.d.ts.map +0 -1
- package/dist/faqts/run.js +0 -62
- package/dist/faqts/run.js.map +0 -1
- package/dist/faqts/transform.d.ts +0 -43
- package/dist/faqts/transform.d.ts.map +0 -1
- package/dist/faqts/transform.js +0 -35
- package/dist/faqts/transform.js.map +0 -1
- package/dist/lang/compile.d.ts +0 -50
- package/dist/lang/compile.d.ts.map +0 -1
- package/dist/lang/compile.js +0 -368
- package/dist/lang/compile.js.map +0 -1
- package/dist/lang/keep.d.ts +0 -109
- package/dist/lang/keep.d.ts.map +0 -1
- package/dist/lang/keep.js +0 -226
- package/dist/lang/keep.js.map +0 -1
- package/dist/lang/parser.d.ts +0 -91
- package/dist/lang/parser.d.ts.map +0 -1
- package/dist/lang/parser.js +0 -1594
- package/dist/lang/parser.js.map +0 -1
- package/dist/mesh/drill-hole/DrillHoleCore.d.ts +0 -90
- package/dist/mesh/drill-hole/DrillHoleCore.d.ts.map +0 -1
- package/dist/mesh/drill-hole/DrillHoleCore.js +0 -287
- package/dist/mesh/drill-hole/DrillHoleCore.js.map +0 -1
- package/dist/mesh/drill-hole/drill-types.d.ts +0 -34
- package/dist/mesh/drill-hole/drill-types.d.ts.map +0 -1
- package/dist/mesh/drill-hole/drill-types.js +0 -7
- package/dist/mesh/drill-hole/drill-types.js.map +0 -1
- package/dist/mesh/fai_drill.d.ts +0 -21
- package/dist/mesh/fai_drill.d.ts.map +0 -1
- package/dist/mesh/fai_drill.js +0 -92
- package/dist/mesh/fai_drill.js.map +0 -1
- package/dist/mesh/fai_extrude.d.ts +0 -24
- package/dist/mesh/fai_extrude.d.ts.map +0 -1
- package/dist/mesh/fai_extrude.js +0 -42
- package/dist/mesh/fai_extrude.js.map +0 -1
- package/dist/mesh/fai_split.d.ts +0 -164
- package/dist/mesh/fai_split.d.ts.map +0 -1
- package/dist/mesh/fai_split.js +0 -269
- package/dist/mesh/fai_split.js.map +0 -1
- package/dist/primitives/svg-extrude.d.ts +0 -43
- package/dist/primitives/svg-extrude.d.ts.map +0 -1
- package/dist/primitives/svg-extrude.js +0 -78
- package/dist/primitives/svg-extrude.js.map +0 -1
- package/dist/primitives/text/cjk.d.ts +0 -61
- package/dist/primitives/text/cjk.d.ts.map +0 -1
- package/dist/primitives/text/cjk.js +0 -215
- package/dist/primitives/text/cjk.js.map +0 -1
- package/dist/primitives/text-geometry.d.ts +0 -47
- package/dist/primitives/text-geometry.d.ts.map +0 -1
- package/dist/primitives/text-geometry.js +0 -127
- package/dist/primitives/text-geometry.js.map +0 -1
- package/dist/test-helpers.d.ts +0 -31
- package/dist/test-helpers.d.ts.map +0 -1
- package/dist/test-helpers.js +0 -55
- package/dist/test-helpers.js.map +0 -1
- package/dist/vendored/brepjs/core/kernelReentrancy.d.ts +0 -41
- package/dist/vendored/brepjs/core/kernelReentrancy.d.ts.map +0 -1
- package/dist/vendored/brepjs/core/kernelReentrancy.js +0 -68
- package/dist/vendored/brepjs/core/kernelReentrancy.js.map +0 -1
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
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
|
-
/** Rotation matrix: +90° around X — converts Y-up vertex data to Z-up. */
|
|
7
|
-
const ROT_Y_TO_Z = new THREE.Matrix4().makeRotationX(Math.PI / 2);
|
|
8
|
-
/**
|
|
9
|
-
* Build a Z-up hole geometry centered on the origin, with the axial direction
|
|
10
|
-
* along Z.
|
|
11
|
-
*
|
|
12
|
-
* - simple: CylinderGeometry rotated to Z-up
|
|
13
|
-
* - screw: makeScrew() already returns Z-up
|
|
14
|
-
*
|
|
15
|
-
* Tolerance is applied as a radial expansion (tolerance/2 on radius).
|
|
16
|
-
*
|
|
17
|
-
* @param params - drill-hole parameters (type, diameter, screw details, tolerance).
|
|
18
|
-
* @param height - axial length of the hole in millimeters.
|
|
19
|
-
* @returns the hole geometry as a Z-up BufferGeometry.
|
|
20
|
-
*/
|
|
21
|
-
export function buildHoleGeometry(params, height) {
|
|
22
|
-
const toleranceRadius = params.tolerance / 2;
|
|
23
|
-
// ── simple: CylinderGeometry → rotate to Z-up ──
|
|
24
|
-
if (params.holeType === 'simple') {
|
|
25
|
-
const r = params.diameter / 2 + toleranceRadius;
|
|
26
|
-
const geo = new THREE.CylinderGeometry(r, r, height, 32);
|
|
27
|
-
geo.applyMatrix4(ROT_Y_TO_Z);
|
|
28
|
-
return geo;
|
|
29
|
-
}
|
|
30
|
-
// ── screw: makeScrew() already returns Z-up ──
|
|
31
|
-
if (params.holeType === 'screw') {
|
|
32
|
-
const geo = makeScrew({
|
|
33
|
-
system: params.screwSystem,
|
|
34
|
-
specIdx: params.screwSpecIdx,
|
|
35
|
-
thread: params.screwThread,
|
|
36
|
-
pitchCustom: 0,
|
|
37
|
-
length: height,
|
|
38
|
-
head: params.screwHead,
|
|
39
|
-
nRad: 32,
|
|
40
|
-
});
|
|
41
|
-
// Center the screw on origin. makeScrew extends from Z=0 to Z=height
|
|
42
|
-
// for the body, plus headHeight = spec.dia for the head (if present).
|
|
43
|
-
// The total length = height + headHeight, so center by half that.
|
|
44
|
-
const spec = getScrewSpec(params.screwSystem, params.screwSpecIdx);
|
|
45
|
-
const headHeight = params.screwHead !== 'none' ? spec.dia : 0;
|
|
46
|
-
const totalLength = height + headHeight;
|
|
47
|
-
geo.translate(0, 0, -totalLength / 2);
|
|
48
|
-
// For screw with head: makeScrew places the head at the +Z end (top of
|
|
49
|
-
// the screw), but for a drill hole the head must be at the -Z end — the
|
|
50
|
-
// entry point at the surface. Reflect Z to put the head at the entry side,
|
|
51
|
-
// and reverse triangle winding to maintain correct normals.
|
|
52
|
-
if (params.screwHead !== 'none') {
|
|
53
|
-
const pos = geo.getAttribute('position');
|
|
54
|
-
for (let i = 0; i < pos.count; i++) {
|
|
55
|
-
pos.setZ(i, -pos.getZ(i));
|
|
56
|
-
}
|
|
57
|
-
pos.needsUpdate = true;
|
|
58
|
-
// Fix winding order: reflection flips triangle orientation
|
|
59
|
-
const idx = geo.index;
|
|
60
|
-
const arr = idx.array;
|
|
61
|
-
for (let i = 0; i < arr.length; i += 3) {
|
|
62
|
-
const tmp = arr[i + 1];
|
|
63
|
-
arr[i + 1] = arr[i + 2];
|
|
64
|
-
arr[i + 2] = tmp;
|
|
65
|
-
}
|
|
66
|
-
idx.needsUpdate = true;
|
|
67
|
-
}
|
|
68
|
-
// Apply tolerance: scale radially (X and Y in Z-up space)
|
|
69
|
-
const baseRadius = spec.dia / 2;
|
|
70
|
-
if (toleranceRadius > 0 && baseRadius > 0) {
|
|
71
|
-
const scale = 1 + toleranceRadius / baseRadius;
|
|
72
|
-
geo.scale(scale, scale, 1);
|
|
73
|
-
}
|
|
74
|
-
return geo;
|
|
75
|
-
}
|
|
76
|
-
// Fallback (should not reach)
|
|
77
|
-
const geo = new THREE.CylinderGeometry(params.diameter / 2, params.diameter / 2, height, 32);
|
|
78
|
-
geo.applyMatrix4(ROT_Y_TO_Z);
|
|
79
|
-
return geo;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Compute the through-hole height by raycasting against the target mesh's
|
|
83
|
-
* bounding box. Returns { height, center } so the cylinder exactly spans the
|
|
84
|
-
* model thickness along the drill direction, without extending outside.
|
|
85
|
-
*
|
|
86
|
-
* @param position - world-space position of the hole entry point.
|
|
87
|
-
* @param direction - the drill direction (normalized internally).
|
|
88
|
-
* @param bbox - world-space bounding box of the target mesh.
|
|
89
|
-
* @returns the height and world-space center of the through hole.
|
|
90
|
-
*/
|
|
91
|
-
export function computeThroughHoleDimensions(position, direction, bbox) {
|
|
92
|
-
const dir = direction.clone().normalize();
|
|
93
|
-
// Manual slab-method intersection: compute distances along dir to bbox entry/exit.
|
|
94
|
-
// This handles edge cases where position is exactly on the bbox boundary
|
|
95
|
-
// (Ray.intersectBox returns null in those cases).
|
|
96
|
-
const p = position;
|
|
97
|
-
const d = dir;
|
|
98
|
-
let tNear = -Infinity;
|
|
99
|
-
let tFar = Infinity;
|
|
100
|
-
// X slab
|
|
101
|
-
if (Math.abs(d.x) > 1e-12) {
|
|
102
|
-
const t1 = (bbox.min.x - p.x) / d.x;
|
|
103
|
-
const t2 = (bbox.max.x - p.x) / d.x;
|
|
104
|
-
tNear = Math.max(tNear, Math.min(t1, t2));
|
|
105
|
-
tFar = Math.min(tFar, Math.max(t1, t2));
|
|
106
|
-
}
|
|
107
|
-
else if (p.x < bbox.min.x || p.x > bbox.max.x) {
|
|
108
|
-
// Parallel to X slab and outside — no intersection
|
|
109
|
-
return { height: 0, center: position.clone() };
|
|
110
|
-
}
|
|
111
|
-
// Y slab
|
|
112
|
-
if (Math.abs(d.y) > 1e-12) {
|
|
113
|
-
const t1 = (bbox.min.y - p.y) / d.y;
|
|
114
|
-
const t2 = (bbox.max.y - p.y) / d.y;
|
|
115
|
-
tNear = Math.max(tNear, Math.min(t1, t2));
|
|
116
|
-
tFar = Math.min(tFar, Math.max(t1, t2));
|
|
117
|
-
}
|
|
118
|
-
else if (p.y < bbox.min.y || p.y > bbox.max.y) {
|
|
119
|
-
return { height: 0, center: position.clone() };
|
|
120
|
-
}
|
|
121
|
-
// Z slab
|
|
122
|
-
if (Math.abs(d.z) > 1e-12) {
|
|
123
|
-
const t1 = (bbox.min.z - p.z) / d.z;
|
|
124
|
-
const t2 = (bbox.max.z - p.z) / d.z;
|
|
125
|
-
tNear = Math.max(tNear, Math.min(t1, t2));
|
|
126
|
-
tFar = Math.min(tFar, Math.max(t1, t2));
|
|
127
|
-
}
|
|
128
|
-
else if (p.z < bbox.min.z || p.z > bbox.max.z) {
|
|
129
|
-
return { height: 0, center: position.clone() };
|
|
130
|
-
}
|
|
131
|
-
// Clamp: if position is inside or on boundary, tNear <= 0 <= tFar
|
|
132
|
-
// Forward distance = tFar (exit point along +dir)
|
|
133
|
-
// Backward distance = -tNear (exit point along -dir, i.e. behind us)
|
|
134
|
-
const forwardDist = tFar > 0 ? tFar : 0;
|
|
135
|
-
const backwardDist = tNear < 0 ? -tNear : 0;
|
|
136
|
-
const height = forwardDist + backwardDist;
|
|
137
|
-
const center = position.clone()
|
|
138
|
-
.add(dir.clone().multiplyScalar((forwardDist - backwardDist) / 2));
|
|
139
|
-
return { height, center };
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Compute the blind-hole center: the hole entry is at the click point,
|
|
143
|
-
* the hole extends inward by `depth`. The cylinder center is at
|
|
144
|
-
* position + direction * (depth / 2).
|
|
145
|
-
*
|
|
146
|
-
* @param position - world-space hole entry point.
|
|
147
|
-
* @param direction - the drill direction (normalized internally).
|
|
148
|
-
* @param depth - blind-hole depth in millimeters.
|
|
149
|
-
* @returns the world-space cylinder center.
|
|
150
|
-
*/
|
|
151
|
-
export function computeBlindHoleCenter(position, direction, depth) {
|
|
152
|
-
return position.clone().add(direction.clone().normalize().multiplyScalar(depth / 2));
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Orient and position a Z-up hole geometry (axial along Z) to world space.
|
|
156
|
-
* Returns a new geometry with the transform baked in.
|
|
157
|
-
*
|
|
158
|
-
* @param geo - Z-up hole geometry centered on the origin.
|
|
159
|
-
* @param direction - world-space axis the hole should point along.
|
|
160
|
-
* @param center - world-space position of the hole center.
|
|
161
|
-
* @returns a transformed clone of the input geometry.
|
|
162
|
-
*/
|
|
163
|
-
export function positionHoleGeometry(geo, direction, center) {
|
|
164
|
-
const result = geo.clone();
|
|
165
|
-
// Rotate Z axis to direction
|
|
166
|
-
const quat = new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 0, 1), direction.clone().normalize());
|
|
167
|
-
result.applyQuaternion(quat);
|
|
168
|
-
// Translate to center
|
|
169
|
-
result.translate(center.x, center.y, center.z);
|
|
170
|
-
return result;
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Resolve the drill direction based on params.direction and the face normal.
|
|
174
|
-
*
|
|
175
|
-
* - 'normal': inward direction = negated face normal
|
|
176
|
-
* - 'x'/'y'/'z': axis-aligned, flipped to point INTO the material
|
|
177
|
-
* (i.e. opposite to the face normal)
|
|
178
|
-
*
|
|
179
|
-
* @param direction - requested drill-direction reference.
|
|
180
|
-
* @param faceNormal - face normal at the drill position.
|
|
181
|
-
* @returns the resolved unit drill direction.
|
|
182
|
-
*/
|
|
183
|
-
export function resolveDrillDirection(direction, faceNormal) {
|
|
184
|
-
if (direction === 'normal') {
|
|
185
|
-
return faceNormal.clone().negate().normalize();
|
|
186
|
-
}
|
|
187
|
-
// Axis-aligned direction
|
|
188
|
-
const axisDir = new THREE.Vector3(direction === 'x' ? 1 : 0, direction === 'y' ? 1 : 0, direction === 'z' ? 1 : 0);
|
|
189
|
-
// Flip to point INTO the material (opposite to face normal)
|
|
190
|
-
if (axisDir.dot(faceNormal) > 0) {
|
|
191
|
-
axisDir.negate();
|
|
192
|
-
}
|
|
193
|
-
return axisDir;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Drill a hole into a THREE.Mesh in world space, returning the resulting
|
|
197
|
-
* geometry in the mesh's local space.
|
|
198
|
-
*
|
|
199
|
-
* @param targetMesh - the mesh to drill into.
|
|
200
|
-
* @param params - drill-hole parameters.
|
|
201
|
-
* @param position - world-space hole entry point.
|
|
202
|
-
* @param faceNormal - world-space normal of the face at the entry point.
|
|
203
|
-
* @returns the drilled geometry in mesh-local space.
|
|
204
|
-
*/
|
|
205
|
-
export async function executeDrillHole(targetMesh, params, position, faceNormal) {
|
|
206
|
-
targetMesh.updateMatrixWorld();
|
|
207
|
-
return executeDrillHoleOnGeometry(targetMesh.geometry, targetMesh.matrixWorld, params, position, faceNormal);
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Core drill computation that accepts geometry + world matrix directly.
|
|
211
|
-
*
|
|
212
|
-
* This avoids the need to temporarily swap mesh.geometry when the mesh
|
|
213
|
-
* currently has a preview geometry on it. Callers that have the G0 geometry
|
|
214
|
-
* in a separate BufferGeometry can use this directly.
|
|
215
|
-
*
|
|
216
|
-
* @param sourceGeometry - the base geometry to drill (mesh-local space).
|
|
217
|
-
* @param worldMatrix - world transform of the source geometry.
|
|
218
|
-
* @param params - drill-hole parameters.
|
|
219
|
-
* @param position - world-space hole entry point.
|
|
220
|
-
* @param faceNormal - world-space face normal at the entry point.
|
|
221
|
-
* @returns the drilled geometry, transformed back into mesh-local space.
|
|
222
|
-
*/
|
|
223
|
-
export async function executeDrillHoleOnGeometry(sourceGeometry, worldMatrix, params, position, faceNormal) {
|
|
224
|
-
// 1. Compute drill direction based on params.direction
|
|
225
|
-
const direction = resolveDrillDirection(params.direction, faceNormal);
|
|
226
|
-
// 2. Compute bbox from the source geometry (in world space)
|
|
227
|
-
sourceGeometry.computeBoundingBox();
|
|
228
|
-
const bbox = sourceGeometry.boundingBox.clone();
|
|
229
|
-
bbox.applyMatrix4(worldMatrix);
|
|
230
|
-
const bboxSize = bbox.getSize(new THREE.Vector3());
|
|
231
|
-
const bboxMax = Math.max(bboxSize.x, bboxSize.y, bboxSize.z);
|
|
232
|
-
// 3. Clamp depth to valid range: [0, bboxMax]
|
|
233
|
-
const safeDepth = Math.max(0, Math.min(params.depth, bboxMax));
|
|
234
|
-
// 4. Compute hole height and center
|
|
235
|
-
let holeHeight;
|
|
236
|
-
let holeCenter;
|
|
237
|
-
if (safeDepth === 0) {
|
|
238
|
-
// Through hole: clip to bbox
|
|
239
|
-
const dims = computeThroughHoleDimensions(position, direction, bbox);
|
|
240
|
-
// Add epsilon on both ends for clean CSG cut
|
|
241
|
-
holeHeight = dims.height + 0.2; // 0.1mm each side
|
|
242
|
-
holeCenter = dims.center;
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
// Blind hole
|
|
246
|
-
holeHeight = safeDepth;
|
|
247
|
-
holeCenter = computeBlindHoleCenter(position, direction, safeDepth);
|
|
248
|
-
// For screw with head: the geometry is centered at (height + headHeight)/2,
|
|
249
|
-
// so the entry (-totalLength/2) must map to position. Adjust holeCenter
|
|
250
|
-
// by direction * headHeight/2 to compensate.
|
|
251
|
-
if (params.holeType === 'screw' && params.screwHead !== 'none') {
|
|
252
|
-
const spec = getScrewSpec(params.screwSystem, params.screwSpecIdx);
|
|
253
|
-
const headHeight = spec.dia;
|
|
254
|
-
holeCenter.add(direction.clone().normalize().multiplyScalar(headHeight / 2));
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
// 5. Build hole geometry (Z-up, centered on origin)
|
|
258
|
-
const holeGeo = buildHoleGeometry(params, holeHeight);
|
|
259
|
-
// 6. Position hole geometry to world space
|
|
260
|
-
const holeGeoWorld = positionHoleGeometry(holeGeo, direction, holeCenter);
|
|
261
|
-
// 7. Clone source geometry and transform to world space
|
|
262
|
-
const targetGeo = sourceGeometry.clone();
|
|
263
|
-
targetGeo.applyMatrix4(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 BufferGeometry
|
|
270
|
-
const resultGeo = manifoldMeshToGeo(result);
|
|
271
|
-
// 11. Transform back to mesh local space
|
|
272
|
-
const invMatrix = new THREE.Matrix4().copy(worldMatrix).invert();
|
|
273
|
-
resultGeo.applyMatrix4(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(resultGeo);
|
|
280
|
-
resultGeo.dispose();
|
|
281
|
-
// 12. Cleanup
|
|
282
|
-
holeGeo.dispose();
|
|
283
|
-
holeGeoWorld.dispose();
|
|
284
|
-
targetGeo.dispose();
|
|
285
|
-
return finalGeo;
|
|
286
|
-
}
|
|
287
|
-
//# sourceMappingURL=DrillHoleCore.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DrillHoleCore.js","sourceRoot":"","sources":["../../../src/mesh/drill-hole/DrillHoleCore.ts"],"names":[],"mappings":"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","sourcesContent":["import * as THREE from 'three'\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 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 THREE.Matrix4().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 BufferGeometry.\n */\nexport function buildHoleGeometry(\n params: DrillHoleParams,\n height: number,\n): THREE.BufferGeometry {\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 = new THREE.CylinderGeometry(r, r, height, 32)\n geo.applyMatrix4(ROT_Y_TO_Z)\n return geo\n }\n\n // ── screw: makeScrew() already returns Z-up ──\n if (params.holeType === 'screw') {\n const geo = 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.translate(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.getAttribute('position')\n for (let i = 0; i < pos.count; i++) {\n pos.setZ(i, -pos.getZ(i))\n }\n pos.needsUpdate = true\n\n // Fix winding order: reflection flips triangle orientation\n const idx = geo.index!\n const arr = idx.array as Uint16Array | Uint32Array\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 idx.needsUpdate = true\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 geo.scale(scale, scale, 1)\n }\n return geo\n }\n\n // Fallback (should not reach)\n const geo = new THREE.CylinderGeometry(params.diameter / 2, params.diameter / 2, height, 32)\n geo.applyMatrix4(ROT_Y_TO_Z)\n return geo\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: THREE.Vector3,\n direction: THREE.Vector3,\n bbox: THREE.Box3,\n): { height: number; center: THREE.Vector3 } {\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: THREE.Vector3,\n direction: THREE.Vector3,\n depth: number,\n): THREE.Vector3 {\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: THREE.BufferGeometry,\n direction: THREE.Vector3,\n center: THREE.Vector3,\n): THREE.BufferGeometry {\n const result = geo.clone()\n // Rotate Z axis to direction\n const quat = new THREE.Quaternion().setFromUnitVectors(\n new THREE.Vector3(0, 0, 1),\n direction.clone().normalize(),\n )\n result.applyQuaternion(quat)\n // Translate to center\n result.translate(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: THREE.Vector3,\n): THREE.Vector3 {\n if (direction === 'normal') {\n return faceNormal.clone().negate().normalize()\n }\n\n // Axis-aligned direction\n const axisDir = new THREE.Vector3(\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 THREE.Mesh in world space, returning the resulting\n * geometry in the mesh's local space.\n *\n * @param targetMesh - the mesh to drill into.\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 targetMesh: THREE.Mesh,\n params: DrillHoleParams,\n position: THREE.Vector3,\n faceNormal: THREE.Vector3,\n): Promise<THREE.BufferGeometry> {\n targetMesh.updateMatrixWorld()\n return executeDrillHoleOnGeometry(\n targetMesh.geometry,\n targetMesh.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 BufferGeometry 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: THREE.BufferGeometry,\n worldMatrix: THREE.Matrix4,\n params: DrillHoleParams,\n position: THREE.Vector3,\n faceNormal: THREE.Vector3,\n): Promise<THREE.BufferGeometry> {\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 sourceGeometry.computeBoundingBox()\n const bbox = sourceGeometry.boundingBox!.clone()\n bbox.applyMatrix4(worldMatrix)\n const bboxSize = bbox.getSize(new THREE.Vector3())\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: THREE.Vector3\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. Clone source geometry and transform to world space\n const targetGeo = sourceGeometry.clone()\n targetGeo.applyMatrix4(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 BufferGeometry\n const resultGeo = manifoldMeshToGeo(result)\n\n // 11. Transform back to mesh local space\n const invMatrix = new THREE.Matrix4().copy(worldMatrix).invert()\n resultGeo.applyMatrix4(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(resultGeo)\n resultGeo.dispose()\n\n // 12. Cleanup\n holeGeo.dispose()\n holeGeoWorld.dispose()\n targetGeo.dispose()\n\n return finalGeo\n}\n"]}
|
|
@@ -1,34 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drill-types.d.ts","sourceRoot":"","sources":["../../../src/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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drill-types.js","sourceRoot":"","sources":["../../../src/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"]}
|
package/dist/mesh/fai_drill.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
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 './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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fai_drill.d.ts","sourceRoot":"","sources":["../../src/mesh/fai_drill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAEjD;;;;;;;GAOG;AACH,wBAAsB,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CA+E7E"}
|
package/dist/mesh/fai_drill.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
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 * as THREE from 'three';
|
|
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 THREE.Vector3(...params.position);
|
|
25
|
-
const faceNormal = new THREE.Vector3(...params.faceNormal);
|
|
26
|
-
// 1. 计算钻孔方向:direction 是 Vec3,确保朝向材料内部
|
|
27
|
-
const direction = new THREE.Vector3(...params.direction).normalize();
|
|
28
|
-
if (direction.dot(faceNormal) > 0) {
|
|
29
|
-
direction.negate();
|
|
30
|
-
}
|
|
31
|
-
// 2. 从输入几何计算 bbox(世界空间)
|
|
32
|
-
const bbox = new THREE.Box3();
|
|
33
|
-
const posVec = new THREE.Vector3();
|
|
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 THREE.Vector3());
|
|
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
|
-
// 9. 清理
|
|
88
|
-
holeGeo.dispose();
|
|
89
|
-
holeGeoWorld.dispose();
|
|
90
|
-
return result;
|
|
91
|
-
}
|
|
92
|
-
//# sourceMappingURL=fai_drill.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fai_drill.js","sourceRoot":"","sources":["../../src/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 * as THREE from 'three'\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 './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 THREE.Vector3(...params.position)\n const faceNormal = new THREE.Vector3(...params.faceNormal)\n\n // 1. 计算钻孔方向:direction 是 Vec3,确保朝向材料内部\n const direction = new THREE.Vector3(...params.direction).normalize()\n if (direction.dot(faceNormal) > 0) {\n direction.negate()\n }\n\n // 2. 从输入几何计算 bbox(世界空间)\n const bbox = new THREE.Box3()\n const posVec = new THREE.Vector3()\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 THREE.Vector3())\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: THREE.Vector3\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 // 9. 清理\n holeGeo.dispose()\n holeGeoWorld.dispose()\n\n return result\n}\n"]}
|
|
@@ -1,24 +0,0 @@
|
|
|
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 './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, originOffset, 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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fai_extrude.d.ts","sourceRoot":"","sources":["../../src/mesh/fai_extrude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAEnD;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CA2BjF"}
|
package/dist/mesh/fai_extrude.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
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 { computeBoolean } from '../boolean/csg-backend.js';
|
|
14
|
-
import { buildExtrudeParts } from '../boolean/extrude-helpers.js';
|
|
15
|
-
/**
|
|
16
|
-
* Execute a face extrude: cut the model at the cutting plane and extrude the
|
|
17
|
-
* middle section by `length` along the plane normal, then union the three
|
|
18
|
-
* segments back into a single solid.
|
|
19
|
-
*
|
|
20
|
-
* @param shape - the world-space shape to extrude.
|
|
21
|
-
* @param params - extrude parameters (normal, originOffset, length, mode).
|
|
22
|
-
* @returns the extruded shape in world space.
|
|
23
|
-
*/
|
|
24
|
-
export async function extrude(shape, params) {
|
|
25
|
-
const mode = params.mode ?? 'centered';
|
|
26
|
-
const { front, back, extruded } = await buildExtrudeParts(shape, params.normal, params.originOffset, params.length, mode);
|
|
27
|
-
// Union 三段为单体
|
|
28
|
-
const meshesToUnion = [];
|
|
29
|
-
for (const part of [front, extruded, back]) {
|
|
30
|
-
if (!part || part.indices.length === 0)
|
|
31
|
-
continue;
|
|
32
|
-
meshesToUnion.push(part);
|
|
33
|
-
}
|
|
34
|
-
if (meshesToUnion.length === 0) {
|
|
35
|
-
throw new Error('No valid geometry to extrude');
|
|
36
|
-
}
|
|
37
|
-
if (meshesToUnion.length === 1) {
|
|
38
|
-
return meshesToUnion[0];
|
|
39
|
-
}
|
|
40
|
-
return computeBoolean(meshesToUnion, 'union');
|
|
41
|
-
}
|
|
42
|
-
//# sourceMappingURL=fai_extrude.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fai_extrude.js","sourceRoot":"","sources":["../../src/mesh/fai_extrude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAI9D;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAAY,EAAE,MAAqB;IAC/D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,UAAU,CAAA;IAEtC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,iBAAiB,CACvD,KAAyB,EACzB,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,YAAY,EACnB,MAAM,CAAC,MAAM,EACb,IAAI,CACL,CAAA;IAED,cAAc;IACd,MAAM,aAAa,GAAuB,EAAE,CAAA;IAC5C,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QAChD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC1B,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACjD,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,aAAa,CAAC,CAAC,CAAC,CAAA;IACzB,CAAC;IAED,OAAO,cAAc,CAAC,aAAa,EAAE,OAAO,CAAC,CAAA;AAC/C,CAAC","sourcesContent":["/**\n * mesh 拉伸 API\n *\n * 提取来源:engine/boolean/extrude-helpers.ts (buildExtrudeParts)\n * 已是纯数据函数(ManifoldMeshData 输入输出),直接包装。\n *\n * 拉伸语义(三段模型):\n * - back(下半):沿法线 N 平移 offsetBack\n * - middle(中段):平面处的截面沿 N 挤出 L\n * - front(上半):沿法线 N 平移 offsetFront\n * 其中 offsetFront - offsetBack === length 恒成立。\n */\n\nimport { computeBoolean } from '../boolean/csg-backend'\nimport { buildExtrudeParts } from '../boolean/extrude-helpers'\nimport type { ManifoldMeshData } from '../boolean/csg-backend'\nimport type { Shape, ExtrudeParams } from './types'\n\n/**\n * Execute a face extrude: cut the model at the cutting plane and extrude the\n * middle section by `length` along the plane normal, then union the three\n * segments back into a single solid.\n *\n * @param shape - the world-space shape to extrude.\n * @param params - extrude parameters (normal, originOffset, length, mode).\n * @returns the extruded shape in world space.\n */\nexport async function extrude(shape: Shape, params: ExtrudeParams): Promise<Shape> {\n const mode = params.mode ?? 'centered'\n\n const { front, back, extruded } = await buildExtrudeParts(\n shape as ManifoldMeshData,\n params.normal,\n params.originOffset,\n params.length,\n mode,\n )\n\n // Union 三段为单体\n const meshesToUnion: ManifoldMeshData[] = []\n for (const part of [front, extruded, back]) {\n if (!part || part.indices.length === 0) continue\n meshesToUnion.push(part)\n }\n\n if (meshesToUnion.length === 0) {\n throw new Error('No valid geometry to extrude')\n }\n\n if (meshesToUnion.length === 1) {\n return meshesToUnion[0]\n }\n\n return computeBoolean(meshesToUnion, 'union')\n}\n"]}
|