Commit Graph
100 Commits
Author SHA1 Message Date
ajandClaude Opus 4.6 b112f70f6a feat: add LeadOut hierarchy (5 classes)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:12:09 -04:00
ajandClaude Sonnet 4.6 f17db1d2f9 feat: add LeadIn hierarchy (7 classes)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 23:07:31 -04:00
ajandClaude Opus 4.6 9b3cf10222 docs: add cutting strategy implementation plan
20 tasks across 5 chunks: LeadIn hierarchy, LeadOut hierarchy,
Tab hierarchy, configuration classes, and ContourCuttingStrategy
orchestrator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:56:52 -04:00
ajandClaude Opus 4.6 e14382f2f3 docs: update cutting strategy spec with review fixes
- Rename Angle properties to ApproachAngle (avoid shadowing Math.Angle)
- Arc rotation from contour winding, not hardcoded CW
- Add winding parameter to LeadIn/LeadOut Generate methods
- Add exit point derivation from Plate quadrant
- Add contour re-indexing section (split/reorder at closest point)
- Add ContourType.cs and AssignmentParameters.cs to file structure
- Clarify normal direction convention
- Note SequenceMethod value 6 intentionally skipped (PEP numbering)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:48:17 -04:00
ajandClaude Opus 4.6 cb30c20eb9 docs: add cutting strategy design spec
Lead-in, lead-out, and tab class hierarchy for CNC cutting
approach/exit geometry, using ShapeProfile + ClosestPointTo
for contour sequencing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:43:05 -04:00
ajandClaude Opus 4.6 e4e1d9b5a3 refactor: rename DefinedShape to ShapeProfile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:19:49 -04:00
ajandClaude Opus 4.6 0c395421cd chore: add .claude/ to .gitignore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:02:54 -04:00
ajandClaude Opus 4.6 612b540d9d refactor: rename Size.Height to Size.Length across codebase
"Length" is more natural than "height" for flat plate materials.
Renames the field on OpenNest.Geometry.Size, Box.Height property,
and all references across 38 files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:01:40 -04:00
ajandClaude Opus 4.6 7e0edd112a refactor: use 'length' instead of 'height' in nest JSON format
Rename SizeDto.Height to SizeDto.Length so the serialized JSON
uses "width"/"length" which is more natural for plate materials.
The core Size struct still uses Height internally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 21:50:53 -04:00
ajandClaude Opus 4.6 c2534ef08b feat: replace XML nest file format with JSON (v2)
Replace three separate XML metadata files (info, drawing-info,
plate-info) and per-plate G-code placement files with a single
nest.json inside the ZIP archive. Programs remain as G-code text
under a programs/ folder.

This eliminates ~400 lines of hand-written XML read/write code
and fragile ID-based dictionary linking. Now uses System.Text.Json
with DTO records for clean serialization. Also adds Priority and
Constraints fields to drawing serialization (previously omitted).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:44:43 -04:00
ajandClaude Opus 4.6 ad50751250 feat: add OpenNest.Console project (renamed from TestHarness)
Console app for running the nesting engine from the command line.
Supports plate size/spacing overrides, quantity limits, overlap
checking with exit codes, and benchmark-friendly flags (--no-save,
--no-log). The MCP test_engine tool shells out to this project.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:43:02 -04:00
ajandClaude Opus 4.6 78ee65d946 fix: resolve grid overlap bug and parallelize fill loops
The push algorithm's copy distance formula (bboxDim - slideDistance)
produced distances smaller than the part width when inflated boundary
arc vertices interacted spuriously, causing ~0.05 unit overlaps between
all adjacent grid parts.

Two fixes applied:
- Clamp ComputeCopyDistance to bboxDim + PartSpacing minimum
- Use circumscribed polygons (R/cos(halfStep)) for PartBoundary arc
  discretization so chord segments never cut inside the true arc,
  eliminating the ChordTolerance offset workaround

Also parallelized three sequential fill loops using Parallel.ForEach:
- FindBestFill angle sweep (up to 38 angles x 2 directions)
- FillPattern angle sweep for group/pair fills
- FillRemainingStrip rotation loop

