fix(core): stop Program.BoundingBox including the origin

Min/max were seeded at 0, so any geometry not touching the origin got an
inflated box, and the first move only updated max (else-if). Rotated
canonical drawings are the common trigger: their origin ends up outside
the shape, which skewed Part bounds and bbox-based alignment.

Track the real extents and keep returning a zero box for empty programs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
aj
2026-09-21 11:07:44 -04:00
co-authored by Claude Sonnet 5
parent f23f0fa566
commit 2a855139d2
2 changed files with 75 additions and 12 deletions
@@ -0,0 +1,50 @@
using OpenNest.CNC;
using OpenNest.Geometry;
namespace OpenNest.Tests.CNC;
public class ProgramBoundingBoxTests
{
[Fact]
public void GeometryAwayFromOrigin_DoesNotIncludeOrigin()
{
var pgm = new OpenNest.CNC.Program();
pgm.Codes.Add(new RapidMove(new Vector(10, 10)));
pgm.Codes.Add(new LinearMove(new Vector(20, 10)));
pgm.Codes.Add(new LinearMove(new Vector(20, 30)));
pgm.Codes.Add(new LinearMove(new Vector(10, 30)));
pgm.Codes.Add(new LinearMove(new Vector(10, 10)));
var box = pgm.BoundingBox();
Assert.Equal(10, box.Left, precision: 6);
Assert.Equal(10, box.Bottom, precision: 6);
Assert.Equal(20, box.Right, precision: 6);
Assert.Equal(30, box.Top, precision: 6);
}
[Fact]
public void GeometryBelowAndLeftOfOrigin_IsTrackedExactly()
{
var pgm = new OpenNest.CNC.Program();
pgm.Codes.Add(new RapidMove(new Vector(-30, -20)));
pgm.Codes.Add(new LinearMove(new Vector(-10, -20)));
pgm.Codes.Add(new LinearMove(new Vector(-10, -5)));
var box = pgm.BoundingBox();
Assert.Equal(-30, box.Left, precision: 6);
Assert.Equal(-20, box.Bottom, precision: 6);
Assert.Equal(-10, box.Right, precision: 6);
Assert.Equal(-5, box.Top, precision: 6);
}
[Fact]
public void EmptyProgram_ReturnsZeroBox()
{
var box = new OpenNest.CNC.Program().BoundingBox();
Assert.Equal(0, box.Width, precision: 6);
Assert.Equal(0, box.Length, precision: 6);
}
}