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>
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>
ComputeRemainderWithin only returned the larger of two possible free
rectangles, permanently losing usable area on the other axis after each
remainder item was placed. Replace the single shrinking box with a list
of free rectangles using guillotine cuts so both sub-areas remain
available for subsequent items.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The sequencer returns parts ordered from exit point inward. Reverse
so part 1 is nearest the origin and cutting works outward.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Advanced sequencer with default 0.25 MinDistanceBetweenRowsColumns
puts every part in its own row, degenerating to a Y-sort. Switch to
LeastCode (nearest-neighbor + 2-opt) for visible results.
Also replace AddRange(linq) with foreach+Add to avoid ObservableList
AddRange re-enumerating a deferred LINQ query for event firing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace old SequenceByNearest with PartSequencerFactory using default
SequenceParameters (Advanced method with serpentine row grouping).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Renamed OpenNest.Engine.Tests → OpenNest.Tests (directory, .csproj,
namespaces in all .cs files). Added OpenNest.IO project reference.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
16 tasks covering test infrastructure, core model changes, part sequencing
(6 strategies + factory), rapid planning (2 strategies), and the PlateProcessor
orchestrator. TDD approach with xUnit tests for each component.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix coordinate transforms (translate-only, no rotation), make orchestrator
non-destructive (ProcessedPart holds result instead of mutating Part.Program),
use readonly structs consistently, add factory mapping and known limitations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Visual Studio re-serialized the designer — removes `this.` prefixes,
modernizes event handler syntax, trims trailing whitespace in resx.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
StripNestEngine only overrode Fill(NestItem), so ActionClone.Fill
and Pack operations fell through to the empty base class defaults.
Now all virtual methods delegate to DefaultNestEngine.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wrap IProgress with AccumulatingProgress so remnant fills prepend
previously placed strip parts to each report. The UI now shows the
full picture (red + purple) instead of replacing strip parts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Nest() now deducts placed counts from input NestItem.Quantity so the
UI loop doesn't create extra plates. All inner DefaultNestEngine.Fill
calls forward the IProgress parameter for live progress updates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The auto-nest code paths (MainForm, MCP, Console) now call
engine.Nest(items, progress, token) instead of manually orchestrating
sequential fill+pack. The default implementation in NestEngineBase
does sequential FillExact+PackArea. StripNestEngine overrides with
its strip strategy. This makes the engine dropdown actually work.
Also consolidates ComputeRemainderWithin into NestEngineBase,
removing duplicates from MainForm and StripNestEngine.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When Strip is selected in the engine dropdown, RunAutoNest_Click
calls StripNestEngine.Nest() instead of sequential FillExact+Pack.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Runs strip and sequential strategies in competition, picks the
denser result. Reports scores for both strategies in output.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New NestEngineBase subclass that dedicates a tight strip to the
largest-area drawing and fills the remnant with remaining drawings.
Tries both bottom and left orientations, uses a shrink loop to find
the tightest strip, and picks the denser result.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Document NestEngineBase hierarchy, NestEngineRegistry, and plugin
loading in the Engine section.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
StripNester becomes StripNestEngine extending NestEngineBase.
Uses DefaultNestEngine internally via composition.
Registered in NestEngineRegistry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pluggable engine architecture with NestEngineBase, DefaultNestEngine,
registry with plugin loading, and global engine switching.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>