Added diagnostic logging to HasOverlaps, FindCopyDistance, and
FillRecursive for debugging fill issues.

Test result: 45 parts @ 79.6% -> 47 parts @ 83.1%, zero overlaps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:36:48 -04:00
ajandClaude Opus 4.6 0e3bf3ccaa feat: try fewer rows in FillRecursive when remainder strip yields more parts
When the greedy maximum-row tiling leaves a thin remainder, tries removing
the last row and re-filling the larger strip. Picks whichever total is
higher. Fixes cases where e.g. 4 rows + 11 remainder = 47 beats 5 rows = 45.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:19:42 -04:00
ajandClaude Opus 4.6 f3662465cf feat: try cardinal rotations in FillRemainingStrip for better strip fills
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:12:07 -04:00
ajandClaude Opus 4.6 4d250e3990 feat: use FillScore for fill result comparisons in NestEngine
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:11:38 -04:00
ajandClaude Opus 4.6 a5b7049ecc feat: add FillScore struct with lexicographic comparison
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:10:09 -04:00
ajandClaude Opus 4.6 add88bd410 docs: add FillScore design spec and implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:03:21 -04:00
ajandClaude Opus 4.6 b55aa7ab42 fix: correct GPU overlap detection coordinate system mismatch
The GPU pair evaluator reported false-positive overlaps for all
candidates because the bitmap coordinate system didn't account for
Part.CreateAtOrigin's Location offset. When rotation produced negative
coordinates, CreateAtOrigin sets Location = -bbox.Location (non-zero),
but the offset formula assumed Location was always (0,0).

Two fixes:
- Rasterize bitmaps from Part.CreateAtOrigin directly (new FromPart
  method) instead of separately rotating polygons and computing bbox,
  eliminating any Polygon.Rotate vs Program.Rotate mismatch
- Correct offset formula to include the Location shift:
  (Part2Offset - partB.Location) instead of raw Part2Offset

Also optimized post-kernel bounding computation: pre-compute vertices
once per rotation group and process results with Parallel.For, matching
the CPU evaluator's concurrency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 07:00:21 -04:00
ajandClaude Opus 4.6 079a44052c perf: pre-allocate tile list capacity and remove redundant bbox walks
Pre-size TilePattern result list from estimated copy count to avoid
resizing. Remove redundant Program.BoundingBox() call and UpdateBounds()
in MakeSeedPattern — the Part's BoundingBox is already correct.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 23:13:22 -04:00
ajandClaude Opus 4.6 94850795cf perf: replace O(p²) startOffset loop with O(p) pass in FindPatternCopyDistance
max(aUpper_i - bLower_j) across all pairs simplifies to
max(aUpper) - min(bLower), computed in a single pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 23:10:44 -04:00
ajandClaude Opus 4.6 53759c5877 perf: eliminate Program.Clone calls from copy-distance computations
FindCopyDistance and FindPatternCopyDistance were cloning entire Parts
(including deep Program copies) just to get offset locations for
GetLines. Compute offset locations directly instead. Also skip the
Pattern wrapper in TilePattern — clone parts directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 23:02:59 -04:00
ajandClaude Opus 4.6 8ad01bb7f8 perf: pre-compute directional edges in PartBoundary constructor
RotationDirection and direction filtering were recomputed on every
GetLines call. Pre-compute edges per PushDirection once in the
constructor so GetLines only translates cached edges.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:59:06 -04:00
ajandClaude Opus 4.6 23b5358352 perf: add CloneAtOffset to skip re-rotation and bbox walk on part clones
Part.Clone() re-clones from the drawing's unrotated program, re-rotates,
and walks all CNC codes twice for bounding box — 4 O(c) passes per clone.
CloneAtOffset clones from the already-rotated program and computes the
bounding box arithmetically, reducing to 1 O(c) pass per clone.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:53:02 -04:00
ajandClaude Opus 4.6 5fc16e9dae perf: halve rotating calipers edge iterations
Opposite hull edges (180° apart) produce identical bounding rectangles
(width/height swapped), so only half the edges need to be checked to
find the minimum area. Applied to the unconstrained overload only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:17:24 -04:00
ajandClaude Opus 4.6 91908c1732 perf: optimize fill hot path — bbox pre-check and geometry inner loop
- Add bounding box rejection in HasOverlaps to skip expensive
  Part.Intersects (CNC→geometry conversion) for non-adjacent parts.
  Eliminates ~35% CPU in IsBetterValidFill for grid layouts.
