Replace single preview PlateView with two stacked previews showing
horizontal and vertical FillLinear results. Each has a label showing
the part count. Apply uses the direction with more parts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Vector-based overloads to SpatialQuery (ray casting, edge distance,
directional gap, perpendicular overlap) and PartGeometry (directional
line filtering) to support pushing parts along any angle, not just
cardinal directions.
Add Compactor.PushBoundingBox for fast coarse positioning using only
bounding box gaps. ActionClone shift+click now uses a two-phase strategy:
BB push first to skip past irregular geometry snags, then geometry push
to settle against actual contours.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- FillExtents.Fill reported progress internally which overwrote the UI's
temporary parts even when a better result (e.g. Pairs with 70 parts)
won the competition. Added final ReportProgress call in FindBestFill
and Fill(groupParts) to ensure the UI always shows the actual winner.
- FillExtents vertical copy distance clamp (Math.Max with pairHeight +
spacing) prevented geometry-aware compaction from ever occurring,
causing visible gaps between rows. Boundaries are already inflated by
halfSpacing so the calculated distance is correct; only fall back to
bounding-box distance on non-positive results.
- PairFiller now sets RemainderPatterns on FillLinear so remainder strips
get pair-based filling instead of only individual parts (+1 part in
tight layouts).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add FileExtension and FileFilter constants to NestFormat and update all
references across Console, MCP, Training, and WinForms projects.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds FillExtents as a fourth nesting phase in both FindBestFill and
Fill(groupParts, Box), running at bestRotation and bestRotation+90°.
Updates Description to reflect the new phase.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace RepeatColumns stub with real implementation: compacts a test column
left against column 1 to derive the copy distance, tiles further columns at
that interval, and clips partial columns to the work area bounds. Adds 4 new
FillExtentsTests covering multi-column fill, rect shapes, non-zero-origin
work areas, and cancellation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace AdjustColumn stub with a convergence loop that distributes the
remaining gap between the topmost part and the work area top edge across
all pairs. TryAdjustPair/TryShiftDirection try shifting part2 up (or down
as fallback) and compact left, rejecting moves that widen the pair.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Size fix (d4222db) changed Size.Width to Y axis and Size.Length to
X axis but only updated DrawPlate/LayoutViewGL. BoundingBox, WorkArea,
rotations, DXF export, and engine code still used the old Width=X
convention, causing the fill engine to get a swapped work area (60x120
instead of 120x60) and parts to fill in the wrong direction.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FlangeShape generates an outer circle with evenly-spaced bolt holes
on a bolt circle pattern. ShapeDefinition.LoadFromJson<T>() provides
generic JSON loading for any shape — no separate preset classes needed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Size.Parse and ToString now use WxL format (width first) matching the
natural convention. Fixed the Plate(w,l) constructor which was swapping
args when creating Size. Fixed PlateView.DrawPlate and DrawControl
ZoomToArea which had width/length mapped to the wrong screen axes.
Simplified Console --size parsing to use Size.TryParse instead of manual
split with confusing PlateHeight/PlateWidth fields. Added Command-Line
Interface section to README documenting all console options.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Relocated add and remove plate buttons from the Plates tab toolstrip
to the right side of the plate header, keeping plate actions together.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Plate nav buttons (first/prev/next/last) now sit in a centered header
bar above the PlateView with a plate info label on the left, making
navigation more accessible without reaching up to the main toolbar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use pole-of-inaccessibility (polylabel) to place part labels at the
visual center of shapes instead of the first path vertex. Labels now
stay correctly positioned regardless of part rotation or shape.
Also adds project README and MIT license.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add null safety in CreateDrawing helper, default Name from class name,
clarify diameter-vs-radius conventions, octagon width definition,
arc direction for rounded rectangles, and MCP parameter mapping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Defines a parametric shape library with abstract ShapeDefinition base
class and concrete subclasses for common CNC shapes (Tier 1+2).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a toolbar button that opens a dockable remnant viewer showing
tiered remnants (priority, size, area, location) with color-coded
overlay rendering on the plate view.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Longest edges produce the flattest tiling rows and should be tried
first. Also deduplicates angles before sorting.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FillLinear now accepts optional RemainderPatterns that are tried in
leftover strips after the main grid fill, improving packing density
when pair patterns fit the narrow residual space.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 tasks across 3 chunks: extract AccumulatingProgress, ShrinkFiller,
AngleCandidateBuilder, PairFiller, RemnantFiller, then rewire both
engines and NestEngineBase.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add plateNumber parameter to PairFiller.Fill signature.
Document strip direction to ShrinkAxis mapping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract shared algorithms from DefaultNestEngine and StripNestEngine
into focused helper classes: PairFiller, AngleCandidateBuilder,
ShrinkFiller, RemnantFiller, AccumulatingProgress.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Compute the label point from the base drawing's unrotated program
and rotate the cached point instead of recomputing on each rotation.
Prevents label jitter caused by arc discretization differences.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace PathPoints[0] label positioning with polylabel algorithm
to place part ID labels at the visual center of each part. Labels
are now centered and readable even in dense nests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two bugs caused the remnant finder to miss valid empty regions:
1. RemoveDominated used an 80% overlap-area threshold that incorrectly
removed L-shaped remnants. A tall strip to one side would "dominate"
wide strips above/below it even though they represent different usable
space. Replaced with geometric containment check — only remove a box
if it's fully inside a larger one.
2. FindTieredRemnants split remnants at the obstacle envelope boundary,
and both pieces could fall below minDimension even though the original
remnant passed the filter (e.g., 6.6" remnant split into 5.35" + 1.25"
with minDim=5.38"). Added fallback to keep the original unsplit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address review feedback: add holes parameter for parts with cutouts,
cache label point in program-local coords to survive zoom/pan, add
fallback for degenerate geometry, use ShapeProfile for outer contour
identification.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add plate-free Push overload and CompactIndividual method that pushes
each part individually against all others as obstacles. Disabled in
StripNestEngine pending investigation — compaction opens irregular gaps
that the remnant finder scatters parts into.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parts created by fill operations share a Program instance via
CloneAtOffset. RotateSelectedParts called Part.Rotate on each,
compounding Program.Rotate on the shared object (1x, 2x, 3x…)
and producing inconsistent bounding boxes. Fix tracks rotated
programs with a HashSet, rotates locations around the group center,
and anchors the bounding box corner to prevent drift.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Skip remnants that are too small to fit any remaining part, avoiding
wasted fill attempts. Recalculated each iteration as quantities deplete.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remainder items were being filled into the full remnant box without
compaction. Added ShrinkFill helper that fills then shrinks the box
horizontally and vertically while maintaining the same part count.
This matches the strip item's shrink behavior and produces tighter
layouts that leave more usable space for subsequent items.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The iterative remnant fill was mutating shared NestItem.Quantity objects,
causing the second TryOrientation call (left) to see depleted quantities
from the first call (bottom). Use a local dictionary instead so both
orientations start with the full quantities.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the single-pass guillotine split approach with RemnantFinder-based
iteration. After each fill, re-discover all free rectangles and try all
remaining items again until no more progress is made. This fills gaps that
were previously left empty after the initial strip + remainder layout.
Also change ActiveWorkArea border color from orange to red.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Active remnant shown as dashed orange rectangle on PlateView during
iterative fill workflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extracts remnant detection from the nesting engine into a standalone
RemnantFinder class using edge projection algorithm, enabling an
iterative nest-area -> get-remnants workflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>