@faicad/faijs 0.18.3 → 0.22.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.map +1 -1
- package/dist/api/api-namespace.js +4 -1
- package/dist/api/api-namespace.js.map +1 -1
- package/dist/api/brep-mirror/joinery-brep.d.ts +1 -1
- package/dist/api/brep-mirror/joinery-brep.d.ts.map +1 -1
- package/dist/api/brep-mirror/joinery-brep.js +22 -20
- package/dist/api/brep-mirror/joinery-brep.js.map +1 -1
- package/dist/api/generated/script-face-manifest.d.ts +4 -0
- package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
- package/dist/api/generated/script-face-manifest.js.map +1 -1
- package/dist/api/index.d.ts +4 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +3 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/knurl.d.ts.map +1 -1
- package/dist/api/knurl.js +1 -0
- package/dist/api/knurl.js.map +1 -1
- package/dist/api/primitives.d.ts +4 -3
- package/dist/api/primitives.d.ts.map +1 -1
- package/dist/api/primitives.js +9 -3
- package/dist/api/primitives.js.map +1 -1
- package/dist/api/profile.d.ts +34 -5
- package/dist/api/profile.d.ts.map +1 -1
- package/dist/api/profile.js +168 -186
- package/dist/api/profile.js.map +1 -1
- package/dist/api/punch-hole.d.ts +77 -0
- package/dist/api/punch-hole.d.ts.map +1 -0
- package/dist/api/punch-hole.js +207 -0
- package/dist/api/punch-hole.js.map +1 -0
- package/dist/api/sketch-on-face.d.ts +85 -0
- package/dist/api/sketch-on-face.d.ts.map +1 -0
- package/dist/api/sketch-on-face.js +136 -0
- package/dist/api/sketch-on-face.js.map +1 -0
- package/dist/api/sketch-on-plane.d.ts +87 -0
- package/dist/api/sketch-on-plane.d.ts.map +1 -0
- package/dist/api/sketch-on-plane.js +106 -0
- package/dist/api/sketch-on-plane.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.map +1 -1
- package/dist/api/transform.d.ts +5 -5
- package/dist/api/transform.d.ts.map +1 -1
- package/dist/api/transform.js +12 -10
- package/dist/api/transform.js.map +1 -1
- package/dist/api/xml-dom.d.ts +27 -0
- package/dist/api/xml-dom.d.ts.map +1 -0
- package/dist/api/xml-dom.js +45 -0
- package/dist/api/xml-dom.js.map +1 -0
- package/dist/boolean/csg-backend.d.ts +6 -6
- package/dist/boolean/csg-backend.d.ts.map +1 -1
- package/dist/boolean/csg-backend.js +9 -9
- package/dist/boolean/csg-backend.js.map +1 -1
- package/dist/boolean/csg-core.d.ts +10 -10
- package/dist/boolean/csg-core.d.ts.map +1 -1
- package/dist/boolean/csg-core.js +24 -24
- package/dist/boolean/csg-core.js.map +1 -1
- package/dist/boolean/extrude-helpers.d.ts +8 -8
- package/dist/boolean/extrude-helpers.d.ts.map +1 -1
- package/dist/boolean/extrude-helpers.js +13 -13
- package/dist/boolean/extrude-helpers.js.map +1 -1
- package/dist/brep/brep-ops.d.ts +24 -10
- package/dist/brep/brep-ops.d.ts.map +1 -1
- package/dist/brep/brep-ops.js +46 -18
- package/dist/brep/brep-ops.js.map +1 -1
- package/dist/brep/brep-topology.d.ts.map +1 -1
- package/dist/brep/brep-topology.js +3 -1
- package/dist/brep/brep-topology.js.map +1 -1
- package/dist/brep/export/export-model.d.ts +79 -0
- package/dist/brep/export/export-model.d.ts.map +1 -0
- package/dist/brep/export/export-model.js +335 -0
- package/dist/brep/export/export-model.js.map +1 -0
- package/dist/brep/primitives-brep.d.ts.map +1 -1
- package/dist/brep/primitives-brep.js +3 -1
- package/dist/brep/primitives-brep.js.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.js +4 -2
- package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
- package/dist/browser-host/csg-worker-protocol.d.ts +3 -3
- package/dist/browser-host/csg-worker-protocol.d.ts.map +1 -1
- package/dist/browser-host/csg-worker-protocol.js.map +1 -1
- package/dist/browser-host/csg-worker.js +3 -3
- package/dist/browser-host/csg-worker.js.map +1 -1
- package/dist/browser-host/inline-csg-backend.d.ts +3 -3
- package/dist/browser-host/inline-csg-backend.d.ts.map +1 -1
- package/dist/browser-host/inline-csg-backend.js +3 -3
- package/dist/browser-host/inline-csg-backend.js.map +1 -1
- package/dist/browser-host/worker-csg-backend.d.ts +3 -3
- package/dist/browser-host/worker-csg-backend.d.ts.map +1 -1
- package/dist/browser-host/worker-csg-backend.js.map +1 -1
- package/dist/cad-runtime/direct-executor.d.ts +4 -0
- package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
- package/dist/cad-runtime/direct-executor.js +17 -1
- package/dist/cad-runtime/direct-executor.js.map +1 -1
- package/dist/cad-runtime/ports.d.ts +3 -3
- 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 +24 -1
- package/dist/cad-runtime/runtime.d.ts.map +1 -1
- package/dist/cad-runtime/runtime.js +53 -3
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/define-op.d.ts +22 -0
- package/dist/define-op.d.ts.map +1 -1
- package/dist/define-op.js +15 -0
- package/dist/define-op.js.map +1 -1
- package/dist/env-agnostic.d.ts +7 -7
- package/dist/env-agnostic.d.ts.map +1 -1
- package/dist/env-agnostic.js +3 -3
- package/dist/env-agnostic.js.map +1 -1
- package/dist/geometry2d/adapt.d.ts +46 -0
- package/dist/geometry2d/adapt.d.ts.map +1 -0
- package/dist/geometry2d/adapt.js +41 -0
- package/dist/geometry2d/adapt.js.map +1 -0
- package/dist/geometry2d/bbox2d.d.ts +82 -0
- package/dist/geometry2d/bbox2d.d.ts.map +1 -0
- package/dist/geometry2d/bbox2d.js +123 -0
- package/dist/geometry2d/bbox2d.js.map +1 -0
- package/dist/geometry2d/blueprint-sketcher.d.ts +27 -0
- package/dist/geometry2d/blueprint-sketcher.d.ts.map +1 -0
- package/dist/geometry2d/blueprint-sketcher.js +29 -0
- package/dist/geometry2d/blueprint-sketcher.js.map +1 -0
- package/dist/geometry2d/blueprint.d.ts +102 -0
- package/dist/geometry2d/blueprint.d.ts.map +1 -0
- package/dist/geometry2d/blueprint.js +225 -0
- package/dist/geometry2d/blueprint.js.map +1 -0
- package/dist/geometry2d/blueprints.d.ts +58 -0
- package/dist/geometry2d/blueprints.d.ts.map +1 -0
- package/dist/geometry2d/blueprints.js +72 -0
- package/dist/geometry2d/blueprints.js.map +1 -0
- package/dist/geometry2d/bridge/lift-on-plane.d.ts +50 -0
- package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -0
- package/dist/geometry2d/bridge/lift-on-plane.js +78 -0
- package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -0
- package/dist/geometry2d/bridge/on-surface.d.ts +98 -0
- package/dist/geometry2d/bridge/on-surface.d.ts.map +1 -0
- package/dist/geometry2d/bridge/on-surface.js +94 -0
- package/dist/geometry2d/bridge/on-surface.js.map +1 -0
- package/dist/geometry2d/bridge/plane.d.ts +69 -0
- package/dist/geometry2d/bridge/plane.d.ts.map +1 -0
- package/dist/geometry2d/bridge/plane.js +96 -0
- package/dist/geometry2d/bridge/plane.js.map +1 -0
- package/dist/geometry2d/canned-blueprints.d.ts +44 -0
- package/dist/geometry2d/canned-blueprints.d.ts.map +1 -0
- package/dist/geometry2d/canned-blueprints.js +94 -0
- package/dist/geometry2d/canned-blueprints.js.map +1 -0
- package/dist/geometry2d/compound-blueprint.d.ts +72 -0
- package/dist/geometry2d/compound-blueprint.d.ts.map +1 -0
- package/dist/geometry2d/compound-blueprint.js +95 -0
- package/dist/geometry2d/compound-blueprint.js.map +1 -0
- package/dist/geometry2d/curve2d.d.ts +298 -0
- package/dist/geometry2d/curve2d.d.ts.map +1 -0
- package/dist/geometry2d/curve2d.js +1110 -0
- package/dist/geometry2d/curve2d.js.map +1 -0
- package/dist/geometry2d/index.d.ts +22 -0
- package/dist/geometry2d/index.d.ts.map +1 -0
- package/dist/geometry2d/index.js +21 -0
- package/dist/geometry2d/index.js.map +1 -0
- package/dist/geometry2d/organise.d.ts +28 -0
- package/dist/geometry2d/organise.d.ts.map +1 -0
- package/dist/geometry2d/organise.js +108 -0
- package/dist/geometry2d/organise.js.map +1 -0
- package/dist/geometry2d/pen-sketcher.d.ts +365 -0
- package/dist/geometry2d/pen-sketcher.d.ts.map +1 -0
- package/dist/geometry2d/pen-sketcher.js +520 -0
- package/dist/geometry2d/pen-sketcher.js.map +1 -0
- package/dist/geometry2d/point.d.ts +44 -0
- package/dist/geometry2d/point.d.ts.map +1 -0
- package/dist/geometry2d/point.js +57 -0
- package/dist/geometry2d/point.js.map +1 -0
- package/dist/geometry2d/svg-ellipse.d.ts +74 -0
- package/dist/geometry2d/svg-ellipse.d.ts.map +1 -0
- package/dist/geometry2d/svg-ellipse.js +163 -0
- package/dist/geometry2d/svg-ellipse.js.map +1 -0
- package/dist/lang/code-to-args.d.ts +29 -3
- package/dist/lang/code-to-args.d.ts.map +1 -1
- package/dist/lang/code-to-args.js +41 -2
- package/dist/lang/code-to-args.js.map +1 -1
- package/dist/lang/codegen.d.ts +45 -1
- package/dist/lang/codegen.d.ts.map +1 -1
- package/dist/lang/codegen.js +135 -6
- package/dist/lang/codegen.js.map +1 -1
- package/dist/lang/host-arg.d.ts +6 -0
- package/dist/lang/host-arg.d.ts.map +1 -1
- package/dist/lang/host-arg.js.map +1 -1
- package/dist/lang/metadata-extractor.d.ts +25 -0
- package/dist/lang/metadata-extractor.d.ts.map +1 -1
- package/dist/lang/metadata-extractor.js +289 -25
- package/dist/lang/metadata-extractor.js.map +1 -1
- package/dist/lang/parse-error.d.ts +7 -1
- package/dist/lang/parse-error.d.ts.map +1 -1
- package/dist/lang/parse-error.js.map +1 -1
- package/dist/lang/security-scanner.d.ts +9 -1
- package/dist/lang/security-scanner.d.ts.map +1 -1
- package/dist/lang/security-scanner.js +38 -1
- package/dist/lang/security-scanner.js.map +1 -1
- package/dist/lang/symbol-table.generated.d.ts +3 -0
- package/dist/lang/symbol-table.generated.d.ts.map +1 -1
- package/dist/lang/symbol-table.generated.js +3 -0
- package/dist/lang/symbol-table.generated.js.map +1 -1
- package/dist/mesh/io.d.ts +62 -9
- package/dist/mesh/io.d.ts.map +1 -1
- package/dist/mesh/io.js +124 -17
- package/dist/mesh/io.js.map +1 -1
- package/dist/mesh/threemf-loader.d.ts +15 -0
- package/dist/mesh/threemf-loader.d.ts.map +1 -0
- package/dist/mesh/threemf-loader.js +163 -0
- package/dist/mesh/threemf-loader.js.map +1 -0
- package/dist/mesh/transform.d.ts +2 -2
- package/dist/mesh/transform.d.ts.map +1 -1
- package/dist/mesh/transform.js +3 -3
- package/dist/mesh/transform.js.map +1 -1
- package/dist/mesh/types.d.ts +2 -2
- package/dist/mesh/types.d.ts.map +1 -1
- package/dist/mesh/types.js.map +1 -1
- package/dist/node-host/cli.d.ts.map +1 -1
- package/dist/node-host/cli.js +53 -26
- package/dist/node-host/cli.js.map +1 -1
- package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
- package/dist/occt-kernel/occtKernel.js +4 -2
- package/dist/occt-kernel/occtKernel.js.map +1 -1
- package/dist/occt-kernel/topologyExt.d.ts.map +1 -1
- package/dist/occt-kernel/topologyExt.js +4 -1
- package/dist/occt-kernel/topologyExt.js.map +1 -1
- package/dist/runtime-state.d.ts +18 -0
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +23 -0
- package/dist/runtime-state.js.map +1 -1
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +1 -1
- package/dist/sdk.js.map +1 -1
- package/dist/tolerance.d.ts +38 -0
- package/dist/tolerance.d.ts.map +1 -0
- package/dist/tolerance.js +40 -0
- package/dist/tolerance.js.map +1 -0
- package/dist/topology/naming/score.js +3 -3
- package/dist/topology/naming/score.js.map +1 -1
- package/dist/units.d.ts +248 -0
- package/dist/units.d.ts.map +1 -0
- package/dist/units.js +397 -0
- package/dist/units.js.map +1 -0
- package/package.json +19 -2
package/dist/mesh/io.js
CHANGED
|
@@ -1,31 +1,138 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* mesh IO API — headless 文件加载
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* STL 由 core 自持的 `mesh/stl-loader.ts` 解析(零 three addons);3MF 由
|
|
5
|
+
* `mesh/threemf-loader.ts` 解析(ZIP 解压 + XML,单位换算到 mm 基准)。
|
|
6
|
+
* 坐标永远以 faijs 基准长度单位(mm)存储 — Shape 不贴 unit 标签(D3)。
|
|
7
|
+
*
|
|
8
|
+
* 单位换算边界(unit-system §5.2):
|
|
9
|
+
* - STL 无单位元数据 → 由 `opts.unit` 显式声明,缺省 mm,不做启发式猜测。
|
|
10
|
+
* - 3MF `<model unit>` 由解析器读取并换算(micron/mm/cm/inch/foot/meter)。
|
|
11
|
+
*
|
|
12
|
+
* 返回契约(unit-system §10.6):`importFile` 返回 `{ shape, unit }` — `unit`
|
|
13
|
+
* 是文件**自己声明的单位**(3MF `<model unit>`、STEP 单位实体),无声明格式
|
|
14
|
+
* (STL)为 null(此时 `opts.unit` 决定刻度)。坐标恒为基准值 — `unit` 只作
|
|
15
|
+
* 元数据(sourceUnit 记录、导出目标判定),绝不参与几何缩放(读入折算已由
|
|
16
|
+
* 内核/解析器完成,二次缩放 = 双重换算)。
|
|
7
17
|
*/
|
|
8
18
|
import { geoToManifoldMesh } from '../boolean/geo-convert.js';
|
|
9
19
|
import { parseStl } from './stl-loader.js';
|
|
20
|
+
import { parseThreemf } from './threemf-loader.js';
|
|
21
|
+
import { mm } from '../units.js';
|
|
22
|
+
/** SI prefixes that may precede .METRE. in a STEP SI_UNIT, → faijs UnitName. */
|
|
23
|
+
const SI_PREFIX_TO_UNIT = {
|
|
24
|
+
'.MILLI.': 'mm',
|
|
25
|
+
'.CENTI.': 'cm',
|
|
26
|
+
'$': 'm',
|
|
27
|
+
};
|
|
28
|
+
/** CONVERSION_BASED_UNIT names (uppercased) found in real-world STEP files. */
|
|
29
|
+
const CONVERSION_NAME_TO_UNIT = {
|
|
30
|
+
'METRE': 'm',
|
|
31
|
+
'METER': 'm',
|
|
32
|
+
'MILLIMETRE': 'mm',
|
|
33
|
+
'MILLIMETER': 'mm',
|
|
34
|
+
'CENTIMETRE': 'cm',
|
|
35
|
+
'CENTIMETER': 'cm',
|
|
36
|
+
'MICROMETRE': 'micron',
|
|
37
|
+
'MICROMETER': 'micron',
|
|
38
|
+
'INCH': 'inch',
|
|
39
|
+
'FOOT': 'foot',
|
|
40
|
+
};
|
|
10
41
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
42
|
+
* Bounded scan window for `detectStepUnit`. Unit entities sit at the front of
|
|
43
|
+
* the DATA section (right after the product/context blocks); 256 KiB covers
|
|
44
|
+
* every real-world header+context preamble observed so far. Recomputable
|
|
45
|
+
* constant — raise if a fixture ever misses.
|
|
46
|
+
*/
|
|
47
|
+
export const STEP_UNIT_SCAN_PREFIX = 256 * 1024;
|
|
48
|
+
/**
|
|
49
|
+
* Parse the declared length unit from STEP text (unit-system §10.4).
|
|
50
|
+
*
|
|
51
|
+
* Unit entities live in the DATA section (not HEADER — ISO 10303-21 reserves
|
|
52
|
+
* HEADER for FILE_DESCRIPTION/FILE_NAME/FILE_SCHEMA), near its start. We scan
|
|
53
|
+
* a bounded prefix; the justification is "unit entities sit at the front of
|
|
54
|
+
* the DATA section", not "top of file".
|
|
13
55
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
56
|
+
* Recognized forms, both attached to a LENGTH_UNIT():
|
|
57
|
+
* - `SI_UNIT(<prefix>, .METRE.)` — prefix `.MILLI.`/`.CENTI.`/`.MICRO.` or `$`.
|
|
58
|
+
* - `CONVERSION_BASED_UNIT('<NAME>', #n)` — inch/foot/etc.
|
|
59
|
+
*
|
|
60
|
+
* Metadata only — NEVER used to scale geometry (OCCT already normalizes on
|
|
61
|
+
* read; re-scaling = double conversion).
|
|
62
|
+
*
|
|
63
|
+
* @param stepText - the full STEP file text to scan (only a bounded prefix is read).
|
|
64
|
+
* @returns the faijs UnitName, or null when no length-unit declaration is found
|
|
65
|
+
* (STEP permits omitting it; caller falls back to the base unit).
|
|
17
66
|
*/
|
|
18
|
-
export
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
67
|
+
export function detectStepUnit(stepText) {
|
|
68
|
+
const head = stepText.slice(0, STEP_UNIT_SCAN_PREFIX);
|
|
69
|
+
// 1) CONVERSION_BASED_UNIT('<NAME>', #n) — non-SI units (inch/foot/…).
|
|
70
|
+
const conv = head.match(/CONVERSION_BASED_UNIT\s*\(\s*'([^']+)'/i);
|
|
71
|
+
if (conv) {
|
|
72
|
+
const mapped = CONVERSION_NAME_TO_UNIT[conv[1].toUpperCase()];
|
|
73
|
+
if (mapped)
|
|
74
|
+
return mapped;
|
|
22
75
|
}
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
76
|
+
// 2) SI_UNIT(<prefix>, .METRE.) — the .METRE. guard excludes angle entities
|
|
77
|
+
// (they carry .RADIAN./.STERADIAN., never .METRE.).
|
|
78
|
+
const si = head.match(/SI_UNIT\s*\(\s*([^)]*?)\s*,\s*\.METRE\.\s*\)/i);
|
|
79
|
+
if (si) {
|
|
80
|
+
const prefix = si[1].trim().toUpperCase();
|
|
81
|
+
if (prefix === '.MICRO.')
|
|
82
|
+
return 'micron';
|
|
83
|
+
const mapped = SI_PREFIX_TO_UNIT[prefix];
|
|
84
|
+
if (mapped)
|
|
85
|
+
return mapped;
|
|
26
86
|
}
|
|
27
|
-
|
|
28
|
-
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/** Map a raw 3MF `<model unit>` attribute to a faijs UnitName (null when absent/unknown). */
|
|
90
|
+
function threemfRawUnitToFaijs(raw) {
|
|
91
|
+
switch (raw) {
|
|
92
|
+
case 'micron': return 'micron';
|
|
93
|
+
case 'millimeter': return 'mm';
|
|
94
|
+
case 'centimeter': return 'cm';
|
|
95
|
+
case 'inch': return 'inch';
|
|
96
|
+
case 'foot': return 'foot';
|
|
97
|
+
case 'meter': return 'm';
|
|
98
|
+
default: return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Load geometry from raw file bytes (headless variant).
|
|
103
|
+
*
|
|
104
|
+
* @param buffer - the raw file bytes to parse (already decompressed; stpz
|
|
105
|
+
* unzipping is the caller's job — faijs never unzips implicitly).
|
|
106
|
+
* @param format - format identifier such as 'stl', '3mf'/'threemf' or 'step'
|
|
107
|
+
* (defaults to 'stl').
|
|
108
|
+
* @param opts - optional settings; `unit` declares the source unit for
|
|
109
|
+
* formats without unit metadata (e.g. STL). Defaults to mm.
|
|
110
|
+
* @returns the shape with base-unit coordinates plus the file's own declared
|
|
111
|
+
* unit (`unit`, metadata only; null when the format has no declaration).
|
|
112
|
+
*/
|
|
113
|
+
export async function importFile(buffer, format, opts) {
|
|
114
|
+
const fmt = (format ?? 'stl').toLowerCase();
|
|
115
|
+
if (fmt === '3mf' || fmt === 'threemf') {
|
|
116
|
+
const mesh = await parseThreemf(buffer);
|
|
117
|
+
const shape = { positions: mesh.positions, indices: mesh.indices };
|
|
118
|
+
// parseThreemf already folded the declared unit into coordinates; surface
|
|
119
|
+
// the raw declaration mapped to a faijs UnitName for metadata.
|
|
120
|
+
return { shape, unit: threemfRawUnitToFaijs(mesh.sourceUnit) };
|
|
121
|
+
}
|
|
122
|
+
if (fmt === 'stl') {
|
|
123
|
+
const scale = (opts?.unit ?? mm).as(mm);
|
|
124
|
+
const geo = parseStl(buffer);
|
|
125
|
+
if (scale !== 1) {
|
|
126
|
+
const attr = geo.getAttribute('position');
|
|
127
|
+
const arr = attr.array;
|
|
128
|
+
for (let i = 0; i < arr.length; i++)
|
|
129
|
+
arr[i] *= scale;
|
|
130
|
+
}
|
|
131
|
+
return { shape: geoToManifoldMesh(geo), unit: null };
|
|
29
132
|
}
|
|
133
|
+
// STEP goes through the BREP chain (loadBrep → OCCT, which normalizes to the
|
|
134
|
+
// base unit on read). The mesh io path has no kernel-independent STEP parser
|
|
135
|
+
// and must not fake one — a missing path is an error, not a fallback.
|
|
136
|
+
throw new Error(`[mesh/io] unsupported format: ${fmt}`);
|
|
30
137
|
}
|
|
31
138
|
//# sourceMappingURL=io.js.map
|
package/dist/mesh/io.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"io.js","sourceRoot":"","sources":["../../src/mesh/io.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"io.js","sourceRoot":"","sources":["../../src/mesh/io.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mesh IO API — headless 文件加载\n *\n * STL 由 core 自持的 `mesh/stl-loader.ts` 解析(零 three addons);3MF 由\n * `mesh/threemf-loader.ts` 解析(ZIP 解压 + XML,单位换算到 mm 基准)。\n * 坐标永远以 faijs 基准长度单位(mm)存储 — Shape 不贴 unit 标签(D3)。\n *\n * 单位换算边界(unit-system §5.2):\n * - STL 无单位元数据 → 由 `opts.unit` 显式声明,缺省 mm,不做启发式猜测。\n * - 3MF `<model unit>` 由解析器读取并换算(micron/mm/cm/inch/foot/meter)。\n *\n * 返回契约(unit-system §10.6):`importFile` 返回 `{ shape, unit }` — `unit`\n * 是文件**自己声明的单位**(3MF `<model unit>`、STEP 单位实体),无声明格式\n * (STL)为 null(此时 `opts.unit` 决定刻度)。坐标恒为基准值 — `unit` 只作\n * 元数据(sourceUnit 记录、导出目标判定),绝不参与几何缩放(读入折算已由\n * 内核/解析器完成,二次缩放 = 双重换算)。\n */\n\nimport * as THREE from 'three'\nimport { geoToManifoldMesh } from '../boolean/geo-convert'\nimport { parseStl } from './stl-loader'\nimport { parseThreemf } from './threemf-loader'\nimport { mm, type UnitName, type ValueWithUnits } from '../units'\nimport type { Shape } from './types'\n\n/** Result of a unit-aware file import. */\nexport interface ImportFileResult {\n shape: Shape\n /**\n * The unit the file itself declares (3MF `<model unit>`, STEP unit entities).\n * null for declaration-less formats (STL) — the caller's opts.unit decided.\n */\n unit: UnitName | null\n}\n\n/** SI prefixes that may precede .METRE. in a STEP SI_UNIT, → faijs UnitName. */\nconst SI_PREFIX_TO_UNIT: Record<string, UnitName> = {\n '.MILLI.': 'mm',\n '.CENTI.': 'cm',\n '$': 'm',\n}\n\n/** CONVERSION_BASED_UNIT names (uppercased) found in real-world STEP files. */\nconst CONVERSION_NAME_TO_UNIT: Record<string, UnitName> = {\n 'METRE': 'm',\n 'METER': 'm',\n 'MILLIMETRE': 'mm',\n 'MILLIMETER': 'mm',\n 'CENTIMETRE': 'cm',\n 'CENTIMETER': 'cm',\n 'MICROMETRE': 'micron',\n 'MICROMETER': 'micron',\n 'INCH': 'inch',\n 'FOOT': 'foot',\n}\n\n/**\n * Bounded scan window for `detectStepUnit`. Unit entities sit at the front of\n * the DATA section (right after the product/context blocks); 256 KiB covers\n * every real-world header+context preamble observed so far. Recomputable\n * constant — raise if a fixture ever misses.\n */\nexport const STEP_UNIT_SCAN_PREFIX = 256 * 1024\n\n/**\n * Parse the declared length unit from STEP text (unit-system §10.4).\n *\n * Unit entities live in the DATA section (not HEADER — ISO 10303-21 reserves\n * HEADER for FILE_DESCRIPTION/FILE_NAME/FILE_SCHEMA), near its start. We scan\n * a bounded prefix; the justification is \"unit entities sit at the front of\n * the DATA section\", not \"top of file\".\n *\n * Recognized forms, both attached to a LENGTH_UNIT():\n * - `SI_UNIT(<prefix>, .METRE.)` — prefix `.MILLI.`/`.CENTI.`/`.MICRO.` or `$`.\n * - `CONVERSION_BASED_UNIT('<NAME>', #n)` — inch/foot/etc.\n *\n * Metadata only — NEVER used to scale geometry (OCCT already normalizes on\n * read; re-scaling = double conversion).\n *\n * @param stepText - the full STEP file text to scan (only a bounded prefix is read).\n * @returns the faijs UnitName, or null when no length-unit declaration is found\n * (STEP permits omitting it; caller falls back to the base unit).\n */\nexport function detectStepUnit(stepText: string): UnitName | null {\n const head = stepText.slice(0, STEP_UNIT_SCAN_PREFIX)\n\n // 1) CONVERSION_BASED_UNIT('<NAME>', #n) — non-SI units (inch/foot/…).\n const conv = head.match(/CONVERSION_BASED_UNIT\\s*\\(\\s*'([^']+)'/i)\n if (conv) {\n const mapped = CONVERSION_NAME_TO_UNIT[conv[1].toUpperCase()]\n if (mapped) return mapped\n }\n\n // 2) SI_UNIT(<prefix>, .METRE.) — the .METRE. guard excludes angle entities\n // (they carry .RADIAN./.STERADIAN., never .METRE.).\n const si = head.match(/SI_UNIT\\s*\\(\\s*([^)]*?)\\s*,\\s*\\.METRE\\.\\s*\\)/i)\n if (si) {\n const prefix = si[1].trim().toUpperCase()\n if (prefix === '.MICRO.') return 'micron'\n const mapped = SI_PREFIX_TO_UNIT[prefix]\n if (mapped) return mapped\n }\n\n return null\n}\n\n/** Map a raw 3MF `<model unit>` attribute to a faijs UnitName (null when absent/unknown). */\nfunction threemfRawUnitToFaijs(raw: string): UnitName | null {\n switch (raw) {\n case 'micron': return 'micron'\n case 'millimeter': return 'mm'\n case 'centimeter': return 'cm'\n case 'inch': return 'inch'\n case 'foot': return 'foot'\n case 'meter': return 'm'\n default: return null\n }\n}\n\n/**\n * Load geometry from raw file bytes (headless variant).\n *\n * @param buffer - the raw file bytes to parse (already decompressed; stpz\n * unzipping is the caller's job — faijs never unzips implicitly).\n * @param format - format identifier such as 'stl', '3mf'/'threemf' or 'step'\n * (defaults to 'stl').\n * @param opts - optional settings; `unit` declares the source unit for\n * formats without unit metadata (e.g. STL). Defaults to mm.\n * @returns the shape with base-unit coordinates plus the file's own declared\n * unit (`unit`, metadata only; null when the format has no declaration).\n */\nexport async function importFile(\n buffer: ArrayBuffer,\n format?: string,\n opts?: { unit?: ValueWithUnits },\n): Promise<ImportFileResult> {\n const fmt = (format ?? 'stl').toLowerCase()\n\n if (fmt === '3mf' || fmt === 'threemf') {\n const mesh = await parseThreemf(buffer)\n const shape: Shape = { positions: mesh.positions, indices: mesh.indices }\n // parseThreemf already folded the declared unit into coordinates; surface\n // the raw declaration mapped to a faijs UnitName for metadata.\n return { shape, unit: threemfRawUnitToFaijs(mesh.sourceUnit) }\n }\n\n if (fmt === 'stl') {\n const scale = (opts?.unit ?? mm).as(mm)\n const geo = parseStl(buffer)\n if (scale !== 1) {\n const attr = geo.getAttribute('position') as THREE.BufferAttribute\n const arr = attr.array as Float32Array\n for (let i = 0; i < arr.length; i++) arr[i] *= scale\n }\n return { shape: geoToManifoldMesh(geo), unit: null }\n }\n\n // STEP goes through the BREP chain (loadBrep → OCCT, which normalizes to the\n // base unit on read). The mesh io path has no kernel-independent STEP parser\n // and must not fake one — a missing path is an error, not a fallback.\n throw new Error(`[mesh/io] unsupported format: ${fmt}`)\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** A parsed 3MF solid: triangle soup in mm base (already unit-scaled). */
|
|
2
|
+
export interface ThreemfMesh {
|
|
3
|
+
positions: Float32Array;
|
|
4
|
+
indices: Uint32Array;
|
|
5
|
+
/** The declared `<model unit>` (raw, e.g. "millimeter"). */
|
|
6
|
+
sourceUnit: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parse 3MF bytes into a mm-base mesh.
|
|
10
|
+
* @param buffer - the raw .3mf (ZIP) bytes.
|
|
11
|
+
* @returns the parsed mesh plus the declared source unit.
|
|
12
|
+
* @throws when the buffer is not a 3MF/ZIP archive or the unit is invalid.
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseThreemf(buffer: ArrayBuffer): Promise<ThreemfMesh>;
|
|
15
|
+
//# sourceMappingURL=threemf-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threemf-loader.d.ts","sourceRoot":"","sources":["../../src/mesh/threemf-loader.ts"],"names":[],"mappings":"AAuCA,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,YAAY,CAAA;IACvB,OAAO,EAAE,WAAW,CAAA;IACpB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAA;CACnB;AA8GD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAmB5E"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* threemf-loader — headless 3MF (ZIP/OPC) geometry loader.
|
|
3
|
+
*
|
|
4
|
+
* 3MF is a ZIP container whose geometry lives in `3D/3dmodel.model`, an XML
|
|
5
|
+
* document. Design requirement (unit-system §2.4/§5): the unit MUST be read
|
|
6
|
+
* from the real (inflated) XML, NOT from the raw bytes — `3D/3dmodel.model` is
|
|
7
|
+
* deflate-compressed inside the ZIP, so scanning the raw buffer cannot find
|
|
8
|
+
* `<model unit="…">` (the 3d_editor precedent returned 'millimeter' for real
|
|
9
|
+
* files). We unzip the entry first, then parse the XML.
|
|
10
|
+
*
|
|
11
|
+
* Coordinate conversion: every coordinate is multiplied by `UNIT_SCALE[unit]`
|
|
12
|
+
* to land in the faijs base length unit (mm).
|
|
13
|
+
*
|
|
14
|
+
* Per-object transform: `<item transform="a b c d e f g h i p q r">` is an
|
|
15
|
+
* ST_Matrix3D stored **column-major** whose last three tokens are the
|
|
16
|
+
* translation `(p,q,r)`. Applied as:
|
|
17
|
+
* x' = a*x + d*y + g*z + p
|
|
18
|
+
* y' = b*x + e*y + h*z + q
|
|
19
|
+
* z' = c*x + f*y + i*z + r
|
|
20
|
+
* so object-local mesh coords bake into world-space positions (the op contract
|
|
21
|
+
* is world-space; `planeDistance` must line up with baked positions).
|
|
22
|
+
*/
|
|
23
|
+
import { unzipSync, strFromU8 } from 'fflate';
|
|
24
|
+
import { parseXmlDocument } from '../api/xml-dom.js';
|
|
25
|
+
import { UNIT_SCALE } from '../units.js';
|
|
26
|
+
/** Map a 3MF unit string to a faijs length unit name. */
|
|
27
|
+
function threemfUnitToFaijs(unit) {
|
|
28
|
+
switch (unit) {
|
|
29
|
+
case 'micron': return 'micron';
|
|
30
|
+
case 'millimeter': return 'mm';
|
|
31
|
+
case 'centimeter': return 'cm';
|
|
32
|
+
case 'inch': return 'inch';
|
|
33
|
+
case 'foot': return 'foot';
|
|
34
|
+
case 'meter': return 'm';
|
|
35
|
+
default: return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Extract the declared unit from an already-parsed `<model>` document. */
|
|
39
|
+
function modelUnit(doc) {
|
|
40
|
+
const model = doc.documentElement;
|
|
41
|
+
if (model && model.getAttribute('unit')) {
|
|
42
|
+
return model.getAttribute('unit');
|
|
43
|
+
}
|
|
44
|
+
// Default per 3MF spec is millimeter.
|
|
45
|
+
return 'millimeter';
|
|
46
|
+
}
|
|
47
|
+
/** Parse the `3D/3dmodel.model` XML and produce an index+position mesh. */
|
|
48
|
+
async function parseModelXml(xml) {
|
|
49
|
+
const doc = await parseXmlDocument(xml);
|
|
50
|
+
const unit = modelUnit(doc);
|
|
51
|
+
const faijsUnit = threemfUnitToFaijs(unit);
|
|
52
|
+
if (faijsUnit === null) {
|
|
53
|
+
throw new Error(`[mesh/threemf] unsupported <model unit>: ${JSON.stringify(unit)}`);
|
|
54
|
+
}
|
|
55
|
+
const scale = UNIT_SCALE[faijsUnit];
|
|
56
|
+
// resources → object → mesh → vertices / triangles
|
|
57
|
+
const resources = doc.documentElement.getElementsByTagName('resources')[0];
|
|
58
|
+
const objects = resources ? resources.getElementsByTagName('object') : [];
|
|
59
|
+
const byObjectId = new Map();
|
|
60
|
+
for (let i = 0; i < objects.length; i++) {
|
|
61
|
+
const obj = objects[i];
|
|
62
|
+
const id = Number(obj.getAttribute('id'));
|
|
63
|
+
if (!Number.isInteger(id))
|
|
64
|
+
continue;
|
|
65
|
+
const meshEl = obj.getElementsByTagName('mesh')[0];
|
|
66
|
+
if (!meshEl)
|
|
67
|
+
continue;
|
|
68
|
+
const verticesEl = meshEl.getElementsByTagName('vertices')[0];
|
|
69
|
+
const trianglesEl = meshEl.getElementsByTagName('triangles')[0];
|
|
70
|
+
if (!verticesEl || !trianglesEl)
|
|
71
|
+
continue;
|
|
72
|
+
const vertexEls = verticesEl.getElementsByTagName('vertex');
|
|
73
|
+
const pos = new Float32Array(vertexEls.length * 3);
|
|
74
|
+
for (let v = 0; v < vertexEls.length; v++) {
|
|
75
|
+
const el = vertexEls[v];
|
|
76
|
+
pos[v * 3] = Number(el.getAttribute('x')) * scale;
|
|
77
|
+
pos[v * 3 + 1] = Number(el.getAttribute('y')) * scale;
|
|
78
|
+
pos[v * 3 + 2] = Number(el.getAttribute('z')) * scale;
|
|
79
|
+
}
|
|
80
|
+
const triEls = trianglesEl.getElementsByTagName('triangle');
|
|
81
|
+
const idx = new Uint32Array(triEls.length * 3);
|
|
82
|
+
for (let t = 0; t < triEls.length; t++) {
|
|
83
|
+
const el = triEls[t];
|
|
84
|
+
idx[t * 3] = Number(el && el.getAttribute('v1'));
|
|
85
|
+
idx[t * 3 + 1] = Number(el && el.getAttribute('v2'));
|
|
86
|
+
idx[t * 3 + 2] = Number(el && el.getAttribute('v3'));
|
|
87
|
+
}
|
|
88
|
+
byObjectId.set(id, { positions: pos, indices: idx });
|
|
89
|
+
}
|
|
90
|
+
// build → item → per-instance transforms (ST_3D, column-major, translation last 3).
|
|
91
|
+
const build = doc.documentElement.getElementsByTagName('build')[0];
|
|
92
|
+
const itemEls = build ? build.getElementsByTagName('item') : [];
|
|
93
|
+
const allPos = [];
|
|
94
|
+
const allIdx = [];
|
|
95
|
+
for (let i = 0; i < itemEls.length; i++) {
|
|
96
|
+
const item = itemEls[i];
|
|
97
|
+
const objId = Number(item.getAttribute('objectid'));
|
|
98
|
+
const src = byObjectId.get(objId);
|
|
99
|
+
if (!src)
|
|
100
|
+
continue;
|
|
101
|
+
const mat = item.getAttribute('transform');
|
|
102
|
+
const [a, b, c, d, e, f, g, h, iz, p, q, r] = mat
|
|
103
|
+
? mat.trim().split(/\s+/).map(Number)
|
|
104
|
+
: [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0];
|
|
105
|
+
const base = allPos.length / 3;
|
|
106
|
+
for (let v = 0; v < src.positions.length; v += 3) {
|
|
107
|
+
const x = src.positions[v];
|
|
108
|
+
const y = src.positions[v + 1];
|
|
109
|
+
const z = src.positions[v + 2];
|
|
110
|
+
allPos.push(a * x + d * y + g * z + p, b * x + e * y + h * z + q, c * x + f * y + iz * z + r);
|
|
111
|
+
}
|
|
112
|
+
for (let t = 0; t < src.indices.length; t++) {
|
|
113
|
+
allIdx.push(src.indices[t] + base);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Fallback: if the build list is empty (some exporters omit <build>), emit
|
|
117
|
+
// every object's mesh directly.
|
|
118
|
+
if (itemEls.length === 0) {
|
|
119
|
+
for (const [, src] of byObjectId) {
|
|
120
|
+
const base = allPos.length / 3;
|
|
121
|
+
for (let v = 0; v < src.positions.length; v++)
|
|
122
|
+
allPos.push(src.positions[v]);
|
|
123
|
+
for (let t = 0; t < src.indices.length; t++)
|
|
124
|
+
allIdx.push(src.indices[t] + base);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (allPos.length === 0) {
|
|
128
|
+
throw new Error('[mesh/threemf] no buildable geometry found in 3dmodel.model');
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
positions: new Float32Array(allPos),
|
|
132
|
+
indices: new Uint32Array(allIdx),
|
|
133
|
+
unit,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Parse 3MF bytes into a mm-base mesh.
|
|
138
|
+
* @param buffer - the raw .3mf (ZIP) bytes.
|
|
139
|
+
* @returns the parsed mesh plus the declared source unit.
|
|
140
|
+
* @throws when the buffer is not a 3MF/ZIP archive or the unit is invalid.
|
|
141
|
+
*/
|
|
142
|
+
export async function parseThreemf(buffer) {
|
|
143
|
+
let entries;
|
|
144
|
+
try {
|
|
145
|
+
entries = unzipSync(new Uint8Array(buffer));
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
throw new Error('[mesh/threemf] not a valid 3MF ZIP archive');
|
|
149
|
+
}
|
|
150
|
+
const modelKey = Object.keys(entries).find((k) => k.toLowerCase() === '3d/3dmodel.model');
|
|
151
|
+
if (!modelKey) {
|
|
152
|
+
throw new Error('[mesh/threemf] missing 3D/3dmodel.model entry');
|
|
153
|
+
}
|
|
154
|
+
const raw = entries[modelKey];
|
|
155
|
+
const xml = strFromU8(raw);
|
|
156
|
+
const parsed = await parseModelXml(xml);
|
|
157
|
+
return {
|
|
158
|
+
positions: parsed.positions,
|
|
159
|
+
indices: parsed.indices,
|
|
160
|
+
sourceUnit: parsed.unit,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=threemf-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threemf-loader.js","sourceRoot":"","sources":["../../src/mesh/threemf-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAiB,MAAM,UAAU,CAAA;AAEpD,yDAAyD;AACzD,SAAS,kBAAkB,CAAC,IAAY;IACtC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAA;QAC9B,KAAK,YAAY,CAAC,CAAC,OAAO,IAAI,CAAA;QAC9B,KAAK,YAAY,CAAC,CAAC,OAAO,IAAI,CAAA;QAC9B,KAAK,MAAM,CAAC,CAAC,OAAO,MAAM,CAAA;QAC1B,KAAK,MAAM,CAAC,CAAC,OAAO,MAAM,CAAA;QAC1B,KAAK,OAAO,CAAC,CAAC,OAAO,GAAG,CAAA;QACxB,OAAO,CAAC,CAAC,OAAO,IAAI,CAAA;IACtB,CAAC;AACH,CAAC;AAUD,2EAA2E;AAC3E,SAAS,SAAS,CAAC,GAAa;IAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,eAAe,CAAA;IACjC,IAAI,KAAK,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC,YAAY,CAAC,MAAM,CAAE,CAAA;IACpC,CAAC;IACD,sCAAsC;IACtC,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,aAAa,CAAC,GAAW;IACtC,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAA;IACvC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC3B,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAC1C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,4CAA4C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACrF,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,CAAA;IAEnC,mDAAmD;IACnD,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1E,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACzE,MAAM,UAAU,GAAG,IAAI,GAAG,EAA6D,CAAA;IAEvF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;QACtB,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;QACzC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YAAE,SAAQ;QACnC,MAAM,MAAM,GAAG,GAAG,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QAClD,IAAI,CAAC,MAAM;YAAE,SAAQ;QACrB,MAAM,UAAU,GAAG,MAAM,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7D,MAAM,WAAW,GAAG,MAAM,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/D,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW;YAAE,SAAQ;QAEzC,MAAM,SAAS,GAAG,UAAU,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAA;QAC3D,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;YACvB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAA;YACjD,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAA;YACrD,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAA;QACvD,CAAC;QAED,MAAM,MAAM,GAAG,WAAW,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAA;QAC3D,MAAM,GAAG,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;YACpB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;YAChD,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;YACpD,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;QACtD,CAAC;QACD,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAA;IACtD,CAAC;IAED,oFAAoF;IACpF,MAAM,KAAK,GAAG,GAAG,CAAC,eAAe,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;IAClE,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/D,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,MAAM,MAAM,GAAa,EAAE,CAAA;IAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;QACvB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAA;QACnD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACjC,IAAI,CAAC,GAAG;YAAE,SAAQ;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;QAC1C,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG;YAC/C,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;YACrC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QAExC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,MAAM,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;YAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAC9B,MAAM,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAC9B,MAAM,CAAC,IAAI,CACT,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EACzB,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EACzB,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAC3B,CAAA;QACH,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;QACpC,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,gCAAgC;IAChC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,UAAU,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE;gBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;YAC5E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE;gBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;QACjF,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAA;IAChF,CAAC;IAED,OAAO;QACL,SAAS,EAAE,IAAI,YAAY,CAAC,MAAM,CAAC;QACnC,OAAO,EAAE,IAAI,WAAW,CAAC,MAAM,CAAC;QAChC,IAAI;KACL,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAmB;IACpD,IAAI,OAAmC,CAAA;IACvC,IAAI,CAAC;QACH,OAAO,GAAG,SAAS,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,kBAAkB,CAAC,CAAA;IACzF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAClE,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAE,CAAA;IAC9B,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC1B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAA;IACvC,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,UAAU,EAAE,MAAM,CAAC,IAAI;KACxB,CAAA;AACH,CAAC","sourcesContent":["/**\n * threemf-loader — headless 3MF (ZIP/OPC) geometry loader.\n *\n * 3MF is a ZIP container whose geometry lives in `3D/3dmodel.model`, an XML\n * document. Design requirement (unit-system §2.4/§5): the unit MUST be read\n * from the real (inflated) XML, NOT from the raw bytes — `3D/3dmodel.model` is\n * deflate-compressed inside the ZIP, so scanning the raw buffer cannot find\n * `<model unit=\"…\">` (the 3d_editor precedent returned 'millimeter' for real\n * files). We unzip the entry first, then parse the XML.\n *\n * Coordinate conversion: every coordinate is multiplied by `UNIT_SCALE[unit]`\n * to land in the faijs base length unit (mm).\n *\n * Per-object transform: `<item transform=\"a b c d e f g h i p q r\">` is an\n * ST_Matrix3D stored **column-major** whose last three tokens are the\n * translation `(p,q,r)`. Applied as:\n * x' = a*x + d*y + g*z + p\n * y' = b*x + e*y + h*z + q\n * z' = c*x + f*y + i*z + r\n * so object-local mesh coords bake into world-space positions (the op contract\n * is world-space; `planeDistance` must line up with baked positions).\n */\nimport { unzipSync, strFromU8 } from 'fflate'\nimport { parseXmlDocument } from '../api/xml-dom'\nimport { UNIT_SCALE, type UnitName } from '../units'\n\n/** Map a 3MF unit string to a faijs length unit name. */\nfunction threemfUnitToFaijs(unit: string): UnitName | null {\n switch (unit) {\n case 'micron': return 'micron'\n case 'millimeter': return 'mm'\n case 'centimeter': return 'cm'\n case 'inch': return 'inch'\n case 'foot': return 'foot'\n case 'meter': return 'm'\n default: return null\n }\n}\n\n/** A parsed 3MF solid: triangle soup in mm base (already unit-scaled). */\nexport interface ThreemfMesh {\n positions: Float32Array\n indices: Uint32Array\n /** The declared `<model unit>` (raw, e.g. \"millimeter\"). */\n sourceUnit: string\n}\n\n/** Extract the declared unit from an already-parsed `<model>` document. */\nfunction modelUnit(doc: Document): string {\n const model = doc.documentElement\n if (model && model.getAttribute('unit')) {\n return model.getAttribute('unit')!\n }\n // Default per 3MF spec is millimeter.\n return 'millimeter'\n}\n\n/** Parse the `3D/3dmodel.model` XML and produce an index+position mesh. */\nasync function parseModelXml(xml: string): Promise<{ positions: Float32Array; indices: Uint32Array; unit: string }> {\n const doc = await parseXmlDocument(xml)\n const unit = modelUnit(doc)\n const faijsUnit = threemfUnitToFaijs(unit)\n if (faijsUnit === null) {\n throw new Error(`[mesh/threemf] unsupported <model unit>: ${JSON.stringify(unit)}`)\n }\n const scale = UNIT_SCALE[faijsUnit]\n\n // resources → object → mesh → vertices / triangles\n const resources = doc.documentElement.getElementsByTagName('resources')[0]\n const objects = resources ? resources.getElementsByTagName('object') : []\n const byObjectId = new Map<number, { positions: Float32Array; indices: Uint32Array }>()\n\n for (let i = 0; i < objects.length; i++) {\n const obj = objects[i]\n const id = Number(obj.getAttribute('id'))\n if (!Number.isInteger(id)) continue\n const meshEl = obj.getElementsByTagName('mesh')[0]\n if (!meshEl) continue\n const verticesEl = meshEl.getElementsByTagName('vertices')[0]\n const trianglesEl = meshEl.getElementsByTagName('triangles')[0]\n if (!verticesEl || !trianglesEl) continue\n\n const vertexEls = verticesEl.getElementsByTagName('vertex')\n const pos = new Float32Array(vertexEls.length * 3)\n for (let v = 0; v < vertexEls.length; v++) {\n const el = vertexEls[v]\n pos[v * 3] = Number(el.getAttribute('x')) * scale\n pos[v * 3 + 1] = Number(el.getAttribute('y')) * scale\n pos[v * 3 + 2] = Number(el.getAttribute('z')) * scale\n }\n\n const triEls = trianglesEl.getElementsByTagName('triangle')\n const idx = new Uint32Array(triEls.length * 3)\n for (let t = 0; t < triEls.length; t++) {\n const el = triEls[t]\n idx[t * 3] = Number(el && el.getAttribute('v1'))\n idx[t * 3 + 1] = Number(el && el.getAttribute('v2'))\n idx[t * 3 + 2] = Number(el && el.getAttribute('v3'))\n }\n byObjectId.set(id, { positions: pos, indices: idx })\n }\n\n // build → item → per-instance transforms (ST_3D, column-major, translation last 3).\n const build = doc.documentElement.getElementsByTagName('build')[0]\n const itemEls = build ? build.getElementsByTagName('item') : []\n const allPos: number[] = []\n const allIdx: number[] = []\n\n for (let i = 0; i < itemEls.length; i++) {\n const item = itemEls[i]\n const objId = Number(item.getAttribute('objectid'))\n const src = byObjectId.get(objId)\n if (!src) continue\n const mat = item.getAttribute('transform')\n const [a, b, c, d, e, f, g, h, iz, p, q, r] = mat\n ? mat.trim().split(/\\s+/).map(Number)\n : [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]\n\n const base = allPos.length / 3\n for (let v = 0; v < src.positions.length; v += 3) {\n const x = src.positions[v]\n const y = src.positions[v + 1]\n const z = src.positions[v + 2]\n allPos.push(\n a * x + d * y + g * z + p,\n b * x + e * y + h * z + q,\n c * x + f * y + iz * z + r,\n )\n }\n for (let t = 0; t < src.indices.length; t++) {\n allIdx.push(src.indices[t] + base)\n }\n }\n\n // Fallback: if the build list is empty (some exporters omit <build>), emit\n // every object's mesh directly.\n if (itemEls.length === 0) {\n for (const [, src] of byObjectId) {\n const base = allPos.length / 3\n for (let v = 0; v < src.positions.length; v++) allPos.push(src.positions[v])\n for (let t = 0; t < src.indices.length; t++) allIdx.push(src.indices[t] + base)\n }\n }\n\n if (allPos.length === 0) {\n throw new Error('[mesh/threemf] no buildable geometry found in 3dmodel.model')\n }\n\n return {\n positions: new Float32Array(allPos),\n indices: new Uint32Array(allIdx),\n unit,\n }\n}\n\n/**\n * Parse 3MF bytes into a mm-base mesh.\n * @param buffer - the raw .3mf (ZIP) bytes.\n * @returns the parsed mesh plus the declared source unit.\n * @throws when the buffer is not a 3MF/ZIP archive or the unit is invalid.\n */\nexport async function parseThreemf(buffer: ArrayBuffer): Promise<ThreemfMesh> {\n let entries: Record<string, Uint8Array>\n try {\n entries = unzipSync(new Uint8Array(buffer))\n } catch {\n throw new Error('[mesh/threemf] not a valid 3MF ZIP archive')\n }\n const modelKey = Object.keys(entries).find((k) => k.toLowerCase() === '3d/3dmodel.model')\n if (!modelKey) {\n throw new Error('[mesh/threemf] missing 3D/3dmodel.model entry')\n }\n const raw = entries[modelKey]!\n const xml = strFromU8(raw)\n const parsed = await parseModelXml(xml)\n return {\n positions: parsed.positions,\n indices: parsed.indices,\n sourceUnit: parsed.unit,\n }\n}"]}
|
package/dist/mesh/transform.d.ts
CHANGED
|
@@ -24,11 +24,11 @@ export declare function translate(shape: Shape, offset: Vec3): Shape;
|
|
|
24
24
|
* Rotate a mesh shape by baking the rotation into its vertices (angles in
|
|
25
25
|
* degrees, optionally about a pivot).
|
|
26
26
|
* @param shape - the mesh shape to rotate.
|
|
27
|
-
* @param
|
|
27
|
+
* @param angles - XYZ Euler angles in degrees.
|
|
28
28
|
* @param pivot - optional rotation pivot point in mm.
|
|
29
29
|
* @returns a new shape with rotated vertices.
|
|
30
30
|
*/
|
|
31
|
-
export declare function rotate_euler(shape: Shape,
|
|
31
|
+
export declare function rotate_euler(shape: Shape, angles: Vec3, pivot?: Vec3): Shape;
|
|
32
32
|
/**
|
|
33
33
|
* Scale a mesh shape by baking the factor into its vertices.
|
|
34
34
|
* @param shape - the mesh shape to scale.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/mesh/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAG,KAAK,CAQ3D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/mesh/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAG,KAAK,CAQ3D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,IAAI,GAAG,KAAK,CAY5E;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,GAAG,KAAK,CAIjF;AAED;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,GAAG,KAAK,CAExE;AA0BD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,GAAG,KAAK,CAE1E"}
|
package/dist/mesh/transform.js
CHANGED
|
@@ -31,12 +31,12 @@ export function translate(shape, offset) {
|
|
|
31
31
|
* Rotate a mesh shape by baking the rotation into its vertices (angles in
|
|
32
32
|
* degrees, optionally about a pivot).
|
|
33
33
|
* @param shape - the mesh shape to rotate.
|
|
34
|
-
* @param
|
|
34
|
+
* @param angles - XYZ Euler angles in degrees.
|
|
35
35
|
* @param pivot - optional rotation pivot point in mm.
|
|
36
36
|
* @returns a new shape with rotated vertices.
|
|
37
37
|
*/
|
|
38
|
-
export function rotate_euler(shape,
|
|
39
|
-
const euler = new THREE.Euler((
|
|
38
|
+
export function rotate_euler(shape, angles, pivot) {
|
|
39
|
+
const euler = new THREE.Euler((angles[0] * Math.PI) / 180, (angles[1] * Math.PI) / 180, (angles[2] * Math.PI) / 180);
|
|
40
40
|
const matrix = new THREE.Matrix4().makeRotationFromEuler(euler);
|
|
41
41
|
if (pivot) {
|
|
42
42
|
matrix.premultiply(new THREE.Matrix4().makeTranslation(pivot[0], pivot[1], pivot[2]));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/mesh/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAY,EAAE,MAAY;IAClD,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,SAAS,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;QACzB,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;QAC7B,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;IAC/B,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAA;AAC9C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/mesh/transform.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mesh 变换 API\n *\n * 提取来源:\n * - engine/mesh-simplify/proxy-mesh-cache.ts (transformMeshData)\n * - engine-store.partTransforms\n *\n * 变换语义(烘焙执行引擎):\n * - translate/rotate_euler/scale3d 直接烘焙顶点(修改 positions)\n * - 执行器(dispatcher / runtime.execute)调用这些函数将变换烘焙进几何\n * - 交互拖拽期间的预览仍由 partTransforms(渲染层瞬态)承担\n * 确认后由引擎重放语句完成烘焙(P2)\n */\n\nimport * as THREE from 'three'\nimport type { Shape, Vec3 } from './types'\n\n/**\n * Translate a mesh shape by baking the offset into its vertices.\n * @param shape - the mesh shape to translate.\n * @param offset - translation vector in mm.\n * @returns a new shape moved by the given offset.\n */\nexport function translate(shape: Shape, offset: Vec3): Shape {\n const positions = new Float32Array(shape.positions)\n for (let i = 0; i < positions.length; i += 3) {\n positions[i] += offset[0]\n positions[i + 1] += offset[1]\n positions[i + 2] += offset[2]\n }\n return { positions, indices: shape.indices }\n}\n\n/**\n * Rotate a mesh shape by baking the rotation into its vertices (angles in\n * degrees, optionally about a pivot).\n * @param shape - the mesh shape to rotate.\n * @param angles - XYZ Euler angles in degrees.\n * @param pivot - optional rotation pivot point in mm.\n * @returns a new shape with rotated vertices.\n */\nexport function rotate_euler(shape: Shape, angles: Vec3, pivot?: Vec3): Shape {\n const euler = new THREE.Euler(\n (angles[0] * Math.PI) / 180,\n (angles[1] * Math.PI) / 180,\n (angles[2] * Math.PI) / 180,\n )\n const matrix = new THREE.Matrix4().makeRotationFromEuler(euler)\n if (pivot) {\n matrix.premultiply(new THREE.Matrix4().makeTranslation(pivot[0], pivot[1], pivot[2]))\n matrix.multiply(new THREE.Matrix4().makeTranslation(-pivot[0], -pivot[1], -pivot[2]))\n }\n return applyMatrix(shape, matrix)\n}\n\n/**\n * Scale a mesh shape by baking the factor into its vertices.\n * @param shape - the mesh shape to scale.\n * @param factor - uniform scale factor or per-axis (x, y, z) factors.\n * @param center - optional fixed point of the scaling (P6 §4.6; default origin).\n * @returns a new shape with scaled vertices.\n */\nexport function scale3d(shape: Shape, factor: number | Vec3, center?: Vec3): Shape {\n const f: [number, number, number] =\n typeof factor === 'number' ? [factor, factor, factor] : [factor[0], factor[1], factor[2]]\n return applyMatrix(shape, scaleMatrix(f, center))\n}\n\n/**\n * Uniformly scale a mesh shape (brepjs `scale` 契约,P6 §4.6)。后台用\n * `scale3d` 的等比参数;`center` 为缩放不动的点,默认原点。\n * @param shape - the mesh shape to scale.\n * @param factor - uniform scale factor (> 0).\n * @param center - optional fixed point of the scaling (default origin).\n * @returns a new shape with uniformly scaled vertices.\n */\nexport function scale(shape: Shape, factor: number, center?: Vec3): Shape {\n return applyMatrix(shape, scaleMatrix([factor, factor, factor], center))\n}\n\n/** 缩放矩阵:围绕 `center`(缺省原点)构造 T(c)·S·T(−c)。 */\nfunction scaleMatrix(f: [number, number, number], center?: Vec3): THREE.Matrix4 {\n const s = new THREE.Matrix4().makeScale(f[0], f[1], f[2])\n if (!center) return s\n return new THREE.Matrix4()\n .makeTranslation(center[0], center[1], center[2])\n .multiply(s)\n .multiply(new THREE.Matrix4().makeTranslation(-center[0], -center[1], -center[2]))\n}\n\n/** 用 THREE.Matrix4 变换几何 */\nfunction applyMatrix(shape: Shape, matrix: THREE.Matrix4): Shape {\n const positions = new Float32Array(shape.positions)\n const v = new THREE.Vector3()\n for (let i = 0; i < positions.length; i += 3) {\n v.set(positions[i], positions[i + 1], positions[i + 2])\n v.applyMatrix4(matrix)\n positions[i] = v.x\n positions[i + 1] = v.y\n positions[i + 2] = v.z\n }\n return { positions, indices: shape.indices }\n}\n\n/**\n * Transform a mesh shape with an arbitrary THREE.Matrix4 (corresponds to the\n * existing transformMeshData function).\n * @param shape - the mesh shape to transform.\n * @param matrix - the 4x4 transform matrix to apply.\n * @returns a new shape with transformed vertices.\n */\nexport function transformMatrix(shape: Shape, matrix: THREE.Matrix4): Shape {\n return applyMatrix(shape, matrix)\n}\n"]}
|
package/dist/mesh/types.d.ts
CHANGED
|
@@ -155,7 +155,7 @@ export interface TranslateParams {
|
|
|
155
155
|
}
|
|
156
156
|
/** Parameters for rotating a shape. */
|
|
157
157
|
export interface RotateParams {
|
|
158
|
-
|
|
158
|
+
angles: Vec3;
|
|
159
159
|
pivot?: Vec3;
|
|
160
160
|
}
|
|
161
161
|
/** Parameters for scaling a shape. */
|
|
@@ -233,7 +233,7 @@ export interface DrillParams {
|
|
|
233
233
|
/** Parameters for extruding a face bounded by a plane. */
|
|
234
234
|
export interface ExtrudeParams {
|
|
235
235
|
normal: Vec3;
|
|
236
|
-
|
|
236
|
+
planeDistance: number;
|
|
237
237
|
length: number;
|
|
238
238
|
mode?: 'centered' | 'forward' | 'backward';
|
|
239
239
|
}
|
package/dist/mesh/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mesh/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mesh/types.ts"],"names":[],"mappings":"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"}
|
package/dist/mesh/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mesh/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA8BH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,CAAU;IACpC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,WAAW,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC,CAAA;AAC3E,CAAC;AAED,aAAa;AAEb,8DAA8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAA;AAC9B,4CAA4C;AAC5C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAA;AACzB,4CAA4C;AAC5C,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAA;AAE3B;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,CAAqB;IAC7C,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,YAAY,CAAA;IACxC,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC9D,CAAC","sourcesContent":["/**\n * mesh 类型定义 — 纯数据几何 API 的类型契约\n *\n * 设计原则(§5.1):\n * - 全部纯数据:输入输出是 ManifoldMeshData 或 JSON 值,不碰 THREE 场景、不读 store\n * - 不可变:每个 API 返回新几何,不修改输入\n * - 坐标系:右手系 +Z 向上、毫米、角度用度\n * - 坐标空间:所有 API 输入/输出均为**世界空间** ManifoldMeshData\n * (局部↔世界变换由执行器负责,mesh 不感知 mesh.matrixWorld)\n *\n * P1 阶段 Shape = ManifoldMeshData(无 worker)。\n * P3+ 阶段 Shape 将变为 worker 内 Manifold 对象的句柄。\n */\n\n// ── 基础类型 ──\n\nexport type Vec3 = [number, number, number]\n\n/**\n * A JSON-serializable value: scalar, null, array, or plain object.\n */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [k: string]: JsonValue }\n\n// ── Shape ──\n\n/**\n * A mesh shape — the core data type of the mesh API.\n *\n * Shape is defined directly in mesh/types.ts rather than re-exported from\n * ops/types.ts; ops/types.ts imports it from here, removing the type cycle.\n */\nexport interface Shape {\n positions: Float32Array\n indices: Uint32Array\n}\n\n/**\n * Structural guard: returns true when the value looks like a mesh Shape\n * (duck-typed via positions/indices, with no requirements on third-party\n * types).\n *\n * Per the keep-syntax design, hosts use this guard to distinguish mesh Shapes\n * from compounds when consuming ExecutionResult.outputs, in the same style as\n * the runtime-internal isShapeLike.\n * @param v - the value to test.\n * @returns true when the value is a mesh Shape.\n */\nexport function isMeshShape(v: unknown): v is Shape {\n return !!v && typeof v === 'object' && 'positions' in v && 'indices' in v\n}\n\n// ── 创建参数 ──\n\n/** Default radial segment count used for rounded geometry. */\nexport const NRAD_DEFAULT = 64\n/** Minimum allowed radial segment count. */\nexport const NRAD_MIN = 3\n/** Maximum allowed radial segment count. */\nexport const NRAD_MAX = 128\n\n/**\n * Clamp an nRad value into the legal range [NRAD_MIN, NRAD_MAX], rounding to\n * the nearest integer; undefined falls back to NRAD_DEFAULT.\n * @param n - the requested radial segment count, or undefined.\n * @returns the clamped radial segment count.\n */\nexport function clampNRad(n: number | undefined): number {\n if (n === undefined) return NRAD_DEFAULT\n return Math.max(NRAD_MIN, Math.min(NRAD_MAX, Math.round(n)))\n}\n\n/**\n * Parameters for creating a box (brepjs `box(width, depth, height, {at?, centered?, segments?})`\n * contract, §4.1 A 决策). Default: min-corner at the origin. `centered: true` shifts so the\n * box is centered at the origin; `at` is CENTER semantics and takes precedence over `centered`.\n */\nexport interface BoxParams {\n /** Side length along X (mm). */\n width: number\n /** Side length along Y (mm). */\n depth: number\n /** Side length along Z (mm). */\n height: number\n /** Center position (brepjs `at`, CENTER semantics); takes precedence over `centered`. */\n at?: Vec3\n /** Center the box at the origin when `at` is absent. Default: false (min-corner at origin). */\n centered?: boolean\n /** Tessellation segment count (box: affects only brep/mesh tessellation, not topology). */\n segments?: number\n /** Internal historical alias for `segments` (accepted by clampNRad, §5.1). */\n nRad?: number\n}\n\n/** Parameters for creating a sphere. */\nexport interface SphereParams {\n radius: number\n segments?: number\n center?: Vec3\n nRad?: number\n}\n\n/** Parameters for creating a cylinder (brepjs contract, §4.3 A). */\nexport interface CylinderParams {\n /** Radius (mm). */\n radius: number\n /** Height along +Z (mm). */\n height: number\n /** Base circle center (brepjs `at`, BASE semantics; default [0, 0, 0]). */\n at?: Vec3\n /** Center the cylinder (base at −h/2 / center at `at`) instead of base at `at`/origin. */\n centered?: boolean\n /** Tessellation segment count (cylinder: affects only tessellation, not topology). */\n segments?: number\n /** Internal historical alias for `segments` (accepted by clampNRad, §5.1). */\n nRad?: number\n}\n\n/** Parameters for creating a cone (or a truncated cone). */\nexport interface ConeParams {\n /** Radius at the base (mm). */\n radiusBottom: number\n /** Radius at the top (mm); 0 for a pointed cone, === radiusBottom for a cylinder. */\n radiusTop: number\n /** Height along +Z (mm). */\n height: number\n /** Base circle center (brepjs `at`, BASE semantics; default [0, 0, 0]). */\n at?: Vec3\n /** Center the cone (base at −h/2 / center at `at`) instead of base at `at`/origin. */\n centered?: boolean\n /** Tessellation segment count (cone: affects only mere tessellation, not topology). */\n segments?: number\n /** Internal historical alias for `segments` (accepted by clampNRad, §5.1). */\n nRad?: number\n}\n\n/**\n * Parameters for creating a wedge (trapezoidal prism).\n */\nexport interface WedgeParams {\n /** Width of the base edge (mm), along the Y axis. */\n width: number\n /** Height of the trapezoid (mm), along the Z axis. */\n height: number\n /** Angle between the base edge and the slope (degrees). */\n angle: number\n /** Total extrusion length (mm), along the X axis. */\n length: number\n center?: Vec3\n nRad?: number\n}\n\n/** Parameters for creating 3D text. */\nexport interface TextParams {\n text: string\n size: number\n depth: number\n}\n\n/** Parameters for extruding an SVG into a solid. */\nexport interface SvgExtrudeParams {\n svg: string\n depth: number\n targetLongSide: number\n naturalWidth?: number\n naturalHeight?: number\n}\n\n/** Parameters for building a solid from an SDF (signed distance function). */\nexport interface SdfParams {\n code: string\n box?: [Vec3, Vec3]\n resolution?: number\n params?: Record<string, number>\n}\n\n// ── 变换参数 ──\n\n/** Parameters for translating a shape. */\nexport interface TranslateParams {\n offset: Vec3\n}\n\n/** Parameters for rotating a shape. */\nexport interface RotateParams {\n
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mesh/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA8BH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,CAAU;IACpC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,WAAW,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC,CAAA;AAC3E,CAAC;AAED,aAAa;AAEb,8DAA8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAA;AAC9B,4CAA4C;AAC5C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAA;AACzB,4CAA4C;AAC5C,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAA;AAE3B;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,CAAqB;IAC7C,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,YAAY,CAAA;IACxC,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC9D,CAAC","sourcesContent":["/**\n * mesh 类型定义 — 纯数据几何 API 的类型契约\n *\n * 设计原则(§5.1):\n * - 全部纯数据:输入输出是 ManifoldMeshData 或 JSON 值,不碰 THREE 场景、不读 store\n * - 不可变:每个 API 返回新几何,不修改输入\n * - 坐标系:右手系 +Z 向上、毫米、角度用度\n * - 坐标空间:所有 API 输入/输出均为**世界空间** ManifoldMeshData\n * (局部↔世界变换由执行器负责,mesh 不感知 mesh.matrixWorld)\n *\n * P1 阶段 Shape = ManifoldMeshData(无 worker)。\n * P3+ 阶段 Shape 将变为 worker 内 Manifold 对象的句柄。\n */\n\n// ── 基础类型 ──\n\nexport type Vec3 = [number, number, number]\n\n/**\n * A JSON-serializable value: scalar, null, array, or plain object.\n */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [k: string]: JsonValue }\n\n// ── Shape ──\n\n/**\n * A mesh shape — the core data type of the mesh API.\n *\n * Shape is defined directly in mesh/types.ts rather than re-exported from\n * ops/types.ts; ops/types.ts imports it from here, removing the type cycle.\n */\nexport interface Shape {\n positions: Float32Array\n indices: Uint32Array\n}\n\n/**\n * Structural guard: returns true when the value looks like a mesh Shape\n * (duck-typed via positions/indices, with no requirements on third-party\n * types).\n *\n * Per the keep-syntax design, hosts use this guard to distinguish mesh Shapes\n * from compounds when consuming ExecutionResult.outputs, in the same style as\n * the runtime-internal isShapeLike.\n * @param v - the value to test.\n * @returns true when the value is a mesh Shape.\n */\nexport function isMeshShape(v: unknown): v is Shape {\n return !!v && typeof v === 'object' && 'positions' in v && 'indices' in v\n}\n\n// ── 创建参数 ──\n\n/** Default radial segment count used for rounded geometry. */\nexport const NRAD_DEFAULT = 64\n/** Minimum allowed radial segment count. */\nexport const NRAD_MIN = 3\n/** Maximum allowed radial segment count. */\nexport const NRAD_MAX = 128\n\n/**\n * Clamp an nRad value into the legal range [NRAD_MIN, NRAD_MAX], rounding to\n * the nearest integer; undefined falls back to NRAD_DEFAULT.\n * @param n - the requested radial segment count, or undefined.\n * @returns the clamped radial segment count.\n */\nexport function clampNRad(n: number | undefined): number {\n if (n === undefined) return NRAD_DEFAULT\n return Math.max(NRAD_MIN, Math.min(NRAD_MAX, Math.round(n)))\n}\n\n/**\n * Parameters for creating a box (brepjs `box(width, depth, height, {at?, centered?, segments?})`\n * contract, §4.1 A 决策). Default: min-corner at the origin. `centered: true` shifts so the\n * box is centered at the origin; `at` is CENTER semantics and takes precedence over `centered`.\n */\nexport interface BoxParams {\n /** Side length along X (mm). */\n width: number\n /** Side length along Y (mm). */\n depth: number\n /** Side length along Z (mm). */\n height: number\n /** Center position (brepjs `at`, CENTER semantics); takes precedence over `centered`. */\n at?: Vec3\n /** Center the box at the origin when `at` is absent. Default: false (min-corner at origin). */\n centered?: boolean\n /** Tessellation segment count (box: affects only brep/mesh tessellation, not topology). */\n segments?: number\n /** Internal historical alias for `segments` (accepted by clampNRad, §5.1). */\n nRad?: number\n}\n\n/** Parameters for creating a sphere. */\nexport interface SphereParams {\n radius: number\n segments?: number\n center?: Vec3\n nRad?: number\n}\n\n/** Parameters for creating a cylinder (brepjs contract, §4.3 A). */\nexport interface CylinderParams {\n /** Radius (mm). */\n radius: number\n /** Height along +Z (mm). */\n height: number\n /** Base circle center (brepjs `at`, BASE semantics; default [0, 0, 0]). */\n at?: Vec3\n /** Center the cylinder (base at −h/2 / center at `at`) instead of base at `at`/origin. */\n centered?: boolean\n /** Tessellation segment count (cylinder: affects only tessellation, not topology). */\n segments?: number\n /** Internal historical alias for `segments` (accepted by clampNRad, §5.1). */\n nRad?: number\n}\n\n/** Parameters for creating a cone (or a truncated cone). */\nexport interface ConeParams {\n /** Radius at the base (mm). */\n radiusBottom: number\n /** Radius at the top (mm); 0 for a pointed cone, === radiusBottom for a cylinder. */\n radiusTop: number\n /** Height along +Z (mm). */\n height: number\n /** Base circle center (brepjs `at`, BASE semantics; default [0, 0, 0]). */\n at?: Vec3\n /** Center the cone (base at −h/2 / center at `at`) instead of base at `at`/origin. */\n centered?: boolean\n /** Tessellation segment count (cone: affects only mere tessellation, not topology). */\n segments?: number\n /** Internal historical alias for `segments` (accepted by clampNRad, §5.1). */\n nRad?: number\n}\n\n/**\n * Parameters for creating a wedge (trapezoidal prism).\n */\nexport interface WedgeParams {\n /** Width of the base edge (mm), along the Y axis. */\n width: number\n /** Height of the trapezoid (mm), along the Z axis. */\n height: number\n /** Angle between the base edge and the slope (degrees). */\n angle: number\n /** Total extrusion length (mm), along the X axis. */\n length: number\n center?: Vec3\n nRad?: number\n}\n\n/** Parameters for creating 3D text. */\nexport interface TextParams {\n text: string\n size: number\n depth: number\n}\n\n/** Parameters for extruding an SVG into a solid. */\nexport interface SvgExtrudeParams {\n svg: string\n depth: number\n targetLongSide: number\n naturalWidth?: number\n naturalHeight?: number\n}\n\n/** Parameters for building a solid from an SDF (signed distance function). */\nexport interface SdfParams {\n code: string\n box?: [Vec3, Vec3]\n resolution?: number\n params?: Record<string, number>\n}\n\n// ── 变换参数 ──\n\n/** Parameters for translating a shape. */\nexport interface TranslateParams {\n offset: Vec3\n}\n\n/** Parameters for rotating a shape. */\nexport interface RotateParams {\n angles: Vec3\n pivot?: Vec3\n}\n\n/** Parameters for scaling a shape. */\nexport interface ScaleParams {\n factor: number | Vec3\n}\n\n// ── 布尔参数 ──\n\n/** Kinds of binary boolean operations. */\nexport type BooleanOperation = 'union' | 'subtract' | 'intersect'\n\n// ── 分割参数 ──\n\n/** A cutting plane defined by a unit normal and a signed offset. */\nexport interface SplitPlane {\n normal: Vec3\n offset: number\n}\n\n/** Parameters for a dovetail split, including the cutting plane setup. */\nexport interface DovetailSplitParams {\n plane: SplitPlane\n planeCenter: Vec3\n widthDir: Vec3\n bboxWidthOnWidthDir: number\n groove: {\n depth: number\n depthTolerance: number\n width: number\n widthTolerance: number\n flapsAngle: number\n }\n}\n\n/** Parameters for a dowel-pin split, including the cutting plane setup. */\nexport interface DowelSplitParams {\n plane: SplitPlane\n planeCenter: Vec3\n widthDir: Vec3\n dowel: {\n diameter: number\n diameterTolerance: number\n height: number\n heightTolerance: number\n }\n selectedSections?: number[] | null\n}\n\n/** Parameters for a straight-tenon split, including the cutting plane setup. */\nexport interface TenonSplitParams {\n plane: SplitPlane\n planeCenter: Vec3\n widthDir: Vec3\n tenon: {\n sideLength: number\n sideLengthTolerance: number\n height: number\n heightTolerance: number\n }\n selectedSections?: number[] | null\n}\n\n/** Result of a joinery split: the two halves plus the cut-out wedge. */\nexport interface SplitResult {\n front: Shape\n back: Shape\n wedge: Shape | null\n}\n\n// ── 钻孔参数 ──\n\n/** Parameters for drilling a hole. */\nexport interface DrillParams {\n diameter: number\n depth?: number\n type: 'through' | 'blind'\n position: Vec3\n direction: Vec3\n faceNormal: Vec3\n tolerance?: number\n holeType?: 'simple' | 'screw'\n screwSystem?: string\n screwSpecIdx?: number\n screwThread?: string\n screwHead?: string\n}\n\n// ── 拉伸参数 ──\n\n/** Parameters for extruding a face bounded by a plane. */\nexport interface ExtrudeParams {\n normal: Vec3\n planeDistance: number\n length: number\n mode?: 'centered' | 'forward' | 'backward'\n}\n\n// ── 雕刻参数 ──\n\n/** Parameters for engraving text or an SVG onto a face. */\nexport interface EngraveParams {\n mode: 'convex' | 'concave'\n depth: number\n face: {\n center: Vec3\n normal: Vec3\n }\n text?: string\n textSize?: number\n svg?: string\n svgNaturalWidth?: number\n svgNaturalHeight?: number\n svgSize?: number\n}\n\n/** Parameters for applying a knurl texture to a face. */\nexport interface KnurlParams {\n face: {\n center: Vec3\n normal: Vec3\n }\n knurlTextureHeight: number\n knurlInvertDisplacement: boolean\n knurlRefineLength: number\n knurlScaleU: number\n knurlScaleV: number\n knurlMappingMode: number\n}\n\n// ── 查询结果 ──\n\n/** Axis-aligned bounding box in world space. */\nexport interface BoundingBox {\n min: Vec3\n max: Vec3\n}\n\n/** Description of a face on a shape: center, normal and area. */\nexport interface FaceDescriptor {\n center: Vec3\n normal: Vec3\n area: number\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/node-host/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAwB,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/node-host/cli.ts"],"names":[],"mappings":"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"}
|