Commit Graph

54 Commits

Author SHA1 Message Date
5949c3ca1f feat: add Delete key to remove source parts during ActionClone
Enables a "move" workflow: clone parts to a new position, then
press Delete to remove the originals. Previously Delete just
cancelled the clone action.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 19:21:23 -04:00
7e86313d7c fix: prevent Delete key from corrupting quantity during ActionClone
ObservableList.Remove fired ItemRemoved even when the item wasn't in
the list, causing Plate to decrement Quantity.Nested for clone preview
parts that were never added — producing -1 counts. Delete in PlateView
now cancels ActionClone instead of trying to remove its preview parts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 21:34:25 -04:00
9db7abcd37 refactor: move material and thickness from Plate to Nest
Material and thickness are properties of the nest (all plates share the
same material/gauge), not individual plates. This moves them to the Nest
class, removes them from Plate and PlateSettings, and updates the UI so
EditNestInfoForm has a material field while EditPlateForm no longer shows
thickness. The nest file format gains top-level thickness/material fields
with backward-compatible reading from PlateDefaults for old files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:00:59 -04:00
134771aa23 feat: add Draw Cut Direction view option and extract PlateRenderer
Add a "Draw Cut Direction" toggle to the View menu that draws small
arrowheads along cutting paths to indicate the direction of travel.
Arrows are placed on both linear and arc moves, spaced ~60px apart,
and correctly follow CW/CCW arc tangents.

Extract all rendering methods (~660 lines) from PlateView into a new
PlateRenderer class, reducing PlateView from 1640 to 979 lines.
PlateView retains input handling, selection, zoom, and part management.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:22:05 -04:00
a2b7be44f8 fix: draw approach rapid directly to first pierce point, not part origin
The approach rapid from sheet origin was drawing to part.Location (the
program coordinate origin) then a second rapid to the actual first
pierce point. This created a dog-leg through the part origin instead
of a single straight rapid to the lead-in. Also fixed PlateProcessor
using the original program's start point instead of the processed one
when the cutting strategy is applied on-the-fly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:38:53 -04:00
f8b0fb573b fix: fill preview now matches accepted layout
Refresh PlateView preview with settled parts after Compactor.Settle
so the accepted layout matches what was shown, not the pre-settle
positions from the last progress report.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 23:39:43 -04:00
036f723876 fix: update PlateView fill path and sync stats with preview
- Route best-result updates to progress form preview in
  PlateView.FillWithProgress (Ctrl+F path) — was still using
  the old SetStationaryParts approach
- Only update results stats (parts, density, area) when
  IsOverallBest so they match the preview display

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:56:41 -04:00
2db8c49838 feat: add etch mark entities from bend lines to CNC program pipeline
Etch marks for up bends are now real geometry entities on an ETCH layer
instead of being drawn dynamically. They flow through the full pipeline:
entities → FilterPanel layers → ConvertGeometry (tagged as Scribe) →
post-processor sequencing before cut geometry.

Also includes ShapeProfile normalization (CW perimeter, CCW cutouts)
applied consistently across all import paths, and inward offset support
for cutout shapes in overlap/offset polygon calculations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 00:42:49 -04:00
f29f086080 feat: add pierce point visualization and rename shape dimensions to Length/Width
Add toggleable pierce point drawing to PlateView that shows small red
filled circles at each rapid move endpoint (where cutting begins). Wire
through View menu, EditNestForm toggle, and MainForm handler.

Also rename RectangleShape/RoundedRectangleShape Width/Height to
Length/Width for consistency with CNC conventions, update MCP tools and
tests accordingly. Fix SplitDrawingForm designer layout ordering and
EntityView bend line selection styling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 21:26:49 -04:00
a7f8972722 feat: add bend line rendering and grain warning in PlateView
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:39:29 -04:00
da8e7e6fd3 feat: interactive cut-off selection and drag via line hit-testing
Select cut-offs by clicking their lines instead of a grip point.
Drag is axis-constrained with live regeneration during movement.
Selected cut-off highlighted with bright blue 3.5px line.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 23:49:27 -04:00
4db51b8cdf fix: regenerate cut-offs on part rotation and default cut direction
- Regenerate cut-off programs after RotateSelectedParts so cut lines
  update when parts are rotated, not just moved
