@faicad/faijs 0.18.3 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/api/api-namespace.d.ts.map +1 -1
  2. package/dist/api/api-namespace.js +4 -1
  3. package/dist/api/api-namespace.js.map +1 -1
  4. package/dist/api/brep-mirror/joinery-brep.d.ts +1 -1
  5. package/dist/api/brep-mirror/joinery-brep.d.ts.map +1 -1
  6. package/dist/api/brep-mirror/joinery-brep.js +19 -19
  7. package/dist/api/brep-mirror/joinery-brep.js.map +1 -1
  8. package/dist/api/index.d.ts +4 -0
  9. package/dist/api/index.d.ts.map +1 -1
  10. package/dist/api/index.js +3 -0
  11. package/dist/api/index.js.map +1 -1
  12. package/dist/api/profile.d.ts.map +1 -1
  13. package/dist/api/profile.js +113 -182
  14. package/dist/api/profile.js.map +1 -1
  15. package/dist/api/punch-hole.d.ts +74 -0
  16. package/dist/api/punch-hole.d.ts.map +1 -0
  17. package/dist/api/punch-hole.js +207 -0
  18. package/dist/api/punch-hole.js.map +1 -0
  19. package/dist/api/sketch-on-face.d.ts +85 -0
  20. package/dist/api/sketch-on-face.d.ts.map +1 -0
  21. package/dist/api/sketch-on-face.js +136 -0
  22. package/dist/api/sketch-on-face.js.map +1 -0
  23. package/dist/api/sketch-on-plane.d.ts +81 -0
  24. package/dist/api/sketch-on-plane.d.ts.map +1 -0
  25. package/dist/api/sketch-on-plane.js +103 -0
  26. package/dist/api/sketch-on-plane.js.map +1 -0
  27. package/dist/boolean/csg-backend.d.ts +6 -6
  28. package/dist/boolean/csg-backend.d.ts.map +1 -1
  29. package/dist/boolean/csg-backend.js +9 -9
  30. package/dist/boolean/csg-backend.js.map +1 -1
  31. package/dist/boolean/csg-core.d.ts +10 -10
  32. package/dist/boolean/csg-core.d.ts.map +1 -1
  33. package/dist/boolean/csg-core.js +24 -24
  34. package/dist/boolean/csg-core.js.map +1 -1
  35. package/dist/boolean/extrude-helpers.d.ts +8 -8
  36. package/dist/boolean/extrude-helpers.d.ts.map +1 -1
  37. package/dist/boolean/extrude-helpers.js +13 -13
  38. package/dist/boolean/extrude-helpers.js.map +1 -1
  39. package/dist/brep/brep-ops.d.ts +20 -6
  40. package/dist/brep/brep-ops.d.ts.map +1 -1
  41. package/dist/brep/brep-ops.js +38 -12
  42. package/dist/brep/brep-ops.js.map +1 -1
  43. package/dist/browser-host/csg-worker-protocol.d.ts +3 -3
  44. package/dist/browser-host/csg-worker-protocol.d.ts.map +1 -1
  45. package/dist/browser-host/csg-worker-protocol.js.map +1 -1
  46. package/dist/browser-host/csg-worker.js +3 -3
  47. package/dist/browser-host/csg-worker.js.map +1 -1
  48. package/dist/browser-host/inline-csg-backend.d.ts +3 -3
  49. package/dist/browser-host/inline-csg-backend.d.ts.map +1 -1
  50. package/dist/browser-host/inline-csg-backend.js +3 -3
  51. package/dist/browser-host/inline-csg-backend.js.map +1 -1
  52. package/dist/browser-host/worker-csg-backend.d.ts +3 -3
  53. package/dist/browser-host/worker-csg-backend.d.ts.map +1 -1
  54. package/dist/browser-host/worker-csg-backend.js.map +1 -1
  55. package/dist/cad-runtime/ports.d.ts +3 -3
  56. package/dist/cad-runtime/ports.d.ts.map +1 -1
  57. package/dist/cad-runtime/ports.js.map +1 -1
  58. package/dist/geometry2d/adapt.d.ts +46 -0
  59. package/dist/geometry2d/adapt.d.ts.map +1 -0
  60. package/dist/geometry2d/adapt.js +41 -0
  61. package/dist/geometry2d/adapt.js.map +1 -0
  62. package/dist/geometry2d/bbox2d.d.ts +82 -0
  63. package/dist/geometry2d/bbox2d.d.ts.map +1 -0
  64. package/dist/geometry2d/bbox2d.js +123 -0
  65. package/dist/geometry2d/bbox2d.js.map +1 -0
  66. package/dist/geometry2d/blueprint-sketcher.d.ts +27 -0
  67. package/dist/geometry2d/blueprint-sketcher.d.ts.map +1 -0
  68. package/dist/geometry2d/blueprint-sketcher.js +29 -0
  69. package/dist/geometry2d/blueprint-sketcher.js.map +1 -0
  70. package/dist/geometry2d/blueprint.d.ts +102 -0
  71. package/dist/geometry2d/blueprint.d.ts.map +1 -0
  72. package/dist/geometry2d/blueprint.js +225 -0
  73. package/dist/geometry2d/blueprint.js.map +1 -0
  74. package/dist/geometry2d/blueprints.d.ts +58 -0
  75. package/dist/geometry2d/blueprints.d.ts.map +1 -0
  76. package/dist/geometry2d/blueprints.js +72 -0
  77. package/dist/geometry2d/blueprints.js.map +1 -0
  78. package/dist/geometry2d/bridge/lift-on-plane.d.ts +50 -0
  79. package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -0
  80. package/dist/geometry2d/bridge/lift-on-plane.js +72 -0
  81. package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -0
  82. package/dist/geometry2d/bridge/on-surface.d.ts +98 -0
  83. package/dist/geometry2d/bridge/on-surface.d.ts.map +1 -0
  84. package/dist/geometry2d/bridge/on-surface.js +94 -0
  85. package/dist/geometry2d/bridge/on-surface.js.map +1 -0
  86. package/dist/geometry2d/bridge/plane.d.ts +69 -0
  87. package/dist/geometry2d/bridge/plane.d.ts.map +1 -0
  88. package/dist/geometry2d/bridge/plane.js +96 -0
  89. package/dist/geometry2d/bridge/plane.js.map +1 -0
  90. package/dist/geometry2d/canned-blueprints.d.ts +44 -0
  91. package/dist/geometry2d/canned-blueprints.d.ts.map +1 -0
  92. package/dist/geometry2d/canned-blueprints.js +94 -0
  93. package/dist/geometry2d/canned-blueprints.js.map +1 -0
  94. package/dist/geometry2d/compound-blueprint.d.ts +72 -0
  95. package/dist/geometry2d/compound-blueprint.d.ts.map +1 -0
  96. package/dist/geometry2d/compound-blueprint.js +95 -0
  97. package/dist/geometry2d/compound-blueprint.js.map +1 -0
  98. package/dist/geometry2d/curve2d.d.ts +298 -0
  99. package/dist/geometry2d/curve2d.d.ts.map +1 -0
  100. package/dist/geometry2d/curve2d.js +1110 -0
  101. package/dist/geometry2d/curve2d.js.map +1 -0
  102. package/dist/geometry2d/index.d.ts +22 -0
  103. package/dist/geometry2d/index.d.ts.map +1 -0
  104. package/dist/geometry2d/index.js +21 -0
  105. package/dist/geometry2d/index.js.map +1 -0
  106. package/dist/geometry2d/organise.d.ts +28 -0
  107. package/dist/geometry2d/organise.d.ts.map +1 -0
  108. package/dist/geometry2d/organise.js +108 -0
  109. package/dist/geometry2d/organise.js.map +1 -0
  110. package/dist/geometry2d/pen-sketcher.d.ts +340 -0
  111. package/dist/geometry2d/pen-sketcher.d.ts.map +1 -0
  112. package/dist/geometry2d/pen-sketcher.js +477 -0
  113. package/dist/geometry2d/pen-sketcher.js.map +1 -0
  114. package/dist/geometry2d/point.d.ts +44 -0
  115. package/dist/geometry2d/point.d.ts.map +1 -0
  116. package/dist/geometry2d/point.js +57 -0
  117. package/dist/geometry2d/point.js.map +1 -0
  118. package/dist/geometry2d/svg-ellipse.d.ts +74 -0
  119. package/dist/geometry2d/svg-ellipse.d.ts.map +1 -0
  120. package/dist/geometry2d/svg-ellipse.js +163 -0
  121. package/dist/geometry2d/svg-ellipse.js.map +1 -0
  122. package/dist/lang/symbol-table.generated.d.ts +3 -0
  123. package/dist/lang/symbol-table.generated.d.ts.map +1 -1
  124. package/dist/lang/symbol-table.generated.js +3 -0
  125. package/dist/lang/symbol-table.generated.js.map +1 -1
  126. package/dist/mesh/types.d.ts +1 -1
  127. package/dist/mesh/types.d.ts.map +1 -1
  128. package/dist/mesh/types.js.map +1 -1
  129. package/package.json +9 -1
