RapidEnumerator primed the walk position at the first pierce point, then the skipped first rapid advanced it again. Raw programs start with a zero rapid so this was invisible, but lead-in programs start with a real incremental offset to the pierce, which shifted every later rapid by that delta and drew rapids off the sheet. Start the walk at the program origin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
117 lines
4.7 KiB
C#
117 lines
4.7 KiB
C#
using OpenNest.CNC;
|
|
using OpenNest.Geometry;
|
|
using Xunit;
|
|
|
|
namespace OpenNest.Tests.CNC
|
|
{
|
|
public class RapidEnumeratorTests
|
|
{
|
|
[Fact]
|
|
public void Enumerate_AbsoluteProgram_OffsetsMotionsByBasePos()
|
|
{
|
|
var pgm = new Program(Mode.Absolute);
|
|
pgm.Codes.Add(new RapidMove(1, 0));
|
|
pgm.Codes.Add(new LinearMove(2, 0));
|
|
pgm.Codes.Add(new RapidMove(3, 3));
|
|
|
|
var segments = RapidEnumerator.Enumerate(
|
|
pgm,
|
|
basePos: new Vector(100, 200),
|
|
startPos: new Vector(0, 0)
|
|
);
|
|
|
|
// Origin → first pierce, then interior rapid from contour end to next rapid target.
|
|
Assert.Equal(2, segments.Count);
|
|
Assert.Equal(new Vector(0, 0), segments[0].From);
|
|
Assert.Equal(new Vector(101, 200), segments[0].To);
|
|
Assert.Equal(new Vector(102, 200), segments[1].From);
|
|
Assert.Equal(new Vector(103, 203), segments[1].To);
|
|
}
|
|
|
|
[Fact]
|
|
public void Enumerate_IncrementalProgram_InterpretsDeltasFromBasePos()
|
|
{
|
|
// Pre-lead-in raw program: first rapid normalized to (0,0), Mode=Incremental
|
|
// (matches ConvertGeometry.ToProgram output).
|
|
var pgm = new Program(Mode.Incremental);
|
|
pgm.Codes.Add(new RapidMove(0, 0));
|
|
pgm.Codes.Add(new LinearMove(5, 0));
|
|
pgm.Codes.Add(new LinearMove(0, 5));
|
|
pgm.Codes.Add(new RapidMove(1, 1));
|
|
|
|
var segments = RapidEnumerator.Enumerate(
|
|
pgm,
|
|
basePos: new Vector(100, 200),
|
|
startPos: new Vector(0, 0)
|
|
);
|
|
|
|
Assert.Equal(2, segments.Count);
|
|
// First rapid: plate origin → part pierce at basePos.
|
|
Assert.Equal(new Vector(0, 0), segments[0].From);
|
|
Assert.Equal(new Vector(100, 200), segments[0].To);
|
|
// Interior rapid: after deltas (5,0) and (0,5) from basePos, rapid delta (1,1).
|
|
Assert.Equal(new Vector(105, 205), segments[1].From);
|
|
Assert.Equal(new Vector(106, 206), segments[1].To);
|
|
}
|
|
|
|
[Fact]
|
|
public void Enumerate_IncrementalProgramWithNonZeroFirstRapid_DoesNotDoubleCountIt()
|
|
{
|
|
// Lead-in programs (ContourCuttingStrategy output) are Incremental and
|
|
// start with a nonzero rapid from the part origin to the first pierce.
|
|
var pgm = new Program(Mode.Incremental);
|
|
pgm.Codes.Add(new RapidMove(2, 3));
|
|
pgm.Codes.Add(new LinearMove(5, 0));
|
|
pgm.Codes.Add(new RapidMove(1, 1));
|
|
|
|
var segments = RapidEnumerator.Enumerate(
|
|
pgm,
|
|
basePos: new Vector(100, 200),
|
|
startPos: new Vector(0, 0)
|
|
);
|
|
|
|
Assert.Equal(2, segments.Count);
|
|
Assert.Equal(new Vector(102, 203), segments[0].To);
|
|
Assert.Equal(new Vector(107, 203), segments[1].From);
|
|
Assert.Equal(new Vector(108, 204), segments[1].To);
|
|
}
|
|
|
|
[Fact]
|
|
public void Enumerate_SubProgramCall_RapidEndsAtAbsoluteHolePierce()
|
|
{
|
|
// Main program: lead-in rapid, a line, then a SubProgramCall for a hole.
|
|
// Sub-program (incremental) starts with RapidMove(radius, 0) to the hole pierce.
|
|
var sub = new Program(Mode.Incremental);
|
|
sub.Codes.Add(new RapidMove(0.5, 0));
|
|
sub.Codes.Add(new LinearMove(0, 0.1));
|
|
|
|
var pgm = new Program(Mode.Absolute);
|
|
pgm.Codes.Add(new RapidMove(0.2, 0.3)); // first pierce (perimeter lead-in)
|
|
pgm.Codes.Add(new LinearMove(1.0, 1.0)); // contour move
|
|
pgm.Codes.Add(
|
|
new SubProgramCall
|
|
{
|
|
Id = 1,
|
|
Program = sub,
|
|
Offset = new Vector(2, 2), // hole center (drawing-local)
|
|
}
|
|
);
|
|
|
|
var basePos = new Vector(100, 200); // part.Location
|
|
var segments = RapidEnumerator.Enumerate(pgm, basePos, startPos: new Vector(0, 0));
|
|
|
|
// Expected rapids:
|
|
// 1. origin → first pierce (0.2+100, 0.3+200) = (100.2, 200.3)
|
|
// 2. end of contour (1+100, 1+200) = (101, 201) → hole pierce (2+100+0.5, 2+200) = (102.5, 202)
|
|
// The sub's internal first rapid is skipped (already drawn in #2).
|
|
Assert.Equal(2, segments.Count);
|
|
|
|
Assert.Equal(new Vector(0, 0), segments[0].From);
|
|
Assert.Equal(new Vector(100.2, 200.3), segments[0].To);
|
|
|
|
Assert.Equal(new Vector(101, 201), segments[1].From);
|
|
Assert.Equal(new Vector(102.5, 202), segments[1].To);
|
|
}
|
|
}
|
|
}
|