mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-05 12:31:50 -05:00
The Circle fill strategy's stripe layouts (FillEndOdd, FillEndEven) now try switching from staggered to straight stripes, a diameter apart over the last staggered stripe, at every stripe, all staggered and all straight included, and keep the switch that places the most; a tie stays staggered. A 9" circle on a 60x120 sheet at 0.2 spacing now fills 89 (five staggered rows, two straight) instead of 88. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
85 lines
2.8 KiB
C#
85 lines
2.8 KiB
C#
using System;
|
|
using OpenNest.Geometry;
|
|
using OpenNest.Math;
|
|
|
|
namespace OpenNest.Engine.CirclePacking
|
|
{
|
|
internal class FillEndEven : FillEngine
|
|
{
|
|
public FillEndEven(Bin bin)
|
|
: base(bin) { }
|
|
|
|
public override void Fill(Item item)
|
|
{
|
|
var bin1 = FillHorizontal(item);
|
|
var bin2 = FillVertical(item);
|
|
|
|
if (bin1.Items.Count > bin2.Items.Count)
|
|
Bin.Items.AddRange(bin1.Items);
|
|
else
|
|
Bin.Items.AddRange(bin2.Items);
|
|
}
|
|
|
|
public override void Fill(Item item, int maxCount)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
private Bin FillHorizontal(Item item) => FillAxis(item, horizontal: true);
|
|
|
|
private Bin FillVertical(Item item) => FillAxis(item, horizontal: false);
|
|
|
|
/// <summary>Stripes run along Y and step along X when horizontal, and the reverse otherwise.</summary>
|
|
private Bin FillAxis(Item item, bool horizontal)
|
|
{
|
|
var bin = Bin.Clone() as Bin;
|
|
|
|
var max = new Vector(
|
|
bin.Right - item.Radius + Tolerance.Epsilon,
|
|
bin.Top - item.Radius + Tolerance.Epsilon
|
|
);
|
|
|
|
// A box's Length runs along X and its Width along Y.
|
|
var stripeSize = horizontal ? bin.Width : bin.Length;
|
|
var diameter = item.Diameter;
|
|
var radius = item.Radius;
|
|
var rows = System.Math.Floor((stripeSize + Tolerance.Epsilon) / diameter);
|
|
|
|
if (rows == 0)
|
|
return bin;
|
|
|
|
var remaining = stripeSize - diameter * rows;
|
|
double oddShift;
|
|
double innerOffset;
|
|
double outerOffset;
|
|
|
|
if (remaining < radius)
|
|
{
|
|
oddShift = remaining;
|
|
innerOffset = diameter;
|
|
outerOffset = Trigonometry.Base(remaining, diameter);
|
|
}
|
|
else
|
|
{
|
|
oddShift = (stripeSize - diameter) / (2 * rows - 1);
|
|
innerOffset = oddShift * 2.0;
|
|
// Adjacent stripes touch diagonally, but stripes two apart sit directly beside
|
|
// each other, so the stripe spacing can never drop below a radius.
|
|
outerOffset = System.Math.Max(Trigonometry.Base(oddShift, diameter), radius);
|
|
}
|
|
|
|
AddStripes(bin, item, new Stripes(
|
|
InnerAlongX: !horizontal,
|
|
OuterStart: (horizontal ? bin.X : bin.Y) + radius,
|
|
OuterMax: horizontal ? max.X : max.Y,
|
|
OuterStep: outerOffset,
|
|
InnerStart: (horizontal ? bin.Y : bin.X) + radius,
|
|
InnerMax: horizontal ? max.Y : max.X,
|
|
InnerStep: innerOffset,
|
|
Shift: oddShift));
|
|
|
|
return bin;
|
|
}
|
|
}
|
|
}
|