- Change default CutDirection from TowardOrigin to AwayFromOrigin so
  cuts start at the origin axis

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 22:58:47 -04:00
ad58332a5d feat: regenerate cut-offs after part drag and fill operations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 20:01:03 -04:00
d4f60d5e8e feat: add cut-off selection, drag-to-reposition, and delete
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:57:26 -04:00
57bd0447e9 feat: add PlateView cut-off rendering with grip handle
Add DrawCutOffs and DrawCutOffGrip methods to PlateView for rendering
cut-off lines and selection grip handles. Includes CutOffSettings and
SelectedCutOff properties, plus GetCutOffAtPoint for hit-testing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:46:49 -04:00
b6ee04f038 fix: use Part.Rotate() in PlateView to avoid mutating shared Programs
RotateSelectedParts was calling Program.Rotate() directly on shared
Program instances, bypassing Part's copy-on-write (EnsureOwnedProgram).
Parts created via CloneAtOffset share the same Program, so rotating one
part would rotate all parts with the same reference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 23:08:47 -04:00
c88cec2beb perf: remove no-op AutoNester.Optimize calls from fill pipelines
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 20:11:49 -04:00
cf1c5fe120 feat: integrate NFP optimization into nest engines and fill UI
Add Compactor.Settle and AutoNester.Optimize post-passes to
NestEngineBase.Nest, StripNestEngine, and PlateView.FillWithProgress
so all fill paths benefit from geometry-aware compaction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 14:43:24 -04:00
2ed02c2dae feat: show selected part bounding box in status bar
Add SelectionChanged event to PlateView and display the selected part's
location and size in a new status bar label. Shows combined bounding box
when multiple parts are selected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 09:38:48 -04:00
8dc12972f5 feat(ui): add drawing selector, color scheme, and async loading to BestFitViewer
Add drawing dropdown to switch between drawings without reopening the
form. Change color scheme to light backgrounds with blue/red part fills
and auto-detect text color. Fix swapped bounding box width/length. Run
best-fit computation on a background thread so the UI stays responsive
during long calculations, with cancellation on drawing switch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:44:21 -04:00
ca35945c13 fix(ui): show active or stationary preview parts, not both overlapping
Draw only one set of preview parts at a time — active (current strategy)
takes precedence over stationary (overall best). Also clears active
parts when setting new stationary parts to prevent stale previews.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 11:50:56 -04:00
4fc8f1f6cf feat(ui): two-bucket preview parts in PlateView
Replace single temporaryParts list with stationaryParts (overall best,
full opacity) and activeParts (current strategy, reduced opacity).
Update SetPlate, Refresh, UpdateMatrix, DrawParts, and FillWithProgress
accordingly. Replace SetTemporaryParts/ClearTemporaryParts/AcceptTemporaryParts
with SetStationaryParts/SetActiveParts/ClearPreviewParts/AcceptPreviewParts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 22:14:59 -04:00
9a4f20ca00 feat(ui): support Accept button in nesting callers 2026-03-18 17:35:33 -04:00
0e1e619f0a refactor(engine): move fill and strategy code to dedicated namespaces
Move fill algorithms to OpenNest.Engine.Fill namespace:
FillLinear, FillExtents, PairFiller, ShrinkFiller, Compactor,
RemnantFiller, RemnantFinder, FillScore, Pattern, PatternTiler,
PartBoundary, RotationAnalysis, AngleCandidateBuilder, and
AccumulatingProgress.

Move strategy layer to OpenNest.Engine.Strategies namespace:
IFillStrategy, FillContext, FillStrategyRegistry, FillHelpers,
and all built-in strategy implementations.

