Commit Graph

82 Commits

Author SHA1 Message Date
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
dde07fc256 merge: resolve polylabel conflicts, keep remote version with hole support
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 09:02:30 -04:00
224fbde19a feat: add polylabel algorithm for part label positioning and README
Use pole-of-inaccessibility (polylabel) to place part labels at the
visual center of shapes instead of the first path vertex. Labels now
stay correctly positioned regardless of part rotation or shape.

Also adds project README and MIT license.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:52:48 -04:00
6e5471271d feat(core): add RoundedRectangleShape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:07:22 -04:00
0651f185e3 feat(core): add OctagonShape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:06:21 -04:00
33377291a6 feat(core): add TShape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:06:08 -04:00
dfd5a15274 feat(core): add TrapezoidShape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:04:15 -04:00
09a7608bcb feat(core): add IsoscelesTriangleShape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:03:14 -04:00
92d2d6d2bc feat(core): add RightTriangleShape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:02:18 -04:00
641734ba70 feat(core): add RingShape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:00:11 -04:00
5d0de4a1b1 feat(core): add CircleShape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 07:59:26 -04:00
f92d09a863 feat(core): add RectangleShape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 07:58:37 -04:00
5670ae79bf feat(core): add ShapeDefinition base class
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 07:57:54 -04:00
44657a86b8 feat(geometry): add PolyLabel algorithm with square test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 20:40:25 -04:00
b42348665f refactor: remove Plate.GetRemnants(), replaced by RemnantFinder
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 12:53:29 -04:00
1757e9e01d refactor: change ContourCuttingStrategy.Apply to accept approachPoint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:23:53 -04:00
62140789a7 feat: add Part.HasManualLeadIns flag
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:23:21 -04:00
ad877383ce feat: add CuttingResult struct
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:22:50 -04:00
93bf15c27f chore: remove redundant using in Rounding.cs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:49:53 -04:00
e017723318 refactor: remove empty Helper class
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:46:36 -04:00
13b01240b1 refactor: extract SpatialQuery from Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:46:14 -04:00
2881815c7a refactor: extract PartGeometry from Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:44:17 -04:00
84d3f90549 refactor: extract Intersect from Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:43:12 -04:00
7c4eac5460 refactor: extract ShapeBuilder from Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:41:40 -04:00
be318bc1c1 refactor: extract GeometryOptimizer from Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:39:52 -04:00
09cdb98dfc refactor: extract Rounding from Helper to OpenNest.Math
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:38:23 -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
3c59da17c2 fix(engine): fix pair candidate filtering for narrow plates and strips
The BestFitFilter's aspect ratio cap of 5.0 was rejecting valid pair
candidates needed for narrow plates (e.g. 60x6.5, aspect 9.2) and
remainder strips on normal plates. Three fixes:

- BestFitFinder: derive MaxAspectRatio from the plate's own aspect
  ratio so narrow plates don't reject all elongated pairs
- SelectPairCandidates: search the full unfiltered candidate list
  (not just Keep=true) in strip mode, so pairs rejected by aspect
  ratio for the main plate can still be used for narrow remainder
  strips
- BestFitCache.Populate: skip caching empty result lists so stale
  pre-computed data from nest files doesn't prevent recomputation

