diff --git a/OpenNest.Core/Splitting/AutoSplitCalculator.cs b/OpenNest.Core/Splitting/AutoSplitCalculator.cs index bebced2..af36b12 100644 --- a/OpenNest.Core/Splitting/AutoSplitCalculator.cs +++ b/OpenNest.Core/Splitting/AutoSplitCalculator.cs @@ -19,19 +19,11 @@ public static class AutoSplitCalculator if (verticalSplits < 0) verticalSplits = 0; if (horizontalSplits < 0) horizontalSplits = 0; - if (verticalSplits > 0) - { - var spacing = partBounds.Width / (verticalSplits + 1); - for (var i = 1; i <= verticalSplits; i++) - lines.Add(new SplitLine(partBounds.X + spacing * i, CutOffAxis.Vertical)); - } + for (var i = 1; i <= verticalSplits; i++) + lines.Add(new SplitLine(partBounds.X + usableWidth * i, CutOffAxis.Vertical)); - if (horizontalSplits > 0) - { - var spacing = partBounds.Length / (horizontalSplits + 1); - for (var i = 1; i <= horizontalSplits; i++) - lines.Add(new SplitLine(partBounds.Y + spacing * i, CutOffAxis.Horizontal)); - } + for (var i = 1; i <= horizontalSplits; i++) + lines.Add(new SplitLine(partBounds.Y + usableHeight * i, CutOffAxis.Horizontal)); return lines; } diff --git a/OpenNest.Tests/Splitting/SplitLineTests.cs b/OpenNest.Tests/Splitting/SplitLineTests.cs index 69b7065..1256930 100644 --- a/OpenNest.Tests/Splitting/SplitLineTests.cs +++ b/OpenNest.Tests/Splitting/SplitLineTests.cs @@ -42,7 +42,7 @@ public class AutoSplitCalculatorTests Assert.Single(lines); Assert.Equal(CutOffAxis.Vertical, lines[0].Axis); - Assert.Equal(50.0, lines[0].Position, 1); + Assert.Equal(58.0, lines[0].Position, 1); } [Fact] diff --git a/OpenNest/Forms/SplitDrawingForm.cs b/OpenNest/Forms/SplitDrawingForm.cs index 1a11fef..6512c80 100644 --- a/OpenNest/Forms/SplitDrawingForm.cs +++ b/OpenNest/Forms/SplitDrawingForm.cs @@ -18,6 +18,7 @@ public partial class SplitDrawingForm : Form private readonly List _splitLines = new(); private CutOffAxis _currentAxis = CutOffAxis.Vertical; private bool _placingLine; + private Vector _placingCursor; // Feature handle drag state private int _dragLineIndex = -1; @@ -78,12 +79,8 @@ public partial class SplitDrawingForm : Form if (usable > 0) { var splits = (int)System.Math.Ceiling(_drawingBounds.Width / usable) - 1; - if (splits > 0) - { - var step = _drawingBounds.Width / (splits + 1); - for (var i = 1; i <= splits; i++) - _splitLines.Add(new SplitLine(_drawingBounds.X + step * i, CutOffAxis.Vertical)); - } + for (var i = 1; i <= splits; i++) + _splitLines.Add(new SplitLine(_drawingBounds.X + usable * i, CutOffAxis.Vertical)); } } else if (axisIndex == 2) @@ -92,12 +89,8 @@ public partial class SplitDrawingForm : Form if (usable > 0) { var splits = (int)System.Math.Ceiling(_drawingBounds.Length / usable) - 1; - if (splits > 0) - { - var step = _drawingBounds.Length / (splits + 1); - for (var i = 1; i <= splits; i++) - _splitLines.Add(new SplitLine(_drawingBounds.Y + step * i, CutOffAxis.Horizontal)); - } + for (var i = 1; i <= splits; i++) + _splitLines.Add(new SplitLine(_drawingBounds.Y + usable * i, CutOffAxis.Horizontal)); } } else @@ -293,6 +286,12 @@ public partial class SplitDrawingForm : Form } } + if (_placingLine) + { + _placingCursor = SnapToMidpoint(worldPt); + pnlPreview.Invalidate(); + } + lblCursor.Text = $"Cursor: {worldPt.X:F2}, {worldPt.Y:F2}"; } @@ -339,6 +338,7 @@ public partial class SplitDrawingForm : Form if (keyData == Keys.Space) { _currentAxis = _currentAxis == CutOffAxis.Vertical ? CutOffAxis.Horizontal : CutOffAxis.Vertical; + pnlPreview.Invalidate(); return true; } if (keyData == Keys.Escape) @@ -381,10 +381,11 @@ public partial class SplitDrawingForm : Form System.Math.Abs(br.X - tl.X), System.Math.Abs(br.Y - tl.Y)); } - // Piece number labels at center of each region + // Piece number and dimension labels at center of each region if (regions.Count > 1) { using var labelFont = new Font("Segoe UI", 14f, FontStyle.Bold, GraphicsUnit.Pixel); + using var dimFont = new Font("Segoe UI", 11f, FontStyle.Regular, GraphicsUnit.Pixel); using var labelBrush = new SolidBrush(Color.FromArgb(200, 255, 255, 255)); using var shadowBrush = new SolidBrush(Color.FromArgb(160, 0, 0, 0)); var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; @@ -394,10 +395,13 @@ public partial class SplitDrawingForm : Form var r = regions[i]; var center = pnlPreview.PointWorldToGraph(r.Center.X, r.Center.Y); var label = (i + 1).ToString(); + var dim = $"{r.Width:F2} x {r.Length:F2}"; // Shadow offset for readability - g.DrawString(label, labelFont, shadowBrush, center.X + 1, center.Y + 1, sf); - g.DrawString(label, labelFont, labelBrush, center.X, center.Y, sf); + g.DrawString(label, labelFont, shadowBrush, center.X + 1, center.Y - 7, sf); + g.DrawString(label, labelFont, labelBrush, center.X, center.Y - 8, sf); + g.DrawString(dim, dimFont, shadowBrush, center.X + 1, center.Y + 9, sf); + g.DrawString(dim, dimFont, labelBrush, center.X, center.Y + 8, sf); } } @@ -469,6 +473,33 @@ public partial class SplitDrawingForm : Form } } + // Placement preview line + if (_placingLine && _placingCursor != null) + { + var isVert = _currentAxis == CutOffAxis.Vertical; + var snapped = _placingCursor; + var pos = isVert ? snapped.X : snapped.Y; + var margin = 10.0; + + PointF pp1, pp2; + if (isVert) + { + pp1 = pnlPreview.PointWorldToGraph(pos, _drawingBounds.Bottom - margin); + pp2 = pnlPreview.PointWorldToGraph(pos, _drawingBounds.Top + margin); + } + else + { + pp1 = pnlPreview.PointWorldToGraph(_drawingBounds.Left - margin, pos); + pp2 = pnlPreview.PointWorldToGraph(_drawingBounds.Right + margin, pos); + } + + using var previewPen = new Pen(Color.FromArgb(180, 255, 213, 79), 1.5f); + previewPen.DashStyle = DashStyle.DashDot; + g.DrawLine(previewPen, pp1, pp2); + + + } + // Feature position handles if (!radStraight.Checked) {