mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-03 17:01:38 -05:00
The spiral used only the least-waste rows and columns. Those often make one pair of blocks the larger on both axes, so it overlapped itself and placed nothing, leaving Fill at two blocks. It now also tries every four-block combination and takes one that holds more parts than both the least-waste spiral and the two-block layout, so ties keep today's layout. A 9 x 6.5 part on a 60 x 120 sheet goes from 109 to 112. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
66 lines
2.1 KiB
C#
66 lines
2.1 KiB
C#
using System.Collections.Generic;
|
|
using OpenNest.Math;
|
|
|
|
namespace OpenNest.Engine.Fill
|
|
{
|
|
internal record CombinationResult(bool Found, int Count1, int Count2);
|
|
|
|
internal static class BestCombination
|
|
{
|
|
/// <summary>
|
|
/// Every count of <paramref name="length1"/> that fits, each with as many of
|
|
/// <paramref name="length2"/> as fit beside it. Spiral blocks need these: the combination
|
|
/// with the least waste is not always one whose blocks can share the sheet.
|
|
/// </summary>
|
|
public static IEnumerable<CombinationResult> AllFrom2(
|
|
double length1,
|
|
double length2,
|
|
double overallLength
|
|
)
|
|
{
|
|
overallLength += Tolerance.Epsilon;
|
|
var maxCount1 = (int)System.Math.Floor(overallLength / length1);
|
|
|
|
for (var c1 = 0; c1 <= maxCount1; c1++)
|
|
{
|
|
var c2 = (int)System.Math.Floor((overallLength - c1 * length1) / length2);
|
|
if (c1 > 0 || c2 > 0)
|
|
yield return new CombinationResult(true, c1, c2);
|
|
}
|
|
}
|
|
|
|
public static CombinationResult FindFrom2(
|
|
double length1,
|
|
double length2,
|
|
double overallLength
|
|
)
|
|
{
|
|
overallLength += Tolerance.Epsilon;
|
|
var count1 = 0;
|
|
var count2 = 0;
|
|
|
|
var maxCount1 = (int)System.Math.Floor(overallLength / length1);
|
|
var bestRemnant = overallLength + 1;
|
|
|
|
for (var c1 = 0; c1 <= maxCount1; c1++)
|
|
{
|
|
var remaining = overallLength - c1 * length1;
|
|
var c2 = (int)System.Math.Floor(remaining / length2);
|
|
var remnant = remaining - c2 * length2;
|
|
|
|
if (!(remnant < bestRemnant))
|
|
continue;
|
|
|
|
count1 = c1;
|
|
count2 = c2;
|
|
bestRemnant = remnant;
|
|
|
|
if (remnant.IsEqualTo(0))
|
|
break;
|
|
}
|
|
|
|
return new CombinationResult(count1 > 0 || count2 > 0, count1, count2);
|
|
}
|
|
}
|
|
}
|