using System; using System.Collections.Generic; using System.Linq; using System.Threading; using OpenNest.Engine; using OpenNest.Engine.Fill; using OpenNest.Geometry; namespace OpenNest.Engine.Jobs.Placement.Fillers; internal class StripPlateFiller : PlateFillerBase { internal StripPlateFiller(Plate plate) : base(plate) { } public override List Fill( NestItem item, Box workArea, IProgress progress, CancellationToken token ) { var inner = new DefaultPlateFiller(Plate); return inner.Fill(item, workArea, progress, token); } public override List Fill( List groupParts, Box workArea, IProgress progress, CancellationToken token ) { var inner = new DefaultPlateFiller(Plate); return inner.Fill(groupParts, workArea, progress, token); } public override List PackArea( Box box, List items, IProgress progress, CancellationToken token ) => PackAreaCore(box, items, progress, token); internal List PackAreaCore( Box box, List items, IProgress progress, CancellationToken token ) { var inner = new DefaultPlateFiller(Plate); return inner.PackArea(box, items, progress, token); } public override List Nest( List items, IProgress progress, CancellationToken token ) { if (items == null || items.Count == 0) return new List(); var workArea = Plate.WorkArea(); var fillItems = items .Where(item => item.Quantity != 1) .OrderBy(item => item.Priority) .ThenByDescending(item => item.Drawing.Area) .ToList(); var packItems = items.Where(item => item.Quantity == 1).ToList(); var allParts = new List(); if (fillItems.Count > 0) { Func> heightFillFunc = (item, box) => { var inner = new RemnantPlateFiller(Plate, RemnantFillPolicy.Horizontal); return inner.Fill(item, box, progress, token); }; Func> widthFillFunc = (item, box) => { var inner = new RemnantPlateFiller(Plate, RemnantFillPolicy.Vertical); return inner.Fill(item, box, progress, token); }; var shrinkResult = IterativeShrinkFiller.Fill( fillItems, workArea, heightFillFunc, Plate.PartSpacing, token, progress, PlateNumber, widthFillFunc ); allParts.AddRange(shrinkResult.Parts); Compactor.Settle(allParts, workArea, Plate.PartSpacing); packItems.AddRange(shrinkResult.Leftovers); } packItems = packItems.Where(item => item.Quantity > 0).ToList(); if (packItems.Count > 0 && !token.IsCancellationRequested) { var packArea = workArea; if (allParts.Count > 0) { var obstacles = allParts .Select(part => part.BoundingBox.Offset(Plate.PartSpacing)) .ToList(); var finder = new RemnantFinder(workArea, obstacles); var remnants = finder.FindRemnants(); packArea = remnants.Count > 0 ? remnants[0] : new Box(0, 0, 0, 0); } if (packArea.Width > 0 && packArea.Length > 0) { var packParts = PackArea(packArea, packItems, progress, token); allParts.AddRange(packParts); } } foreach (var item in items) { if (item.Quantity <= 0) continue; var placed = allParts.Count(part => ReferenceEquals(part.BaseDrawing, item.Drawing)); item.Quantity = System.Math.Max(0, item.Quantity - placed); } return allParts; } }