- Optimize RayEdgeDistance: access Line fields directly instead of
  property getters (avoids Vector struct copies), inline IsEqualTo
  with direct range comparison (avoids Math.Abs), and precompute
  deltas for reuse in interpolation.
- Cache line endpoints in DirectionalDistance outer loop to avoid
  repeated struct copies in the inner loop.
- Add fill timer to ActionClone.Fill, displayed in PlateView status
  bar as "Fill: N parts in M ms".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:10:25 -04:00
ajandClaude Opus 4.6 35d7248da0 refactor: move OpenNest.Test to separate test data repo
Test code and fixture data now live together in the OpenNest.Test repo
at git.thecozycat.net/aj/OpenNest.Test.git.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 21:06:43 -04:00
ajandClaude Opus 4.6 574342b5be chore: add OpenNest.Test to solution
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:47:17 -04:00
ajandClaude Opus 4.6 c1811af5d5 test: add RemnantFillTests for remnant area filling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:43:55 -04:00
ajandClaude Opus 4.6 1c3d9e08bd test: add FillTests for full plate fill and remainder strip refill
Added Xunit.SkippableFact package for conditional test skipping when
test data is unavailable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:03:39 -04:00
ajandClaude Opus 4.6 54da2bd2da refactor: convert OpenNest.Test to xUnit project with TestData helper
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:00:39 -04:00
ajandClaude Opus 4.6 bb64249af9 docs: add xUnit test suite implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:56:35 -04:00
ajandClaude Opus 4.6 3705d50546 feat: add remainder strip re-fill to improve pattern fill density
After the main fill, detect if the last column/row is an "oddball"
with fewer parts than the main grid. If so, remove those parts and
re-fill the remainder strip independently using all strategies
(linear, rect best-fit, pairs). Improves 30→32 parts on the test
case (96x48 plate with 30x7.5 interlocking parts).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:15:42 -04:00
ajandClaude Opus 4.6 3516199f25 docs: add MCP service design and implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 18:33:13 -04:00
ajandClaude Opus 4.6 57c35450dd docs: update remnant fill investigation with root causes and fix details
Documents both issues found (narrow pair selection, incomplete pattern tiling)
and their fixes with before/after results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 18:33:10 -04:00
ajandClaude Opus 4.6 435a08074b feat: improve remnant fill with rotation sweep, smart pair selection, and partial pattern fill
Narrow remnant strips now get more parts by:
- Sweeping rotations every 5° when the strip is narrower than the part
- Including all pairs that fit the strip width (not just top 50 by area)
- Placing individual parts from incomplete pattern copies that still fit
- Using finer polygon tolerance (0.01) for hull edge angle detection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 18:33:06 -04:00
ajandClaude Opus 4.6 c5a9c27160 feat: add F key zoom-to-fit and fix middle-click conflict in PlateView
- F key triggers ZoomToFit; Ctrl+F passes through for ActionClone fill
- Middle-button double-click ZoomToFit skipped when parts are selected
  to avoid conflicting with middle-click 90° rotation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 18:28:55 -04:00
