mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 02:41:06 -04:00
DefaultPlateFiller becomes PlateFiller(plate, policy, layout); PlateFillerBase and StripPlateFiller are gone. PlateLayout.FillThenPack is the old orchestrator path (Fill and both Remnants); PlateLayout.Strips is the old StripPlateFiller.Nest, and Strip is Fill policy plus Strips layout. Lifetimes are unchanged: a strip-layout filler runs every Fill, group Fill and PackArea on a fresh inner filler and gives each strip fresh remnant fillers, so learned angles and PlateNumber never leak into them. The comparer, preferred direction, trim axis and angle recording now read the policy directly. The base class's unsorted two-angle BuildAngles is dropped: only DefaultPlateFiller's pipeline called BuildAngles, and Strip never ran it. Layout-neutral: all 29 FillStackCharacterizationTests pins pass unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
46 lines
2.1 KiB
C#
46 lines
2.1 KiB
C#
#nullable enable
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using OpenNest.Engine.BestFit;
|
|
using OpenNest.Engine.Jobs.Adapters;
|
|
using OpenNest.Engine.Jobs.Placement.Fillers;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.Engine.Jobs.Placement;
|
|
|
|
/// <summary>
|
|
/// Runs the Fill strategy for one private drawing on a private plate, for callers that turn the
|
|
/// result into job poses. The caller owns the drawing and must call
|
|
/// <see cref="BestFitCache.Invalidate"/> for it when finished.
|
|
/// </summary>
|
|
internal static class PrivatePlateFill
|
|
{
|
|
/// <param name="length">X extent of the plate and work area.</param>
|
|
/// <param name="width">Y extent of the plate and work area.</param>
|
|
/// <param name="quantity">Copies wanted; zero fills the whole area.</param>
|
|
internal static List<Part> Run(Drawing drawing, RotationPolicy rotation, double spacing,
|
|
double length, double width, int quantity, CancellationToken token)
|
|
{
|
|
var plate = new Plate(new Size(width, length)) { PartSpacing = spacing };
|
|
// The drawing is private: stabilize this cache entry before Fill's candidate pruning.
|
|
var fits = BestFitCache.GetOrCompute(drawing, plate.Size.Length, plate.Size.Width, spacing);
|
|
var sorted = fits.OrderBy(f => f.RotatedArea).ThenBy(f => f.Candidate.StrategyIndex)
|
|
.ThenBy(f => f.Candidate.Part2Rotation).ThenBy(f => f.Candidate.Part2Offset.X)
|
|
.ThenBy(f => f.Candidate.Part2Offset.Y).ThenBy(f => f.OptimalRotation).ToArray();
|
|
fits.Clear();
|
|
fits.AddRange(sorted);
|
|
// A positive quantity lets supporting strategies avoid surplus rows. Zero still
|
|
// fills the whole area (the cutout lattice caller requires an uncapped lattice).
|
|
var filler = new PlateFiller(plate) { StopAtQuantity = true };
|
|
return filler.Fill(new NestItem
|
|
{
|
|
Drawing = drawing,
|
|
Quantity = quantity,
|
|
RotationStart = rotation.Start,
|
|
RotationEnd = rotation.End,
|
|
StepAngle = DrawingJobMapper.LegacyStep(rotation),
|
|
}, new Box(0, 0, length, width), null!, token);
|
|
}
|
|
}
|