@faicad/sheetmetal 0.16.1 → 0.18.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 (103) hide show
  1. package/dist/allowanceFns.d.ts +1 -1
  2. package/dist/allowanceFns.d.ts.map +1 -1
  3. package/dist/allowanceFns.js +1 -1
  4. package/dist/allowanceFns.js.map +1 -1
  5. package/dist/api.d.ts +21 -20
  6. package/dist/api.d.ts.map +1 -1
  7. package/dist/api.js +20 -20
  8. package/dist/api.js.map +1 -1
  9. package/dist/authorFns.d.ts +2 -2
  10. package/dist/authorFns.d.ts.map +1 -1
  11. package/dist/authorFns.js +61 -51
  12. package/dist/authorFns.js.map +1 -1
  13. package/dist/bendTableFns.d.ts +1 -1
  14. package/dist/bendTableFns.d.ts.map +1 -1
  15. package/dist/bendTableFns.js +1 -1
  16. package/dist/bendTableFns.js.map +1 -1
  17. package/dist/contourFlangeFns.d.ts +5 -4
  18. package/dist/contourFlangeFns.d.ts.map +1 -1
  19. package/dist/contourFlangeFns.js +59 -44
  20. package/dist/contourFlangeFns.js.map +1 -1
  21. package/dist/cutoutFns.d.ts +5 -5
  22. package/dist/cutoutFns.d.ts.map +1 -1
  23. package/dist/cutoutFns.js +22 -14
  24. package/dist/cutoutFns.js.map +1 -1
  25. package/dist/dxfFns.d.ts +1 -1
  26. package/dist/dxfFns.d.ts.map +1 -1
  27. package/dist/dxfFns.js +1 -1
  28. package/dist/dxfFns.js.map +1 -1
  29. package/dist/facade.d.ts +43 -42
  30. package/dist/facade.d.ts.map +1 -1
  31. package/dist/facade.js +83 -83
  32. package/dist/facade.js.map +1 -1
  33. package/dist/featureTreeFns.d.ts +1 -1
  34. package/dist/featureTreeFns.d.ts.map +1 -1
  35. package/dist/featureTreeFns.js +1 -1
  36. package/dist/featureTreeFns.js.map +1 -1
  37. package/dist/foldFns.d.ts +3 -3
  38. package/dist/foldFns.d.ts.map +1 -1
  39. package/dist/foldFns.js +12 -12
  40. package/dist/foldFns.js.map +1 -1
  41. package/dist/foreignUnfoldFns.d.ts +2 -1
  42. package/dist/foreignUnfoldFns.d.ts.map +1 -1
  43. package/dist/foreignUnfoldFns.js +21 -10
  44. package/dist/foreignUnfoldFns.js.map +1 -1
  45. package/dist/formFns.d.ts +4 -4
  46. package/dist/formFns.d.ts.map +1 -1
  47. package/dist/formFns.js +91 -76
  48. package/dist/formFns.js.map +1 -1
  49. package/dist/geometryOps.d.ts +53 -0
  50. package/dist/geometryOps.d.ts.map +1 -0
  51. package/dist/geometryOps.js +104 -0
  52. package/dist/geometryOps.js.map +1 -0
  53. package/dist/hemFns.d.ts +2 -2
  54. package/dist/hemFns.d.ts.map +1 -1
  55. package/dist/hemFns.js +4 -4
  56. package/dist/hemFns.js.map +1 -1
  57. package/dist/internal.d.ts +2 -1
  58. package/dist/internal.d.ts.map +1 -1
  59. package/dist/internal.js +1 -1
  60. package/dist/internal.js.map +1 -1
  61. package/dist/jogFns.d.ts +2 -2
  62. package/dist/jogFns.d.ts.map +1 -1
  63. package/dist/jogFns.js +6 -6
  64. package/dist/jogFns.js.map +1 -1
  65. package/dist/loftedFlangeFns.d.ts +2 -2
  66. package/dist/loftedFlangeFns.d.ts.map +1 -1
  67. package/dist/loftedFlangeFns.js +35 -25
  68. package/dist/loftedFlangeFns.js.map +1 -1
  69. package/dist/miterFns.d.ts +3 -3
  70. package/dist/miterFns.d.ts.map +1 -1
  71. package/dist/miterFns.js +30 -19
  72. package/dist/miterFns.js.map +1 -1
  73. package/dist/nestFns.d.ts +1 -1
  74. package/dist/nestFns.d.ts.map +1 -1
  75. package/dist/nestFns.js +1 -1
  76. package/dist/nestFns.js.map +1 -1
  77. package/dist/polygonFns.d.ts +2 -2
  78. package/dist/polygonFns.d.ts.map +1 -1
  79. package/dist/polygonFns.js +1 -1
  80. package/dist/polygonFns.js.map +1 -1
  81. package/dist/reliefFns.d.ts +4 -4
  82. package/dist/reliefFns.d.ts.map +1 -1
  83. package/dist/reliefFns.js +39 -31
  84. package/dist/reliefFns.js.map +1 -1
  85. package/dist/reportFns.d.ts +1 -1
  86. package/dist/reportFns.d.ts.map +1 -1
  87. package/dist/reportFns.js +1 -1
  88. package/dist/reportFns.js.map +1 -1
  89. package/dist/tabFns.d.ts +3 -3
  90. package/dist/tabFns.d.ts.map +1 -1
  91. package/dist/tabFns.js +21 -13
  92. package/dist/tabFns.js.map +1 -1
  93. package/dist/types.d.ts +21 -1
  94. package/dist/types.d.ts.map +1 -1
  95. package/dist/types.js.map +1 -1
  96. package/dist/unfoldFns.d.ts +1 -1
  97. package/dist/unfoldFns.d.ts.map +1 -1
  98. package/dist/unfoldFns.js +2 -2
  99. package/dist/unfoldFns.js.map +1 -1
  100. package/dist/validateFns.d.ts.map +1 -1
  101. package/dist/validateFns.js +4 -6
  102. package/dist/validateFns.js.map +1 -1
  103. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"polygonFns.js","sourceRoot":"","sources":["../src/polygonFns.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 2D simple-polygon geometry for true-shape (no-fit-polygon) nesting: an ordered\n * vertex loop plus the overlap predicate that is the correctness backbone of the\n * packer. A false negative here would let two parts physically collide on the laser\n * bed, so the predicate is exhaustive: two simple polygons overlap iff any of their\n * edges cross OR one polygon contains a vertex of the other (the latter catches full\n * containment, where no edges cross).\n *\n * Sheet-metal flat outlines are straight-edged polylines; an arc edge (rare in a\n * developed pattern) is approximated by its two endpoints — the same pre-existing\n * assumption the DXF/SVG writers and the bbox nester make.\n */\n\nimport {\n type Result,\n ok,\n err,\n isOk,\n validationError,\n getEdges,\n curveStartPoint,\n curveEndPoint,\n} from '@faicad/faijs/brepjs-compat';\nimport type { Wire } from '@faicad/faijs/brepjs-compat';\nimport type { FlatPattern } from './types.js';\n\n/** A 2D point as a plain `[x, y]` coordinate tuple. */\nexport type Pt2 = [number, number];\n\n/** A simple (non-self-intersecting) polygon as an ordered, non-closing vertex loop. */\nexport type Polygon = Pt2[];\n\nconst EPS = 1e-9;\n\n/**\n * Ordered vertex loop of a closed outline wire — one vertex per edge start point, the\n * same 2D read the DXF writer (`outlinePoints`) and the bbox nester (`patternBbox`)\n * use. The loop is NOT closed (the last vertex is not repeated); edges are taken as\n * `v[i] → v[(i+1) % n]`.\n *\n * @param outline - the closed outline wire to read into a vertex loop.\n * @returns a `Result<Polygon>` — `ok` with the ordered vertex loop, or `err` with a\n * `validationError` when the outline is empty or has fewer than 3 vertices.\n */\nexport function wireToPolygon(outline: Wire): Result<Polygon> {\n const edges = getEdges(outline);\n if (edges.length === 0) {\n return err(validationError('EMPTY_OUTLINE', 'outline wire has no edges to read'));\n }\n const poly: Polygon = [];\n for (const edge of edges) {\n const p = curveStartPoint(edge);\n poly.push([p[0], p[1]]);\n }\n if (poly.length < 3) {\n return err(validationError('EMPTY_OUTLINE', 'outline polygon has fewer than 3 vertices'));\n }\n return ok(poly);\n}\n\n/** A bend line in the developed plane: a segment plus its fold direction. */\nexport interface FlatPatternBendLine {\n from: Pt2;\n to: Pt2;\n direction: 'up' | 'down';\n}\n\n/** A flat pattern reduced to serializable 2D polylines for a developed-view overlay. */\nexport interface FlatPatternPolylines {\n /** Closed outer boundary as an ordered, non-closing vertex loop. */\n outline: Polygon;\n /** Interior cutout loops (holes / slots / polygon cutouts). */\n holes: Polygon[];\n /** Bend lines, each with its fold direction. */\n bendLines: FlatPatternBendLine[];\n /** Open form-feature cut paths in the blank (e.g. louver/lance three-sided cuts). */\n formCuts: Polygon[];\n /** Form-feature hinge lines (the uncut fold edge a louver/lance forms up along). */\n formHinges: { from: Pt2; to: Pt2 }[];\n}\n\n/**\n * Read a wire as an OPEN polyline: every edge start plus the final edge's end,\n * so the last vertex of a non-closing path (a form cut) isn't dropped the way\n * {@link wireToPolygon} drops it for closed loops.\n *\n * Arc edges are linearised to their endpoints — the same assumption\n * {@link wireToPolygon} and the DXF writer make. Form cuts are straight-sided\n * today (louver/lance slits), so this is exact; a future curved form-feature cut\n * would render as straight chords in the overlay until arc tessellation is added.\n */\nfunction wireToOpenPolyline(wire: Wire): Pt2[] {\n const edges = getEdges(wire);\n if (edges.length === 0) return [];\n const pts: Pt2[] = edges.map((edge) => {\n const p = curveStartPoint(edge);\n return [p[0], p[1]];\n });\n const lastEdge = edges[edges.length - 1];\n if (lastEdge) {\n const e = curveEndPoint(lastEdge);\n pts.push([e[0], e[1]]);\n }\n return pts;\n}\n\n/**\n * Reduce a {@link FlatPattern} to serializable 2D polylines (outline, holes, bend\n * lines) for a developed-pattern overlay. Best-effort: a wire that fails to read\n * is dropped rather than throwing, so a partial pattern still yields what it can.\n * Arc edges are approximated by endpoints, the same assumption {@link wireToPolygon}\n * and the DXF writer make.\n *\n * @param pattern - the flat pattern to reduce to 2D polylines.\n * @returns a {@link FlatPatternPolylines} with the outline, holes, bend lines,\n * form cuts, and form hinges as plain 2D vertex loops.\n */\nexport function flatPatternToPolylines(pattern: FlatPattern): FlatPatternPolylines {\n const outlineResult = wireToPolygon(pattern.outline);\n const outline = isOk(outlineResult) ? outlineResult.value : [];\n const holes: Polygon[] = [];\n for (const hole of pattern.holes) {\n const holeResult = wireToPolygon(hole);\n if (isOk(holeResult)) holes.push(holeResult.value);\n }\n const bendLines: FlatPatternBendLine[] = pattern.bendLines.map((bend) => {\n const start = curveStartPoint(bend.line);\n const end = curveEndPoint(bend.line);\n return {\n from: [start[0], start[1]],\n to: [end[0], end[1]],\n direction: bend.direction,\n };\n });\n const formCuts = pattern.formCuts.map(wireToOpenPolyline).filter((p) => p.length >= 2);\n const formHinges = pattern.formHinges.map((hinge) => {\n const start = curveStartPoint(hinge);\n const end = curveEndPoint(hinge);\n return { from: [start[0], start[1]] as Pt2, to: [end[0], end[1]] as Pt2 };\n });\n return { outline, holes, bendLines, formCuts, formHinges };\n}\n\n/**\n * Signed area (CCW positive) — used to normalise orientation and reject degenerates.\n *\n * @param poly - the polygon to measure.\n * @returns the signed area in square units: positive for counter-clockwise vertex\n * order, negative for clockwise.\n */\nexport function signedArea(poly: Polygon): number {\n let a = 0;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i, i += 1) {\n const pi = poly[i];\n const pj = poly[j];\n if (pi === undefined || pj === undefined) continue;\n a += pj[0] * pi[1] - pi[0] * pj[1];\n }\n return a / 2;\n}\n\n/**\n * Axis-aligned bounds of a polygon.\n *\n * @param poly - the polygon to bound.\n * @returns the axis-aligned bounding box as `[minX, minY, maxX, maxY]`.\n */\nexport function polygonBounds(poly: Polygon): [number, number, number, number] {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const p of poly) {\n if (p[0] < minX) minX = p[0];\n if (p[0] > maxX) maxX = p[0];\n if (p[1] < minY) minY = p[1];\n if (p[1] > maxY) maxY = p[1];\n }\n return [minX, minY, maxX, maxY];\n}\n\n/**\n * Rotate every vertex (CCW, degrees, about the origin), then translate by (dx, dy).\n *\n * @param poly - the polygon to transform.\n * @param dx - the translation along X applied after rotation.\n * @param dy - the translation along Y applied after rotation.\n * @param rotationDeg - the counter-clockwise rotation angle in degrees.\n * @returns a new `Polygon` with every vertex rotated then translated.\n */\nexport function transformPolygon(poly: Polygon, dx: number, dy: number, rotationDeg: number): Polygon {\n const rad = (rotationDeg * Math.PI) / 180;\n const c = Math.cos(rad);\n const s = Math.sin(rad);\n return poly.map(([x, y]) => {\n const rx = x * c - y * s;\n const ry = x * s + y * c;\n return [rx + dx, ry + dy] as Pt2;\n });\n}\n\n/**\n * Ray-cast point-in-polygon: points strictly inside return true; behaviour for a\n * point exactly on the boundary is undefined (the overlap predicate handles edge\n * contact separately via segment-intersection).\n *\n * @param poly - the polygon to test against.\n * @param x - the point's X coordinate.\n * @param y - the point's Y coordinate.\n * @returns `true` when the point is strictly inside the polygon.\n */\nexport function pointInPolygon(poly: Polygon, x: number, y: number): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i, i += 1) {\n const pi = poly[i];\n const pj = poly[j];\n if (pi === undefined || pj === undefined) continue;\n const intersect =\n pi[1] > y !== pj[1] > y && x < ((pj[0] - pi[0]) * (y - pi[1])) / (pj[1] - pi[1]) + pi[0];\n if (intersect) inside = !inside;\n }\n return inside;\n}\n\nfunction orient(ax: number, ay: number, bx: number, by: number, cx: number, cy: number): number {\n return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);\n}\n\nfunction onSegment(ax: number, ay: number, bx: number, by: number, px: number, py: number): boolean {\n return (\n Math.min(ax, bx) - EPS <= px &&\n px <= Math.max(ax, bx) + EPS &&\n Math.min(ay, by) - EPS <= py &&\n py <= Math.max(ay, by) + EPS\n );\n}\n\n/**\n * Proper-or-improper segment intersection (`p1p2` vs `p3p4`). Returns true when the\n * segments cross OR touch (collinear overlap or a shared endpoint), so it is\n * conservative for the overlap test — never a false negative.\n *\n * @param p1 - first endpoint of the first segment.\n * @param p2 - second endpoint of the first segment.\n * @param p3 - first endpoint of the second segment.\n * @param p4 - second endpoint of the second segment.\n * @returns `true` when the two segments cross or touch, `false` otherwise.\n */\nexport function segmentsIntersect(p1: Pt2, p2: Pt2, p3: Pt2, p4: Pt2): boolean {\n const d1 = orient(p3[0], p3[1], p4[0], p4[1], p1[0], p1[1]);\n const d2 = orient(p3[0], p3[1], p4[0], p4[1], p2[0], p2[1]);\n const d3 = orient(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]);\n const d4 = orient(p1[0], p1[1], p2[0], p2[1], p4[0], p4[1]);\n\n if (((d1 > EPS && d2 < -EPS) || (d1 < -EPS && d2 > EPS)) && ((d3 > EPS && d4 < -EPS) || (d3 < -EPS && d4 > EPS))) {\n return true;\n }\n\n if (Math.abs(d1) <= EPS && onSegment(p3[0], p3[1], p4[0], p4[1], p1[0], p1[1])) return true;\n if (Math.abs(d2) <= EPS && onSegment(p3[0], p3[1], p4[0], p4[1], p2[0], p2[1])) return true;\n if (Math.abs(d3) <= EPS && onSegment(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1])) return true;\n if (Math.abs(d4) <= EPS && onSegment(p1[0], p1[1], p2[0], p2[1], p4[0], p4[1])) return true;\n return false;\n}\n\n/**\n * Do two simple polygons overlap? True iff any edge of `a` intersects any edge of\n * `b`, or one polygon fully contains a vertex of the other. This pair of conditions\n * is exhaustive for simple polygons: a disjoint pair has no crossing edges and no\n * mutually-contained vertex; a touching-but-non-overlapping pair (shared edge/vertex,\n * zero interior overlap) is caught by `segmentsIntersect` and so is reported as\n * overlapping — callers wanting a clearance gap should inflate via {@link polygonsOverlapWithClearance}.\n *\n * Centroid containment is NOT sufficient on its own (a concave part's centroid can\n * lie outside it), so a representative INTERIOR vertex of each polygon is tested for\n * containment in the other — combined with the edge-crossing test this covers the\n * nested-without-crossing case.\n *\n * @param a - the first polygon.\n * @param b - the second polygon.\n * @returns `true` when the polygons overlap (including edge touch), `false` when they\n * are disjoint.\n */\nexport function polygonsOverlap(a: Polygon, b: Polygon): boolean {\n for (let i = 0; i < a.length; i += 1) {\n const a1 = a[i];\n const a2 = a[(i + 1) % a.length];\n if (a1 === undefined || a2 === undefined) continue;\n for (let j = 0; j < b.length; j += 1) {\n const b1 = b[j];\n const b2 = b[(j + 1) % b.length];\n if (b1 === undefined || b2 === undefined) continue;\n if (segmentsIntersect(a1, a2, b1, b2)) return true;\n }\n }\n // No edges cross: the only remaining overlap is full containment. If any vertex of\n // one lies strictly inside the other, the polygons overlap. (With no crossings,\n // containment of a single vertex implies containment of the whole polygon.)\n for (const v of a) {\n if (pointInPolygon(b, v[0], v[1])) return true;\n }\n for (const v of b) {\n if (pointInPolygon(a, v[0], v[1])) return true;\n }\n return false;\n}\n\n/**\n * Overlap test honoring a clearance gap: the two polygons must stay at least\n * `clearance` apart. Implemented by testing raw overlap and, when disjoint, the\n * minimum edge-to-edge distance against the clearance. `clearance <= 0` is the plain\n * {@link polygonsOverlap}.\n *\n * @param a - the first polygon.\n * @param b - the second polygon.\n * @param clearance - the minimum required gap between the polygons.\n * @returns `true` when the polygons overlap or come closer than `clearance`.\n */\nexport function polygonsOverlapWithClearance(a: Polygon, b: Polygon, clearance: number): boolean {\n if (polygonsOverlap(a, b)) return true;\n if (clearance <= EPS) return false;\n return minEdgeDistance(a, b) < clearance - EPS;\n}\n\n/** Minimum distance between any edge of `a` and any edge of `b` (both assumed disjoint). */\nfunction minEdgeDistance(a: Polygon, b: Polygon): number {\n let min = Infinity;\n for (let i = 0; i < a.length; i += 1) {\n const a1 = a[i];\n const a2 = a[(i + 1) % a.length];\n if (a1 === undefined || a2 === undefined) continue;\n for (let j = 0; j < b.length; j += 1) {\n const b1 = b[j];\n const b2 = b[(j + 1) % b.length];\n if (b1 === undefined || b2 === undefined) continue;\n const d = segmentSegmentDistance(a1, a2, b1, b2);\n if (d < min) min = d;\n }\n }\n return min;\n}\n\nfunction segmentSegmentDistance(p1: Pt2, p2: Pt2, p3: Pt2, p4: Pt2): number {\n if (segmentsIntersect(p1, p2, p3, p4)) return 0;\n return Math.min(\n pointSegmentDistance(p1, p3, p4),\n pointSegmentDistance(p2, p3, p4),\n pointSegmentDistance(p3, p1, p2),\n pointSegmentDistance(p4, p1, p2)\n );\n}\n\nfunction pointSegmentDistance(p: Pt2, a: Pt2, b: Pt2): number {\n const vx = b[0] - a[0];\n const vy = b[1] - a[1];\n const wx = p[0] - a[0];\n const wy = p[1] - a[1];\n const len2 = vx * vx + vy * vy;\n let t = len2 <= EPS ? 0 : (wx * vx + wy * vy) / len2;\n t = Math.max(0, Math.min(1, t));\n const dx = p[0] - (a[0] + t * vx);\n const dy = p[1] - (a[1] + t * vy);\n return Math.hypot(dx, dy);\n}\n"]}