ajandClaude Opus 4.6 d1353d58e5 feat: add configurable chord tolerance for offset drawing and push geometry
Replace hardcoded PushChordTolerance constant with a configurable
OffsetTolerance property on PlateView (default 0.001), giving smoother
arc profiles in offset drawing and push-to-part collision detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 17:48:05 -04:00
ajandClaude Opus 4.6 df283d15dc docs: update remnant fill investigation — engine needs more rotation candidates
The engine gets 7 parts where manual nesting gets 9, all at the same
rotation. The fix is trying more rotations across all fill strategies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:12:51 -04:00
ajandClaude Opus 4.6 892b11b341 docs: add remnant fill optimization investigation plan
MCP fill_remnants gets 7 parts vs UI Ctrl+F gets 9 in the same strip.
Documents root cause analysis and files to investigate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:10:26 -04:00
ajandClaude Opus 4.6 38b4b6debf Merge branch 'feature/mcp-service'
Add OpenNest.IO class library and OpenNest.Mcp server for Claude Code
integration. Extract IO classes from WinForms project, add
Plate.GetRemnants(), and expose 12 MCP tools for loading nests,
running nesting algorithms, and inspecting results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:03:35 -04:00
ajandClaude Opus 4.6 8952b9d0ea fix(mcp): add [McpServerToolType] attribute to all tool classes
Without this attribute, WithToolsFromAssembly does not discover
the tool methods and the server reports no tools capability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:01:47 -04:00
ajandClaude Opus 4.6 5951a6a5c0 docs: update CLAUDE.md with OpenNest.IO and OpenNest.Mcp projects
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:53:19 -04:00
ajandClaude Opus 4.6 f55779a01a feat(mcp): publish OpenNest.Mcp and register in .mcp.json
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:52:40 -04:00
ajandClaude Opus 4.6 e9ea290907 fix(mcp): add null guards and safe parsing to pack_plate
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:52:10 -04:00
ajandClaude Opus 4.6 0c56a9049a feat(mcp): add inspection tools — get_plate_info, get_parts, check_overlaps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:49:02 -04:00
ajandClaude Opus 4.6 8806bccb4e feat(mcp): add nesting tools — fill_plate, fill_area, fill_remnants, pack_plate
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:48:30 -04:00
ajandClaude Opus 4.6 3e8f8cd3bf feat(mcp): add setup tools — create_plate, clear_plate
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:47:55 -04:00
ajandClaude Opus 4.6 721197f1d4 feat(mcp): add input tools — load_nest, import_dxf, create_drawing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:47:33 -04:00
ajandClaude Opus 4.6 d02dfb92e9 feat: scaffold OpenNest.Mcp project with session state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:46:02 -04:00
ajandClaude Opus 4.6 a9af5effc5 feat: add Plate.GetRemnants() for finding empty edge strips
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:43:27 -04:00
ajandClaude Opus 4.6 cc286dd9b7 refactor: extract OpenNest.IO class library from WinForms project
Move DxfImporter, DxfExporter, NestReader, NestWriter, ProgramReader,
and Extensions into a new OpenNest.IO class library. The WinForms project
now references OpenNest.IO instead of ACadSharp directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:41:07 -04:00
ajandClaude Opus 4.6 4196a30791 refactor: unify FillLinear tiling into recursive FillRecursive method
Extract MakeSeedPattern for shared part creation, and replace the
two-step primary/perpendicular tiling with a single FillRecursive
method that tiles along one axis then recurses perpendicular.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:00:09 -04:00
ajandClaude Opus 4.6 c28d5d8c12 fix: use CPU evaluator for best-fit cache, remove broken GPU dilation
The GPU bitmap evaluator produces false overlap detections due to
discretization errors at cell boundaries. Use the CPU PairEvaluator
(exact geometric intersection) for now. Also remove the double-counted
spacing dilation from GpuPairEvaluator for when GPU is revisited.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 14:20:13 -04:00
ajandClaude Opus 4.6 3220306d3a feat: add reverse push directions for concave interlocking and cache best-fit results
Add PushDirection.Right and PushDirection.Up to RotationSlideStrategy so
parts can approach from all four directions. This discovers concave
interlocking arrangements (e.g. L-shaped parts nesting into each other's
cavities) that the original Left/Down-only slides could never reach.

