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 exitPoint = approachPoint;
|
||||||
var entities = partProgram.ToGeometry();
|
var entities = partProgram.ToGeometry();
|
||||||
entities.RemoveAll(e => e.Layer == SpecialLayers.Rapid);
|
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);
|
var profile = new ShapeProfile(entities);
|
||||||
|
|
||||||
// Find closest point on perimeter from exit point
|
// Find closest point on perimeter from exit point
|
||||||
@@ -22,10 +27,23 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
var orderedCutouts = SequenceCutouts(profile.Cutouts, perimeterPoint);
|
var orderedCutouts = SequenceCutouts(profile.Cutouts, perimeterPoint);
|
||||||
orderedCutouts.Reverse();
|
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 result = new Program(Mode.Absolute);
|
||||||
var currentPoint = exitPoint;
|
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)
|
foreach (var cutout in orderedCutouts)
|
||||||
{
|
{
|
||||||
var contourType = DetectContourType(cutout);
|
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>();
|
var moves = new List<ICode>();
|
||||||
|
|
||||||
@@ -228,15 +246,15 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
{
|
{
|
||||||
if (entity is Line line)
|
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)
|
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)
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -246,5 +264,14 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
|
|
||||||
return moves;
|
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);
|
var entities = ConvertProgram.ToGeometry(cleanProgram);
|
||||||
|
entities.RemoveAll(e => e.Layer == SpecialLayers.Scribe);
|
||||||
profile = new ShapeProfile(entities);
|
profile = new ShapeProfile(entities);
|
||||||
|
|
||||||
contours = new List<ShapeInfo>();
|
contours = new List<ShapeInfo>();
|
||||||
|
|||||||
Reference in New Issue
Block a user