fix(bestfit): never reject pair candidates by utilization

Thin-framed, hollow, or concave parts (e.g. SULLYS-035's frame) have
inherently low part-to-bbox utilization yet nest tightly, so the 30%
MinUtilization floor wrongly dropped every candidate for them. Pair
quality is judged by the rotated pair bounding-box area the results
are already sorted on; utilization now only ever serves as the
high-aspect exception (UtilizationOverride), never as a rejection.

Adds a hollow-frame helper plus regression tests that kept pairs
exist with low utilization and results stay sorted by pair area.
This commit is contained in:
aj
2026-09-26 14:14:44 -04:00
parent 77b729e58c
commit 094c4c196b
3 changed files with 53 additions and 11 deletions
+8 -11
View File
@@ -7,7 +7,14 @@ namespace OpenNest.Engine.BestFit
public double MaxPlateWidth { get; set; }
public double MaxPlateHeight { get; set; }
public double MaxAspectRatio { get; set; } = 5.0;
public double MinUtilization { get; set; } = 0.3;
/// <summary>
/// A high-aspect pair is kept anyway when this much of its rotated bounding box is
/// actual part area. Utilization is only ever an exception here, never a rejection:
/// thin-framed, hollow, or concave (e.g. S-shaped) parts have inherently low
/// part-to-bbox utilization, yet can nest tightly — their quality is judged by the
/// pair bounding-box area the results are sorted on, not by utilization.
/// </summary>
public double UtilizationOverride { get; set; } = 0.75;
public void Apply(List<BestFitResult> results)
@@ -40,16 +47,6 @@ namespace OpenNest.Engine.BestFit
continue;
}
if (result.Utilization < MinUtilization)
{
result.Keep = false;
result.Reason = string.Format(
"Utilization {0:P0} below minimum",
result.Utilization
);
continue;
}
result.Reason = "Valid";
}
}