feat: add NestEngine.FillLinear with 4-config rotation/axis optimization
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenNest.Converters;
|
||||||
using OpenNest.Geometry;
|
using OpenNest.Geometry;
|
||||||
using OpenNest.Math;
|
using OpenNest.Math;
|
||||||
using OpenNest.RectanglePacking;
|
using OpenNest.RectanglePacking;
|
||||||
@@ -107,6 +109,77 @@ namespace OpenNest
|
|||||||
return parts.Count > 0;
|
return parts.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool FillLinear(NestItem item)
|
||||||
|
{
|
||||||
|
var workArea = Plate.WorkArea();
|
||||||
|
var bestRotation = FindBestRotation(item);
|
||||||
|
|
||||||
|
var engine = new FillLinear(workArea, Plate.PartSpacing);
|
||||||
|
|
||||||
|
// Try 4 configurations: 2 rotations x 2 axes.
|
||||||
|
var configs = new[]
|
||||||
|
{
|
||||||
|
engine.Fill(item.Drawing, bestRotation, NestDirection.Horizontal),
|
||||||
|
engine.Fill(item.Drawing, bestRotation, NestDirection.Vertical),
|
||||||
|
engine.Fill(item.Drawing, bestRotation + Angle.HalfPI, NestDirection.Horizontal),
|
||||||
|
engine.Fill(item.Drawing, bestRotation + Angle.HalfPI, NestDirection.Vertical)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pick the configuration with the most parts.
|
||||||
|
List<Part> best = null;
|
||||||
|
|
||||||
|
foreach (var config in configs)
|
||||||
|
{
|
||||||
|
if (best == null || config.Count > best.Count)
|
||||||
|
best = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best == null || best.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Limit to requested quantity if specified.
|
||||||
|
if (item.Quantity > 0 && best.Count > item.Quantity)
|
||||||
|
best = best.Take(item.Quantity).ToList();
|
||||||
|
|
||||||
|
Plate.Parts.AddRange(best);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double FindBestRotation(NestItem item)
|
||||||
|
{
|
||||||
|
var entities = ConvertProgram.ToGeometry(item.Drawing.Program)
|
||||||
|
.Where(e => e.Layer != SpecialLayers.Rapid);
|
||||||
|
|
||||||
|
var shapes = Helper.GetShapes(entities);
|
||||||
|
|
||||||
|
if (shapes.Count == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Find the largest shape (outer profile).
|
||||||
|
Shape largest = shapes[0];
|
||||||
|
double largestArea = largest.Area();
|
||||||
|
|
||||||
|
for (int i = 1; i < shapes.Count; i++)
|
||||||
|
{
|
||||||
|
var area = shapes[i].Area();
|
||||||
|
if (area > largestArea)
|
||||||
|
{
|
||||||
|
largest = shapes[i];
|
||||||
|
largestArea = area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundingRectangleResult result;
|
||||||
|
|
||||||
|
if (item.RotationStart.IsEqualTo(0) && item.RotationEnd.IsEqualTo(0))
|
||||||
|
result = largest.FindBestRotation();
|
||||||
|
else
|
||||||
|
result = largest.FindBestRotation(item.RotationStart, item.RotationEnd);
|
||||||
|
|
||||||
|
// Negate the angle to align the minimum bounding rectangle with the axes.
|
||||||
|
return -result.Angle;
|
||||||
|
}
|
||||||
|
|
||||||
private List<Part> ConvertToParts(Bin bin, List<NestItem> items)
|
private List<Part> ConvertToParts(Bin bin, List<NestItem> items)
|
||||||
{
|
{
|
||||||
var parts = new List<Part>();
|
var parts = new List<Part>();
|
||||||
|
|||||||
Reference in New Issue
Block a user