Commit Graph

109 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
c575d82f80 Merge feature/gpu-bitmap-bestfit into master 2026-03-07 20:02:22 -05:00
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
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
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
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
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
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
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
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
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
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
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
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
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