← back to pin list

Nesting rules — Jordan's rulings (2026-08-10/12)

kerfmaster pin list · Big capabilities

rulingA decision by Aristide or Jordan. True because it was decided; it can be superseded, but it cannot be stale.

Content last changed 2026-08-18 — computed from the item itself, not typed.

Jordan answered the open nesting questions on 2026-08-10. These settle the flags in item 3; the engine itself remains downstream of the definition phase.

  1. The customer's own layout is only a starting point. Customers often send a DXF already laid out as a nest; we may re-nest it for better yield.
  2. Multi-part files: every disjoint outer contour is its own part; everything inside it (holes, islands, bridges) travels with it.
  3. Part-to-part spacing is a material-table value. Interim rule until the tables fill in: gap = material thickness, never less than 0.200". Belongs in materials.json with provenance decided (Jordan 2026-08-10) when wired.
  4. Rotation & grain: whether grain direction matters is defined per job by the customer (a UI flag — intent, not built). Grain defined → rotations locked to 180° only; grain not defined → rotation free (any angle).
  5. Common-line cutting is ruled OUT — "a big no-no in precision laser cutting." Never share one cut line between two parts.
  6. Nesting inside large holes/cutouts is acceptable, even preferred to save material. (Cut-order safety applies: interior parts finish before the surrounding boundary does.)
  7. Sheet size is operator-defined per job — not a fixed 4×8. Packing strategy: fill Y, consume minimum X, so the unused remainder can be sheared off as one clean remnant. Example: 60×120 sheet, parts held to 24" of X at full Y → shear at 24", save a 60×96 sheet. Yield is measured including the value of that clean remnant, not just parts-per-sheet. This is a BIAS, not a strict rule (Jordan, 2026-08-10): favour the shearable remnant, but it may lose to a materially better nest.
  8. Priority order when objectives fight: material is king, tipping potential is queen, time is jack. Jordan expects sequencing to fall out of the existing cut-order safety rules.
  9. The beat-target vs Metacam: its nest quality is good; its weakness is performance — 32-bit only, enormous rendering times, hangs on jobs with many little parts. We must match its nests and beat it on speed and robustness at scale.
  10. Part-to-sheet-edge gap = the part-to-part gap (thickness, floor 0.200") — same number, one rule.
  11. One nest MAY mix jobs. Intended workflow (interface intent, not built): the operator has files from multiple jobs open and asks for a combined nest — grouped by material × thickness as always.

Still open: sheet-tab shop numbers — the thickness threshold where tabs stop being needed, and width/count per material × thickness below it (item 3a).

Record — 2026-08-10: first applied, on Jordan's instruction

Jordan (TL-1016 kit): multi-part files become per-part files, then re-nest better than the customer's layout; grain not specified → rotation free. Built split_parts.py + build_split_page.py: heal → contours grouped into parts (outer owns what it contains) → one DXF per part → min-area rotation → row nest. Honest v1: consumes minimum of ONE axis so the remnant shears clean (the bias above), no common-line, but it is a packer, not an optimizer. Assumptions pending operator values: sheet 48×96 (ruling says operator-defined per job), clearance 0.375" (ruling says thickness with 0.200" floor — TL-1016's title block carries no material or thickness, so a conservative gap was used and stated). Both are parameters, re-run is minutes.

2026-08-11, Jordan (rulings on the TL-1016 kit):

  1. Sheet orientation: the 96" dimension runs in X, not Y.
  2. Slat bias (a bias, not a rule): favor a part's LONGER dimension running in X so it bridges more bed slats and resists tipping.
  3. Minimum part-to-part distance 0.200" for these files — and nest tighter than shelf boxes: flip similar parts 180° and slide them together (his 'you can do much better'). Measured minimum on the placed outlines is printed on every split page; the packer pads its slide by 5 thou so outline sampling can never eat the ruled distance.
  4. Open profiles close at a 0.020" tolerance, debris is eliminated. Root cause measured first (his question): the customer's AutoCAD profiles come from a 3D scanner; every spline arrives open, every ellipse is a partial arc, and fragments OVERLAP instead of meeting — every open end sat 5–11 thou from other geometry, several traces overran their own start by inches. So closure is trim + duplicate-drop at 0.020, not gap-bridging (bridging would double-cut the overlaps). One boundary in -82 is genuinely incomplete in the source (~5" of edge never drawn) and ships open, reported.

