Files
OpenNest/OpenNest.Engine/RectanglePacking/FillBestFit.cs
T
aj 451841401a refactor(engine): align namespaces with directory layout under OpenNest.Engine
All 132 OpenNest.Engine source files now declare namespaces matching
their nested directories: Jobs/, Jobs/Placement/, Jobs/Adapters/,
Fill/, RectanglePacking/, CirclePacking/, and engine-root types moved
from 'OpenNest' to 'OpenNest.Engine'. RootNamespace updated accordingly.
Consumers (Api, Console, Mcp, Benchmark, Training, desktop app, tests)
gained the explicit usings the move requires; CLAUDE.md updated.
2026-09-21 13:18:34 -04:00

90 lines
2.9 KiB
C#

using System;
using OpenNest.Engine.Fill;
using OpenNest.Math;
namespace OpenNest.Engine.RectanglePacking
{
internal class FillBestFit : FillEngine
{
public FillBestFit(Bin bin)
: base(bin) { }
public override void Fill(Item item)
{
var bin1 = BestFitHorizontal(item);
var bin2 = BestFitVertical(item);
if (bin1.Items.Count == bin2.Items.Count)
{
var usedArea1 = bin1.Items.GetBoundingBox().Area();
var usedArea2 = bin2.Items.GetBoundingBox().Area();
if (usedArea2 < usedArea1)
Bin.Items.AddRange(bin2.Items);
else
Bin.Items.AddRange(bin1.Items);
}
else if (bin1.Items.Count > bin2.Items.Count)
Bin.Items.AddRange(bin1.Items);
else
Bin.Items.AddRange(bin2.Items);
}
public override void Fill(Item item, int maxCount)
{
Fill(item);
if (Bin.Items.Count > maxCount)
Bin.Items.RemoveRange(maxCount, Bin.Items.Count - maxCount);
}
private Bin BestFitHorizontal(Item item) => BestFitAxis(item, horizontal: true);
private Bin BestFitVertical(Item item) => BestFitAxis(item, horizontal: false);
private Bin BestFitAxis(Item item, bool horizontal)
{
var bin = Bin.Clone() as Bin;
var primarySize = horizontal ? item.Length : item.Width;
var secondarySize = horizontal ? item.Width : item.Length;
var binPrimary = horizontal ? bin.Length : Bin.Width;
var binSecondary = horizontal ? bin.Width : Bin.Length;
var combo = BestCombination.FindFrom2(primarySize, secondarySize, binPrimary);
if (!combo.Found)
return bin;
var normalPrimary = combo.Count1;
var rotatePrimary = combo.Count2;
var normalSecondary = (int)
System.Math.Floor((binSecondary + Tolerance.Epsilon) / secondarySize);
var rotateSecondary = (int)
System.Math.Floor((binSecondary + Tolerance.Epsilon) / primarySize);
var (normalRows, normalCols) = horizontal
? (normalSecondary, normalPrimary)
: (normalPrimary, normalSecondary);
var (rotateRows, rotateCols) = horizontal
? (rotateSecondary, rotatePrimary)
: (rotatePrimary, rotateSecondary);
item.Location = bin.Location;
bin.Items.AddRange(FillGrid(item, normalRows, normalCols, int.MaxValue));
if (horizontal)
item.Location.X += item.Length * normalPrimary;
else
item.Location.Y += item.Width * normalPrimary;
item.Rotate();
bin.Items.AddRange(FillGrid(item, rotateRows, rotateCols, int.MaxValue));
return bin;
}
}
}