perf: add CloneAtOffset to skip re-rotation and bbox walk on part clones

Part.Clone() re-clones from the drawing's unrotated program, re-rotates,
and walks all CNC codes twice for bounding box — 4 O(c) passes per clone.
CloneAtOffset clones from the already-rotated program and computes the
bounding box arithmetically, reducing to 1 O(c) pass per clone.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 22:53:02 -04:00
parent 5fc16e9dae
commit 23b5358352
3 changed files with 27 additions and 9 deletions

View File

@@ -208,5 +208,29 @@ namespace OpenNest
return part;
}
/// <summary>
/// Creates an offset copy of the part. Clones from the already-rotated
/// program (skips re-rotation) and computes the bounding box arithmetically
/// (skips Program.BoundingBox walk).
/// </summary>
public Part CloneAtOffset(Vector offset)
{
var clonedProgram = Program.Clone() as Program;
var part = new Part(BaseDrawing, clonedProgram,
location + offset,
new Box(BoundingBox.X + offset.X, BoundingBox.Y + offset.Y,
BoundingBox.Width, BoundingBox.Height));
return part;
}
private Part(Drawing baseDrawing, Program program, Vector location, Box boundingBox)
{
BaseDrawing = baseDrawing;
Program = program;
this.location = location;
BoundingBox = boundingBox;
}
}
}

View File

@@ -76,8 +76,7 @@ namespace OpenNest
var pushDir = GetPushDirection(direction);
var opposite = Helper.OppositeDirection(pushDir);
var partB = (Part)partA.Clone();
partB.Offset(MakeOffset(direction, bboxDim));
var partB = partA.CloneAtOffset(MakeOffset(direction, bboxDim));
var movingLines = boundary.GetLines(partB.Location, pushDir);
var stationaryLines = boundary.GetLines(partA.Location, opposite);
@@ -364,8 +363,7 @@ namespace OpenNest
if (nextPos + dim > limit + Tolerance.Epsilon)
break;
var clone = (Part)template.Clone();
clone.Offset(MakeOffset(direction, copyDistance * count));
var clone = template.CloneAtOffset(MakeOffset(direction, copyDistance * count));
seed.Parts.Add(clone);
count++;
}

View File

@@ -24,11 +24,7 @@ namespace OpenNest
var pattern = new Pattern();
foreach (var part in Parts)
{
var clone = (Part)part.Clone();
clone.Offset(offset);
pattern.Parts.Add(clone);
}
pattern.Parts.Add(part.CloneAtOffset(offset));
pattern.UpdateBounds();
return pattern;