@chestnutlabs/toolpath-core 0.15.0 → 0.17.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.
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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"}
package/dist/builder.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { IR_SCHEMA_VERSION } from './ir.js';
2
2
  import { computeSegmentBounds } from './bounds.js';
3
+ import { classifyModelBounds } from './classify.js';
3
4
  import { buildSourceIndex } from './source-index.js';
4
5
  /**
5
6
  * Accumulates segments and produces a canonical {@link ToolpathIR}.
@@ -119,7 +120,11 @@ export class ToolpathIRBuilder {
119
120
  const origin = this.originOffset ?? { x: 0, y: 0, z: 0 };
120
121
  const layers = deriveLayers(segments, origin.z);
121
122
  const { bounds, boundsWithTravel, objectBounds } = computeSegmentBounds(segments, origin);
123
+ const { modelBounds, classification } = classifyModelBounds(segments, origin);
122
124
  const sourceIndex = buildSourceIndex(segments.srcByte, count);
125
+ // Honest at build time from whatever channels exist; the dialect runner refreshes both after
126
+ // annotation settles the object/feature channels (DD-026 D5, lifecycle §5).
127
+ this.capabilities.nonModelClassification = classification;
123
128
  const header = {
124
129
  irSchemaVersion: IR_SCHEMA_VERSION,
125
130
  parserVersion: this.opts.parserVersion ?? 'unknown',
@@ -148,6 +153,7 @@ export class ToolpathIRBuilder {
148
153
  bounds,
149
154
  boundsWithTravel,
150
155
  objectBounds,
156
+ modelBounds,
151
157
  sourceIndex
152
158
  };
153
159
  }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Non-model geometry classification (DD-026 D4/D5/D7).
3
+ *
4
+ * A pure, O(segments) pass that decides which extrusion is the **printed model** and which is slicer
5
+ * housekeeping (skirt, brim, raft, support, prime/wipe tower, purge, wipe), then reports the model's
6
+ * bounding box (`modelBounds`) and a confidence (`nonModelClassification`). It reads only the settled
7
+ * `kind` / `feature` / `object` channels — no geometry, no source, no allocation beyond one bounds
8
+ * accumulator — so it is safe to run at parse time and again after dialect annotation settles the
9
+ * channels (`gcode-dialects` runner finalize), where it becomes authoritative.
10
+ *
11
+ * Honesty model (DD-026 D7): membership is the only `known`-grade signal because it labels each
12
+ * segment's identity explicitly; role-only exclusion is `inferred` (an unmarked prime line could still
13
+ * be counted as model); nothing excludable at all is `unavailable` and yields empty bounds — never a
14
+ * guess. This deliberately under-claims a bracket-only file as `inferred` rather than `known`, the
15
+ * safe direction: without per-segment membership we cannot rule out other unmarked housekeeping.
16
+ */
17
+ import { type Confidence, type ToolpathBounds, type ToolpathSegments, type Vec3 } from './ir.js';
18
+ /**
19
+ * Feature roles excluded from the model (DD-026 D4 rule 4). Towers/raft/purge and the perimeter-adjacent
20
+ * skirt/brim/support are housekeeping; the generic `Custom` role stays in-frame (an unmapped token is
21
+ * kept as model rather than wrongly excluded — the safe direction, RR-007 §7).
22
+ */
23
+ export declare const HOUSEKEEPING_ROLES: ReadonlySet<number>;
24
+ /** True when the feature-role index is one the model-bounds classifier excludes (DD-026 D4). */
25
+ export declare function isHousekeepingRole(role: number): boolean;
26
+ export interface ModelClassification {
27
+ /** Bounds of the classified model extrusion; empty (Infinity/-Infinity) when unknowable. */
28
+ modelBounds: ToolpathBounds;
29
+ /** Confidence that `modelBounds` reflects the printed model (DD-026 D7). */
30
+ classification: Confidence;
31
+ }
32
+ /**
33
+ * Classify extrusion into model vs. housekeeping and return the model bounds + confidence (DD-026 D4).
34
+ *
35
+ * Precedence per extrusion segment:
36
+ * 1. explicit housekeeping role / wipe → excluded (beats membership: a tower inside an open object
37
+ * bracket is still a tower, RR-007 §8 rule 1);
38
+ * 2. with a membership channel, `object == 0` → excluded (not a member — catches an unmarked prime);
39
+ * 3. with a membership channel, `object != 0` → model;
40
+ * 4. without a membership channel, anything not excluded by rule 1 → model (role fallback).
41
+ *
42
+ * Confidence: `known` when a membership channel drove it; `inferred` when only role exclusion applied;
43
+ * `unavailable` (empty bounds) when there was neither membership nor any excludable role — the file is
44
+ * genuinely unclassifiable and framing must fall back + disclose.
45
+ */
46
+ export declare function classifyModelBounds(seg: ToolpathSegments, origin: Vec3): ModelClassification;
47
+ //# sourceMappingURL=classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../src/classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAyB,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAGxH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAQjD,CAAC;AAEH,gGAAgG;AAChG,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAOD,MAAM,WAAW,mBAAmB;IAClC,4FAA4F;IAC5F,WAAW,EAAE,cAAc,CAAC;IAC5B,4EAA4E;IAC5E,cAAc,EAAE,UAAU,CAAC;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,GAAG,mBAAmB,CAsC5F"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Non-model geometry classification (DD-026 D4/D5/D7).
3
+ *
4
+ * A pure, O(segments) pass that decides which extrusion is the **printed model** and which is slicer
5
+ * housekeeping (skirt, brim, raft, support, prime/wipe tower, purge, wipe), then reports the model's
6
+ * bounding box (`modelBounds`) and a confidence (`nonModelClassification`). It reads only the settled
7
+ * `kind` / `feature` / `object` channels — no geometry, no source, no allocation beyond one bounds
8
+ * accumulator — so it is safe to run at parse time and again after dialect annotation settles the
9
+ * channels (`gcode-dialects` runner finalize), where it becomes authoritative.
10
+ *
11
+ * Honesty model (DD-026 D7): membership is the only `known`-grade signal because it labels each
12
+ * segment's identity explicitly; role-only exclusion is `inferred` (an unmarked prime line could still
13
+ * be counted as model); nothing excludable at all is `unavailable` and yields empty bounds — never a
14
+ * guess. This deliberately under-claims a bracket-only file as `inferred` rather than `known`, the
15
+ * safe direction: without per-segment membership we cannot rule out other unmarked housekeeping.
16
+ */
17
+ import { FeatureRole, MoveKind } from './ir.js';
18
+ import { emptyBounds } from './bounds.js';
19
+ /**
20
+ * Feature roles excluded from the model (DD-026 D4 rule 4). Towers/raft/purge and the perimeter-adjacent
21
+ * skirt/brim/support are housekeeping; the generic `Custom` role stays in-frame (an unmapped token is
22
+ * kept as model rather than wrongly excluded — the safe direction, RR-007 §7).
23
+ */
24
+ export const HOUSEKEEPING_ROLES = new Set([
25
+ FeatureRole.Skirt,
26
+ FeatureRole.Brim,
27
+ FeatureRole.Support,
28
+ FeatureRole.Raft,
29
+ FeatureRole.PrimeTower,
30
+ FeatureRole.WipeTower,
31
+ FeatureRole.Purge
32
+ ]);
33
+ /** True when the feature-role index is one the model-bounds classifier excludes (DD-026 D4). */
34
+ export function isHousekeepingRole(role) {
35
+ return HOUSEKEEPING_ROLES.has(role);
36
+ }
37
+ /** An extrusion segment is housekeeping if it carries an excluded role or is a wipe move. */
38
+ function isHousekeepingSegment(seg, i) {
39
+ return isHousekeepingRole(seg.feature[i]) || (seg.kind[i] & MoveKind.Wipe) !== 0;
40
+ }
41
+ /**
42
+ * Classify extrusion into model vs. housekeeping and return the model bounds + confidence (DD-026 D4).
43
+ *
44
+ * Precedence per extrusion segment:
45
+ * 1. explicit housekeeping role / wipe → excluded (beats membership: a tower inside an open object
46
+ * bracket is still a tower, RR-007 §8 rule 1);
47
+ * 2. with a membership channel, `object == 0` → excluded (not a member — catches an unmarked prime);
48
+ * 3. with a membership channel, `object != 0` → model;
49
+ * 4. without a membership channel, anything not excluded by rule 1 → model (role fallback).
50
+ *
51
+ * Confidence: `known` when a membership channel drove it; `inferred` when only role exclusion applied;
52
+ * `unavailable` (empty bounds) when there was neither membership nor any excludable role — the file is
53
+ * genuinely unclassifiable and framing must fall back + disclose.
54
+ */
55
+ export function classifyModelBounds(seg, origin) {
56
+ let hasMembership = false;
57
+ let hasExcludableRole = false;
58
+ for (let i = 0; i < seg.count; i++) {
59
+ if ((seg.kind[i] & MoveKind.Extrude) === 0)
60
+ continue;
61
+ if (seg.object[i] !== 0)
62
+ hasMembership = true;
63
+ if (isHousekeepingSegment(seg, i))
64
+ hasExcludableRole = true;
65
+ }
66
+ const classification = hasMembership ? 'known' : hasExcludableRole ? 'inferred' : 'unavailable';
67
+ const modelBounds = emptyBounds();
68
+ if (classification === 'unavailable')
69
+ return { modelBounds, classification };
70
+ const b = modelBounds;
71
+ for (let i = 0; i < seg.count; i++) {
72
+ if ((seg.kind[i] & MoveKind.Extrude) === 0)
73
+ continue;
74
+ if (isHousekeepingSegment(seg, i))
75
+ continue; // rule 1
76
+ if (hasMembership && seg.object[i] === 0)
77
+ continue; // rule 2 (rule 3 keeps members through)
78
+ const sx = origin.x + seg.x0[i];
79
+ const sy = origin.y + seg.y0[i];
80
+ const sz = origin.z + seg.z0[i];
81
+ const ex = origin.x + seg.x1[i];
82
+ const ey = origin.y + seg.y1[i];
83
+ const ez = origin.z + seg.z1[i];
84
+ if (sx < b.min.x)
85
+ b.min.x = sx;
86
+ if (sy < b.min.y)
87
+ b.min.y = sy;
88
+ if (sz < b.min.z)
89
+ b.min.z = sz;
90
+ if (sx > b.max.x)
91
+ b.max.x = sx;
92
+ if (sy > b.max.y)
93
+ b.max.y = sy;
94
+ if (sz > b.max.z)
95
+ b.max.z = sz;
96
+ if (ex < b.min.x)
97
+ b.min.x = ex;
98
+ if (ey < b.min.y)
99
+ b.min.y = ey;
100
+ if (ez < b.min.z)
101
+ b.min.z = ez;
102
+ if (ex > b.max.x)
103
+ b.max.x = ex;
104
+ if (ey > b.max.y)
105
+ b.max.y = ey;
106
+ if (ez > b.max.z)
107
+ b.max.z = ez;
108
+ }
109
+ return { modelBounds, classification };
110
+ }
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  export * from './ir.js';
9
9
  export * from './builder.js';
