feat: add FillPolicy record and FillHelpers.FillWithDirectionPreference
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
using OpenNest.Engine.Fill;
|
using OpenNest.Engine.Fill;
|
||||||
using OpenNest.Geometry;
|
using OpenNest.Geometry;
|
||||||
using OpenNest.Math;
|
using OpenNest.Math;
|
||||||
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -63,5 +64,42 @@ namespace OpenNest.Engine.Strategies
|
|||||||
|
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a fill function with direction preference logic.
|
||||||
|
/// If preferred is null, tries both directions and returns the better result.
|
||||||
|
/// If preferred is set, tries preferred first; only tries other if preferred yields zero.
|
||||||
|
/// </summary>
|
||||||
|
public static List<Part> FillWithDirectionPreference(
|
||||||
|
Func<NestDirection, List<Part>> fillFunc,
|
||||||
|
NestDirection? preferred,
|
||||||
|
IFillComparer comparer,
|
||||||
|
Box workArea)
|
||||||
|
{
|
||||||
|
if (preferred == null)
|
||||||
|
{
|
||||||
|
var h = fillFunc(NestDirection.Horizontal);
|
||||||
|
var v = fillFunc(NestDirection.Vertical);
|
||||||
|
|
||||||
|
if ((h == null || h.Count == 0) && (v == null || v.Count == 0))
|
||||||
|
return new List<Part>();
|
||||||
|
|
||||||
|
if (h == null || h.Count == 0) return v;
|
||||||
|
if (v == null || v.Count == 0) return h;
|
||||||
|
|
||||||
|
return comparer.IsBetter(h, v, workArea) ? h : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
var other = preferred == NestDirection.Horizontal
|
||||||
|
? NestDirection.Vertical
|
||||||
|
: NestDirection.Horizontal;
|
||||||
|
|
||||||
|
var pref = fillFunc(preferred.Value);
|
||||||
|
if (pref != null && pref.Count > 0)
|
||||||
|
return pref;
|
||||||
|
|
||||||
|
var fallback = fillFunc(other);
|
||||||
|
return fallback ?? new List<Part>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace OpenNest.Engine.Strategies
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Groups engine scoring and direction policy into a single object.
|
||||||
|
/// Set by the engine, consumed by strategies via FillContext.Policy.
|
||||||
|
/// </summary>
|
||||||
|
public record FillPolicy(IFillComparer Comparer, NestDirection? PreferredDirection = null);
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using OpenNest.Engine;
|
||||||
|
using OpenNest.Engine.Fill;
|
||||||
|
using OpenNest.Engine.Strategies;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.Tests;
|
||||||
|
|
||||||
|
public class FillWithDirectionPreferenceTests
|
||||||
|
{
|
||||||
|
private readonly IFillComparer comparer = new DefaultFillComparer();
|
||||||
|
private readonly Box workArea = new(0, 0, 100, 100);
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NullPreference_TriesBothDirections_ReturnsBetter()
|
||||||
|
{
|
||||||
|
var hParts = new List<Part> { TestHelpers.MakePartAt(0, 0, 10), TestHelpers.MakePartAt(12, 0, 10) };
|
||||||
|
var vParts = new List<Part> { TestHelpers.MakePartAt(0, 0, 10) };
|
||||||
|
|
||||||
|
var result = FillHelpers.FillWithDirectionPreference(
|
||||||
|
dir => dir == NestDirection.Horizontal ? hParts : vParts,
|
||||||
|
null, comparer, workArea);
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreferredDirection_UsedFirst_WhenProducesResults()
|
||||||
|
{
|
||||||
|
var hParts = new List<Part> { TestHelpers.MakePartAt(0, 0, 10), TestHelpers.MakePartAt(12, 0, 10) };
|
||||||
|
var vParts = new List<Part> { TestHelpers.MakePartAt(0, 0, 10), TestHelpers.MakePartAt(0, 12, 10), TestHelpers.MakePartAt(0, 24, 10) };
|
||||||
|
|
||||||
|
var result = FillHelpers.FillWithDirectionPreference(
|
||||||
|
dir => dir == NestDirection.Horizontal ? hParts : vParts,
|
||||||
|
NestDirection.Horizontal, comparer, workArea);
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Count); // H has results, so H is returned (preferred)
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreferredDirection_FallsBack_WhenPreferredReturnsEmpty()
|
||||||
|
{
|
||||||
|
var vParts = new List<Part> { TestHelpers.MakePartAt(0, 0, 10) };
|
||||||
|
|
||||||
|
var result = FillHelpers.FillWithDirectionPreference(
|
||||||
|
dir => dir == NestDirection.Horizontal ? new List<Part>() : vParts,
|
||||||
|
NestDirection.Horizontal, comparer, workArea);
|
||||||
|
|
||||||
|
Assert.Equal(1, result.Count); // Falls back to V
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user