fix: correct Width/Length axis mapping and add spiral center-fill
Box constructor and derived properties (Right, Top, Center, Translate, Offset) had Width and Length swapped — Length is X axis, Width is Y axis. Corrected across Core geometry, plate bounding box, rectangle packing, fill algorithms, tests, and UI renderers. Added FillSpiral with center remnant detection and recursive FillBest on the gap between the 4 spiral quadrants. RectFill.FillBest now compares spiral+center vs full best-fit fairly. BestCombination returns a CombinationResult record instead of out params. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,13 +50,13 @@ namespace OpenNest
|
||||
{
|
||||
cutPosition = Position.X;
|
||||
lineStart = StartLimit ?? bounds.Y;
|
||||
lineEnd = EndLimit ?? (bounds.Y + bounds.Length + settings.Overtravel);
|
||||
lineEnd = EndLimit ?? (bounds.Y + bounds.Width + settings.Overtravel);
|
||||
}
|
||||
else
|
||||
{
|
||||
cutPosition = Position.Y;
|
||||
lineStart = StartLimit ?? bounds.X;
|
||||
lineEnd = EndLimit ?? (bounds.X + bounds.Width + settings.Overtravel);
|
||||
lineEnd = EndLimit ?? (bounds.X + bounds.Length + settings.Overtravel);
|
||||
}
|
||||
|
||||
var exclusions = new List<(double Start, double End)>();
|
||||
@@ -176,13 +176,13 @@ namespace OpenNest
|
||||
|
||||
private (double Min, double Max) AxisBounds(Box bb, double clearance) =>
|
||||
Axis == CutOffAxis.Vertical
|
||||
? (bb.X - clearance, bb.X + bb.Width + clearance)
|
||||
: (bb.Y - clearance, bb.Y + bb.Length + clearance);
|
||||
? (bb.X - clearance, bb.X + bb.Length + clearance)
|
||||
: (bb.Y - clearance, bb.Y + bb.Width + clearance);
|
||||
|
||||
private (double Start, double End) CrossAxisBounds(Box bb, double clearance) =>
|
||||
Axis == CutOffAxis.Vertical
|
||||
? (bb.Y - clearance, bb.Y + bb.Length + clearance)
|
||||
: (bb.X - clearance, bb.X + bb.Width + clearance);
|
||||
? (bb.Y - clearance, bb.Y + bb.Width + clearance)
|
||||
: (bb.X - clearance, bb.X + bb.Length + clearance);
|
||||
|
||||
private Program BuildProgram(List<(double Start, double End)> segments, CutOffSettings settings)
|
||||
{
|
||||
|
||||
@@ -420,8 +420,8 @@ namespace OpenNest.Geometry
|
||||
|
||||
boundingBox.X = minX;
|
||||
boundingBox.Y = minY;
|
||||
boundingBox.Width = maxX - minX;
|
||||
boundingBox.Length = maxY - minY;
|
||||
boundingBox.Length = maxX - minX;
|
||||
boundingBox.Width = maxY - minY;
|
||||
}
|
||||
|
||||
public override Entity OffsetEntity(double distance, OffsetSide side)
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace OpenNest.Geometry
|
||||
|
||||
double minX = boxes[0].X;
|
||||
double minY = boxes[0].Y;
|
||||
double maxX = boxes[0].X + boxes[0].Width;
|
||||
double maxY = boxes[0].Y + boxes[0].Length;
|
||||
double maxX = boxes[0].Right;
|
||||
double maxY = boxes[0].Top;
|
||||
|
||||
foreach (var box in boxes)
|
||||
{
|
||||
|
||||
@@ -14,15 +14,15 @@ namespace OpenNest.Geometry
|
||||
public Box(double x, double y, double w, double h)
|
||||
{
|
||||
Location = new Vector(x, y);
|
||||
Width = w;
|
||||
Length = h;
|
||||
Length = w;
|
||||
Width = h;
|
||||
}
|
||||
|
||||
public Vector Location;
|
||||
|
||||
public Vector Center
|
||||
{
|
||||
get { return new Vector(X + Width * 0.5, Y + Length * 0.5); }
|
||||
get { return new Vector(X + Length * 0.5, Y + Width * 0.5); }
|
||||
}
|
||||
|
||||
public Size Size;
|
||||
@@ -76,12 +76,12 @@ namespace OpenNest.Geometry
|
||||
|
||||
public Box Translate(double x, double y)
|
||||
{
|
||||
return new Box(X + x, Y + y, Width, Length);
|
||||
return new Box(X + x, Y + y, Length, Width);
|
||||
}
|
||||
|
||||
public Box Translate(Vector offset)
|
||||
{
|
||||
return new Box(X + offset.X, Y + offset.Y, Width, Length);
|
||||
return new Box(X + offset.X, Y + offset.Y, Length, Width);
|
||||
}
|
||||
|
||||
public double Left
|
||||
@@ -91,12 +91,12 @@ namespace OpenNest.Geometry
|
||||
|
||||
public double Right
|
||||
{
|
||||
get { return X + Width; }
|
||||
get { return X + Length; }
|
||||
}
|
||||
|
||||
public double Top
|
||||
{
|
||||
get { return Y + Length; }
|
||||
get { return Y + Width; }
|
||||
}
|
||||
|
||||
public double Bottom
|
||||
@@ -207,7 +207,7 @@ namespace OpenNest.Geometry
|
||||
|
||||
public Box Offset(double d)
|
||||
{
|
||||
return new Box(X - d, Y - d, Width + d * 2, Length + d * 2);
|
||||
return new Box(X - d, Y - d, Length + d * 2, Width + d * 2);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
var x = large.Left;
|
||||
var y = small.Top;
|
||||
var w = large.Width;
|
||||
var w = large.Length;
|
||||
var h = large.Top - y;
|
||||
|
||||
return new Box(x, y, w, h);
|
||||
@@ -23,7 +23,7 @@
|
||||
var x = large.Left;
|
||||
var y = large.Bottom;
|
||||
var w = small.Left - x;
|
||||
var h = large.Length;
|
||||
var h = large.Width;
|
||||
|
||||
return new Box(x, y, w, h);
|
||||
}
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
var x = large.Left;
|
||||
var y = large.Bottom;
|
||||
var w = large.Width;
|
||||
var w = large.Length;
|
||||
var h = small.Top - y;
|
||||
|
||||
return new Box(x, y, w, h);
|
||||
@@ -49,7 +49,7 @@
|
||||
var x = small.Right;
|
||||
var y = large.Bottom;
|
||||
var w = large.Right - x;
|
||||
var h = large.Length;
|
||||
var h = large.Width;
|
||||
|
||||
return new Box(x, y, w, h);
|
||||
}
|
||||
|
||||
@@ -370,23 +370,23 @@ namespace OpenNest.Geometry
|
||||
if (StartPoint.X < EndPoint.X)
|
||||
{
|
||||
boundingBox.X = StartPoint.X;
|
||||
boundingBox.Width = EndPoint.X - StartPoint.X;
|
||||
boundingBox.Length = EndPoint.X - StartPoint.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundingBox.X = EndPoint.X;
|
||||
boundingBox.Width = StartPoint.X - EndPoint.X;
|
||||
boundingBox.Length = StartPoint.X - EndPoint.X;
|
||||
}
|
||||
|
||||
if (StartPoint.Y < EndPoint.Y)
|
||||
{
|
||||
boundingBox.Y = StartPoint.Y;
|
||||
boundingBox.Length = EndPoint.Y - StartPoint.Y;
|
||||
boundingBox.Width = EndPoint.Y - StartPoint.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundingBox.Y = EndPoint.Y;
|
||||
boundingBox.Length = StartPoint.Y - EndPoint.Y;
|
||||
boundingBox.Width = StartPoint.Y - EndPoint.Y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -311,8 +311,8 @@ namespace OpenNest.Geometry
|
||||
|
||||
boundingBox.X = minX;
|
||||
boundingBox.Y = minY;
|
||||
boundingBox.Width = maxX - minX;
|
||||
boundingBox.Length = maxY - minY;
|
||||
boundingBox.Length = maxX - minX;
|
||||
boundingBox.Width = maxY - minY;
|
||||
}
|
||||
|
||||
public override Entity OffsetEntity(double distance, OffsetSide side)
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace OpenNest
|
||||
var part = new Part(BaseDrawing, Program,
|
||||
location + offset,
|
||||
new Box(BoundingBox.X + offset.X, BoundingBox.Y + offset.Y,
|
||||
BoundingBox.Width, BoundingBox.Length));
|
||||
BoundingBox.Length, BoundingBox.Width));
|
||||
|
||||
return part;
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ namespace OpenNest
|
||||
{
|
||||
var plateBox = new Box();
|
||||
|
||||
// Convention: Size.Length = X axis (horizontal), Size.Width = Y axis (vertical)
|
||||
// Width = Y axis (vertical), Length = X axis (horizontal)
|
||||
switch (Quadrant)
|
||||
{
|
||||
case 1:
|
||||
@@ -451,8 +451,8 @@ namespace OpenNest
|
||||
return new Box();
|
||||
}
|
||||
|
||||
plateBox.Width = Size.Length;
|
||||
plateBox.Length = Size.Width;
|
||||
plateBox.Width = Size.Width;
|
||||
plateBox.Length = Size.Length;
|
||||
|
||||
if (!includeParts)
|
||||
return plateBox;
|
||||
@@ -468,11 +468,11 @@ namespace OpenNest
|
||||
? partsBox.Bottom
|
||||
: plateBox.Bottom;
|
||||
|
||||
boundingBox.Width = partsBox.Right > plateBox.Right
|
||||
boundingBox.Length = partsBox.Right > plateBox.Right
|
||||
? partsBox.Right - boundingBox.X
|
||||
: plateBox.Right - boundingBox.X;
|
||||
|
||||
boundingBox.Length = partsBox.Top > plateBox.Top
|
||||
boundingBox.Width = partsBox.Top > plateBox.Top
|
||||
? partsBox.Top - boundingBox.Y
|
||||
: plateBox.Top - boundingBox.Y;
|
||||
|
||||
@@ -489,8 +489,8 @@ namespace OpenNest
|
||||
|
||||
box.X += EdgeSpacing.Left;
|
||||
box.Y += EdgeSpacing.Bottom;
|
||||
box.Width -= EdgeSpacing.Left + EdgeSpacing.Right;
|
||||
box.Length -= EdgeSpacing.Top + EdgeSpacing.Bottom;
|
||||
box.Length -= EdgeSpacing.Left + EdgeSpacing.Right;
|
||||
box.Width -= EdgeSpacing.Top + EdgeSpacing.Bottom;
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ public static class AutoSplitCalculator
|
||||
|
||||
var lines = new List<SplitLine>();
|
||||
|
||||
var verticalSplits = usableWidth > 0 ? (int)System.Math.Ceiling(partBounds.Width / usableWidth) - 1 : 0;
|
||||
var horizontalSplits = usableHeight > 0 ? (int)System.Math.Ceiling(partBounds.Length / usableHeight) - 1 : 0;
|
||||
var verticalSplits = usableWidth > 0 ? (int)System.Math.Ceiling(partBounds.Length / usableWidth) - 1 : 0;
|
||||
var horizontalSplits = usableHeight > 0 ? (int)System.Math.Ceiling(partBounds.Width / usableHeight) - 1 : 0;
|
||||
|
||||
if (verticalSplits < 0) verticalSplits = 0;
|
||||
if (horizontalSplits < 0) horizontalSplits = 0;
|
||||
@@ -34,14 +34,14 @@ public static class AutoSplitCalculator
|
||||
|
||||
if (verticalPieces > 1)
|
||||
{
|
||||
var spacing = partBounds.Width / verticalPieces;
|
||||
var spacing = partBounds.Length / verticalPieces;
|
||||
for (var i = 1; i < verticalPieces; i++)
|
||||
lines.Add(new SplitLine(partBounds.X + spacing * i, CutOffAxis.Vertical));
|
||||
}
|
||||
|
||||
if (horizontalPieces > 1)
|
||||
{
|
||||
var spacing = partBounds.Length / horizontalPieces;
|
||||
var spacing = partBounds.Width / horizontalPieces;
|
||||
for (var i = 1; i < horizontalPieces; i++)
|
||||
lines.Add(new SplitLine(partBounds.Y + spacing * i, CutOffAxis.Horizontal));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user