Commit Graph

731 Commits

Author SHA1 Message Date
d4f424f274 refactor: simplify FillExtents with PartPair record and FillLinear delegation
Replace verbose value tuple with named PartPair record struct, extract
AnchorToWorkArea/PairBbox helpers to eliminate duplication, and delegate
RepeatColumns to FillLinear.Fill which already handles geometry-aware
column tiling with overlap fallback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 19:16:16 -04:00
028b1fabfc fix: move bend line action links above list for more vertical space
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 18:32:53 -04:00
a7c2fcffe6 test: add edge case tests for Collision; update CLAUDE.md 2026-03-29 09:43:31 -04:00
b834813889 refactor: delegate Part.Intersects to Collision.Check 2026-03-29 09:41:40 -04:00
4fa6100722 test: add hole subtraction and batch collision tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 09:40:28 -04:00
8f2fbee02c feat: add Collision static class with Sutherland-Hodgman clipping and tests
Polygon-polygon collision detection using convex decomposition (ear-clipping
triangulation) followed by Sutherland-Hodgman clipping on each triangle pair.
Handles overlapping, non-overlapping, edge-touching, containment, and concave
polygons. Includes hole subtraction support for future use.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 09:35:41 -04:00
230a11d32e feat: add CollisionResult data class for polygon collision detection
Immutable result type that holds overlap flag, overlap regions (as polygons),
intersection points, and computed overlap area.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 09:32:51 -04:00
953429dae9 fix: add overlap safety check and diagnostics to FillGrid Step 2
FillGrid had no overlap check after perpendicular tiling of the row
pattern (Step 2), unlike Step 1 which had one. When geometry-aware
FindPatternCopyDistance underestimated row spacing, overlapping parts
were returned unchecked.

Changes:
- Make FillLinear.HasOverlappingParts shape-aware (bbox pre-filter +
  Part.Intersects) instead of bbox-only, preventing false positives on
  interlocking pairs while catching real overlaps
- Add missing overlap safety check after Step 2 perpendicular tiling
  with bbox fallback
- Add diagnostic Debug.WriteLine logging when overlap fallback triggers,
  including engine label, step, direction, work area, spacing, pattern
  details, and overlapping part locations/rotations for reproduction
- Add FillLinear.Label property set at all callsites for log traceability
- Refactor LinearFillStrategy and ExtentsFillStrategy to use shared
  FillHelpers.BestOverAngles helper for angle-sweep logic

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 22:08:38 -04:00
1c2b569ff4 fix: eliminate endpoint gaps in EllipseConverter arc output
EllipseConverter computed arc radius from start point only, causing
~0.0009 unit gaps between consecutive arcs. Use circumcircle of
(start, mid, end) points so both endpoints lie exactly on the arc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:37:01 -04:00
048b10a1e9 refactor: deduplicate BestFitHorizontal and BestFitVertical
Extract shared BestFitAxis helper parameterized by orientation,
eliminating 23-line duplicate in rectangle packing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:23:08 -04:00
3022982f6d refactor: consolidate HasOverlappingParts into FillHelpers
StripeFiller and FillExtents had identical 24-line overlap detection
methods; move to FillHelpers and delegate from both callers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:22:00 -04:00
cc85493a0c refactor: deduplicate EvenlyDistribute horizontal and vertical
Extract shared EvenlyDistribute helper parameterized by axis,
eliminating 27-line duplicate between the two methods.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:20:01 -04:00
3da287cdc0 refactor: extract generic MergePass from GeometryOptimizer
The arc and line Optimize methods had identical merge-loop structure;
extract a generic MergePass helper with type-specific delegates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:19:04 -04:00
d1a701a7f7 refactor: move shared GetRectangle to Action base class
Both ActionSelect and ActionZoomWindow had identical 29-line
GetRectangle methods; consolidate into the common base class.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:16:00 -04:00
17f786c9e8 refactor: delegate Program.Rotate(angle) to Rotate(angle, origin)
The parameterless rotation is equivalent to rotating around (0,0),
so delegate to the origin overload to eliminate 30-line duplicate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:14:51 -04:00
b7a8e2662c refactor: deduplicate FillHorizontal and FillVertical in FillEndOdd
Extract shared FillAxis helper parameterized by orientation,
eliminating 34-line duplicate between horizontal and vertical fills.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:13:00 -04:00
912a47c5e8 refactor: extract shared ArcFit utilities from SplineConverter and GeometrySimplifier
Move identical FitWithStartTangent and MaxRadialDeviation methods
to a shared ArcFit class, eliminating 40-line duplicate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:11:47 -04:00
a85213a524 refactor: deduplicate SortColumnsByHeight and SortRowsByWidth
Extract shared SortStrips helper parameterized by axis selectors,
eliminating 61-line near-duplicate between column and row sorting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:05:54 -04:00
fb696aaf58 refactor: remove dead code and deduplicate SpatialQuery
Remove 4 unused ClosestDistance methods and extract shared
FindVerticalLimits/FindHorizontalLimits helpers from the
GetLargestBox methods, eliminating 6 duplicate code groups.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:03:27 -04:00
d854a1f5d2 fix: use arc joins at convex corners in offset geometry
Convex corners were being miter-joined (lines extended to a point)
because IntersectsUnbounded always finds an intersection for non-parallel
lines. Now checks the cross product of original line directions to detect
convex corners and inserts an arc instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:53:20 -04:00
abc707f1d9 fix: allow line-on-line contact and remove extra spacing gap
- Part.Intersects: filter intersection points at a vertex of either
  shape (was both), so edge-touching parts are not flagged as overlapping
