@faicad/faijs 0.30.9 → 0.31.1
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/align/index.d.ts +64 -0
- package/dist/api/align/index.d.ts.map +1 -0
- package/dist/api/align/index.js +101 -0
- package/dist/api/align/index.js.map +1 -0
- package/dist/api/api-namespace.d.ts +5 -4
- package/dist/api/api-namespace.d.ts.map +1 -1
- package/dist/api/api-namespace.js +36 -4
- package/dist/api/api-namespace.js.map +1 -1
- package/dist/api/boolean-op/index.d.ts +65 -0
- package/dist/api/boolean-op/index.d.ts.map +1 -0
- package/dist/api/boolean-op/index.js +113 -0
- package/dist/api/boolean-op/index.js.map +1 -0
- package/dist/api/boolean.d.ts.map +1 -1
- package/dist/api/boolean.js +15 -27
- package/dist/api/boolean.js.map +1 -1
- package/dist/api/brep-operations/healingFns.d.ts +13 -0
- package/dist/api/brep-operations/healingFns.d.ts.map +1 -1
- package/dist/api/brep-operations/healingFns.js +28 -1
- package/dist/api/brep-operations/healingFns.js.map +1 -1
- package/dist/api/brep-operations/topologyFns.d.ts +27 -6
- package/dist/api/brep-operations/topologyFns.d.ts.map +1 -1
- package/dist/api/brep-operations/topologyFns.js +46 -22
- package/dist/api/brep-operations/topologyFns.js.map +1 -1
- package/dist/api/chamfer.d.ts +5 -4
- package/dist/api/chamfer.d.ts.map +1 -1
- package/dist/api/chamfer.js +12 -11
- package/dist/api/chamfer.js.map +1 -1
- package/dist/api/curve-sketch/index.d.ts.map +1 -1
- package/dist/api/curve-sketch/index.js +9 -3
- package/dist/api/curve-sketch/index.js.map +1 -1
- package/dist/api/draft.d.ts.map +1 -1
- package/dist/api/draft.js +1 -3
- package/dist/api/draft.js.map +1 -1
- package/dist/api/engrave.d.ts.map +1 -1
- package/dist/api/engrave.js +3 -13
- package/dist/api/engrave.js.map +1 -1
- package/dist/api/export-3mf.d.ts +73 -0
- package/dist/api/export-3mf.d.ts.map +1 -0
- package/dist/api/export-3mf.js +121 -0
- package/dist/api/export-3mf.js.map +1 -0
- package/dist/api/export-brep.d.ts +6 -0
- package/dist/api/export-brep.d.ts.map +1 -1
- package/dist/api/export-brep.js +11 -2
- package/dist/api/export-brep.js.map +1 -1
- package/dist/api/export-step.d.ts +67 -0
- package/dist/api/export-step.d.ts.map +1 -0
- package/dist/api/export-step.js +98 -0
- package/dist/api/export-step.js.map +1 -0
- package/dist/api/export-stl.d.ts +8 -0
- package/dist/api/export-stl.d.ts.map +1 -1
- package/dist/api/export-stl.js +23 -8
- package/dist/api/export-stl.js.map +1 -1
- package/dist/api/feature-repair.d.ts +1 -1
- package/dist/api/feature-repair.d.ts.map +1 -1
- package/dist/api/feature-repair.js +1 -7
- package/dist/api/feature-repair.js.map +1 -1
- package/dist/api/fillet-variable.d.ts.map +1 -1
- package/dist/api/fillet-variable.js +0 -1
- package/dist/api/fillet-variable.js.map +1 -1
- package/dist/api/fillet.d.ts +3 -3
- package/dist/api/fillet.d.ts.map +1 -1
- package/dist/api/fillet.js +3 -4
- package/dist/api/fillet.js.map +1 -1
- package/dist/api/generated/operations.js +6 -6
- package/dist/api/generated/operations.js.map +1 -1
- package/dist/api/generated/script-face-manifest.d.ts +1 -1
- package/dist/api/generated/script-face-manifest.js +3 -3
- package/dist/api/generated/script-face-manifest.js.map +1 -1
- package/dist/api/generated/script-face.d.ts +1 -1
- package/dist/api/generated/script-face.js +1 -1
- 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.js +10 -10
- package/dist/api/generated/topology.js.map +1 -1
- package/dist/api/helix.d.ts +1 -1
- package/dist/api/helix.js +1 -1
- package/dist/api/helix.js.map +1 -1
- package/dist/api/index.d.ts +4 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +16 -4
- package/dist/api/index.js.map +1 -1
- package/dist/api/internal/compat-op.d.ts +6 -6
- package/dist/api/internal/compat-op.d.ts.map +1 -1
- package/dist/api/internal/compat-op.js +7 -9
- package/dist/api/internal/compat-op.js.map +1 -1
- package/dist/api/internal/export-members.d.ts +80 -0
- package/dist/api/internal/export-members.d.ts.map +1 -0
- package/dist/api/internal/export-members.js +104 -0
- package/dist/api/internal/export-members.js.map +1 -0
- package/dist/api/internal/l3-bridge.d.ts +17 -0
- package/dist/api/internal/l3-bridge.d.ts.map +1 -1
- package/dist/api/internal/l3-bridge.js +23 -1
- package/dist/api/internal/l3-bridge.js.map +1 -1
- package/dist/api/measure-query/index.d.ts +262 -0
- package/dist/api/measure-query/index.d.ts.map +1 -0
- package/dist/api/measure-query/index.js +390 -0
- package/dist/api/measure-query/index.js.map +1 -0
- package/dist/api/pattern.d.ts.map +1 -1
- package/dist/api/pattern.js +0 -3
- package/dist/api/pattern.js.map +1 -1
- package/dist/api/primitives.d.ts +6 -6
- package/dist/api/primitives.d.ts.map +1 -1
- package/dist/api/primitives.js +12 -11
- package/dist/api/primitives.js.map +1 -1
- package/dist/api/profile.d.ts.map +1 -1
- package/dist/api/profile.js +0 -1
- package/dist/api/profile.js.map +1 -1
- package/dist/api/punch-hole.d.ts.map +1 -1
- package/dist/api/punch-hole.js +0 -1
- package/dist/api/punch-hole.js.map +1 -1
- package/dist/api/replicate.d.ts +5 -7
- package/dist/api/replicate.d.ts.map +1 -1
- package/dist/api/replicate.js +18 -56
- package/dist/api/replicate.js.map +1 -1
- package/dist/api/section-by-plane.d.ts.map +1 -1
- package/dist/api/section-by-plane.js +0 -1
- package/dist/api/section-by-plane.js.map +1 -1
- package/dist/api/shell.d.ts +1 -1
- package/dist/api/shell.d.ts.map +1 -1
- package/dist/api/shell.js +11 -2
- package/dist/api/shell.js.map +1 -1
- package/dist/api/sketch-on-face.d.ts +3 -3
- package/dist/api/sketch-on-face.d.ts.map +1 -1
- package/dist/api/sketch-on-face.js +6 -4
- package/dist/api/sketch-on-face.js.map +1 -1
- package/dist/api/sketch-on-plane.d.ts.map +1 -1
- package/dist/api/sketch-on-plane.js +0 -1
- package/dist/api/sketch-on-plane.js.map +1 -1
- package/dist/api/split-by-plane.d.ts.map +1 -1
- package/dist/api/split-by-plane.js +0 -1
- package/dist/api/split-by-plane.js.map +1 -1
- package/dist/api/split.d.ts +1 -1
- package/dist/api/split.js +1 -1
- package/dist/api/split.js.map +1 -1
- package/dist/api/surface/arg-spec.d.ts +3 -12
- package/dist/api/surface/arg-spec.d.ts.map +1 -1
- package/dist/api/surface/arg-spec.js +19 -26
- package/dist/api/surface/arg-spec.js.map +1 -1
- package/dist/api/sweep.d.ts +15 -3
- package/dist/api/sweep.d.ts.map +1 -1
- package/dist/api/sweep.js +5 -3
- package/dist/api/sweep.js.map +1 -1
- package/dist/api/thicken.d.ts.map +1 -1
- package/dist/api/thicken.js +11 -2
- package/dist/api/thicken.js.map +1 -1
- package/dist/api/transform.d.ts +3 -3
- package/dist/api/transform.d.ts.map +1 -1
- package/dist/api/transform.js +47 -17
- package/dist/api/transform.js.map +1 -1
- package/dist/boolean/index.d.ts +23 -0
- package/dist/boolean/index.d.ts.map +1 -0
- package/dist/boolean/index.js +27 -0
- package/dist/boolean/index.js.map +1 -0
- package/dist/brep/brep-chain.d.ts +1 -19
- package/dist/brep/brep-chain.d.ts.map +1 -1
- package/dist/brep/brep-chain.js +0 -1
- package/dist/brep/brep-chain.js.map +1 -1
- package/dist/brep/brep-ops.d.ts +4 -1
- package/dist/brep/brep-ops.d.ts.map +1 -1
- package/dist/brep/brep-ops.js +9 -5
- package/dist/brep/brep-ops.js.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.js +0 -3
- package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
- package/dist/brep/engine/adapters/brepkit.d.ts +4 -3
- package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brepkit.js +4 -98
- package/dist/brep/engine/adapters/brepkit.js.map +1 -1
- package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
- package/dist/brep/engine/adapters/occt.js +0 -144
- package/dist/brep/engine/adapters/occt.js.map +1 -1
- package/dist/brep/engine/native-history.d.ts +27 -0
- package/dist/brep/engine/native-history.d.ts.map +1 -0
- package/dist/brep/engine/native-history.js +54 -0
- package/dist/brep/engine/native-history.js.map +1 -0
- package/dist/brep/engine/registry.d.ts +2 -4
- package/dist/brep/engine/registry.d.ts.map +1 -1
- package/dist/brep/engine/registry.js +1 -1
- package/dist/brep/engine/registry.js.map +1 -1
- package/dist/brep/engine/types.d.ts +35 -77
- package/dist/brep/engine/types.d.ts.map +1 -1
- package/dist/brep/engine/types.js.map +1 -1
- package/dist/brep/export/export-model.d.ts +21 -0
- package/dist/brep/export/export-model.d.ts.map +1 -1
- package/dist/brep/export/export-model.js +171 -73
- package/dist/brep/export/export-model.js.map +1 -1
- package/dist/brep/export/step.d.ts +17 -1
- package/dist/brep/export/step.d.ts.map +1 -1
- package/dist/brep/export/step.js +133 -0
- package/dist/brep/export/step.js.map +1 -1
- package/dist/brep/export/stl.d.ts +22 -1
- package/dist/brep/export/stl.d.ts.map +1 -1
- package/dist/brep/export/stl.js +58 -10
- package/dist/brep/export/stl.js.map +1 -1
- package/dist/brep/export/transform12.d.ts +47 -0
- package/dist/brep/export/transform12.d.ts.map +1 -0
- package/dist/brep/export/transform12.js +87 -0
- package/dist/brep/export/transform12.js.map +1 -0
- package/dist/brep/face-evolution.d.ts +53 -0
- package/dist/brep/face-evolution.d.ts.map +1 -1
- package/dist/brep/face-evolution.js +65 -0
- package/dist/brep/face-evolution.js.map +1 -1
- package/dist/browser-host/index.d.ts +4 -1
- package/dist/browser-host/index.d.ts.map +1 -1
- package/dist/browser-host/index.js +7 -1
- package/dist/browser-host/index.js.map +1 -1
- package/dist/browser.d.ts +4 -8
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +4 -26
- package/dist/browser.js.map +1 -1
- package/dist/cad-runtime/backend-dispatch.d.ts +13 -58
- package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
- package/dist/cad-runtime/backend-dispatch.js +22 -80
- package/dist/cad-runtime/backend-dispatch.js.map +1 -1
- package/dist/cad-runtime/content-key.d.ts +3 -3
- package/dist/cad-runtime/content-key.js +3 -3
- package/dist/cad-runtime/content-key.js.map +1 -1
- package/dist/cad-runtime/ports.d.ts +28 -0
- package/dist/cad-runtime/ports.d.ts.map +1 -1
- package/dist/cad-runtime/ports.js.map +1 -1
- package/dist/cad-runtime/runtime.d.ts +33 -12
- package/dist/cad-runtime/runtime.d.ts.map +1 -1
- package/dist/cad-runtime/runtime.js +44 -48
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/define-op.d.ts +6 -11
- package/dist/define-op.d.ts.map +1 -1
- package/dist/define-op.js +3 -20
- package/dist/define-op.js.map +1 -1
- package/dist/env-agnostic.d.ts +2 -2
- package/dist/env-agnostic.d.ts.map +1 -1
- package/dist/env-agnostic.js +1 -1
- package/dist/env-agnostic.js.map +1 -1
- package/dist/index.d.ts +13 -64
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -75
- package/dist/index.js.map +1 -1
- package/dist/lang/symbol-table.generated.d.ts +17 -0
- package/dist/lang/symbol-table.generated.d.ts.map +1 -1
- package/dist/lang/symbol-table.generated.js +17 -0
- package/dist/lang/symbol-table.generated.js.map +1 -1
- package/dist/mesh/index.d.ts +18 -23
- package/dist/mesh/index.d.ts.map +1 -1
- package/dist/mesh/index.js +18 -20
- package/dist/mesh/index.js.map +1 -1
- package/dist/mesh/io.d.ts +42 -14
- package/dist/mesh/io.d.ts.map +1 -1
- package/dist/mesh/io.js +77 -13
- package/dist/mesh/io.js.map +1 -1
- package/dist/mesh/threemf-loader.d.ts +38 -4
- package/dist/mesh/threemf-loader.d.ts.map +1 -1
- package/dist/mesh/threemf-loader.js +115 -34
- package/dist/mesh/threemf-loader.js.map +1 -1
- package/dist/mesh/types.d.ts +30 -0
- package/dist/mesh/types.d.ts.map +1 -1
- package/dist/mesh/types.js.map +1 -1
- package/dist/node-host/execute-script.d.ts +2 -1
- package/dist/node-host/execute-script.d.ts.map +1 -1
- package/dist/node-host/execute-script.js +5 -4
- package/dist/node-host/execute-script.js.map +1 -1
- package/dist/node-host/index.d.ts +1 -0
- package/dist/node-host/index.d.ts.map +1 -1
- package/dist/node-host/index.js +4 -0
- package/dist/node-host/index.js.map +1 -1
- package/dist/primitives/index.d.ts +19 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +21 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/runtime-state.d.ts +63 -29
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +57 -0
- package/dist/runtime-state.js.map +1 -1
- package/dist/sdf/index.d.ts +12 -0
- package/dist/sdf/index.d.ts.map +1 -0
- package/dist/sdf/index.js +13 -0
- package/dist/sdf/index.js.map +1 -0
- package/dist/sdk.d.ts +0 -1
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js.map +1 -1
- package/dist/weapp.d.ts +2 -2
- package/dist/weapp.d.ts.map +1 -1
- package/dist/weapp.js +1 -1
- package/dist/weapp.js.map +1 -1
- package/package.json +276 -35
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
*
|
|
14
14
|
* 红线(§10.3 3a):绝不文本级改坐标 — 坐标只在几何层缩放,文本层只碰单位实体。
|
|
15
15
|
*/
|
|
16
|
-
import { buildStlBufferFromMesh } from './stl.js';
|
|
16
|
+
import { buildStlBufferFromMesh, composeMatrix12, bakeMatrix12ToPositions } from './stl.js';
|
|
17
17
|
import { writeZipEntries } from '../../io/zip.js';
|
|
18
18
|
import { UNIT_SCALE } from '../../units.js';
|
|
19
19
|
import { getBrepApi } from '../handle-bridge.js';
|
|
20
|
+
import { getBackends, BrepUnsupportedError } from '../../runtime-state.js';
|
|
20
21
|
import { exportStepFromSolids } from './step.js';
|
|
21
22
|
import { detectStepUnit, STEP_UNIT_SCAN_PREFIX } from '../../mesh/io.js';
|
|
22
23
|
/** UnitName → 3MF <model unit> 枚举全名(唯一真源;yard 无对应值)。 */
|
|
@@ -72,19 +73,27 @@ function rewriteStepUnitEntities(stepText, unit) {
|
|
|
72
73
|
}
|
|
73
74
|
const lenId = maxId + 1;
|
|
74
75
|
const convId = maxId + 2;
|
|
75
|
-
// 2)
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
// 2) 存在性守卫:必须至少有一条 LENGTH_UNIT 挂 SI_UNIT(.MILLI.,.METRE.),否则
|
|
77
|
+
// 没有可改写的声明(凭空插入单位声明 = 伪造文件单位)。
|
|
78
|
+
// OCCT 实测形态(实体括号内还有 LENGTH_UNIT() / NAMED_UNIT(*) 的括号,且
|
|
79
|
+
// `=`、`)` 前后都有空格):
|
|
80
|
+
// #346 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) );
|
|
81
|
+
// 故实体体的字符类用 [^;](STEP 实体行内不含分号)而不是 [^)]——后者跨不过
|
|
82
|
+
// `LENGTH_UNIT()` 与 `NAMED_UNIT(*)` 自带的括号,整段永远匹配不上。
|
|
83
|
+
const siDecl = out.match(/#(\d+)\s*=\s*\([^;]*?SI_UNIT\s*\(\s*\.MILLI\.\s*,\s*\.METRE\.\s*\)[^;]*?\)\s*;/);
|
|
84
|
+
if (!siDecl) {
|
|
80
85
|
throw new Error(`[export/step] no SI_UNIT(.MILLI.,.METRE.) entity found; cannot rewrite declaration to ${name}`);
|
|
81
86
|
}
|
|
82
|
-
// 3)
|
|
83
|
-
//
|
|
84
|
-
//
|
|
87
|
+
// 3) 把**全部** SI_UNIT(.MILLI.,.METRE.) 换成 CONVERSION_BASED_UNIT(各 context
|
|
88
|
+
// 共享同一份换算因子实体),插入换算因子与基准米实体:
|
|
89
|
+
// #si=( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) );
|
|
90
|
+
// → #si=( LENGTH_UNIT() NAMED_UNIT(*) CONVERSION_BASED_UNIT('INCH',#conv) );
|
|
85
91
|
// #conv=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(25.4),#len);
|
|
86
92
|
// #len=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT($,.METRE.));
|
|
87
|
-
|
|
93
|
+
// 全局替换而不是只改第一条:多零件导出会写出多条 LENGTH_UNIT 声明(每个 part 一个
|
|
94
|
+
// context,实测 2 个 part → #346 与 #690),只改第一条会让同一文件里并存两种长度
|
|
95
|
+
// 单位声明——而坐标是按同一 scale 换算过的。
|
|
96
|
+
out = out.replace(/SI_UNIT\s*\(\s*\.MILLI\.\s*,\s*\.METRE\.\s*\)/g, `CONVERSION_BASED_UNIT('${name}',#${convId})`);
|
|
88
97
|
// 在 DATA 段结束前(ENDSEC;)插入新实体。
|
|
89
98
|
const insert = [
|
|
90
99
|
`#${convId}=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(${inchFactor}),#${lenId});`,
|
|
@@ -282,40 +291,65 @@ function build3mfModelXml(entries, unit, scale, printConfig, fileMeta) {
|
|
|
282
291
|
const objs = [];
|
|
283
292
|
const mats = [];
|
|
284
293
|
const items = [];
|
|
294
|
+
let nextObjId = 1;
|
|
295
|
+
// 逐三角形材质分组的 basematerials id 从「顶层条目数 + 1」起,与 object id(1..N)
|
|
296
|
+
// 错开(P3:resources 内 id 唯一)。对象级颜色 basematerials 复用其 object id。
|
|
285
297
|
let nextMatId = entries.length + 1;
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
tris
|
|
298
|
+
// 递归发射一个节点为 <object>(叶带 mesh、容器带 <components>),返回其 object id。
|
|
299
|
+
function emitObject(e) {
|
|
300
|
+
// P8 契约(库面):无 mesh 且无子节点的条目 → 静默跳过(不发射 <object>/<item>),
|
|
301
|
+
// 与 op 层「无三角载荷即 E_EXPORT_3MF_EMPTY 显式报错」形成双值防护。显式容器
|
|
302
|
+
// (children 已声明,即便为空 [])仍发射,以便装配层级(含空装配)可写。
|
|
303
|
+
const isContainer = e.children !== undefined;
|
|
304
|
+
if (!e.mesh && !isContainer)
|
|
305
|
+
return undefined;
|
|
306
|
+
const id = nextObjId++;
|
|
307
|
+
let meshXml = '';
|
|
308
|
+
if (e.mesh) {
|
|
309
|
+
const pos = scalePositions(e.mesh.positions, scale);
|
|
310
|
+
const verts = [];
|
|
311
|
+
for (let v = 0; v < pos.length; v += 3) {
|
|
312
|
+
verts.push(`<vertex x="${pos[v]}" y="${pos[v + 1]}" z="${pos[v + 2]}"/>`);
|
|
313
|
+
}
|
|
314
|
+
// P4(3MF Core 逐三角形材质):materialGroups(appearance.color)→ 每组
|
|
315
|
+
// 一个独立 basematerials 资源(id 与对象 id 错开,P3 曾与对象共用 id、
|
|
316
|
+
// 违反 resources 内 id 唯一),分组三角形用 `<triangle pid p1..p3>` 引用。
|
|
317
|
+
const groupPids = [];
|
|
318
|
+
const groups = (e.materialGroups ?? []).filter((g) => g.appearance?.color);
|
|
319
|
+
for (const g of groups) {
|
|
320
|
+
groupPids.push(nextMatId);
|
|
321
|
+
mats.push(`<basematerials id="${nextMatId}"><base name="${xmlAttr(`${e.name ?? `part${id}`}_g${groupPids.length}`)}" displaycolor="${hexColor(g.appearance.color)}"/></basematerials>`);
|
|
322
|
+
nextMatId++;
|
|
323
|
+
}
|
|
324
|
+
const tris = [];
|
|
325
|
+
const triCount = e.mesh.indices.length / 3;
|
|
326
|
+
let gi = 0;
|
|
327
|
+
for (let t = 0; t < triCount; t++) {
|
|
328
|
+
while (gi < groups.length && t >= groups[gi].start + groups[gi].count)
|
|
329
|
+
gi++;
|
|
330
|
+
const inGroup = gi < groups.length && t >= groups[gi].start;
|
|
331
|
+
const matAttr = inGroup ? ` pid="${groupPids[gi]}" p1="0" p2="0" p3="0"` : '';
|
|
332
|
+
tris.push(`<triangle v1="${e.mesh.indices[t * 3]}" v2="${e.mesh.indices[t * 3 + 1]}" v3="${e.mesh.indices[t * 3 + 2]}"${matAttr}/>`);
|
|
333
|
+
}
|
|
334
|
+
meshXml = `<mesh><vertices>${verts.join('')}</vertices><triangles>${tris.join('')}</triangles></mesh>`;
|
|
313
335
|
}
|
|
314
|
-
//
|
|
315
|
-
|
|
316
|
-
// parseThreemf 只读 resources)不识别,导入→导出→导入颜色丢失。
|
|
336
|
+
// 对象级颜色 basematerials:复用 object id(既有契约,解析器按 id 取首个资源)。
|
|
337
|
+
let pidAttr = '';
|
|
317
338
|
if (e.color) {
|
|
318
|
-
mats.push(`<basematerials id="${
|
|
339
|
+
mats.push(`<basematerials id="${id}"><base name="${xmlAttr(e.name ?? 'p' + id)}" displaycolor="${hexColor(e.color)}"/></basematerials>`);
|
|
340
|
+
pidAttr = ` pid="${id}" pindex="0"`;
|
|
341
|
+
}
|
|
342
|
+
// 装配层级 → <components>(子节点递归;<component transform> 写相对父位姿)。
|
|
343
|
+
let compXml = '';
|
|
344
|
+
if (e.children && e.children.length > 0) {
|
|
345
|
+
const comps = e.children.map((child) => {
|
|
346
|
+
const cid = emitObject(child);
|
|
347
|
+
if (cid === undefined)
|
|
348
|
+
return '';
|
|
349
|
+
const tf = child.transform ? ` transform="${matrix12ToAttr(transformToMatrix12(child.transform))}"` : '';
|
|
350
|
+
return `<component objectid="${cid}"${tf}/>`;
|
|
351
|
+
}).filter((s) => s !== '');
|
|
352
|
+
compXml = comps.length > 0 ? `<components>${comps.join('')}</components>` : '';
|
|
319
353
|
}
|
|
320
354
|
// 零件级元数据(设计文档 2026-10-05-meta §6.1):partnumber 属性 +
|
|
321
355
|
// `<metadatagroup><metadata>`(3MF 自定义标签须带命名空间前缀;faijs
|
|
@@ -343,9 +377,17 @@ function build3mfModelXml(entries, unit, scale, printConfig, fileMeta) {
|
|
|
343
377
|
}
|
|
344
378
|
}
|
|
345
379
|
const metadatagroup = metadatas.length > 0 ? `<metadatagroup>${metadatas.join('')}</metadatagroup>` : '';
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
380
|
+
const nameAttr = xmlAttr(e.name ?? `part${id}`);
|
|
381
|
+
objs.push(`<object id="${id}" type="model" name="${nameAttr}"${partnumberAttr}${pidAttr}>${metadatagroup}${meshXml}${compXml}</object>`);
|
|
382
|
+
return id;
|
|
383
|
+
}
|
|
384
|
+
for (const e of entries) {
|
|
385
|
+
const id = emitObject(e);
|
|
386
|
+
if (id === undefined)
|
|
387
|
+
continue;
|
|
388
|
+
const tf = e.transform ? ` transform="${matrix12ToAttr(transformToMatrix12(e.transform))}"` : '';
|
|
389
|
+
items.push(`<item objectid="${id}"${tf}/>`);
|
|
390
|
+
}
|
|
349
391
|
// 整体级元数据(`<model>` 直接子级 `<metadata>`):well-known 名经映射写标准
|
|
350
392
|
// 3MF 名,vendor 名写 `faijs:` 前缀。排在 `<resources>` 之前(3MF Core)。
|
|
351
393
|
const modelMetas = [];
|
|
@@ -381,6 +423,51 @@ function hexColor(c) {
|
|
|
381
423
|
const h = (v) => Math.round(Math.min(1, Math.max(0, v)) * 255).toString(16).padStart(2, '0');
|
|
382
424
|
return `#${h(c[0])}${h(c[1])}${h(c[2])}`;
|
|
383
425
|
}
|
|
426
|
+
export { transformToMatrix12 } from './transform12.js';
|
|
427
|
+
import { scaleTransform, transformToMatrix12 } from './transform12.js';
|
|
428
|
+
/**
|
|
429
|
+
* ExportEntry → StepExportEntry 的递归映射器(step 分支同步/异步共用,单一真源)。
|
|
430
|
+
* 容器只传名/色与子节点(compound 几何 == 成员并集,写出会重复);位姿平移按
|
|
431
|
+
* 单位刻度换算,与几何缩放同一 scale 因子(「声明单位 == 坐标刻度」对组件位姿
|
|
432
|
+
* 同样成立)。solid 经 kernel.scale 的 owned copy 缩放,入 ownedHandles 由调用方
|
|
433
|
+
* 统一释放。
|
|
434
|
+
*/
|
|
435
|
+
function makeStepEntryMapper(kernel, scale, ownedHandles) {
|
|
436
|
+
const toStepEntry = (e) => {
|
|
437
|
+
const head = {
|
|
438
|
+
...(e.name ? { name: e.name } : {}),
|
|
439
|
+
...(e.color ? { color: [...e.color] } : {}),
|
|
440
|
+
};
|
|
441
|
+
const transform = e.transform ? scaleTransform(e.transform, scale) : undefined;
|
|
442
|
+
if (e.children && e.children.length > 0) {
|
|
443
|
+
return {
|
|
444
|
+
...head,
|
|
445
|
+
...(transform ? { transform } : {}),
|
|
446
|
+
children: e.children.map(toStepEntry),
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
if (e.solid) {
|
|
450
|
+
if (scale === 1)
|
|
451
|
+
return { solid: e.solid, ...head };
|
|
452
|
+
const scaled = kernel.scale(e.solid, { x: 0, y: 0, z: 0 }, scale);
|
|
453
|
+
ownedHandles.push(scaled);
|
|
454
|
+
return { solid: scaled, ...head };
|
|
455
|
+
}
|
|
456
|
+
return {
|
|
457
|
+
...head,
|
|
458
|
+
...(e.mesh ? { mesh: { positions: scalePositions(e.mesh.positions, scale), indices: e.mesh.indices } } : {}),
|
|
459
|
+
};
|
|
460
|
+
};
|
|
461
|
+
return toStepEntry;
|
|
462
|
+
}
|
|
463
|
+
function fmtNum(v) {
|
|
464
|
+
if (Number.isInteger(v))
|
|
465
|
+
return String(v);
|
|
466
|
+
return String(Math.round(v * 1e6) / 1e6);
|
|
467
|
+
}
|
|
468
|
+
function matrix12ToAttr(m) {
|
|
469
|
+
return m.map(fmtNum).join(' ');
|
|
470
|
+
}
|
|
384
471
|
/**
|
|
385
472
|
* Synchronous twin of {@link exportModel} for hosts already holding a live
|
|
386
473
|
* kernel (CLI, in-process consumers). Same invariants: declared unit ==
|
|
@@ -400,7 +487,29 @@ export function exportModelSync(entries, format, opts) {
|
|
|
400
487
|
unit = 'mm';
|
|
401
488
|
const scale = 1 / UNIT_SCALE[unit];
|
|
402
489
|
if (format === 'stl') {
|
|
403
|
-
|
|
490
|
+
// 步骤 5(方案 §2.1 / §4.3 L1-5):装配展平 + 顶点烘焙。递归把 children 拍平成叶,
|
|
491
|
+
// 每个叶的世界变换 = 父世界变换 ∘ 本节点局部 transform(row-major 3×4,平移在末列)。
|
|
492
|
+
// 先在世界空间烘焙 transform,再按单位换算缩放坐标(缩放同时作用于平移分量,坐标与声明成对)。
|
|
493
|
+
const flatten = (list, accTf) => {
|
|
494
|
+
const out = [];
|
|
495
|
+
for (const e of list) {
|
|
496
|
+
const tf = e.transform ? transformToMatrix12(e.transform) : null;
|
|
497
|
+
const world = tf && accTf ? composeMatrix12(accTf, tf) : tf ?? accTf ?? null;
|
|
498
|
+
if (e.children && e.children.length > 0) {
|
|
499
|
+
out.push(...flatten(e.children, world));
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
if (!e.mesh)
|
|
503
|
+
continue;
|
|
504
|
+
let pos = e.mesh.positions;
|
|
505
|
+
if (world)
|
|
506
|
+
pos = bakeMatrix12ToPositions(pos, world);
|
|
507
|
+
pos = scalePositions(pos, scale);
|
|
508
|
+
out.push({ pos, idx: e.mesh.indices });
|
|
509
|
+
}
|
|
510
|
+
return out;
|
|
511
|
+
};
|
|
512
|
+
const bufs = flatten(entries, null);
|
|
404
513
|
if (bufs.length === 0)
|
|
405
514
|
throw new Error('[export/stl] no mesh entries');
|
|
406
515
|
if (bufs.length === 1)
|
|
@@ -421,22 +530,18 @@ export function exportModelSync(entries, format, opts) {
|
|
|
421
530
|
return buildStlBufferFromMesh(mergedPos, mergedIdx);
|
|
422
531
|
}
|
|
423
532
|
if (format === 'step') {
|
|
533
|
+
// 步骤 6(方案 §2.3 / P1):STEP 装配层级走 XCAF,仅 occt 具备;非 occt 引擎在
|
|
534
|
+
// 触碰任何句柄之前报 E_BREP_UNSUPPORTED(带当前引擎名),不落入 getBrepApi 的
|
|
535
|
+
// 未初始化异常,也不把 brepkit 句柄交给 occt 内核(句柄不得跨引擎传递)。
|
|
536
|
+
const engineId = getBackends().config.brepEngineId;
|
|
537
|
+
if (engineId !== 'occt') {
|
|
538
|
+
throw new BrepUnsupportedError(`E_BREP_UNSUPPORTED: op 'exportModel:step' requires engine occt (current=${engineId ?? '<none>'})`);
|
|
539
|
+
}
|
|
424
540
|
const kernel = getBrepApi();
|
|
425
541
|
const ownedHandles = [];
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
return { solid: e.solid, ...(e.name ? { name: e.name } : {}), ...(e.color ? { color: [...e.color] } : {}) };
|
|
430
|
-
const scaled = kernel.scale(e.solid, { x: 0, y: 0, z: 0 }, scale);
|
|
431
|
-
ownedHandles.push(scaled);
|
|
432
|
-
return { solid: scaled, ...(e.name ? { name: e.name } : {}), ...(e.color ? { color: [...e.color] } : {}) };
|
|
433
|
-
}
|
|
434
|
-
return {
|
|
435
|
-
...(e.mesh ? { mesh: { positions: scalePositions(e.mesh.positions, scale), indices: e.mesh.indices } } : {}),
|
|
436
|
-
...(e.name ? { name: e.name } : {}),
|
|
437
|
-
...(e.color ? { color: [...e.color] } : {}),
|
|
438
|
-
};
|
|
439
|
-
});
|
|
542
|
+
// 层级映射(步骤 7 / P3):ExportEntry 树 → StepExportEntry 树(映射器见
|
|
543
|
+
// makeStepEntryMapper——同步/异步分支共用,单一真源)。
|
|
544
|
+
const stepEntries = entries.map(makeStepEntryMapper(kernel, scale, ownedHandles));
|
|
440
545
|
const buffer = exportStepFromSolids(kernel, stepEntries);
|
|
441
546
|
for (const h of ownedHandles) {
|
|
442
547
|
try {
|
|
@@ -512,25 +617,18 @@ export async function exportModel(entries, format, opts) {
|
|
|
512
617
|
return buildStlBufferFromMesh(mergedPos, mergedIdx);
|
|
513
618
|
}
|
|
514
619
|
if (format === 'step') {
|
|
620
|
+
// 步骤 6(方案 §2.3 / P1):同同步分支,取内核前先断言 occt 引擎身份。
|
|
621
|
+
const engineId = getBackends().config.brepEngineId;
|
|
622
|
+
if (engineId !== 'occt') {
|
|
623
|
+
throw new BrepUnsupportedError(`E_BREP_UNSUPPORTED: op 'exportModel:step' requires engine occt (current=${engineId ?? '<none>'})`);
|
|
624
|
+
}
|
|
515
625
|
// 同一 scale 变量喂两类条目(§10.3 规则 7,修 E4):mesh 缩放 positions,
|
|
516
626
|
// solid 用 owned copy 做 kernel.scale —— 不释放调用方缓存里的原句柄。
|
|
517
627
|
// 先过门禁再取内核(同同步分支:拒绝理由与引擎装配状态无关)。
|
|
518
628
|
const kernel = (await import('../handle-bridge.js')).getBrepApi();
|
|
519
629
|
const ownedHandles = [];
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
if (scale === 1)
|
|
523
|
-
return { solid: e.solid, ...(e.name ? { name: e.name } : {}), ...(e.color ? { color: [...e.color] } : {}) };
|
|
524
|
-
const scaled = kernel.scale(e.solid, { x: 0, y: 0, z: 0 }, scale);
|
|
525
|
-
ownedHandles.push(scaled);
|
|
526
|
-
return { solid: scaled, ...(e.name ? { name: e.name } : {}), ...(e.color ? { color: [...e.color] } : {}) };
|
|
527
|
-
}
|
|
528
|
-
return {
|
|
529
|
-
...(e.mesh ? { mesh: { positions: scalePositions(e.mesh.positions, scale), indices: e.mesh.indices } } : {}),
|
|
530
|
-
...(e.name ? { name: e.name } : {}),
|
|
531
|
-
...(e.color ? { color: [...e.color] } : {}),
|
|
532
|
-
};
|
|
533
|
-
});
|
|
630
|
+
// 同步分支同一映射器(单一真源)。
|
|
631
|
+
const stepEntries = entries.map(makeStepEntryMapper(kernel, scale, ownedHandles));
|
|
534
632
|
const buffer = exportStepFromSolids(kernel, stepEntries);
|
|
535
633
|
for (const h of ownedHandles) {
|
|
536
634
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export-model.js","sourceRoot":"","sources":["../../../src/brep/export/export-model.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * exportModel — 统一导出入口(unit-system §10.6 二 / R11 / 裁决 J)\n *\n * 单一真源:坐标单位换算与文件单位声明由**同一次换算**产出(§10.3 规则 3),\n * 声明与坐标必须同源。CLI(writeOutput)与宿主(3d_editor)共用本入口。\n *\n * 格式分派(§10.6 表):\n * - stl:坐标缩放到 unit 刻度,无声明(格式不支持)。\n * - step:预缩放 + 文本层只改写单位实体(§10.3 规则 3a;OCCT 恒写\n * SI_UNIT(.MILLI.,.METRE.),坐标预先缩放到目标刻度后声明必须跟上)。\n * - 3mf:坐标缩放到 unit 刻度 + <model unit> 与坐标同源;yard 不在 3MF\n * 枚举 → 成对回落到 mm(§10.3 规则 2)。\n *\n * 红线(§10.3 3a):绝不文本级改坐标 — 坐标只在几何层缩放,文本层只碰单位实体。\n */\n\nimport { buildStlBufferFromMesh } from './stl'\nimport { writeZipEntries } from '../../io/zip'\nimport { UNIT_SCALE, type UnitName } from '../../units'\nimport type { BrepHandle } from '../engine/types'\nimport type { BrepEngineApi } from '../engine/primitives'\nimport { getBrepApi } from '../handle-bridge'\nimport { exportStepFromSolids, type StepExportEntry } from './step'\nimport { detectStepUnit, STEP_UNIT_SCAN_PREFIX } from '../../mesh/io'\nimport type { PbrAppearance } from '../../api/appearance'\nimport type { ShapeMeta, FileMeta } from '../../api/meta'\n\n/** 导出条目:一个 part 的几何来源。精确 BREP 与三角网格二选一,solid 优先。 */\nexport interface ExportEntry {\n /** 精确 BREP 句柄(来自 brep 链,导出 ADVANCED_FACE)。 */\n solid?: BrepHandle\n /** 三角网格(基准单位刻度;调用方只做世界变换烘焙,不做单位缩放)。 */\n mesh?: { positions: Float32Array; indices: Uint32Array }\n /** 实体名(写 STEP PRODUCT 名 / 3MF <object name>)。 */\n name?: string\n /** sRGB 0..1 颜色(STEP 走 XCAF COLOUR_RGB,3MF 走 basematerials)。 */\n color?: readonly [number, number, number]\n /**\n * 逐三角形材质分组(P4,3MF 走多 basematerials + `<triangle pid p1..p3>`):\n * start/count 为**三角形索引**区间,appearance.color 为该组基色。\n */\n materialGroups?: Array<{ start: number; count: number; appearance: PbrAppearance }>\n /**\n * 零件级说明性元数据(设计文档 2026-10-05-meta §6.1):写 3MF\n * `<object name/partnumber>` + `<metadatagroup>`;STEP 走 PRODUCT name(既有)。\n */\n meta?: ShapeMeta\n}\n\n/** Output formats supported by the unified {@link exportModel} entry. */\nexport type ExportFormat = 'stl' | 'step' | '3mf'\n\n/**\n * Options controlling {@link exportModel}/{@link exportModelSync} output\n * (unit-system §10.3): the declared target unit and optional 3MF print config.\n */\nexport interface ExportOptions {\n /**\n * 目标长度单位。缺省 'mm'。语义是「文件里声明的单位」——\n * 实现负责把坐标换算到该单位刻度并与声明成对写出(§10.3)。\n */\n unit?: UnitName\n /** 3MF 打印配置(可选,原样进 model 层)。 */\n printConfig?: unknown\n /** 整体级元数据(设计文档 2026-10-05-meta §6.1):3MF 写 `<model>` 级 `<metadata>`。 */\n fileMeta?: FileMeta\n}\n\n/** UnitName → 3MF <model unit> 枚举全名(唯一真源;yard 无对应值)。 */\nexport const UNIT_NAME_TO_3MF: Partial<Record<UnitName, 'micron' | 'millimeter' | 'centimeter' | 'inch' | 'foot' | 'meter'>> = {\n mm: 'millimeter',\n cm: 'centimeter',\n m: 'meter',\n micron: 'micron',\n inch: 'inch',\n foot: 'foot',\n // yard 无 3MF 枚举值 — 调用方必须先成对回落到 mm(§10.3 规则 2)。\n}\n\n/** 缩放 Float32 positions 到目标单位刻度(基准值 ÷ unitScale(unit))。 */\nfunction scalePositions(positions: Float32Array, scale: number): Float32Array {\n if (scale === 1) return positions\n const out = new Float32Array(positions.length)\n for (let i = 0; i < positions.length; i++) out[i] = positions[i] * scale\n return out\n}\n\n/** STEP 单位声明改写:SI_UNIT(.MILLI.,.METRE.) → 目标单位实体(只碰单位实体,红线)。 */\nfunction rewriteStepUnitEntities(stepText: string, unit: UnitName): string {\n // mm 是 OCCT 的原生写出形态,无需改写。\n if (unit === 'mm') return stepText\n\n // SI 面积/体积单位实体的前缀同样要跟着换(LENGTH/AREA/VOLUME 挂同一前缀链),\n // 但坐标已缩放 → 只需把 LENGTH 链上的前缀换掉;面积/体积单位在 STEP 里由\n // SI_UNIT 前缀 + 幂次表达,XCAF 写出的实体形态是 SI_UNIT(.MILLI.,.METRE.)\n // 挂在长度、平方与立方三条依赖链上。为保守起见只改写显式 LENGTH_UNIT 链上的\n // SI_UNIT —— 具体做法:全局替换 SI_UNIT 前缀(同一文件里坐标相关单位恒为\n // 长度链;角度 SI_UNIT(.RADIAN.) 不含 METRE 不会被命中)。\n let out = stepText\n\n if (unit === 'cm' || unit === 'm' || unit === 'micron') {\n const prefix = unit === 'cm' ? '.CENTI.' : unit === 'm' ? '$' : '.MICRO.'\n // OCCT 写出恒为 SI_UNIT(.MILLI.,.METRE.)(实测);$ 前缀形态(无前缀=米)\n // 在 OCCT 输出中不会出现,但容错处理(若上游将来变化)。\n out = out.replace(/SI_UNIT\\s*\\(\\s*\\.MILLI\\.\\s*,\\s*\\.METRE\\.\\s*\\)/g,\n prefix === '$' ? 'SI_UNIT($,.METRE.)' : `SI_UNIT(${prefix},.METRE.)`)\n return out\n }\n\n // inch / foot:CONVERSION_BASED_UNIT 形态。需要注入换算因子实体并替换\n // LENGTH_UNIT 依赖。最简形态:把 SI_UNIT(.MILLI.,.METRE.) 替换为\n // CONVERSION_BASED_UNIT('INCH', #factor),并附加 MEASURE_WITH_UNIT 实体。\n // 实体编号:取文件内最大 #n + 1、+2(附加实体挂在文件尾部 DATA 段内合法)。\n const inchFactor = unit === 'inch' ? 25.4 : 304.8\n const name = unit === 'inch' ? 'INCH' : 'FOOT'\n\n // 1) 收集现有最大实体编号\n let maxId = 0\n for (const m of out.matchAll(/#(\\d+)\\s*=/g)) {\n const id = Number(m[1])\n if (id > maxId) maxId = id\n }\n const lenId = maxId + 1\n const convId = maxId + 2\n\n // 2) 找到 LENGTH_UNIT() 里挂 SI_UNIT 的实体行,替换为 CONVERSION_BASED_UNIT\n // 并把 SI_UNIT 挂到 LENGTH_MEASURE 上。OCCT 输出形态(实测):\n // #n=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.));\n const siLine = out.match(/#(\\d+)\\s*=\\s*\\([^)]*SI_UNIT\\s*\\(\\s*\\.MILLI\\.\\s*,\\s*\\.METRE\\.\\s*\\)[^)]*\\)\\s*;/)\n if (!siLine) {\n throw new Error(`[export/step] no SI_UNIT(.MILLI.,.METRE.) entity found; cannot rewrite declaration to ${name}`)\n }\n\n // 3) 替换原 SI_UNIT 实体为 CONVERSION_BASED_UNIT,插入换算因子与基准米实体:\n // #si=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.));\n // → #si=(LENGTH_UNIT()NAMED_UNIT(*)CONVERSION_BASED_UNIT('INCH',#conv));\n // #conv=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(25.4),#len);\n // #len=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT($,.METRE.));\n out = out.replace(siLine[0], siLine[0].replace(/SI_UNIT\\s*\\(\\s*\\.MILLI\\.\\s*,\\s*\\.METRE\\.\\s*\\)/, `CONVERSION_BASED_UNIT('${name}',#${convId})`))\n // 在 DATA 段结束前(ENDSEC;)插入新实体。\n const insert = [\n `#${convId}=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(${inchFactor}),#${lenId});`,\n `#${lenId}=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT($,.METRE.));`,\n ].join('\\n')\n out = out.replace(/ENDSEC\\s*;/, `${insert}\\nENDSEC;`)\n return out\n}\n\n/**\n * STEP 文件级元数据 → P21 header 重写(`FILE_NAME`/`FILE_DESCRIPTION`)。\n *\n * 设计文档 2026-10-05-meta §6.2 第 6 步:`exportModel` 已有 SI_UNIT 声明重写的\n * 先例——同样只对 header 里 FILE_NAME(...)/FILE_DESCRIPTION(...) 行做文本替换,\n * 绝不碰 DATA 段几何实体(红线 §10.3 3a:文本层只改声明/元数据,坐标不动)。\n *\n * FILE_NAME(name, time_stamp, author, organization, preprocessor_version, ...)\n * FILE_DESCRIPTION(description_list, implementation_level)\n * 映射(§3.3):title→name, creationDate→time_stamp, author|designer→author 列表,\n * organization→organization, application→preprocessor, description→description。\n * 无对应的字段(copyright/licenseTerms/rating/modificationDate)**不写**(§5.3 头:\n * STEP 无标准位置,不发明)。\n *\n * 宽容失败:找不到 FILE_NAME/FILE_DESCRIPTION 行则留空(P21 头由内核写出,形态\n * 已知为 `FILE_DESCRIPTION(('Open CASCADE Model'),'2;1');` 一行,但在字符串内)。\n *\n * @param stepText 内核产出的 STEP 全文(ISO-10303-21)。\n * @param fileMeta 目标文件级元数据。\n * @returns 改写后的 STEP 文本。\n */\nexport function rewriteFileMetaHeader(stepText: string, fileMeta: FileMeta): string {\n let out = stepText\n\n const title = fileMeta.title && fileMeta.title.length > 0 ? fileMeta.title : undefined\n const ts = fileMeta.creationDate && fileMeta.creationDate.length > 0\n ? fileMeta.creationDate\n : (fileMeta.modificationDate && fileMeta.modificationDate.length > 0 ? fileMeta.modificationDate : undefined)\n const authorList = fileMeta.author && fileMeta.author.length > 0 ? [fileMeta.author] : []\n const org = fileMeta.organization && fileMeta.organization.length > 0 ? fileMeta.organization : undefined\n const preproc = fileMeta.application && fileMeta.application.length > 0 ? fileMeta.application : undefined\n const designer = fileMeta.designer && fileMeta.designer.length > 0 ? fileMeta.designer : undefined\n const desc = fileMeta.description && fileMeta.description.length > 0 ? fileMeta.description : undefined\n\n // 1) FILE_NAME(用平衡括号/引号感知的枚举,整块替换 —— 逐参安全,不依赖行结构)。\n const fn = matchEntity(out, 'FILE_NAME')\n if (fn) {\n const params = splitP21Params(fn.inner)\n const next: string[] = []\n if (title !== undefined || ts !== undefined || authorList.length > 0 || org !== undefined || preproc !== undefined || designer !== undefined) {\n next.push(stepStr(title ?? paramStr(params[0]) ?? 'STEP File'))\n next.push(stepStr(ts ?? paramStr(params[1]) ?? ''))\n next.push(authorList.length > 0 ? p21List(authorList) : (params[2] ?? \"('')\"))\n next.push(org !== undefined ? p21List([org]) : (params[3] ?? \"('')\"))\n // 保留内核写出的后续参数原样(preprocessor_version / originating_system /\n // authorisation)——FILE_NAME 可带 6..7 参,不丢既有值。\n next.push(preproc !== undefined ? stepStr(preproc) : (params[4] ?? ''))\n next.push(designer !== undefined ? stepStr(designer) : (params[5] ?? ''))\n for (let i = 6; i < params.length; i++) next.push(params[i])\n // 末尾空参保留则拼 ',' 会使整行以 ',' 结尾 → 过滤空的尾部。\n while (next.length > 0 && next[next.length - 1] === '') next.pop()\n out = splice(out, fn.start, fn.end, `FILE_NAME(${next.join(',')})`)\n }\n }\n\n // 2) FILE_DESCRIPTION(description_list, implementation_level):替换描述列表。\n const fd = matchEntity(out, 'FILE_DESCRIPTION')\n if (fd) {\n const params = splitP21Params(fd.inner)\n if (desc !== undefined && params.length > 0) {\n const impl = params[params.length - 1]\n out = splice(out, fd.start, fd.end, `FILE_DESCRIPTION((${stepStr(desc)}),${impl})`)\n }\n }\n\n return out\n}\n\n/** [start, end) 区间替换为 replacement(end 为闭合括号后一位,仍保留其后的 `;`)。 */\nfunction splice(s: string, start: number, end: number, replacement: string): string {\n return s.slice(0, start) + replacement + s.slice(end)\n}\n\n/** FileMeta 是否含可映射到 STEP header 的字段(避免对无 header 字段的 fileMeta 做无谓解码重写)。 */\nfunction fileMetaHasHeaderFields(f: FileMeta): boolean {\n return !!(f.title || f.description || f.designer || f.author || f.organization || f.application\n || f.creationDate || f.modificationDate)\n}\n\n/**\n * 在文本中定位 `NAME(` … 匹配的 `)` (引号忽略、内层括号计入)并返回\n * `{ start, end, inner }`;找不到返回 null。start/end 是 `NAME(` 起始/闭合 `)` 之后\n * 一位的偏移,供调用方做字符串拼接替换(不做正则整行匹配——行内可含 `;` 等字符)。\n */\nfunction matchEntity(text: string, name: string): { start: number; end: number; inner: string } | null {\n const re = new RegExp(`${name}\\\\s*\\\\(`)\n const m = re.exec(text)\n if (!m) return null\n const start = m.index\n const head = m.index + m[0].length\n let depth = 1\n let i = head\n for (; i < text.length && depth > 0; i++) {\n const c = text[i]\n if (c === `'`) {\n // 跳过字符串字面量(含 ISO10303-21 双引号转义)\n i++\n while (i < text.length) {\n if (text[i] === `'` && text[i + 1] === `'`) { i += 2; continue }\n if (text[i] === `'`) break\n i++\n }\n } else if (c === '(') depth++\n else if (c === ')') depth--\n }\n return { start, end: i - 1, inner: text.slice(head, i - 1) }\n}\n\n/** 把一层参数(逗号分隔,忽略括号与字符串内的逗号)拆分(trim,原样保留字面量)。 */\nfunction splitP21Params(inner: string): string[] {\n const out: string[] = []\n let cur = ''\n let depth = 0\n for (let i = 0; i < inner.length; i++) {\n const c = inner[i]\n if (c === `'`) {\n // 字符串字面量:整体吸收(含 ISO10303-21 转义 ''),不拆其内逗号/括号。\n const start = i\n i++\n while (i < inner.length) {\n if (inner[i] === `'` && inner[i + 1] === `'`) { i += 2; continue }\n if (inner[i] === `'`) { i++; break }\n i++\n }\n cur += inner.slice(start, i)\n i-- // for 循环还会 +1,落到字符串结束引号后一个字符\n continue\n }\n if (c === '(') depth++\n else if (c === ')') depth--\n if (c === ',' && depth === 0) { out.push(cur.trim()); cur = '' }\n else cur += c\n }\n if (cur.trim() !== '') out.push(cur.trim())\n return out\n}\n\n/** 单个 P21 字符串字面量的未转义内容(剥离包裹引号与 '' 转义)。 */\nfunction paramStr(p: string | undefined): string | undefined {\n if (p === undefined) return undefined\n const m = /^'((?:[^']|'')*)'$/.exec(p.trim())\n return m ? m[1].replace(/''/g, `'`) : undefined\n}\n\n/** 单个 P21 字符串字面量(已转义)。 */\nfunction stepStr(v: string): string {\n return `'${v.replace(/'/g, \"''\")}'`\n}\n\n/** P21 列表字面量:(['a','b']) → `('a','b')`。 */\nfunction p21List(items: string[]): string {\n return `(${items.map(stepStr).join(',')})`\n}\n\n/** 3MF写出:最小 ZIP 容器(deflate),落 3D/3dmodel.model + [Content_Types].xml + _rels。 */\nfunction build3mfBuffer(modelXml: string): ArrayBuffer {\n const contentTypes = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"model\" ContentType=\"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\"/></Types>`\n const rels = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Target=\"/3D/3dmodel.model\" Id=\"rel0\" Type=\"http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel\"/></Relationships>`\n\n const zipped = writeZipEntries({\n '[Content_Types].xml': new TextEncoder().encode(contentTypes),\n '_rels/.rels': new TextEncoder().encode(rels),\n '3D/3dmodel.model': new TextEncoder().encode(modelXml),\n })\n return zipped.buffer.slice(zipped.byteOffset, zipped.byteOffset + zipped.byteLength) as ArrayBuffer\n}\n\n/** 组 3MF <model> XML:单位声明与坐标由同一 scale 变量产出(同源,§10.3 规则 3)。 */\nfunction build3mfModelXml(entries: ExportEntry[], unit: UnitName, scale: number, printConfig?: unknown, fileMeta?: FileMeta): string {\n const unitAttr = UNIT_NAME_TO_3MF[unit]\n if (!unitAttr) {\n // 调用方(exportModel)保证 unit 已成对回落;直接到这里 = 内部错误。\n throw new Error(`[export/3mf] unit ${unit} has no 3MF enum value`)\n }\n const objs: string[] = []\n const mats: string[] = []\n const items: string[] = []\n let nextMatId = entries.length + 1\n entries.forEach((e, i) => {\n if (!e.mesh) return\n const pos = scalePositions(e.mesh.positions, scale)\n const verts: string[] = []\n for (let v = 0; v < pos.length; v += 3) {\n verts.push(`<vertex x=\"${pos[v]}\" y=\"${pos[v + 1]}\" z=\"${pos[v + 2]}\"/>`)\n }\n // P4(3MF Core 逐三角形材质):materialGroups(appearance.color)→ 每组\n // 一个独立 basematerials 资源(id 与对象 id 错开,P3 曾与对象共用 id、\n // 违反 resources 内 id 唯一),分组三角形用 `<triangle pid p1..p3>` 引用。\n const groupPids: number[] = []\n const groups = (e.materialGroups ?? []).filter((g) => g.appearance?.color)\n for (const g of groups) {\n groupPids.push(nextMatId)\n mats.push(\n `<basematerials id=\"${nextMatId}\"><base name=\"${xmlAttr(`${e.name ?? `part${i + 1}`}_g${groupPids.length}`)}\" displaycolor=\"${hexColor(g.appearance.color!)}\"/></basematerials>`,\n )\n nextMatId++\n }\n const tris: string[] = []\n const triCount = e.mesh.indices.length / 3\n let gi = 0\n for (let t = 0; t < triCount; t++) {\n while (gi < groups.length && t >= groups[gi].start + groups[gi].count) gi++\n const inGroup = gi < groups.length && t >= groups[gi].start\n const matAttr = inGroup ? ` pid=\"${groupPids[gi]}\" p1=\"0\" p2=\"0\" p3=\"0\"` : ''\n tris.push(\n `<triangle v1=\"${e.mesh.indices[t * 3]}\" v2=\"${e.mesh.indices[t * 3 + 1]}\" v3=\"${e.mesh.indices[t * 3 + 2]}\"${matAttr}/>`,\n )\n }\n // P3(v2 §8 3MF 行,Core 规范):basematerials 必须声明在 <resources>,\n // object 用 pid/pindex 引用——此前内联在 <object> 内的写法解析器(\n // parseThreemf 只读 resources)不识别,导入→导出→导入颜色丢失。\n if (e.color) {\n mats.push(`<basematerials id=\"${i + 1}\"><base name=\"${xmlAttr(e.name ?? 'p' + i)}\" displaycolor=\"${hexColor(e.color)}\"/></basematerials>`)\n }\n // 零件级元数据(设计文档 2026-10-05-meta §6.1):partnumber 属性 +\n // `<metadatagroup><metadata>`(3MF 自定义标签须带命名空间前缀;faijs\n // 无前缀键一律补 `faijs:` 前缀,跨工具链兼容)。description 3MF 无对象级\n // 标准位 → 写 `faijs:description`(规范允许 vendor 前缀名)。\n const partnumberAttr = e.meta?.partNumber ? ` partnumber=\"${xmlAttr(e.meta.partNumber)}\"` : ''\n const metadatas: string[] = []\n const meta = e.meta\n if (meta) {\n const metaPairs: Array<[string, string]> = []\n if (meta.description !== undefined && meta.description !== '') metaPairs.push(['faijs:description', meta.description])\n if (meta.metadata) {\n for (const [k, v] of Object.entries(meta.metadata)) {\n metaPairs.push([k.includes(':') ? k : `faijs:${k}`, v])\n }\n }\n // 同键不重复(首见保留)。\n const seen = new Set<string>()\n for (const [k, v] of metaPairs) {\n if (seen.has(k)) continue\n seen.add(k)\n metadatas.push(`<metadata name=\"${xmlAttr(k)}\">${xmlAttr(v)}</metadata>`)\n }\n }\n const metadatagroup = metadatas.length > 0 ? `<metadatagroup>${metadatas.join('')}</metadatagroup>` : ''\n objs.push(`<object id=\"${i + 1}\" type=\"model\" name=\"${xmlAttr(e.name ?? `part${i + 1}`)}\"${partnumberAttr}${e.color ? ` pid=\"${i + 1}\" pindex=\"0\"` : ''}>${metadatagroup}<mesh><vertices>${verts.join('')}</vertices><triangles>${tris.join('')}</triangles></mesh></object>`)\n items.push(`<item objectid=\"${i + 1}\"/>`)\n })\n // 整体级元数据(`<model>` 直接子级 `<metadata>`):well-known 名经映射写标准\n // 3MF 名,vendor 名写 `faijs:` 前缀。排在 `<resources>` 之前(3MF Core)。\n const modelMetas: string[] = []\n if (fileMeta) {\n const wellKnown: Array<[Exclude<keyof FileMeta, 'metadata'>, string]> = [\n ['title', 'Title'],\n ['designer', 'Designer'],\n ['description', 'Description'],\n ['copyright', 'Copyright'],\n ['licenseTerms', 'LicenseTerms'],\n ['rating', 'Rating'],\n ['creationDate', 'CreationDate'],\n ['modificationDate', 'ModificationDate'],\n ['application', 'Application'],\n ]\n for (const [field, name] of wellKnown) {\n if (fileMeta[field] !== undefined) modelMetas.push(`<metadata name=\"${name}\">${xmlAttr(String(fileMeta[field]))}</metadata>`)\n }\n if (fileMeta.metadata) {\n for (const [k, v] of Object.entries(fileMeta.metadata)) {\n modelMetas.push(`<metadata name=\"${xmlAttr(k.includes(':') ? k : `faijs:${k}`)}\">${xmlAttr(v)}</metadata>`)\n }\n }\n }\n const pc = printConfig ? `<metadata name=\"printConfig\">${xmlAttr(String(printConfig))}</metadata>` : ''\n return `<model unit=\"${unitAttr}\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\" xmlns:faijs=\"http://schemas.faicad.dev/3mf/2026/10\">${pc}${modelMetas.join('')}<resources>${mats.join('')}${objs.join('')}</resources><build>${items.join('')}</build></model>`\n}\n\nfunction xmlAttr(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"')\n}\n\nfunction hexColor(c: readonly [number, number, number]): string {\n const h = (v: number) => Math.round(Math.min(1, Math.max(0, v)) * 255).toString(16).padStart(2, '0')\n return `#${h(c[0])}${h(c[1])}${h(c[2])}`\n}\n\n/**\n * Synchronous twin of {@link exportModel} for hosts already holding a live\n * kernel (CLI, in-process consumers). Same invariants: declared unit ==\n * written coordinate scale. Only 'stl' / 'step' (3mf is also sync but is\n * routed through the same code path below).\n *\n * @param entries - the shapes to export (BREP solids preferred, mesh fallback).\n * @param format - output format: 'stl' | 'step' | '3mf'.\n * @param opts - optional target unit and 3MF print config.\n * @returns the serialized file bytes (ArrayBuffer).\n */\nexport function exportModelSync(\n entries: ExportEntry[],\n format: ExportFormat,\n opts?: ExportOptions,\n): ArrayBuffer {\n if (entries.length === 0) throw new Error('[export] no exportable entries')\n\n let unit = opts?.unit ?? 'mm'\n if (format === '3mf' && !UNIT_NAME_TO_3MF[unit]) unit = 'mm'\n const scale = 1 / UNIT_SCALE[unit]\n\n if (format === 'stl') {\n const bufs = entries.filter((e) => e.mesh).map((e) => ({ pos: scalePositions(e.mesh!.positions, scale), idx: e.mesh!.indices }))\n if (bufs.length === 0) throw new Error('[export/stl] no mesh entries')\n if (bufs.length === 1) return buildStlBufferFromMesh(bufs[0]!.pos, bufs[0]!.idx)\n const totalTris = bufs.reduce((n, b) => n + b.idx.length / 3, 0)\n const mergedPos = new Float32Array(bufs.reduce((n, b) => n + b.pos.length, 0))\n const mergedIdx = new Uint32Array(totalTris * 3)\n let po = 0\n let io2 = 0\n let base = 0\n for (const b of bufs) {\n mergedPos.set(b.pos, po)\n for (let i = 0; i < b.idx.length; i++) mergedIdx[io2++] = b.idx[i] + base\n base += b.pos.length / 3\n po += b.pos.length\n }\n return buildStlBufferFromMesh(mergedPos, mergedIdx)\n }\n\n if (format === 'step') {\n const kernel = getBrepApi()\n const ownedHandles: BrepHandle[] = []\n const stepEntries: StepExportEntry[] = entries.map((e) => {\n if (e.solid) {\n if (scale === 1) return { solid: e.solid, ...(e.name ? { name: e.name } : {}), ...(e.color ? { color: [...e.color] as [number, number, number] } : {}) }\n const scaled = kernel.scale(e.solid, { x: 0, y: 0, z: 0 }, scale)\n ownedHandles.push(scaled)\n return { solid: scaled, ...(e.name ? { name: e.name } : {}), ...(e.color ? { color: [...e.color] as [number, number, number] } : {}) }\n }\n return {\n ...(e.mesh ? { mesh: { positions: scalePositions(e.mesh.positions, scale), indices: e.mesh.indices } } : {}),\n ...(e.name ? { name: e.name } : {}),\n ...(e.color ? { color: [...e.color] as [number, number, number] } : {}),\n }\n })\n const buffer = exportStepFromSolids(kernel, stepEntries)\n for (const h of ownedHandles) {\n try { kernel.release(h) } catch { /* already released */ }\n }\n // 文本层只替换 header 声明/元数据(红线:绝不文本级改坐标——坐标已在几何层缩放)。\n const applyTextRewrites = (buf: ArrayBuffer): ArrayBuffer => {\n let text = new TextDecoder().decode(new Uint8Array(buf))\n if (unit !== 'mm') text = rewriteStepUnitEntities(text, unit)\n if (opts?.fileMeta && fileMetaHasHeaderFields(opts.fileMeta)) text = rewriteFileMetaHeader(text, opts.fileMeta)\n return new TextEncoder().encode(text).buffer\n }\n return applyTextRewrites(buffer)\n }\n\n if (format === '3mf') {\n return build3mfBuffer(build3mfModelXml(entries, unit, scale, opts?.printConfig, opts?.fileMeta))\n }\n\n throw new Error(`[export] unsupported format: ${format}`)\n}\n\n/**\n * 统一导出入口:按 format 分派到各写出器。\n * **内部不变式:写出的坐标刻度 == 文件声明的单位。** 这是本 API 存在的唯一理由。\n * @param entries - 待导出的几何条目(BREP solid 优先,缺则走 mesh)。\n * @param format - 输出格式:'stl' | 'step' | '3mf'。\n * @param opts - 可选的目标单位与 3MF 打印配置。\n * @returns 文件字节\n * @throws 目标单位该格式不支持且无法回落时(不静默降级)\n */\nexport async function exportModel(\n entries: ExportEntry[],\n format: ExportFormat,\n opts?: ExportOptions,\n): Promise<ArrayBuffer> {\n if (entries.length === 0) throw new Error('[export] no exportable entries')\n\n let unit = opts?.unit ?? 'mm'\n\n // 3MF 枚举回落(§10.3 规则 2):yard 不在枚举 → 成对回落到 mm(坐标+声明)。\n if (format === '3mf' && !UNIT_NAME_TO_3MF[unit]) {\n unit = 'mm'\n }\n\n // scale = 基准值 → 目标单位刻度(fromBase(1, unit, 'length') 的表实现)。\n const scale = 1 / UNIT_SCALE[unit]\n\n if (format === 'stl') {\n // STL 无声明:坐标按 unit 刻度写出,调用方保证 unit 语义(当前文档单位)。\n const parts: ArrayBuffer[] = []\n for (const e of entries) {\n if (!e.mesh) continue // STL 只吃 mesh;solid 条目由宿主先三角化\n parts.push(buildStlBufferFromMesh(scalePositions(e.mesh.positions, scale), e.mesh.indices))\n }\n if (parts.length === 0) throw new Error('[export/stl] no mesh entries')\n if (parts.length === 1) return parts[0]!\n // 多 mesh:合并顶点后再写(binary STL 无对象概念,多实体合一个 soup)。\n const bufs = entries.filter((e) => e.mesh).map((e) => {\n const pos = scalePositions(e.mesh!.positions, scale)\n return { pos, idx: e.mesh!.indices }\n })\n const totalTris = bufs.reduce((n, b) => n + b.idx.length / 3, 0)\n const mergedPos = new Float32Array(bufs.reduce((n, b) => n + b.pos.length, 0))\n const mergedIdx = new Uint32Array(totalTris * 3)\n let po = 0\n let io2 = 0\n let base = 0\n for (const b of bufs) {\n mergedPos.set(b.pos, po)\n for (let i = 0; i < b.idx.length; i++) mergedIdx[io2++] = b.idx[i] + base\n base += b.pos.length / 3\n po += b.pos.length\n }\n return buildStlBufferFromMesh(mergedPos, mergedIdx)\n }\n\n if (format === 'step') {\n // 同一 scale 变量喂两类条目(§10.3 规则 7,修 E4):mesh 缩放 positions,\n // solid 用 owned copy 做 kernel.scale —— 不释放调用方缓存里的原句柄。\n // 先过门禁再取内核(同同步分支:拒绝理由与引擎装配状态无关)。\n const kernel = (await import('../handle-bridge')).getBrepApi() as BrepEngineApi\n const ownedHandles: BrepHandle[] = []\n const stepEntries: StepExportEntry[] = entries.map((e) => {\n if (e.solid) {\n if (scale === 1) return { solid: e.solid, ...(e.name ? { name: e.name } : {}), ...(e.color ? { color: [...e.color] as [number, number, number] } : {}) }\n const scaled = kernel.scale(e.solid, { x: 0, y: 0, z: 0 }, scale)\n ownedHandles.push(scaled)\n return { solid: scaled, ...(e.name ? { name: e.name } : {}), ...(e.color ? { color: [...e.color] as [number, number, number] } : {}) }\n }\n return {\n ...(e.mesh ? { mesh: { positions: scalePositions(e.mesh.positions, scale), indices: e.mesh.indices } } : {}),\n ...(e.name ? { name: e.name } : {}),\n ...(e.color ? { color: [...e.color] as [number, number, number] } : {}),\n }\n })\n const buffer = exportStepFromSolids(kernel, stepEntries)\n for (const h of ownedHandles) {\n try { kernel.release(h) } catch { /* already released */ }\n }\n // 文本层只替换 header 声明/元数据(红线:绝不文本级改坐标——坐标已在几何层缩放)。\n let text = new TextDecoder().decode(new Uint8Array(buffer))\n if (unit !== 'mm') text = rewriteStepUnitEntities(text, unit)\n if (opts?.fileMeta && fileMetaHasHeaderFields(opts.fileMeta)) text = rewriteFileMetaHeader(text, opts.fileMeta)\n return new TextEncoder().encode(text).buffer\n }\n\n if (format === '3mf') {\n return build3mfBuffer(build3mfModelXml(entries, unit, scale, opts?.printConfig, opts?.fileMeta))\n }\n\n throw new Error(`[export] unsupported format: ${format}`)\n}\n\n/**\n * 导出后回读声明单位(自检与验收用;与 detectStepUnit 互为对偶)。\n * @param data - the exported file bytes (ArrayBuffer or decoded Uint8Array).\n * @param format - the format the bytes were produced in.\n * @returns the declared unit, or null when the format cannot declare one (STL)\n * or the declaration cannot be parsed.\n */\nexport function readDeclaredUnit(data: ArrayBuffer | Uint8Array, format: ExportFormat): UnitName | null {\n if (format === 'stl') return null\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data)\n const text = new TextDecoder().decode(bytes).slice(0, STEP_UNIT_SCAN_PREFIX)\n\n if (format === '3mf') {\n const m = text.match(/<model[^>]*\\sunit=\"([^\"]+)\"/)\n if (!m) return null\n for (const [name, val] of Object.entries(UNIT_NAME_TO_3MF)) {\n if (val === m[1]) return name as UnitName\n }\n return null\n }\n\n // step\n return detectStepUnit(text)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"export-model.js","sourceRoot":"","sources":["../../../src/brep/export/export-model.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * exportModel — 统一导出入口(unit-system §10.6 二 / R11 / 裁决 J)\n *\n * 单一真源:坐标单位换算与文件单位声明由**同一次换算**产出(§10.3 规则 3),\n * 声明与坐标必须同源。CLI(writeOutput)与宿主(3d_editor)共用本入口。\n *\n * 格式分派(§10.6 表):\n * - stl:坐标缩放到 unit 刻度,无声明(格式不支持)。\n * - step:预缩放 + 文本层只改写单位实体(§10.3 规则 3a;OCCT 恒写\n * SI_UNIT(.MILLI.,.METRE.),坐标预先缩放到目标刻度后声明必须跟上)。\n * - 3mf:坐标缩放到 unit 刻度 + <model unit> 与坐标同源;yard 不在 3MF\n * 枚举 → 成对回落到 mm(§10.3 规则 2)。\n *\n * 红线(§10.3 3a):绝不文本级改坐标 — 坐标只在几何层缩放,文本层只碰单位实体。\n */\n\nimport { buildStlBufferFromMesh, composeMatrix12, bakeMatrix12ToPositions } from './stl'\nimport { writeZipEntries } from '../../io/zip'\nimport { UNIT_SCALE, type UnitName } from '../../units'\nimport type { Vec3 } from '../../mesh/types'\nimport type { BrepHandle } from '../engine/types'\nimport type { BrepEngineApi } from '../engine/primitives'\nimport { getBrepApi } from '../handle-bridge'\nimport { getBackends, BrepUnsupportedError } from '../../runtime-state'\nimport { exportStepFromSolids, type StepExportEntry } from './step'\nimport { detectStepUnit, STEP_UNIT_SCAN_PREFIX } from '../../mesh/io'\nimport type { PbrAppearance } from '../../api/appearance'\nimport type { ShapeMeta, FileMeta } from '../../api/meta'\n\n/** 导出条目:一个 part 的几何来源。精确 BREP 与三角网格二选一,solid 优先。 */\nexport interface ExportEntry {\n /** 精确 BREP 句柄(来自 brep 链,导出 ADVANCED_FACE)。 */\n solid?: BrepHandle\n /** 三角网格(基准单位刻度;调用方只做世界变换烘焙,不做单位缩放)。 */\n mesh?: { positions: Float32Array; indices: Uint32Array }\n /** 实体名(写 STEP PRODUCT 名 / 3MF <object name>)。 */\n name?: string\n /** sRGB 0..1 颜色(STEP 走 XCAF COLOUR_RGB,3MF 走 basematerials)。 */\n color?: readonly [number, number, number]\n /**\n * 逐三角形材质分组(P4,3MF 走多 basematerials + `<triangle pid p1..p3>`):\n * start/count 为**三角形索引**区间,appearance.color 为该组基色。\n */\n materialGroups?: Array<{ start: number; count: number; appearance: PbrAppearance }>\n /**\n * 零件级说明性元数据(设计文档 2026-10-05-meta §6.1):写 3MF\n * `<object name/partnumber>` + `<metadatagroup>`;STEP 走 PRODUCT name(既有)。\n */\n meta?: ShapeMeta\n /**\n * 装配子节点(方案 2026-10-08 §2.1 / 第 4 步):存在时本条目是装配容器,写出器据此\n * 生成 3MF `<components>`(每个 child 一个 `<component objectid>`,子节点的 `transform`\n * 写进 `<component transform>`);STL / STEP 分支忽略此字段或将其展平(逐层烘焙 /\n * 逐实体通道,第 5、7 步)。\n */\n children?: ExportEntry[]\n /**\n * 本节点相对父的位姿(与 `Shape.transform` 同形态,方案 §2.1)。写出器消费:3MF 写\n * `<component transform>`、STEP 写 XCAF location(第 7 步)、STL 顶点烘焙(第 5 步)。\n */\n transform?: { translate?: Vec3; rotate?: { angle: number; axis?: Vec3 }; matrix?: number[] }\n}\n\n/** Output formats supported by the unified {@link exportModel} entry. */\nexport type ExportFormat = 'stl' | 'step' | '3mf'\n\n/**\n * Options controlling {@link exportModel}/{@link exportModelSync} output\n * (unit-system §10.3): the declared target unit and optional 3MF print config.\n */\nexport interface ExportOptions {\n /**\n * 目标长度单位。缺省 'mm'。语义是「文件里声明的单位」——\n * 实现负责把坐标换算到该单位刻度并与声明成对写出(§10.3)。\n */\n unit?: UnitName\n /** 3MF 打印配置(可选,原样进 model 层)。 */\n printConfig?: unknown\n /** 整体级元数据(设计文档 2026-10-05-meta §6.1):3MF 写 `<model>` 级 `<metadata>`。 */\n fileMeta?: FileMeta\n}\n\n/** UnitName → 3MF <model unit> 枚举全名(唯一真源;yard 无对应值)。 */\nexport const UNIT_NAME_TO_3MF: Partial<Record<UnitName, 'micron' | 'millimeter' | 'centimeter' | 'inch' | 'foot' | 'meter'>> = {\n mm: 'millimeter',\n cm: 'centimeter',\n m: 'meter',\n micron: 'micron',\n inch: 'inch',\n foot: 'foot',\n // yard 无 3MF 枚举值 — 调用方必须先成对回落到 mm(§10.3 规则 2)。\n}\n\n/** 缩放 Float32 positions 到目标单位刻度(基准值 ÷ unitScale(unit))。 */\nfunction scalePositions(positions: Float32Array, scale: number): Float32Array {\n if (scale === 1) return positions\n const out = new Float32Array(positions.length)\n for (let i = 0; i < positions.length; i++) out[i] = positions[i] * scale\n return out\n}\n\n/** STEP 单位声明改写:SI_UNIT(.MILLI.,.METRE.) → 目标单位实体(只碰单位实体,红线)。 */\nfunction rewriteStepUnitEntities(stepText: string, unit: UnitName): string {\n // mm 是 OCCT 的原生写出形态,无需改写。\n if (unit === 'mm') return stepText\n\n // SI 面积/体积单位实体的前缀同样要跟着换(LENGTH/AREA/VOLUME 挂同一前缀链),\n // 但坐标已缩放 → 只需把 LENGTH 链上的前缀换掉;面积/体积单位在 STEP 里由\n // SI_UNIT 前缀 + 幂次表达,XCAF 写出的实体形态是 SI_UNIT(.MILLI.,.METRE.)\n // 挂在长度、平方与立方三条依赖链上。为保守起见只改写显式 LENGTH_UNIT 链上的\n // SI_UNIT —— 具体做法:全局替换 SI_UNIT 前缀(同一文件里坐标相关单位恒为\n // 长度链;角度 SI_UNIT(.RADIAN.) 不含 METRE 不会被命中)。\n let out = stepText\n\n if (unit === 'cm' || unit === 'm' || unit === 'micron') {\n const prefix = unit === 'cm' ? '.CENTI.' : unit === 'm' ? '$' : '.MICRO.'\n // OCCT 写出恒为 SI_UNIT(.MILLI.,.METRE.)(实测);$ 前缀形态(无前缀=米)\n // 在 OCCT 输出中不会出现,但容错处理(若上游将来变化)。\n out = out.replace(/SI_UNIT\\s*\\(\\s*\\.MILLI\\.\\s*,\\s*\\.METRE\\.\\s*\\)/g,\n prefix === '$' ? 'SI_UNIT($,.METRE.)' : `SI_UNIT(${prefix},.METRE.)`)\n return out\n }\n\n // inch / foot:CONVERSION_BASED_UNIT 形态。需要注入换算因子实体并替换\n // LENGTH_UNIT 依赖。最简形态:把 SI_UNIT(.MILLI.,.METRE.) 替换为\n // CONVERSION_BASED_UNIT('INCH', #factor),并附加 MEASURE_WITH_UNIT 实体。\n // 实体编号:取文件内最大 #n + 1、+2(附加实体挂在文件尾部 DATA 段内合法)。\n const inchFactor = unit === 'inch' ? 25.4 : 304.8\n const name = unit === 'inch' ? 'INCH' : 'FOOT'\n\n // 1) 收集现有最大实体编号\n let maxId = 0\n for (const m of out.matchAll(/#(\\d+)\\s*=/g)) {\n const id = Number(m[1])\n if (id > maxId) maxId = id\n }\n const lenId = maxId + 1\n const convId = maxId + 2\n\n // 2) 存在性守卫:必须至少有一条 LENGTH_UNIT 挂 SI_UNIT(.MILLI.,.METRE.),否则\n // 没有可改写的声明(凭空插入单位声明 = 伪造文件单位)。\n // OCCT 实测形态(实体括号内还有 LENGTH_UNIT() / NAMED_UNIT(*) 的括号,且\n // `=`、`)` 前后都有空格):\n // #346 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) );\n // 故实体体的字符类用 [^;](STEP 实体行内不含分号)而不是 [^)]——后者跨不过\n // `LENGTH_UNIT()` 与 `NAMED_UNIT(*)` 自带的括号,整段永远匹配不上。\n const siDecl = out.match(/#(\\d+)\\s*=\\s*\\([^;]*?SI_UNIT\\s*\\(\\s*\\.MILLI\\.\\s*,\\s*\\.METRE\\.\\s*\\)[^;]*?\\)\\s*;/)\n if (!siDecl) {\n throw new Error(`[export/step] no SI_UNIT(.MILLI.,.METRE.) entity found; cannot rewrite declaration to ${name}`)\n }\n\n // 3) 把**全部** SI_UNIT(.MILLI.,.METRE.) 换成 CONVERSION_BASED_UNIT(各 context\n // 共享同一份换算因子实体),插入换算因子与基准米实体:\n // #si=( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) );\n // → #si=( LENGTH_UNIT() NAMED_UNIT(*) CONVERSION_BASED_UNIT('INCH',#conv) );\n // #conv=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(25.4),#len);\n // #len=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT($,.METRE.));\n // 全局替换而不是只改第一条:多零件导出会写出多条 LENGTH_UNIT 声明(每个 part 一个\n // context,实测 2 个 part → #346 与 #690),只改第一条会让同一文件里并存两种长度\n // 单位声明——而坐标是按同一 scale 换算过的。\n out = out.replace(/SI_UNIT\\s*\\(\\s*\\.MILLI\\.\\s*,\\s*\\.METRE\\.\\s*\\)/g, `CONVERSION_BASED_UNIT('${name}',#${convId})`)\n // 在 DATA 段结束前(ENDSEC;)插入新实体。\n const insert = [\n `#${convId}=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(${inchFactor}),#${lenId});`,\n `#${lenId}=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT($,.METRE.));`,\n ].join('\\n')\n out = out.replace(/ENDSEC\\s*;/, `${insert}\\nENDSEC;`)\n return out\n}\n\n/**\n * STEP 文件级元数据 → P21 header 重写(`FILE_NAME`/`FILE_DESCRIPTION`)。\n *\n * 设计文档 2026-10-05-meta §6.2 第 6 步:`exportModel` 已有 SI_UNIT 声明重写的\n * 先例——同样只对 header 里 FILE_NAME(...)/FILE_DESCRIPTION(...) 行做文本替换,\n * 绝不碰 DATA 段几何实体(红线 §10.3 3a:文本层只改声明/元数据,坐标不动)。\n *\n * FILE_NAME(name, time_stamp, author, organization, preprocessor_version, ...)\n * FILE_DESCRIPTION(description_list, implementation_level)\n * 映射(§3.3):title→name, creationDate→time_stamp, author|designer→author 列表,\n * organization→organization, application→preprocessor, description→description。\n * 无对应的字段(copyright/licenseTerms/rating/modificationDate)**不写**(§5.3 头:\n * STEP 无标准位置,不发明)。\n *\n * 宽容失败:找不到 FILE_NAME/FILE_DESCRIPTION 行则留空(P21 头由内核写出,形态\n * 已知为 `FILE_DESCRIPTION(('Open CASCADE Model'),'2;1');` 一行,但在字符串内)。\n *\n * @param stepText 内核产出的 STEP 全文(ISO-10303-21)。\n * @param fileMeta 目标文件级元数据。\n * @returns 改写后的 STEP 文本。\n */\nexport function rewriteFileMetaHeader(stepText: string, fileMeta: FileMeta): string {\n let out = stepText\n\n const title = fileMeta.title && fileMeta.title.length > 0 ? fileMeta.title : undefined\n const ts = fileMeta.creationDate && fileMeta.creationDate.length > 0\n ? fileMeta.creationDate\n : (fileMeta.modificationDate && fileMeta.modificationDate.length > 0 ? fileMeta.modificationDate : undefined)\n const authorList = fileMeta.author && fileMeta.author.length > 0 ? [fileMeta.author] : []\n const org = fileMeta.organization && fileMeta.organization.length > 0 ? fileMeta.organization : undefined\n const preproc = fileMeta.application && fileMeta.application.length > 0 ? fileMeta.application : undefined\n const designer = fileMeta.designer && fileMeta.designer.length > 0 ? fileMeta.designer : undefined\n const desc = fileMeta.description && fileMeta.description.length > 0 ? fileMeta.description : undefined\n\n // 1) FILE_NAME(用平衡括号/引号感知的枚举,整块替换 —— 逐参安全,不依赖行结构)。\n const fn = matchEntity(out, 'FILE_NAME')\n if (fn) {\n const params = splitP21Params(fn.inner)\n const next: string[] = []\n if (title !== undefined || ts !== undefined || authorList.length > 0 || org !== undefined || preproc !== undefined || designer !== undefined) {\n next.push(stepStr(title ?? paramStr(params[0]) ?? 'STEP File'))\n next.push(stepStr(ts ?? paramStr(params[1]) ?? ''))\n next.push(authorList.length > 0 ? p21List(authorList) : (params[2] ?? \"('')\"))\n next.push(org !== undefined ? p21List([org]) : (params[3] ?? \"('')\"))\n // 保留内核写出的后续参数原样(preprocessor_version / originating_system /\n // authorisation)——FILE_NAME 可带 6..7 参,不丢既有值。\n next.push(preproc !== undefined ? stepStr(preproc) : (params[4] ?? ''))\n next.push(designer !== undefined ? stepStr(designer) : (params[5] ?? ''))\n for (let i = 6; i < params.length; i++) next.push(params[i])\n // 末尾空参保留则拼 ',' 会使整行以 ',' 结尾 → 过滤空的尾部。\n while (next.length > 0 && next[next.length - 1] === '') next.pop()\n out = splice(out, fn.start, fn.end, `FILE_NAME(${next.join(',')})`)\n }\n }\n\n // 2) FILE_DESCRIPTION(description_list, implementation_level):替换描述列表。\n const fd = matchEntity(out, 'FILE_DESCRIPTION')\n if (fd) {\n const params = splitP21Params(fd.inner)\n if (desc !== undefined && params.length > 0) {\n const impl = params[params.length - 1]\n out = splice(out, fd.start, fd.end, `FILE_DESCRIPTION((${stepStr(desc)}),${impl})`)\n }\n }\n\n return out\n}\n\n/** [start, end) 区间替换为 replacement(end 为闭合括号后一位,仍保留其后的 `;`)。 */\nfunction splice(s: string, start: number, end: number, replacement: string): string {\n return s.slice(0, start) + replacement + s.slice(end)\n}\n\n/** FileMeta 是否含可映射到 STEP header 的字段(避免对无 header 字段的 fileMeta 做无谓解码重写)。 */\nfunction fileMetaHasHeaderFields(f: FileMeta): boolean {\n return !!(f.title || f.description || f.designer || f.author || f.organization || f.application\n || f.creationDate || f.modificationDate)\n}\n\n/**\n * 在文本中定位 `NAME(` … 匹配的 `)` (引号忽略、内层括号计入)并返回\n * `{ start, end, inner }`;找不到返回 null。start/end 是 `NAME(` 起始/闭合 `)` 之后\n * 一位的偏移,供调用方做字符串拼接替换(不做正则整行匹配——行内可含 `;` 等字符)。\n */\nfunction matchEntity(text: string, name: string): { start: number; end: number; inner: string } | null {\n const re = new RegExp(`${name}\\\\s*\\\\(`)\n const m = re.exec(text)\n if (!m) return null\n const start = m.index\n const head = m.index + m[0].length\n let depth = 1\n let i = head\n for (; i < text.length && depth > 0; i++) {\n const c = text[i]\n if (c === `'`) {\n // 跳过字符串字面量(含 ISO10303-21 双引号转义)\n i++\n while (i < text.length) {\n if (text[i] === `'` && text[i + 1] === `'`) { i += 2; continue }\n if (text[i] === `'`) break\n i++\n }\n } else if (c === '(') depth++\n else if (c === ')') depth--\n }\n return { start, end: i - 1, inner: text.slice(head, i - 1) }\n}\n\n/** 把一层参数(逗号分隔,忽略括号与字符串内的逗号)拆分(trim,原样保留字面量)。 */\nfunction splitP21Params(inner: string): string[] {\n const out: string[] = []\n let cur = ''\n let depth = 0\n for (let i = 0; i < inner.length; i++) {\n const c = inner[i]\n if (c === `'`) {\n // 字符串字面量:整体吸收(含 ISO10303-21 转义 ''),不拆其内逗号/括号。\n const start = i\n i++\n while (i < inner.length) {\n if (inner[i] === `'` && inner[i + 1] === `'`) { i += 2; continue }\n if (inner[i] === `'`) { i++; break }\n i++\n }\n cur += inner.slice(start, i)\n i-- // for 循环还会 +1,落到字符串结束引号后一个字符\n continue\n }\n if (c === '(') depth++\n else if (c === ')') depth--\n if (c === ',' && depth === 0) { out.push(cur.trim()); cur = '' }\n else cur += c\n }\n if (cur.trim() !== '') out.push(cur.trim())\n return out\n}\n\n/** 单个 P21 字符串字面量的未转义内容(剥离包裹引号与 '' 转义)。 */\nfunction paramStr(p: string | undefined): string | undefined {\n if (p === undefined) return undefined\n const m = /^'((?:[^']|'')*)'$/.exec(p.trim())\n return m ? m[1].replace(/''/g, `'`) : undefined\n}\n\n/** 单个 P21 字符串字面量(已转义)。 */\nfunction stepStr(v: string): string {\n return `'${v.replace(/'/g, \"''\")}'`\n}\n\n/** P21 列表字面量:(['a','b']) → `('a','b')`。 */\nfunction p21List(items: string[]): string {\n return `(${items.map(stepStr).join(',')})`\n}\n\n/** 3MF写出:最小 ZIP 容器(deflate),落 3D/3dmodel.model + [Content_Types].xml + _rels。 */\nfunction build3mfBuffer(modelXml: string): ArrayBuffer {\n const contentTypes = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"model\" ContentType=\"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\"/></Types>`\n const rels = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Target=\"/3D/3dmodel.model\" Id=\"rel0\" Type=\"http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel\"/></Relationships>`\n\n const zipped = writeZipEntries({\n '[Content_Types].xml': new TextEncoder().encode(contentTypes),\n '_rels/.rels': new TextEncoder().encode(rels),\n '3D/3dmodel.model': new TextEncoder().encode(modelXml),\n })\n return zipped.buffer.slice(zipped.byteOffset, zipped.byteOffset + zipped.byteLength) as ArrayBuffer\n}\n\n/** 组 3MF <model> XML:单位声明与坐标由同一 scale 变量产出(同源,§10.3 规则 3)。 */\nfunction build3mfModelXml(entries: ExportEntry[], unit: UnitName, scale: number, printConfig?: unknown, fileMeta?: FileMeta): string {\n const unitAttr = UNIT_NAME_TO_3MF[unit]\n if (!unitAttr) {\n // 调用方(exportModel)保证 unit 已成对回落;直接到这里 = 内部错误。\n throw new Error(`[export/3mf] unit ${unit} has no 3MF enum value`)\n }\n const objs: string[] = []\n const mats: string[] = []\n const items: string[] = []\n let nextObjId = 1\n // 逐三角形材质分组的 basematerials id 从「顶层条目数 + 1」起,与 object id(1..N)\n // 错开(P3:resources 内 id 唯一)。对象级颜色 basematerials 复用其 object id。\n let nextMatId = entries.length + 1\n\n // 递归发射一个节点为 <object>(叶带 mesh、容器带 <components>),返回其 object id。\n function emitObject(e: ExportEntry): number | undefined {\n // P8 契约(库面):无 mesh 且无子节点的条目 → 静默跳过(不发射 <object>/<item>),\n // 与 op 层「无三角载荷即 E_EXPORT_3MF_EMPTY 显式报错」形成双值防护。显式容器\n // (children 已声明,即便为空 [])仍发射,以便装配层级(含空装配)可写。\n const isContainer = e.children !== undefined\n if (!e.mesh && !isContainer) return undefined\n const id = nextObjId++\n let meshXml = ''\n if (e.mesh) {\n const pos = scalePositions(e.mesh.positions, scale)\n const verts: string[] = []\n for (let v = 0; v < pos.length; v += 3) {\n verts.push(`<vertex x=\"${pos[v]}\" y=\"${pos[v + 1]}\" z=\"${pos[v + 2]}\"/>`)\n }\n // P4(3MF Core 逐三角形材质):materialGroups(appearance.color)→ 每组\n // 一个独立 basematerials 资源(id 与对象 id 错开,P3 曾与对象共用 id、\n // 违反 resources 内 id 唯一),分组三角形用 `<triangle pid p1..p3>` 引用。\n const groupPids: number[] = []\n const groups = (e.materialGroups ?? []).filter((g) => g.appearance?.color)\n for (const g of groups) {\n groupPids.push(nextMatId)\n mats.push(\n `<basematerials id=\"${nextMatId}\"><base name=\"${xmlAttr(`${e.name ?? `part${id}`}_g${groupPids.length}`)}\" displaycolor=\"${hexColor(g.appearance.color!)}\"/></basematerials>`,\n )\n nextMatId++\n }\n const tris: string[] = []\n const triCount = e.mesh.indices.length / 3\n let gi = 0\n for (let t = 0; t < triCount; t++) {\n while (gi < groups.length && t >= groups[gi].start + groups[gi].count) gi++\n const inGroup = gi < groups.length && t >= groups[gi].start\n const matAttr = inGroup ? ` pid=\"${groupPids[gi]}\" p1=\"0\" p2=\"0\" p3=\"0\"` : ''\n tris.push(\n `<triangle v1=\"${e.mesh.indices[t * 3]}\" v2=\"${e.mesh.indices[t * 3 + 1]}\" v3=\"${e.mesh.indices[t * 3 + 2]}\"${matAttr}/>`,\n )\n }\n meshXml = `<mesh><vertices>${verts.join('')}</vertices><triangles>${tris.join('')}</triangles></mesh>`\n }\n // 对象级颜色 basematerials:复用 object id(既有契约,解析器按 id 取首个资源)。\n let pidAttr = ''\n if (e.color) {\n mats.push(`<basematerials id=\"${id}\"><base name=\"${xmlAttr(e.name ?? 'p' + id)}\" displaycolor=\"${hexColor(e.color)}\"/></basematerials>`)\n pidAttr = ` pid=\"${id}\" pindex=\"0\"`\n }\n // 装配层级 → <components>(子节点递归;<component transform> 写相对父位姿)。\n let compXml = ''\n if (e.children && e.children.length > 0) {\n const comps = e.children.map((child) => {\n const cid = emitObject(child)\n if (cid === undefined) return ''\n const tf = child.transform ? ` transform=\"${matrix12ToAttr(transformToMatrix12(child.transform))}\"` : ''\n return `<component objectid=\"${cid}\"${tf}/>`\n }).filter((s) => s !== '')\n compXml = comps.length > 0 ? `<components>${comps.join('')}</components>` : ''\n }\n // 零件级元数据(设计文档 2026-10-05-meta §6.1):partnumber 属性 +\n // `<metadatagroup><metadata>`(3MF 自定义标签须带命名空间前缀;faijs\n // 无前缀键一律补 `faijs:` 前缀,跨工具链兼容)。description 3MF 无对象级\n // 标准位 → 写 `faijs:description`(规范允许 vendor 前缀名)。\n const partnumberAttr = e.meta?.partNumber ? ` partnumber=\"${xmlAttr(e.meta.partNumber)}\"` : ''\n const metadatas: string[] = []\n const meta = e.meta\n if (meta) {\n const metaPairs: Array<[string, string]> = []\n if (meta.description !== undefined && meta.description !== '') metaPairs.push(['faijs:description', meta.description])\n if (meta.metadata) {\n for (const [k, v] of Object.entries(meta.metadata)) {\n metaPairs.push([k.includes(':') ? k : `faijs:${k}`, v])\n }\n }\n // 同键不重复(首见保留)。\n const seen = new Set<string>()\n for (const [k, v] of metaPairs) {\n if (seen.has(k)) continue\n seen.add(k)\n metadatas.push(`<metadata name=\"${xmlAttr(k)}\">${xmlAttr(v)}</metadata>`)\n }\n }\n const metadatagroup = metadatas.length > 0 ? `<metadatagroup>${metadatas.join('')}</metadatagroup>` : ''\n const nameAttr = xmlAttr(e.name ?? `part${id}`)\n objs.push(`<object id=\"${id}\" type=\"model\" name=\"${nameAttr}\"${partnumberAttr}${pidAttr}>${metadatagroup}${meshXml}${compXml}</object>`)\n return id\n }\n\n for (const e of entries) {\n const id = emitObject(e)\n if (id === undefined) continue\n const tf = e.transform ? ` transform=\"${matrix12ToAttr(transformToMatrix12(e.transform))}\"` : ''\n items.push(`<item objectid=\"${id}\"${tf}/>`)\n }\n // 整体级元数据(`<model>` 直接子级 `<metadata>`):well-known 名经映射写标准\n // 3MF 名,vendor 名写 `faijs:` 前缀。排在 `<resources>` 之前(3MF Core)。\n const modelMetas: string[] = []\n if (fileMeta) {\n const wellKnown: Array<[Exclude<keyof FileMeta, 'metadata'>, string]> = [\n ['title', 'Title'],\n ['designer', 'Designer'],\n ['description', 'Description'],\n ['copyright', 'Copyright'],\n ['licenseTerms', 'LicenseTerms'],\n ['rating', 'Rating'],\n ['creationDate', 'CreationDate'],\n ['modificationDate', 'ModificationDate'],\n ['application', 'Application'],\n ]\n for (const [field, name] of wellKnown) {\n if (fileMeta[field] !== undefined) modelMetas.push(`<metadata name=\"${name}\">${xmlAttr(String(fileMeta[field]))}</metadata>`)\n }\n if (fileMeta.metadata) {\n for (const [k, v] of Object.entries(fileMeta.metadata)) {\n modelMetas.push(`<metadata name=\"${xmlAttr(k.includes(':') ? k : `faijs:${k}`)}\">${xmlAttr(v)}</metadata>`)\n }\n }\n }\n const pc = printConfig ? `<metadata name=\"printConfig\">${xmlAttr(String(printConfig))}</metadata>` : ''\n return `<model unit=\"${unitAttr}\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\" xmlns:faijs=\"http://schemas.faicad.dev/3mf/2026/10\">${pc}${modelMetas.join('')}<resources>${mats.join('')}${objs.join('')}</resources><build>${items.join('')}</build></model>`\n}\n\nfunction xmlAttr(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"')\n}\n\nfunction hexColor(c: readonly [number, number, number]): string {\n const h = (v: number) => Math.round(Math.min(1, Math.max(0, v)) * 255).toString(16).padStart(2, '0')\n return `#${h(c[0])}${h(c[1])}${h(c[2])}`\n}\n\nexport { transformToMatrix12 } from './transform12'\nimport { scaleTransform, transformToMatrix12 } from './transform12'\n\n/**\n * ExportEntry → StepExportEntry 的递归映射器(step 分支同步/异步共用,单一真源)。\n * 容器只传名/色与子节点(compound 几何 == 成员并集,写出会重复);位姿平移按\n * 单位刻度换算,与几何缩放同一 scale 因子(「声明单位 == 坐标刻度」对组件位姿\n * 同样成立)。solid 经 kernel.scale 的 owned copy 缩放,入 ownedHandles 由调用方\n * 统一释放。\n */\nfunction makeStepEntryMapper(\n kernel: BrepEngineApi,\n scale: number,\n ownedHandles: BrepHandle[],\n): (e: ExportEntry) => StepExportEntry {\n const toStepEntry = (e: ExportEntry): StepExportEntry => {\n const head = {\n ...(e.name ? { name: e.name } : {}),\n ...(e.color ? { color: [...e.color] as [number, number, number] } : {}),\n }\n const transform = e.transform ? scaleTransform(e.transform, scale) : undefined\n if (e.children && e.children.length > 0) {\n return {\n ...head,\n ...(transform ? { transform } : {}),\n children: e.children.map(toStepEntry),\n }\n }\n if (e.solid) {\n if (scale === 1) return { solid: e.solid, ...head }\n const scaled = kernel.scale(e.solid, { x: 0, y: 0, z: 0 }, scale)\n ownedHandles.push(scaled)\n return { solid: scaled, ...head }\n }\n return {\n ...head,\n ...(e.mesh ? { mesh: { positions: scalePositions(e.mesh.positions, scale), indices: e.mesh.indices } } : {}),\n }\n }\n return toStepEntry\n}\n\nfunction fmtNum(v: number): string {\n if (Number.isInteger(v)) return String(v)\n return String(Math.round(v * 1e6) / 1e6)\n}\n\nfunction matrix12ToAttr(m: number[]): string {\n return m.map(fmtNum).join(' ')\n}\n\n/**\n * Synchronous twin of {@link exportModel} for hosts already holding a live\n * kernel (CLI, in-process consumers). Same invariants: declared unit ==\n * written coordinate scale. Only 'stl' / 'step' (3mf is also sync but is\n * routed through the same code path below).\n *\n * @param entries - the shapes to export (BREP solids preferred, mesh fallback).\n * @param format - output format: 'stl' | 'step' | '3mf'.\n * @param opts - optional target unit and 3MF print config.\n * @returns the serialized file bytes (ArrayBuffer).\n */\nexport function exportModelSync(\n entries: ExportEntry[],\n format: ExportFormat,\n opts?: ExportOptions,\n): ArrayBuffer {\n if (entries.length === 0) throw new Error('[export] no exportable entries')\n\n let unit = opts?.unit ?? 'mm'\n if (format === '3mf' && !UNIT_NAME_TO_3MF[unit]) unit = 'mm'\n const scale = 1 / UNIT_SCALE[unit]\n\n if (format === 'stl') {\n // 步骤 5(方案 §2.1 / §4.3 L1-5):装配展平 + 顶点烘焙。递归把 children 拍平成叶,\n // 每个叶的世界变换 = 父世界变换 ∘ 本节点局部 transform(row-major 3×4,平移在末列)。\n // 先在世界空间烘焙 transform,再按单位换算缩放坐标(缩放同时作用于平移分量,坐标与声明成对)。\n const flatten = (\n list: ExportEntry[],\n accTf: number[] | null,\n ): Array<{ pos: Float32Array; idx: Uint32Array }> => {\n const out: Array<{ pos: Float32Array; idx: Uint32Array }> = []\n for (const e of list) {\n const tf = e.transform ? transformToMatrix12(e.transform) : null\n const world = tf && accTf ? composeMatrix12(accTf, tf) : tf ?? accTf ?? null\n if (e.children && e.children.length > 0) {\n out.push(...flatten(e.children, world))\n continue\n }\n if (!e.mesh) continue\n let pos = e.mesh.positions\n if (world) pos = bakeMatrix12ToPositions(pos, world)\n pos = scalePositions(pos, scale)\n out.push({ pos, idx: e.mesh.indices })\n }\n return out\n }\n const bufs = flatten(entries, null)\n if (bufs.length === 0) throw new Error('[export/stl] no mesh entries')\n if (bufs.length === 1) return buildStlBufferFromMesh(bufs[0]!.pos, bufs[0]!.idx)\n const totalTris = bufs.reduce((n, b) => n + b.idx.length / 3, 0)\n const mergedPos = new Float32Array(bufs.reduce((n, b) => n + b.pos.length, 0))\n const mergedIdx = new Uint32Array(totalTris * 3)\n let po = 0\n let io2 = 0\n let base = 0\n for (const b of bufs) {\n mergedPos.set(b.pos, po)\n for (let i = 0; i < b.idx.length; i++) mergedIdx[io2++] = b.idx[i] + base\n base += b.pos.length / 3\n po += b.pos.length\n }\n return buildStlBufferFromMesh(mergedPos, mergedIdx)\n }\n\n if (format === 'step') {\n // 步骤 6(方案 §2.3 / P1):STEP 装配层级走 XCAF,仅 occt 具备;非 occt 引擎在\n // 触碰任何句柄之前报 E_BREP_UNSUPPORTED(带当前引擎名),不落入 getBrepApi 的\n // 未初始化异常,也不把 brepkit 句柄交给 occt 内核(句柄不得跨引擎传递)。\n const engineId = getBackends().config.brepEngineId\n if (engineId !== 'occt') {\n throw new BrepUnsupportedError(\n `E_BREP_UNSUPPORTED: op 'exportModel:step' requires engine occt (current=${engineId ?? '<none>'})`,\n )\n }\n const kernel = getBrepApi()\n const ownedHandles: BrepHandle[] = []\n // 层级映射(步骤 7 / P3):ExportEntry 树 → StepExportEntry 树(映射器见\n // makeStepEntryMapper——同步/异步分支共用,单一真源)。\n const stepEntries: StepExportEntry[] = entries.map(makeStepEntryMapper(kernel, scale, ownedHandles))\n const buffer = exportStepFromSolids(kernel, stepEntries)\n for (const h of ownedHandles) {\n try { kernel.release(h) } catch { /* already released */ }\n }\n // 文本层只替换 header 声明/元数据(红线:绝不文本级改坐标——坐标已在几何层缩放)。\n const applyTextRewrites = (buf: ArrayBuffer): ArrayBuffer => {\n let text = new TextDecoder().decode(new Uint8Array(buf))\n if (unit !== 'mm') text = rewriteStepUnitEntities(text, unit)\n if (opts?.fileMeta && fileMetaHasHeaderFields(opts.fileMeta)) text = rewriteFileMetaHeader(text, opts.fileMeta)\n return new TextEncoder().encode(text).buffer\n }\n return applyTextRewrites(buffer)\n }\n\n if (format === '3mf') {\n return build3mfBuffer(build3mfModelXml(entries, unit, scale, opts?.printConfig, opts?.fileMeta))\n }\n\n throw new Error(`[export] unsupported format: ${format}`)\n}\n\n/**\n * 统一导出入口:按 format 分派到各写出器。\n * **内部不变式:写出的坐标刻度 == 文件声明的单位。** 这是本 API 存在的唯一理由。\n * @param entries - 待导出的几何条目(BREP solid 优先,缺则走 mesh)。\n * @param format - 输出格式:'stl' | 'step' | '3mf'。\n * @param opts - 可选的目标单位与 3MF 打印配置。\n * @returns 文件字节\n * @throws 目标单位该格式不支持且无法回落时(不静默降级)\n */\nexport async function exportModel(\n entries: ExportEntry[],\n format: ExportFormat,\n opts?: ExportOptions,\n): Promise<ArrayBuffer> {\n if (entries.length === 0) throw new Error('[export] no exportable entries')\n\n let unit = opts?.unit ?? 'mm'\n\n // 3MF 枚举回落(§10.3 规则 2):yard 不在枚举 → 成对回落到 mm(坐标+声明)。\n if (format === '3mf' && !UNIT_NAME_TO_3MF[unit]) {\n unit = 'mm'\n }\n\n // scale = 基准值 → 目标单位刻度(fromBase(1, unit, 'length') 的表实现)。\n const scale = 1 / UNIT_SCALE[unit]\n\n if (format === 'stl') {\n // STL 无声明:坐标按 unit 刻度写出,调用方保证 unit 语义(当前文档单位)。\n const parts: ArrayBuffer[] = []\n for (const e of entries) {\n if (!e.mesh) continue // STL 只吃 mesh;solid 条目由宿主先三角化\n parts.push(buildStlBufferFromMesh(scalePositions(e.mesh.positions, scale), e.mesh.indices))\n }\n if (parts.length === 0) throw new Error('[export/stl] no mesh entries')\n if (parts.length === 1) return parts[0]!\n // 多 mesh:合并顶点后再写(binary STL 无对象概念,多实体合一个 soup)。\n const bufs = entries.filter((e) => e.mesh).map((e) => {\n const pos = scalePositions(e.mesh!.positions, scale)\n return { pos, idx: e.mesh!.indices }\n })\n const totalTris = bufs.reduce((n, b) => n + b.idx.length / 3, 0)\n const mergedPos = new Float32Array(bufs.reduce((n, b) => n + b.pos.length, 0))\n const mergedIdx = new Uint32Array(totalTris * 3)\n let po = 0\n let io2 = 0\n let base = 0\n for (const b of bufs) {\n mergedPos.set(b.pos, po)\n for (let i = 0; i < b.idx.length; i++) mergedIdx[io2++] = b.idx[i] + base\n base += b.pos.length / 3\n po += b.pos.length\n }\n return buildStlBufferFromMesh(mergedPos, mergedIdx)\n }\n\n if (format === 'step') {\n // 步骤 6(方案 §2.3 / P1):同同步分支,取内核前先断言 occt 引擎身份。\n const engineId = getBackends().config.brepEngineId\n if (engineId !== 'occt') {\n throw new BrepUnsupportedError(\n `E_BREP_UNSUPPORTED: op 'exportModel:step' requires engine occt (current=${engineId ?? '<none>'})`,\n )\n }\n // 同一 scale 变量喂两类条目(§10.3 规则 7,修 E4):mesh 缩放 positions,\n // solid 用 owned copy 做 kernel.scale —— 不释放调用方缓存里的原句柄。\n // 先过门禁再取内核(同同步分支:拒绝理由与引擎装配状态无关)。\n const kernel = (await import('../handle-bridge')).getBrepApi() as BrepEngineApi\n const ownedHandles: BrepHandle[] = []\n // 同步分支同一映射器(单一真源)。\n const stepEntries: StepExportEntry[] = entries.map(makeStepEntryMapper(kernel, scale, ownedHandles))\n const buffer = exportStepFromSolids(kernel, stepEntries)\n for (const h of ownedHandles) {\n try { kernel.release(h) } catch { /* already released */ }\n }\n // 文本层只替换 header 声明/元数据(红线:绝不文本级改坐标——坐标已在几何层缩放)。\n let text = new TextDecoder().decode(new Uint8Array(buffer))\n if (unit !== 'mm') text = rewriteStepUnitEntities(text, unit)\n if (opts?.fileMeta && fileMetaHasHeaderFields(opts.fileMeta)) text = rewriteFileMetaHeader(text, opts.fileMeta)\n return new TextEncoder().encode(text).buffer\n }\n\n if (format === '3mf') {\n return build3mfBuffer(build3mfModelXml(entries, unit, scale, opts?.printConfig, opts?.fileMeta))\n }\n\n throw new Error(`[export] unsupported format: ${format}`)\n}\n\n/**\n * 导出后回读声明单位(自检与验收用;与 detectStepUnit 互为对偶)。\n * @param data - the exported file bytes (ArrayBuffer or decoded Uint8Array).\n * @param format - the format the bytes were produced in.\n * @returns the declared unit, or null when the format cannot declare one (STL)\n * or the declaration cannot be parsed.\n */\nexport function readDeclaredUnit(data: ArrayBuffer | Uint8Array, format: ExportFormat): UnitName | null {\n if (format === 'stl') return null\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data)\n const text = new TextDecoder().decode(bytes).slice(0, STEP_UNIT_SCAN_PREFIX)\n\n if (format === '3mf') {\n const m = text.match(/<model[^>]*\\sunit=\"([^\"]+)\"/)\n if (!m) return null\n for (const [name, val] of Object.entries(UNIT_NAME_TO_3MF)) {\n if (val === m[1]) return name as UnitName\n }\n return null\n }\n\n // step\n return detectStepUnit(text)\n}\n"]}
|