Files
OpenNest/OpenNest.Tests/TestLeadIns.cs
T
ajandClaude Opus 5.5 8c7dc41ce8 feat(planning): warn about tipping parts and retire legacy lead-in assignment
Plan Cutting is now the only automatic lead-in assignment, and parts the
support grid cannot hold level are reported wherever they lack a
steadying tab.

- Remove Assign Lead-ins (plate and nest), LeadInAssigner, the lead-in
  tool's Auto-Assign button and the Auto Tab size range; old settings
  with autoTab sizes still load
- Manual Place Lead-in tabs the clicked entry when support tabs are on
  and the grid cannot hold the part (SupportTabSettings)
- New PartSupport finding: Plan Cutting replay and best-effort plans
  warn when a drawing pin, a lead-in that does not fit or no single tab
  leaves a part unsteady; the pre-post review checks each placed
  program's outside tab gap. These warnings replace the advisory
  weak-tab notes; only the inside-corner tab note stays advisory, and
  never for a pin
- Pinned perimeters keep their pin but carry the support analysis
- Draw grid points as pixel-snapped squares without anti-aliasing
- Post fixtures build lead-ins through a test-only TestLeadIns helper
- Docs: support tabs, pre-post verification and planner notes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 23:54:40 -04:00

58 lines
2.0 KiB
C#

using OpenNest.CNC;
using OpenNest.Engine.Sequencing;
using OpenNest.Geometry;
namespace OpenNest.Tests;
/// <summary>
/// Gives every unlocked part on a plate its lead-ins from the plate's cutting parameters, left
/// to right, the way the retired Assign Lead-ins command did. Post fixtures use it to build
/// programs with lead-ins without running Plan Cutting, so their expected output is unchanged.
/// </summary>
internal static class TestLeadIns
{
public static void Apply(Plate plate)
{
var parameters = plate.CuttingParameters;
if (parameters == null)
return;
var sequenced = new LeftSideSequencer().Sequence(plate.Parts.ToList(), plate);
var exitPoint = PlateHelper.GetExitPoint(plate);
// The first pass fixes each part's pierce; the second faces each part toward the next pierce.
var piercePoints = Pass(null);
Pass(piercePoints);
Vector[] Pass(Vector[] nextPiercePoints)
{
var pierces = new Vector[sequenced.Count];
var current = exitPoint;
for (var i = 0; i < sequenced.Count; i++)
{
var part = sequenced[i].Part;
if (!part.LeadInsLocked)
{
if (part.HasManualLeadIns)
part.RemoveLeadIns();
var approach = current - part.Location;
if (nextPiercePoints != null && i + 1 < sequenced.Count)
part.ApplyLeadIns(parameters, approach, nextPiercePoints[i + 1] - part.Location);
else
part.ApplyLeadIns(parameters, approach);
}
pierces[i] = Pierce(part);
current = part.Location;
}
return pierces;
}
}
private static Vector Pierce(Part part)
{
foreach (var code in part.Program.Codes)
if (code is Motion motion)
return motion.EndPoint + part.Location;
return part.Location;
}
}