@@ -1 +1 @@
1
- {"version":3,"file":"csg-core.js","sourceRoot":"","sources":["../../src/boolean/csg-core.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * csg-core — CSG 纯计算函数(从 csg-worker.ts 提取)\n *\n *\n * 这些函数不依赖 Worker 环境(无 self.onmessage / postMessage),\n * 可被 WorkerCsgBackend(经 csg-worker.ts)和 InlineCsgBackend(主线程直跑)共用。\n *\n * 依赖:manifold-3d 核心模块(Manifold / Mesh 构造器)、dovetail-math、joinery-shapes\n */\n\nimport type { Manifold as ManifoldInstance } from 'manifold-3d/manifold'\nimport {\n vec3Cross, vec3Normalize,\n type Vec3,\n} from './dovetail-math'\nimport {\n buildWedgeGeometry,\n buildDowelGeometry,\n buildStraightTenonGeometry,\n} from './joinery-shapes'\n\n// ── 类型别名 ──\n\ntype ManifoldCtor = typeof import('manifold-3d/manifold').Manifold\ntype MeshCtor = typeof import('manifold-3d/manifold').Mesh\n\n// ── Manifold → MeshData 转换 ──\n\n/**\n * Extract {positions, indices} from a Manifold mesh.\n * Handles the numProp > 3 case (manifold may carry extra property channels).\n * @param manifold The manifold from which to read mesh data.\n * @returns The extracted positions and indices buffers.\n */\nexport function manifoldToMeshData(manifold: ManifoldInstance): {\n positions: Float32Array; indices: Uint32Array\n} {\n const resultMesh = manifold.getMesh()\n const numProp = resultMesh.numProp || 3\n const vertPropsLen = resultMesh.vertProperties ? resultMesh.vertProperties.length : 0\n const vertCount = numProp > 0 ? Math.floor(vertPropsLen / numProp) : 0\n const positions = new Float32Array(vertCount * 3)\n for (let i = 0; i < vertCount; i++) {\n const base = i * numProp\n positions[i * 3] = resultMesh.vertProperties[base]\n positions[i * 3 + 1] = resultMesh.vertProperties[base + 1]\n positions[i * 3 + 2] = resultMesh.vertProperties[base + 2]\n }\n const triVerts = resultMesh.triVerts\n const indices = triVerts ? new Uint32Array(triVerts) : new Uint32Array(0)\n return { positions, indices }\n}\n\n// ── MeshData → Manifold ──\n\n/**\n * Build a Manifold from mesh data, welding duplicate vertices when the density\n * is too high (close to one independent vertex per triangle) before Manifold.ofMesh.\n * Shared by the Inline and Worker backends so both produce identical input conversion.\n * @param Manifold The Manifold constructor from the manifold module.\n * @param Mesh The Mesh constructor from the manifold module.\n * @param mesh The mesh data (positions and indices).\n * @returns The constructed Manifold instance.\n */\nexport function meshToManifold(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n mesh: { positions: Float32Array; indices: Uint32Array },\n): ManifoldInstance {\n const triCount = mesh.indices.length / 3\n const vertCount = mesh.positions.length / 3\n let positions = mesh.positions\n let indices = mesh.indices\n\n if (vertCount >= triCount * 3 * 0.9) {\n const welded = weldPositionsWorker(mesh.positions, mesh.indices, mesh.indices.length)\n positions = welded.positions\n indices = welded.indices\n }\n\n return Manifold.ofMesh(new Mesh({\n numProp: 3,\n vertProperties: positions,\n triVerts: indices,\n }))\n}\n\n/**\n * Sequentially apply a boolean operation across an array of Manifolds.\n * The caller is responsible for deleting the input manifolds and the result.\n * @param op The boolean operation to apply (union/subtract/intersect).\n * @param manifolds The manifolds to combine in order.\n * @returns The resulting Manifold of the chain.\n */\nexport function chainBoolean(\n op: 'union' | 'subtract' | 'intersect',\n manifolds: ManifoldInstance[],\n): ManifoldInstance {\n let result = manifolds[0]\n for (let i = 1; i < manifolds.length; i++) {\n switch (op) {\n case 'union':\n result = result.add(manifolds[i])\n break\n case 'subtract':\n result = result.subtract(manifolds[i])\n break\n case 'intersect':\n result = result.intersect(manifolds[i])\n break\n }\n }\n return result\n}\n\n// ── 顶点焊接 ──\n\n/**\n * Weld duplicate vertices using a quantized 1 µm grid.\n * Uses three nested numeric Maps (no string allocation).\n * @param positions The input vertex positions.\n * @param indices The input triangle indices.\n * @param count The number of indices to process.\n * @returns The welded positions and remapped indices buffers.\n */\nexport function weldPositionsWorker(\n positions: Float32Array,\n indices: Uint32Array,\n count: number,\n): { positions: Float32Array; indices: Uint32Array } {\n const mapX = new Map<number, Map<number, Map<number, number>>>()\n const weldedPosArr: number[] = []\n const weldedIdxArr: number[] = []\n\n for (let i = 0; i < count; i++) {\n const vi = indices[i]\n const x = positions[vi * 3]\n const y = positions[vi * 3 + 1]\n const z = positions[vi * 3 + 2]\n const qx = Math.round(x * 1e6)\n const qy = Math.round(y * 1e6)\n const qz = Math.round(z * 1e6)\n\n let mapY = mapX.get(qx)\n if (mapY === undefined) {\n mapY = new Map<number, Map<number, number>>()\n mapX.set(qx, mapY)\n }\n let mapZ = mapY.get(qy)\n if (mapZ === undefined) {\n mapZ = new Map<number, number>()\n mapY.set(qy, mapZ)\n }\n let ni = mapZ.get(qz)\n if (ni === undefined) {\n ni = weldedPosArr.length / 3\n mapZ.set(qz, ni)\n weldedPosArr.push(x, y, z)\n }\n weldedIdxArr.push(ni)\n }\n\n return {\n positions: new Float32Array(weldedPosArr),\n indices: new Uint32Array(weldedIdxArr),\n }\n}\n\n// ── Union-Find ──\n\n/** Simple union-find for clustering cap triangles by shared edges. */\nexport class SimpleUnionFind {\n private parent: number[]\n private rank: number[]\n\n /**\n * Create a union-find structure with n initial singletons.\n * @param n The number of elements.\n */\n constructor(n: number) {\n this.parent = Array.from({ length: n }, (_, i) => i)\n this.rank = new Array(n).fill(0)\n }\n\n /**\n * Find the root representative of the element x (with path compression).\n * @param x The element to look up.\n * @returns The root index of the set containing x.\n */\n find(x: number): number {\n if (this.parent[x] !== x) {\n this.parent[x] = this.find(this.parent[x])\n }\n return this.parent[x]\n }\n\n /**\n * Union the sets containing x and y.\n * @param x The first element.\n * @param y The second element.\n */\n union(x: number, y: number): void {\n const px = this.find(x)\n const py = this.find(y)\n if (px === py) return\n if (this.rank[px] < this.rank[py]) {\n this.parent[px] = py\n } else if (this.rank[px] > this.rank[py]) {\n this.parent[py] = px\n } else {\n this.parent[py] = px\n this.rank[px]++\n }\n }\n}\n\n// ── Wedge (trapezoidal prism) creation ──\n\n/**\n * Create a wedge (trapezoidal prism) Manifold from cutting-plane parameters.\n * @param Manifold The Manifold constructor from the manifold module.\n * @param Mesh The Mesh constructor from the manifold module.\n * @param planeCenter Center of the cutting plane.\n * @param normal Cutting plane normal (unit vector).\n * @param widthDir Extrusion direction (unit vector).\n * @param depth Wedge depth (mm).\n * @param width Wedge width (mm).\n * @param angleDeg Slant angle of the wedge sides (degrees).\n * @param extrudeLength Total extrusion length along widthDir (mm).\n * @returns The constructed wedge Manifold.\n */\nexport function createWedge(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n planeCenter: Vec3,\n normal: Vec3,\n widthDir: Vec3,\n depth: number,\n width: number,\n angleDeg: number,\n extrudeLength: number,\n): ManifoldInstance {\n const { positions, indices } = buildWedgeGeometry(\n planeCenter, normal, widthDir, depth, width, angleDeg, extrudeLength,\n )\n const mesh = new Mesh({\n numProp: 3,\n vertProperties: positions,\n triVerts: indices,\n })\n return Manifold.ofMesh(mesh)\n}\n\n// ── Cap component detection ──\n\n/**\n * Detect connected components of cap faces on the cutting plane.\n * Returns an array of components, each being a Set of vertex indices.\n * @param upper The upper mesh to scan for cap faces.\n * @param normal The cutting plane normal.\n * @param originOffset The cutting plane offset along the normal.\n * @returns An array of components, each a Set of vertex indices on the cap.\n */\nexport function detectCapComponents(\n upper: ManifoldInstance,\n normal: Vec3,\n originOffset: number,\n): Set<number>[] {\n const mesh = upper.getMesh()\n const eps = 0.001\n const numProp = mesh.numProp || 3\n const vertCount = Math.floor(mesh.vertProperties.length / numProp)\n const triVerts = mesh.triVerts\n if (!triVerts || triVerts.length === 0) return []\n\n const capVertSet = new Set<number>()\n interface CapTri { v0: number; v1: number; v2: number }\n const capTris: CapTri[] = []\n const triCount = triVerts.length / 3\n for (let t = 0; t < triCount; t++) {\n const i0 = triVerts[t * 3]\n const i1 = triVerts[t * 3 + 1]\n const i2 = triVerts[t * 3 + 2]\n const d0 = Math.abs(\n mesh.vertProperties[i0 * numProp] * normal[0] +\n mesh.vertProperties[i0 * numProp + 1] * normal[1] +\n mesh.vertProperties[i0 * numProp + 2] * normal[2] - originOffset)\n const d1 = Math.abs(\n mesh.vertProperties[i1 * numProp] * normal[0] +\n mesh.vertProperties[i1 * numProp + 1] * normal[1] +\n mesh.vertProperties[i1 * numProp + 2] * normal[2] - originOffset)\n const d2 = Math.abs(\n mesh.vertProperties[i2 * numProp] * normal[0] +\n mesh.vertProperties[i2 * numProp + 1] * normal[1] +\n mesh.vertProperties[i2 * numProp + 2] * normal[2] - originOffset)\n if (d0 < eps && d1 < eps && d2 < eps) {\n capTris.push({ v0: i0, v1: i1, v2: i2 })\n capVertSet.add(i0); capVertSet.add(i1); capVertSet.add(i2)\n }\n }\n if (capTris.length === 0) return []\n\n const uf = new SimpleUnionFind(vertCount)\n for (const tri of capTris) {\n uf.union(tri.v0, tri.v1)\n uf.union(tri.v1, tri.v2)\n uf.union(tri.v0, tri.v2)\n }\n\n const compMap = new Map<number, Set<number>>()\n for (const vi of capVertSet) {\n const root = uf.find(vi)\n if (!compMap.has(root)) compMap.set(root, new Set<number>())\n compMap.get(root)!.add(vi)\n }\n\n return Array.from(compMap.values())\n}\n\n// ── Cross-section width computation ──\n\n/**\n * Compute the actual extent of the model's cross-section at the cutting plane\n * along the width direction.\n * @param upper The upper mesh to measure.\n * @param normal The cutting plane normal.\n * @param originOffset The cutting plane offset along the normal.\n * @param widthDir The width direction along which to measure.\n * @param comp Optional connected component to restrict the measurement to.\n * @returns The cross-section extent along the width direction (0 when none found).\n */\nexport function computeCrossSectionWidth(\n upper: ManifoldInstance,\n normal: Vec3,\n originOffset: number,\n widthDir: Vec3,\n comp?: Set<number>,\n): number {\n const mesh = upper.getMesh()\n const eps = 0.001\n let minProj = Infinity\n let maxProj = -Infinity\n let found = false\n\n const numProp = mesh.numProp || 3\n const vertCount = Math.floor(mesh.vertProperties.length / numProp)\n for (let i = 0; i < vertCount; i++) {\n if (comp && !comp.has(i)) continue\n\n const base = i * numProp\n const x = mesh.vertProperties[base]\n const y = mesh.vertProperties[base + 1]\n const z = mesh.vertProperties[base + 2]\n\n const dist = x * normal[0] + y * normal[1] + z * normal[2] - originOffset\n if (Math.abs(dist) < eps) {\n const proj = x * widthDir[0] + y * widthDir[1] + z * widthDir[2]\n if (proj < minProj) minProj = proj\n if (proj > maxProj) maxProj = proj\n found = true\n }\n }\n\n if (!found) return 0\n return maxProj - minProj\n}\n\n// ── Cross-section centroid computation ──\n\n/**\n * Compute the centroid of vertices lying on the cutting plane.\n * @param upper The upper mesh to scan.\n * @param normal The cutting plane normal.\n * @param originOffset The cutting plane offset along the normal.\n * @param fallback The centroid fallback when no vertex lies on the plane.\n * @param comp Optional connected component to restrict the measurement to.\n * @returns The computed centroid, or the fallback when none is found.\n */\nexport function computeCrossSectionCentroid(\n upper: ManifoldInstance,\n normal: Vec3,\n originOffset: number,\n fallback: Vec3,\n comp?: Set<number>,\n): Vec3 {\n const mesh = upper.getMesh()\n const eps = 0.001\n let cx = 0, cy = 0, cz = 0\n let count = 0\n\n const numProp = mesh.numProp || 3\n const vertCount = Math.floor(mesh.vertProperties.length / numProp)\n for (let i = 0; i < vertCount; i++) {\n if (comp && !comp.has(i)) continue\n\n const base = i * numProp\n const x = mesh.vertProperties[base]\n const y = mesh.vertProperties[base + 1]\n const z = mesh.vertProperties[base + 2]\n\n const dist = x * normal[0] + y * normal[1] + z * normal[2] - originOffset\n if (Math.abs(dist) < eps) {\n cx += x\n cy += y\n cz += z\n count++\n }\n }\n\n if (count === 0) return fallback\n return [cx / count, cy / count, cz / count]\n}\n\n// ── Dovetail boolean split ──\n\n/**\n * Perform the dovetail split using boolean operations.\n * @param Manifold - the Manifold constructor from the manifold module.\n * @param Mesh - the Mesh constructor from the manifold module.\n * @param original - the original manifold to split.\n * @param normal - the cutting plane normal (unit vector).\n * @param originOffset - the plane equation origin offset along the normal.\n * @param planeCenter - a point on the cutting plane used to center the wedge.\n * @param widthDirInput - the width direction in the cutting plane (will be normalized).\n * @param bboxWidthOnWidthDir - the model's bounding-box width along widthDir, used as a fallback cross-section width.\n * @param groove - the dovetail groove design parameters (depth, tolerances, width, flaps angle).\n * @param keepOriginal - when true, the original manifold is not deleted after splitting (default false).\n * @returns a tuple of the split upper manifold, lower manifold, and the trimmed wedge mesh data (or null when empty).\n */\nexport function dovetailBooleanSplit(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n original: ManifoldInstance,\n normal: Vec3,\n originOffset: number,\n planeCenter: Vec3,\n widthDirInput: Vec3,\n bboxWidthOnWidthDir: number,\n groove: {\n depth: number\n depthTolerance: number\n width: number\n widthTolerance: number\n flapsAngle: number\n },\n keepOriginal: boolean = false,\n): [ManifoldInstance, ManifoldInstance,\n { positions: Float32Array; indices: Uint32Array } | null] {\n const widthDir = vec3Normalize(widthDirInput)\n\n // Step 1: Split by plane → upper + lower\n const [upper, lower] = original.splitByPlane(normal, originOffset)\n if (!keepOriginal) original.delete()\n\n // Step 2: Compute actual cross-section width at the cutting plane\n let crossSectionWidth = computeCrossSectionWidth(upper, normal, originOffset, widthDir)\n if (crossSectionWidth <= 0) {\n crossSectionWidth = bboxWidthOnWidthDir\n }\n const extrudeLength = crossSectionWidth + 0.2\n\n // Step 3: Create wedge W with generous overhang along widthDir\n const overhang = 20\n\n const wedgeW = createWedge(\n Manifold, Mesh,\n planeCenter, normal, widthDir,\n groove.depth, groove.width, groove.flapsAngle,\n extrudeLength + overhang,\n )\n\n // Trim the wedge to the model by intersecting with lower.\n let wedgeForUnion: ManifoldInstance\n let wedgeMeshData: { positions: Float32Array; indices: Uint32Array } | null\n let lowerForSubtract: ManifoldInstance\n\n if (!wedgeW.isEmpty() && !lower.isEmpty()) {\n const lowerMeshData = manifoldToMeshData(lower)\n\n const trimmedWedge = wedgeW.intersect(lower)\n wedgeW.delete()\n lower.delete()\n\n wedgeMeshData = trimmedWedge.isEmpty() ? null : manifoldToMeshData(trimmedWedge)\n wedgeForUnion = trimmedWedge\n\n lowerForSubtract = Manifold.ofMesh(new Mesh({\n numProp: 3,\n vertProperties: lowerMeshData.positions,\n triVerts: lowerMeshData.indices,\n }))\n } else {\n wedgeMeshData = null\n wedgeForUnion = wedgeW\n lowerForSubtract = lower\n }\n\n // Step 5: union(upper, wedgeForUnion) → upper'\n let upperResult: ManifoldInstance\n if (upper.isEmpty()) {\n upper.delete()\n upperResult = wedgeForUnion\n } else if (wedgeForUnion.isEmpty()) {\n wedgeForUnion.delete()\n upperResult = upper\n } else {\n upperResult = upper.add(wedgeForUnion)\n upper.delete()\n wedgeForUnion.delete()\n }\n\n // Step 6: Create tolerance wedge W_tol\n const wedgeTol = createWedge(\n Manifold, Mesh,\n planeCenter, normal, widthDir,\n groove.depth + groove.depthTolerance,\n groove.width + groove.widthTolerance,\n groove.flapsAngle,\n extrudeLength + overhang,\n )\n\n // Step 7: lower.subtract(wedgeTol) → lower'\n let lowerResult: ManifoldInstance\n if (lowerForSubtract.isEmpty()) {\n wedgeTol.delete()\n lowerResult = lowerForSubtract\n } else if (wedgeTol.isEmpty()) {\n wedgeTol.delete()\n lowerResult = lowerForSubtract\n } else {\n lowerResult = lowerForSubtract.subtract(wedgeTol)\n lowerForSubtract.delete()\n wedgeTol.delete()\n }\n\n return [upperResult, lowerResult, wedgeMeshData]\n}\n\n// ── Dowel (cylinder) creation ──\n\n/**\n * Create a cylindrical Manifold for the dowel tenon.\n * @param Manifold - the Manifold constructor from the manifold module.\n * @param Mesh - the Mesh constructor from the manifold module.\n * @param centroid - the center of the cylinder in the cutting plane.\n * @param normal - the cutting plane normal (unit vector, points \"up\").\n * @param widthDir - the width direction in the cutting plane (unit vector).\n * @param depthDir - the depth direction in the cutting plane (unit vector).\n * @param diameter - the cylinder diameter (mm).\n * @param height - the cylinder height (mm), extends along -normal.\n * @param segments - the number of circular segments (default 32).\n * @returns the resulting cylindrical Manifold instance.\n */\nexport function createDowel(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n centroid: Vec3,\n normal: Vec3,\n widthDir: Vec3,\n depthDir: Vec3,\n diameter: number,\n height: number,\n segments: number = 32,\n): ManifoldInstance {\n const { positions, indices } = buildDowelGeometry(\n centroid, normal, widthDir, depthDir, diameter, height, segments,\n )\n const mesh = new Mesh({\n numProp: 3,\n vertProperties: positions,\n triVerts: indices,\n })\n return Manifold.ofMesh(mesh)\n}\n\n// ── Straight tenon (box) creation ──\n\n/**\n * Create a box-shaped Manifold for the straight tenon.\n * @param Manifold - the Manifold constructor from the manifold module.\n * @param Mesh - the Mesh constructor from the manifold module.\n * @param centroid - the center of the box in the cutting plane.\n * @param normal - the cutting plane normal (unit vector, points \"up\").\n * @param widthDir - the width direction in the cutting plane (unit vector).\n * @param depthDir - the depth direction in the cutting plane (unit vector).\n * @param sideLength - the square cross-section side length (mm).\n * @param height - the box height (mm), extends along -normal.\n * @returns the resulting box-shaped Manifold instance.\n */\nexport function createStraightTenon(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n centroid: Vec3,\n normal: Vec3,\n widthDir: Vec3,\n depthDir: Vec3,\n sideLength: number,\n height: number,\n): ManifoldInstance {\n const { positions, indices } = buildStraightTenonGeometry(\n centroid, normal, widthDir, depthDir, sideLength, height,\n )\n const mesh = new Mesh({\n numProp: 3,\n vertProperties: positions,\n triVerts: indices,\n })\n return Manifold.ofMesh(mesh)\n}\n\n// ── Dowel / Straight-tenon boolean split ──\n\n/**\n * Perform the dowel (or straight-tenon) split using boolean operations.\n * @param Manifold - the Manifold constructor from the manifold module.\n * @param Mesh - the Mesh constructor from the manifold module.\n * @param original - the original manifold to split.\n * @param normal - the cutting plane normal (unit vector).\n * @param originOffset - the plane equation origin offset along the normal.\n * @param planeCenter - a point on the cutting plane used to center the joinery.\n * @param widthDirInput - the width direction in the cutting plane (will be normalized).\n * @param shape - the joinery shape: 'dowel' or 'tenon'.\n * @param params - the joinery sizing parameters (size, tolerances, height).\n * @param keepOriginal - when true, the original manifold is not deleted after splitting (default false).\n * @param selectedSections - optional list of indices selecting which cap sections receive joinery placement; null or empty means a single placement at the overall cross-section centroid.\n * @returns a tuple of the split upper manifold, lower manifold, and the generated joinery mesh data (or null).\n */\nexport function dowelOrTenonBooleanSplit(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n original: ManifoldInstance,\n normal: Vec3,\n originOffset: number,\n planeCenter: Vec3,\n widthDirInput: Vec3,\n shape: 'dowel' | 'tenon',\n params: {\n size: number\n sizeTolerance: number\n height: number\n heightTolerance: number\n },\n keepOriginal: boolean = false,\n selectedSections?: number[] | null,\n): [ManifoldInstance, ManifoldInstance,\n { positions: Float32Array; indices: Uint32Array } | null] {\n const widthDir = vec3Normalize(widthDirInput)\n const depthDir = vec3Normalize(vec3Cross(normal, widthDir))\n\n // Step 1: Split by plane → upper + lower\n const [upper, lower] = original.splitByPlane(normal, originOffset)\n if (!keepOriginal) original.delete()\n\n // Step 2: Detect cap components (multi-section support)\n const components = detectCapComponents(upper, normal, originOffset)\n\n // Build the list of joinery placements: one per selected section\n interface JoineryPlacement { centroid: Vec3 }\n let placements: JoineryPlacement[]\n\n if (components.length <= 1 || !selectedSections || selectedSections.length === 0) {\n const centroid = computeCrossSectionCentroid(upper, normal, originOffset, planeCenter)\n placements = [{ centroid }]\n } else {\n const compInfo = components.map((comp, idx) => {\n const compWidth = computeCrossSectionWidth(upper, normal, originOffset, widthDir, comp)\n const compCentroid = computeCrossSectionCentroid(upper, normal, originOffset, planeCenter, comp)\n const compDepth = computeCrossSectionWidth(upper, normal, originOffset, depthDir, comp)\n const area = compWidth * compDepth\n return { idx, comp, area, centroid: compCentroid }\n })\n compInfo.sort((a, b) => b.area - a.area)\n\n placements = []\n for (const selId of selectedSections) {\n if (selId < compInfo.length) {\n placements.push({ centroid: compInfo[selId].centroid })\n }\n }\n if (placements.length === 0) {\n const centroid = computeCrossSectionCentroid(upper, normal, originOffset, planeCenter)\n placements = [{ centroid }]\n }\n }\n\n // Step 3: For each placement, create shape C (no tolerance) and union into upper\n let shapeMeshData: { positions: Float32Array; indices: Uint32Array } | null = null\n\n let upperResult = upper\n let upperOwned = true\n\n for (let pIdx = 0; pIdx < placements.length; pIdx++) {\n const { centroid } = placements[pIdx]\n let shapeC: ManifoldInstance\n if (shape === 'dowel') {\n shapeC = createDowel(Manifold, Mesh, centroid, normal, widthDir, depthDir,\n params.size, params.height, 32)\n } else {\n shapeC = createStraightTenon(Manifold, Mesh, centroid, normal, widthDir, depthDir,\n params.size, params.height)\n }\n\n if (pIdx === 0) {\n shapeMeshData = shapeC.isEmpty() ? null : manifoldToMeshData(shapeC)\n }\n\n if (upperResult.isEmpty()) {\n if (upperOwned) upperResult.delete()\n upperResult = shapeC\n upperOwned = true\n } else if (shapeC.isEmpty()) {\n shapeC.delete()\n } else {\n const newUpper = upperResult.add(shapeC)\n if (upperOwned) upperResult.delete()\n upperResult = newUpper\n shapeC.delete()\n upperOwned = true\n }\n }\n\n // Step 4: For each placement, create shape C_tol (with tolerance) and subtract from lower\n const tolSize = params.size + params.sizeTolerance\n const tolHeight = params.height + params.heightTolerance\n\n let lowerResult = lower\n let lowerOwned = true\n\n for (const { centroid } of placements) {\n let shapeCTol: ManifoldInstance\n if (shape === 'dowel') {\n shapeCTol = createDowel(Manifold, Mesh, centroid, normal, widthDir, depthDir,\n tolSize, tolHeight, 32)\n } else {\n shapeCTol = createStraightTenon(Manifold, Mesh, centroid, normal, widthDir, depthDir,\n tolSize, tolHeight)\n }\n\n if (lowerResult.isEmpty()) {\n shapeCTol.delete()\n } else if (shapeCTol.isEmpty()) {\n shapeCTol.delete()\n } else {\n const newLower = lowerResult.subtract(shapeCTol)\n if (lowerOwned) lowerResult.delete()\n lowerResult = newLower\n shapeCTol.delete()\n lowerOwned = true\n }\n }\n\n return [upperResult, lowerResult, shapeMeshData]\n}\n"]}
1
+ {"version":3,"file":"csg-core.js","sourceRoot":"","sources":["../../src/boolean/csg-core.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * csg-core — CSG 纯计算函数(从 csg-worker.ts 提取)\n *\n *\n * 这些函数不依赖 Worker 环境(无 self.onmessage / postMessage),\n * 可被 WorkerCsgBackend(经 csg-worker.ts)和 InlineCsgBackend(主线程直跑)共用。\n *\n * 依赖:manifold-3d 核心模块(Manifold / Mesh 构造器)、dovetail-math、joinery-shapes\n */\n\nimport type { Manifold as ManifoldInstance } from 'manifold-3d/manifold'\nimport {\n vec3Cross, vec3Normalize,\n type Vec3,\n} from './dovetail-math'\nimport {\n buildWedgeGeometry,\n buildDowelGeometry,\n buildStraightTenonGeometry,\n} from './joinery-shapes'\n\n// ── 类型别名 ──\n\ntype ManifoldCtor = typeof import('manifold-3d/manifold').Manifold\ntype MeshCtor = typeof import('manifold-3d/manifold').Mesh\n\n// ── Manifold → MeshData 转换 ──\n\n/**\n * Extract {positions, indices} from a Manifold mesh.\n * Handles the numProp > 3 case (manifold may carry extra property channels).\n * @param manifold The manifold from which to read mesh data.\n * @returns The extracted positions and indices buffers.\n */\nexport function manifoldToMeshData(manifold: ManifoldInstance): {\n positions: Float32Array; indices: Uint32Array\n} {\n const resultMesh = manifold.getMesh()\n const numProp = resultMesh.numProp || 3\n const vertPropsLen = resultMesh.vertProperties ? resultMesh.vertProperties.length : 0\n const vertCount = numProp > 0 ? Math.floor(vertPropsLen / numProp) : 0\n const positions = new Float32Array(vertCount * 3)\n for (let i = 0; i < vertCount; i++) {\n const base = i * numProp\n positions[i * 3] = resultMesh.vertProperties[base]\n positions[i * 3 + 1] = resultMesh.vertProperties[base + 1]\n positions[i * 3 + 2] = resultMesh.vertProperties[base + 2]\n }\n const triVerts = resultMesh.triVerts\n const indices = triVerts ? new Uint32Array(triVerts) : new Uint32Array(0)\n return { positions, indices }\n}\n\n// ── MeshData → Manifold ──\n\n/**\n * Build a Manifold from mesh data, welding duplicate vertices when the density\n * is too high (close to one independent vertex per triangle) before Manifold.ofMesh.\n * Shared by the Inline and Worker backends so both produce identical input conversion.\n * @param Manifold The Manifold constructor from the manifold module.\n * @param Mesh The Mesh constructor from the manifold module.\n * @param mesh The mesh data (positions and indices).\n * @returns The constructed Manifold instance.\n */\nexport function meshToManifold(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n mesh: { positions: Float32Array; indices: Uint32Array },\n): ManifoldInstance {\n const triCount = mesh.indices.length / 3\n const vertCount = mesh.positions.length / 3\n let positions = mesh.positions\n let indices = mesh.indices\n\n if (vertCount >= triCount * 3 * 0.9) {\n const welded = weldPositionsWorker(mesh.positions, mesh.indices, mesh.indices.length)\n positions = welded.positions\n indices = welded.indices\n }\n\n return Manifold.ofMesh(new Mesh({\n numProp: 3,\n vertProperties: positions,\n triVerts: indices,\n }))\n}\n\n/**\n * Sequentially apply a boolean operation across an array of Manifolds.\n * The caller is responsible for deleting the input manifolds and the result.\n * @param op The boolean operation to apply (union/subtract/intersect).\n * @param manifolds The manifolds to combine in order.\n * @returns The resulting Manifold of the chain.\n */\nexport function chainBoolean(\n op: 'union' | 'subtract' | 'intersect',\n manifolds: ManifoldInstance[],\n): ManifoldInstance {\n let result = manifolds[0]\n for (let i = 1; i < manifolds.length; i++) {\n switch (op) {\n case 'union':\n result = result.add(manifolds[i])\n break\n case 'subtract':\n result = result.subtract(manifolds[i])\n break\n case 'intersect':\n result = result.intersect(manifolds[i])\n break\n }\n }\n return result\n}\n\n// ── 顶点焊接 ──\n\n/**\n * Weld duplicate vertices using a quantized 1 µm grid.\n * Uses three nested numeric Maps (no string allocation).\n * @param positions The input vertex positions.\n * @param indices The input triangle indices.\n * @param count The number of indices to process.\n * @returns The welded positions and remapped indices buffers.\n */\nexport function weldPositionsWorker(\n positions: Float32Array,\n indices: Uint32Array,\n count: number,\n): { positions: Float32Array; indices: Uint32Array } {\n const mapX = new Map<number, Map<number, Map<number, number>>>()\n const weldedPosArr: number[] = []\n const weldedIdxArr: number[] = []\n\n for (let i = 0; i < count; i++) {\n const vi = indices[i]\n const x = positions[vi * 3]\n const y = positions[vi * 3 + 1]\n const z = positions[vi * 3 + 2]\n const qx = Math.round(x * 1e6)\n const qy = Math.round(y * 1e6)\n const qz = Math.round(z * 1e6)\n\n let mapY = mapX.get(qx)\n if (mapY === undefined) {\n mapY = new Map<number, Map<number, number>>()\n mapX.set(qx, mapY)\n }\n let mapZ = mapY.get(qy)\n if (mapZ === undefined) {\n mapZ = new Map<number, number>()\n mapY.set(qy, mapZ)\n }\n let ni = mapZ.get(qz)\n if (ni === undefined) {\n ni = weldedPosArr.length / 3\n mapZ.set(qz, ni)\n weldedPosArr.push(x, y, z)\n }\n weldedIdxArr.push(ni)\n }\n\n return {\n positions: new Float32Array(weldedPosArr),\n indices: new Uint32Array(weldedIdxArr),\n }\n}\n\n// ── Union-Find ──\n\n/** Simple union-find for clustering cap triangles by shared edges. */\nexport class SimpleUnionFind {\n private parent: number[]\n private rank: number[]\n\n /**\n * Create a union-find structure with n initial singletons.\n * @param n The number of elements.\n */\n constructor(n: number) {\n this.parent = Array.from({ length: n }, (_, i) => i)\n this.rank = new Array(n).fill(0)\n }\n\n /**\n * Find the root representative of the element x (with path compression).\n * @param x The element to look up.\n * @returns The root index of the set containing x.\n */\n find(x: number): number {\n if (this.parent[x] !== x) {\n this.parent[x] = this.find(this.parent[x])\n }\n return this.parent[x]\n }\n\n /**\n * Union the sets containing x and y.\n * @param x The first element.\n * @param y The second element.\n */\n union(x: number, y: number): void {\n const px = this.find(x)\n const py = this.find(y)\n if (px === py) return\n if (this.rank[px] < this.rank[py]) {\n this.parent[px] = py\n } else if (this.rank[px] > this.rank[py]) {\n this.parent[py] = px\n } else {\n this.parent[py] = px\n this.rank[px]++\n }\n }\n}\n\n// ── Wedge (trapezoidal prism) creation ──\n\n/**\n * Create a wedge (trapezoidal prism) Manifold from cutting-plane parameters.\n * @param Manifold The Manifold constructor from the manifold module.\n * @param Mesh The Mesh constructor from the manifold module.\n * @param planeCenter Center of the cutting plane.\n * @param normal Cutting plane normal (unit vector).\n * @param widthDir Extrusion direction (unit vector).\n * @param depth Wedge depth (mm).\n * @param width Wedge width (mm).\n * @param angleDeg Slant angle of the wedge sides (degrees).\n * @param extrudeLength Total extrusion length along widthDir (mm).\n * @returns The constructed wedge Manifold.\n */\nexport function createWedge(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n planeCenter: Vec3,\n normal: Vec3,\n widthDir: Vec3,\n depth: number,\n width: number,\n angleDeg: number,\n extrudeLength: number,\n): ManifoldInstance {\n const { positions, indices } = buildWedgeGeometry(\n planeCenter, normal, widthDir, depth, width, angleDeg, extrudeLength,\n )\n const mesh = new Mesh({\n numProp: 3,\n vertProperties: positions,\n triVerts: indices,\n })\n return Manifold.ofMesh(mesh)\n}\n\n// ── Cap component detection ──\n\n/**\n * Detect connected components of cap faces on the cutting plane.\n * Returns an array of components, each being a Set of vertex indices.\n * @param upper The upper mesh to scan for cap faces.\n * @param normal The cutting plane normal.\n * @param planeDistance The cutting plane offset along the normal.\n * @returns An array of components, each a Set of vertex indices on the cap.\n */\nexport function detectCapComponents(\n upper: ManifoldInstance,\n normal: Vec3,\n planeDistance: number,\n): Set<number>[] {\n const mesh = upper.getMesh()\n const eps = 0.001\n const numProp = mesh.numProp || 3\n const vertCount = Math.floor(mesh.vertProperties.length / numProp)\n const triVerts = mesh.triVerts\n if (!triVerts || triVerts.length === 0) return []\n\n const capVertSet = new Set<number>()\n interface CapTri { v0: number; v1: number; v2: number }\n const capTris: CapTri[] = []\n const triCount = triVerts.length / 3\n for (let t = 0; t < triCount; t++) {\n const i0 = triVerts[t * 3]\n const i1 = triVerts[t * 3 + 1]\n const i2 = triVerts[t * 3 + 2]\n const d0 = Math.abs(\n mesh.vertProperties[i0 * numProp] * normal[0] +\n mesh.vertProperties[i0 * numProp + 1] * normal[1] +\n mesh.vertProperties[i0 * numProp + 2] * normal[2] - planeDistance)\n const d1 = Math.abs(\n mesh.vertProperties[i1 * numProp] * normal[0] +\n mesh.vertProperties[i1 * numProp + 1] * normal[1] +\n mesh.vertProperties[i1 * numProp + 2] * normal[2] - planeDistance)\n const d2 = Math.abs(\n mesh.vertProperties[i2 * numProp] * normal[0] +\n mesh.vertProperties[i2 * numProp + 1] * normal[1] +\n mesh.vertProperties[i2 * numProp + 2] * normal[2] - planeDistance)\n if (d0 < eps && d1 < eps && d2 < eps) {\n capTris.push({ v0: i0, v1: i1, v2: i2 })\n capVertSet.add(i0); capVertSet.add(i1); capVertSet.add(i2)\n }\n }\n if (capTris.length === 0) return []\n\n const uf = new SimpleUnionFind(vertCount)\n for (const tri of capTris) {\n uf.union(tri.v0, tri.v1)\n uf.union(tri.v1, tri.v2)\n uf.union(tri.v0, tri.v2)\n }\n\n const compMap = new Map<number, Set<number>>()\n for (const vi of capVertSet) {\n const root = uf.find(vi)\n if (!compMap.has(root)) compMap.set(root, new Set<number>())\n compMap.get(root)!.add(vi)\n }\n\n return Array.from(compMap.values())\n}\n\n// ── Cross-section width computation ──\n\n/**\n * Compute the actual extent of the model's cross-section at the cutting plane\n * along the width direction.\n * @param upper The upper mesh to measure.\n * @param normal The cutting plane normal.\n * @param planeDistance The cutting plane offset along the normal.\n * @param widthDir The width direction along which to measure.\n * @param comp Optional connected component to restrict the measurement to.\n * @returns The cross-section extent along the width direction (0 when none found).\n */\nexport function computeCrossSectionWidth(\n upper: ManifoldInstance,\n normal: Vec3,\n planeDistance: number,\n widthDir: Vec3,\n comp?: Set<number>,\n): number {\n const mesh = upper.getMesh()\n const eps = 0.001\n let minProj = Infinity\n let maxProj = -Infinity\n let found = false\n\n const numProp = mesh.numProp || 3\n const vertCount = Math.floor(mesh.vertProperties.length / numProp)\n for (let i = 0; i < vertCount; i++) {\n if (comp && !comp.has(i)) continue\n\n const base = i * numProp\n const x = mesh.vertProperties[base]\n const y = mesh.vertProperties[base + 1]\n const z = mesh.vertProperties[base + 2]\n\n const dist = x * normal[0] + y * normal[1] + z * normal[2] - planeDistance\n if (Math.abs(dist) < eps) {\n const proj = x * widthDir[0] + y * widthDir[1] + z * widthDir[2]\n if (proj < minProj) minProj = proj\n if (proj > maxProj) maxProj = proj\n found = true\n }\n }\n\n if (!found) return 0\n return maxProj - minProj\n}\n\n// ── Cross-section centroid computation ──\n\n/**\n * Compute the centroid of vertices lying on the cutting plane.\n * @param upper The upper mesh to scan.\n * @param normal The cutting plane normal.\n * @param planeDistance The cutting plane offset along the normal.\n * @param fallback The centroid fallback when no vertex lies on the plane.\n * @param comp Optional connected component to restrict the measurement to.\n * @returns The computed centroid, or the fallback when none is found.\n */\nexport function computeCrossSectionCentroid(\n upper: ManifoldInstance,\n normal: Vec3,\n planeDistance: number,\n fallback: Vec3,\n comp?: Set<number>,\n): Vec3 {\n const mesh = upper.getMesh()\n const eps = 0.001\n let cx = 0, cy = 0, cz = 0\n let count = 0\n\n const numProp = mesh.numProp || 3\n const vertCount = Math.floor(mesh.vertProperties.length / numProp)\n for (let i = 0; i < vertCount; i++) {\n if (comp && !comp.has(i)) continue\n\n const base = i * numProp\n const x = mesh.vertProperties[base]\n const y = mesh.vertProperties[base + 1]\n const z = mesh.vertProperties[base + 2]\n\n const dist = x * normal[0] + y * normal[1] + z * normal[2] - planeDistance\n if (Math.abs(dist) < eps) {\n cx += x\n cy += y\n cz += z\n count++\n }\n }\n\n if (count === 0) return fallback\n return [cx / count, cy / count, cz / count]\n}\n\n// ── Dovetail boolean split ──\n\n/**\n * Perform the dovetail split using boolean operations.\n * @param Manifold - the Manifold constructor from the manifold module.\n * @param Mesh - the Mesh constructor from the manifold module.\n * @param original - the original manifold to split.\n * @param normal - the cutting plane normal (unit vector).\n * @param planeDistance - the plane equation origin offset along the normal.\n * @param planeCenter - a point on the cutting plane used to center the wedge.\n * @param widthDirInput - the width direction in the cutting plane (will be normalized).\n * @param bboxWidthOnWidthDir - the model's bounding-box width along widthDir, used as a fallback cross-section width.\n * @param groove - the dovetail groove design parameters (depth, tolerances, width, flaps angle).\n * @param keepOriginal - when true, the original manifold is not deleted after splitting (default false).\n * @returns a tuple of the split upper manifold, lower manifold, and the trimmed wedge mesh data (or null when empty).\n */\nexport function dovetailBooleanSplit(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n original: ManifoldInstance,\n normal: Vec3,\n planeDistance: number,\n planeCenter: Vec3,\n widthDirInput: Vec3,\n bboxWidthOnWidthDir: number,\n groove: {\n depth: number\n depthTolerance: number\n width: number\n widthTolerance: number\n flapsAngle: number\n },\n keepOriginal: boolean = false,\n): [ManifoldInstance, ManifoldInstance,\n { positions: Float32Array; indices: Uint32Array } | null] {\n const widthDir = vec3Normalize(widthDirInput)\n\n // Step 1: Split by plane → upper + lower\n const [upper, lower] = original.splitByPlane(normal, planeDistance)\n if (!keepOriginal) original.delete()\n\n // Step 2: Compute actual cross-section width at the cutting plane\n let crossSectionWidth = computeCrossSectionWidth(upper, normal, planeDistance, widthDir)\n if (crossSectionWidth <= 0) {\n crossSectionWidth = bboxWidthOnWidthDir\n }\n const extrudeLength = crossSectionWidth + 0.2\n\n // Step 3: Create wedge W with generous overhang along widthDir\n const overhang = 20\n\n const wedgeW = createWedge(\n Manifold, Mesh,\n planeCenter, normal, widthDir,\n groove.depth, groove.width, groove.flapsAngle,\n extrudeLength + overhang,\n )\n\n // Trim the wedge to the model by intersecting with lower.\n let wedgeForUnion: ManifoldInstance\n let wedgeMeshData: { positions: Float32Array; indices: Uint32Array } | null\n let lowerForSubtract: ManifoldInstance\n\n if (!wedgeW.isEmpty() && !lower.isEmpty()) {\n const lowerMeshData = manifoldToMeshData(lower)\n\n const trimmedWedge = wedgeW.intersect(lower)\n wedgeW.delete()\n lower.delete()\n\n wedgeMeshData = trimmedWedge.isEmpty() ? null : manifoldToMeshData(trimmedWedge)\n wedgeForUnion = trimmedWedge\n\n lowerForSubtract = Manifold.ofMesh(new Mesh({\n numProp: 3,\n vertProperties: lowerMeshData.positions,\n triVerts: lowerMeshData.indices,\n }))\n } else {\n wedgeMeshData = null\n wedgeForUnion = wedgeW\n lowerForSubtract = lower\n }\n\n // Step 5: union(upper, wedgeForUnion) → upper'\n let upperResult: ManifoldInstance\n if (upper.isEmpty()) {\n upper.delete()\n upperResult = wedgeForUnion\n } else if (wedgeForUnion.isEmpty()) {\n wedgeForUnion.delete()\n upperResult = upper\n } else {\n upperResult = upper.add(wedgeForUnion)\n upper.delete()\n wedgeForUnion.delete()\n }\n\n // Step 6: Create tolerance wedge W_tol\n const wedgeTol = createWedge(\n Manifold, Mesh,\n planeCenter, normal, widthDir,\n groove.depth + groove.depthTolerance,\n groove.width + groove.widthTolerance,\n groove.flapsAngle,\n extrudeLength + overhang,\n )\n\n // Step 7: lower.subtract(wedgeTol) → lower'\n let lowerResult: ManifoldInstance\n if (lowerForSubtract.isEmpty()) {\n wedgeTol.delete()\n lowerResult = lowerForSubtract\n } else if (wedgeTol.isEmpty()) {\n wedgeTol.delete()\n lowerResult = lowerForSubtract\n } else {\n lowerResult = lowerForSubtract.subtract(wedgeTol)\n lowerForSubtract.delete()\n wedgeTol.delete()\n }\n\n return [upperResult, lowerResult, wedgeMeshData]\n}\n\n// ── Dowel (cylinder) creation ──\n\n/**\n * Create a cylindrical Manifold for the dowel tenon.\n * @param Manifold - the Manifold constructor from the manifold module.\n * @param Mesh - the Mesh constructor from the manifold module.\n * @param centroid - the center of the cylinder in the cutting plane.\n * @param normal - the cutting plane normal (unit vector, points \"up\").\n * @param widthDir - the width direction in the cutting plane (unit vector).\n * @param depthDir - the depth direction in the cutting plane (unit vector).\n * @param diameter - the cylinder diameter (mm).\n * @param height - the cylinder height (mm), extends along -normal.\n * @param segments - the number of circular segments (default 32).\n * @returns the resulting cylindrical Manifold instance.\n */\nexport function createDowel(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n centroid: Vec3,\n normal: Vec3,\n widthDir: Vec3,\n depthDir: Vec3,\n diameter: number,\n height: number,\n segments: number = 32,\n): ManifoldInstance {\n const { positions, indices } = buildDowelGeometry(\n centroid, normal, widthDir, depthDir, diameter, height, segments,\n )\n const mesh = new Mesh({\n numProp: 3,\n vertProperties: positions,\n triVerts: indices,\n })\n return Manifold.ofMesh(mesh)\n}\n\n// ── Straight tenon (box) creation ──\n\n/**\n * Create a box-shaped Manifold for the straight tenon.\n * @param Manifold - the Manifold constructor from the manifold module.\n * @param Mesh - the Mesh constructor from the manifold module.\n * @param centroid - the center of the box in the cutting plane.\n * @param normal - the cutting plane normal (unit vector, points \"up\").\n * @param widthDir - the width direction in the cutting plane (unit vector).\n * @param depthDir - the depth direction in the cutting plane (unit vector).\n * @param sideLength - the square cross-section side length (mm).\n * @param height - the box height (mm), extends along -normal.\n * @returns the resulting box-shaped Manifold instance.\n */\nexport function createStraightTenon(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n centroid: Vec3,\n normal: Vec3,\n widthDir: Vec3,\n depthDir: Vec3,\n sideLength: number,\n height: number,\n): ManifoldInstance {\n const { positions, indices } = buildStraightTenonGeometry(\n centroid, normal, widthDir, depthDir, sideLength, height,\n )\n const mesh = new Mesh({\n numProp: 3,\n vertProperties: positions,\n triVerts: indices,\n })\n return Manifold.ofMesh(mesh)\n}\n\n// ── Dowel / Straight-tenon boolean split ──\n\n/**\n * Perform the dowel (or straight-tenon) split using boolean operations.\n * @param Manifold - the Manifold constructor from the manifold module.\n * @param Mesh - the Mesh constructor from the manifold module.\n * @param original - the original manifold to split.\n * @param normal - the cutting plane normal (unit vector).\n * @param planeDistance - the plane equation origin offset along the normal.\n * @param planeCenter - a point on the cutting plane used to center the joinery.\n * @param widthDirInput - the width direction in the cutting plane (will be normalized).\n * @param shape - the joinery shape: 'dowel' or 'tenon'.\n * @param params - the joinery sizing parameters (size, tolerances, height).\n * @param keepOriginal - when true, the original manifold is not deleted after splitting (default false).\n * @param selectedSections - optional list of indices selecting which cap sections receive joinery placement; null or empty means a single placement at the overall cross-section centroid.\n * @returns a tuple of the split upper manifold, lower manifold, and the generated joinery mesh data (or null).\n */\nexport function dowelOrTenonBooleanSplit(\n Manifold: ManifoldCtor,\n Mesh: MeshCtor,\n original: ManifoldInstance,\n normal: Vec3,\n planeDistance: number,\n planeCenter: Vec3,\n widthDirInput: Vec3,\n shape: 'dowel' | 'tenon',\n params: {\n size: number\n sizeTolerance: number\n height: number\n heightTolerance: number\n },\n keepOriginal: boolean = false,\n selectedSections?: number[] | null,\n): [ManifoldInstance, ManifoldInstance,\n { positions: Float32Array; indices: Uint32Array } | null] {\n const widthDir = vec3Normalize(widthDirInput)\n const depthDir = vec3Normalize(vec3Cross(normal, widthDir))\n\n // Step 1: Split by plane → upper + lower\n const [upper, lower] = original.splitByPlane(normal, planeDistance)\n if (!keepOriginal) original.delete()\n\n // Step 2: Detect cap components (multi-section support)\n const components = detectCapComponents(upper, normal, planeDistance)\n\n // Build the list of joinery placements: one per selected section\n interface JoineryPlacement { centroid: Vec3 }\n let placements: JoineryPlacement[]\n\n if (components.length <= 1 || !selectedSections || selectedSections.length === 0) {\n const centroid = computeCrossSectionCentroid(upper, normal, planeDistance, planeCenter)\n placements = [{ centroid }]\n } else {\n const compInfo = components.map((comp, idx) => {\n const compWidth = computeCrossSectionWidth(upper, normal, planeDistance, widthDir, comp)\n const compCentroid = computeCrossSectionCentroid(upper, normal, planeDistance, planeCenter, comp)\n const compDepth = computeCrossSectionWidth(upper, normal, planeDistance, depthDir, comp)\n const area = compWidth * compDepth\n return { idx, comp, area, centroid: compCentroid }\n })\n compInfo.sort((a, b) => b.area - a.area)\n\n placements = []\n for (const selId of selectedSections) {\n if (selId < compInfo.length) {\n placements.push({ centroid: compInfo[selId].centroid })\n }\n }\n if (placements.length === 0) {\n const centroid = computeCrossSectionCentroid(upper, normal, planeDistance, planeCenter)\n placements = [{ centroid }]\n }\n }\n\n // Step 3: For each placement, create shape C (no tolerance) and union into upper\n let shapeMeshData: { positions: Float32Array; indices: Uint32Array } | null = null\n\n let upperResult = upper\n let upperOwned = true\n\n for (let pIdx = 0; pIdx < placements.length; pIdx++) {\n const { centroid } = placements[pIdx]\n let shapeC: ManifoldInstance\n if (shape === 'dowel') {\n shapeC = createDowel(Manifold, Mesh, centroid, normal, widthDir, depthDir,\n params.size, params.height, 32)\n } else {\n shapeC = createStraightTenon(Manifold, Mesh, centroid, normal, widthDir, depthDir,\n params.size, params.height)\n }\n\n if (pIdx === 0) {\n shapeMeshData = shapeC.isEmpty() ? null : manifoldToMeshData(shapeC)\n }\n\n if (upperResult.isEmpty()) {\n if (upperOwned) upperResult.delete()\n upperResult = shapeC\n upperOwned = true\n } else if (shapeC.isEmpty()) {\n shapeC.delete()\n } else {\n const newUpper = upperResult.add(shapeC)\n if (upperOwned) upperResult.delete()\n upperResult = newUpper\n shapeC.delete()\n upperOwned = true\n }\n }\n\n // Step 4: For each placement, create shape C_tol (with tolerance) and subtract from lower\n const tolSize = params.size + params.sizeTolerance\n const tolHeight = params.height + params.heightTolerance\n\n let lowerResult = lower\n let lowerOwned = true\n\n for (const { centroid } of placements) {\n let shapeCTol: ManifoldInstance\n if (shape === 'dowel') {\n shapeCTol = createDowel(Manifold, Mesh, centroid, normal, widthDir, depthDir,\n tolSize, tolHeight, 32)\n } else {\n shapeCTol = createStraightTenon(Manifold, Mesh, centroid, normal, widthDir, depthDir,\n tolSize, tolHeight)\n }\n\n if (lowerResult.isEmpty()) {\n shapeCTol.delete()\n } else if (shapeCTol.isEmpty()) {\n shapeCTol.delete()\n } else {\n const newLower = lowerResult.subtract(shapeCTol)\n if (lowerOwned) lowerResult.delete()\n lowerResult = newLower\n shapeCTol.delete()\n lowerOwned = true\n }\n }\n\n return [upperResult, lowerResult, shapeMeshData]\n}\n"]}
@@ -11,7 +11,7 @@
11
11
  * 交互期的快速预览走 engine/components/extrude-preview-nosplit.ts(不 split 原模型)。
