Extension lines now walk in from the dimension line until they come 6px from
the drawing's outline, as on the CAD Converter, passing measured points that
are off the outline (a rounded rectangle's sharp corners). The flange bolt
circle is a leader landing on the dotted circle from outside, between holes,
instead of a linear dimension whose extension lines crossed the flange.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Shape Library's hole diameter leader now crosses its hole through the
center to the far edge, arrows pointing out onto both edges, wherever the
label is dragged. The hole pattern dimension measures a dotted bolt circle
through the hole centers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add Delete Plate to the plate row menu beside Duplicate Plate, enabled
when Remove Selected Plate is. Drop the Plates tab's add-plate button
and the Plate menu's Add and Remove items: the list's trailing empty
plate already provides new plates, and removal stays on the tab.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dimension-editing rewrite replaced the invalid-input test with
InvalidEntryStaysOpenInRedAndKeepsTheLastShape, so the Windows
acceptance gate found zero cases for the old name and failed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first fill of a new drawing was blamed on the best-fit pair search, but on the
reported nest that search takes ~3.4 s. The time goes to FillLinear.FillGrid, run
thousands of times by the Pairs, Row/Column and Linear strategies: pattern copy-distance
slides and the grid overlap check. Every change keeps the output bit for bit (part
poses compared on the benchmark nest; best-fit results unchanged).
- ConvexDecomposition.Triangulate: unlink clipped vertices from a circular list instead
of List.RemoveAt, and remember why a vertex failed the ear test (same neighbors, same
blocking vertex still present) instead of retesting it after every ear. Compared
bitwise against a frozen pre-change copy, including the blocker-clipped case.
- Collision: skip triangles whose box misses the other triangulation's union box (exact:
min/max and monotone subtraction), reuse each triangle's open vertices, and let the
overlap-only path stop at its first region when there are no holes. Check still
returns every region.
- SpatialQuery.ExtractEntityVertices presizes its set; FillLinear extracts each entity
list's vertices once per copy-distance search rather than once per pair.
- StripeFiller converges its stripe angles and tiles its grids in parallel. Dedup claims,
cached remnant fills, ranking and progress stay in candidate order, and grids are tiled
only for configurations a claim can still win (GridDedup.Contains), so results and
reports do not depend on the thread count.
- LinearFillStrategy fills its angles in parallel through
FillHelpers.BestOverAnglesInParallel; angle results, ranking and progress stay in order.
Benchmark (one drawing, 60x120, 0.25 spacing, cleared plate, interleaved runs):
FillItem Lattice 291/317 s -> 164/153 s, 132 parts both; PairFiller alone 48 s -> 38-42 s.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dragging a dimension's label moves the dimension: a linear one slides
out from the drawing (never onto it) and its label along the line, an
inline one slides its label, a leader's label goes anywhere and the
leader follows. A click without dragging still opens the editor.
The preview zooms with the wheel, pans with the middle button and fits
again with F or a middle double-click. Once zoomed or panned by hand,
parameter edits keep the view; a new shape or configuration fits it and
puts dragged dimensions back. An open editor follows its label.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Shape Library no longer has a side panel of inputs. Each length is a
dimension line or leader on the preview; click its label to type a new
value (Enter applies, Esc cancels, Tab moves to the next dimension), as
Edit Clamps does on the plate. Invalid values keep the editor open in
red and the last good shape on screen. Settings with no place on the
drawing (sides, pipe size, clearance, blind) are clickable notes along
the bottom. The flange hole leader carries the count beside the size,
such as "Ø7/8" x 8 holes".
Shapes declare their dimensions through ShapeDefinition.GetDimensions;
lengths show as fractions when exact to 1/64 (Fraction.Format). Edit
Clamps' inline text box moves to a shared DimensionBox.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pair filler topped its grid off with single parts at 0 or 90 degrees,
so a narrow strip beside the grid held half of what it could: on a 60x120
sheet of N26-29X parts the plate fill gave 132, while deleting the last
column and filling the strip gave 136. The strip is now also laid out the
way the Row strategy lays one, rows of best-fit pairs turned so whole pairs
span it, and that layout replaces the singles when it places more.
Each strip size is laid out once per fill and skipped when the singles
already fill it by area. On the benchmark nest the plate fill now reaches
136 with the hand-made layout's rotations, about 17% slower (156 s vs
133 s with best fits cached). The pinned L-shape fills gain a part (52 to
53). The auto-nest problem-nest corpus keeps its baseline.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copying a layout meant recreating the plate and copying its parts by hand.
Ctrl+drag a row in the Plates list drops a copy at that slot; the row's
right-click menu has Duplicate Plate, which inserts the copy after it.
Plate.CopyLayout copies the sheet (size, outline, spacing, quadrant, grain,
clamps, support bed), the parts with their programs and lead-in state,
common-line groups and cut-off definitions, regenerated in their places in
the sequence, as a save and reload would. The copy is one sheet with no
stock item codes, since those name particular physical sheets. The desktop
gives it its own cutting parameters and records it as one undo step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The empty new-plate header read only "New plate (empty)", so the sheet
size of the plate about to be nested was hidden until parts were added.
FormatHeader now appends the size (and quantity above one) there too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The corpus is meant to hold every nest that ever caused a problem, tagged with
what it guards, but it could only plan cutting paths. Nests tagged
`checks: auto-nest` now run the Default engine on their demand and fail when the
layout is invalid, leaves parts unplaced, or uses more sheets than their
`auto-nest: N sheets` line; planner runs skip them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Irregular engine grows each sheet from one side, so parts that fit only
when the outer ones hug opposite edges never met: ten one-off brackets
(four tapered 112-inch bars, four gussets, two small plates) stacked three bars
on one sheet and took three 60 x 120 sheets where two hold them.
After the search, a sheet-reduction pass splits a complete single-stock plan
over one sheet fewer and packs each sheet edge first: large parts to the
corners (flush, most outline on the edges, thinnest across the sheet), small
parts into the gaps last, and one key part into the pocket between. Clamped
sides move in past the keep-outs so edge parts line up on one straight edge.
When no sampled orientation fits the key, ContactFit turns it by its contacts
(each overlap a linear constraint on dx, dy and rotation) instead of sampling
more angles; the exact no-fit free region then confirms the angle, so spacing
and validation are unchanged. That job now nests on two sheets, the middle bar
at 4.4 degrees; the repository benchmark jobs are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
File > Drawing Library opened the window unowned, so clicking the main
window buried it. It is now owned by the main window: still modeless,
so nests stay editable, but it always stays on top of it. It keeps its
taskbar button and minimize, which nesting during a release relies on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Make Nests bound each tab it nested to its saved record but left the
tab's history off its save point, so the tab showed " *" and closing it
asked to save. Yes uploaded a second revision, and a release that had
already looked up that draft (the panel asks the operator to save and
close an open draft) then merged with If-Match on the old revision: the
server refused it, that group failed, no nest after it was saved and the
release was not recorded. End() then closed the leftover tabs through
the unsaved prompt, whose Yes the release lockout refused.
- Binding a released tab marks its save point (EditNestForm.MarkSaved).
- Make Nests re-reads each merge target and merges at the revision now on
the server; one saved while the release runs is still refused.
- End() closes the tabs it did not save without the prompt
(CloseDiscardingChanges), after taking them off the release list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Layout label counted parts off the plate or inside the edge spacing, but
nothing showed which part or where, so the user had to hunt for it. Each edge
finding now gets a canvas marker like the overlap and spacing ones: a red
crosshair where a part leaves the sheet and an orange ring at the gap to the
edge, in every visible display mode, with hover text that carries the finding's
message. Markers are retained across edits like the other overlay findings
(only a changed part's marker drops), and a sheet size, edge spacing or outline
change clears them. Validate Nest already located these findings through
PostVerificationFinding.Location.
"Near edge" / "inside the edge spacing" read as a spacing rule rather than a
placement problem, so the label, overlay messages, PlateEdgeReview findings
and the Validate Nest category now say the part is outside the work area. Off
the plate keeps its wording. The PostVerificationKind.EdgeSpacing name stays.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The status bar's "Layout: OK" ran its own snapshot check of overlaps and
part spacing, separate from Validate Nest and posting, so a part dragged
off the sheet still read OK.
The plate capture now owns the sheet frame (sheet box, work area,
outline), and the worker runs PlateEdgeReview's material check on it:
"N off plate" and "N near edge" join the label. Snapshots hold no leads,
so leads past the sheet stay a Validate Nest/posting finding. The
geometry stamp now includes edge spacing and outline so changing them
marks the result out of date. Bare-part captures (Plan Cutting) have no
frame and are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copy and Cut paste through ActionClone, which added each clone to the plate
but never recorded the groups the sources were in, so a pasted common-line
pair came out as separate parts held to the part spacing. ActionClone now
reads the copied parts' groups when it starts (before Cut removes the
sources and their groups) and joins each paste's clones the same way, at the
source group's kerf.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moving one member of a common-line group used to break the group, so a drag
or nudge silently undid a join. Selecting a member, by click or window, now
selects its whole group, so drag, nudge, push, rotate and align carry the
joined parts together and keep their shared spans.
Right-clicking a part now offers Join Common Line and Remove Common Line,
running the Plate > Arrange commands on the selection. A right-click on a part
keeps its selection (or selects it with its group) instead of clearing it, so
the menu has something to act on; a right-click on empty plate still clears.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the filter on and every drawing nested, the Drawings tab was a blank
list with no hint why. It now shows a note that turns the filter off when
clicked. The filter is never turned off on its own: it is the user's
choice and would stay off when new drawings arrive.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Six-decimal incremental PEP programs round arc centers, so an arc's end
tangent misses its neighbor's by about gap / radius (1.6e-5 rad on the
offset 5/32" fillet in the reported nest). Two parts resting one spacing
apart then gave the slide contact a Minkowski cone a hair wider than a
half-plane, which the classifier read as the whole plane: every direction
blocked, so the top part could not be pushed sideways along the part below.
SlideContact now reads a cone up to TangentSlack (1e-4 rad) past a
half-plane as a noisy half-plane and widens its boundary and concave-ray
comparisons by the excess, so near-tangential slides read as tangential.
A direction admitted that way can enter material by at most travel x
excess at that contact, and every other contact is still classified on its
own; wider cones remain real overlap and block. Raising JointTolerance was
not needed for this case and is left at 1e-6.
Whole-job benchmarks (synthetic nests plus the PEP job at 3 and 60 parts,
--parallel 1) are identical before and after for every engine.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A part placed exactly one part spacing from its neighbor touches the
neighbor's offset contour. PEP drawings round arc centers to six decimals,
so their offset contours carry hairline kinks and joint gaps where the parts
touch; the slide kernel then classifies that contact as blocking in every
direction, and Push moved the part 0 even straight away from the neighbor.
An obstacle whose bounds end at or behind the moving part's trailing side
can only fall further behind, so Push and PushBoundingBox now skip it
(within Tolerance.Epsilon) instead of only when strictly behind.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clicking and window selection paired the cut-off program's codes as
rapid/cut at even positions. A head-locked far-edge segment carries lock
comments (and, cut from the far edge, a rapid return) between its cuts,
so no pair matched and the line could not be selected, though it drew.
CutOff.CutStrokes now walks the motions once for the renderer, click
hit test, window selection and the Sheet Cut-Off preview, so what is
selectable matches what is drawn.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FormStartPosition.CenterParent is not applied to modeless windows, so the
viewer opened wherever Windows placed it. Center it on its owner in OnLoad,
shrunk to fit and kept inside that screen's working area.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Slice 3 of common-line cutting. On costly plate (N26-295: 3/16 RA310S at about
$2,500 a sheet) pairing parts one kerf apart fits the part the spacing cannot:
the last plate's 38 parts fit on one 48x120 with Auto Nest only with pairs.
- Drawing Properties gains "Allow common line" (Drawing.AllowCommonLine, off by
default because customer edge-quality needs vary). The nest's CommonLineUsage
(Off / When it adds parts / Whenever available) is set in Auto Nest and seeded
from Tools > Nest Defaults; both persist (nest.json, defaults.json).
- NestPipeline runs the ordinary solve, then, with a level on, trials where
eligible parts are offered as kerf-gap pair compounds. Placed pairs expand into
parts plus explicit NestJobCommonLine groups, are validated again, and
CommonLineRanking keeps a trial only by the level: count first, then sheets;
"when it adds parts" keeps the plain layout on a tie, "whenever" also takes a
shorter cut or less material, never at the cost of a part. Engines, FillScore
and their comparers are unchanged; Off asks the engine exactly what it did.
- NestLayoutCheck exempts members only through a sheet's explicit group list and
only when the job allows common lines; materializing and committing create
Plate.CommonLines.
- Server nesting writes common-line jobs as version 3 and replays the recorded
trial answers, so the desktop binds the same groups.
- Fill Area honors the level through a PlateFillService overload.
- The benchmark gains --common-lines <level> --kerf <k>.
Benchmark (synthetic nests + N26-295, --parallel 1): with no flag and with
--common-lines off every engine matches the base commit; with a level on no
layout becomes invalid and three runs save a sheet at equal nested area.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
N26-295's PT42 pairs saved spacing in slice 1 but every shared edge was
still cut twice, costing a pass per edge and risking a freed part
tipping under the head on the second pass.
Plan Cutting now cuts a plate's common lines once unless the plate is set
to cut them twice. Each group is cut member by member, owner before
partner (a captured dependency that search and replay enforce, so a kept
order cutting the partner first is a constraint conflict): the member's
holes, then the shared cuts it owns as open CommonLine centerline cuts
entered through the notch on the span's axis, then its remainder pieces,
each ramped in from the kerf the shared cut opened. Capture marks the
shared spans as tabs on the owned clean copy, so replay's contour
accounting proves each perimeter is cut exactly once; a lead that fits
at neither end refuses as UnsupportedGeometry naming the span, never
shortened. Material still comes from the drawing, so utilization,
quantity and overlap results do not change. Members are never
support-tabbed; locked or excluded members and broken groups refuse.
The CI Fiber post writes shared cuts in the cut-off form with a lead-in
and no G41/G42, and remainders in the contour form on their perimeter's
compensation side, named by a remainder comment. Cincinnati CL (whose
PreApplied mode offsets nothing) and Gravograph refuse such nests, as do
the desktop and console for any post without ICommonLinePostProcessor;
nothing falls back to a silent double cut. Plate > Arrange > Cut Common
Lines Twice keeps slice 1's behavior, persists with the plate and makes
an open plan stale.
Pre-post review now checks each span is cut once, on its centerline, by
the member cut first, and the rapid check treats a finished member's
remainders as an obstacle. Compensation start in void and cancel in
kerf are unconfirmed on the CI FIBER 4020; release waits on a 3/16
stainless coupon trial.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The job it acts on is shown as Stopping and then Stopped, and the rest of the
app talks about stopping server jobs, so the button now says Stop Job too.
Expensive alloy jobs (N26-295, 310 stainless) could not fit their last
PT42 at full part spacing; the plate was squeezed to 0.2 spacing with a
part 0.14 from the edge. Parts whose straight edges face each other one
kerf apart are cut on the same centerline, saving the spacing along each
shared edge.
Plate.CommonLines holds groups of parts and the kerf they were joined
at. Shared spans are derived from the placed clean perimeters, never
stored, so a moved member breaks its group instead of leaving a stale
span. Plate > Arrange > Join Common Line slides the selected parts
together at the plate's kerf; Remove Common Line ungroups them. The
plate draws shared spans as a dashed centerline.
Both spacing checks hold group members to the kerf instead of the part
spacing, and a new pre-post Common lines check reports broken groups, a
changed kerf, and leads that run into a partner. Groups persist as part
positions in an optional commonLines array that older readers ignore.
This first slice still cuts every shared edge twice; single-pass cutting
through Plan Cutting and the posts comes next.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ring-shaped parts (a plate with a large center hole) were left unlabeled:
the material at their pole is too narrow for the ID, and the label was
never tried anywhere else. Group IDs were likewise only ever placed beside
the dotted outline, so a cramped cluster lost its ID or straddled the
sheet edge.
A part whose pole spot is too tight now takes the roomiest clear spot
within its own extents, such as its empty hole. A group ID takes the
roomiest spot inside its outline or beside it; with none clear it may
cover the group's own parts near the center, since operators read part
detail from the parts list. No ID sits across the sheet outline.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EditNestForm's debounce timer is a System.Timers.Timer whose Elapsed ran
on a pool thread, checked drawingListBox1.IsHandleCreated, then called
drawingListBox1.Invoke. Invoke reads Handle, so a handle destroyed
between the check and the call was re-created on the pool thread (the
cross-thread check is off outside the debugger) while the UI thread was
disposing the window, which threw "Dispose() cannot be called while
doing CreateHandle()". The timer starts enabled at 50 ms, so short
WinForms tests such as LedgerCodeRecheckTests.NoLedgerOrNoCodes_ChecksNothing
hit it intermittently on CI.
Elapsed now posts to the window's UI synchronization context and the
refresh checks IsDisposed there; the timer is disposed with the form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each dotted group outline was padded 1 pt beyond its parts. At overview scale
a 0.25 in part spacing is only ~1.3 pt, so the outlines of two adjacent
clusters (e.g. the six small bars and the two holed plates on N26-27Y plate 1)
overlapped, and the later group - with its ID - was silently dropped.
Pad outlines by under half the part spacing instead, so neighboring clusters
both get their outline and ID.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Database-mode Open dialog now allows multi-row selection and a Get
Materials command (button and context menu) that downloads the chosen
nests, or every nest the current search matches across all pages, and
lists the sheets they use by material, grade, thickness and size with
the quantity and the nests using each. Needed to order stock for a whole
job's worth of nests at once instead of opening them one by one.
Material, grade and thickness come from each nest's server record;
sizes and duplicates from its plates, skipping plates with no parts.
Copy All and Save CSV export the list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Validate Nest and the pre-post review checked overlaps and part-to-part
spacing but never the sheet itself, so a part dragged past the plate edge,
a lead-in piercing off the sheet, or a part inside the edge spacing could
post without a warning. Only Auto Nest's own layout check held parts to
the work area.
PlateEdgeReview adds two finding kinds:
- OffPlate: any cut, lead or scribe motion past the sheet, or clean
material outside an outlined sheet or over one of its obstacles.
- EdgeSpacing: clean material (leads excluded) outside the work area, or
closer than the largest edge spacing to an outline or obstacle - the
bound Auto Nest's layout check applies, with SpacingSlack, so layouts it
accepted stay clear.
Cut-off parts are exempt. Routing-replay test fixtures sit at the sheet
origin with leads hanging off it; their route assertions now ignore the
sheet-bound kinds, and the post-contract fixture moves onto the sheet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tabs suit thin plate, but on anything thicker than 0.25 in the parts
are too hard to break out of the sheet, and the Cutting Parameters
dialog was one global set for every job. Its settings now live on the
nest's machine thickness: leads on the existing Outside/Inside Cuts
tabs, and lead-in angle rounding, tabs and pierce on a new Tabs &
Pierce tab (ThicknessConfig.Cutting). In Database mode every
workstation gets the same settings through the shared machine.
The dialog and the Place Lead-in panel say what they edit, and save
back to that thickness (MachineCuttingDefaults.WriteTo, converted to
the machine's units). A thickness with no Tabs & Pierce of its own, or
a nest the machine has no thickness for, keeps this PC's settings as
before. If the machine can't be saved (server offline, a conflict),
the edit is kept on this PC for that job and the user is told.
Machine Configuration can copy one thickness's Tabs & Pierce to
thinner or thicker ones, so the 0.25 in rule takes a few clicks.
An older desktop saving a shared machine would silently erase these
settings, since it doesn't know them. Machine configuration classes
now keep unknown fields, and the server refuses a machine save that
leaves out a field the stored machine has a value for, telling the
user to update OpenNest.
The Plan Cutting status line now reports tabs from SupportTabs; since
"Tab every part" was retired it always said off.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nobody tabs every part, but tabbing by size is useful even on a plate
that has a support grid. Cutting Settings > Tabs now offers "Only tab
parts the support grid can't hold level" or "Tab parts by size"
(CuttingParameters.TabBySize), which ignores the bed and tabs each part
whose minimum-area bounding rectangle's narrow side is in the range.
The support grid choice still falls back to that range on plates with
no bed, as before.
The range fields become TabSizeMinWidth/TabSizeMaxWidth; their JSON
keys stay noBedTabMinWidth/noBedTabMaxWidth so saved settings and nests
read unchanged. TabsEnabled stays as the per-contour flag Plan Cutting,
Place Lead-in and drawing pins set on the parts they tab.
Saved user settings with "Tab every part" read as tabs by size from 0
to 9999, which tabs the same parts. Only the user's settings migrate;
a plate's recorded parameters and pins replay as planned.
Plan Cutting, Place Lead-in and the pre-post review all go through
SupportTabSettings, so they agree on which parts need a tab. A
size-tabbed part is held by any clear tab, so it is never a rapid
obstacle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
.NET 8 defaults Process.Start to UseShellExecute=false, so handing it the
temp DXF tried to run the file as an executable and threw an unhandled
Win32Exception that took the app down. Open it through the shell so the
.dxf association is used, report write/launch failures in a message box,
and replace characters a file name cannot hold in the nest name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A tail separator that landed on a front-edge clamp was skipped outright, so
a plate lost its whole remnant (19.5 in on a 48 x 120 sheet with the part
ending at a rail clamp) over a 1.5-in clamp. The separator now steps to the
clamp's far edge plus its clearance, repeating for any clamp it then meets,
and reports ClampMovedTailSeparator. The kept tail is shorter by that
distance and must still meet the minimum tail length; a separator pushed off
the sheet still reports NoSafeTailSeparator.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The release smoke instantiated the multi-phase fill engine through its
old Fill alias, so it never proved the current name. It now creates
Lattice and checks that Fill still resolves to Lattice, as it does for
the Opus55NestingEngine rename.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The multi-phase fill engine and strategy is named Lattice; the docs still
called it Fill in several places. Generic fill passes stay lowercase and
the renamed-engines alias table is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The multi-phase fill strategy has been named Lattice since the engine
rename, but the console's --engine help and the MCP tool descriptions
still offered it as Fill. Fill keeps working as an alias.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Interlocked rows, such as staggered triangles, cannot slide straight past
their neighbors, so capping the step with a push left them unable to
pattern down. The calculated step now moves the full distance like a fixed
nudge, even off the plate or onto a part; the layout check reports either.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Set Offset Increment gains a "Calculated distance" option. With it on, the
arrow keys move the selection by its own size plus the part spacing,
measured on its geometry like a fill's copy distance, so it lands tight
without a push back. The move stops early at an edge, clamp or part, and a
clone preview steps clear of the copy just placed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>