mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-26 20:01:05 -04:00
fix(engine): remove only rail clamps and always name them on the sheet
Last-resort removal ran on any clamped stock, but only a rail-following plate can record which clamp to pull and its removal time: an explicit-zone target lost the instruction entirely. NestPlateStock now carries the rail its zones were resolved from (NestStockBuilder, DrawingJobMapper.FromPlate); recovery removes clamps only from rail-backed stock, and commit falls back to the stock's rail when the target plate has none. Runs are now ordered by distance from the origin along the edge, not by zone list order. PM 346d46ed-9336-4706-9392-52ed14d6bd33; PM 6ded8ac4 item (d)
This commit is contained in:
1 parent
3bf63b74f9
commit
af50da7609
7 files changed
+101
-13
No files matched your search
@@ -58,7 +58,8 @@ public static class DrawingJobMapper
|
||||
plate.Quadrant,
|
||||
cost: null,
|
||||
clampZones: new List<ClampZone>(plate.ClampZones)
|
||||
);
|
||||
)
|
||||
{ ClampRail = plate.ClampRail };
|
||||
}
|
||||
|
||||
public static Program ToProgram(PartGeometrySnapshot geometry)
|
||||
|
||||
@@ -56,7 +56,7 @@ internal static class ClampRemovalRecovery
|
||||
return null;
|
||||
|
||||
var availableStock = job.Plates.Where(s => s.Quantity != 0).ToList();
|
||||
if (!availableStock.Any(s => s.ClampZones.Count > 0))
|
||||
if (!availableStock.Any(CanRemoveClamps))
|
||||
return null;
|
||||
|
||||
var partsById = job.Parts.ToDictionary(p => p.Id, StringComparer.Ordinal);
|
||||
@@ -153,7 +153,7 @@ internal static class ClampRemovalRecovery
|
||||
Removal best = null;
|
||||
foreach (var stock in stocks)
|
||||
{
|
||||
if (stock.ClampZones.Count == 0)
|
||||
if (!CanRemoveClamps(stock))
|
||||
continue;
|
||||
token.ThrowIfCancellationRequested();
|
||||
var found = MinimalRemovalForStock(part, stock, options, engine, token);
|
||||
@@ -165,10 +165,16 @@ internal static class ClampRemovalRecovery
|
||||
return best;
|
||||
}
|
||||
|
||||
/// <summary>Only clamps resolved from a machine rail can be removed (see
|
||||
/// <see cref="NestPlateStock.ClampRail"/>): explicit zones have no clamp to name.</summary>
|
||||
private static bool CanRemoveClamps(NestPlateStock stock) =>
|
||||
stock.ClampRail != null && stock.ClampZones.Count > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Ascending run size, then ascending start index: the first contiguous run of the
|
||||
/// stock's own clamp zones (already ordered by rail position) whose removal lets the
|
||||
/// part fit alone is both the fewest clamps and, among ties, the run nearest the origin.
|
||||
/// stock's own clamp zones, ordered by distance from the origin along the edge, whose
|
||||
/// removal lets the part fit alone is both the fewest clamps and, among ties, the run
|
||||
/// nearest the origin.
|
||||
/// </summary>
|
||||
private static Removal MinimalRemovalForStock(
|
||||
NestJobPart part,
|
||||
@@ -178,7 +184,11 @@ internal static class ClampRemovalRecovery
|
||||
CancellationToken token
|
||||
)
|
||||
{
|
||||
var zones = stock.ClampZones;
|
||||
// Placement-frame X is signed from the origin, so |centre X| is the distance along
|
||||
// the edge in every quadrant.
|
||||
var zones = stock.ClampZones
|
||||
.OrderBy(z => System.Math.Abs(z.Bounds.X + z.Bounds.Length / 2))
|
||||
.ToList();
|
||||
for (var run = 1; run <= zones.Count; run++)
|
||||
{
|
||||
for (var start = 0; start + run <= zones.Count; start++)
|
||||
@@ -263,7 +273,8 @@ internal static class ClampRemovalRecovery
|
||||
stock.Quadrant,
|
||||
stock.Cost,
|
||||
plateFrameZones
|
||||
);
|
||||
)
|
||||
{ ClampRail = stock.ClampRail };
|
||||
}
|
||||
|
||||
private static string Suffixed(string stockId, IReadOnlyList<string> removedIds) =>
|
||||
|
||||
@@ -71,7 +71,9 @@ public static class NestPipelineCommit
|
||||
if (SameInPlacementFrame(plate.ClampZones, stock.ClampZones, left, bottom))
|
||||
return;
|
||||
|
||||
var rail = plate.ClampRail;
|
||||
// A plate without a rail still takes the rail its stock was resolved from, so a
|
||||
// last-resort removal on that stock is never committed without naming the clamp.
|
||||
var rail = plate.ClampRail ?? stock.ClampRail;
|
||||
plate.SetClampRail(null); // explicit zones from here on
|
||||
foreach (var zone in stock.ClampZones)
|
||||
plate.ClampZones.Add(new ClampZone(zone.Id, zone.Bounds.Translate(-left, -bottom)));
|
||||
|
||||
@@ -81,6 +81,14 @@ public sealed class NestPlateStock
|
||||
/// </summary>
|
||||
internal IReadOnlyList<ClampZone> SheetClampZones { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The machine clamp rail <see cref="ClampZones"/> were resolved from, when the stock was
|
||||
/// built from a rail-following plate; null for explicit zones. Only rail-backed clamps may
|
||||
/// be taken off as a last resort (D8): the rail is what lets a committed sheet name the
|
||||
/// clamps to pull and carry their removal time, so explicit zones are never removed.
|
||||
/// </summary>
|
||||
internal ClampRail ClampRail { get; init; }
|
||||
|
||||
/// <summary>Generic per-physical-sheet cost; null selects area scoring.</summary>
|
||||
public double? Cost { get; }
|
||||
public string Id { get; }
|
||||
|
||||
@@ -33,7 +33,8 @@ public static class NestStockBuilder
|
||||
template.Quadrant,
|
||||
option.Cost == 0 ? null : option.Cost,
|
||||
ClampZonesFor(template, size)
|
||||
));
|
||||
)
|
||||
{ ClampRail = template.ClampRail });
|
||||
}
|
||||
NestJobValidator.ValidateStockCosts(stock);
|
||||
return stock.AsReadOnly();
|
||||
|
||||
Reference in new issue
Block a user