- NestEngineBase.HasOverlaps: use epsilon-based bounding box pre-filter
  consistent with FillExtents and Plate.HasOverlappingParts
- PartGeometry.GetOffsetPartLines: remove extra chordTolerance added to
  spacing offset — was causing 0.002" gap beyond the intended part spacing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:36:35 -04:00
61b917c398 chore: remove docs/superpowers and add to gitignore
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:48:59 -04:00
e3e51611d5 fix: only remove bend-generated etch entities, preserve user etch lines
UpdateEtchEntities was removing all entities on the ETCH layer, which
also deleted user-added etch marks like part numbers. Now tags generated
bend etch lines with a BendEtch tag and filters on that instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:47:26 -04:00
8104bd3626 feat: rotate bend labels parallel to bend line and center them
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:36:10 -04:00
ae262b8a77 feat: add scrollbar and arrow key navigation to FileListControl
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 13:53:36 -04:00
afbbc9ed79 feat: improve EntityView labels for circles and small entities
Place circle labels on the circumference using golden angle distribution
so concentric circles don't overlap. Hide labels when the entity is too
small on screen to fit the badge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:05:32 -04:00
6071e6fa14 refactor: remove Plate menu Fill and Fill Area items replaced by Ctrl+F
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 09:54:15 -04:00
afdd386456 feat: add entity index labels toggle to EntityView and CadConverterForm
Labels are drawn at each entity's midpoint with a filled background
circle for readability. Toggle via "Labels" checkbox in the detail bar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 09:49:07 -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
80e8693da3 fix: add overlap detection safety net for pair tiling
Shape.OffsetOutward produces inward offsets for certain rotated polygons,
causing geometry-aware copy distances to be too small and placing
overlapping parts. Root cause is in the offset winding direction
detection — this commit adds safety nets while that is investigated.

- FillLinear.FillGrid: detect bbox overlaps after geometry-aware tiling,
  fall back to bbox-based spacing when overlaps found
- FillExtents.RepeatColumns: detect overlaps after Compactor computes
  copy distance, fall back to columnWidth + spacing
- PairFiller/StripeFiller remnant fills: use FillLinear directly instead
  of spawning full engine pipeline (avoids strategies with the bug)
