brepjs-sheetmetal 0.1.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.
package/dist/api.d.ts ADDED
@@ -0,0 +1,128 @@
1
+ import { Result, Solid } from 'brepjs';
2
+ import { AuthorSpec, FlangeSpec } from './authorFns.js';
3
+ import { MiterPlane } from './miterFns.js';
4
+ import { SlotPlacement } from './tabFns.js';
5
+ import { DxfOptions } from './dxfFns.js';
6
+ import { NestOptions, NestResult } from './nestFns.js';
7
+ import { BendTable } from './bendTableFns.js';
8
+ import { SheetMetalPart, FlatPattern, FlatInput, BendReport, BendRule, ReliefSpec, CutoutSpec, TabSpec, ContourFlangeSpec, LoftedFlangeSpec, HemSpec, JogSpec, UnfoldResult, SheetMetalWarning } from './types.js';
9
+ /** Author a straight-bend part: a base flat plus folded-up flanges. */
10
+ export declare function author(spec: AuthorSpec): Result<SheetMetalPart>;
11
+ /** Flatten an authored part into a developed flat pattern + bend report + warnings. */
12
+ export declare function unfold(part: SheetMetalPart): Result<UnfoldResult>;
13
+ /**
14
+ * Unfold an imported sheet-metal solid that has no feature tree, by detecting its
15
+ * geometry (planar panels + cylindrical bends) numerically. `kFactor` defaults to
16
+ * the mid-surface neutral axis (0.5); supply a known material's K-factor to match
17
+ * its development.
18
+ */
19
+ export declare function unfoldSolid(solid: Solid, opts?: {
20
+ kFactor?: number;
21
+ }): Result<UnfoldResult>;
22
+ /** Fold a flat pattern (region-tree) up into a 3D part — the inverse of {@link unfold}. */
23
+ export declare function fold(input: FlatInput): Result<SheetMetalPart>;
24
+ /** Cut a part by an oriented plane, removing material on the `+normal` side. */
25
+ export declare function miter(part: SheetMetalPart, plane: MiterPlane): Result<SheetMetalPart>;
26
+ /** Auto-miter the shared corner of two flanges with an optional gap. */
27
+ export declare function miterCorner(part: SheetMetalPart, flangeIdA: string, flangeIdB: string, gap?: number): Result<SheetMetalPart>;
28
+ /** Add a bend relief slot at each mid-edge end of a partial flange's bend line. */
29
+ export declare function bendRelief(part: SheetMetalPart, flangeId: string, spec?: ReliefSpec): Result<SheetMetalPart>;
30
+ /** Add a bend relief to every partial-span bend in the part. */
31
+ export declare function autoReliefs(part: SheetMetalPart, spec?: ReliefSpec): Result<SheetMetalPart>;
32
+ /** Cut a corner relief notch at the shared corner of two adjacent flanges. */
33
+ export declare function relieveCorner(part: SheetMetalPart, flangeIdA: string, flangeIdB: string, spec?: ReliefSpec): Result<SheetMetalPart>;
34
+ /** Punch a cutout (hole / slot / polygon) through a named flat region's thickness. */
35
+ export declare function addCutout(part: SheetMetalPart, spec: CutoutSpec): Result<SheetMetalPart>;
36
+ /** Punch a circular hole of `diameter` centred at region-local `(x, y)`. */
37
+ export declare function addHole(part: SheetMetalPart, region: string, x: number, y: number, diameter: number): Result<SheetMetalPart>;
38
+ /** Punch a slot (rectangular or obround) centred at region-local `(x, y)`. */
39
+ export declare function addSlot(part: SheetMetalPart, region: string, opts: {
40
+ x: number;
41
+ y: number;
42
+ length: number;
43
+ width: number;
44
+ angleDeg?: number;
45
+ round?: boolean;
46
+ }): Result<SheetMetalPart>;
47
+ /** Punch an arbitrary polygon cutout from its region-local `points`. */
48
+ export declare function addPolygonCutout(part: SheetMetalPart, region: string, points: [number, number][]): Result<SheetMetalPart>;
49
+ /** Fuse a rectangular tab (additive protrusion) onto a region's edge. */
50
+ export declare function addTab(part: SheetMetalPart, spec: TabSpec): Result<SheetMetalPart>;
51
+ /** Self-fixturing tab-and-slot joint: a tab on one region + a matching slot on another. */
52
+ export declare function tabAndSlot(part: SheetMetalPart, tab: TabSpec, slot: SlotPlacement): Result<SheetMetalPart>;
53
+ /** Form a louver (vent flap cut on 3 sides, formed up along the hinge) on a region. */
54
+ export declare function louver(part: SheetMetalPart, opts: {
55
+ region: string;
56
+ x: number;
57
+ y: number;
58
+ length: number;
59
+ width: number;
60
+ height: number;
61
+ direction?: 'up' | 'down';
62
+ }): Result<SheetMetalPart>;
63
+ /** Form a round emboss (raised) or dimple (recessed) on a region. */
64
+ export declare function emboss(part: SheetMetalPart, opts: {
65
+ region: string;
66
+ x: number;
67
+ y: number;
68
+ diameter: number;
69
+ height: number;
70
+ kind: 'dimple' | 'emboss';
71
+ }): Result<SheetMetalPart>;
72
+ /**
73
+ * Author a contour flange: an open line/arc profile swept along a base edge into a
74
+ * multi-bend cross-section. The development is exact (Σ segment developed lengths).
75
+ */
76
+ export declare function contourFlange(part: SheetMetalPart, spec: ContourFlangeSpec): Result<SheetMetalPart>;
77
+ /**
78
+ * Author a lofted / ruled transition flange between two parallel open profiles. The
79
+ * development is by triangulation — exact for a developable transition, an
80
+ * approximation (with a `DEVELOPMENT_APPROXIMATE` unfold warning) otherwise.
81
+ */
82
+ export declare function loftedFlange(part: SheetMetalPart, spec: LoftedFlangeSpec): Result<SheetMetalPart>;
83
+ /**
84
+ * Author a hem: fold a region edge back ~180°+ onto its parent and run a short
85
+ * return leg. The development is exact (Σ curl bend allowances + return length).
86
+ */
87
+ export declare function hem(part: SheetMetalPart, spec: HemSpec): Result<SheetMetalPart>;
88
+ /**
89
+ * Author a jog (joggle): two opposite bends stepping the flat by `offsetHeight`
90
+ * perpendicular to its plane, then continuing parallel. Development is exact.
91
+ */
92
+ export declare function jog(part: SheetMetalPart, spec: JogSpec): Result<SheetMetalPart>;
93
+ /** Emit an annotated multi-layer DXF string for a flat pattern. */
94
+ export declare function toDXF(pattern: FlatPattern, options?: DxfOptions): Result<string>;
95
+ /**
96
+ * Nest developed flat patterns onto stock sheets to reduce waste. The default
97
+ * `strategy: "bbox"` packs each part as its outline bounding box (fast, no
98
+ * interlocking). `strategy: "nfp"` is true-shape / no-fit-polygon nesting: the actual
99
+ * outline polygons are packed so concave (L-shaped) parts interlock for higher
100
+ * utilization. The NFP packer is a HEURISTIC (bottom-left-fill) — not provably
101
+ * optimal — but never overlaps parts and never drops a part silently.
102
+ */
103
+ export declare function nest(patterns: FlatPattern[], options: NestOptions): Result<NestResult>;
104
+ /** Emit one fabrication-ready DXF for a single nested sheet (all parts placed). */
105
+ export declare function nestToDXF(result: NestResult, patterns: FlatPattern[], sheetIndex: number, options?: DxfOptions): Result<string>;
106
+ /** Build a bend report by walking the part's feature tree. */
107
+ export declare function report(part: SheetMetalPart): Result<BendReport>;
108
+ /** Project the report already computed by {@link unfold} without re-walking the tree. */
109
+ export declare function reportFrom(result: UnfoldResult): Result<BendReport>;
110
+ /** Serialize a bend report to stable pretty-printed JSON. */
111
+ export declare function reportJSON(report: BendReport): string;
112
+ /** Manufacturability checks — advisory warnings, never errors. */
113
+ export declare function validate(part: SheetMetalPart): SheetMetalWarning[];
114
+ /** Bend allowance `BA = (π/180)·|angle|·(R + K·T)` for a single bend. */
115
+ export declare function allowance(angleDeg: number, thickness: number, rule: BendRule, onWarning?: (warning: SheetMetalWarning) => void): Result<number>;
116
+ /** Neutral-axis developed length of a bend region (numerically equal to the allowance). */
117
+ export declare function developed(angleDeg: number, thickness: number, rule: BendRule, onWarning?: (warning: SheetMetalWarning) => void): Result<number>;
118
+ /** Register (or replace) a shop bend table so rules can reference it by id. */
119
+ export declare function addBendTable(table: BendTable): Result<BendTable>;
120
+ /** Look up a registered bend table by id (starter tables included). */
121
+ export declare function bendTable(id: string): BendTable | undefined;
122
+ /**
123
+ * Resolve a bend's developed allowance through the single resolution point:
124
+ * a referenced bend table, then an explicit `rule.allowance`, then the K-factor
125
+ * formula. This is what {@link developed} delegates to.
126
+ */
127
+ export declare function resolveAllowance(rule: BendRule, angleDeg: number, thickness: number, onWarning?: (warning: SheetMetalWarning) => void): Result<number>;
128
+ export type { AuthorSpec, FlangeSpec, MiterPlane, DxfOptions, SlotPlacement, NestOptions, NestResult };
@@ -0,0 +1,100 @@
1
+ import { Result, Vec3 } from 'brepjs';
2
+ import { BendRule, EdgeRef, FlatSide, MaterialSpec, MiterSpec, SheetMetalPart } from './types.js';
3
+ import { FeatureTree } from './featureTreeFns.js';
4
+ /** Authoring options for the base flat the flanges attach to. */
5
+ export interface BaseFlatSpec {
6
+ /** Extent along the run (+X) axis. */
7
+ length: number;
8
+ /** Extent along the width (+Y) axis. */
9
+ width: number;
10
+ }
11
+ /** Which edge a flange folds off (of the base, or of its parent flange). */
12
+ export type FlangeSide = FlatSide;
13
+ /** A single flange to author off an edge of its parent flat. */
14
+ export interface FlangeSpec {
15
+ id: string;
16
+ /** Flat length measured from the end of the bend along the flange plane. */
17
+ length: number;
18
+ /** Signed fold angle in degrees. */
19
+ angleDeg: number;
20
+ rule: BendRule;
21
+ /** Parent edge to attach to. Default `'xmax'` (the leading +X edge). */
22
+ side?: FlangeSide | undefined;
23
+ /** Fold direction relative to the parent face normal. Default `'up'`. */
24
+ direction?: 'up' | 'down' | undefined;
25
+ /** Id of another flange this flange folds off (its distal edge). Default = base flat. */
26
+ parent?: string | undefined;
27
+ /** Start position along the parent edge. Default `0`. */
28
+ offset?: number | undefined;
29
+ /** Extent along the parent edge. Default = full parent-edge length. */
30
+ width?: number | undefined;
31
+ miter?: MiterSpec | undefined;
32
+ }
33
+ /**
34
+ * A seam: a bend connecting two already-authored flats that is intentionally left
35
+ * unfolded (a free edge). Closing the last wall of a box/tube back onto an earlier
36
+ * flat produces a cyclic feature graph; the feature tree turns this edge into a
37
+ * SEAM_CUT, and the unfold leaves the flats connected through the spanning tree.
38
+ */
39
+ export interface SeamSpec {
40
+ /** Flat id the seam folds from (an authored flange, or `'root'`/`'face-0'` for the base). */
41
+ parent: string;
42
+ /** Flat id the seam meets (must already be authored; `'root'`/`'face-0'` = base). */
43
+ child: string;
44
+ angleDeg: number;
45
+ rule: BendRule;
46
+ }
47
+ /** Inputs for {@link authorPart}. */
48
+ export interface AuthorSpec {
49
+ thickness: number;
50
+ base: BaseFlatSpec;
51
+ flanges: FlangeSpec[];
52
+ material?: MaterialSpec | undefined;
53
+ /** Optional seams that close a profile into a tube/box (left unfolded). */
54
+ seams?: SeamSpec[] | undefined;
55
+ }
56
+ /**
57
+ * Stable edge reference for flange attachment. The base flat is `face-0`; every
58
+ * flange face is `face-<n+1>` in authoring order. The leading edge of a flat is
59
+ * `edgeIndex 0`. The reference also carries `parentId`/`side`/`offset`/`extent`
60
+ * so the feature tree and recursive unfold can resolve the exact parent edge a
61
+ * flange folds from without reading topology back out of the B-rep.
62
+ */
63
+ export declare function baseEdgeRef(faceIndex: number): EdgeRef;
64
+ /**
65
+ * A flat in the part: the base, or a placed flange face. Each carries the world
66
+ * frame (origin + orthonormal axes) of its top surface so a child flange can be
67
+ * built directly off any of its four edges, at any fold direction.
68
+ */
69
+ export interface FlatFrame {
70
+ id: string;
71
+ /** Near corner of the flat on its −normal (bottom) surface; the flat spans
72
+ * `thickness` along +n. Local `(x, y)` maps to `origin + x·u + y·v`. */
73
+ origin: Vec3;
74
+ /** In-plane direction; the flat spans `[0, uLen]` along it. */
75
+ u: Vec3;
76
+ /** In-plane direction; the flat spans `[0, vLen]` along it. */
77
+ v: Vec3;
78
+ /** Outward face normal of the top surface (n = u × v). */
79
+ n: Vec3;
80
+ uLen: number;
81
+ vLen: number;
82
+ }
83
+ /**
84
+ * Author a sheet-metal part: a base flat plus an arbitrary tree of flanges. Each
85
+ * flange folds off one of the four edges of its parent flat (the base by default,
86
+ * or another flange via `parent`), in the requested direction (up/down), over an
87
+ * optional sub-span of that edge (`offset`/`width`). Returns a {@link SheetMetalPart}
88
+ * carrying the folded 3D solid and the recorded bend feature tree the unfold
89
+ * consumes. All construction stays on the public, OCCT-WASM-safe API.
90
+ */
91
+ export declare function authorPart(spec: AuthorSpec): Result<SheetMetalPart>;
92
+ /**
93
+ * World {@link FlatFrame} of every flat region of an authored part, keyed by region
94
+ * id (`'root'` for the base). Reconstructed from the recorded bend/flange feature
95
+ * tree using the exact same edge/transform/child-frame math {@link authorPart} uses
96
+ * to place the geometry, so a cutout authored in a region's local `(x, y)` lands on
97
+ * the matching folded face. Walks the feature tree in BFS order so a chained
98
+ * flange's parent frame is always known first.
99
+ */
100
+ export declare function worldFrames(part: SheetMetalPart, tree?: FeatureTree): Result<Map<string, FlatFrame>>;
@@ -0,0 +1,58 @@
1
+ import { Result } from 'brepjs';
2
+ import { BendRule, SheetMetalWarning } from './types.js';
3
+ /**
4
+ * One row of a shop bend table: the tabulated value for a single
5
+ * (thickness, innerRadius, bend-angle) operating point. `value` is a bend
6
+ * allowance (`kind: 'allowance'`) or a bend deduction (`kind: 'deduction'`),
7
+ * per the owning {@link BendTable}.
8
+ */
9
+ export interface BendTableRow {
10
+ /** Material thickness the row was measured at. */
11
+ thickness: number;
12
+ /** Inner bend radius the row was measured at. */
13
+ radius: number;
14
+ /** Swept bend angle in degrees (90° = a right-angle bend). */
15
+ angleDeg: number;
16
+ /** Bend allowance or bend deduction, per the table's {@link BendTable.kind}. */
17
+ value: number;
18
+ }
19
+ /**
20
+ * A named shop bend table: empirical bend-allowance or bend-deduction values
21
+ * measured per (thickness, radius, angle). When a {@link BendRule} references a
22
+ * table by id, {@link resolveBendAllowance} interpolates the table instead of
23
+ * applying the K-factor formula, so the developed length matches the shop's
24
+ * actual press-brake results.
25
+ *
26
+ * `kind` selects how a row's `value` is interpreted: an `'allowance'` table
27
+ * tabulates the developed arc length directly; a `'deduction'` table tabulates
28
+ * the bend deduction, which is converted to an allowance on lookup (see
29
+ * {@link resolveBendAllowance} for the OSSB conversion).
30
+ */
31
+ export interface BendTable {
32
+ id: string;
33
+ kind: 'allowance' | 'deduction';
34
+ rows: BendTableRow[];
35
+ }
36
+ /**
37
+ * Register (or replace) a bend table under its id, so a {@link BendRule} with a
38
+ * matching `bendTableRef` resolves against it. Returns the registered table.
39
+ */
40
+ export declare function registerBendTable(table: BendTable): Result<BendTable>;
41
+ /** Look up a registered bend table by id (registers the starter tables on first use). */
42
+ export declare function getBendTable(id: string): BendTable | undefined;
43
+ /**
44
+ * The single source of truth for a bend's developed (neutral-axis) length.
45
+ *
46
+ * Precedence:
47
+ * 1. `rule.bendTableRef` — look up the table and interpolate it (linear in
48
+ * angle, bilinear across thickness × radius), converting a deduction table
49
+ * to an allowance via {@link allowanceFromDeduction}. Outside the table
50
+ * extents the lookup clamps to the nearest breakpoint and reports a
51
+ * `MIN_RADIUS`-class warning through `onWarning` rather than extrapolating.
52
+ * 2. `rule.allowance` — an explicit per-bend override, returned verbatim.
53
+ * 3. The K-factor formula BA = (π/180)·|angle|·(R + K·T).
54
+ *
55
+ * The returned value is in the same units and sense the rest of the package's
56
+ * `developedLength` consumes (a strip width along the developed pattern).
57
+ */
58
+ export declare function resolveBendAllowance(rule: BendRule, angleDeg: number, thickness: number, onWarning?: (warning: SheetMetalWarning) => void): Result<number>;