10
10
  export * from './bounds.js';
11
+ export * from './classify.js';
11
12
  export * from './source-index.js';
12
13
  export * from './metadata.js';
13
14
  export * from './progress.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@
8
8
  export * from './ir.js';
9
9
  export * from './builder.js';
10
10
  export * from './bounds.js';
11
+ export * from './classify.js';
11
12
  export * from './source-index.js';
12
13
  export * from './metadata.js';
13
14
  export * from './progress.js';
package/dist/ir.d.ts CHANGED
@@ -53,6 +53,14 @@ export declare const FeatureRole: {
53
53
  readonly Bridge: 8;
54
54
  readonly Travel: 9;
55
55
  readonly Custom: 10;
56
+ /** Prime tower / prime pillar — the purge column built up alongside the model. */
57
+ readonly PrimeTower: 11;
58
+ /** Wipe tower — the multi-material wipe/prime structure (PrusaSlicer/ideaMaker vocabulary). */
59
+ readonly WipeTower: 12;
60
+ /** Raft — the sacrificial base under the model (distinct from `Brim`). */
61
+ readonly Raft: 13;
62
+ /** Purge / flush material (e.g. Bambu `FLUSH_START/END`) — extruded but not part of the model. */
63
+ readonly Purge: 14;
56
64
  };
