fix(ui): cache offset paths and scale temp parts on zoom
Cache offset polygon geometry on LayoutPart so DrawOffset no longer recomputes the expensive offset pipeline every paint cycle. The costly OffsetEntity/ToPolygonWithTolerance/RemoveSelfIntersections chain now runs only when rotation, spacing, or tolerance actually changes. Also update temporary parts in UpdateMatrix() so preview parts during nesting scale correctly with zoom. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,6 @@ using System.Windows.Forms;
|
|||||||
using OpenNest.Actions;
|
using OpenNest.Actions;
|
||||||
using OpenNest.CNC;
|
using OpenNest.CNC;
|
||||||
using OpenNest.Collections;
|
using OpenNest.Collections;
|
||||||
using OpenNest.Converters;
|
|
||||||
using OpenNest.Forms;
|
using OpenNest.Forms;
|
||||||
using OpenNest.Geometry;
|
using OpenNest.Geometry;
|
||||||
using OpenNest.Math;
|
using OpenNest.Math;
|
||||||
@@ -512,37 +511,17 @@ namespace OpenNest.Controls
|
|||||||
{
|
{
|
||||||
using (var offsetPen = new Pen(Color.FromArgb(120, 255, 100, 100)))
|
using (var offsetPen = new Pen(Color.FromArgb(120, 255, 100, 100)))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < parts.Count; i++)
|
for (var i = 0; i < parts.Count; i++)
|
||||||
{
|
{
|
||||||
var part = parts[i].BasePart;
|
var layoutPart = parts[i];
|
||||||
var entities = ConvertProgram.ToGeometry(part.Program);
|
|
||||||
var shapes = Helper.GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
|
||||||
|
|
||||||
foreach (var shape in shapes)
|
if (layoutPart.IsDirty)
|
||||||
{
|
layoutPart.Update(this);
|
||||||
var offsetEntity = shape.OffsetEntity(Plate.PartSpacing, OffsetSide.Left) as Shape;
|
|
||||||
|
|
||||||
if (offsetEntity == null)
|
layoutPart.UpdateOffset(Plate.PartSpacing, OffsetTolerance, Matrix);
|
||||||
continue;
|
|
||||||
|
|
||||||
var polygon = offsetEntity.ToPolygonWithTolerance(OffsetTolerance);
|
if (layoutPart.OffsetPath != null)
|
||||||
polygon.RemoveSelfIntersections();
|
g.DrawPath(offsetPen, layoutPart.OffsetPath);
|
||||||
polygon.Offset(part.Location);
|
|
||||||
|
|
||||||
if (polygon.Vertices.Count < 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var pts = new PointF[polygon.Vertices.Count];
|
|
||||||
|
|
||||||
for (int j = 0; j < pts.Length; j++)
|
|
||||||
pts[j] = new PointF((float)polygon.Vertices[j].X, (float)polygon.Vertices[j].Y);
|
|
||||||
|
|
||||||
var path = new GraphicsPath();
|
|
||||||
path.AddLines(pts);
|
|
||||||
path.Transform(Matrix);
|
|
||||||
g.DrawPath(offsetPen, path);
|
|
||||||
path.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1090,6 +1069,7 @@ namespace OpenNest.Controls
|
|||||||
{
|
{
|
||||||
base.UpdateMatrix();
|
base.UpdateMatrix();
|
||||||
parts.ForEach(p => p.Update(this));
|
parts.ForEach(p => p.Update(this));
|
||||||
|
temporaryParts.ForEach(p => p.Update(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
using System.Drawing;
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using OpenNest.Controls;
|
using OpenNest.Controls;
|
||||||
|
using OpenNest.Converters;
|
||||||
using OpenNest.Geometry;
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
namespace OpenNest
|
namespace OpenNest
|
||||||
@@ -17,6 +20,11 @@ namespace OpenNest
|
|||||||
private Brush brush;
|
private Brush brush;
|
||||||
private Pen pen;
|
private Pen pen;
|
||||||
|
|
||||||
|
private List<PointF[]> _offsetPolygonPoints;
|
||||||
|
private double _cachedOffsetSpacing;
|
||||||
|
private double _cachedOffsetTolerance;
|
||||||
|
private double _cachedOffsetRotation = double.NaN;
|
||||||
|
|
||||||
public readonly Part BasePart;
|
public readonly Part BasePart;
|
||||||
|
|
||||||
static LayoutPart()
|
static LayoutPart()
|
||||||
@@ -92,6 +100,8 @@ namespace OpenNest
|
|||||||
g.DrawString(id, programIdFont, Brushes.Black, pt.X, pt.Y);
|
g.DrawString(id, programIdFont, Brushes.Black, pt.X, pt.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GraphicsPath OffsetPath { get; private set; }
|
||||||
|
|
||||||
public void Update(DrawControl plateView)
|
public void Update(DrawControl plateView)
|
||||||
{
|
{
|
||||||
Path = GraphicsHelper.GetGraphicsPath(BasePart.Program, BasePart.Location);
|
Path = GraphicsHelper.GetGraphicsPath(BasePart.Program, BasePart.Location);
|
||||||
@@ -99,6 +109,86 @@ namespace OpenNest
|
|||||||
IsDirty = false;
|
IsDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateOffset(double spacing, double tolerance, Matrix matrix)
|
||||||
|
{
|
||||||
|
if (_offsetPolygonPoints == null ||
|
||||||
|
spacing != _cachedOffsetSpacing ||
|
||||||
|
tolerance != _cachedOffsetTolerance ||
|
||||||
|
BasePart.Rotation != _cachedOffsetRotation)
|
||||||
|
{
|
||||||
|
_offsetPolygonPoints = ComputeOffsetPolygons(spacing, tolerance);
|
||||||
|
_cachedOffsetSpacing = spacing;
|
||||||
|
_cachedOffsetTolerance = tolerance;
|
||||||
|
_cachedOffsetRotation = BasePart.Rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
RebuildOffsetPath(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InvalidateOffset()
|
||||||
|
{
|
||||||
|
_offsetPolygonPoints = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PointF[]> ComputeOffsetPolygons(double spacing, double tolerance)
|
||||||
|
{
|
||||||
|
var result = new List<PointF[]>();
|
||||||
|
var entities = ConvertProgram.ToGeometry(BasePart.Program);
|
||||||
|
var shapes = Helper.GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||||
|
|
||||||
|
foreach (var shape in shapes)
|
||||||
|
{
|
||||||
|
var offsetEntity = shape.OffsetEntity(spacing, OffsetSide.Left) as Shape;
|
||||||
|
|
||||||
|
if (offsetEntity == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var polygon = offsetEntity.ToPolygonWithTolerance(tolerance);
|
||||||
|
polygon.RemoveSelfIntersections();
|
||||||
|
|
||||||
|
if (polygon.Vertices.Count < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var pts = new PointF[polygon.Vertices.Count];
|
||||||
|
|
||||||
|
for (var j = 0; j < pts.Length; j++)
|
||||||
|
pts[j] = new PointF((float)polygon.Vertices[j].X, (float)polygon.Vertices[j].Y);
|
||||||
|
|
||||||
|
result.Add(pts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RebuildOffsetPath(Matrix matrix)
|
||||||
|
{
|
||||||
|
OffsetPath?.Dispose();
|
||||||
|
|
||||||
|
if (_offsetPolygonPoints == null || _offsetPolygonPoints.Count == 0)
|
||||||
|
{
|
||||||
|
OffsetPath = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = new GraphicsPath();
|
||||||
|
var dx = (float)BasePart.Location.X;
|
||||||
|
var dy = (float)BasePart.Location.Y;
|
||||||
|
|
||||||
|
foreach (var pts in _offsetPolygonPoints)
|
||||||
|
{
|
||||||
|
var offsetPts = new PointF[pts.Length];
|
||||||
|
|
||||||
|
for (var i = 0; i < pts.Length; i++)
|
||||||
|
offsetPts[i] = new PointF(pts[i].X + dx, pts[i].Y + dy);
|
||||||
|
|
||||||
|
path.AddLines(offsetPts);
|
||||||
|
path.StartFigure();
|
||||||
|
}
|
||||||
|
|
||||||
|
path.Transform(matrix);
|
||||||
|
OffsetPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
public static LayoutPart Create(Part part, PlateView plateView)
|
public static LayoutPart Create(Part part, PlateView plateView)
|
||||||
{
|
{
|
||||||
var layoutPart = new LayoutPart(part);
|
var layoutPart = new LayoutPart(part);
|
||||||
|
|||||||
Reference in New Issue
Block a user