12
12
  *
13
13
  * 放在 engine/boolean/ 下的约束:**不得 import stores**(保持与 csg.ts 同层的纯度)。
14
- * 平面参数(normal / originOffset)由调用方用 computePlaneParams 算好后传入。
14
+ * 平面参数(normal / planeDistance)由调用方用 computePlaneParams 算好后传入。
15
15
  */
16
16
  import * as THREE from 'three';
17
17
  import type { ManifoldMeshData } from '../boolean/csg-backend.js';
@@ -41,15 +41,15 @@ export declare function computeExtrudeOffsets(mode: ExtrudeOffsetMode, length: n
41
41
  back: number;
42
42
  };
43
43
  /**
44
- * 由 computePlaneParams 的 (normal, originOffset) 构造 THREE 世界平面。
44
+ * 由 computePlaneParams 的 (normal, planeDistance) 构造 THREE 世界平面。
45
45
  *
46
- * 约定:平面方程为 `N · p = originOffset`;THREE.Plane 用 `N · p + constant = 0`,
47
- * 故 constant = -originOffset。THREE 裁剪保留 distanceToPoint >= 0 的一侧(法线正侧)。
46
+ * 约定:平面方程为 `N · p = planeDistance`;THREE.Plane 用 `N · p + constant = 0`,
47
+ * 故 constant = -planeDistance。THREE 裁剪保留 distanceToPoint >= 0 的一侧(法线正侧)。
48
48
  * @param normal - the cutting plane normal as a 3-component array.
49
- * @param originOffset - the plane equation origin offset along the normal.
49
+ * @param planeDistance - the plane equation origin offset along the normal.
50
50
  * @returns a THREE.Plane and its normalized normal vector.
51
51
  */
