mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-02 14:48:50 -04:00
fix(packing): apply work-area slack only at plate boundaries
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using OpenNest.Engine.NestingEngines.Rectangles;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
|
||||
@@ -33,13 +34,21 @@ internal static class AreaPacker
|
||||
/// right/top sides, so neighbouring parts are one spacing apart and the last may touch the
|
||||
/// area's edge. A cancelled token stops between candidates and keeps the best layout so far.
|
||||
/// </summary>
|
||||
/// <param name="workArea">Plate work area, when known. Only matching right/top boundaries
|
||||
/// receive the existing work-area overhang allowance; internal areas remain strict.</param>
|
||||
public static List<Part> Pack(
|
||||
Box area, IReadOnlyList<NestItem> items, double spacing, IFillComparer comparer, CancellationToken token)
|
||||
Box area, IReadOnlyList<NestItem> items, double spacing, IFillComparer comparer, CancellationToken token, Box? workArea = null)
|
||||
{
|
||||
var boxes = items.Select(i => i.Drawing.Program.BoundingBox()).ToList();
|
||||
var types = new List<PackType>(items.Count);
|
||||
var demand = new int[items.Count];
|
||||
var packArea = (area.Length + spacing) * (area.Width + spacing);
|
||||
// Only the positive edges can overhang: placements anchor at a free box's lower-left.
|
||||
var rightSlack = workArea != null && System.Math.Abs(area.Right - workArea.Right) <= MaxRectsSheet.Eps
|
||||
? SheetPacker.OverhangAllowance : 0;
|
||||
var topSlack = workArea != null && System.Math.Abs(area.Top - workArea.Top) <= MaxRectsSheet.Eps
|
||||
? SheetPacker.OverhangAllowance : 0;
|
||||
// Include boundary slack in this upper bound so a near-full-area item is not capped at zero.
|
||||
var packArea = (area.Length + spacing + rightSlack) * (area.Width + spacing + topSlack);
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
var w = boxes[i].Length + spacing;
|
||||
@@ -67,7 +76,7 @@ internal static class AreaPacker
|
||||
if (best != null && token.IsCancellationRequested)
|
||||
return best;
|
||||
|
||||
var sheet = new MaxRectsSheet(area.Length + spacing, area.Width + spacing);
|
||||
var sheet = new MaxRectsSheet(area.Length + spacing, area.Width + spacing, rightSlack, topSlack);
|
||||
var placed = MaxRectsPacker.Pack(
|
||||
types, (int[])demand.Clone(), sheet, rule, mode, CancellationToken.None);
|
||||
var tierScores = tiers
|
||||
|
||||
@@ -50,9 +50,13 @@ internal sealed class MaxRectsSheet
|
||||
|
||||
private readonly List<Rect> free = new();
|
||||
private readonly List<Rect> used = new();
|
||||
private readonly double rightSlack;
|
||||
private readonly double topSlack;
|
||||
|
||||
public MaxRectsSheet(double width, double height)
|
||||
public MaxRectsSheet(double width, double height, double rightSlack = 0, double topSlack = 0)
|
||||
{
|
||||
this.rightSlack = rightSlack;
|
||||
this.topSlack = topSlack;
|
||||
Width = width;
|
||||
Height = height;
|
||||
free.Add(new Rect(0, 0, width, height));
|
||||
@@ -68,9 +72,15 @@ internal sealed class MaxRectsSheet
|
||||
(Rect Place, double Primary, double Secondary)? best = null;
|
||||
foreach (var f in free)
|
||||
{
|
||||
if (w > f.W + Eps || h > f.H + Eps)
|
||||
// Clamp only at the bin's allowed plate boundaries. Internal free edges still
|
||||
// use Eps, and real sizes are retained there to preserve neighbour spacing.
|
||||
var packW = w > f.W && w <= f.W + rightSlack && System.Math.Abs(f.Right - Width) <= Eps
|
||||
? f.W : w;
|
||||
var packH = h > f.H && h <= f.H + topSlack && System.Math.Abs(f.Top - Height) <= Eps
|
||||
? f.H : h;
|
||||
if (packW > f.W + Eps || packH > f.H + Eps)
|
||||
continue;
|
||||
var place = new Rect(f.X, f.Y, w, h);
|
||||
var place = new Rect(f.X, f.Y, packW, packH);
|
||||
var (p, s) = Score(f, place, rule);
|
||||
if (best is not { } b || p < b.Primary - Eps
|
||||
|| (p <= b.Primary + Eps && s < b.Secondary - Eps))
|
||||
|
||||
Reference in New Issue
Block a user