2026-08-12, Jordan (on his MetaCam nest example):

  1. Y utilization first is now IMPLEMENTED, not just a bias on record. His note: 'prioritize maxing Y utilization first as we discussed yesterday' — ruling 7 above, which the 8-11 row packer did not yet honour (it filled X per row, remnant across the top). The packer now runs transposed: a row becomes a column, each column fills the full sheet height before X advances, and the remnant is one full-height strip at far X, recovered with a single shear cut. Measured on the TL kit: -82 leaves a 47.5" strip of the 96; -81 sheet 2 leaves 82.5".
  2. Lead-ins live in the nest, and facing flats hosting one sit at lead + standoff into the gap on top of outlines never closer than 0.200. Both follow the MATERIAL when the split is given one (split_parts.py <src> <label> [w] [h] [material] sets LEAD = STAND = tables.lead_len, thickness with the 0.150 floor); with no material both sit at the 0.150 floor. Learned on the 3/16 tube fixture (2026-08-13): a nest packed at the floor put 22 pierces under the 0.187 standoff, worst 0.029 clear — re-nested with the material key, every neighbour-facing pierce cleared it. split_parts.plan_lead: start centred on the part's longest flat (the hypotenuse — start-point rule 2026-07-30), pierce on the scrap side, planned BEFORE nesting so the packer reserves the room via a second sliding profile; audit_clearance now also MEASURES pierce/lead-to-neighbour on the placed sheets (0.1551 / 0.1585 on the kit). Leads ride red in the sheet DXF and SVG; the MetaCam profile files stay geometry-only — MetaCam applies its own leads, and an open lead line would read there as an open contour. Hole leads are post-stage; they do not change the nest.

2026-08-12 later, Jordan (circled the pockets): 'large gaps in nest'. Root cause: the packer took parts in fixed tallest-first order and slid each to first contact — it never chose WHICH part meshes with the profile it faces, so mismatched wavy edges strand ~1" enclosed pockets, and the small parts that could plug them all queued to the end. Fix, measured: parts still go biggest-first in 1" size classes, but within a class the packer places whichever part+flip slides tightest against the live profile; after every placement, parts under 3" may 'free-tuck' anywhere that does not push the local profile out at all. Remnant strip: -82 47.5"→50.2", -81 sheet 2 82.5"→86.6"; clearances still measured 0.205/0.2006 outline, 0.1558/0.1554 pierce.

2026-08-12, Jordan (guard.pdf + red-circled snip): rotate for fitment. Packer now searches rotation variants, not just 0/180: big parts try fine tilts (±7.5°, ±15° either side of 0/180) so slightly-mismatched scanner hypotenuses can lie together; parts under 3" rotate freely in 30° steps (grain unspecified → rotation free, ruling 4). Placement stores a true rotation+translation; manifest column is now rot_deg. Measured on the TL kit: 54 of 77 / 63 of 93 parts placed rotated, clearances hold (0.2051/0.2006 outline, 0.1558/0.1556 pierce) — but remnant moved only 50.15→50.18 and 86.56→86.67: X consumption is quantized by whole columns of near-equal-width trapezoids, and the remaining pockets are enclosed by shape differences among 77 unique scanner outlines. Rotation search will pay properly on repeated-part jobs like the guard nest (3 shapes × 47 copies), where a part rotates INTO its sibling's notch.

2026-08-12, Aristide (bottom-row snip): column seeds now choose their flip by measurement, not list order. The first part of each column slides against the flat sheet edge, where 0° and 180° score identically — the tie fell to variant list order, a coin toss on which wavy edge faces the next part. Aristide spotted the two lost tosses (columns 2 and 4 on -82); measured cost 1.07" and 1.28" of pair height. Fix: one-step lookahead — each tied seed variant is placed hypothetically and the seed whose best next placement slides tightest wins. On -82 all five bottom-row seeds now flip to the meshing orientation (58 of 77 parts rotated; -81: 75 of 93). Clearances hold (0.205/0.2009 outline, 0.156/0.1557 pierce). Honest remnant numbers: 50.18→50.17 and [1.94, 86.67]→[1.69, 86.63] — the per-pair savings strand as slack at each column's top rather than freeing a whole column on this kit; the pattern's real payoff stays with repeated-part jobs.

