fix: exempt scribe/etch contours from lead-ins and kerf
Scribe/etch lines were being treated as cut contours by ContourCuttingStrategy, receiving lead-ins and kerf compensation. Now they are separated before ShapeProfile construction and emitted as plain moves with LayerType.Scribe preserved. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,11 @@ namespace OpenNest.CNC.CuttingStrategy
|
||||
var exitPoint = approachPoint;
|
||||
var entities = partProgram.ToGeometry();
|
||||
entities.RemoveAll(e => e.Layer == SpecialLayers.Rapid);
|
||||
|
||||
// Separate scribe/etch entities — they don't get lead-ins or kerf
|
||||
var scribeEntities = entities.FindAll(e => e.Layer == SpecialLayers.Scribe);
|
||||
entities.RemoveAll(e => e.Layer == SpecialLayers.Scribe);
|
||||
|
||||
var profile = new ShapeProfile(entities);
|
||||
|
||||
// Find closest point on perimeter from exit point
|
||||
@@ -22,10 +27,23 @@ namespace OpenNest.CNC.CuttingStrategy
|
||||
var orderedCutouts = SequenceCutouts(profile.Cutouts, perimeterPoint);
|
||||
orderedCutouts.Reverse();
|
||||
|
||||
// Build output program: cutouts first (farthest to nearest), perimeter last
|
||||
// Build output program: scribe first, cutouts second, perimeter last
|
||||
var result = new Program(Mode.Absolute);
|
||||
var currentPoint = exitPoint;
|
||||
|
||||
// Emit scribe/etch contours first (no lead-ins, no kerf)
|
||||
if (scribeEntities.Count > 0)
|
||||
{
|
||||
var scribeShapes = ShapeBuilder.GetShapes(scribeEntities);
|
||||
foreach (var scribe in scribeShapes)
|
||||
{
|
||||
var startPt = GetShapeStartPoint(scribe);
|
||||
result.Codes.Add(new RapidMove(startPt));
|
||||
result.Codes.AddRange(ConvertShapeToMoves(scribe, startPt, LayerType.Scribe));
|
||||
currentPoint = startPt;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var cutout in orderedCutouts)
|
||||
{
|
||||
var contourType = DetectContourType(cutout);
|
||||
@@ -220,7 +238,7 @@ namespace OpenNest.CNC.CuttingStrategy
|
||||
};
|
||||
}
|
||||
|
||||
private List<ICode> ConvertShapeToMoves(Shape shape, Vector startPoint)
|
||||
private List<ICode> ConvertShapeToMoves(Shape shape, Vector startPoint, LayerType layer = LayerType.Display)
|
||||
{
|
||||
var moves = new List<ICode>();
|
||||
|
||||
@@ -228,15 +246,15 @@ namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
if (entity is Line line)
|
||||
{
|
||||
moves.Add(new LinearMove(line.EndPoint));
|
||||
moves.Add(new LinearMove(line.EndPoint) { Layer = layer });
|
||||
}
|
||||
else if (entity is Arc arc)
|
||||
{
|
||||
moves.Add(new ArcMove(arc.EndPoint(), arc.Center, arc.IsReversed ? RotationType.CW : RotationType.CCW));
|
||||
moves.Add(new ArcMove(arc.EndPoint(), arc.Center, arc.IsReversed ? RotationType.CW : RotationType.CCW) { Layer = layer });
|
||||
}
|
||||
else if (entity is Circle circle)
|
||||
{
|
||||
moves.Add(new ArcMove(startPoint, circle.Center, circle.Rotation));
|
||||
moves.Add(new ArcMove(startPoint, circle.Center, circle.Rotation) { Layer = layer });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -246,5 +264,14 @@ namespace OpenNest.CNC.CuttingStrategy
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static Vector GetShapeStartPoint(Shape shape)
|
||||
{
|
||||
var first = shape.Entities[0];
|
||||
if (first is Line line) return line.StartPoint;
|
||||
if (first is Arc arc) return arc.StartPoint();
|
||||
if (first is Circle circle) return new Vector(circle.Center.X + circle.Radius, circle.Center.Y);
|
||||
return Vector.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,6 +249,7 @@ namespace OpenNest.Actions
|
||||
}
|
||||
|
||||
var entities = ConvertProgram.ToGeometry(cleanProgram);
|
||||
entities.RemoveAll(e => e.Layer == SpecialLayers.Scribe);
|
||||
profile = new ShapeProfile(entities);
|
||||
|
||||
contours = new List<ShapeInfo>();
|
||||
|
||||
Reference in New Issue
Block a user