@faicad/faijs 0.32.2 → 0.33.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/api-namespace.js +3 -3
- package/dist/api/api-namespace.js.map +1 -1
- package/dist/api/assembly/index.d.ts +1 -0
- package/dist/api/assembly/index.d.ts.map +1 -1
- package/dist/api/assembly/index.js +1 -0
- package/dist/api/assembly/index.js.map +1 -1
- package/dist/api/assembly/lower.d.ts.map +1 -1
- package/dist/api/assembly/lower.js +7 -0
- package/dist/api/assembly/lower.js.map +1 -1
- package/dist/api/assembly/normalize.d.ts.map +1 -1
- package/dist/api/assembly/normalize.js +2 -1
- package/dist/api/assembly/normalize.js.map +1 -1
- package/dist/api/assembly/solve-tree.d.ts +46 -0
- package/dist/api/assembly/solve-tree.d.ts.map +1 -0
- package/dist/api/assembly/solve-tree.js +135 -0
- package/dist/api/assembly/solve-tree.js.map +1 -0
- package/dist/api/assembly/solve.d.ts +7 -0
- package/dist/api/assembly/solve.d.ts.map +1 -1
- package/dist/api/assembly/solve.js.map +1 -1
- package/dist/api/assembly/solvers/assembly-tree.d.ts +4 -0
- package/dist/api/assembly/solvers/assembly-tree.d.ts.map +1 -1
- package/dist/api/assembly/solvers/assembly-tree.js +1 -0
- package/dist/api/assembly/solvers/assembly-tree.js.map +1 -1
- package/dist/api/assembly/solvers/global-solver.d.ts.map +1 -1
- package/dist/api/assembly/solvers/global-solver.js +210 -3
- package/dist/api/assembly/solvers/global-solver.js.map +1 -1
- package/dist/api/assembly/solvers/types.d.ts +8 -0
- package/dist/api/assembly/solvers/types.d.ts.map +1 -1
- package/dist/api/assembly/solvers/types.js.map +1 -1
- package/dist/api/assembly/types.d.ts +32 -1
- package/dist/api/assembly/types.d.ts.map +1 -1
- package/dist/api/assembly/types.js.map +1 -1
- package/dist/api/assembly/validate.d.ts +2 -2
- package/dist/api/assembly/validate.d.ts.map +1 -1
- package/dist/api/assembly/validate.js +24 -2
- package/dist/api/assembly/validate.js.map +1 -1
- package/dist/api/cadquery-selectors/edge.js +1 -1
- package/dist/api/cadquery-selectors/edge.js.map +1 -1
- package/dist/api/cadquery-selectors/entity.d.ts +29 -20
- package/dist/api/cadquery-selectors/entity.d.ts.map +1 -1
- package/dist/api/cadquery-selectors/entity.js +26 -20
- package/dist/api/cadquery-selectors/entity.js.map +1 -1
- package/dist/api/cadquery-selectors/face.d.ts +4 -2
- package/dist/api/cadquery-selectors/face.d.ts.map +1 -1
- package/dist/api/cadquery-selectors/face.js +8 -7
- package/dist/api/cadquery-selectors/face.js.map +1 -1
- package/dist/api/cadquery-selectors/resolve.d.ts +7 -6
- package/dist/api/cadquery-selectors/resolve.d.ts.map +1 -1
- package/dist/api/cadquery-selectors/resolve.js +13 -11
- package/dist/api/cadquery-selectors/resolve.js.map +1 -1
- package/dist/api/chamfer.js +1 -1
- package/dist/api/chamfer.js.map +1 -1
- package/dist/api/draft.js +1 -1
- package/dist/api/draft.js.map +1 -1
- package/dist/api/edge-ref.js +2 -2
- package/dist/api/edge-ref.js.map +1 -1
- package/dist/api/engrave.js +1 -1
- package/dist/api/engrave.js.map +1 -1
- package/dist/api/export-3mf.js +1 -1
- package/dist/api/export-3mf.js.map +1 -1
- package/dist/api/export-brep.js +1 -1
- package/dist/api/export-brep.js.map +1 -1
- package/dist/api/export-step.d.ts +12 -13
- package/dist/api/export-step.d.ts.map +1 -1
- package/dist/api/export-step.js +19 -17
- package/dist/api/export-step.js.map +1 -1
- package/dist/api/extrude.js +3 -3
- package/dist/api/extrude.js.map +1 -1
- package/dist/api/face-ref.js +2 -2
- package/dist/api/face-ref.js.map +1 -1
- package/dist/api/feature-repair.js +2 -2
- package/dist/api/feature-repair.js.map +1 -1
- package/dist/api/fillet-variable.js +1 -1
- package/dist/api/fillet-variable.js.map +1 -1
- package/dist/api/fillet.js +1 -1
- package/dist/api/fillet.js.map +1 -1
- package/dist/api/geom.js +1 -1
- package/dist/api/geom.js.map +1 -1
- package/dist/api/import-step.d.ts.map +1 -1
- package/dist/api/import-step.js +4 -2
- package/dist/api/import-step.js.map +1 -1
- package/dist/api/pattern.js +1 -1
- package/dist/api/pattern.js.map +1 -1
- package/dist/api/place.js +1 -1
- package/dist/api/place.js.map +1 -1
- package/dist/api/punch-hole.js +1 -1
- package/dist/api/punch-hole.js.map +1 -1
- package/dist/api/replicate.js +1 -1
- package/dist/api/replicate.js.map +1 -1
- package/dist/api/revolve.js +1 -1
- package/dist/api/revolve.js.map +1 -1
- package/dist/api/section-by-plane.js +1 -1
- package/dist/api/section-by-plane.js.map +1 -1
- package/dist/api/shell.js +1 -1
- package/dist/api/shell.js.map +1 -1
- package/dist/api/sketch-on-face.js +1 -1
- package/dist/api/sketch-on-face.js.map +1 -1
- package/dist/api/split-by-plane.js +1 -1
- package/dist/api/split-by-plane.js.map +1 -1
- package/dist/api/split.js +1 -1
- package/dist/api/split.js.map +1 -1
- package/dist/api/thicken.js +1 -1
- package/dist/api/thicken.js.map +1 -1
- package/dist/api/topo-resolve.js +4 -4
- package/dist/api/topo-resolve.js.map +1 -1
- package/dist/api/transform.js +1 -1
- package/dist/api/transform.js.map +1 -1
- package/dist/api/view/view-projection.d.ts +8 -0
- package/dist/api/view/view-projection.d.ts.map +1 -1
- package/dist/api/view/view-projection.js +73 -2
- package/dist/api/view/view-projection.js.map +1 -1
- package/dist/boolean/cross-section.d.ts.map +1 -1
- package/dist/boolean/cross-section.js +3 -1
- package/dist/boolean/cross-section.js.map +1 -1
- package/dist/brep/brep-ops.d.ts +26 -0
- package/dist/brep/brep-ops.d.ts.map +1 -1
- package/dist/brep/brep-ops.js +45 -0
- package/dist/brep/brep-ops.js.map +1 -1
- package/dist/brep/brep-topology.js +1 -1
- package/dist/brep/brep-topology.js.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.js +2 -0
- package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
- package/dist/brep/engine/primitives.d.ts +17 -0
- package/dist/brep/engine/primitives.d.ts.map +1 -1
- package/dist/brep/engine/primitives.js.map +1 -1
- package/dist/brep/export/export-model.d.ts.map +1 -1
- package/dist/brep/export/export-model.js +36 -11
- package/dist/brep/export/export-model.js.map +1 -1
- package/dist/brep/export/step-flat.d.ts +35 -0
- package/dist/brep/export/step-flat.d.ts.map +1 -0
- package/dist/brep/export/step-flat.js +94 -0
- package/dist/brep/export/step-flat.js.map +1 -0
- package/dist/brep/export/step.d.ts.map +1 -1
- package/dist/brep/export/step.js +42 -21
- package/dist/brep/export/step.js.map +1 -1
- package/dist/brep/handle-bridge.d.ts +4 -4
- package/dist/brep/handle-bridge.js +4 -4
- package/dist/brep/handle-bridge.js.map +1 -1
- package/dist/brep/svg/svg-to-solid.d.ts +3 -17
- package/dist/brep/svg/svg-to-solid.d.ts.map +1 -1
- package/dist/brep/svg/svg-to-solid.js +16 -317
- package/dist/brep/svg/svg-to-solid.js.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.js +10 -0
- package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.d.ts +1 -1
- package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.js +7 -6
- package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
- package/dist/brepkit-kernel/multi-version-test.d.ts +7 -7
- package/dist/brepkit-kernel/multi-version-test.d.ts.map +1 -1
- package/dist/brepkit-kernel/multi-version-test.js +10 -10
- package/dist/brepkit-kernel/multi-version-test.js.map +1 -1
- package/dist/cad-runtime/direct-executor.js +2 -2
- package/dist/cad-runtime/direct-executor.js.map +1 -1
- package/dist/cad-runtime/runtime.js +5 -5
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/geometry2d/curve2d.js +42 -1
- package/dist/geometry2d/curve2d.js.map +1 -1
- package/dist/math3d/Box3.js.map +1 -1
- package/dist/math3d/Euler.js.map +1 -1
- package/dist/math3d/Mat4.js.map +1 -1
- package/dist/math3d/Plane.js.map +1 -1
- package/dist/math3d/Quat.js.map +1 -1
- package/dist/math3d/Vec2.js.map +1 -1
- package/dist/math3d/Vec3.js.map +1 -1
- package/dist/math3d/index.js.map +1 -1
- package/dist/mesh/meshdata/contour.d.ts +34 -0
- package/dist/mesh/meshdata/contour.d.ts.map +1 -0
- package/dist/mesh/meshdata/contour.js +39 -0
- package/dist/mesh/meshdata/contour.js.map +1 -0
- package/dist/mesh/meshdata/extrude.d.ts +25 -0
- package/dist/mesh/meshdata/extrude.d.ts.map +1 -0
- package/dist/mesh/meshdata/extrude.js +198 -0
- package/dist/mesh/meshdata/extrude.js.map +1 -0
- package/dist/mesh/meshdata/index.js.map +1 -1
- package/dist/mesh/meshdata/ops.js.map +1 -1
- package/dist/mesh/meshdata/parametric.js.map +1 -1
- package/dist/mesh/meshdata/weld.js.map +1 -1
- package/dist/node-host/cli.d.ts.map +1 -1
- package/dist/node-host/cli.js +3 -2
- package/dist/node-host/cli.js.map +1 -1
- package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
- package/dist/occt-kernel/occt-primitives.js +2 -0
- package/dist/occt-kernel/occt-primitives.js.map +1 -1
- package/dist/primitives/svg/svg-path.d.ts +192 -0
- package/dist/primitives/svg/svg-path.d.ts.map +1 -0
- package/dist/primitives/svg/svg-path.js +776 -0
- package/dist/primitives/svg/svg-path.js.map +1 -0
- package/dist/third-party/earcut.d.ts +19 -0
- package/dist/third-party/earcut.d.ts.map +1 -0
- package/dist/third-party/earcut.js +575 -0
- package/dist/third-party/earcut.js.map +1 -0
- package/package.json +22 -3
package/dist/api/extrude.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extrude.js","sourceRoot":"","sources":["../../src/api/extrude.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api extrude — `cad.extrude`(平台 parity op,BREP-only)\n *\n * 归属(分层红线):`cad.extrude` 是「面 → 棱柱」的**平台** op,FCStd Pad/Pocket\n * 链路与 TS 面共用它(原 `cad.fai_extrude` 路线废弃)。up-to(拉伸到面 / 到支持体端面)属\n * CadQuery `until=` 同族语义,因此落在**本 op**;`fai_extrude`(`fai_` 前缀的\n * faijs 扩展 op,与 fai_drill / fai_split 同族)不得承载它。\n *\n * 为什么是手写 op 而不是继续用生成投影:生成投影是一条 1:1 转发通道\n * (`defineOp({ brep: __own_* })` 直连 api/brep-operations/ 的源函数),有两个硬约束——\n * ① 参数表只有位置形参;D11 归一化只在「单 plain-object 形态」下按 params 表\n * 映射(api/internal/dual-form-args.ts),`(face, { upTo })` 属位置形态 →\n * 原样喂给 compat extrude → 报错,无法表达对象形态;\n * ② 生成投影没有 faijs 侧入参解析挂点,只把实参原样转发给源函数 → 依赖 faceRef 解析 /\n * 内核直调(extrudeUpToSolid)的 up-to 实现无法在生成投影里承载,落回本手写模块。\n * 先例:arg-spec 的 `fillet` 条目(faijs 侧由手写 dual-op 覆盖,生成模块符号为\n * 孤儿 by design)。\n *\n * 长度形态**委托给生成投影**(`projectedExtrude`):compat 投影仍是唯一拉伸引擎,\n * 既有 `cad.extrude(face, [x,y,z])` 语义零漂移。\n */\n\nimport { extrude as projectedExtrude } from './generated/operations'\nimport { Vec3 as Vec3C, Mat4 } from '../math3d'\nimport { solidToShape, matrixToArray } from '../brep/brep-ops'\nimport { getSolidBoundingBox } from '../brep/brep-utils'\nimport { getCurrentStmt, getBackends, MeshUnsupportedError } from '../runtime-state'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { fromBrep, brepOf, isCurveShape } from '../shape'\nimport { runtimeLineage } from '../topology/naming/lineage'\nimport { formatRoleName, semantic, wall } from '../topology/naming/role-name'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { defineOp } from '../sdk'\nimport { assertPositiveNumber } from './assert'\nimport { meshFaceEntry, meshKernelFailure, meshSolidProductWithBackend } from './internal/mesh-solid-op'\nimport type { Shape, Vec3 } from '../mesh/types'\nimport type { BrepHandle } from '../brep/engine/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport type { FaceTopoRef } from '../topology/naming'\nimport { TopoRefError } from '../topology/naming'\n\n/**\n\n * extrude 的 construct 词汇表(计划 §4.4):`cap:bottom` / `cap:top` / `wall:<i>`。\n *\n * 判定口径:\n * - 拉伸方向**优先由 op 给出**(`hintAxis`),但必须由现场几何裁定:只有当至少\n * 两张面的法向与该方向 |cos| ≈ 1 时才采信,否则回退到纯几何判定(A2,见下);\n * - 面法向与拉伸轴 |cos| ≈ 1 → 端面:中心沿轴分量小者 `cap:bottom`、大者 `cap:top`;\n * - 面法向与拉伸轴 |cos| ≈ 0 → 侧面 `wall:<i>`,i = 该面在侧面枚举中的相对序\n * (OCCT prism 的侧面顺序 = profile wire 的边序——makeWire 按构造顺序收边,\n * prism 不重排;G3-L1 改参重放依赖该稳定性);\n * - 侧面含**非平面**(profile 里的弧段扫出圆柱面)同样进表:圆柱面 uv 中点法向\n * 是径向,与拉伸轴垂直,判定与平面侧面同式。\n *\n * @param kernel - the OCCT kernel.\n * @param solid - the extruded solid.\n * @param hintAxis - 拉伸方向(op 已知;仅作候选,由现场几何确认)。\n * @returns role(线格式串)→ hash 子表。\n */\nfunction extrudeConstructRoles(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n hintAxis?: readonly [number, number, number],\n): Map<string, number[]> {\n const roles = new Map<string, number[]>()\n const faceHandles = kernel.getSubShapes(solid, 'face')\n try {\n const hashes = kernel.subShapeHashes(solid, 'face', 2147483647)\n // A2 (2026-09-26, Beds.FCStd): 侧面可能是**圆柱面**——profile 含弧段时,该弧\n // 沿拉伸方向扫出的就是一个圆柱侧面。旧实现只在 `surfaceType === 'plane'` 时\n // 取法向,于是圆柱侧面 normals[i] === undefined:既拿不到 `wall:<i>`,还让\n // `wallIdx` 跳过它们 —— wall 序号因此不再是 profile 边序(违反 role-name.ts\n // 的契约「wall:3 = 由 profile 第 3 条边扫出」)。实测 Beds part28(轮廓含 4\n // 段弧)10 面只覆盖 6 个(缺序号 2/4/6/8),下游 fillet 的 `cad.edgeRef`\n // 遂抛 `edgeRef: adjacent face ordinal 2 has no role lineage`。\n // 圆柱面 uv 中点的法向是径向、与拉伸轴垂直(|cos| ≈ 0),可直接用于侧面判定。\n const planar = faceHandles.map((f) => kernel.surfaceType(f) === 'plane')\n const normals: (readonly [number, number, number])[] = faceHandles.map((f) => {\n const uv = kernel.uvBounds(f)\n const n = kernel.surfaceNormal(f, (uv.uMin + uv.uMax) / 2, (uv.vMin + uv.vMax) / 2)\n return [n.x, n.y, n.z] as const\n })\n const centers = faceHandles.map((f) => {\n const c = kernel.surfaceCenterOfMass(f)\n return [c.x, c.y, c.z] as const\n })\n\n // 拉伸轴:op 已知的拉伸方向优先(须由现场几何确认),否则找一对\n // |cos| ≈ 1 的反平行平面法向 → 带符号单位方向。\n //\n // A2 (2026-09-26, Beds.FCStd part28): 纯几何判定取「第一对反平行的平面法向」,\n // 但方形类轮廓的**一对对侧平面侧壁同样反平行**——Beds 的柱子于是把 X 向侧壁\n // 判成端盖、把真正的 Z 向端盖当成 wall,4 个圆柱侧面彻底无名(10 面只覆盖 6,\n // 缺序号 2/4/6/8),下游 fillet 的 `cad.edgeRef` 抛\n // `edgeRef: adjacent face ordinal 2 has no role lineage`。方向由 op 给出、\n // 由几何裁定(至少两张面法向与该方向 |cos| ≈ 1 才采信),两者缺一不可。\n let axis: readonly [number, number, number] | undefined\n const hintLen = hintAxis ? Math.hypot(hintAxis[0], hintAxis[1], hintAxis[2]) : 0\n if (hintAxis && hintLen > 1e-9) {\n const d: readonly [number, number, number] = [\n hintAxis[0] / hintLen, hintAxis[1] / hintLen, hintAxis[2] / hintLen,\n ]\n const aligned = normals.filter((n) => {\n const len = Math.hypot(n[0], n[1], n[2])\n if (len < 1e-9) return false\n return Math.abs((n[0] * d[0] + n[1] * d[1] + n[2] * d[2]) / len) > 0.999\n })\n if (aligned.length >= 2) axis = d\n }\n for (let i = 0; i < normals.length && !axis; i++) {\n // 端面必须是一对反平行的**平面**法向(棱柱的端盖恒为平面)。\n if (!planar[i]) continue\n const a = normals[i]\n if (!a) continue\n for (let j = i + 1; j < normals.length; j++) {\n if (!planar[j]) continue\n const b = normals[j]\n if (!b) continue\n const lenA = Math.hypot(a[0], a[1], a[2])\n const lenB = Math.hypot(b[0], b[1], b[2])\n if (lenA < 1e-9 || lenB < 1e-9) continue\n const cos = (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]) / (lenA * lenB)\n if (Math.abs(cos) > 0.999) {\n // b 反向即「从 i 面指向 j 面」的方向\n axis = [b[0] - a[0], b[1] - a[1], b[2] - a[2]] as const\n break\n }\n }\n }\n const axisLen = axis ? Math.hypot(axis[0], axis[1], axis[2]) : 0\n if (axis && axisLen > 1e-9) {\n const ax: readonly [number, number, number] = [axis[0] / axisLen, axis[1] / axisLen, axis[2] / axisLen]\n // 端面:沿轴投影最小者 = cap:bottom,最大者 = cap:top\n const capCandidates: { idx: number; t: number }[] = []\n for (let i = 0; i < normals.length; i++) {\n if (!planar[i]) continue\n const n = normals[i]\n if (!n) continue\n const len = Math.hypot(n[0], n[1], n[2]) || 1\n const cos = Math.abs(n[0] * ax[0] + n[1] * ax[1] + n[2] * ax[2]) / len\n if (cos > 0.999) {\n capCandidates.push({ idx: i, t: centers[i]![0] * ax[0] + centers[i]![1] * ax[1] + centers[i]![2] * ax[2] })\n }\n }\n if (capCandidates.length >= 2) {\n capCandidates.sort((p, q) => p.t - q.t)\n const bottom = capCandidates[0]!\n const top = capCandidates[capCandidates.length - 1]!\n // 端面词汇用 semantic('bottom'/'top'——与 box 同形)。计划 §4.4 写的\n // `cap:<name>` 前缀形态与 RoleName 契约冲突(semantic 名不允许 ':',\n // role-name.ts SEMANTIC_NAME_RE),落地以契约为准:semantic 直名。\n if (hashes[bottom.idx] !== undefined) roles.set(formatRoleName(semantic('bottom')), [hashes[bottom.idx]!])\n if (hashes[top.idx] !== undefined) roles.set(formatRoleName(semantic('top')), [hashes[top.idx]!])\n }\n // 侧面:|cos| ≈ 0,按枚举序编号(= profile 边序)。平面/圆柱侧面一律进表\n // (A2)——跳过圆柱侧面会让 wall 序号脱离 profile 边序。\n let wallIdx = 0\n for (let i = 0; i < normals.length; i++) {\n const n = normals[i]\n if (!n || hashes[i] === undefined) continue\n const len = Math.hypot(n[0], n[1], n[2]) || 1\n const cos = Math.abs(n[0] * ax[0] + n[1] * ax[1] + n[2] * ax[2]) / len\n if (cos < 0.001) {\n roles.set(formatRoleName(wall(wallIdx)), [hashes[i]!])\n wallIdx++\n }\n }\n }\n return roles\n } finally {\n for (const h of faceHandles) {\n try { kernel.release(h) } catch { /* 已释放 */ }\n }\n }\n}\n\n/** 显式平面目标(up-to 截断面):点 + 法向(点在平面上即可,无需共面于面边界)。 */\nexport interface UpToPlaneSpec {\n /** 平面上一点(世界坐标)。type:[x,y,z] */\n point: Vec3\n /** 平面法向(世界坐标,方向仅定半空间语义,截断取两侧之一)。type:[x,y,z] */\n normal: Vec3\n}\n\n/** up-to 目标:显式面引用 / 显式平面 / 支持体沿拉伸方向的远端(last)/近端(first)端面。 */\nexport type ExtrudeUpTo = FaceTopoRef | 'last' | 'first' | { plane: UpToPlaneSpec }\n\n/** `cad.extrude` 的对象形态参数(位置形态由 {@link normalizeExtrudeOptions} 归一到这里)。 */\nexport interface ExtrudeOptions {\n /** 拉伸量(mm,>0)。up-to 模式下无需给。 */\n length?: number\n /** 拉伸方向(世界坐标);缺省 [0,0,1]。 */\n normal?: Vec3\n /** 沿 normal 的前进方向;缺省 'forward'('backward' 等价于方向取反)。 */\n mode?: 'forward' | 'backward'\n /** 拉伸到面 / 到支持体端面;提供时忽略 length。 */\n upTo?: ExtrudeUpTo\n /** upTo 'last'/'first' 的支持体(累积支持体,由转换器显式传入)。 */\n baseFeature?: Shape\n /** 截断面沿其法向的偏移(mm);缺省 0。 */\n offset?: number\n}\n\n/** 判定是否为朴素对象(对象形态判别器,避免误吞 Shape / 数组)。 */\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v) && Object.getPrototypeOf(v) === Object.prototype\n}\n\n/**\n * 归一化 `cad.extrude` 的两种调用形态。\n *\n * - 位置形态(与生成投影同款,历史产物在用):`cad.extrude(face, 10)` /\n * `cad.extrude(face, [x,y,z])`——向量即「方向 × 长度」,恒为沿该方向前进。\n * - 对象形态(faijs 面):`cad.extrude(face, { length, normal, mode, upTo, ... })`。\n *\n * @param params - 调用点第二实参(数字 / 向量 / 对象)。\n * @returns 归一化后的对象形态参数。\n * @throws Error 参数既非数字 / 向量 / 朴素对象时(不猜)。\n */\nfunction normalizeExtrudeOptions(params: unknown): ExtrudeOptions {\n if (isPlainObject(params)) return params as ExtrudeOptions\n if (Array.isArray(params)) {\n const v = params as Vec3\n const len = Math.hypot(v[0] ?? 0, v[1] ?? 0, v[2] ?? 0)\n if (!Number.isFinite(len) || len < 1e-12) {\n throw new Error('E_EXTRUDE_ZERO_VECTOR: extrude direction vector has zero length')\n }\n return { length: len, normal: [v[0] / len, v[1] / len, v[2] / len], mode: 'forward' }\n }\n if (typeof params === 'number') return { length: params, normal: [0, 0, 1], mode: 'forward' }\n throw new Error('E_EXTRUDE_BAD_PARAMS: extrude expects (face, number | [x,y,z] | { length | upTo, ... })')\n}\n\n/**\n * 参数自校验:up-to 模式下无需 length;否则 length 必须为正数。\n *\n * @param o - 归一化后的参数。\n */\nfunction assertExtrudeOptions(o: ExtrudeOptions): void {\n if (o.upTo !== undefined) return // up-to 模式:长度由目标面决定\n assertPositiveNumber(o.length, 'extrude.length')\n}\n\n/** bbox 对角线长度(长试探的余量基数)。 */\nfunction bboxDiag(bbox: { min: Vec3; max: Vec3 }): number {\n return Math.hypot(bbox.max[0] - bbox.min[0], bbox.max[1] - bbox.min[1], bbox.max[2] - bbox.min[2])\n}\n\n/**\n * 目标面法向负侧的半空间覆盖盒(截断长拉伸用)——定向版。\n *\n * GOTCHA(PadTest Pad001 斜置基准面实测):轴对齐盒的边界不是斜面本身,\n * 截断呈台阶而非精确斜平面(体积 7076 vs 真值 4860)。正确做法:在局部基\n * (u, v, n) 里构造盒(深度沿 −n 伸出 R、横向 ±R),再用 kernel.transform\n * 旋到世界系——盒的 n=R 端面就是精确的目标平面。\n *\n * @param kernel - BREP 内核。\n * @param faceCenter - 目标面中心(世界坐标,盒的 n=0 端面过此点)。\n * @param faceNormal - 目标面法向(半空间保留 −n 侧…即盒占据 −n 侧深度)。\n * @param reach - 覆盖半径 R。\n * @returns 定向半空间盒的 brep 句柄。\n */\nfunction farSideBox(kernel: BrepEngineApi, faceCenter: Vec3, faceNormal: Vec3, reach: number): BrepHandle {\n const unit = new Vec3C(...faceNormal).normalize()\n const center = new Vec3C(...faceCenter)\n // 与 n 正交的正交基 u,v\n const aux = Math.abs(unit.y) < 0.9 ? new Vec3C(0, 1, 0) : new Vec3C(1, 0, 0)\n const u = new Vec3C().crossVectors(unit, aux).normalize()\n const v = new Vec3C().crossVectors(unit, u).normalize()\n const R = reach\n // 局部系盒:x∈[−R,R] (u), y∈[−R,R] (v), z∈[−R,0] (n 深度侧)\n const box = kernel.makeBoxFromCorners(\n { x: -R, y: -R, z: -R },\n { x: R, y: R, z: 0 },\n )\n // 旋转矩阵:列 = u, v, n;平移 = center(局部 z=0 端面落到过 center 的目标平面)\n const m = new Mat4().makeBasis(u, v, unit).setPosition(center)\n return kernel.transform(box, matrixToArray(m))\n}\n\n/**\n * up-to 拉伸:occt-wasm 未暴露 `BRepFeat_MakePrism`,用「长拉伸 → 与目标面侧\n * 半空间盒求交」等价组合;长试探上限只作布尔构造辅助,不进入结果几何。\n *\n * @param kernel - BREP 内核。\n * @param inputSolid - 轮廓实体句柄。\n * @param o - 归一化参数(需带 upTo)。\n * @returns 截断后的实体句柄。\n * @throws Error E_UP_TO_* 系列:缺支持体 / 方向与目标面平行 / 不相交(禁静默)。\n */\nfunction extrudeUpToSolid(kernel: BrepEngineApi, inputSolid: BrepHandle, o: ExtrudeOptions): BrepHandle {\n const normal = new Vec3C(...(o.normal ?? [0, 0, 1])).normalize()\n const offset = o.offset ?? 0\n const upTo = o.upTo as ExtrudeUpTo\n\n // 1) 方向目标:FaceTopoRef → 现场面几何;'last'/'first' → baseFeature 支持体\n // 沿拉伸方向的端面(远端 last / 近端 first)。\n let targetCenter: Vec3\n let targetNormal: Vec3\n if (typeof upTo === 'string') {\n const base = o.baseFeature\n const baseSolid = base ? (brepOf(base) as BrepHandle | undefined) : undefined\n if (!baseSolid) {\n throw new Error('E_UP_TO_NO_BASE: upTo \"last\"/\"first\" requires a baseFeature shape')\n }\n // 支持体 bbox 沿拉伸方向的远端/近端平面(R-C:baseFeature 显式传参)\n const bbox = getSolidBoundingBox(kernel, baseSolid)\n const pick = (which: 'max' | 'min'): Vec3 => {\n const c: Vec3 = [\n (bbox.min[0] + bbox.max[0]) / 2,\n (bbox.min[1] + bbox.max[1]) / 2,\n (bbox.min[2] + bbox.max[2]) / 2,\n ]\n const extent = which === 'max' ? 1 : -1\n const proj =\n (bbox.max[0] - bbox.min[0]) * Math.abs(normal.x) +\n (bbox.max[1] - bbox.min[1]) * Math.abs(normal.y) +\n (bbox.max[2] - bbox.min[2]) * Math.abs(normal.z)\n return [\n c[0] + ((normal.x * proj) / 2) * extent,\n c[1] + ((normal.y * proj) / 2) * extent,\n c[2] + ((normal.z * proj) / 2) * extent,\n ]\n }\n targetCenter = pick(upTo === 'last' ? 'max' : 'min')\n targetNormal = [normal.x, normal.y, normal.z]\n } else if (upTo && typeof upTo === 'object' && 'plane' in upTo) {\n // 显式平面目标(datum plane 等无限平面:截断面由平面方程决定,不受\n // 目标面边界限制——斜置基准面时顶面是斜的,定长路径语义错误)。\n targetCenter = [...upTo.plane.point] as Vec3\n targetNormal = [...upTo.plane.normal] as Vec3\n } else {\n // GOTCHA(探针实测):FaceTopoRef 携带的 hint 是 faceRef 现场捕获的\n // center/normal 快照,直接使用;不要对拉伸轮廓(sketch 面)做二次\n // resolveFaceGeometry——引用的面在目标体上、不在轮廓上,会 E_TOPO_NOT_FOUND。\n if (upTo.hint.center && upTo.hint.normal) {\n targetCenter = [...upTo.hint.center] as Vec3\n targetNormal = [...upTo.hint.normal] as Vec3\n } else {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', 'extrude upTo: face ref hint has no center/normal snapshot')\n }\n }\n\n // 2) 长试探长度:GOTCHA(探针实测)——不能按轮廓自身 bbox 对角线算(小轮廓够不到\n // 远处目标面);必须取「截断平面沿拉伸方向的投影距离」加余量,保证长拉伸至\n // 少穿过目标面。\n const bbox = getSolidBoundingBox(kernel, inputSolid)\n const shiftedCenter0: Vec3 = [\n targetCenter[0] + targetNormal[0] * offset,\n targetCenter[1] + targetNormal[1] * offset,\n targetCenter[2] + targetNormal[2] * offset,\n ]\n // 自动定向(仅 { plane } 目标):FreeCAD UpToFace 朝目标面所在方向拉伸。\n // GOTCHA(PadTest Pad001 实测,probe 探针):斜置基准面在草图局部坐标里\n // 位于轮廓的反方向(圆心处平面交点 t=−26 而非 +26),固定沿 +Z 拉截不到\n // 平面(体积 597 ≠ 真值 4860)。轮廓 bbox 中心到截断平面的有向投影与\n // 拉伸方向异号 → 翻转拉伸方向(就地翻转 Vector3,后续 tMax/keepSide 自洽)。\n if (upTo && typeof upTo === 'object' && 'plane' in upTo) {\n const c0: Vec3 = [\n (bbox.min[0] + bbox.max[0]) / 2,\n (bbox.min[1] + bbox.max[1]) / 2,\n (bbox.min[2] + bbox.max[2]) / 2,\n ]\n const tnAuto = new Vec3C(...targetNormal).normalize()\n const dAuto =\n (c0[0] - shiftedCenter0[0]) * tnAuto.x +\n (c0[1] - shiftedCenter0[1]) * tnAuto.y +\n (c0[2] - shiftedCenter0[2]) * tnAuto.z\n // 沿拉伸方向到平面的有向交点参数:t = −((c0−plane)·n) / (dir·n)。\n // t<0 → 平面在行进反方向 → 翻转(FreeCAD UpToFace 朝平面拉伸)。\n const tAuto = -dAuto / normal.dot(tnAuto)\n if (tAuto < 0) {\n normal.multiplyScalar(-1)\n }\n }\n const cornerProjections = [\n [bbox.min[0], bbox.min[1], bbox.min[2]],\n [bbox.max[0], bbox.min[1], bbox.min[2]],\n [bbox.min[0], bbox.max[1], bbox.min[2]],\n [bbox.min[0], bbox.min[1], bbox.max[2]],\n [bbox.max[0], bbox.max[1], bbox.min[2]],\n [bbox.max[0], bbox.min[1], bbox.max[2]],\n [bbox.min[0], bbox.max[1], bbox.max[2]],\n [bbox.max[0], bbox.max[1], bbox.max[2]],\n ] as Vec3[]\n const planePoint0 = new Vec3C(...shiftedCenter0)\n const tn0 = new Vec3C(...targetNormal).normalize()\n const planeD = planePoint0.dot(tn0)\n const dirD = normal.dot(tn0)\n if (Math.abs(dirD) < 1e-9) {\n throw new Error('E_UP_TO_PARALLEL: extrude direction is parallel to the target face plane')\n }\n const tMax = cornerProjections\n .map((p) => (planeD - new Vec3C(...p).dot(tn0)) / dirD)\n .reduce((a, b) => Math.max(a, b), 0)\n const L = tMax + Math.abs(offset) + bboxDiag(bbox) * 0.1 + 1\n const longSolid = kernel.extrude(inputSolid, normal.x * L, normal.y * L, normal.z * L)\n\n // 3) 截断平面 = 目标面 + offset(沿面法向)。GOTCHA(探针实测):半空间侧不能固定\n // 取「法向负侧」——目标面法向朝向与拉伸方向无必然关系。正确语义:保留「包含\n // 拉伸起点」的那一侧。farSideBox 覆盖「传入法向的反侧」,因此传 -keepSide。\n const tn = tn0\n const startCenter = new Vec3C(\n (bbox.min[0] + bbox.max[0]) / 2,\n (bbox.min[1] + bbox.max[1]) / 2,\n (bbox.min[2] + bbox.max[2]) / 2,\n )\n const planePoint = new Vec3C(...shiftedCenter0)\n const d = startCenter.sub(planePoint).dot(tn)\n // 保留侧法向:起点所在侧(d 与 tn 同号 → 正侧;异号 → 负侧);d≈0 时退化为\n // 拉伸方向(起点在面上时按拉伸方向截)\n const keepSide = Math.abs(d) < 1e-9 ? normal.clone() : tn.clone().multiplyScalar(Math.sign(d))\n // GOTCHA(PadTest Pad001 斜置基准面实测):targetCenter 可以是平面上离轮廓\n // 很远的任意一点(基准面 point 在草图局部坐标里横向偏 ~100),reach 若只取\n // L(按轮廓到截断面的投影距离)则半空间盒横向盖不住长拉伸体 → common 为空。\n // reach 必须 ≥ 平面点到拉伸体的距离 + 体对角线(全方向覆盖)。\n const reach =\n new Vec3C(...shiftedCenter0).distanceTo(\n new Vec3C((bbox.min[0] + bbox.max[0]) / 2, (bbox.min[1] + bbox.max[1]) / 2, (bbox.min[2] + bbox.max[2]) / 2),\n ) + bboxDiag(bbox) + Math.abs(offset) + 1\n const halfspace = farSideBox(kernel, shiftedCenter0, [-keepSide.x, -keepSide.y, -keepSide.z], reach)\n\n // 4) 求交:长拉伸 ∩ 半空间盒\n const clipped = kernel.common(longSolid, halfspace)\n kernel.release(longSolid)\n kernel.release(halfspace)\n\n // 预检:方向上不相交 → 显式报错(禁静默)\n const clippedBBox = getSolidBoundingBox(kernel, clipped)\n if (!Number.isFinite(bboxDiag(clippedBBox)) || bboxDiag(clippedBBox) < 1e-9) {\n kernel.release(clipped)\n throw new Error('E_UP_TO_NO_INTERSECTION: extrude direction does not reach the target face')\n }\n return clipped\n}\n\n/**\n * `cad.extrude` 的**网格链**实现(方案 2026-10-01 §4 Phase 3-2)。\n *\n * 输入是一张**网格链面**(`cad.sketchOnFace` 在近似拓扑面上铺出来的那种),\n * 输出是一个**新的网格零件**——与输入网格实体同链。\n *\n * 只支持\"面 + 方向 + 距离\"这一支:`upTo` 需要精度链上的求交/裁切(`extrudeUpToSolid`\n * 走 BREP 内核),近似链没有对应能力,故如实拒绝而不是静默退化成普通拉伸——\n * \"拉伸到那张面\"和\"拉伸这么长\"是两件不同的事,悄悄替换会让用户拿到一个错的实体。\n *\n * 方向语义与 BREP 侧**完全一致**(同一份 `normalizeExtrudeOptions`):位置形态\n * `cad.extrude(face, 5)` 沿 +Z,`cad.extrude(face, [x,y,z])` 沿该向量;\n * 缺省法向 `[0,0,1]` 不自动改用面法向——那是两条链共同的行为约定,不在这里分叉。\n *\n * @param input - the mesh-chain face to extrude.\n * @param params - the same positional/object forms the BREP branch accepts.\n * @returns the new mesh solid (a new mesh part).\n * @throws {MeshUnsupportedError} on the mesh path when `upTo` is requested.\n */\nfunction extrudeMeshChain(input: Shape, params: unknown): Shape {\n if (!input) throw new Error('[api/extrude] no input geometry')\n if (isCurveShape(input)) {\n throw new Error(\n 'E_EXTRUDE_NEEDS_FACE: extrude requires a 2D face input, got a 1D curve (kind=\"curve\")',\n )\n }\n const entry = meshFaceEntry(input, 'extrude')\n\n const o = normalizeExtrudeOptions(params)\n assertExtrudeOptions(o)\n if (o.upTo !== undefined) {\n throw new MeshUnsupportedError(\n 'E_MESH_SOLID_UNSUPPORTED: extrude upTo is not available on the mesh path — it needs the precision ' +\n 'chain to intersect and trim against a target face. Give an explicit length instead',\n getCurrentStmt(),\n )\n }\n\n const normal = new Vec3C(...(o.normal ?? [0, 0, 1])).normalize()\n const sign = o.mode === 'backward' ? -1 : 1\n const v: Vec3 = [normal.x * o.length! * sign, normal.y * o.length! * sign, normal.z * o.length! * sign]\n\n let solid: BrepHandle\n try {\n solid = entry.kernel.extrude(entry.face, v[0]!, v[1]!, v[2]!)\n } catch (cause) {\n throw meshKernelFailure(\n 'extrude',\n 'E_EXTRUDE_FAILED',\n `extruding a mesh-chain face by ${o.length} along [${v.join(', ')}]`,\n cause,\n )\n }\n return meshSolidProductWithBackend(entry.backend, solid)\n}\n\n/**\n * 沿 normal 拉伸几何(面 → 棱柱)。\n *\n * up-to 模式(`upTo`)与长度模式(`length`)二选一;长度模式委托生成投影\n * (brepjs extrude 为唯一引擎),up-to 模式走半空间组合。\n *\n * **网格链**(`meshEngines: ['brepkit']`,方案 2026-10-01 §4 Phase 3):输入是\n * `cad.sketchOnFace` 在网格实体识别面上铺出的网格链面时,本 op 沿同一份方向语义\n * 拉伸出**一个新的网格零件**。网格链上不支持 `upTo`\n * (需精度链求交裁切)——会以 `E_MESH_SOLID_UNSUPPORTED` 明确拒绝,不静默当定长拉伸。\n *\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name extrude\n * @returns Shape 拉伸后的几何。\n * @param input - 目标几何(平面面)。type:Shape required:true\n * @param params.length - 总拉伸量(mm,>0)。up-to 模式下无需给。type:number\n * @param params.normal - 拉伸方向(世界坐标)。type:[x,y,z] 默认 [0,0,1]\n * @param params.mode - 沿 normal 的前进方向:forward 正向 / backward 反向。type:'forward' | 'backward' 默认 'forward'\n * @param params.upTo - 拉伸到面:FaceTopoRef 指定面 / 'last' 支持体远端面 / 'first' 近端面(需 baseFeature)。提供时忽略 length。type:'last' | 'first' | FaceTopoRef\n * @param params.baseFeature - upTo 'last'/'first' 的支持体几何(累积支持体)。type:Shape\n * @param params.offset - 截断面沿其法向的偏移(mm)。type:number 默认 0\n * @example\n * const p = await cad.extrude(part0, [0, 0, 10])\n * const p = await cad.extrude(part0, { length: 10 })\n * const p = await cad.extrude(sk, { upTo: cad.faceRef(part0, 3) })\n * const p = await cad.extrude(sk, { upTo: 'last', baseFeature: part0 })\n */\nexport const extrude = defineOp({\n name: 'extrude',\n meshEngines: ['brepkit'],\n mesh(input: Shape, params: unknown): Shape {\n return extrudeMeshChain(input, params)\n },\n brep: async (input: Shape, params: unknown): Promise<Shape> => {\n if (!input) throw new Error('[api/extrude] no input geometry')\n // Phase 3 执行前预检:1D 曲线(wire / helix / sketch as:'wire')不是面,不得落进\n // 内核深层才报「操作失败」——维度不符在调用内核前明确拒绝(1D 判别位 kind='curve')。\n if (isCurveShape(input)) {\n throw new Error(\n 'E_EXTRUDE_NEEDS_FACE: extrude requires a 2D face input, got a 1D curve (kind=\"curve\")',\n )\n }\n const o = normalizeExtrudeOptions(params)\n assertExtrudeOptions(o)\n // A2: 拉伸方向同时是链根建表的候选轴(extrudeConstructRoles 的 hintAxis),\n // 两条路径(定长 / up-to)都要用,故提到分支之前。\n const normal = new Vec3C(...(o.normal ?? [0, 0, 1])).normalize()\n\n if (o.upTo !== undefined) {\n const kernel = getBrepApi()\n const inputSolid = brepOf(input) as BrepHandle | undefined\n if (!inputSolid) throw new Error('[api/extrude] input is not BREP')\n const clipped = extrudeUpToSolid(kernel, inputSolid, o)\n // E3-b(2026-09-23,同 revolve 修法):不能对投影产物再走一次 fromBrep——\n // 同语句 registeredStmtId 去重会吞掉第二次登记(part 键保持空表,下游\n // fillet/chamfer 的 edgeRef 报 nameless shape)。upTo 路径不经过投影/\n // adoptOut,fromBrep 只在此走一次,roleTable 直挂 + solid 句柄登记。\n const origin = String(getCurrentStmt()?.id ?? '')\n return fromBrep(solidToShape(kernel, clipped), {\n solid: clipped,\n roleTable: new Map([[origin, extrudeConstructRoles(kernel, clipped, normal.toArray() as Vec3)]]),\n })\n }\n\n // 长度形态:委托生成投影(生成投影自带 Result 翻转 / adopt 收养)\n const sign = o.mode === 'backward' ? -1 : 1\n const v: Vec3 = [normal.x * o.length! * sign, normal.y * o.length! * sign, normal.z * o.length! * sign]\n let result: Shape\n // GOTCHA:projectedExtrude 是 occt-gated 的生成投影 op,\n // 在 brepkit 引擎下执行前即抛 E_BREP_UNSUPPORTED。brepkit 有原生 L1 extrude\n // (face→solid),直接走 kernel.extrude——与 revolve.ts 同路径(不经生成投影)。\n // occt 路径保持 projectedExtrude 不变,不回退既有几何/命名行为。\n if (getBackends().config.brepEngineId === 'brepkit') {\n const kernel = getBrepApi()\n const faceHandle = brepOf(input) as BrepHandle | undefined\n if (!faceHandle) throw new Error('[api/extrude] brepkit path: input is not BREP')\n const solid = kernel.extrude(faceHandle, v[0]!, v[1]!, v[2]!)\n result = fromBrep(solidToShape(kernel, solid), { solid })\n } else {\n result = (await projectedExtrude(input, v)) as Shape\n }\n // E3 后续:委托路径同样要建链根表(投影只给几何,命名是 faijs 语义)。\n // E3-b(2026-09-23,同 revolve 修法):不能对投影产物再走一次 fromBrep——\n // 同语句 registeredStmtId 去重会吞掉第二次登记(part 键保持空表,下游\n // fillet/chamfer 的 edgeRef 报 `input shape has no role table`)。改经\n // runtimeLineage.recordOutput 落语句键表 + part 键权威位。\n // D12(2026-09-24):取内核走 getBrepApi;引擎未初始化 → 跳过建表(纯 mesh 结果)。\n let kernel: BrepEngineApi | null = null\n try { kernel = getBrepApi() } catch { /* no engine -> skip role table */ }\n const solid = kernel ? (brepOf(result) as BrepHandle | undefined) : undefined\n if (kernel && solid) {\n const origin = String(getCurrentStmt()?.id ?? '')\n const table = new Map([[origin, extrudeConstructRoles(kernel, solid, normal.toArray() as Vec3)]])\n const part = getCurrentStmt()?.outputs?.[0]\n runtimeLineage.recordOutput(origin as never, table, solid as never, part as never)\n }\n return result\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [{ kind: 'semantic', name: 'top' }, { kind: 'semantic', name: 'bottom' }, { kind: 'wall', index: 0 }] } } as Provenance,\n\n paramDims: { length: 'length', offset: 'length', normal: 'plain' },\n})\n"]}
|
|
1
|
+
{"version":3,"file":"extrude.js","sourceRoot":"","sources":["../../src/api/extrude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACpE,OAAO,EAAE,IAAI,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACpF,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAA;AAE7E,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAA;AAKxG,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,qBAAqB,CAC5B,MAAqB,EACrB,KAAiB,EACjB,QAA4C;IAE5C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAA;IACzC,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IACtD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAA;QAC/D,6DAA6D;QAC7D,qDAAqD;QACrD,yDAAyD;QACzD,4DAA4D;QAC5D,yDAAyD;QACzD,wDAAwD;QACxD,6DAA6D;QAC7D,+CAA+C;QAC/C,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAA;QACxE,MAAM,OAAO,GAA0C,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC3E,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;YACnF,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAU,CAAA;QACjC,CAAC,CAAC,CAAA;QACF,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACpC,MAAM,CAAC,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAA;YACvC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAU,CAAA;QACjC,CAAC,CAAC,CAAA;QAEF,mCAAmC;QACnC,gCAAgC;QAChC,EAAE;QACF,2DAA2D;QAC3D,8CAA8C;QAC9C,gDAAgD;QAChD,2CAA2C;QAC3C,oEAAoE;QACpE,2CAA2C;QAC3C,IAAI,IAAmD,CAAA;QACvD,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAChF,IAAI,QAAQ,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAsC;gBAC3C,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO;aACpE,CAAA;YACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;gBACnC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;gBACxC,IAAI,GAAG,GAAG,IAAI;oBAAE,OAAO,KAAK,CAAA;gBAC5B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAA;YAC1E,CAAC,CAAC,CAAA;YACF,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;gBAAE,IAAI,GAAG,CAAC,CAAA;QACnC,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YACjD,kCAAkC;YAClC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;gBAAE,SAAQ;YACxB,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;YACpB,IAAI,CAAC,CAAC;gBAAE,SAAQ;YAChB,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5C,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;oBAAE,SAAQ;gBACxB,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;gBACpB,IAAI,CAAC,CAAC;oBAAE,SAAQ;gBAChB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;gBACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;gBACzC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI;oBAAE,SAAQ;gBACxC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;gBACrE,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC;oBAC1B,wBAAwB;oBACxB,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAU,CAAA;oBACvD,MAAK;gBACP,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAChE,IAAI,IAAI,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;YAC3B,MAAM,EAAE,GAAsC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAA;YACvG,wCAAwC;YACxC,MAAM,aAAa,GAAiC,EAAE,CAAA;YACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;oBAAE,SAAQ;gBACxB,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;gBACpB,IAAI,CAAC,CAAC;oBAAE,SAAQ;gBAChB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;gBAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAA;gBACtE,IAAI,GAAG,GAAG,KAAK,EAAE,CAAC;oBAChB,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;gBAC7G,CAAC;YACH,CAAC;YACD,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBAC9B,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;gBACvC,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAE,CAAA;gBAChC,MAAM,GAAG,GAAG,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAE,CAAA;gBACpD,sDAAsD;gBACtD,sDAAsD;gBACtD,sDAAsD;gBACtD,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS;oBAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAE,CAAC,CAAC,CAAA;gBAC1G,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS;oBAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,CAAC,CAAA;YACnG,CAAC;YACD,gDAAgD;YAChD,uCAAuC;YACvC,IAAI,OAAO,GAAG,CAAC,CAAA;YACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;gBACpB,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS;oBAAE,SAAQ;gBAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;gBAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAA;gBACtE,IAAI,GAAG,GAAG,KAAK,EAAE,CAAC;oBAChB,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAA;oBACtD,OAAO,EAAE,CAAA;gBACX,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;YAAS,CAAC;QACT,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,IAAI,CAAC;gBAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;AACH,CAAC;AA6BD,0CAA0C;AAC1C,SAAS,aAAa,CAAC,CAAU;IAC/B,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,SAAS,CAAA;AAClH,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,uBAAuB,CAAC,MAAe;IAC9C,IAAI,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,MAAwB,CAAA;IAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,MAAc,CAAA;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;QACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,KAAK,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;QACpF,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;IACvF,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;IAC7F,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAA;AAC5G,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,CAAiB;IAC7C,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;QAAE,OAAM,CAAC,oBAAoB;IACrD,oBAAoB,CAAC,CAAC,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AAClD,CAAC;AAED,4BAA4B;AAC5B,SAAS,QAAQ,CAAC,IAA8B;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AACpG,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,UAAU,CAAC,MAAqB,EAAE,UAAgB,EAAE,UAAgB,EAAE,KAAa;IAC1F,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC,SAAS,EAAE,CAAA;IACjD,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,GAAG,UAAU,CAAC,CAAA;IACvC,iBAAiB;IACjB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAC5E,MAAM,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,SAAS,EAAE,CAAA;IACzD,MAAM,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;IACvD,MAAM,CAAC,GAAG,KAAK,CAAA;IACf,oDAAoD;IACpD,MAAM,GAAG,GAAG,MAAM,CAAC,kBAAkB,CACnC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EACvB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CACrB,CAAA;IACD,0DAA0D;IAC1D,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IAC9D,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;AAChD,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,gBAAgB,CAAC,MAAqB,EAAE,UAAsB,EAAE,CAAiB;IACxF,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;IAChE,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAA;IAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAmB,CAAA;IAElC,+DAA+D;IAC/D,mCAAmC;IACnC,IAAI,YAAkB,CAAA;IACtB,IAAI,YAAkB,CAAA;IACtB,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,CAAA;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAE,MAAM,CAAC,IAAI,CAA4B,CAAC,CAAC,CAAC,SAAS,CAAA;QAC7E,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAA;QACtF,CAAC;QACD,+CAA+C;QAC/C,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QACnD,MAAM,IAAI,GAAG,CAAC,KAAoB,EAAQ,EAAE;YAC1C,MAAM,CAAC,GAAS;gBACd,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC/B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC/B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;aAChC,CAAA;YACD,MAAM,MAAM,GAAG,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YACvC,MAAM,IAAI,GACR,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;gBAChD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;gBAChD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YAClD,OAAO;gBACL,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM;gBACvC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM;gBACvC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM;aACxC,CAAA;QACH,CAAC,CAAA;QACD,YAAY,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QACpD,YAAY,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IAC/C,CAAC;SAAM,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QAC/D,yCAAyC;QACzC,kCAAkC;QAClC,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAS,CAAA;QAC5C,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAS,CAAA;IAC/C,CAAC;SAAM,CAAC;QACN,oDAAoD;QACpD,6CAA6C;QAC7C,2DAA2D;QAC3D,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACzC,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAS,CAAA;YAC5C,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAS,CAAA;QAC9C,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,2DAA2D,CAAC,CAAA;QACjH,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,0CAA0C;IAC1C,aAAa;IACb,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IACpD,MAAM,cAAc,GAAS;QAC3B,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM;QAC1C,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM;QAC1C,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM;KAC3C,CAAA;IACD,oDAAoD;IACpD,mDAAmD;IACnD,6CAA6C;IAC7C,6CAA6C;IAC7C,qDAAqD;IACrD,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACxD,MAAM,EAAE,GAAS;YACf,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC/B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC/B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;SAChC,CAAA;QACD,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,GAAG,YAAY,CAAC,CAAC,SAAS,EAAE,CAAA;QACrD,MAAM,KAAK,GACT,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YACtC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YACtC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAA;QACxC,iDAAiD;QACjD,+CAA+C;QAC/C,MAAM,KAAK,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QACzC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;QAC3B,CAAC;IACH,CAAC;IACD,MAAM,iBAAiB,GAAG;QACxB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAC9B,CAAA;IACX,MAAM,WAAW,GAAG,IAAI,KAAK,CAAC,GAAG,cAAc,CAAC,CAAA;IAChD,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,GAAG,YAAY,CAAC,CAAC,SAAS,EAAE,CAAA;IAClD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACnC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAA;IAC7F,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB;SAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;SACtD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACtC,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAA;IAC5D,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAEtF,qDAAqD;IACrD,2CAA2C;IAC3C,qDAAqD;IACrD,MAAM,EAAE,GAAG,GAAG,CAAA;IACd,MAAM,WAAW,GAAG,IAAI,KAAK,CAC3B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAC/B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAC/B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAChC,CAAA;IACD,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,GAAG,cAAc,CAAC,CAAA;IAC/C,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC7C,+CAA+C;IAC/C,qBAAqB;IACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9F,wDAAwD;IACxD,gDAAgD;IAChD,6CAA6C;IAC7C,uCAAuC;IACvC,MAAM,KAAK,GACT,IAAI,KAAK,CAAC,GAAG,cAAc,CAAC,CAAC,UAAU,CACrC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAC7G,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAC3C,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IAEpG,mBAAmB;IACnB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IACnD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACzB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAEzB,wBAAwB;IACxB,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,EAAE,CAAC;QAC5E,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACvB,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAA;IAC9F,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,gBAAgB,CAAC,KAAY,EAAE,MAAe;IACrD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IAC9D,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAA;IACH,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IAE7C,MAAM,CAAC,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAA;IACzC,oBAAoB,CAAC,CAAC,CAAC,CAAA;IACvB,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,oBAAoB,CAC5B,oGAAoG;YACpG,oFAAoF,EACpF,cAAc,EAAE,CACjB,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;IAChE,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3C,MAAM,CAAC,GAAS,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAO,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAO,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAO,GAAG,IAAI,CAAC,CAAA;IAEvG,IAAI,KAAiB,CAAA;IACrB,IAAI,CAAC;QACH,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,CAAA;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,iBAAiB,CACrB,SAAS,EACT,kBAAkB,EAClB,kCAAkC,CAAC,CAAC,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EACpE,KAAK,CACN,CAAA;IACH,CAAC;IACD,OAAO,2BAA2B,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;AAC1D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,CAAC,SAAS,CAAC;IACxB,IAAI,CAAC,KAAY,EAAE,MAAe;QAChC,OAAO,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IACxC,CAAC;IACD,IAAI,EAAE,KAAK,EAAE,KAAY,EAAE,MAAe,EAAkB,EAAE;QAC5D,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;QAC9D,+DAA+D;QAC/D,qDAAqD;QACrD,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAA;QACH,CAAC;QACD,MAAM,CAAC,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAA;QACzC,oBAAoB,CAAC,CAAC,CAAC,CAAA;QACvB,yDAAyD;QACzD,+BAA+B;QAC/B,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;QAEhE,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;YAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAA2B,CAAA;YAC1D,IAAI,UAAU,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;YAChF,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAA;YACvD,uDAAuD;YACvD,gDAAgD;YAChD,2DAA2D;YAC3D,sDAAsD;YACtD,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;YACjD,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;gBAC7C,KAAK,EAAE,OAAO;gBACd,SAAS,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,qBAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAU,CAAC,CAAC,CAAC,CAAC;aACjG,CAAC,CAAA;QACJ,CAAC;QAED,2CAA2C;QAC3C,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC3C,MAAM,CAAC,GAAS,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAO,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAO,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAO,GAAG,IAAI,CAAC,CAAA;QACvG,IAAI,MAAa,CAAA;QACjB,iDAAiD;QACjD,+DAA+D;QAC/D,6DAA6D;QAC7D,8CAA8C;QAC9C,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACpD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;YAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAA2B,CAAA;YAC1D,IAAI,UAAU,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;YAC9F,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,CAAA;YAC7D,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QAC3D,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,CAAC,MAAM,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAU,CAAA;QACtD,CAAC;QACD,0CAA0C;QAC1C,uDAAuD;QACvD,gDAAgD;QAChD,iEAAiE;QACjE,iDAAiD;QACjD,4DAA4D;QAC5D,IAAI,MAAM,GAAyB,IAAI,CAAA;QACvC,IAAI,CAAC;YAAC,MAAM,GAAG,UAAU,EAAE,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,kCAAkC,CAAC,CAAC;QAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,MAAM,CAAC,MAAM,CAA4B,CAAC,CAAC,CAAC,SAAS,CAAA;QAC7E,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;YACjD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAU,CAAC,CAAC,CAAC,CAAC,CAAA;YACjG,MAAM,IAAI,GAAG,cAAc,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;YAC3C,cAAc,CAAC,YAAY,CAAC,MAAe,EAAE,KAAK,EAAE,KAAc,EAAE,IAAa,CAAC,CAAA;QACpF,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAgB;IAExL,SAAS,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE;CACnE,CAAC,CAAA","sourcesContent":["/**\n * api extrude — `cad.extrude`(平台 parity op,BREP-only)\n *\n * 归属(分层红线):`cad.extrude` 是「面 → 棱柱」的**平台** op,FCStd Pad/Pocket\n * 链路与 TS 面共用它(原 `cad.fai_extrude` 路线废弃)。up-to(拉伸到面 / 到支持体端面)属\n * CadQuery `until=` 同族语义,因此落在**本 op**;`fai_extrude`(`fai_` 前缀的\n * faijs 扩展 op,与 fai_drill / fai_split 同族)不得承载它。\n *\n * 为什么是手写 op 而不是继续用生成投影:生成投影是一条 1:1 转发通道\n * (`defineOp({ brep: __own_* })` 直连 api/brep-operations/ 的源函数),有两个硬约束——\n * ① 参数表只有位置形参;D11 归一化只在「单 plain-object 形态」下按 params 表\n * 映射(api/internal/dual-form-args.ts),`(face, { upTo })` 属位置形态 →\n * 原样喂给 compat extrude → 报错,无法表达对象形态;\n * ② 生成投影没有 faijs 侧入参解析挂点,只把实参原样转发给源函数 → 依赖 faceRef 解析 /\n * 内核直调(extrudeUpToSolid)的 up-to 实现无法在生成投影里承载,落回本手写模块。\n * 先例:arg-spec 的 `fillet` 条目(faijs 侧由手写 dual-op 覆盖,生成模块符号为\n * 孤儿 by design)。\n *\n * 长度形态**委托给生成投影**(`projectedExtrude`):compat 投影仍是唯一拉伸引擎,\n * 既有 `cad.extrude(face, [x,y,z])` 语义零漂移。\n */\n\nimport { extrude as projectedExtrude } from './generated/operations'\nimport { Vec3 as Vec3C, Mat4 } from '../math3d'\nimport { solidToShape, matrixToArray } from '../brep/brep-ops'\nimport { getSolidBoundingBox } from '../brep/brep-utils'\nimport { getCurrentStmt, getBackends, MeshUnsupportedError } from '../runtime-state'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { fromBrep, brepOf, isCurveShape } from '../shape'\nimport { runtimeLineage } from '../topology/naming/lineage'\nimport { formatRoleName, semantic, wall } from '../topology/naming/role-name'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { defineOp } from '../sdk'\nimport { assertPositiveNumber } from './assert'\nimport { meshFaceEntry, meshKernelFailure, meshSolidProductWithBackend } from './internal/mesh-solid-op'\nimport type { Shape, Vec3 } from '../mesh/types'\nimport type { BrepHandle } from '../brep/engine/types'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport type { FaceTopoRef } from '../topology/naming'\nimport { TopoRefError } from '../topology/naming'\n\n/**\n\n * extrude 的 construct 词汇表(计划 §4.4):`cap:bottom` / `cap:top` / `wall:<i>`。\n *\n * 判定口径:\n * - 拉伸方向**优先由 op 给出**(`hintAxis`),但必须由现场几何裁定:只有当至少\n * 两张面的法向与该方向 |cos| ≈ 1 时才采信,否则回退到纯几何判定(A2,见下);\n * - 面法向与拉伸轴 |cos| ≈ 1 → 端面:中心沿轴分量小者 `cap:bottom`、大者 `cap:top`;\n * - 面法向与拉伸轴 |cos| ≈ 0 → 侧面 `wall:<i>`,i = 该面在侧面枚举中的相对序\n * (OCCT prism 的侧面顺序 = profile wire 的边序——makeWire 按构造顺序收边,\n * prism 不重排;G3-L1 改参重放依赖该稳定性);\n * - 侧面含**非平面**(profile 里的弧段扫出圆柱面)同样进表:圆柱面 uv 中点法向\n * 是径向,与拉伸轴垂直,判定与平面侧面同式。\n *\n * @param kernel - the OCCT kernel.\n * @param solid - the extruded solid.\n * @param hintAxis - 拉伸方向(op 已知;仅作候选,由现场几何确认)。\n * @returns role(线格式串)→ hash 子表。\n */\nfunction extrudeConstructRoles(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n hintAxis?: readonly [number, number, number],\n): Map<string, number[]> {\n const roles = new Map<string, number[]>()\n const faceHandles = kernel.getSubShapes(solid, 'face')\n try {\n const hashes = kernel.subShapeHashes(solid, 'face', 2147483647)\n // A2 (2026-09-26, Beds.FCStd): 侧面可能是**圆柱面**——profile 含弧段时,该弧\n // 沿拉伸方向扫出的就是一个圆柱侧面。旧实现只在 `surfaceType === 'plane'` 时\n // 取法向,于是圆柱侧面 normals[i] === undefined:既拿不到 `wall:<i>`,还让\n // `wallIdx` 跳过它们 —— wall 序号因此不再是 profile 边序(违反 role-name.ts\n // 的契约「wall:3 = 由 profile 第 3 条边扫出」)。实测 Beds part28(轮廓含 4\n // 段弧)10 面只覆盖 6 个(缺序号 2/4/6/8),下游 fillet 的 `cad.edgeRef`\n // 遂抛 `edgeRef: adjacent face ordinal 2 has no role lineage`。\n // 圆柱面 uv 中点的法向是径向、与拉伸轴垂直(|cos| ≈ 0),可直接用于侧面判定。\n const planar = faceHandles.map((f) => kernel.surfaceType(f) === 'plane')\n const normals: (readonly [number, number, number])[] = faceHandles.map((f) => {\n const uv = kernel.uvBounds(f)\n const n = kernel.surfaceNormal(f, (uv.uMin + uv.uMax) / 2, (uv.vMin + uv.vMax) / 2)\n return [n.x, n.y, n.z] as const\n })\n const centers = faceHandles.map((f) => {\n const c = kernel.surfaceCenterOfMass(f)\n return [c.x, c.y, c.z] as const\n })\n\n // 拉伸轴:op 已知的拉伸方向优先(须由现场几何确认),否则找一对\n // |cos| ≈ 1 的反平行平面法向 → 带符号单位方向。\n //\n // A2 (2026-09-26, Beds.FCStd part28): 纯几何判定取「第一对反平行的平面法向」,\n // 但方形类轮廓的**一对对侧平面侧壁同样反平行**——Beds 的柱子于是把 X 向侧壁\n // 判成端盖、把真正的 Z 向端盖当成 wall,4 个圆柱侧面彻底无名(10 面只覆盖 6,\n // 缺序号 2/4/6/8),下游 fillet 的 `cad.edgeRef` 抛\n // `edgeRef: adjacent face ordinal 2 has no role lineage`。方向由 op 给出、\n // 由几何裁定(至少两张面法向与该方向 |cos| ≈ 1 才采信),两者缺一不可。\n let axis: readonly [number, number, number] | undefined\n const hintLen = hintAxis ? Math.hypot(hintAxis[0], hintAxis[1], hintAxis[2]) : 0\n if (hintAxis && hintLen > 1e-9) {\n const d: readonly [number, number, number] = [\n hintAxis[0] / hintLen, hintAxis[1] / hintLen, hintAxis[2] / hintLen,\n ]\n const aligned = normals.filter((n) => {\n const len = Math.hypot(n[0], n[1], n[2])\n if (len < 1e-9) return false\n return Math.abs((n[0] * d[0] + n[1] * d[1] + n[2] * d[2]) / len) > 0.999\n })\n if (aligned.length >= 2) axis = d\n }\n for (let i = 0; i < normals.length && !axis; i++) {\n // 端面必须是一对反平行的**平面**法向(棱柱的端盖恒为平面)。\n if (!planar[i]) continue\n const a = normals[i]\n if (!a) continue\n for (let j = i + 1; j < normals.length; j++) {\n if (!planar[j]) continue\n const b = normals[j]\n if (!b) continue\n const lenA = Math.hypot(a[0], a[1], a[2])\n const lenB = Math.hypot(b[0], b[1], b[2])\n if (lenA < 1e-9 || lenB < 1e-9) continue\n const cos = (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]) / (lenA * lenB)\n if (Math.abs(cos) > 0.999) {\n // b 反向即「从 i 面指向 j 面」的方向\n axis = [b[0] - a[0], b[1] - a[1], b[2] - a[2]] as const\n break\n }\n }\n }\n const axisLen = axis ? Math.hypot(axis[0], axis[1], axis[2]) : 0\n if (axis && axisLen > 1e-9) {\n const ax: readonly [number, number, number] = [axis[0] / axisLen, axis[1] / axisLen, axis[2] / axisLen]\n // 端面:沿轴投影最小者 = cap:bottom,最大者 = cap:top\n const capCandidates: { idx: number; t: number }[] = []\n for (let i = 0; i < normals.length; i++) {\n if (!planar[i]) continue\n const n = normals[i]\n if (!n) continue\n const len = Math.hypot(n[0], n[1], n[2]) || 1\n const cos = Math.abs(n[0] * ax[0] + n[1] * ax[1] + n[2] * ax[2]) / len\n if (cos > 0.999) {\n capCandidates.push({ idx: i, t: centers[i]![0] * ax[0] + centers[i]![1] * ax[1] + centers[i]![2] * ax[2] })\n }\n }\n if (capCandidates.length >= 2) {\n capCandidates.sort((p, q) => p.t - q.t)\n const bottom = capCandidates[0]!\n const top = capCandidates[capCandidates.length - 1]!\n // 端面词汇用 semantic('bottom'/'top'——与 box 同形)。计划 §4.4 写的\n // `cap:<name>` 前缀形态与 RoleName 契约冲突(semantic 名不允许 ':',\n // role-name.ts SEMANTIC_NAME_RE),落地以契约为准:semantic 直名。\n if (hashes[bottom.idx] !== undefined) roles.set(formatRoleName(semantic('bottom')), [hashes[bottom.idx]!])\n if (hashes[top.idx] !== undefined) roles.set(formatRoleName(semantic('top')), [hashes[top.idx]!])\n }\n // 侧面:|cos| ≈ 0,按枚举序编号(= profile 边序)。平面/圆柱侧面一律进表\n // (A2)——跳过圆柱侧面会让 wall 序号脱离 profile 边序。\n let wallIdx = 0\n for (let i = 0; i < normals.length; i++) {\n const n = normals[i]\n if (!n || hashes[i] === undefined) continue\n const len = Math.hypot(n[0], n[1], n[2]) || 1\n const cos = Math.abs(n[0] * ax[0] + n[1] * ax[1] + n[2] * ax[2]) / len\n if (cos < 0.001) {\n roles.set(formatRoleName(wall(wallIdx)), [hashes[i]!])\n wallIdx++\n }\n }\n }\n return roles\n } finally {\n for (const h of faceHandles) {\n try { kernel.release(h) } catch { /* 已释放 */ }\n }\n }\n}\n\n/** 显式平面目标(up-to 截断面):点 + 法向(点在平面上即可,无需共面于面边界)。 */\nexport interface UpToPlaneSpec {\n /** 平面上一点(世界坐标)。type:[x,y,z] */\n point: Vec3\n /** 平面法向(世界坐标,方向仅定半空间语义,截断取两侧之一)。type:[x,y,z] */\n normal: Vec3\n}\n\n/** up-to 目标:显式面引用 / 显式平面 / 支持体沿拉伸方向的远端(last)/近端(first)端面。 */\nexport type ExtrudeUpTo = FaceTopoRef | 'last' | 'first' | { plane: UpToPlaneSpec }\n\n/** `cad.extrude` 的对象形态参数(位置形态由 {@link normalizeExtrudeOptions} 归一到这里)。 */\nexport interface ExtrudeOptions {\n /** 拉伸量(mm,>0)。up-to 模式下无需给。 */\n length?: number\n /** 拉伸方向(世界坐标);缺省 [0,0,1]。 */\n normal?: Vec3\n /** 沿 normal 的前进方向;缺省 'forward'('backward' 等价于方向取反)。 */\n mode?: 'forward' | 'backward'\n /** 拉伸到面 / 到支持体端面;提供时忽略 length。 */\n upTo?: ExtrudeUpTo\n /** upTo 'last'/'first' 的支持体(累积支持体,由转换器显式传入)。 */\n baseFeature?: Shape\n /** 截断面沿其法向的偏移(mm);缺省 0。 */\n offset?: number\n}\n\n/** 判定是否为朴素对象(对象形态判别器,避免误吞 Shape / 数组)。 */\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v) && Object.getPrototypeOf(v) === Object.prototype\n}\n\n/**\n * 归一化 `cad.extrude` 的两种调用形态。\n *\n * - 位置形态(与生成投影同款,历史产物在用):`cad.extrude(face, 10)` /\n * `cad.extrude(face, [x,y,z])`——向量即「方向 × 长度」,恒为沿该方向前进。\n * - 对象形态(faijs 面):`cad.extrude(face, { length, normal, mode, upTo, ... })`。\n *\n * @param params - 调用点第二实参(数字 / 向量 / 对象)。\n * @returns 归一化后的对象形态参数。\n * @throws Error 参数既非数字 / 向量 / 朴素对象时(不猜)。\n */\nfunction normalizeExtrudeOptions(params: unknown): ExtrudeOptions {\n if (isPlainObject(params)) return params as ExtrudeOptions\n if (Array.isArray(params)) {\n const v = params as Vec3\n const len = Math.hypot(v[0] ?? 0, v[1] ?? 0, v[2] ?? 0)\n if (!Number.isFinite(len) || len < 1e-12) {\n throw new Error('E_EXTRUDE_ZERO_VECTOR: extrude direction vector has zero length')\n }\n return { length: len, normal: [v[0] / len, v[1] / len, v[2] / len], mode: 'forward' }\n }\n if (typeof params === 'number') return { length: params, normal: [0, 0, 1], mode: 'forward' }\n throw new Error('E_EXTRUDE_BAD_PARAMS: extrude expects (face, number | [x,y,z] | { length | upTo, ... })')\n}\n\n/**\n * 参数自校验:up-to 模式下无需 length;否则 length 必须为正数。\n *\n * @param o - 归一化后的参数。\n */\nfunction assertExtrudeOptions(o: ExtrudeOptions): void {\n if (o.upTo !== undefined) return // up-to 模式:长度由目标面决定\n assertPositiveNumber(o.length, 'extrude.length')\n}\n\n/** bbox 对角线长度(长试探的余量基数)。 */\nfunction bboxDiag(bbox: { min: Vec3; max: Vec3 }): number {\n return Math.hypot(bbox.max[0] - bbox.min[0], bbox.max[1] - bbox.min[1], bbox.max[2] - bbox.min[2])\n}\n\n/**\n * 目标面法向负侧的半空间覆盖盒(截断长拉伸用)——定向版。\n *\n * GOTCHA(PadTest Pad001 斜置基准面实测):轴对齐盒的边界不是斜面本身,\n * 截断呈台阶而非精确斜平面(体积 7076 vs 真值 4860)。正确做法:在局部基\n * (u, v, n) 里构造盒(深度沿 −n 伸出 R、横向 ±R),再用 kernel.transform\n * 旋到世界系——盒的 n=R 端面就是精确的目标平面。\n *\n * @param kernel - BREP 内核。\n * @param faceCenter - 目标面中心(世界坐标,盒的 n=0 端面过此点)。\n * @param faceNormal - 目标面法向(半空间保留 −n 侧…即盒占据 −n 侧深度)。\n * @param reach - 覆盖半径 R。\n * @returns 定向半空间盒的 brep 句柄。\n */\nfunction farSideBox(kernel: BrepEngineApi, faceCenter: Vec3, faceNormal: Vec3, reach: number): BrepHandle {\n const unit = new Vec3C(...faceNormal).normalize()\n const center = new Vec3C(...faceCenter)\n // 与 n 正交的正交基 u,v\n const aux = Math.abs(unit.y) < 0.9 ? new Vec3C(0, 1, 0) : new Vec3C(1, 0, 0)\n const u = new Vec3C().crossVectors(unit, aux).normalize()\n const v = new Vec3C().crossVectors(unit, u).normalize()\n const R = reach\n // 局部系盒:x∈[−R,R] (u), y∈[−R,R] (v), z∈[−R,0] (n 深度侧)\n const box = kernel.makeBoxFromCorners(\n { x: -R, y: -R, z: -R },\n { x: R, y: R, z: 0 },\n )\n // 旋转矩阵:列 = u, v, n;平移 = center(局部 z=0 端面落到过 center 的目标平面)\n const m = new Mat4().makeBasis(u, v, unit).setPosition(center)\n return kernel.transform(box, matrixToArray(m))\n}\n\n/**\n * up-to 拉伸:occt-wasm 未暴露 `BRepFeat_MakePrism`,用「长拉伸 → 与目标面侧\n * 半空间盒求交」等价组合;长试探上限只作布尔构造辅助,不进入结果几何。\n *\n * @param kernel - BREP 内核。\n * @param inputSolid - 轮廓实体句柄。\n * @param o - 归一化参数(需带 upTo)。\n * @returns 截断后的实体句柄。\n * @throws Error E_UP_TO_* 系列:缺支持体 / 方向与目标面平行 / 不相交(禁静默)。\n */\nfunction extrudeUpToSolid(kernel: BrepEngineApi, inputSolid: BrepHandle, o: ExtrudeOptions): BrepHandle {\n const normal = new Vec3C(...(o.normal ?? [0, 0, 1])).normalize()\n const offset = o.offset ?? 0\n const upTo = o.upTo as ExtrudeUpTo\n\n // 1) 方向目标:FaceTopoRef → 现场面几何;'last'/'first' → baseFeature 支持体\n // 沿拉伸方向的端面(远端 last / 近端 first)。\n let targetCenter: Vec3\n let targetNormal: Vec3\n if (typeof upTo === 'string') {\n const base = o.baseFeature\n const baseSolid = base ? (brepOf(base) as BrepHandle | undefined) : undefined\n if (baseSolid === undefined) {\n throw new Error('E_UP_TO_NO_BASE: upTo \"last\"/\"first\" requires a baseFeature shape')\n }\n // 支持体 bbox 沿拉伸方向的远端/近端平面(R-C:baseFeature 显式传参)\n const bbox = getSolidBoundingBox(kernel, baseSolid)\n const pick = (which: 'max' | 'min'): Vec3 => {\n const c: Vec3 = [\n (bbox.min[0] + bbox.max[0]) / 2,\n (bbox.min[1] + bbox.max[1]) / 2,\n (bbox.min[2] + bbox.max[2]) / 2,\n ]\n const extent = which === 'max' ? 1 : -1\n const proj =\n (bbox.max[0] - bbox.min[0]) * Math.abs(normal.x) +\n (bbox.max[1] - bbox.min[1]) * Math.abs(normal.y) +\n (bbox.max[2] - bbox.min[2]) * Math.abs(normal.z)\n return [\n c[0] + ((normal.x * proj) / 2) * extent,\n c[1] + ((normal.y * proj) / 2) * extent,\n c[2] + ((normal.z * proj) / 2) * extent,\n ]\n }\n targetCenter = pick(upTo === 'last' ? 'max' : 'min')\n targetNormal = [normal.x, normal.y, normal.z]\n } else if (upTo && typeof upTo === 'object' && 'plane' in upTo) {\n // 显式平面目标(datum plane 等无限平面:截断面由平面方程决定,不受\n // 目标面边界限制——斜置基准面时顶面是斜的,定长路径语义错误)。\n targetCenter = [...upTo.plane.point] as Vec3\n targetNormal = [...upTo.plane.normal] as Vec3\n } else {\n // GOTCHA(探针实测):FaceTopoRef 携带的 hint 是 faceRef 现场捕获的\n // center/normal 快照,直接使用;不要对拉伸轮廓(sketch 面)做二次\n // resolveFaceGeometry——引用的面在目标体上、不在轮廓上,会 E_TOPO_NOT_FOUND。\n if (upTo.hint.center && upTo.hint.normal) {\n targetCenter = [...upTo.hint.center] as Vec3\n targetNormal = [...upTo.hint.normal] as Vec3\n } else {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', 'extrude upTo: face ref hint has no center/normal snapshot')\n }\n }\n\n // 2) 长试探长度:GOTCHA(探针实测)——不能按轮廓自身 bbox 对角线算(小轮廓够不到\n // 远处目标面);必须取「截断平面沿拉伸方向的投影距离」加余量,保证长拉伸至\n // 少穿过目标面。\n const bbox = getSolidBoundingBox(kernel, inputSolid)\n const shiftedCenter0: Vec3 = [\n targetCenter[0] + targetNormal[0] * offset,\n targetCenter[1] + targetNormal[1] * offset,\n targetCenter[2] + targetNormal[2] * offset,\n ]\n // 自动定向(仅 { plane } 目标):FreeCAD UpToFace 朝目标面所在方向拉伸。\n // GOTCHA(PadTest Pad001 实测,probe 探针):斜置基准面在草图局部坐标里\n // 位于轮廓的反方向(圆心处平面交点 t=−26 而非 +26),固定沿 +Z 拉截不到\n // 平面(体积 597 ≠ 真值 4860)。轮廓 bbox 中心到截断平面的有向投影与\n // 拉伸方向异号 → 翻转拉伸方向(就地翻转 Vector3,后续 tMax/keepSide 自洽)。\n if (upTo && typeof upTo === 'object' && 'plane' in upTo) {\n const c0: Vec3 = [\n (bbox.min[0] + bbox.max[0]) / 2,\n (bbox.min[1] + bbox.max[1]) / 2,\n (bbox.min[2] + bbox.max[2]) / 2,\n ]\n const tnAuto = new Vec3C(...targetNormal).normalize()\n const dAuto =\n (c0[0] - shiftedCenter0[0]) * tnAuto.x +\n (c0[1] - shiftedCenter0[1]) * tnAuto.y +\n (c0[2] - shiftedCenter0[2]) * tnAuto.z\n // 沿拉伸方向到平面的有向交点参数:t = −((c0−plane)·n) / (dir·n)。\n // t<0 → 平面在行进反方向 → 翻转(FreeCAD UpToFace 朝平面拉伸)。\n const tAuto = -dAuto / normal.dot(tnAuto)\n if (tAuto < 0) {\n normal.multiplyScalar(-1)\n }\n }\n const cornerProjections = [\n [bbox.min[0], bbox.min[1], bbox.min[2]],\n [bbox.max[0], bbox.min[1], bbox.min[2]],\n [bbox.min[0], bbox.max[1], bbox.min[2]],\n [bbox.min[0], bbox.min[1], bbox.max[2]],\n [bbox.max[0], bbox.max[1], bbox.min[2]],\n [bbox.max[0], bbox.min[1], bbox.max[2]],\n [bbox.min[0], bbox.max[1], bbox.max[2]],\n [bbox.max[0], bbox.max[1], bbox.max[2]],\n ] as Vec3[]\n const planePoint0 = new Vec3C(...shiftedCenter0)\n const tn0 = new Vec3C(...targetNormal).normalize()\n const planeD = planePoint0.dot(tn0)\n const dirD = normal.dot(tn0)\n if (Math.abs(dirD) < 1e-9) {\n throw new Error('E_UP_TO_PARALLEL: extrude direction is parallel to the target face plane')\n }\n const tMax = cornerProjections\n .map((p) => (planeD - new Vec3C(...p).dot(tn0)) / dirD)\n .reduce((a, b) => Math.max(a, b), 0)\n const L = tMax + Math.abs(offset) + bboxDiag(bbox) * 0.1 + 1\n const longSolid = kernel.extrude(inputSolid, normal.x * L, normal.y * L, normal.z * L)\n\n // 3) 截断平面 = 目标面 + offset(沿面法向)。GOTCHA(探针实测):半空间侧不能固定\n // 取「法向负侧」——目标面法向朝向与拉伸方向无必然关系。正确语义:保留「包含\n // 拉伸起点」的那一侧。farSideBox 覆盖「传入法向的反侧」,因此传 -keepSide。\n const tn = tn0\n const startCenter = new Vec3C(\n (bbox.min[0] + bbox.max[0]) / 2,\n (bbox.min[1] + bbox.max[1]) / 2,\n (bbox.min[2] + bbox.max[2]) / 2,\n )\n const planePoint = new Vec3C(...shiftedCenter0)\n const d = startCenter.sub(planePoint).dot(tn)\n // 保留侧法向:起点所在侧(d 与 tn 同号 → 正侧;异号 → 负侧);d≈0 时退化为\n // 拉伸方向(起点在面上时按拉伸方向截)\n const keepSide = Math.abs(d) < 1e-9 ? normal.clone() : tn.clone().multiplyScalar(Math.sign(d))\n // GOTCHA(PadTest Pad001 斜置基准面实测):targetCenter 可以是平面上离轮廓\n // 很远的任意一点(基准面 point 在草图局部坐标里横向偏 ~100),reach 若只取\n // L(按轮廓到截断面的投影距离)则半空间盒横向盖不住长拉伸体 → common 为空。\n // reach 必须 ≥ 平面点到拉伸体的距离 + 体对角线(全方向覆盖)。\n const reach =\n new Vec3C(...shiftedCenter0).distanceTo(\n new Vec3C((bbox.min[0] + bbox.max[0]) / 2, (bbox.min[1] + bbox.max[1]) / 2, (bbox.min[2] + bbox.max[2]) / 2),\n ) + bboxDiag(bbox) + Math.abs(offset) + 1\n const halfspace = farSideBox(kernel, shiftedCenter0, [-keepSide.x, -keepSide.y, -keepSide.z], reach)\n\n // 4) 求交:长拉伸 ∩ 半空间盒\n const clipped = kernel.common(longSolid, halfspace)\n kernel.release(longSolid)\n kernel.release(halfspace)\n\n // 预检:方向上不相交 → 显式报错(禁静默)\n const clippedBBox = getSolidBoundingBox(kernel, clipped)\n if (!Number.isFinite(bboxDiag(clippedBBox)) || bboxDiag(clippedBBox) < 1e-9) {\n kernel.release(clipped)\n throw new Error('E_UP_TO_NO_INTERSECTION: extrude direction does not reach the target face')\n }\n return clipped\n}\n\n/**\n * `cad.extrude` 的**网格链**实现(方案 2026-10-01 §4 Phase 3-2)。\n *\n * 输入是一张**网格链面**(`cad.sketchOnFace` 在近似拓扑面上铺出来的那种),\n * 输出是一个**新的网格零件**——与输入网格实体同链。\n *\n * 只支持\"面 + 方向 + 距离\"这一支:`upTo` 需要精度链上的求交/裁切(`extrudeUpToSolid`\n * 走 BREP 内核),近似链没有对应能力,故如实拒绝而不是静默退化成普通拉伸——\n * \"拉伸到那张面\"和\"拉伸这么长\"是两件不同的事,悄悄替换会让用户拿到一个错的实体。\n *\n * 方向语义与 BREP 侧**完全一致**(同一份 `normalizeExtrudeOptions`):位置形态\n * `cad.extrude(face, 5)` 沿 +Z,`cad.extrude(face, [x,y,z])` 沿该向量;\n * 缺省法向 `[0,0,1]` 不自动改用面法向——那是两条链共同的行为约定,不在这里分叉。\n *\n * @param input - the mesh-chain face to extrude.\n * @param params - the same positional/object forms the BREP branch accepts.\n * @returns the new mesh solid (a new mesh part).\n * @throws {MeshUnsupportedError} on the mesh path when `upTo` is requested.\n */\nfunction extrudeMeshChain(input: Shape, params: unknown): Shape {\n if (!input) throw new Error('[api/extrude] no input geometry')\n if (isCurveShape(input)) {\n throw new Error(\n 'E_EXTRUDE_NEEDS_FACE: extrude requires a 2D face input, got a 1D curve (kind=\"curve\")',\n )\n }\n const entry = meshFaceEntry(input, 'extrude')\n\n const o = normalizeExtrudeOptions(params)\n assertExtrudeOptions(o)\n if (o.upTo !== undefined) {\n throw new MeshUnsupportedError(\n 'E_MESH_SOLID_UNSUPPORTED: extrude upTo is not available on the mesh path — it needs the precision ' +\n 'chain to intersect and trim against a target face. Give an explicit length instead',\n getCurrentStmt(),\n )\n }\n\n const normal = new Vec3C(...(o.normal ?? [0, 0, 1])).normalize()\n const sign = o.mode === 'backward' ? -1 : 1\n const v: Vec3 = [normal.x * o.length! * sign, normal.y * o.length! * sign, normal.z * o.length! * sign]\n\n let solid: BrepHandle\n try {\n solid = entry.kernel.extrude(entry.face, v[0]!, v[1]!, v[2]!)\n } catch (cause) {\n throw meshKernelFailure(\n 'extrude',\n 'E_EXTRUDE_FAILED',\n `extruding a mesh-chain face by ${o.length} along [${v.join(', ')}]`,\n cause,\n )\n }\n return meshSolidProductWithBackend(entry.backend, solid)\n}\n\n/**\n * 沿 normal 拉伸几何(面 → 棱柱)。\n *\n * up-to 模式(`upTo`)与长度模式(`length`)二选一;长度模式委托生成投影\n * (brepjs extrude 为唯一引擎),up-to 模式走半空间组合。\n *\n * **网格链**(`meshEngines: ['brepkit']`,方案 2026-10-01 §4 Phase 3):输入是\n * `cad.sketchOnFace` 在网格实体识别面上铺出的网格链面时,本 op 沿同一份方向语义\n * 拉伸出**一个新的网格零件**。网格链上不支持 `upTo`\n * (需精度链求交裁切)——会以 `E_MESH_SOLID_UNSUPPORTED` 明确拒绝,不静默当定长拉伸。\n *\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name extrude\n * @returns Shape 拉伸后的几何。\n * @param input - 目标几何(平面面)。type:Shape required:true\n * @param params.length - 总拉伸量(mm,>0)。up-to 模式下无需给。type:number\n * @param params.normal - 拉伸方向(世界坐标)。type:[x,y,z] 默认 [0,0,1]\n * @param params.mode - 沿 normal 的前进方向:forward 正向 / backward 反向。type:'forward' | 'backward' 默认 'forward'\n * @param params.upTo - 拉伸到面:FaceTopoRef 指定面 / 'last' 支持体远端面 / 'first' 近端面(需 baseFeature)。提供时忽略 length。type:'last' | 'first' | FaceTopoRef\n * @param params.baseFeature - upTo 'last'/'first' 的支持体几何(累积支持体)。type:Shape\n * @param params.offset - 截断面沿其法向的偏移(mm)。type:number 默认 0\n * @example\n * const p = await cad.extrude(part0, [0, 0, 10])\n * const p = await cad.extrude(part0, { length: 10 })\n * const p = await cad.extrude(sk, { upTo: cad.faceRef(part0, 3) })\n * const p = await cad.extrude(sk, { upTo: 'last', baseFeature: part0 })\n */\nexport const extrude = defineOp({\n name: 'extrude',\n meshEngines: ['brepkit'],\n mesh(input: Shape, params: unknown): Shape {\n return extrudeMeshChain(input, params)\n },\n brep: async (input: Shape, params: unknown): Promise<Shape> => {\n if (!input) throw new Error('[api/extrude] no input geometry')\n // Phase 3 执行前预检:1D 曲线(wire / helix / sketch as:'wire')不是面,不得落进\n // 内核深层才报「操作失败」——维度不符在调用内核前明确拒绝(1D 判别位 kind='curve')。\n if (isCurveShape(input)) {\n throw new Error(\n 'E_EXTRUDE_NEEDS_FACE: extrude requires a 2D face input, got a 1D curve (kind=\"curve\")',\n )\n }\n const o = normalizeExtrudeOptions(params)\n assertExtrudeOptions(o)\n // A2: 拉伸方向同时是链根建表的候选轴(extrudeConstructRoles 的 hintAxis),\n // 两条路径(定长 / up-to)都要用,故提到分支之前。\n const normal = new Vec3C(...(o.normal ?? [0, 0, 1])).normalize()\n\n if (o.upTo !== undefined) {\n const kernel = getBrepApi()\n const inputSolid = brepOf(input) as BrepHandle | undefined\n if (inputSolid === undefined) throw new Error('[api/extrude] input is not BREP')\n const clipped = extrudeUpToSolid(kernel, inputSolid, o)\n // E3-b(2026-09-23,同 revolve 修法):不能对投影产物再走一次 fromBrep——\n // 同语句 registeredStmtId 去重会吞掉第二次登记(part 键保持空表,下游\n // fillet/chamfer 的 edgeRef 报 nameless shape)。upTo 路径不经过投影/\n // adoptOut,fromBrep 只在此走一次,roleTable 直挂 + solid 句柄登记。\n const origin = String(getCurrentStmt()?.id ?? '')\n return fromBrep(solidToShape(kernel, clipped), {\n solid: clipped,\n roleTable: new Map([[origin, extrudeConstructRoles(kernel, clipped, normal.toArray() as Vec3)]]),\n })\n }\n\n // 长度形态:委托生成投影(生成投影自带 Result 翻转 / adopt 收养)\n const sign = o.mode === 'backward' ? -1 : 1\n const v: Vec3 = [normal.x * o.length! * sign, normal.y * o.length! * sign, normal.z * o.length! * sign]\n let result: Shape\n // GOTCHA:projectedExtrude 是 occt-gated 的生成投影 op,\n // 在 brepkit 引擎下执行前即抛 E_BREP_UNSUPPORTED。brepkit 有原生 L1 extrude\n // (face→solid),直接走 kernel.extrude——与 revolve.ts 同路径(不经生成投影)。\n // occt 路径保持 projectedExtrude 不变,不回退既有几何/命名行为。\n if (getBackends().config.brepEngineId === 'brepkit') {\n const kernel = getBrepApi()\n const faceHandle = brepOf(input) as BrepHandle | undefined\n if (faceHandle === undefined) throw new Error('[api/extrude] brepkit path: input is not BREP')\n const solid = kernel.extrude(faceHandle, v[0]!, v[1]!, v[2]!)\n result = fromBrep(solidToShape(kernel, solid), { solid })\n } else {\n result = (await projectedExtrude(input, v)) as Shape\n }\n // E3 后续:委托路径同样要建链根表(投影只给几何,命名是 faijs 语义)。\n // E3-b(2026-09-23,同 revolve 修法):不能对投影产物再走一次 fromBrep——\n // 同语句 registeredStmtId 去重会吞掉第二次登记(part 键保持空表,下游\n // fillet/chamfer 的 edgeRef 报 `input shape has no role table`)。改经\n // runtimeLineage.recordOutput 落语句键表 + part 键权威位。\n // D12(2026-09-24):取内核走 getBrepApi;引擎未初始化 → 跳过建表(纯 mesh 结果)。\n let kernel: BrepEngineApi | null = null\n try { kernel = getBrepApi() } catch { /* no engine -> skip role table */ }\n const solid = kernel ? (brepOf(result) as BrepHandle | undefined) : undefined\n if (kernel && solid) {\n const origin = String(getCurrentStmt()?.id ?? '')\n const table = new Map([[origin, extrudeConstructRoles(kernel, solid, normal.toArray() as Vec3)]])\n const part = getCurrentStmt()?.outputs?.[0]\n runtimeLineage.recordOutput(origin as never, table, solid as never, part as never)\n }\n return result\n },\n naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [{ kind: 'semantic', name: 'top' }, { kind: 'semantic', name: 'bottom' }, { kind: 'wall', index: 0 }] } } as Provenance,\n\n paramDims: { length: 'length', offset: 'length', normal: 'plain' },\n})\n"]}
|
package/dist/api/face-ref.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* 绝不静默拿序号硬取。
|
|
16
16
|
*/
|
|
17
17
|
import { getBrepApi } from '../brep/handle-bridge.js';
|
|
18
|
-
import {
|
|
18
|
+
import { hasBrep } from '../shape.js';
|
|
19
19
|
import { captureFaceHint, findOriginRole, TopoRefError } from '../topology/naming/index.js';
|
|
20
20
|
import { buildEdgeResolutionContext } from './topo-resolve.js';
|
|
21
21
|
/**
|
|
@@ -44,7 +44,7 @@ export function faceRef(of, faceOrdinal) {
|
|
|
44
44
|
if (!kernel) {
|
|
45
45
|
throw new TopoRefError('E_TOPO_MESH_UNSUPPORTED', 'face', 'faceRef: topology references are BREP-only (mesh path unsupported)');
|
|
46
46
|
}
|
|
47
|
-
if (!
|
|
47
|
+
if (!hasBrep(of)) {
|
|
48
48
|
throw new TopoRefError('E_TOPO_MESH_UNSUPPORTED', 'face', 'faceRef: input shape has no BREP solid (mesh shapes do not carry topology identity)');
|
|
49
49
|
}
|
|
50
50
|
const ctx = buildEdgeResolutionContext(kernel, of);
|
package/dist/api/face-ref.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"face-ref.js","sourceRoot":"","sources":["../../src/api/face-ref.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"face-ref.js","sourceRoot":"","sources":["../../src/api/face-ref.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAClC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAElF,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AAE3D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,OAAO,CAAC,EAAS,EAAE,WAAmB;IACpD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,qDAAqD,WAAW,GAAG,CAAC,CAAA;IACzH,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,mDAAmD;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,YAAY,CAAC,yBAAyB,EAAE,MAAM,EAAE,oEAAoE,CAAC,CAAA;IACjI,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QACjB,MAAM,IAAI,YAAY,CAAC,yBAAyB,EAAE,MAAM,EAAE,qFAAqF,CAAC,CAAA;IAClJ,CAAC;IAED,MAAM,GAAG,GAAG,0BAA0B,CAAC,MAAM,EAAE,EAAY,CAAC,CAAA;IAC5D,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,2CAA2C,CAAC,CAAA;IAEzG,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,WAAW,CAAC,CAAA;IAC7D,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,IAAI,YAAY,CACpB,kBAAkB,EAClB,MAAM,EACN,yBAAyB,WAAW,qBAAqB,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAC7E,CAAA;IACH,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAA;IAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,yDAAyD,CAAC,CAAA;IAC/G,CAAC;IACD,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,WAAW,CAAC,CAAA;IACnF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,yBAAyB,WAAW,sBAAsB,CAAC,CAAA;IAChH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAA;AAC7G,CAAC","sourcesContent":["/**\n * api face-ref — 面引用查询:把「面序号」解析成 `FaceTopoRef`(1 起)\n *\n * extrude 的 `upTo` 参数(拉伸到面,PadTest UpToFace 链路)需要指向\n * 「某个实体上第 N 张面」的引用。外部格式(FCStd 的 `UpToFace` LinkSub 等)\n * 只给序号,本模块与 `edge-ref.ts` 同构:在内核现场枚举里取第 N 张面,\n * 经输入 Shape 的命名槽(RoleTable + subShapeHashes)反查它的\n * `{origin, role}` 血统,合成 `FaceTopoRef`。\n *\n * 序号语义(GOTCHA):与 `edgeRef` 一致,1 起 == FreeCAD 的 `FaceN`\n * (`getSubShapes(solid,'face')` 用 TopExp::MapShapes + IndexedMap 枚举,\n * 与 `edge-ref.ts` 头注同源已记档)。\n *\n * 纯查询:同步、无副作用、不改 Shape;定不了案一律抛 `TopoRefError`,\n * 绝不静默拿序号硬取。\n */\n\nimport type { Shape } from '../mesh/types'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { hasBrep } from '../shape'\nimport { captureFaceHint, findOriginRole, TopoRefError } from '../topology/naming'\nimport type { FaceTopoRef } from '../topology/naming'\nimport { buildEdgeResolutionContext } from './topo-resolve'\n\n/**\n * 查询几何体第 N 张面的 `FaceTopoRef`,供 `cad.extrude` 的 `upTo` 等参数使用:\n * `cad.extrude(part0, { upTo: cad.faceRef(part0, 3) })`。\n *\n * 定不了案(无 BREP / 序号越界 / 面无 role 血统)抛 `TopoRefError`。\n * @group 查询\n * @inputs 1\n * @async false\n * @qual ok\n * @name faceRef\n * @returns FaceTopoRef 该面的拓扑引用(origin/role 血统 + 几何 hint)。\n * @param of - 目标几何(BREP 实体所在的 Shape)。type:Shape required:true\n * @param faceOrdinal - 面序号(1 起;等于 FreeCAD 的 `FaceN`)。type:number required:true\n * @note 序号 1 起,与命名层 `TopoRef.ordinal` 及 FreeCAD `FaceN` 同序(`getSubShapes(solid,'face')` 用 TopExp::MapShapes + IndexedMap 枚举)。\n * @example\n * const part1 = cad.extrude(sk, { upTo: cad.faceRef(part0, 3) })\n */\nexport function faceRef(of: Shape, faceOrdinal: number): FaceTopoRef {\n if (!Number.isInteger(faceOrdinal) || faceOrdinal < 1) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', `faceRef: faceOrdinal must be an integer >= 1 (got ${faceOrdinal})`)\n }\n const kernel = getBrepApi()\n // Phase 1.9(D6/§3):mesh 路径不支持拓扑引用——静态判定、显式抛错,不静默降级\n if (!kernel) {\n throw new TopoRefError('E_TOPO_MESH_UNSUPPORTED', 'face', 'faceRef: topology references are BREP-only (mesh path unsupported)')\n }\n if (!hasBrep(of)) {\n throw new TopoRefError('E_TOPO_MESH_UNSUPPORTED', 'face', 'faceRef: input shape has no BREP solid (mesh shapes do not carry topology identity)')\n }\n\n const ctx = buildEdgeResolutionContext(kernel, of as object)\n if (!ctx) throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', 'faceRef: input has no BREP naming context')\n\n const face = ctx.faces.find((f) => f.ordinal === faceOrdinal)\n if (!face || face.handle === undefined) {\n throw new TopoRefError(\n 'E_TOPO_NOT_FOUND',\n 'face',\n `faceRef: face ordinal ${faceOrdinal} out of range [1, ${ctx.faces.length}]`,\n )\n }\n\n const table = ctx.roleTable\n if (!table) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', 'faceRef: input shape has no role table (nameless shape)')\n }\n const found = findOriginRole(table, ctx.faces.map((f) => f.hash ?? 0), faceOrdinal)\n if (!found) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', `faceRef: face ordinal ${faceOrdinal} has no role lineage`)\n }\n\n return { kind: 'face', origin: found.origin, role: found.role, hint: captureFaceHint(kernel, face.handle) }\n}\n"]}
|
|
@@ -33,7 +33,7 @@ import { buildEdgeResolutionContext } from './topo-resolve.js';
|
|
|
33
33
|
/** BREP 输入守卫:取 BREP 句柄,无则报错。 */
|
|
34
34
|
function requireBrep(input, op) {
|
|
35
35
|
const handle = brepOf(input);
|
|
36
|
-
if (
|
|
36
|
+
if (handle === undefined)
|
|
37
37
|
throw new Error(`E_${op.toUpperCase()}_NO_BREP: ${op} input is not BREP`);
|
|
38
38
|
return handle;
|
|
39
39
|
}
|
|
@@ -211,7 +211,7 @@ export const removeHolesFromFace = defineOp({
|
|
|
211
211
|
throw new Error('E_REMOVEHOLES_NO_FACE: removeHolesFromFace requires a face shape');
|
|
212
212
|
const kernel = getBrepApi();
|
|
213
213
|
const handle = brepOf(face);
|
|
214
|
-
if (
|
|
214
|
+
if (handle === undefined)
|
|
215
215
|
throw new Error('E_REMOVEHOLES_NO_BREP: removeHolesFromFace input is not BREP');
|
|
216
216
|
return adopt(kernel, kernel.removeHolesFromFace(handle));
|
|
217
217
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-repair.js","sourceRoot":"","sources":["../../src/api/feature-repair.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api feature-repair — L1 薄包装族(手写 op,Phase 5)\n *\n * 六条 L1 已有动作的手写薄包装,全部走 `getBrepApi()`(D12):\n * - `defeature(shape, faces)` — 移除特征面(孔/凸台等)\n * - `removeHolesFromFace(face)` — 移除面上的孔\n * - `reverseShape(shape)` — 反转壳体朝向 —— **occt-only**(见下)\n * - `unifySameDomain(shape)` — 合并同域面/边\n * - `sew(shapes, tolerance?)` — 缝合壳\n * - `sewAndSolidify(shapes, tolerance?)` — 缝合并固化为实体\n *\n * 每条都极薄:解析入参 → 直调 L1 → 收养。选面口径与 `shell`/`draft` 一致\n * (FaceTopoRef[],设计原则 4)。\n *\n * 引擎声明(**逐条判定,不整族一刀切**):\n * - `reverseShape` 声明 `engines: ['occt']` —— 实证收窄:brepkit 实测在 **op 级**\n * 失败(`invalid solid handle: index N is out of bounds`,callee = reverseShape,\n * 非输入构造侧),静态门须在执行前拒绝。\n * - 其余五条保持中立(无 engines)。\n * 注意 `unifySameDomain` 在 brepkit 上**可用但语义有差**(会把体重新居中),\n * 未收窄 —— 缺证据表明它不可用,不擅自扩大范围。\n *\n * 未覆盖(诚实留档,本轮未验):`defeature` / `sew` / `sewAndSolidify` /\n * `removeHolesFromFace` 在 brepkit 上的 op 级行为未取得干净证据(探针的面输入\n * 先撞到 faceRef/输入构造侧限制),故不做引擎声明。\n */\n\nimport type { Shape } from '../mesh/types'\nimport type { BrepHandle } from '../brep/engine/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { brepOf, fromBrep } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { FaceTopoRef } from '../topology/naming'\nimport { resolveTopoRef, TopoRefError } from '../topology/naming'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { buildEdgeResolutionContext } from './topo-resolve'\n\ntype ProvenanceLike = Provenance\n\n/** BREP 输入守卫:取 BREP 句柄,无则报错。 */\nfunction requireBrep(input: Shape, op: string): BrepHandle {\n const handle = brepOf(input) as BrepHandle | undefined\n if (!handle) throw new Error(`E_${op.toUpperCase()}_NO_BREP: ${op} input is not BREP`)\n return handle\n}\n\n/** 解析 FaceTopoRef[] → 句柄数组(shell/draft 同款口径)。 */\nfunction resolveFaces(kernel: ReturnType<typeof getBrepApi>, input: Shape, refs: FaceTopoRef[], op: string): BrepHandle[] {\n const ctx = buildEdgeResolutionContext(kernel, input as object)\n if (!ctx) throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', `${op}: input has no BREP naming context`)\n return refs.map((ref) => {\n if (!ref || (ref as { kind?: unknown }).kind !== 'face') {\n throw new Error(`E_${op.toUpperCase()}_BAD_FACE_REF: every faces entry must be a FaceTopoRef (cad.faceRef)`)\n }\n const r = resolveTopoRef(ref, ctx)\n if (r.handle === undefined) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', `${op}: face resolved without handle (${ref.origin}/${ref.role})`)\n }\n return r.handle as BrepHandle\n })\n}\n\n/** 借入一组输入 Shape → 句柄数组(sew 族)。 */\nfunction borrowHandles(shapes: Shape[], op: string): BrepHandle[] {\n if (!Array.isArray(shapes) || shapes.length === 0) {\n throw new Error(`E_${op.toUpperCase()}_NO_SHAPES: ${op} requires a non-empty array of shapes`)\n }\n return shapes.map((s) => {\n const h = brepOf(s) as BrepHandle | undefined\n if (!h) throw new Error(`E_${op.toUpperCase()}_NO_BREP: ${op} input shape is not BREP`)\n return h\n })\n}\n\nfunction adopt(kernel: ReturnType<typeof getBrepApi>, handle: BrepHandle): Shape {\n return fromBrep(solidToShape(kernel, handle), { solid: handle })\n}\n\nconst kernelNaming = { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as ProvenanceLike\n\n/**\n * 移除特征面(孔/凸台等),恢复基础形状。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name defeature\n * @note 中立 op:L1 defeature 两引擎同实现。仅 BREP 可用。\n * @returns Shape 移除特征后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param faces - 要移除的面(FaceTopoRef[],cad.faceRef 产物)。type:FaceTopoRef[] required:true\n * @example\n * const base = await cad.defeature(part0, [cad.faceRef(part0, 5)])\n */\nexport const defeature = defineOp({\n brep(input: Shape, faces: FaceTopoRef[]) {\n if (!Array.isArray(faces) || faces.length === 0) {\n throw new Error('E_DEFEATURE_NO_FACES: defeature requires at least one FaceTopoRef')\n }\n const kernel = getBrepApi()\n const solid = requireBrep(input, 'defeature')\n const handles = resolveFaces(kernel, input, faces, 'defeature')\n return adopt(kernel, kernel.defeature(solid, handles))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/**\n * 反转壳体朝向(内表面 ↔ 外表面)。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name reverseShape\n * @note **occt-only**(`engines: ['occt']`,实证收窄):brepkit 实测在 op 级抛\n * `invalid solid handle: index N is out of bounds`(非输入侧失败),\n * 故由静态门在执行前拒绝而非等到运行时。产物 `getVolume` 返回**有向**体积\n * (朝向反转 ⇒ 符号翻转)。仅 BREP 可用。\n * @returns Shape 朝向反转后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @example\n * const flipped = await cad.reverseShape(sh)\n */\nexport const reverseShape = defineOp({\n // 实证收窄(2026-09-24):brepkit op 级失败 → 静态门提前拒绝。\n engines: ['occt'],\n brep(input: Shape) {\n const kernel = getBrepApi()\n const solid = requireBrep(input, 'reverseShape')\n return adopt(kernel, kernel.reverseShape(solid))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/**\n * 合并同域面/边(去除被分割成多片的冗余细分)。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name unifySameDomain\n * @note 中立 op:L1 unifySameDomain 两引擎同实现。仅 BREP 可用。\n * @returns Shape 合并后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @example\n * const merged = await cad.unifySameDomain(part0)\n */\nexport const unifySameDomain = defineOp({\n brep(input: Shape) {\n const kernel = getBrepApi()\n const solid = requireBrep(input, 'unifySameDomain')\n return adopt(kernel, kernel.unifySameDomain(solid))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/** `cad.sew` / `cad.sewAndSolidify` 公共参数。 */\nexport interface SewParams {\n /** 缝合容差(mm,可选)。 */\n tolerance?: number\n}\n\n/**\n * 缝合:把一组面/壳沿公共边缝成一张壳。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name sew\n * @note 中立 op:L1 sew 两引擎同实现。产物是壳(不保证闭合);要实体用 sewAndSolidify。\n * @returns Shape 缝合后的壳。\n * @param shapes - 面/壳集合。type:Shape[] required:true\n * @param params.tolerance - 缝合容差(mm)。type:number required:false\n * @example\n * const shellShape = await cad.sew([f1, f2, f3], { tolerance: 1e-5 })\n */\nexport const sew = defineOp({\n brep(shapes: Shape[], params?: SewParams) {\n const kernel = getBrepApi()\n const handles = borrowHandles(shapes, 'sew')\n return adopt(kernel, kernel.sew(handles, params?.tolerance))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/**\n * 缝合并固化为实体:缝合后若闭合则生成 solid。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name sewAndSolidify\n * @note 中立 op:L1 sewAndSolidify 两引擎同实现。仅 BREP 可用。\n * @returns Shape 缝合固化后的实体。\n * @param shapes - 面/壳集合。type:Shape[] required:true\n * @param params.tolerance - 缝合容差(mm)。type:number required:false\n * @example\n * const solid = await cad.sewAndSolidify([f1, f2, f3, f4, f5, f6])\n */\nexport const sewAndSolidify = defineOp({\n brep(shapes: Shape[], params?: SewParams) {\n const kernel = getBrepApi()\n const handles = borrowHandles(shapes, 'sewAndSolidify')\n return adopt(kernel, kernel.sewAndSolidify(handles, params?.tolerance))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/**\n * 移除面(或实体某面)上的孔。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name removeHolesFromFace\n * @note 中立 op:L1 removeHolesFromFace 两引擎同实现。入参为含孔的面 Shape\n * (L1 形参是面句柄;借入输入 Shape 的 BREP 槽位句柄)。\n * @returns Shape 去孔后的面。\n * @param face - 含孔的面几何。type:Shape required:true\n * @example\n * const plain = await cad.removeHolesFromFace(faceWithHoles)\n */\nexport const removeHolesFromFace = defineOp({\n brep(face: Shape) {\n if (!face) throw new Error('E_REMOVEHOLES_NO_FACE: removeHolesFromFace requires a face shape')\n const kernel = getBrepApi()\n const handle = brepOf(face) as BrepHandle | undefined\n if (!handle) throw new Error('E_REMOVEHOLES_NO_BREP: removeHolesFromFace input is not BREP')\n return adopt(kernel, kernel.removeHolesFromFace(handle))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n"]}
|
|
1
|
+
{"version":3,"file":"feature-repair.js","sourceRoot":"","sources":["../../src/api/feature-repair.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api feature-repair — L1 薄包装族(手写 op,Phase 5)\n *\n * 六条 L1 已有动作的手写薄包装,全部走 `getBrepApi()`(D12):\n * - `defeature(shape, faces)` — 移除特征面(孔/凸台等)\n * - `removeHolesFromFace(face)` — 移除面上的孔\n * - `reverseShape(shape)` — 反转壳体朝向 —— **occt-only**(见下)\n * - `unifySameDomain(shape)` — 合并同域面/边\n * - `sew(shapes, tolerance?)` — 缝合壳\n * - `sewAndSolidify(shapes, tolerance?)` — 缝合并固化为实体\n *\n * 每条都极薄:解析入参 → 直调 L1 → 收养。选面口径与 `shell`/`draft` 一致\n * (FaceTopoRef[],设计原则 4)。\n *\n * 引擎声明(**逐条判定,不整族一刀切**):\n * - `reverseShape` 声明 `engines: ['occt']` —— 实证收窄:brepkit 实测在 **op 级**\n * 失败(`invalid solid handle: index N is out of bounds`,callee = reverseShape,\n * 非输入构造侧),静态门须在执行前拒绝。\n * - 其余五条保持中立(无 engines)。\n * 注意 `unifySameDomain` 在 brepkit 上**可用但语义有差**(会把体重新居中),\n * 未收窄 —— 缺证据表明它不可用,不擅自扩大范围。\n *\n * 未覆盖(诚实留档,本轮未验):`defeature` / `sew` / `sewAndSolidify` /\n * `removeHolesFromFace` 在 brepkit 上的 op 级行为未取得干净证据(探针的面输入\n * 先撞到 faceRef/输入构造侧限制),故不做引擎声明。\n */\n\nimport type { Shape } from '../mesh/types'\nimport type { BrepHandle } from '../brep/engine/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { brepOf, fromBrep } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { FaceTopoRef } from '../topology/naming'\nimport { resolveTopoRef, TopoRefError } from '../topology/naming'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { buildEdgeResolutionContext } from './topo-resolve'\n\ntype ProvenanceLike = Provenance\n\n/** BREP 输入守卫:取 BREP 句柄,无则报错。 */\nfunction requireBrep(input: Shape, op: string): BrepHandle {\n const handle = brepOf(input) as BrepHandle | undefined\n if (handle === undefined) throw new Error(`E_${op.toUpperCase()}_NO_BREP: ${op} input is not BREP`)\n return handle\n}\n\n/** 解析 FaceTopoRef[] → 句柄数组(shell/draft 同款口径)。 */\nfunction resolveFaces(kernel: ReturnType<typeof getBrepApi>, input: Shape, refs: FaceTopoRef[], op: string): BrepHandle[] {\n const ctx = buildEdgeResolutionContext(kernel, input as object)\n if (!ctx) throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', `${op}: input has no BREP naming context`)\n return refs.map((ref) => {\n if (!ref || (ref as { kind?: unknown }).kind !== 'face') {\n throw new Error(`E_${op.toUpperCase()}_BAD_FACE_REF: every faces entry must be a FaceTopoRef (cad.faceRef)`)\n }\n const r = resolveTopoRef(ref, ctx)\n if (r.handle === undefined) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'face', `${op}: face resolved without handle (${ref.origin}/${ref.role})`)\n }\n return r.handle as BrepHandle\n })\n}\n\n/** 借入一组输入 Shape → 句柄数组(sew 族)。 */\nfunction borrowHandles(shapes: Shape[], op: string): BrepHandle[] {\n if (!Array.isArray(shapes) || shapes.length === 0) {\n throw new Error(`E_${op.toUpperCase()}_NO_SHAPES: ${op} requires a non-empty array of shapes`)\n }\n return shapes.map((s) => {\n const h = brepOf(s) as BrepHandle | undefined\n if (!h) throw new Error(`E_${op.toUpperCase()}_NO_BREP: ${op} input shape is not BREP`)\n return h\n })\n}\n\nfunction adopt(kernel: ReturnType<typeof getBrepApi>, handle: BrepHandle): Shape {\n return fromBrep(solidToShape(kernel, handle), { solid: handle })\n}\n\nconst kernelNaming = { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as ProvenanceLike\n\n/**\n * 移除特征面(孔/凸台等),恢复基础形状。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name defeature\n * @note 中立 op:L1 defeature 两引擎同实现。仅 BREP 可用。\n * @returns Shape 移除特征后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param faces - 要移除的面(FaceTopoRef[],cad.faceRef 产物)。type:FaceTopoRef[] required:true\n * @example\n * const base = await cad.defeature(part0, [cad.faceRef(part0, 5)])\n */\nexport const defeature = defineOp({\n brep(input: Shape, faces: FaceTopoRef[]) {\n if (!Array.isArray(faces) || faces.length === 0) {\n throw new Error('E_DEFEATURE_NO_FACES: defeature requires at least one FaceTopoRef')\n }\n const kernel = getBrepApi()\n const solid = requireBrep(input, 'defeature')\n const handles = resolveFaces(kernel, input, faces, 'defeature')\n return adopt(kernel, kernel.defeature(solid, handles))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/**\n * 反转壳体朝向(内表面 ↔ 外表面)。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name reverseShape\n * @note **occt-only**(`engines: ['occt']`,实证收窄):brepkit 实测在 op 级抛\n * `invalid solid handle: index N is out of bounds`(非输入侧失败),\n * 故由静态门在执行前拒绝而非等到运行时。产物 `getVolume` 返回**有向**体积\n * (朝向反转 ⇒ 符号翻转)。仅 BREP 可用。\n * @returns Shape 朝向反转后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @example\n * const flipped = await cad.reverseShape(sh)\n */\nexport const reverseShape = defineOp({\n // 实证收窄(2026-09-24):brepkit op 级失败 → 静态门提前拒绝。\n engines: ['occt'],\n brep(input: Shape) {\n const kernel = getBrepApi()\n const solid = requireBrep(input, 'reverseShape')\n return adopt(kernel, kernel.reverseShape(solid))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/**\n * 合并同域面/边(去除被分割成多片的冗余细分)。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name unifySameDomain\n * @note 中立 op:L1 unifySameDomain 两引擎同实现。仅 BREP 可用。\n * @returns Shape 合并后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @example\n * const merged = await cad.unifySameDomain(part0)\n */\nexport const unifySameDomain = defineOp({\n brep(input: Shape) {\n const kernel = getBrepApi()\n const solid = requireBrep(input, 'unifySameDomain')\n return adopt(kernel, kernel.unifySameDomain(solid))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/** `cad.sew` / `cad.sewAndSolidify` 公共参数。 */\nexport interface SewParams {\n /** 缝合容差(mm,可选)。 */\n tolerance?: number\n}\n\n/**\n * 缝合:把一组面/壳沿公共边缝成一张壳。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name sew\n * @note 中立 op:L1 sew 两引擎同实现。产物是壳(不保证闭合);要实体用 sewAndSolidify。\n * @returns Shape 缝合后的壳。\n * @param shapes - 面/壳集合。type:Shape[] required:true\n * @param params.tolerance - 缝合容差(mm)。type:number required:false\n * @example\n * const shellShape = await cad.sew([f1, f2, f3], { tolerance: 1e-5 })\n */\nexport const sew = defineOp({\n brep(shapes: Shape[], params?: SewParams) {\n const kernel = getBrepApi()\n const handles = borrowHandles(shapes, 'sew')\n return adopt(kernel, kernel.sew(handles, params?.tolerance))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/**\n * 缝合并固化为实体:缝合后若闭合则生成 solid。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name sewAndSolidify\n * @note 中立 op:L1 sewAndSolidify 两引擎同实现。仅 BREP 可用。\n * @returns Shape 缝合固化后的实体。\n * @param shapes - 面/壳集合。type:Shape[] required:true\n * @param params.tolerance - 缝合容差(mm)。type:number required:false\n * @example\n * const solid = await cad.sewAndSolidify([f1, f2, f3, f4, f5, f6])\n */\nexport const sewAndSolidify = defineOp({\n brep(shapes: Shape[], params?: SewParams) {\n const kernel = getBrepApi()\n const handles = borrowHandles(shapes, 'sewAndSolidify')\n return adopt(kernel, kernel.sewAndSolidify(handles, params?.tolerance))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n\n/**\n * 移除面(或实体某面)上的孔。\n * @group 修复\n * @inputs 1\n * @async true\n * @qual ok\n * @name removeHolesFromFace\n * @note 中立 op:L1 removeHolesFromFace 两引擎同实现。入参为含孔的面 Shape\n * (L1 形参是面句柄;借入输入 Shape 的 BREP 槽位句柄)。\n * @returns Shape 去孔后的面。\n * @param face - 含孔的面几何。type:Shape required:true\n * @example\n * const plain = await cad.removeHolesFromFace(faceWithHoles)\n */\nexport const removeHolesFromFace = defineOp({\n brep(face: Shape) {\n if (!face) throw new Error('E_REMOVEHOLES_NO_FACE: removeHolesFromFace requires a face shape')\n const kernel = getBrepApi()\n const handle = brepOf(face) as BrepHandle | undefined\n if (handle === undefined) throw new Error('E_REMOVEHOLES_NO_BREP: removeHolesFromFace input is not BREP')\n return adopt(kernel, kernel.removeHolesFromFace(handle))\n },\n naming: kernelNaming,\n\n paramDims: {},\n})\n"]}
|
|
@@ -31,7 +31,7 @@ function filletVariableBrep(input, edge, startRadius, endRadius) {
|
|
|
31
31
|
}
|
|
32
32
|
const kernel = getBrepApi();
|
|
33
33
|
const solid = brepOf(input);
|
|
34
|
-
if (
|
|
34
|
+
if (solid === undefined)
|
|
35
35
|
throw new Error('E_FILLETVAR_NO_BREP: filletVariable input is not BREP');
|
|
36
36
|
const ctx = buildEdgeResolutionContext(kernel, input);
|
|
37
37
|
if (!ctx)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fillet-variable.js","sourceRoot":"","sources":["../../src/api/fillet-variable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AAE3D,8CAA8C;AAC9C,SAAS,kBAAkB,CAAC,KAAY,EAAE,IAAiB,EAAE,WAAmB,EAAE,SAAiB;IACjG,IAAI,CAAC,IAAI,IAAK,IAA2B,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,mFAAmF,CAAC,CAAA;IACtG,CAAC;IACD,MAAM,KAAK,GAAI,IAA4B,CAAC,KAAK,CAAA;IACjD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC,CAAA;IACvG,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAA;QAC7F,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAA2B,CAAA;IACrD,IAAI,
|
|
1
|
+
{"version":3,"file":"fillet-variable.js","sourceRoot":"","sources":["../../src/api/fillet-variable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AAE3D,8CAA8C;AAC9C,SAAS,kBAAkB,CAAC,KAAY,EAAE,IAAiB,EAAE,WAAmB,EAAE,SAAiB;IACjG,IAAI,CAAC,IAAI,IAAK,IAA2B,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,mFAAmF,CAAC,CAAA;IACtG,CAAC;IACD,MAAM,KAAK,GAAI,IAA4B,CAAC,KAAK,CAAA;IACjD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC,CAAA;IACvG,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAA;QAC7F,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAA2B,CAAA;IACrD,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;IAEjG,MAAM,GAAG,GAAG,0BAA0B,CAAC,MAAM,EAAE,KAAe,CAAC,CAAA;IAC/D,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,kDAAkD,CAAC,CAAA;IAChH,MAAM,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACnC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,iDAAiD,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAA;IAClJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,MAAoB,EAAE,WAAW,EAAE,SAAS,CAAC,CAAA;IAC3F,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;IACrC,IAAI,CAAC,KAAY,EAAE,IAAiB,EAAE,EAAU,EAAE,EAAU;QAC1D,OAAO,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;IAChD,CAAC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE,EAAgB;IAE1E,SAAS,EAAE,EAAE;CACd,CAAC,CAAA","sourcesContent":["/**\n * api fillet-variable — 变半径圆角:单边起止半径(手写中立 op,Phase 5)\n *\n * 中立 op:L1 `filletVariable(solid, edge, startRadius, endRadius)` 在 occt 与\n * brepkit 两侧均有真实现(engine-method-map 实测 `dialect`)⇒ 走 `getBrepApi()`\n * (D12),不声明 engines(中立 op:实现只经 L1 契约面)。\n *\n * 这是 faijs 简化形态(单边 + 起止半径);旧版的 per-edge 回调形态\n * (`variableFillet`)维持 skip(状态化回调不可静态建模)。\n * 选边口径与 `fillet` 一致(EdgeTopoRef,faces 两面 role 线路)。\n */\n\nimport type { Shape } from '../mesh/types'\nimport type { BrepHandle } from '../brep/engine/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { brepOf, fromBrep } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { EdgeTopoRef } from '../topology/naming'\nimport { resolveTopoRef, TopoRefError } from '../topology/naming'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { buildEdgeResolutionContext } from './topo-resolve'\n\n/** BREP 路径:解析边引用 → L1 filletVariable → 收养。 */\nfunction filletVariableBrep(input: Shape, edge: EdgeTopoRef, startRadius: number, endRadius: number): Shape {\n if (!edge || (edge as { kind?: unknown }).kind !== 'edge') {\n throw new Error('E_FILLETVAR_BAD_EDGE_REF: edge must be an EdgeTopoRef (as consumed by cad.fillet)')\n }\n const faces = (edge as { faces?: unknown }).faces\n if (!Array.isArray(faces) || faces.length !== 2) {\n throw new Error('E_FILLETVAR_BAD_EDGE_REF: EdgeTopoRef.faces must be a two-entry RoleQualifier pair')\n }\n for (const r of [startRadius, endRadius]) {\n if (typeof r !== 'number' || !Number.isFinite(r) || r <= 0) {\n throw new Error('E_FILLETVAR_BAD_RADIUS: startRadius / endRadius must be positive numbers')\n }\n }\n const kernel = getBrepApi()\n const solid = brepOf(input) as BrepHandle | undefined\n if (solid === undefined) throw new Error('E_FILLETVAR_NO_BREP: filletVariable input is not BREP')\n\n const ctx = buildEdgeResolutionContext(kernel, input as object)\n if (!ctx) throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', 'filletVariable: input has no BREP naming context')\n const r = resolveTopoRef(edge, ctx)\n if (r.handle === undefined) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `filletVariable: edge resolved without handle (${edge.faces[0].role}/${edge.faces[1].role})`)\n }\n\n const result = kernel.filletVariable(solid, r.handle as BrepHandle, startRadius, endRadius)\n return fromBrep(solidToShape(kernel, result), { solid: result })\n}\n\n/**\n * 变半径圆角:对单条边施加从起点到终点的线性变半径圆角。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name filletVariable\n * @note 中立 op:L1 filletVariable 两引擎同实现。`r1 == r2` 时与 cad.fillet 等半径\n * 结果等价。旧版的 per-edge 回调变半径(variableFillet)不上脚本面。\n * 仅 BREP 可用。\n * @returns Shape 变半径圆角后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param edge - 目标边(EdgeTopoRef,同 cad.fillet 的 edges 条目)。type:EdgeTopoRef required:true\n * @param r1 - 起点半径(mm,>0)。type:number required:true\n * @param r2 - 终点半径(mm,>0)。type:number required:true\n * @example\n * const v = await cad.filletVariable(part0, partEdges[0], 1, 4)\n */\nexport const filletVariable = defineOp({\n brep(input: Shape, edge: EdgeTopoRef, r1: number, r2: number) {\n return filletVariableBrep(input, edge, r1, r2)\n },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n"]}
|
package/dist/api/fillet.js
CHANGED
|
@@ -84,7 +84,7 @@ function filletBrep(input, params) {
|
|
|
84
84
|
// L1 面(D12):filletWithHistory 是 L1,全链路中立。
|
|
85
85
|
const kernel = getBrepApi();
|
|
86
86
|
const solid = brepOf(input);
|
|
87
|
-
if (
|
|
87
|
+
if (solid === undefined)
|
|
88
88
|
throw new Error('E_FILLET_NO_BREP: fillet input is not BREP');
|
|
89
89
|
const edges = params.edges;
|
|
90
90
|
const radius = params.radius;
|
package/dist/api/fillet.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fillet.js","sourceRoot":"","sources":["../../src/api/fillet.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api fillet — fillet 圆角库函数(BREP-only)\n *\n * 平台分层(narrowing plan Phase 5,D11):**中立 op**——`filletWithHistory` 是\n * L1 核心面(brepkit 亦实现),实现全程走 L1(getBrepApi,D12),不声明 engines。\n * 实现体内不分支:两引擎都走 `filletWithRoleTable` 历史轨(见 `filletBrep`)。\n *\n * 与 chamfer 的差异:fillet 用 filletWithHistory 走面演化 + roleTable 传播\n * (chamfer 在 P5 同步改造)。M1 只支持等半径;M2 计划支持变半径与几何限定符。\n *\n * M1:\n * - 等半径(number):kernel.filletWithHistory(solid, edges, radius, hashes, bound)\n * - 走 filletWithRoleTable 传播 roleTable\n * - BREP-only:mesh 输入 → E_MESH_UNSUPPORTED(backend-dispatch 静态判定)\n *\n * M2(未实施):\n * - 变半径 [r1, r2]:filletVariable + 单边 + 不产 roleTable(降级)\n * - 几何限定符字符串选边(§4)\n */\n\nimport type { Shape } from '../mesh/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { filletWithRoleTable } from '../brep/face-evolution'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { getCurrentStmt } from '../runtime-state'\nimport { fromBrep, brepOf, inputRoleTable } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { BrepHandle } from '../brep/engine/types'\nimport type { EdgeTopoRef, ResolutionContext } from '../topology/naming'\nimport { resolveTopoRef, TopoRefError } from '../topology/naming'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { buildEdgeResolutionContext } from './topo-resolve'\nimport { meshKernelFailure, meshSolidEntry, meshSolidProduct, resolveMeshEdges } from './internal/mesh-solid-op'\n\n// ── 参数自校验(api 层被直接 import 时的防御层)──\n\n/** 边选择器校验选项。 */\nexport interface EdgeSelectorCheckOptions {\n /**\n * 允许 1 起序号作为边选择器(**仅网格链**;见 `resolveMeshEdges`)。\n *\n * 精度链不开这个口子:BREP 的边身份是 role 线路(两个相邻面的 `(origin, role)`),\n * 序号只是内核枚举序,跨特征会漂移——让精度链接受序号等于把\"可重放的引用\"降级成\n * \"这次跑出来的下标\"。近似链相反:没有 role 层,序号是唯一无歧义的指认方式。\n */\n readonly allowOrdinals?: boolean\n}\n\n/**\n * Validate fillet parameters: `edges` must be a non-empty array of EdgeTopoRef\n * (each with kind key \"edge\" and a two-entry faces pair) — or of 1-based\n * ordinals when `opts.allowOrdinals` (the mesh chain); `radius` must be a\n * positive number (M1: uniform radius only).\n * @param params the raw fillet operation parameters.\n * @param opts the selector-form options (mesh chain allows ordinals).\n */\nexport function assertFilletParams(\n params: Record<string, unknown>,\n opts?: EdgeSelectorCheckOptions,\n): void {\n const edges = params.edges\n if (!Array.isArray(edges) || edges.length === 0) {\n throw new Error('E_FILLET_NO_EDGES: fillet requires at least one edge')\n }\n for (const e of edges) {\n if (opts?.allowOrdinals && typeof e === 'number') {\n if (!Number.isInteger(e) || e < 1) {\n throw new Error('E_FILLET_BAD_EDGE_REF: an edge ordinal must be a positive integer (1-based)')\n }\n continue\n }\n if (!e || typeof e !== 'object' || (e as { kind?: unknown }).kind !== 'edge') {\n throw new Error('E_FILLET_BAD_EDGE_REF: every edge entry must be an EdgeTopoRef with kind:\"edge\"')\n }\n const faces = (e as { faces?: unknown }).faces\n if (!Array.isArray(faces) || faces.length !== 2) {\n throw new Error('E_FILLET_BAD_EDGE_REF: EdgeTopoRef.faces must be a two-entry RoleQualifier pair')\n }\n }\n const radius = params.radius\n if (typeof radius !== 'number' || !Number.isFinite(radius) || radius <= 0) {\n throw new Error('E_FILLET_BAD_RADIUS: fillet.radius must be a positive number')\n }\n}\n\n/** 解析一条 EdgeTopoRef → handle;失败抛命名层 TopoRefError。 */\nfunction resolveEdge(ctx: ResolutionContext, ref: EdgeTopoRef): BrepHandle {\n const r = resolveTopoRef(ref, ctx)\n if (r.handle === undefined) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `fillet: edge resolved without handle (${ref.faces[0].role}/${ref.faces[1].role})`)\n }\n return r.handle as BrepHandle\n}\n\n/**\n * 把内核 OcctError 回译成 E_FILLET_RADIUS_TOO_LARGE。\n *\n * OCCT 在半径超过邻面尺寸、三面交汇处、凹边处都可能失败。\n * 绝不可静默返回未圆角的原形状(§9 风险)。\n */\nfunction translateOcctError(err: unknown): Error {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('E_FILLET') || msg.includes('E_TOPO')) return err as Error\n return new Error(`E_FILLET_RADIUS_TOO_LARGE: OCCT fillet failed — ${msg}`)\n}\n\n/** BREP-only 主入口(M1 等半径 flow)。 */\nfunction filletBrep(input: Shape, params: Record<string, unknown>): Shape {\n // L1 面(D12):filletWithHistory 是 L1,全链路中立。\n const kernel = getBrepApi()\n const solid = brepOf(input) as BrepHandle | undefined\n if (!solid) throw new Error('E_FILLET_NO_BREP: fillet input is not BREP')\n\n const edges = params.edges as EdgeTopoRef[]\n const radius = params.radius as number\n const ctx = buildEdgeResolutionContext(kernel, input as object)\n if (!ctx) throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', 'fillet: input has no edge naming context')\n\n // 解析所有 EdgeTopoRef → Edge 句柄\n const edgeHandles = edges.map((e) => resolveEdge(ctx, e))\n\n // 输入 roleTable + outStmt(与 boolean.ts 同构)。Phase 1.6:origin=本次语句 StmtId。\n const inputTable = inputRoleTable(input) as ReadonlyMap<unknown, unknown> | undefined\n const outStmt = String(getCurrentStmt()?.id ?? '')\n\n let resultSolid: BrepHandle\n let faceEvolution: Map<number, number[]> | undefined\n let roleTable: ReadonlyMap<unknown, unknown> | undefined\n\n try {\n const r = filletWithRoleTable(\n kernel,\n solid,\n edgeHandles,\n radius,\n inputTable ?? new Map(),\n outStmt,\n )\n resultSolid = r.result\n faceEvolution = r.faceEvolution\n roleTable = r.roleTable\n } catch (err) {\n throw translateOcctError(err)\n }\n\n return fromBrep(\n solidToShape(kernel, resultSolid),\n { solid: resultSolid, faceEvolution, roleTable },\n )\n}\n\n/**\n * 网格实体路径:对近似拓扑里识别出的边倒圆角(方案 2026-10-01 §3.5 三明治)。\n *\n * 与 BREP 路径的三处实质差异,都是\"网格零件没有精度链、没有 role 层\"的直接后果:\n * - 边**按几何或序号**解析:`EdgeTopoRef` 走长度/中点匹配;**1 起序号**直接取自近似\n * 拓扑的 `edges` 数组下标 + 1(等长边靠几何分不开,序号是唯一无歧义的指认方式);\n * - 内核调用走 L1 裸 `kernel.fillet`(`filletWithHistory` 是精度链的面演化能力,\n * 近似拓扑没有 hash 演化可言,故**不产生** faceEvolution / roleTable,如实缺席\n * 而不是造一张恒等映射);\n * - 产物句柄写回后由 `meshSolidProduct` 重新三角化并重建近似拓扑。\n *\n * GOTCHA(2026-10-01 实测,见 `brepkit-kernel/mesh-solid-topology.test.ts`):\n * 一次请求里的**全部**边交给内核,会在共面边链(如圆柱端盖的 64 条边)上被整体\n * 拒绝——不是单条边不可倒,而是\"一次性磨圆会自交\"。故本实现**如实失败**,不自动\n * 拆成逐边重试(运行时换策略会掩盖几何事实)。要给共面边链倒角,请分多次调用,\n * 每次一组几何上互不相邻的边。\n *\n * @param input - the mesh-solid input.\n * @param params - the validated fillet parameters.\n * @returns the filleted mesh solid as a new mesh part.\n */\nfunction filletMeshSolid(input: Shape, params: Record<string, unknown>): Shape {\n const edges = params.edges as (number | EdgeTopoRef)[]\n const radius = params.radius as number\n const entry = meshSolidEntry(input, 'fillet')\n const edgeHandles = resolveMeshEdges(entry, edges, 'fillet')\n\n let result: BrepHandle\n try {\n result = entry.kernel.fillet(entry.solid, edgeHandles, radius)\n } catch (cause) {\n throw meshKernelFailure(\n 'fillet',\n 'E_FILLET_RADIUS_TOO_LARGE',\n `fillet(r=${radius}) on ${edgeHandles.length} edge(s)`,\n cause,\n )\n }\n return meshSolidProduct(entry, result)\n}\n\n/**\n * 在几何体上做圆角(等半径)。\n *\n * 两条路径都以 `meshEngines: ['brepkit']` 之外的事实为界:BREP 输入走\n * `filletWithHistory`(带面演化与 roleTable 传播);**网格实体**输入走网格后端\n * (近似拓扑无 role,边按几何或序号解析,无面演化)。非 BREP 的**裸网格**输入仍抛\n * `E_MESH_SOLID_UNSUPPORTED`——裸网格没有近似拓扑,没有边可选。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name fillet\n * @note `radius` 为正数(mm)。BREP 路径圆角后 roleTable 经 filletWithHistory 传播,\n * 后续特征仍可按 role 选面/选边;网格实体路径没有 role 层,边只能按几何或\n * 序号(近似拓扑 `edges` 数组下标 + 1)指认。\n * @returns Shape 圆角后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.edges - 参与圆角的边:相邻两面的 role 线路(EdgeTopoRef[]);网格链上也可用 1 起序号。type:EdgeTopoRef[] required:true\n * @param params.radius - 圆角半径(mm,>0)。type:number required:true\n * @example\n * const p = await cad.fillet(part0, { edges: [{ kind:'edge', faces:[{ origin:'box', role:'box:top' }, { origin:'box', role:'box:front' }], hint:{ kind:'edge' } }], radius:2 })\n * const q = await cad.fillet(meshPart, { edges: [3], radius: 1 })\n */\nexport const fillet = defineOp({\n meshEngines: ['brepkit'],\n mesh(input: Shape, params: Record<string, unknown>) {\n assertFilletParams(params, { allowOrdinals: true })\n return filletMeshSolid(input, params)\n },\n brep(input: Shape, params: Record<string, unknown>) {\n assertFilletParams(params)\n return filletBrep(input, params)\n },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n"]}
|
|
1
|
+
{"version":3,"file":"fillet.js","sourceRoot":"","sources":["../../src/api/fillet.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api fillet — fillet 圆角库函数(BREP-only)\n *\n * 平台分层(narrowing plan Phase 5,D11):**中立 op**——`filletWithHistory` 是\n * L1 核心面(brepkit 亦实现),实现全程走 L1(getBrepApi,D12),不声明 engines。\n * 实现体内不分支:两引擎都走 `filletWithRoleTable` 历史轨(见 `filletBrep`)。\n *\n * 与 chamfer 的差异:fillet 用 filletWithHistory 走面演化 + roleTable 传播\n * (chamfer 在 P5 同步改造)。M1 只支持等半径;M2 计划支持变半径与几何限定符。\n *\n * M1:\n * - 等半径(number):kernel.filletWithHistory(solid, edges, radius, hashes, bound)\n * - 走 filletWithRoleTable 传播 roleTable\n * - BREP-only:mesh 输入 → E_MESH_UNSUPPORTED(backend-dispatch 静态判定)\n *\n * M2(未实施):\n * - 变半径 [r1, r2]:filletVariable + 单边 + 不产 roleTable(降级)\n * - 几何限定符字符串选边(§4)\n */\n\nimport type { Shape } from '../mesh/types'\nimport { solidToShape } from '../brep/brep-ops'\nimport { filletWithRoleTable } from '../brep/face-evolution'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { getCurrentStmt } from '../runtime-state'\nimport { fromBrep, brepOf, inputRoleTable } from '../shape'\nimport { defineOp } from '../sdk'\nimport type { BrepHandle } from '../brep/engine/types'\nimport type { EdgeTopoRef, ResolutionContext } from '../topology/naming'\nimport { resolveTopoRef, TopoRefError } from '../topology/naming'\nimport type { Provenance } from '../topology/naming/lineage'\nimport { buildEdgeResolutionContext } from './topo-resolve'\nimport { meshKernelFailure, meshSolidEntry, meshSolidProduct, resolveMeshEdges } from './internal/mesh-solid-op'\n\n// ── 参数自校验(api 层被直接 import 时的防御层)──\n\n/** 边选择器校验选项。 */\nexport interface EdgeSelectorCheckOptions {\n /**\n * 允许 1 起序号作为边选择器(**仅网格链**;见 `resolveMeshEdges`)。\n *\n * 精度链不开这个口子:BREP 的边身份是 role 线路(两个相邻面的 `(origin, role)`),\n * 序号只是内核枚举序,跨特征会漂移——让精度链接受序号等于把\"可重放的引用\"降级成\n * \"这次跑出来的下标\"。近似链相反:没有 role 层,序号是唯一无歧义的指认方式。\n */\n readonly allowOrdinals?: boolean\n}\n\n/**\n * Validate fillet parameters: `edges` must be a non-empty array of EdgeTopoRef\n * (each with kind key \"edge\" and a two-entry faces pair) — or of 1-based\n * ordinals when `opts.allowOrdinals` (the mesh chain); `radius` must be a\n * positive number (M1: uniform radius only).\n * @param params the raw fillet operation parameters.\n * @param opts the selector-form options (mesh chain allows ordinals).\n */\nexport function assertFilletParams(\n params: Record<string, unknown>,\n opts?: EdgeSelectorCheckOptions,\n): void {\n const edges = params.edges\n if (!Array.isArray(edges) || edges.length === 0) {\n throw new Error('E_FILLET_NO_EDGES: fillet requires at least one edge')\n }\n for (const e of edges) {\n if (opts?.allowOrdinals && typeof e === 'number') {\n if (!Number.isInteger(e) || e < 1) {\n throw new Error('E_FILLET_BAD_EDGE_REF: an edge ordinal must be a positive integer (1-based)')\n }\n continue\n }\n if (!e || typeof e !== 'object' || (e as { kind?: unknown }).kind !== 'edge') {\n throw new Error('E_FILLET_BAD_EDGE_REF: every edge entry must be an EdgeTopoRef with kind:\"edge\"')\n }\n const faces = (e as { faces?: unknown }).faces\n if (!Array.isArray(faces) || faces.length !== 2) {\n throw new Error('E_FILLET_BAD_EDGE_REF: EdgeTopoRef.faces must be a two-entry RoleQualifier pair')\n }\n }\n const radius = params.radius\n if (typeof radius !== 'number' || !Number.isFinite(radius) || radius <= 0) {\n throw new Error('E_FILLET_BAD_RADIUS: fillet.radius must be a positive number')\n }\n}\n\n/** 解析一条 EdgeTopoRef → handle;失败抛命名层 TopoRefError。 */\nfunction resolveEdge(ctx: ResolutionContext, ref: EdgeTopoRef): BrepHandle {\n const r = resolveTopoRef(ref, ctx)\n if (r.handle === undefined) {\n throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', `fillet: edge resolved without handle (${ref.faces[0].role}/${ref.faces[1].role})`)\n }\n return r.handle as BrepHandle\n}\n\n/**\n * 把内核 OcctError 回译成 E_FILLET_RADIUS_TOO_LARGE。\n *\n * OCCT 在半径超过邻面尺寸、三面交汇处、凹边处都可能失败。\n * 绝不可静默返回未圆角的原形状(§9 风险)。\n */\nfunction translateOcctError(err: unknown): Error {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('E_FILLET') || msg.includes('E_TOPO')) return err as Error\n return new Error(`E_FILLET_RADIUS_TOO_LARGE: OCCT fillet failed — ${msg}`)\n}\n\n/** BREP-only 主入口(M1 等半径 flow)。 */\nfunction filletBrep(input: Shape, params: Record<string, unknown>): Shape {\n // L1 面(D12):filletWithHistory 是 L1,全链路中立。\n const kernel = getBrepApi()\n const solid = brepOf(input) as BrepHandle | undefined\n if (solid === undefined) throw new Error('E_FILLET_NO_BREP: fillet input is not BREP')\n\n const edges = params.edges as EdgeTopoRef[]\n const radius = params.radius as number\n const ctx = buildEdgeResolutionContext(kernel, input as object)\n if (!ctx) throw new TopoRefError('E_TOPO_NOT_FOUND', 'edge', 'fillet: input has no edge naming context')\n\n // 解析所有 EdgeTopoRef → Edge 句柄\n const edgeHandles = edges.map((e) => resolveEdge(ctx, e))\n\n // 输入 roleTable + outStmt(与 boolean.ts 同构)。Phase 1.6:origin=本次语句 StmtId。\n const inputTable = inputRoleTable(input) as ReadonlyMap<unknown, unknown> | undefined\n const outStmt = String(getCurrentStmt()?.id ?? '')\n\n let resultSolid: BrepHandle\n let faceEvolution: Map<number, number[]> | undefined\n let roleTable: ReadonlyMap<unknown, unknown> | undefined\n\n try {\n const r = filletWithRoleTable(\n kernel,\n solid,\n edgeHandles,\n radius,\n inputTable ?? new Map(),\n outStmt,\n )\n resultSolid = r.result\n faceEvolution = r.faceEvolution\n roleTable = r.roleTable\n } catch (err) {\n throw translateOcctError(err)\n }\n\n return fromBrep(\n solidToShape(kernel, resultSolid),\n { solid: resultSolid, faceEvolution, roleTable },\n )\n}\n\n/**\n * 网格实体路径:对近似拓扑里识别出的边倒圆角(方案 2026-10-01 §3.5 三明治)。\n *\n * 与 BREP 路径的三处实质差异,都是\"网格零件没有精度链、没有 role 层\"的直接后果:\n * - 边**按几何或序号**解析:`EdgeTopoRef` 走长度/中点匹配;**1 起序号**直接取自近似\n * 拓扑的 `edges` 数组下标 + 1(等长边靠几何分不开,序号是唯一无歧义的指认方式);\n * - 内核调用走 L1 裸 `kernel.fillet`(`filletWithHistory` 是精度链的面演化能力,\n * 近似拓扑没有 hash 演化可言,故**不产生** faceEvolution / roleTable,如实缺席\n * 而不是造一张恒等映射);\n * - 产物句柄写回后由 `meshSolidProduct` 重新三角化并重建近似拓扑。\n *\n * GOTCHA(2026-10-01 实测,见 `brepkit-kernel/mesh-solid-topology.test.ts`):\n * 一次请求里的**全部**边交给内核,会在共面边链(如圆柱端盖的 64 条边)上被整体\n * 拒绝——不是单条边不可倒,而是\"一次性磨圆会自交\"。故本实现**如实失败**,不自动\n * 拆成逐边重试(运行时换策略会掩盖几何事实)。要给共面边链倒角,请分多次调用,\n * 每次一组几何上互不相邻的边。\n *\n * @param input - the mesh-solid input.\n * @param params - the validated fillet parameters.\n * @returns the filleted mesh solid as a new mesh part.\n */\nfunction filletMeshSolid(input: Shape, params: Record<string, unknown>): Shape {\n const edges = params.edges as (number | EdgeTopoRef)[]\n const radius = params.radius as number\n const entry = meshSolidEntry(input, 'fillet')\n const edgeHandles = resolveMeshEdges(entry, edges, 'fillet')\n\n let result: BrepHandle\n try {\n result = entry.kernel.fillet(entry.solid, edgeHandles, radius)\n } catch (cause) {\n throw meshKernelFailure(\n 'fillet',\n 'E_FILLET_RADIUS_TOO_LARGE',\n `fillet(r=${radius}) on ${edgeHandles.length} edge(s)`,\n cause,\n )\n }\n return meshSolidProduct(entry, result)\n}\n\n/**\n * 在几何体上做圆角(等半径)。\n *\n * 两条路径都以 `meshEngines: ['brepkit']` 之外的事实为界:BREP 输入走\n * `filletWithHistory`(带面演化与 roleTable 传播);**网格实体**输入走网格后端\n * (近似拓扑无 role,边按几何或序号解析,无面演化)。非 BREP 的**裸网格**输入仍抛\n * `E_MESH_SOLID_UNSUPPORTED`——裸网格没有近似拓扑,没有边可选。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name fillet\n * @note `radius` 为正数(mm)。BREP 路径圆角后 roleTable 经 filletWithHistory 传播,\n * 后续特征仍可按 role 选面/选边;网格实体路径没有 role 层,边只能按几何或\n * 序号(近似拓扑 `edges` 数组下标 + 1)指认。\n * @returns Shape 圆角后的几何。\n * @param input - 目标几何。type:Shape required:true\n * @param params.edges - 参与圆角的边:相邻两面的 role 线路(EdgeTopoRef[]);网格链上也可用 1 起序号。type:EdgeTopoRef[] required:true\n * @param params.radius - 圆角半径(mm,>0)。type:number required:true\n * @example\n * const p = await cad.fillet(part0, { edges: [{ kind:'edge', faces:[{ origin:'box', role:'box:top' }, { origin:'box', role:'box:front' }], hint:{ kind:'edge' } }], radius:2 })\n * const q = await cad.fillet(meshPart, { edges: [3], radius: 1 })\n */\nexport const fillet = defineOp({\n meshEngines: ['brepkit'],\n mesh(input: Shape, params: Record<string, unknown>) {\n assertFilletParams(params, { allowOrdinals: true })\n return filletMeshSolid(input, params)\n },\n brep(input: Shape, params: Record<string, unknown>) {\n assertFilletParams(params)\n return filletBrep(input, params)\n },\n naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } } as Provenance,\n\n paramDims: {},\n})\n"]}
|
package/dist/api/geom.js
CHANGED
|
@@ -18,7 +18,7 @@ function geomQuery(of, anchor, faceOrdinal) {
|
|
|
18
18
|
if (faceOrdinal !== undefined) {
|
|
19
19
|
const solid = brepOf(of);
|
|
20
20
|
const kernel = getBrepApi();
|
|
21
|
-
if (solid && kernel) {
|
|
21
|
+
if (solid !== undefined && kernel) {
|
|
22
22
|
try {
|
|
23
23
|
const faces = kernel.getSubShapes(solid, 'face');
|
|
24
24
|
if (faceOrdinal < faces.length) {
|
package/dist/api/geom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geom.js","sourceRoot":"","sources":["../../src/api/geom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,mGAAmG;AACnG,OAAO,KAAK,SAAS,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAGjC,sFAAsF;AACtF,SAAS,SAAS,CAChB,EAAS,EACT,MAAwB,EACxB,WAA+B;IAE/B,iCAAiC;IACjC,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAA2B,CAAA;QAClD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;QAC3B,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"geom.js","sourceRoot":"","sources":["../../src/api/geom.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api geom — $geom 查询函数族(有形签名)\n *\n *\n * `cad.<feature>(of, anchor?, ordinal?)`:\n * - of 是 Shape(编译产物 `ctx.<var>` 引用),非变量名\n * - faceNormal:faceOrdinal + brepOf(of) + kernel(拓扑引用)\n * 优先 → anchor 几何反查(兜底)→ 报错\n * - bboxCenter/bboxMin/bboxMax:mesh 包围盒查询\n */\n\nimport type { Shape, Vec3 } from '../mesh/types'\n// B3 correction (2026-10-06): no library-face cad aggregate — import the impl from its own module.\nimport * as meshQuery from '../mesh/query'\nimport { getBrepApi } from '../brep/handle-bridge'\nimport { brepOf } from '../shape'\nimport type { BrepHandle } from '../brep/engine/types'\n\n/** 内部实现:faceNormal 专用——faceOrdinal+BREP 优先 → anchor 反查 → 报错(逻辑迁移自 resolveGeomRef)。 */\nfunction geomQuery(\n of: Shape,\n anchor: Vec3 | undefined,\n faceOrdinal: number | undefined,\n): Vec3 {\n // 优先路径:faceOrdinal 拓扑引用(BREP 路径)\n if (faceOrdinal !== undefined) {\n const solid = brepOf(of) as BrepHandle | undefined\n const kernel = getBrepApi()\n if (solid !== undefined && kernel) {\n try {\n const faces = kernel.getSubShapes(solid, 'face')\n if (faceOrdinal < faces.length) {\n const face = faces[faceOrdinal]\n // 面法向:用 surfaceNormal 在 (0.5, 0.5) 处取\n let normal: Vec3 = [0, 0, 1]\n try {\n const n = kernel.surfaceNormal(face, 0.5, 0.5)\n normal = [n.x, n.y, n.z]\n } catch {\n // surfaceNormal 可能对某些面失败,用默认法向\n }\n kernel.release(face)\n for (let i = 0; i < faces.length; i++) {\n if (i !== faceOrdinal) kernel.release(faces[i])\n }\n return normal\n }\n // ordinal 越界 → 释放并降级到 anchor\n for (const f of faces) kernel.release(f)\n } catch {\n // BREP 取面失败 → 降级到 anchor\n }\n }\n }\n\n // 兜底路径:anchor 几何反查\n if (!anchor) {\n throw new Error('[GeomRef] faceNormal requires anchor or faceOrdinal')\n }\n const face = meshQuery.faceAt(of, { point: anchor })\n if (!face) {\n throw new Error(`[GeomRef] faceAt failed for anchor at ${anchor}`)\n }\n return face.normal\n}\n\n/**\n * 查询面上某点(锚点)的法向。\n * @group 查询\n * @inputs 1\n * @async false\n * @qual ok\n * @name faceNormal\n * @returns Vec3 面上锚点处的法向 [x,y,z]。\n * @param of - 目标几何(编译产物 ctx.<var> 引用)。type:Shape required:true\n * @param anchor - 锚点(几何反查兜底)。type:[x,y,z]\n * @param ordinal - 面序号(BREP 拓扑引用优先)。type:number\n * @example\n * const n = cad.faceNormal(part0, [0, 0, 5])\n */\nexport function faceNormal(of: Shape, anchor?: Vec3, ordinal?: number): Vec3 {\n return geomQuery(of, anchor, ordinal)\n}\n\n/**\n * 查询几何包围盒中心。\n * @group 查询\n * @inputs 1\n * @async false\n * @qual ok\n * @name bboxCenter\n * @returns Vec3 包围盒中心 [x,y,z]。交互式可编辑(参数量引用)。\n * @param of - 目标几何。type:Shape required:true\n * @example\n * const c = cad.bboxCenter(part0)\n */\nexport function bboxCenter(of: Shape): Vec3 {\n return meshQuery.bboxCenter(of)\n}\n\n/**\n * 查询几何包围盒最小角点。\n * @group 查询\n * @inputs 1\n * @async false\n * @qual ok\n * @name bboxMin\n * @returns Vec3 包围盒最小角点 [x,y,z]。\n * @param of - 目标几何。type:Shape required:true\n * @example\n * const mn = cad.bboxMin(part0)\n */\nexport function bboxMin(of: Shape): Vec3 {\n return meshQuery.boundingBox(of).min\n}\n\n/**\n * 查询几何包围盒最大角点。\n * @group 查询\n * @inputs 1\n * @async false\n * @qual ok\n * @name bboxMax\n * @returns Vec3 包围盒最大角点 [x,y,z]。\n * @param of - 目标几何。type:Shape required:true\n * @example\n * const mx = cad.bboxMax(part0)\n */\nexport function bboxMax(of: Shape): Vec3 {\n return meshQuery.boundingBox(of).max\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-step.d.ts","sourceRoot":"","sources":["../../src/api/import-step.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAwB1C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAkDpF;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;
|
|
1
|
+
{"version":3,"file":"import-step.d.ts","sourceRoot":"","sources":["../../src/api/import-step.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAwB1C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAkDpF;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;CAUtB,CAAA"}
|