Compare commits
12 Commits
3d4204db7b
...
d16ef36d34
| Author | SHA1 | Date | |
|---|---|---|---|
| d16ef36d34 | |||
| 5307c5c85a | |||
| 21321740d6 | |||
| 7f8c708d3f | |||
| ab4f806820 | |||
| c9b5ee1918 | |||
| f34dce95da | |||
| a2a19938d3 | |||
| c064c7647a | |||
| 8a712b9755 | |||
| 82de512f44 | |||
| f903cbe18a |
@@ -65,7 +65,8 @@ namespace OpenNest.CNC
|
|||||||
{
|
{
|
||||||
return new ArcMove(EndPoint, CenterPoint, Rotation)
|
return new ArcMove(EndPoint, CenterPoint, Rotation)
|
||||||
{
|
{
|
||||||
Layer = Layer
|
Layer = Layer,
|
||||||
|
Suppressed = Suppressed
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,10 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
result.Codes.AddRange(leadOut.Generate(perimeterPt, normal, winding));
|
result.Codes.AddRange(leadOut.Generate(perimeterPt, normal, winding));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert to incremental mode to match the convention used by
|
||||||
|
// the rest of the system (rendering, bounding box, drag, etc.).
|
||||||
|
result.Mode = Mode.Incremental;
|
||||||
|
|
||||||
return new CuttingResult
|
return new CuttingResult
|
||||||
{
|
{
|
||||||
Program = result,
|
Program = result,
|
||||||
@@ -102,7 +106,7 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
return ordered;
|
return ordered;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContourType DetectContourType(Shape cutout)
|
public static ContourType DetectContourType(Shape cutout)
|
||||||
{
|
{
|
||||||
if (cutout.Entities.Count == 1 && cutout.Entities[0] is Circle)
|
if (cutout.Entities.Count == 1 && cutout.Entities[0] is Circle)
|
||||||
return ContourType.ArcCircle;
|
return ContourType.ArcCircle;
|
||||||
@@ -110,7 +114,7 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
return ContourType.Internal;
|
return ContourType.Internal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double ComputeNormal(Vector point, Entity entity, ContourType contourType)
|
public static double ComputeNormal(Vector point, Entity entity, ContourType contourType)
|
||||||
{
|
{
|
||||||
double normal;
|
double normal;
|
||||||
|
|
||||||
@@ -141,7 +145,7 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
return Math.Angle.NormalizeRad(normal);
|
return Math.Angle.NormalizeRad(normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RotationType DetermineWinding(Shape shape)
|
public static RotationType DetermineWinding(Shape shape)
|
||||||
{
|
{
|
||||||
// Use signed area: positive = CCW, negative = CW
|
// Use signed area: positive = CCW, negative = CW
|
||||||
var area = shape.Area();
|
var area = shape.Area();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
return new List<ICode>
|
return new List<ICode>
|
||||||
{
|
{
|
||||||
new RapidMove(piercePoint),
|
new RapidMove(piercePoint),
|
||||||
new ArcMove(contourStartPoint, arcCenter, winding)
|
new ArcMove(contourStartPoint, arcCenter, winding) { Layer = LayerType.Leadin }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
return new List<ICode>
|
return new List<ICode>
|
||||||
{
|
{
|
||||||
new RapidMove(piercePoint),
|
new RapidMove(piercePoint),
|
||||||
new LinearMove(arcStart),
|
new LinearMove(arcStart) { Layer = LayerType.Leadin },
|
||||||
new ArcMove(contourStartPoint, arcCenter, winding)
|
new ArcMove(contourStartPoint, arcCenter, winding) { Layer = LayerType.Leadin }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
return new List<ICode>
|
return new List<ICode>
|
||||||
{
|
{
|
||||||
new RapidMove(piercePoint),
|
new RapidMove(piercePoint),
|
||||||
new LinearMove(arcStart),
|
new LinearMove(arcStart) { Layer = LayerType.Leadin },
|
||||||
new ArcMove(contourStartPoint, arcCenter, winding)
|
new ArcMove(contourStartPoint, arcCenter, winding) { Layer = LayerType.Leadin }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
return new List<ICode>
|
return new List<ICode>
|
||||||
{
|
{
|
||||||
new RapidMove(piercePoint),
|
new RapidMove(piercePoint),
|
||||||
new LinearMove(contourStartPoint)
|
new LinearMove(contourStartPoint) { Layer = LayerType.Leadin }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||||
{
|
{
|
||||||
var approachAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
var approachAngle = contourNormalAngle + Angle.HalfPI - Angle.ToRadians(ApproachAngle);
|
||||||
return new Vector(
|
return new Vector(
|
||||||
contourStartPoint.X + Length * System.Math.Cos(approachAngle),
|
contourStartPoint.X + Length * System.Math.Cos(approachAngle),
|
||||||
contourStartPoint.Y + Length * System.Math.Sin(approachAngle));
|
contourStartPoint.Y + Length * System.Math.Sin(approachAngle));
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
{
|
{
|
||||||
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||||
|
|
||||||
var secondAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle1);
|
var secondAngle = contourNormalAngle + Angle.HalfPI - Angle.ToRadians(ApproachAngle1);
|
||||||
var midPoint = new Vector(
|
var midPoint = new Vector(
|
||||||
contourStartPoint.X + Length2 * System.Math.Cos(secondAngle),
|
contourStartPoint.X + Length2 * System.Math.Cos(secondAngle),
|
||||||
contourStartPoint.Y + Length2 * System.Math.Sin(secondAngle));
|
contourStartPoint.Y + Length2 * System.Math.Sin(secondAngle));
|
||||||
@@ -24,14 +24,14 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
return new List<ICode>
|
return new List<ICode>
|
||||||
{
|
{
|
||||||
new RapidMove(piercePoint),
|
new RapidMove(piercePoint),
|
||||||
new LinearMove(midPoint),
|
new LinearMove(midPoint) { Layer = LayerType.Leadin },
|
||||||
new LinearMove(contourStartPoint)
|
new LinearMove(contourStartPoint) { Layer = LayerType.Leadin }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||||
{
|
{
|
||||||
var secondAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle1);
|
var secondAngle = contourNormalAngle + Angle.HalfPI - Angle.ToRadians(ApproachAngle1);
|
||||||
var midX = contourStartPoint.X + Length2 * System.Math.Cos(secondAngle);
|
var midX = contourStartPoint.X + Length2 * System.Math.Cos(secondAngle);
|
||||||
var midY = contourStartPoint.Y + Length2 * System.Math.Sin(secondAngle);
|
var midY = contourStartPoint.Y + Length2 * System.Math.Sin(secondAngle);
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
|
|
||||||
return new List<ICode>
|
return new List<ICode>
|
||||||
{
|
{
|
||||||
new ArcMove(endPoint, arcCenter, winding)
|
new ArcMove(endPoint, arcCenter, winding) { Layer = LayerType.Leadout }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ namespace OpenNest.CNC.CuttingStrategy
|
|||||||
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||||
RotationType winding = RotationType.CW)
|
RotationType winding = RotationType.CW)
|
||||||
{
|
{
|
||||||
var overcutAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
var overcutAngle = contourNormalAngle + Angle.HalfPI - Angle.ToRadians(ApproachAngle);
|
||||||
var endPoint = new Vector(
|
var endPoint = new Vector(
|
||||||
contourEndPoint.X + Length * System.Math.Cos(overcutAngle),
|
contourEndPoint.X + Length * System.Math.Cos(overcutAngle),
|
||||||
contourEndPoint.Y + Length * System.Math.Sin(overcutAngle));
|
contourEndPoint.Y + Length * System.Math.Sin(overcutAngle));
|
||||||
|
|
||||||
return new List<ICode>
|
return new List<ICode>
|
||||||
{
|
{
|
||||||
new LinearMove(endPoint)
|
new LinearMove(endPoint) { Layer = LayerType.Leadout }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ namespace OpenNest.CNC
|
|||||||
{
|
{
|
||||||
return new LinearMove(EndPoint)
|
return new LinearMove(EndPoint)
|
||||||
{
|
{
|
||||||
Layer = Layer
|
Layer = Layer,
|
||||||
|
Suppressed = Suppressed
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ namespace OpenNest.CNC
|
|||||||
|
|
||||||
public int Feedrate { get; set; }
|
public int Feedrate { get; set; }
|
||||||
|
|
||||||
|
public bool Suppressed { get; set; }
|
||||||
|
|
||||||
protected Motion()
|
protected Motion()
|
||||||
{
|
{
|
||||||
Feedrate = CNC.Feedrate.UseDefault;
|
Feedrate = CNC.Feedrate.UseDefault;
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ namespace OpenNest.CNC
|
|||||||
|
|
||||||
public override ICode Clone()
|
public override ICode Clone()
|
||||||
{
|
{
|
||||||
return new RapidMove(EndPoint);
|
return new RapidMove(EndPoint)
|
||||||
|
{
|
||||||
|
Suppressed = Suppressed
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace OpenNest
|
|||||||
{
|
{
|
||||||
private Vector location;
|
private Vector location;
|
||||||
private bool ownsProgram;
|
private bool ownsProgram;
|
||||||
|
private double preLeadInRotation;
|
||||||
|
|
||||||
public readonly Drawing BaseDrawing;
|
public readonly Drawing BaseDrawing;
|
||||||
|
|
||||||
@@ -56,6 +57,38 @@ namespace OpenNest
|
|||||||
|
|
||||||
public bool HasManualLeadIns { get; set; }
|
public bool HasManualLeadIns { get; set; }
|
||||||
|
|
||||||
|
public bool LeadInsLocked { get; set; }
|
||||||
|
|
||||||
|
public CNC.CuttingStrategy.CuttingParameters CuttingParameters { get; set; }
|
||||||
|
|
||||||
|
public void ApplyLeadIns(CNC.CuttingStrategy.CuttingParameters parameters, Vector approachPoint)
|
||||||
|
{
|
||||||
|
preLeadInRotation = Rotation;
|
||||||
|
var strategy = new CNC.CuttingStrategy.ContourCuttingStrategy { Parameters = parameters };
|
||||||
|
var result = strategy.Apply(Program, approachPoint);
|
||||||
|
Program = result.Program;
|
||||||
|
CuttingParameters = parameters;
|
||||||
|
HasManualLeadIns = true;
|
||||||
|
UpdateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveLeadIns()
|
||||||
|
{
|
||||||
|
var rotation = preLeadInRotation;
|
||||||
|
var location = Location;
|
||||||
|
Program = BaseDrawing.Program.Clone() as Program;
|
||||||
|
ownsProgram = true;
|
||||||
|
|
||||||
|
if (!Math.Tolerance.IsEqualTo(rotation, 0))
|
||||||
|
Program.Rotate(rotation);
|
||||||
|
|
||||||
|
Location = location;
|
||||||
|
HasManualLeadIns = false;
|
||||||
|
LeadInsLocked = false;
|
||||||
|
CuttingParameters = null;
|
||||||
|
UpdateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the rotation of the part in radians.
|
/// Gets the rotation of the part in radians.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ namespace OpenNest
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Material Material { get; set; }
|
public Material Material { get; set; }
|
||||||
|
|
||||||
|
public CNC.CuttingStrategy.CuttingParameters CuttingParameters { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Material grain direction in radians. 0 = horizontal.
|
/// Material grain direction in radians. 0 = horizontal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ namespace OpenNest
|
|||||||
|
|
||||||
public static readonly Layer Display = new Layer("DISPLAY") { Color = Color.Cyan };
|
public static readonly Layer Display = new Layer("DISPLAY") { Color = Color.Cyan };
|
||||||
|
|
||||||
public static readonly Layer Leadin = new Layer("LEADIN") { Color = Color.Yellow };
|
public static readonly Layer Leadin = new Layer("LEADIN") { Color = Color.Brown };
|
||||||
|
|
||||||
public static readonly Layer Leadout = new Layer("LEADOUT") { Color = Color.Yellow };
|
public static readonly Layer Leadout = new Layer("LEADOUT") { Color = Color.Brown };
|
||||||
|
|
||||||
public static readonly Layer Scribe = new Layer("SCRIBE") { Color = Color.Magenta };
|
public static readonly Layer Scribe = new Layer("SCRIBE") { Color = Color.Magenta };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using OpenNest.Engine.Sequencing;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenNest.Engine
|
||||||
|
{
|
||||||
|
public class LeadInAssigner
|
||||||
|
{
|
||||||
|
public IPartSequencer Sequencer { get; set; }
|
||||||
|
|
||||||
|
public void Assign(Plate plate)
|
||||||
|
{
|
||||||
|
var parameters = plate.CuttingParameters;
|
||||||
|
if (parameters == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var sequenced = Sequencer.Sequence(plate.Parts.ToList(), plate);
|
||||||
|
var currentPoint = PlateHelper.GetExitPoint(plate);
|
||||||
|
|
||||||
|
foreach (var sp in sequenced)
|
||||||
|
{
|
||||||
|
var part = sp.Part;
|
||||||
|
|
||||||
|
if (part.LeadInsLocked)
|
||||||
|
{
|
||||||
|
currentPoint = part.Location;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.HasManualLeadIns)
|
||||||
|
part.RemoveLeadIns();
|
||||||
|
|
||||||
|
var localApproach = currentPoint - part.Location;
|
||||||
|
part.ApplyLeadIns(parameters, localApproach);
|
||||||
|
|
||||||
|
currentPoint = part.Location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,6 +74,8 @@ namespace OpenNest.IO
|
|||||||
public double X { get; init; }
|
public double X { get; init; }
|
||||||
public double Y { get; init; }
|
public double Y { get; init; }
|
||||||
public double Rotation { get; init; }
|
public double Rotation { get; init; }
|
||||||
|
public bool HasManualLeadIns { get; init; }
|
||||||
|
public bool LeadInsLocked { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CutOffDto
|
public record CutOffDto
|
||||||
|
|||||||
@@ -214,6 +214,8 @@ namespace OpenNest.IO
|
|||||||
var part = new Part(dwg);
|
var part = new Part(dwg);
|
||||||
part.Rotate(partDto.Rotation);
|
part.Rotate(partDto.Rotation);
|
||||||
part.Offset(new Vector(partDto.X, partDto.Y));
|
part.Offset(new Vector(partDto.X, partDto.Y));
|
||||||
|
part.HasManualLeadIns = partDto.HasManualLeadIns;
|
||||||
|
part.LeadInsLocked = partDto.LeadInsLocked;
|
||||||
plate.Parts.Add(part);
|
plate.Parts.Add(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,7 +173,9 @@ namespace OpenNest.IO
|
|||||||
DrawingId = match.Key,
|
DrawingId = match.Key,
|
||||||
X = part.Location.X,
|
X = part.Location.X,
|
||||||
Y = part.Location.Y,
|
Y = part.Location.Y,
|
||||||
Rotation = part.Rotation
|
Rotation = part.Rotation,
|
||||||
|
HasManualLeadIns = part.HasManualLeadIns,
|
||||||
|
LeadInsLocked = part.LeadInsLocked
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,6 +338,9 @@ namespace OpenNest.IO
|
|||||||
if (arcMove.Layer != LayerType.Cut)
|
if (arcMove.Layer != LayerType.Cut)
|
||||||
sb.Append(GetLayerString(arcMove.Layer));
|
sb.Append(GetLayerString(arcMove.Layer));
|
||||||
|
|
||||||
|
if (arcMove.Suppressed)
|
||||||
|
sb.Append(":SUPPRESSED");
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,6 +362,9 @@ namespace OpenNest.IO
|
|||||||
if (linearMove.Layer != LayerType.Cut)
|
if (linearMove.Layer != LayerType.Cut)
|
||||||
sb.Append(GetLayerString(linearMove.Layer));
|
sb.Append(GetLayerString(linearMove.Layer));
|
||||||
|
|
||||||
|
if (linearMove.Suppressed)
|
||||||
|
sb.Append(":SUPPRESSED");
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ namespace OpenNest.IO
|
|||||||
double x = 0;
|
double x = 0;
|
||||||
double y = 0;
|
double y = 0;
|
||||||
var layer = LayerType.Cut;
|
var layer = LayerType.Cut;
|
||||||
|
var suppressed = false;
|
||||||
|
|
||||||
while (section == CodeSection.Line)
|
while (section == CodeSection.Line)
|
||||||
{
|
{
|
||||||
@@ -164,25 +165,32 @@ namespace OpenNest.IO
|
|||||||
|
|
||||||
case ':':
|
case ':':
|
||||||
{
|
{
|
||||||
var value = code.Value.Trim().ToUpper();
|
var tags = code.Value.Trim().ToUpper().Split(':');
|
||||||
|
|
||||||
switch (value)
|
foreach (var tag in tags)
|
||||||
{
|
{
|
||||||
case "DISPLAY":
|
switch (tag)
|
||||||
layer = LayerType.Display;
|
{
|
||||||
break;
|
case "DISPLAY":
|
||||||
|
layer = LayerType.Display;
|
||||||
|
break;
|
||||||
|
|
||||||
case "LEADIN":
|
case "LEADIN":
|
||||||
layer = LayerType.Leadin;
|
layer = LayerType.Leadin;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "LEADOUT":
|
case "LEADOUT":
|
||||||
layer = LayerType.Leadout;
|
layer = LayerType.Leadout;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "SCRIBE":
|
case "SCRIBE":
|
||||||
layer = LayerType.Scribe;
|
layer = LayerType.Scribe;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "SUPPRESSED":
|
||||||
|
suppressed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -195,7 +203,7 @@ namespace OpenNest.IO
|
|||||||
if (isRapid)
|
if (isRapid)
|
||||||
program.Codes.Add(new RapidMove(x, y));
|
program.Codes.Add(new RapidMove(x, y));
|
||||||
else
|
else
|
||||||
program.Codes.Add(new LinearMove(x, y) { Layer = layer });
|
program.Codes.Add(new LinearMove(x, y) { Layer = layer, Suppressed = suppressed });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadArc(RotationType rotation)
|
private void ReadArc(RotationType rotation)
|
||||||
@@ -205,6 +213,7 @@ namespace OpenNest.IO
|
|||||||
double i = 0;
|
double i = 0;
|
||||||
double j = 0;
|
double j = 0;
|
||||||
var layer = LayerType.Cut;
|
var layer = LayerType.Cut;
|
||||||
|
var suppressed = false;
|
||||||
|
|
||||||
while (section == CodeSection.Arc)
|
while (section == CodeSection.Arc)
|
||||||
{
|
{
|
||||||
@@ -236,25 +245,32 @@ namespace OpenNest.IO
|
|||||||
|
|
||||||
case ':':
|
case ':':
|
||||||
{
|
{
|
||||||
var value = code.Value.Trim().ToUpper();
|
var tags = code.Value.Trim().ToUpper().Split(':');
|
||||||
|
|
||||||
switch (value)
|
foreach (var tag in tags)
|
||||||
{
|
{
|
||||||
case "DISPLAY":
|
switch (tag)
|
||||||
layer = LayerType.Display;
|
{
|
||||||
break;
|
case "DISPLAY":
|
||||||
|
layer = LayerType.Display;
|
||||||
|
break;
|
||||||
|
|
||||||
case "LEADIN":
|
case "LEADIN":
|
||||||
layer = LayerType.Leadin;
|
layer = LayerType.Leadin;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "LEADOUT":
|
case "LEADOUT":
|
||||||
layer = LayerType.Leadout;
|
layer = LayerType.Leadout;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "SCRIBE":
|
case "SCRIBE":
|
||||||
layer = LayerType.Scribe;
|
layer = LayerType.Scribe;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "SUPPRESSED":
|
||||||
|
suppressed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -269,7 +285,8 @@ namespace OpenNest.IO
|
|||||||
EndPoint = new Vector(x, y),
|
EndPoint = new Vector(x, y),
|
||||||
CenterPoint = new Vector(i, j),
|
CenterPoint = new Vector(i, j),
|
||||||
Rotation = rotation,
|
Rotation = rotation,
|
||||||
Layer = layer
|
Layer = layer,
|
||||||
|
Suppressed = suppressed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
using OpenNest.CNC;
|
||||||
|
using OpenNest.CNC.CuttingStrategy;
|
||||||
|
using OpenNest.Engine;
|
||||||
|
using OpenNest.Engine.Sequencing;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.Tests;
|
||||||
|
|
||||||
|
public class LeadInAssignerTests
|
||||||
|
{
|
||||||
|
private static Part MakeSquarePartAt(double x, double y)
|
||||||
|
{
|
||||||
|
var pgm = new Program();
|
||||||
|
pgm.Codes.Add(new RapidMove(new Vector(0, 0)));
|
||||||
|
pgm.Codes.Add(new LinearMove(new Vector(0, 10)));
|
||||||
|
pgm.Codes.Add(new LinearMove(new Vector(10, 10)));
|
||||||
|
pgm.Codes.Add(new LinearMove(new Vector(10, 0)));
|
||||||
|
pgm.Codes.Add(new LinearMove(new Vector(0, 0)));
|
||||||
|
var drawing = new Drawing("test", pgm);
|
||||||
|
return new Part(drawing, new Vector(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Assign_SetsHasManualLeadInsOnAllParts()
|
||||||
|
{
|
||||||
|
var plate = new Plate(60, 120);
|
||||||
|
plate.Parts.Add(MakeSquarePartAt(10, 10));
|
||||||
|
plate.Parts.Add(MakeSquarePartAt(30, 30));
|
||||||
|
plate.CuttingParameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
var assigner = new LeadInAssigner { Sequencer = new LeftSideSequencer() };
|
||||||
|
assigner.Assign(plate);
|
||||||
|
|
||||||
|
Assert.All(plate.Parts, p => Assert.True(p.HasManualLeadIns));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Assign_SkipsLockedParts()
|
||||||
|
{
|
||||||
|
var plate = new Plate(60, 120);
|
||||||
|
var lockedPart = MakeSquarePartAt(10, 10);
|
||||||
|
lockedPart.LeadInsLocked = true;
|
||||||
|
lockedPart.HasManualLeadIns = true;
|
||||||
|
var originalProgram = lockedPart.Program;
|
||||||
|
|
||||||
|
plate.Parts.Add(lockedPart);
|
||||||
|
plate.Parts.Add(MakeSquarePartAt(30, 30));
|
||||||
|
plate.CuttingParameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
var assigner = new LeadInAssigner { Sequencer = new LeftSideSequencer() };
|
||||||
|
assigner.Assign(plate);
|
||||||
|
|
||||||
|
Assert.Same(originalProgram, lockedPart.Program);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Assign_RemovesExistingLeadInsBeforeReapply()
|
||||||
|
{
|
||||||
|
var plate = new Plate(60, 120);
|
||||||
|
plate.Parts.Add(MakeSquarePartAt(10, 10));
|
||||||
|
plate.CuttingParameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
var assigner = new LeadInAssigner { Sequencer = new LeftSideSequencer() };
|
||||||
|
assigner.Assign(plate);
|
||||||
|
var countAfterFirst = plate.Parts[0].Program.Codes.Count;
|
||||||
|
|
||||||
|
assigner.Assign(plate);
|
||||||
|
var countAfterSecond = plate.Parts[0].Program.Codes.Count;
|
||||||
|
|
||||||
|
Assert.Equal(countAfterFirst, countAfterSecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Assign_PartsContainLeadinLayerCodes()
|
||||||
|
{
|
||||||
|
var plate = new Plate(60, 120);
|
||||||
|
plate.Parts.Add(MakeSquarePartAt(10, 10));
|
||||||
|
plate.CuttingParameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
var assigner = new LeadInAssigner { Sequencer = new LeftSideSequencer() };
|
||||||
|
assigner.Assign(plate);
|
||||||
|
|
||||||
|
var hasLeadin = plate.Parts[0].Program.Codes.OfType<LinearMove>().Any(m => m.Layer == LayerType.Leadin);
|
||||||
|
Assert.True(hasLeadin);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
using OpenNest.CNC;
|
||||||
|
using OpenNest.CNC.CuttingStrategy;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.Tests;
|
||||||
|
|
||||||
|
public class LeadInLayerTagTests
|
||||||
|
{
|
||||||
|
private static readonly Vector Point = new(5, 5);
|
||||||
|
private const double Normal = 0.0;
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LineLeadIn_SetsLeadinLayer()
|
||||||
|
{
|
||||||
|
var leadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 };
|
||||||
|
var codes = leadIn.Generate(Point, Normal);
|
||||||
|
var linear = codes.OfType<LinearMove>().Single();
|
||||||
|
Assert.Equal(LayerType.Leadin, linear.Layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ArcLeadIn_SetsLeadinLayer()
|
||||||
|
{
|
||||||
|
var leadIn = new ArcLeadIn { Radius = 0.25 };
|
||||||
|
var codes = leadIn.Generate(Point, Normal);
|
||||||
|
var arc = codes.OfType<ArcMove>().Single();
|
||||||
|
Assert.Equal(LayerType.Leadin, arc.Layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LineArcLeadIn_SetsLeadinLayerOnAllMoves()
|
||||||
|
{
|
||||||
|
var leadIn = new LineArcLeadIn { LineLength = 0.5, ArcRadius = 0.25, ApproachAngle = 135 };
|
||||||
|
var codes = leadIn.Generate(Point, Normal);
|
||||||
|
Assert.All(codes.OfType<LinearMove>(), m => Assert.Equal(LayerType.Leadin, m.Layer));
|
||||||
|
Assert.All(codes.OfType<ArcMove>(), m => Assert.Equal(LayerType.Leadin, m.Layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CleanHoleLeadIn_SetsLeadinLayerOnAllMoves()
|
||||||
|
{
|
||||||
|
var leadIn = new CleanHoleLeadIn { LineLength = 0.5, ArcRadius = 0.25, Kerf = 0.05 };
|
||||||
|
var codes = leadIn.Generate(Point, Normal);
|
||||||
|
Assert.All(codes.OfType<LinearMove>(), m => Assert.Equal(LayerType.Leadin, m.Layer));
|
||||||
|
Assert.All(codes.OfType<ArcMove>(), m => Assert.Equal(LayerType.Leadin, m.Layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LineLineLeadIn_SetsLeadinLayerOnAllMoves()
|
||||||
|
{
|
||||||
|
var leadIn = new LineLineLeadIn { Length1 = 0.5, Length2 = 0.3, ApproachAngle1 = 90, ApproachAngle2 = 90 };
|
||||||
|
var codes = leadIn.Generate(Point, Normal);
|
||||||
|
Assert.All(codes.OfType<LinearMove>(), m => Assert.Equal(LayerType.Leadin, m.Layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NoLeadIn_NoLinearOrArcMoves()
|
||||||
|
{
|
||||||
|
var leadIn = new NoLeadIn();
|
||||||
|
var codes = leadIn.Generate(Point, Normal);
|
||||||
|
Assert.Empty(codes.OfType<LinearMove>());
|
||||||
|
Assert.Empty(codes.OfType<ArcMove>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LineLeadOut_SetsLeadoutLayer()
|
||||||
|
{
|
||||||
|
var leadOut = new LineLeadOut { Length = 0.5, ApproachAngle = 90 };
|
||||||
|
var codes = leadOut.Generate(Point, Normal);
|
||||||
|
var linear = codes.OfType<LinearMove>().Single();
|
||||||
|
Assert.Equal(LayerType.Leadout, linear.Layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ArcLeadOut_SetsLeadoutLayer()
|
||||||
|
{
|
||||||
|
var leadOut = new ArcLeadOut { Radius = 0.25 };
|
||||||
|
var codes = leadOut.Generate(Point, Normal);
|
||||||
|
var arc = codes.OfType<ArcMove>().Single();
|
||||||
|
Assert.Equal(LayerType.Leadout, arc.Layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NoLeadOut_ReturnsEmptyList()
|
||||||
|
{
|
||||||
|
var leadOut = new NoLeadOut();
|
||||||
|
var codes = leadOut.Generate(Point, Normal);
|
||||||
|
Assert.Empty(codes);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using OpenNest.CNC;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.Tests;
|
||||||
|
|
||||||
|
public class MotionSuppressedTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void LinearMove_Suppressed_DefaultsFalse()
|
||||||
|
{
|
||||||
|
var move = new LinearMove(new Vector(1, 2));
|
||||||
|
Assert.False(move.Suppressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ArcMove_Suppressed_DefaultsFalse()
|
||||||
|
{
|
||||||
|
var move = new ArcMove(new Vector(1, 2), new Vector(0, 0));
|
||||||
|
Assert.False(move.Suppressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RapidMove_Suppressed_DefaultsFalse()
|
||||||
|
{
|
||||||
|
var move = new RapidMove(new Vector(1, 2));
|
||||||
|
Assert.False(move.Suppressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Suppressed_CanBeSet()
|
||||||
|
{
|
||||||
|
var move = new LinearMove(new Vector(1, 2));
|
||||||
|
move.Suppressed = true;
|
||||||
|
Assert.True(move.Suppressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Clone_PreservesSuppressed()
|
||||||
|
{
|
||||||
|
var move = new LinearMove(new Vector(1, 2));
|
||||||
|
move.Suppressed = true;
|
||||||
|
var clone = (LinearMove)move.Clone();
|
||||||
|
Assert.True(clone.Suppressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
using OpenNest.CNC;
|
||||||
|
using OpenNest.CNC.CuttingStrategy;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
|
||||||
|
namespace OpenNest.Tests;
|
||||||
|
|
||||||
|
public class PartLeadInTests
|
||||||
|
{
|
||||||
|
private static Part MakeSquarePart()
|
||||||
|
{
|
||||||
|
var pgm = new Program();
|
||||||
|
pgm.Codes.Add(new RapidMove(new Vector(0, 0)));
|
||||||
|
pgm.Codes.Add(new LinearMove(new Vector(0, 10)));
|
||||||
|
pgm.Codes.Add(new LinearMove(new Vector(10, 10)));
|
||||||
|
pgm.Codes.Add(new LinearMove(new Vector(10, 0)));
|
||||||
|
pgm.Codes.Add(new LinearMove(new Vector(0, 0)));
|
||||||
|
var drawing = new Drawing("test", pgm);
|
||||||
|
return new Part(drawing);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ApplyLeadIns_SetsHasManualLeadIns()
|
||||||
|
{
|
||||||
|
var part = MakeSquarePart();
|
||||||
|
var parameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 },
|
||||||
|
InternalLeadIn = new LineLeadIn { Length = 0.25, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
part.ApplyLeadIns(parameters, new Vector(-5, -5));
|
||||||
|
|
||||||
|
Assert.True(part.HasManualLeadIns);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ApplyLeadIns_StoresCuttingParameters()
|
||||||
|
{
|
||||||
|
var part = MakeSquarePart();
|
||||||
|
var parameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 },
|
||||||
|
InternalLeadIn = new LineLeadIn { Length = 0.25, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
part.ApplyLeadIns(parameters, new Vector(-5, -5));
|
||||||
|
|
||||||
|
Assert.Same(parameters, part.CuttingParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ApplyLeadIns_ProgramContainsLeadinCodes()
|
||||||
|
{
|
||||||
|
var part = MakeSquarePart();
|
||||||
|
var parameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
part.ApplyLeadIns(parameters, new Vector(-5, -5));
|
||||||
|
|
||||||
|
var hasLeadin = part.Program.Codes.OfType<LinearMove>().Any(m => m.Layer == LayerType.Leadin);
|
||||||
|
Assert.True(hasLeadin);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveLeadIns_RestoresOriginalProgram()
|
||||||
|
{
|
||||||
|
var part = MakeSquarePart();
|
||||||
|
var originalCodeCount = part.Program.Codes.Count;
|
||||||
|
var parameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
part.ApplyLeadIns(parameters, new Vector(-5, -5));
|
||||||
|
part.RemoveLeadIns();
|
||||||
|
|
||||||
|
Assert.False(part.HasManualLeadIns);
|
||||||
|
Assert.Null(part.CuttingParameters);
|
||||||
|
Assert.Equal(originalCodeCount, part.Program.Codes.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveLeadIns_PreservesRotation()
|
||||||
|
{
|
||||||
|
var part = MakeSquarePart();
|
||||||
|
part.Rotate(System.Math.PI / 4); // 45 degrees
|
||||||
|
var rotation = part.Rotation;
|
||||||
|
|
||||||
|
var parameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
part.ApplyLeadIns(parameters, new Vector(-5, -5));
|
||||||
|
part.RemoveLeadIns();
|
||||||
|
|
||||||
|
Assert.Equal(rotation, part.Rotation, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveLeadIns_PreservesLocation()
|
||||||
|
{
|
||||||
|
var part = MakeSquarePart();
|
||||||
|
part.Offset(20, 30);
|
||||||
|
var location = part.Location;
|
||||||
|
|
||||||
|
var parameters = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = new LineLeadIn { Length = 0.5, ApproachAngle = 90 }
|
||||||
|
};
|
||||||
|
|
||||||
|
part.ApplyLeadIns(parameters, new Vector(-5, -5));
|
||||||
|
part.RemoveLeadIns();
|
||||||
|
|
||||||
|
Assert.Equal(location.X, part.Location.X, 6);
|
||||||
|
Assert.Equal(location.Y, part.Location.Y, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LeadInsLocked_DefaultsFalse()
|
||||||
|
{
|
||||||
|
var part = MakeSquarePart();
|
||||||
|
Assert.False(part.LeadInsLocked);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,330 @@
|
|||||||
|
using OpenNest.CNC.CuttingStrategy;
|
||||||
|
using OpenNest.Controls;
|
||||||
|
using OpenNest.Converters;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace OpenNest.Actions
|
||||||
|
{
|
||||||
|
[DisplayName("Place Lead-in")]
|
||||||
|
public class ActionLeadIn : Action
|
||||||
|
{
|
||||||
|
private LayoutPart selectedLayoutPart;
|
||||||
|
private Part selectedPart;
|
||||||
|
private ShapeProfile profile;
|
||||||
|
private List<ShapeInfo> contours;
|
||||||
|
private Vector snapPoint;
|
||||||
|
private Entity snapEntity;
|
||||||
|
private ContourType snapContourType;
|
||||||
|
private double snapNormal;
|
||||||
|
private bool hasSnap;
|
||||||
|
private ContextMenuStrip contextMenu;
|
||||||
|
|
||||||
|
public ActionLeadIn(PlateView plateView)
|
||||||
|
: base(plateView)
|
||||||
|
{
|
||||||
|
ConnectEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ConnectEvents()
|
||||||
|
{
|
||||||
|
plateView.MouseMove += OnMouseMove;
|
||||||
|
plateView.MouseDown += OnMouseDown;
|
||||||
|
plateView.KeyDown += OnKeyDown;
|
||||||
|
plateView.Paint += OnPaint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DisconnectEvents()
|
||||||
|
{
|
||||||
|
plateView.MouseMove -= OnMouseMove;
|
||||||
|
plateView.MouseDown -= OnMouseDown;
|
||||||
|
plateView.KeyDown -= OnKeyDown;
|
||||||
|
plateView.Paint -= OnPaint;
|
||||||
|
|
||||||
|
contextMenu?.Dispose();
|
||||||
|
contextMenu = null;
|
||||||
|
|
||||||
|
selectedLayoutPart = null;
|
||||||
|
selectedPart = null;
|
||||||
|
profile = null;
|
||||||
|
contours = null;
|
||||||
|
hasSnap = false;
|
||||||
|
plateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CancelAction() { }
|
||||||
|
|
||||||
|
public override bool IsBusy() => selectedPart != null;
|
||||||
|
|
||||||
|
private void OnMouseMove(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (selectedPart == null || contours == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var worldPt = plateView.CurrentPoint;
|
||||||
|
|
||||||
|
// Transform world point into program-local space by subtracting the
|
||||||
|
// part's location. The contour shapes are already in the program's
|
||||||
|
// rotated coordinate system, so no additional un-rotation is needed.
|
||||||
|
var localPt = new Vector(worldPt.X - selectedPart.Location.X,
|
||||||
|
worldPt.Y - selectedPart.Location.Y);
|
||||||
|
|
||||||
|
// Find closest contour and point
|
||||||
|
var bestDist = double.MaxValue;
|
||||||
|
hasSnap = false;
|
||||||
|
|
||||||
|
foreach (var info in contours)
|
||||||
|
{
|
||||||
|
var closest = info.Shape.ClosestPointTo(localPt, out var entity);
|
||||||
|
var dist = closest.DistanceTo(localPt);
|
||||||
|
|
||||||
|
if (dist < bestDist)
|
||||||
|
{
|
||||||
|
bestDist = dist;
|
||||||
|
snapPoint = closest;
|
||||||
|
snapEntity = entity;
|
||||||
|
snapContourType = info.ContourType;
|
||||||
|
snapNormal = ContourCuttingStrategy.ComputeNormal(closest, entity, info.ContourType);
|
||||||
|
hasSnap = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMouseDown(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Button == MouseButtons.Left)
|
||||||
|
{
|
||||||
|
if (selectedPart == null)
|
||||||
|
{
|
||||||
|
// First click: select a part
|
||||||
|
SelectPartAtCursor();
|
||||||
|
}
|
||||||
|
else if (hasSnap)
|
||||||
|
{
|
||||||
|
// Second click: commit lead-in at snap point
|
||||||
|
CommitLeadIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (e.Button == MouseButtons.Right)
|
||||||
|
{
|
||||||
|
if (selectedPart != null && selectedPart.HasManualLeadIns)
|
||||||
|
ShowContextMenu(e.Location);
|
||||||
|
else
|
||||||
|
DeselectPart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnKeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.KeyCode == Keys.Escape)
|
||||||
|
{
|
||||||
|
if (selectedPart != null)
|
||||||
|
DeselectPart();
|
||||||
|
else
|
||||||
|
plateView.SetAction(typeof(ActionSelect));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPaint(object sender, PaintEventArgs e)
|
||||||
|
{
|
||||||
|
if (!hasSnap || selectedPart == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var parameters = plateView.Plate?.CuttingParameters;
|
||||||
|
if (parameters == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Transform snap point from local part space to world space
|
||||||
|
var worldSnap = TransformToWorld(snapPoint);
|
||||||
|
|
||||||
|
// Get the appropriate lead-in for this contour type
|
||||||
|
var leadIn = SelectLeadIn(parameters, snapContourType);
|
||||||
|
if (leadIn == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the pierce point (in local space)
|
||||||
|
var piercePoint = leadIn.GetPiercePoint(snapPoint, snapNormal);
|
||||||
|
var worldPierce = TransformToWorld(piercePoint);
|
||||||
|
|
||||||
|
var g = e.Graphics;
|
||||||
|
var oldSmooth = g.SmoothingMode;
|
||||||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
|
||||||
|
// Draw the lead-in preview as a line from pierce point to contour point
|
||||||
|
var pt1 = plateView.PointWorldToGraph(worldPierce);
|
||||||
|
var pt2 = plateView.PointWorldToGraph(worldSnap);
|
||||||
|
|
||||||
|
using var pen = new Pen(Color.Yellow, 2.0f / plateView.ViewScale);
|
||||||
|
g.DrawLine(pen, pt1, pt2);
|
||||||
|
|
||||||
|
// Draw a small circle at the pierce point
|
||||||
|
var radius = 3.0f / plateView.ViewScale;
|
||||||
|
g.FillEllipse(Brushes.Yellow, pt1.X - radius, pt1.Y - radius, radius * 2, radius * 2);
|
||||||
|
|
||||||
|
// Draw a small circle at the contour start point
|
||||||
|
g.FillEllipse(Brushes.Lime, pt2.X - radius, pt2.Y - radius, radius * 2, radius * 2);
|
||||||
|
|
||||||
|
g.SmoothingMode = oldSmooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectPartAtCursor()
|
||||||
|
{
|
||||||
|
var layoutPart = plateView.GetPartAtPoint(plateView.CurrentPoint);
|
||||||
|
if (layoutPart == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var part = layoutPart.BasePart;
|
||||||
|
|
||||||
|
// Don't allow lead-in placement on cut-off parts
|
||||||
|
if (part.BaseDrawing.IsCutOff)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If part already has locked lead-ins, don't allow re-placement
|
||||||
|
if (part.LeadInsLocked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
selectedLayoutPart = layoutPart;
|
||||||
|
selectedPart = part;
|
||||||
|
|
||||||
|
// Build contour info from the part's program geometry
|
||||||
|
BuildContourInfo();
|
||||||
|
|
||||||
|
// Highlight the selected part
|
||||||
|
layoutPart.IsSelected = true;
|
||||||
|
plateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildContourInfo()
|
||||||
|
{
|
||||||
|
// Get a clean program (no lead-ins) in the part's current rotated space.
|
||||||
|
// If the part has manual lead-ins, rebuild from base drawing + rotation.
|
||||||
|
// Otherwise the current Program is already clean and rotated.
|
||||||
|
CNC.Program cleanProgram;
|
||||||
|
|
||||||
|
if (selectedPart.HasManualLeadIns)
|
||||||
|
{
|
||||||
|
cleanProgram = selectedPart.BaseDrawing.Program.Clone() as CNC.Program;
|
||||||
|
if (!OpenNest.Math.Tolerance.IsEqualTo(selectedPart.Rotation, 0))
|
||||||
|
cleanProgram.Rotate(selectedPart.Rotation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cleanProgram = selectedPart.Program;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entities = ConvertProgram.ToGeometry(cleanProgram);
|
||||||
|
profile = new ShapeProfile(entities);
|
||||||
|
|
||||||
|
contours = new List<ShapeInfo>();
|
||||||
|
|
||||||
|
// Perimeter is always External
|
||||||
|
if (profile.Perimeter != null)
|
||||||
|
{
|
||||||
|
contours.Add(new ShapeInfo
|
||||||
|
{
|
||||||
|
Shape = profile.Perimeter,
|
||||||
|
ContourType = ContourType.External
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cutouts
|
||||||
|
foreach (var cutout in profile.Cutouts)
|
||||||
|
{
|
||||||
|
contours.Add(new ShapeInfo
|
||||||
|
{
|
||||||
|
Shape = cutout,
|
||||||
|
ContourType = ContourCuttingStrategy.DetectContourType(cutout)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CommitLeadIn()
|
||||||
|
{
|
||||||
|
var parameters = plateView.Plate?.CuttingParameters;
|
||||||
|
if (parameters == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Remove any existing lead-ins first
|
||||||
|
if (selectedPart.HasManualLeadIns)
|
||||||
|
selectedPart.RemoveLeadIns();
|
||||||
|
|
||||||
|
// Apply lead-ins using the snap point as the approach point.
|
||||||
|
// snapPoint is in the program's local coordinate space (rotated, not offset),
|
||||||
|
// which is what Part.ApplyLeadIns expects.
|
||||||
|
selectedPart.ApplyLeadIns(parameters, snapPoint);
|
||||||
|
selectedPart.LeadInsLocked = true;
|
||||||
|
|
||||||
|
// Rebuild the layout part's graphics
|
||||||
|
selectedLayoutPart.IsDirty = true;
|
||||||
|
selectedLayoutPart.Update();
|
||||||
|
|
||||||
|
// Deselect and reset
|
||||||
|
DeselectPart();
|
||||||
|
plateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeselectPart()
|
||||||
|
{
|
||||||
|
if (selectedLayoutPart != null)
|
||||||
|
{
|
||||||
|
selectedLayoutPart.IsSelected = false;
|
||||||
|
selectedLayoutPart = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedPart = null;
|
||||||
|
profile = null;
|
||||||
|
contours = null;
|
||||||
|
hasSnap = false;
|
||||||
|
plateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowContextMenu(Point location)
|
||||||
|
{
|
||||||
|
contextMenu?.Dispose();
|
||||||
|
contextMenu = new ContextMenuStrip();
|
||||||
|
|
||||||
|
var removeItem = new ToolStripMenuItem("Remove All Lead-ins");
|
||||||
|
removeItem.Click += (s, e) =>
|
||||||
|
{
|
||||||
|
selectedPart.RemoveLeadIns();
|
||||||
|
selectedLayoutPart.IsDirty = true;
|
||||||
|
selectedLayoutPart.Update();
|
||||||
|
DeselectPart();
|
||||||
|
plateView.Invalidate();
|
||||||
|
};
|
||||||
|
|
||||||
|
contextMenu.Items.Add(removeItem);
|
||||||
|
contextMenu.Show(plateView, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector TransformToWorld(Vector localPt)
|
||||||
|
{
|
||||||
|
// The contours are already in rotated local space (we rotated the program
|
||||||
|
// before building the profile), so just add the part location offset
|
||||||
|
return new Vector(localPt.X + selectedPart.Location.X,
|
||||||
|
localPt.Y + selectedPart.Location.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LeadIn SelectLeadIn(CuttingParameters parameters, ContourType contourType)
|
||||||
|
{
|
||||||
|
return contourType switch
|
||||||
|
{
|
||||||
|
ContourType.ArcCircle => parameters.ArcCircleLeadIn ?? parameters.InternalLeadIn,
|
||||||
|
ContourType.Internal => parameters.InternalLeadIn,
|
||||||
|
_ => parameters.ExternalLeadIn
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ShapeInfo
|
||||||
|
{
|
||||||
|
public Shape Shape { get; set; }
|
||||||
|
public ContourType ContourType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+156
@@ -0,0 +1,156 @@
|
|||||||
|
namespace OpenNest.Forms
|
||||||
|
{
|
||||||
|
partial class CuttingParametersForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.tabControl = new System.Windows.Forms.TabControl();
|
||||||
|
this.tabExternal = new System.Windows.Forms.TabPage();
|
||||||
|
this.tabInternal = new System.Windows.Forms.TabPage();
|
||||||
|
this.tabArcCircle = new System.Windows.Forms.TabPage();
|
||||||
|
this.acceptButton = new System.Windows.Forms.Button();
|
||||||
|
this.cancelButton = new System.Windows.Forms.Button();
|
||||||
|
this.bottomPanel = new OpenNest.Controls.BottomPanel();
|
||||||
|
this.tabControl.SuspendLayout();
|
||||||
|
this.bottomPanel.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// tabControl
|
||||||
|
//
|
||||||
|
this.tabControl.Controls.Add(this.tabExternal);
|
||||||
|
this.tabControl.Controls.Add(this.tabInternal);
|
||||||
|
this.tabControl.Controls.Add(this.tabArcCircle);
|
||||||
|
this.tabControl.Dock = System.Windows.Forms.DockStyle.Top;
|
||||||
|
this.tabControl.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.tabControl.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.tabControl.Name = "tabControl";
|
||||||
|
this.tabControl.SelectedIndex = 0;
|
||||||
|
this.tabControl.Size = new System.Drawing.Size(380, 348);
|
||||||
|
this.tabControl.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// tabExternal
|
||||||
|
//
|
||||||
|
this.tabExternal.Location = new System.Drawing.Point(4, 25);
|
||||||
|
this.tabExternal.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.tabExternal.Name = "tabExternal";
|
||||||
|
this.tabExternal.Padding = new System.Windows.Forms.Padding(8);
|
||||||
|
this.tabExternal.Size = new System.Drawing.Size(372, 319);
|
||||||
|
this.tabExternal.TabIndex = 0;
|
||||||
|
this.tabExternal.Text = "External";
|
||||||
|
this.tabExternal.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// tabInternal
|
||||||
|
//
|
||||||
|
this.tabInternal.Location = new System.Drawing.Point(4, 25);
|
||||||
|
this.tabInternal.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.tabInternal.Name = "tabInternal";
|
||||||
|
this.tabInternal.Padding = new System.Windows.Forms.Padding(8);
|
||||||
|
this.tabInternal.Size = new System.Drawing.Size(372, 319);
|
||||||
|
this.tabInternal.TabIndex = 1;
|
||||||
|
this.tabInternal.Text = "Internal";
|
||||||
|
this.tabInternal.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// tabArcCircle
|
||||||
|
//
|
||||||
|
this.tabArcCircle.Location = new System.Drawing.Point(4, 25);
|
||||||
|
this.tabArcCircle.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.tabArcCircle.Name = "tabArcCircle";
|
||||||
|
this.tabArcCircle.Padding = new System.Windows.Forms.Padding(8);
|
||||||
|
this.tabArcCircle.Size = new System.Drawing.Size(372, 319);
|
||||||
|
this.tabArcCircle.TabIndex = 2;
|
||||||
|
this.tabArcCircle.Text = "Arc / Circle";
|
||||||
|
this.tabArcCircle.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// acceptButton
|
||||||
|
//
|
||||||
|
this.acceptButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.acceptButton.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||||
|
this.acceptButton.Location = new System.Drawing.Point(165, 11);
|
||||||
|
this.acceptButton.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.acceptButton.Name = "acceptButton";
|
||||||
|
this.acceptButton.Size = new System.Drawing.Size(90, 28);
|
||||||
|
this.acceptButton.TabIndex = 8;
|
||||||
|
this.acceptButton.Text = "OK";
|
||||||
|
this.acceptButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// cancelButton
|
||||||
|
//
|
||||||
|
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||||
|
this.cancelButton.Location = new System.Drawing.Point(263, 11);
|
||||||
|
this.cancelButton.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.cancelButton.Name = "cancelButton";
|
||||||
|
this.cancelButton.Size = new System.Drawing.Size(90, 28);
|
||||||
|
this.cancelButton.TabIndex = 9;
|
||||||
|
this.cancelButton.Text = "Cancel";
|
||||||
|
this.cancelButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// bottomPanel
|
||||||
|
//
|
||||||
|
this.bottomPanel.Controls.Add(this.acceptButton);
|
||||||
|
this.bottomPanel.Controls.Add(this.cancelButton);
|
||||||
|
this.bottomPanel.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
|
this.bottomPanel.Location = new System.Drawing.Point(0, 406);
|
||||||
|
this.bottomPanel.Name = "bottomPanel";
|
||||||
|
this.bottomPanel.Size = new System.Drawing.Size(380, 50);
|
||||||
|
this.bottomPanel.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// CuttingParametersForm
|
||||||
|
//
|
||||||
|
this.AcceptButton = this.acceptButton;
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.CancelButton = this.cancelButton;
|
||||||
|
this.ClientSize = new System.Drawing.Size(380, 456);
|
||||||
|
this.Controls.Add(this.tabControl);
|
||||||
|
this.Controls.Add(this.bottomPanel);
|
||||||
|
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||||
|
this.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "CuttingParametersForm";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.ShowInTaskbar = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.Text = "Cutting Parameters";
|
||||||
|
this.tabControl.ResumeLayout(false);
|
||||||
|
this.bottomPanel.ResumeLayout(false);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.TabControl tabControl;
|
||||||
|
private System.Windows.Forms.TabPage tabExternal;
|
||||||
|
private System.Windows.Forms.TabPage tabInternal;
|
||||||
|
private System.Windows.Forms.TabPage tabArcCircle;
|
||||||
|
private Controls.BottomPanel bottomPanel;
|
||||||
|
private System.Windows.Forms.Button acceptButton;
|
||||||
|
private System.Windows.Forms.Button cancelButton;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,476 @@
|
|||||||
|
using OpenNest.CNC.CuttingStrategy;
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace OpenNest.Forms
|
||||||
|
{
|
||||||
|
public partial class CuttingParametersForm : Form
|
||||||
|
{
|
||||||
|
private static readonly string[] LeadInTypes =
|
||||||
|
{ "None", "Line", "Arc", "Line + Arc", "Clean Hole", "Line + Line" };
|
||||||
|
|
||||||
|
private static readonly string[] LeadOutTypes =
|
||||||
|
{ "None", "Line", "Arc", "Microtab" };
|
||||||
|
|
||||||
|
private ComboBox cboExternalLeadIn, cboExternalLeadOut;
|
||||||
|
private ComboBox cboInternalLeadIn, cboInternalLeadOut;
|
||||||
|
private ComboBox cboArcCircleLeadIn, cboArcCircleLeadOut;
|
||||||
|
|
||||||
|
private Panel pnlExternalLeadIn, pnlExternalLeadOut;
|
||||||
|
private Panel pnlInternalLeadIn, pnlInternalLeadOut;
|
||||||
|
private Panel pnlArcCircleLeadIn, pnlArcCircleLeadOut;
|
||||||
|
|
||||||
|
private CheckBox chkTabsEnabled;
|
||||||
|
private NumericUpDown nudTabWidth;
|
||||||
|
|
||||||
|
public CuttingParameters Parameters { get; set; } = new CuttingParameters();
|
||||||
|
|
||||||
|
public CuttingParametersForm()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
SetupTab(tabExternal,
|
||||||
|
out cboExternalLeadIn, out pnlExternalLeadIn,
|
||||||
|
out cboExternalLeadOut, out pnlExternalLeadOut);
|
||||||
|
SetupTab(tabInternal,
|
||||||
|
out cboInternalLeadIn, out pnlInternalLeadIn,
|
||||||
|
out cboInternalLeadOut, out pnlInternalLeadOut);
|
||||||
|
SetupTab(tabArcCircle,
|
||||||
|
out cboArcCircleLeadIn, out pnlArcCircleLeadIn,
|
||||||
|
out cboArcCircleLeadOut, out pnlArcCircleLeadOut);
|
||||||
|
|
||||||
|
SetupTabsSection();
|
||||||
|
PopulateDropdowns();
|
||||||
|
|
||||||
|
cboExternalLeadIn.SelectedIndexChanged += OnLeadInTypeChanged;
|
||||||
|
cboInternalLeadIn.SelectedIndexChanged += OnLeadInTypeChanged;
|
||||||
|
cboArcCircleLeadIn.SelectedIndexChanged += OnLeadInTypeChanged;
|
||||||
|
|
||||||
|
cboExternalLeadOut.SelectedIndexChanged += OnLeadOutTypeChanged;
|
||||||
|
cboInternalLeadOut.SelectedIndexChanged += OnLeadOutTypeChanged;
|
||||||
|
cboArcCircleLeadOut.SelectedIndexChanged += OnLeadOutTypeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnLoad(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnLoad(e);
|
||||||
|
LoadFromParameters(Parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetupTab(TabPage tab,
|
||||||
|
out ComboBox leadInCombo, out Panel leadInPanel,
|
||||||
|
out ComboBox leadOutCombo, out Panel leadOutPanel)
|
||||||
|
{
|
||||||
|
var grpLeadIn = new GroupBox
|
||||||
|
{
|
||||||
|
Text = "Lead-In",
|
||||||
|
Location = new System.Drawing.Point(4, 4),
|
||||||
|
Size = new System.Drawing.Size(364, 168)
|
||||||
|
};
|
||||||
|
tab.Controls.Add(grpLeadIn);
|
||||||
|
|
||||||
|
grpLeadIn.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = "Type:",
|
||||||
|
Location = new System.Drawing.Point(8, 22),
|
||||||
|
AutoSize = true
|
||||||
|
});
|
||||||
|
|
||||||
|
leadInCombo = new ComboBox
|
||||||
|
{
|
||||||
|
DropDownStyle = ComboBoxStyle.DropDownList,
|
||||||
|
Location = new System.Drawing.Point(90, 19),
|
||||||
|
Size = new System.Drawing.Size(250, 24)
|
||||||
|
};
|
||||||
|
grpLeadIn.Controls.Add(leadInCombo);
|
||||||
|
|
||||||
|
leadInPanel = new Panel
|
||||||
|
{
|
||||||
|
Location = new System.Drawing.Point(8, 48),
|
||||||
|
Size = new System.Drawing.Size(340, 112),
|
||||||
|
AutoScroll = true
|
||||||
|
};
|
||||||
|
grpLeadIn.Controls.Add(leadInPanel);
|
||||||
|
|
||||||
|
var grpLeadOut = new GroupBox
|
||||||
|
{
|
||||||
|
Text = "Lead-Out",
|
||||||
|
Location = new System.Drawing.Point(4, 176),
|
||||||
|
Size = new System.Drawing.Size(364, 132)
|
||||||
|
};
|
||||||
|
tab.Controls.Add(grpLeadOut);
|
||||||
|
|
||||||
|
grpLeadOut.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = "Type:",
|
||||||
|
Location = new System.Drawing.Point(8, 22),
|
||||||
|
AutoSize = true
|
||||||
|
});
|
||||||
|
|
||||||
|
leadOutCombo = new ComboBox
|
||||||
|
{
|
||||||
|
DropDownStyle = ComboBoxStyle.DropDownList,
|
||||||
|
Location = new System.Drawing.Point(90, 19),
|
||||||
|
Size = new System.Drawing.Size(250, 24)
|
||||||
|
};
|
||||||
|
grpLeadOut.Controls.Add(leadOutCombo);
|
||||||
|
|
||||||
|
leadOutPanel = new Panel
|
||||||
|
{
|
||||||
|
Location = new System.Drawing.Point(8, 48),
|
||||||
|
Size = new System.Drawing.Size(340, 76),
|
||||||
|
AutoScroll = true
|
||||||
|
};
|
||||||
|
grpLeadOut.Controls.Add(leadOutPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupTabsSection()
|
||||||
|
{
|
||||||
|
var grpTabs = new GroupBox
|
||||||
|
{
|
||||||
|
Text = "Tabs",
|
||||||
|
Location = new System.Drawing.Point(4, 350),
|
||||||
|
Size = new System.Drawing.Size(372, 55),
|
||||||
|
Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right
|
||||||
|
};
|
||||||
|
|
||||||
|
chkTabsEnabled = new CheckBox
|
||||||
|
{
|
||||||
|
Text = "Enable Tabs",
|
||||||
|
Location = new System.Drawing.Point(12, 22),
|
||||||
|
AutoSize = true
|
||||||
|
};
|
||||||
|
chkTabsEnabled.CheckedChanged += (s, e) => nudTabWidth.Enabled = chkTabsEnabled.Checked;
|
||||||
|
grpTabs.Controls.Add(chkTabsEnabled);
|
||||||
|
|
||||||
|
grpTabs.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = "Width:",
|
||||||
|
Location = new System.Drawing.Point(160, 23),
|
||||||
|
AutoSize = true
|
||||||
|
});
|
||||||
|
|
||||||
|
nudTabWidth = new NumericUpDown
|
||||||
|
{
|
||||||
|
Location = new System.Drawing.Point(215, 20),
|
||||||
|
Size = new System.Drawing.Size(100, 22),
|
||||||
|
DecimalPlaces = 4,
|
||||||
|
Increment = 0.0625m,
|
||||||
|
Minimum = 0,
|
||||||
|
Maximum = 9999,
|
||||||
|
Value = 0.25m,
|
||||||
|
Enabled = false
|
||||||
|
};
|
||||||
|
grpTabs.Controls.Add(nudTabWidth);
|
||||||
|
|
||||||
|
Controls.Add(grpTabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateDropdowns()
|
||||||
|
{
|
||||||
|
foreach (var combo in new[] { cboExternalLeadIn, cboInternalLeadIn, cboArcCircleLeadIn })
|
||||||
|
{
|
||||||
|
combo.Items.AddRange(LeadInTypes);
|
||||||
|
combo.SelectedIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var combo in new[] { cboExternalLeadOut, cboInternalLeadOut, cboArcCircleLeadOut })
|
||||||
|
{
|
||||||
|
combo.Items.AddRange(LeadOutTypes);
|
||||||
|
combo.SelectedIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLeadInTypeChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var combo = (ComboBox)sender;
|
||||||
|
var panel = GetLeadInPanel(combo);
|
||||||
|
if (panel != null)
|
||||||
|
BuildLeadInParamControls(panel, combo.SelectedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLeadOutTypeChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var combo = (ComboBox)sender;
|
||||||
|
var panel = GetLeadOutPanel(combo);
|
||||||
|
if (panel != null)
|
||||||
|
BuildLeadOutParamControls(panel, combo.SelectedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Panel GetLeadInPanel(ComboBox combo)
|
||||||
|
{
|
||||||
|
if (combo == cboExternalLeadIn) return pnlExternalLeadIn;
|
||||||
|
if (combo == cboInternalLeadIn) return pnlInternalLeadIn;
|
||||||
|
if (combo == cboArcCircleLeadIn) return pnlArcCircleLeadIn;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Panel GetLeadOutPanel(ComboBox combo)
|
||||||
|
{
|
||||||
|
if (combo == cboExternalLeadOut) return pnlExternalLeadOut;
|
||||||
|
if (combo == cboInternalLeadOut) return pnlInternalLeadOut;
|
||||||
|
if (combo == cboArcCircleLeadOut) return pnlArcCircleLeadOut;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void BuildLeadInParamControls(Panel panel, int typeIndex)
|
||||||
|
{
|
||||||
|
panel.Controls.Clear();
|
||||||
|
var y = 0;
|
||||||
|
|
||||||
|
switch (typeIndex)
|
||||||
|
{
|
||||||
|
case 1: // Line
|
||||||
|
AddNumericField(panel, "Length:", 0.25, ref y, "Length");
|
||||||
|
AddNumericField(panel, "Approach Angle:", 90, ref y, "ApproachAngle");
|
||||||
|
break;
|
||||||
|
case 2: // Arc
|
||||||
|
AddNumericField(panel, "Radius:", 0.25, ref y, "Radius");
|
||||||
|
break;
|
||||||
|
case 3: // Line + Arc
|
||||||
|
AddNumericField(panel, "Line Length:", 0.25, ref y, "LineLength");
|
||||||
|
AddNumericField(panel, "Arc Radius:", 0.125, ref y, "ArcRadius");
|
||||||
|
AddNumericField(panel, "Approach Angle:", 135, ref y, "ApproachAngle");
|
||||||
|
break;
|
||||||
|
case 4: // Clean Hole
|
||||||
|
AddNumericField(panel, "Line Length:", 0.25, ref y, "LineLength");
|
||||||
|
AddNumericField(panel, "Arc Radius:", 0.125, ref y, "ArcRadius");
|
||||||
|
AddNumericField(panel, "Kerf:", 0.06, ref y, "Kerf");
|
||||||
|
break;
|
||||||
|
case 5: // Line + Line
|
||||||
|
AddNumericField(panel, "Length 1:", 0.25, ref y, "Length1");
|
||||||
|
AddNumericField(panel, "Angle 1:", 90, ref y, "Angle1");
|
||||||
|
AddNumericField(panel, "Length 2:", 0.25, ref y, "Length2");
|
||||||
|
AddNumericField(panel, "Angle 2:", 90, ref y, "Angle2");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void BuildLeadOutParamControls(Panel panel, int typeIndex)
|
||||||
|
{
|
||||||
|
panel.Controls.Clear();
|
||||||
|
var y = 0;
|
||||||
|
|
||||||
|
switch (typeIndex)
|
||||||
|
{
|
||||||
|
case 1: // Line
|
||||||
|
AddNumericField(panel, "Length:", 0.25, ref y, "Length");
|
||||||
|
AddNumericField(panel, "Approach Angle:", 90, ref y, "ApproachAngle");
|
||||||
|
break;
|
||||||
|
case 2: // Arc
|
||||||
|
AddNumericField(panel, "Radius:", 0.25, ref y, "Radius");
|
||||||
|
break;
|
||||||
|
case 3: // Microtab
|
||||||
|
AddNumericField(panel, "Gap Size:", 0.06, ref y, "GapSize");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddNumericField(Panel panel, string label, double defaultValue,
|
||||||
|
ref int y, string tag)
|
||||||
|
{
|
||||||
|
panel.Controls.Add(new Label
|
||||||
|
{
|
||||||
|
Text = label,
|
||||||
|
Location = new System.Drawing.Point(0, y + 3),
|
||||||
|
AutoSize = true
|
||||||
|
});
|
||||||
|
|
||||||
|
panel.Controls.Add(new NumericUpDown
|
||||||
|
{
|
||||||
|
Location = new System.Drawing.Point(130, y),
|
||||||
|
Size = new System.Drawing.Size(120, 22),
|
||||||
|
DecimalPlaces = 4,
|
||||||
|
Increment = 0.0625m,
|
||||||
|
Minimum = 0,
|
||||||
|
Maximum = 9999,
|
||||||
|
Value = (decimal)defaultValue,
|
||||||
|
Tag = tag
|
||||||
|
});
|
||||||
|
|
||||||
|
y += 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadFromParameters(CuttingParameters p)
|
||||||
|
{
|
||||||
|
LoadLeadIn(cboExternalLeadIn, pnlExternalLeadIn, p.ExternalLeadIn);
|
||||||
|
LoadLeadOut(cboExternalLeadOut, pnlExternalLeadOut, p.ExternalLeadOut);
|
||||||
|
|
||||||
|
LoadLeadIn(cboInternalLeadIn, pnlInternalLeadIn, p.InternalLeadIn);
|
||||||
|
LoadLeadOut(cboInternalLeadOut, pnlInternalLeadOut, p.InternalLeadOut);
|
||||||
|
|
||||||
|
LoadLeadIn(cboArcCircleLeadIn, pnlArcCircleLeadIn, p.ArcCircleLeadIn);
|
||||||
|
LoadLeadOut(cboArcCircleLeadOut, pnlArcCircleLeadOut, p.ArcCircleLeadOut);
|
||||||
|
|
||||||
|
chkTabsEnabled.Checked = p.TabsEnabled;
|
||||||
|
if (p.TabConfig != null)
|
||||||
|
nudTabWidth.Value = (decimal)p.TabConfig.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LoadLeadIn(ComboBox combo, Panel panel, LeadIn leadIn)
|
||||||
|
{
|
||||||
|
switch (leadIn)
|
||||||
|
{
|
||||||
|
case LineLeadIn line:
|
||||||
|
combo.SelectedIndex = 1;
|
||||||
|
SetParam(panel, "Length", line.Length);
|
||||||
|
SetParam(panel, "ApproachAngle", line.ApproachAngle);
|
||||||
|
break;
|
||||||
|
case ArcLeadIn arc:
|
||||||
|
combo.SelectedIndex = 2;
|
||||||
|
SetParam(panel, "Radius", arc.Radius);
|
||||||
|
break;
|
||||||
|
case LineArcLeadIn lineArc:
|
||||||
|
combo.SelectedIndex = 3;
|
||||||
|
SetParam(panel, "LineLength", lineArc.LineLength);
|
||||||
|
SetParam(panel, "ArcRadius", lineArc.ArcRadius);
|
||||||
|
SetParam(panel, "ApproachAngle", lineArc.ApproachAngle);
|
||||||
|
break;
|
||||||
|
case CleanHoleLeadIn cleanHole:
|
||||||
|
combo.SelectedIndex = 4;
|
||||||
|
SetParam(panel, "LineLength", cleanHole.LineLength);
|
||||||
|
SetParam(panel, "ArcRadius", cleanHole.ArcRadius);
|
||||||
|
SetParam(panel, "Kerf", cleanHole.Kerf);
|
||||||
|
break;
|
||||||
|
case LineLineLeadIn lineLine:
|
||||||
|
combo.SelectedIndex = 5;
|
||||||
|
SetParam(panel, "Length1", lineLine.Length1);
|
||||||
|
SetParam(panel, "Angle1", lineLine.ApproachAngle1);
|
||||||
|
SetParam(panel, "Length2", lineLine.Length2);
|
||||||
|
SetParam(panel, "Angle2", lineLine.ApproachAngle2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
combo.SelectedIndex = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LoadLeadOut(ComboBox combo, Panel panel, LeadOut leadOut)
|
||||||
|
{
|
||||||
|
switch (leadOut)
|
||||||
|
{
|
||||||
|
case LineLeadOut line:
|
||||||
|
combo.SelectedIndex = 1;
|
||||||
|
SetParam(panel, "Length", line.Length);
|
||||||
|
SetParam(panel, "ApproachAngle", line.ApproachAngle);
|
||||||
|
break;
|
||||||
|
case ArcLeadOut arc:
|
||||||
|
combo.SelectedIndex = 2;
|
||||||
|
SetParam(panel, "Radius", arc.Radius);
|
||||||
|
break;
|
||||||
|
case MicrotabLeadOut microtab:
|
||||||
|
combo.SelectedIndex = 3;
|
||||||
|
SetParam(panel, "GapSize", microtab.GapSize);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
combo.SelectedIndex = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CuttingParameters BuildParameters()
|
||||||
|
{
|
||||||
|
var p = new CuttingParameters
|
||||||
|
{
|
||||||
|
ExternalLeadIn = BuildLeadIn(cboExternalLeadIn, pnlExternalLeadIn),
|
||||||
|
ExternalLeadOut = BuildLeadOut(cboExternalLeadOut, pnlExternalLeadOut),
|
||||||
|
InternalLeadIn = BuildLeadIn(cboInternalLeadIn, pnlInternalLeadIn),
|
||||||
|
InternalLeadOut = BuildLeadOut(cboInternalLeadOut, pnlInternalLeadOut),
|
||||||
|
ArcCircleLeadIn = BuildLeadIn(cboArcCircleLeadIn, pnlArcCircleLeadIn),
|
||||||
|
ArcCircleLeadOut = BuildLeadOut(cboArcCircleLeadOut, pnlArcCircleLeadOut),
|
||||||
|
TabsEnabled = chkTabsEnabled.Checked,
|
||||||
|
TabConfig = new NormalTab { Size = (double)nudTabWidth.Value }
|
||||||
|
};
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LeadIn BuildLeadIn(ComboBox combo, Panel panel)
|
||||||
|
{
|
||||||
|
switch (combo.SelectedIndex)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return new LineLeadIn
|
||||||
|
{
|
||||||
|
Length = GetParam(panel, "Length", 0.25),
|
||||||
|
ApproachAngle = GetParam(panel, "ApproachAngle", 90)
|
||||||
|
};
|
||||||
|
case 2:
|
||||||
|
return new ArcLeadIn
|
||||||
|
{
|
||||||
|
Radius = GetParam(panel, "Radius", 0.25)
|
||||||
|
};
|
||||||
|
case 3:
|
||||||
|
return new LineArcLeadIn
|
||||||
|
{
|
||||||
|
LineLength = GetParam(panel, "LineLength", 0.25),
|
||||||
|
ArcRadius = GetParam(panel, "ArcRadius", 0.125),
|
||||||
|
ApproachAngle = GetParam(panel, "ApproachAngle", 135)
|
||||||
|
};
|
||||||
|
case 4:
|
||||||
|
return new CleanHoleLeadIn
|
||||||
|
{
|
||||||
|
LineLength = GetParam(panel, "LineLength", 0.25),
|
||||||
|
ArcRadius = GetParam(panel, "ArcRadius", 0.125),
|
||||||
|
Kerf = GetParam(panel, "Kerf", 0.06)
|
||||||
|
};
|
||||||
|
case 5:
|
||||||
|
return new LineLineLeadIn
|
||||||
|
{
|
||||||
|
Length1 = GetParam(panel, "Length1", 0.25),
|
||||||
|
ApproachAngle1 = GetParam(panel, "Angle1", 90),
|
||||||
|
Length2 = GetParam(panel, "Length2", 0.25),
|
||||||
|
ApproachAngle2 = GetParam(panel, "Angle2", 90)
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return new NoLeadIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LeadOut BuildLeadOut(ComboBox combo, Panel panel)
|
||||||
|
{
|
||||||
|
switch (combo.SelectedIndex)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return new LineLeadOut
|
||||||
|
{
|
||||||
|
Length = GetParam(panel, "Length", 0.25),
|
||||||
|
ApproachAngle = GetParam(panel, "ApproachAngle", 90)
|
||||||
|
};
|
||||||
|
case 2:
|
||||||
|
return new ArcLeadOut
|
||||||
|
{
|
||||||
|
Radius = GetParam(panel, "Radius", 0.25)
|
||||||
|
};
|
||||||
|
case 3:
|
||||||
|
return new MicrotabLeadOut
|
||||||
|
{
|
||||||
|
GapSize = GetParam(panel, "GapSize", 0.06)
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return new NoLeadOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetParam(Panel panel, string tag, double value)
|
||||||
|
{
|
||||||
|
foreach (Control c in panel.Controls)
|
||||||
|
{
|
||||||
|
if (c is NumericUpDown nud && (string)nud.Tag == tag)
|
||||||
|
{
|
||||||
|
nud.Value = (decimal)value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double GetParam(Panel panel, string tag, double defaultValue)
|
||||||
|
{
|
||||||
|
foreach (Control c in panel.Controls)
|
||||||
|
{
|
||||||
|
if (c is NumericUpDown nud && (string)nud.Tag == tag)
|
||||||
|
return (double)nud.Value;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+25
-1
@@ -38,6 +38,8 @@
|
|||||||
this.qtyColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
this.qtyColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
|
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
|
||||||
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
|
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
|
||||||
|
this.btnAssignLeadIns = new System.Windows.Forms.ToolStripButton();
|
||||||
|
this.btnPlaceLeadIn = new System.Windows.Forms.ToolStripButton();
|
||||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||||
this.drawingListBox1 = new OpenNest.Controls.DrawingListBox();
|
this.drawingListBox1 = new OpenNest.Controls.DrawingListBox();
|
||||||
this.toolStrip2 = new System.Windows.Forms.ToolStrip();
|
this.toolStrip2 = new System.Windows.Forms.ToolStrip();
|
||||||
@@ -133,7 +135,9 @@
|
|||||||
this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
|
this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
|
||||||
this.toolStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
|
this.toolStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||||
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
this.toolStripButton1});
|
this.toolStripButton1,
|
||||||
|
this.btnAssignLeadIns,
|
||||||
|
this.btnPlaceLeadIn});
|
||||||
this.toolStrip1.Location = new System.Drawing.Point(3, 3);
|
this.toolStrip1.Location = new System.Drawing.Point(3, 3);
|
||||||
this.toolStrip1.Name = "toolStrip1";
|
this.toolStrip1.Name = "toolStrip1";
|
||||||
this.toolStrip1.Size = new System.Drawing.Size(227, 31);
|
this.toolStrip1.Size = new System.Drawing.Size(227, 31);
|
||||||
@@ -152,6 +156,24 @@
|
|||||||
this.toolStripButton1.Text = "Calculate Cut Time";
|
this.toolStripButton1.Text = "Calculate Cut Time";
|
||||||
this.toolStripButton1.Click += new System.EventHandler(this.CalculateSelectedPlateCutTime_Click);
|
this.toolStripButton1.Click += new System.EventHandler(this.CalculateSelectedPlateCutTime_Click);
|
||||||
//
|
//
|
||||||
|
// btnAssignLeadIns
|
||||||
|
//
|
||||||
|
this.btnAssignLeadIns.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||||
|
this.btnAssignLeadIns.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||||
|
this.btnAssignLeadIns.Name = "btnAssignLeadIns";
|
||||||
|
this.btnAssignLeadIns.Size = new System.Drawing.Size(96, 28);
|
||||||
|
this.btnAssignLeadIns.Text = "Assign Lead-ins";
|
||||||
|
this.btnAssignLeadIns.Click += new System.EventHandler(this.AssignLeadIns_Click);
|
||||||
|
//
|
||||||
|
// btnPlaceLeadIn
|
||||||
|
//
|
||||||
|
this.btnPlaceLeadIn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||||
|
this.btnPlaceLeadIn.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||||
|
this.btnPlaceLeadIn.Name = "btnPlaceLeadIn";
|
||||||
|
this.btnPlaceLeadIn.Size = new System.Drawing.Size(90, 28);
|
||||||
|
this.btnPlaceLeadIn.Text = "Place Lead-in";
|
||||||
|
this.btnPlaceLeadIn.Click += new System.EventHandler(this.PlaceLeadIn_Click);
|
||||||
|
//
|
||||||
// tabPage2
|
// tabPage2
|
||||||
//
|
//
|
||||||
this.tabPage2.Controls.Add(this.drawingListBox1);
|
this.tabPage2.Controls.Add(this.drawingListBox1);
|
||||||
@@ -266,5 +288,7 @@
|
|||||||
private System.Windows.Forms.ToolStripButton toolStripButton2;
|
private System.Windows.Forms.ToolStripButton toolStripButton2;
|
||||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||||
private System.Windows.Forms.ToolStripButton toolStripButton3;
|
private System.Windows.Forms.ToolStripButton toolStripButton3;
|
||||||
|
private System.Windows.Forms.ToolStripButton btnAssignLeadIns;
|
||||||
|
private System.Windows.Forms.ToolStripButton btnPlaceLeadIn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using OpenNest.CNC.CuttingStrategy;
|
using OpenNest.CNC.CuttingStrategy;
|
||||||
using OpenNest.Collections;
|
using OpenNest.Collections;
|
||||||
using OpenNest.Controls;
|
using OpenNest.Controls;
|
||||||
|
using OpenNest.Engine;
|
||||||
using OpenNest.Engine.Sequencing;
|
using OpenNest.Engine.Sequencing;
|
||||||
using OpenNest.IO;
|
using OpenNest.IO;
|
||||||
using OpenNest.Math;
|
using OpenNest.Math;
|
||||||
@@ -711,6 +712,52 @@ namespace OpenNest.Forms
|
|||||||
CalculateCurrentPlateCutTime();
|
CalculateCurrentPlateCutTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AssignLeadIns_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (PlateView?.Plate == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var plate = PlateView.Plate;
|
||||||
|
|
||||||
|
using var form = new CuttingParametersForm();
|
||||||
|
if (plate.CuttingParameters != null)
|
||||||
|
form.Parameters = plate.CuttingParameters;
|
||||||
|
|
||||||
|
if (form.ShowDialog(this) != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var parameters = form.BuildParameters();
|
||||||
|
plate.CuttingParameters = parameters;
|
||||||
|
|
||||||
|
var assigner = new LeadInAssigner
|
||||||
|
{
|
||||||
|
Sequencer = new LeftSideSequencer()
|
||||||
|
};
|
||||||
|
assigner.Assign(plate);
|
||||||
|
|
||||||
|
PlateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PlaceLeadIn_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (PlateView?.Plate == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var plate = PlateView.Plate;
|
||||||
|
|
||||||
|
// Ensure cutting parameters are configured
|
||||||
|
if (plate.CuttingParameters == null)
|
||||||
|
{
|
||||||
|
using var form = new CuttingParametersForm();
|
||||||
|
if (form.ShowDialog(this) != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
plate.CuttingParameters = form.BuildParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
PlateView.SetAction(typeof(Actions.ActionLeadIn));
|
||||||
|
}
|
||||||
|
|
||||||
private void ImportDrawings_Click(object sender, EventArgs e)
|
private void ImportDrawings_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Import();
|
Import();
|
||||||
|
|||||||
Generated
+57
-59
@@ -28,77 +28,75 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||||
this.label1 = new System.Windows.Forms.Label();
|
label1 = new System.Windows.Forms.Label();
|
||||||
this.numericUpDown1 = new OpenNest.Controls.NumericUpDown();
|
numericUpDown1 = new OpenNest.Controls.NumericUpDown();
|
||||||
this.tableLayoutPanel1.SuspendLayout();
|
tableLayoutPanel1.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)numericUpDown1).BeginInit();
|
||||||
this.SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// tableLayoutPanel1
|
// tableLayoutPanel1
|
||||||
//
|
//
|
||||||
this.tableLayoutPanel1.ColumnCount = 2;
|
tableLayoutPanel1.ColumnCount = 2;
|
||||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);
|
tableLayoutPanel1.Controls.Add(label1, 0, 0);
|
||||||
this.tableLayoutPanel1.Controls.Add(this.numericUpDown1, 1, 0);
|
tableLayoutPanel1.Controls.Add(numericUpDown1, 1, 0);
|
||||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.tableLayoutPanel1.RowCount = 1;
|
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
tableLayoutPanel1.RowCount = 1;
|
||||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(220, 36);
|
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
this.tableLayoutPanel1.TabIndex = 0;
|
tableLayoutPanel1.Size = new System.Drawing.Size(266, 35);
|
||||||
|
tableLayoutPanel1.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// label1
|
// label1
|
||||||
//
|
//
|
||||||
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
label1.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||||
this.label1.AutoSize = true;
|
label1.AutoSize = true;
|
||||||
this.label1.Location = new System.Drawing.Point(3, 11);
|
label1.Location = new System.Drawing.Point(4, 10);
|
||||||
this.label1.Name = "label1";
|
label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
this.label1.Size = new System.Drawing.Size(62, 13);
|
label1.Name = "label1";
|
||||||
this.label1.TabIndex = 0;
|
label1.Size = new System.Drawing.Size(64, 15);
|
||||||
this.label1.Text = "Sequence :";
|
label1.TabIndex = 0;
|
||||||
|
label1.Text = "Sequence :";
|
||||||
//
|
//
|
||||||
// numericUpDown1
|
// numericUpDown1
|
||||||
//
|
//
|
||||||
this.numericUpDown1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
numericUpDown1.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||||
this.numericUpDown1.Location = new System.Drawing.Point(71, 8);
|
numericUpDown1.Location = new System.Drawing.Point(76, 6);
|
||||||
this.numericUpDown1.Minimum = new decimal(new int[] {
|
numericUpDown1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
1,
|
numericUpDown1.Minimum = new decimal(new int[] { 1, 0, 0, 0 });
|
||||||
0,
|
numericUpDown1.Name = "numericUpDown1";
|
||||||
0,
|
numericUpDown1.Size = new System.Drawing.Size(186, 23);
|
||||||
0});
|
numericUpDown1.Suffix = "";
|
||||||
this.numericUpDown1.Name = "numericUpDown1";
|
numericUpDown1.TabIndex = 1;
|
||||||
this.numericUpDown1.Size = new System.Drawing.Size(146, 20);
|
numericUpDown1.Value = new decimal(new int[] { 1, 0, 0, 0 });
|
||||||
this.numericUpDown1.TabIndex = 1;
|
numericUpDown1.Leave += numericUpDown1_Leave;
|
||||||
this.numericUpDown1.Value = new decimal(new int[] {
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0});
|
|
||||||
this.numericUpDown1.Leave += new System.EventHandler(this.numericUpDown1_Leave);
|
|
||||||
//
|
//
|
||||||
// SequenceForm
|
// SequenceForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(220, 36);
|
ClientSize = new System.Drawing.Size(266, 35);
|
||||||
this.ControlBox = false;
|
ControlBox = false;
|
||||||
this.Controls.Add(this.tableLayoutPanel1);
|
Controls.Add(tableLayoutPanel1);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||||
this.Location = new System.Drawing.Point(100, 100);
|
Location = new System.Drawing.Point(100, 100);
|
||||||
this.MaximizeBox = false;
|
Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.MinimizeBox = false;
|
MaximizeBox = false;
|
||||||
this.Name = "SequenceForm";
|
MinimizeBox = false;
|
||||||
this.ShowIcon = false;
|
MinimumSize = new System.Drawing.Size(268, 74);
|
||||||
this.ShowInTaskbar = false;
|
Name = "SequenceForm";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
ShowIcon = false;
|
||||||
this.Text = "Set Sequence";
|
ShowInTaskbar = false;
|
||||||
this.tableLayoutPanel1.ResumeLayout(false);
|
StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
this.tableLayoutPanel1.PerformLayout();
|
Text = "Set Sequence";
|
||||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
|
tableLayoutPanel1.ResumeLayout(false);
|
||||||
this.ResumeLayout(false);
|
tableLayoutPanel1.PerformLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)numericUpDown1).EndInit();
|
||||||
|
ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,74 @@ namespace OpenNest
|
|||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void GetGraphicsPaths(this Program pgm, Vector origin,
|
||||||
|
out GraphicsPath cutPath, out GraphicsPath leadPath)
|
||||||
|
{
|
||||||
|
cutPath = new GraphicsPath();
|
||||||
|
leadPath = new GraphicsPath();
|
||||||
|
var curpos = origin;
|
||||||
|
|
||||||
|
AddProgramSplit(cutPath, leadPath, pgm, pgm.Mode, ref curpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddProgramSplit(GraphicsPath cutPath, GraphicsPath leadPath,
|
||||||
|
Program pgm, Mode mode, ref Vector curpos)
|
||||||
|
{
|
||||||
|
mode = pgm.Mode;
|
||||||
|
|
||||||
|
for (var i = 0; i < pgm.Length; ++i)
|
||||||
|
{
|
||||||
|
var code = pgm[i];
|
||||||
|
|
||||||
|
switch (code.Type)
|
||||||
|
{
|
||||||
|
case CodeType.ArcMove:
|
||||||
|
var arc = (ArcMove)code;
|
||||||
|
if (arc.Suppressed)
|
||||||
|
{
|
||||||
|
var endpt = arc.EndPoint;
|
||||||
|
if (mode == Mode.Incremental) endpt += curpos;
|
||||||
|
curpos = endpt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var arcPath = (arc.Layer == LayerType.Leadin || arc.Layer == LayerType.Leadout)
|
||||||
|
? leadPath : cutPath;
|
||||||
|
AddArc(arcPath, arc, mode, ref curpos);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CodeType.LinearMove:
|
||||||
|
var line = (LinearMove)code;
|
||||||
|
if (line.Suppressed)
|
||||||
|
{
|
||||||
|
var endpt = line.EndPoint;
|
||||||
|
if (mode == Mode.Incremental) endpt += curpos;
|
||||||
|
curpos = endpt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var linePath = (line.Layer == LayerType.Leadin || line.Layer == LayerType.Leadout)
|
||||||
|
? leadPath : cutPath;
|
||||||
|
AddLine(linePath, line, mode, ref curpos);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CodeType.RapidMove:
|
||||||
|
AddLine(cutPath, (RapidMove)code, mode, ref curpos);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CodeType.SubProgramCall:
|
||||||
|
var tmpmode = mode;
|
||||||
|
var subpgm = (SubProgramCall)code;
|
||||||
|
if (subpgm.Program != null)
|
||||||
|
{
|
||||||
|
cutPath.StartFigure();
|
||||||
|
leadPath.StartFigure();
|
||||||
|
AddProgramSplit(cutPath, leadPath, subpgm.Program, mode, ref curpos);
|
||||||
|
}
|
||||||
|
mode = tmpmode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void AddArc(GraphicsPath path, ArcMove arc, Mode mode, ref Vector curpos)
|
private static void AddArc(GraphicsPath path, ArcMove arc, Mode mode, ref Vector curpos)
|
||||||
{
|
{
|
||||||
var endpt = arc.EndPoint;
|
var endpt = arc.EndPoint;
|
||||||
|
|||||||
+26
-2
@@ -15,6 +15,7 @@ namespace OpenNest
|
|||||||
private static Color selectedColor;
|
private static Color selectedColor;
|
||||||
private static Pen selectedPen;
|
private static Pen selectedPen;
|
||||||
private static Brush selectedBrush;
|
private static Brush selectedBrush;
|
||||||
|
private static Pen leadInPen;
|
||||||
|
|
||||||
private Color color;
|
private Color color;
|
||||||
private Brush brush;
|
private Brush brush;
|
||||||
@@ -34,6 +35,7 @@ namespace OpenNest
|
|||||||
{
|
{
|
||||||
programIdFont = new Font(SystemFonts.DefaultFont, FontStyle.Bold | FontStyle.Underline);
|
programIdFont = new Font(SystemFonts.DefaultFont, FontStyle.Bold | FontStyle.Underline);
|
||||||
SelectedColor = Color.FromArgb(90, 150, 200, 255);
|
SelectedColor = Color.FromArgb(90, 150, 200, 255);
|
||||||
|
leadInPen = new Pen(Color.OrangeRed, 1.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LayoutPart(Part part)
|
private LayoutPart(Part part)
|
||||||
@@ -52,6 +54,8 @@ namespace OpenNest
|
|||||||
|
|
||||||
public GraphicsPath Path { get; private set; }
|
public GraphicsPath Path { get; private set; }
|
||||||
|
|
||||||
|
public GraphicsPath LeadInPath { get; private set; }
|
||||||
|
|
||||||
public Color Color
|
public Color Color
|
||||||
{
|
{
|
||||||
get { return color; }
|
get { return color; }
|
||||||
@@ -83,6 +87,9 @@ namespace OpenNest
|
|||||||
g.FillPath(brush, Path);
|
g.FillPath(brush, Path);
|
||||||
g.DrawPath(pen, Path);
|
g.DrawPath(pen, Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LeadInPath != null)
|
||||||
|
g.DrawPath(leadInPen, LeadInPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(Graphics g, string id)
|
public void Draw(Graphics g, string id)
|
||||||
@@ -98,6 +105,9 @@ namespace OpenNest
|
|||||||
g.DrawPath(pen, Path);
|
g.DrawPath(pen, Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LeadInPath != null)
|
||||||
|
g.DrawPath(leadInPen, LeadInPath);
|
||||||
|
|
||||||
using var sf = new StringFormat
|
using var sf = new StringFormat
|
||||||
{
|
{
|
||||||
Alignment = StringAlignment.Center,
|
Alignment = StringAlignment.Center,
|
||||||
@@ -138,8 +148,22 @@ namespace OpenNest
|
|||||||
|
|
||||||
public void Update(DrawControl plateView)
|
public void Update(DrawControl plateView)
|
||||||
{
|
{
|
||||||
Path = GraphicsHelper.GetGraphicsPath(BasePart.Program, BasePart.Location);
|
if (BasePart.HasManualLeadIns)
|
||||||
Path.Transform(plateView.Matrix);
|
{
|
||||||
|
BasePart.Program.GetGraphicsPaths(BasePart.Location, out var cutPath, out var leadPath);
|
||||||
|
cutPath.Transform(plateView.Matrix);
|
||||||
|
leadPath.Transform(plateView.Matrix);
|
||||||
|
Path = cutPath;
|
||||||
|
LeadInPath?.Dispose();
|
||||||
|
LeadInPath = leadPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Path = GraphicsHelper.GetGraphicsPath(BasePart.Program, BasePart.Location);
|
||||||
|
Path.Transform(plateView.Matrix);
|
||||||
|
LeadInPath?.Dispose();
|
||||||
|
LeadInPath = null;
|
||||||
|
}
|
||||||
|
|
||||||
_labelPoint ??= ComputeLabelPoint();
|
_labelPoint ??= ComputeLabelPoint();
|
||||||
var rotatedLabel = _labelPoint.Value.Rotate(BasePart.Rotation);
|
var rotatedLabel = _labelPoint.Value.Rotate(BasePart.Rotation);
|
||||||
|
|||||||
Reference in New Issue
Block a user