diff --git a/OpenNest/Controls/PlateView.cs b/OpenNest/Controls/PlateView.cs index 368e2aa..5ef9bba 100644 --- a/OpenNest/Controls/PlateView.cs +++ b/OpenNest/Controls/PlateView.cs @@ -12,7 +12,6 @@ using System.Windows.Forms; using OpenNest.Actions; using OpenNest.CNC; using OpenNest.Collections; -using OpenNest.Converters; using OpenNest.Forms; using OpenNest.Geometry; using OpenNest.Math; @@ -512,37 +511,17 @@ namespace OpenNest.Controls { 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 entities = ConvertProgram.ToGeometry(part.Program); - var shapes = Helper.GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid)); + var layoutPart = parts[i]; - foreach (var shape in shapes) - { - var offsetEntity = shape.OffsetEntity(Plate.PartSpacing, OffsetSide.Left) as Shape; + if (layoutPart.IsDirty) + layoutPart.Update(this); - if (offsetEntity == null) - continue; + layoutPart.UpdateOffset(Plate.PartSpacing, OffsetTolerance, Matrix); - var polygon = offsetEntity.ToPolygonWithTolerance(OffsetTolerance); - polygon.RemoveSelfIntersections(); - 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(); - } + if (layoutPart.OffsetPath != null) + g.DrawPath(offsetPen, layoutPart.OffsetPath); } } } @@ -1090,6 +1069,7 @@ namespace OpenNest.Controls { base.UpdateMatrix(); parts.ForEach(p => p.Update(this)); + temporaryParts.ForEach(p => p.Update(this)); } } } diff --git a/OpenNest/LayoutPart.cs b/OpenNest/LayoutPart.cs index ea9b7d8..94685d6 100644 --- a/OpenNest/LayoutPart.cs +++ b/OpenNest/LayoutPart.cs @@ -1,7 +1,10 @@ -using System.Drawing; +using System.Collections.Generic; +using System.Drawing; using System.Drawing.Drawing2D; +using System.Linq; using System.Windows.Forms; using OpenNest.Controls; +using OpenNest.Converters; using OpenNest.Geometry; namespace OpenNest @@ -17,6 +20,11 @@ namespace OpenNest private Brush brush; private Pen pen; + private List _offsetPolygonPoints; + private double _cachedOffsetSpacing; + private double _cachedOffsetTolerance; + private double _cachedOffsetRotation = double.NaN; + public readonly Part BasePart; static LayoutPart() @@ -92,6 +100,8 @@ namespace OpenNest g.DrawString(id, programIdFont, Brushes.Black, pt.X, pt.Y); } + public GraphicsPath OffsetPath { get; private set; } + public void Update(DrawControl plateView) { Path = GraphicsHelper.GetGraphicsPath(BasePart.Program, BasePart.Location); @@ -99,6 +109,86 @@ namespace OpenNest 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 ComputeOffsetPolygons(double spacing, double tolerance) + { + var result = new List(); + 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) { var layoutPart = new LayoutPart(part);