You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Let the operator set where the hold-down magnets actually are, and have the generated
toolpath route around them — not just warn about them.
Motivation
#9 covers recommending and visualising magnet positions, but closes with an explicit scope
limit:
Magnets are preview/advisory only — they do not affect generated plot paths.
That is the part that matters in practice. The operator does not place magnets where the app
suggests — the sheet, the tape and the previous job decide that — so the useful direction is
the reverse: tell the app where the magnets went, and let it keep the carriage off them.
Nothing in the pipeline is obstacle-aware today. Travel between strokes is a single straight G1 from the end of one stroke to the start of the next
(src/plot/gcode.ts:86):
orderPolylines (src/plot/gcode.ts:26) picks that next stroke purely
by nearest distance, so on an A0 bed a travel leg can cross the full sheet — straight over a
magnet. The pen or knife carriage then strikes it, which at travel feed drags the sheet, loses
the work origin (no limit switches, $22=0 — nothing recovers a lost origin) and ruins the job.
Proposal
Magnets become real geometry in the plot pipeline, not an overlay.
Set positions: click to place a magnet marker on the canvas at a paper-mm position;
drag to move, delete to remove. Each magnet has a radius (its physical size plus a safety
margin) — one global default in settings, overridable per magnet. Persisted with the
session, and on the gateway (Persist app settings on the gateway (shared across clients) #14) since the magnets outlive a browser tab.
Worth considering: a jog-to-set flow like the registration wizard's — jog the carriage
over each magnet and press Set, which records the magnet exactly where the machine
can reach it rather than where the canvas says it is.
Route travel around them — a pure src/plot/ function, avoid.ts: given a travel
segment and a set of circular keep-out zones, return a short detour polyline that clears
them (tangent-based detour around each intersected circle is enough for circles this
sparse; no general path planner needed). generateGcode emits the detour as pen-up G1
moves instead of the single straight leg.
Refuse to cut through one: if cut/draw geometry — not travel — falls inside a magnet
zone, no routing can fix it. Block the plot with a clear warning naming the overlap, since
this is the case that breaks the machine rather than the drawing.
Feed the same zones into stroke ordering, so the nearest-stroke choice prefers a next
stroke it can reach without a detour. Nice-to-have; correct routing comes first.
Acceptance criteria
Operator can add, move, remove and size magnet markers; positions persist across reload.
Travel moves that would cross a magnet zone are re-routed clear of it, and the detour is
visible in the preview.
Geometry (not travel) overlapping a magnet zone blocks the plot with a warning that says
which magnet and which stroke.
The avoidance transform is pure and unit-tested in src/plot/__tests__/ — segment
clear of a zone is untouched, segment through a zone detours, chord grazing the edge,
overlapping zones, start or end point inside a zone.
Plot-time estimate accounts for the detours (estimatePlotTime already measures whatever
G-code it is given, so this should follow for free — confirm).
Hardware-verified: a job whose travel crosses a magnet completes without the carriage
touching it (leave unchecked until the operator confirms on the machine — see AGENTS.md).
Relationship
Extends #9 past its "advisory only" note — #9 can stay as the recommend/visualise overlay and
this issue is the routing behaviour on top of it, or #9 folds into this one at triage. The
jog-to-set flow reuses the registration wizard (v1.2.0). Magnet size/margin settings belong on
the Settings page (#57), shared state on #14. Part of epic #10.
Summary
Let the operator set where the hold-down magnets actually are, and have the generated
toolpath route around them — not just warn about them.
Motivation
#9 covers recommending and visualising magnet positions, but closes with an explicit scope
limit:
That is the part that matters in practice. The operator does not place magnets where the app
suggests — the sheet, the tape and the previous job decide that — so the useful direction is
the reverse: tell the app where the magnets went, and let it keep the carriage off them.
Nothing in the pipeline is obstacle-aware today. Travel between strokes is a single straight
G1from the end of one stroke to the start of the next(src/plot/gcode.ts:86):
orderPolylines(src/plot/gcode.ts:26) picks that next stroke purelyby nearest distance, so on an A0 bed a travel leg can cross the full sheet — straight over a
magnet. The pen or knife carriage then strikes it, which at travel feed drags the sheet, loses
the work origin (no limit switches,
$22=0— nothing recovers a lost origin) and ruins the job.Proposal
Magnets become real geometry in the plot pipeline, not an overlay.
drag to move, delete to remove. Each magnet has a radius (its physical size plus a safety
margin) — one global default in settings, overridable per magnet. Persisted with the
session, and on the gateway (Persist app settings on the gateway (shared across clients) #14) since the magnets outlive a browser tab.
over each magnet and press Set, which records the magnet exactly where the machine
can reach it rather than where the canvas says it is.
src/plot/function,avoid.ts: given a travelsegment and a set of circular keep-out zones, return a short detour polyline that clears
them (tangent-based detour around each intersected circle is enough for circles this
sparse; no general path planner needed).
generateGcodeemits the detour as pen-upG1moves instead of the single straight leg.
zone, no routing can fix it. Block the plot with a clear warning naming the overlap, since
this is the case that breaks the machine rather than the drawing.
stroke it can reach without a detour. Nice-to-have; correct routing comes first.
Acceptance criteria
visible in the preview.
which magnet and which stroke.
src/plot/__tests__/— segmentclear of a zone is untouched, segment through a zone detours, chord grazing the edge,
overlapping zones, start or end point inside a zone.
estimatePlotTimealready measures whateverG-code it is given, so this should follow for free — confirm).
touching it (leave unchecked until the operator confirms on the machine — see AGENTS.md).
Relationship
Extends #9 past its "advisory only" note — #9 can stay as the recommend/visualise overlay and
this issue is the routing behaviour on top of it, or #9 folds into this one at triage. The
jog-to-set flow reuses the registration wizard (v1.2.0). Magnet size/margin settings belong on
the Settings page (#57), shared state on #14. Part of epic #10.