Introduce BestFitCache so best-fit results are computed once at step size
0.25 and shared between the viewer and nesting engine. The GPU evaluator
factory is configured once at startup instead of being wired per call
site, and NestEngine.CreateEvaluator is removed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 14:02:41 -04:00
ajandClaude Opus 4.6 031264e98f refactor: pre-compute offset boundaries in FillLinear via PartBoundary
Extract offset polygon computation into PartBoundary, which builds
and caches inflated boundary polygons per unique part geometry.
FillLinear now uses symmetric half-spacing and reuses boundaries
across tiling passes, avoiding redundant offset calculations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 13:28:01 -04:00
ajandClaude Opus 4.6 a92ba7af89 feat: resolve per-entity color and line type from DXF imports
Add LineTypeName to Layer and propagate resolved color/line-type
through all DXF entity conversions (Arc, Circle, Line, Spline,
Polyline, LwPolyline, Ellipse). Entities that inherit ByLayer
properties now correctly resolve to their layer's values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 13:27:56 -04:00
ajandClaude Opus 4.6 2225c4ef09 feat: add BestFitCell control with screen-space text overlay
Extract a BestFitCell subclass from PlateView for the Best-Fit Viewer
grid cells. Text metadata is now painted in screen coordinates (after
resetting the graphics transform) so it stays fixed regardless of zoom.
Parts auto-zoom to fit on every resize.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 13:26:29 -04:00
ajandClaude Opus 4.6 e078ef4b77 feat: implement color and line type exclusion filters on CadConverterForm
Add per-entity IsVisible flag and wire up the Colors and Line Types
checkedlistboxes to filter entities by exclusion — checking an item
hides matching entities from the preview and from drawing export.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 13:14:09 -04:00
ajandClaude Opus 4.6 bc392b37dc refactor: move GpuEvaluatorFactory to OpenNest.Gpu project
GPU factory logic belongs with the GPU implementation, not the UI.
Changed from internal to public and updated namespace to OpenNest.Gpu.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 21:40:56 -05:00
ajandClaude Opus 4.6 99edad4228 refactor: extract responsibilities from NestEngine into focused classes
- Move BuildPairParts to BestFitResult.BuildParts() instance method
- Extract BinConverter (RectanglePacking) for Part/NestItem/Bin conversions
- Extract RotationAnalysis for FindBestRotation and FindHullEdgeAngles

NestEngine reduced from 484 to 287 lines — now purely orchestration,
strategy selection, and comparison logic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 21:37:50 -05:00
ajandClaude Opus 4.6 b738d4c72c refactor: clean up NestEngine — collapse overloads, extract helper, remove dead code
- Fill(NestItem) and Fill(List<Part>) now delegate to their Box overloads
- Add Part.CreateAtOrigin() to replace repeated 4-line build-at-origin pattern
  used in NestEngine, RotationSlideStrategy, and PairEvaluator
- Remove dead code: FillArea overloads, Fill(NestItem, int), FillWithPairs(NestItem),
  ConvertTileResultToParts, PackBottomLeft.FindPointHorizontal, Pattern.GetLines/GetOffsetLines,
  unused count variable in FillNoRotation
- Simplify IsBetterValidFill to delegate to IsBetterFill after overlap check

NestEngine reduced from 717 to 484 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 21:31:15 -05:00
ajandClaude Opus 4.6 d3704378c2 refactor: replace VPattern/HPattern with unified FillGrid method
Consolidates two nearly-identical grid generation methods into a single
FillGrid method with a columnMajor parameter. Fixes bug in HPattern
where inner loop used rows instead of columns, and fixes FillNoRotation
silently discarding results by not adding them to Bin.Items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 21:27:11 -05:00
ajandClaude Opus 4.6 062981ebe9 fix: compute accurate bounding metrics for GPU pair results
Replace grid-cell-based dimensions with geometry-aware computation using
convex hull and rotating calipers to determine minimum bounding rectangle
for valid pair candidates. Overlap results now short-circuit with zeroed
metrics instead of using stale grid dimensions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 20:55:16 -05:00
ajandClaude Opus 4.6 43a27df73c fix: handle multi-part pattern copy distance in FillLinear
FindPatternCopyDistance now checks every pair of parts across adjacent
patterns so that multi-part patterns (e.g. interlocking pairs) maintain
correct spacing between ALL parts, not just the bounding boxes. The
original single-part logic is preserved as a fast path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 20:55:12 -05:00
ajandClaude Opus 4.6 1d46ce2298 feat: add BestFitViewerForm for visualizing best-fit nesting results
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 20:06:28 -05:00
aj c575d82f80 Merge feature/gpu-bitmap-bestfit into master 2026-03-07 20:02:22 -05:00
ajandClaude Opus 4.6 90b89a5dfa feat: add FillRectangleBestFit strategy and remove false overlap rejection
- Remove IsBetterValidFill overlap gate for FillLinear results; the
  geometry-aware spacing in FillLinear is sufficient and the overlap
  check produced false positives on parts with arcs/curves, causing
  valid grid layouts to be rejected in favor of inferior pair fills.
