@faicad/faijs 0.29.3 → 0.29.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/appearance.d.ts +138 -0
- package/dist/api/appearance.d.ts.map +1 -0
- package/dist/api/appearance.js +230 -0
- package/dist/api/appearance.js.map +1 -0
- package/dist/api/import-step.d.ts.map +1 -1
- package/dist/api/import-step.js +28 -0
- package/dist/api/import-step.js.map +1 -1
- package/dist/api/index.d.ts +4 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +2 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/meta.d.ts +93 -0
- package/dist/api/meta.d.ts.map +1 -0
- package/dist/api/meta.js +99 -0
- package/dist/api/meta.js.map +1 -0
- package/dist/api/primitives.d.ts.map +1 -1
- package/dist/api/primitives.js +117 -2
- package/dist/api/primitives.js.map +1 -1
- package/dist/brep/brep-ops.d.ts.map +1 -1
- package/dist/brep/brep-ops.js +28 -3
- package/dist/brep/brep-ops.js.map +1 -1
- package/dist/brep/engine/adapters/occt.js +1 -1
- package/dist/brep/engine/adapters/occt.js.map +1 -1
- package/dist/brep/export/export-model.d.ts +40 -0
- package/dist/brep/export/export-model.d.ts.map +1 -1
- package/dist/brep/export/export-model.js +268 -25
- package/dist/brep/export/export-model.js.map +1 -1
- package/dist/brep/export/step-meta-header.d.ts +102 -0
- package/dist/brep/export/step-meta-header.d.ts.map +1 -0
- package/dist/brep/export/step-meta-header.js +225 -0
- package/dist/brep/export/step-meta-header.js.map +1 -0
- package/dist/brep/export/step.d.ts +5 -1
- package/dist/brep/export/step.d.ts.map +1 -1
- package/dist/brep/export/step.js +11 -2
- package/dist/brep/export/step.js.map +1 -1
- package/dist/define-op.d.ts.map +1 -1
- package/dist/define-op.js +63 -1
- package/dist/define-op.js.map +1 -1
- package/dist/lang/metadata-extractor.d.ts.map +1 -1
- package/dist/lang/metadata-extractor.js +2 -21
- package/dist/lang/metadata-extractor.js.map +1 -1
- package/dist/lang/types.d.ts +5 -6
- package/dist/lang/types.d.ts.map +1 -1
- package/dist/lang/types.js.map +1 -1
- package/dist/mesh/io.d.ts +6 -0
- package/dist/mesh/io.d.ts.map +1 -1
- package/dist/mesh/io.js +25 -1
- package/dist/mesh/io.js.map +1 -1
- package/dist/mesh/primitives.d.ts.map +1 -1
- package/dist/mesh/primitives.js +41 -6
- package/dist/mesh/primitives.js.map +1 -1
- package/dist/mesh/threemf-loader.d.ts +23 -0
- package/dist/mesh/threemf-loader.d.ts.map +1 -1
- package/dist/mesh/threemf-loader.js +182 -8
- package/dist/mesh/threemf-loader.js.map +1 -1
- package/dist/mesh/types.d.ts +38 -0
- package/dist/mesh/types.d.ts.map +1 -1
- package/dist/mesh/types.js.map +1 -1
- package/dist/occt-kernel/highLevelApi.d.ts +4 -1
- package/dist/occt-kernel/highLevelApi.d.ts.map +1 -1
- package/dist/occt-kernel/highLevelApi.js +4 -2
- package/dist/occt-kernel/highLevelApi.js.map +1 -1
- package/dist/occt-kernel/occt-primitives.js +1 -1
- package/dist/occt-kernel/occt-primitives.js.map +1 -1
- package/dist/occt-kernel/occtKernel.d.ts +1 -1
- package/dist/occt-kernel/occtKernel.js +1 -1
- package/dist/occt-kernel/occtKernel.js.map +1 -1
- package/dist/occt-kernel/stepMetaParser.d.ts +44 -0
- package/dist/occt-kernel/stepMetaParser.d.ts.map +1 -0
- package/dist/occt-kernel/stepMetaParser.js +166 -0
- package/dist/occt-kernel/stepMetaParser.js.map +1 -0
- package/dist/shape.d.ts +11 -3
- package/dist/shape.d.ts.map +1 -1
- package/dist/shape.js +4 -2
- package/dist/shape.js.map +1 -1
- package/dist/step/stepMetaParser.d.ts +55 -0
- package/dist/step/stepMetaParser.d.ts.map +1 -0
- package/dist/step/stepMetaParser.js +177 -0
- package/dist/step/stepMetaParser.js.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"occtKernel.js","sourceRoot":"","sources":["../../src/occt-kernel/occtKernel.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * occt-wasm 封装层 — 替代 occt-import-js\n *\n * 提供 STEP/BREP → Mesh 转换和 Mesh → STEP 导出能力。\n * 利用 occt-wasm 的 meshShape() 获取 faceGroups(面→三角形映射),\n * 利用 wireframe() 获取边折线数据,利用 edgeToFaceMap() 获取边→面关联。\n */\nimport type { OcctKernel, ShapeHandle, Mesh, EdgeData, SurfaceKind, CurveKind, BoundingBox, Vec3, XCAFDocument, LabelInfo, LabelTag } from 'occt-wasm'\n\nimport { getSolidColorsOrdered } from './stepColorParser'\nimport { SEWING_TOLERANCE } from '../tolerance'\nimport { computeEffectiveDeflection, type MeshDeflectionOptions } from '../brep/effective-deflection'\nimport { mm } from '../units'\n\n/** A single tessellated mesh produced by the OCCT kernel. */\nexport interface WasmTessellatedMesh {\n positions: Float32Array\n normals: Float32Array\n indices: Uint32Array\n}\n\n/** Result of importing a shape into the OCCT kernel. */\nexport interface WasmImportResult {\n shapeHandle: ShapeHandle\n meshes: WasmTessellatedMesh[]\n meshWithGroups: Mesh\n}\n\n// F5 设计意图说明:\n// OCCT WASM 内核是环境级单例,不是实例级。在整个浏览器页面/Node 进程中只应\n// 初始化一次;多个 CadRuntime 实例共享同一个 kernel 是正确的行为。\n//\n// 2026-09-26 跨实例共享(随 0.18.2 发布):\n// kernelInstance / initPromise / customInitFn 从\"模块级单例\"提升为挂在\n// globalThis 上的共享状态(与 runtime-state.ts 的 `__FAICAD_FAIJS_RUNTIME__`\n// 同款设计)。原因:CDN 装载的第三方库(sheetmetal/cq-compat/faijs-gears)\n// 在 jsDelivr +esm 打包时把 peer `@faicad/faijs` 外部化为**独立模块实例**\n// (根入口与 /api/ 子路径是不同 URL → 不同 bundle),模块级单例导致:\n// - 库实例的 occt 内核从未初始化 → `occt-wasm kernel not initialized`;\n// - 各实例持有不同内核 → 句柄不互通 → `meshShape: Invalid shape ID`。\n// 挂在 globalThis 后,任一实例 initOcctWasm() 产出的内核全局可见,句柄互通。\n// 构建期去重(external / dedupe)仍是主手段,这里是兜底(同 runtime-state 注释)。\n\nconst OCCT_KERNEL_KEY = '__FAICAD_FAIJS_OCCT_KERNEL__'\nconst OCCT_KERNEL_STATE_VERSION = 1\n\n/** occt 内核共享状态(跨 faijs 模块实例,浏览器/Node 双环境)。 */\ninterface OcctKernelSharedState {\n stateVersion: number\n kernelInstance: OcctKernel | null\n initPromise: Promise<OcctKernel> | null\n /** 浏览器 host 注入的 OCCT 初始化函数 */\n customInitFn: (() => Promise<OcctKernel>) | null\n}\n\n/**\n * 获取 occt 内核共享状态(单例)。\n *\n * 挂在 globalThis 上是为了让\"两份 faijs 代码\"(宿主 bundle 一份、第三方库\n * 外部化一份)共享同一份内核状态——否则两份 kernelInstance 导致内核各自\n * 初始化、句柄不互通(几何孤岛)。\n *\n * @returns the shared occt kernel state singleton.\n */\nfunction getOcctKernelSharedState(): OcctKernelSharedState {\n const g = globalThis as unknown as Record<string, unknown>\n const existing = g[OCCT_KERNEL_KEY] as OcctKernelSharedState | undefined\n if (existing) {\n if (existing.stateVersion !== OCCT_KERNEL_STATE_VERSION) {\n throw new Error(\n `[faijs] occt kernel state version mismatch: loaded=${existing.stateVersion}, expected=${OCCT_KERNEL_STATE_VERSION}`,\n )\n }\n return existing\n }\n const created: OcctKernelSharedState = {\n stateVersion: OCCT_KERNEL_STATE_VERSION,\n kernelInstance: null,\n initPromise: null,\n customInitFn: null,\n }\n g[OCCT_KERNEL_KEY] = created\n return created\n}\n\n/**\n * Let the browser host inject the OCCT initialization function.\n *\n * The browser host calls this to register its own init logic (dev/prod/CDN/e2e\n * branches); faijs's initOcctWasm() prefers the injected function. 注入的挂点\n * 写入共享状态——任意 faijs 实例(含 CDN 外部化实例)调 initOcctWasm() 时\n * 都优先使用同一份宿主初始化函数。\n *\n * When nothing is injected, initOcctWasm() reads the WASM from node_modules in\n * a Node environment.\n *\n * @param fn - the initialization function to use, or null to clear\n */\nexport function setOcctWasmInitFn(fn: (() => Promise<OcctKernel>) | null): void {\n const s = getOcctKernelSharedState()\n s.customInitFn = fn\n // 挂点变化后丢弃进行中的初始化(下一次 init 用新挂点重来)。\n s.initPromise = null\n}\n\n/**\n * Resolve the occt-wasm WASM file path (linker-agnostic).\n *\n * Walks the package exports (occt-wasm@3.8.4 exports \"./dist/occt-wasm.wasm\"),\n * independent of cwd / hoisting / pnpm|npm linker (verified pattern C).\n * Replaces the old 4-level `..` path guessing + process.cwd() fallback.\n *\n * Lazy-fetches node:module (Node >= 20.16 process.getBuiltinModule): a static\n * `import { createRequire } from 'node:module'` must not be used — occtKernel is\n * on the browser build's (demo vite build) import chain, and a static node:*\n * import would be externalized and error. This function is only called in the\n * Node branch (initOcctWasm); it never runs in a browser environment.\n *\n * @returns the resolved WASM file path\n */\nexport function resolveOcctWasmPath(): string {\n const builtin = (process as { getBuiltinModule?: (id: string) => unknown }).getBuiltinModule?.('node:module') as\n | { createRequire: (filename: string) => { resolve: (id: string) => string } }\n | undefined\n if (!builtin) {\n throw new Error('[faijs] resolveOcctWasmPath requires Node.js (process.getBuiltinModule)')\n }\n return builtin.createRequire(import.meta.url).resolve('occt-wasm/dist/occt-wasm.wasm')\n}\n\n/**\n * Initialize the occt-wasm kernel (singleton).\n *\n * - Node.js test environment: read the WASM file from node_modules, pass an ArrayBuffer.\n * - Development: direct ESM import, Vite resolves node_modules. The WASM file is loaded from public/wasm/occt-wasm.wasm.\n * - Production: dynamically import the whole module + WASM from a CDN.\n *\n * @returns the initialized raw OCCT kernel (native L2 face — NOT BrepEngineApi;\n * the L1 contract face is built separately by createOcctPrimitives()\n * in brep/engine/adapters/occt.ts as an explicit object literal).\n */\nexport async function initOcctWasm(): Promise<OcctKernel> {\n const s = getOcctKernelSharedState()\n if (s.kernelInstance) return s.kernelInstance\n if (s.initPromise) return s.initPromise\n\n s.initPromise = (async () => {\n // 优先使用浏览器 host 注入的初始化函数(共享挂点,跨实例生效)\n if (s.customInitFn) {\n s.kernelInstance = await s.customInitFn()\n return s.kernelInstance\n }\n\n // Node.js 环境:从 node_modules 读取 WASM 文件\n if (typeof process !== 'undefined' && process.versions?.node) {\n const { OcctKernel: Ctor } = await import('occt-wasm')\n // 与 resolveOcctWasmPath 同款:经 process.getBuiltinModule 取 node:fs,\n // 不用 `await import('node:fs')`——后者会被 vite 打包器静态分析 externalize\n // 并在浏览器构建时报 \"node:fs has been externalized\" warning(本分支运行时\n // 不会在浏览器执行,但打包器仍会对动态 import 字符串告警)。\n const fsBuiltin = (process as { getBuiltinModule?: (id: string) => unknown }).getBuiltinModule?.('node:fs') as\n | { readFileSync: (p: string) => Buffer }\n | undefined\n if (!fsBuiltin) {\n throw new Error('[faijs] occt-wasm init requires Node.js (process.getBuiltinModule)')\n }\n const wasmPath = resolveOcctWasmPath()\n const buf = fsBuiltin.readFileSync(wasmPath)\n const wasmBinary = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer\n s.kernelInstance = await Ctor.init({ wasm: wasmBinary })\n return s.kernelInstance\n }\n\n throw new Error('initOcctWasm: no init function set and not in Node environment. Call setOcctWasmInitFn() first.')\n })()\n\n return s.initPromise\n}\n\n/**\n * Get the initialized kernel instance (initOcctWasm must be called first).\n *\n * @returns the initialized OCCT kernel\n */\nexport function getKernel(): OcctKernel {\n const k = getOcctKernelSharedState().kernelInstance\n if (!k) throw new Error('occt-wasm kernel not initialized — call initOcctWasm() first')\n return k\n}\n\n/**\n * Native-face alias for getKernel() (plan D3 ②): symmetric with\n * getBrepkitKernel() on the brepkit side. Platform-specific code uses this\n * name; the original getKernel() stays for existing host code.\n */\nexport const getOcctKernel = getKernel\n\n/** Release the kernel instance (call when the app unloads). */\nexport function disposeOcctWasm(): void {\n const s = getOcctKernelSharedState()\n if (s.kernelInstance) {\n s.kernelInstance[Symbol.dispose]()\n s.kernelInstance = null\n s.initPromise = null\n }\n}\n\n/** Options controlling mesh deflection during tessellation. */\nexport type { MeshDeflectionOptions } from '../brep/effective-deflection'\n\n/**\n * Compute the effective linear deflection, applying relative scaling\n * exactly as OCCT does internally: `linDefl * bboxDiagonal` when relative=true.\n *\n * 实现已移到引擎中立的 `brep/effective-deflection.ts`(函数体只用\n * `getBoundingBox`,与 OCCT 无关)——此处 re-export 保持既有导入面零迁移。\n * 本模块内部仍要用它,故 import 后再 re-export(纯 re-export 不产生本地绑定)。\n *\n * @param kernel - the OCCT kernel\n * @param shape - the shape whose bounding box drives relative scaling\n * @param options - the requested deflection options\n * @returns the effective linear and angular deflection values\n */\nexport { computeEffectiveDeflection }\n\n/**\n * Import a STEP file to ShapeHandle + Mesh (including face groups).\n *\n * Uses meshShape() rather than tessellate(), so face-group data is available\n * (each face's triangle range [triStart, triCount, faceHash]).\n *\n * @param stepData - STEP file bytes\n * @param deflection - optional mesh deflection options\n * @returns the import result with shape handle and meshes\n */\nexport async function importStepToMesh(\n stepData: ArrayBuffer | Uint8Array,\n deflection?: MeshDeflectionOptions,\n): Promise<WasmImportResult> {\n const kernel = await initOcctWasm()\n const ab = stepData instanceof Uint8Array ? stepData.buffer.slice(stepData.byteOffset, stepData.byteOffset + stepData.byteLength) as ArrayBuffer : stepData\n const shape = kernel.importStep(ab)\n\n const eff = computeEffectiveDeflection(kernel, shape, deflection)\n const mesh = kernel.meshShape(shape, { linearDeflection: eff.linearDeflection, angularDeflection: eff.angularDeflection })\n\n return {\n shapeHandle: shape,\n meshes: [{\n positions: mesh.positions,\n normals: mesh.normals,\n indices: mesh.indices,\n }],\n meshWithGroups: mesh,\n }\n}\n\n// ── Assembly (XCAF) support ──\n\n/** A node in the XCAF assembly tree (mirrors the STEP_T occurrence concept). */\nexport interface AssemblyPartNode {\n /** Dotted path: 'o0', 'o0.o1', 'o0.o1.o2' — matches STEP_T occurrence path. */\n labelPath: string\n /** XCAF label name (falls back to labelPath if empty). */\n name: string\n /** True if this node is an assembly (has child components). */\n isAssembly: boolean\n /**\n * True when `isAssembly` was **synthesised by this reader**, not read from the\n * file: a single XCAF product holding a multi-solid compound gets split into\n * virtual children so each solid becomes its own scene node.\n *\n * The distinction matters to callers that must answer \"is this file really an\n * assembly?\" — e.g. `Assembly.importStep` parity, where upstream rejects a STEP\n * with no assembly structure (`shape_tool.IsAssembly_s` is false for such a\n * product). Without this flag a flat multi-solid STEP looks like an assembly.\n */\n syntheticGroup?: boolean\n /** True if this node is a component reference (leaf part with location). */\n isComponent: boolean\n /** Shape handle with location baked in (for components) or raw shape (for roots).\n * Caller must release this handle. Null for empty assembly labels. */\n shapeHandle: ShapeHandle | null\n /** Deduplication key for prototype shapes (same geometry = same key).\n * Only set for leaf (non-assembly) nodes. */\n prototypeKey: string | null\n /** RGB color [r,g,b] in 0..1 range, or null if no color. */\n color: [number, number, number] | null\n /** Child nodes (recursive). Empty for leaf parts. */\n children: AssemblyPartNode[]\n}\n\nconst IDENTITY_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0]\n\n/**\n * Import a STEP file via XCAF (STEPCAFControl_Reader), preserving the assembly\n * tree, names, colors, and per-component locations.\n *\n * Unlike `importStepToMesh` (which flattens via STEPControl_Reader.OneShape()),\n * this function returns the full assembly tree structure.\n *\n * The caller is responsible for releasing all shapeHandle values in the tree\n * (use `releaseAssemblyTree`).\n *\n * @param stepData - STEP file bytes\n * @returns the root assembly-part nodes\n */\nexport async function importAssemblyFromStep(\n stepData: ArrayBuffer | Uint8Array,\n): Promise<AssemblyPartNode[]> {\n const kernel = (await initOcctWasm()) as unknown as OcctKernel\n const stepText = stepData instanceof Uint8Array\n ? new TextDecoder().decode(stepData)\n : new TextDecoder().decode(new Uint8Array(stepData))\n\n // Parse sub-shape colors from STEP text (fallback for when XCAF label has no color).\n // STEP files from NX/SolidWorks often store colors as STYLED_ITEM on individual\n // solids rather than on XCAF labels, so getLabelInfo returns hasColor=false.\n const solidColors = getSolidColorsOrdered(stepText)\n\n // XCAFDocument.fromSTEP uses STEPCAFControl_Reader with color/name/layer modes\n const doc = kernel.importXCAFFromSTEP(stepText)\n try {\n const rootTags = doc.getRoots()\n const nodes: AssemblyPartNode[] = []\n const cursor = { idx: 0 }\n for (let i = 0; i < rootTags.length; i++) {\n nodes.push(walkLabel(kernel, doc, rootTags[i], `o${i}`, solidColors, cursor))\n }\n return nodes\n } finally {\n doc.close()\n }\n}\n\n/** Walk-context: tracks the current position in the solidColors array across\n * recursive walkLabel calls so that multi-solid compounds consume colors in order. */\ninterface WalkCtx {\n idx: number\n}\n\nfunction walkLabel(\n kernel: OcctKernel,\n doc: XCAFDocument,\n tag: LabelTag,\n path: string,\n solidColors: ([number, number, number] | null)[],\n ctx: WalkCtx,\n): AssemblyPartNode {\n const info: LabelInfo = doc.getLabelInfo(tag)\n const name = info.name || path\n const color = info.hasColor ? [info.color[0], info.color[1], info.color[2]] as [number, number, number] : null\n\n if (info.isAssembly) {\n const childTags = doc.getChildren(tag)\n const children: AssemblyPartNode[] = []\n for (let i = 0; i < childTags.length; i++) {\n children.push(walkLabel(kernel, doc, childTags[i], `${path}.o${i}`, solidColors, ctx))\n }\n // Assembly nodes have no shape of their own; release if one was returned\n if (info.shapeHandle) kernel.release(info.shapeHandle)\n return {\n labelPath: path,\n name,\n isAssembly: true,\n isComponent: false,\n shapeHandle: null,\n prototypeKey: null,\n color,\n children,\n }\n }\n\n // Leaf component — shapeHandle has location baked in (OCCT GetShape semantics)\n // Check if this is a compound with multiple solids — if so, split into\n // separate child nodes so each solid becomes its own mesh/scene-tree node.\n // This handles STEP files that have a single PRODUCT containing a compound\n // of multiple MANIFOLD_SOLID_BREP entities (common in NX/SolidWorks exports).\n if (info.shapeHandle) {\n const solids = kernel.getSubShapes(info.shapeHandle, 'solid')\n if (solids.length > 1) {\n // Multi-solid compound → split into virtual assembly children\n // Each child gets its own solid shapeHandle (already at correct location\n // because getSubShapes extracts from the located compound).\n const children: AssemblyPartNode[] = []\n for (let si = 0; si < solids.length; si++) {\n const childPath = `${path}.s${si}`\n const childName = `${name} [${si + 1}]`\n let childProtoKey: string | null\n try {\n childProtoKey = String(kernel.hashCode(solids[si], 2147483647))\n } catch {\n childProtoKey = null\n }\n // Use STEP-parsed color if label has no color (sub-shape level color)\n const childColor = color ?? (solidColors[ctx.idx] ?? null)\n ctx.idx++\n children.push({\n labelPath: childPath,\n name: childName,\n isAssembly: false,\n isComponent: true,\n shapeHandle: solids[si],\n prototypeKey: childProtoKey,\n color: childColor,\n children: [],\n })\n }\n // Release the compound shape itself — children hold individual solids\n kernel.release(info.shapeHandle)\n return {\n labelPath: path,\n name,\n isAssembly: true, // mark as assembly so it becomes a group node\n syntheticGroup: true, // ...but it is NOT an assembly in the file\n isComponent: false,\n shapeHandle: null,\n prototypeKey: null,\n color,\n children,\n }\n }\n // Single solid (or non-solid) — release the extra sub-shape handles\n for (const s of solids) kernel.release(s)\n }\n\n let prototypeKey: string | null = null\n if (info.shapeHandle) {\n // Get un-located shape for dedup (located with identity = remove location)\n try {\n const unlocated = kernel.located(info.shapeHandle, IDENTITY_MATRIX)\n prototypeKey = String(kernel.hashCode(unlocated, 2147483647))\n kernel.release(unlocated)\n } catch {\n // Fallback: use shapeHandle hash directly (less accurate dedup)\n prototypeKey = String(kernel.hashCode(info.shapeHandle, 2147483647))\n }\n }\n\n // For single-solid leaf parts, also try STEP-parsed color as fallback\n const finalColor = color ?? (solidColors[ctx.idx] ?? null)\n ctx.idx++\n\n return {\n labelPath: path,\n name,\n isAssembly: false,\n isComponent: info.isComponent,\n shapeHandle: info.shapeHandle,\n prototypeKey,\n color: finalColor,\n children: [],\n }\n}\n\n/** Recursively release all shapeHandle values in an assembly tree.\n *\n * @param kernel - the OCCT kernel used to release handles\n * @param nodes - the assembly tree nodes to release\n */\nexport function releaseAssemblyTree(kernel: OcctKernel, nodes: AssemblyPartNode[]): void {\n for (const node of nodes) {\n if (node.shapeHandle) kernel.release(node.shapeHandle)\n if (node.children.length > 0) releaseAssemblyTree(kernel, node.children)\n }\n}\n\n/** Collect all leaf (non-assembly) nodes from an assembly tree.\n *\n * @param nodes - the assembly tree nodes to traverse\n * @returns the collected leaf part nodes in depth-first order\n */\nexport function collectLeafParts(nodes: AssemblyPartNode[]): AssemblyPartNode[] {\n const leaves: AssemblyPartNode[] = []\n function walk(node: AssemblyPartNode) {\n if (node.isAssembly) {\n for (const child of node.children) walk(child)\n } else {\n leaves.push(node)\n }\n }\n for (const node of nodes) walk(node)\n return leaves\n}\n\n/**\n * Import BREP text to ShapeHandle + Mesh.\n *\n * @param brepData - BREP file content as a string\n * @param deflection - optional mesh deflection options\n * @returns the import result with shape handle and meshes\n */\nexport async function importBrepToMesh(\n brepData: string,\n deflection?: MeshDeflectionOptions,\n): Promise<WasmImportResult> {\n const kernel = await initOcctWasm()\n const shape = kernel.fromBREP(brepData)\n\n const eff = computeEffectiveDeflection(kernel, shape, deflection)\n const mesh = kernel.meshShape(shape, { linearDeflection: eff.linearDeflection, angularDeflection: eff.angularDeflection })\n\n return {\n shapeHandle: shape,\n meshes: [{\n positions: mesh.positions,\n normals: mesh.normals,\n indices: mesh.indices,\n }],\n meshWithGroups: mesh,\n }\n}\n\n/**\n * Mesh → STEP export: rebuild a STEP solid from a triangle mesh.\n * Follows the pattern from occt-wasm/examples/stl2step.mjs.\n *\n * @param positions - vertex array [x0,y0,z0, x1,y1,z1, ...]\n * @param indices - index array [i0,i1,i2, i3,i4,i5, ...]\n * @param tolerance - sewing tolerance in mm (default 0.01)\n * @returns the STEP file content string\n */\nexport function meshesToStep(\n positions: Float32Array,\n indices: Uint32Array,\n tolerance = SEWING_TOLERANCE.as(mm),\n): string {\n const kernel = getKernel()\n const faces: ShapeHandle[] = []\n let solid: ShapeHandle | null = null\n\n try {\n for (let i = 0; i < indices.length; i += 3) {\n const ia = indices[i] * 3\n const ib = indices[i + 1] * 3\n const ic = indices[i + 2] * 3\n const face = kernel.buildTriFace(\n { x: positions[ia], y: positions[ia + 1], z: positions[ia + 2] },\n { x: positions[ib], y: positions[ib + 1], z: positions[ib + 2] },\n { x: positions[ic], y: positions[ic + 1], z: positions[ic + 2] },\n )\n faces.push(face)\n }\n\n solid = kernel.sewAndSolidify(faces, tolerance)\n const unified = kernel.unifySameDomain(solid)\n kernel.release(solid)\n solid = unified\n return kernel.exportStep(solid)\n } finally {\n if (solid !== null) kernel.release(solid)\n for (const f of faces) kernel.release(f)\n }\n}\n\n/**\n * Release a shape handle.\n *\n * @param handle - the shape handle to release\n */\nexport function releaseShape(handle: ShapeHandle): void {\n const k = getOcctKernelSharedState().kernelInstance\n if (k) k.release(handle)\n}\n\n/** 导出类型供外部使用 */\nexport type { OcctKernel, ShapeHandle, Mesh, EdgeData, SurfaceKind, CurveKind, BoundingBox, Vec3, XCAFDocument, LabelInfo, LabelTag }\n"]}
|
|
1
|
+
{"version":3,"file":"occtKernel.js","sourceRoot":"","sources":["../../src/occt-kernel/occtKernel.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * occt-wasm 封装层 — 替代 occt-import-js\n *\n * 提供 STEP/BREP → Mesh 转换和 Mesh → STEP 导出能力。\n * 利用 occt-wasm 的 meshShape() 获取 faceGroups(面→三角形映射),\n * 利用 wireframe() 获取边折线数据,利用 edgeToFaceMap() 获取边→面关联。\n */\nimport type { OcctKernel, ShapeHandle, Mesh, EdgeData, SurfaceKind, CurveKind, BoundingBox, Vec3, XCAFDocument, LabelInfo, LabelTag } from 'occt-wasm'\n\nimport { getSolidColorsOrdered } from './stepColorParser'\nimport { SEWING_TOLERANCE } from '../tolerance'\nimport { computeEffectiveDeflection, type MeshDeflectionOptions } from '../brep/effective-deflection'\nimport { mm } from '../units'\n\n/** A single tessellated mesh produced by the OCCT kernel. */\nexport interface WasmTessellatedMesh {\n positions: Float32Array\n normals: Float32Array\n indices: Uint32Array\n}\n\n/** Result of importing a shape into the OCCT kernel. */\nexport interface WasmImportResult {\n shapeHandle: ShapeHandle\n meshes: WasmTessellatedMesh[]\n meshWithGroups: Mesh\n}\n\n// F5 设计意图说明:\n// OCCT WASM 内核是环境级单例,不是实例级。在整个浏览器页面/Node 进程中只应\n// 初始化一次;多个 CadRuntime 实例共享同一个 kernel 是正确的行为。\n//\n// 2026-09-26 跨实例共享(随 0.18.2 发布):\n// kernelInstance / initPromise / customInitFn 从\"模块级单例\"提升为挂在\n// globalThis 上的共享状态(与 runtime-state.ts 的 `__FAICAD_FAIJS_RUNTIME__`\n// 同款设计)。原因:CDN 装载的第三方库(sheetmetal/cq-compat/faijs-gears)\n// 在 jsDelivr +esm 打包时把 peer `@faicad/faijs` 外部化为**独立模块实例**\n// (根入口与 /api/ 子路径是不同 URL → 不同 bundle),模块级单例导致:\n// - 库实例的 occt 内核从未初始化 → `occt-wasm kernel not initialized`;\n// - 各实例持有不同内核 → 句柄不互通 → `meshShape: Invalid shape ID`。\n// 挂在 globalThis 后,任一实例 initOcctWasm() 产出的内核全局可见,句柄互通。\n// 构建期去重(external / dedupe)仍是主手段,这里是兜底(同 runtime-state 注释)。\n\nconst OCCT_KERNEL_KEY = '__FAICAD_FAIJS_OCCT_KERNEL__'\nconst OCCT_KERNEL_STATE_VERSION = 1\n\n/** occt 内核共享状态(跨 faijs 模块实例,浏览器/Node 双环境)。 */\ninterface OcctKernelSharedState {\n stateVersion: number\n kernelInstance: OcctKernel | null\n initPromise: Promise<OcctKernel> | null\n /** 浏览器 host 注入的 OCCT 初始化函数 */\n customInitFn: (() => Promise<OcctKernel>) | null\n}\n\n/**\n * 获取 occt 内核共享状态(单例)。\n *\n * 挂在 globalThis 上是为了让\"两份 faijs 代码\"(宿主 bundle 一份、第三方库\n * 外部化一份)共享同一份内核状态——否则两份 kernelInstance 导致内核各自\n * 初始化、句柄不互通(几何孤岛)。\n *\n * @returns the shared occt kernel state singleton.\n */\nfunction getOcctKernelSharedState(): OcctKernelSharedState {\n const g = globalThis as unknown as Record<string, unknown>\n const existing = g[OCCT_KERNEL_KEY] as OcctKernelSharedState | undefined\n if (existing) {\n if (existing.stateVersion !== OCCT_KERNEL_STATE_VERSION) {\n throw new Error(\n `[faijs] occt kernel state version mismatch: loaded=${existing.stateVersion}, expected=${OCCT_KERNEL_STATE_VERSION}`,\n )\n }\n return existing\n }\n const created: OcctKernelSharedState = {\n stateVersion: OCCT_KERNEL_STATE_VERSION,\n kernelInstance: null,\n initPromise: null,\n customInitFn: null,\n }\n g[OCCT_KERNEL_KEY] = created\n return created\n}\n\n/**\n * Let the browser host inject the OCCT initialization function.\n *\n * The browser host calls this to register its own init logic (dev/prod/CDN/e2e\n * branches); faijs's initOcctWasm() prefers the injected function. 注入的挂点\n * 写入共享状态——任意 faijs 实例(含 CDN 外部化实例)调 initOcctWasm() 时\n * 都优先使用同一份宿主初始化函数。\n *\n * When nothing is injected, initOcctWasm() reads the WASM from node_modules in\n * a Node environment.\n *\n * @param fn - the initialization function to use, or null to clear\n */\nexport function setOcctWasmInitFn(fn: (() => Promise<OcctKernel>) | null): void {\n const s = getOcctKernelSharedState()\n s.customInitFn = fn\n // 挂点变化后丢弃进行中的初始化(下一次 init 用新挂点重来)。\n s.initPromise = null\n}\n\n/**\n * Resolve the occt-wasm WASM file path (linker-agnostic).\n *\n * Walks the package exports (occt-wasm@5.6.0 exports \"./dist/occt-wasm.wasm\"),\n * independent of cwd / hoisting / pnpm|npm linker (verified pattern C).\n * Replaces the old 4-level `..` path guessing + process.cwd() fallback.\n *\n * Lazy-fetches node:module (Node >= 20.16 process.getBuiltinModule): a static\n * `import { createRequire } from 'node:module'` must not be used — occtKernel is\n * on the browser build's (demo vite build) import chain, and a static node:*\n * import would be externalized and error. This function is only called in the\n * Node branch (initOcctWasm); it never runs in a browser environment.\n *\n * @returns the resolved WASM file path\n */\nexport function resolveOcctWasmPath(): string {\n const builtin = (process as { getBuiltinModule?: (id: string) => unknown }).getBuiltinModule?.('node:module') as\n | { createRequire: (filename: string) => { resolve: (id: string) => string } }\n | undefined\n if (!builtin) {\n throw new Error('[faijs] resolveOcctWasmPath requires Node.js (process.getBuiltinModule)')\n }\n return builtin.createRequire(import.meta.url).resolve('occt-wasm/dist/occt-wasm.wasm')\n}\n\n/**\n * Initialize the occt-wasm kernel (singleton).\n *\n * - Node.js test environment: read the WASM file from node_modules, pass an ArrayBuffer.\n * - Development: direct ESM import, Vite resolves node_modules. The WASM file is loaded from public/wasm/occt-wasm.wasm.\n * - Production: dynamically import the whole module + WASM from a CDN.\n *\n * @returns the initialized raw OCCT kernel (native L2 face — NOT BrepEngineApi;\n * the L1 contract face is built separately by createOcctPrimitives()\n * in brep/engine/adapters/occt.ts as an explicit object literal).\n */\nexport async function initOcctWasm(): Promise<OcctKernel> {\n const s = getOcctKernelSharedState()\n if (s.kernelInstance) return s.kernelInstance\n if (s.initPromise) return s.initPromise\n\n s.initPromise = (async () => {\n // 优先使用浏览器 host 注入的初始化函数(共享挂点,跨实例生效)\n if (s.customInitFn) {\n s.kernelInstance = await s.customInitFn()\n return s.kernelInstance\n }\n\n // Node.js 环境:从 node_modules 读取 WASM 文件\n if (typeof process !== 'undefined' && process.versions?.node) {\n const { OcctKernel: Ctor } = await import('occt-wasm')\n // 与 resolveOcctWasmPath 同款:经 process.getBuiltinModule 取 node:fs,\n // 不用 `await import('node:fs')`——后者会被 vite 打包器静态分析 externalize\n // 并在浏览器构建时报 \"node:fs has been externalized\" warning(本分支运行时\n // 不会在浏览器执行,但打包器仍会对动态 import 字符串告警)。\n const fsBuiltin = (process as { getBuiltinModule?: (id: string) => unknown }).getBuiltinModule?.('node:fs') as\n | { readFileSync: (p: string) => Buffer }\n | undefined\n if (!fsBuiltin) {\n throw new Error('[faijs] occt-wasm init requires Node.js (process.getBuiltinModule)')\n }\n const wasmPath = resolveOcctWasmPath()\n const buf = fsBuiltin.readFileSync(wasmPath)\n const wasmBinary = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer\n s.kernelInstance = await Ctor.init({ wasm: wasmBinary })\n return s.kernelInstance\n }\n\n throw new Error('initOcctWasm: no init function set and not in Node environment. Call setOcctWasmInitFn() first.')\n })()\n\n return s.initPromise\n}\n\n/**\n * Get the initialized kernel instance (initOcctWasm must be called first).\n *\n * @returns the initialized OCCT kernel\n */\nexport function getKernel(): OcctKernel {\n const k = getOcctKernelSharedState().kernelInstance\n if (!k) throw new Error('occt-wasm kernel not initialized — call initOcctWasm() first')\n return k\n}\n\n/**\n * Native-face alias for getKernel() (plan D3 ②): symmetric with\n * getBrepkitKernel() on the brepkit side. Platform-specific code uses this\n * name; the original getKernel() stays for existing host code.\n */\nexport const getOcctKernel = getKernel\n\n/** Release the kernel instance (call when the app unloads). */\nexport function disposeOcctWasm(): void {\n const s = getOcctKernelSharedState()\n if (s.kernelInstance) {\n s.kernelInstance[Symbol.dispose]()\n s.kernelInstance = null\n s.initPromise = null\n }\n}\n\n/** Options controlling mesh deflection during tessellation. */\nexport type { MeshDeflectionOptions } from '../brep/effective-deflection'\n\n/**\n * Compute the effective linear deflection, applying relative scaling\n * exactly as OCCT does internally: `linDefl * bboxDiagonal` when relative=true.\n *\n * 实现已移到引擎中立的 `brep/effective-deflection.ts`(函数体只用\n * `getBoundingBox`,与 OCCT 无关)——此处 re-export 保持既有导入面零迁移。\n * 本模块内部仍要用它,故 import 后再 re-export(纯 re-export 不产生本地绑定)。\n *\n * @param kernel - the OCCT kernel\n * @param shape - the shape whose bounding box drives relative scaling\n * @param options - the requested deflection options\n * @returns the effective linear and angular deflection values\n */\nexport { computeEffectiveDeflection }\n\n/**\n * Import a STEP file to ShapeHandle + Mesh (including face groups).\n *\n * Uses meshShape() rather than tessellate(), so face-group data is available\n * (each face's triangle range [triStart, triCount, faceHash]).\n *\n * @param stepData - STEP file bytes\n * @param deflection - optional mesh deflection options\n * @returns the import result with shape handle and meshes\n */\nexport async function importStepToMesh(\n stepData: ArrayBuffer | Uint8Array,\n deflection?: MeshDeflectionOptions,\n): Promise<WasmImportResult> {\n const kernel = await initOcctWasm()\n const ab = stepData instanceof Uint8Array ? stepData.buffer.slice(stepData.byteOffset, stepData.byteOffset + stepData.byteLength) as ArrayBuffer : stepData\n const shape = kernel.importStep(ab)\n\n const eff = computeEffectiveDeflection(kernel, shape, deflection)\n const mesh = kernel.meshShape(shape, { linearDeflection: eff.linearDeflection, angularDeflection: eff.angularDeflection })\n\n return {\n shapeHandle: shape,\n meshes: [{\n positions: mesh.positions,\n normals: mesh.normals,\n indices: mesh.indices,\n }],\n meshWithGroups: mesh,\n }\n}\n\n// ── Assembly (XCAF) support ──\n\n/** A node in the XCAF assembly tree (mirrors the STEP_T occurrence concept). */\nexport interface AssemblyPartNode {\n /** Dotted path: 'o0', 'o0.o1', 'o0.o1.o2' — matches STEP_T occurrence path. */\n labelPath: string\n /** XCAF label name (falls back to labelPath if empty). */\n name: string\n /** True if this node is an assembly (has child components). */\n isAssembly: boolean\n /**\n * True when `isAssembly` was **synthesised by this reader**, not read from the\n * file: a single XCAF product holding a multi-solid compound gets split into\n * virtual children so each solid becomes its own scene node.\n *\n * The distinction matters to callers that must answer \"is this file really an\n * assembly?\" — e.g. `Assembly.importStep` parity, where upstream rejects a STEP\n * with no assembly structure (`shape_tool.IsAssembly_s` is false for such a\n * product). Without this flag a flat multi-solid STEP looks like an assembly.\n */\n syntheticGroup?: boolean\n /** True if this node is a component reference (leaf part with location). */\n isComponent: boolean\n /** Shape handle with location baked in (for components) or raw shape (for roots).\n * Caller must release this handle. Null for empty assembly labels. */\n shapeHandle: ShapeHandle | null\n /** Deduplication key for prototype shapes (same geometry = same key).\n * Only set for leaf (non-assembly) nodes. */\n prototypeKey: string | null\n /** RGB color [r,g,b] in 0..1 range, or null if no color. */\n color: [number, number, number] | null\n /** Child nodes (recursive). Empty for leaf parts. */\n children: AssemblyPartNode[]\n}\n\nconst IDENTITY_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0]\n\n/**\n * Import a STEP file via XCAF (STEPCAFControl_Reader), preserving the assembly\n * tree, names, colors, and per-component locations.\n *\n * Unlike `importStepToMesh` (which flattens via STEPControl_Reader.OneShape()),\n * this function returns the full assembly tree structure.\n *\n * The caller is responsible for releasing all shapeHandle values in the tree\n * (use `releaseAssemblyTree`).\n *\n * @param stepData - STEP file bytes\n * @returns the root assembly-part nodes\n */\nexport async function importAssemblyFromStep(\n stepData: ArrayBuffer | Uint8Array,\n): Promise<AssemblyPartNode[]> {\n const kernel = (await initOcctWasm()) as unknown as OcctKernel\n const stepText = stepData instanceof Uint8Array\n ? new TextDecoder().decode(stepData)\n : new TextDecoder().decode(new Uint8Array(stepData))\n\n // Parse sub-shape colors from STEP text (fallback for when XCAF label has no color).\n // STEP files from NX/SolidWorks often store colors as STYLED_ITEM on individual\n // solids rather than on XCAF labels, so getLabelInfo returns hasColor=false.\n const solidColors = getSolidColorsOrdered(stepText)\n\n // XCAFDocument.fromSTEP uses STEPCAFControl_Reader with color/name/layer modes\n const doc = kernel.importXCAFFromSTEP(stepText)\n try {\n const rootTags = doc.getRoots()\n const nodes: AssemblyPartNode[] = []\n const cursor = { idx: 0 }\n for (let i = 0; i < rootTags.length; i++) {\n nodes.push(walkLabel(kernel, doc, rootTags[i], `o${i}`, solidColors, cursor))\n }\n return nodes\n } finally {\n doc.close()\n }\n}\n\n/** Walk-context: tracks the current position in the solidColors array across\n * recursive walkLabel calls so that multi-solid compounds consume colors in order. */\ninterface WalkCtx {\n idx: number\n}\n\nfunction walkLabel(\n kernel: OcctKernel,\n doc: XCAFDocument,\n tag: LabelTag,\n path: string,\n solidColors: ([number, number, number] | null)[],\n ctx: WalkCtx,\n): AssemblyPartNode {\n const info: LabelInfo = doc.getLabelInfo(tag)\n const name = info.name || path\n const color = info.hasColor ? [info.color[0], info.color[1], info.color[2]] as [number, number, number] : null\n\n if (info.isAssembly) {\n const childTags = doc.getChildren(tag)\n const children: AssemblyPartNode[] = []\n for (let i = 0; i < childTags.length; i++) {\n children.push(walkLabel(kernel, doc, childTags[i], `${path}.o${i}`, solidColors, ctx))\n }\n // Assembly nodes have no shape of their own; release if one was returned\n if (info.shapeHandle) kernel.release(info.shapeHandle)\n return {\n labelPath: path,\n name,\n isAssembly: true,\n isComponent: false,\n shapeHandle: null,\n prototypeKey: null,\n color,\n children,\n }\n }\n\n // Leaf component — shapeHandle has location baked in (OCCT GetShape semantics)\n // Check if this is a compound with multiple solids — if so, split into\n // separate child nodes so each solid becomes its own mesh/scene-tree node.\n // This handles STEP files that have a single PRODUCT containing a compound\n // of multiple MANIFOLD_SOLID_BREP entities (common in NX/SolidWorks exports).\n if (info.shapeHandle) {\n const solids = kernel.getSubShapes(info.shapeHandle, 'solid')\n if (solids.length > 1) {\n // Multi-solid compound → split into virtual assembly children\n // Each child gets its own solid shapeHandle (already at correct location\n // because getSubShapes extracts from the located compound).\n const children: AssemblyPartNode[] = []\n for (let si = 0; si < solids.length; si++) {\n const childPath = `${path}.s${si}`\n const childName = `${name} [${si + 1}]`\n let childProtoKey: string | null\n try {\n childProtoKey = String(kernel.hashCode(solids[si], 2147483647))\n } catch {\n childProtoKey = null\n }\n // Use STEP-parsed color if label has no color (sub-shape level color)\n const childColor = color ?? (solidColors[ctx.idx] ?? null)\n ctx.idx++\n children.push({\n labelPath: childPath,\n name: childName,\n isAssembly: false,\n isComponent: true,\n shapeHandle: solids[si],\n prototypeKey: childProtoKey,\n color: childColor,\n children: [],\n })\n }\n // Release the compound shape itself — children hold individual solids\n kernel.release(info.shapeHandle)\n return {\n labelPath: path,\n name,\n isAssembly: true, // mark as assembly so it becomes a group node\n syntheticGroup: true, // ...but it is NOT an assembly in the file\n isComponent: false,\n shapeHandle: null,\n prototypeKey: null,\n color,\n children,\n }\n }\n // Single solid (or non-solid) — release the extra sub-shape handles\n for (const s of solids) kernel.release(s)\n }\n\n let prototypeKey: string | null = null\n if (info.shapeHandle) {\n // Get un-located shape for dedup (located with identity = remove location)\n try {\n const unlocated = kernel.located(info.shapeHandle, IDENTITY_MATRIX)\n prototypeKey = String(kernel.hashCode(unlocated, 2147483647))\n kernel.release(unlocated)\n } catch {\n // Fallback: use shapeHandle hash directly (less accurate dedup)\n prototypeKey = String(kernel.hashCode(info.shapeHandle, 2147483647))\n }\n }\n\n // For single-solid leaf parts, also try STEP-parsed color as fallback\n const finalColor = color ?? (solidColors[ctx.idx] ?? null)\n ctx.idx++\n\n return {\n labelPath: path,\n name,\n isAssembly: false,\n isComponent: info.isComponent,\n shapeHandle: info.shapeHandle,\n prototypeKey,\n color: finalColor,\n children: [],\n }\n}\n\n/** Recursively release all shapeHandle values in an assembly tree.\n *\n * @param kernel - the OCCT kernel used to release handles\n * @param nodes - the assembly tree nodes to release\n */\nexport function releaseAssemblyTree(kernel: OcctKernel, nodes: AssemblyPartNode[]): void {\n for (const node of nodes) {\n if (node.shapeHandle) kernel.release(node.shapeHandle)\n if (node.children.length > 0) releaseAssemblyTree(kernel, node.children)\n }\n}\n\n/** Collect all leaf (non-assembly) nodes from an assembly tree.\n *\n * @param nodes - the assembly tree nodes to traverse\n * @returns the collected leaf part nodes in depth-first order\n */\nexport function collectLeafParts(nodes: AssemblyPartNode[]): AssemblyPartNode[] {\n const leaves: AssemblyPartNode[] = []\n function walk(node: AssemblyPartNode) {\n if (node.isAssembly) {\n for (const child of node.children) walk(child)\n } else {\n leaves.push(node)\n }\n }\n for (const node of nodes) walk(node)\n return leaves\n}\n\n/**\n * Import BREP text to ShapeHandle + Mesh.\n *\n * @param brepData - BREP file content as a string\n * @param deflection - optional mesh deflection options\n * @returns the import result with shape handle and meshes\n */\nexport async function importBrepToMesh(\n brepData: string,\n deflection?: MeshDeflectionOptions,\n): Promise<WasmImportResult> {\n const kernel = await initOcctWasm()\n const shape = kernel.fromBREP(brepData)\n\n const eff = computeEffectiveDeflection(kernel, shape, deflection)\n const mesh = kernel.meshShape(shape, { linearDeflection: eff.linearDeflection, angularDeflection: eff.angularDeflection })\n\n return {\n shapeHandle: shape,\n meshes: [{\n positions: mesh.positions,\n normals: mesh.normals,\n indices: mesh.indices,\n }],\n meshWithGroups: mesh,\n }\n}\n\n/**\n * Mesh → STEP export: rebuild a STEP solid from a triangle mesh.\n * Follows the pattern from occt-wasm/examples/stl2step.mjs.\n *\n * @param positions - vertex array [x0,y0,z0, x1,y1,z1, ...]\n * @param indices - index array [i0,i1,i2, i3,i4,i5, ...]\n * @param tolerance - sewing tolerance in mm (default 0.01)\n * @returns the STEP file content string\n */\nexport function meshesToStep(\n positions: Float32Array,\n indices: Uint32Array,\n tolerance = SEWING_TOLERANCE.as(mm),\n): string {\n const kernel = getKernel()\n const faces: ShapeHandle[] = []\n let solid: ShapeHandle | null = null\n\n try {\n for (let i = 0; i < indices.length; i += 3) {\n const ia = indices[i] * 3\n const ib = indices[i + 1] * 3\n const ic = indices[i + 2] * 3\n const face = kernel.buildTriFace(\n { x: positions[ia], y: positions[ia + 1], z: positions[ia + 2] },\n { x: positions[ib], y: positions[ib + 1], z: positions[ib + 2] },\n { x: positions[ic], y: positions[ic + 1], z: positions[ic + 2] },\n )\n faces.push(face)\n }\n\n solid = kernel.sewAndSolidify(faces, tolerance)\n const unified = kernel.unifySameDomain(solid)\n kernel.release(solid)\n solid = unified\n return kernel.exportStep(solid)\n } finally {\n if (solid !== null) kernel.release(solid)\n for (const f of faces) kernel.release(f)\n }\n}\n\n/**\n * Release a shape handle.\n *\n * @param handle - the shape handle to release\n */\nexport function releaseShape(handle: ShapeHandle): void {\n const k = getOcctKernelSharedState().kernelInstance\n if (k) k.release(handle)\n}\n\n/** 导出类型供外部使用 */\nexport type { OcctKernel, ShapeHandle, Mesh, EdgeData, SurfaceKind, CurveKind, BoundingBox, Vec3, XCAFDocument, LabelInfo, LabelTag }\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STEP 元数据解析器 — 从 STEP (P21) 文本头部与 PRODUCT 层提取
|
|
3
|
+
* FileMeta(文件级)与 ShapeMeta(零件级描述字/料号)。
|
|
4
|
+
*
|
|
5
|
+
* 与 stepColorParser 同一原则:纯文本扫描,不依赖 OCCT 内核(XCAF label 层
|
|
6
|
+
* 是否暴露 description/属性不确定,见设计文档 2026-10-05-meta §6.3 风险 2)。
|
|
7
|
+
*
|
|
8
|
+
* 读取面映射(§3.3):
|
|
9
|
+
* - HEADER FILE_NAME(name,time_stamp,author,organization,preprocessor,originator)
|
|
10
|
+
* → title / creationDate / author / organization / application / designer。
|
|
11
|
+
* - HEADER FILE_DESCRIPTION(...) → description(逗号拼接,去首尾引号)。
|
|
12
|
+
* - DATA PRODUCT(name,description,frame)(第一个、leaf 使用的)→ 零件 description。
|
|
13
|
+
* name 已由 OCCT label 提供(不在本解析器处理)。
|
|
14
|
+
* - PRODUCT → PRODUCT_DEFINITION_FORMATION/WITH_SPECIFIED_SOURCE-关联的料号通道:
|
|
15
|
+
* PART_NUMBER_PROPERTY/IDENTIFICATION 命名在 §3.3 表里列出的 PART 层通道(P4
|
|
16
|
+
* 标 "IDENTIFICATION 内核支持" 待实测),这里尽量从 PRODUCT_DEFINITION 挂的
|
|
17
|
+
* UDA(GENERAL_PROPERTY + PROPERTY_DEFINITION)捞自定义属性。
|
|
18
|
+
*
|
|
19
|
+
* 所有扫描都容错:找不到就不给对应字段,绝不让解析器抛(信息性收益)。
|
|
20
|
+
*/
|
|
21
|
+
/** Header 级人物贡献字段(FILE_NAME 组内的三四五参数)。 */
|
|
22
|
+
export interface StepFileMeta {
|
|
23
|
+
title?: string;
|
|
24
|
+
creationDate?: string;
|
|
25
|
+
designer?: string;
|
|
26
|
+
author?: string;
|
|
27
|
+
organization?: string;
|
|
28
|
+
application?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
/** 自定义 FILE_DESCRIPTION/FILE_NAME 之外的 vendor 属性(metadata 笼)。 */
|
|
31
|
+
metadata?: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
/** STEP 伙伴级 P21 解析出的轻量属性。 */
|
|
34
|
+
export interface StepPartMeta {
|
|
35
|
+
/** 产品描述(PRODUCT( ..., description, id ))。空串/缺省不设。 */
|
|
36
|
+
description?: string;
|
|
37
|
+
/** 自定义属性:`PROPERTY_DEFINITION(...)` + `GENERAL_PROPERTY('name', value, ...)`。 */
|
|
38
|
+
metadata?: Record<string, string>;
|
|
39
|
+
}
|
|
40
|
+
/** Header 段整块(FILE_NAME / FILE_DESCRIPTION / FILE_SCHEMA)→ FileMeta。 */
|
|
41
|
+
export declare function parseStepHeaderMeta(text: string): StepFileMeta;
|
|
42
|
+
/** 伙伴层 PRODUCT 描述 + 根相关字段解析(简化:只取第一个 PRODUCT)。 */
|
|
43
|
+
export declare function parseStepPartMeta(text: string): StepPartMeta;
|
|
44
|
+
//# sourceMappingURL=stepMetaParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stepMetaParser.d.ts","sourceRoot":"","sources":["../../src/occt-kernel/stepMetaParser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAClC;AAED,6BAA6B;AAC7B,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAClC;AA2DD,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CA+C9D;AAED,kDAAkD;AAClD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAyB5D"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STEP 元数据解析器 — 从 STEP (P21) 文本头部与 PRODUCT 层提取
|
|
3
|
+
* FileMeta(文件级)与 ShapeMeta(零件级描述字/料号)。
|
|
4
|
+
*
|
|
5
|
+
* 与 stepColorParser 同一原则:纯文本扫描,不依赖 OCCT 内核(XCAF label 层
|
|
6
|
+
* 是否暴露 description/属性不确定,见设计文档 2026-10-05-meta §6.3 风险 2)。
|
|
7
|
+
*
|
|
8
|
+
* 读取面映射(§3.3):
|
|
9
|
+
* - HEADER FILE_NAME(name,time_stamp,author,organization,preprocessor,originator)
|
|
10
|
+
* → title / creationDate / author / organization / application / designer。
|
|
11
|
+
* - HEADER FILE_DESCRIPTION(...) → description(逗号拼接,去首尾引号)。
|
|
12
|
+
* - DATA PRODUCT(name,description,frame)(第一个、leaf 使用的)→ 零件 description。
|
|
13
|
+
* name 已由 OCCT label 提供(不在本解析器处理)。
|
|
14
|
+
* - PRODUCT → PRODUCT_DEFINITION_FORMATION/WITH_SPECIFIED_SOURCE-关联的料号通道:
|
|
15
|
+
* PART_NUMBER_PROPERTY/IDENTIFICATION 命名在 §3.3 表里列出的 PART 层通道(P4
|
|
16
|
+
* 标 "IDENTIFICATION 内核支持" 待实测),这里尽量从 PRODUCT_DEFINITION 挂的
|
|
17
|
+
* UDA(GENERAL_PROPERTY + PROPERTY_DEFINITION)捞自定义属性。
|
|
18
|
+
*
|
|
19
|
+
* 所有扫描都容错:找不到就不给对应字段,绝不让解析器抛(信息性收益)。
|
|
20
|
+
*/
|
|
21
|
+
/** 剥离一层引号(STEP 字符串形如 `'abc'`),出双引号化转义;去末尾换行。 */
|
|
22
|
+
function unquote(s) {
|
|
23
|
+
const t = s.trim();
|
|
24
|
+
if (t.startsWith("'") && t.endsWith("'"))
|
|
25
|
+
return t.slice(1, -1);
|
|
26
|
+
return t;
|
|
27
|
+
}
|
|
28
|
+
/** 任一 `HEADER`/`DATA` 段中的实体文本(多行),从 header 段中取整行。 */
|
|
29
|
+
function headerLines(text) {
|
|
30
|
+
const m = /HEADER;\n([\s\S]*?)\nENDSEC;/.exec(text);
|
|
31
|
+
return m ? m[1] : '';
|
|
32
|
+
}
|
|
33
|
+
/** `TYPE(...)` 实体块捕获:从开括号起做括号配平扫描到闭合(容错 LIST/嵌套)。 */
|
|
34
|
+
function entityBlock(text, type) {
|
|
35
|
+
const re = new RegExp(`${type}\\s*\\(`, 'g');
|
|
36
|
+
let m;
|
|
37
|
+
while ((m = re.exec(text)) !== null) {
|
|
38
|
+
let depth = 0;
|
|
39
|
+
let inQuote = false;
|
|
40
|
+
let i = m.index + m[0].length - 1; // 停在开括号
|
|
41
|
+
for (; i < text.length; i++) {
|
|
42
|
+
const c = text[i];
|
|
43
|
+
if (c === "'")
|
|
44
|
+
inQuote = !inQuote;
|
|
45
|
+
if (inQuote)
|
|
46
|
+
continue;
|
|
47
|
+
if (c === '(')
|
|
48
|
+
depth++;
|
|
49
|
+
else if (c === ')') {
|
|
50
|
+
depth--;
|
|
51
|
+
if (depth === 0)
|
|
52
|
+
return text.slice(m.index, i + 1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
/** 逗号分隔的顶层简单参数(忽略嵌套括号内容仍按逗号简单切——够用即可)。 */
|
|
59
|
+
function splitTopLevel(body) {
|
|
60
|
+
// 剥离外层括号后,按未被引号包裹的逗号切分(不处理嵌套括号——STEP 伙伴级
|
|
61
|
+
// FILE_NAME/FILE_DESCRIPTION 参数都是简单标量/字符串,不涉及深层嵌套)。
|
|
62
|
+
const s = body.slice(body.indexOf('(') + 1, body.lastIndexOf(')'));
|
|
63
|
+
const parts = [];
|
|
64
|
+
let cur = '';
|
|
65
|
+
let inQuote = false;
|
|
66
|
+
for (let i = 0; i < s.length; i++) {
|
|
67
|
+
const c = s[i];
|
|
68
|
+
if (c === "'")
|
|
69
|
+
inQuote = !inQuote;
|
|
70
|
+
if (c === ',' && !inQuote) {
|
|
71
|
+
parts.push(cur);
|
|
72
|
+
cur = '';
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
cur += c;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
parts.push(cur);
|
|
79
|
+
return parts.map((p) => p.trim());
|
|
80
|
+
}
|
|
81
|
+
/** Header 段整块(FILE_NAME / FILE_DESCRIPTION / FILE_SCHEMA)→ FileMeta。 */
|
|
82
|
+
export function parseStepHeaderMeta(text) {
|
|
83
|
+
const meta = {};
|
|
84
|
+
const header = headerLines(text);
|
|
85
|
+
if (!header)
|
|
86
|
+
return meta;
|
|
87
|
+
const fileBlock = entityBlock(header, 'FILE_NAME');
|
|
88
|
+
if (fileBlock) {
|
|
89
|
+
const parts = splitTopLevel(fileBlock);
|
|
90
|
+
// FILE_NAME(name, time_stamp, author(list), organization(list), preprocessor, originator)
|
|
91
|
+
// 引号数组形如 `('x')`,去首尾括号后 unquote;author/organization 可能为列表。
|
|
92
|
+
const inline = (p) => {
|
|
93
|
+
if (!p)
|
|
94
|
+
return undefined;
|
|
95
|
+
const v = unquote(p.replace(/^\(|\)$/g, ''));
|
|
96
|
+
return v === '' ? undefined : v;
|
|
97
|
+
};
|
|
98
|
+
const title = inline(parts[0]);
|
|
99
|
+
if (title)
|
|
100
|
+
meta.title = title;
|
|
101
|
+
const cdate = inline(parts[1]);
|
|
102
|
+
if (cdate)
|
|
103
|
+
meta.creationDate = cdate;
|
|
104
|
+
const author = inline(parts[2] ?? '');
|
|
105
|
+
if (author)
|
|
106
|
+
meta.author = author;
|
|
107
|
+
const org = inline(parts[3] ?? '');
|
|
108
|
+
if (org)
|
|
109
|
+
meta.organization = org;
|
|
110
|
+
// preprocessor → application(编辑器导入后端把 preprocessor 视为 APP);
|
|
111
|
+
// originator → designer。
|
|
112
|
+
const pre = inline(parts[4] ?? '');
|
|
113
|
+
if (pre)
|
|
114
|
+
meta.application = pre;
|
|
115
|
+
const origin = inline(parts[5] ?? '');
|
|
116
|
+
if (origin)
|
|
117
|
+
meta.designer = origin;
|
|
118
|
+
}
|
|
119
|
+
const descBlock = entityBlock(header, 'FILE_DESCRIPTION');
|
|
120
|
+
if (descBlock) {
|
|
121
|
+
// FILE_DESCRIPTION(description_list, implementation_context):描述只取第一个
|
|
122
|
+
// 顶层参数(描述串列表,`('a','b')` 形态含内层逗号);实现上下文不算。
|
|
123
|
+
// 直接取 `FILE_DESCRIPTION((…),` 里第一层括号内的引号字符串列表。
|
|
124
|
+
const m = /FILE_DESCRIPTION\s*\(\s*\((.*?)\)\s*,\s*/.exec(descBlock);
|
|
125
|
+
if (m) {
|
|
126
|
+
const joined = m[1]
|
|
127
|
+
.split(',')
|
|
128
|
+
.map((p) => unquote(p.trim()))
|
|
129
|
+
.filter((v) => v !== '');
|
|
130
|
+
if (joined.length > 0)
|
|
131
|
+
meta.description = joined.join(', ');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return meta;
|
|
135
|
+
}
|
|
136
|
+
/** 伙伴层 PRODUCT 描述 + 根相关字段解析(简化:只取第一个 PRODUCT)。 */
|
|
137
|
+
export function parseStepPartMeta(text) {
|
|
138
|
+
const out = {};
|
|
139
|
+
// 逐 PRODUCT 取 description(第 2 个参数)。
|
|
140
|
+
const dataRe = /PRODUCT\s*\(/g;
|
|
141
|
+
let m;
|
|
142
|
+
while ((m = dataRe.exec(text)) !== null) {
|
|
143
|
+
const close = text.indexOf(')', m.index);
|
|
144
|
+
if (close < 0)
|
|
145
|
+
break;
|
|
146
|
+
const inner = text.slice(m.index, close + 1);
|
|
147
|
+
const descM = /,\s*'([^']*)'/.exec(inner);
|
|
148
|
+
if (descM) {
|
|
149
|
+
const d = descM[1];
|
|
150
|
+
if (d !== '')
|
|
151
|
+
out.description = d;
|
|
152
|
+
break; // 只取第一个
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// 属性笼(UDA:GENERAL_PROPERTY('name', value?) 挂在 PROPERTY_DEFINITION 上)。
|
|
156
|
+
const props = {};
|
|
157
|
+
const gpRe = /GENERAL_PROPERTY\s*\(\s*'([^']*)'\s*,\s*([^,)]+)/g;
|
|
158
|
+
let gm;
|
|
159
|
+
while ((gm = gpRe.exec(text)) !== null) {
|
|
160
|
+
props[gm[1]] = unquote(gm[2]);
|
|
161
|
+
}
|
|
162
|
+
if (Object.keys(props).length > 0)
|
|
163
|
+
out.metadata = props;
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=stepMetaParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stepMetaParser.js","sourceRoot":"","sources":["../../src/occt-kernel/stepMetaParser.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * STEP 元数据解析器 — 从 STEP (P21) 文本头部与 PRODUCT 层提取\n * FileMeta(文件级)与 ShapeMeta(零件级描述字/料号)。\n *\n * 与 stepColorParser 同一原则:纯文本扫描,不依赖 OCCT 内核(XCAF label 层\n * 是否暴露 description/属性不确定,见设计文档 2026-10-05-meta §6.3 风险 2)。\n *\n * 读取面映射(§3.3):\n * - HEADER FILE_NAME(name,time_stamp,author,organization,preprocessor,originator)\n * → title / creationDate / author / organization / application / designer。\n * - HEADER FILE_DESCRIPTION(...) → description(逗号拼接,去首尾引号)。\n * - DATA PRODUCT(name,description,frame)(第一个、leaf 使用的)→ 零件 description。\n * name 已由 OCCT label 提供(不在本解析器处理)。\n * - PRODUCT → PRODUCT_DEFINITION_FORMATION/WITH_SPECIFIED_SOURCE-关联的料号通道:\n * PART_NUMBER_PROPERTY/IDENTIFICATION 命名在 §3.3 表里列出的 PART 层通道(P4\n * 标 \"IDENTIFICATION 内核支持\" 待实测),这里尽量从 PRODUCT_DEFINITION 挂的\n * UDA(GENERAL_PROPERTY + PROPERTY_DEFINITION)捞自定义属性。\n *\n * 所有扫描都容错:找不到就不给对应字段,绝不让解析器抛(信息性收益)。\n */\n\n/** Header 级人物贡献字段(FILE_NAME 组内的三四五参数)。 */\nexport interface StepFileMeta {\n title?: string\n creationDate?: string\n designer?: string\n author?: string\n organization?: string\n application?: string\n description?: string\n /** 自定义 FILE_DESCRIPTION/FILE_NAME 之外的 vendor 属性(metadata 笼)。 */\n metadata?: Record<string, string>\n}\n\n/** STEP 伙伴级 P21 解析出的轻量属性。 */\nexport interface StepPartMeta {\n /** 产品描述(PRODUCT( ..., description, id ))。空串/缺省不设。 */\n description?: string\n /** 自定义属性:`PROPERTY_DEFINITION(...)` + `GENERAL_PROPERTY('name', value, ...)`。 */\n metadata?: Record<string, string>\n}\n\n/** 剥离一层引号(STEP 字符串形如 `'abc'`),出双引号化转义;去末尾换行。 */\nfunction unquote(s: string): string {\n const t = s.trim()\n if (t.startsWith(\"'\") && t.endsWith(\"'\")) return t.slice(1, -1)\n return t\n}\n\n/** 任一 `HEADER`/`DATA` 段中的实体文本(多行),从 header 段中取整行。 */\nfunction headerLines(text: string): string {\n const m = /HEADER;\\n([\\s\\S]*?)\\nENDSEC;/.exec(text)\n return m ? m[1] : ''\n}\n\n/** `TYPE(...)` 实体块捕获:从开括号起做括号配平扫描到闭合(容错 LIST/嵌套)。 */\nfunction entityBlock(text: string, type: string): string | undefined {\n const re = new RegExp(`${type}\\\\s*\\\\(`, 'g')\n let m: RegExpExecArray | null\n while ((m = re.exec(text)) !== null) {\n let depth = 0\n let inQuote = false\n let i = m.index + m[0].length - 1 // 停在开括号\n for (; i < text.length; i++) {\n const c = text[i]\n if (c === \"'\") inQuote = !inQuote\n if (inQuote) continue\n if (c === '(') depth++\n else if (c === ')') {\n depth--\n if (depth === 0) return text.slice(m.index, i + 1)\n }\n }\n }\n return undefined\n}\n\n/** 逗号分隔的顶层简单参数(忽略嵌套括号内容仍按逗号简单切——够用即可)。 */\nfunction splitTopLevel(body: string): string[] {\n // 剥离外层括号后,按未被引号包裹的逗号切分(不处理嵌套括号——STEP 伙伴级\n // FILE_NAME/FILE_DESCRIPTION 参数都是简单标量/字符串,不涉及深层嵌套)。\n const s = body.slice(body.indexOf('(') + 1, body.lastIndexOf(')'))\n const parts: string[] = []\n let cur = ''\n let inQuote = false\n for (let i = 0; i < s.length; i++) {\n const c = s[i]\n if (c === \"'\") inQuote = !inQuote\n if (c === ',' && !inQuote) {\n parts.push(cur)\n cur = ''\n } else {\n cur += c\n }\n }\n parts.push(cur)\n return parts.map((p) => p.trim())\n}\n\n/** Header 段整块(FILE_NAME / FILE_DESCRIPTION / FILE_SCHEMA)→ FileMeta。 */\nexport function parseStepHeaderMeta(text: string): StepFileMeta {\n const meta: StepFileMeta = {}\n const header = headerLines(text)\n if (!header) return meta\n\n const fileBlock = entityBlock(header, 'FILE_NAME')\n if (fileBlock) {\n const parts = splitTopLevel(fileBlock)\n // FILE_NAME(name, time_stamp, author(list), organization(list), preprocessor, originator)\n // 引号数组形如 `('x')`,去首尾括号后 unquote;author/organization 可能为列表。\n const inline = (p: string): string | undefined => {\n if (!p) return undefined\n const v = unquote(p.replace(/^\\(|\\)$/g, ''))\n return v === '' ? undefined : v\n }\n const title = inline(parts[0])\n if (title) meta.title = title\n const cdate = inline(parts[1])\n if (cdate) meta.creationDate = cdate\n const author = inline(parts[2] ?? '')\n if (author) meta.author = author\n const org = inline(parts[3] ?? '')\n if (org) meta.organization = org\n // preprocessor → application(编辑器导入后端把 preprocessor 视为 APP);\n // originator → designer。\n const pre = inline(parts[4] ?? '')\n if (pre) meta.application = pre\n const origin = inline(parts[5] ?? '')\n if (origin) meta.designer = origin\n }\n\n const descBlock = entityBlock(header, 'FILE_DESCRIPTION')\n if (descBlock) {\n // FILE_DESCRIPTION(description_list, implementation_context):描述只取第一个\n // 顶层参数(描述串列表,`('a','b')` 形态含内层逗号);实现上下文不算。\n // 直接取 `FILE_DESCRIPTION((…),` 里第一层括号内的引号字符串列表。\n const m = /FILE_DESCRIPTION\\s*\\(\\s*\\((.*?)\\)\\s*,\\s*/.exec(descBlock)\n if (m) {\n const joined = m[1]\n .split(',')\n .map((p) => unquote(p.trim()))\n .filter((v) => v !== '')\n if (joined.length > 0) meta.description = joined.join(', ')\n }\n }\n\n return meta\n}\n\n/** 伙伴层 PRODUCT 描述 + 根相关字段解析(简化:只取第一个 PRODUCT)。 */\nexport function parseStepPartMeta(text: string): StepPartMeta {\n const out: StepPartMeta = {}\n // 逐 PRODUCT 取 description(第 2 个参数)。\n const dataRe = /PRODUCT\\s*\\(/g\n let m: RegExpExecArray | null\n while ((m = dataRe.exec(text)) !== null) {\n const close = text.indexOf(')', m.index)\n if (close < 0) break\n const inner = text.slice(m.index, close + 1)\n const descM = /,\\s*'([^']*)'/.exec(inner)\n if (descM) {\n const d = descM[1]\n if (d !== '') out.description = d\n break // 只取第一个\n }\n }\n // 属性笼(UDA:GENERAL_PROPERTY('name', value?) 挂在 PROPERTY_DEFINITION 上)。\n const props: Record<string, string> = {}\n const gpRe = /GENERAL_PROPERTY\\s*\\(\\s*'([^']*)'\\s*,\\s*([^,)]+)/g\n let gm: RegExpExecArray | null\n while ((gm = gpRe.exec(text)) !== null) {\n props[gm[1]] = unquote(gm[2])\n }\n if (Object.keys(props).length > 0) out.metadata = props\n return out\n}"]}
|
package/dist/shape.d.ts
CHANGED
|
@@ -10,11 +10,19 @@
|
|
|
10
10
|
* - 新增 hasBrep / brepOf:引擎侧判定"某 Shape 是否在 BREP 链上"。
|
|
11
11
|
*/
|
|
12
12
|
import type { Shape } from './mesh/types.js';
|
|
13
|
+
import { type ShapeAppearanceMethods } from './api/appearance.js';
|
|
14
|
+
import { type ShapeMetaMethods } from './api/meta.js';
|
|
13
15
|
import { type ShapeSlot } from './runtime-state.js';
|
|
14
16
|
/** Discriminator for the concrete shape kinds. */
|
|
15
17
|
export type ShapeKind = 'solid' | 'shape2d' | 'curve' | 'compound';
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
+
/**
|
|
19
|
+
* A solid mesh shape produced by a constructor.
|
|
20
|
+
*
|
|
21
|
+
* 运行时形态带外观方法(attachAppearanceMethods 在 solid()/curve() 挂载,
|
|
22
|
+
* 设计文档 2026-10-05 v2 §3.2/§4.2):`box1.setColor(...)` 等成员调用走
|
|
23
|
+
* `asm1.solve()` 同款语句形态;方法不序列化,`appearance` 字段随产物传递。
|
|
24
|
+
*/
|
|
25
|
+
export interface SolidShape extends Shape, ShapeAppearanceMethods, ShapeMetaMethods {
|
|
18
26
|
kind: 'solid';
|
|
19
27
|
}
|
|
20
28
|
/** A structural compound grouping a list of child shapes. */
|
|
@@ -29,7 +37,7 @@ export interface CompoundShape {
|
|
|
29
37
|
* `fromBrepCurve()`)。执行链路照走 `solidToShape`(wire → 空 0/0 载荷,不抛),
|
|
30
38
|
* 显示经 `wireframe`。
|
|
31
39
|
*/
|
|
32
|
-
export interface CurveShape extends Shape {
|
|
40
|
+
export interface CurveShape extends Shape, ShapeAppearanceMethods, ShapeMetaMethods {
|
|
33
41
|
kind: 'curve';
|
|
34
42
|
}
|
|
35
43
|
/** A shape that the api layer exports as a finished result. */
|
package/dist/shape.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAiE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAM/G,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAA;AAElE
|
|
1
|
+
{"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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"}
|
package/dist/shape.js
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* 库函数不再手动登记(P2 落地)。
|
|
10
10
|
* - 新增 hasBrep / brepOf:引擎侧判定"某 Shape 是否在 BREP 链上"。
|
|
11
11
|
*/
|
|
12
|
+
import { attachAppearanceMethods } from './api/appearance.js';
|
|
13
|
+
import { attachMetaMethods } from './api/meta.js';
|
|
12
14
|
import { getRuntimeState, registerFunctionBrep, nameOf, getCurrentStmt } from './runtime-state.js';
|
|
13
15
|
import { asStmtId } from './identity.js';
|
|
14
16
|
import { runtimeLineage } from './topology/naming/lineage.js';
|
|
@@ -21,7 +23,7 @@ import { runtimeLineage } from './topology/naming/lineage.js';
|
|
|
21
23
|
export function solid(mesh) {
|
|
22
24
|
const s = { ...mesh, kind: 'solid' };
|
|
23
25
|
getRuntimeState().created.add(s);
|
|
24
|
-
return s;
|
|
26
|
+
return attachMetaMethods(attachAppearanceMethods(s));
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* 1D 曲线 Shape 构造器(wire / helix / edge-loop 等 1D 产物)。
|
|
@@ -35,7 +37,7 @@ export function solid(mesh) {
|
|
|
35
37
|
export function curve(mesh) {
|
|
36
38
|
const s = { ...mesh, kind: 'curve' };
|
|
37
39
|
getRuntimeState().created.add(s);
|
|
38
|
-
return s;
|
|
40
|
+
return attachMetaMethods(attachAppearanceMethods(s));
|
|
39
41
|
}
|
|
40
42
|
/**
|
|
41
43
|
* BREP 产物构造器:同时登记 mesh 与 OCCT 句柄(+ 可选面演化)。
|
package/dist/shape.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape.js","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api shape — 类型化构造器 + 身份槽\n *\n *\n * 变更要点:\n * - 身份表(created / slots / shapeToName)改读全局锚点 runtime-state,\n * 使\"两份 faijs 代码\"共享同一份状态(解决 Shape 身份孤岛)。\n * - 新增 fromBrep(mesh, holder):BREP 产物一次登记句柄与面演化,\n * 库函数不再手动登记(P2 落地)。\n * - 新增 hasBrep / brepOf:引擎侧判定\"某 Shape 是否在 BREP 链上\"。\n */\n\nimport type { Shape } from './mesh/types'\nimport { getRuntimeState, registerFunctionBrep, nameOf, getCurrentStmt, type ShapeSlot } from './runtime-state'\nimport { asStmtId } from './identity'\nimport { runtimeLineage } from './topology/naming/lineage'\n\n// ── Shape 构造器 ──\n\n/** Discriminator for the concrete shape kinds. */\nexport type ShapeKind = 'solid' | 'shape2d' | 'curve' | 'compound'\n\n/** A solid mesh shape produced by a constructor. */\nexport interface SolidShape extends Shape {\n kind: 'solid'\n}\n\n/** A structural compound grouping a list of child shapes. */\nexport interface CompoundShape {\n kind: 'compound'\n children: Shape[]\n}\n\n/**\n * 1D 曲线 Shape(wire / helix / edge-loop 等无三角载荷的 1D 几何)。\n *\n * `kind: 'curve'` 表达「无三角载荷」,与 `'solid'` 对称(见 `curve()` /\n * `fromBrepCurve()`)。执行链路照走 `solidToShape`(wire → 空 0/0 载荷,不抛),\n * 显示经 `wireframe`。\n */\nexport interface CurveShape extends Shape {\n kind: 'curve'\n}\n\n/** A shape that the api layer exports as a finished result. */\nexport type StdShape = SolidShape | CompoundShape | CurveShape\n\n/**\n * 实体 Shape 构造器:mesh 产物必须经此创建。\n *\n * @param mesh - the mesh shape to wrap as a solid.\n * @returns the created solid shape.\n */\nexport function solid(mesh: Shape): SolidShape {\n const s: SolidShape = { ...mesh, kind: 'solid' }\n getRuntimeState().created.add(s)\n return s\n}\n\n/**\n * 1D 曲线 Shape 构造器(wire / helix / edge-loop 等 1D 产物)。\n *\n * 与 `solid` 对称:登记到 identity 表(供 `isShape` 识别),`kind` 设为 `'curve'`\n * 以表达「无三角载荷的 1D 几何」(执行链路照走 `solidToShape`,显示经 `wireframe`)。\n *\n * @param mesh - the mesh payload (positions/indices) to wrap as a curve.\n * @returns the created curve shape.\n */\nexport function curve(mesh: Shape): CurveShape {\n const s: CurveShape = { ...mesh, kind: 'curve' }\n getRuntimeState().created.add(s)\n return s\n}\n\n/**\n * BREP 产物构造器:同时登记 mesh 与 OCCT 句柄(+ 可选面演化)。\n *\n * 库函数用它替代 `solid(mesh)` + 手动登记句柄两步行:\n * ```ts\n * return fromBrep(solidToShape(kernel, resultSolid), {\n * solid: resultSolid,\n * faceEvolution: identityEvolution(kernel, resultSolid),\n * })\n * ```\n *\n * @param mesh - the mesh shape to register.\n * @param holder - the BREP holder providing the OCCT handle and optional face evolution.\n * @returns the created solid shape with the BREP handle attached.\n */\nexport function fromBrep(mesh: Shape, holder: BrepHolder): SolidShape {\n const s = solid(mesh)\n attachBrep(s, holder)\n return s\n}\n\n/**\n * 1D 曲线产物的 BREP 登记构造器:与 `fromBrep` 对称,但 `kind` 取 `'curve'`\n * (维持既有「有无三角载荷」语义——1D 几何无三角载荷,不得报 `'solid'`)。\n * 登记逻辑与 `fromBrep` 共用 `attachBrep`,保证两种形态走同一份身份/血缘/释放语义。\n *\n * @param mesh - the mesh payload (positions/indices) to wrap as a curve.\n * @param holder - the BREP holder providing the OCCT handle and optional face evolution.\n * @returns the created curve shape with the BREP handle attached.\n */\nexport function fromBrepCurve(mesh: Shape, holder: BrepHolder): CurveShape {\n const s = curve(mesh)\n attachBrep(s, holder)\n return s\n}\n\n/**\n * 网格实体产物的构造器:与 `fromBrep` 对称,登记网格实体句柄(近似链)而非\n * BREP 句柄(精度链)。\n *\n * ```ts\n * return fromMeshSolid(displayMesh, { meshSolid: result.solid })\n * ```\n *\n * 与 `fromBrep` 的三点差别(方案 §3.2):\n * 1. 写 `slot.meshSolid`,**不写** `slot.solid`——网格零件永不进 BREP 链;\n * 2. 不登记函数 BREP 域(`registerFunctionBrep`)——句柄所有权在\n * `MeshSolidRegistry`,按 BREP 内核释放是错的(可能是另一个内核);\n * 3. 不旁挂 roleTable(近似拓扑不给语义 role——role 是 BREP 真拓扑的专有能力)。\n *\n * @param mesh - the mesh shape to wrap as a solid (display mesh).\n * @param holder - the mesh-solid holder providing the handle identity.\n * @returns the created solid shape carrying the mesh-solid slot.\n */\nexport function fromMeshSolid(mesh: Shape, holder: MeshSolidHolder): SolidShape {\n const s = solid(mesh)\n attachMeshSolid(s, holder.meshSolid)\n return s\n}\n\n/** 网格实体句柄容器(与 `BrepHolder` 对称;类型为 unknown 以保持零依赖)。 */\nexport interface MeshSolidHolder {\n /** 网格实体句柄的**身份**(句柄本体在 `MeshSolidRegistry`)。 */\n meshSolid: unknown\n}\n\n/**\n * 网格链**面**产物的构造器(方案 2026-10-01 §4 Phase 3)。与 `fromBrep` 的\n * 面产物对称:BREP 侧 `sketchOnFace` 返回 `fromBrep(solidToShape(kernel, face),\n * { solid: face })`,这里返回 `fromMeshFace(meshShape(face), { meshFace: face })`。\n *\n * `kind` 沿用 `'solid'`(不是 `'shape2d'`):与 BREP 侧的面 Shape 保持同一形态,\n * 好让 `extrude` 的 `isCurveShape` 预检在两条链上行为一致——面不是 1D 曲线,\n * 不该被面消费 op 当成曲线拒掉。\n *\n * @param mesh - the face's display mesh (its own tessellation).\n * @param holder - the mesh-face holder providing the handle identity.\n * @returns the created shape carrying the mesh-face slot.\n */\nexport function fromMeshFace(mesh: Shape, holder: MeshFaceHolder): SolidShape {\n const s = solid(mesh)\n attachMeshFace(s, holder.meshFace)\n return s\n}\n\n/** 网格链面句柄容器(与 `MeshSolidHolder` 对称;类型为 unknown 以保持零依赖)。 */\nexport interface MeshFaceHolder {\n /** 网格链面句柄的**身份**。 */\n meshFace: unknown\n}\n\n/**\n * 把网格实体句柄登记到已构造的 Shape。\n *\n * 互斥红线:该 Shape 已有 BREP 句柄或网格链面句柄时**直接抛错**——一个 Shape\n * 同时声称两种链身份是设计缺陷,不能静默覆盖任何一侧。\n *\n * @param s - the already-constructed shape.\n * @param meshSolid - the mesh solid handle.\n * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.\n */\nexport function attachMeshSolid(s: Shape, meshSolid: unknown): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n if (slot.solid !== undefined) {\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a BREP handle — a shape is either on the precision chain or the mesh chain, never both',\n )\n }\n if (slot.meshFace !== undefined) {\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a mesh-chain face handle — a shape is either a mesh solid or a mesh-chain face, never both',\n )\n }\n slot.meshSolid = meshSolid\n state.slots.set(s, slot)\n}\n\n/**\n * 把网格链**面**句柄登记到已构造的 Shape。\n *\n * 与 `attachMeshSolid` 同一条互斥红线:已有任意另一种链身份即抛错。\n *\n * @param s - the already-constructed shape.\n * @param meshFace - the mesh-chain face handle.\n * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.\n */\nexport function attachMeshFace(s: Shape, meshFace: unknown): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n if (slot.solid !== undefined || slot.meshSolid !== undefined) {\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a BREP or mesh-solid handle — a mesh-chain face is its own identity',\n )\n }\n slot.meshFace = meshFace\n state.slots.set(s, slot)\n}\n\n/**\n * 该 Shape 是否携带网格链面(`sketchOnFace` 在近似拓扑面上的产物)。\n *\n * @param shape - the shape to test.\n * @returns true if the shape carries a mesh-chain face handle.\n */\nexport function hasMeshFace(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.meshFace !== undefined\n}\n\n/**\n * 读取该 Shape 的网格链面句柄(无则 undefined)。\n *\n * @param shape - the shape whose mesh-chain face handle to read.\n * @returns the mesh-chain face handle, or undefined if none.\n */\nexport function meshFaceOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.meshFace\n}\n\n/**\n * 该 Shape 是否携带网格实体(网格零件)。引擎分派与 UI 查询用。\n *\n * 与 `hasBrep` 互斥:正常路径下二者不可能同时为真(`attachMeshSolid` 已经把\n * 互斥钉在写入侧,`assertShapeSlotExclusive` 在分派前再兜一层)。\n *\n * @param shape - the shape to test.\n * @returns true if the shape carries a mesh solid handle.\n */\nexport function hasMeshSolid(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.meshSolid !== undefined\n}\n\n/**\n * 读取该 Shape 的网格实体句柄(无则 undefined)。\n *\n * @param shape - the shape whose mesh solid handle to read.\n * @returns the mesh solid handle, or undefined if none.\n */\nexport function meshSolidOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.meshSolid\n}\n\n/**\n * 把 BREP 句柄登记到已构造的 Shape(由 `solid` / `curve` 产出)。\n *\n * 集中 brep 登记的四步(identity 槽登记已由构造器完成;此处只补:① 身份槽挂载\n * 句柄 / ② 血缘图语句键旁挂 roleTable / ③ 函数 BREP 域登记)。供 `fromBrep` /\n * `fromBrepCurve` 共用——禁止绕开本函数手写登记(否则等于复制一整套身份、血缘与\n * 释放语义)。\n *\n * @param s - the already-constructed shape (solid or curve).\n * @param holder - the BREP holder to attach.\n */\nfunction attachBrep(s: Shape, holder: BrepHolder): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n if (slot.meshSolid !== undefined || slot.meshFace !== undefined) {\n // 互斥红线的另一侧:网格链产物不得再被登记成 BREP 实体(一个 Shape 只能\n // 在精度链或网格链之一上)。\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a mesh-chain handle — a shape is either on the precision chain or the mesh chain, never both',\n )\n }\n slot.solid = holder.solid\n if (holder.faceEvolution) slot.faceEvolution = holder.faceEvolution\n // 1.10 前置③:roleTable **不再写 slot**(字段已删)——权威落点是下方血缘图\n // 旁挂(语句键 + part 键),解析缓存 miss 由回走重算恢复。\n state.slots.set(s, slot)\n // 1.10 前置③:roleTable 权威旁挂(**语句键**)在血缘图。part 键的记录在\n // define-op.wrapped(impl 返回后 anchor.outputs 名字已定)——此处 shape 还未\n // 被 executor 命名,nameOf(s) 为 undefined,不能在这里记 part 键。\n const stmt = getCurrentStmt()\n if (stmt && (holder.roleTable || holder.solid !== undefined)) {\n runtimeLineage.recordOutput(\n asStmtId(stmt.id),\n holder.roleTable as ReadonlyMap<string, ReadonlyMap<string, readonly number[]>> | undefined,\n holder.solid,\n )\n }\n // 函数 BREP 域(§5.6):函数体内 op 产生的新句柄登记到当前域,函数返回后统一释放\n registerFunctionBrep(holder.solid)\n}\n\n/** BREP 句柄 + 面演化 + 拓扑命名 RoleTable(对应 OCCT 的 ShapeHandle)。类型为 unknown 以保持零依赖。 */\nexport interface BrepHolder {\n solid: unknown\n faceEvolution?: Map<number, number[]>\n /**\n * 1.10 前置③:产形 op 交付 role 表的唯一入口。fromBrep 把它**旁挂到血缘图**\n * (语句键 + part 键);slot 侧的缓存存储已删(ShapeSlot 不再有该字段)。\n */\n roleTable?: unknown\n}\n\n/**\n * compound Shape 构造器:结构(层级)而非新几何。\n *\n * @param children - the child shapes to group.\n * @returns the created compound shape.\n */\nexport function compound(children: Shape[]): CompoundShape {\n const c: CompoundShape = { kind: 'compound', children }\n getRuntimeState().created.add(c)\n return c\n}\n\n/**\n * 是否为构造器产物(终端判定与 compound 检测的依据)。\n *\n * @param v - the value to test.\n * @returns true if the value was created by a shape constructor.\n */\nexport function isShape(v: unknown): v is Shape {\n return !!v && typeof v === 'object' && getRuntimeState().created.has(v)\n}\n\n/**\n * Returns true if the value is a strict compound shape created by a constructor.\n *\n * @param v - the value to test.\n * @returns true if the value is a strict compound shape.\n */\nexport function isCompound(v: unknown): v is CompoundShape {\n return isShape(v) && (v as { kind?: string }).kind === 'compound'\n}\n\n/**\n * 结构判定:是否为 compound 形态(keep-syntax §5.3 D5,对任意库函数零要求)。\n * 引擎内部的终端/消费判定用结构判定;SDK 公开的 isShape/isCompound 保持 WeakSet 严格。\n *\n * @param v - the value to test.\n * @returns true if the value has compound shape structure.\n */\nexport function isCompoundLike(v: unknown): v is CompoundShape {\n return !!v && typeof v === 'object'\n && (v as { kind?: string }).kind === 'compound'\n && Array.isArray((v as { children?: unknown }).children)\n}\n\n/**\n * 1D 曲线判定(1D 判别位,Phase 3):`kind === 'curve'`。\n *\n * 面消费 op(extrude / revolve / sweep 等)用它做**执行前**输入维度预检——\n * 1D 产物(wire / helix / sketch as:'wire')喂给面 op 时必须是明确的预检失败,\n * 不得落进内核深层才报「操作失败」。与 SDK 的 WeakSet 严格 `isShape` 不同,\n * 本判定是结构判定(与 `isCompoundLike` 同族),对跨库产物零要求。\n *\n * @param v - the value to test.\n * @returns true when the value is a 1D curve shape.\n */\nexport function isCurveShape(v: unknown): v is CurveShape {\n return !!v && typeof v === 'object' && (v as { kind?: string }).kind === 'curve'\n}\n\n// ── 身份槽 ──\n\nexport type { ShapeSlot }\n\n/**\n * 读取 Shape 的身份槽(无则 undefined)。\n *\n * @param shape - the shape whose slot to read.\n * @returns the identity slot, or undefined if none is registered.\n */\nexport function getSlot(shape: object): ShapeSlot | undefined {\n return getRuntimeState().slots.get(shape)\n}\n\n/**\n * 读取或创建 Shape 的身份槽。\n *\n * @param shape - the shape whose slot to read or create.\n * @returns the shape's identity slot.\n */\nexport function ensureSlot(shape: object): ShapeSlot {\n const state = getRuntimeState()\n let slot = state.slots.get(shape)\n if (!slot) {\n slot = {}\n state.slots.set(shape, slot)\n }\n return slot\n}\n\n/**\n * 读输入 Shape 的 roleTable(op 实现读**输入**表的唯一读口,1.10 前置③)。\n *\n * 语义 = 旧 `getSlot(shape)?.roleTable`:权威落点在血缘图的 part 键旁挂\n * (上一条语句 fromBrep 时记录),slot 缓存字段已删除。未记录 → undefined\n * (mesh 产物 / 无命名)。\n *\n * @param shape - the input shape whose role table to read.\n * @returns the role table (unknown — callers assert their table type), or undefined.\n */\nexport function inputRoleTable(shape: object): unknown | undefined {\n const name = nameOf(shape)\n return name ? runtimeLineage.tableOfPart(name) : undefined\n}\n\n/**\n * 该 Shape 是否在 BREP 链上(有 OCCT 句柄)。引擎分派与 UI 查询用。\n *\n * @param shape - the shape to test.\n * @returns true if the shape has an attached OCCT handle.\n */\nexport function hasBrep(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.solid !== undefined\n}\n\n/**\n * 读取该 Shape 的 OCCT 句柄(无则 undefined)。库函数用前必须判空。\n *\n * @param shape - the shape whose handle to read.\n * @returns the OCCT handle, or undefined if none.\n */\nexport function brepOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.solid\n}\n\n/**\n * nameOf 批量版:Shape[] → 成员名(装配 memberNames,P6 替代读 IR)。\n *\n * @param shapes - the shapes to name.\n * @returns the member names, one per shape (empty string when unnamed).\n */\nexport function nameOfShapes(shapes: Shape[]): string[] {\n return shapes.map((s) => String(nameOf(s) ?? ''))\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shape.js","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api shape — 类型化构造器 + 身份槽\n *\n *\n * 变更要点:\n * - 身份表(created / slots / shapeToName)改读全局锚点 runtime-state,\n * 使\"两份 faijs 代码\"共享同一份状态(解决 Shape 身份孤岛)。\n * - 新增 fromBrep(mesh, holder):BREP 产物一次登记句柄与面演化,\n * 库函数不再手动登记(P2 落地)。\n * - 新增 hasBrep / brepOf:引擎侧判定\"某 Shape 是否在 BREP 链上\"。\n */\n\nimport type { Shape } from './mesh/types'\nimport { attachAppearanceMethods, type ShapeAppearanceMethods } from './api/appearance'\nimport { attachMetaMethods, type ShapeMetaMethods } from './api/meta'\nimport { getRuntimeState, registerFunctionBrep, nameOf, getCurrentStmt, type ShapeSlot } from './runtime-state'\nimport { asStmtId } from './identity'\nimport { runtimeLineage } from './topology/naming/lineage'\n\n// ── Shape 构造器 ──\n\n/** Discriminator for the concrete shape kinds. */\nexport type ShapeKind = 'solid' | 'shape2d' | 'curve' | 'compound'\n\n/**\n * A solid mesh shape produced by a constructor.\n *\n * 运行时形态带外观方法(attachAppearanceMethods 在 solid()/curve() 挂载,\n * 设计文档 2026-10-05 v2 §3.2/§4.2):`box1.setColor(...)` 等成员调用走\n * `asm1.solve()` 同款语句形态;方法不序列化,`appearance` 字段随产物传递。\n */\nexport interface SolidShape extends Shape, ShapeAppearanceMethods, ShapeMetaMethods {\n kind: 'solid'\n}\n\n/** A structural compound grouping a list of child shapes. */\nexport interface CompoundShape {\n kind: 'compound'\n children: Shape[]\n}\n\n/**\n * 1D 曲线 Shape(wire / helix / edge-loop 等无三角载荷的 1D 几何)。\n *\n * `kind: 'curve'` 表达「无三角载荷」,与 `'solid'` 对称(见 `curve()` /\n * `fromBrepCurve()`)。执行链路照走 `solidToShape`(wire → 空 0/0 载荷,不抛),\n * 显示经 `wireframe`。\n */\nexport interface CurveShape extends Shape, ShapeAppearanceMethods, ShapeMetaMethods {\n kind: 'curve'\n}\n\n/** A shape that the api layer exports as a finished result. */\nexport type StdShape = SolidShape | CompoundShape | CurveShape\n\n/**\n * 实体 Shape 构造器:mesh 产物必须经此创建。\n *\n * @param mesh - the mesh shape to wrap as a solid.\n * @returns the created solid shape.\n */\nexport function solid(mesh: Shape): SolidShape {\n const s = { ...mesh, kind: 'solid' } as SolidShape\n getRuntimeState().created.add(s)\n return attachMetaMethods(attachAppearanceMethods(s)) as SolidShape\n}\n\n/**\n * 1D 曲线 Shape 构造器(wire / helix / edge-loop 等 1D 产物)。\n *\n * 与 `solid` 对称:登记到 identity 表(供 `isShape` 识别),`kind` 设为 `'curve'`\n * 以表达「无三角载荷的 1D 几何」(执行链路照走 `solidToShape`,显示经 `wireframe`)。\n *\n * @param mesh - the mesh payload (positions/indices) to wrap as a curve.\n * @returns the created curve shape.\n */\nexport function curve(mesh: Shape): CurveShape {\n const s = { ...mesh, kind: 'curve' } as CurveShape\n getRuntimeState().created.add(s)\n return attachMetaMethods(attachAppearanceMethods(s)) as CurveShape\n}\n\n/**\n * BREP 产物构造器:同时登记 mesh 与 OCCT 句柄(+ 可选面演化)。\n *\n * 库函数用它替代 `solid(mesh)` + 手动登记句柄两步行:\n * ```ts\n * return fromBrep(solidToShape(kernel, resultSolid), {\n * solid: resultSolid,\n * faceEvolution: identityEvolution(kernel, resultSolid),\n * })\n * ```\n *\n * @param mesh - the mesh shape to register.\n * @param holder - the BREP holder providing the OCCT handle and optional face evolution.\n * @returns the created solid shape with the BREP handle attached.\n */\nexport function fromBrep(mesh: Shape, holder: BrepHolder): SolidShape {\n const s = solid(mesh)\n attachBrep(s, holder)\n return s\n}\n\n/**\n * 1D 曲线产物的 BREP 登记构造器:与 `fromBrep` 对称,但 `kind` 取 `'curve'`\n * (维持既有「有无三角载荷」语义——1D 几何无三角载荷,不得报 `'solid'`)。\n * 登记逻辑与 `fromBrep` 共用 `attachBrep`,保证两种形态走同一份身份/血缘/释放语义。\n *\n * @param mesh - the mesh payload (positions/indices) to wrap as a curve.\n * @param holder - the BREP holder providing the OCCT handle and optional face evolution.\n * @returns the created curve shape with the BREP handle attached.\n */\nexport function fromBrepCurve(mesh: Shape, holder: BrepHolder): CurveShape {\n const s = curve(mesh)\n attachBrep(s, holder)\n return s\n}\n\n/**\n * 网格实体产物的构造器:与 `fromBrep` 对称,登记网格实体句柄(近似链)而非\n * BREP 句柄(精度链)。\n *\n * ```ts\n * return fromMeshSolid(displayMesh, { meshSolid: result.solid })\n * ```\n *\n * 与 `fromBrep` 的三点差别(方案 §3.2):\n * 1. 写 `slot.meshSolid`,**不写** `slot.solid`——网格零件永不进 BREP 链;\n * 2. 不登记函数 BREP 域(`registerFunctionBrep`)——句柄所有权在\n * `MeshSolidRegistry`,按 BREP 内核释放是错的(可能是另一个内核);\n * 3. 不旁挂 roleTable(近似拓扑不给语义 role——role 是 BREP 真拓扑的专有能力)。\n *\n * @param mesh - the mesh shape to wrap as a solid (display mesh).\n * @param holder - the mesh-solid holder providing the handle identity.\n * @returns the created solid shape carrying the mesh-solid slot.\n */\nexport function fromMeshSolid(mesh: Shape, holder: MeshSolidHolder): SolidShape {\n const s = solid(mesh)\n attachMeshSolid(s, holder.meshSolid)\n return s\n}\n\n/** 网格实体句柄容器(与 `BrepHolder` 对称;类型为 unknown 以保持零依赖)。 */\nexport interface MeshSolidHolder {\n /** 网格实体句柄的**身份**(句柄本体在 `MeshSolidRegistry`)。 */\n meshSolid: unknown\n}\n\n/**\n * 网格链**面**产物的构造器(方案 2026-10-01 §4 Phase 3)。与 `fromBrep` 的\n * 面产物对称:BREP 侧 `sketchOnFace` 返回 `fromBrep(solidToShape(kernel, face),\n * { solid: face })`,这里返回 `fromMeshFace(meshShape(face), { meshFace: face })`。\n *\n * `kind` 沿用 `'solid'`(不是 `'shape2d'`):与 BREP 侧的面 Shape 保持同一形态,\n * 好让 `extrude` 的 `isCurveShape` 预检在两条链上行为一致——面不是 1D 曲线,\n * 不该被面消费 op 当成曲线拒掉。\n *\n * @param mesh - the face's display mesh (its own tessellation).\n * @param holder - the mesh-face holder providing the handle identity.\n * @returns the created shape carrying the mesh-face slot.\n */\nexport function fromMeshFace(mesh: Shape, holder: MeshFaceHolder): SolidShape {\n const s = solid(mesh)\n attachMeshFace(s, holder.meshFace)\n return s\n}\n\n/** 网格链面句柄容器(与 `MeshSolidHolder` 对称;类型为 unknown 以保持零依赖)。 */\nexport interface MeshFaceHolder {\n /** 网格链面句柄的**身份**。 */\n meshFace: unknown\n}\n\n/**\n * 把网格实体句柄登记到已构造的 Shape。\n *\n * 互斥红线:该 Shape 已有 BREP 句柄或网格链面句柄时**直接抛错**——一个 Shape\n * 同时声称两种链身份是设计缺陷,不能静默覆盖任何一侧。\n *\n * @param s - the already-constructed shape.\n * @param meshSolid - the mesh solid handle.\n * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.\n */\nexport function attachMeshSolid(s: Shape, meshSolid: unknown): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n if (slot.solid !== undefined) {\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a BREP handle — a shape is either on the precision chain or the mesh chain, never both',\n )\n }\n if (slot.meshFace !== undefined) {\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a mesh-chain face handle — a shape is either a mesh solid or a mesh-chain face, never both',\n )\n }\n slot.meshSolid = meshSolid\n state.slots.set(s, slot)\n}\n\n/**\n * 把网格链**面**句柄登记到已构造的 Shape。\n *\n * 与 `attachMeshSolid` 同一条互斥红线:已有任意另一种链身份即抛错。\n *\n * @param s - the already-constructed shape.\n * @param meshFace - the mesh-chain face handle.\n * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.\n */\nexport function attachMeshFace(s: Shape, meshFace: unknown): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n if (slot.solid !== undefined || slot.meshSolid !== undefined) {\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a BREP or mesh-solid handle — a mesh-chain face is its own identity',\n )\n }\n slot.meshFace = meshFace\n state.slots.set(s, slot)\n}\n\n/**\n * 该 Shape 是否携带网格链面(`sketchOnFace` 在近似拓扑面上的产物)。\n *\n * @param shape - the shape to test.\n * @returns true if the shape carries a mesh-chain face handle.\n */\nexport function hasMeshFace(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.meshFace !== undefined\n}\n\n/**\n * 读取该 Shape 的网格链面句柄(无则 undefined)。\n *\n * @param shape - the shape whose mesh-chain face handle to read.\n * @returns the mesh-chain face handle, or undefined if none.\n */\nexport function meshFaceOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.meshFace\n}\n\n/**\n * 该 Shape 是否携带网格实体(网格零件)。引擎分派与 UI 查询用。\n *\n * 与 `hasBrep` 互斥:正常路径下二者不可能同时为真(`attachMeshSolid` 已经把\n * 互斥钉在写入侧,`assertShapeSlotExclusive` 在分派前再兜一层)。\n *\n * @param shape - the shape to test.\n * @returns true if the shape carries a mesh solid handle.\n */\nexport function hasMeshSolid(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.meshSolid !== undefined\n}\n\n/**\n * 读取该 Shape 的网格实体句柄(无则 undefined)。\n *\n * @param shape - the shape whose mesh solid handle to read.\n * @returns the mesh solid handle, or undefined if none.\n */\nexport function meshSolidOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.meshSolid\n}\n\n/**\n * 把 BREP 句柄登记到已构造的 Shape(由 `solid` / `curve` 产出)。\n *\n * 集中 brep 登记的四步(identity 槽登记已由构造器完成;此处只补:① 身份槽挂载\n * 句柄 / ② 血缘图语句键旁挂 roleTable / ③ 函数 BREP 域登记)。供 `fromBrep` /\n * `fromBrepCurve` 共用——禁止绕开本函数手写登记(否则等于复制一整套身份、血缘与\n * 释放语义)。\n *\n * @param s - the already-constructed shape (solid or curve).\n * @param holder - the BREP holder to attach.\n */\nfunction attachBrep(s: Shape, holder: BrepHolder): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n if (slot.meshSolid !== undefined || slot.meshFace !== undefined) {\n // 互斥红线的另一侧:网格链产物不得再被登记成 BREP 实体(一个 Shape 只能\n // 在精度链或网格链之一上)。\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a mesh-chain handle — a shape is either on the precision chain or the mesh chain, never both',\n )\n }\n slot.solid = holder.solid\n if (holder.faceEvolution) slot.faceEvolution = holder.faceEvolution\n // 1.10 前置③:roleTable **不再写 slot**(字段已删)——权威落点是下方血缘图\n // 旁挂(语句键 + part 键),解析缓存 miss 由回走重算恢复。\n state.slots.set(s, slot)\n // 1.10 前置③:roleTable 权威旁挂(**语句键**)在血缘图。part 键的记录在\n // define-op.wrapped(impl 返回后 anchor.outputs 名字已定)——此处 shape 还未\n // 被 executor 命名,nameOf(s) 为 undefined,不能在这里记 part 键。\n const stmt = getCurrentStmt()\n if (stmt && (holder.roleTable || holder.solid !== undefined)) {\n runtimeLineage.recordOutput(\n asStmtId(stmt.id),\n holder.roleTable as ReadonlyMap<string, ReadonlyMap<string, readonly number[]>> | undefined,\n holder.solid,\n )\n }\n // 函数 BREP 域(§5.6):函数体内 op 产生的新句柄登记到当前域,函数返回后统一释放\n registerFunctionBrep(holder.solid)\n}\n\n/** BREP 句柄 + 面演化 + 拓扑命名 RoleTable(对应 OCCT 的 ShapeHandle)。类型为 unknown 以保持零依赖。 */\nexport interface BrepHolder {\n solid: unknown\n faceEvolution?: Map<number, number[]>\n /**\n * 1.10 前置③:产形 op 交付 role 表的唯一入口。fromBrep 把它**旁挂到血缘图**\n * (语句键 + part 键);slot 侧的缓存存储已删(ShapeSlot 不再有该字段)。\n */\n roleTable?: unknown\n}\n\n/**\n * compound Shape 构造器:结构(层级)而非新几何。\n *\n * @param children - the child shapes to group.\n * @returns the created compound shape.\n */\nexport function compound(children: Shape[]): CompoundShape {\n const c: CompoundShape = { kind: 'compound', children }\n getRuntimeState().created.add(c)\n return c\n}\n\n/**\n * 是否为构造器产物(终端判定与 compound 检测的依据)。\n *\n * @param v - the value to test.\n * @returns true if the value was created by a shape constructor.\n */\nexport function isShape(v: unknown): v is Shape {\n return !!v && typeof v === 'object' && getRuntimeState().created.has(v)\n}\n\n/**\n * Returns true if the value is a strict compound shape created by a constructor.\n *\n * @param v - the value to test.\n * @returns true if the value is a strict compound shape.\n */\nexport function isCompound(v: unknown): v is CompoundShape {\n return isShape(v) && (v as { kind?: string }).kind === 'compound'\n}\n\n/**\n * 结构判定:是否为 compound 形态(keep-syntax §5.3 D5,对任意库函数零要求)。\n * 引擎内部的终端/消费判定用结构判定;SDK 公开的 isShape/isCompound 保持 WeakSet 严格。\n *\n * @param v - the value to test.\n * @returns true if the value has compound shape structure.\n */\nexport function isCompoundLike(v: unknown): v is CompoundShape {\n return !!v && typeof v === 'object'\n && (v as { kind?: string }).kind === 'compound'\n && Array.isArray((v as { children?: unknown }).children)\n}\n\n/**\n * 1D 曲线判定(1D 判别位,Phase 3):`kind === 'curve'`。\n *\n * 面消费 op(extrude / revolve / sweep 等)用它做**执行前**输入维度预检——\n * 1D 产物(wire / helix / sketch as:'wire')喂给面 op 时必须是明确的预检失败,\n * 不得落进内核深层才报「操作失败」。与 SDK 的 WeakSet 严格 `isShape` 不同,\n * 本判定是结构判定(与 `isCompoundLike` 同族),对跨库产物零要求。\n *\n * @param v - the value to test.\n * @returns true when the value is a 1D curve shape.\n */\nexport function isCurveShape(v: unknown): v is CurveShape {\n return !!v && typeof v === 'object' && (v as { kind?: string }).kind === 'curve'\n}\n\n// ── 身份槽 ──\n\nexport type { ShapeSlot }\n\n/**\n * 读取 Shape 的身份槽(无则 undefined)。\n *\n * @param shape - the shape whose slot to read.\n * @returns the identity slot, or undefined if none is registered.\n */\nexport function getSlot(shape: object): ShapeSlot | undefined {\n return getRuntimeState().slots.get(shape)\n}\n\n/**\n * 读取或创建 Shape 的身份槽。\n *\n * @param shape - the shape whose slot to read or create.\n * @returns the shape's identity slot.\n */\nexport function ensureSlot(shape: object): ShapeSlot {\n const state = getRuntimeState()\n let slot = state.slots.get(shape)\n if (!slot) {\n slot = {}\n state.slots.set(shape, slot)\n }\n return slot\n}\n\n/**\n * 读输入 Shape 的 roleTable(op 实现读**输入**表的唯一读口,1.10 前置③)。\n *\n * 语义 = 旧 `getSlot(shape)?.roleTable`:权威落点在血缘图的 part 键旁挂\n * (上一条语句 fromBrep 时记录),slot 缓存字段已删除。未记录 → undefined\n * (mesh 产物 / 无命名)。\n *\n * @param shape - the input shape whose role table to read.\n * @returns the role table (unknown — callers assert their table type), or undefined.\n */\nexport function inputRoleTable(shape: object): unknown | undefined {\n const name = nameOf(shape)\n return name ? runtimeLineage.tableOfPart(name) : undefined\n}\n\n/**\n * 该 Shape 是否在 BREP 链上(有 OCCT 句柄)。引擎分派与 UI 查询用。\n *\n * @param shape - the shape to test.\n * @returns true if the shape has an attached OCCT handle.\n */\nexport function hasBrep(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.solid !== undefined\n}\n\n/**\n * 读取该 Shape 的 OCCT 句柄(无则 undefined)。库函数用前必须判空。\n *\n * @param shape - the shape whose handle to read.\n * @returns the OCCT handle, or undefined if none.\n */\nexport function brepOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.solid\n}\n\n/**\n * nameOf 批量版:Shape[] → 成员名(装配 memberNames,P6 替代读 IR)。\n *\n * @param shapes - the shapes to name.\n * @returns the member names, one per shape (empty string when unnamed).\n */\nexport function nameOfShapes(shapes: Shape[]): string[] {\n return shapes.map((s) => String(nameOf(s) ?? ''))\n}\n"]}
|