perf: pre-compute directional edges in PartBoundary constructor
RotationDirection and direction filtering were recomputed on every GetLines call. Pre-compute edges per PushDirection once in the constructor so GetLines only translates cached edges. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,12 +9,17 @@ namespace OpenNest
|
|||||||
/// Pre-computed offset boundary polygons for a part's geometry.
|
/// Pre-computed offset boundary polygons for a part's geometry.
|
||||||
/// Polygons are stored at program-local origin (no location applied)
|
/// Polygons are stored at program-local origin (no location applied)
|
||||||
/// and can be efficiently translated to any location when extracting lines.
|
/// and can be efficiently translated to any location when extracting lines.
|
||||||
|
/// Directional edge filtering is pre-computed once in the constructor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PartBoundary
|
public class PartBoundary
|
||||||
{
|
{
|
||||||
private const double ChordTolerance = 0.01;
|
private const double ChordTolerance = 0.01;
|
||||||
|
|
||||||
private readonly List<Polygon> _polygons;
|
private readonly List<Polygon> _polygons;
|
||||||
|
private readonly (Vector start, Vector end)[] _leftEdges;
|
||||||
|
private readonly (Vector start, Vector end)[] _rightEdges;
|
||||||
|
private readonly (Vector start, Vector end)[] _upEdges;
|
||||||
|
private readonly (Vector start, Vector end)[] _downEdges;
|
||||||
|
|
||||||
public PartBoundary(Part part, double spacing)
|
public PartBoundary(Part part, double spacing)
|
||||||
{
|
{
|
||||||
@@ -33,6 +38,59 @@ namespace OpenNest
|
|||||||
polygon.RemoveSelfIntersections();
|
polygon.RemoveSelfIntersections();
|
||||||
_polygons.Add(polygon);
|
_polygons.Add(polygon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrecomputeDirectionalEdges(
|
||||||
|
out _leftEdges, out _rightEdges, out _upEdges, out _downEdges);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrecomputeDirectionalEdges(
|
||||||
|
out (Vector start, Vector end)[] leftEdges,
|
||||||
|
out (Vector start, Vector end)[] rightEdges,
|
||||||
|
out (Vector start, Vector end)[] upEdges,
|
||||||
|
out (Vector start, Vector end)[] downEdges)
|
||||||
|
{
|
||||||
|
var left = new List<(Vector, Vector)>();
|
||||||
|
var right = new List<(Vector, Vector)>();
|
||||||
|
var up = new List<(Vector, Vector)>();
|
||||||
|
var down = new List<(Vector, Vector)>();
|
||||||
|
|
||||||
|
foreach (var polygon in _polygons)
|
||||||
|
{
|
||||||
|
var verts = polygon.Vertices;
|
||||||
|
|
||||||
|
if (verts.Count < 3)
|
||||||
|
{
|
||||||
|
for (var i = 1; i < verts.Count; i++)
|
||||||
|
{
|
||||||
|
var edge = (verts[i - 1], verts[i]);
|
||||||
|
left.Add(edge);
|
||||||
|
right.Add(edge);
|
||||||
|
up.Add(edge);
|
||||||
|
down.Add(edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sign = polygon.RotationDirection() == RotationType.CCW ? 1.0 : -1.0;
|
||||||
|
|
||||||
|
for (var i = 1; i < verts.Count; i++)
|
||||||
|
{
|
||||||
|
var dx = verts[i].X - verts[i - 1].X;
|
||||||
|
var dy = verts[i].Y - verts[i - 1].Y;
|
||||||
|
var edge = (verts[i - 1], verts[i]);
|
||||||
|
|
||||||
|
if (-sign * dy > 0) left.Add(edge);
|
||||||
|
if ( sign * dy > 0) right.Add(edge);
|
||||||
|
if (-sign * dx > 0) up.Add(edge);
|
||||||
|
if ( sign * dx > 0) down.Add(edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leftEdges = left.ToArray();
|
||||||
|
rightEdges = right.ToArray();
|
||||||
|
upEdges = up.ToArray();
|
||||||
|
downEdges = down.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -41,10 +99,11 @@ namespace OpenNest
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Line> GetLines(Vector location, PushDirection facingDirection)
|
public List<Line> GetLines(Vector location, PushDirection facingDirection)
|
||||||
{
|
{
|
||||||
var lines = new List<Line>();
|
var edges = GetDirectionalEdges(facingDirection);
|
||||||
|
var lines = new List<Line>(edges.Length);
|
||||||
|
|
||||||
foreach (var polygon in _polygons)
|
foreach (var (start, end) in edges)
|
||||||
lines.AddRange(TranslateDirectionalLines(polygon, location, facingDirection));
|
lines.Add(new Line(start.Offset(location), end.Offset(location)));
|
||||||
|
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
@@ -76,60 +135,16 @@ namespace OpenNest
|
|||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Line> TranslateDirectionalLines(
|
private (Vector start, Vector end)[] GetDirectionalEdges(PushDirection direction)
|
||||||
Polygon polygon, Vector location, PushDirection facingDirection)
|
|
||||||
{
|
{
|
||||||
var verts = polygon.Vertices;
|
switch (direction)
|
||||||
|
|
||||||
if (verts.Count < 3)
|
|
||||||
{
|
{
|
||||||
var fallback = new List<Line>();
|
case PushDirection.Left: return _leftEdges;
|
||||||
|
case PushDirection.Right: return _rightEdges;
|
||||||
if (verts.Count >= 2)
|
case PushDirection.Up: return _upEdges;
|
||||||
{
|
case PushDirection.Down: return _downEdges;
|
||||||
var last = verts[0].Offset(location);
|
default: return _leftEdges;
|
||||||
|
|
||||||
for (var i = 1; i < verts.Count; i++)
|
|
||||||
{
|
|
||||||
var current = verts[i].Offset(location);
|
|
||||||
fallback.Add(new Line(last, current));
|
|
||||||
last = current;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
var sign = polygon.RotationDirection() == RotationType.CCW ? 1.0 : -1.0;
|
|
||||||
var result = new List<Line>();
|
|
||||||
var prev = verts[0].Offset(location);
|
|
||||||
|
|
||||||
for (var i = 1; i < verts.Count; i++)
|
|
||||||
{
|
|
||||||
var current = verts[i].Offset(location);
|
|
||||||
|
|
||||||
// Use un-translated deltas — translation doesn't affect direction.
|
|
||||||
var dx = verts[i].X - verts[i - 1].X;
|
|
||||||
var dy = verts[i].Y - verts[i - 1].Y;
|
|
||||||
|
|
||||||
bool keep;
|
|
||||||
|
|
||||||
switch (facingDirection)
|
|
||||||
{
|
|
||||||
case PushDirection.Left: keep = -sign * dy > 0; break;
|
|
||||||
case PushDirection.Right: keep = sign * dy > 0; break;
|
|
||||||
case PushDirection.Up: keep = -sign * dx > 0; break;
|
|
||||||
case PushDirection.Down: keep = sign * dx > 0; break;
|
|
||||||
default: keep = true; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keep)
|
|
||||||
result.Add(new Line(prev, current));
|
|
||||||
|
|
||||||
prev = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user