Merge branch 'feature/cutting-strategy' into master
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class AssignmentParameters
|
||||||
|
{
|
||||||
|
public SequenceMethod Method { get; set; } = SequenceMethod.Advanced;
|
||||||
|
public string Preference { get; set; } = "ILAT";
|
||||||
|
public double MinGeometryLength { get; set; } = 0.01;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class ContourCuttingStrategy
|
||||||
|
{
|
||||||
|
public CuttingParameters Parameters { get; set; }
|
||||||
|
|
||||||
|
public Program Apply(Program partProgram, Plate plate)
|
||||||
|
{
|
||||||
|
var exitPoint = GetExitPoint(plate);
|
||||||
|
var entities = partProgram.ToGeometry();
|
||||||
|
var profile = new ShapeProfile(entities);
|
||||||
|
|
||||||
|
// Find closest point on perimeter from exit point
|
||||||
|
var perimeterPoint = profile.Perimeter.ClosestPointTo(exitPoint, out var perimeterEntity);
|
||||||
|
|
||||||
|
// Chain cutouts by nearest-neighbor from perimeter point, then reverse
|
||||||
|
// so farthest cutouts are cut first, nearest-to-perimeter cut last
|
||||||
|
var orderedCutouts = SequenceCutouts(profile.Cutouts, perimeterPoint);
|
||||||
|
orderedCutouts.Reverse();
|
||||||
|
|
||||||
|
// Build output program: cutouts first (farthest to nearest), perimeter last
|
||||||
|
var result = new Program();
|
||||||
|
var currentPoint = exitPoint;
|
||||||
|
|
||||||
|
foreach (var cutout in orderedCutouts)
|
||||||
|
{
|
||||||
|
var contourType = DetectContourType(cutout);
|
||||||
|
var closestPt = cutout.ClosestPointTo(currentPoint, out var entity);
|
||||||
|
var normal = ComputeNormal(closestPt, entity, contourType);
|
||||||
|
var winding = DetermineWinding(cutout);
|
||||||
|
|
||||||
|
var leadIn = SelectLeadIn(contourType);
|
||||||
|
var leadOut = SelectLeadOut(contourType);
|
||||||
|
|
||||||
|
result.Codes.AddRange(leadIn.Generate(closestPt, normal, winding));
|
||||||
|
// Contour re-indexing: split shape entities at closestPt so cutting
|
||||||
|
// starts there, convert to ICode, and add to result.Codes
|
||||||
|
throw new System.NotImplementedException("Contour re-indexing not yet implemented");
|
||||||
|
result.Codes.AddRange(leadOut.Generate(closestPt, normal, winding));
|
||||||
|
|
||||||
|
currentPoint = closestPt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perimeter last
|
||||||
|
{
|
||||||
|
var perimeterPt = profile.Perimeter.ClosestPointTo(currentPoint, out perimeterEntity);
|
||||||
|
var normal = ComputeNormal(perimeterPt, perimeterEntity, ContourType.External);
|
||||||
|
var winding = DetermineWinding(profile.Perimeter);
|
||||||
|
|
||||||
|
var leadIn = SelectLeadIn(ContourType.External);
|
||||||
|
var leadOut = SelectLeadOut(ContourType.External);
|
||||||
|
|
||||||
|
result.Codes.AddRange(leadIn.Generate(perimeterPt, normal, winding));
|
||||||
|
throw new System.NotImplementedException("Contour re-indexing not yet implemented");
|
||||||
|
result.Codes.AddRange(leadOut.Generate(perimeterPt, normal, winding));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector GetExitPoint(Plate plate)
|
||||||
|
{
|
||||||
|
var w = plate.Size.Width;
|
||||||
|
var l = plate.Size.Length;
|
||||||
|
|
||||||
|
return plate.Quadrant switch
|
||||||
|
{
|
||||||
|
1 => new Vector(0, 0), // Q1 TopRight origin -> exit BottomLeft
|
||||||
|
2 => new Vector(w, 0), // Q2 TopLeft origin -> exit BottomRight
|
||||||
|
3 => new Vector(w, l), // Q3 BottomLeft origin -> exit TopRight
|
||||||
|
4 => new Vector(0, l), // Q4 BottomRight origin -> exit TopLeft
|
||||||
|
_ => new Vector(0, 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Shape> SequenceCutouts(List<Shape> cutouts, Vector startPoint)
|
||||||
|
{
|
||||||
|
var remaining = new List<Shape>(cutouts);
|
||||||
|
var ordered = new List<Shape>();
|
||||||
|
var currentPoint = startPoint;
|
||||||
|
|
||||||
|
while (remaining.Count > 0)
|
||||||
|
{
|
||||||
|
var nearest = remaining[0];
|
||||||
|
var nearestPt = nearest.ClosestPointTo(currentPoint);
|
||||||
|
var nearestDist = nearestPt.DistanceTo(currentPoint);
|
||||||
|
|
||||||
|
for (var i = 1; i < remaining.Count; i++)
|
||||||
|
{
|
||||||
|
var pt = remaining[i].ClosestPointTo(currentPoint);
|
||||||
|
var dist = pt.DistanceTo(currentPoint);
|
||||||
|
if (dist < nearestDist)
|
||||||
|
{
|
||||||
|
nearest = remaining[i];
|
||||||
|
nearestPt = pt;
|
||||||
|
nearestDist = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ordered.Add(nearest);
|
||||||
|
remaining.Remove(nearest);
|
||||||
|
currentPoint = nearestPt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ContourType DetectContourType(Shape cutout)
|
||||||
|
{
|
||||||
|
if (cutout.Entities.Count == 1 && cutout.Entities[0] is Circle)
|
||||||
|
return ContourType.ArcCircle;
|
||||||
|
|
||||||
|
return ContourType.Internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double ComputeNormal(Vector point, Entity entity, ContourType contourType)
|
||||||
|
{
|
||||||
|
double normal;
|
||||||
|
|
||||||
|
if (entity is Line line)
|
||||||
|
{
|
||||||
|
// Perpendicular to line direction
|
||||||
|
var tangent = line.EndPoint.AngleFrom(line.StartPoint);
|
||||||
|
normal = tangent + Math.Angle.HalfPI;
|
||||||
|
}
|
||||||
|
else if (entity is Arc arc)
|
||||||
|
{
|
||||||
|
// Radial direction from center to point
|
||||||
|
normal = point.AngleFrom(arc.Center);
|
||||||
|
}
|
||||||
|
else if (entity is Circle circle)
|
||||||
|
{
|
||||||
|
normal = point.AngleFrom(circle.Center);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
normal = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For internal contours, flip the normal (point into scrap)
|
||||||
|
if (contourType == ContourType.Internal || contourType == ContourType.ArcCircle)
|
||||||
|
normal += System.Math.PI;
|
||||||
|
|
||||||
|
return Math.Angle.NormalizeRad(normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RotationType DetermineWinding(Shape shape)
|
||||||
|
{
|
||||||
|
// Use signed area: positive = CCW, negative = CW
|
||||||
|
var area = shape.Area();
|
||||||
|
return area >= 0 ? RotationType.CCW : RotationType.CW;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LeadIn SelectLeadIn(ContourType contourType)
|
||||||
|
{
|
||||||
|
return contourType switch
|
||||||
|
{
|
||||||
|
ContourType.ArcCircle => Parameters.ArcCircleLeadIn ?? Parameters.InternalLeadIn,
|
||||||
|
ContourType.Internal => Parameters.InternalLeadIn,
|
||||||
|
_ => Parameters.ExternalLeadIn
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private LeadOut SelectLeadOut(ContourType contourType)
|
||||||
|
{
|
||||||
|
return contourType switch
|
||||||
|
{
|
||||||
|
ContourType.ArcCircle => Parameters.ArcCircleLeadOut ?? Parameters.InternalLeadOut,
|
||||||
|
ContourType.Internal => Parameters.InternalLeadOut,
|
||||||
|
_ => Parameters.ExternalLeadOut
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public enum ContourType
|
||||||
|
{
|
||||||
|
External,
|
||||||
|
Internal,
|
||||||
|
ArcCircle
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class CuttingParameters
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string MachineName { get; set; }
|
||||||
|
public string MaterialName { get; set; }
|
||||||
|
public string Grade { get; set; }
|
||||||
|
public double Thickness { get; set; }
|
||||||
|
|
||||||
|
public double Kerf { get; set; }
|
||||||
|
public double PartSpacing { get; set; }
|
||||||
|
|
||||||
|
public LeadIn ExternalLeadIn { get; set; } = new NoLeadIn();
|
||||||
|
public LeadOut ExternalLeadOut { get; set; } = new NoLeadOut();
|
||||||
|
|
||||||
|
public LeadIn InternalLeadIn { get; set; } = new LineLeadIn { Length = 0.125, ApproachAngle = 90 };
|
||||||
|
public LeadOut InternalLeadOut { get; set; } = new NoLeadOut();
|
||||||
|
|
||||||
|
public LeadIn ArcCircleLeadIn { get; set; } = new NoLeadIn();
|
||||||
|
public LeadOut ArcCircleLeadOut { get; set; } = new NoLeadOut();
|
||||||
|
|
||||||
|
public Tab TabConfig { get; set; }
|
||||||
|
public bool TabsEnabled { get; set; }
|
||||||
|
|
||||||
|
public SequenceParameters Sequencing { get; set; } = new SequenceParameters();
|
||||||
|
public AssignmentParameters Assignment { get; set; } = new AssignmentParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class ArcLeadIn : LeadIn
|
||||||
|
{
|
||||||
|
public double Radius { get; set; }
|
||||||
|
|
||||||
|
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||||
|
|
||||||
|
var arcCenter = new Vector(
|
||||||
|
contourStartPoint.X + Radius * System.Math.Cos(contourNormalAngle),
|
||||||
|
contourStartPoint.Y + Radius * System.Math.Sin(contourNormalAngle));
|
||||||
|
|
||||||
|
return new List<ICode>
|
||||||
|
{
|
||||||
|
new RapidMove(piercePoint),
|
||||||
|
new ArcMove(contourStartPoint, arcCenter, winding)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||||
|
{
|
||||||
|
var arcCenterX = contourStartPoint.X + Radius * System.Math.Cos(contourNormalAngle);
|
||||||
|
var arcCenterY = contourStartPoint.Y + Radius * System.Math.Sin(contourNormalAngle);
|
||||||
|
|
||||||
|
return new Vector(
|
||||||
|
arcCenterX + Radius * System.Math.Cos(contourNormalAngle),
|
||||||
|
arcCenterY + Radius * System.Math.Sin(contourNormalAngle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using OpenNest.Math;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class CleanHoleLeadIn : LeadIn
|
||||||
|
{
|
||||||
|
public double LineLength { get; set; }
|
||||||
|
public double ArcRadius { get; set; }
|
||||||
|
public double Kerf { get; set; }
|
||||||
|
|
||||||
|
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||||
|
|
||||||
|
var arcCenterX = contourStartPoint.X + ArcRadius * System.Math.Cos(contourNormalAngle);
|
||||||
|
var arcCenterY = contourStartPoint.Y + ArcRadius * System.Math.Sin(contourNormalAngle);
|
||||||
|
var arcCenter = new Vector(arcCenterX, arcCenterY);
|
||||||
|
|
||||||
|
var lineAngle = contourNormalAngle + Angle.ToRadians(135.0);
|
||||||
|
var arcStart = new Vector(
|
||||||
|
arcCenterX + ArcRadius * System.Math.Cos(lineAngle),
|
||||||
|
arcCenterY + ArcRadius * System.Math.Sin(lineAngle));
|
||||||
|
|
||||||
|
return new List<ICode>
|
||||||
|
{
|
||||||
|
new RapidMove(piercePoint),
|
||||||
|
new LinearMove(arcStart),
|
||||||
|
new ArcMove(contourStartPoint, arcCenter, winding)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||||
|
{
|
||||||
|
var arcCenterX = contourStartPoint.X + ArcRadius * System.Math.Cos(contourNormalAngle);
|
||||||
|
var arcCenterY = contourStartPoint.Y + ArcRadius * System.Math.Sin(contourNormalAngle);
|
||||||
|
|
||||||
|
var lineAngle = contourNormalAngle + Angle.ToRadians(135.0);
|
||||||
|
var arcStartX = arcCenterX + ArcRadius * System.Math.Cos(lineAngle);
|
||||||
|
var arcStartY = arcCenterY + ArcRadius * System.Math.Sin(lineAngle);
|
||||||
|
|
||||||
|
return new Vector(
|
||||||
|
arcStartX + LineLength * System.Math.Cos(lineAngle),
|
||||||
|
arcStartY + LineLength * System.Math.Sin(lineAngle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public abstract class LeadIn
|
||||||
|
{
|
||||||
|
public abstract List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW);
|
||||||
|
|
||||||
|
public abstract Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using OpenNest.Math;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class LineArcLeadIn : LeadIn
|
||||||
|
{
|
||||||
|
public double LineLength { get; set; }
|
||||||
|
public double ApproachAngle { get; set; } = 135.0;
|
||||||
|
public double ArcRadius { get; set; }
|
||||||
|
|
||||||
|
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||||
|
|
||||||
|
var arcCenterX = contourStartPoint.X + ArcRadius * System.Math.Cos(contourNormalAngle);
|
||||||
|
var arcCenterY = contourStartPoint.Y + ArcRadius * System.Math.Sin(contourNormalAngle);
|
||||||
|
var arcCenter = new Vector(arcCenterX, arcCenterY);
|
||||||
|
|
||||||
|
var lineAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
||||||
|
var arcStart = new Vector(
|
||||||
|
arcCenterX + ArcRadius * System.Math.Cos(lineAngle),
|
||||||
|
arcCenterY + ArcRadius * System.Math.Sin(lineAngle));
|
||||||
|
|
||||||
|
return new List<ICode>
|
||||||
|
{
|
||||||
|
new RapidMove(piercePoint),
|
||||||
|
new LinearMove(arcStart),
|
||||||
|
new ArcMove(contourStartPoint, arcCenter, winding)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||||
|
{
|
||||||
|
var arcCenterX = contourStartPoint.X + ArcRadius * System.Math.Cos(contourNormalAngle);
|
||||||
|
var arcCenterY = contourStartPoint.Y + ArcRadius * System.Math.Sin(contourNormalAngle);
|
||||||
|
|
||||||
|
var lineAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
||||||
|
var arcStartX = arcCenterX + ArcRadius * System.Math.Cos(lineAngle);
|
||||||
|
var arcStartY = arcCenterY + ArcRadius * System.Math.Sin(lineAngle);
|
||||||
|
|
||||||
|
return new Vector(
|
||||||
|
arcStartX + LineLength * System.Math.Cos(lineAngle),
|
||||||
|
arcStartY + LineLength * System.Math.Sin(lineAngle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using OpenNest.Math;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class LineLeadIn : LeadIn
|
||||||
|
{
|
||||||
|
public double Length { get; set; }
|
||||||
|
public double ApproachAngle { get; set; } = 90.0;
|
||||||
|
|
||||||
|
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||||
|
|
||||||
|
return new List<ICode>
|
||||||
|
{
|
||||||
|
new RapidMove(piercePoint),
|
||||||
|
new LinearMove(contourStartPoint)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||||
|
{
|
||||||
|
var approachAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
||||||
|
return new Vector(
|
||||||
|
contourStartPoint.X + Length * System.Math.Cos(approachAngle),
|
||||||
|
contourStartPoint.Y + Length * System.Math.Sin(approachAngle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using OpenNest.Math;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class LineLineLeadIn : LeadIn
|
||||||
|
{
|
||||||
|
public double Length1 { get; set; }
|
||||||
|
public double ApproachAngle1 { get; set; } = 90.0;
|
||||||
|
public double Length2 { get; set; }
|
||||||
|
public double ApproachAngle2 { get; set; } = 90.0;
|
||||||
|
|
||||||
|
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||||
|
|
||||||
|
var secondAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle1);
|
||||||
|
var midPoint = new Vector(
|
||||||
|
contourStartPoint.X + Length2 * System.Math.Cos(secondAngle),
|
||||||
|
contourStartPoint.Y + Length2 * System.Math.Sin(secondAngle));
|
||||||
|
|
||||||
|
return new List<ICode>
|
||||||
|
{
|
||||||
|
new RapidMove(piercePoint),
|
||||||
|
new LinearMove(midPoint),
|
||||||
|
new LinearMove(contourStartPoint)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||||
|
{
|
||||||
|
var secondAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle1);
|
||||||
|
var midX = contourStartPoint.X + Length2 * System.Math.Cos(secondAngle);
|
||||||
|
var midY = contourStartPoint.Y + Length2 * System.Math.Sin(secondAngle);
|
||||||
|
|
||||||
|
var firstAngle = secondAngle + Angle.ToRadians(ApproachAngle2);
|
||||||
|
return new Vector(
|
||||||
|
midX + Length1 * System.Math.Cos(firstAngle),
|
||||||
|
midY + Length1 * System.Math.Sin(firstAngle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class NoLeadIn : LeadIn
|
||||||
|
{
|
||||||
|
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
return new List<ICode>
|
||||||
|
{
|
||||||
|
new RapidMove(contourStartPoint)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||||
|
{
|
||||||
|
return contourStartPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class ArcLeadOut : LeadOut
|
||||||
|
{
|
||||||
|
public double Radius { get; set; }
|
||||||
|
|
||||||
|
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
var arcCenterX = contourEndPoint.X + Radius * System.Math.Cos(contourNormalAngle);
|
||||||
|
var arcCenterY = contourEndPoint.Y + Radius * System.Math.Sin(contourNormalAngle);
|
||||||
|
var arcCenter = new Vector(arcCenterX, arcCenterY);
|
||||||
|
|
||||||
|
var endPoint = new Vector(
|
||||||
|
arcCenterX + Radius * System.Math.Cos(contourNormalAngle + System.Math.PI / 2),
|
||||||
|
arcCenterY + Radius * System.Math.Sin(contourNormalAngle + System.Math.PI / 2));
|
||||||
|
|
||||||
|
return new List<ICode>
|
||||||
|
{
|
||||||
|
new ArcMove(endPoint, arcCenter, winding)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public abstract class LeadOut
|
||||||
|
{
|
||||||
|
public abstract List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using OpenNest.Math;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class LineLeadOut : LeadOut
|
||||||
|
{
|
||||||
|
public double Length { get; set; }
|
||||||
|
public double ApproachAngle { get; set; } = 90.0;
|
||||||
|
|
||||||
|
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
var overcutAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
||||||
|
var endPoint = new Vector(
|
||||||
|
contourEndPoint.X + Length * System.Math.Cos(overcutAngle),
|
||||||
|
contourEndPoint.Y + Length * System.Math.Sin(overcutAngle));
|
||||||
|
|
||||||
|
return new List<ICode>
|
||||||
|
{
|
||||||
|
new LinearMove(endPoint)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class MicrotabLeadOut : LeadOut
|
||||||
|
{
|
||||||
|
public double GapSize { get; set; } = 0.03;
|
||||||
|
|
||||||
|
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
return new List<ICode>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class NoLeadOut : LeadOut
|
||||||
|
{
|
||||||
|
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
return new List<ICode>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
// Values match PEP Technology's numbering scheme (value 6 intentionally skipped)
|
||||||
|
public enum SequenceMethod
|
||||||
|
{
|
||||||
|
RightSide = 1,
|
||||||
|
LeastCode = 2,
|
||||||
|
Advanced = 3,
|
||||||
|
BottomSide = 4,
|
||||||
|
EdgeStart = 5,
|
||||||
|
LeftSide = 7,
|
||||||
|
RightSideAlt = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SequenceParameters
|
||||||
|
{
|
||||||
|
public SequenceMethod Method { get; set; } = SequenceMethod.Advanced;
|
||||||
|
public double SmallCutoutWidth { get; set; } = 1.5;
|
||||||
|
public double SmallCutoutHeight { get; set; } = 1.5;
|
||||||
|
public double MediumCutoutWidth { get; set; } = 8.0;
|
||||||
|
public double MediumCutoutHeight { get; set; } = 8.0;
|
||||||
|
public double DistanceMediumSmall { get; set; }
|
||||||
|
public bool AlternateRowsColumns { get; set; } = true;
|
||||||
|
public bool AlternateCutoutsWithinRowColumn { get; set; } = true;
|
||||||
|
public double MinDistanceBetweenRowsColumns { get; set; } = 0.25;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class BreakerTab : Tab
|
||||||
|
{
|
||||||
|
public double BreakerDepth { get; set; }
|
||||||
|
public double BreakerLeadInLength { get; set; }
|
||||||
|
public double BreakerAngle { get; set; }
|
||||||
|
|
||||||
|
public override List<ICode> Generate(
|
||||||
|
Vector tabStartPoint, Vector tabEndPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
var codes = new List<ICode>();
|
||||||
|
|
||||||
|
if (TabLeadOut != null)
|
||||||
|
codes.AddRange(TabLeadOut.Generate(tabStartPoint, contourNormalAngle, winding));
|
||||||
|
|
||||||
|
var scoreAngle = contourNormalAngle + System.Math.PI;
|
||||||
|
var scoreEnd = new Vector(
|
||||||
|
tabStartPoint.X + BreakerDepth * System.Math.Cos(scoreAngle),
|
||||||
|
tabStartPoint.Y + BreakerDepth * System.Math.Sin(scoreAngle));
|
||||||
|
codes.Add(new LinearMove(scoreEnd));
|
||||||
|
codes.Add(new RapidMove(tabEndPoint));
|
||||||
|
|
||||||
|
if (TabLeadIn != null)
|
||||||
|
codes.AddRange(TabLeadIn.Generate(tabEndPoint, contourNormalAngle, winding));
|
||||||
|
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class MachineTab : Tab
|
||||||
|
{
|
||||||
|
public int MachineTabId { get; set; }
|
||||||
|
|
||||||
|
public override List<ICode> Generate(
|
||||||
|
Vector tabStartPoint, Vector tabEndPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
return new List<ICode>
|
||||||
|
{
|
||||||
|
new RapidMove(tabEndPoint)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public class NormalTab : Tab
|
||||||
|
{
|
||||||
|
public double CutoutMinWidth { get; set; }
|
||||||
|
public double CutoutMinHeight { get; set; }
|
||||||
|
public double CutoutMaxWidth { get; set; }
|
||||||
|
public double CutoutMaxHeight { get; set; }
|
||||||
|
|
||||||
|
public override List<ICode> Generate(
|
||||||
|
Vector tabStartPoint, Vector tabEndPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW)
|
||||||
|
{
|
||||||
|
var codes = new List<ICode>();
|
||||||
|
|
||||||
|
if (TabLeadOut != null)
|
||||||
|
codes.AddRange(TabLeadOut.Generate(tabStartPoint, contourNormalAngle, winding));
|
||||||
|
|
||||||
|
codes.Add(new RapidMove(tabEndPoint));
|
||||||
|
|
||||||
|
if (TabLeadIn != null)
|
||||||
|
codes.AddRange(TabLeadIn.Generate(tabEndPoint, contourNormalAngle, winding));
|
||||||
|
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AppliesToCutout(double cutoutWidth, double cutoutHeight)
|
||||||
|
{
|
||||||
|
return cutoutWidth >= CutoutMinWidth && cutoutWidth <= CutoutMaxWidth
|
||||||
|
&& cutoutHeight >= CutoutMinHeight && cutoutHeight <= CutoutMaxHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.CNC.CuttingStrategy
|
||||||
|
{
|
||||||
|
public abstract class Tab
|
||||||
|
{
|
||||||
|
public double Size { get; set; } = 0.03;
|
||||||
|
public LeadIn TabLeadIn { get; set; }
|
||||||
|
public LeadOut TabLeadOut { get; set; }
|
||||||
|
|
||||||
|
public abstract List<ICode> Generate(
|
||||||
|
Vector tabStartPoint, Vector tabEndPoint, double contourNormalAngle,
|
||||||
|
RotationType winding = RotationType.CW);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user