Changing the nest defaults (Nest Info, Set as default, Edit Plate on an empty sheet) left the editor's trailing empty sheet on the old size and quadrant, so the writer's clamp-preserving empty-sheet rule saved it as a stale extra sheet. PlateManager.ChangePlateDefaults wraps a defaults edit: a trailing empty, cutoff-free sheet that exactly matched the old defaults (and followed their rail with no removed clamps or explicit zones) takes the new defaults; every other empty sheet keeps its configuration and is still written. PM cade6901-5f4a-4503-85bf-0ea681d9ca7f
8.6 KiB
Nest file format and saved cutting state
.nest is a ZIP archive with additive version-2 JSON metadata in nest.json.
Old files remain readable. Older applications ignore the new cutting-state fields;
opening and saving with an older application loses that state.
Job metadata
nest.json carries the workflow fields shown in the nest info dialog:
name, customer, dateCreated, dateLastModified, notes, material,
thickness, plus status ("Quote", "ToBeCut", "HasBeenCut") and madeBy.
Status and made-by are additive: files written before them load as Quote with an
empty maker, and an unrecognized status value likewise falls back to Quote.
Programs and placements
programs/program-Nis drawing N's clean G-code program; optionalprograms/program-N-subscontains its hole sub-programs.- Each serialized plate has a one-based
id. Itspartsarray excludes cut-offs; each placement retainsdrawingId,x,y, androtation(radians). - A placement with
HasManualLeadInsalso writesparts/plate-P/part-K, andparts/plate-P/part-K-subswhen it has hole sub-programs. P is the serialized plate ID; K is the zero-based index in that plate's serialized parts array. Empty plates and cut-offs do not consume these part indices. - The placement's
programfield references that ZIP entry. Its G-code is saved in the already-rotated local part frame, with the placed origin at(x, y). Existing:LEADIN,:LEADOUT, and other layer tags, tab gaps, and G65 calls are retained rather than regenerated by a cutting strategy during load. Hole IDs may be negative: they are identifiers, not validity sentinels. drawingHashprotects against restoring obsolete cutting paths after an externally edited drawing. It is uppercase SHA-256 of UTF-8 text composed of the main text's decimal UTF-16 character count,:, main text, and sub-program text (empty when absent). The hash includes both drawing entries so changing a hole alone invalidates the placed cutting program. Text is read without a BOM; otherwise whitespace and line endings participate in the hash.
The reader constructs and places a clean part first, then installs its saved
program without rotating it again. The drawing reference remains authoritative
for Remove Lead-ins: removing them restores the clean drawing at the saved pose.
Successful restoration marks the part as carrying lead-ins and restores its
leadInsLocked flag. The per-part CuttingParameters reference remains null;
the saved program, not strategy regeneration, determines the cutting geometry.
Missing program references in legacy files load clean and silently, even when
old transient flags were true. A missing or mismatched drawing hash likewise
loads clean silently. A referenced but missing, unparseable, or motionless part
program, or an unresolved/empty hole sub-program, leaves that part clean and
unlocked without discarding the rest of the nest. NestReader.Warnings identifies
the plate, zero-based part index, and entry; File > Open displays these warnings.
The program reader is not a general G-code or geometric safety validator; the
saved cutting geometry is not validated against the drawing.
Plate cutting parameters
Each plate's optional cuttingParameters stores the settings used by Assign
Lead-ins and Place Lead-in. Missing settings stay null, preserving the old default
selection behavior. OpenNest.IO.CuttingParametersSerializer owns the shared
cross-platform DTO mapping; the desktop settings serializer delegates to it so
existing saved settings keep their JSON contract. Settings are independent of
the saved part programs: restoring settings never regenerates those programs.
Clamp zones
Each plate may carry an optional clamps array of fixed rectangular keep-out
regions in plate coordinates: id, x, y, length (X extent) and width
(Y extent, the depth intrusion from the y = 0 operator-side edge for machine
clamps). Zones are exclusion and display data only - never material, quantity,
utilization, cut sequence or CNC output. Files without the key load with no
zones, and an individually malformed entry (blank id, non-positive size) is
dropped while the rest of the nest loads.
plateDefaults.clampRail optionally stores the nest's machine clamp rail:
width (along the edge), depth (into the sheet) and centers (X positions
measured from the plate origin along the origin-side edge). New plates follow
the rail and resolve it for their own size and quadrant; clamps wholly beyond a
sheet are skipped and one still reaching onto it keeps its whole footprint, so
a zone may extend past the sheet edge. The key is omitted
when a nest has no rail, so such files are unchanged; a missing, empty or
malformed rail loads as none. On load a plate follows the rail again only when
its saved clamps are exactly the rail's zones for that sheet; any other saved
zones are kept as written.
The rail's optional removalMinutes is the time to take one clamp off and put
it back; a missing or invalid value loads as five minutes. A plate on which
Auto Nest removed clamps as a last resort lists their rail ids in an optional
removedClamps array (omitted when none were removed); its clamps already
exclude them, and it follows the rail minus those ids. A malformed
removedClamps value reads as none removed (non-string entries are skipped);
the saved clamps load either way.
An empty plate (no parts, no cut-offs) is omitted from the file unless that would lose clamp zones: it is omitted like any other empty plate only when a new plate from the saved defaults would recreate it (same size and quadrant, zones the saved rail recreates), which keeps the editor's trailing empty sheet out of the file while it matches the defaults. Nest-defaults edits move only an untouched trailing empty, cutoff-free sheet to the new size, quadrant, edge and part spacing, re-resolving its rail. It must have exactly matched the old defaults and followed their rail with no removed clamps or explicit zones (or have had no rail and no zones when the defaults had none). Edited sheets, middle empty sheets, and sheets with parts, cut-offs, removed clamps or explicit zones are not changed. An empty plate with other zones, or a rail-following one whose size or quadrant differs from the saved defaults, is still written.
Drawing edits
DrawingProgramSnapshot captures serialized main and hole-program text before
the converter is loaded. After an accepted edit, only parts referencing drawings
whose program text changed are rebuilt (lead-ins, tabs, and locks cleared); their
location and rotation remain unchanged. Reference identity, not editable names,
keys this comparison. The desktop invalidates the affected layout graphics.
Name, quantity, and color edits leave placed programs alone. The properties
editor previously called LayoutPart.Update, a color refresh, not Part.Update;
it now explicitly refreshes only the edited drawing's layout colors.
Verification and limits
The automated tests cover save/reopen/re-save, rotated/manual/locked parts, lead-outs and tab gaps, hole binding, clean removal, stale drawings, damaged entries isolated from other parts, plate settings, and CI Fiber posting before and after reload. Drawing-change decision logic runs on Linux; desktop rendering, dialog values, and clicks require Windows acceptance.
Known separate issue: the cutting strategy currently labels contour cuts
Display. CI Fiber includes them, but GravographIS skips Display. Saving restores
the existing layers; this change does not alter the strategy or either post.
Future hardening: make numeric G-code serialization/parsing culture-invariant
as a coordinated compatibility change; do not change just one side. Program
content deduplication is optional and must not change per-part ownership.
Stock-option prices
The existing plateOptions entries retain width, length and cost; no new .nest
format version is required. Legacy zero cost means unspecified, not a free sheet.
Positive costs are generic per-sheet values in caller-consistent units. Solving
requires all available options to be priced or all to be unspecified.
Desktop and accepted MCP/API jobs retain offered options (API rows with zero available
quantity are excluded because .nest options do not retain inventory). MCP save also preserves
loaded job metadata, plate defaults and salvage settings, and accepted whole-job
requirements are stored on drawings. Options do not persist finite inventory or
associate a historical purchase price with each physical sheet. API quote archives
additionally retain request costs and validated proposal cost summaries; old archives
without summaries load with Costs == null.