@faicad/faijs 0.35.2 → 0.35.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/api/assembly/entities.js +14 -4
  2. package/dist/api/assembly/entities.js.map +1 -1
  3. package/dist/api/extrude.d.ts.map +1 -1
  4. package/dist/api/extrude.js +4 -1
  5. package/dist/api/extrude.js.map +1 -1
  6. package/dist/api/fillet.d.ts.map +1 -1
  7. package/dist/api/fillet.js +47 -0
  8. package/dist/api/fillet.js.map +1 -1
  9. package/dist/api/generated/script-face-manifest.js +1 -1
  10. package/dist/api/generated/script-face-manifest.js.map +1 -1
  11. package/dist/api/generated/topology.js +1 -1
  12. package/dist/api/generated/topology.js.map +1 -1
  13. package/dist/api/primitives.d.ts +3 -2
  14. package/dist/api/primitives.d.ts.map +1 -1
  15. package/dist/api/primitives.js +3 -2
  16. package/dist/api/primitives.js.map +1 -1
  17. package/dist/api/surface/arg-spec.d.ts.map +1 -1
  18. package/dist/api/surface/arg-spec.js +5 -6
  19. package/dist/api/surface/arg-spec.js.map +1 -1
  20. package/dist/api/topo-resolve.d.ts.map +1 -1
  21. package/dist/api/topo-resolve.js +24 -5
  22. package/dist/api/topo-resolve.js.map +1 -1
  23. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  24. package/dist/brepkit-kernel/brepkitKernel.js +13 -2
  25. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  26. package/dist/brepkit-kernel/brepkitWasm.d.ts +3 -1
  27. package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
  28. package/dist/brepkit-kernel/brepkitWasm.js +6 -2
  29. package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
  30. package/dist/cad-runtime/runtime.d.ts.map +1 -1
  31. package/dist/cad-runtime/runtime.js +15 -2
  32. package/dist/cad-runtime/runtime.js.map +1 -1
  33. package/dist/extra/ops/load.d.ts.map +1 -1
  34. package/dist/extra/ops/load.js +40 -2
  35. package/dist/extra/ops/load.js.map +1 -1
  36. package/dist/mesh/primitives.d.ts +6 -4
  37. package/dist/mesh/primitives.d.ts.map +1 -1
  38. package/dist/mesh/primitives.js +15 -8
  39. package/dist/mesh/primitives.js.map +1 -1
  40. package/dist/mesh/types.d.ts +4 -3
  41. package/dist/mesh/types.d.ts.map +1 -1
  42. package/dist/mesh/types.js.map +1 -1
  43. package/dist/primitives/brep-primitives.d.ts.map +1 -1
  44. package/dist/primitives/brep-primitives.js +39 -12
  45. package/dist/primitives/brep-primitives.js.map +1 -1
  46. package/dist/topology/naming/geom-hint.d.ts +12 -0
  47. package/dist/topology/naming/geom-hint.d.ts.map +1 -1
  48. package/dist/topology/naming/geom-hint.js +1 -1
  49. package/dist/topology/naming/geom-hint.js.map +1 -1
  50. package/dist/topology/naming/lineage.d.ts +1 -0
  51. package/dist/topology/naming/lineage.d.ts.map +1 -1
  52. package/dist/topology/naming/lineage.js +37 -1
  53. package/dist/topology/naming/lineage.js.map +1 -1
  54. package/dist/topology/naming/resolve-face.d.ts +13 -2
  55. package/dist/topology/naming/resolve-face.d.ts.map +1 -1
  56. package/dist/topology/naming/resolve-face.js +18 -2
  57. package/dist/topology/naming/resolve-face.js.map +1 -1
  58. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../../src/extra/ops/load.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAyBhD;;;;;;;;;GASG;AACH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,CAgK1F"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../../src/extra/ops/load.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AA4BhD;;;;;;;;;GASG;AACH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,CAkM1F"}
@@ -12,7 +12,10 @@
12
12
  import { importFile, detectStepUnit } from '../../mesh/io.js';
13
13
  import { isCadFormat } from '../../brep/brep-chain.js';
14
14
  import { loadBrepAssembly, loadBrepAssemblyNative, solidToShape, } from '../../brep/brep-ops.js';
15
+ import { weldToleranceFor } from '../../brep/mesh-solid.js';
15
16
  import { importBrepToMesh } from '../../occt-kernel/occtKernel.js';
17
+ import { reconstructSolidFromMesh } from '../../occt-kernel/meshReconstruct.js';
18
+ import { parseStl } from '../../mesh/stl-loader.js';
16
19
  import { OCCT_BREP_ENGINE_ID } from '../../brep/engine/adapters/occt.js';
17
20
  import { OpError } from '../../api/internal/result-unwrap.js';
18
21
  import { getBackends, BrepUnsupportedError, getCurrentStmt, setPendingDetectedUnit, setPendingImportModel, setPendingMeshSolid, setPendingMeshTopology, } from '../../runtime-state.js';
