feat: overhaul SplitDrawingForm — EntityView, draggable feature handles, UI fixes

- Replace raw Panel with EntityView (via SplitPreview subclass) for proper
  zoom-to-point, middle-button pan, and double-buffered rendering
- Add draggable handles for tab/spike positions along split lines; positions
  flow through to WeldGapTabSplit and SpikeGrooveSplit via SplitLine.FeaturePositions
- Fix OK/Cancel buttons hidden off-screen by putting them in a bottom-docked panel
- Fix DrawControl not invalidating on resize
- Swap plate Width/Length label order, default edge spacing to 0.5
- Rename tab labels: Tab Width→Tab Length, Tab Height→Weld Gap, default count 2
- Spike depth now calculated (read-only), groove depth means positioning depth
  beyond spike tip (default 0.125), converted to total depth internally
- Set entity layers visible so EntityView renders them

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 14:26:43 -04:00
parent ba7aa39941
commit cd8adc97d6
12 changed files with 1118 additions and 743 deletions

View File

@@ -26,15 +26,19 @@ public class SpikeGrooveSplit : ISplitFeature
var isVertical = line.Axis == CutOffAxis.Vertical;
var pos = line.Position;
// Place pairs evenly: one near each end, with margin
var margin = extent * 0.15;
// Use custom positions if provided, otherwise place evenly with margin
var pairPositions = new List<double>();
if (pairCount == 1)
if (line.FeaturePositions.Count > 0)
{
pairPositions.AddRange(line.FeaturePositions);
}
else if (pairCount == 1)
{
pairPositions.Add(extentStart + extent / 2);
}
else
{
var margin = extent * 0.15;
var usable = extent - 2 * margin;
for (var i = 0; i < pairCount; i++)
pairPositions.Add(extentStart + margin + usable * i / (pairCount - 1));

View File

@@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace OpenNest;
/// <summary>
@@ -9,6 +11,13 @@ public class SplitLine
public double Position { get; }
public CutOffAxis Axis { get; }
/// <summary>
/// Optional custom center positions for features (tabs/spikes) along the split line.
/// Values are absolute coordinates on the perpendicular axis.
/// When empty, feature generators use their default even spacing.
/// </summary>
public List<double> FeaturePositions { get; set; } = new();
public SplitLine(double position, CutOffAxis axis)
{
Position = position;

View File

@@ -18,8 +18,18 @@ public class WeldGapTabSplit : ISplitFeature
var tabWidth = parameters.TabWidth;
var tabHeight = parameters.TabHeight;
// Evenly space tabs along the split line
var spacing = extent / (tabCount + 1);
// Use custom positions if provided, otherwise evenly space
var tabCenters = new List<double>();
if (line.FeaturePositions.Count > 0)
{
tabCenters.AddRange(line.FeaturePositions);
}
else
{
var spacing = extent / (tabCount + 1);
for (var i = 0; i < tabCount; i++)
tabCenters.Add(extentStart + spacing * (i + 1));
}
var negEntities = new List<Entity>();
var isVertical = line.Axis == CutOffAxis.Vertical;
@@ -30,9 +40,9 @@ public class WeldGapTabSplit : ISplitFeature
var cursor = extentStart;
for (var i = 0; i < tabCount; i++)
for (var i = 0; i < tabCenters.Count; i++)
{
var tabCenter = extentStart + spacing * (i + 1);
var tabCenter = tabCenters[i];
var tabStart = tabCenter - tabWidth / 2;
var tabEnd = tabCenter + tabWidth / 2;