Also fixes console --size parsing to use LxW format matching
Size.Parse convention, and includes prior engine refactoring
(sequential fill loops, parallel FillPattern, pre-sorted edge
arrays in RotationSlideStrategy).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 01:14:07 -04:00
6993d169e4 perf(core): optimize geometry with edge pruning and vertex dedup
Vector implements IEquatable<Vector> with proper GetHashCode for HashSet usage.
Polygon.FindCrossing uses bounding-box pruning to skip non-overlapping edge pairs.
Helper.DirectionalDistance deduplicates vertices via HashSet, sorts edges for
early-exit pruning, and adds a new array-based overload that avoids allocations.
PartBoundary sorts directional edges and exposes GetEdges for zero-alloc access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:51:44 -04:00
a9aaab8337 refactor: use ShapeProfile perimeter for boundary and intersection
Replace shape-list iteration with ShapeProfile.Perimeter in both
Part.Intersects and PartBoundary, simplifying the logic and ensuring
only the outermost contour is used for collision detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 12:41:03 -04:00
65ded42120 feat(core): add Program.ToString() and fix sub-program rotation origin
Add G-code serialization via ToString() for debugging/ML workflows.
Fix Rotate(angle, origin) to propagate origin to sub-programs instead
of calling the single-argument overload.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 12:40:57 -04:00
1a9bd795a8 perf(core): share Program instance in CloneAtOffset
Offset-only copies don't modify program codes, so sharing the instance
avoids expensive cloning during large pattern tiling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:14:21 -04:00
b509a4139d refactor: optimize directional distance for GPU-friendly batching
Add primitive-parameter RayEdgeDistance overload with AggressiveInlining,
merge Left/Right and Up/Down cases. Add DirectionalDistance overload that
accepts (dx, dy) translation without creating Line objects, and FlattenLines
for packing segments into flat arrays for GPU transfer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 20:29:36 -04:00
bc3f1543ee refactor: extract FindCrossing and SplitAtCrossing from RemoveSelfIntersections
Break deeply nested loop structure into focused helper methods,
reducing max nesting from 5 levels to 2. Uses GetRange/AddRange
for cleaner loop building.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:20:11 -04:00
6b0bafc9de merge: integrate NFP-based autonesting from feature/nfp-autonest
Brings in the full NFP implementation: ConvexDecomposition, NoFitPolygon,
InnerFitPolygon, NfpCache, BottomLeftFill, SimulatedAnnealing optimizer,
and INestOptimizer interface. Resolves conflicts by keeping master's
progress reporting infrastructure alongside the new AutoNest methods,
and adapting RunAutoNest_Click to use NFP AutoNest with async/cancellation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:40:38 -04:00
09fc8b889e fix: close polygon offset shape and handle nest template load failure
Shape.OffsetEntity computed joins between consecutive offset segments
but never joined the last segment back to the first, leaving the
closing corner with a straight line instead of a proper miter/arc.
Track the first entity and apply the same join logic after the loop.

Also wrap nest template loading in try-catch so a corrupt template
file doesn't crash the app on startup — falls back to default nest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 07:37:39 -04:00
c68139e15e merge: resolve .gitignore conflict, keep both entries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 07:22:45 -04:00
66b3aeafc1 fix: correct inverted quadrant-to-exit-point mapping in GetExitPoint
The exit point should be the corner farthest from the origin so the
perimeter (cut last) ends near the machine home. The mapping was
backwards — Q1 (origin bottom-left) was returning (0,0) instead of
(w,l).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:59:04 -04:00
616575e0ee feat: wire contour re-indexing into ContourCuttingStrategy.Apply()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 23:57:17 -04:00
2b4cb849ba feat: add Shape.ReindexAt(Vector, Entity) for contour reordering
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 23:54:54 -04:00
3de44a7293 feat: add Arc.SplitAt(Vector) splitting primitive 2026-03-12 23:53:25 -04:00
b2ff704b73 feat: add Line.SplitAt(Vector) splitting primitive 2026-03-12 23:53:23 -04:00
441628eff2 feat: add ContourCuttingStrategy orchestrator
Exit point from plate quadrant, nearest-neighbor cutout
sequencing via ShapeProfile + ClosestPointTo, contour type
detection, and normal angle computation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:15:38 -04:00
ac7d90ae17 feat: add CuttingParameters and configuration classes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:13:36 -04:00
459738e373 feat: add Tab hierarchy (4 classes)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:13:31 -04:00
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
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
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
d0d334e734 fix: use chain tolerance for shape building to handle DXF endpoint gaps
DXF files can have endpoint gaps at entity junctions that fall right at
the floating-point boundary of Tolerance.Epsilon (0.00001). This caused
shapes to not close, resulting in 0 area and 0% utilization in Best-Fit.

Added ChainTolerance (0.0001) for endpoint chaining in GetConnected and
Shape.IsClosed, keeping the tighter Epsilon for geometric precision.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:37:39 -04:00