Files
OpenNest/OpenNest.Engine/Strategies/CircleFillStrategy.cs
T
ajandClaude Opus 5.5 8cc8d04b64 feat(engine): stagger round parts in plate fills
FillEndOdd and FillEndEven had no production callers, so round parts
only got stripe layouts. A Circle strategy now runs them in the fill
pipeline: 8in circles on a 60x120 go from 98 to 112.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:44:00 -05:00

57 lines
2.0 KiB
C#

using System.Collections.Generic;
using System.Linq;
using OpenNest.Engine.CirclePacking;
using OpenNest.Engine.Fill;
using OpenNest.Engine.Jobs;
using OpenNest.Engine.Jobs.Cutouts;
using OpenNest.Geometry;
namespace OpenNest.Engine.Strategies;
/// <summary>
/// Staggers round parts edge to edge with <see cref="FillEndOdd"/> and <see cref="FillEndEven"/>,
/// which stretch a row's pitch to the sheet so the next row drops deeper than a fixed lattice does.
/// </summary>
public class CircleFillStrategy : IFillStrategy
{
public string Name => "Circle";
public NestPhase Phase => NestPhase.Custom;
public int Order => 170;
public List<Part> Fill(FillContext context)
{
if (context.PartType != PartType.Circle)
return null;
var item = Item.TryCreate(PartGeometrySnapshot.FromProgram(context.Item.Drawing.Program));
if (item == null)
return null;
// Half the gap on every disc, and the work area grown to match, so discs keep the spacing
// from each other and only their own radius from the work area's edges.
var gap = context.Plate.PartSpacing + CutoutCirclePacker.Margin;
var spaced = item.Clone();
spaced.Radius += gap * 0.5;
var area = context.WorkArea.Offset(gap * 0.5);
var comparer = context.Policy?.Comparer ?? new DefaultFillComparer();
var odd = Pack(area, spaced, bin => new FillEndOdd(bin), item, context.Item.Drawing);
var even = Pack(area, spaced, bin => new FillEndEven(bin), item, context.Item.Drawing);
return comparer.IsBetter(even, odd, context.WorkArea) ? even : odd;
}
private static List<Part> Pack(
Box area,
Item spaced,
System.Func<Bin, FillEngine> engine,
Item item,
Drawing drawing
)
{
var bin = new Bin { Location = area.Location, Size = area.Size };
engine(bin).Fill(spaced);
return bin.Items.Select(i => new Part(drawing, i.Center + item.PartOffset)).ToList();
}
}