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>
The forward bounding-box gap check (gap < 0) incorrectly skipped obstacles
for irregular shapes like SULLYS-003 whose narrow handle extends past an
adjacent part's BB edge while the wide body still needs contact detection.
Replaced with a reverse-direction gap check that only skips obstacles the
moving part has entirely cleared. Also fixed edge distance check to prevent
overshooting the work area boundary when already at the limit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moving BasePart locations via Compactor.Push bypassed LayoutPart.Offset
which sets IsDirty. Without it, graphics paths were stale until a zoom
triggered a full rebuild.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>