52
- export declare function makeWorldPlane(normal: [number, number, number], originOffset: number): {
52
+ export declare function makeWorldPlane(normal: [number, number, number], planeDistance: number): {
53
53
  plane: THREE.Plane;
54
54
  normalVec: THREE.Vector3;
55
55
  };
@@ -61,12 +61,12 @@ export declare function makeWorldPlane(normal: [number, number, number], originO
61
61
  *
62
62
  * @param worldMesh 世界空间的源网格(局部几何 × matrixWorld)
63
63
  * @param normal 切割平面法线(单位向量)
64
- * @param originOffset 平面方程 N·p = originOffset 的右端
64
+ * @param planeDistance 平面方程 N·p = planeDistance 的右端
65
65
  * @param length 拉伸长度 L
66
66
  * @param mode 三段位移模式
67
67
  * @returns the split front, back, and extruded middle mesh parts.
68
68
  */
69
- export declare function buildExtrudeParts(worldMesh: ManifoldMeshData, normal: [number, number, number], originOffset: number, length: number, mode: ExtrudeOffsetMode): Promise<ExtrudeParts>;
69
+ export declare function buildExtrudeParts(worldMesh: ManifoldMeshData, normal: [number, number, number], planeDistance: number, length: number, mode: ExtrudeOffsetMode): Promise<ExtrudeParts>;
70
70
  /**
71
71
  * 沿法线方向按 scaleFactor 缩放每个顶点到平面的有向距离。
72
72
  * 平面上的顶点不动,离面顶点按比例外推。
@@ -1 +1 @@
1
- {"version":3,"file":"extrude-helpers.d.ts","sourceRoot":"","sources":["../../src/boolean/extrude-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAE9D,qEAAqE;AACrE,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;AAEnE,mDAAmD;AACnD,eAAO,MAAM,eAAe,MAAM,CAAA;AAElC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC9B,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC7B,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAA;CAClC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,MAAM,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAUjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAChC,YAAY,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAA;CAAE,CAMlD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,gBAAgB,EAC3B,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAChC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,YAAY,CAAC,CAyBvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAChC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,gBAAgB,CAUlB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,gBAAgB,EACtB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACnC,QAAQ,EAAE,MAAM,GACf,gBAAgB,CAYlB"}
1
+ {"version":3,"file":"extrude-helpers.d.ts","sourceRoot":"","sources":["../../src/boolean/extrude-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAE9D,qEAAqE;AACrE,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;AAEnE,mDAAmD;AACnD,eAAO,MAAM,eAAe,MAAM,CAAA;AAElC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC9B,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC7B,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAA;CAClC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,MAAM,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAUjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAChC,aAAa,EAAE,MAAM,GACpB;IAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAA;CAAE,CAMlD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,gBAAgB,EAC3B,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAChC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,YAAY,CAAC,CAyBvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAChC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,gBAAgB,CAUlB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,gBAAgB,EACtB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACnC,QAAQ,EAAE,MAAM,GACf,gBAAgB,CAYlB"}
@@ -11,7 +11,7 @@
11
11
  * 交互期的快速预览走 engine/components/extrude-preview-nosplit.ts(不 split 原模型)。
12
12
  *
13
13
  * 放在 engine/boolean/ 下的约束:**不得 import stores**(保持与 csg.ts 同层的纯度)。
14
- * 平面参数(normal / originOffset)由调用方用 computePlaneParams 算好后传入。
14
+ * 平面参数(normal / planeDistance)由调用方用 computePlaneParams 算好后传入。
15
15
  */
16
16
  import * as THREE from 'three';
17
17
  import { computeSplit } from '../boolean/csg-backend.js';
@@ -38,18 +38,18 @@ export function computeExtrudeOffsets(mode, length) {
38
38
  }
39
39
  }
40
40
  /**
41
- * 由 computePlaneParams 的 (normal, originOffset) 构造 THREE 世界平面。
41
+ * 由 computePlaneParams 的 (normal, planeDistance) 构造 THREE 世界平面。
42
42
  *
43
- * 约定:平面方程为 `N · p = originOffset`;THREE.Plane 用 `N · p + constant = 0`,
44
- * 故 constant = -originOffset。THREE 裁剪保留 distanceToPoint >= 0 的一侧(法线正侧)。
43
+ * 约定:平面方程为 `N · p = planeDistance`;THREE.Plane 用 `N · p + constant = 0`,
44
+ * 故 constant = -planeDistance。THREE 裁剪保留 distanceToPoint >= 0 的一侧(法线正侧)。
45
45
  * @param normal - the cutting plane normal as a 3-component array.
46
- * @param originOffset - the plane equation origin offset along the normal.
46
+ * @param planeDistance - the plane equation origin offset along the normal.
47
47
  * @returns a THREE.Plane and its normalized normal vector.
48
48
  */
49
- export function makeWorldPlane(normal, originOffset) {
49
+ export function makeWorldPlane(normal, planeDistance) {
50
50
  const normalVec = new THREE.Vector3(normal[0], normal[1], normal[2]).normalize();
51
51
  return {
52
- plane: new THREE.Plane(normalVec.clone(), -originOffset),
52
+ plane: new THREE.Plane(normalVec.clone(), -planeDistance),
53
53
  normalVec,
54
54
  };
55
55
  }
@@ -61,25 +61,25 @@ export function makeWorldPlane(normal, originOffset) {
61
61
  *
62
62
  * @param worldMesh 世界空间的源网格(局部几何 × matrixWorld)
63
63
  * @param normal 切割平面法线(单位向量)
64
- * @param originOffset 平面方程 N·p = originOffset 的右端
64
+ * @param planeDistance 平面方程 N·p = planeDistance 的右端
65
65
  * @param length 拉伸长度 L
66
66
  * @param mode 三段位移模式
67
67
  * @returns the split front, back, and extruded middle mesh parts.
68
68
  */
69
- export async function buildExtrudeParts(worldMesh, normal, originOffset, length, mode) {
69
+ export async function buildExtrudeParts(worldMesh, normal, planeDistance, length, mode) {
70
70
  const { front: offsetFront, back: offsetBack } = computeExtrudeOffsets(mode, length);
71
71
  // 拉伸方向 D 恒等于切割平面法线 N
72
72
  const D = [normal[0], normal[1], normal[2]];
73
73
  // 1. 平面处切开 → front / back
74
- const splitResult = await computeSplit(worldMesh, normal, originOffset);
74
+ const splitResult = await computeSplit(worldMesh, normal, planeDistance);
75
75
  let front = splitResult.front;
76
76
  let back = splitResult.back;
77
77
  let extruded = null;
78
78
  // 2. 从 front 再切一片厚 SLICE_THICKNESS 的薄壳
79
- const capSplit = await computeSplit(splitResult.front, normal, originOffset + SLICE_THICKNESS);
80
- // 3. 薄壳以平面为锚点沿 N 放大 L/SLICE_THICKNESS → 占据 [originOffset, originOffset+L]
79
+ const capSplit = await computeSplit(splitResult.front, normal, planeDistance + SLICE_THICKNESS);
80
+ // 3. 薄壳以平面为锚点沿 N 放大 L/SLICE_THICKNESS → 占据 [planeDistance, planeDistance+L]
81
81
  if (capSplit.back && capSplit.back.indices.length > 0) {
82
- extruded = scaleMeshAlongNormal(capSplit.back, D, originOffset, length / SLICE_THICKNESS);
82
+ extruded = scaleMeshAlongNormal(capSplit.back, D, planeDistance, length / SLICE_THICKNESS);
83
83
  }
84
84
  // 4. 三段各自沿 D 位移;中段起点对齐 back 侧
85
85
  if (front)
@@ -1 +1 @@
1
- {"version":3,"file":"extrude-helpers.js","sourceRoot":"","sources":["../../src/boolean/extrude-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 拉伸(extrude)几何工具集 —— 从 ExtrudeRenderer.tsx 抽出的纯几何函数。\n *\n * 拉伸的语义(三段模型):在切割平面把模型切开,得到\n * - back(下半):沿法线 N 平移 offsetBack\n * - middle(中段):平面处的截面沿 N 挤出 L,落在 [offsetBack, offsetBack + L]\n * - front(上半):沿法线 N 平移 offsetFront\n * 其中 offsetFront - offsetBack === L 恒成立(见 computeExtrudeOffsets)。\n *\n * 本模块只负责「全分辨率、几何正确」的那条路径(预览提交 / 无预览直接执行)。\n * 交互期的快速预览走 engine/components/extrude-preview-nosplit.ts(不 split 原模型)。\n *\n * 放在 engine/boolean/ 下的约束:**不得 import stores**(保持与 csg.ts 同层的纯度)。\n * 平面参数(normal / originOffset)由调用方用 computePlaneParams 算好后传入。\n */\nimport * as THREE from 'three'\nimport { computeSplit } from '../boolean/csg-backend'\nimport type { ManifoldMeshData } from '../boolean/csg-backend'\n\n/** 与 extrude-store 的 ExtrusionMode 结构兼容(此处不 import store,避免层级倒置)。 */\nexport type ExtrudeOffsetMode = 'centered' | 'forward' | 'backward'\n\n/** slice 法取薄片的厚度(沿法线),随后按 L/SLICE_THICKNESS 拉伸。 */\nexport const SLICE_THICKNESS = 0.2\n\n/**\n * The three mesh parts produced by an extrude operation.\n */\nexport interface ExtrudeParts {\n front: ManifoldMeshData | null\n back: ManifoldMeshData | null\n extruded: ManifoldMeshData | null\n}\n\n/**\n * 三段的位移量。不变量:front - back === length。\n * - centered:平面居中,上下各推 L/2\n * - forward:只推上半 L,下半不动\n * - backward:只拉下半 -L,上半不动\n * @param mode - the offset mode ('centered', 'forward', or 'backward').\n * @param length - the extrusion length L (mm).\n * @returns the front and back displacement amounts, with front - back === length.\n */\nexport function computeExtrudeOffsets(\n mode: ExtrudeOffsetMode,\n length: number,\n): { front: number; back: number } {\n switch (mode) {\n case 'forward':\n return { front: length, back: 0 }\n case 'backward':\n return { front: 0, back: -length }\n case 'centered':\n default:\n return { front: length / 2, back: -length / 2 }\n }\n}\n\n/**\n * 由 computePlaneParams 的 (normal, originOffset) 构造 THREE 世界平面。\n *\n * 约定:平面方程为 `N · p = originOffset`;THREE.Plane 用 `N · p + constant = 0`,\n * 故 constant = -originOffset。THREE 裁剪保留 distanceToPoint >= 0 的一侧(法线正侧)。\n * @param normal - the cutting plane normal as a 3-component array.\n * @param originOffset - the plane equation origin offset along the normal.\n * @returns a THREE.Plane and its normalized normal vector.\n */\nexport function makeWorldPlane(\n normal: [number, number, number],\n originOffset: number,\n): { plane: THREE.Plane; normalVec: THREE.Vector3 } {\n const normalVec = new THREE.Vector3(normal[0], normal[1], normal[2]).normalize()\n return {\n plane: new THREE.Plane(normalVec.clone(), -originOffset),\n normalVec,\n }\n}\n\n/**\n * 全分辨率构建拉伸三段(世界空间进、世界空间出)。\n *\n * 这是**提交路径的唯一真相**:预览无论用什么近似手段,执行时都走这里重算,\n * so preview geometry errors do not pollute the final model.\n *\n * @param worldMesh 世界空间的源网格(局部几何 × matrixWorld)\n * @param normal 切割平面法线(单位向量)\n * @param originOffset 平面方程 N·p = originOffset 的右端\n * @param length 拉伸长度 L\n * @param mode 三段位移模式\n * @returns the split front, back, and extruded middle mesh parts.\n */\nexport async function buildExtrudeParts(\n worldMesh: ManifoldMeshData,\n normal: [number, number, number],\n originOffset: number,\n length: number,\n mode: ExtrudeOffsetMode,\n): Promise<ExtrudeParts> {\n const { front: offsetFront, back: offsetBack } = computeExtrudeOffsets(mode, length)\n // 拉伸方向 D 恒等于切割平面法线 N\n const D: [number, number, number] = [normal[0], normal[1], normal[2]]\n\n // 1. 平面处切开 → front / back\n const splitResult = await computeSplit(worldMesh, normal, originOffset)\n let front: ManifoldMeshData | null = splitResult.front\n let back: ManifoldMeshData | null = splitResult.back\n let extruded: ManifoldMeshData | null = null\n\n // 2. 从 front 再切一片厚 SLICE_THICKNESS 的薄壳\n const capSplit = await computeSplit(splitResult.front, normal, originOffset + SLICE_THICKNESS)\n\n // 3. 薄壳以平面为锚点沿 N 放大 L/SLICE_THICKNESS → 占据 [originOffset, originOffset+L]\n if (capSplit.back && capSplit.back.indices.length > 0) {\n extruded = scaleMeshAlongNormal(capSplit.back, D, originOffset, length / SLICE_THICKNESS)\n }\n\n // 4. 三段各自沿 D 位移;中段起点对齐 back 侧\n if (front) front = offsetMesh(front, D, offsetFront)\n if (back) back = offsetMesh(back, D, offsetBack)\n if (extruded) extruded = offsetMesh(extruded, D, offsetBack)\n\n return { front, back, extruded }\n}\n\n/**\n * 沿法线方向按 scaleFactor 缩放每个顶点到平面的有向距离。\n * 平面上的顶点不动,离面顶点按比例外推。\n * @param mesh - the source mesh data to scale.\n * @param normal - the plane normal (unit vector).\n * @param planeOffset - the plane offset along the normal.\n * @param scaleFactor - the scaling factor applied to each vertex's signed distance to the plane.\n * @returns the scaled mesh data (positions rewritten, indices unchanged).\n */\nexport function scaleMeshAlongNormal(\n mesh: ManifoldMeshData,\n normal: [number, number, number],\n planeOffset: number,\n scaleFactor: number,\n): ManifoldMeshData {\n const out = new Float32Array(mesh.positions)\n for (let i = 0; i < out.length; i += 3) {\n const d = out[i] * normal[0] + out[i + 1] * normal[1] + out[i + 2] * normal[2] - planeOffset\n const delta = d * scaleFactor - d\n out[i] += normal[0] * delta\n out[i + 1] += normal[1] * delta\n out[i + 2] += normal[2] * delta\n }\n return { positions: out, indices: mesh.indices }\n}\n\n/**\n * 整体沿 direction 平移 distance(distance 为 0 时原样返回,不拷贝)。\n * @param mesh - the source mesh data to translate.\n * @param direction - the translation direction (not necessarily unit length).\n * @param distance - the translation distance (mm); 0 returns the mesh unchanged.\n * @returns the translated mesh data (positions rewritten, indices unchanged).\n */\nexport function offsetMesh(\n mesh: ManifoldMeshData,\n direction: [number, number, number],\n distance: number,\n): ManifoldMeshData {\n if (distance === 0) return mesh\n const dx = direction[0] * distance\n const dy = direction[1] * distance\n const dz = direction[2] * distance\n const out = new Float32Array(mesh.positions)\n for (let i = 0; i < out.length; i += 3) {\n out[i] += dx\n out[i + 1] += dy\n out[i + 2] += dz\n }\n return { positions: out, indices: mesh.indices }\n}\n"]}
1
+ {"version":3,"file":"extrude-helpers.js","sourceRoot":"","sources":["../../src/boolean/extrude-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 拉伸(extrude)几何工具集 —— 从 ExtrudeRenderer.tsx 抽出的纯几何函数。\n *\n * 拉伸的语义(三段模型):在切割平面把模型切开,得到\n * - back(下半):沿法线 N 平移 offsetBack\n * - middle(中段):平面处的截面沿 N 挤出 L,落在 [offsetBack, offsetBack + L]\n * - front(上半):沿法线 N 平移 offsetFront\n * 其中 offsetFront - offsetBack === L 恒成立(见 computeExtrudeOffsets)。\n *\n * 本模块只负责「全分辨率、几何正确」的那条路径(预览提交 / 无预览直接执行)。\n * 交互期的快速预览走 engine/components/extrude-preview-nosplit.ts(不 split 原模型)。\n *\n * 放在 engine/boolean/ 下的约束:**不得 import stores**(保持与 csg.ts 同层的纯度)。\n * 平面参数(normal / planeDistance)由调用方用 computePlaneParams 算好后传入。\n */\nimport * as THREE from 'three'\nimport { computeSplit } from '../boolean/csg-backend'\nimport type { ManifoldMeshData } from '../boolean/csg-backend'\n\n/** 与 extrude-store 的 ExtrusionMode 结构兼容(此处不 import store,避免层级倒置)。 */\nexport type ExtrudeOffsetMode = 'centered' | 'forward' | 'backward'\n\n/** slice 法取薄片的厚度(沿法线),随后按 L/SLICE_THICKNESS 拉伸。 */\nexport const SLICE_THICKNESS = 0.2\n\n/**\n * The three mesh parts produced by an extrude operation.\n */\nexport interface ExtrudeParts {\n front: ManifoldMeshData | null\n back: ManifoldMeshData | null\n extruded: ManifoldMeshData | null\n}\n\n/**\n * 三段的位移量。不变量:front - back === length。\n * - centered:平面居中,上下各推 L/2\n * - forward:只推上半 L,下半不动\n * - backward:只拉下半 -L,上半不动\n * @param mode - the offset mode ('centered', 'forward', or 'backward').\n * @param length - the extrusion length L (mm).\n * @returns the front and back displacement amounts, with front - back === length.\n */\nexport function computeExtrudeOffsets(\n mode: ExtrudeOffsetMode,\n length: number,\n): { front: number; back: number } {\n switch (mode) {\n case 'forward':\n return { front: length, back: 0 }\n case 'backward':\n return { front: 0, back: -length }\n case 'centered':\n default:\n return { front: length / 2, back: -length / 2 }\n }\n}\n\n/**\n * 由 computePlaneParams 的 (normal, planeDistance) 构造 THREE 世界平面。\n *\n * 约定:平面方程为 `N · p = planeDistance`;THREE.Plane 用 `N · p + constant = 0`,\n * 故 constant = -planeDistance。THREE 裁剪保留 distanceToPoint >= 0 的一侧(法线正侧)。\n * @param normal - the cutting plane normal as a 3-component array.\n * @param planeDistance - the plane equation origin offset along the normal.\n * @returns a THREE.Plane and its normalized normal vector.\n */\nexport function makeWorldPlane(\n normal: [number, number, number],\n planeDistance: number,\n): { plane: THREE.Plane; normalVec: THREE.Vector3 } {\n const normalVec = new THREE.Vector3(normal[0], normal[1], normal[2]).normalize()\n return {\n plane: new THREE.Plane(normalVec.clone(), -planeDistance),\n normalVec,\n }\n}\n\n/**\n * 全分辨率构建拉伸三段(世界空间进、世界空间出)。\n *\n * 这是**提交路径的唯一真相**:预览无论用什么近似手段,执行时都走这里重算,\n * so preview geometry errors do not pollute the final model.\n *\n * @param worldMesh 世界空间的源网格(局部几何 × matrixWorld)\n * @param normal 切割平面法线(单位向量)\n * @param planeDistance 平面方程 N·p = planeDistance 的右端\n * @param length 拉伸长度 L\n * @param mode 三段位移模式\n * @returns the split front, back, and extruded middle mesh parts.\n */\nexport async function buildExtrudeParts(\n worldMesh: ManifoldMeshData,\n normal: [number, number, number],\n planeDistance: number,\n length: number,\n mode: ExtrudeOffsetMode,\n): Promise<ExtrudeParts> {\n const { front: offsetFront, back: offsetBack } = computeExtrudeOffsets(mode, length)\n // 拉伸方向 D 恒等于切割平面法线 N\n const D: [number, number, number] = [normal[0], normal[1], normal[2]]\n\n // 1. 平面处切开 → front / back\n const splitResult = await computeSplit(worldMesh, normal, planeDistance)\n let front: ManifoldMeshData | null = splitResult.front\n let back: ManifoldMeshData | null = splitResult.back\n let extruded: ManifoldMeshData | null = null\n\n // 2. 从 front 再切一片厚 SLICE_THICKNESS 的薄壳\n const capSplit = await computeSplit(splitResult.front, normal, planeDistance + SLICE_THICKNESS)\n\n // 3. 薄壳以平面为锚点沿 N 放大 L/SLICE_THICKNESS → 占据 [planeDistance, planeDistance+L]\n if (capSplit.back && capSplit.back.indices.length > 0) {\n extruded = scaleMeshAlongNormal(capSplit.back, D, planeDistance, length / SLICE_THICKNESS)\n }\n\n // 4. 三段各自沿 D 位移;中段起点对齐 back 侧\n if (front) front = offsetMesh(front, D, offsetFront)\n if (back) back = offsetMesh(back, D, offsetBack)\n if (extruded) extruded = offsetMesh(extruded, D, offsetBack)\n\n return { front, back, extruded }\n}\n\n/**\n * 沿法线方向按 scaleFactor 缩放每个顶点到平面的有向距离。\n * 平面上的顶点不动,离面顶点按比例外推。\n * @param mesh - the source mesh data to scale.\n * @param normal - the plane normal (unit vector).\n * @param planeOffset - the plane offset along the normal.\n * @param scaleFactor - the scaling factor applied to each vertex's signed distance to the plane.\n * @returns the scaled mesh data (positions rewritten, indices unchanged).\n */\nexport function scaleMeshAlongNormal(\n mesh: ManifoldMeshData,\n normal: [number, number, number],\n planeOffset: number,\n scaleFactor: number,\n): ManifoldMeshData {\n const out = new Float32Array(mesh.positions)\n for (let i = 0; i < out.length; i += 3) {\n const d = out[i] * normal[0] + out[i + 1] * normal[1] + out[i + 2] * normal[2] - planeOffset\n const delta = d * scaleFactor - d\n out[i] += normal[0] * delta\n out[i + 1] += normal[1] * delta\n out[i + 2] += normal[2] * delta\n }\n return { positions: out, indices: mesh.indices }\n}\n\n/**\n * 整体沿 direction 平移 distance(distance 为 0 时原样返回,不拷贝)。\n * @param mesh - the source mesh data to translate.\n * @param direction - the translation direction (not necessarily unit length).\n * @param distance - the translation distance (mm); 0 returns the mesh unchanged.\n * @returns the translated mesh data (positions rewritten, indices unchanged).\n */\nexport function offsetMesh(\n mesh: ManifoldMeshData,\n direction: [number, number, number],\n distance: number,\n): ManifoldMeshData {\n if (distance === 0) return mesh\n const dx = direction[0] * distance\n const dy = direction[1] * distance\n const dz = direction[2] * distance\n const out = new Float32Array(mesh.positions)\n for (let i = 0; i < out.length; i += 3) {\n out[i] += dx\n out[i + 1] += dy\n out[i + 2] += dz\n }\n return { positions: out, indices: mesh.indices }\n}\n"]}
@@ -181,10 +181,16 @@ export declare function drillBrep(kernel: BrepEngineApi, solid: BrepHandle, para
181
181
  export interface SplitBrepParams {
182
182
  /** 切割平面法线 */
183
183
  normal: Vec3;
184
- /** 切割平面原点偏移(法线方向上的距离) */
185
- originOffset: number;
186
- /** 切割平面中心点 */
187
- planeCenter: Vec3;
184
+ /**
185
+ * 切割平面位置:世界系平面方程 d 值(n·x = planeDistance)。
186
+ * 与 planeCenter 二选一必填;都缺省时抛错,不隐式回退。
187
+ */
188
+ planeDistance?: number;
189
+ /**
190
+ * 切割平面位置:世界坐标点(平面中心)。
191
+ * 与 planeDistance 二选一必填;都缺省时抛错,不隐式回退。
192
+ */
193
+ planeCenter?: Vec3;
188
194
  }
189
195
  /** splitBrep 的结果 */
190
196
  export interface SplitBrepResult {
@@ -214,8 +220,16 @@ export declare function splitBrep(kernel: BrepEngineApi, solid: BrepHandle, para
214
220
  export interface ExtrudeBrepParams {
215
221
  /** 拉伸法线方向 */
216
222
  normal: Vec3;
217
- /** 平面原点偏移 */
218
- originOffset: number;
223
+ /**
224
+ * 切割平面位置:世界系平面方程 d 值(n·x = planeDistance)。
225
+ * 与 planeCenter 二选一必填;都缺省时抛错,不隐式回退。
226
+ */
227
+ planeDistance?: number;
228
+ /**
229
+ * 切割平面位置:世界坐标点(平面中心)。
230
+ * 与 planeDistance 二选一必填;都缺省时抛错,不隐式回退。
231
+ */
232
+ planeCenter?: Vec3;
219
233
  /** 拉伸长度 */
220
234
  length: number;
221
235
  /** 拉伸模式 */
@@ -1 +1 @@
1
- {"version":3,"file":"brep-ops.d.ts","sourceRoot":"","sources":["../../src/brep/brep-ops.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"brep-ops.d.ts","sourceRoot":"","sources":["../../src/brep/brep-ops.ts"],"names":[],"mappings":"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"}
@@ -308,7 +308,6 @@ export function splitBrep(kernel, solid, params) {
308
308
  const bbox = getSolidBoundingBox(kernel, solid);
309
309
  const bboxSize = new THREE.Vector3(bbox.max[0] - bbox.min[0], bbox.max[1] - bbox.min[1], bbox.max[2] - bbox.min[2]);
310
310
  const bboxMax = Math.max(bboxSize.x, bboxSize.y, bboxSize.z);
311
- const bboxCenter = new THREE.Vector3((bbox.min[0] + bbox.max[0]) / 2, (bbox.min[1] + bbox.max[1]) / 2, (bbox.min[2] + bbox.max[2]) / 2);
312
311
  // 创建一个大的盒子代表法线正方向的半空间
313
312
  const normal = new THREE.Vector3(...params.normal).normalize();
314
313
  const halfSize = bboxMax * 3; // 足够大
@@ -319,10 +318,9 @@ export function splitBrep(kernel, solid, params) {
319
318
  const rotMatrix = new THREE.Matrix4().makeRotationFromQuaternion(quat);
320
319
  // 在局部坐标系中,盒子从 Z=0(切割平面)延伸到 Z=halfSize
321
320
  const localBox = kernel.makeBoxFromCorners({ x: -halfSize, y: -halfSize, z: 0 }, { x: halfSize, y: halfSize, z: halfSize });
322
- // 计算切割平面的世界坐标原点
323
- const planeOrigin = params.planeCenter
324
- ? new THREE.Vector3(...params.planeCenter)
325
- : bboxCenter.clone().add(normal.clone().multiplyScalar(params.originOffset));
321
+ // 计算切割平面的世界坐标原点(planeCenter / planeDistance 二选一必填,
322
+ // 都缺省直接报错,不隐式回退 bbox 中心)
323
+ const planeOrigin = resolvePlaneOrigin(normal, params.planeCenter, params.planeDistance);
326
324
  const transMatrix = new THREE.Matrix4().makeTranslation(planeOrigin.x, planeOrigin.y, planeOrigin.z);
327
325
  const finalMatrix = new THREE.Matrix4().multiplyMatrices(transMatrix, rotMatrix);
328
326
  const halfSpaceBox = kernel.transform(localBox, matrixToArray(finalMatrix));
@@ -338,6 +336,17 @@ export function splitBrep(kernel, solid, params) {
338
336
  throw new Error(`[splitBrep] OCCT split failed: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
339
337
  }
340
338
  }
339
+ /** 从 planeCenter / planeDistance 收敛出切割平面上的一个点(planeOrigin)。 */
340
+ function resolvePlaneOrigin(normal, planeCenter, planeDistance) {
341
+ if (planeCenter !== undefined) {
342
+ return new THREE.Vector3(...planeCenter);
343
+ }
344
+ if (planeDistance !== undefined) {
345
+ // 平面方程 n·x = d 上的点:取法线上距原点 d 处(n 为单位向量)
346
+ return normal.clone().multiplyScalar(planeDistance);
347
+ }
348
+ throw new Error('[extrudeBrep] plane location missing: provide planeCenter or planeDistance (implicit bbox-center fallback is forbidden)');
349
+ }
341
350
  /**
342
351
  * BREP 拉伸:在切割平面处将实体切开,中段沿法线拉伸 length,三段 fuse。
343
352
  *
@@ -358,18 +367,17 @@ export function extrudeBrep(kernel, solid, params) {
358
367
  const mode = params.mode ?? 'centered';
359
368
  const normal = new THREE.Vector3(...params.normal).normalize();
360
369
  const length = params.length;
361
- // 1. 创建切割平面盒子
362
- const bbox = getSolidBoundingBox(kernel, solid);
363
- const bboxCenter = new THREE.Vector3((bbox.min[0] + bbox.max[0]) / 2, (bbox.min[1] + bbox.max[1]) / 2, (bbox.min[2] + bbox.max[2]) / 2);
364
- const planeOrigin = bboxCenter.clone().add(normal.clone().multiplyScalar(params.originOffset));
370
+ // 1. 确定切割平面位置(世界系,来源静态:planeCenter 或 planeDistance,
371
+ // 都缺省直接报错,不隐式回退 bbox 中心)
372
+ const planeOrigin = resolvePlaneOrigin(normal, params.planeCenter, params.planeDistance);
365
373
  // 2. 分割实体
366
374
  const splitResult = splitBrep(kernel, solid, {
367
375
  normal: [normal.x, normal.y, normal.z],
368
- originOffset: params.originOffset,
369
376
  planeCenter: [planeOrigin.x, planeOrigin.y, planeOrigin.z],
370
377
  });
371
378
  // 3. 获取截面
372
379
  // 使用 section 获取切割平面与实体的交线
380
+ const bbox = getSolidBoundingBox(kernel, solid);
373
381
  const zAxis = new THREE.Vector3(0, 0, 1);
374
382
  const quat = new THREE.Quaternion().setFromUnitVectors(zAxis, normal);
375
383
  const rotMatrix = new THREE.Matrix4().makeRotationFromQuaternion(quat);
@@ -428,7 +436,25 @@ export function extrudeBrep(kernel, solid, params) {
428
436
  kernel.release(splitResult.back);
429
437
  throw new Error('[extrudeBrep] failed to build extrusion from section');
430
438
  }
431
- // 5. 计算各段位置
439
+ // 5. 中段落位补偿(修复 centered 模式中空 / 开壳)
440
+ //
441
+ // 切割平面位于 planeOrigin,splitBrep 产出的 front/back 其切面恰好在 planeOrigin。
442
+ // - forward:front 偏移 +L、back 偏移 0 → 中段(从 planeOrigin 沿 +normal 拉伸 L,
443
+ // 底面在 planeOrigin)的顶面(planeOrigin+L)正好接 front 底面,无需位移。
444
+ // - backward:front 偏移 0、back 偏移 -L → 中段(沿 -normal 拉伸 L,顶在 planeOrigin)
445
+ // 底面(planeOrigin-L)正好接 back 顶面,无需位移。
446
+ // - centered:front 偏移 +L/2、back 偏移 -L/2,二者之间让出 L 的缝隙;但中段默认
447
+ // 从 planeOrigin 沿 +normal 拉伸 L,落在 planeOrigin→planeOrigin+L,与 back 顶面
448
+ // (planeOrigin-L/2) 和 front 底面 (planeOrigin+L/2) 各错开 L/2,形成两道 L/2 的缝隙
449
+ // → fuse 后实体开壳 / 中空。必须对中段额外沿 -normal 位移 L/2,使其落在
450
+ // planeOrigin-L/2 → planeOrigin+L/2,正好填补缝隙。
451
+ const middleOffset = mode === 'centered' ? -length / 2 : 0;
452
+ if (middleOffset !== 0) {
453
+ const translatedMiddle = kernel.translate(extrudedSolid, normal.x * middleOffset, normal.y * middleOffset, normal.z * middleOffset);
454
+ kernel.release(extrudedSolid);
455
+ extrudedSolid = translatedMiddle;
456
+ }
457
+ // 6. 计算各段位置
432
458
  let frontOffset;
433
459
  let backOffset;
434
460
  if (mode === 'centered') {
@@ -448,7 +474,7 @@ export function extrudeBrep(kernel, solid, params) {
448
474
  kernel.release(splitResult.front);
449
475
  const backTranslated = kernel.translate(splitResult.back, normal.x * backOffset, normal.y * backOffset, normal.z * backOffset);
450
476
  kernel.release(splitResult.back);
451
- // 6. Fuse 三段
477
+ // 7. Fuse 三段
452
478
  let result;
453
479
  try {
454
480
  const fused1 = kernel.fuse(frontTranslated, extrudedSolid);