1
+ {"version":3,"file":"polygonFns.js","sourceRoot":"","sources":["../src/polygonFns.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 2D simple-polygon geometry for true-shape (no-fit-polygon) nesting: an ordered\n * vertex loop plus the overlap predicate that is the correctness backbone of the\n * packer. A false negative here would let two parts physically collide on the laser\n * bed, so the predicate is exhaustive: two simple polygons overlap iff any of their\n * edges cross OR one polygon contains a vertex of the other (the latter catches full\n * containment, where no edges cross).\n *\n * Sheet-metal flat outlines are straight-edged polylines; an arc edge (rare in a\n * developed pattern) is approximated by its two endpoints — the same pre-existing\n * assumption the DXF/SVG writers and the bbox nester make.\n */\n\nimport type { Wire } from './types.js';\nimport {type Result, ok, err, isOk, validationError, getEdges, curveStartPoint, curveEndPoint} from '@faicad/faijs/api';\n\nimport type { FlatPattern } from './types.js';\n\n/** A 2D point as a plain `[x, y]` coordinate tuple. */\nexport type Pt2 = [number, number];\n\n/** A simple (non-self-intersecting) polygon as an ordered, non-closing vertex loop. */\nexport type Polygon = Pt2[];\n\nconst EPS = 1e-9;\n\n/**\n * Ordered vertex loop of a closed outline wire — one vertex per edge start point, the\n * same 2D read the DXF writer (`outlinePoints`) and the bbox nester (`patternBbox`)\n * use. The loop is NOT closed (the last vertex is not repeated); edges are taken as\n * `v[i] → v[(i+1) % n]`.\n *\n * @param outline - the closed outline wire to read into a vertex loop.\n * @returns a `Result<Polygon>` — `ok` with the ordered vertex loop, or `err` with a\n * `validationError` when the outline is empty or has fewer than 3 vertices.\n */\nexport function wireToPolygon(outline: Wire): Result<Polygon> {\n const edges = getEdges(outline);\n if (edges.length === 0) {\n return err(validationError('EMPTY_OUTLINE', 'outline wire has no edges to read'));\n }\n const poly: Polygon = [];\n for (const edge of edges) {\n const p = curveStartPoint(edge);\n poly.push([p[0], p[1]]);\n }\n if (poly.length < 3) {\n return err(validationError('EMPTY_OUTLINE', 'outline polygon has fewer than 3 vertices'));\n }\n return ok(poly);\n}\n\n/** A bend line in the developed plane: a segment plus its fold direction. */\nexport interface FlatPatternBendLine {\n from: Pt2;\n to: Pt2;\n direction: 'up' | 'down';\n}\n\n/** A flat pattern reduced to serializable 2D polylines for a developed-view overlay. */\nexport interface FlatPatternPolylines {\n /** Closed outer boundary as an ordered, non-closing vertex loop. */\n outline: Polygon;\n /** Interior cutout loops (holes / slots / polygon cutouts). */\n holes: Polygon[];\n /** Bend lines, each with its fold direction. */\n bendLines: FlatPatternBendLine[];\n /** Open form-feature cut paths in the blank (e.g. louver/lance three-sided cuts). */\n formCuts: Polygon[];\n /** Form-feature hinge lines (the uncut fold edge a louver/lance forms up along). */\n formHinges: { from: Pt2; to: Pt2 }[];\n}\n\n/**\n * Read a wire as an OPEN polyline: every edge start plus the final edge's end,\n * so the last vertex of a non-closing path (a form cut) isn't dropped the way\n * {@link wireToPolygon} drops it for closed loops.\n *\n * Arc edges are linearised to their endpoints — the same assumption\n * {@link wireToPolygon} and the DXF writer make. Form cuts are straight-sided\n * today (louver/lance slits), so this is exact; a future curved form-feature cut\n * would render as straight chords in the overlay until arc tessellation is added.\n */\nfunction wireToOpenPolyline(wire: Wire): Pt2[] {\n const edges = getEdges(wire);\n if (edges.length === 0) return [];\n const pts: Pt2[] = edges.map((edge) => {\n const p = curveStartPoint(edge);\n return [p[0], p[1]];\n });\n const lastEdge = edges[edges.length - 1];\n if (lastEdge) {\n const e = curveEndPoint(lastEdge);\n pts.push([e[0], e[1]]);\n }\n return pts;\n}\n\n/**\n * Reduce a {@link FlatPattern} to serializable 2D polylines (outline, holes, bend\n * lines) for a developed-pattern overlay. Best-effort: a wire that fails to read\n * is dropped rather than throwing, so a partial pattern still yields what it can.\n * Arc edges are approximated by endpoints, the same assumption {@link wireToPolygon}\n * and the DXF writer make.\n *\n * @param pattern - the flat pattern to reduce to 2D polylines.\n * @returns a {@link FlatPatternPolylines} with the outline, holes, bend lines,\n * form cuts, and form hinges as plain 2D vertex loops.\n */\nexport function flatPatternToPolylines(pattern: FlatPattern): FlatPatternPolylines {\n const outlineResult = wireToPolygon(pattern.outline);\n const outline = isOk(outlineResult) ? outlineResult.value : [];\n const holes: Polygon[] = [];\n for (const hole of pattern.holes) {\n const holeResult = wireToPolygon(hole);\n if (isOk(holeResult)) holes.push(holeResult.value);\n }\n const bendLines: FlatPatternBendLine[] = pattern.bendLines.map((bend) => {\n const start = curveStartPoint(bend.line);\n const end = curveEndPoint(bend.line);\n return {\n from: [start[0], start[1]],\n to: [end[0], end[1]],\n direction: bend.direction,\n };\n });\n const formCuts = pattern.formCuts.map(wireToOpenPolyline).filter((p) => p.length >= 2);\n const formHinges = pattern.formHinges.map((hinge) => {\n const start = curveStartPoint(hinge);\n const end = curveEndPoint(hinge);\n return { from: [start[0], start[1]] as Pt2, to: [end[0], end[1]] as Pt2 };\n });\n return { outline, holes, bendLines, formCuts, formHinges };\n}\n\n/**\n * Signed area (CCW positive) — used to normalise orientation and reject degenerates.\n *\n * @param poly - the polygon to measure.\n * @returns the signed area in square units: positive for counter-clockwise vertex\n * order, negative for clockwise.\n */\nexport function signedArea(poly: Polygon): number {\n let a = 0;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i, i += 1) {\n const pi = poly[i];\n const pj = poly[j];\n if (pi === undefined || pj === undefined) continue;\n a += pj[0] * pi[1] - pi[0] * pj[1];\n }\n return a / 2;\n}\n\n/**\n * Axis-aligned bounds of a polygon.\n *\n * @param poly - the polygon to bound.\n * @returns the axis-aligned bounding box as `[minX, minY, maxX, maxY]`.\n */\nexport function polygonBounds(poly: Polygon): [number, number, number, number] {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const p of poly) {\n if (p[0] < minX) minX = p[0];\n if (p[0] > maxX) maxX = p[0];\n if (p[1] < minY) minY = p[1];\n if (p[1] > maxY) maxY = p[1];\n }\n return [minX, minY, maxX, maxY];\n}\n\n/**\n * Rotate every vertex (CCW, degrees, about the origin), then translate by (dx, dy).\n *\n * @param poly - the polygon to transform.\n * @param dx - the translation along X applied after rotation.\n * @param dy - the translation along Y applied after rotation.\n * @param rotationDeg - the counter-clockwise rotation angle in degrees.\n * @returns a new `Polygon` with every vertex rotated then translated.\n */\nexport function transformPolygon(poly: Polygon, dx: number, dy: number, rotationDeg: number): Polygon {\n const rad = (rotationDeg * Math.PI) / 180;\n const c = Math.cos(rad);\n const s = Math.sin(rad);\n return poly.map(([x, y]) => {\n const rx = x * c - y * s;\n const ry = x * s + y * c;\n return [rx + dx, ry + dy] as Pt2;\n });\n}\n\n/**\n * Ray-cast point-in-polygon: points strictly inside return true; behaviour for a\n * point exactly on the boundary is undefined (the overlap predicate handles edge\n * contact separately via segment-intersection).\n *\n * @param poly - the polygon to test against.\n * @param x - the point's X coordinate.\n * @param y - the point's Y coordinate.\n * @returns `true` when the point is strictly inside the polygon.\n */\nexport function pointInPolygon(poly: Polygon, x: number, y: number): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i, i += 1) {\n const pi = poly[i];\n const pj = poly[j];\n if (pi === undefined || pj === undefined) continue;\n const intersect =\n pi[1] > y !== pj[1] > y && x < ((pj[0] - pi[0]) * (y - pi[1])) / (pj[1] - pi[1]) + pi[0];\n if (intersect) inside = !inside;\n }\n return inside;\n}\n\nfunction orient(ax: number, ay: number, bx: number, by: number, cx: number, cy: number): number {\n return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);\n}\n\nfunction onSegment(ax: number, ay: number, bx: number, by: number, px: number, py: number): boolean {\n return (\n Math.min(ax, bx) - EPS <= px &&\n px <= Math.max(ax, bx) + EPS &&\n Math.min(ay, by) - EPS <= py &&\n py <= Math.max(ay, by) + EPS\n );\n}\n\n/**\n * Proper-or-improper segment intersection (`p1p2` vs `p3p4`). Returns true when the\n * segments cross OR touch (collinear overlap or a shared endpoint), so it is\n * conservative for the overlap test — never a false negative.\n *\n * @param p1 - first endpoint of the first segment.\n * @param p2 - second endpoint of the first segment.\n * @param p3 - first endpoint of the second segment.\n * @param p4 - second endpoint of the second segment.\n * @returns `true` when the two segments cross or touch, `false` otherwise.\n */\nexport function segmentsIntersect(p1: Pt2, p2: Pt2, p3: Pt2, p4: Pt2): boolean {\n const d1 = orient(p3[0], p3[1], p4[0], p4[1], p1[0], p1[1]);\n const d2 = orient(p3[0], p3[1], p4[0], p4[1], p2[0], p2[1]);\n const d3 = orient(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]);\n const d4 = orient(p1[0], p1[1], p2[0], p2[1], p4[0], p4[1]);\n\n if (((d1 > EPS && d2 < -EPS) || (d1 < -EPS && d2 > EPS)) && ((d3 > EPS && d4 < -EPS) || (d3 < -EPS && d4 > EPS))) {\n return true;\n }\n\n if (Math.abs(d1) <= EPS && onSegment(p3[0], p3[1], p4[0], p4[1], p1[0], p1[1])) return true;\n if (Math.abs(d2) <= EPS && onSegment(p3[0], p3[1], p4[0], p4[1], p2[0], p2[1])) return true;\n if (Math.abs(d3) <= EPS && onSegment(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1])) return true;\n if (Math.abs(d4) <= EPS && onSegment(p1[0], p1[1], p2[0], p2[1], p4[0], p4[1])) return true;\n return false;\n}\n\n/**\n * Do two simple polygons overlap? True iff any edge of `a` intersects any edge of\n * `b`, or one polygon fully contains a vertex of the other. This pair of conditions\n * is exhaustive for simple polygons: a disjoint pair has no crossing edges and no\n * mutually-contained vertex; a touching-but-non-overlapping pair (shared edge/vertex,\n * zero interior overlap) is caught by `segmentsIntersect` and so is reported as\n * overlapping — callers wanting a clearance gap should inflate via {@link polygonsOverlapWithClearance}.\n *\n * Centroid containment is NOT sufficient on its own (a concave part's centroid can\n * lie outside it), so a representative INTERIOR vertex of each polygon is tested for\n * containment in the other — combined with the edge-crossing test this covers the\n * nested-without-crossing case.\n *\n * @param a - the first polygon.\n * @param b - the second polygon.\n * @returns `true` when the polygons overlap (including edge touch), `false` when they\n * are disjoint.\n */\nexport function polygonsOverlap(a: Polygon, b: Polygon): boolean {\n for (let i = 0; i < a.length; i += 1) {\n const a1 = a[i];\n const a2 = a[(i + 1) % a.length];\n if (a1 === undefined || a2 === undefined) continue;\n for (let j = 0; j < b.length; j += 1) {\n const b1 = b[j];\n const b2 = b[(j + 1) % b.length];\n if (b1 === undefined || b2 === undefined) continue;\n if (segmentsIntersect(a1, a2, b1, b2)) return true;\n }\n }\n // No edges cross: the only remaining overlap is full containment. If any vertex of\n // one lies strictly inside the other, the polygons overlap. (With no crossings,\n // containment of a single vertex implies containment of the whole polygon.)\n for (const v of a) {\n if (pointInPolygon(b, v[0], v[1])) return true;\n }\n for (const v of b) {\n if (pointInPolygon(a, v[0], v[1])) return true;\n }\n return false;\n}\n\n/**\n * Overlap test honoring a clearance gap: the two polygons must stay at least\n * `clearance` apart. Implemented by testing raw overlap and, when disjoint, the\n * minimum edge-to-edge distance against the clearance. `clearance <= 0` is the plain\n * {@link polygonsOverlap}.\n *\n * @param a - the first polygon.\n * @param b - the second polygon.\n * @param clearance - the minimum required gap between the polygons.\n * @returns `true` when the polygons overlap or come closer than `clearance`.\n */\nexport function polygonsOverlapWithClearance(a: Polygon, b: Polygon, clearance: number): boolean {\n if (polygonsOverlap(a, b)) return true;\n if (clearance <= EPS) return false;\n return minEdgeDistance(a, b) < clearance - EPS;\n}\n\n/** Minimum distance between any edge of `a` and any edge of `b` (both assumed disjoint). */\nfunction minEdgeDistance(a: Polygon, b: Polygon): number {\n let min = Infinity;\n for (let i = 0; i < a.length; i += 1) {\n const a1 = a[i];\n const a2 = a[(i + 1) % a.length];\n if (a1 === undefined || a2 === undefined) continue;\n for (let j = 0; j < b.length; j += 1) {\n const b1 = b[j];\n const b2 = b[(j + 1) % b.length];\n if (b1 === undefined || b2 === undefined) continue;\n const d = segmentSegmentDistance(a1, a2, b1, b2);\n if (d < min) min = d;\n }\n }\n return min;\n}\n\nfunction segmentSegmentDistance(p1: Pt2, p2: Pt2, p3: Pt2, p4: Pt2): number {\n if (segmentsIntersect(p1, p2, p3, p4)) return 0;\n return Math.min(\n pointSegmentDistance(p1, p3, p4),\n pointSegmentDistance(p2, p3, p4),\n pointSegmentDistance(p3, p1, p2),\n pointSegmentDistance(p4, p1, p2)\n );\n}\n\nfunction pointSegmentDistance(p: Pt2, a: Pt2, b: Pt2): number {\n const vx = b[0] - a[0];\n const vy = b[1] - a[1];\n const wx = p[0] - a[0];\n const wy = p[1] - a[1];\n const len2 = vx * vx + vy * vy;\n let t = len2 <= EPS ? 0 : (wx * vx + wy * vy) / len2;\n t = Math.max(0, Math.min(1, t));\n const dx = p[0] - (a[0] + t * vx);\n const dy = p[1] - (a[1] + t * vy);\n return Math.hypot(dx, dy);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type Result } from '@faicad/faijs/brepjs-compat';
1
+ import { type Result } from '@faicad/faijs/api';
2
2
  import type { ReliefSpec, SheetMetalPart } from './types.js';
3
3
  /**
4
4
  * Add a bend relief to a flange: a small slot cut into the PARENT flat at each end
@@ -16,7 +16,7 @@ import type { ReliefSpec, SheetMetalPart } from './types.js';
16
16
  * @param spec - the relief specification (default rectangular).
17
17
  * @returns the updated part with the bend relief recorded, or an error.
18
18
  */
19
- export declare function addBendRelief(part: SheetMetalPart, flangeId: string, spec?: ReliefSpec): Result<SheetMetalPart>;
19
+ export declare function addBendRelief(part: SheetMetalPart, flangeId: string, spec?: ReliefSpec): Promise<Result<SheetMetalPart>>;
20
20
  /**
21
21
  * Add a bend relief to every partial-span bend (a flange that does not span its
22
22
  * full parent edge). Full-span flanges are skipped — they have no mid-edge bend
@@ -26,7 +26,7 @@ export declare function addBendRelief(part: SheetMetalPart, flangeId: string, sp
26
26
  * @param spec - the relief specification (default rectangular).
27
27
  * @returns the updated part with all needed bend reliefs, or an error.
28
28
  */
29
- export declare function autoBendReliefs(part: SheetMetalPart, spec?: ReliefSpec): Result<SheetMetalPart>;
29
+ export declare function autoBendReliefs(part: SheetMetalPart, spec?: ReliefSpec): Promise<Result<SheetMetalPart>>;
30
30
  /**
31
31
  * Corner relief between two adjacent flanges: a notch cut at their shared corner so
32
32
  * the two upright flanges clear each other once folded — the alternative to a 45°
@@ -40,5 +40,5 @@ export declare function autoBendReliefs(part: SheetMetalPart, spec?: ReliefSpec)
40
40
  * @param spec - the relief specification (default rectangular).
41
41
  * @returns the updated part with the corner relief recorded, or an error.
42
42
  */
43
- export declare function cornerRelief(part: SheetMetalPart, flangeIdA: string, flangeIdB: string, spec?: ReliefSpec): Result<SheetMetalPart>;
43
+ export declare function cornerRelief(part: SheetMetalPart, flangeIdA: string, flangeIdB: string, spec?: ReliefSpec): Promise<Result<SheetMetalPart>>;
44
44
  //# sourceMappingURL=reliefFns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reliefFns.d.ts","sourceRoot":"","sources":["../src/reliefFns.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EAqBZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAIV,UAAU,EACV,cAAc,EACf,MAAM,YAAY,CAAC;AAWpB;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,UAAqC,GAC1C,MAAM,CAAC,cAAc,CAAC,CAiDxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,EACpB,IAAI,GAAE,UAAqC,GAC1C,MAAM,CAAC,cAAc,CAAC,CAaxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,UAAqC,GAC1C,MAAM,CAAC,cAAc,CAAC,CA8DxB"}
1
+ {"version":3,"file":"reliefFns.d.ts","sourceRoot":"","sources":["../src/reliefFns.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,KAAK,MAAM,EAAmL,MAAM,mBAAmB,CAAC;AAChO,OAAO,KAAK,EAIV,UAAU,EACV,cAAc,EACf,MAAM,YAAY,CAAC;AAWpB;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,UAAqC,GAC1C,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAmDjC;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,cAAc,EACpB,IAAI,GAAE,UAAqC,GAC1C,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAajC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,UAAqC,GAC1C,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAgEjC"}
package/dist/reliefFns.js CHANGED
@@ -1,4 +1,6 @@
1
- import { ok, err, validationError, box, cut, rotate, translate, getBounds, getSolids, isValid, curveStartPoint, curveEndPoint, vecAdd, vecSub, vecScale, vecCross, vecDot, vecNormalize, } from '@faicad/faijs/brepjs-compat';
1
+ import { getBounds } from './geometryOps.js';
2
+ import { translate } from './geometryOps.js';
3
+ import { ok, err, kernelError, validationError, box, cut, rotate, getSolids, isValid, curveStartPoint, curveEndPoint, vecAdd, vecSub, vecScale, vecCross, vecDot, vecNormalize } from '@faicad/faijs/api';
2
4
  import { normalizeSolid } from './internal.js';
3
5
  import { unfold } from './unfoldFns.js';
4
6
  import { developedLength } from './allowanceFns.js';
@@ -20,7 +22,7 @@ const Z_AXIS = [0, 0, 1];
20
22
  * @param spec - the relief specification (default rectangular).
21
23
  * @returns the updated part with the bend relief recorded, or an error.
22
24
  */
23
- export function addBendRelief(part, flangeId, spec = { shape: 'rectangular' }) {
25
+ export async function addBendRelief(part, flangeId, spec = { shape: 'rectangular' }) {
24
26
  if (part.solid === undefined) {
25
27
  return err(validationError('NO_SOLID', 'addBendRelief: part has no folded solid to cut'));
26
28
  }
@@ -33,16 +35,19 @@ export function addBendRelief(part, flangeId, spec = { shape: 'rectangular' }) {
33
35
  if (!dims.ok)
34
36
  return dims;
35
37
  const { width, depth } = dims.value;
36
- const geo = bendReliefGeometry(part, flange, bend, width, depth);
37
- if (geo === undefined) {
38
- return err(validationError('BEND_RELIEF_NOT_NEEDED', `addBendRelief: bend '${flangeId}' spans its full parent edge; no relief end to cut`));
39
- }
38
+ let geo;
40
39
  let solid = part.solid;
41
- for (const tool of geo.tools3d) {
42
- const result = cut(solid, tool);
43
- if (!result.ok)
44
- return result;
45
- solid = normalizeSolid(result.value);
40
+ try {
41
+ geo = await bendReliefGeometry(part, flange, bend, width, depth);
42
+ if (geo === undefined) {
43
+ return err(validationError('BEND_RELIEF_NOT_NEEDED', `addBendRelief: bend '${flangeId}' spans its full parent edge; no relief end to cut`));
44
+ }
45
+ for (const tool of geo.tools3d) {
46
+ solid = normalizeSolid((await cut(solid, tool)));
47
+ }
48
+ }
49
+ catch (e) {
50
+ return err(kernelError('CUT_FAILED', `bend relief: ${e instanceof Error ? e.message : String(e)}`));
46
51
  }
47
52
  if (!isValid(solid) || getSolids(solid).length > 1) {
48
53
  return err(validationError('RELIEF_SEVERED_SOLID', `addBendRelief: slot (width ${width}, depth ${depth}) severs flange '${flangeId}' into multiple bodies; reduce width/depth`));
@@ -66,12 +71,12 @@ export function addBendRelief(part, flangeId, spec = { shape: 'rectangular' }) {
66
71
  * @param spec - the relief specification (default rectangular).
67
72
  * @returns the updated part with all needed bend reliefs, or an error.
68
73
  */
69
- export function autoBendReliefs(part, spec = { shape: 'rectangular' }) {
74
+ export async function autoBendReliefs(part, spec = { shape: 'rectangular' }) {
70
75
  let current = part;
71
76
  for (const flange of part.flanges) {
72
77
  // Let addBendRelief own the needed/not-needed decision rather than recomputing
73
78
  // the relief geometry here just to peek (which also allocated throwaway tools).
74
- const next = addBendRelief(current, flange.id, spec);
79
+ const next = await addBendRelief(current, flange.id, spec);
75
80
  if (!next.ok) {
76
81
  if (next.error.code === 'BEND_RELIEF_NOT_NEEDED')
77
82
  continue;
@@ -94,7 +99,7 @@ export function autoBendReliefs(part, spec = { shape: 'rectangular' }) {
94
99
  * @param spec - the relief specification (default rectangular).
95
100
  * @returns the updated part with the corner relief recorded, or an error.
96
101
  */
97
- export function cornerRelief(part, flangeIdA, flangeIdB, spec = { shape: 'rectangular' }) {
102
+ export async function cornerRelief(part, flangeIdA, flangeIdB, spec = { shape: 'rectangular' }) {
98
103
  if (part.solid === undefined) {
99
104
  return err(validationError('NO_SOLID', 'cornerRelief: part has no folded solid'));
100
105
  }
@@ -120,11 +125,14 @@ export function cornerRelief(part, flangeIdA, flangeIdB, spec = { shape: 'rectan
120
125
  const flangeA = part.flanges.find((f) => f.id === flangeIdA);
121
126
  const flangeB = part.flanges.find((f) => f.id === flangeIdB);
122
127
  const geo = cornerReliefGeometry(part, axisA, axisB, bendA, bendB, side, flangeA, flangeB);
123
- const tool = squareTool(part.solid, geo.cornerXY, side);
124
- const result = cut(part.solid, tool);
125
- if (!result.ok)
126
- return result;
127
- const solid = normalizeSolid(result.value);
128
+ let solid;
129
+ try {
130
+ const tool = await squareTool(part.solid, geo.cornerXY, side);
131
+ solid = normalizeSolid((await cut(part.solid, tool)));
132
+ }
133
+ catch (e) {
134
+ return err(kernelError('CUT_FAILED', `corner relief: ${e instanceof Error ? e.message : String(e)}`));
135
+ }
128
136
  if (!isValid(solid) || getSolids(solid).length > 1) {
129
137
  return err(validationError('RELIEF_SEVERED_SOLID', `cornerRelief: notch (side ${side}) severs the part into multiple bodies; reduce width/depth`));
130
138
  }
@@ -174,7 +182,7 @@ function reliefDims(spec, thickness, dev) {
174
182
  * way. Returns `undefined` when the flange spans its full parent edge (no mid-edge
175
183
  * end to relieve).
176
184
  */
177
- function bendReliefGeometry(part, flange, bend, width, depth) {
185
+ async function bendReliefGeometry(part, flange, bend, width, depth) {
178
186
  if (part.solid === undefined)
179
187
  return undefined;
180
188
  const axis = vecNormalize(bend.axisDir);
@@ -197,7 +205,7 @@ function bendReliefGeometry(part, flange, bend, width, depth) {
197
205
  ends.push(span);
198
206
  for (const s of ends) {
199
207
  const at = vecAdd(edgeBase, vecScale(axis, s));
200
- tools3d.push(slotTool3d(at, axis, inward, width, depth, part.thickness));
208
+ tools3d.push(await slotTool3d(at, axis, inward, width, depth, part.thickness));
201
209
  }
202
210
  const notches2d = bendNotches2d(part, flange, width, depth, atStart, atEnd);
203
211
  return { tools3d, notches2d };
@@ -324,7 +332,7 @@ function parentEdgeLength(part, flange) {
324
332
  * whose `width` axis runs along the parent edge and `depth` axis points inward,
325
333
  * placed so it straddles the edge point `at` and cuts through the parent surface.
326
334
  */
327
- function slotTool3d(at, along, inward, width, depth, thickness) {
335
+ async function slotTool3d(at, along, inward, width, depth, thickness) {
328
336
  const margin = thickness + 2;
329
337
  // Canonical: width along +X, depth along +Y, height along +Z (cuts through Z).
330
338
  // Rotating by `deg` sends +X→along and +Y→(along rotated +90° = [-along.y, along.x]).
@@ -332,10 +340,10 @@ function slotTool3d(at, along, inward, width, depth, thickness) {
332
340
  // into the parent rather than out into the flange.
333
341
  const rotPerp = [-along[1], along[0], 0];
334
342
  const y0 = vecDot(rotPerp, inward) >= 0 ? 0 : -depth;
335
- let tool = box(width, depth, thickness + 2 * margin);
336
- tool = translate(tool, [-width / 2, y0, -margin]);
337
- tool = orientXY(tool, along);
338
- return translate(tool, [at[0], at[1], 0]);
343
+ let tool = (await box({ width, depth, height: thickness + 2 * margin }));
344
+ tool = (await translate(tool, [-width / 2, y0, -margin]));
345
+ tool = await orientXY(tool, along);
346
+ return (await translate(tool, [at[0], at[1], 0]));
339
347
  }
340
348
  /**
341
349
  * Square corner-relief tool: a `side × side × (height + margins)` block CENTRED on
@@ -344,19 +352,19 @@ function slotTool3d(at, along, inward, width, depth, thickness) {
344
352
  * base corners for the supported perpendicular flange shapes, so the tool stays
345
353
  * axis-aligned.
346
354
  */
347
- function squareTool(solid, cornerXY, side) {
355
+ async function squareTool(solid, cornerXY, side) {
348
356
  const b = getBounds(solid);
349
357
  const margin = 2;
350
358
  const h = side / 2;
351
- const tool = box(side, side, b.zMax - b.zMin + 2 * margin);
352
- return translate(tool, [cornerXY[0] - h, cornerXY[1] - h, b.zMin - margin]);
359
+ const tool = (await box({ width: side, depth: side, height: b.zMax - b.zMin + 2 * margin }));
360
+ return (await translate(tool, [cornerXY[0] - h, cornerXY[1] - h, b.zMin - margin]));
353
361
  }
354
362
  /** Rotate a shape about +Z so its local +X axis points along `xT` (in the XY plane). */
355
- function orientXY(shape, xT) {
363
+ async function orientXY(shape, xT) {
356
364
  const deg = (Math.atan2(xT[1], xT[0]) * 180) / Math.PI;
357
365
  if (Math.abs(deg) < 1e-9)
358
366
  return shape;
359
- return rotate(shape, deg, { at: [0, 0, 0], axis: Z_AXIS });
367
+ return (await rotate(shape, deg, { at: [0, 0, 0], axis: Z_AXIS }));
360
368
  }
361
369
  function toPt2(v) {
362
370
  return [v[0], v[1]];
@@ -1 +1 @@
1
- {"version":3,"file":"reliefFns.js","sourceRoot":"","sources":["../src/reliefFns.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type Result,\n type Vec3,\n type Solid,\n ok,\n err,\n validationError,\n box,\n cut,\n rotate,\n translate,\n getBounds,\n getSolids,\n isValid,\n curveStartPoint,\n curveEndPoint,\n vecAdd,\n vecSub,\n vecScale,\n vecCross,\n vecDot,\n vecNormalize,\n} from '@faicad/faijs/brepjs-compat';\nimport type {\n BendFeature,\n FlangeFeature,\n ReliefFeature,\n ReliefSpec,\n SheetMetalPart,\n} from './types.js';\nimport { normalizeSolid } from './internal.js';\nimport { unfold } from './unfoldFns.js';\nimport { developedLength } from './allowanceFns.js';\n\nconst EPS = 1e-6;\nconst Z_AXIS: Vec3 = [0, 0, 1];\n\ntype Pt2 = [number, number];\ntype NotchRect = [number, number, number, number];\n\n/**\n * Add a bend relief to a flange: a small slot cut into the PARENT flat at each end\n * of the bend line that does not reach the parent edge endpoint (a partial/offset\n * flange). Without it the parent material tears at the corner where the bend\n * terminates mid-edge. Each slot is `width` (≈ thickness) along the parent edge by\n * `depth` (≈ developed length + clearance) into the parent flat, cut from the 3D\n * solid and recorded so {@link unfold} replays the 2D notch.\n *\n * A relief is a recorded feature replayed by unfold — exactly the pattern\n * {@link autoMiterCorner} establishes for corner miters.\n *\n * @param part - the sheet metal part to cut.\n * @param flangeId - the flange (bend) ID to relieve.\n * @param spec - the relief specification (default rectangular).\n * @returns the updated part with the bend relief recorded, or an error.\n */\nexport function addBendRelief(\n part: SheetMetalPart,\n flangeId: string,\n spec: ReliefSpec = { shape: 'rectangular' }\n): Result<SheetMetalPart> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', 'addBendRelief: part has no folded solid to cut'));\n }\n const flange = part.flanges.find((f) => f.id === flangeId);\n const bend = part.bends.find((b) => b.id === flangeId);\n if (flange === undefined || bend === undefined) {\n return err(validationError('UNKNOWN_FLANGE', `addBendRelief: flange '${flangeId}' not found`));\n }\n\n const dims = reliefDims(spec, part.thickness, devOf(bend, part.thickness));\n if (!dims.ok) return dims;\n const { width, depth } = dims.value;\n\n const geo = bendReliefGeometry(part, flange, bend, width, depth);\n if (geo === undefined) {\n return err(\n validationError(\n 'BEND_RELIEF_NOT_NEEDED',\n `addBendRelief: bend '${flangeId}' spans its full parent edge; no relief end to cut`\n )\n );\n }\n\n let solid = part.solid;\n for (const tool of geo.tools3d) {\n const result = cut(solid, tool);\n if (!result.ok) return result;\n solid = normalizeSolid(result.value);\n }\n if (!isValid(solid) || getSolids(solid).length > 1) {\n return err(\n validationError(\n 'RELIEF_SEVERED_SOLID',\n `addBendRelief: slot (width ${width}, depth ${depth}) severs flange '${flangeId}' into multiple bodies; reduce width/depth`\n )\n );\n }\n\n const feature: ReliefFeature = {\n kind: 'bend',\n shape: spec.shape,\n flangeA: flangeId,\n width,\n depth,\n notches: geo.notches2d,\n };\n\n return ok({ ...part, solid, reliefs: [...(part.reliefs ?? []), feature] });\n}\n\n/**\n * Add a bend relief to every partial-span bend (a flange that does not span its\n * full parent edge). Full-span flanges are skipped — they have no mid-edge bend\n * terminus to relieve. Convenience over calling {@link addBendRelief} per flange.\n *\n * @param part - the sheet metal part to process.\n * @param spec - the relief specification (default rectangular).\n * @returns the updated part with all needed bend reliefs, or an error.\n */\nexport function autoBendReliefs(\n part: SheetMetalPart,\n spec: ReliefSpec = { shape: 'rectangular' }\n): Result<SheetMetalPart> {\n let current = part;\n for (const flange of part.flanges) {\n // Let addBendRelief own the needed/not-needed decision rather than recomputing\n // the relief geometry here just to peek (which also allocated throwaway tools).\n const next = addBendRelief(current, flange.id, spec);\n if (!next.ok) {\n if (next.error.code === 'BEND_RELIEF_NOT_NEEDED') continue;\n return next;\n }\n current = next.value;\n }\n return ok(current);\n}\n\n/**\n * Corner relief between two adjacent flanges: a notch cut at their shared corner so\n * the two upright flanges clear each other once folded — the alternative to a 45°\n * miter for the same corner {@link autoMiterCorner} handles. The notch is cut from\n * the solid and recorded as a {@link ReliefFeature}; the corner is also recorded in\n * `miters` (gap 0) so the collision check treats the interference as resolved.\n *\n * @param part - the sheet metal part to cut.\n * @param flangeIdA - the first flange ID.\n * @param flangeIdB - the second flange ID.\n * @param spec - the relief specification (default rectangular).\n * @returns the updated part with the corner relief recorded, or an error.\n */\nexport function cornerRelief(\n part: SheetMetalPart,\n flangeIdA: string,\n flangeIdB: string,\n spec: ReliefSpec = { shape: 'rectangular' }\n): Result<SheetMetalPart> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', 'cornerRelief: part has no folded solid'));\n }\n const bendA = part.bends.find((b) => b.id === flangeIdA);\n const bendB = part.bends.find((b) => b.id === flangeIdB);\n if (bendA === undefined || bendB === undefined) {\n return err(\n validationError('UNKNOWN_FLANGE', `cornerRelief: flange '${flangeIdA}' or '${flangeIdB}' not found`)\n );\n }\n const axisA = vecNormalize(bendA.axisDir);\n const axisB = vecNormalize(bendB.axisDir);\n if (Math.hypot(...vecCross(axisA, axisB)) < EPS) {\n return err(\n validationError('PARALLEL_FLANGES', 'cornerRelief: flange bend axes are parallel; no corner to relieve')\n );\n }\n\n const devClearance = Math.max(devOf(bendA, part.thickness), devOf(bendB, part.thickness));\n const dims = reliefDims(spec, part.thickness, devClearance);\n if (!dims.ok) return dims;\n const { depth } = dims.value;\n\n // The corner notch is a square; its side is the user's `width` when given, else\n // the depth clearance. Both recorded dims are the actual side so a consumer\n // reading width/depth reconstructs the real cut (not a stale clearance value).\n const side = spec.width ?? depth;\n\n const flangeA = part.flanges.find((f) => f.id === flangeIdA);\n const flangeB = part.flanges.find((f) => f.id === flangeIdB);\n const geo = cornerReliefGeometry(part, axisA, axisB, bendA, bendB, side, flangeA, flangeB);\n const tool = squareTool(part.solid, geo.cornerXY, side);\n const result = cut(part.solid, tool);\n if (!result.ok) return result;\n\n const solid = normalizeSolid(result.value);\n if (!isValid(solid) || getSolids(solid).length > 1) {\n return err(\n validationError(\n 'RELIEF_SEVERED_SOLID',\n `cornerRelief: notch (side ${side}) severs the part into multiple bodies; reduce width/depth`\n )\n );\n }\n\n const feature: ReliefFeature = {\n kind: 'corner',\n shape: spec.shape,\n flangeA: flangeIdA,\n flangeB: flangeIdB,\n width: side,\n depth: side,\n notches: [geo.notch2d],\n };\n\n return ok({\n ...part,\n solid,\n reliefs: [...(part.reliefs ?? []), feature],\n miters: [...(part.miters ?? []), { flangeA: flangeIdA, flangeB: flangeIdB, gap: 0 }],\n });\n}\n\n/**\n * Developed strip width of a bend, via the canonical {@link developedLength} so the\n * default relief depth tracks the same neutral-axis arc length the unfold uses.\n * Falls back to the inner radius if the rule is degenerate (the depth is only a\n * heuristic clearance, so a positive fallback keeps a valid default tool).\n */\nfunction devOf(bend: BendFeature, thickness: number): number {\n const dev = developedLength(bend.angleDeg, thickness, bend.rule);\n return dev.ok ? dev.value : bend.rule.innerRadius;\n}\n\n/** Resolve relief width/depth from the spec, defaulting to thickness / (dev + T). */\nfunction reliefDims(\n spec: ReliefSpec,\n thickness: number,\n dev: number\n): Result<{ width: number; depth: number }> {\n const width = spec.width ?? thickness;\n const depth = spec.depth ?? dev + thickness;\n if (!Number.isFinite(width) || width <= 0) {\n return err(validationError('INVALID_RELIEF_WIDTH', `relief width must be positive, got ${width}`));\n }\n if (!Number.isFinite(depth) || depth <= 0) {\n return err(validationError('INVALID_RELIEF_DEPTH', `relief depth must be positive, got ${depth}`));\n }\n return ok({ width, depth });\n}\n\ninterface BendReliefGeometry {\n tools3d: Solid[];\n notches2d: NotchRect[];\n}\n\n/**\n * Build the 3D cut tools and 2D developed-plane notch rectangles for a bend relief.\n * In 3D each slot straddles a bend-line end on the parent edge and cuts inward\n * (toward the parent interior) by `depth`, full thickness. In 2D the slot sits at\n * the corresponding bend-line endpoint and cuts into the parent rectangle the same\n * way. Returns `undefined` when the flange spans its full parent edge (no mid-edge\n * end to relieve).\n */\nfunction bendReliefGeometry(\n part: SheetMetalPart,\n flange: FlangeFeature,\n bend: BendFeature,\n width: number,\n depth: number\n): BendReliefGeometry | undefined {\n if (part.solid === undefined) return undefined;\n\n const axis = vecNormalize(bend.axisDir);\n const span = flange.span;\n const offset = flange.offset ?? flange.baseEdge.offset ?? 0;\n const edgeLen = parentEdgeLength(part, flange);\n\n const atStart = offset > EPS;\n const atEnd = offset + span < edgeLen - EPS;\n if (!atStart && !atEnd) return undefined;\n\n const b = getBounds(part.solid);\n const center: Vec3 = [(b.xMin + b.xMax) / 2, (b.yMin + b.yMax) / 2, 0];\n const inward = inwardRun(bend.axisOrigin, axis, center);\n const edgeBase: Vec3 = [bend.axisOrigin[0], bend.axisOrigin[1], 0];\n\n const tools3d: Solid[] = [];\n const ends: number[] = [];\n if (atStart) ends.push(0);\n if (atEnd) ends.push(span);\n for (const s of ends) {\n const at = vecAdd(edgeBase, vecScale(axis, s));\n tools3d.push(slotTool3d(at, axis, inward, width, depth, part.thickness));\n }\n\n const notches2d = bendNotches2d(part, flange, width, depth, atStart, atEnd);\n return { tools3d, notches2d };\n}\n\n/**\n * Developed-plane notch rectangles for a bend relief, located at the bend-line ends\n * and cutting into the PARENT rectangle (opposite the develop-out direction). The\n * unfold is the source of truth for 2D placement, so we read the developed bend\n * line straight from it and offset inward.\n */\nfunction bendNotches2d(\n part: SheetMetalPart,\n flange: FlangeFeature,\n width: number,\n depth: number,\n atStart: boolean,\n atEnd: boolean\n): NotchRect[] {\n const placed = developedBendLine(part, flange);\n if (placed === undefined) return [];\n const { bendA, bendB, inward } = placed;\n const len = Math.max(dist2(bendA, bendB), EPS);\n const along: Pt2 = [(bendB[0] - bendA[0]) / len, (bendB[1] - bendA[1]) / len];\n const half = width / 2;\n const make = (p: Pt2): NotchRect => {\n const c0: Pt2 = [p[0] - along[0] * half, p[1] - along[1] * half];\n const c1: Pt2 = [\n p[0] + along[0] * half + inward[0] * depth,\n p[1] + along[1] * half + inward[1] * depth,\n ];\n return [Math.min(c0[0], c1[0]), Math.min(c0[1], c1[1]), Math.max(c0[0], c1[0]), Math.max(c0[1], c1[1])];\n };\n const notches: NotchRect[] = [];\n if (atStart) notches.push(make(bendA));\n if (atEnd) notches.push(make(bendB));\n return notches;\n}\n\ninterface DevelopedBendLine {\n bendA: Pt2;\n bendB: Pt2;\n inward: Pt2;\n}\n\n/**\n * Locate a flange's bend line in the developed plane by re-running the unfold and\n * matching by flange id — the unfold owns 2D placement, so the notch always\n * coincides with the real developed geometry. Matching by id (not by geometric\n * signature) keeps placement correct when several flanges share the same\n * span/angle/direction, as in {@link autoBendReliefs}.\n */\nfunction developedBendLine(part: SheetMetalPart, flange: FlangeFeature): DevelopedBendLine | undefined {\n const unfolded = unfold({ ...part, reliefs: undefined });\n if (!unfolded.ok) return undefined;\n const bl = unfolded.value.pattern.bendLines.find((b) => b.id === flange.id);\n if (bl === undefined) return undefined;\n const a = toPt2(curveStartPoint(bl.line));\n const b = toPt2(curveEndPoint(bl.line));\n return { bendA: a, bendB: b, inward: bl.inward };\n}\n\ninterface CornerReliefGeometry {\n cornerXY: Pt2;\n notch2d: NotchRect;\n}\n\n/**\n * Corner relief geometry: the shared-corner point of the two flanges' bend lines in\n * world XY, plus a square developed-plane notch CENTRED on the reflex corner of the\n * two flanges (`(baseLength, width)` for the classic +X/+Y L). Centring the square\n * on the corner bites the base and both flange roots equally, so the developed\n * outline stays a single closed loop (a notch landing its far corner exactly on the\n * reflex vertex would pinch the boundary).\n */\nfunction cornerReliefGeometry(\n part: SheetMetalPart,\n axisA: Vec3,\n axisB: Vec3,\n bendA: BendFeature,\n bendB: BendFeature,\n side: number,\n flangeA: FlangeFeature | undefined,\n flangeB: FlangeFeature | undefined\n): CornerReliefGeometry {\n const corner = cornerPoint(bendA.axisOrigin, axisA, bendB.axisOrigin, axisB);\n const [cx, cy] = developedCorner(part, flangeA, flangeB);\n const h = side / 2;\n const notch2d: NotchRect = [cx - h, cy - h, cx + h, cy + h];\n return { cornerXY: [corner[0], corner[1]], notch2d };\n}\n\n/**\n * Developed-plane base corner shared by two perpendicular base flanges, picked from\n * their sides: an `xmax` flange's corner x is `baseLength`, an `xmin`'s is `0`; a\n * `ymax`'s corner y is `width`, a `ymin`'s is `0`. Defaults to the +X/+Y corner.\n */\nfunction developedCorner(\n part: SheetMetalPart,\n flangeA: FlangeFeature | undefined,\n flangeB: FlangeFeature | undefined\n): Pt2 {\n let cx = part.baseLength;\n let cy = part.width;\n for (const f of [flangeA, flangeB]) {\n const side = f?.baseEdge.side;\n if (side === 'xmin') cx = 0;\n else if (side === 'xmax') cx = part.baseLength;\n else if (side === 'ymin') cy = 0;\n else if (side === 'ymax') cy = part.width;\n }\n return [cx, cy];\n}\n\n/** Point on bend A's line closest to bend B's line (their shared corner). */\nfunction cornerPoint(originA: Vec3, dirA: Vec3, originB: Vec3, dirB: Vec3): Vec3 {\n const w0 = vecSub(originA, originB);\n const a = vecDot(dirA, dirA);\n const b = vecDot(dirA, dirB);\n const c = vecDot(dirB, dirB);\n const d = vecDot(dirA, w0);\n const e = vecDot(dirB, w0);\n const denom = a * c - b * b;\n if (Math.abs(denom) < 1e-9) return originA;\n const sc = (b * e - c * d) / denom;\n return vecAdd(originA, vecScale(dirA, sc));\n}\n\n/** In-plane perpendicular to `axis` pointing toward the part center (into the parent). */\nfunction inwardRun(axisOrigin: Vec3, axis: Vec3, center: Vec3): Vec3 {\n const perp = vecNormalize(vecCross(axis, Z_AXIS));\n const toCenter: Vec3 = [center[0] - axisOrigin[0], center[1] - axisOrigin[1], 0];\n const dot = perp[0] * toCenter[0] + perp[1] * toCenter[1];\n return dot >= 0 ? perp : [-perp[0], -perp[1], -perp[2]];\n}\n\n/** Parent-edge length the flange folds off (base edge for root flanges). */\nfunction parentEdgeLength(part: SheetMetalPart, flange: FlangeFeature): number {\n const side = flange.baseEdge.side ?? 'xmax';\n const onWidthEdge = side === 'xmax' || side === 'xmin';\n const parentId = flange.baseEdge.parentId;\n if (parentId === undefined || parentId === 'root' || parentId === 'face-0') {\n return onWidthEdge ? part.width : part.baseLength;\n }\n const parent = part.flanges.find((f) => f.id === parentId);\n if (parent === undefined) return onWidthEdge ? part.width : part.baseLength;\n return onWidthEdge ? parent.length : parent.span;\n}\n\n/**\n * A box tool for a bend-relief slot: a `width × depth × (thickness + margins)` block\n * whose `width` axis runs along the parent edge and `depth` axis points inward,\n * placed so it straddles the edge point `at` and cuts through the parent surface.\n */\nfunction slotTool3d(\n at: Vec3,\n along: Vec3,\n inward: Vec3,\n width: number,\n depth: number,\n thickness: number\n): Solid {\n const margin = thickness + 2;\n // Canonical: width along +X, depth along +Y, height along +Z (cuts through Z).\n // Rotating by `deg` sends +X→along and +Y→(along rotated +90° = [-along.y, along.x]).\n // If that rotated +Y opposes `inward`, build the block extending in −Y so it cuts\n // into the parent rather than out into the flange.\n const rotPerp: Vec3 = [-along[1], along[0], 0];\n const y0 = vecDot(rotPerp, inward) >= 0 ? 0 : -depth;\n let tool: Solid = box(width, depth, thickness + 2 * margin);\n tool = translate(tool, [-width / 2, y0, -margin]);\n tool = orientXY(tool, along);\n return translate(tool, [at[0], at[1], 0]);\n}\n\n/**\n * Square corner-relief tool: a `side × side × (height + margins)` block CENTRED on\n * the corner point in XY and spanning the full part height, so it removes material\n * from the base corner and both flange roots. Corner reliefs sit at axis-aligned\n * base corners for the supported perpendicular flange shapes, so the tool stays\n * axis-aligned.\n */\nfunction squareTool(solid: Solid, cornerXY: Pt2, side: number): Solid {\n const b = getBounds(solid);\n const margin = 2;\n const h = side / 2;\n const tool = box(side, side, b.zMax - b.zMin + 2 * margin);\n return translate(tool, [cornerXY[0] - h, cornerXY[1] - h, b.zMin - margin]);\n}\n\n/** Rotate a shape about +Z so its local +X axis points along `xT` (in the XY plane). */\nfunction orientXY(shape: Solid, xT: Vec3): Solid {\n const deg = (Math.atan2(xT[1], xT[0]) * 180) / Math.PI;\n if (Math.abs(deg) < 1e-9) return shape;\n return rotate(shape, deg, { at: [0, 0, 0], axis: Z_AXIS });\n}\n\nfunction toPt2(v: Vec3): Pt2 {\n return [v[0], v[1]];\n}\n\nfunction dist2(a: Pt2, b: Pt2): number {\n return Math.hypot(a[0] - b[0], a[1] - b[1]);\n}\n"]}
1
+ {"version":3,"file":"reliefFns.js","sourceRoot":"","sources":["../src/reliefFns.ts"],"names":[],"mappings":"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","sourcesContent":["import { getBounds } from './geometryOps.js';\nimport type { Solid } from './types.js';\nimport { translate } from './geometryOps.js';\nimport {type Result, type Vec3, ok, err, kernelError, validationError, box, cut, rotate, getSolids, isValid, curveStartPoint, curveEndPoint, vecAdd, vecSub, vecScale, vecCross, vecDot, vecNormalize} from '@faicad/faijs/api';\nimport type {\n BendFeature,\n FlangeFeature,\n ReliefFeature,\n ReliefSpec,\n SheetMetalPart,\n} from './types.js';\nimport { normalizeSolid } from './internal.js';\nimport { unfold } from './unfoldFns.js';\nimport { developedLength } from './allowanceFns.js';\n\nconst EPS = 1e-6;\nconst Z_AXIS: Vec3 = [0, 0, 1];\n\ntype Pt2 = [number, number];\ntype NotchRect = [number, number, number, number];\n\n/**\n * Add a bend relief to a flange: a small slot cut into the PARENT flat at each end\n * of the bend line that does not reach the parent edge endpoint (a partial/offset\n * flange). Without it the parent material tears at the corner where the bend\n * terminates mid-edge. Each slot is `width` (≈ thickness) along the parent edge by\n * `depth` (≈ developed length + clearance) into the parent flat, cut from the 3D\n * solid and recorded so {@link unfold} replays the 2D notch.\n *\n * A relief is a recorded feature replayed by unfold — exactly the pattern\n * {@link autoMiterCorner} establishes for corner miters.\n *\n * @param part - the sheet metal part to cut.\n * @param flangeId - the flange (bend) ID to relieve.\n * @param spec - the relief specification (default rectangular).\n * @returns the updated part with the bend relief recorded, or an error.\n */\nexport async function addBendRelief(\n part: SheetMetalPart,\n flangeId: string,\n spec: ReliefSpec = { shape: 'rectangular' }\n): Promise<Result<SheetMetalPart>> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', 'addBendRelief: part has no folded solid to cut'));\n }\n const flange = part.flanges.find((f) => f.id === flangeId);\n const bend = part.bends.find((b) => b.id === flangeId);\n if (flange === undefined || bend === undefined) {\n return err(validationError('UNKNOWN_FLANGE', `addBendRelief: flange '${flangeId}' not found`));\n }\n\n const dims = reliefDims(spec, part.thickness, devOf(bend, part.thickness));\n if (!dims.ok) return dims;\n const { width, depth } = dims.value;\n\n let geo: BendReliefGeometry | undefined;\n let solid = part.solid;\n try {\n geo = await bendReliefGeometry(part, flange, bend, width, depth);\n if (geo === undefined) {\n return err(\n validationError(\n 'BEND_RELIEF_NOT_NEEDED',\n `addBendRelief: bend '${flangeId}' spans its full parent edge; no relief end to cut`\n )\n );\n }\n for (const tool of geo.tools3d) {\n solid = normalizeSolid((await cut(solid, tool)) as Solid);\n }\n } catch (e) {\n return err(kernelError('CUT_FAILED', `bend relief: ${e instanceof Error ? e.message : String(e)}`));\n }\n if (!isValid(solid) || getSolids(solid).length > 1) {\n return err(\n validationError(\n 'RELIEF_SEVERED_SOLID',\n `addBendRelief: slot (width ${width}, depth ${depth}) severs flange '${flangeId}' into multiple bodies; reduce width/depth`\n )\n );\n }\n\n const feature: ReliefFeature = {\n kind: 'bend',\n shape: spec.shape,\n flangeA: flangeId,\n width,\n depth,\n notches: geo.notches2d,\n };\n\n return ok({ ...part, solid, reliefs: [...(part.reliefs ?? []), feature] });\n}\n\n/**\n * Add a bend relief to every partial-span bend (a flange that does not span its\n * full parent edge). Full-span flanges are skipped — they have no mid-edge bend\n * terminus to relieve. Convenience over calling {@link addBendRelief} per flange.\n *\n * @param part - the sheet metal part to process.\n * @param spec - the relief specification (default rectangular).\n * @returns the updated part with all needed bend reliefs, or an error.\n */\nexport async function autoBendReliefs(\n part: SheetMetalPart,\n spec: ReliefSpec = { shape: 'rectangular' }\n): Promise<Result<SheetMetalPart>> {\n let current = part;\n for (const flange of part.flanges) {\n // Let addBendRelief own the needed/not-needed decision rather than recomputing\n // the relief geometry here just to peek (which also allocated throwaway tools).\n const next = await addBendRelief(current, flange.id, spec);\n if (!next.ok) {\n if (next.error.code === 'BEND_RELIEF_NOT_NEEDED') continue;\n return next;\n }\n current = next.value;\n }\n return ok(current);\n}\n\n/**\n * Corner relief between two adjacent flanges: a notch cut at their shared corner so\n * the two upright flanges clear each other once folded — the alternative to a 45°\n * miter for the same corner {@link autoMiterCorner} handles. The notch is cut from\n * the solid and recorded as a {@link ReliefFeature}; the corner is also recorded in\n * `miters` (gap 0) so the collision check treats the interference as resolved.\n *\n * @param part - the sheet metal part to cut.\n * @param flangeIdA - the first flange ID.\n * @param flangeIdB - the second flange ID.\n * @param spec - the relief specification (default rectangular).\n * @returns the updated part with the corner relief recorded, or an error.\n */\nexport async function cornerRelief(\n part: SheetMetalPart,\n flangeIdA: string,\n flangeIdB: string,\n spec: ReliefSpec = { shape: 'rectangular' }\n): Promise<Result<SheetMetalPart>> {\n if (part.solid === undefined) {\n return err(validationError('NO_SOLID', 'cornerRelief: part has no folded solid'));\n }\n const bendA = part.bends.find((b) => b.id === flangeIdA);\n const bendB = part.bends.find((b) => b.id === flangeIdB);\n if (bendA === undefined || bendB === undefined) {\n return err(\n validationError('UNKNOWN_FLANGE', `cornerRelief: flange '${flangeIdA}' or '${flangeIdB}' not found`)\n );\n }\n const axisA = vecNormalize(bendA.axisDir);\n const axisB = vecNormalize(bendB.axisDir);\n if (Math.hypot(...vecCross(axisA, axisB)) < EPS) {\n return err(\n validationError('PARALLEL_FLANGES', 'cornerRelief: flange bend axes are parallel; no corner to relieve')\n );\n }\n\n const devClearance = Math.max(devOf(bendA, part.thickness), devOf(bendB, part.thickness));\n const dims = reliefDims(spec, part.thickness, devClearance);\n if (!dims.ok) return dims;\n const { depth } = dims.value;\n\n // The corner notch is a square; its side is the user's `width` when given, else\n // the depth clearance. Both recorded dims are the actual side so a consumer\n // reading width/depth reconstructs the real cut (not a stale clearance value).\n const side = spec.width ?? depth;\n\n const flangeA = part.flanges.find((f) => f.id === flangeIdA);\n const flangeB = part.flanges.find((f) => f.id === flangeIdB);\n const geo = cornerReliefGeometry(part, axisA, axisB, bendA, bendB, side, flangeA, flangeB);\n let solid: Solid;\n try {\n const tool = await squareTool(part.solid, geo.cornerXY, side);\n solid = normalizeSolid((await cut(part.solid, tool)) as Solid);\n } catch (e) {\n return err(kernelError('CUT_FAILED', `corner relief: ${e instanceof Error ? e.message : String(e)}`));\n }\n if (!isValid(solid) || getSolids(solid).length > 1) {\n return err(\n validationError(\n 'RELIEF_SEVERED_SOLID',\n `cornerRelief: notch (side ${side}) severs the part into multiple bodies; reduce width/depth`\n )\n );\n }\n\n const feature: ReliefFeature = {\n kind: 'corner',\n shape: spec.shape,\n flangeA: flangeIdA,\n flangeB: flangeIdB,\n width: side,\n depth: side,\n notches: [geo.notch2d],\n };\n\n return ok({\n ...part,\n solid,\n reliefs: [...(part.reliefs ?? []), feature],\n miters: [...(part.miters ?? []), { flangeA: flangeIdA, flangeB: flangeIdB, gap: 0 }],\n });\n}\n\n/**\n * Developed strip width of a bend, via the canonical {@link developedLength} so the\n * default relief depth tracks the same neutral-axis arc length the unfold uses.\n * Falls back to the inner radius if the rule is degenerate (the depth is only a\n * heuristic clearance, so a positive fallback keeps a valid default tool).\n */\nfunction devOf(bend: BendFeature, thickness: number): number {\n const dev = developedLength(bend.angleDeg, thickness, bend.rule);\n return dev.ok ? dev.value : bend.rule.innerRadius;\n}\n\n/** Resolve relief width/depth from the spec, defaulting to thickness / (dev + T). */\nfunction reliefDims(\n spec: ReliefSpec,\n thickness: number,\n dev: number\n): Result<{ width: number; depth: number }> {\n const width = spec.width ?? thickness;\n const depth = spec.depth ?? dev + thickness;\n if (!Number.isFinite(width) || width <= 0) {\n return err(validationError('INVALID_RELIEF_WIDTH', `relief width must be positive, got ${width}`));\n }\n if (!Number.isFinite(depth) || depth <= 0) {\n return err(validationError('INVALID_RELIEF_DEPTH', `relief depth must be positive, got ${depth}`));\n }\n return ok({ width, depth });\n}\n\ninterface BendReliefGeometry {\n tools3d: Solid[];\n notches2d: NotchRect[];\n}\n\n/**\n * Build the 3D cut tools and 2D developed-plane notch rectangles for a bend relief.\n * In 3D each slot straddles a bend-line end on the parent edge and cuts inward\n * (toward the parent interior) by `depth`, full thickness. In 2D the slot sits at\n * the corresponding bend-line endpoint and cuts into the parent rectangle the same\n * way. Returns `undefined` when the flange spans its full parent edge (no mid-edge\n * end to relieve).\n */\nasync function bendReliefGeometry(\n part: SheetMetalPart,\n flange: FlangeFeature,\n bend: BendFeature,\n width: number,\n depth: number\n): Promise<BendReliefGeometry | undefined> {\n if (part.solid === undefined) return undefined;\n\n const axis = vecNormalize(bend.axisDir);\n const span = flange.span;\n const offset = flange.offset ?? flange.baseEdge.offset ?? 0;\n const edgeLen = parentEdgeLength(part, flange);\n\n const atStart = offset > EPS;\n const atEnd = offset + span < edgeLen - EPS;\n if (!atStart && !atEnd) return undefined;\n\n const b = getBounds(part.solid);\n const center: Vec3 = [(b.xMin + b.xMax) / 2, (b.yMin + b.yMax) / 2, 0];\n const inward = inwardRun(bend.axisOrigin, axis, center);\n const edgeBase: Vec3 = [bend.axisOrigin[0], bend.axisOrigin[1], 0];\n\n const tools3d: Solid[] = [];\n const ends: number[] = [];\n if (atStart) ends.push(0);\n if (atEnd) ends.push(span);\n for (const s of ends) {\n const at = vecAdd(edgeBase, vecScale(axis, s));\n tools3d.push(await slotTool3d(at, axis, inward, width, depth, part.thickness));\n }\n\n const notches2d = bendNotches2d(part, flange, width, depth, atStart, atEnd);\n return { tools3d, notches2d };\n}\n\n/**\n * Developed-plane notch rectangles for a bend relief, located at the bend-line ends\n * and cutting into the PARENT rectangle (opposite the develop-out direction). The\n * unfold is the source of truth for 2D placement, so we read the developed bend\n * line straight from it and offset inward.\n */\nfunction bendNotches2d(\n part: SheetMetalPart,\n flange: FlangeFeature,\n width: number,\n depth: number,\n atStart: boolean,\n atEnd: boolean\n): NotchRect[] {\n const placed = developedBendLine(part, flange);\n if (placed === undefined) return [];\n const { bendA, bendB, inward } = placed;\n const len = Math.max(dist2(bendA, bendB), EPS);\n const along: Pt2 = [(bendB[0] - bendA[0]) / len, (bendB[1] - bendA[1]) / len];\n const half = width / 2;\n const make = (p: Pt2): NotchRect => {\n const c0: Pt2 = [p[0] - along[0] * half, p[1] - along[1] * half];\n const c1: Pt2 = [\n p[0] + along[0] * half + inward[0] * depth,\n p[1] + along[1] * half + inward[1] * depth,\n ];\n return [Math.min(c0[0], c1[0]), Math.min(c0[1], c1[1]), Math.max(c0[0], c1[0]), Math.max(c0[1], c1[1])];\n };\n const notches: NotchRect[] = [];\n if (atStart) notches.push(make(bendA));\n if (atEnd) notches.push(make(bendB));\n return notches;\n}\n\ninterface DevelopedBendLine {\n bendA: Pt2;\n bendB: Pt2;\n inward: Pt2;\n}\n\n/**\n * Locate a flange's bend line in the developed plane by re-running the unfold and\n * matching by flange id — the unfold owns 2D placement, so the notch always\n * coincides with the real developed geometry. Matching by id (not by geometric\n * signature) keeps placement correct when several flanges share the same\n * span/angle/direction, as in {@link autoBendReliefs}.\n */\nfunction developedBendLine(part: SheetMetalPart, flange: FlangeFeature): DevelopedBendLine | undefined {\n const unfolded = unfold({ ...part, reliefs: undefined });\n if (!unfolded.ok) return undefined;\n const bl = unfolded.value.pattern.bendLines.find((b) => b.id === flange.id);\n if (bl === undefined) return undefined;\n const a = toPt2(curveStartPoint(bl.line));\n const b = toPt2(curveEndPoint(bl.line));\n return { bendA: a, bendB: b, inward: bl.inward };\n}\n\ninterface CornerReliefGeometry {\n cornerXY: Pt2;\n notch2d: NotchRect;\n}\n\n/**\n * Corner relief geometry: the shared-corner point of the two flanges' bend lines in\n * world XY, plus a square developed-plane notch CENTRED on the reflex corner of the\n * two flanges (`(baseLength, width)` for the classic +X/+Y L). Centring the square\n * on the corner bites the base and both flange roots equally, so the developed\n * outline stays a single closed loop (a notch landing its far corner exactly on the\n * reflex vertex would pinch the boundary).\n */\nfunction cornerReliefGeometry(\n part: SheetMetalPart,\n axisA: Vec3,\n axisB: Vec3,\n bendA: BendFeature,\n bendB: BendFeature,\n side: number,\n flangeA: FlangeFeature | undefined,\n flangeB: FlangeFeature | undefined\n): CornerReliefGeometry {\n const corner = cornerPoint(bendA.axisOrigin, axisA, bendB.axisOrigin, axisB);\n const [cx, cy] = developedCorner(part, flangeA, flangeB);\n const h = side / 2;\n const notch2d: NotchRect = [cx - h, cy - h, cx + h, cy + h];\n return { cornerXY: [corner[0], corner[1]], notch2d };\n}\n\n/**\n * Developed-plane base corner shared by two perpendicular base flanges, picked from\n * their sides: an `xmax` flange's corner x is `baseLength`, an `xmin`'s is `0`; a\n * `ymax`'s corner y is `width`, a `ymin`'s is `0`. Defaults to the +X/+Y corner.\n */\nfunction developedCorner(\n part: SheetMetalPart,\n flangeA: FlangeFeature | undefined,\n flangeB: FlangeFeature | undefined\n): Pt2 {\n let cx = part.baseLength;\n let cy = part.width;\n for (const f of [flangeA, flangeB]) {\n const side = f?.baseEdge.side;\n if (side === 'xmin') cx = 0;\n else if (side === 'xmax') cx = part.baseLength;\n else if (side === 'ymin') cy = 0;\n else if (side === 'ymax') cy = part.width;\n }\n return [cx, cy];\n}\n\n/** Point on bend A's line closest to bend B's line (their shared corner). */\nfunction cornerPoint(originA: Vec3, dirA: Vec3, originB: Vec3, dirB: Vec3): Vec3 {\n const w0 = vecSub(originA, originB);\n const a = vecDot(dirA, dirA);\n const b = vecDot(dirA, dirB);\n const c = vecDot(dirB, dirB);\n const d = vecDot(dirA, w0);\n const e = vecDot(dirB, w0);\n const denom = a * c - b * b;\n if (Math.abs(denom) < 1e-9) return originA;\n const sc = (b * e - c * d) / denom;\n return vecAdd(originA, vecScale(dirA, sc));\n}\n\n/** In-plane perpendicular to `axis` pointing toward the part center (into the parent). */\nfunction inwardRun(axisOrigin: Vec3, axis: Vec3, center: Vec3): Vec3 {\n const perp = vecNormalize(vecCross(axis, Z_AXIS));\n const toCenter: Vec3 = [center[0] - axisOrigin[0], center[1] - axisOrigin[1], 0];\n const dot = perp[0] * toCenter[0] + perp[1] * toCenter[1];\n return dot >= 0 ? perp : [-perp[0], -perp[1], -perp[2]];\n}\n\n/** Parent-edge length the flange folds off (base edge for root flanges). */\nfunction parentEdgeLength(part: SheetMetalPart, flange: FlangeFeature): number {\n const side = flange.baseEdge.side ?? 'xmax';\n const onWidthEdge = side === 'xmax' || side === 'xmin';\n const parentId = flange.baseEdge.parentId;\n if (parentId === undefined || parentId === 'root' || parentId === 'face-0') {\n return onWidthEdge ? part.width : part.baseLength;\n }\n const parent = part.flanges.find((f) => f.id === parentId);\n if (parent === undefined) return onWidthEdge ? part.width : part.baseLength;\n return onWidthEdge ? parent.length : parent.span;\n}\n\n/**\n * A box tool for a bend-relief slot: a `width × depth × (thickness + margins)` block\n * whose `width` axis runs along the parent edge and `depth` axis points inward,\n * placed so it straddles the edge point `at` and cuts through the parent surface.\n */\nasync function slotTool3d(\n at: Vec3,\n along: Vec3,\n inward: Vec3,\n width: number,\n depth: number,\n thickness: number\n): Promise<Solid> {\n const margin = thickness + 2;\n // Canonical: width along +X, depth along +Y, height along +Z (cuts through Z).\n // Rotating by `deg` sends +X→along and +Y→(along rotated +90° = [-along.y, along.x]).\n // If that rotated +Y opposes `inward`, build the block extending in −Y so it cuts\n // into the parent rather than out into the flange.\n const rotPerp: Vec3 = [-along[1], along[0], 0];\n const y0 = vecDot(rotPerp, inward) >= 0 ? 0 : -depth;\n let tool: Solid = (await box({ width, depth, height: thickness + 2 * margin })) as Solid;\n tool = (await translate(tool, [-width / 2, y0, -margin])) as Solid;\n tool = await orientXY(tool, along);\n return (await translate(tool, [at[0], at[1], 0])) as Solid;\n}\n\n/**\n * Square corner-relief tool: a `side × side × (height + margins)` block CENTRED on\n * the corner point in XY and spanning the full part height, so it removes material\n * from the base corner and both flange roots. Corner reliefs sit at axis-aligned\n * base corners for the supported perpendicular flange shapes, so the tool stays\n * axis-aligned.\n */\nasync function squareTool(solid: Solid, cornerXY: Pt2, side: number): Promise<Solid> {\n const b = getBounds(solid);\n const margin = 2;\n const h = side / 2;\n const tool = (await box({ width: side, depth: side, height: b.zMax - b.zMin + 2 * margin })) as Solid;\n return (await translate(tool, [cornerXY[0] - h, cornerXY[1] - h, b.zMin - margin])) as Solid;\n}\n\n/** Rotate a shape about +Z so its local +X axis points along `xT` (in the XY plane). */\nasync function orientXY(shape: Solid, xT: Vec3): Promise<Solid> {\n const deg = (Math.atan2(xT[1], xT[0]) * 180) / Math.PI;\n if (Math.abs(deg) < 1e-9) return shape;\n return (await rotate(shape, deg, { at: [0, 0, 0], axis: Z_AXIS })) as Solid;\n}\n\nfunction toPt2(v: Vec3): Pt2 {\n return [v[0], v[1]];\n}\n\nfunction dist2(a: Pt2, b: Pt2): number {\n return Math.hypot(a[0] - b[0], a[1] - b[1]);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type Result } from '@faicad/faijs/brepjs-compat';
1
+ import { type Result } from '@faicad/faijs/api';
2
2
  import type { BendReport, SheetMetalPart, UnfoldResult } from './types.js';
3
3
  /**
4
4
  * Build the bend-table JSON report directly from an authored part. Walks the
@@ -1 +1 @@
1
- {"version":3,"file":"reportFns.d.ts","sourceRoot":"","sources":["../src/reportFns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAA4B,MAAM,6BAA6B,CAAC;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI3E;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,CAiBpE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,CA0BzE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAEvD"}
1
+ {"version":3,"file":"reportFns.d.ts","sourceRoot":"","sources":["../src/reportFns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,MAAM,EAA2B,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI3E;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,CAiBpE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,CA0BzE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAEvD"}
package/dist/reportFns.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ok, err, validationError } from '@faicad/faijs/brepjs-compat';
1
+ import { ok, err, validationError } from '@faicad/faijs/api';
2
2
  import { featureTree } from './featureTreeFns.js';
3
3
  import { layoutTree, reportFromLayout } from './unfoldFns.js';
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"reportFns.js","sourceRoot":"","sources":["../src/reportFns.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Result, ok, err, validationError } from '@faicad/faijs/brepjs-compat';\nimport type { BendReport, SheetMetalPart, UnfoldResult } from './types.js';\nimport { featureTree } from './featureTreeFns.js';\nimport { layoutTree, reportFromLayout } from './unfoldFns.js';\n\n/**\n * Build the bend-table JSON report directly from an authored part. Walks the\n * same tree layout the unfold consumes so the per-bend values and the total flat\n * size agree with the flat pattern. `allowance` is the consumed neutral-axis arc\n * length (the bend allowance); `flatLength` is the straight flange leg past the\n * bend — distinct values a downstream nesting/cut-list tool needs separately.\n *\n * @param part - the authored part to build the report from.\n * @returns the bend-table report, or an error if the part tree or layout cannot\n * be built.\n */\nexport function buildReport(part: SheetMetalPart): Result<BendReport> {\n const treeResult = featureTree(part);\n if (!treeResult.ok) return treeResult;\n const tree = treeResult.value;\n\n const baseLength = part.baseLength;\n if (!Number.isFinite(baseLength) || baseLength <= 0) {\n return err(validationError('INVALID_BASE_LENGTH', `part baseLength must be positive, got ${baseLength}`));\n }\n const width = part.width;\n if (!Number.isFinite(width) || width <= 0) {\n return err(validationError('INVALID_WIDTH', `part width must be positive, got ${width}`));\n }\n\n const layout = layoutTree(part, tree, baseLength, width);\n if (!layout.ok) return layout;\n return ok(reportFromLayout(layout.value));\n}\n\n/**\n * Project the report already computed by `unfold` into the standalone\n * `BendReport` shape, defensively re-validating its numeric fields. This keeps\n * the report a pure function of a previously-unfolded result without re-walking\n * the tree.\n *\n * @param result - the unfold result whose report is projected.\n * @returns the standalone `BendReport`, or an error if a numeric field is not\n * finite or positive.\n */\nexport function reportFromUnfold(result: UnfoldResult): Result<BendReport> {\n const { report } = result;\n for (const bend of report.bends) {\n if (!Number.isFinite(bend.allowance) || bend.allowance < 0) {\n return err(\n validationError('INVALID_ALLOWANCE', `bend '${bend.id}' allowance must be finite, non-negative, got ${bend.allowance}`)\n );\n }\n if (!Number.isFinite(bend.flatLength) || bend.flatLength < 0) {\n return err(\n validationError('INVALID_FLAT_LENGTH', `bend '${bend.id}' flatLength must be finite, non-negative, got ${bend.flatLength}`)\n );\n }\n }\n\n const [run, width] = report.totalFlatSize;\n if (!Number.isFinite(run) || run <= 0 || !Number.isFinite(width) || width <= 0) {\n return err(\n validationError('INVALID_FLAT_SIZE', `totalFlatSize must be finite with positive dimensions, got [${run}, ${width}]`)\n );\n }\n\n return ok({\n bends: report.bends.map((bend) => ({ ...bend })),\n totalFlatSize: [run, width],\n });\n}\n\n/**\n * Serialize a `BendReport` to a stable, pretty-printed JSON string.\n *\n * @param report - the bend report to serialize.\n * @returns the pretty-printed JSON string.\n */\nexport function reportToJSON(report: BendReport): string {\n return JSON.stringify(report, null, 2);\n}\n"]}
1
+ {"version":3,"file":"reportFns.js","sourceRoot":"","sources":["../src/reportFns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,EAAE,EAAE,GAAG,EAAE,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAExE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE9D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,IAAoB;IAC9C,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,UAAU,CAAC,EAAE;QAAE,OAAO,UAAU,CAAC;IACtC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC;IAE9B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACpD,OAAO,GAAG,CAAC,eAAe,CAAC,qBAAqB,EAAE,yCAAyC,UAAU,EAAE,CAAC,CAAC,CAAC;IAC5G,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAO,GAAG,CAAC,eAAe,CAAC,eAAe,EAAE,oCAAoC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC5F,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,MAAM,CAAC;IAC9B,OAAO,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;YAC3D,OAAO,GAAG,CACR,eAAe,CAAC,mBAAmB,EAAE,SAAS,IAAI,CAAC,EAAE,iDAAiD,IAAI,CAAC,SAAS,EAAE,CAAC,CACxH,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YAC7D,OAAO,GAAG,CACR,eAAe,CAAC,qBAAqB,EAAE,SAAS,IAAI,CAAC,EAAE,kDAAkD,IAAI,CAAC,UAAU,EAAE,CAAC,CAC5H,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC/E,OAAO,GAAG,CACR,eAAe,CAAC,mBAAmB,EAAE,+DAA+D,GAAG,KAAK,KAAK,GAAG,CAAC,CACtH,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC;QACR,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QAChD,aAAa,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC;KAC5B,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkB;IAC7C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC","sourcesContent":["import {type Result, ok, err, validationError} from '@faicad/faijs/api';\nimport type { BendReport, SheetMetalPart, UnfoldResult } from './types.js';\nimport { featureTree } from './featureTreeFns.js';\nimport { layoutTree, reportFromLayout } from './unfoldFns.js';\n\n/**\n * Build the bend-table JSON report directly from an authored part. Walks the\n * same tree layout the unfold consumes so the per-bend values and the total flat\n * size agree with the flat pattern. `allowance` is the consumed neutral-axis arc\n * length (the bend allowance); `flatLength` is the straight flange leg past the\n * bend — distinct values a downstream nesting/cut-list tool needs separately.\n *\n * @param part - the authored part to build the report from.\n * @returns the bend-table report, or an error if the part tree or layout cannot\n * be built.\n */\nexport function buildReport(part: SheetMetalPart): Result<BendReport> {\n const treeResult = featureTree(part);\n if (!treeResult.ok) return treeResult;\n const tree = treeResult.value;\n\n const baseLength = part.baseLength;\n if (!Number.isFinite(baseLength) || baseLength <= 0) {\n return err(validationError('INVALID_BASE_LENGTH', `part baseLength must be positive, got ${baseLength}`));\n }\n const width = part.width;\n if (!Number.isFinite(width) || width <= 0) {\n return err(validationError('INVALID_WIDTH', `part width must be positive, got ${width}`));\n }\n\n const layout = layoutTree(part, tree, baseLength, width);\n if (!layout.ok) return layout;\n return ok(reportFromLayout(layout.value));\n}\n\n/**\n * Project the report already computed by `unfold` into the standalone\n * `BendReport` shape, defensively re-validating its numeric fields. This keeps\n * the report a pure function of a previously-unfolded result without re-walking\n * the tree.\n *\n * @param result - the unfold result whose report is projected.\n * @returns the standalone `BendReport`, or an error if a numeric field is not\n * finite or positive.\n */\nexport function reportFromUnfold(result: UnfoldResult): Result<BendReport> {\n const { report } = result;\n for (const bend of report.bends) {\n if (!Number.isFinite(bend.allowance) || bend.allowance < 0) {\n return err(\n validationError('INVALID_ALLOWANCE', `bend '${bend.id}' allowance must be finite, non-negative, got ${bend.allowance}`)\n );\n }\n if (!Number.isFinite(bend.flatLength) || bend.flatLength < 0) {\n return err(\n validationError('INVALID_FLAT_LENGTH', `bend '${bend.id}' flatLength must be finite, non-negative, got ${bend.flatLength}`)\n );\n }\n }\n\n const [run, width] = report.totalFlatSize;\n if (!Number.isFinite(run) || run <= 0 || !Number.isFinite(width) || width <= 0) {\n return err(\n validationError('INVALID_FLAT_SIZE', `totalFlatSize must be finite with positive dimensions, got [${run}, ${width}]`)\n );\n }\n\n return ok({\n bends: report.bends.map((bend) => ({ ...bend })),\n totalFlatSize: [run, width],\n });\n}\n\n/**\n * Serialize a `BendReport` to a stable, pretty-printed JSON string.\n *\n * @param report - the bend report to serialize.\n * @returns the pretty-printed JSON string.\n */\nexport function reportToJSON(report: BendReport): string {\n return JSON.stringify(report, null, 2);\n}\n"]}
package/dist/tabFns.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type Result } from '@faicad/faijs/brepjs-compat';
1
+ import { type Result } from '@faicad/faijs/api';
2
2
  import type { TabSpec, SheetMetalPart } from './types.js';
3
3
  /**
4
4
  * Fuse a rectangular tab onto a named flat region's edge — additive material (the
@@ -14,7 +14,7 @@ import type { TabSpec, SheetMetalPart } from './types.js';
14
14
  * @param spec - the tab specification.
15
15
  * @returns the updated part with the tab feature recorded, or an error.
16
16
  */
17
- export declare function addTab(part: SheetMetalPart, spec: TabSpec): Result<SheetMetalPart>;
17
+ export declare function addTab(part: SheetMetalPart, spec: TabSpec): Promise<Result<SheetMetalPart>>;
18
18
  /** The mating-slot placement for a {@link tabAndSlot} joint. */
19
19
  export interface SlotPlacement {
20
20
  region: string;
@@ -39,5 +39,5 @@ export interface SlotPlacement {
39
39
  * @param slot - the slot placement.
40
40
  * @returns the updated part with the tab-and-slot feature recorded, or an error.
41
41
  */
42
- export declare function tabAndSlot(part: SheetMetalPart, tab: TabSpec, slot: SlotPlacement): Result<SheetMetalPart>;
42
+ export declare function tabAndSlot(part: SheetMetalPart, tab: TabSpec, slot: SlotPlacement): Promise<Result<SheetMetalPart>>;
43
43
  //# sourceMappingURL=tabFns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tabFns.d.ts","sourceRoot":"","sources":["../src/tabFns.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EAgBZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAc,cAAc,EAAE,MAAM,YAAY,CAAC;AAUtE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,CAyDlF;AAED,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B;;0EAEsE;IACtE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,aAAa,GAClB,MAAM,CAAC,cAAc,CAAC,CAqBxB"}
1
+ {"version":3,"file":"tabFns.d.ts","sourceRoot":"","sources":["../src/tabFns.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,MAAM,EAA4I,MAAM,mBAAmB,CAAC;AACzL,OAAO,KAAK,EAAE,OAAO,EAAc,cAAc,EAAE,MAAM,YAAY,CAAC;AAUtE;;;;;;;;;;;;;GAaG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CA2DjG;AAED,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B;;0EAEsE;IACtE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAqBjC"}