using System; using System.Collections.Generic; using System.Threading; using OpenNest.Engine.Jobs.Placement.Fillers; using OpenNest.Geometry; namespace OpenNest.Engine.Jobs.Placement; /// /// Public single-plate placement service over the internal fillers. Resolves one of the four /// built-in placement strategies by explicit name — no process-global registry state is read or /// modified. Operations return proposed s only; caller-owned plate mutation /// (accepting a preview, adding parts to a plate) and cancel/discard behavior remain with the /// caller, exactly as they were with the legacy single-plate engine surface. /// public static class PlateFillService { /// The four built-in strategy names, in registry display order. public static IReadOnlyList BuiltInStrategies { get; } = [ "Default", "Strip", "Vertical Remnant", "Horizontal Remnant", ]; public static List FillItem( string strategy, Plate plate, NestItem item, Box workArea, IProgress progress, CancellationToken token ) { var filler = CreateFiller(strategy, plate); return filler.Fill(item, workArea, progress, token); } public static List FillGroup( string strategy, Plate plate, List groupParts, Box workArea, IProgress progress, CancellationToken token ) { var filler = CreateFiller(strategy, plate); return filler.Fill(groupParts, workArea, progress, token); } public static List PackArea( string strategy, Plate plate, Box box, List items, IProgress progress, CancellationToken token ) { var filler = CreateFiller(strategy, plate); return filler.PackArea(box, items, progress, token); } private static PlateFillerBase CreateFiller(string strategy, Plate plate) { ArgumentNullException.ThrowIfNull(strategy); ArgumentNullException.ThrowIfNull(plate); // OrdinalIgnoreCase mirrors the legacy registry's ActiveEngineName matching so the // interactive callers keep their tolerant name handling while moving off global state. foreach (var candidate in BuiltInStrategies) { if (candidate.Equals(strategy, StringComparison.OrdinalIgnoreCase)) { return candidate switch { "Default" => new DefaultPlateFiller(plate), "Strip" => new StripPlateFiller(plate), "Vertical Remnant" => new RemnantPlateFiller(plate, RemnantFillPolicy.Vertical), _ => new RemnantPlateFiller(plate, RemnantFillPolicy.Horizontal), }; } } throw new NotSupportedException( $"Unknown placement strategy: {strategy}. Known strategies: {string.Join(", ", BuiltInStrategies)}." ); } }