diff --git a/OpenNest.Engine/FillLinear.cs b/OpenNest.Engine/FillLinear.cs index b804495..fab809c 100644 --- a/OpenNest.Engine/FillLinear.cs +++ b/OpenNest.Engine/FillLinear.cs @@ -259,9 +259,10 @@ namespace OpenNest } /// - /// Fills a single row of identical parts along one axis using geometry-aware spacing. + /// Creates a seed pattern containing a single part positioned at the work area origin. + /// Returns an empty pattern if the part does not fit. /// - public Pattern FillRow(Drawing drawing, double rotationAngle, NestDirection direction) + private Pattern MakeSeedPattern(Drawing drawing, double rotationAngle) { var pattern = new Pattern(); @@ -278,17 +279,55 @@ namespace OpenNest template.BoundingBox.Height > WorkArea.Height + Tolerance.Epsilon) return pattern; - var boundary = new PartBoundary(template, HalfSpacing); - pattern.Parts.Add(template); + pattern.UpdateBounds(); + return pattern; + } + + /// + /// Recursively fills the work area. At depth 0, tiles the pattern along the + /// primary axis, then recurses perpendicular. At depth 1, tiles and returns. + /// + private List FillRecursive(Pattern pattern, NestDirection direction, int depth) + { + var boundaries = CreateBoundaries(pattern); + var result = new List(pattern.Parts); + result.AddRange(TilePattern(pattern, direction, boundaries)); + + if (depth == 0 && result.Count > pattern.Parts.Count) + { + var rowPattern = new Pattern(); + rowPattern.Parts.AddRange(result); + rowPattern.UpdateBounds(); + return FillRecursive(rowPattern, PerpendicularAxis(direction), depth + 1); + } + + if (depth == 0) + { + // Single part didn't tile along primary — still try perpendicular. + return FillRecursive(pattern, PerpendicularAxis(direction), depth + 1); + } + + return result; + } + + /// + /// Fills a single row of identical parts along one axis using geometry-aware spacing. + /// + public Pattern FillRow(Drawing drawing, double rotationAngle, NestDirection direction) + { + var seed = MakeSeedPattern(drawing, rotationAngle); + + if (seed.Parts.Count == 0) + return seed; + + var template = seed.Parts[0]; + var boundary = new PartBoundary(template, HalfSpacing); var copyDistance = FindCopyDistance(template, direction, boundary); if (copyDistance <= 0) - { - pattern.UpdateBounds(); - return pattern; - } + return seed; var dim = GetDimension(template.BoundingBox, direction); var start = GetStart(template.BoundingBox, direction); @@ -305,12 +344,12 @@ namespace OpenNest var clone = (Part)template.Clone(); clone.Offset(MakeOffset(direction, copyDistance * count)); - pattern.Parts.Add(clone); + seed.Parts.Add(clone); count++; } - pattern.UpdateBounds(); - return pattern; + seed.UpdateBounds(); + return seed; } /// @@ -318,58 +357,31 @@ namespace OpenNest /// public List Fill(Pattern pattern, NestDirection primaryAxis) { - var result = new List(); - if (pattern.Parts.Count == 0) - return result; + return new List(); var offset = WorkArea.Location - pattern.BoundingBox.Location; var basePattern = pattern.Clone(offset); if (basePattern.BoundingBox.Width > WorkArea.Width + Tolerance.Epsilon || basePattern.BoundingBox.Height > WorkArea.Height + Tolerance.Epsilon) - return result; + return new List(); - var boundaries = CreateBoundaries(basePattern); - - result.AddRange(basePattern.Parts); - - // Tile along the primary axis. - var primaryTiles = TilePattern(basePattern, primaryAxis, boundaries); - result.AddRange(primaryTiles); - - // Build a full-row pattern for perpendicular tiling. - if (primaryTiles.Count > 0) - { - var rowPattern = new Pattern(); - rowPattern.Parts.AddRange(result); - rowPattern.UpdateBounds(); - basePattern = rowPattern; - boundaries = CreateBoundaries(basePattern); - } - - // Tile along the perpendicular axis. - result.AddRange(TilePattern(basePattern, PerpendicularAxis(primaryAxis), boundaries)); - - return result; + return FillRecursive(basePattern, primaryAxis, depth: 0); } /// - /// Fills the work area by creating a row along the primary axis, - /// then tiling that row pattern along the perpendicular axis. + /// Fills the work area by creating a seed part, then recursively tiling + /// along the primary axis and then the perpendicular axis. /// public List Fill(Drawing drawing, double rotationAngle, NestDirection primaryAxis) { - var rowPattern = FillRow(drawing, rotationAngle, primaryAxis); + var seed = MakeSeedPattern(drawing, rotationAngle); - if (rowPattern.Parts.Count == 0) + if (seed.Parts.Count == 0) return new List(); - var boundaries = CreateBoundaries(rowPattern); - var result = new List(rowPattern.Parts); - result.AddRange(TilePattern(rowPattern, PerpendicularAxis(primaryAxis), boundaries)); - - return result; + return FillRecursive(seed, primaryAxis, depth: 0); } } }