merge: resolve .gitignore conflict, keep both entries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class AssignmentParameters
|
||||
{
|
||||
public SequenceMethod Method { get; set; } = SequenceMethod.Advanced;
|
||||
public string Preference { get; set; } = "ILAT";
|
||||
public double MinGeometryLength { get; set; } = 0.01;
|
||||
}
|
||||
}
|
||||
206
OpenNest.Core/CNC/CuttingStrategy/ContourCuttingStrategy.cs
Normal file
206
OpenNest.Core/CNC/CuttingStrategy/ContourCuttingStrategy.cs
Normal file
@@ -0,0 +1,206 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class ContourCuttingStrategy
|
||||
{
|
||||
public CuttingParameters Parameters { get; set; }
|
||||
|
||||
public Program Apply(Program partProgram, Plate plate)
|
||||
{
|
||||
var exitPoint = GetExitPoint(plate);
|
||||
var entities = partProgram.ToGeometry();
|
||||
var profile = new ShapeProfile(entities);
|
||||
|
||||
// Find closest point on perimeter from exit point
|
||||
var perimeterPoint = profile.Perimeter.ClosestPointTo(exitPoint, out var perimeterEntity);
|
||||
|
||||
// Chain cutouts by nearest-neighbor from perimeter point, then reverse
|
||||
// so farthest cutouts are cut first, nearest-to-perimeter cut last
|
||||
var orderedCutouts = SequenceCutouts(profile.Cutouts, perimeterPoint);
|
||||
orderedCutouts.Reverse();
|
||||
|
||||
// Build output program: cutouts first (farthest to nearest), perimeter last
|
||||
var result = new Program();
|
||||
var currentPoint = exitPoint;
|
||||
|
||||
foreach (var cutout in orderedCutouts)
|
||||
{
|
||||
var contourType = DetectContourType(cutout);
|
||||
var closestPt = cutout.ClosestPointTo(currentPoint, out var entity);
|
||||
var normal = ComputeNormal(closestPt, entity, contourType);
|
||||
var winding = DetermineWinding(cutout);
|
||||
|
||||
var leadIn = SelectLeadIn(contourType);
|
||||
var leadOut = SelectLeadOut(contourType);
|
||||
|
||||
result.Codes.AddRange(leadIn.Generate(closestPt, normal, winding));
|
||||
var reindexed = cutout.ReindexAt(closestPt, entity);
|
||||
result.Codes.AddRange(ConvertShapeToMoves(reindexed, closestPt));
|
||||
// TODO: MicrotabLeadOut — trim last cutting move by GapSize
|
||||
result.Codes.AddRange(leadOut.Generate(closestPt, normal, winding));
|
||||
|
||||
currentPoint = closestPt;
|
||||
}
|
||||
|
||||
// Perimeter last
|
||||
{
|
||||
var perimeterPt = profile.Perimeter.ClosestPointTo(currentPoint, out perimeterEntity);
|
||||
var normal = ComputeNormal(perimeterPt, perimeterEntity, ContourType.External);
|
||||
var winding = DetermineWinding(profile.Perimeter);
|
||||
|
||||
var leadIn = SelectLeadIn(ContourType.External);
|
||||
var leadOut = SelectLeadOut(ContourType.External);
|
||||
|
||||
result.Codes.AddRange(leadIn.Generate(perimeterPt, normal, winding));
|
||||
var reindexed = profile.Perimeter.ReindexAt(perimeterPt, perimeterEntity);
|
||||
result.Codes.AddRange(ConvertShapeToMoves(reindexed, perimeterPt));
|
||||
// TODO: MicrotabLeadOut — trim last cutting move by GapSize
|
||||
result.Codes.AddRange(leadOut.Generate(perimeterPt, normal, winding));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Vector GetExitPoint(Plate plate)
|
||||
{
|
||||
var w = plate.Size.Width;
|
||||
var l = plate.Size.Length;
|
||||
|
||||
return plate.Quadrant switch
|
||||
{
|
||||
1 => new Vector(w, l), // Q1 origin BottomLeft -> exit TopRight
|
||||
2 => new Vector(0, l), // Q2 origin BottomRight -> exit TopLeft
|
||||
3 => new Vector(0, 0), // Q3 origin TopRight -> exit BottomLeft
|
||||
4 => new Vector(w, 0), // Q4 origin TopLeft -> exit BottomRight
|
||||
_ => new Vector(w, l)
|
||||
};
|
||||
}
|
||||
|
||||
private List<Shape> SequenceCutouts(List<Shape> cutouts, Vector startPoint)
|
||||
{
|
||||
var remaining = new List<Shape>(cutouts);
|
||||
var ordered = new List<Shape>();
|
||||
var currentPoint = startPoint;
|
||||
|
||||
while (remaining.Count > 0)
|
||||
{
|
||||
var nearest = remaining[0];
|
||||
var nearestPt = nearest.ClosestPointTo(currentPoint);
|
||||
var nearestDist = nearestPt.DistanceTo(currentPoint);
|
||||
|
||||
for (var i = 1; i < remaining.Count; i++)
|
||||
{
|
||||
var pt = remaining[i].ClosestPointTo(currentPoint);
|
||||
var dist = pt.DistanceTo(currentPoint);
|
||||
if (dist < nearestDist)
|
||||
{
|
||||
nearest = remaining[i];
|
||||
nearestPt = pt;
|
||||
nearestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
ordered.Add(nearest);
|
||||
remaining.Remove(nearest);
|
||||
currentPoint = nearestPt;
|
||||
}
|
||||
|
||||
return ordered;
|
||||
}
|
||||
|
||||
private ContourType DetectContourType(Shape cutout)
|
||||
{
|
||||
if (cutout.Entities.Count == 1 && cutout.Entities[0] is Circle)
|
||||
return ContourType.ArcCircle;
|
||||
|
||||
return ContourType.Internal;
|
||||
}
|
||||
|
||||
private double ComputeNormal(Vector point, Entity entity, ContourType contourType)
|
||||
{
|
||||
double normal;
|
||||
|
||||
if (entity is Line line)
|
||||
{
|
||||
// Perpendicular to line direction
|
||||
var tangent = line.EndPoint.AngleFrom(line.StartPoint);
|
||||
normal = tangent + Math.Angle.HalfPI;
|
||||
}
|
||||
else if (entity is Arc arc)
|
||||
{
|
||||
// Radial direction from center to point
|
||||
normal = point.AngleFrom(arc.Center);
|
||||
}
|
||||
else if (entity is Circle circle)
|
||||
{
|
||||
normal = point.AngleFrom(circle.Center);
|
||||
}
|
||||
else
|
||||
{
|
||||
normal = 0;
|
||||
}
|
||||
|
||||
// For internal contours, flip the normal (point into scrap)
|
||||
if (contourType == ContourType.Internal || contourType == ContourType.ArcCircle)
|
||||
normal += System.Math.PI;
|
||||
|
||||
return Math.Angle.NormalizeRad(normal);
|
||||
}
|
||||
|
||||
private RotationType DetermineWinding(Shape shape)
|
||||
{
|
||||
// Use signed area: positive = CCW, negative = CW
|
||||
var area = shape.Area();
|
||||
return area >= 0 ? RotationType.CCW : RotationType.CW;
|
||||
}
|
||||
|
||||
private LeadIn SelectLeadIn(ContourType contourType)
|
||||
{
|
||||
return contourType switch
|
||||
{
|
||||
ContourType.ArcCircle => Parameters.ArcCircleLeadIn ?? Parameters.InternalLeadIn,
|
||||
ContourType.Internal => Parameters.InternalLeadIn,
|
||||
_ => Parameters.ExternalLeadIn
|
||||
};
|
||||
}
|
||||
|
||||
private LeadOut SelectLeadOut(ContourType contourType)
|
||||
{
|
||||
return contourType switch
|
||||
{
|
||||
ContourType.ArcCircle => Parameters.ArcCircleLeadOut ?? Parameters.InternalLeadOut,
|
||||
ContourType.Internal => Parameters.InternalLeadOut,
|
||||
_ => Parameters.ExternalLeadOut
|
||||
};
|
||||
}
|
||||
|
||||
private List<ICode> ConvertShapeToMoves(Shape shape, Vector startPoint)
|
||||
{
|
||||
var moves = new List<ICode>();
|
||||
|
||||
foreach (var entity in shape.Entities)
|
||||
{
|
||||
if (entity is Line line)
|
||||
{
|
||||
moves.Add(new LinearMove(line.EndPoint));
|
||||
}
|
||||
else if (entity is Arc arc)
|
||||
{
|
||||
moves.Add(new ArcMove(arc.EndPoint(), arc.Center, arc.IsReversed ? RotationType.CW : RotationType.CCW));
|
||||
}
|
||||
else if (entity is Circle circle)
|
||||
{
|
||||
moves.Add(new ArcMove(startPoint, circle.Center, circle.Rotation));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.InvalidOperationException($"Unsupported entity type: {entity.Type}");
|
||||
}
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
OpenNest.Core/CNC/CuttingStrategy/ContourType.cs
Normal file
9
OpenNest.Core/CNC/CuttingStrategy/ContourType.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public enum ContourType
|
||||
{
|
||||
External,
|
||||
Internal,
|
||||
ArcCircle
|
||||
}
|
||||
}
|
||||
30
OpenNest.Core/CNC/CuttingStrategy/CuttingParameters.cs
Normal file
30
OpenNest.Core/CNC/CuttingStrategy/CuttingParameters.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class CuttingParameters
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string MachineName { get; set; }
|
||||
public string MaterialName { get; set; }
|
||||
public string Grade { get; set; }
|
||||
public double Thickness { get; set; }
|
||||
|
||||
public double Kerf { get; set; }
|
||||
public double PartSpacing { get; set; }
|
||||
|
||||
public LeadIn ExternalLeadIn { get; set; } = new NoLeadIn();
|
||||
public LeadOut ExternalLeadOut { get; set; } = new NoLeadOut();
|
||||
|
||||
public LeadIn InternalLeadIn { get; set; } = new LineLeadIn { Length = 0.125, ApproachAngle = 90 };
|
||||
public LeadOut InternalLeadOut { get; set; } = new NoLeadOut();
|
||||
|
||||
public LeadIn ArcCircleLeadIn { get; set; } = new NoLeadIn();
|
||||
public LeadOut ArcCircleLeadOut { get; set; } = new NoLeadOut();
|
||||
|
||||
public Tab TabConfig { get; set; }
|
||||
public bool TabsEnabled { get; set; }
|
||||
|
||||
public SequenceParameters Sequencing { get; set; } = new SequenceParameters();
|
||||
public AssignmentParameters Assignment { get; set; } = new AssignmentParameters();
|
||||
}
|
||||
}
|
||||
36
OpenNest.Core/CNC/CuttingStrategy/LeadIns/ArcLeadIn.cs
Normal file
36
OpenNest.Core/CNC/CuttingStrategy/LeadIns/ArcLeadIn.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class ArcLeadIn : LeadIn
|
||||
{
|
||||
public double Radius { get; set; }
|
||||
|
||||
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||
|
||||
var arcCenter = new Vector(
|
||||
contourStartPoint.X + Radius * System.Math.Cos(contourNormalAngle),
|
||||
contourStartPoint.Y + Radius * System.Math.Sin(contourNormalAngle));
|
||||
|
||||
return new List<ICode>
|
||||
{
|
||||
new RapidMove(piercePoint),
|
||||
new ArcMove(contourStartPoint, arcCenter, winding)
|
||||
};
|
||||
}
|
||||
|
||||
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||
{
|
||||
var arcCenterX = contourStartPoint.X + Radius * System.Math.Cos(contourNormalAngle);
|
||||
var arcCenterY = contourStartPoint.Y + Radius * System.Math.Sin(contourNormalAngle);
|
||||
|
||||
return new Vector(
|
||||
arcCenterX + Radius * System.Math.Cos(contourNormalAngle),
|
||||
arcCenterY + Radius * System.Math.Sin(contourNormalAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
49
OpenNest.Core/CNC/CuttingStrategy/LeadIns/CleanHoleLeadIn.cs
Normal file
49
OpenNest.Core/CNC/CuttingStrategy/LeadIns/CleanHoleLeadIn.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class CleanHoleLeadIn : LeadIn
|
||||
{
|
||||
public double LineLength { get; set; }
|
||||
public double ArcRadius { get; set; }
|
||||
public double Kerf { get; set; }
|
||||
|
||||
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||
|
||||
var arcCenterX = contourStartPoint.X + ArcRadius * System.Math.Cos(contourNormalAngle);
|
||||
var arcCenterY = contourStartPoint.Y + ArcRadius * System.Math.Sin(contourNormalAngle);
|
||||
var arcCenter = new Vector(arcCenterX, arcCenterY);
|
||||
|
||||
var lineAngle = contourNormalAngle + Angle.ToRadians(135.0);
|
||||
var arcStart = new Vector(
|
||||
arcCenterX + ArcRadius * System.Math.Cos(lineAngle),
|
||||
arcCenterY + ArcRadius * System.Math.Sin(lineAngle));
|
||||
|
||||
return new List<ICode>
|
||||
{
|
||||
new RapidMove(piercePoint),
|
||||
new LinearMove(arcStart),
|
||||
new ArcMove(contourStartPoint, arcCenter, winding)
|
||||
};
|
||||
}
|
||||
|
||||
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||
{
|
||||
var arcCenterX = contourStartPoint.X + ArcRadius * System.Math.Cos(contourNormalAngle);
|
||||
var arcCenterY = contourStartPoint.Y + ArcRadius * System.Math.Sin(contourNormalAngle);
|
||||
|
||||
var lineAngle = contourNormalAngle + Angle.ToRadians(135.0);
|
||||
var arcStartX = arcCenterX + ArcRadius * System.Math.Cos(lineAngle);
|
||||
var arcStartY = arcCenterY + ArcRadius * System.Math.Sin(lineAngle);
|
||||
|
||||
return new Vector(
|
||||
arcStartX + LineLength * System.Math.Cos(lineAngle),
|
||||
arcStartY + LineLength * System.Math.Sin(lineAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
13
OpenNest.Core/CNC/CuttingStrategy/LeadIns/LeadIn.cs
Normal file
13
OpenNest.Core/CNC/CuttingStrategy/LeadIns/LeadIn.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public abstract class LeadIn
|
||||
{
|
||||
public abstract List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW);
|
||||
|
||||
public abstract Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle);
|
||||
}
|
||||
}
|
||||
49
OpenNest.Core/CNC/CuttingStrategy/LeadIns/LineArcLeadIn.cs
Normal file
49
OpenNest.Core/CNC/CuttingStrategy/LeadIns/LineArcLeadIn.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class LineArcLeadIn : LeadIn
|
||||
{
|
||||
public double LineLength { get; set; }
|
||||
public double ApproachAngle { get; set; } = 135.0;
|
||||
public double ArcRadius { get; set; }
|
||||
|
||||
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||
|
||||
var arcCenterX = contourStartPoint.X + ArcRadius * System.Math.Cos(contourNormalAngle);
|
||||
var arcCenterY = contourStartPoint.Y + ArcRadius * System.Math.Sin(contourNormalAngle);
|
||||
var arcCenter = new Vector(arcCenterX, arcCenterY);
|
||||
|
||||
var lineAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
||||
var arcStart = new Vector(
|
||||
arcCenterX + ArcRadius * System.Math.Cos(lineAngle),
|
||||
arcCenterY + ArcRadius * System.Math.Sin(lineAngle));
|
||||
|
||||
return new List<ICode>
|
||||
{
|
||||
new RapidMove(piercePoint),
|
||||
new LinearMove(arcStart),
|
||||
new ArcMove(contourStartPoint, arcCenter, winding)
|
||||
};
|
||||
}
|
||||
|
||||
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||
{
|
||||
var arcCenterX = contourStartPoint.X + ArcRadius * System.Math.Cos(contourNormalAngle);
|
||||
var arcCenterY = contourStartPoint.Y + ArcRadius * System.Math.Sin(contourNormalAngle);
|
||||
|
||||
var lineAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
||||
var arcStartX = arcCenterX + ArcRadius * System.Math.Cos(lineAngle);
|
||||
var arcStartY = arcCenterY + ArcRadius * System.Math.Sin(lineAngle);
|
||||
|
||||
return new Vector(
|
||||
arcStartX + LineLength * System.Math.Cos(lineAngle),
|
||||
arcStartY + LineLength * System.Math.Sin(lineAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
32
OpenNest.Core/CNC/CuttingStrategy/LeadIns/LineLeadIn.cs
Normal file
32
OpenNest.Core/CNC/CuttingStrategy/LeadIns/LineLeadIn.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class LineLeadIn : LeadIn
|
||||
{
|
||||
public double Length { get; set; }
|
||||
public double ApproachAngle { get; set; } = 90.0;
|
||||
|
||||
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||
|
||||
return new List<ICode>
|
||||
{
|
||||
new RapidMove(piercePoint),
|
||||
new LinearMove(contourStartPoint)
|
||||
};
|
||||
}
|
||||
|
||||
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||
{
|
||||
var approachAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
||||
return new Vector(
|
||||
contourStartPoint.X + Length * System.Math.Cos(approachAngle),
|
||||
contourStartPoint.Y + Length * System.Math.Sin(approachAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
44
OpenNest.Core/CNC/CuttingStrategy/LeadIns/LineLineLeadIn.cs
Normal file
44
OpenNest.Core/CNC/CuttingStrategy/LeadIns/LineLineLeadIn.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class LineLineLeadIn : LeadIn
|
||||
{
|
||||
public double Length1 { get; set; }
|
||||
public double ApproachAngle1 { get; set; } = 90.0;
|
||||
public double Length2 { get; set; }
|
||||
public double ApproachAngle2 { get; set; } = 90.0;
|
||||
|
||||
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
var piercePoint = GetPiercePoint(contourStartPoint, contourNormalAngle);
|
||||
|
||||
var secondAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle1);
|
||||
var midPoint = new Vector(
|
||||
contourStartPoint.X + Length2 * System.Math.Cos(secondAngle),
|
||||
contourStartPoint.Y + Length2 * System.Math.Sin(secondAngle));
|
||||
|
||||
return new List<ICode>
|
||||
{
|
||||
new RapidMove(piercePoint),
|
||||
new LinearMove(midPoint),
|
||||
new LinearMove(contourStartPoint)
|
||||
};
|
||||
}
|
||||
|
||||
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||
{
|
||||
var secondAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle1);
|
||||
var midX = contourStartPoint.X + Length2 * System.Math.Cos(secondAngle);
|
||||
var midY = contourStartPoint.Y + Length2 * System.Math.Sin(secondAngle);
|
||||
|
||||
var firstAngle = secondAngle + Angle.ToRadians(ApproachAngle2);
|
||||
return new Vector(
|
||||
midX + Length1 * System.Math.Cos(firstAngle),
|
||||
midY + Length1 * System.Math.Sin(firstAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
22
OpenNest.Core/CNC/CuttingStrategy/LeadIns/NoLeadIn.cs
Normal file
22
OpenNest.Core/CNC/CuttingStrategy/LeadIns/NoLeadIn.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class NoLeadIn : LeadIn
|
||||
{
|
||||
public override List<ICode> Generate(Vector contourStartPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
return new List<ICode>
|
||||
{
|
||||
new RapidMove(contourStartPoint)
|
||||
};
|
||||
}
|
||||
|
||||
public override Vector GetPiercePoint(Vector contourStartPoint, double contourNormalAngle)
|
||||
{
|
||||
return contourStartPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
OpenNest.Core/CNC/CuttingStrategy/LeadOuts/ArcLeadOut.cs
Normal file
27
OpenNest.Core/CNC/CuttingStrategy/LeadOuts/ArcLeadOut.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class ArcLeadOut : LeadOut
|
||||
{
|
||||
public double Radius { get; set; }
|
||||
|
||||
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
var arcCenterX = contourEndPoint.X + Radius * System.Math.Cos(contourNormalAngle);
|
||||
var arcCenterY = contourEndPoint.Y + Radius * System.Math.Sin(contourNormalAngle);
|
||||
var arcCenter = new Vector(arcCenterX, arcCenterY);
|
||||
|
||||
var endPoint = new Vector(
|
||||
arcCenterX + Radius * System.Math.Cos(contourNormalAngle + System.Math.PI / 2),
|
||||
arcCenterY + Radius * System.Math.Sin(contourNormalAngle + System.Math.PI / 2));
|
||||
|
||||
return new List<ICode>
|
||||
{
|
||||
new ArcMove(endPoint, arcCenter, winding)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
11
OpenNest.Core/CNC/CuttingStrategy/LeadOuts/LeadOut.cs
Normal file
11
OpenNest.Core/CNC/CuttingStrategy/LeadOuts/LeadOut.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public abstract class LeadOut
|
||||
{
|
||||
public abstract List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW);
|
||||
}
|
||||
}
|
||||
26
OpenNest.Core/CNC/CuttingStrategy/LeadOuts/LineLeadOut.cs
Normal file
26
OpenNest.Core/CNC/CuttingStrategy/LeadOuts/LineLeadOut.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class LineLeadOut : LeadOut
|
||||
{
|
||||
public double Length { get; set; }
|
||||
public double ApproachAngle { get; set; } = 90.0;
|
||||
|
||||
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
var overcutAngle = contourNormalAngle + Angle.ToRadians(ApproachAngle);
|
||||
var endPoint = new Vector(
|
||||
contourEndPoint.X + Length * System.Math.Cos(overcutAngle),
|
||||
contourEndPoint.Y + Length * System.Math.Sin(overcutAngle));
|
||||
|
||||
return new List<ICode>
|
||||
{
|
||||
new LinearMove(endPoint)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class MicrotabLeadOut : LeadOut
|
||||
{
|
||||
public double GapSize { get; set; } = 0.03;
|
||||
|
||||
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
return new List<ICode>();
|
||||
}
|
||||
}
|
||||
}
|
||||
14
OpenNest.Core/CNC/CuttingStrategy/LeadOuts/NoLeadOut.cs
Normal file
14
OpenNest.Core/CNC/CuttingStrategy/LeadOuts/NoLeadOut.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class NoLeadOut : LeadOut
|
||||
{
|
||||
public override List<ICode> Generate(Vector contourEndPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
return new List<ICode>();
|
||||
}
|
||||
}
|
||||
}
|
||||
27
OpenNest.Core/CNC/CuttingStrategy/SequenceParameters.cs
Normal file
27
OpenNest.Core/CNC/CuttingStrategy/SequenceParameters.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
// Values match PEP Technology's numbering scheme (value 6 intentionally skipped)
|
||||
public enum SequenceMethod
|
||||
{
|
||||
RightSide = 1,
|
||||
LeastCode = 2,
|
||||
Advanced = 3,
|
||||
BottomSide = 4,
|
||||
EdgeStart = 5,
|
||||
LeftSide = 7,
|
||||
RightSideAlt = 8
|
||||
}
|
||||
|
||||
public class SequenceParameters
|
||||
{
|
||||
public SequenceMethod Method { get; set; } = SequenceMethod.Advanced;
|
||||
public double SmallCutoutWidth { get; set; } = 1.5;
|
||||
public double SmallCutoutHeight { get; set; } = 1.5;
|
||||
public double MediumCutoutWidth { get; set; } = 8.0;
|
||||
public double MediumCutoutHeight { get; set; } = 8.0;
|
||||
public double DistanceMediumSmall { get; set; }
|
||||
public bool AlternateRowsColumns { get; set; } = true;
|
||||
public bool AlternateCutoutsWithinRowColumn { get; set; } = true;
|
||||
public double MinDistanceBetweenRowsColumns { get; set; } = 0.25;
|
||||
}
|
||||
}
|
||||
34
OpenNest.Core/CNC/CuttingStrategy/Tabs/BreakerTab.cs
Normal file
34
OpenNest.Core/CNC/CuttingStrategy/Tabs/BreakerTab.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class BreakerTab : Tab
|
||||
{
|
||||
public double BreakerDepth { get; set; }
|
||||
public double BreakerLeadInLength { get; set; }
|
||||
public double BreakerAngle { get; set; }
|
||||
|
||||
public override List<ICode> Generate(
|
||||
Vector tabStartPoint, Vector tabEndPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
var codes = new List<ICode>();
|
||||
|
||||
if (TabLeadOut != null)
|
||||
codes.AddRange(TabLeadOut.Generate(tabStartPoint, contourNormalAngle, winding));
|
||||
|
||||
var scoreAngle = contourNormalAngle + System.Math.PI;
|
||||
var scoreEnd = new Vector(
|
||||
tabStartPoint.X + BreakerDepth * System.Math.Cos(scoreAngle),
|
||||
tabStartPoint.Y + BreakerDepth * System.Math.Sin(scoreAngle));
|
||||
codes.Add(new LinearMove(scoreEnd));
|
||||
codes.Add(new RapidMove(tabEndPoint));
|
||||
|
||||
if (TabLeadIn != null)
|
||||
codes.AddRange(TabLeadIn.Generate(tabEndPoint, contourNormalAngle, winding));
|
||||
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
OpenNest.Core/CNC/CuttingStrategy/Tabs/MachineTab.cs
Normal file
20
OpenNest.Core/CNC/CuttingStrategy/Tabs/MachineTab.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class MachineTab : Tab
|
||||
{
|
||||
public int MachineTabId { get; set; }
|
||||
|
||||
public override List<ICode> Generate(
|
||||
Vector tabStartPoint, Vector tabEndPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
return new List<ICode>
|
||||
{
|
||||
new RapidMove(tabEndPoint)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
36
OpenNest.Core/CNC/CuttingStrategy/Tabs/NormalTab.cs
Normal file
36
OpenNest.Core/CNC/CuttingStrategy/Tabs/NormalTab.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public class NormalTab : Tab
|
||||
{
|
||||
public double CutoutMinWidth { get; set; }
|
||||
public double CutoutMinHeight { get; set; }
|
||||
public double CutoutMaxWidth { get; set; }
|
||||
public double CutoutMaxHeight { get; set; }
|
||||
|
||||
public override List<ICode> Generate(
|
||||
Vector tabStartPoint, Vector tabEndPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW)
|
||||
{
|
||||
var codes = new List<ICode>();
|
||||
|
||||
if (TabLeadOut != null)
|
||||
codes.AddRange(TabLeadOut.Generate(tabStartPoint, contourNormalAngle, winding));
|
||||
|
||||
codes.Add(new RapidMove(tabEndPoint));
|
||||
|
||||
if (TabLeadIn != null)
|
||||
codes.AddRange(TabLeadIn.Generate(tabEndPoint, contourNormalAngle, winding));
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
public bool AppliesToCutout(double cutoutWidth, double cutoutHeight)
|
||||
{
|
||||
return cutoutWidth >= CutoutMinWidth && cutoutWidth <= CutoutMaxWidth
|
||||
&& cutoutHeight >= CutoutMinHeight && cutoutHeight <= CutoutMaxHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
OpenNest.Core/CNC/CuttingStrategy/Tabs/Tab.cs
Normal file
16
OpenNest.Core/CNC/CuttingStrategy/Tabs/Tab.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CNC.CuttingStrategy
|
||||
{
|
||||
public abstract class Tab
|
||||
{
|
||||
public double Size { get; set; } = 0.03;
|
||||
public LeadIn TabLeadIn { get; set; }
|
||||
public LeadOut TabLeadOut { get; set; }
|
||||
|
||||
public abstract List<ICode> Generate(
|
||||
Vector tabStartPoint, Vector tabEndPoint, double contourNormalAngle,
|
||||
RotationType winding = RotationType.CW);
|
||||
}
|
||||
}
|
||||
@@ -155,6 +155,28 @@ namespace OpenNest.Geometry
|
||||
Center.Y + Radius * System.Math.Sin(EndAngle));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits the arc at the given point, returning two sub-arcs.
|
||||
/// Either half may be null if the split point coincides with an endpoint.
|
||||
/// </summary>
|
||||
/// <param name="point">The point at which to split the arc.</param>
|
||||
/// <returns>A tuple of (first, second) sub-arcs.</returns>
|
||||
public (Arc first, Arc second) SplitAt(Vector point)
|
||||
{
|
||||
if (point.DistanceTo(StartPoint()) < Tolerance.Epsilon)
|
||||
return (null, new Arc(Center, Radius, StartAngle, EndAngle, IsReversed));
|
||||
|
||||
if (point.DistanceTo(EndPoint()) < Tolerance.Epsilon)
|
||||
return (new Arc(Center, Radius, StartAngle, EndAngle, IsReversed), null);
|
||||
|
||||
var splitAngle = Angle.NormalizeRad(Center.AngleTo(point));
|
||||
|
||||
var firstArc = new Arc(Center, Radius, StartAngle, splitAngle, IsReversed);
|
||||
var secondArc = new Arc(Center, Radius, splitAngle, EndAngle, IsReversed);
|
||||
|
||||
return (firstArc, secondArc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given arc has the same center point and radius as this.
|
||||
/// </summary>
|
||||
@@ -388,7 +410,7 @@ namespace OpenNest.Geometry
|
||||
boundingBox.X = minX;
|
||||
boundingBox.Y = minY;
|
||||
boundingBox.Width = maxX - minX;
|
||||
boundingBox.Height = maxY - minY;
|
||||
boundingBox.Length = maxY - minY;
|
||||
}
|
||||
|
||||
public override Entity OffsetEntity(double distance, OffsetSide side)
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace OpenNest.Geometry
|
||||
double minX = boxes[0].X;
|
||||
double minY = boxes[0].Y;
|
||||
double maxX = boxes[0].X + boxes[0].Width;
|
||||
double maxY = boxes[0].Y + boxes[0].Height;
|
||||
double maxY = boxes[0].Y + boxes[0].Length;
|
||||
|
||||
foreach (var box in boxes)
|
||||
{
|
||||
|
||||
@@ -15,14 +15,14 @@ namespace OpenNest.Geometry
|
||||
{
|
||||
Location = new Vector(x, y);
|
||||
Width = w;
|
||||
Height = h;
|
||||
Length = h;
|
||||
}
|
||||
|
||||
public Vector Location;
|
||||
|
||||
public Vector Center
|
||||
{
|
||||
get { return new Vector(X + Width * 0.5, Y + Height * 0.5); }
|
||||
get { return new Vector(X + Width * 0.5, Y + Length * 0.5); }
|
||||
}
|
||||
|
||||
public Size Size;
|
||||
@@ -45,10 +45,10 @@ namespace OpenNest.Geometry
|
||||
set { Size.Width = value; }
|
||||
}
|
||||
|
||||
public double Height
|
||||
public double Length
|
||||
{
|
||||
get { return Size.Height; }
|
||||
set { Size.Height = value; }
|
||||
get { return Size.Length; }
|
||||
set { Size.Length = value; }
|
||||
}
|
||||
|
||||
public void MoveTo(double x, double y)
|
||||
@@ -86,7 +86,7 @@ namespace OpenNest.Geometry
|
||||
|
||||
public double Top
|
||||
{
|
||||
get { return Y + Height; }
|
||||
get { return Y + Length; }
|
||||
}
|
||||
|
||||
public double Bottom
|
||||
@@ -96,12 +96,12 @@ namespace OpenNest.Geometry
|
||||
|
||||
public double Area()
|
||||
{
|
||||
return Width * Height;
|
||||
return Width * Length;
|
||||
}
|
||||
|
||||
public double Perimeter()
|
||||
{
|
||||
return Width * 2 + Height * 2;
|
||||
return Width * 2 + Length * 2;
|
||||
}
|
||||
|
||||
public bool Intersects(Box box)
|
||||
@@ -197,12 +197,12 @@ namespace OpenNest.Geometry
|
||||
|
||||
public Box Offset(double d)
|
||||
{
|
||||
return new Box(X - d, Y - d, Width + d * 2, Height + d * 2);
|
||||
return new Box(X - d, Y - d, Width + d * 2, Length + d * 2);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[Box: X={0}, Y={1}, Width={2}, Height={3}]", X, Y, Width, Height);
|
||||
return string.Format("[Box: X={0}, Y={1}, Width={2}, Length={3}]", X, Y, Width, Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
var x = large.Left;
|
||||
var y = large.Bottom;
|
||||
var w = small.Left - x;
|
||||
var h = large.Height;
|
||||
var h = large.Length;
|
||||
|
||||
return new Box(x, y, w, h);
|
||||
}
|
||||
@@ -49,7 +49,7 @@
|
||||
var x = small.Right;
|
||||
var y = large.Bottom;
|
||||
var w = large.Right - x;
|
||||
var h = large.Height;
|
||||
var h = large.Length;
|
||||
|
||||
return new Box(x, y, w, h);
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ namespace OpenNest.Geometry
|
||||
boundingBox.X = Center.X - Radius;
|
||||
boundingBox.Y = Center.Y - Radius;
|
||||
boundingBox.Width = Diameter;
|
||||
boundingBox.Height = Diameter;
|
||||
boundingBox.Length = Diameter;
|
||||
}
|
||||
|
||||
public override Entity OffsetEntity(double distance, OffsetSide side)
|
||||
|
||||
@@ -381,12 +381,12 @@ namespace OpenNest.Geometry
|
||||
if (StartPoint.Y < EndPoint.Y)
|
||||
{
|
||||
boundingBox.Y = StartPoint.Y;
|
||||
boundingBox.Height = EndPoint.Y - StartPoint.Y;
|
||||
boundingBox.Length = EndPoint.Y - StartPoint.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundingBox.Y = EndPoint.Y;
|
||||
boundingBox.Height = StartPoint.Y - EndPoint.Y;
|
||||
boundingBox.Length = StartPoint.Y - EndPoint.Y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,6 +414,25 @@ namespace OpenNest.Geometry
|
||||
return OffsetEntity(distance, side);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits the line at the given point, returning two sub-lines.
|
||||
/// Either half may be null if the split point coincides with an endpoint.
|
||||
/// </summary>
|
||||
/// <param name="point">The point at which to split the line.</param>
|
||||
/// <returns>A tuple of (first, second) sub-lines.</returns>
|
||||
public (Line first, Line second) SplitAt(Vector point)
|
||||
{
|
||||
var first = point.DistanceTo(StartPoint) < Tolerance.Epsilon
|
||||
? null
|
||||
: new Line(StartPoint, point);
|
||||
|
||||
var second = point.DistanceTo(EndPoint) < Tolerance.Epsilon
|
||||
? null
|
||||
: new Line(point, EndPoint);
|
||||
|
||||
return (first, second);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the closest point on the line to the given point.
|
||||
/// </summary>
|
||||
|
||||
@@ -312,7 +312,7 @@ namespace OpenNest.Geometry
|
||||
boundingBox.X = minX;
|
||||
boundingBox.Y = minY;
|
||||
boundingBox.Width = maxX - minX;
|
||||
boundingBox.Height = maxY - minY;
|
||||
boundingBox.Length = maxY - minY;
|
||||
}
|
||||
|
||||
public override Entity OffsetEntity(double distance, OffsetSide side)
|
||||
|
||||
@@ -201,6 +201,68 @@ namespace OpenNest.Geometry
|
||||
return closestPt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new shape with entities reordered so that the given point on
|
||||
/// the given entity becomes the new start point of the contour.
|
||||
/// </summary>
|
||||
/// <param name="point">The point on the entity to reindex at.</param>
|
||||
/// <param name="entity">The entity containing the point.</param>
|
||||
/// <returns>A new reindexed shape.</returns>
|
||||
public Shape ReindexAt(Vector point, Entity entity)
|
||||
{
|
||||
// Circle case: return a new shape with just the circle
|
||||
if (entity is Circle)
|
||||
{
|
||||
var result = new Shape();
|
||||
result.Entities.Add(entity);
|
||||
return result;
|
||||
}
|
||||
|
||||
var i = Entities.IndexOf(entity);
|
||||
if (i < 0)
|
||||
throw new ArgumentException("Entity not found in shape", nameof(entity));
|
||||
|
||||
// Split the entity at the point
|
||||
Entity firstHalf = null;
|
||||
Entity secondHalf = null;
|
||||
|
||||
if (entity is Line line)
|
||||
{
|
||||
var (f, s) = line.SplitAt(point);
|
||||
firstHalf = f;
|
||||
secondHalf = s;
|
||||
}
|
||||
else if (entity is Arc arc)
|
||||
{
|
||||
var (f, s) = arc.SplitAt(point);
|
||||
firstHalf = f;
|
||||
secondHalf = s;
|
||||
}
|
||||
|
||||
// Build reindexed entity list
|
||||
var entities = new List<Entity>();
|
||||
|
||||
// secondHalf of split entity (if not null)
|
||||
if (secondHalf != null)
|
||||
entities.Add(secondHalf);
|
||||
|
||||
// Entities after the split index (wrapping)
|
||||
for (var j = i + 1; j < Entities.Count; j++)
|
||||
entities.Add(Entities[j]);
|
||||
|
||||
// Entities before the split index (wrapping)
|
||||
for (var j = 0; j < i; j++)
|
||||
entities.Add(Entities[j]);
|
||||
|
||||
// firstHalf of split entity (if not null)
|
||||
if (firstHalf != null)
|
||||
entities.Add(firstHalf);
|
||||
|
||||
var reindexed = new Shape();
|
||||
reindexed.Entities.AddRange(entities);
|
||||
return reindexed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the shape to a polygon.
|
||||
/// </summary>
|
||||
@@ -399,7 +461,7 @@ namespace OpenNest.Geometry
|
||||
public override Entity OffsetEntity(double distance, OffsetSide side)
|
||||
{
|
||||
var offsetShape = new Shape();
|
||||
var definedShape = new DefinedShape(this);
|
||||
var definedShape = new ShapeProfile(this);
|
||||
|
||||
Entity lastEntity = null;
|
||||
Entity lastOffsetEntity = null;
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
namespace OpenNest.Geometry
|
||||
{
|
||||
public class DefinedShape
|
||||
public class ShapeProfile
|
||||
{
|
||||
public DefinedShape(Shape shape)
|
||||
public ShapeProfile(Shape shape)
|
||||
{
|
||||
Update(shape.Entities);
|
||||
}
|
||||
|
||||
public DefinedShape(List<Entity> entities)
|
||||
public ShapeProfile(List<Entity> entities)
|
||||
{
|
||||
Update(entities);
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace OpenNest.Geometry
|
||||
{
|
||||
public struct Size
|
||||
{
|
||||
public Size(double width, double height)
|
||||
public Size(double width, double length)
|
||||
{
|
||||
Height = height;
|
||||
Length = length;
|
||||
Width = width;
|
||||
}
|
||||
|
||||
public double Height;
|
||||
public double Length;
|
||||
|
||||
public double Width;
|
||||
|
||||
@@ -21,10 +21,10 @@ namespace OpenNest.Geometry
|
||||
if (a.Length > 2)
|
||||
throw new FormatException("Invalid size format.");
|
||||
|
||||
var height = double.Parse(a[0]);
|
||||
var length = double.Parse(a[0]);
|
||||
var width = double.Parse(a[1]);
|
||||
|
||||
return new Size(width, height);
|
||||
return new Size(width, length);
|
||||
}
|
||||
|
||||
public static bool TryParse(string s, out Size size)
|
||||
@@ -44,12 +44,12 @@ namespace OpenNest.Geometry
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} x {1}", Height, Width);
|
||||
return string.Format("{0} x {1}", Length, Width);
|
||||
}
|
||||
|
||||
public string ToString(int decimalPlaces)
|
||||
{
|
||||
return string.Format("{0} x {1}", System.Math.Round(Height, decimalPlaces), System.Math.Round(Width, decimalPlaces));
|
||||
return string.Format("{0} x {1}", System.Math.Round(Length, decimalPlaces), System.Math.Round(Width, decimalPlaces));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace OpenNest
|
||||
var part = new Part(BaseDrawing, clonedProgram,
|
||||
location + offset,
|
||||
new Box(BoundingBox.X + offset.X, BoundingBox.Y + offset.Y,
|
||||
BoundingBox.Width, BoundingBox.Height));
|
||||
BoundingBox.Width, BoundingBox.Length));
|
||||
|
||||
return part;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace OpenNest
|
||||
{
|
||||
const double oneAndHalfPI = System.Math.PI * 1.5;
|
||||
|
||||
Size = new Size(Size.Height, Size.Width);
|
||||
Size = new Size(Size.Length, Size.Width);
|
||||
|
||||
if (rotationDirection == RotationType.CW)
|
||||
{
|
||||
@@ -128,7 +128,7 @@ namespace OpenNest
|
||||
switch (Quadrant)
|
||||
{
|
||||
case 1:
|
||||
Offset(0, Size.Height);
|
||||
Offset(0, Size.Length);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
@@ -136,7 +136,7 @@ namespace OpenNest
|
||||
break;
|
||||
|
||||
case 3:
|
||||
Offset(0, -Size.Height);
|
||||
Offset(0, -Size.Length);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
@@ -165,7 +165,7 @@ namespace OpenNest
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Offset(0, Size.Height);
|
||||
Offset(0, Size.Length);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
@@ -173,7 +173,7 @@ namespace OpenNest
|
||||
break;
|
||||
|
||||
case 4:
|
||||
Offset(0, -Size.Height);
|
||||
Offset(0, -Size.Length);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -200,19 +200,19 @@ namespace OpenNest
|
||||
switch (Quadrant)
|
||||
{
|
||||
case 1:
|
||||
centerpt = new Vector(Size.Width * 0.5, Size.Height * 0.5);
|
||||
centerpt = new Vector(Size.Width * 0.5, Size.Length * 0.5);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
centerpt = new Vector(-Size.Width * 0.5, Size.Height * 0.5);
|
||||
centerpt = new Vector(-Size.Width * 0.5, Size.Length * 0.5);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
centerpt = new Vector(-Size.Width * 0.5, -Size.Height * 0.5);
|
||||
centerpt = new Vector(-Size.Width * 0.5, -Size.Length * 0.5);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
centerpt = new Vector(Size.Width * 0.5, -Size.Height * 0.5);
|
||||
centerpt = new Vector(Size.Width * 0.5, -Size.Length * 0.5);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -308,12 +308,12 @@ namespace OpenNest
|
||||
|
||||
case 3:
|
||||
plateBox.X = (float)-Size.Width;
|
||||
plateBox.Y = (float)-Size.Height;
|
||||
plateBox.Y = (float)-Size.Length;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
plateBox.X = 0;
|
||||
plateBox.Y = (float)-Size.Height;
|
||||
plateBox.Y = (float)-Size.Length;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -321,7 +321,7 @@ namespace OpenNest
|
||||
}
|
||||
|
||||
plateBox.Width = Size.Width;
|
||||
plateBox.Height = Size.Height;
|
||||
plateBox.Length = Size.Length;
|
||||
|
||||
if (!includeParts)
|
||||
return plateBox;
|
||||
@@ -341,7 +341,7 @@ namespace OpenNest
|
||||
? partsBox.Right - boundingBox.X
|
||||
: plateBox.Right - boundingBox.X;
|
||||
|
||||
boundingBox.Height = partsBox.Top > plateBox.Top
|
||||
boundingBox.Length = partsBox.Top > plateBox.Top
|
||||
? partsBox.Top - boundingBox.Y
|
||||
: plateBox.Top - boundingBox.Y;
|
||||
|
||||
@@ -359,7 +359,7 @@ namespace OpenNest
|
||||
box.X += EdgeSpacing.Left;
|
||||
box.Y += EdgeSpacing.Bottom;
|
||||
box.Width -= EdgeSpacing.Left + EdgeSpacing.Right;
|
||||
box.Height -= EdgeSpacing.Top + EdgeSpacing.Bottom;
|
||||
box.Length -= EdgeSpacing.Top + EdgeSpacing.Bottom;
|
||||
|
||||
return box;
|
||||
}
|
||||
@@ -383,28 +383,28 @@ namespace OpenNest
|
||||
var bounds = Parts.GetBoundingBox();
|
||||
|
||||
double width;
|
||||
double height;
|
||||
double length;
|
||||
|
||||
switch (Quadrant)
|
||||
{
|
||||
case 1:
|
||||
width = System.Math.Abs(bounds.Right) + EdgeSpacing.Right;
|
||||
height = System.Math.Abs(bounds.Top) + EdgeSpacing.Top;
|
||||
length = System.Math.Abs(bounds.Top) + EdgeSpacing.Top;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
width = System.Math.Abs(bounds.Left) + EdgeSpacing.Left;
|
||||
height = System.Math.Abs(bounds.Top) + EdgeSpacing.Top;
|
||||
length = System.Math.Abs(bounds.Top) + EdgeSpacing.Top;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
width = System.Math.Abs(bounds.Left) + EdgeSpacing.Left;
|
||||
height = System.Math.Abs(bounds.Bottom) + EdgeSpacing.Bottom;
|
||||
length = System.Math.Abs(bounds.Bottom) + EdgeSpacing.Bottom;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
width = System.Math.Abs(bounds.Right) + EdgeSpacing.Right;
|
||||
height = System.Math.Abs(bounds.Bottom) + EdgeSpacing.Bottom;
|
||||
length = System.Math.Abs(bounds.Bottom) + EdgeSpacing.Bottom;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -413,7 +413,7 @@ namespace OpenNest
|
||||
|
||||
Size = new Size(
|
||||
Helper.RoundUpToNearest(width, roundingFactor),
|
||||
Helper.RoundUpToNearest(height, roundingFactor));
|
||||
Helper.RoundUpToNearest(length, roundingFactor));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -422,7 +422,7 @@ namespace OpenNest
|
||||
/// <returns></returns>
|
||||
public double Area()
|
||||
{
|
||||
return Size.Width * Size.Height;
|
||||
return Size.Width * Size.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -503,7 +503,7 @@ namespace OpenNest
|
||||
|
||||
if (maxRight < work.Right)
|
||||
{
|
||||
var strip = new Box(maxRight, work.Bottom, work.Right - maxRight, work.Height);
|
||||
var strip = new Box(maxRight, work.Bottom, work.Right - maxRight, work.Length);
|
||||
if (strip.Area() > 1.0)
|
||||
results.Add(strip);
|
||||
}
|
||||
@@ -548,7 +548,7 @@ namespace OpenNest
|
||||
|
||||
if (minLeft > work.Left)
|
||||
{
|
||||
var strip = new Box(work.Left, work.Bottom, minLeft - work.Left, work.Height);
|
||||
var strip = new Box(work.Left, work.Bottom, minLeft - work.Left, work.Length);
|
||||
if (strip.Area() > 1.0)
|
||||
results.Add(strip);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user