mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-20 05:01:36 -04:00
The writer omitted an empty rail sheet when its size, quadrant and zones matched the defaults, ignoring spacing, so a sheet left at the old part or edge spacing after a defaults change (configured stock under C17) was dropped on save. The comparison now includes edge and part spacing. PM 455f6763-f0aa-40da-b9ad-11de4b2ea95b
146 lines
8.8 KiB
Markdown
146 lines
8.8 KiB
Markdown
# 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-N` is drawing N's clean G-code program; optional
|
|
`programs/program-N-subs` contains its hole sub-programs.
|
|
- Each serialized plate has a one-based `id`. Its `parts` array excludes cut-offs;
|
|
each placement retains `drawingId`, `x`, `y`, and `rotation` (radians).
|
|
- A placement with `HasManualLeadIns` also writes `parts/plate-P/part-K`, and
|
|
`parts/plate-P/part-K-subs` when 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 `program` field 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.
|
|
- `drawingHash` protects 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. A plate that follows a rail other than the nest's default
|
|
saves it in its own optional `clampRail` (same shape), so its removal state and
|
|
time survive a reload; plates following the default rail omit it.
|
|
|
|
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, quadrant, edge
|
|
and part spacing, 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, quadrant or
|
|
spacing 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`.
|