Commit Graph

41 Commits

Author SHA1 Message Date
e4e1d9b5a3 refactor: rename DefinedShape to ShapeProfile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:19:49 -04:00
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
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
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
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
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
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
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
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
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
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
848023a2b9 refactor: rewrite DxfExporter for ACadSharp
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:30:23 -05:00
d185adecfa refactor: rewrite DxfImporter for ACadSharp
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:26:33 -05:00
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
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
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
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
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
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
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
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
4d270ae68e fix: remove self-intersecting loops from polygon offset
Polygon offset at concave corners creates geometry that folds back
through itself. Added RemoveSelfIntersections() to Polygon that
detects non-adjacent edge crossings and removes the smaller loop
at each crossing. Applied to both collision detection and rendering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:23:44 -05:00
08b31d0797 fix: stop push at contact boundary and filter edges by direction
RayEdgeDistance returned double.MaxValue for touching vertices (dist ≈ 0),
causing rays from other vertices to hit the far side of stationary parts
and allow movement through obstacles. Now returns 0 when touching so the
distance > 0 check in PushSelected correctly prevents further movement.

Added directional edge filtering using outward normals to discard
back-facing edges before ray checks, reducing line count by ~2/3.
DirectionalDistance now checks both StartPoint and EndPoint per line
to preserve vertices at filtered edge boundaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:42:40 -05:00
6561b478a5 fix: prevent scientific notation in G-code output
ProgramReader treats 'E' as a code letter, so values like
"6.66E-08" get split into X:"6.66" and E:"-08", corrupting
the parsed coordinate. Use fixed-point format string instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 20:54:20 -05:00
1c4015ac62 fix: CadConverter SetRotation ignored rotation parameter
SetRotation always forced CW regardless of the requested rotation,
so cutouts (which should be CCW for kerf-left) were also set to CW.
Now uses the rotation parameter to set the correct winding direction.

Also reverts the Shape.OffsetEntity cutout side inversion since the
correct fix is proper winding from the converter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 19:41:42 -05:00
64cacf6d17 feat: add View > Draw Offset menu item
Toggles offset geometry visualization from the View menu, matching
the existing Draw Rapids and Draw Bounds menu pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 19:31:55 -05:00
eb7fb097b9 feat: add DrawOffset toggle to PlateView
Shows the offset geometry (PartSpacing buffer) around each part as a
semi-transparent red outline. Toggle via PlateView.DrawOffset property.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 19:28:05 -05:00
3931012079 feat: rewrite PushSelected to use polygon directional-distance
Parts now push based on actual cut geometry instead of bounding boxes,
allowing irregular shapes to nestle together with PartSpacing gap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 18:29:50 -05:00
26d020ce3d feat: move PushDirection enum to OpenNest.Core
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 18:23:02 -05:00
e4df9cacd8 Move converters to OpenNest.Converters namespace
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:04:46 -05:00
67a66e10fd Move geometry primitives to OpenNest.Geometry namespace
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:02:12 -05:00
8d9aebb83f Move math utilities to OpenNest.Math namespace
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:51:16 -05:00
255d3962a6 Rename CircularMove to ArcMove
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 08:16:43 -05:00
2d956fd3f7 Restructure project layout to flatten directory structure
Move all projects from Source/ to repository root for simpler navigation.
- Remove External/ dependency DLLs (will use NuGet packages)
- Remove Installer/ NSIS script
- Replace PartCollection/PlateCollection with ObservableList
- Add packages.config for NuGet dependencies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 20:29:12 -05:00