Parts were not redrawn after AssignLeadIns because their LayoutPart
graphics paths were stale.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cover assign, remove, re-assign, multiple rotations, and external
HasManualLeadIns scenarios to verify rotation is preserved throughout
the lead-in lifecycle.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Track preLeadInRotation when parts are rotated so lead-in removal
can restore the correct rotation. Remove stale HasManualLeadIns and
LeadInsLocked deserialization from NestReader since these flags are
transient state, not persisted data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove LeadInsLocked guard so parts can be re-selected for lead-in
re-placement. Change preview color from yellow to magenta for better
visibility against the cyan contour highlight.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CCW arcs (e.g. the top of a U-slot) had the radial normal pointing
into the part material instead of into the scrap. This caused the
lead-in preview to flip sides on concave features.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Decorate all properties with [Category], [DisplayName], and [Description]
attributes for use in the WinForms PropertyGrid config dialog. Reorder
properties to match category grouping (1. Output through B. Libraries)
and replace property-level XML doc comments with the attribute descriptions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Part.Program stores coordinates relative to the part's own origin, but
the Cincinnati post processor emits G90 (absolute positioning). Inline
features were writing part-relative coordinates directly without adding
Part.Location, producing incorrect output. Sub-program mode was
unaffected because it uses G92 to set up local coordinate systems.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>