style: apply CSharpier formatting to all C# sources
Repo-wide sweep with the pinned CSharpier 1.3.0 tool. Whitespace and line-wrapping only; OpenNest.Engine.Tests (109) and OpenNest.IO.Tests pass after reformat, full solution builds 0 errors. Added .csharpierignore so csproj/config XML keeps its existing layout (CSharpier's XML wrapping churns attributes with zero benefit). Formatting is now enforceable: dotnet csharpier check . passes.
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using OpenNest.Engine;
|
||||
using OpenNest.Engine.BestFit;
|
||||
using OpenNest.Engine.Fill;
|
||||
@@ -5,21 +10,18 @@ using OpenNest.Engine.Strategies;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
using OpenNest.RectanglePacking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace OpenNest
|
||||
{
|
||||
public class DefaultNestEngine : NestEngineBase
|
||||
{
|
||||
public DefaultNestEngine(Plate plate) : base(plate) { }
|
||||
public DefaultNestEngine(Plate plate)
|
||||
: base(plate) { }
|
||||
|
||||
public override string Name => "Default";
|
||||
|
||||
public override string Description => "Multi-phase nesting (Linear, Pairs, RectBestFit, Extents)";
|
||||
public override string Description =>
|
||||
"Multi-phase nesting (Linear, Pairs, RectBestFit, Extents)";
|
||||
|
||||
private readonly AngleCandidateBuilder angleBuilder = new();
|
||||
|
||||
@@ -29,7 +31,11 @@ namespace OpenNest
|
||||
set => angleBuilder.ForceFullSweep = value;
|
||||
}
|
||||
|
||||
public override List<double> BuildAngles(NestItem item, ClassificationResult classification, Box workArea)
|
||||
public override List<double> BuildAngles(
|
||||
NestItem item,
|
||||
ClassificationResult classification,
|
||||
Box workArea
|
||||
)
|
||||
{
|
||||
return angleBuilder.Build(item, classification, workArea);
|
||||
}
|
||||
@@ -41,8 +47,12 @@ namespace OpenNest
|
||||
|
||||
// --- Public Fill API ---
|
||||
|
||||
public override List<Part> Fill(NestItem item, Box workArea,
|
||||
IProgress<NestProgress> progress, CancellationToken token)
|
||||
public override List<Part> Fill(
|
||||
NestItem item,
|
||||
Box workArea,
|
||||
IProgress<NestProgress> progress,
|
||||
CancellationToken token
|
||||
)
|
||||
{
|
||||
PhaseResults.Clear();
|
||||
AngleResults.Clear();
|
||||
@@ -67,18 +77,23 @@ namespace OpenNest
|
||||
var fast = TryFillSmallQuantity(canonicalItem, workArea);
|
||||
if (fast != null && fast.Count >= canonicalItem.Quantity)
|
||||
{
|
||||
Debug.WriteLine($"[Fill] Fast path: placed {fast.Count} parts for qty={canonicalItem.Quantity}");
|
||||
Debug.WriteLine(
|
||||
$"[Fill] Fast path: placed {fast.Count} parts for qty={canonicalItem.Quantity}"
|
||||
);
|
||||
WinnerPhase = NestPhase.Pairs;
|
||||
fast = RebindAndUnCanonicalize(fast, originalDrawing, sourceAngle);
|
||||
ReportProgress(progress, new ProgressReport
|
||||
{
|
||||
Phase = WinnerPhase,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = fast,
|
||||
WorkArea = workArea,
|
||||
Description = $"Fast path: {fast.Count} parts",
|
||||
IsOverallBest = true,
|
||||
});
|
||||
ReportProgress(
|
||||
progress,
|
||||
new ProgressReport
|
||||
{
|
||||
Phase = WinnerPhase,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = fast,
|
||||
WorkArea = workArea,
|
||||
Description = $"Fast path: {fast.Count} parts",
|
||||
IsOverallBest = true,
|
||||
}
|
||||
);
|
||||
return fast;
|
||||
}
|
||||
}
|
||||
@@ -88,16 +103,24 @@ namespace OpenNest
|
||||
{
|
||||
effectiveWorkArea = ShrinkWorkArea(canonicalItem, workArea, Plate.PartSpacing);
|
||||
if (effectiveWorkArea != workArea)
|
||||
Debug.WriteLine($"[Fill] Low-qty shrink: {canonicalItem.Quantity} requested, " +
|
||||
$"from {workArea.Width:F1}x{workArea.Length:F1} " +
|
||||
$"to {effectiveWorkArea.Width:F1}x{effectiveWorkArea.Length:F1}");
|
||||
Debug.WriteLine(
|
||||
$"[Fill] Low-qty shrink: {canonicalItem.Quantity} requested, "
|
||||
+ $"from {workArea.Width:F1}x{workArea.Length:F1} "
|
||||
+ $"to {effectiveWorkArea.Width:F1}x{effectiveWorkArea.Length:F1}"
|
||||
);
|
||||
}
|
||||
|
||||
var best = RunFillPipeline(canonicalItem, effectiveWorkArea, progress, token);
|
||||
|
||||
if (canonicalItem.Quantity > 0 && best.Count < canonicalItem.Quantity && effectiveWorkArea != workArea)
|
||||
if (
|
||||
canonicalItem.Quantity > 0
|
||||
&& best.Count < canonicalItem.Quantity
|
||||
&& effectiveWorkArea != workArea
|
||||
)
|
||||
{
|
||||
Debug.WriteLine($"[Fill] Low-qty fallback: got {best.Count}, need {canonicalItem.Quantity}, retrying full area");
|
||||
Debug.WriteLine(
|
||||
$"[Fill] Low-qty fallback: got {best.Count}, need {canonicalItem.Quantity}, retrying full area"
|
||||
);
|
||||
PhaseResults.Clear();
|
||||
AngleResults.Clear();
|
||||
best = RunFillPipeline(canonicalItem, workArea, progress, token);
|
||||
@@ -108,15 +131,18 @@ namespace OpenNest
|
||||
|
||||
best = RebindAndUnCanonicalize(best, originalDrawing, sourceAngle);
|
||||
|
||||
ReportProgress(progress, new ProgressReport
|
||||
{
|
||||
Phase = WinnerPhase,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = best,
|
||||
WorkArea = workArea,
|
||||
Description = BuildProgressSummary(),
|
||||
IsOverallBest = true,
|
||||
});
|
||||
ReportProgress(
|
||||
progress,
|
||||
new ProgressReport
|
||||
{
|
||||
Phase = WinnerPhase,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = best,
|
||||
WorkArea = workArea,
|
||||
Description = BuildProgressSummary(),
|
||||
IsOverallBest = true,
|
||||
}
|
||||
);
|
||||
|
||||
return best;
|
||||
}
|
||||
@@ -126,7 +152,11 @@ namespace OpenNest
|
||||
/// original Drawing (so consumers see the user's drawing identity, not the transient canonical copy)
|
||||
/// and composes sourceAngle onto each Part's rotation via CanonicalFrame.FromCanonical.
|
||||
/// </summary>
|
||||
private static List<Part> RebindAndUnCanonicalize(List<Part> parts, Drawing original, double sourceAngle)
|
||||
private static List<Part> RebindAndUnCanonicalize(
|
||||
List<Part> parts,
|
||||
Drawing original,
|
||||
double sourceAngle
|
||||
)
|
||||
{
|
||||
if (parts == null || parts.Count == 0)
|
||||
return parts;
|
||||
@@ -164,8 +194,10 @@ namespace OpenNest
|
||||
private static List<Part> TryPlaceSingle(Drawing drawing, Box workArea)
|
||||
{
|
||||
var part = Part.CreateAtOrigin(drawing);
|
||||
if (part.BoundingBox.Width > workArea.Width + Tolerance.Epsilon ||
|
||||
part.BoundingBox.Length > workArea.Length + Tolerance.Epsilon)
|
||||
if (
|
||||
part.BoundingBox.Width > workArea.Width + Tolerance.Epsilon
|
||||
|| part.BoundingBox.Length > workArea.Length + Tolerance.Epsilon
|
||||
)
|
||||
return null;
|
||||
|
||||
part.Offset(workArea.Location - part.BoundingBox.Location);
|
||||
@@ -175,7 +207,11 @@ namespace OpenNest
|
||||
private List<Part> TryPlaceBestFitPair(Drawing drawing, Box workArea)
|
||||
{
|
||||
var bestFits = BestFitCache.GetOrCompute(
|
||||
drawing, Plate.Size.Length, Plate.Size.Width, Plate.PartSpacing);
|
||||
drawing,
|
||||
Plate.Size.Length,
|
||||
Plate.Size.Width,
|
||||
Plate.PartSpacing
|
||||
);
|
||||
|
||||
// Build pair candidates with a canonical drawing so their geometry matches
|
||||
// the coordinate frame of the cached fit results.
|
||||
@@ -189,9 +225,15 @@ namespace OpenNest
|
||||
continue;
|
||||
|
||||
// Skip pairs that can't possibly fit the work area in either orientation.
|
||||
if (fit.ShortestSide > System.Math.Min(workArea.Width, workArea.Length) + Tolerance.Epsilon)
|
||||
if (
|
||||
fit.ShortestSide
|
||||
> System.Math.Min(workArea.Width, workArea.Length) + Tolerance.Epsilon
|
||||
)
|
||||
continue;
|
||||
if (fit.LongestSide > System.Math.Max(workArea.Width, workArea.Length) + Tolerance.Epsilon)
|
||||
if (
|
||||
fit.LongestSide
|
||||
> System.Math.Max(workArea.Width, workArea.Length) + Tolerance.Epsilon
|
||||
)
|
||||
continue;
|
||||
|
||||
var landscape = fit.BuildParts(canonicalDrawing);
|
||||
@@ -247,8 +289,10 @@ namespace OpenNest
|
||||
private static bool TryOffsetToWorkArea(List<Part> parts, Box workArea)
|
||||
{
|
||||
var bbox = ((IEnumerable<IBoundable>)parts).GetBoundingBox();
|
||||
if (bbox.Width > workArea.Width + Tolerance.Epsilon ||
|
||||
bbox.Length > workArea.Length + Tolerance.Epsilon)
|
||||
if (
|
||||
bbox.Width > workArea.Width + Tolerance.Epsilon
|
||||
|| bbox.Length > workArea.Length + Tolerance.Epsilon
|
||||
)
|
||||
return false;
|
||||
|
||||
var offset = workArea.Location - bbox.Location;
|
||||
@@ -271,7 +315,10 @@ namespace OpenNest
|
||||
return workArea;
|
||||
|
||||
var bin = new Bin { Size = new Size(workArea.Width, workArea.Length) };
|
||||
var packItem = new Item { Size = new Size(bbox.Width + spacing, bbox.Length + spacing) };
|
||||
var packItem = new Item
|
||||
{
|
||||
Size = new Size(bbox.Width + spacing, bbox.Length + spacing),
|
||||
};
|
||||
var packer = new FillBestFit(bin);
|
||||
packer.Fill(packItem);
|
||||
var fullCount = bin.Items.Count;
|
||||
@@ -303,8 +350,12 @@ namespace OpenNest
|
||||
return new Box(workArea.X, workArea.Y, newLength, newWidth);
|
||||
}
|
||||
|
||||
private List<Part> RunFillPipeline(NestItem item, Box workArea,
|
||||
IProgress<NestProgress> progress, CancellationToken token)
|
||||
private List<Part> RunFillPipeline(
|
||||
NestItem item,
|
||||
Box workArea,
|
||||
IProgress<NestProgress> progress,
|
||||
CancellationToken token
|
||||
)
|
||||
{
|
||||
var context = new FillContext
|
||||
{
|
||||
@@ -326,8 +377,12 @@ namespace OpenNest
|
||||
return context.CurrentBest ?? new List<Part>();
|
||||
}
|
||||
|
||||
public override List<Part> Fill(List<Part> groupParts, Box workArea,
|
||||
IProgress<NestProgress> progress, CancellationToken token)
|
||||
public override List<Part> Fill(
|
||||
List<Part> groupParts,
|
||||
Box workArea,
|
||||
IProgress<NestProgress> progress,
|
||||
CancellationToken token
|
||||
)
|
||||
{
|
||||
if (groupParts == null || groupParts.Count == 0)
|
||||
return new List<Part>();
|
||||
@@ -346,25 +401,34 @@ namespace OpenNest
|
||||
var best = FillHelpers.FillPattern(engine, groupParts, angles, workArea, Comparer);
|
||||
PhaseResults.Add(new PhaseResult(NestPhase.Linear, best?.Count ?? 0, 0));
|
||||
|
||||
Debug.WriteLine($"[Fill(groupParts,Box)] Linear pattern: {best?.Count ?? 0} parts | WorkArea: {workArea.Width:F1}x{workArea.Length:F1}");
|
||||
Debug.WriteLine(
|
||||
$"[Fill(groupParts,Box)] Linear pattern: {best?.Count ?? 0} parts | WorkArea: {workArea.Width:F1}x{workArea.Length:F1}"
|
||||
);
|
||||
|
||||
ReportProgress(progress, new ProgressReport
|
||||
{
|
||||
Phase = NestPhase.Linear,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = best,
|
||||
WorkArea = workArea,
|
||||
Description = BuildProgressSummary(),
|
||||
IsOverallBest = true,
|
||||
});
|
||||
ReportProgress(
|
||||
progress,
|
||||
new ProgressReport
|
||||
{
|
||||
Phase = NestPhase.Linear,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = best,
|
||||
WorkArea = workArea,
|
||||
Description = BuildProgressSummary(),
|
||||
IsOverallBest = true,
|
||||
}
|
||||
);
|
||||
|
||||
return best ?? new List<Part>();
|
||||
}
|
||||
|
||||
// --- Pack API ---
|
||||
|
||||
public override List<Part> PackArea(Box box, List<NestItem> items,
|
||||
IProgress<NestProgress> progress, CancellationToken token)
|
||||
public override List<Part> PackArea(
|
||||
Box box,
|
||||
List<NestItem> items,
|
||||
IProgress<NestProgress> progress,
|
||||
CancellationToken token
|
||||
)
|
||||
{
|
||||
var binItems = BinConverter.ToItems(items, Plate.PartSpacing, Plate.Area());
|
||||
var bin = BinConverter.CreateBin(box, Plate.PartSpacing);
|
||||
@@ -399,7 +463,10 @@ namespace OpenNest
|
||||
sw.Stop();
|
||||
|
||||
var phaseResult = new PhaseResult(
|
||||
strategy.Phase, result?.Count ?? 0, sw.ElapsedMilliseconds);
|
||||
strategy.Phase,
|
||||
result?.Count ?? 0,
|
||||
sw.ElapsedMilliseconds
|
||||
);
|
||||
context.PhaseResults.Add(phaseResult);
|
||||
|
||||
// Keep engine's PhaseResults in sync so BuildProgressSummary() works
|
||||
@@ -409,7 +476,11 @@ namespace OpenNest
|
||||
// FillContext.ReportProgress updates CurrentBest during the
|
||||
// strategy's angle sweep. This catches strategies that return a
|
||||
// result without reporting it (e.g. RectBestFit).
|
||||
var improved = context.Policy.Comparer.IsBetter(result, context.CurrentBest, context.WorkArea);
|
||||
var improved = context.Policy.Comparer.IsBetter(
|
||||
result,
|
||||
context.CurrentBest,
|
||||
context.WorkArea
|
||||
);
|
||||
if (improved)
|
||||
{
|
||||
context.CurrentBest = result;
|
||||
@@ -419,15 +490,18 @@ namespace OpenNest
|
||||
|
||||
if (improved && context.CurrentBest != null && context.CurrentBest.Count > 0)
|
||||
{
|
||||
ReportProgress(context.Progress, new ProgressReport
|
||||
{
|
||||
Phase = context.WinnerPhase,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = context.CurrentBest,
|
||||
WorkArea = context.WorkArea,
|
||||
Description = BuildProgressSummary(),
|
||||
IsOverallBest = true,
|
||||
});
|
||||
ReportProgress(
|
||||
context.Progress,
|
||||
new ProgressReport
|
||||
{
|
||||
Phase = context.WinnerPhase,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = context.CurrentBest,
|
||||
WorkArea = context.WorkArea,
|
||||
Description = BuildProgressSummary(),
|
||||
IsOverallBest = true,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,6 +512,5 @@ namespace OpenNest
|
||||
|
||||
RecordProductiveAngles(context.AngleResults);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user