Add argument validation to EllipseConverter.Convert for tolerance and
semi-axis parameters. Narrow bare catch in Extensions.cs spline method
to log via Debug.WriteLine. Remove unused lineCount variable from
SolidWorksBendDetectorTests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add EllipseConverter static class with foundational methods for converting
ellipse parameters to circular arcs: EvaluatePoint, EvaluateTangent,
EvaluateNormal, and IntersectNormals. All 8 unit tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New EngineOverlapTests verifies all engine types produce overlap-free
results. New StrategyOverlapTests checks each fill strategy individually.
StripeFillerTests updated to verify returned parts are overlap-free
rather than just asserting non-empty results. Remove obsolete FitCircle
tests from GeometrySimplifierTests (method was removed).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Geometry Simplifier:
- Replace least-squares circle fitting with mirror axis algorithm
that constrains center to perpendicular bisector of chord, guaranteeing
zero-gap endpoint connectivity by construction
- Golden section search optimizes center position along the axis
- Increase default tolerance from 0.005 to 0.5 for practical CNC use
- Support existing arcs in simplification runs (sample arc points to
find larger replacement arcs spanning lines + arcs together)
- Add tolerance zone visualization (offset original geometry ±tolerance)
- Show original geometry overlay with orange dashed lines in preview
- Add "Original" checkbox to CadConverter for comparing old vs new
- Store OriginalEntities on FileListItem to prevent tolerance creep
when re-running simplifier with different settings
Bend Detection:
- Propagate bend notes to collinear bend lines split by cutouts
using infinite-line perpendicular distance check
- Add bend note text rendering in EntityView at bend line midpoints
DXF Import:
- Fix trimmed ellipse closing chord: only close when sweep ≈ 2π,
preventing phantom lines through slot cutouts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Foundation for the geometry simplifier that will replace consecutive line
segments with fitted arcs. Adds ArcCandidate data class, GeometrySimplifier
with stub Analyze/Apply methods, and FitCircle using the Kasa algebraic
least-squares method. Also adds InternalsVisibleTo for OpenNest.Tests on
OpenNest.Core.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DxfImporter now filters ETCH entities (like BEND) since etch marks are
generated from bends during export, not cut geometry. GeometryOptimizer
no longer merges lines/arcs across different layers and preserves layer
and color on merged entities. EntityView draws etch marks directly from
the Bends list so they remain visible without relying on imported ETCH
entities.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consolidate duplicated static methods (SplitFeatures, ComputeCutDistance,
IsFeatureEtch, feature ordering) from CincinnatiSheetWriter and
CincinnatiPartSubprogramWriter into a shared FeatureUtils class. Move
inline sub-program registry building from Post() into
CincinnatiPartSubprogramWriter.BuildRegistry().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
After splitting a drawing with a circular hole, CadConverterForm writes
the split piece to DXF and re-imports it. The circle (decomposed into
two semicircular arcs by DrawingSplitter) was being incorrectly merged
back into a single zero-sweep arc by GeometryOptimizer.TryJoinArcs
during reimport.
Root cause: TryJoinArcs mutated input arc angles in-place and didn't
guard against merging two arcs that together form a full circle. When
arc2 had startAngle=π, endAngle=0 (DXF wrap-around from 360°→0°), the
mutation produced startAngle=-π, and the merge created an arc with
startAngle=π, endAngle=π (zero sweep), losing half the hole.
Fix: use local variables instead of mutating inputs, require arcs to be
adjacent (endpoints touching) rather than just overlapping, and refuse
to merge when the combined sweep would be a full circle.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FitToPlate now places split lines at usable-width intervals so each
piece (except the last) fills the entire plate work area. Also adds a
live yellow preview line that follows the cursor during manual split
line placement, and piece dimension labels in the preview regions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DrawingSplitter now clips bend lines to each piece's region using
Liang-Barsky line clipping and offsets them to the new origin. Bend
properties (direction, angle, radius, note text) are preserved through
the entire split pipeline instead of being lost during re-import.
CadConverterForm applies the same origin offset to bends before passing
them to the splitter, and creates FileListItems directly from split
results to avoid re-detection overwriting the bend metadata.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces a pluggable bend detection system in OpenNest.IO.Bending:
- IBendDetector takes CadDocument directly to preserve MText/layer/linetype info
- SolidWorksBendDetector finds lines on BEND layer with CENTER linetype and matches nearby MText notes
- BendDetectorRegistry auto-registers SolidWorks detector and supports AutoDetect
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces OpenNest.Core/Bending/ with Bend and BendDirection types as
the foundation for bend line detection. Includes 6 passing unit tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace polygon boolean clipping with direct entity splitting using
bounding box filtering and exact intersection math. Eliminates Clipper2
precision drift that caused contour gaps (0.0035") breaking area
calculation and ShapeBuilder chaining.
Also fixes SpikeGrooveSplit: spike depth is now grooveDepth + weldGap
(spike protrudes past groove), both V-shapes use same angle formula,
and weldGap no longer double-subtracted from tip depth.
SplitDrawingForm: fix parameter mapping (GrooveDepth direct from nud,
not inflated), remove redundant Spike Depth display, add feature
contour preview and trimmed split lines at feature positions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add ToLine() to SplitLine and create SplitLineIntersect static class with
FindIntersection, CrossesSplitLine, and SideOf methods for testing entity
intersections against split lines. These helpers support the upcoming
Clipper2-free DrawingSplitter rewrite.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the main drawing splitting algorithm that orchestrates splitting
a Drawing into multiple pieces along split lines using Clipper2 polygon
clipping. After clipping, recovers original arcs by matching clipped edges
back to perimeter entities, stitches in feature edges from ISplitFeature
where polygon edges lie on split lines, and normalizes each piece's origin.
Key fix from plan: filters rapid-layer entities before ShapeProfile
construction so cutouts are properly separated from perimeters.
Includes 7 integration tests covering vertical/horizontal splits, three-way
splits, property copying, origin normalization, cutout assignment, and
grid (cross) splits.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add MaterialLibraryResolver for Cincinnati post processor to resolve
G89 library files from material/thickness/gas configuration
- Add Nest.AssistGas property with serialization support in nest format
- Add etch library support with separate gas configuration
- Fix CutOff tests to match AwayFromOrigin default cut direction
- Fix plate info label not updating after ResizePlateToFitParts
- Add cutoff and remnants toolbar button icons
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PolygonHelper.ExtractPerimeterPolygon always used OffsetSide.Right
assuming CCW winding, but DXF imports can produce CW winding. This
caused the spacing polygon to shrink inward instead of expanding
outward, making parts overlap during nesting.
Now detects winding direction via polygon signed area and selects
the correct OffsetSide accordingly.
Also adds save_nest MCP tool and a BOM-to-nest builder utility
(tools/NestBuilder) for batch-creating nest files from Excel BOMs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
G-code output was concatenated without spaces (e.g. N1005G0X1.4375Y-0.6562).
Now emits standard spacing (N1005 G0 X1.4375 Y-0.6562) across all motion
commands, line numbers, kerf comp, feedrates, M-codes, and comments.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each unique part geometry (drawing + rotation) is written once as a
reusable sub-program called via M98, reducing output size for nests
with repeated parts. G92 coordinate repositioning handles per-instance
plate placement with restore after each call. Cut-offs remain inline.
Controlled by UsePartSubprograms (default false) and PartSubprogramStart
config properties.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move ProgramVariable and ProgramVariableManager from
OpenNest.Posts.Cincinnati to OpenNest.Core/CNC (namespace OpenNest.CNC)
so they can be used internally in nest programs
- Add parameterless constructor to CincinnatiPostProcessor that loads
config from a .json file next to the DLL (creates defaults on first run)
- Enums serialize as readable strings (e.g., "Inches", "ControllerSide")
- Config file: OpenNest.Posts.Cincinnati.json in the Posts/ directory
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use CultureInfo.InvariantCulture in CoordinateFormatter, SpeedClassifier,
and CincinnatiPreambleWriter to prevent locale-dependent G-code output
- Make CincinnatiPostConfig sealed per spec
- Fix SpeedClassifier.Classify threshold to >= (matching spec)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Orchestrates CincinnatiPreambleWriter and CincinnatiSheetWriter to produce
a complete Cincinnati CNC output file from a Nest; includes 4 integration tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract MakePoint/AxisBounds/CrossAxisBounds helpers in CutOff to
eliminate repeated axis-dependent branching
- Simplify BuildProgram loop from 4 code paths to 2
- Use static EmptyExclusions to avoid per-part list allocations
- Fix double event subscription in ActionCutOff constructor
- Dispose debounce timer in DisconnectEvents
- Remove redundant BuildPerimeterCache call in OnMouseDown
- Extract TotalCutLength test helper, remove duplicate test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace CutOff.BuildPerimeterCache (List<Shape>) with Plate.BuildPerimeterCache
(Dictionary<Part, Entity>) throughout. Consolidate two Regenerate overloads into
a single method with optional cache parameter. Fix Shape intersection bug where
non-intersecting entities added spurious Vector.Zero points to results.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Test drawings used CCW winding, causing OffsetSide.Left to produce
inward offsets. The BestFit pipeline then positioned pairs so actual
shapes overlapped, failing all 1232 candidates. Changed to CW winding
to match CNC convention where OffsetSide.Left = outward.
Also fixed EdgeStartSequencer test: centerPart at (25,55) was only 4.5
from the top edge (plate Y=60), closer than midPart at (10,10). Moved
to (25,25) for correct ordering.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>