fix: resolve infinite loop in multi-plate autonest and wire into console
- Change while(true) to bounded for-loop (max 100 plates) in MainForm - Use Drawing.Name comparison instead of reference equality for quantity deduction - Add Math.Max(0, ...) guard to prevent negative quantities - Tune SA parameters for faster convergence (cooling=0.995, minTemp=0.1, maxNoImprove=500) - Add --autonest flag to OpenNest.Console for CLI-based NFP autonesting Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@ var checkOverlaps = false;
|
||||
var noSave = false;
|
||||
var noLog = false;
|
||||
var keepParts = false;
|
||||
var autoNest = false;
|
||||
|
||||
for (var i = 0; i < args.Length; i++)
|
||||
{
|
||||
@@ -60,6 +61,9 @@ for (var i = 0; i < args.Length; i++)
|
||||
case "--keep-parts":
|
||||
keepParts = true;
|
||||
break;
|
||||
case "--autonest":
|
||||
autoNest = true;
|
||||
break;
|
||||
case "--help":
|
||||
case "-h":
|
||||
PrintUsage();
|
||||
@@ -145,11 +149,38 @@ else
|
||||
|
||||
Console.WriteLine("---");
|
||||
|
||||
// Run fill.
|
||||
// Run fill or autonest.
|
||||
var sw = Stopwatch.StartNew();
|
||||
var engine = new NestEngine(plate);
|
||||
var item = new NestItem { Drawing = drawing, Quantity = quantity };
|
||||
var success = engine.Fill(item);
|
||||
bool success;
|
||||
|
||||
if (autoNest)
|
||||
{
|
||||
// AutoNest: use all drawings (or specific drawing if --drawing given).
|
||||
var nestItems = new List<NestItem>();
|
||||
|
||||
if (drawingName != null)
|
||||
{
|
||||
nestItems.Add(new NestItem { Drawing = drawing, Quantity = quantity > 0 ? quantity : 1 });
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var d in nest.Drawings)
|
||||
nestItems.Add(new NestItem { Drawing = d, Quantity = quantity > 0 ? quantity : 1 });
|
||||
}
|
||||
|
||||
Console.WriteLine($"AutoNest: {nestItems.Count} drawing(s), {nestItems.Sum(i => i.Quantity)} total parts");
|
||||
|
||||
var parts = NestEngine.AutoNest(nestItems, plate);
|
||||
plate.Parts.AddRange(parts);
|
||||
success = parts.Count > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var engine = new NestEngine(plate);
|
||||
var item = new NestItem { Drawing = drawing, Quantity = quantity };
|
||||
success = engine.Fill(item);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// Check overlaps.
|
||||
@@ -208,6 +239,7 @@ void PrintUsage()
|
||||
Console.Error.WriteLine(" --spacing <value> Override part spacing");
|
||||
Console.Error.WriteLine(" --size <WxH> Override plate size (e.g. 120x60)");
|
||||
Console.Error.WriteLine(" --output <path> Output nest file path (default: <input>-result.zip)");
|
||||
Console.Error.WriteLine(" --autonest Use NFP-based mixed-part autonesting instead of linear fill");
|
||||
Console.Error.WriteLine(" --keep-parts Don't clear existing parts before filling");
|
||||
Console.Error.WriteLine(" --check-overlaps Run overlap detection after fill (exit code 1 if found)");
|
||||
Console.Error.WriteLine(" --no-save Skip saving output file");
|
||||
|
||||
@@ -13,9 +13,9 @@ namespace OpenNest
|
||||
/// </summary>
|
||||
public class SimulatedAnnealing : INestOptimizer
|
||||
{
|
||||
private const double DefaultCoolingRate = 0.997;
|
||||
private const double DefaultMinTemperature = 0.01;
|
||||
private const int DefaultMaxNoImprovement = 2000;
|
||||
private const double DefaultCoolingRate = 0.995;
|
||||
private const double DefaultMinTemperature = 0.1;
|
||||
private const int DefaultMaxNoImprovement = 500;
|
||||
|
||||
public NestResult Optimize(List<NestItem> items, Box workArea, NfpCache cache,
|
||||
Dictionary<int, List<double>> candidateRotations,
|
||||
|
||||
@@ -680,8 +680,9 @@ namespace OpenNest.Forms
|
||||
return;
|
||||
|
||||
var items = form.GetNestItems();
|
||||
var maxPlates = 100;
|
||||
|
||||
while (true)
|
||||
for (var plateCount = 0; plateCount < maxPlates; plateCount++)
|
||||
{
|
||||
var remaining = items.Where(i => i.Quantity > 0).ToList();
|
||||
|
||||
@@ -698,14 +699,15 @@ namespace OpenNest.Forms
|
||||
break;
|
||||
|
||||
plate.Parts.AddRange(parts);
|
||||
activeForm.Nest.UpdateDrawingQuantities();
|
||||
|
||||
// Reduce remaining quantities by how many were placed per drawing.
|
||||
// Deduct placed quantities using Drawing.Name to avoid reference issues.
|
||||
foreach (var item in remaining)
|
||||
{
|
||||
var placed = parts.Count(p => p.BaseDrawing == item.Drawing);
|
||||
item.Quantity -= placed;
|
||||
var placed = parts.Count(p => p.BaseDrawing.Name == item.Drawing.Name);
|
||||
item.Quantity = System.Math.Max(0, item.Quantity - placed);
|
||||
}
|
||||
|
||||
activeForm.Nest.UpdateDrawingQuantities();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user