@faicad/faijs 0.18.0 → 0.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/extrude.d.ts.map +1 -1
- package/dist/api/extrude.js +52 -13
- package/dist/api/extrude.js.map +1 -1
- package/dist/api/profile.d.ts +10 -6
- package/dist/api/profile.d.ts.map +1 -1
- package/dist/api/profile.js +106 -24
- package/dist/api/profile.js.map +1 -1
- package/dist/api/transform.d.ts +12 -8
- package/dist/api/transform.d.ts.map +1 -1
- package/dist/api/transform.js +62 -32
- package/dist/api/transform.js.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.d.ts +2 -1
- package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.js +48 -12
- package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
- package/dist/occt-kernel/occtKernel.d.ts +3 -1
- package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
- package/dist/occt-kernel/occtKernel.js +73 -29
- package/dist/occt-kernel/occtKernel.js.map +1 -1
- package/package.json +2 -3
package/dist/api/profile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/api/profile.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * stdlib profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。\n *\n * 用途:faijs 此前没有「从 2D 轮廓构造 planar face」的能力,导致草图轮廓无法喂给\n * extrude/revolve。本 op 接收 2D 轮廓(线段 + 圆弧),在 z=0 平面用 OCCT 构面:\n * makeLineEdge/makeArcEdge → makeWire → makeFace(+ addHolesInFace)。\n *\n * 设计:\n * - 输入:{ contours: ProfileLoop[] },每个 loop = 有序 segments(line / arc,z=0)。\n * - 外环 = 面积(shoelace)绝对值最大的 loop;其余 loop 作为孔。\n * - 圆弧:用起点/中点/终点三点的 makeArcEdge;整圆(sweep≈2π)拆成两段弧。\n * - 输出:Shape(mesh 三角化 + 句柄登记)。brep-only(下游 extrude/revolve 亦 brep-only)。\n *\n * 坐标系:输入 2D 点即 (x, y, 0),法向 +Z;草图在 Body 局部系内的定位由调用方(fcstd 端口)\n * 在轮廓坐标里预先变换,或由下游特征的 Placement 承担。\n */\n\nimport type { Shape } from '../mesh/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { solidToShape } from '../brep/brep-ops'\nimport { fromBrep, fromBrepCurve } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\n\n// ── 参数形状(与 fcstd Contour 结构相同,避免引擎依赖端口层)──\n\n/** 直线段(2D,z=0;端点为绝对坐标)。 */\nexport interface ProfileLineSeg {\n kind: 'line'\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/** 圆弧段(圆心 + 半径 + 起止角,弧度;z=0)。 */\nexport interface ProfileArcSeg {\n kind: 'arc'\n cx: number\n cy: number\n radius: number\n /** 起始角(弧度) */\n startAngle: number\n /** 终止角(弧度) */\n endAngle: number\n ccw: boolean\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/** 一条有序 2D 轮廓段(直线或圆弧)。 */\nexport type ProfileSeg = ProfileLineSeg | ProfileArcSeg\n\n/** 单个轮廓环:有序段序列(首尾相接)。 */\nexport interface ProfileLoop {\n segments: ProfileSeg[]\n}\n\n/** `cad.profile` 参数:轮廓环集合(第一个为外环,其余为孔)。 */\nexport interface ProfileParams {\n contours: ProfileLoop[]\n /**\n * 产物形态:'face'(默认)构面;'wire' 只交出不带面的外环 wire(1D 曲线),\n * 供扫掠族(sweep/loft/…)直接作 spine。'wire' 形态丢弃孔环(扫掠脊柱为单闭合轮廓)。\n */\n as?: 'face' | 'wire'\n}\n\n// ── 参数自校验 ──\n\n/**\n * Validate profile parameters: `contours` must be a non-empty array of loops,\n * each with at least one segment.\n * @param params the raw profile operation parameters.\n */\nexport function assertProfileParams(params: Record<string, unknown>): void {\n const contours = params.contours\n if (!Array.isArray(contours) || contours.length === 0) {\n throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour')\n }\n for (const loop of contours) {\n if (!loop || typeof loop !== 'object' || !Array.isArray((loop as ProfileLoop).segments)) {\n throw new Error('E_PROFILE_BAD_LOOP: each contour must have a segments array')\n }\n if ((loop as ProfileLoop).segments.length === 0) {\n throw new Error('E_PROFILE_EMPTY_LOOP: a contour must have at least one segment')\n }\n }\n}\n\n/**\n * 单环带符号面积(对每段做有向面积积分,而非只用段起点 shoelace)。\n *\n * 直线段:1/2 (x1·y2 − x2·y1)。\n * 圆弧段:1/2 ∫(x dy − y dx) 的解析解 = 1/2 [r²·sweep + cx·r(sin a1 − sin a0) − cy·r(cos a1 − cos a0)]。\n * 整圆(单段弧、起终点重合)由此得到 πr²,不再是 0——否则「整圆 + 方孔」会把孔误判成外环。\n */\nfunction loopSignedArea(loop: ProfileLoop): number {\n let a = 0\n for (const seg of loop.segments) {\n if (seg.kind === 'line') {\n a += (seg.x1 * seg.y2 - seg.x2 * seg.y1) / 2\n continue\n }\n let sweep = seg.endAngle - seg.startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n const { cx, cy, radius: r, startAngle: a0 } = seg\n const a1 = a0 + sweep\n a += 0.5 * (r * r * sweep + cx * r * (Math.sin(a1) - Math.sin(a0)) - cy * r * (Math.cos(a1) - Math.cos(a0)))\n }\n return a\n}\n\n/** 圆弧 → 一条或两条 makeArcEdge(整圆拆分)。 */\nfunction arcToHandles(\n kernel: BrepEngineApi,\n seg: ProfileArcSeg,\n): ReturnType<BrepEngineApi['makeArcEdge']>[] {\n const { cx, cy, radius, startAngle, endAngle, ccw = true } = seg\n // GOTCHA(2026-09-25,A3 FCBL_tree_entourage):ccw 必须参与弧的几何方向。\n // makeArcEdge 按「起点-中点-终点」三点定弧,旧实现一律取 CCW 中点\n // ((start+end)/2 归一化到 (0,2π]),ccw:false 的弧被画成 CCW **长弧**(补角)。\n // 实测后果:长弧穿过旋转轴 → revolve 产物退化(bbox NaN)→ BRepMesh 挂死\n // (进程无声死亡);正确 CW 短弧下内核 revolve 仅 ~19ms。\n let sweep: number\n let midAngle: number\n if (ccw) {\n sweep = endAngle - startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n midAngle = startAngle + sweep / 2\n } else {\n // 顺时针:从 startAngle 递减到 endAngle,扫角取反向归一化\n sweep = startAngle - endAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n midAngle = startAngle - sweep / 2\n }\n\n const makeOne = (a0: number, am: number, a1: number): ReturnType<BrepEngineApi['makeArcEdge']> => {\n const start = { x: cx + radius * Math.cos(a0), y: cy + radius * Math.sin(a0), z: 0 }\n const m = { x: cx + radius * Math.cos(am), y: cy + radius * Math.sin(am), z: 0 }\n const end = { x: cx + radius * Math.cos(a1), y: cy + radius * Math.sin(a1), z: 0 }\n return kernel.makeArcEdge(start, m, end)\n }\n\n // 整圆(sweep≈2π):拆成两段半圆,避免 makeArcEdge 起点≈终点退化\n if (sweep >= 2 * Math.PI - 1e-9) {\n const half = 2 * Math.PI / 2\n const dir = ccw ? 1 : -1\n return [\n makeOne(startAngle, startAngle + dir * half / 2, startAngle + dir * half),\n makeOne(startAngle + dir * half, startAngle + dir * (half + half / 2), startAngle + dir * 2 * Math.PI),\n ]\n }\n return [makeOne(startAngle, midAngle, endAngle)]\n}\n\n/** 单环 → wire handle(仅构面,不释放中间句柄,遵循现有惯例)。 */\nfunction loopToWire(kernel: BrepEngineApi, loop: ProfileLoop): ReturnType<BrepEngineApi['makeWire']> {\n const edges: ReturnType<BrepEngineApi['makeLineEdge']>[] = []\n for (const seg of loop.segments) {\n if (seg.kind === 'line') {\n edges.push(kernel.makeLineEdge({ x: seg.x1, y: seg.y1, z: 0 }, { x: seg.x2, y: seg.y2, z: 0 }))\n } else {\n // 极小扫角(退化弧)→ 退化为线段,避免构边失败\n let sweep = seg.endAngle - seg.startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n if (sweep < 1e-9) {\n edges.push(kernel.makeLineEdge({ x: seg.x1, y: seg.y1, z: 0 }, { x: seg.x2, y: seg.y2, z: 0 }))\n } else {\n edges.push(...arcToHandles(kernel, seg))\n }\n }\n }\n return kernel.makeWire(edges as ReturnType<BrepEngineApi['makeLineEdge']>[])\n}\n\n/**\n * BREP 路径:2D 轮廓 → planar face(外环 + 孔),或 'wire' 形态仅交外环 wire。\n *\n * 导出供 `@faicad/faijs-sketch` 等下游库复用——构面实现单点,草图求解结果经此构面。\n *\n * @param params - 轮廓环集合与产物形态。\n * @returns Shape(`as:'wire'` 时为 1D 曲线)。\n */\nexport function buildProfileShape(params: ProfileParams): Shape {\n const kernel = getBrepApi()\n const as = params.as ?? 'face'\n\n const loops = params.contours.map((loop) => ({ loop, area: Math.abs(loopSignedArea(loop)) }))\n // 面积最大者为外环,其余为孔\n let outerIdx = 0\n for (let i = 1; i < loops.length; i++) {\n if (loops[i]!.area > loops[outerIdx]!.area) outerIdx = i\n }\n\n const outerWire = loopToWire(kernel, loops[outerIdx]!.loop)\n\n // 'wire' 形态:只交外环 wire(1D 曲线),不构面 —— 供扫掠族作 spine。\n if (as === 'wire') {\n return fromBrepCurve(solidToShape(kernel, outerWire), { solid: outerWire })\n }\n\n const face = kernel.makeFace(outerWire)\n\n const holeWires: ReturnType<BrepEngineApi['makeWire']>[] = []\n for (let i = 0; i < loops.length; i++) {\n if (i === outerIdx) continue\n holeWires.push(loopToWire(kernel, loops[i]!.loop))\n }\n if (holeWires.length > 0) {\n const faced = kernel.addHolesInFace(face, holeWires)\n kernel.release(face)\n return fromBrep(solidToShape(kernel, faced), { solid: faced })\n }\n\n kernel.release(outerWire)\n return fromBrep(solidToShape(kernel, face), { solid: face })\n}\n\n/**\n * 从 2D 轮廓构造平面(creator,无输入)。仅 BREP 可用。\n * @group 创建\n * @inputs 0\n * @async false\n * @qual ok\n * @name profile\n * @returns Shape 平面几何(mesh 三角化 + BREP 句柄);`as:'wire'` 时返回 1D 曲线(kind:'curve')。\n * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔)。type:ProfileLoop[] required:true\n * @param params.as - 产物形态:'face'(默认)构面;'wire' 只交外环 wire(1D 曲线)。type:'face'|'wire' required:false\n * @example\n * const f = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }] })\n * const w = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }], as: 'wire' })\n */\nexport const profile = defineOp({\n capabilities: ['directEdit'],\n brep(params: Record<string, unknown>) {\n assertProfileParams(params)\n return buildProfileShape(params as unknown as ProfileParams)\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } } as Provenance,\n})"]}
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/api/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAiDjC,cAAc;AAEd;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA+B;IACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAA;IAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAA;IACjF,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAE,IAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxF,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAA;QAChF,CAAC;QACD,IAAK,IAAoB,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAA;QACnF,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,IAAiB;IACvC,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;YAC5C,SAAQ;QACV,CAAC;QACD,IAAI,KAAK,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAA;QACzC,OAAO,KAAK,IAAI,CAAC;YAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;QACvC,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE;YAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;QAChD,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,GAAG,GAAG,CAAA;QACjD,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAA;QACrB,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9G,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED,oCAAoC;AACpC,SAAS,YAAY,CACnB,MAAqB,EACrB,GAAkB;IAElB,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,GAAG,IAAI,EAAE,GAAG,GAAG,CAAA;IAChE,4DAA4D;IAC5D,4CAA4C;IAC5C,8DAA8D;IAC9D,qDAAqD;IACrD,wCAAwC;IACxC,IAAI,KAAa,CAAA;IACjB,IAAI,QAAgB,CAAA;IACpB,IAAI,GAAG,EAAE,CAAC;QACR,KAAK,GAAG,QAAQ,GAAG,UAAU,CAAA;QAC7B,OAAO,KAAK,IAAI,CAAC;YAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;QACvC,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE;YAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;QAChD,QAAQ,GAAG,UAAU,GAAG,KAAK,GAAG,CAAC,CAAA;IACnC,CAAC;SAAM,CAAC;QACN,yCAAyC;QACzC,KAAK,GAAG,UAAU,GAAG,QAAQ,CAAA;QAC7B,OAAO,KAAK,IAAI,CAAC;YAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;QACvC,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE;YAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;QAChD,QAAQ,GAAG,UAAU,GAAG,KAAK,GAAG,CAAC,CAAA;IACnC,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU,EAA4C,EAAE;QAC/F,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;QACpF,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;QAChF,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;QAClF,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,CAAA;IAC1C,CAAC,CAAA;IAED,6CAA6C;IAC7C,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;QAC5B,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACxB,OAAO;YACL,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC;YACzE,OAAO,CAAC,UAAU,GAAG,GAAG,GAAG,IAAI,EAAE,UAAU,GAAG,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;SACvG,CAAA;IACH,CAAC;IACD,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAA;AAClD,CAAC;AAED,4CAA4C;AAC5C,SAAS,UAAU,CAAC,MAAqB,EAAE,IAAiB;IAC1D,MAAM,KAAK,GAAgD,EAAE,CAAA;IAC7D,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACjG,CAAC;aAAM,CAAC;YACN,0BAA0B;YAC1B,IAAI,KAAK,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAA;YACzC,OAAO,KAAK,IAAI,CAAC;gBAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;YACvC,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE;gBAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;YAChD,IAAI,KAAK,GAAG,IAAI,EAAE,CAAC;gBACjB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACjG,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAoD,CAAC,CAAA;AAC9E,CAAC;AAED,2CAA2C;AAC3C,SAAS,aAAa,CAAC,IAAiB;IACtC,MAAM,GAAG,GAAoC,EAAE,CAAA;IAC/C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;YAClC,SAAQ;QACV,CAAC;QACD,IAAI,KAAK,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAA;QACzC,OAAO,KAAK,IAAI,CAAC;YAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;QACvC,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE;YAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;QAChD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;QAC9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,UAAU,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;YAC1C,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAC1F,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,mDAAmD;AACnD,SAAS,eAAe,CAAC,IAAqC,EAAE,EAAU,EAAE,EAAU;IACpF,IAAI,MAAM,GAAG,KAAK,CAAA;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QAC9D,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAA;QACrB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAA;QACrB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAA;QACrB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAA;QACrB,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE;YAAE,MAAM,GAAG,CAAC,MAAM,CAAA;IAC5F,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAqB;IACrD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,IAAI,MAAM,CAAA;IAE9B,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAE7F,mDAAmD;IACnD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IACrD,MAAM,MAAM,GAAG,IAAI,KAAK,CAAS,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAE,CAAA;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI;gBAAE,SAAQ;YACzD,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBAAE,SAAQ;YAC3D,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI;gBAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAChF,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,CAAS,EAAU,EAAE;QACpC,IAAI,CAAC,GAAG,CAAC,CAAA;QACT,IAAI,GAAG,GAAG,CAAC,CAAA;QACX,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC1B,CAAC,EAAE,CAAA;YACH,GAAG,GAAG,MAAM,CAAC,GAAG,CAAE,CAAA;QACpB,CAAC;QACD,OAAO,CAAC,CAAA;IACV,CAAC,CAAA;IAED,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAA;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;aACpC,CAAC;YACJ,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAA;YACpB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAC1B,IAAI,GAAG;gBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;;gBACf,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;QAClB,IAAI,KAAK,GAAG,OAAO,CAAC,CAAC,CAAE,CAAA;QACvB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,KAAK,CAAC,GAAG,CAAE,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAE,CAAC,IAAI;gBAAE,KAAK,GAAG,GAAG,CAAA;QACxD,CAAC;QACD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,CAAA;QACnD,OAAO,aAAa,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,qBAAqB;IACrB,MAAM,KAAK,GAA4C,EAAE,CAAA;IACzD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,CAAA;QACjD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QAClC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC9B,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,CAAA;YACtE,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;YACpD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YACpB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,CAAA;QACnB,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;IACxD,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,KAAc,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;AACtE,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC;IAC9B,YAAY,EAAE,CAAC,YAAY,CAAC;IAC5B,IAAI,CAAC,MAA+B;QAClC,mBAAmB,CAAC,MAAM,CAAC,CAAA;QAC3B,OAAO,iBAAiB,CAAC,MAAkC,CAAC,CAAA;IAC9D,CAAC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,EAAgB;CACtF,CAAC,CAAA","sourcesContent":["/**\n * stdlib profile — 从 2D 轮廓构面(creator 函数,无输入,brep-only)。\n *\n * 用途:faijs 此前没有「从 2D 轮廓构造 planar face」的能力,导致草图轮廓无法喂给\n * extrude/revolve。本 op 接收 2D 轮廓(线段 + 圆弧),在 z=0 平面用 OCCT 构面:\n * makeLineEdge/makeArcEdge → makeWire → makeFace(+ addHolesInFace)。\n *\n * 设计:\n * - 输入:{ contours: ProfileLoop[] },每个 loop = 有序 segments(line / arc,z=0)。\n * - 环语义:嵌套 = 孔,不相交 = 独立岛(多岛 → face 的 compound),见 buildProfileShape。\n * - 圆弧:用起点/中点/终点三点的 makeArcEdge;整圆(sweep≈2π)拆成两段弧。\n * - 输出:Shape(mesh 三角化 + 句柄登记)。brep-only(下游 extrude/revolve 亦 brep-only)。\n *\n * 坐标系:输入 2D 点即 (x, y, 0),法向 +Z;草图在 Body 局部系内的定位由调用方(fcstd 端口)\n * 在轮廓坐标里预先变换,或由下游特征的 Placement 承担。\n */\n\nimport type { Shape } from '../mesh/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { solidToShape } from '../brep/brep-ops'\nimport { fromBrep, fromBrepCurve } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { Provenance } from '../topology/naming/lineage'\n\n// ── 参数形状(与 fcstd Contour 结构相同,避免引擎依赖端口层)──\n\n/** 直线段(2D,z=0;端点为绝对坐标)。 */\nexport interface ProfileLineSeg {\n kind: 'line'\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/** 圆弧段(圆心 + 半径 + 起止角,弧度;z=0)。 */\nexport interface ProfileArcSeg {\n kind: 'arc'\n cx: number\n cy: number\n radius: number\n /** 起始角(弧度) */\n startAngle: number\n /** 终止角(弧度) */\n endAngle: number\n ccw: boolean\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\n/** 一条有序 2D 轮廓段(直线或圆弧)。 */\nexport type ProfileSeg = ProfileLineSeg | ProfileArcSeg\n\n/** 单个轮廓环:有序段序列(首尾相接)。 */\nexport interface ProfileLoop {\n segments: ProfileSeg[]\n}\n\n/** `cad.profile` 参数:轮廓环集合。语义见 {@link buildProfileShape}(嵌套=孔,不相交=独立岛)。 */\nexport interface ProfileParams {\n contours: ProfileLoop[]\n /**\n * 产物形态:'face'(默认)构面;'wire' 只交出不带面的最大岛外环 wire(1D 曲线),\n * 供扫掠族(sweep/loft/…)直接作 spine。'wire' 形态丢弃孔环(扫掠脊柱为单闭合轮廓)。\n */\n as?: 'face' | 'wire'\n}\n\n// ── 参数自校验 ──\n\n/**\n * Validate profile parameters: `contours` must be a non-empty array of loops,\n * each with at least one segment.\n * @param params the raw profile operation parameters.\n */\nexport function assertProfileParams(params: Record<string, unknown>): void {\n const contours = params.contours\n if (!Array.isArray(contours) || contours.length === 0) {\n throw new Error('E_PROFILE_NO_CONTOURS: profile requires at least one contour')\n }\n for (const loop of contours) {\n if (!loop || typeof loop !== 'object' || !Array.isArray((loop as ProfileLoop).segments)) {\n throw new Error('E_PROFILE_BAD_LOOP: each contour must have a segments array')\n }\n if ((loop as ProfileLoop).segments.length === 0) {\n throw new Error('E_PROFILE_EMPTY_LOOP: a contour must have at least one segment')\n }\n }\n}\n\n/**\n * 单环带符号面积(对每段做有向面积积分,而非只用段起点 shoelace)。\n *\n * 直线段:1/2 (x1·y2 − x2·y1)。\n * 圆弧段:1/2 ∫(x dy − y dx) 的解析解 = 1/2 [r²·sweep + cx·r(sin a1 − sin a0) − cy·r(cos a1 − cos a0)]。\n * 整圆(单段弧、起终点重合)由此得到 πr²,不再是 0——否则「整圆 + 方孔」会把孔误判成外环。\n */\nfunction loopSignedArea(loop: ProfileLoop): number {\n let a = 0\n for (const seg of loop.segments) {\n if (seg.kind === 'line') {\n a += (seg.x1 * seg.y2 - seg.x2 * seg.y1) / 2\n continue\n }\n let sweep = seg.endAngle - seg.startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n const { cx, cy, radius: r, startAngle: a0 } = seg\n const a1 = a0 + sweep\n a += 0.5 * (r * r * sweep + cx * r * (Math.sin(a1) - Math.sin(a0)) - cy * r * (Math.cos(a1) - Math.cos(a0)))\n }\n return a\n}\n\n/** 圆弧 → 一条或两条 makeArcEdge(整圆拆分)。 */\nfunction arcToHandles(\n kernel: BrepEngineApi,\n seg: ProfileArcSeg,\n): ReturnType<BrepEngineApi['makeArcEdge']>[] {\n const { cx, cy, radius, startAngle, endAngle, ccw = true } = seg\n // GOTCHA(2026-09-25,A3 FCBL_tree_entourage):ccw 必须参与弧的几何方向。\n // makeArcEdge 按「起点-中点-终点」三点定弧,旧实现一律取 CCW 中点\n // ((start+end)/2 归一化到 (0,2π]),ccw:false 的弧被画成 CCW **长弧**(补角)。\n // 实测后果:长弧穿过旋转轴 → revolve 产物退化(bbox NaN)→ BRepMesh 挂死\n // (进程无声死亡);正确 CW 短弧下内核 revolve 仅 ~19ms。\n let sweep: number\n let midAngle: number\n if (ccw) {\n sweep = endAngle - startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n midAngle = startAngle + sweep / 2\n } else {\n // 顺时针:从 startAngle 递减到 endAngle,扫角取反向归一化\n sweep = startAngle - endAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n midAngle = startAngle - sweep / 2\n }\n\n const makeOne = (a0: number, am: number, a1: number): ReturnType<BrepEngineApi['makeArcEdge']> => {\n const start = { x: cx + radius * Math.cos(a0), y: cy + radius * Math.sin(a0), z: 0 }\n const m = { x: cx + radius * Math.cos(am), y: cy + radius * Math.sin(am), z: 0 }\n const end = { x: cx + radius * Math.cos(a1), y: cy + radius * Math.sin(a1), z: 0 }\n return kernel.makeArcEdge(start, m, end)\n }\n\n // 整圆(sweep≈2π):拆成两段半圆,避免 makeArcEdge 起点≈终点退化\n if (sweep >= 2 * Math.PI - 1e-9) {\n const half = 2 * Math.PI / 2\n const dir = ccw ? 1 : -1\n return [\n makeOne(startAngle, startAngle + dir * half / 2, startAngle + dir * half),\n makeOne(startAngle + dir * half, startAngle + dir * (half + half / 2), startAngle + dir * 2 * Math.PI),\n ]\n }\n return [makeOne(startAngle, midAngle, endAngle)]\n}\n\n/** 单环 → wire handle(仅构面,不释放中间句柄,遵循现有惯例)。 */\nfunction loopToWire(kernel: BrepEngineApi, loop: ProfileLoop): ReturnType<BrepEngineApi['makeWire']> {\n const edges: ReturnType<BrepEngineApi['makeLineEdge']>[] = []\n for (const seg of loop.segments) {\n if (seg.kind === 'line') {\n edges.push(kernel.makeLineEdge({ x: seg.x1, y: seg.y1, z: 0 }, { x: seg.x2, y: seg.y2, z: 0 }))\n } else {\n // 极小扫角(退化弧)→ 退化为线段,避免构边失败\n let sweep = seg.endAngle - seg.startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n if (sweep < 1e-9) {\n edges.push(kernel.makeLineEdge({ x: seg.x1, y: seg.y1, z: 0 }, { x: seg.x2, y: seg.y2, z: 0 }))\n } else {\n edges.push(...arcToHandles(kernel, seg))\n }\n }\n }\n return kernel.makeWire(edges as ReturnType<BrepEngineApi['makeLineEdge']>[])\n}\n\n/** 环 → 2D 采样多边形(直线取端点、弧等角采样),用于环间包含性判定。 */\nfunction loopToPolygon(loop: ProfileLoop): Array<{ x: number; y: number }> {\n const pts: Array<{ x: number; y: number }> = []\n for (const seg of loop.segments) {\n if (seg.kind === 'line') {\n pts.push({ x: seg.x1, y: seg.y1 })\n continue\n }\n let sweep = seg.endAngle - seg.startAngle\n while (sweep <= 0) sweep += 2 * Math.PI\n while (sweep > 2 * Math.PI) sweep -= 2 * Math.PI\n const n = Math.max(8, Math.ceil((sweep / (2 * Math.PI)) * 32))\n for (let k = 0; k < n; k++) {\n const a = seg.startAngle + (sweep * k) / n\n pts.push({ x: seg.cx + seg.radius * Math.cos(a), y: seg.cy + seg.radius * Math.sin(a) })\n }\n }\n return pts\n}\n\n/** 射线法:点是否在多边形内(采样多边形足够密,顶点/边界角落情形由环间不共边保证不出现)。 */\nfunction polygonContains(poly: Array<{ x: number; y: number }>, px: number, py: number): boolean {\n let inside = false\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const xi = poly[i]!.x\n const yi = poly[i]!.y\n const xj = poly[j]!.x\n const yj = poly[j]!.y\n if (yi > py !== yj > py && px < ((xj - xi) * (py - yi)) / (yj - yi) + xi) inside = !inside\n }\n return inside\n}\n\n/**\n * BREP 路径:2D 轮廓集合 → planar face 集合。\n *\n * GOTCHA(2026-09-26,Beds part16/39):环语义是「**嵌套 = 孔,不相交 = 独立岛**」\n * (与 FreeCAD 草图一致),不是「面积最大者当外环、其余全当孔」。旧实现把双岛轮廓的\n * 第二个岛判成「洞外面」→ `addHolesInFace` 收到与外环不相交的 wire → 构面退化\n * (7 面、volume 0)。多岛产物 = compound(每岛一面、各带自己的孔),下游\n * `cad.extrude` 对 compound 输入逐面挤出(kernel MakePrism 收复合形状)。\n *\n * @param params - 轮廓环集合与产物形态。\n * @returns Shape(单岛为 face;多岛为 face 的 compound;`as:'wire'` 为 1D 曲线)。\n */\nexport function buildProfileShape(params: ProfileParams): Shape {\n const kernel = getBrepApi()\n const as = params.as ?? 'face'\n\n const loops = params.contours.map((loop) => ({ loop, area: Math.abs(loopSignedArea(loop)) }))\n\n // 包含分类:每个环的直接父环 = 面积最小的严格包含它的环;深度偶数 = 岛,奇数 = 父环的孔。\n const polys = loops.map((l) => loopToPolygon(l.loop))\n const parent = new Array<number>(loops.length).fill(-1)\n for (let i = 0; i < loops.length; i++) {\n const probe = polys[i]![0]!\n for (let j = 0; j < loops.length; j++) {\n if (i === j || loops[j]!.area <= loops[i]!.area) continue\n if (!polygonContains(polys[j]!, probe.x, probe.y)) continue\n if (parent[i] === -1 || loops[j]!.area < loops[parent[i]]!.area) parent[i] = j\n }\n }\n const depthOf = (i: number): number => {\n let d = 0\n let cur = i\n while (parent[cur] !== -1) {\n d++\n cur = parent[cur]!\n }\n return d\n }\n\n const islands: number[] = []\n const holesOf = new Map<number, number[]>()\n for (let i = 0; i < loops.length; i++) {\n if (depthOf(i) % 2 === 0) islands.push(i)\n else {\n const p = parent[i]!\n const arr = holesOf.get(p)\n if (arr) arr.push(i)\n else holesOf.set(p, [i])\n }\n }\n\n // 'wire' 形态:只交最大岛的外环 wire(1D 曲线),不构面 —— 供扫掠族作 spine。\n if (as === 'wire') {\n let outer = islands[0]!\n for (const isl of islands) {\n if (loops[isl]!.area > loops[outer]!.area) outer = isl\n }\n const wire = loopToWire(kernel, loops[outer]!.loop)\n return fromBrepCurve(solidToShape(kernel, wire), { solid: wire })\n }\n\n // 每岛一面(岛环为外环,直接子环为孔)\n const faces: ReturnType<BrepEngineApi['makeFace']>[] = []\n for (const isl of islands) {\n const wire = loopToWire(kernel, loops[isl]!.loop)\n const face = kernel.makeFace(wire)\n const holes = holesOf.get(isl)\n if (holes && holes.length > 0) {\n const holeWires = holes.map((h) => loopToWire(kernel, loops[h]!.loop))\n const faced = kernel.addHolesInFace(face, holeWires)\n kernel.release(face)\n faces.push(faced)\n } else {\n faces.push(face)\n }\n }\n\n if (faces.length === 1) {\n const f = faces[0]!\n return fromBrep(solidToShape(kernel, f), { solid: f })\n }\n const compound = kernel.makeCompound(faces as never)\n return fromBrep(solidToShape(kernel, compound), { solid: compound })\n}\n\n/**\n * 从 2D 轮廓构造平面(creator,无输入)。仅 BREP 可用。\n * @group 创建\n * @inputs 0\n * @async false\n * @qual ok\n * @name profile\n * @returns Shape 平面几何(mesh 三角化 + BREP 句柄);`as:'wire'` 时返回 1D 曲线(kind:'curve')。\n * @param params.contours - 有序 2D 轮廓(线段/圆弧;外环 + 孔)。type:ProfileLoop[] required:true\n * @param params.as - 产物形态:'face'(默认)构面;'wire' 只交外环 wire(1D 曲线)。type:'face'|'wire' required:false\n * @example\n * const f = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }] })\n * const w = cad.profile({ contours: [{ segments: [{ kind:'line', x1:0,y1:0,x2:10,y2:0 }, ...] }], as: 'wire' })\n */\nexport const profile = defineOp({\n capabilities: ['directEdit'],\n brep(params: Record<string, unknown>) {\n assertProfileParams(params)\n return buildProfileShape(params as unknown as ProfileParams)\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [] } } as Provenance,\n})"]}
|
package/dist/api/transform.d.ts
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* stdlib transform — 变换对象库函数(translate/rotate_euler/scale/scale3d)
|
|
3
3
|
*
|
|
4
|
-
* 平台分层(narrowing plan Phase 5,D11
|
|
5
|
-
* - `translate` / `scale
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* 平台分层(narrowing plan Phase 5,D11 + 2026-09-28 D 批降级):
|
|
5
|
+
* - `translate` / `scale`:**中立 op**(不再声明 `engines:['occt']`)。BREP 路径按引擎
|
|
6
|
+
* 能力**静态定轨**(读与 dispatchPath 同源的能力集,非运行时探测):
|
|
7
|
+
* - occt(声明 `translateWithHistory` / `scaleWithHistory`)→ 走 face-evolution.ts 的
|
|
8
|
+
* `translateWithHashEvolution` / `scaleWithHashEvolution` 权威面演化(历史路径),
|
|
9
|
+
* 产 hash 面映射并传播 roleTable;
|
|
10
|
+
* - brepkit(未声明该二核函数,但裸 `kernel.translate` / `kernel.scale` 是真实现)→
|
|
11
|
+
* L1 `translateBrep` / `scaleBrep`:几何精确,**另加 identityHashEvolution**。
|
|
12
|
+
* 变换不改变面数/顺序,恒等映射真实成立(非伪造)——挂恒等面演化并传播 roleTable,
|
|
13
|
+
* 选面/命名在降级路径不丢(区别于 boolean/chamfer 这种毁面重造、严禁伪造的情形)。
|
|
9
14
|
* - `rotate_euler` / `scale3d`:**中立 op**——内核无单次 WithHistory 可表达
|
|
10
|
-
* (任意欧拉+pivot /
|
|
11
|
-
*
|
|
15
|
+
* (任意欧拉+pivot / 非等比),走 `rotateBrep` / `scaleBrep` + identity 面演化
|
|
16
|
+
* (只用 L1,跨引擎一致,不声明 engines)。
|
|
12
17
|
*
|
|
13
18
|
* dispatchPath 静态判定 brep/mesh,
|
|
14
19
|
* BREP 路径用 brepOf(input) 取输入实体、fromBrep 登记输出实体。
|
|
15
20
|
*/
|
|
16
21
|
import type { Shape } from '../mesh/types.js';
|
|
17
|
-
/** BREP 路径:变换 solid + 恒等面演化 + 三角化 + fromBrep 登记。 */
|
|
18
22
|
/**
|
|
19
23
|
* Validate translate parameters: `offset` must be a vec3.
|
|
20
24
|
* @param params - the raw translate operation parameters.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/api/transform.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/api/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAQ,MAAM,eAAe,CAAA;AAqBhD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE3E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAKxE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAQvE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAQzE;AA0FD;;;;;;;;;;;;;IAaI;AACJ,eAAO,MAAM,SAAS;;CAgBpB,CAAA;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY;;CAevB,CAAA;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,KAAK;;CAkBhB,CAAA;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,OAAO;;CAkBlB,CAAA"}
|
package/dist/api/transform.js
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* stdlib transform — 变换对象库函数(translate/rotate_euler/scale/scale3d)
|
|
3
3
|
*
|
|
4
|
-
* 平台分层(narrowing plan Phase 5,D11
|
|
5
|
-
* - `translate` / `scale
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* 平台分层(narrowing plan Phase 5,D11 + 2026-09-28 D 批降级):
|
|
5
|
+
* - `translate` / `scale`:**中立 op**(不再声明 `engines:['occt']`)。BREP 路径按引擎
|
|
6
|
+
* 能力**静态定轨**(读与 dispatchPath 同源的能力集,非运行时探测):
|
|
7
|
+
* - occt(声明 `translateWithHistory` / `scaleWithHistory`)→ 走 face-evolution.ts 的
|
|
8
|
+
* `translateWithHashEvolution` / `scaleWithHashEvolution` 权威面演化(历史路径),
|
|
9
|
+
* 产 hash 面映射并传播 roleTable;
|
|
10
|
+
* - brepkit(未声明该二核函数,但裸 `kernel.translate` / `kernel.scale` 是真实现)→
|
|
11
|
+
* L1 `translateBrep` / `scaleBrep`:几何精确,**另加 identityHashEvolution**。
|
|
12
|
+
* 变换不改变面数/顺序,恒等映射真实成立(非伪造)——挂恒等面演化并传播 roleTable,
|
|
13
|
+
* 选面/命名在降级路径不丢(区别于 boolean/chamfer 这种毁面重造、严禁伪造的情形)。
|
|
9
14
|
* - `rotate_euler` / `scale3d`:**中立 op**——内核无单次 WithHistory 可表达
|
|
10
|
-
* (任意欧拉+pivot /
|
|
11
|
-
*
|
|
15
|
+
* (任意欧拉+pivot / 非等比),走 `rotateBrep` / `scaleBrep` + identity 面演化
|
|
16
|
+
* (只用 L1,跨引擎一致,不声明 engines)。
|
|
12
17
|
*
|
|
13
18
|
* dispatchPath 静态判定 brep/mesh,
|
|
14
19
|
* BREP 路径用 brepOf(input) 取输入实体、fromBrep 登记输出实体。
|
|
15
20
|
*/
|
|
16
21
|
import { cad } from '../mesh/index.js';
|
|
17
|
-
import { rotateBrep, scaleBrep, solidToShape } from '../brep/brep-ops.js';
|
|
22
|
+
import { translateBrep, rotateBrep, scaleBrep, solidToShape } from '../brep/brep-ops.js';
|
|
18
23
|
import { identityEvolution, identityHashEvolution, scaleWithHashEvolution, translateWithHashEvolution, } from '../brep/face-evolution.js';
|
|
19
24
|
import { getBrepApi } from '../brep/handle-bridge.js';
|
|
25
|
+
import { getBackends } from '../runtime-state.js';
|
|
26
|
+
import { engineCapabilitySet } from '../cad-runtime/backend-dispatch.js';
|
|
20
27
|
import { fromBrep, brepOf, inputRoleTable } from '../shape.js';
|
|
21
28
|
import { propagateAllOrigins } from '../topology/naming/roles.js';
|
|
22
29
|
import { defineOp } from '../sdk.js';
|
|
23
30
|
import { assertVec3, assertPositiveNumber } from './assert.js';
|
|
24
|
-
/** BREP 路径:变换 solid + 恒等面演化 + 三角化 + fromBrep 登记。 */
|
|
25
31
|
/**
|
|
26
32
|
* Validate translate parameters: `offset` must be a vec3.
|
|
27
33
|
* @param params - the raw translate operation parameters.
|
|
@@ -70,54 +76,82 @@ export function assertScale3dParams(params) {
|
|
|
70
76
|
/**
|
|
71
77
|
* BREP 路径:变换 solid + 面演化 + roleTable 传播 + 三角化 + fromBrep 登记。
|
|
72
78
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* `
|
|
76
|
-
*
|
|
79
|
+
* 静态双轨:
|
|
80
|
+
* - 引擎声明 `translateWithHistory` / `scaleWithHistory`(occt)→ 权威历史路径
|
|
81
|
+
* (`translateWithHashEvolution` / `scaleWithHashEvolution`),产内核给出的面映射 + roleTable。
|
|
82
|
+
* - 引擎只声明裸方法(brepkit:裸 `translate`/`scale` 是真实现,但无 `*WithHistory`)→
|
|
83
|
+
* L1 裸调用 + identityHashEvolution。变换是刚体变换、面数/顺序保持不变,恒等映射
|
|
84
|
+
* **真实成立**(非伪造;由 brep/face-evolution.ordering.test.ts 钉住)——因此 brepkit
|
|
85
|
+
* 降级路径保留恒等面演化与 roleTable 传播,选面/命名不因降级而丢失。
|
|
86
|
+
* `rotate_euler` / `scale3d` 走 `rotateBrep` / `scaleBrep` + identity 面演化(既有语义,跨引擎中性)。
|
|
77
87
|
* @param op - the transform operation name.
|
|
78
88
|
* @param input - the input geometry.
|
|
79
89
|
* @param params - the operation parameters.
|
|
80
90
|
* @returns the transformed Shape.
|
|
81
91
|
*/
|
|
82
92
|
function transformBrep(op, input, params) {
|
|
83
|
-
// L1 面:rotateBrep/scaleBrep/identityHashEvolution 只用 L1(D12)。
|
|
93
|
+
// L1 面:translateBrep/rotateBrep/scaleBrep/identityHashEvolution 只用 L1(D12)。
|
|
84
94
|
const kernel = getBrepApi();
|
|
85
95
|
const inputSolid = brepOf(input);
|
|
86
96
|
if (!inputSolid)
|
|
87
97
|
throw new Error('[stdlib/transform] input is not BREP');
|
|
98
|
+
// 静态双轨(无运行时 try-catch 回退——按引擎**声明**的能力集在执行前定轨):
|
|
99
|
+
// - occt(声明 *WithHistory)→ 权威历史路径(产内核面映射 + roleTable)。
|
|
100
|
+
// - brepkit(裸 translate/scale 是真实现,无 *WithHistory)→ L1 裸调用 + identityHashEvolution。
|
|
101
|
+
// 变换不改变面数/顺序,恒等映射真实成立(非伪造),故仍挂恒等面演化与 roleTable 传播。
|
|
102
|
+
const caps = engineCapabilitySet(getBackends().config.brepCapabilities);
|
|
103
|
+
const hasTranslateHistory = caps.has('translateWithHistory');
|
|
104
|
+
const hasScaleHistory = caps.has('scaleWithHistory');
|
|
88
105
|
let resultSolid;
|
|
89
|
-
|
|
106
|
+
// 面演化(hash 键):权威路径用内核映射,降级/中立路径用 identity 恒等映射。
|
|
107
|
+
let historyEvolution;
|
|
90
108
|
if (op === 'translate') {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
109
|
+
if (hasTranslateHistory) {
|
|
110
|
+
// 权威映射:内核 translateWithHistory(1:1 全覆盖,实测见 evolution-bindings.test.ts)
|
|
111
|
+
const r = translateWithHashEvolution(kernel, inputSolid, params.offset);
|
|
112
|
+
resultSolid = r.result;
|
|
113
|
+
historyEvolution = r.evolution;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// brepkit 降级:L1 裸 translate(几何精确)+ identity(变换保面序,真实正确)。
|
|
117
|
+
resultSolid = translateBrep(kernel, inputSolid, params.offset);
|
|
118
|
+
historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid);
|
|
119
|
+
}
|
|
95
120
|
}
|
|
96
121
|
else if (op === 'scale') {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
122
|
+
if (hasScaleHistory) {
|
|
123
|
+
// 权威映射:内核 scaleWithHistory(仅均匀 —— assertScaleParams 已保证 factor 是 number)
|
|
124
|
+
const r = scaleWithHashEvolution(kernel, inputSolid, params.center ?? [0, 0, 0], params.factor);
|
|
125
|
+
resultSolid = r.result;
|
|
126
|
+
historyEvolution = r.evolution;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// brepkit 降级:L1 裸 scale(几何精确)+ identity(变换保面序,真实正确)。
|
|
130
|
+
const center = params.center ?? [0, 0, 0];
|
|
131
|
+
resultSolid = scaleBrep(kernel, inputSolid, params.factor, center);
|
|
132
|
+
historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid);
|
|
133
|
+
}
|
|
101
134
|
}
|
|
102
135
|
else {
|
|
103
|
-
// rotate_euler(任意欧拉角+pivot)/ scale3d(非等比):内核无单次 WithHistory 可表达
|
|
136
|
+
// rotate_euler(任意欧拉角+pivot)/ scale3d(非等比):内核无单次 WithHistory 可表达 →
|
|
137
|
+
// L1 rotate/scale + identity 面演化(既有语义,face-evolution.ordering.test.ts 钉住)。
|
|
104
138
|
if (op === 'rotate_euler') {
|
|
105
139
|
resultSolid = rotateBrep(kernel, inputSolid, params.anglesDeg, params.pivot);
|
|
106
140
|
}
|
|
107
141
|
else {
|
|
108
142
|
resultSolid = scaleBrep(kernel, inputSolid, params.factor, params.center);
|
|
109
143
|
}
|
|
110
|
-
|
|
144
|
+
historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid);
|
|
111
145
|
}
|
|
112
|
-
//
|
|
146
|
+
// 变换面 1:1 保留——沿演化传播 roleTable(所有 origin),跨引擎一致(含 brepkit 降级路径)。
|
|
113
147
|
const inputTable = inputRoleTable(input);
|
|
114
148
|
let roleTable;
|
|
115
149
|
if (inputTable && inputTable.size > 0) {
|
|
116
|
-
roleTable = propagateAllOrigins(inputTable,
|
|
150
|
+
roleTable = propagateAllOrigins(inputTable, historyEvolution);
|
|
117
151
|
}
|
|
118
152
|
return fromBrep(solidToShape(kernel, resultSolid), {
|
|
119
153
|
solid: resultSolid,
|
|
120
|
-
//
|
|
154
|
+
// 变换维护拓扑,面 ordinal 不变 → 挂 identity 面演化(供显示/选面,跨引擎一致)。
|
|
121
155
|
faceEvolution: identityEvolution(kernel, resultSolid),
|
|
122
156
|
roleTable,
|
|
123
157
|
});
|
|
@@ -153,8 +187,6 @@ export const translate = defineOp({
|
|
|
153
187
|
// D11: `translate(p, 10, 0, 0)` == `translate(p, { offset: [10, 0, 0] })`;
|
|
154
188
|
// `offset` is a vec3 slot sitting after the single leading Shape argument.
|
|
155
189
|
slotMap: { keys: ['offset'], vec3Keys: ['offset'], shapeArity: 1 },
|
|
156
|
-
// 平台 op:权威面演化依赖 occt-only translateWithHistory(face-evolution.ts,D3)。
|
|
157
|
-
engines: ['occt'],
|
|
158
190
|
naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
|
|
159
191
|
});
|
|
160
192
|
/**
|
|
@@ -227,8 +259,6 @@ export const scale = defineOp({
|
|
|
227
259
|
// D11(§4.6):`scale(p, 2)` == `scale(p, { factor: 2 })`(标量槽);尾参 options
|
|
228
260
|
// ({center})经 dual-form-args 尾参合并并入。
|
|
229
261
|
slotMap: { keys: ['factor'], shapeArity: 1 },
|
|
230
|
-
// 平台 op:权威面演化依赖 occt-only scaleWithHistory(face-evolution.ts,D3)。
|
|
231
|
-
engines: ['occt'],
|
|
232
262
|
naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
|
|
233
263
|
});
|
|
234
264
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/api/transform.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * stdlib transform — 变换对象库函数(translate/rotate_euler/scale/scale3d)\n *\n * 平台分层(narrowing plan Phase 5,D11):\n * - `translate` / `scale`:**平台 op(occt)**——权威面演化走\n * `translateWithHistory` / `scaleWithHistory`(occt-only,face-evolution.ts 的\n * translateWithHashEvolution/scaleWithHashEvolution 经 getOcctKernel() 调用)→\n * `engines: ['occt']`。\n * - `rotate_euler` / `scale3d`:**中立 op**——内核无单次 WithHistory 可表达\n * (任意欧拉+pivot / 非等比),退回 `identityHashEvolution` + `rotateBrep`/\n * `scaleBrep`(只用 L1:transform/generalTransform/subShapeHashes),不声明 engines。\n *\n * dispatchPath 静态判定 brep/mesh,\n * BREP 路径用 brepOf(input) 取输入实体、fromBrep 登记输出实体。\n */\n\nimport type { Shape, Vec3 } from '../mesh/types'\nimport { cad } from '../mesh'\nimport { rotateBrep, scaleBrep, solidToShape } from '../brep/brep-ops'\nimport {\n identityEvolution,\n identityHashEvolution,\n scaleWithHashEvolution,\n translateWithHashEvolution,\n} from '../brep/face-evolution'\nimport type { HashEvolution } from '../brep/face-evolution'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { fromBrep, brepOf, inputRoleTable } from '../shape'\nimport { propagateAllOrigins } from '../topology/naming/roles'\nimport type { RoleTable } from '../topology/naming/types'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { defineOp } from '../sdk'\nimport { assertVec3, assertPositiveNumber } from './assert'\nimport type { BrepHandle } from '../brep/engine/types'\n\n/** BREP 路径:变换 solid + 恒等面演化 + 三角化 + fromBrep 登记。 */\n\n/**\n * Validate translate parameters: `offset` must be a vec3.\n * @param params - the raw translate operation parameters.\n */\nexport function assertTranslateParams(params: Record<string, unknown>): void {\n assertVec3(params.offset, 'translate.offset')\n}\n\n/**\n * Validate rotate_euler parameters: `anglesDeg` must be a vec3, and `pivot`\n * (if provided) must also be a vec3.\n * @param params - the raw rotate_euler operation parameters.\n */\nexport function assertRotateParams(params: Record<string, unknown>): void {\n assertVec3(params.anglesDeg, 'rotate_euler.anglesDeg')\n if (params.pivot !== undefined && params.pivot !== null) {\n assertVec3(params.pivot, 'rotate_euler.pivot')\n }\n}\n\n/**\n * Validate scale parameters (brepjs contract, §4.6 裁决 2): `factor` must be a\n * positive number (uniform). The non-uniform array form belongs to `scale3d` —\n * any `scale(p, { factor: [x,y,z] })` call throws an explicit `E_ARGS_FORM`\n * error pointing at `scale3d` (error hint ≠ compatibility).\n * @param params - the raw scale operation parameters.\n */\nexport function assertScaleParams(params: Record<string, unknown>): void {\n if (Array.isArray(params.factor)) {\n throw new Error(\n '[faijs/args] scale: E_ARGS_FORM: uniform scaling takes a single number ' +\n '(scale(p, s, { center? })). Non-uniform scaling uses scale3d(p, [x,y,z]).',\n )\n }\n assertPositiveNumber(params.factor, 'scale.factor')\n}\n\n/**\n * Validate scale3d parameters (P6: factor locked to Vec3): `factor` must be a\n * vec3. The uniform scalar form belongs to `scale` — any `scale3d(p, 2)` call\n * throws an explicit `E_ARGS_FORM` error pointing at `scale` (§4.6 裁决 2).\n * @param params - the raw scale3d operation parameters.\n */\nexport function assertScale3dParams(params: Record<string, unknown>): void {\n if (typeof params.factor === 'number') {\n throw new Error(\n '[faijs/args] scale3d: E_ARGS_FORM: factor must be a vec3 [x, y, z]. ' +\n 'Uniform scaling now uses scale(p, 2) (§4.6 裁决 2).',\n )\n }\n assertVec3(params.factor, 'scale3d.factor')\n}\n\n/**\n * BREP 路径:变换 solid + 面演化 + roleTable 传播 + 三角化 + fromBrep 登记。\n *\n * Phase 0.3:优先走内核**权威**面演化(`translateWithHistory` / `scaleWithHistory`);\n * 内核无法单次表达的(`rotate_euler` 任意欧拉+pivot、`scale3d` 非等比)退回\n * `identityHashEvolution`,其\"面枚举序号在变换后保持\"的假设由\n * `brep/face-evolution.ordering.test.ts` 实测钉住。\n * @param op - the transform operation name.\n * @param input - the input geometry.\n * @param params - the operation parameters.\n * @returns the transformed Shape.\n */\nfunction transformBrep(op: string, input: Shape, params: Record<string, unknown>): Shape {\n // L1 面:rotateBrep/scaleBrep/identityHashEvolution 只用 L1(D12)。\n const kernel = getBrepApi()\n const inputSolid = brepOf(input) as BrepHandle | undefined\n if (!inputSolid) throw new Error('[stdlib/transform] input is not BREP')\n\n let resultSolid: BrepHandle\n let hashEvolution: HashEvolution\n\n if (op === 'translate') {\n // 权威映射:内核 translateWithHistory(1:1 全覆盖,实测见 evolution-bindings.test.ts)\n const r = translateWithHashEvolution(kernel, inputSolid, params.offset as Vec3)\n resultSolid = r.result\n hashEvolution = r.evolution\n } else if (op === 'scale') {\n // 权威映射:内核 scaleWithHistory(仅均匀 —— assertScaleParams 已保证 factor 是 number)\n const r = scaleWithHashEvolution(\n kernel,\n inputSolid,\n (params.center as Vec3 | undefined) ?? [0, 0, 0],\n params.factor as number,\n )\n resultSolid = r.result\n hashEvolution = r.evolution\n } else {\n // rotate_euler(任意欧拉角+pivot)/ scale3d(非等比):内核无单次 WithHistory 可表达\n if (op === 'rotate_euler') {\n resultSolid = rotateBrep(kernel, inputSolid, params.anglesDeg as Vec3, params.pivot as Vec3 | undefined)\n } else {\n resultSolid = scaleBrep(kernel, inputSolid, params.factor as number | Vec3, params.center as Vec3 | undefined)\n }\n hashEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n\n // §2.4/§3.3:刚体变换面 1:1 保留 —— 沿演化传播 roleTable(所有 origin)\n const inputTable = inputRoleTable(input) as RoleTable | undefined\n let roleTable: RoleTable | undefined\n if (inputTable && inputTable.size > 0) {\n roleTable = propagateAllOrigins(inputTable, hashEvolution)\n }\n\n return fromBrep(solidToShape(kernel, resultSolid), {\n solid: resultSolid,\n // 变换不改变拓扑,面 ordinal 不变(与旧路径一致)\n faceEvolution: identityEvolution(kernel, resultSolid),\n roleTable,\n })\n}\n\n/**\n * 平移几何体。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name translate\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 平移后的几何,装配的相对位置靠成员的变换语句表达。\n * @param input - 目标几何。type:Shape required:true\n * @param params.offset - 平移向量(mm)。type:[x,y,z] required:true\n * @example\n * const p1 = cad.translate(part0, { offset: [10, 0, 0] })\n */\nexport const translate = defineOp({\n name: 'translate',\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/translate] no input geometry')\n assertTranslateParams(params)\n return cad.translate(input, params.offset as Vec3)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/translate] no input geometry')\n assertTranslateParams(params)\n return transformBrep('translate', input, params)\n },\n // D11: `translate(p, 10, 0, 0)` == `translate(p, { offset: [10, 0, 0] })`;\n // `offset` is a vec3 slot sitting after the single leading Shape argument.\n slotMap: { keys: ['offset'], vec3Keys: ['offset'], shapeArity: 1 },\n // 平台 op:权威面演化依赖 occt-only translateWithHistory(face-evolution.ts,D3)。\n engines: ['occt'],\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 绕轴旋转几何体。anglesDeg 为欧拉角(度,XYZ 顺序)。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name rotate_euler\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 旋转后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.anglesDeg - 欧拉角(度,XYZ 顺序)。type:[x,y,z] required:true\n * @param params.pivot - 旋转中心。type:[x,y,z] 默认 原点\n * @example\n * const p2 = cad.rotate_euler(part0, { anglesDeg: [0, 0, 45] })\n * const p3 = cad.rotate_euler(part0, { anglesDeg: [0, 0, 45], pivot: [0,0,0] })\n */\nexport const rotate_euler = defineOp({\n name: 'rotate_euler',\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/rotate_euler] no input geometry')\n assertRotateParams(params)\n return cad.rotate_euler(input, params.anglesDeg as Vec3, params.pivot as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/rotate_euler] no input geometry')\n assertRotateParams(params)\n return transformBrep('rotate_euler', input, params)\n },\n // D11: `rotate_euler(p, 0, 0, 45)` == `rotate_euler(p, { anglesDeg: [0, 0, 45] })`.\n slotMap: { keys: ['anglesDeg'], vec3Keys: ['anglesDeg'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 等比缩放几何体(brepjs 契约,§4.6 裁决 2)。factor 只收 number;不动点默认\n * 原点(与 vendored `scale(shape, factor, { center? })` 一致),`center` 可选。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name scale\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 缩放后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.factor - 等比缩放系数(> 0)。type:number required:true\n * @param params.center - 缩放不动点(p 保持不动)。type:[x,y,z] 默认 [0,0,0](原点)\n * @example\n * const p4 = cad.scale(part0, 2)\n * const p5 = cad.scale(part0, { factor: 2, center: [10, 0, 0] })\n */\nexport const scale = defineOp({\n name: 'scale',\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/scale] no input geometry')\n assertScaleParams(params)\n return cad.scale(input, params.factor as number, params.center as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/scale] no input geometry')\n assertScaleParams(params)\n return transformBrep('scale', input, params)\n },\n // L3 schema: factor/center for codegen/UI panels.\n schema: { factor: 'number', center: 'vec3?' },\n // D11(§4.6):`scale(p, 2)` == `scale(p, { factor: 2 })`(标量槽);尾参 options\n // ({center})经 dual-form-args 尾参合并并入。\n slotMap: { keys: ['factor'], shapeArity: 1 },\n // 平台 op:权威面演化依赖 occt-only scaleWithHistory(face-evolution.ts,D3)。\n engines: ['occt'],\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 非等比缩放几何体(faijs 语义,§1.4.4 裁决 2)。factor 定死 vec3 — 等比缩放请用\n * `scale(p, s)`,`scale3d(p, [x,y,z])` 才可非等比。`center` 为不动点(默认原点)。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name scale3d\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 缩放后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.factor - 三轴缩放系数(均 > 0)。type:[x,y,z] required:true\n * @param params.center - 缩放不动点。type:[x,y,z] 默认 [0,0,0](原点)\n * @example\n * const p4 = cad.scale3d(part0, { factor: [2, 1, 1] })\n * const p5 = cad.scale3d(part0, [2, 1, 1], { center: [10, 0, 0] })\n */\nexport const scale3d = defineOp({\n name: 'scale3d',\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/scale3d] no input geometry')\n assertScale3dParams(params)\n return cad.scale3d(input, params.factor as Vec3, params.center as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/scale3d] no input geometry')\n assertScale3dParams(params)\n return transformBrep('scale3d', input, params)\n },\n // L3 schema: factor/center for codegen/UI panels.\n schema: { factor: 'vec3', center: 'vec3?' },\n // D11(裁决 2):`scale3d(p, [1,2,3])` == `scale3d(p, { factor: [1,2,3] })`;\n // 标量 factor(如 `scale(p, 2)`)由 assertScale3dParams 拒绝并提示 `scale`。\n slotMap: { keys: ['factor'], vec3Keys: ['factor'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n"]}
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/api/transform.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * stdlib transform — 变换对象库函数(translate/rotate_euler/scale/scale3d)\n *\n * 平台分层(narrowing plan Phase 5,D11 + 2026-09-28 D 批降级):\n * - `translate` / `scale`:**中立 op**(不再声明 `engines:['occt']`)。BREP 路径按引擎\n * 能力**静态定轨**(读与 dispatchPath 同源的能力集,非运行时探测):\n * - occt(声明 `translateWithHistory` / `scaleWithHistory`)→ 走 face-evolution.ts 的\n * `translateWithHashEvolution` / `scaleWithHashEvolution` 权威面演化(历史路径),\n * 产 hash 面映射并传播 roleTable;\n * - brepkit(未声明该二核函数,但裸 `kernel.translate` / `kernel.scale` 是真实现)→\n * L1 `translateBrep` / `scaleBrep`:几何精确,**另加 identityHashEvolution**。\n * 变换不改变面数/顺序,恒等映射真实成立(非伪造)——挂恒等面演化并传播 roleTable,\n * 选面/命名在降级路径不丢(区别于 boolean/chamfer 这种毁面重造、严禁伪造的情形)。\n * - `rotate_euler` / `scale3d`:**中立 op**——内核无单次 WithHistory 可表达\n * (任意欧拉+pivot / 非等比),走 `rotateBrep` / `scaleBrep` + identity 面演化\n * (只用 L1,跨引擎一致,不声明 engines)。\n *\n * dispatchPath 静态判定 brep/mesh,\n * BREP 路径用 brepOf(input) 取输入实体、fromBrep 登记输出实体。\n */\n\nimport type { Shape, Vec3 } from '../mesh/types'\nimport { cad } from '../mesh'\nimport { translateBrep, rotateBrep, scaleBrep, solidToShape } from '../brep/brep-ops'\nimport {\n identityEvolution,\n identityHashEvolution,\n scaleWithHashEvolution,\n translateWithHashEvolution,\n} from '../brep/face-evolution'\nimport type { HashEvolution } from '../brep/face-evolution'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { getBackends } from '../runtime-state'\nimport { engineCapabilitySet } from '../cad-runtime/backend-dispatch'\nimport { fromBrep, brepOf, inputRoleTable } from '../shape'\nimport { propagateAllOrigins } from '../topology/naming/roles'\nimport type { RoleTable } from '../topology/naming/types'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { defineOp } from '../sdk'\nimport { assertVec3, assertPositiveNumber } from './assert'\nimport type { BrepHandle } from '../brep/engine/types'\n\n/**\n * Validate translate parameters: `offset` must be a vec3.\n * @param params - the raw translate operation parameters.\n */\nexport function assertTranslateParams(params: Record<string, unknown>): void {\n assertVec3(params.offset, 'translate.offset')\n}\n\n/**\n * Validate rotate_euler parameters: `anglesDeg` must be a vec3, and `pivot`\n * (if provided) must also be a vec3.\n * @param params - the raw rotate_euler operation parameters.\n */\nexport function assertRotateParams(params: Record<string, unknown>): void {\n assertVec3(params.anglesDeg, 'rotate_euler.anglesDeg')\n if (params.pivot !== undefined && params.pivot !== null) {\n assertVec3(params.pivot, 'rotate_euler.pivot')\n }\n}\n\n/**\n * Validate scale parameters (brepjs contract, §4.6 裁决 2): `factor` must be a\n * positive number (uniform). The non-uniform array form belongs to `scale3d` —\n * any `scale(p, { factor: [x,y,z] })` call throws an explicit `E_ARGS_FORM`\n * error pointing at `scale3d` (error hint ≠ compatibility).\n * @param params - the raw scale operation parameters.\n */\nexport function assertScaleParams(params: Record<string, unknown>): void {\n if (Array.isArray(params.factor)) {\n throw new Error(\n '[faijs/args] scale: E_ARGS_FORM: uniform scaling takes a single number ' +\n '(scale(p, s, { center? })). Non-uniform scaling uses scale3d(p, [x,y,z]).',\n )\n }\n assertPositiveNumber(params.factor, 'scale.factor')\n}\n\n/**\n * Validate scale3d parameters (P6: factor locked to Vec3): `factor` must be a\n * vec3. The uniform scalar form belongs to `scale` — any `scale3d(p, 2)` call\n * throws an explicit `E_ARGS_FORM` error pointing at `scale` (§4.6 裁决 2).\n * @param params - the raw scale3d operation parameters.\n */\nexport function assertScale3dParams(params: Record<string, unknown>): void {\n if (typeof params.factor === 'number') {\n throw new Error(\n '[faijs/args] scale3d: E_ARGS_FORM: factor must be a vec3 [x, y, z]. ' +\n 'Uniform scaling now uses scale(p, 2) (§4.6 裁决 2).',\n )\n }\n assertVec3(params.factor, 'scale3d.factor')\n}\n\n/**\n * BREP 路径:变换 solid + 面演化 + roleTable 传播 + 三角化 + fromBrep 登记。\n *\n * 静态双轨:\n * - 引擎声明 `translateWithHistory` / `scaleWithHistory`(occt)→ 权威历史路径\n * (`translateWithHashEvolution` / `scaleWithHashEvolution`),产内核给出的面映射 + roleTable。\n * - 引擎只声明裸方法(brepkit:裸 `translate`/`scale` 是真实现,但无 `*WithHistory`)→\n * L1 裸调用 + identityHashEvolution。变换是刚体变换、面数/顺序保持不变,恒等映射\n * **真实成立**(非伪造;由 brep/face-evolution.ordering.test.ts 钉住)——因此 brepkit\n * 降级路径保留恒等面演化与 roleTable 传播,选面/命名不因降级而丢失。\n * `rotate_euler` / `scale3d` 走 `rotateBrep` / `scaleBrep` + identity 面演化(既有语义,跨引擎中性)。\n * @param op - the transform operation name.\n * @param input - the input geometry.\n * @param params - the operation parameters.\n * @returns the transformed Shape.\n */\nfunction transformBrep(op: string, input: Shape, params: Record<string, unknown>): Shape {\n // L1 面:translateBrep/rotateBrep/scaleBrep/identityHashEvolution 只用 L1(D12)。\n const kernel = getBrepApi()\n const inputSolid = brepOf(input) as BrepHandle | undefined\n if (!inputSolid) throw new Error('[stdlib/transform] input is not BREP')\n\n // 静态双轨(无运行时 try-catch 回退——按引擎**声明**的能力集在执行前定轨):\n // - occt(声明 *WithHistory)→ 权威历史路径(产内核面映射 + roleTable)。\n // - brepkit(裸 translate/scale 是真实现,无 *WithHistory)→ L1 裸调用 + identityHashEvolution。\n // 变换不改变面数/顺序,恒等映射真实成立(非伪造),故仍挂恒等面演化与 roleTable 传播。\n const caps = engineCapabilitySet(getBackends().config.brepCapabilities)\n const hasTranslateHistory = caps.has('translateWithHistory')\n const hasScaleHistory = caps.has('scaleWithHistory')\n\n let resultSolid: BrepHandle\n // 面演化(hash 键):权威路径用内核映射,降级/中立路径用 identity 恒等映射。\n let historyEvolution: HashEvolution\n\n if (op === 'translate') {\n if (hasTranslateHistory) {\n // 权威映射:内核 translateWithHistory(1:1 全覆盖,实测见 evolution-bindings.test.ts)\n const r = translateWithHashEvolution(kernel, inputSolid, params.offset as Vec3)\n resultSolid = r.result\n historyEvolution = r.evolution\n } else {\n // brepkit 降级:L1 裸 translate(几何精确)+ identity(变换保面序,真实正确)。\n resultSolid = translateBrep(kernel, inputSolid, params.offset as Vec3)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n } else if (op === 'scale') {\n if (hasScaleHistory) {\n // 权威映射:内核 scaleWithHistory(仅均匀 —— assertScaleParams 已保证 factor 是 number)\n const r = scaleWithHashEvolution(\n kernel,\n inputSolid,\n (params.center as Vec3 | undefined) ?? [0, 0, 0],\n params.factor as number,\n )\n resultSolid = r.result\n historyEvolution = r.evolution\n } else {\n // brepkit 降级:L1 裸 scale(几何精确)+ identity(变换保面序,真实正确)。\n const center = (params.center as Vec3 | undefined) ?? [0, 0, 0]\n resultSolid = scaleBrep(kernel, inputSolid, params.factor as number, center)\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n } else {\n // rotate_euler(任意欧拉角+pivot)/ scale3d(非等比):内核无单次 WithHistory 可表达 →\n // L1 rotate/scale + identity 面演化(既有语义,face-evolution.ordering.test.ts 钉住)。\n if (op === 'rotate_euler') {\n resultSolid = rotateBrep(kernel, inputSolid, params.anglesDeg as Vec3, params.pivot as Vec3 | undefined)\n } else {\n resultSolid = scaleBrep(kernel, inputSolid, params.factor as number | Vec3, params.center as Vec3 | undefined)\n }\n historyEvolution = identityHashEvolution(kernel, inputSolid, resultSolid)\n }\n\n // 变换面 1:1 保留——沿演化传播 roleTable(所有 origin),跨引擎一致(含 brepkit 降级路径)。\n const inputTable = inputRoleTable(input) as RoleTable | undefined\n let roleTable: RoleTable | undefined\n if (inputTable && inputTable.size > 0) {\n roleTable = propagateAllOrigins(inputTable, historyEvolution)\n }\n\n return fromBrep(solidToShape(kernel, resultSolid), {\n solid: resultSolid,\n // 变换维护拓扑,面 ordinal 不变 → 挂 identity 面演化(供显示/选面,跨引擎一致)。\n faceEvolution: identityEvolution(kernel, resultSolid),\n roleTable,\n })\n}\n\n/**\n * 平移几何体。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name translate\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 平移后的几何,装配的相对位置靠成员的变换语句表达。\n * @param input - 目标几何。type:Shape required:true\n * @param params.offset - 平移向量(mm)。type:[x,y,z] required:true\n * @example\n * const p1 = cad.translate(part0, { offset: [10, 0, 0] })\n */\nexport const translate = defineOp({\n name: 'translate',\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/translate] no input geometry')\n assertTranslateParams(params)\n return cad.translate(input, params.offset as Vec3)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/translate] no input geometry')\n assertTranslateParams(params)\n return transformBrep('translate', input, params)\n },\n // D11: `translate(p, 10, 0, 0)` == `translate(p, { offset: [10, 0, 0] })`;\n // `offset` is a vec3 slot sitting after the single leading Shape argument.\n slotMap: { keys: ['offset'], vec3Keys: ['offset'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 绕轴旋转几何体。anglesDeg 为欧拉角(度,XYZ 顺序)。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name rotate_euler\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 旋转后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.anglesDeg - 欧拉角(度,XYZ 顺序)。type:[x,y,z] required:true\n * @param params.pivot - 旋转中心。type:[x,y,z] 默认 原点\n * @example\n * const p2 = cad.rotate_euler(part0, { anglesDeg: [0, 0, 45] })\n * const p3 = cad.rotate_euler(part0, { anglesDeg: [0, 0, 45], pivot: [0,0,0] })\n */\nexport const rotate_euler = defineOp({\n name: 'rotate_euler',\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/rotate_euler] no input geometry')\n assertRotateParams(params)\n return cad.rotate_euler(input, params.anglesDeg as Vec3, params.pivot as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/rotate_euler] no input geometry')\n assertRotateParams(params)\n return transformBrep('rotate_euler', input, params)\n },\n // D11: `rotate_euler(p, 0, 0, 45)` == `rotate_euler(p, { anglesDeg: [0, 0, 45] })`.\n slotMap: { keys: ['anglesDeg'], vec3Keys: ['anglesDeg'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 等比缩放几何体(brepjs 契约,§4.6 裁决 2)。factor 只收 number;不动点默认\n * 原点(与 vendored `scale(shape, factor, { center? })` 一致),`center` 可选。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name scale\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 缩放后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.factor - 等比缩放系数(> 0)。type:number required:true\n * @param params.center - 缩放不动点(p 保持不动)。type:[x,y,z] 默认 [0,0,0](原点)\n * @example\n * const p4 = cad.scale(part0, 2)\n * const p5 = cad.scale(part0, { factor: 2, center: [10, 0, 0] })\n */\nexport const scale = defineOp({\n name: 'scale',\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/scale] no input geometry')\n assertScaleParams(params)\n return cad.scale(input, params.factor as number, params.center as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/scale] no input geometry')\n assertScaleParams(params)\n return transformBrep('scale', input, params)\n },\n // L3 schema: factor/center for codegen/UI panels.\n schema: { factor: 'number', center: 'vec3?' },\n // D11(§4.6):`scale(p, 2)` == `scale(p, { factor: 2 })`(标量槽);尾参 options\n // ({center})经 dual-form-args 尾参合并并入。\n slotMap: { keys: ['factor'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n\n/**\n * 非等比缩放几何体(faijs 语义,§1.4.4 裁决 2)。factor 定死 vec3 — 等比缩放请用\n * `scale(p, s)`,`scale3d(p, [x,y,z])` 才可非等比。`center` 为不动点(默认原点)。\n * @group 变换\n * @inputs 1\n * @async false\n * @qual ok\n * @name scale3d\n * @deprecated **`../3d_editor` 消费面**(原 `@deprecated` 措辞已于 2026-09-22 校正):该 op 为编辑器应用提供(承载拖拽与时间线语句),不属 faijs 平台面,但**不是废弃项**——它服务真实负载。**变更其 API 形态必须同步更新 `../3d_editor`**(见 `docs/plans/2026-09-22-topology-identity-development-plan.md` §2)。faijs 平台面不提供等价 op(需要时须按平台需求另行设计,不得直接搬用本 op)。\n * @returns Shape 缩放后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.factor - 三轴缩放系数(均 > 0)。type:[x,y,z] required:true\n * @param params.center - 缩放不动点。type:[x,y,z] 默认 [0,0,0](原点)\n * @example\n * const p4 = cad.scale3d(part0, { factor: [2, 1, 1] })\n * const p5 = cad.scale3d(part0, [2, 1, 1], { center: [10, 0, 0] })\n */\nexport const scale3d = defineOp({\n name: 'scale3d',\n mesh: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/scale3d] no input geometry')\n assertScale3dParams(params)\n return cad.scale3d(input, params.factor as Vec3, params.center as Vec3 | undefined)\n },\n brep: (input: Shape, params: Record<string, unknown>) => {\n if (!input) throw new Error('[stdlib/scale3d] no input geometry')\n assertScale3dParams(params)\n return transformBrep('scale3d', input, params)\n },\n // L3 schema: factor/center for codegen/UI panels.\n schema: { factor: 'vec3', center: 'vec3?' },\n // D11(裁决 2):`scale3d(p, [1,2,3])` == `scale3d(p, { factor: [1,2,3] })`;\n // 标量 factor(如 `scale(p, 2)`)由 assertScale3dParams 拒绝并提示 `scale`。\n slotMap: { keys: ['factor'], vec3Keys: ['factor'], shapeArity: 1 },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n})\n"]}
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
/** brepkit 内核实例形态(BrepKernel 类,228 个方法;类型面见 npm 包 brepkit_wasm.d.ts)。 */
|
|
11
11
|
export type BrepKitKernel = any;
|
|
12
12
|
/**
|
|
13
|
-
* 注入自定义 brepkit wasm
|
|
13
|
+
* 注入自定义 brepkit wasm 初始化函数(宿主装配期调用一次)。写入共享挂点——
|
|
14
|
+
* 任意 faijs 实例(含 CDN 外部化实例 / 小程序 Worker 副实例)都优先使用。
|
|
14
15
|
* @param fn - the initialization function to use, or null to clear
|
|
15
16
|
*/
|
|
16
17
|
export declare function setBrepkitWasmInitFn(fn: (() => Promise<BrepKitKernel>) | null): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brepkitWasm.d.ts","sourceRoot":"","sources":["../../src/brepkit-kernel/brepkitWasm.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,yEAAyE;AACzE,MAAM,MAAM,aAAa,GAAG,GAAG,CAAA;
|
|
1
|
+
{"version":3,"file":"brepkitWasm.d.ts","sourceRoot":"","sources":["../../src/brepkit-kernel/brepkitWasm.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,yEAAyE;AACzE,MAAM,MAAM,aAAa,GAAG,GAAG,CAAA;AAkD/B;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,CAAC,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAKpF;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC,CAuBxD;AAED;mCACmC;AACnC,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C"}
|
|
@@ -7,26 +7,62 @@
|
|
|
7
7
|
* - 未注入时,node 环境直接 require('brepkit-wasm')(该包胶水零 eval,可直接装载);
|
|
8
8
|
* - 两边都没有 → 抛带上下文的错误(报错好于掩盖,禁止静默回退)。
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// 2026-09-26 跨实例共享(随 0.18.2 发布):customInitFn / initPromise 从模块级
|
|
11
|
+
// 单例提升为挂在 globalThis 上的共享状态(与 occtKernel.ts / runtime-state.ts
|
|
12
|
+
// 同款设计)。原因:CDN 外部化的 faijs 多实例各自持有独立内核 → 句柄不互通
|
|
13
|
+
// (occtKernel.ts 顶部注释详述);小程序 Worker 场景同理。挂到 globalThis 后,
|
|
14
|
+
// 任一实例 initBrepkitWasm() 产出的内核全局可见,句柄互通。
|
|
15
|
+
// 构建期去重(external / dedupe)仍是主手段,这里是兜底。
|
|
16
|
+
const BREPKIT_KERNEL_KEY = '__FAICAD_FAIJS_BREPKIT_KERNEL__';
|
|
17
|
+
const BREPKIT_KERNEL_STATE_VERSION = 1;
|
|
12
18
|
/**
|
|
13
|
-
*
|
|
19
|
+
* 获取 brepkit 内核共享状态(单例)。
|
|
20
|
+
*
|
|
21
|
+
* 挂在 globalThis 上是为了让"两份 faijs 代码"(宿主 bundle 一份、第三方库
|
|
22
|
+
* 外部化一份)共享同一份内核状态——否则两份 initPromise 导致内核各自初始化、
|
|
23
|
+
* 句柄不互通(几何孤岛)。
|
|
24
|
+
*
|
|
25
|
+
* @returns the shared brepkit kernel state singleton.
|
|
26
|
+
*/
|
|
27
|
+
function getBrepkitKernelSharedState() {
|
|
28
|
+
const g = globalThis;
|
|
29
|
+
const existing = g[BREPKIT_KERNEL_KEY];
|
|
30
|
+
if (existing) {
|
|
31
|
+
if (existing.stateVersion !== BREPKIT_KERNEL_STATE_VERSION) {
|
|
32
|
+
throw new Error(`[faijs] brepkit kernel state version mismatch: loaded=${existing.stateVersion}, expected=${BREPKIT_KERNEL_STATE_VERSION}`);
|
|
33
|
+
}
|
|
34
|
+
return existing;
|
|
35
|
+
}
|
|
36
|
+
const created = {
|
|
37
|
+
stateVersion: BREPKIT_KERNEL_STATE_VERSION,
|
|
38
|
+
customInitFn: null,
|
|
39
|
+
initPromise: null,
|
|
40
|
+
};
|
|
41
|
+
g[BREPKIT_KERNEL_KEY] = created;
|
|
42
|
+
return created;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 注入自定义 brepkit wasm 初始化函数(宿主装配期调用一次)。写入共享挂点——
|
|
46
|
+
* 任意 faijs 实例(含 CDN 外部化实例 / 小程序 Worker 副实例)都优先使用。
|
|
14
47
|
* @param fn - the initialization function to use, or null to clear
|
|
15
48
|
*/
|
|
16
49
|
export function setBrepkitWasmInitFn(fn) {
|
|
17
|
-
|
|
18
|
-
|
|
50
|
+
const s = getBrepkitKernelSharedState();
|
|
51
|
+
s.customInitFn = fn;
|
|
52
|
+
// 挂点变化后丢弃进行中的初始化(下一次 init 用新挂点重来)。
|
|
53
|
+
s.initPromise = null;
|
|
19
54
|
}
|
|
20
55
|
/**
|
|
21
56
|
* 初始化并返回 BrepKernel 单例(幂等:多次调用共享同一次初始化)。
|
|
22
57
|
* @returns Promise 解析为 BrepKernel 实例。
|
|
23
58
|
*/
|
|
24
59
|
export function initBrepkitWasm() {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
60
|
+
const s = getBrepkitKernelSharedState();
|
|
61
|
+
if (s.initPromise)
|
|
62
|
+
return s.initPromise;
|
|
63
|
+
s.initPromise = (async () => {
|
|
64
|
+
if (s.customInitFn)
|
|
65
|
+
return await s.customInitFn();
|
|
30
66
|
// node 环境(单测 / CLI):npm 包默认装载路径
|
|
31
67
|
if (typeof process !== 'undefined' && process.versions?.node) {
|
|
32
68
|
// Non-literal specifier: brepkit-wasm is an optional runtime injection, not
|
|
@@ -41,11 +77,11 @@ export function initBrepkitWasm() {
|
|
|
41
77
|
}
|
|
42
78
|
throw new Error('initBrepkitWasm: no init function set and not in Node environment. Call setBrepkitWasmInitFn() first.');
|
|
43
79
|
})();
|
|
44
|
-
return initPromise;
|
|
80
|
+
return s.initPromise;
|
|
45
81
|
}
|
|
46
82
|
/** 是否已初始化完成(测试诊断用)。
|
|
47
83
|
* @returns true 表示 init 已启动/完成。 */
|
|
48
84
|
export function isBrepkitInitialized() {
|
|
49
|
-
return initPromise !== null;
|
|
85
|
+
return getBrepkitKernelSharedState().initPromise !== null;
|
|
50
86
|
}
|
|
51
87
|
//# sourceMappingURL=brepkitWasm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brepkitWasm.js","sourceRoot":"","sources":["../../src/brepkit-kernel/brepkitWasm.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,IAAI,YAAY,
|
|
1
|
+
{"version":3,"file":"brepkitWasm.js","sourceRoot":"","sources":["../../src/brepkit-kernel/brepkitWasm.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,gEAAgE;AAChE,+DAA+D;AAC/D,8CAA8C;AAC9C,0DAA0D;AAC1D,yCAAyC;AACzC,uCAAuC;AAEvC,MAAM,kBAAkB,GAAG,iCAAiC,CAAA;AAC5D,MAAM,4BAA4B,GAAG,CAAC,CAAA;AAStC;;;;;;;;GAQG;AACH,SAAS,2BAA2B;IAClC,MAAM,CAAC,GAAG,UAAgD,CAAA;IAC1D,MAAM,QAAQ,GAAG,CAAC,CAAC,kBAAkB,CAAyC,CAAA;IAC9E,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,QAAQ,CAAC,YAAY,KAAK,4BAA4B,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CACb,yDAAyD,QAAQ,CAAC,YAAY,cAAc,4BAA4B,EAAE,CAC3H,CAAA;QACH,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,MAAM,OAAO,GAA6B;QACxC,YAAY,EAAE,4BAA4B;QAC1C,YAAY,EAAE,IAAI;QAClB,WAAW,EAAE,IAAI;KAClB,CAAA;IACD,CAAC,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAA;IAC/B,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,EAAyC;IAC5E,MAAM,CAAC,GAAG,2BAA2B,EAAE,CAAA;IACvC,CAAC,CAAC,YAAY,GAAG,EAAE,CAAA;IACnB,mCAAmC;IACnC,CAAC,CAAC,WAAW,GAAG,IAAI,CAAA;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,GAAG,2BAA2B,EAAE,CAAA;IACvC,IAAI,CAAC,CAAC,WAAW;QAAE,OAAO,CAAC,CAAC,WAAW,CAAA;IACvC,CAAC,CAAC,WAAW,GAAG,CAAC,KAAK,IAA4B,EAAE;QAClD,IAAI,CAAC,CAAC,YAAY;YAAE,OAAO,MAAM,CAAC,CAAC,YAAY,EAAE,CAAA;QACjD,gCAAgC;QAEhC,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;YAC7D,4EAA4E;YAC5E,yEAAyE;YACzE,wEAAwE;YACxE,MAAM,SAAS,GAAG,cAAc,CAAA;YAChC,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAEtD,CAAA;YACD,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,kGAAkG,CAAC,CAAA;YACrH,CAAC;YACD,OAAO,IAAI,GAAG,CAAC,UAAU,EAAmB,CAAA;QAC9C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uGAAuG,CAAC,CAAA;IAC1H,CAAC,CAAC,EAAE,CAAA;IACJ,OAAO,CAAC,CAAC,WAAW,CAAA;AACtB,CAAC;AAED;mCACmC;AACnC,MAAM,UAAU,oBAAoB;IAClC,OAAO,2BAA2B,EAAE,CAAC,WAAW,KAAK,IAAI,CAAA;AAC3D,CAAC","sourcesContent":["/**\n * brepkit-kernel/brepkitWasm — brepkit-wasm 装载(setOcctWasmInitFn 同构的注入点)\n *\n * 装载策略(与 occt-kernel 一致):\n * - 宿主可调用 setBrepkitWasmInitFn(fn) 注入自定义初始化函数\n * (小程序 Worker 传 WXWebAssembly 实例化路径;node 测试走 npm 包默认 init);\n * - 未注入时,node 环境直接 require('brepkit-wasm')(该包胶水零 eval,可直接装载);\n * - 两边都没有 → 抛带上下文的错误(报错好于掩盖,禁止静默回退)。\n */\n\n/** brepkit 内核实例形态(BrepKernel 类,228 个方法;类型面见 npm 包 brepkit_wasm.d.ts)。 */\nexport type BrepKitKernel = any\n\ntype BrepKitInitFn = () => Promise<BrepKitKernel>\n\n// 2026-09-26 跨实例共享(随 0.18.2 发布):customInitFn / initPromise 从模块级\n// 单例提升为挂在 globalThis 上的共享状态(与 occtKernel.ts / runtime-state.ts\n// 同款设计)。原因:CDN 外部化的 faijs 多实例各自持有独立内核 → 句柄不互通\n// (occtKernel.ts 顶部注释详述);小程序 Worker 场景同理。挂到 globalThis 后,\n// 任一实例 initBrepkitWasm() 产出的内核全局可见,句柄互通。\n// 构建期去重(external / dedupe)仍是主手段,这里是兜底。\n\nconst BREPKIT_KERNEL_KEY = '__FAICAD_FAIJS_BREPKIT_KERNEL__'\nconst BREPKIT_KERNEL_STATE_VERSION = 1\n\n/** brepkit 内核共享状态(跨 faijs 模块实例,浏览器/Node/小程序 Worker 多环境)。 */\ninterface BrepkitKernelSharedState {\n stateVersion: number\n customInitFn: BrepKitInitFn | null\n initPromise: Promise<BrepKitKernel> | null\n}\n\n/**\n * 获取 brepkit 内核共享状态(单例)。\n *\n * 挂在 globalThis 上是为了让\"两份 faijs 代码\"(宿主 bundle 一份、第三方库\n * 外部化一份)共享同一份内核状态——否则两份 initPromise 导致内核各自初始化、\n * 句柄不互通(几何孤岛)。\n *\n * @returns the shared brepkit kernel state singleton.\n */\nfunction getBrepkitKernelSharedState(): BrepkitKernelSharedState {\n const g = globalThis as unknown as Record<string, unknown>\n const existing = g[BREPKIT_KERNEL_KEY] as BrepkitKernelSharedState | undefined\n if (existing) {\n if (existing.stateVersion !== BREPKIT_KERNEL_STATE_VERSION) {\n throw new Error(\n `[faijs] brepkit kernel state version mismatch: loaded=${existing.stateVersion}, expected=${BREPKIT_KERNEL_STATE_VERSION}`,\n )\n }\n return existing\n }\n const created: BrepkitKernelSharedState = {\n stateVersion: BREPKIT_KERNEL_STATE_VERSION,\n customInitFn: null,\n initPromise: null,\n }\n g[BREPKIT_KERNEL_KEY] = created\n return created\n}\n\n/**\n * 注入自定义 brepkit wasm 初始化函数(宿主装配期调用一次)。写入共享挂点——\n * 任意 faijs 实例(含 CDN 外部化实例 / 小程序 Worker 副实例)都优先使用。\n * @param fn - the initialization function to use, or null to clear\n */\nexport function setBrepkitWasmInitFn(fn: (() => Promise<BrepKitKernel>) | null): void {\n const s = getBrepkitKernelSharedState()\n s.customInitFn = fn\n // 挂点变化后丢弃进行中的初始化(下一次 init 用新挂点重来)。\n s.initPromise = null\n}\n\n/**\n * 初始化并返回 BrepKernel 单例(幂等:多次调用共享同一次初始化)。\n * @returns Promise 解析为 BrepKernel 实例。\n */\nexport function initBrepkitWasm(): Promise<BrepKitKernel> {\n const s = getBrepkitKernelSharedState()\n if (s.initPromise) return s.initPromise\n s.initPromise = (async (): Promise<BrepKitKernel> => {\n if (s.customInitFn) return await s.customInitFn()\n // node 环境(单测 / CLI):npm 包默认装载路径\n\n if (typeof process !== 'undefined' && process.versions?.node) {\n // Non-literal specifier: brepkit-wasm is an optional runtime injection, not\n // a declared dependency — a literal would make tsc fail with TS2307 when\n // the package is absent. A missing package surfaces at runtime (below).\n const specifier = 'brepkit-wasm'\n const mod = (await import(/* @vite-ignore */ specifier)) as {\n BrepKernel: new () => BrepKitKernel\n }\n if (!mod?.BrepKernel) {\n throw new Error('initBrepkitWasm: brepkit-wasm is not installed; install it or call setBrepkitWasmInitFn() first.')\n }\n return new mod.BrepKernel() as BrepKitKernel\n }\n throw new Error('initBrepkitWasm: no init function set and not in Node environment. Call setBrepkitWasmInitFn() first.')\n })()\n return s.initPromise\n}\n\n/** 是否已初始化完成(测试诊断用)。\n * @returns true 表示 init 已启动/完成。 */\nexport function isBrepkitInitialized(): boolean {\n return getBrepkitKernelSharedState().initPromise !== null\n}\n"]}
|
|
@@ -22,7 +22,9 @@ export interface WasmImportResult {
|
|
|
22
22
|
* Let the browser host inject the OCCT initialization function.
|
|
23
23
|
*
|
|
24
24
|
* The browser host calls this to register its own init logic (dev/prod/CDN/e2e
|
|
25
|
-
* branches); faijs's initOcctWasm() prefers the injected function.
|
|
25
|
+
* branches); faijs's initOcctWasm() prefers the injected function. 注入的挂点
|
|
26
|
+
* 写入共享状态——任意 faijs 实例(含 CDN 外部化实例)调 initOcctWasm() 时
|
|
27
|
+
* 都优先使用同一份宿主初始化函数。
|
|
26
28
|
*
|
|
27
29
|
* When nothing is injected, initOcctWasm() reads the WASM from node_modules in
|
|
28
30
|
* a Node environment.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"occtKernel.d.ts","sourceRoot":"","sources":["../../src/occt-kernel/occtKernel.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAItJ,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,YAAY,CAAA;IACvB,OAAO,EAAE,YAAY,CAAA;IACrB,OAAO,EAAE,WAAW,CAAA;CACrB;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,WAAW,CAAA;IACxB,MAAM,EAAE,mBAAmB,EAAE,CAAA;IAC7B,cAAc,EAAE,IAAI,CAAA;CACrB;
|
|
1
|
+
{"version":3,"file":"occtKernel.d.ts","sourceRoot":"","sources":["../../src/occt-kernel/occtKernel.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAItJ,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,YAAY,CAAA;IACvB,OAAO,EAAE,YAAY,CAAA;IACrB,OAAO,EAAE,WAAW,CAAA;CACrB;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,WAAW,CAAA;IACxB,MAAM,EAAE,mBAAmB,EAAE,CAAA;IAC7B,cAAc,EAAE,IAAI,CAAA;CACrB;AA2DD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAK9E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAQ5C;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,CA2BxD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,UAAU,CAItC;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,kBAAY,CAAA;AAEtC,+DAA+D;AAC/D,wBAAgB,eAAe,IAAI,IAAI,CAOtC;AAED,+DAA+D;AAC/D,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;6EACyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAC1C,MAAM,EAAE;IAAE,cAAc,CAAC,KAAK,EAAE,CAAC,EAAE,gBAAgB,CAAC,EAAE,OAAO,GAAG,WAAW,CAAA;CAAE,EAC7E,KAAK,EAAE,CAAC,EACR,OAAO,GAAE,qBAA0B,GAClC;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAwBzD;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,WAAW,GAAG,UAAU,EAClC,UAAU,CAAC,EAAE,qBAAqB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CAiB3B;AAID,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAA;IACjB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,UAAU,EAAE,OAAO,CAAA;IACnB,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAA;IACpB;2EACuE;IACvE,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B;kDAC8C;IAC9C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,4DAA4D;IAC5D,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IACtC,qDAAqD;IACrD,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC7B;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,WAAW,GAAG,UAAU,GACjC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAwB7B;AAyHD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAKvF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,gBAAgB,EAAE,CAW9E;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,qBAAqB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CAgB3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,YAAY,EACvB,OAAO,EAAE,WAAW,EACpB,SAAS,SAAO,GACf,MAAM,CA2BR;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAGtD;AAED,gBAAgB;AAChB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAA"}
|