fix: resolve rendering issues when applying lead-ins to parts
Three issues caused incorrect rendering after lead-in application: - Rapid move entities from ToGeometry() were included in ShapeProfile contour detection, turning traversal paths into cutting moves - Program created with Mode.Incremental default made the absolute-to- incremental conversion a no-op, leaving coordinates unconverted - AddProgramSplit didn't call StartFigure() at rapid moves, causing GraphicsPath to draw implicit connecting lines between contours - Part.Rotation returned 0 from the new program instead of the actual rotation, displacing the sequence label on rotated parts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ 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);
|
||||||
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,7 +23,7 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
orderedCutouts.Reverse();
|
orderedCutouts.Reverse();
|
||||||
|
|
||||||
// Build output program: cutouts first (farthest to nearest), perimeter last
|
// Build output program: cutouts first (farthest to nearest), perimeter last
|
||||||
var result = new Program();
|
var result = new Program(Mode.Absolute);
|
||||||
var currentPoint = exitPoint;
|
var currentPoint = exitPoint;
|
||||||
|
|
||||||
foreach (var cutout in orderedCutouts)
|
foreach (var cutout in orderedCutouts)
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ namespace OpenNest
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double Rotation
|
public double Rotation
|
||||||
{
|
{
|
||||||
get { return Program.Rotation; }
|
get { return HasManualLeadIns ? preLeadInRotation : Program.Rotation; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+56
-14
@@ -135,6 +135,8 @@ namespace OpenNest
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CodeType.RapidMove:
|
case CodeType.RapidMove:
|
||||||
|
cutPath.StartFigure();
|
||||||
|
leadPath.StartFigure();
|
||||||
AddLine(cutPath, (RapidMove)code, mode, ref curpos);
|
AddLine(cutPath, (RapidMove)code, mode, ref curpos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -203,12 +205,6 @@ namespace OpenNest
|
|||||||
size, size,
|
size, size,
|
||||||
(float)startAngle,
|
(float)startAngle,
|
||||||
(float)sweepAngle);
|
(float)sweepAngle);
|
||||||
|
|
||||||
if (arc.Layer == LayerType.Leadin || arc.Layer == LayerType.Leadout)
|
|
||||||
{
|
|
||||||
path.AddArc(pt.X, pt.Y, size, size, (float)(-startAngle + sweepAngle), (float)-sweepAngle);
|
|
||||||
path.CloseFigure();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curpos = endpt;
|
curpos = endpt;
|
||||||
@@ -226,9 +222,6 @@ namespace OpenNest
|
|||||||
|
|
||||||
path.AddLine(pt1, pt2);
|
path.AddLine(pt1, pt2);
|
||||||
|
|
||||||
if (line.Layer == LayerType.Leadin || line.Layer == LayerType.Leadout)
|
|
||||||
path.CloseFigure();
|
|
||||||
|
|
||||||
curpos = pt;
|
curpos = pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,14 +232,23 @@ namespace OpenNest
|
|||||||
if (mode == Mode.Incremental)
|
if (mode == Mode.Incremental)
|
||||||
pt += curpos;
|
pt += curpos;
|
||||||
|
|
||||||
path.CloseFigure();
|
|
||||||
|
|
||||||
curpos = pt;
|
curpos = pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddProgram(GraphicsPath path, Program pgm, Mode mode, ref Vector curpos)
|
private static void AddProgram(GraphicsPath path, Program pgm, Mode mode, ref Vector curpos)
|
||||||
{
|
{
|
||||||
mode = pgm.Mode;
|
mode = pgm.Mode;
|
||||||
|
GraphicsPath currentFigure = null;
|
||||||
|
|
||||||
|
void Flush()
|
||||||
|
{
|
||||||
|
if (currentFigure != null)
|
||||||
|
{
|
||||||
|
path.AddPath(currentFigure, false);
|
||||||
|
currentFigure.Dispose();
|
||||||
|
currentFigure = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < pgm.Length; ++i)
|
for (int i = 0; i < pgm.Length; ++i)
|
||||||
{
|
{
|
||||||
@@ -255,25 +257,54 @@ namespace OpenNest
|
|||||||
switch (code.Type)
|
switch (code.Type)
|
||||||
{
|
{
|
||||||
case CodeType.ArcMove:
|
case CodeType.ArcMove:
|
||||||
AddArc(path, (ArcMove)code, mode, ref curpos);
|
{
|
||||||
|
var arc = (ArcMove)code;
|
||||||
|
if (arc.Layer != LayerType.Leadin && arc.Layer != LayerType.Leadout)
|
||||||
|
{
|
||||||
|
if (currentFigure == null) currentFigure = new GraphicsPath();
|
||||||
|
AddArc(currentFigure, arc, mode, ref curpos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Flush();
|
||||||
|
var endpt = arc.EndPoint;
|
||||||
|
if (mode == Mode.Incremental) endpt += curpos;
|
||||||
|
curpos = endpt;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CodeType.LinearMove:
|
case CodeType.LinearMove:
|
||||||
AddLine(path, (LinearMove)code, mode, ref curpos);
|
{
|
||||||
|
var line = (LinearMove)code;
|
||||||
|
if (line.Layer != LayerType.Leadin && line.Layer != LayerType.Leadout)
|
||||||
|
{
|
||||||
|
if (currentFigure == null) currentFigure = new GraphicsPath();
|
||||||
|
AddLine(currentFigure, line, mode, ref curpos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Flush();
|
||||||
|
var endpt = line.EndPoint;
|
||||||
|
if (mode == Mode.Incremental) endpt += curpos;
|
||||||
|
curpos = endpt;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CodeType.RapidMove:
|
case CodeType.RapidMove:
|
||||||
|
Flush();
|
||||||
AddLine(path, (RapidMove)code, mode, ref curpos);
|
AddLine(path, (RapidMove)code, mode, ref curpos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CodeType.SubProgramCall:
|
case CodeType.SubProgramCall:
|
||||||
{
|
{
|
||||||
|
Flush();
|
||||||
var tmpmode = mode;
|
var tmpmode = mode;
|
||||||
var subpgm = (SubProgramCall)code;
|
var subpgm = (SubProgramCall)code;
|
||||||
|
|
||||||
if (subpgm.Program != null)
|
if (subpgm.Program != null)
|
||||||
{
|
{
|
||||||
path.StartFigure();
|
|
||||||
AddProgram(path, subpgm.Program, mode, ref curpos);
|
AddProgram(path, subpgm.Program, mode, ref curpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,6 +313,8 @@ namespace OpenNest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddArc(GraphicsPath path, Arc arc)
|
private static void AddArc(GraphicsPath path, Arc arc)
|
||||||
@@ -331,6 +364,15 @@ namespace OpenNest
|
|||||||
{
|
{
|
||||||
foreach (var entity in shape.Entities)
|
foreach (var entity in shape.Entities)
|
||||||
{
|
{
|
||||||
|
if (entity.Layer != null)
|
||||||
|
{
|
||||||
|
if (string.Equals(entity.Layer.Name, SpecialLayers.Leadin.Name, System.StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(entity.Layer.Name, SpecialLayers.Leadout.Name, System.StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (entity.Type)
|
switch (entity.Type)
|
||||||
{
|
{
|
||||||
case EntityType.Arc:
|
case EntityType.Arc:
|
||||||
|
|||||||
Reference in New Issue
Block a user