feat: handle SubProgramCall offsets in BoundingBox and Rotate

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-09 14:47:40 -04:00
parent 09eac96a03
commit bc859aa28c
2 changed files with 51 additions and 1 deletions

View File

@@ -89,6 +89,17 @@ namespace OpenNest.CNC
{
var subpgm = (SubProgramCall)code;
if (subpgm.Offset.X != 0 || subpgm.Offset.Y != 0)
{
var cos = System.Math.Cos(angle);
var sin = System.Math.Sin(angle);
var dx = subpgm.Offset.X - origin.X;
var dy = subpgm.Offset.Y - origin.Y;
subpgm.Offset = new Geometry.Vector(
origin.X + dx * cos - dy * sin,
origin.Y + dx * sin + dy * cos);
}
if (subpgm.Program != null)
subpgm.Program.Rotate(angle, origin);
}
@@ -422,7 +433,10 @@ namespace OpenNest.CNC
case CodeType.SubProgramCall:
{
var subpgm = (SubProgramCall)code;
var box = subpgm.Program.BoundingBox(ref pos);
var subPos = subpgm.Offset.X != 0 || subpgm.Offset.Y != 0
? new Vector(subpgm.Offset.X, subpgm.Offset.Y)
: pos;
var box = subpgm.Program.BoundingBox(ref subPos);
if (box.Left < minX)
minX = box.Left;

View File

@@ -158,4 +158,40 @@ public class HoleSubProgramTests
// But different offsets
Assert.NotEqual(calls[0].Offset.X, calls[1].Offset.X);
}
[Fact]
public void Program_BoundingBox_IncludesSubProgramOffset()
{
var sub = new Program(Mode.Incremental);
sub.Codes.Add(new LinearMove(1, 0));
var main = new Program(Mode.Absolute);
main.SubPrograms[1] = sub;
main.Codes.Add(new SubProgramCall { Id = 1, Program = sub, Offset = new Vector(10, 20) });
var box = main.BoundingBox();
// Sub-program line goes from (10,20) to (11,20)
Assert.True(box.Right >= 11);
Assert.True(box.Top >= 20);
}
[Fact]
public void Program_Rotate_RotatesSubProgramCallOffsets()
{
var sub = new Program(Mode.Incremental);
sub.Codes.Add(new LinearMove(1, 0));
var main = new Program(Mode.Absolute);
main.SubPrograms[1] = sub;
main.Codes.Add(new SubProgramCall { Id = 1, Program = sub, Offset = new Vector(10, 0) });
// Rotate 90 degrees CCW around origin
main.Rotate(System.Math.PI / 2);
var call = main.Codes.OfType<SubProgramCall>().First();
// (10, 0) rotated 90 CCW = (0, 10)
Assert.Equal(0, call.Offset.X, 1);
Assert.Equal(10, call.Offset.Y, 1);
}
}