When TabsEnabled is set, trims the end of each contour using a circle
centered at the lead-in point with radius equal to the tab size. The
uncut gap between the trim point and the contour start keeps the part
connected to the sheet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The offset direction (start→pierce) is reversed from the approach
direction (pierce→start), so the old formula produced 180°−angle
instead of the requested angle. Invisible at the 90° default but
caused 45° to render as 135°.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Scribe/etch lines were being treated as cut contours by
ContourCuttingStrategy, receiving lead-ins and kerf compensation.
Now they are separated before ShapeProfile construction and emitted
as plain moves with LayerType.Scribe preserved.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Clears all manual lead-ins from every part on the active plate and
rebuilds the layout graphics.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Save/restore cutting parameters as JSON in user settings so values
survive between sessions. Add pierce clearance numeric input to the
CuttingParametersForm.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scales down lead-ins that would place the pierce point too close to the
opposite wall of small holes. Uses quadratic solve to find the maximum
safe distance inside a clearance-reduced radius. Adds Scale() method to
all LeadIn types and applies clamping in both the strategy and the
interactive preview.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three issues caused incorrect rendering after lead-in application:
- Rapid move entities from ToGeometry() were included in ShapeProfile
contour detection, turning traversal paths into cutting moves
- Program created with Mode.Incremental default made the absolute-to-
incremental conversion a no-op, leaving coordinates unconverted
- AddProgramSplit didn't call StartFigure() at rapid moves, causing
GraphicsPath to draw implicit connecting lines between contours
- Part.Rotation returned 0 from the new program instead of the actual
rotation, displacing the sequence label on rotated parts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructure the cutting parameters dialog with separate Lead-In and
Lead-Out GroupBoxes per tab, exposing editable length/angle/radius
fields for lead-outs (previously hardcoded). Add Tabs section with
enable checkbox and width control. Also fix lead-in/lead-out angle
calculations and convert cutting strategy output to incremental mode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a text-only toolbar button to the Plates tab that opens the
CuttingParametersForm, saves the chosen parameters on the plate, and
runs LeadInAssigner with LeftSideSequencer to auto-assign lead-ins.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add GetGraphicsPaths/AddProgramSplit to GraphicsHelper that builds separate
GraphicsPath objects for cut vs lead-in/lead-out codes, skipping suppressed
codes. Update LayoutPart to use split paths when HasManualLeadIns is set,
drawing lead-in geometry in yellow regardless of selection state.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds LayerType.Leadout to all LinearMove and ArcMove instances produced
by LineLeadOut and ArcLeadOut Generate() methods.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds LayerType.Leadin to all LinearMove and ArcMove instances produced
by LineLeadIn, ArcLeadIn, LineArcLeadIn, CleanHoleLeadIn, and
LineLineLeadIn Generate() methods, plus tests covering all subclasses.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds Suppressed bool to the Motion base class so LinearMove, ArcMove,
and RapidMove can be flagged for skip during rendering and post-processing
when they fall within a tab gap. Clone() updated on all three subclasses
to preserve the flag. Covered by new MotionSuppressedTests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add radius-based arc feedrate calculation (Variables/Percentages modes)
with configurable radius ranges (#123/#124/#125 or inline expressions)
- Fix arc distance in SpeedClassifier using actual arc length instead of
chord length (full circles previously computed as zero)
- Fix G89 P spacing: P now adjacent to filename per CL-707 manual syntax
- Add lead-out feedrate support (#129) and arc lead-in feedrate (#127)
- Fix pallet exchange: StartAndEnd emits M50 in preamble + last sheet only
- Add G121 Smart Rapids emission when UseSmartRapids is enabled
- Add G90 absolute mode to main program preamble alongside G20/G21
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add ArcFit.FitWithDualTangent to constrain replacement arcs to match
tangent directions at both endpoints, preventing kinks without
introducing gaps. Add DXF year selection to CAD converter export.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove pass-through wrappers (FitWithStartTangent, MaxRadialDeviation), extract
PerpendicularDistance and NormalizeAngle helpers to deduplicate mirror axis math,
convert GetExitDirection to switch expression, and simplify ComputeEndTangent.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change Nest() to decide fill vs pack based on total area coverage
instead of qty != 1. Items covering < 10% of the plate are packed,
so large parts get prime position and small low-qty parts fill gaps.
Qty=2 items are placed as interlocking best-fit pairs in remnant
spaces after the main pack phase, rather than as separate rectangles.
- Add ShouldFill() capacity-based heuristic
- Split pack phase: regular items pack first, then pairs
- Add PlaceBestFitPairs() for Phase 3 remnant pair placement
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
For qty 1-2, skip the full 6-strategy pipeline: place a single part
or a best-fit pair directly. For larger low quantities, shrink the
work area in both dimensions (sqrt scaling with 2x margin) before
running strategies, with fallback to full area if insufficient.
- Add TryFillSmallQuantity fast path (qty=1 single, qty=2 best-fit pair)
- Add ShrinkWorkArea with proportional dual-axis reduction
- Extract RunFillPipeline helper from Fill()
- Make ShrinkFiller.EstimateStartBox internal with margin parameter
- Add MaxQuantity to FillContext for strategy-level access
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Break the 113-line click handler into single-responsibility methods:
RunAutoNestAsync, GetOrCreatePlate, NestSinglePlateAsync, and
CreatePreviewPlate (eliminates duplicated plate-cloning code).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
- Skip ExtentsFillStrategy for rectangle/circle parts
- Skip PairsFillStrategy for circle parts
- PackBottomLeft now tries rotated orientation when items don't fit
- PackBottomLeft tries both area-descending and length-descending sort
orders, keeping whichever places more parts (tighter bbox on tie)
- Add user constraint override tests for AngleCandidateBuilder
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace RotationAnalysis.FindBestRotation with PartClassifier.Classify in
RunPipeline, propagate ClassificationResult through BuildAngles signatures and
FillContext.PartType, and rewrite AngleCandidateBuilder to dispatch on part type
(Circle=1 angle, Rectangle=2, Irregular=full sweep).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covers all 9 cases: pure rectangle, rounded rectangle, rect with notch,
circle, L-shape, triangle, serrated edge (perimeter ratio), tilted rect
(primary angle), and empty drawing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OffsetOutward now normalizes to CW winding before offsetting instead of
trial-and-error with bounding box comparison. CadConverterForm designer
regenerated with new entityView1 properties.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>
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>
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>
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>
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>
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>
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>
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>