Add using directives to all consuming files across Engine, UI,
MCP, and Tests projects.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 16:46:11 -04:00
42f2475f3c fix: correct Size width/length axis mapping throughout codebase
The Size fix (d4222db) changed Size.Width to Y axis and Size.Length to
X axis but only updated DrawPlate/LayoutViewGL. BoundingBox, WorkArea,
rotations, DXF export, and engine code still used the old Width=X
convention, causing the fill engine to get a swapped work area (60x120
instead of 120x60) and parts to fill in the wrong direction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:20:24 -04:00
d4222db0e8 fix: correct Size width/length ordering and add CLI docs to README
Size.Parse and ToString now use WxL format (width first) matching the
natural convention. Fixed the Plate(w,l) constructor which was swapping
args when creating Size. Fixed PlateView.DrawPlate and DrawControl
ZoomToArea which had width/length mapped to the wrong screen axes.

Simplified Console --size parsing to use Size.TryParse instead of manual
split with confusing PlateHeight/PlateWidth fields. Added Command-Line
Interface section to README documenting all console options.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 10:29:13 -04:00
9d40d78562 feat(ui): add remnant viewer tool window
Adds a toolbar button that opens a dockable remnant viewer showing
tiered remnants (priority, size, area, location) with color-coded
overlay rendering on the plate view.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:49:51 -04:00
195e29da52 fix(ui): rotate grouped parts around shared center with dedup
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>
2026-03-16 14:11:07 -04:00
3d23943b69 fix(engine): use RemnantFinder for iterative remnant filling in StripNestEngine
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>
2026-03-16 13:11:28 -04:00
4911d05869 feat: wire ActiveWorkArea from NestProgress to PlateView
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 12:57:51 -04:00
2b4f7c4e80 feat: draw active work area as dashed orange rectangle on PlateView
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 12:56:37 -04:00
bd3984037c refactor: migrate WinForms callsites to NestEngineRegistry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:11:11 -04:00
289a2044a6 fix(ui): mark LayoutParts dirty after PushSelected so paths rebuild
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>
2026-03-15 14:20:18 -04:00
7508fbf715 refactor(engine): delegate PlateView.PushSelected to Compactor and add iterative compaction
PushSelected now calls Compactor.Push instead of duplicating the push
logic. Compactor.Push moves parts as a group (single min distance) to
preserve grid layouts. Compact tries both left-first and down-first
orderings, iterating up to 20 times until movement drops below
threshold, and keeps whichever ordering traveled further.

Also includes a cancellation check in FillWithProgress to avoid
accepting parts after the user stops a nest.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 14:16:35 -04:00
8e0c082876 refactor(ui): optimize PushSelected with directional filtering and lazy line computation
Extract direction helpers to Helper class (EdgeDistance, DirectionalGap,
DirectionToOffset, IsHorizontalDirection) and use them to skip parts not
ahead in the push direction or further than the current best distance.
Defer line computation until parts survive bounding box checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 01:30:50 -04:00
776e9d218c fix(ui): cache offset paths and scale temp parts on zoom
Cache offset polygon geometry on LayoutPart so DrawOffset no longer
recomputes the expensive offset pipeline every paint cycle. The costly
OffsetEntity/ToPolygonWithTolerance/RemoveSelfIntersections chain now
runs only when rotation, spacing, or tolerance actually changes.

Also update temporary parts in UpdateMatrix() so preview parts during
nesting scale correctly with zoom.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:29:27 -04:00
9773449563 feat(ui): add FillWithProgress to PlateView, use from ActionClone
Moves async fill+progress orchestration into PlateView so ActionClone's
Ctrl+F fill shows the NestProgressForm dialog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:39:30 -04:00
c545f91d28 feat(ui): add temporary parts list to PlateView with preview drawing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:29:30 -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
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
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
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
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
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
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