- Add FillRectangleBestFit strategy that uses BestCombination to mix
  normal and rotated orientations, filling remnant strips for higher
  part counts on rectangular parts.
- All Fill overloads now compare linear, rectangle best-fit, and
  pair-based strategies, picking whichever yields the most parts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 20:00:38 -05:00
ajandClaude Opus 4.6 0c14d7f854 fix: align best-fit sweep to include offset=0 for grid arrangements
The perpendicular sweep started at perpMin (e.g. -8.75) which with
coarse step sizes never landed on offset=0, missing the perfect
side-by-side and stacked same-orientation patterns for rectangular parts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:24:37 -05:00
ajandClaude Opus 4.6 73c20c30ce fix: exclude rapid moves from Part.Intersects to fix FillLinear rejection
Part.Intersects included rapid move geometry (G00 traversals) when
checking for overlaps, causing false positives. The overlap validation
added in 5bebfcb rejected all FillLinear configs, producing 0 parts.
Every other GetShapes caller already filters SpecialLayers.Rapid.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:52:35 -05:00
ajandClaude Opus 4.6 7ed4572f8a feat: add GPU status indicator and device probe
- GpuEvaluatorFactory probes for CUDA/OpenCL devices at startup
- Status bar shows "GPU : <device name>" (green) or "GPU : None (CPU)" (gray)
- Factory skips GPU evaluator creation entirely when no device found
- Logs actual exception message on failure for debugging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:34:45 -05:00
ajandClaude Opus 4.6 5bebfcb612 feat: wire GpuPairEvaluator into NestEngine with auto-detection
NestEngine.CreateEvaluator factory delegate allows injection of GPU
evaluator from UI layer. GpuEvaluatorFactory.Create attempts GPU,
returns null (CPU fallback) if unavailable. All NestEngine call sites
wired up.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:27:15 -05:00
ajandClaude Opus 4.6 1c1508bc9e feat: add GpuPairEvaluator with ILGPU bitmap overlap kernel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:24:39 -05:00
ajandClaude Opus 4.6 8d28167b2f feat: add OpenNest.Gpu project with PartBitmap rasterizer
Introduces the OpenNest.Gpu class library with ILGPU dependencies and a
PartBitmap class that rasterizes Drawing closed shapes into integer grids
for GPU-based overlap testing. Supports rotation and spacing dilation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:22:27 -05:00
ajandClaude Opus 4.6 b83d09c3a7 refactor: extract IPairEvaluator interface from PairEvaluator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:19:05 -05:00
ajandClaude Opus 4.6 dd7383467b feat: add Polygon.ContainsPoint using ray casting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:13:12 -05:00
ajandClaude Opus 4.6 688b00b3e4 docs: add GPU bitmap best fit implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:06:01 -05:00
ajandClaude Opus 4.6 443556d2e3 docs: add GPU bitmap best fit evaluation design
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:03:40 -05:00
ajandClaude Opus 4.6 bc411949b8 fix: use offset geometry for moving part in FillLinear spacing
Offset the moving shape's geometry by PartSpacing instead of adding
spacing linearly to the copy distance. This guarantees minimum clearance
in all directions for curved/complex shapes, not just along the slide axis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 14:10:48 -05:00
ajandClaude Opus 4.6 54cdf21264 docs: update CLAUDE.md for .NET 8 migration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:32:11 -05:00
ajandClaude Opus 4.6 0e7eb3df81 chore: update solution file for Visual Studio 17
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:31:43 -05:00
ajandClaude Opus 4.6 e6e87b7cad refactor: simplify MainApp for .NET 8 DPI handling
DPI awareness is now handled by the ApplicationHighDpiMode project property.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:31:19 -05:00
ajandClaude Opus 4.6 848023a2b9 refactor: rewrite DxfExporter for ACadSharp
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:30:23 -05:00
ajandClaude Opus 4.6 d185adecfa refactor: rewrite DxfImporter for ACadSharp
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:26:33 -05:00
ajandClaude Opus 4.6 3baa942f4e refactor: rewrite IO Extensions for ACadSharp
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:25:04 -05:00
ajandClaude Opus 4.6 263c2d0ae1 feat: convert OpenNest WinForms project to .NET 8 SDK-style
Build errors expected in IO files — netDxf references not yet migrated to ACadSharp.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:23:47 -05:00
ajandClaude Opus 4.6 a6949a390d feat: convert OpenNest.Engine to .NET 8 SDK-style project
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:22:09 -05:00
ajandClaude Opus 4.6 6ce81d99a7 feat: convert OpenNest.Core to .NET 8 SDK-style project
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:21:16 -05:00
ajandClaude Opus 4.6 afca2068cc feat: integrate best-fit pair finding into NestEngine.Fill
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:03:03 -05:00
ajandClaude Opus 4.6 955446a2f4 feat: add BestFitFinder orchestrator with hull edge angle strategies
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:54:26 -05:00
ajandClaude Opus 4.6 7a0aac9f59 feat: add BestFitFilter and TileEvaluator for pair filtering and tiling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:51:44 -05:00
ajandClaude Opus 4.6 2a8b2dfdee feat: add PairEvaluator with overlap detection and rotating calipers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:49:26 -05:00
ajandClaude Opus 4.6 21e1c959d3 feat: add RotationSlideStrategy with directional push contact algorithm
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:45:28 -05:00
ajandClaude Opus 4.6 86fee08670 feat: add PairCandidate, BestFitResult, and IBestFitStrategy for best-fit pair finding
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:42:43 -05:00
ajandClaude Opus 4.6 b030de77a8 feat: restore previous action on Escape from ActionSelect
Pressing Escape from ActionSelect now restores the previous action
(e.g. ActionClone) instead of staying in Select mode. Adds
ConnectEvents() to the Action base class for action resume support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 10:51:28 -05:00
ajandClaude Opus 4.6 0573cb2f6d feat: fill open area and optimize pattern rotation via convex hull
ActionClone.Fill() now computes the largest open rectangle from the
cursor position (trying both vertical and horizontal) and passes it
to the engine, so fills no longer overlap existing parts.

