refactor: extract ShapeBuilder from Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ namespace OpenNest.Converters
|
||||
{
|
||||
public static Program ToProgram(IList<Entity> geometry)
|
||||
{
|
||||
var shapes = Helper.GetShapes(geometry);
|
||||
var shapes = ShapeBuilder.GetShapes(geometry);
|
||||
|
||||
if (shapes.Count == 0)
|
||||
return null;
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace OpenNest
|
||||
public void UpdateArea()
|
||||
{
|
||||
var geometry = ConvertProgram.ToGeometry(Program).Where(entity => entity.Layer != SpecialLayers.Rapid);
|
||||
var shapes = Helper.GetShapes(geometry);
|
||||
var shapes = ShapeBuilder.GetShapes(geometry);
|
||||
|
||||
if (shapes.Count == 0)
|
||||
return;
|
||||
|
||||
150
OpenNest.Core/Geometry/ShapeBuilder.cs
Normal file
150
OpenNest.Core/Geometry/ShapeBuilder.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using OpenNest.Math;
|
||||
|
||||
namespace OpenNest.Geometry
|
||||
{
|
||||
public static class ShapeBuilder
|
||||
{
|
||||
public static List<Shape> GetShapes(IEnumerable<Entity> entities)
|
||||
{
|
||||
var lines = new List<Line>();
|
||||
var arcs = new List<Arc>();
|
||||
var circles = new List<Circle>();
|
||||
var shapes = new List<Shape>();
|
||||
|
||||
var entities2 = new Queue<Entity>(entities);
|
||||
|
||||
while (entities2.Count > 0)
|
||||
{
|
||||
var entity = entities2.Dequeue();
|
||||
|
||||
switch (entity.Type)
|
||||
{
|
||||
case EntityType.Arc:
|
||||
arcs.Add((Arc)entity);
|
||||
break;
|
||||
|
||||
case EntityType.Circle:
|
||||
circles.Add((Circle)entity);
|
||||
break;
|
||||
|
||||
case EntityType.Line:
|
||||
lines.Add((Line)entity);
|
||||
break;
|
||||
|
||||
case EntityType.Shape:
|
||||
var shape = (Shape)entity;
|
||||
shape.Entities.ForEach(e => entities2.Enqueue(e));
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Fail("Unhandled geometry type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var circle in circles)
|
||||
{
|
||||
var shape = new Shape();
|
||||
shape.Entities.Add(circle);
|
||||
shape.UpdateBounds();
|
||||
shapes.Add(shape);
|
||||
}
|
||||
|
||||
var entityList = new List<Entity>();
|
||||
|
||||
entityList.AddRange(lines);
|
||||
entityList.AddRange(arcs);
|
||||
|
||||
while (entityList.Count > 0)
|
||||
{
|
||||
var next = entityList[0];
|
||||
var shape = new Shape();
|
||||
shape.Entities.Add(next);
|
||||
|
||||
entityList.RemoveAt(0);
|
||||
|
||||
Vector startPoint = new Vector();
|
||||
Entity connected;
|
||||
|
||||
switch (next.Type)
|
||||
{
|
||||
case EntityType.Arc:
|
||||
var arc = (Arc)next;
|
||||
startPoint = arc.EndPoint();
|
||||
break;
|
||||
|
||||
case EntityType.Line:
|
||||
var line = (Line)next;
|
||||
startPoint = line.EndPoint;
|
||||
break;
|
||||
}
|
||||
|
||||
while ((connected = GetConnected(startPoint, entityList)) != null)
|
||||
{
|
||||
shape.Entities.Add(connected);
|
||||
entityList.Remove(connected);
|
||||
|
||||
switch (connected.Type)
|
||||
{
|
||||
case EntityType.Arc:
|
||||
var arc = (Arc)connected;
|
||||
startPoint = arc.EndPoint();
|
||||
break;
|
||||
|
||||
case EntityType.Line:
|
||||
var line = (Line)connected;
|
||||
startPoint = line.EndPoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shape.UpdateBounds();
|
||||
shapes.Add(shape);
|
||||
}
|
||||
|
||||
return shapes;
|
||||
}
|
||||
|
||||
internal static Entity GetConnected(Vector pt, IEnumerable<Entity> geometry)
|
||||
{
|
||||
var tol = Tolerance.ChainTolerance;
|
||||
|
||||
foreach (var geo in geometry)
|
||||
{
|
||||
switch (geo.Type)
|
||||
{
|
||||
case EntityType.Arc:
|
||||
var arc = (Arc)geo;
|
||||
|
||||
if (arc.StartPoint().DistanceTo(pt) <= tol)
|
||||
return arc;
|
||||
|
||||
if (arc.EndPoint().DistanceTo(pt) <= tol)
|
||||
{
|
||||
arc.Reverse();
|
||||
return arc;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EntityType.Line:
|
||||
var line = (Line)geo;
|
||||
|
||||
if (line.StartPoint.DistanceTo(pt) <= tol)
|
||||
return line;
|
||||
|
||||
if (line.EndPoint.DistanceTo(pt) <= tol)
|
||||
{
|
||||
line.Reverse();
|
||||
return line;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace OpenNest.Geometry
|
||||
|
||||
private void Update(List<Entity> entities)
|
||||
{
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
|
||||
Perimeter = shapes[0];
|
||||
Cutouts = new List<Shape>();
|
||||
|
||||
@@ -11,147 +11,6 @@ namespace OpenNest
|
||||
{
|
||||
public static class Helper
|
||||
{
|
||||
public static List<Shape> GetShapes(IEnumerable<Entity> entities)
|
||||
{
|
||||
var lines = new List<Line>();
|
||||
var arcs = new List<Arc>();
|
||||
var circles = new List<Circle>();
|
||||
var shapes = new List<Shape>();
|
||||
|
||||
var entities2 = new Queue<Entity>(entities);
|
||||
|
||||
while (entities2.Count > 0)
|
||||
{
|
||||
var entity = entities2.Dequeue();
|
||||
|
||||
switch (entity.Type)
|
||||
{
|
||||
case EntityType.Arc:
|
||||
arcs.Add((Arc)entity);
|
||||
break;
|
||||
|
||||
case EntityType.Circle:
|
||||
circles.Add((Circle)entity);
|
||||
break;
|
||||
|
||||
case EntityType.Line:
|
||||
lines.Add((Line)entity);
|
||||
break;
|
||||
|
||||
case EntityType.Shape:
|
||||
var shape = (Shape)entity;
|
||||
shape.Entities.ForEach(e => entities2.Enqueue(e));
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Fail("Unhandled geometry type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var circle in circles)
|
||||
{
|
||||
var shape = new Shape();
|
||||
shape.Entities.Add(circle);
|
||||
shape.UpdateBounds();
|
||||
shapes.Add(shape);
|
||||
}
|
||||
|
||||
var entityList = new List<Entity>();
|
||||
|
||||
entityList.AddRange(lines);
|
||||
entityList.AddRange(arcs);
|
||||
|
||||
while (entityList.Count > 0)
|
||||
{
|
||||
var next = entityList[0];
|
||||
var shape = new Shape();
|
||||
shape.Entities.Add(next);
|
||||
|
||||
entityList.RemoveAt(0);
|
||||
|
||||
Vector startPoint = new Vector();
|
||||
Entity connected;
|
||||
|
||||
switch (next.Type)
|
||||
{
|
||||
case EntityType.Arc:
|
||||
var arc = (Arc)next;
|
||||
startPoint = arc.EndPoint();
|
||||
break;
|
||||
|
||||
case EntityType.Line:
|
||||
var line = (Line)next;
|
||||
startPoint = line.EndPoint;
|
||||
break;
|
||||
}
|
||||
|
||||
while ((connected = GetConnected(startPoint, entityList)) != null)
|
||||
{
|
||||
shape.Entities.Add(connected);
|
||||
entityList.Remove(connected);
|
||||
|
||||
switch (connected.Type)
|
||||
{
|
||||
case EntityType.Arc:
|
||||
var arc = (Arc)connected;
|
||||
startPoint = arc.EndPoint();
|
||||
break;
|
||||
|
||||
case EntityType.Line:
|
||||
var line = (Line)connected;
|
||||
startPoint = line.EndPoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shape.UpdateBounds();
|
||||
shapes.Add(shape);
|
||||
}
|
||||
|
||||
return shapes;
|
||||
}
|
||||
|
||||
internal static Entity GetConnected(Vector pt, IEnumerable<Entity> geometry)
|
||||
{
|
||||
var tol = Math.Tolerance.ChainTolerance;
|
||||
|
||||
foreach (var geo in geometry)
|
||||
{
|
||||
switch (geo.Type)
|
||||
{
|
||||
case EntityType.Arc:
|
||||
var arc = (Arc)geo;
|
||||
|
||||
if (arc.StartPoint().DistanceTo(pt) <= tol)
|
||||
return arc;
|
||||
|
||||
if (arc.EndPoint().DistanceTo(pt) <= tol)
|
||||
{
|
||||
arc.Reverse();
|
||||
return arc;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EntityType.Line:
|
||||
var line = (Line)geo;
|
||||
|
||||
if (line.StartPoint.DistanceTo(pt) <= tol)
|
||||
return line;
|
||||
|
||||
if (line.EndPoint.DistanceTo(pt) <= tol)
|
||||
{
|
||||
line.Reverse();
|
||||
return line;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static bool Intersects(Arc arc1, Arc arc2, out List<Vector> pts)
|
||||
{
|
||||
var c1 = new Circle(arc1.Center, arc1.Radius);
|
||||
@@ -519,7 +378,7 @@ namespace OpenNest
|
||||
public static List<Line> GetPartLines(Part part, double chordTolerance = 0.001)
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program);
|
||||
var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
var shapes = ShapeBuilder.GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
var lines = new List<Line>();
|
||||
|
||||
foreach (var shape in shapes)
|
||||
@@ -535,7 +394,7 @@ namespace OpenNest
|
||||
public static List<Line> GetPartLines(Part part, PushDirection facingDirection, double chordTolerance = 0.001)
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program);
|
||||
var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
var shapes = ShapeBuilder.GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
var lines = new List<Line>();
|
||||
|
||||
foreach (var shape in shapes)
|
||||
@@ -551,7 +410,7 @@ namespace OpenNest
|
||||
public static List<Line> GetOffsetPartLines(Part part, double spacing, double chordTolerance = 0.001)
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program);
|
||||
var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
var shapes = ShapeBuilder.GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
var lines = new List<Line>();
|
||||
|
||||
foreach (var shape in shapes)
|
||||
@@ -575,7 +434,7 @@ namespace OpenNest
|
||||
public static List<Line> GetOffsetPartLines(Part part, double spacing, PushDirection facingDirection, double chordTolerance = 0.001)
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program);
|
||||
var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
var shapes = ShapeBuilder.GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
var lines = new List<Line>();
|
||||
|
||||
foreach (var shape in shapes)
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace OpenNest
|
||||
public static TimingInfo GetTimingInfo(Program pgm)
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(pgm);
|
||||
var shapes = Helper.GetShapes(entities.Where(entity => entity.Layer != SpecialLayers.Rapid));
|
||||
var shapes = ShapeBuilder.GetShapes(entities.Where(entity => entity.Layer != SpecialLayers.Rapid));
|
||||
var info = new TimingInfo { PierceCount = shapes.Count };
|
||||
|
||||
var last = entities[0];
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace OpenNest.Engine.BestFit
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(drawing.Program)
|
||||
.Where(e => e.Layer != SpecialLayers.Rapid);
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
|
||||
var points = new List<Vector>();
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace OpenNest.Engine.BestFit
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program)
|
||||
.Where(e => e.Layer != SpecialLayers.Rapid);
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
shapes.ForEach(s => s.Offset(part.Location));
|
||||
return shapes;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ namespace OpenNest.Engine.BestFit
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program)
|
||||
.Where(e => e.Layer != SpecialLayers.Rapid);
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
var points = new List<Vector>();
|
||||
|
||||
foreach (var shape in shapes)
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace OpenNest
|
||||
var entities = ConvertProgram.ToGeometry(item.Drawing.Program)
|
||||
.Where(e => e.Layer != SpecialLayers.Rapid);
|
||||
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
|
||||
if (shapes.Count == 0)
|
||||
return 0;
|
||||
@@ -65,7 +65,7 @@ namespace OpenNest
|
||||
var entities = ConvertProgram.ToGeometry(part.Program)
|
||||
.Where(e => e.Layer != SpecialLayers.Rapid);
|
||||
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
|
||||
foreach (var shape in shapes)
|
||||
{
|
||||
|
||||
@@ -258,7 +258,7 @@ namespace OpenNest.Gpu
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program)
|
||||
.Where(e => e.Layer != SpecialLayers.Rapid);
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
var points = new List<Vector>();
|
||||
|
||||
foreach (var shape in shapes)
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace OpenNest.Gpu
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program)
|
||||
.Where(e => e.Layer != SpecialLayers.Rapid);
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
|
||||
var polygons = new List<Polygon>();
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace OpenNest.Gpu
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(drawing.Program)
|
||||
.Where(e => e.Layer != SpecialLayers.Rapid);
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
|
||||
var polygons = new List<Polygon>();
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace OpenNest.Actions
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program).Where(e => e.Layer == SpecialLayers.Cut).ToList();
|
||||
entities.ForEach(entity => entity.Offset(part.Location));
|
||||
var shapes = Helper.GetShapes(entities);
|
||||
var shapes = ShapeBuilder.GetShapes(entities);
|
||||
var shape = new Shape();
|
||||
shape.Entities.AddRange(shapes);
|
||||
ShapePartPairs.Add(new Pair() { Part = part, Shape = shape });
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace OpenNest
|
||||
{
|
||||
var result = new List<PointF[]>();
|
||||
var entities = ConvertProgram.ToGeometry(BasePart.Program);
|
||||
var shapes = Helper.GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
var shapes = ShapeBuilder.GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
|
||||
|
||||
foreach (var shape in shapes)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user