2026-08-12, Jordan + Aristide (heal-only overlay request): the -82 'missing ~5" edge' was OUR defect, not the file's. SolidWorks shows the plate closed; we and MetaCam showed one open boundary. Instrumented replay of close_scan_fragments on -82 proved the edge exists in the source (a zigzag notch between (34.82, 78.90) and (38.58, 75.78), drawn as overlapping fragments plus elliptical-arc duplicates of lines): the duplicate-drop removed 3 fragment copies — each justified at the time because the trace's own overrun still covered the span — then the self-overlap trim cut that overrun (9 prims spanning the notch) because its tail touched the chain's early body, assuming everything before the foot was overlap. Two locally-correct steps jointly deleted every copy of a real edge. The still-open report was honest but self-inflicted. Fix APPLIED (2026-08-12, coverage-gated trim in close_scan_fragments): a trim only discards overrun prims still covered within tol by surviving geometry, walked from the overlap outward; the first uncovered prim and everything past it survives as a fragment for re-stitch (stat overrun_prims_kept). Re-run of -82: 97 sole-copy prims recovered, among them a COMPLETE part outline (funnel part at (41.7,74.0), 83 prims) the old trim deleted entirely — with it and its neighbour recognised, five 0.51" squares turn out to be their HOLES, so the honest count is 74 parts + 353 holes, not 77 + 348; the customer-count check needs re-doing against the drawing. Still open and reported (never silently closed): one funnel part ships as two open chains (gaps 4.88") whose two seams are multi-copy scanner zigzag scraps that close into 0.2" micro-loops, and one outer with a 0.068" seam gap beyond the 0.020 stitch tol. Heal-only DXF for overlay: viewer/tl101682_healonly.dxf (no dedupe, no trim, no stitch — 4166 healed prims, everything the file contains).

NEXT STEP TAKEN (2026-08-12, same day): coverage-gated SEAM BRIDGE — an open end may join another open end by a straight span only when every 0.01" sample of the span lies within tol of geometry the file contains (it re-draws scanner back-and-forth scraps lying on the boundary line; a chord over a real opening fails the gate); capped 0.35", each bridge reported with its length. Dedupe widened to closed chains when every sample is covered by OTHER geometry at true distance (tol+sample slack), one-at-a-time so a twin always survives. NEST GATE: a group whose outer is still open is never placed — held out to _heldout.dxf and listed. -82 result: 3 bridges (0.068/0.276/0.276), 0 open contours (first time), funnel whole at 8.68x6.67 with 11 holes, 73 parts + 349 holes, 21 dup drops — every dropped chain measured within 0.010" of surviving geometry; the two 12-hole parts were counting micro-scrap hairs as holes, real holes untouched. FIRST CONTACT WITH THE RAILS (2026-08-13, TL-1016-61, build 026): the nest gate held out a 6.34x10.10 part whose outer was open 0.710" — the missing edge shipped in the customer file as a doubled 0.006" hairline sliver whose ends coincide exactly with the open ends. SEAM_MAX raised 0.35 to 1.0: the coverage gate is the safety (every 0.01" sample of the span must lie on drawn geometry), the cap only refuses wild joins. Re-run: one reported 0.710 bridge, sliver consumed as duplicate, 48 parts + 239 holes, 0 open, 0 held out, debris 0.

2026-08-13, Aristide (ruling) — combined-kit nest groupings confirmed: “nest for efficiency as directed before.” Kit parts from one job mix on shared sheets, grouped by material × thickness, packed for best yield — no per-part-number sheet separation. This closes the grouping question that was parked awaiting a partner call.

2026-08-13, Aristide (ruling, same day — scope clarified): “give me all separate orders, nested per ORDER.” Efficiency nesting applies WITHIN an order, never across orders: each order (TL-1016-61 … -70) keeps its own sheet(s) and its own program, 1:1 order-to-G-code. No cross-order pooling of parts, even on matching material × thickness. The broader same-day reading (“kit parts from one job mix on shared sheets”) is superseded by this clarification.

The objective, ruled (Jordan, 2026-08-18 — empty_space.png)

Minimum X usage is the packing objective, because the remnant is the full-height strip beyond the nest's max X — every inch of X saved is sellable material. Jordan, on the -93 sheet: 'we had plenty of space to pack parts without creating another row in X… I highlighted the area on this sheet that could even be occupied by the wider parts from the bottom right. This would give us less usage of the sheet measured in X, so the remainder of the 60x120 sheet would be greater and therefore more cost efficient.' Rules that fall out of it: (1) an internal void is FREE space — fill it before any part extends the X frontier; (2) a part's distance to the sheet's Y edge may run under the 0.200 part-to-part floor at Jordan's discretion (his -86 ring at 0.161 physical stands — he acknowledged the number and kept it, because avoiding an extra X row outranks it); (3) applied on -93 2026-08-18: the two widest right-column parts (p019, p026) moved into the internal void, X extent 23.273→22.308, remnant 96.73→97.69. The packer does not yet DO this itself — void-filling is manual-move territory today; making the packer X-extent-driven is open.