@@ -76,9 +79,15 @@ export async function load(params) {
76
79
  const buffer = (await assets.resolveByKey(file)).bytes;
77
80
  assertFileMagic(fmt, buffer, file);
78
81
  // 静态判定路径:mesh 模式 / 无 kernel / 非 CAD 源 → mesh 路径;否则 BREP 路径
82
+ // STL 特例(2026-10-17):brepkit/occt 的 L1 面都有 importStl——STL 可以在内核里
83
+ // 直接构造成**真 BREP 实体**(带面-边邻接),而不是走 importIndexedMesh→weld 的
84
+ // 网格路径。网格路径的产物在 brepkit 下无任何特征操作能力(边无邻接面、钻孔/分割
85
+ // 无实现);BREP 路径则圆角可选边、钻孔/分割走内核布尔,全链可用。**3MF 仍走 mesh
86
+ // 路径**(内核无 import3mf,三角网格只能 importIndexedMesh)。
79
87
  const { config, kernel: kernels } = getBackends();
80
88
  const kernel = kernels.brep;
81
- const useBrep = config.mode !== 'mesh' && !!kernel && isCadFormat({ format: fmt }, true);
89
+ const useBrep = config.mode !== 'mesh' && !!kernel &&
90
+ (isCadFormat({ format: fmt }, true) || fmt === 'stl');
82
91
  // brep 模式且将走 mesh-only 路径 → 调用前抛错,不静默回退
83
92
  if (!useBrep && config.mode === 'brep') {
84
93
  throw new BrepUnsupportedError('E_BREP_UNSUPPORTED: load op has no BREP implementation for this source');
@@ -138,7 +147,36 @@ export async function load(params) {
138
147
  };
139
148
  let brepParts;
140
149
  let assembly;
141
- if (fmt === 'brep' && hasXcafChannel) {
150
+ if (fmt === 'stl') {
151
+ // STL 原生 BREP 通道:kernel.importStl → 单实体(无装配层级;成员名 imported:0)。
152
+ // 与 loadBrepAssemblyNative 同一 L1 契约面;STL 无内部单位声明 → 默认 mm
153
+ // (detectStepUnit 对 STL 文本必然返回 null,registerDetectedUnit 落到 'mm')。
154
+ //
155
+ // importStl 的实体**逐面独立、边不共享**——直接用它,edge naming 没有邻接面
156
+ // (圆角选不了边)。缝合方式按内核分派(mesh 后端与 brep 引擎**同内核**才可用
157
+ // 其私有 weld 原语,句柄域必须一致):
158
+ // · brepkit(weapp):importStl → weld(缝共享边)→ unify(合并共面)——与
159
+ // mesh 路径 normalizeMeshSolid 同一规范化管线;
160
+ // · occt(web):网格 → OCCT 愈合管线 reconstructSolidFromMesh(importStl →
161
+ // fixShape → healSolid → unifySameDomain,见 occt-kernel/meshReconstruct.ts)——
162
+ // brepkit 的 weld 吃 brepkit 句柄,不能处理 occt 句柄。
163
+ const meshBackend = getBackends().kernel.meshSolid;
164
+ const canWeld = meshBackend !== undefined && meshBackend.kernel === kernel;
165
+ let solid;
166
+ if (canWeld) {
167
+ const imported = kernel.importStl(buffer);
168
+ const faces = kernel.getSubShapes(imported, 'face');
169
+ solid = meshBackend.ops.weld(faces, weldToleranceFor(kernel, imported));
170
+ meshBackend.ops.unify(solid);
171
+ kernel.release(imported);
172
+ }
173
+ else {
174
+ const parsed = parseStl(buffer);
175
+ solid = reconstructSolidFromMesh(kernel, parsed.positions, parsed.indices);
176
+ }
177
+ brepParts = [{ index: 0, name: file, shape: solidToShape(kernel, solid), solid, color: null }];
178
+ }
179
+ else if (fmt === 'brep' && hasXcafChannel) {
142
180
  // CASCADE BREP 文本(单 solid,无装配树):XCAF(STEPCAFControl_Reader)
143
181
  // 读不了 BREP 语法——occt 下唯一读取实现是 kernel.fromBREP(importBrepToMesh)。
144
182
  // 非 occt 引擎走下方 `loadBrepAssemblyNative`(同一 kernel.fromBREP,走契约面)。
@@ -1 +1 @@
1
- {"version":3,"file":"load.js","sourceRoot":"","sources":["../../../src/extra/ops/load.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * faijs-extra load — 加载库函数(统一 load 函数)\n *\n * file 指定资产名(用户上传文件名,不含路径、含后缀),经宿主资产解析器按名解析;\n * 格式由 file 后缀白名单自判(不依赖宿主 format 参数),isCadFormat 静态判定 brep/mesh,\n * 产物经 solid()/fromBrep() 构造器创建。\n *\n * @platform occt — 本文件 import `occt-kernel/occtKernel`(BREP 路径的 XCAF /\n * `importBrepToMesh` 平台面)。mesh 路径(STL/3MF)不依赖平台模块;本 op 无\n * `engines` 声明(不按 op 整体做引擎门,运行时按引擎能力静态分派,见下方注释)。\n */\n\nimport type { Shape } from '../../mesh/types'\nimport type { CompoundShape } from '../../shape'\nimport type { ImportModel, ImportAssemblyNode } from '../../mesh/import-model'\nimport { importFile, detectStepUnit } from '../../mesh/io'\nimport { isCadFormat } from '../../brep/brep-chain'\nimport {\n loadBrepAssembly, loadBrepAssemblyNative, solidToShape, type LoadBrepAssemblyPart,\n} from '../../brep/brep-ops'\nimport { importBrepToMesh } from '../../occt-kernel/occtKernel'\nimport { OCCT_BREP_ENGINE_ID } from '../../brep/engine/adapters/occt'\nimport type { BrepHandle } from '../../brep/engine/types'\nimport { OpError } from '../../api/internal/result-unwrap'\nimport {\n getBackends, BrepUnsupportedError, getCurrentStmt,\n setPendingDetectedUnit, setPendingImportModel,\n setPendingMeshSolid, setPendingMeshTopology,\n} from '../../runtime-state'\nimport { solid, compound, fromBrep, fromMeshSolid } from '../../shape'\nimport { UNIT_DIM, type UnitName } from '../../units'\nimport type { BrepEngineApi } from '../../brep/engine/primitives'\nimport { runtimeLineage } from '../../topology/naming/lineage'\nimport { asStmtId, type PartName } from '../../identity'\nimport { HASH_UPPER_BOUND } from '../../brep/face-evolution'\n// 只取**类型**:后端实现的运行时依赖(内核、拓扑构建器)留在 core,不进扩展库。\nimport type { MeshSolidBackend } from '../../brep/mesh-solid'\n\n/**\n * 执行加载操作(统一 load 函数)\n *\n * 按 params.file(资产名)从宿主资产库解析 buffer。\n *\n * 静态分派:\n * - CAD 源 + kernel + 非 mesh 模式 → BREP 路径(loadBrep 异常 = 未预期错误,冒泡上报)\n * - 非 CAD 源 / 无 kernel / mesh 模式 → mesh 路径\n * - brep 模式且将走 mesh 路径 → 调用前抛 BrepUnsupportedError(不静默回退)\n */\n/**\n * 加载几何资产。`file` 指定资产名(用户上传文件名,不含路径、含后缀),内容经宿主资产解析器按名解析,**引用而非拷贝**。\n * @group 创建\n * @inputs 0\n * @async true\n * @qual ok\n * @name load\n * @note 语言正常化后 loadFile/loadUrl/loadByKey 别名已删除(A4),统一为 `load` 一个函数。\n * @returns Shape 加载的几何,永远是 part 的第一条语句,后面可接特征链。\n * @param params.file - 资产文件名(用户上传名,不含路径、含后缀,如 'vise.3mf');内容按名从宿主资产库取。type:string\n * @param params.unit - **强制设置模型的源单位**:仅对无内部单位声明的 mesh 格式\n * (STL/3MF)有效——提供即覆盖/忽略模型内部记录的单位(3MF `<model unit>`),\n * 按指定单位折算坐标;只有调用方确实知道单位时才提供(用户手写脚本)。未提供\n * 时:STL faijs 启发式(guessStlUnit)、3MF 文件声明。**STEP/BREP 不支持**——\n * 走 OCCT 链、单位由文件内部声明决定(读取时折算),提供 unit 直接报错。type:string\n * @note 格式由 `file` 后缀白名单自判:stl/3mf → mesh 路径;step/stp/stpz/brep → BREP 路径。宿主不再传 `format`。\n * @note 后缀白名单未命中 → 报错(不猜格式);3MF 后缀会做 zip 魔数 sanity(后缀与内容明显不符时报错)。\n * @note 本 op 要求导入物含实体(历史契约)。非实体(wire/face/shell)的导入是平台 `cad.import_brep` 的一等能力,不由本 op 承担。\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用的「文件导入 Feature」提供——`file` 读的是应用侧资产库(按用户上传文件名注册),产物语句位置与命名都是画布语义。不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。2026-10-06 起多零件文件不再单零件收敛——全量以 compound + `ExecutionResult.importModels` 返回;宿主按 `importModel.parts` 身份批量建 part。\n * @example\n * const p = await cad.load({ file: 'box.stl' })\n * const p = await cad.load({ file: 'box.3mf' })\n * const p = await cad.load({ file: 'model.step' })\n */\nexport async function load(params: Record<string, unknown>): Promise<Shape | CompoundShape> {\n const assets = getBackends().assets as {\n resolveByKey(key: string): Promise<{ bytes: ArrayBuffer }>\n } | undefined\n if (!assets) {\n throw new OpError('load', 'E_OP_FAILED', '[extra/load] assets is required for load op')\n }\n\n // P8:参数面收敛为 file(资产名,不含路径、含后缀)。key/path/url/format 三键已删除。\n const file = params.file\n if (typeof file !== 'string' || file === '') {\n throw new OpError('load', 'E_ARGS_FORM', '[extra/load] load op requires a non-empty file (asset file name, no path)')\n }\n if (file.includes('/') || file.includes('\\\\')) {\n throw new OpError('load', 'E_ARGS_FORM', `[extra/load] file must not contain path separators: ${JSON.stringify(file)}`)\n }\n\n // 格式自判:file 后缀白名单 → 归一化格式;未命中即报错(不猜格式)。\n const fmt = formatFromFile(file)\n if (!fmt) {\n throw new OpError('load', 'E_ARGS_FORM', `[extra/load] unsupported file extension in: ${JSON.stringify(file)}`)\n }\n\n const buffer = (await assets.resolveByKey(file)).bytes\n assertFileMagic(fmt, buffer, file)\n\n // 静态判定路径:mesh 模式 / 无 kernel / 非 CAD 源 → mesh 路径;否则 BREP 路径\n const { config, kernel: kernels } = getBackends()\n const kernel = kernels.brep as BrepEngineApi | null\n const useBrep = config.mode !== 'mesh' && !!kernel && isCadFormat({ format: fmt }, true)\n\n // brep 模式且将走 mesh-only 路径 → 调用前抛错,不静默回退\n if (!useBrep && config.mode === 'brep') {\n throw new BrepUnsupportedError('E_BREP_UNSUPPORTED: load op has no BREP implementation for this source')\n }\n\n // mesh 路径:importFile 返回 { shape, parts, unit, importModel? } — unit 是文件\n // 源单位(必然有值;faijs 单一真源;元数据;坐标已是基准值)。opts.unit 强制\n // 设置源单位(mesh 格式:STL 直接折算;3MF 覆盖 `<model unit>` 声明);未提供\n // 时 STL 走 guessStlUnit 猜测、3MF 走文件声明。P0(方案 §5.4):多零件 mesh\n // (多 object 3MF)不再折叠——全量 parts 以 compound 返回 + importModel 登记;\n // 单零件保持现状(buildMeshPart)。\n if (!useBrep) {\n const opts = buildImportOpts(params.unit)\n const { shape, parts, unit, importModel } = await importFile(buffer, fmt, opts)\n registerDetectedUnit(unit)\n if (importModel) registerImportModel(importModel)\n if (parts.length > 1) {\n // 多零件:compound 全量返回(children 序 = parts.index = importModel.parts.index)。\n // 多零件的网格实体/近似拓扑登记属 P2(宿主按 compound.children 建 part 时处理)。\n return compound(parts)\n }\n return buildMeshPart(shape, file)\n }\n\n // BREP 路径(直接执行,不包 try-catch!异常 = 未预期错误,冒泡上报)\n // P2:brepChain(meshShapeCache)归引擎侧,loadBrepAssembly 不传。\n // P0(方案 §5.3):多 solid 文件经 XCAF 装配树全量导入——多零件返回 compound\n // (children 序 = parts.index),单零件返回单一 Shape(行为与现状一致)。\n // **不再接收/使用 partIndex**(取件点唯一,宿主不再拆)。\n // 单位(unit-system §5.2):STEP/.brep 走 OCCT 链——OCCT 读取时按文件内部\n // 单位声明折算(XCAF / fromBREP 均如此),**不支持用户强制设置单位**。因此\n // BREP 路径**拒绝 params.unit**:用户显式提供 unit → 明确报错(不缩放、不\n // workaround——缩放+重三角化会改变几何精度语义,且与文件声明矛盾)。\n // STL/3MF(mesh 路径,importFile)支持 opts.unit 强制折算(坐标可直接缩放)。\n const forcedUnit = buildImportOpts(params.unit)?.unit\n if (forcedUnit) {\n throw new OpError(\n 'load',\n 'E_ARGS_FORM',\n `[extra/load] ${JSON.stringify(file)}: unit 参数不支持 ${fmt}(STEP/BREP 走 OCCT 链,` +\n '单位由文件内部声明决定、读取时折算,OCCT 不支持强制设置单位);' +\n 'unit 仅支持无内部单位声明的 mesh 格式(STL/3MF)。',\n )\n }\n const text = new TextDecoder().decode(new Uint8Array(buffer))\n const declared = detectStepUnit(text) ?? 'mm'\n const hash = await contentHash(buffer)\n // key 带引擎 id(见 loadCache 注释):缓存值持有该内核的 BREP 句柄。\n const cacheKey = hash ? `${config.brepEngineId ?? '<none>'}:${hash}` : null\n // 装配读取通道(**静态**按引擎分派,无运行时回退):\n // - XCAF(`STEPCAFControl_Reader`)是 occt 内核的装配读取器 → 装配树 + 零件名/颜色;\n // - 其余引擎(brepkit)没有 XCAF → 走 L1 契约面的原生通道\n // `loadBrepAssemblyNative`(importStep/fromBREP + getSubShapes 枚举实体)。\n // 代价是零件身份只有 `imported:<i>`、无装配层级——引擎能力事实,非降级回退。\n const hasXcafChannel = config.brepEngineId === OCCT_BREP_ENGINE_ID\n /** 装配读取(无缓存):XCAF 通道产装配层级,原生通道无层级(引擎能力事实)。 */\n const readBrepParts = async (): Promise<{\n parts: LoadBrepAssemblyPart[]\n assembly?: ImportAssemblyNode\n }> => {\n if (!hasXcafChannel) return loadBrepAssemblyNative(kernel!, buffer)\n const r = await loadBrepAssembly(kernel!, buffer)\n return { parts: r.parts, ...(r.assembly ? { assembly: r.assembly } : {}) }\n }\n let brepParts: LoadBrepAssemblyPart[]\n let assembly: ImportAssemblyNode | undefined\n if (fmt === 'brep' && hasXcafChannel) {\n // CASCADE BREP 文本(单 solid,无装配树):XCAF(STEPCAFControl_Reader)\n // 读不了 BREP 语法——occt 下唯一读取实现是 kernel.fromBREP(importBrepToMesh)。\n // 非 occt 引擎走下方 `loadBrepAssemblyNative`(同一 kernel.fromBREP,走契约面)。\n // 产物与 STEP 单零件同构(fromBrep + solid 句柄,句柄归 brepChain 管理)。\n const imported = await importBrepToMesh(text)\n const handle = imported.shapeHandle as unknown as BrepHandle\n brepParts = [{ index: 0, name: file, shape: solidToShape(kernel!, handle), solid: handle, color: null }]\n } else if (cacheKey) {\n const cached = loadCache.get(cacheKey)\n if (cached) {\n brepParts = cached.parts\n assembly = cached.assembly\n } else {\n const r = await readBrepParts()\n brepParts = r.parts\n assembly = r.assembly\n loadCache.set(cacheKey, { parts: brepParts, assembly })\n }\n } else {\n const r = await readBrepParts()\n brepParts = r.parts\n assembly = r.assembly\n }\n // BREP 路径的源单位:文件声明(文本探测,无声明 → 'mm',与 OCCT 约定一致)。\n // unit 必然有值(faijs 单一真源),registerDetectedUnit 总是登记。\n registerDetectedUnit(declared)\n const importModel: ImportModel = {\n format: fmt === 'brep' ? 'brep' : 'step',\n unit: declared,\n parts: brepParts.map((p) => ({\n index: p.index,\n name: p.name,\n ...(p.color ? { color: p.color } : {}),\n })),\n ...(assembly ? { assembly } : {}),\n }\n registerImportModel(importModel)\n if (brepParts.length === 1) {\n const p = brepParts[0]\n return buildBrepPart(kernel, p, getCurrentStmt()?.outputs[0])\n }\n // 多零件:每个 child 带自己的 BREP solid(宿主经 brepOf(child) 读取)+\n // 逐成员 roleTable;终端合并表按同一 StmtId 落 statement 键 + part 键。\n const stmtId = String(getCurrentStmt()?.id ?? '')\n const mergedRoles = new Map<string, number[]>()\n const children = brepParts.map((p, idx) => {\n const memberRoles = buildImportedRoles(kernel, p.solid, idx)\n for (const [role, hashes] of memberRoles) mergedRoles.set(role, hashes)\n return fromBrep(p.shape, {\n solid: p.solid,\n roleTable: new Map([[stmtId, memberRoles]]),\n })\n })\n const out = compound(children)\n if (stmtId) {\n const part = getCurrentStmt()?.outputs[0]\n // load 是裸 async 函数(不经 defineOp 包装),part 键 roleTable 不会由\n // 包装层登记(import-step.ts GOTCHA 注释)——必须手动落 part 键,否则\n // 下游 edgeRef/chamfer 报 \"input shape has no role table (nameless shape)\"。\n runtimeLineage.recordOutput(asStmtId(stmtId), new Map([[stmtId, mergedRoles]]), undefined, part)\n }\n return out\n}\n\n/**\n * 单零件 BREP 链根:fromBrep + roleTable,statement 键与 part 键同时登记。\n *\n * 与 `import-step.ts:74-80` 同构(方案 2026-09-18 §5.1:链根建 roleTable——\n * 导入文件的面没有语义名,按枚举序命名 `imported:<i>`,同一文件重复导入\n * 枚举序稳定,role 名跨次导入保持一致)。与 import_step 的差异:load 是裸\n * async 函数(不经 defineOp),part 键 roleTable(outputTablesByPart)不会\n * 由包装层登记,必须在此手动 `runtimeLineage.recordOutput(..., part)` 落\n * part 键——否则 `buildNamingInput` 的 roleTableCache 为空、`edgeRef` 的\n * `tableOfPart` 为空,STEP 导入件所有边 faces===null(倒角/圆角被禁用)。\n */\nfunction buildBrepPart(\n kernel: BrepEngineApi,\n p: LoadBrepAssemblyPart,\n part: PartName | undefined,\n): Shape {\n const stmtId = String(getCurrentStmt()?.id ?? '')\n const roles = buildImportedRoles(kernel, p.solid)\n // recordOutput 的 roleTable 形参外层键是 string(宽松 map),不声明成\n // RoleTable(外层键 StmtId)——避免空 stmt 时 '' 键触发类型不符。\n const table = new Map<string, Map<string, number[]>>([[stmtId, roles]])\n const shape = fromBrep(p.shape, { solid: p.solid, roleTable: table })\n if (stmtId) {\n runtimeLineage.recordOutput(asStmtId(stmtId), table, p.solid, part)\n }\n return shape\n}\n\n/**\n * 导入面按枚举序命名(E3 / H12,与 import-step.ts 同构)。\n *\n * - 单零件:`imported:<i>`(i = 内核面枚举序,0 起);\n * - 多零件 compound 成员:`imported:<memberIdx>:<i>`——同一 StmtId 下\n * 逐成员 role 键唯一(方案 2026-09-18 §7.5 的 origin 撞名红线 / 评审\n * P0-2):几何相同的成员(如装配中两个同型件)面 hash 会相同,若都用\n * 裸 `imported:<i>` 会在合并表的 `roleOfOrdinal` 里撞名。\n */\nfunction buildImportedRoles(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n memberIdx?: number,\n): Map<string, number[]> {\n const hashes = kernel.subShapeHashes(solid, 'face', HASH_UPPER_BOUND)\n const prefix = memberIdx === undefined ? '' : `${memberIdx}:`\n const roles = new Map<string, number[]>()\n for (let i = 0; i < hashes.length; i++) {\n roles.set(`imported:${prefix}${i}`, [hashes[i]!])\n }\n return roles\n}\n\n/**\n * mesh 路径产物构造:装了网格后端则产出**网格实体 + 近似拓扑**,否则退回裸网格。\n *\n * 两条分支的边界(方案 2026-10-01 §3.3):\n * - **未装配网格后端**(`kernel.meshSolid` 缺失)→ `solid(shape)`。这是宿主的装配\n * 事实(如小程序构建不装 brepkit),不是静默降级:该 part 本来就没有网格内核可用。\n * - **装配了但规范化失败**(开放/非流形/自交网格)→ **抛错**,绝不退化成\"无拓扑的\n * 裸网格\"——那会让所有下游 mesh op 失去选择能力,属于\"报错好于掩盖\"。\n *\n * 显示 mesh 用**网格实体的三角化**而不是原始 STL 顶点数组:规则 1(拓扑 faceRuns\n * 所索引的三角形必须就是用户看到的三角形)。用原始 STL 数组 + 实体重新三角化会让\n * 两者三角形数/序错位,faceRuns 直接失效。\n *\n * @param shape - the parsed mesh payload (base-unit coordinates).\n * @param file - the source file name (error messages).\n * @returns the constructed shape (mesh solid when a backend is assembled).\n */\nfunction buildMeshPart(shape: Shape, file: string): Shape {\n const backend = getBackends().kernel.meshSolid as MeshSolidBackend | undefined\n if (!backend) return solid(shape)\n\n const part = getCurrentStmt()?.outputs[0]\n let result: ReturnType<MeshSolidBackend['normalize']>\n try {\n result = backend.normalize({ positions: shape.positions, indices: shape.indices })\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err)\n throw new OpError(\n 'load',\n 'E_MESH_SOLID_UNWELDABLE',\n `E_MESH_SOLID_UNWELDABLE: [extra/load] ${JSON.stringify(file)} could not be normalized into a mesh solid` +\n `${part ? ` (part \"${part}\")` : ''}: ${reason}`,\n { cause: err },\n )\n }\n\n // 句柄 + 近似拓扑登记:load op 拿不到 CadRuntime 实例,故走 pending 通道\n // (与 detectedUnit / multiPartCount 同模式),引擎在语句执行后收编。\n if (part) {\n setPendingMeshSolid(part, result.solid)\n setPendingMeshTopology(part, backend.buildTopologyData(result))\n }\n return fromMeshSolid(\n { positions: result.mesh.positions, indices: result.mesh.indices },\n { meshSolid: result.solid },\n )\n}\n\n/**\n * 文件级解析缓存(P2,2026-10-06):按文件内容 SHA-256 缓存解析产物。\n *\n * 背景:execute 全量重放时同一文件会被反复解析(e2e 重放序列 3 次 execute × 2 条\n * load 语句 = 6 次 XCAF 解析)。occt-wasm 在 Web Worker 环境下每次 XCAF 解析都会\n * 累积 OCCT 资源,约第 6 次解析后 BOP(common/cut)整体挂死(node 环境不复现,\n * 内存充足)。缓存命中后同一文件全量重放只解析一次,既根治 worker BOP 挂死,\n * 也消除重复解析/三角化的成本。\n *\n * 缓存 key = **引擎 id + 内容 SHA-256**(不按文件名——同名文件内容可不同,内容指纹\n * 才可靠)。带上引擎 id 是因为缓存值持有**该内核的** BREP 句柄:换引擎(或换内核\n * 版本)后旧句柄对新内核无效,仅按内容指纹做 key 会把 A 引擎的句柄交给 B 引擎。\n * 缓存持有解析产物(compound 的 BREP solid 句柄等),与 statementCache 同生命周期\n * (runtime 级;worker 重建时模块重载自然清空)。缓存只是优化:digest 计算失败时\n * 跳过缓存(功能等价,不静默降级语义)。\n */\nconst loadCache = new Map<string, { parts: LoadBrepAssemblyPart[]; assembly?: ImportAssemblyNode }>()\n\nasync function contentHash(buffer: ArrayBuffer): Promise<string | null> {\n try {\n const digest = await globalThis.crypto.subtle.digest('SHA-256', buffer)\n return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, '0')).join('')\n } catch {\n return null // 无 WebCrypto(罕见环境):跳过缓存,功能等价\n }\n}\n\n/**\n * 文件加载白名单(P8 §4.2/§4.3,与 3d_editor config/file-formats 的 CAD 模型扩展名对齐):\n * mesh 路径 stl/3mf;BREP 路径 step/stp/stpz/brep。\n * iges/igs 刻意不在白名单——occt-wasm 未链接 TKDEIGES(brep-chain CAD_FORMATS 注释),\n * 走 BREP 路径必然失败;报「不支持的扩展名」比报内核错误更清晰。宿主 iges 现状路径保留。\n * 返回归一化格式:stp/stpz → 'step',其余原样;白名单未命中返回 undefined。\n */\nconst LOAD_EXTENSION_WHITELIST: Record<string, string> = {\n stl: 'stl',\n '3mf': '3mf',\n step: 'step',\n stp: 'step',\n stpz: 'step',\n brep: 'brep',\n}\n\nfunction formatFromFile(file: string): string | undefined {\n const ext = file.split('.').pop()?.toLowerCase() ?? ''\n return LOAD_EXTENSION_WHITELIST[ext]\n}\n\n/**\n * 魔数 sanity(P8 §4.3):后缀定格式后用文件头校验,后缀与内容明显不符时报错。\n * 仅 3MF 做显式魔数(zip 头 PK\\x03\\x04 / PK\\x05\\x06,可靠且歧义小);\n * STL(文本/二进制歧义)、STEP/IGES/BREP(文本格式)不做魔数,由各解析器内部消歧/报错——\n * 遵循「解析外部数据必须宽容」红线:只有可靠判据才拒绝,不误伤正常文件。\n */\nfunction assertFileMagic(fmt: string, buffer: ArrayBuffer, file: string): void {\n if (fmt !== '3mf') return\n const bytes = new Uint8Array(buffer.slice(0, 4))\n const isZip = bytes[0] === 0x50 && bytes[1] === 0x4b && (bytes[2] === 0x03 || bytes[2] === 0x05)\n if (!isZip) {\n throw new OpError(\n 'load',\n 'E_ARGS_FORM',\n `[extra/load] file ${JSON.stringify(file)} has .3mf extension but content is not a 3MF archive`,\n )\n }\n}\n\n/**\n * params.unit(UnitName 字符串,固化在脚本行里)→ importFile 的 opts.unit。\n * 契约(unit-system §5.2):提供即**强制设置模型的源单位**——只对无内部单位\n * 声明、坐标可直接折算的 mesh 格式(STL/3MF)有效;STEP/BREP 走 OCCT 链\n * (单位由文件内部声明决定),unit 参数由 load op 在 BREP 路径**明确报错**,\n * 不在此处拦截(保持 importFile 对 mesh 格式的单一职责)。非法/非长度单位\n * 直接报错。\n */\nfunction buildImportOpts(unitParam: unknown): { unit: UnitName } | undefined {\n if (typeof unitParam !== 'string' || unitParam === '') return undefined\n if (UNIT_DIM[unitParam as UnitName] !== 'length') {\n throw new OpError('load', 'E_ARGS_FORM', `[extra/load] unknown or non-length unit: ${JSON.stringify(unitParam)}`)\n }\n return { unit: unitParam as UnitName }\n}\n\n/** Register the file's source unit for the current statement's output part. */\nfunction registerDetectedUnit(unit: UnitName): void {\n const stmt = getCurrentStmt()\n const part = stmt?.outputs[0]\n if (part) setPendingDetectedUnit(part, unit)\n}\n\n/**\n * Register the current statement's output part's import model (P0,方案\n * 2026-10-06-step-3mf-multipart-import-plan.md §5.5): the structure data\n * (parts identity table + STEP assembly + Bambu views) of a `cad.load`.\n * 单/多零件均登记(单零件 parts 长度 1)。引擎在语句执行后收编进\n * ExecutionResult.importModels,宿主据此批量建 part,不再自行解析文件。\n */\nfunction registerImportModel(model: ImportModel): void {\n const stmt = getCurrentStmt()\n const part = stmt?.outputs[0]\n if (part) setPendingImportModel(part, model)\n}\n"]}
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../../src/extra/ops/load.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * faijs-extra load — 加载库函数(统一 load 函数)\n *\n * file 指定资产名(用户上传文件名,不含路径、含后缀),经宿主资产解析器按名解析;\n * 格式由 file 后缀白名单自判(不依赖宿主 format 参数),isCadFormat 静态判定 brep/mesh,\n * 产物经 solid()/fromBrep() 构造器创建。\n *\n * @platform occt — 本文件 import `occt-kernel/occtKernel`(BREP 路径的 XCAF /\n * `importBrepToMesh` 平台面)。mesh 路径(STL/3MF)不依赖平台模块;本 op 无\n * `engines` 声明(不按 op 整体做引擎门,运行时按引擎能力静态分派,见下方注释)。\n */\n\nimport type { Shape } from '../../mesh/types'\nimport type { CompoundShape } from '../../shape'\nimport type { ImportModel, ImportAssemblyNode } from '../../mesh/import-model'\nimport { importFile, detectStepUnit } from '../../mesh/io'\nimport { isCadFormat } from '../../brep/brep-chain'\nimport {\n loadBrepAssembly, loadBrepAssemblyNative, solidToShape, type LoadBrepAssemblyPart,\n} from '../../brep/brep-ops'\nimport { weldToleranceFor } from '../../brep/mesh-solid'\nimport { importBrepToMesh } from '../../occt-kernel/occtKernel'\nimport { reconstructSolidFromMesh } from '../../occt-kernel/meshReconstruct'\nimport { parseStl } from '../../mesh/stl-loader'\nimport { OCCT_BREP_ENGINE_ID } from '../../brep/engine/adapters/occt'\nimport type { BrepHandle } from '../../brep/engine/types'\nimport { OpError } from '../../api/internal/result-unwrap'\nimport {\n getBackends, BrepUnsupportedError, getCurrentStmt,\n setPendingDetectedUnit, setPendingImportModel,\n setPendingMeshSolid, setPendingMeshTopology,\n} from '../../runtime-state'\nimport { solid, compound, fromBrep, fromMeshSolid } from '../../shape'\nimport { UNIT_DIM, type UnitName } from '../../units'\nimport type { BrepEngineApi } from '../../brep/engine/primitives'\nimport { runtimeLineage } from '../../topology/naming/lineage'\nimport { asStmtId, type PartName } from '../../identity'\nimport { HASH_UPPER_BOUND } from '../../brep/face-evolution'\n// 只取**类型**:后端实现的运行时依赖(内核、拓扑构建器)留在 core,不进扩展库。\nimport type { MeshSolidBackend } from '../../brep/mesh-solid'\n\n/**\n * 执行加载操作(统一 load 函数)\n *\n * 按 params.file(资产名)从宿主资产库解析 buffer。\n *\n * 静态分派:\n * - CAD 源 + kernel + 非 mesh 模式 → BREP 路径(loadBrep 异常 = 未预期错误,冒泡上报)\n * - 非 CAD 源 / 无 kernel / mesh 模式 → mesh 路径\n * - brep 模式且将走 mesh 路径 → 调用前抛 BrepUnsupportedError(不静默回退)\n */\n/**\n * 加载几何资产。`file` 指定资产名(用户上传文件名,不含路径、含后缀),内容经宿主资产解析器按名解析,**引用而非拷贝**。\n * @group 创建\n * @inputs 0\n * @async true\n * @qual ok\n * @name load\n * @note 语言正常化后 loadFile/loadUrl/loadByKey 别名已删除(A4),统一为 `load` 一个函数。\n * @returns Shape 加载的几何,永远是 part 的第一条语句,后面可接特征链。\n * @param params.file - 资产文件名(用户上传名,不含路径、含后缀,如 'vise.3mf');内容按名从宿主资产库取。type:string\n * @param params.unit - **强制设置模型的源单位**:仅对无内部单位声明的 mesh 格式\n * (STL/3MF)有效——提供即覆盖/忽略模型内部记录的单位(3MF `<model unit>`),\n * 按指定单位折算坐标;只有调用方确实知道单位时才提供(用户手写脚本)。未提供\n * 时:STL faijs 启发式(guessStlUnit)、3MF 文件声明。**STEP/BREP 不支持**——\n * 走 OCCT 链、单位由文件内部声明决定(读取时折算),提供 unit 直接报错。type:string\n * @note 格式由 `file` 后缀白名单自判:stl/3mf → mesh 路径;step/stp/stpz/brep → BREP 路径。宿主不再传 `format`。\n * @note 后缀白名单未命中 → 报错(不猜格式);3MF 后缀会做 zip 魔数 sanity(后缀与内容明显不符时报错)。\n * @note 本 op 要求导入物含实体(历史契约)。非实体(wire/face/shell)的导入是平台 `cad.import_brep` 的一等能力,不由本 op 承担。\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用的「文件导入 Feature」提供——`file` 读的是应用侧资产库(按用户上传文件名注册),产物语句位置与命名都是画布语义。不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**。2026-10-06 起多零件文件不再单零件收敛——全量以 compound + `ExecutionResult.importModels` 返回;宿主按 `importModel.parts` 身份批量建 part。\n * @example\n * const p = await cad.load({ file: 'box.stl' })\n * const p = await cad.load({ file: 'box.3mf' })\n * const p = await cad.load({ file: 'model.step' })\n */\nexport async function load(params: Record<string, unknown>): Promise<Shape | CompoundShape> {\n const assets = getBackends().assets as {\n resolveByKey(key: string): Promise<{ bytes: ArrayBuffer }>\n } | undefined\n if (!assets) {\n throw new OpError('load', 'E_OP_FAILED', '[extra/load] assets is required for load op')\n }\n\n // P8:参数面收敛为 file(资产名,不含路径、含后缀)。key/path/url/format 三键已删除。\n const file = params.file\n if (typeof file !== 'string' || file === '') {\n throw new OpError('load', 'E_ARGS_FORM', '[extra/load] load op requires a non-empty file (asset file name, no path)')\n }\n if (file.includes('/') || file.includes('\\\\')) {\n throw new OpError('load', 'E_ARGS_FORM', `[extra/load] file must not contain path separators: ${JSON.stringify(file)}`)\n }\n\n // 格式自判:file 后缀白名单 → 归一化格式;未命中即报错(不猜格式)。\n const fmt = formatFromFile(file)\n if (!fmt) {\n throw new OpError('load', 'E_ARGS_FORM', `[extra/load] unsupported file extension in: ${JSON.stringify(file)}`)\n }\n\n const buffer = (await assets.resolveByKey(file)).bytes\n assertFileMagic(fmt, buffer, file)\n\n // 静态判定路径:mesh 模式 / 无 kernel / 非 CAD 源 → mesh 路径;否则 BREP 路径\n // STL 特例(2026-10-17):brepkit/occt 的 L1 面都有 importStl——STL 可以在内核里\n // 直接构造成**真 BREP 实体**(带面-边邻接),而不是走 importIndexedMesh→weld 的\n // 网格路径。网格路径的产物在 brepkit 下无任何特征操作能力(边无邻接面、钻孔/分割\n // 无实现);BREP 路径则圆角可选边、钻孔/分割走内核布尔,全链可用。**3MF 仍走 mesh\n // 路径**(内核无 import3mf,三角网格只能 importIndexedMesh)。\n const { config, kernel: kernels } = getBackends()\n const kernel = kernels.brep as BrepEngineApi | null\n const useBrep =\n config.mode !== 'mesh' && !!kernel &&\n (isCadFormat({ format: fmt }, true) || fmt === 'stl')\n\n // brep 模式且将走 mesh-only 路径 → 调用前抛错,不静默回退\n if (!useBrep && config.mode === 'brep') {\n throw new BrepUnsupportedError('E_BREP_UNSUPPORTED: load op has no BREP implementation for this source')\n }\n\n // mesh 路径:importFile 返回 { shape, parts, unit, importModel? } — unit 是文件\n // 源单位(必然有值;faijs 单一真源;元数据;坐标已是基准值)。opts.unit 强制\n // 设置源单位(mesh 格式:STL 直接折算;3MF 覆盖 `<model unit>` 声明);未提供\n // 时 STL 走 guessStlUnit 猜测、3MF 走文件声明。P0(方案 §5.4):多零件 mesh\n // (多 object 3MF)不再折叠——全量 parts 以 compound 返回 + importModel 登记;\n // 单零件保持现状(buildMeshPart)。\n if (!useBrep) {\n const opts = buildImportOpts(params.unit)\n const { shape, parts, unit, importModel } = await importFile(buffer, fmt, opts)\n registerDetectedUnit(unit)\n if (importModel) registerImportModel(importModel)\n if (parts.length > 1) {\n // 多零件:compound 全量返回(children 序 = parts.index = importModel.parts.index)。\n // 多零件的网格实体/近似拓扑登记属 P2(宿主按 compound.children 建 part 时处理)。\n return compound(parts)\n }\n return buildMeshPart(shape, file)\n }\n\n // BREP 路径(直接执行,不包 try-catch!异常 = 未预期错误,冒泡上报)\n // P2:brepChain(meshShapeCache)归引擎侧,loadBrepAssembly 不传。\n // P0(方案 §5.3):多 solid 文件经 XCAF 装配树全量导入——多零件返回 compound\n // (children 序 = parts.index),单零件返回单一 Shape(行为与现状一致)。\n // **不再接收/使用 partIndex**(取件点唯一,宿主不再拆)。\n // 单位(unit-system §5.2):STEP/.brep 走 OCCT 链——OCCT 读取时按文件内部\n // 单位声明折算(XCAF / fromBREP 均如此),**不支持用户强制设置单位**。因此\n // BREP 路径**拒绝 params.unit**:用户显式提供 unit → 明确报错(不缩放、不\n // workaround——缩放+重三角化会改变几何精度语义,且与文件声明矛盾)。\n // STL/3MF(mesh 路径,importFile)支持 opts.unit 强制折算(坐标可直接缩放)。\n const forcedUnit = buildImportOpts(params.unit)?.unit\n if (forcedUnit) {\n throw new OpError(\n 'load',\n 'E_ARGS_FORM',\n `[extra/load] ${JSON.stringify(file)}: unit 参数不支持 ${fmt}(STEP/BREP 走 OCCT 链,` +\n '单位由文件内部声明决定、读取时折算,OCCT 不支持强制设置单位);' +\n 'unit 仅支持无内部单位声明的 mesh 格式(STL/3MF)。',\n )\n }\n const text = new TextDecoder().decode(new Uint8Array(buffer))\n const declared = detectStepUnit(text) ?? 'mm'\n const hash = await contentHash(buffer)\n // key 带引擎 id(见 loadCache 注释):缓存值持有该内核的 BREP 句柄。\n const cacheKey = hash ? `${config.brepEngineId ?? '<none>'}:${hash}` : null\n // 装配读取通道(**静态**按引擎分派,无运行时回退):\n // - XCAF(`STEPCAFControl_Reader`)是 occt 内核的装配读取器 → 装配树 + 零件名/颜色;\n // - 其余引擎(brepkit)没有 XCAF → 走 L1 契约面的原生通道\n // `loadBrepAssemblyNative`(importStep/fromBREP + getSubShapes 枚举实体)。\n // 代价是零件身份只有 `imported:<i>`、无装配层级——引擎能力事实,非降级回退。\n const hasXcafChannel = config.brepEngineId === OCCT_BREP_ENGINE_ID\n /** 装配读取(无缓存):XCAF 通道产装配层级,原生通道无层级(引擎能力事实)。 */\n const readBrepParts = async (): Promise<{\n parts: LoadBrepAssemblyPart[]\n assembly?: ImportAssemblyNode\n }> => {\n if (!hasXcafChannel) return loadBrepAssemblyNative(kernel!, buffer)\n const r = await loadBrepAssembly(kernel!, buffer)\n return { parts: r.parts, ...(r.assembly ? { assembly: r.assembly } : {}) }\n }\n let brepParts: LoadBrepAssemblyPart[]\n let assembly: ImportAssemblyNode | undefined\n if (fmt === 'stl') {\n // STL 原生 BREP 通道:kernel.importStl → 单实体(无装配层级;成员名 imported:0)。\n // 与 loadBrepAssemblyNative 同一 L1 契约面;STL 无内部单位声明 → 默认 mm\n // (detectStepUnit 对 STL 文本必然返回 null,registerDetectedUnit 落到 'mm')。\n //\n // importStl 的实体**逐面独立、边不共享**——直接用它,edge naming 没有邻接面\n // (圆角选不了边)。缝合方式按内核分派(mesh 后端与 brep 引擎**同内核**才可用\n // 其私有 weld 原语,句柄域必须一致):\n // · brepkit(weapp):importStl → weld(缝共享边)→ unify(合并共面)——与\n // mesh 路径 normalizeMeshSolid 同一规范化管线;\n // · occt(web):网格 → OCCT 愈合管线 reconstructSolidFromMesh(importStl →\n // fixShape → healSolid → unifySameDomain,见 occt-kernel/meshReconstruct.ts)——\n // brepkit 的 weld 吃 brepkit 句柄,不能处理 occt 句柄。\n const meshBackend = getBackends().kernel.meshSolid as MeshSolidBackend | undefined\n const canWeld = meshBackend !== undefined && meshBackend.kernel === kernel\n let solid: BrepHandle\n if (canWeld) {\n const imported = kernel!.importStl(buffer)\n const faces = kernel!.getSubShapes(imported, 'face')\n solid = meshBackend!.ops.weld(faces, weldToleranceFor(kernel!, imported))\n meshBackend!.ops.unify(solid)\n kernel!.release(imported)\n } else {\n const parsed = parseStl(buffer)\n solid = reconstructSolidFromMesh(kernel!, parsed.positions, parsed.indices)\n }\n brepParts = [{ index: 0, name: file, shape: solidToShape(kernel!, solid), solid, color: null }]\n } else if (fmt === 'brep' && hasXcafChannel) {\n // CASCADE BREP 文本(单 solid,无装配树):XCAF(STEPCAFControl_Reader)\n // 读不了 BREP 语法——occt 下唯一读取实现是 kernel.fromBREP(importBrepToMesh)。\n // 非 occt 引擎走下方 `loadBrepAssemblyNative`(同一 kernel.fromBREP,走契约面)。\n // 产物与 STEP 单零件同构(fromBrep + solid 句柄,句柄归 brepChain 管理)。\n const imported = await importBrepToMesh(text)\n const handle = imported.shapeHandle as unknown as BrepHandle\n brepParts = [{ index: 0, name: file, shape: solidToShape(kernel!, handle), solid: handle, color: null }]\n } else if (cacheKey) {\n const cached = loadCache.get(cacheKey)\n if (cached) {\n brepParts = cached.parts\n assembly = cached.assembly\n } else {\n const r = await readBrepParts()\n brepParts = r.parts\n assembly = r.assembly\n loadCache.set(cacheKey, { parts: brepParts, assembly })\n }\n } else {\n const r = await readBrepParts()\n brepParts = r.parts\n assembly = r.assembly\n }\n // BREP 路径的源单位:文件声明(文本探测,无声明 → 'mm',与 OCCT 约定一致)。\n // unit 必然有值(faijs 单一真源),registerDetectedUnit 总是登记。\n registerDetectedUnit(declared)\n const importModel: ImportModel = {\n format: fmt === 'brep' ? 'brep' : 'step',\n unit: declared,\n parts: brepParts.map((p) => ({\n index: p.index,\n name: p.name,\n ...(p.color ? { color: p.color } : {}),\n })),\n ...(assembly ? { assembly } : {}),\n }\n registerImportModel(importModel)\n if (brepParts.length === 1) {\n const p = brepParts[0]\n return buildBrepPart(kernel, p, getCurrentStmt()?.outputs[0])\n }\n // 多零件:每个 child 带自己的 BREP solid(宿主经 brepOf(child) 读取)+\n // 逐成员 roleTable;终端合并表按同一 StmtId 落 statement 键 + part 键。\n const stmtId = String(getCurrentStmt()?.id ?? '')\n const mergedRoles = new Map<string, number[]>()\n const children = brepParts.map((p, idx) => {\n const memberRoles = buildImportedRoles(kernel, p.solid, idx)\n for (const [role, hashes] of memberRoles) mergedRoles.set(role, hashes)\n return fromBrep(p.shape, {\n solid: p.solid,\n roleTable: new Map([[stmtId, memberRoles]]),\n })\n })\n const out = compound(children)\n if (stmtId) {\n const part = getCurrentStmt()?.outputs[0]\n // load 是裸 async 函数(不经 defineOp 包装),part 键 roleTable 不会由\n // 包装层登记(import-step.ts GOTCHA 注释)——必须手动落 part 键,否则\n // 下游 edgeRef/chamfer 报 \"input shape has no role table (nameless shape)\"。\n runtimeLineage.recordOutput(asStmtId(stmtId), new Map([[stmtId, mergedRoles]]), undefined, part)\n }\n return out\n}\n\n/**\n * 单零件 BREP 链根:fromBrep + roleTable,statement 键与 part 键同时登记。\n *\n * 与 `import-step.ts:74-80` 同构(方案 2026-09-18 §5.1:链根建 roleTable——\n * 导入文件的面没有语义名,按枚举序命名 `imported:<i>`,同一文件重复导入\n * 枚举序稳定,role 名跨次导入保持一致)。与 import_step 的差异:load 是裸\n * async 函数(不经 defineOp),part 键 roleTable(outputTablesByPart)不会\n * 由包装层登记,必须在此手动 `runtimeLineage.recordOutput(..., part)` 落\n * part 键——否则 `buildNamingInput` 的 roleTableCache 为空、`edgeRef` 的\n * `tableOfPart` 为空,STEP 导入件所有边 faces===null(倒角/圆角被禁用)。\n */\nfunction buildBrepPart(\n kernel: BrepEngineApi,\n p: LoadBrepAssemblyPart,\n part: PartName | undefined,\n): Shape {\n const stmtId = String(getCurrentStmt()?.id ?? '')\n const roles = buildImportedRoles(kernel, p.solid)\n // recordOutput 的 roleTable 形参外层键是 string(宽松 map),不声明成\n // RoleTable(外层键 StmtId)——避免空 stmt 时 '' 键触发类型不符。\n const table = new Map<string, Map<string, number[]>>([[stmtId, roles]])\n const shape = fromBrep(p.shape, { solid: p.solid, roleTable: table })\n if (stmtId) {\n runtimeLineage.recordOutput(asStmtId(stmtId), table, p.solid, part)\n }\n return shape\n}\n\n/**\n * 导入面按枚举序命名(E3 / H12,与 import-step.ts 同构)。\n *\n * - 单零件:`imported:<i>`(i = 内核面枚举序,0 起);\n * - 多零件 compound 成员:`imported:<memberIdx>:<i>`——同一 StmtId 下\n * 逐成员 role 键唯一(方案 2026-09-18 §7.5 的 origin 撞名红线 / 评审\n * P0-2):几何相同的成员(如装配中两个同型件)面 hash 会相同,若都用\n * 裸 `imported:<i>` 会在合并表的 `roleOfOrdinal` 里撞名。\n */\nfunction buildImportedRoles(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n memberIdx?: number,\n): Map<string, number[]> {\n const hashes = kernel.subShapeHashes(solid, 'face', HASH_UPPER_BOUND)\n const prefix = memberIdx === undefined ? '' : `${memberIdx}:`\n const roles = new Map<string, number[]>()\n for (let i = 0; i < hashes.length; i++) {\n roles.set(`imported:${prefix}${i}`, [hashes[i]!])\n }\n return roles\n}\n\n/**\n * mesh 路径产物构造:装了网格后端则产出**网格实体 + 近似拓扑**,否则退回裸网格。\n *\n * 两条分支的边界(方案 2026-10-01 §3.3):\n * - **未装配网格后端**(`kernel.meshSolid` 缺失)→ `solid(shape)`。这是宿主的装配\n * 事实(如小程序构建不装 brepkit),不是静默降级:该 part 本来就没有网格内核可用。\n * - **装配了但规范化失败**(开放/非流形/自交网格)→ **抛错**,绝不退化成\"无拓扑的\n * 裸网格\"——那会让所有下游 mesh op 失去选择能力,属于\"报错好于掩盖\"。\n *\n * 显示 mesh 用**网格实体的三角化**而不是原始 STL 顶点数组:规则 1(拓扑 faceRuns\n * 所索引的三角形必须就是用户看到的三角形)。用原始 STL 数组 + 实体重新三角化会让\n * 两者三角形数/序错位,faceRuns 直接失效。\n *\n * @param shape - the parsed mesh payload (base-unit coordinates).\n * @param file - the source file name (error messages).\n * @returns the constructed shape (mesh solid when a backend is assembled).\n */\nfunction buildMeshPart(shape: Shape, file: string): Shape {\n const backend = getBackends().kernel.meshSolid as MeshSolidBackend | undefined\n if (!backend) return solid(shape)\n\n const part = getCurrentStmt()?.outputs[0]\n let result: ReturnType<MeshSolidBackend['normalize']>\n try {\n result = backend.normalize({ positions: shape.positions, indices: shape.indices })\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err)\n throw new OpError(\n 'load',\n 'E_MESH_SOLID_UNWELDABLE',\n `E_MESH_SOLID_UNWELDABLE: [extra/load] ${JSON.stringify(file)} could not be normalized into a mesh solid` +\n `${part ? ` (part \"${part}\")` : ''}: ${reason}`,\n { cause: err },\n )\n }\n\n // 句柄 + 近似拓扑登记:load op 拿不到 CadRuntime 实例,故走 pending 通道\n // (与 detectedUnit / multiPartCount 同模式),引擎在语句执行后收编。\n if (part) {\n setPendingMeshSolid(part, result.solid)\n setPendingMeshTopology(part, backend.buildTopologyData(result))\n }\n return fromMeshSolid(\n { positions: result.mesh.positions, indices: result.mesh.indices },\n { meshSolid: result.solid },\n )\n}\n\n/**\n * 文件级解析缓存(P2,2026-10-06):按文件内容 SHA-256 缓存解析产物。\n *\n * 背景:execute 全量重放时同一文件会被反复解析(e2e 重放序列 3 次 execute × 2 条\n * load 语句 = 6 次 XCAF 解析)。occt-wasm 在 Web Worker 环境下每次 XCAF 解析都会\n * 累积 OCCT 资源,约第 6 次解析后 BOP(common/cut)整体挂死(node 环境不复现,\n * 内存充足)。缓存命中后同一文件全量重放只解析一次,既根治 worker BOP 挂死,\n * 也消除重复解析/三角化的成本。\n *\n * 缓存 key = **引擎 id + 内容 SHA-256**(不按文件名——同名文件内容可不同,内容指纹\n * 才可靠)。带上引擎 id 是因为缓存值持有**该内核的** BREP 句柄:换引擎(或换内核\n * 版本)后旧句柄对新内核无效,仅按内容指纹做 key 会把 A 引擎的句柄交给 B 引擎。\n * 缓存持有解析产物(compound 的 BREP solid 句柄等),与 statementCache 同生命周期\n * (runtime 级;worker 重建时模块重载自然清空)。缓存只是优化:digest 计算失败时\n * 跳过缓存(功能等价,不静默降级语义)。\n */\nconst loadCache = new Map<string, { parts: LoadBrepAssemblyPart[]; assembly?: ImportAssemblyNode }>()\n\nasync function contentHash(buffer: ArrayBuffer): Promise<string | null> {\n try {\n const digest = await globalThis.crypto.subtle.digest('SHA-256', buffer)\n return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, '0')).join('')\n } catch {\n return null // 无 WebCrypto(罕见环境):跳过缓存,功能等价\n }\n}\n\n/**\n * 文件加载白名单(P8 §4.2/§4.3,与 3d_editor config/file-formats 的 CAD 模型扩展名对齐):\n * mesh 路径 stl/3mf;BREP 路径 step/stp/stpz/brep。\n * iges/igs 刻意不在白名单——occt-wasm 未链接 TKDEIGES(brep-chain CAD_FORMATS 注释),\n * 走 BREP 路径必然失败;报「不支持的扩展名」比报内核错误更清晰。宿主 iges 现状路径保留。\n * 返回归一化格式:stp/stpz → 'step',其余原样;白名单未命中返回 undefined。\n */\nconst LOAD_EXTENSION_WHITELIST: Record<string, string> = {\n stl: 'stl',\n '3mf': '3mf',\n step: 'step',\n stp: 'step',\n stpz: 'step',\n brep: 'brep',\n}\n\nfunction formatFromFile(file: string): string | undefined {\n const ext = file.split('.').pop()?.toLowerCase() ?? ''\n return LOAD_EXTENSION_WHITELIST[ext]\n}\n\n/**\n * 魔数 sanity(P8 §4.3):后缀定格式后用文件头校验,后缀与内容明显不符时报错。\n * 仅 3MF 做显式魔数(zip 头 PK\\x03\\x04 / PK\\x05\\x06,可靠且歧义小);\n * STL(文本/二进制歧义)、STEP/IGES/BREP(文本格式)不做魔数,由各解析器内部消歧/报错——\n * 遵循「解析外部数据必须宽容」红线:只有可靠判据才拒绝,不误伤正常文件。\n */\nfunction assertFileMagic(fmt: string, buffer: ArrayBuffer, file: string): void {\n if (fmt !== '3mf') return\n const bytes = new Uint8Array(buffer.slice(0, 4))\n const isZip = bytes[0] === 0x50 && bytes[1] === 0x4b && (bytes[2] === 0x03 || bytes[2] === 0x05)\n if (!isZip) {\n throw new OpError(\n 'load',\n 'E_ARGS_FORM',\n `[extra/load] file ${JSON.stringify(file)} has .3mf extension but content is not a 3MF archive`,\n )\n }\n}\n\n/**\n * params.unit(UnitName 字符串,固化在脚本行里)→ importFile 的 opts.unit。\n * 契约(unit-system §5.2):提供即**强制设置模型的源单位**——只对无内部单位\n * 声明、坐标可直接折算的 mesh 格式(STL/3MF)有效;STEP/BREP 走 OCCT 链\n * (单位由文件内部声明决定),unit 参数由 load op 在 BREP 路径**明确报错**,\n * 不在此处拦截(保持 importFile 对 mesh 格式的单一职责)。非法/非长度单位\n * 直接报错。\n */\nfunction buildImportOpts(unitParam: unknown): { unit: UnitName } | undefined {\n if (typeof unitParam !== 'string' || unitParam === '') return undefined\n if (UNIT_DIM[unitParam as UnitName] !== 'length') {\n throw new OpError('load', 'E_ARGS_FORM', `[extra/load] unknown or non-length unit: ${JSON.stringify(unitParam)}`)\n }\n return { unit: unitParam as UnitName }\n}\n\n/** Register the file's source unit for the current statement's output part. */\nfunction registerDetectedUnit(unit: UnitName): void {\n const stmt = getCurrentStmt()\n const part = stmt?.outputs[0]\n if (part) setPendingDetectedUnit(part, unit)\n}\n\n/**\n * Register the current statement's output part's import model (P0,方案\n * 2026-10-06-step-3mf-multipart-import-plan.md §5.5): the structure data\n * (parts identity table + STEP assembly + Bambu views) of a `cad.load`.\n * 单/多零件均登记(单零件 parts 长度 1)。引擎在语句执行后收编进\n * ExecutionResult.importModels,宿主据此批量建 part,不再自行解析文件。\n */\nfunction registerImportModel(model: ImportModel): void {\n const stmt = getCurrentStmt()\n const part = stmt?.outputs[0]\n if (part) setPendingImportModel(part, model)\n}\n"]}
@@ -17,10 +17,12 @@ import type { Shape, BoxParams, SphereParams, CylinderParams, ConeParams, WedgeP
17
17
  * Create a box solid (brepjs contract, §4.1 A 决策).
18
18
  *
19
19
  * `box(width, depth, height)` — X=width, Y=depth, Z=height — places the
20
- * min-corner at the origin by default (`centered:false`). `centered: true`
21
- * centers the box at the origin; `at` is CENTER semantics and takes precedence
22
- * over `centered`. The `segments` option is consumed by the tessellation
23
- * caller (this mesh builder keeps it via clampNRad when present).
20
+ * min-corner at the origin by default (`centered:false`), bottom flush at
21
+ * z=0. `centered: true` centers the box at the origin; `at` is BASE
22
+ * semantics (bottom-center, same as cylinder/cone) — with `centered: true`
23
+ * given together, `at` is the box center. The `segments` option is consumed
24
+ * by the tessellation caller (this mesh builder keeps it via clampNRad when
25
+ * present).
24
26
  *
25
27
  * @param params - box parameters (width/depth/height, optional at/centered/segments).
26
28
  * @returns the box shape.
@@ -1 +1 @@
1
- {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/mesh/primitives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAiBjH;;;;;;;;;;;GAWG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,KAAK,CAkC5C;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,CAQlD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,KAAK,CAkBtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,KAAK,CAiC9C;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAwDhD;AAED;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,MAAM,EAAE;IAClC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAA;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAA;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,KAAK,CAAC,CAYjB;AAED;;;;;;GAMG;AACH,wBAAsB,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAc3D"}
1
+ {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/mesh/primitives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAiBjH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,KAAK,CAwC5C;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,CAQlD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,KAAK,CAkBtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,KAAK,CAiC9C;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAwDhD;AAED;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,MAAM,EAAE;IAClC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAA;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAA;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,KAAK,CAAC,CAYjB;AAED;;;;;;GAMG;AACH,wBAAsB,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAc3D"}
@@ -32,10 +32,12 @@ const ROT_Y_TO_Z = new Mat4().makeRotationX(Math.PI / 2);
32
32
  * Create a box solid (brepjs contract, §4.1 A 决策).
33
33
  *
34
34
  * `box(width, depth, height)` — X=width, Y=depth, Z=height — places the
35
- * min-corner at the origin by default (`centered:false`). `centered: true`
36
- * centers the box at the origin; `at` is CENTER semantics and takes precedence
37
- * over `centered`. The `segments` option is consumed by the tessellation
38
- * caller (this mesh builder keeps it via clampNRad when present).
35
+ * min-corner at the origin by default (`centered:false`), bottom flush at
36
+ * z=0. `centered: true` centers the box at the origin; `at` is BASE
37
+ * semantics (bottom-center, same as cylinder/cone) — with `centered: true`
38
+ * given together, `at` is the box center. The `segments` option is consumed
39
+ * by the tessellation caller (this mesh builder keeps it via clampNRad when
40
+ * present).
39
41
  *
40
42
  * @param params - box parameters (width/depth/height, optional at/centered/segments).
41
43
  * @returns the box shape.
@@ -46,15 +48,20 @@ export function box(params) {
46
48
  // after the +90° rotateX the dims map to X=width, Y=depth, Z=height.
47
49
  const geo = boxGeometry(width, height, depth);
48
50
  const rotated = transformShape(geo, ROT_Y_TO_Z);
49
- // 原 brepjs box semantics: corner at origin by default; centered at origin when
50
- // `centered` (no `at`); `at` (CENTER semantics) takes precedence.
51
+ // brepjs box semantics (2026-10-16 统一 BASE 锚点,与 cylinder/cone 一致):
52
+ // 几何以原点为中心(底面中心在 (0,0,-h/2)):
53
+ // - at(无 centered):底面中心落在 at → t = at + [0,0,h/2];
54
+ // - at + centered:以 at 为中心 → t = at;
55
+ // - centered(无 at):居中到原点 → t = [0,0,0];
56
+ // - 默认:角点在原点 → t = [w/2, d/2, h/2]。
51
57
  const at = params.at;
52
58
  let tx = 0;
53
59
  let ty = 0;
54
60
  let tz = 0;
55
61
  if (at !== undefined) {
56
- ;
57
- [tx, ty, tz] = at;
62
+ tx = at[0];
63
+ ty = at[1];
64
+ tz = at[2] + (params.centered === true ? 0 : height / 2);
58
65
  }
59
66
  else if (!params.centered) {
60
67
  tx = width / 2;
@@ -1 +1 @@
1
- {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../../src/mesh/primitives.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mesh 基本体 API — 从现有纯函数提取的统一接口\n *\n * 提取来源(§5.7):\n * - box/sphere/cylinder/cone/wedge ← engine/primitives/mesh-primitives.ts (makePrimitiveGeo)\n * - screw ← engine/primitives/screw/screw.ts (makeScrew)\n *\n * `text` / `svgExtrude`(three 的 Shape / ExtrudeGeometry / SVGLoader 链)已随\n * B 组迁到 `core/src/extra` 的 `mesh/primitives.ts`,core 的 mesh 面不再\n * 承载 three 的非基础几何生成链。\n *\n * 所有函数返回 Shape (ManifoldMeshData):parametric GeoData → geoToManifoldMesh 转换。\n * 坐标系:Z-up、毫米。\n */\n\nimport { Mat4 } from '../math3d'\nimport { boxGeometry, cylinderGeometry, coneGeometry, sphereGeometry, type GeoData } from './meshdata/parametric'\nimport { transformShape, translateShape } from './meshdata/ops'\nimport { geoToManifoldMesh } from '../boolean/csg-backend'\nimport type { Shape, BoxParams, SphereParams, CylinderParams, ConeParams, WedgeParams, SdfParams } from './types'\nimport { clampNRad } from './types'\n\n// ── 内部工具 ──\n\n/** GeoData → Shape (ManifoldMeshData);可选携带面结构元数据。 */\nfunction geoToShape(geo: GeoData, faceRanges?: Shape['faceRanges']): Shape {\n const shape = geoToManifoldMesh(geo) as Shape\n if (faceRanges !== undefined) shape.faceRanges = faceRanges\n return shape\n}\n\n/** Y-up → Z-up rotation (rotateX by PI/2), same as three's `makeRotationX(Math.PI / 2)`. */\nconst ROT_Y_TO_Z = new Mat4().makeRotationX(Math.PI / 2)\n\n// ── 创建 API ──\n\n/**\n * Create a box solid (brepjs contract, §4.1 A 决策).\n *\n * `box(width, depth, height)` — X=width, Y=depth, Z=height — places the\n * min-corner at the origin by default (`centered:false`). `centered: true`\n * centers the box at the origin; `at` is CENTER semantics and takes precedence\n * over `centered`. The `segments` option is consumed by the tessellation\n * caller (this mesh builder keeps it via clampNRad when present).\n *\n * @param params - box parameters (width/depth/height, optional at/centered/segments).\n * @returns the box shape.\n */\nexport function box(params: BoxParams): Shape {\n const { width, depth, height } = params\n // boxGeometry(width, height, depth) is Y-up (X=width, Y=height, Z=depth);\n // after the +90° rotateX the dims map to X=width, Y=depth, Z=height.\n const geo = boxGeometry(width, height, depth)\n const rotated = transformShape(geo, ROT_Y_TO_Z)\n // 原 brepjs box semantics: corner at origin by default; centered at origin when\n // `centered` (no `at`); `at` (CENTER semantics) takes precedence.\n const at = params.at\n let tx = 0\n let ty = 0\n let tz = 0\n if (at !== undefined) {\n ;[tx, ty, tz] = at\n } else if (!params.centered) {\n tx = width / 2\n ty = depth / 2\n tz = height / 2\n }\n const translated = tx !== 0 || ty !== 0 || tz !== 0\n ? translateShape(rotated, tx, ty, tz)\n : rotated\n // 面结构(P4 面级):BoxGeometry 12 三角形 = 6 面 × 2,顺序固定\n // (+X, −X, +Y, −Y, +Z, −Z);geoToManifoldMesh 焊接顶点保三角形序,故面序契约成立。\n // 面序号契约(setFaceColor 的 faceIds 即此序号):0=+X, 1=−X, 2=+Y, 3=−Y, 4=+Z, 5=−Z。\n const faceRanges: Shape['faceRanges'] = [\n { start: 0, count: 2 },\n { start: 2, count: 2 },\n { start: 4, count: 2 },\n { start: 6, count: 2 },\n { start: 8, count: 2 },\n { start: 10, count: 2 },\n ]\n return geoToShape(translated, faceRanges)\n}\n\n/**\n * Create a sphere centered at the origin (or the optional `center`).\n *\n * @param params - sphere parameters (radius, optional segments, optional center).\n * @returns the sphere shape.\n */\nexport function sphere(params: SphereParams): Shape {\n const segs = clampNRad(params.nRad ?? params.segments)\n const geo = sphereGeometry(params.radius, segs, segs)\n const rotated = transformShape(geo, ROT_Y_TO_Z)\n const translated = params.center\n ? translateShape(rotated, params.center[0], params.center[1], params.center[2])\n : rotated\n return geoToShape(translated)\n}\n\n/**\n * Create a cylinder along +Z (`cylinder(radius, height, { at?, centered?,\n * segments? })` brepjs 契约,§4.3 A 决策;与 brep 路径逐点对齐)。\n *\n * 锚点:`at` 是**底面轴心**(BASE)语义(默认 [0,0,0],底面在原点、+Z 延伸);\n * `centered:true` 指底面落到 −h/2(无 at 时居中到原点)——与 `at` 同给时以\n * `at` 为中心。`segments` 经 clampNRad 消费(P0 §5)。\n *\n * @param params - cylinder parameters (radius, height, optional at/centered/segments).\n * @returns the cylinder shape.\n */\nexport function cylinder(params: CylinderParams): Shape {\n const segs = clampNRad(params.nRad ?? params.segments)\n const geo = cylinderGeometry(params.radius, params.radius, params.height, segs)\n const rotated = transformShape(geo, ROT_Y_TO_Z)\n // geometry(rotateX 后)沿 z ∈ [-h/2, +h/2](three 默认 Y-up 居中):\n // 目标底面中心 in baseZ = (at?.[2] ?? 0) - (centered ? h/2 : 0) → 平移到 baseZ + h/2。\n const baseX = params.at?.[0] ?? 0\n const baseY = params.at?.[1] ?? 0\n const baseZ = (params.at?.[2] ?? 0) - (params.centered === true ? params.height / 2 : 0)\n const translated = translateShape(rotated, baseX, baseY, baseZ + params.height / 2)\n // 面结构(P4 面级):CylinderGeometry 三角形布局稳定——侧面 2*segs(tri 0..2segs-1)、\n // 顶盖 segs、底盖 segs。面序号契约:0=侧面, 1=顶, 2=底。\n const faceRanges: Shape['faceRanges'] = [\n { start: 0, count: 2 * segs },\n { start: 2 * segs, count: segs },\n { start: 3 * segs, count: segs },\n ]\n return geoToShape(translated, faceRanges)\n}\n\n/**\n * Create a cone, or a frustum when the top and bottom radii differ\n * (`cone(bottomRadius, topRadius, height, { at?, centered?, segments? })` brepjs\n * 契约,§4.1 P 决策;与 brep 路径逐点对齐)。\n *\n * 锚点:`at` 是**底面轴心**(BASE)语义(默认 [0,0,0],底面在原点、+Z 延伸);\n * `centered:true` 指底面落到 −h/2(无 at 时居中到原点)——与 `at` 同给时以\n * `at` 为中心。`segments` 经 clampNRad 消费(P0 §5)。\n *\n * @param params - cone parameters (radiusBottom, radiusTop, height, optional at/centered/segments).\n * @returns the cone shape.\n */\nexport function cone(params: ConeParams): Shape {\n const segs = clampNRad(params.nRad ?? params.segments)\n // radiusTop === 0 → 尖锥(coneGeometry 顶点在顶);其余(含 radiusTop ===\n // radiusBottom 的等径圆柱/圆台)用 cylinderGeometry(radiusTop/bottom 各就各位)。\n let geo: GeoData\n if (params.radiusTop === 0) {\n geo = coneGeometry(Math.max(params.radiusBottom, params.radiusTop), params.height, segs)\n } else {\n geo = cylinderGeometry(params.radiusTop, params.radiusBottom, params.height, segs)\n }\n const rotated = transformShape(geo, ROT_Y_TO_Z)\n // geometry(rotateX 后)沿 z ∈ [-h/2, +h/2](three 默认 Y-up 居中):\n // 目标底面中心 in baseZ = (at?.[2] ?? 0) - (centered ? h/2 : 0) → 平坦平移 baseZ + h/2。\n const baseX = params.at?.[0] ?? 0\n const baseY = params.at?.[1] ?? 0\n const baseZ = (params.at?.[2] ?? 0) - (params.centered === true ? params.height / 2 : 0)\n const translated = translateShape(rotated, baseX, baseY, baseZ + params.height / 2)\n // 面结构(P4 面级):radiusTop=0 的 ConeGeometry 只有 2 面——侧面(segs 个\n // 三角扇)+ 底盖(segs 个);radiusTop>0 的圆台 CylinderGeometry 3 面\n // (侧面 2*segs、顶、底,同 cylinder 布局)。面序号契约:0=侧面, 1=底\n // (尖锥);0=侧面, 1=顶, 2=底(圆台)。\n const faceRanges: Shape['faceRanges'] =\n params.radiusTop === 0\n ? [\n { start: 0, count: segs },\n { start: segs, count: segs },\n ]\n : [\n { start: 0, count: 2 * segs },\n { start: 2 * segs, count: segs },\n { start: 3 * segs, count: segs },\n ]\n return geoToShape(translated, faceRanges)\n}\n\n/**\n * Create a wedge (ramp) solid, fully parameterized and Z-up.\n *\n * @param params - wedge parameters (width, height, angle, length, optional center).\n * @returns the wedge shape.\n */\nexport function wedge(params: WedgeParams): Shape {\n const width = params.width\n const height = params.height\n const angle = params.angle\n const length = params.length\n\n const angleRad = (angle * Math.PI) / 180\n const halfExtrude = length / 2\n const hw = width / 2\n const halfTopWidth = Math.max(0, hw - height / Math.tan(angleRad))\n // 顶边塌缩(斜坡已在宽度内到顶)→ 三角棱柱(与 brep wedge 的退化处理一致,\n // 保证 mesh/brep 同参数 bbox 一致;零面积三角形会破坏 manifold)。\n const degenerate = halfTopWidth <= 1e-12\n\n const positions = degenerate\n ? new Float32Array([\n -halfExtrude, -hw, 0,\n -halfExtrude, hw, 0,\n -halfExtrude, 0, height,\n halfExtrude, -hw, 0,\n halfExtrude, hw, 0,\n halfExtrude, 0, height,\n ])\n : new Float32Array([\n -halfExtrude, -hw, 0,\n -halfExtrude, hw, 0,\n -halfExtrude, halfTopWidth, height,\n -halfExtrude, -halfTopWidth, height,\n halfExtrude, -hw, 0,\n halfExtrude, hw, 0,\n halfExtrude, halfTopWidth, height,\n halfExtrude, -halfTopWidth, height,\n ])\n\n const indices = degenerate\n ? new Uint32Array([\n 0, 1, 2, 3, 5, 4,\n 0, 3, 4, 0, 4, 1,\n 0, 2, 5, 0, 5, 3,\n 1, 4, 5, 1, 5, 2,\n ])\n : new Uint32Array([\n 0, 1, 2, 0, 2, 3,\n 4, 6, 5, 4, 7, 6,\n 0, 4, 5, 0, 5, 1,\n 3, 2, 6, 3, 6, 7,\n 0, 3, 7, 0, 7, 4,\n 1, 5, 6, 1, 6, 2,\n ])\n\n const geo: GeoData = { positions, indices }\n\n const translated = params.center\n ? translateShape(geo, params.center[0], params.center[1], params.center[2])\n : geo\n return geoToShape(translated)\n}\n\n/**\n * Create a screw (threaded) geometry.\n *\n * @param params - screw parameters (system, specIdx, thread, length, head, optional pitchCustom and nRad).\n * @returns the screw shape.\n */\nexport async function screw(params: {\n system: 'metric' | 'imperial'\n specIdx: number\n thread: 'coarse' | 'fine' | 'custom' | 'none'\n pitchCustom?: number\n length: number\n head: 'hex' | 'chc' | 'none'\n nRad?: number\n}): Promise<Shape> {\n const { makeScrew } = await import('../primitives/screw/screw')\n const geo = makeScrew({\n system: params.system,\n specIdx: params.specIdx,\n thread: params.thread,\n pitchCustom: params.pitchCustom ?? 0,\n length: params.length,\n head: params.head,\n nRad: clampNRad(params.nRad),\n })\n return geoToShape(geo)\n}\n\n/**\n * Create a mesh from SDF (signed distance field) code, sampling the field with\n * marching cubes.\n *\n * @param params - SDF parameters (code, optional bounds, params, resolution).\n * @returns the sampled shape.\n */\nexport async function sdf(params: SdfParams): Promise<Shape> {\n const { runSdf } = await import('../sdf/sdf-runner')\n const box = params.box ?? [[-10, -10, -10], [10, 10, 10]]\n const bounds: [number, number, number, number, number, number] = [\n box[0][0], box[0][1], box[0][2],\n box[1][0], box[1][1], box[1][2],\n ]\n const mesh = await runSdf(\n params.code,\n params.params ?? {},\n bounds,\n params.resolution ?? 1.0,\n )\n return { positions: mesh.positions, indices: mesh.indices }\n}\n"]}
1
+ {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../../src/mesh/primitives.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mesh 基本体 API — 从现有纯函数提取的统一接口\n *\n * 提取来源(§5.7):\n * - box/sphere/cylinder/cone/wedge ← engine/primitives/mesh-primitives.ts (makePrimitiveGeo)\n * - screw ← engine/primitives/screw/screw.ts (makeScrew)\n *\n * `text` / `svgExtrude`(three 的 Shape / ExtrudeGeometry / SVGLoader 链)已随\n * B 组迁到 `core/src/extra` 的 `mesh/primitives.ts`,core 的 mesh 面不再\n * 承载 three 的非基础几何生成链。\n *\n * 所有函数返回 Shape (ManifoldMeshData):parametric GeoData → geoToManifoldMesh 转换。\n * 坐标系:Z-up、毫米。\n */\n\nimport { Mat4 } from '../math3d'\nimport { boxGeometry, cylinderGeometry, coneGeometry, sphereGeometry, type GeoData } from './meshdata/parametric'\nimport { transformShape, translateShape } from './meshdata/ops'\nimport { geoToManifoldMesh } from '../boolean/csg-backend'\nimport type { Shape, BoxParams, SphereParams, CylinderParams, ConeParams, WedgeParams, SdfParams } from './types'\nimport { clampNRad } from './types'\n\n// ── 内部工具 ──\n\n/** GeoData → Shape (ManifoldMeshData);可选携带面结构元数据。 */\nfunction geoToShape(geo: GeoData, faceRanges?: Shape['faceRanges']): Shape {\n const shape = geoToManifoldMesh(geo) as Shape\n if (faceRanges !== undefined) shape.faceRanges = faceRanges\n return shape\n}\n\n/** Y-up → Z-up rotation (rotateX by PI/2), same as three's `makeRotationX(Math.PI / 2)`. */\nconst ROT_Y_TO_Z = new Mat4().makeRotationX(Math.PI / 2)\n\n// ── 创建 API ──\n\n/**\n * Create a box solid (brepjs contract, §4.1 A 决策).\n *\n * `box(width, depth, height)` — X=width, Y=depth, Z=height — places the\n * min-corner at the origin by default (`centered:false`), bottom flush at\n * z=0. `centered: true` centers the box at the origin; `at` is BASE\n * semantics (bottom-center, same as cylinder/cone) — with `centered: true`\n * given together, `at` is the box center. The `segments` option is consumed\n * by the tessellation caller (this mesh builder keeps it via clampNRad when\n * present).\n *\n * @param params - box parameters (width/depth/height, optional at/centered/segments).\n * @returns the box shape.\n */\nexport function box(params: BoxParams): Shape {\n const { width, depth, height } = params\n // boxGeometry(width, height, depth) is Y-up (X=width, Y=height, Z=depth);\n // after the +90° rotateX the dims map to X=width, Y=depth, Z=height.\n const geo = boxGeometry(width, height, depth)\n const rotated = transformShape(geo, ROT_Y_TO_Z)\n // brepjs box semantics (2026-10-16 统一 BASE 锚点,与 cylinder/cone 一致):\n // 几何以原点为中心(底面中心在 (0,0,-h/2)):\n // - at(无 centered):底面中心落在 at → t = at + [0,0,h/2];\n // - at + centered:以 at 为中心 → t = at;\n // - centered(无 at):居中到原点 → t = [0,0,0];\n // - 默认:角点在原点 → t = [w/2, d/2, h/2]。\n const at = params.at\n let tx = 0\n let ty = 0\n let tz = 0\n if (at !== undefined) {\n tx = at[0]\n ty = at[1]\n tz = at[2] + (params.centered === true ? 0 : height / 2)\n } else if (!params.centered) {\n tx = width / 2\n ty = depth / 2\n tz = height / 2\n }\n const translated = tx !== 0 || ty !== 0 || tz !== 0\n ? translateShape(rotated, tx, ty, tz)\n : rotated\n // 面结构(P4 面级):BoxGeometry 12 三角形 = 6 面 × 2,顺序固定\n // (+X, −X, +Y, −Y, +Z, −Z);geoToManifoldMesh 焊接顶点保三角形序,故面序契约成立。\n // 面序号契约(setFaceColor 的 faceIds 即此序号):0=+X, 1=−X, 2=+Y, 3=−Y, 4=+Z, 5=−Z。\n const faceRanges: Shape['faceRanges'] = [\n { start: 0, count: 2 },\n { start: 2, count: 2 },\n { start: 4, count: 2 },\n { start: 6, count: 2 },\n { start: 8, count: 2 },\n { start: 10, count: 2 },\n ]\n return geoToShape(translated, faceRanges)\n}\n\n/**\n * Create a sphere centered at the origin (or the optional `center`).\n *\n * @param params - sphere parameters (radius, optional segments, optional center).\n * @returns the sphere shape.\n */\nexport function sphere(params: SphereParams): Shape {\n const segs = clampNRad(params.nRad ?? params.segments)\n const geo = sphereGeometry(params.radius, segs, segs)\n const rotated = transformShape(geo, ROT_Y_TO_Z)\n const translated = params.center\n ? translateShape(rotated, params.center[0], params.center[1], params.center[2])\n : rotated\n return geoToShape(translated)\n}\n\n/**\n * Create a cylinder along +Z (`cylinder(radius, height, { at?, centered?,\n * segments? })` brepjs 契约,§4.3 A 决策;与 brep 路径逐点对齐)。\n *\n * 锚点:`at` 是**底面轴心**(BASE)语义(默认 [0,0,0],底面在原点、+Z 延伸);\n * `centered:true` 指底面落到 −h/2(无 at 时居中到原点)——与 `at` 同给时以\n * `at` 为中心。`segments` 经 clampNRad 消费(P0 §5)。\n *\n * @param params - cylinder parameters (radius, height, optional at/centered/segments).\n * @returns the cylinder shape.\n */\nexport function cylinder(params: CylinderParams): Shape {\n const segs = clampNRad(params.nRad ?? params.segments)\n const geo = cylinderGeometry(params.radius, params.radius, params.height, segs)\n const rotated = transformShape(geo, ROT_Y_TO_Z)\n // geometry(rotateX 后)沿 z ∈ [-h/2, +h/2](three 默认 Y-up 居中):\n // 目标底面中心 in baseZ = (at?.[2] ?? 0) - (centered ? h/2 : 0) → 平移到 baseZ + h/2。\n const baseX = params.at?.[0] ?? 0\n const baseY = params.at?.[1] ?? 0\n const baseZ = (params.at?.[2] ?? 0) - (params.centered === true ? params.height / 2 : 0)\n const translated = translateShape(rotated, baseX, baseY, baseZ + params.height / 2)\n // 面结构(P4 面级):CylinderGeometry 三角形布局稳定——侧面 2*segs(tri 0..2segs-1)、\n // 顶盖 segs、底盖 segs。面序号契约:0=侧面, 1=顶, 2=底。\n const faceRanges: Shape['faceRanges'] = [\n { start: 0, count: 2 * segs },\n { start: 2 * segs, count: segs },\n { start: 3 * segs, count: segs },\n ]\n return geoToShape(translated, faceRanges)\n}\n\n/**\n * Create a cone, or a frustum when the top and bottom radii differ\n * (`cone(bottomRadius, topRadius, height, { at?, centered?, segments? })` brepjs\n * 契约,§4.1 P 决策;与 brep 路径逐点对齐)。\n *\n * 锚点:`at` 是**底面轴心**(BASE)语义(默认 [0,0,0],底面在原点、+Z 延伸);\n * `centered:true` 指底面落到 −h/2(无 at 时居中到原点)——与 `at` 同给时以\n * `at` 为中心。`segments` 经 clampNRad 消费(P0 §5)。\n *\n * @param params - cone parameters (radiusBottom, radiusTop, height, optional at/centered/segments).\n * @returns the cone shape.\n */\nexport function cone(params: ConeParams): Shape {\n const segs = clampNRad(params.nRad ?? params.segments)\n // radiusTop === 0 → 尖锥(coneGeometry 顶点在顶);其余(含 radiusTop ===\n // radiusBottom 的等径圆柱/圆台)用 cylinderGeometry(radiusTop/bottom 各就各位)。\n let geo: GeoData\n if (params.radiusTop === 0) {\n geo = coneGeometry(Math.max(params.radiusBottom, params.radiusTop), params.height, segs)\n } else {\n geo = cylinderGeometry(params.radiusTop, params.radiusBottom, params.height, segs)\n }\n const rotated = transformShape(geo, ROT_Y_TO_Z)\n // geometry(rotateX 后)沿 z ∈ [-h/2, +h/2](three 默认 Y-up 居中):\n // 目标底面中心 in baseZ = (at?.[2] ?? 0) - (centered ? h/2 : 0) → 平坦平移 baseZ + h/2。\n const baseX = params.at?.[0] ?? 0\n const baseY = params.at?.[1] ?? 0\n const baseZ = (params.at?.[2] ?? 0) - (params.centered === true ? params.height / 2 : 0)\n const translated = translateShape(rotated, baseX, baseY, baseZ + params.height / 2)\n // 面结构(P4 面级):radiusTop=0 的 ConeGeometry 只有 2 面——侧面(segs 个\n // 三角扇)+ 底盖(segs 个);radiusTop>0 的圆台 CylinderGeometry 3 面\n // (侧面 2*segs、顶、底,同 cylinder 布局)。面序号契约:0=侧面, 1=底\n // (尖锥);0=侧面, 1=顶, 2=底(圆台)。\n const faceRanges: Shape['faceRanges'] =\n params.radiusTop === 0\n ? [\n { start: 0, count: segs },\n { start: segs, count: segs },\n ]\n : [\n { start: 0, count: 2 * segs },\n { start: 2 * segs, count: segs },\n { start: 3 * segs, count: segs },\n ]\n return geoToShape(translated, faceRanges)\n}\n\n/**\n * Create a wedge (ramp) solid, fully parameterized and Z-up.\n *\n * @param params - wedge parameters (width, height, angle, length, optional center).\n * @returns the wedge shape.\n */\nexport function wedge(params: WedgeParams): Shape {\n const width = params.width\n const height = params.height\n const angle = params.angle\n const length = params.length\n\n const angleRad = (angle * Math.PI) / 180\n const halfExtrude = length / 2\n const hw = width / 2\n const halfTopWidth = Math.max(0, hw - height / Math.tan(angleRad))\n // 顶边塌缩(斜坡已在宽度内到顶)→ 三角棱柱(与 brep wedge 的退化处理一致,\n // 保证 mesh/brep 同参数 bbox 一致;零面积三角形会破坏 manifold)。\n const degenerate = halfTopWidth <= 1e-12\n\n const positions = degenerate\n ? new Float32Array([\n -halfExtrude, -hw, 0,\n -halfExtrude, hw, 0,\n -halfExtrude, 0, height,\n halfExtrude, -hw, 0,\n halfExtrude, hw, 0,\n halfExtrude, 0, height,\n ])\n : new Float32Array([\n -halfExtrude, -hw, 0,\n -halfExtrude, hw, 0,\n -halfExtrude, halfTopWidth, height,\n -halfExtrude, -halfTopWidth, height,\n halfExtrude, -hw, 0,\n halfExtrude, hw, 0,\n halfExtrude, halfTopWidth, height,\n halfExtrude, -halfTopWidth, height,\n ])\n\n const indices = degenerate\n ? new Uint32Array([\n 0, 1, 2, 3, 5, 4,\n 0, 3, 4, 0, 4, 1,\n 0, 2, 5, 0, 5, 3,\n 1, 4, 5, 1, 5, 2,\n ])\n : new Uint32Array([\n 0, 1, 2, 0, 2, 3,\n 4, 6, 5, 4, 7, 6,\n 0, 4, 5, 0, 5, 1,\n 3, 2, 6, 3, 6, 7,\n 0, 3, 7, 0, 7, 4,\n 1, 5, 6, 1, 6, 2,\n ])\n\n const geo: GeoData = { positions, indices }\n\n const translated = params.center\n ? translateShape(geo, params.center[0], params.center[1], params.center[2])\n : geo\n return geoToShape(translated)\n}\n\n/**\n * Create a screw (threaded) geometry.\n *\n * @param params - screw parameters (system, specIdx, thread, length, head, optional pitchCustom and nRad).\n * @returns the screw shape.\n */\nexport async function screw(params: {\n system: 'metric' | 'imperial'\n specIdx: number\n thread: 'coarse' | 'fine' | 'custom' | 'none'\n pitchCustom?: number\n length: number\n head: 'hex' | 'chc' | 'none'\n nRad?: number\n}): Promise<Shape> {\n const { makeScrew } = await import('../primitives/screw/screw')\n const geo = makeScrew({\n system: params.system,\n specIdx: params.specIdx,\n thread: params.thread,\n pitchCustom: params.pitchCustom ?? 0,\n length: params.length,\n head: params.head,\n nRad: clampNRad(params.nRad),\n })\n return geoToShape(geo)\n}\n\n/**\n * Create a mesh from SDF (signed distance field) code, sampling the field with\n * marching cubes.\n *\n * @param params - SDF parameters (code, optional bounds, params, resolution).\n * @returns the sampled shape.\n */\nexport async function sdf(params: SdfParams): Promise<Shape> {\n const { runSdf } = await import('../sdf/sdf-runner')\n const box = params.box ?? [[-10, -10, -10], [10, 10, 10]]\n const bounds: [number, number, number, number, number, number] = [\n box[0][0], box[0][1], box[0][2],\n box[1][0], box[1][1], box[1][2],\n ]\n const mesh = await runSdf(\n params.code,\n params.params ?? {},\n bounds,\n params.resolution ?? 1.0,\n )\n return { positions: mesh.positions, indices: mesh.indices }\n}\n"]}
@@ -125,8 +125,9 @@ export declare const NRAD_MAX = 128;
125
125
  export declare function clampNRad(n: number | undefined): number;
126
126
  /**
127
127
  * Parameters for creating a box (原 brepjs `box(width, depth, height, {at?, centered?, segments?})`
128
- * contract, §4.1 A 决策). Default: min-corner at the origin. `centered: true` shifts so the
129
- * box is centered at the origin; `at` is CENTER semantics and takes precedence over `centered`.
128
+ * contract, §4.1 A 决策). Default: min-corner at the origin, bottom flush at z=0.
129
+ * `centered: true` shifts so the box is centered at the origin; `at` is BASE semantics
130
+ * (bottom-center, same as cylinder/cone); with `centered: true` given together, `at` is the center.
130
131
  */
131
132
  export interface BoxParams {
132
133
  /** Side length along X (mm). */
@@ -135,7 +136,7 @@ export interface BoxParams {
135
136
  depth: number;
136
137
  /** Side length along Z (mm). */
137
138
  height: number;
138
- /** Center position (原 brepjs `at`, CENTER semantics); takes precedence over `centered`. */
139
+ /** Bottom-center position (原 brepjs `at`, BASE semantics, same as cylinder/cone); with `centered` it is the center. */
139
140
  at?: Vec3;
140
141
  /** Center the box at the origin when `at` is absent. Default: false (min-corner at origin). */
141
142
  centered?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mesh/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAI5C,oCAAoC;AACpC,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAE3C;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAA;AAI9B;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,KAAK;IACpB,SAAS,EAAE,YAAY,CAAA;IACvB,OAAO,EAAE,WAAW,CAAA;IACpB,8HAA8H;IAC9H,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,yDAAyD;IACzD,UAAU,CAAC,EAAE,aAAa,CAAA;IAC1B,gEAAgE;IAChE,cAAc,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,aAAa,CAAA;KAAE,CAAC,CAAA;IACnF,2EAA2E;IAC3E,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,IAAI,CAAA;SAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC5F;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACrD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,CAElD;AAID,8DAA8D;AAC9D,eAAO,MAAM,YAAY,KAAK,CAAA;AAC9B,4CAA4C;AAC5C,eAAO,MAAM,QAAQ,IAAI,CAAA;AACzB,4CAA4C;AAC5C,eAAO,MAAM,QAAQ,MAAM,CAAA;AAE3B;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGvD;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,2FAA2F;IAC3F,EAAE,CAAC,EAAE,IAAI,CAAA;IACT,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wCAAwC;AACxC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,sEAAsE;AACtE,MAAM,WAAW,cAAc;IAC7B,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,6EAA6E;IAC7E,EAAE,CAAC,EAAE,IAAI,CAAA;IACT,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,4DAA4D;AAC5D,MAAM,WAAW,UAAU;IACzB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAA;IACjB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,6EAA6E;IAC7E,EAAE,CAAC,EAAE,IAAI,CAAA;IACT,sFAAsF;IACtF,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAA;IACb,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,uCAAuC;AACvC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAED,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,8EAA8E;AAC9E,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAID,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,IAAI,CAAA;CACb;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,IAAI,CAAA;IACZ,KAAK,CAAC,EAAE,IAAI,CAAA;CACb;AAED,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAID,0CAA0C;AAC1C,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAA;AAIjE,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,IAAI,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,UAAU,CAAA;IACjB,WAAW,EAAE,IAAI,CAAA;IACjB,QAAQ,EAAE,IAAI,CAAA;IACd,mBAAmB,EAAE,MAAM,CAAA;IAC3B,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAA;QACb,cAAc,EAAE,MAAM,CAAA;QACtB,KAAK,EAAE,MAAM,CAAA;QACb,cAAc,EAAE,MAAM,CAAA;QACtB,UAAU,EAAE,MAAM,CAAA;KACnB,CAAA;CACF;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,UAAU,CAAA;IACjB,WAAW,EAAE,IAAI,CAAA;IACjB,QAAQ,EAAE,IAAI,CAAA;IACd,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAA;QAChB,iBAAiB,EAAE,MAAM,CAAA;QACzB,MAAM,EAAE,MAAM,CAAA;QACd,eAAe,EAAE,MAAM,CAAA;KACxB,CAAA;IACD,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;CACnC;AAED,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,UAAU,CAAA;IACjB,WAAW,EAAE,IAAI,CAAA;IACjB,QAAQ,EAAE,IAAI,CAAA;IACd,KAAK,EAAE;QACL,UAAU,EAAE,MAAM,CAAA;QAClB,mBAAmB,EAAE,MAAM,CAAA;QAC3B,MAAM,EAAE,MAAM,CAAA;QACd,eAAe,EAAE,MAAM,CAAA;KACxB,CAAA;IACD,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;CACnC;AAED,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAID,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,SAAS,GAAG,OAAO,CAAA;IACzB,QAAQ,EAAE,IAAI,CAAA;IACd,SAAS,EAAE,IAAI,CAAA;IACf,UAAU,EAAE,IAAI,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAID,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,IAAI,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;CAC3C;AAID,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE;QACJ,MAAM,EAAE,IAAI,CAAA;QACZ,MAAM,EAAE,IAAI,CAAA;KACb,CAAA;IACD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE;QACJ,MAAM,EAAE,IAAI,CAAA;QACZ,MAAM,EAAE,IAAI,CAAA;KACb,CAAA;IACD,kBAAkB,EAAE,MAAM,CAAA;IAC1B,uBAAuB,EAAE,OAAO,CAAA;IAChC,iBAAiB,EAAE,MAAM,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAID,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,IAAI,CAAA;IACT,GAAG,EAAE,IAAI,CAAA;CACV;AAED,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,IAAI,CAAA;IACZ,MAAM,EAAE,IAAI,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mesh/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mesh/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAuFH;;;;;;;;;;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\nimport type { PbrAppearance } from '../api/appearance'\nimport type { ShapeMeta } from '../api/meta'\n\n// ── 基础类型 ──\n\n/** 三维坐标 / RGB 颜色元组(分量 sRGB 0–1)。 */\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 *\n * 外观(PBR):`appearance` 为可选数据字段(设计文档 2026-10-05 v2 §4.2),\n * 双链路产物自解释、可序列化;外观设置是 Shape **方法**(非 op,见\n * `api/appearance.ts` 的 `ShapeAppearanceMethods` / `attachAppearanceMethods`),\n * 方法只挂载在产物构造点(solid/curve)返回的实例上,基础 Shape 保持纯数据\n * 契约——因此本接口**不** extends 方法接口,`isMeshShape` 鸭子判定不受影响。\n */\nexport interface Shape {\n positions: Float32Array\n indices: Uint32Array\n /** Per-vertex normals (x, y, z interleaved), length = positions.length. Optional; derived via creased-normals when absent. */\n normals?: Float32Array\n /** 可选:形状级外观(mesh/brep 双链路产物自解释;worker 序列化保留字段、不保留方法)。 */\n appearance?: PbrAppearance\n /** Phase 2:面级外观分组 [三角形起始, 数量, 外观];存在时优先于 appearance 作为未分组默认。 */\n materialGroups?: Array<{ start: number; count: number; appearance: PbrAppearance }>\n /** Phase 2:顶点颜色(3MF colorgroup / 面级 mesh 链),sRGB 0–1,长度 = positions 长度。 */\n vertexColors?: Float32Array\n /**\n * 零件级说明性元数据(设计文档 2026-10-05-meta §4.3):名称/描述/料号/自定义\n * 键值,随 Shape 走 mesh/brep 双链路、JSON 可序列化。设置方法是 Shape 实例\n * 方法(非 op,见 `api/meta.ts` 的 `ShapeMetaMethods` / `attachMetaMethods`),\n * 方法只挂载在产物构造点(solid/curve)返回的实例上,基础 Shape 保持纯数据\n * 契约——因此本接口**不** extends 方法接口,`isMeshShape` 鸭子判定不受影响。\n */\n meta?: ShapeMeta\n /**\n * 装配节点位姿(方案 2026-10-08 §2.1「装配模型 = 节点属性,单一真源」):节点\n * **相对其父**的位置/姿态。可选、纯数据、JSON 可序列化——与 `appearance` /\n * `meta` 同为**字段**而非方法,随 Shape 一起过 worker 序列化与 `structuredClone`\n * (`isMeshShape` 鸭子判定不看本字段)。装配层级就是 Shape / CompoundShape\n * 自身的 `children` + 本字段,**没有**平行的装配树。\n *\n * 取值形态(三种等价书写,均为可序列化纯数据):`translate` 平移;`rotate`\n * 单一轴角(`angle` 按本文件约定用**度**,`axis` 为轴向量);`matrix` 3×4\n * 行主序 12 元组——即 3MF `<component transform>` 与 XCAF location 的直接形态。\n * 三者的复合顺序与形态间优先级由读侧实现固定(§5 第 4、5 步),本字段只定\n * 义取值形态。\n *\n * 写入方两个、写回同一字段:导入侧(XCAF location / 3MF component transform)\n * 与求解侧(`AssemblyTransform[]`)。导出侧**只读**它:STL 顶点烘焙、3MF\n * `<component transform>`、STEP XCAF location(§2.1 映射表)。分量刻度与\n * `positions` 同(基准单位),换算到声明单位由写出器成对完成(§2.1)。\n *\n * 阶段说明:本字段随 §5 第 3 步引入;写出器在 §5 第 4(3MF components)、第 5\n * (导入归一 / STL 烘焙)步之前不消费它(`export-model.test.ts` 用「带与不带\n * `transform` 的导出字节相等」钉住这一当前事实,届时翻转)。\n */\n transform?: { translate?: Vec3; rotate?: { angle: number; axis?: Vec3 }; matrix?: number[] }\n /**\n * 面结构元数据:面序号 → 三角形区间 [start, count)(start/count 为三角形索引,\n * 对应 positions/indices 焊接后的三角形序列)。仅参数化 primitives 构造时记录\n * (面结构构造时已知、三角形顺序固定);manifold 布尔/组合/导入后无 CAD 面\n * 概念,本字段不存在。`setFaceColor`/`setFaceMaterial` 依赖本字段把面序号映射\n * 到三角形区间并写入 materialGroups。\n */\n faceRanges?: Array<{ start: number; count: number }>\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
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mesh/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAuFH;;;;;;;;;;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\nimport type { PbrAppearance } from '../api/appearance'\nimport type { ShapeMeta } from '../api/meta'\n\n// ── 基础类型 ──\n\n/** 三维坐标 / RGB 颜色元组(分量 sRGB 0–1)。 */\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 *\n * 外观(PBR):`appearance` 为可选数据字段(设计文档 2026-10-05 v2 §4.2),\n * 双链路产物自解释、可序列化;外观设置是 Shape **方法**(非 op,见\n * `api/appearance.ts` 的 `ShapeAppearanceMethods` / `attachAppearanceMethods`),\n * 方法只挂载在产物构造点(solid/curve)返回的实例上,基础 Shape 保持纯数据\n * 契约——因此本接口**不** extends 方法接口,`isMeshShape` 鸭子判定不受影响。\n */\nexport interface Shape {\n positions: Float32Array\n indices: Uint32Array\n /** Per-vertex normals (x, y, z interleaved), length = positions.length. Optional; derived via creased-normals when absent. */\n normals?: Float32Array\n /** 可选:形状级外观(mesh/brep 双链路产物自解释;worker 序列化保留字段、不保留方法)。 */\n appearance?: PbrAppearance\n /** Phase 2:面级外观分组 [三角形起始, 数量, 外观];存在时优先于 appearance 作为未分组默认。 */\n materialGroups?: Array<{ start: number; count: number; appearance: PbrAppearance }>\n /** Phase 2:顶点颜色(3MF colorgroup / 面级 mesh 链),sRGB 0–1,长度 = positions 长度。 */\n vertexColors?: Float32Array\n /**\n * 零件级说明性元数据(设计文档 2026-10-05-meta §4.3):名称/描述/料号/自定义\n * 键值,随 Shape 走 mesh/brep 双链路、JSON 可序列化。设置方法是 Shape 实例\n * 方法(非 op,见 `api/meta.ts` 的 `ShapeMetaMethods` / `attachMetaMethods`),\n * 方法只挂载在产物构造点(solid/curve)返回的实例上,基础 Shape 保持纯数据\n * 契约——因此本接口**不** extends 方法接口,`isMeshShape` 鸭子判定不受影响。\n */\n meta?: ShapeMeta\n /**\n * 装配节点位姿(方案 2026-10-08 §2.1「装配模型 = 节点属性,单一真源」):节点\n * **相对其父**的位置/姿态。可选、纯数据、JSON 可序列化——与 `appearance` /\n * `meta` 同为**字段**而非方法,随 Shape 一起过 worker 序列化与 `structuredClone`\n * (`isMeshShape` 鸭子判定不看本字段)。装配层级就是 Shape / CompoundShape\n * 自身的 `children` + 本字段,**没有**平行的装配树。\n *\n * 取值形态(三种等价书写,均为可序列化纯数据):`translate` 平移;`rotate`\n * 单一轴角(`angle` 按本文件约定用**度**,`axis` 为轴向量);`matrix` 3×4\n * 行主序 12 元组——即 3MF `<component transform>` 与 XCAF location 的直接形态。\n * 三者的复合顺序与形态间优先级由读侧实现固定(§5 第 4、5 步),本字段只定\n * 义取值形态。\n *\n * 写入方两个、写回同一字段:导入侧(XCAF location / 3MF component transform)\n * 与求解侧(`AssemblyTransform[]`)。导出侧**只读**它:STL 顶点烘焙、3MF\n * `<component transform>`、STEP XCAF location(§2.1 映射表)。分量刻度与\n * `positions` 同(基准单位),换算到声明单位由写出器成对完成(§2.1)。\n *\n * 阶段说明:本字段随 §5 第 3 步引入;写出器在 §5 第 4(3MF components)、第 5\n * (导入归一 / STL 烘焙)步之前不消费它(`export-model.test.ts` 用「带与不带\n * `transform` 的导出字节相等」钉住这一当前事实,届时翻转)。\n */\n transform?: { translate?: Vec3; rotate?: { angle: number; axis?: Vec3 }; matrix?: number[] }\n /**\n * 面结构元数据:面序号 → 三角形区间 [start, count)(start/count 为三角形索引,\n * 对应 positions/indices 焊接后的三角形序列)。仅参数化 primitives 构造时记录\n * (面结构构造时已知、三角形顺序固定);manifold 布尔/组合/导入后无 CAD 面\n * 概念,本字段不存在。`setFaceColor`/`setFaceMaterial` 依赖本字段把面序号映射\n * 到三角形区间并写入 materialGroups。\n */\n faceRanges?: Array<{ start: number; count: number }>\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, bottom flush at z=0.\n * `centered: true` shifts so the box is centered at the origin; `at` is BASE semantics\n * (bottom-center, same as cylinder/cone); with `centered: true` given together, `at` is the center.\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 /** Bottom-center position (原 brepjs `at`, BASE semantics, same as cylinder/cone); with `centered` it is the center. */\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":"brep-primitives.d.ts","sourceRoot":"","sources":["../../src/primitives/brep-primitives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EACZ,cAAc,EACd,UAAU,EACV,WAAW,EACX,KAAK,EACN,MAAM,eAAe,CAAA;AAItB;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG;IAC7C,SAAS,EAAE,YAAY,CAAA;IACvB,OAAO,EAAE,WAAW,CAAA;CACrB,CAEA;AA6JD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,KAAK,EAAE,UAAU,CAAA;IACjB,kCAAkC;IAClC,IAAI,EAAE,WAAW,GAAG,MAAM,CAAA;IAC1B,0BAA0B;IAC1B,IAAI,EAAE,aAAa,GAAG,OAAO,GAAG,MAAM,CAAA;CACvC;AAED,qDAAqD;AACrD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,YAAY,GAAG,cAAc,GAAG,UAAU,GAAG,WAAW,CAAA;AA6BlG;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,aAAa,GAAG,OAAO,GAAG,MAAM,EACtC,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,GAChC,qBAAqB,CAkCvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,KAAK,GACX,qBAAqB,CAIvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAEhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,aAAa,EACnB,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,GAChC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAAA;CAAE,CAQ9C"}
1
+ {"version":3,"file":"brep-primitives.d.ts","sourceRoot":"","sources":["../../src/primitives/brep-primitives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EACZ,cAAc,EACd,UAAU,EACV,WAAW,EACX,KAAK,EACN,MAAM,eAAe,CAAA;AAItB;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG;IAC7C,SAAS,EAAE,YAAY,CAAA;IACvB,OAAO,EAAE,WAAW,CAAA;CACrB,CAEA;AAsLD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,KAAK,EAAE,UAAU,CAAA;IACjB,kCAAkC;IAClC,IAAI,EAAE,WAAW,GAAG,MAAM,CAAA;IAC1B,0BAA0B;IAC1B,IAAI,EAAE,aAAa,GAAG,OAAO,GAAG,MAAM,CAAA;CACvC;AAED,qDAAqD;AACrD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,YAAY,GAAG,cAAc,GAAG,UAAU,GAAG,WAAW,CAAA;AA6BlG;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,aAAa,GAAG,OAAO,GAAG,MAAM,EACtC,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,GAChC,qBAAqB,CAkCvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,KAAK,GACX,qBAAqB,CAIvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAEhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,aAAa,EACnB,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,GAChC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAAA;CAAE,CAQ9C"}