- Add PairOverlapDiagnosticTests reproducing the issue
- MCP config: use shadow-copy wrapper for dev hot-reload

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 23:52:50 -04:00
d7eb3ebd7a fix: skip aspect ratio rejection when best-fit utilization is high
High-utilization pairs (>=75%) are no longer discarded for exceeding
the aspect ratio limit, since the material isn't being wasted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:15:45 -04:00
4404d3a5d0 feat: add OpenNest.Data machine configuration system 2026-03-27 20:30:55 -04:00
d27dee3db9 feat: add MachineConfigForm editor with tree navigation and MainForm menu integration
Wires the OpenNest.Data layer into the UI: adds project reference, creates MachineConfigForm (tree-based editor for machines/materials/thicknesses with import/export), and adds Tools > Machine Configuration... menu item.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:27:44 -04:00
7081c7b4d0 feat: add embedded CL-980 default config with first-run EnsureDefaults
Embeds CL-980.json as a resource in OpenNest.Data and adds EnsureDefaults()
to LocalJsonProvider, which seeds the machines directory on first run when empty.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:23:00 -04:00
a6e813bc85 feat: add IDataProvider interface and LocalJsonProvider with JSON file CRUD
One JSON file per machine named by GUID, stored in a configurable directory.
Supports save, load, list (as summaries), and delete with IO-error retry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:19:56 -04:00
98453243fc feat: add MachineConfig, MaterialConfig, MachineSummary with parameter lookup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:16:59 -04:00
64874857a1 feat: add LeadConfig, CutOffConfig, and ThicknessConfig data models 2026-03-27 20:14:39 -04:00
5d3fcb2dc8 feat: add OpenNest.Data project with MachineType and UnitSystem enums 2026-03-27 20:13:54 -04:00
ae9a63b5ce feat: add Parts/Groups tabs with editable material, thickness, and per-group plate sizes
- Parts tab: shows all BOM items, editable Material/Thickness for
  matched rows, grayed-out rows for items without DXF files
- Groups tab: auto-computed from parts with editable Plate Width/Length
  per material+thickness group
- Editing Material/Thickness on Parts tab immediately re-groups
- Per-group plate sizes preserved across re-groups

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:50:06 -04:00
596328148d fix: correct dock z-order so Fill control gets remaining space
Fill must be at index 0 (front) so it's processed last by the
docking layout engine. Edge docks at higher indices process first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:07:32 -04:00
6cd48a623d fix: use fixed height for input group instead of AutoSize
AutoSize with Dock.Fill child causes circular sizing and collapses
the GroupBox. Use fixed Height=200 instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:04:43 -04:00
42243c7df0 fix: rewrite BomImportForm layout using TableLayoutPanel for DPI safety
Replaced absolute-positioned controls with TableLayoutPanel in the input
section and Dock-based layout for bottom buttons. Fixes controls being
hidden at non-100% DPI scaling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:58:50 -04:00
4b10d4801c fix: correct dock order and make BomImportForm resizable
- Add Fill control last so edge-docked controls get space first
- Remove stale hardcoded Location on bottom panel
- Switch to Sizable border with MinimumSize so user can resize

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:55:18 -04:00
f0bdaa14e6 fix: increase BomImportForm size and enable font auto-scaling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:50:23 -04:00
79ddce346b fix: move mnuFileImportBom construction before AddRange to avoid null reference
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:47:05 -04:00
20777541c0 fix: address review findings — MdiParent conflict, null guard, Drawing.Material
- Fix critical: use MdiParentForm (custom property) instead of MdiParent
  (WinForms property) in ImportBom_Click to avoid InvalidOperationException
- Add null guard in CreateNests_Click
- Set Drawing.Material from BOM group
- Move DxfImporter creation outside loop
- Improve summary label text with reason descriptions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:40:18 -04:00
7c8168b002 feat: add 'Import BOM...' menu item to MainForm File menu 2026-03-27 17:35:48 -04:00
203bd4eeea feat: add BomImportForm nest creation logic
Task 9: CreateNests_Click validates plate dimensions, then for each
MaterialGroup creates a Nest with name '{job} - {thickness} {material}',
sets PlateDefaults (size, thickness, material, quadrant=1, spacing),
imports each matched DXF via DxfImporter, converts entities to Program
with leading RapidMove offset handling (same pattern as CadConverterForm),
sets Quantity.Required from BOM qty, then opens an EditNestForm for each
nest that has drawings. Summary MessageBox reports count and import errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 17:34:15 -04:00
02d15dea9c feat: add BomImportForm file browsing and analysis logic
Task 8: BrowseBom_Click auto-fills DXF folder and derives job name by
stripping ' BOM' suffix; BrowseDxf_Click opens folder browser;
Analyze_Click reads BOM via BomReader, runs BomAnalyzer, populates
DataGridView with material/thickness/parts/qty columns, updates summary
label with skipped/unmatched counts, and enables Create Nests button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 17:33:39 -04:00
a88937b716 feat: add BomImportForm designer layout and shell
Task 7: WinForms dialog for BOM import with Input groupbox (job name,
BOM file, DXF folder, plate size, Analyze button), Material Groups
DataGridView, and bottom panel (summary label, Create Nests, Close).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 17:33:13 -04:00