Pattern fills try all convex hull edge angles to find the rotation
that maximizes part count.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 10:51:21 -05:00
ajandClaude Opus 4.6 0b2100a661 fix: restore SelectedParts after plate switch in ActionClone
SetPlate clears SelectedParts, which broke bounds drawing and rotation
for surviving actions. Add OnPlateChanged hook so ActionClone can
re-populate SelectedParts after a plate switch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 10:11:22 -05:00
ajandClaude Opus 4.6 fd778e2fd2 fix: preserve ActionClone across plate switches
SetPlate unconditionally reset the action to ActionSelect, clearing
the clone pattern when switching plates. Add SurvivesPlateChange
virtual property to Action base class so actions can opt in to
persisting across plate changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 10:05:13 -05:00
ajandClaude Opus 4.6 40b40ca4ba feat: unify ActionAddPart into ActionClone and add group fill support
Merge ActionAddPart into ActionClone by adding a Drawing constructor,
eliminating the redundant class. ActionClone now handles both adding
new parts from a drawing and cloning selected part groups. Added
Ctrl+F fill support for groups using FillLinear pattern tiling, and
adopted quadrant-aware push directions from ActionAddPart. Refactored
FillLinear to extract shared helpers and add a Fill(Pattern) overload
for tiling arbitrary part groups across the work area.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 09:56:48 -05:00
ajandClaude Opus 4.6 5807255931 feat: replace Fill method with geometry-aware FillLinear algorithm
Fill(NestItem) now uses actual part geometry instead of bounding boxes.
Also fixes Fill(NestItem, maxCount) which previously threw NotImplementedException.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 07:53:02 -05:00
ajandClaude Opus 4.6 5707bff89b feat: rotate selected parts 90° on middle mouse click
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:12:03 -05:00