feat(engine): rebind live fill previews to the drawing's original frame
DefaultPlateFiller runs its search in a canonical (MBR-axis-aligned) copy of the drawing. Intermediate progress reports — the Nesting Progress dialog, PlateView's active-parts overlay — were showing that transient canonical orientation instead of the drawing's real one. FillContext.OriginalDrawing carries the pre-canonicalization drawing through the pipeline; ReportProgress rebinds reported parts to it via CanonicalFrame.RebindToOriginal before they reach the UI. Uses a shallow list copy rather than per-part Part.Clone() — Clone() re-derives its target rotation from BaseDrawing.Program.Rotation + Rotation, which would double-count the canonical drawing's baked source angle.
This commit is contained in:
@@ -112,7 +112,7 @@ internal class DefaultPlateFiller : PlateFillerBase
|
||||
);
|
||||
}
|
||||
|
||||
var best = RunFillPipeline(canonicalItem, effectiveWorkArea, progress, token);
|
||||
var best = RunFillPipeline(canonicalItem, originalDrawing, effectiveWorkArea, progress, token);
|
||||
|
||||
if (
|
||||
canonicalItem.Quantity > 0
|
||||
@@ -125,7 +125,7 @@ internal class DefaultPlateFiller : PlateFillerBase
|
||||
);
|
||||
PhaseResults.Clear();
|
||||
AngleResults.Clear();
|
||||
best = RunFillPipeline(canonicalItem, workArea, progress, token);
|
||||
best = RunFillPipeline(canonicalItem, originalDrawing, workArea, progress, token);
|
||||
}
|
||||
|
||||
if (canonicalItem.Quantity > 0 && best.Count > canonicalItem.Quantity)
|
||||
@@ -333,6 +333,7 @@ internal class DefaultPlateFiller : PlateFillerBase
|
||||
|
||||
private List<Part> RunFillPipeline(
|
||||
NestItem item,
|
||||
Drawing originalDrawing,
|
||||
Box workArea,
|
||||
IProgress<NestProgress> progress,
|
||||
CancellationToken token
|
||||
@@ -341,6 +342,7 @@ internal class DefaultPlateFiller : PlateFillerBase
|
||||
var context = new FillContext
|
||||
{
|
||||
Item = item,
|
||||
OriginalDrawing = originalDrawing,
|
||||
WorkArea = workArea,
|
||||
Plate = Plate,
|
||||
PlateNumber = PlateNumber,
|
||||
@@ -474,7 +476,7 @@ internal class DefaultPlateFiller : PlateFillerBase
|
||||
{
|
||||
Phase = context.WinnerPhase,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = context.CurrentBest,
|
||||
Parts = context.ToOriginalFrame(context.CurrentBest),
|
||||
WorkArea = context.WorkArea,
|
||||
Description = BuildProgressSummary(),
|
||||
IsOverallBest = true,
|
||||
|
||||
@@ -20,6 +20,16 @@ namespace OpenNest.Engine.Strategies
|
||||
public int MaxQuantity { get; init; }
|
||||
public PartType PartType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The pre-canonicalization drawing that <see cref="Item"/>'s canonical copy was built
|
||||
/// from. When set, <see cref="ReportProgress"/> rebinds reported parts to this drawing
|
||||
/// before they reach <see cref="Progress"/>, so intermediate previews (e.g. the Nesting
|
||||
/// Progress dialog, PlateView's active-parts overlay) show the drawing's real/visible
|
||||
/// orientation instead of the transient canonical (MBR-axis-aligned) one. Null when the
|
||||
/// caller isn't operating in canonical frame (e.g. tests driving a strategy directly).
|
||||
/// </summary>
|
||||
public Drawing OriginalDrawing { get; init; }
|
||||
|
||||
public List<Part> CurrentBest { get; set; }
|
||||
|
||||
/// <summary>For progress reporting only; comparisons use Policy.Comparer.</summary>
|
||||
@@ -57,12 +67,32 @@ namespace OpenNest.Engine.Strategies
|
||||
{
|
||||
Phase = ActivePhase,
|
||||
PlateNumber = PlateNumber,
|
||||
Parts = isNewBest ? parts : CurrentBest,
|
||||
Parts = ToOriginalFrame(isNewBest ? parts : CurrentBest),
|
||||
WorkArea = WorkArea,
|
||||
Description = description,
|
||||
IsOverallBest = isNewBest,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebinds <paramref name="parts"/> to <see cref="OriginalDrawing"/> for outward-facing
|
||||
/// progress reports. Uses a shallow list copy (not per-part <see cref="Part.Clone"/>) so
|
||||
/// <see cref="CanonicalFrame.RebindToOriginal"/>'s in-place slot replacement can't corrupt
|
||||
/// the caller's list (e.g. <see cref="CurrentBest"/>) — <c>Part.Clone()</c> re-derives its
|
||||
/// target rotation from <c>BaseDrawing.Program.Rotation + Rotation</c>, which double-counts
|
||||
/// the canonical drawing's baked source angle whenever it's non-zero. No-op when
|
||||
/// <see cref="OriginalDrawing"/> isn't set. Internal so callers that build their own
|
||||
/// <see cref="ProgressReport"/> outside <see cref="ReportProgress"/> (e.g. the fallback
|
||||
/// report in <c>DefaultPlateFiller.RunPipelineCore</c> for strategies that don't self-report)
|
||||
/// can apply the same rebind before reaching the UI.
|
||||
/// </summary>
|
||||
internal List<Part> ToOriginalFrame(List<Part> parts)
|
||||
{
|
||||
if (parts == null || parts.Count == 0 || OriginalDrawing == null)
|
||||
return parts;
|
||||
|
||||
return CanonicalFrame.RebindToOriginal(new List<Part>(parts), OriginalDrawing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user