57
65
  export type FeatureRoleName = keyof typeof FeatureRole;
58
66
  export interface Warning {
@@ -202,6 +210,18 @@ export interface ToolpathIR {
202
210
  * "frame the printed object, not the skirt" (#306/#6); a consumer checks it is finite before use.
203
211
  */
204
212
  objectBounds: ToolpathBounds;
213
+ /**
214
+ * Bounds over the **printed model** — extrusion classified as model by the non-model classifier
215
+ * (DD-026 D4/D5): object membership when present, otherwise all extrusion minus explicit housekeeping
216
+ * roles (skirt, brim, raft, support, prime/wipe tower, purge) and wipe moves. Strictly additive to
217
+ * `objectBounds` (whose object-channel contract is unchanged): `modelBounds` also excludes housekeeping
218
+ * that carries an object label (e.g. a Bambu prime tower emitted inside an open object bracket) and
219
+ * works for label-less files that still mark their housekeeping. Empty (Infinity/-Infinity) when the
220
+ * model is unknowable (no membership and nothing excludable — an honest "cannot classify", never a
221
+ * guess). Framing precedence is `modelBounds → objectBounds → bounds`; see
222
+ * `header.capabilities.nonModelClassification` (`known` | `inferred` | `unavailable`) for confidence.
223
+ */
224
+ modelBounds: ToolpathBounds;
205
225
  sourceIndex: SourceIndex;
206
226
  }
207
227
  //# sourceMappingURL=ir.d.ts.map
package/dist/ir.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../src/ir.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../src/ir.ts"],"names":[],"mappings":"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"}
package/dist/ir.js CHANGED
@@ -36,5 +36,15 @@ export const FeatureRole = {
36
36
  Brim: 7,
37
37
  Bridge: 8,
38
38
  Travel: 9,
39
- Custom: 10
39
+ Custom: 10,
40
+ // Non-model housekeeping roles (DD-026 D2/D3a). First-class so the model-bounds classifier can
41
+ // exclude them by role rather than folding them into the generic `Custom` (which stays in-frame).
42
+ /** Prime tower / prime pillar — the purge column built up alongside the model. */
43
+ PrimeTower: 11,
44
+ /** Wipe tower — the multi-material wipe/prime structure (PrusaSlicer/ideaMaker vocabulary). */
45
+ WipeTower: 12,
46
+ /** Raft — the sacrificial base under the model (distinct from `Brim`). */
47
+ Raft: 13,
48
+ /** Purge / flush material (e.g. Bambu `FLUSH_START/END`) — extruded but not part of the model. */
49
+ Purge: 14
40
50
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chestnutlabs/toolpath-core",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "Neutral ToolpathIR and capability model for the Chestnut Labs G-code Preview toolpath stack.",
5
5
  "keywords": [
6
6
  "gcode",