style: apply CSharpier formatting to all C# sources

Repo-wide sweep with the pinned CSharpier 1.3.0 tool. Whitespace and
line-wrapping only; OpenNest.Engine.Tests (109) and OpenNest.IO.Tests
pass after reformat, full solution builds 0 errors.

Added .csharpierignore so csproj/config XML keeps its existing layout
(CSharpier's XML wrapping churns attributes with zero benefit).

Formatting is now enforceable: dotnet csharpier check . passes.
This commit is contained in:
aj
2026-09-20 16:41:50 -04:00
parent 8e6fa677fb
commit aec0523062
476 changed files with 16592 additions and 7800 deletions
+20 -7
View File
@@ -5,19 +5,28 @@ namespace OpenNest;
public static class AutoSplitCalculator
{
public static List<SplitLine> FitToPlate(Box partBounds, double plateWidth, double plateHeight,
double edgeSpacing, double featureOverhang)
public static List<SplitLine> FitToPlate(
Box partBounds,
double plateWidth,
double plateHeight,
double edgeSpacing,
double featureOverhang
)
{
var usableWidth = plateWidth - 2 * edgeSpacing - featureOverhang;
var usableHeight = plateHeight - 2 * edgeSpacing - featureOverhang;
var lines = new List<SplitLine>();
var verticalSplits = usableWidth > 0 ? (int)System.Math.Ceiling(partBounds.Length / usableWidth) - 1 : 0;
var horizontalSplits = usableHeight > 0 ? (int)System.Math.Ceiling(partBounds.Width / usableHeight) - 1 : 0;
var verticalSplits =
usableWidth > 0 ? (int)System.Math.Ceiling(partBounds.Length / usableWidth) - 1 : 0;
var horizontalSplits =
usableHeight > 0 ? (int)System.Math.Ceiling(partBounds.Width / usableHeight) - 1 : 0;
if (verticalSplits < 0) verticalSplits = 0;
if (horizontalSplits < 0) horizontalSplits = 0;
if (verticalSplits < 0)
verticalSplits = 0;
if (horizontalSplits < 0)
horizontalSplits = 0;
for (var i = 1; i <= verticalSplits; i++)
lines.Add(new SplitLine(partBounds.X + usableWidth * i, CutOffAxis.Vertical));
@@ -28,7 +37,11 @@ public static class AutoSplitCalculator
return lines;
}
public static List<SplitLine> SplitByCount(Box partBounds, int horizontalPieces, int verticalPieces)
public static List<SplitLine> SplitByCount(
Box partBounds,
int horizontalPieces,
int verticalPieces
)
{
var lines = new List<SplitLine>();
+212 -77
View File
@@ -10,7 +10,11 @@ namespace OpenNest;
/// </summary>
public static class DrawingSplitter
{
public static List<Drawing> Split(Drawing drawing, List<SplitLine> splitLines, SplitParameters parameters)
public static List<Drawing> Split(
Drawing drawing,
List<SplitLine> splitLines,
SplitParameters parameters
)
{
if (splitLines.Count == 0)
return new List<Drawing> { drawing };
@@ -35,8 +39,8 @@ public static class DrawingSplitter
// Polygonize cutouts once. Used for trimming feature edges (so cut lines
// don't travel through a cutout interior) and for hole/containment tests
// in the final component-assembly pass.
var cutoutPolygons = profile.Cutouts
.Select(c => c.ToPolygon())
var cutoutPolygons = profile
.Cutouts.Select(c => c.ToPolygon())
.Where(p => p != null)
.ToList();
@@ -45,7 +49,14 @@ public static class DrawingSplitter
foreach (var region in regions)
{
var pieceEntities = ClipPerimeterToRegion(perimeter, region, sortedLines, feature, parameters, cutoutPolygons);
var pieceEntities = ClipPerimeterToRegion(
perimeter,
region,
sortedLines,
feature,
parameters,
cutoutPolygons
);
if (pieceEntities.Count == 0)
continue;
@@ -72,13 +83,18 @@ public static class DrawingSplitter
private static ShapeProfile BuildProfile(Drawing drawing)
{
var entities = ConvertProgram.ToGeometry(drawing.Program)
var entities = ConvertProgram
.ToGeometry(drawing.Program)
.Where(e => e.Layer != SpecialLayers.Rapid)
.ToList();
return new ShapeProfile(entities);
}
private static List<Entity> CollectCutouts(List<Shape> cutouts, Box region, List<SplitLine> splitLines)
private static List<Entity> CollectCutouts(
List<Shape> cutouts,
Box region,
List<SplitLine> splitLines
)
{
var entities = new List<Entity>();
foreach (var cutout in cutouts)
@@ -95,7 +111,12 @@ public static class DrawingSplitter
return entities;
}
private static Drawing BuildPieceDrawing(Drawing source, List<Entity> entities, int pieceIndex, Box region)
private static Drawing BuildPieceDrawing(
Drawing source,
List<Entity> entities,
int pieceIndex,
Box region
)
{
var pieceBounds = entities.Select(e => e.BoundingBox).ToList().GetBoundingBox();
var offsetX = -pieceBounds.X;
@@ -123,15 +144,23 @@ public static class DrawingSplitter
if (clipped == null)
continue;
piece.Bends.Add(new Bending.Bend
{
StartPoint = new Vector(clipped.Value.Start.X + offsetX, clipped.Value.Start.Y + offsetY),
EndPoint = new Vector(clipped.Value.End.X + offsetX, clipped.Value.End.Y + offsetY),
Direction = bend.Direction,
Angle = bend.Angle,
Radius = bend.Radius,
NoteText = bend.NoteText,
});
piece.Bends.Add(
new Bending.Bend
{
StartPoint = new Vector(
clipped.Value.Start.X + offsetX,
clipped.Value.Start.Y + offsetY
),
EndPoint = new Vector(
clipped.Value.End.X + offsetX,
clipped.Value.End.Y + offsetY
),
Direction = bend.Direction,
Angle = bend.Angle,
Radius = bend.Radius,
NoteText = bend.NoteText,
}
);
}
}
@@ -146,10 +175,17 @@ public static class DrawingSplitter
{
var dx = end.X - start.X;
var dy = end.Y - start.Y;
double t0 = 0, t1 = 1;
double t0 = 0,
t1 = 1;
double[] p = { -dx, dx, -dy, dy };
double[] q = { start.X - box.Left, box.Right - start.X, start.Y - box.Bottom, box.Top - start.Y };
double[] q =
{
start.X - box.Left,
box.Right - start.X,
start.Y - box.Bottom,
box.Top - start.Y,
};
for (var i = 0; i < 4; i++)
{
@@ -190,7 +226,12 @@ public static class DrawingSplitter
if (shape.Entities[i] is Circle circle)
{
var arc1 = new Arc(circle.Center, circle.Radius, 0, System.Math.PI);
var arc2 = new Arc(circle.Center, circle.Radius, System.Math.PI, System.Math.PI * 2);
var arc2 = new Arc(
circle.Center,
circle.Radius,
System.Math.PI,
System.Math.PI * 2
);
shape.Entities.RemoveAt(i);
shape.Entities.Insert(i, arc2);
shape.Entities.Insert(i, arc1);
@@ -202,15 +243,21 @@ public static class DrawingSplitter
{
return line.Axis == CutOffAxis.Vertical
? line.Position > bounds.Left + OpenNest.Math.Tolerance.Epsilon
&& line.Position < bounds.Right - OpenNest.Math.Tolerance.Epsilon
&& line.Position < bounds.Right - OpenNest.Math.Tolerance.Epsilon
: line.Position > bounds.Bottom + OpenNest.Math.Tolerance.Epsilon
&& line.Position < bounds.Top - OpenNest.Math.Tolerance.Epsilon;
&& line.Position < bounds.Top - OpenNest.Math.Tolerance.Epsilon;
}
private static List<Box> BuildClipRegions(List<SplitLine> sortedLines, Box bounds)
{
var verticals = sortedLines.Where(l => l.Axis == CutOffAxis.Vertical).OrderBy(l => l.Position).ToList();
var horizontals = sortedLines.Where(l => l.Axis == CutOffAxis.Horizontal).OrderBy(l => l.Position).ToList();
var verticals = sortedLines
.Where(l => l.Axis == CutOffAxis.Vertical)
.OrderBy(l => l.Position)
.ToList();
var horizontals = sortedLines
.Where(l => l.Axis == CutOffAxis.Horizontal)
.OrderBy(l => l.Position)
.ToList();
var xEdges = new List<double> { bounds.Left };
xEdges.AddRange(verticals.Select(v => v.Position));
@@ -222,8 +269,15 @@ public static class DrawingSplitter
var regions = new List<Box>();
for (var yi = 0; yi < yEdges.Count - 1; yi++)
for (var xi = 0; xi < xEdges.Count - 1; xi++)
regions.Add(new Box(xEdges[xi], yEdges[yi], xEdges[xi + 1] - xEdges[xi], yEdges[yi + 1] - yEdges[yi]));
for (var xi = 0; xi < xEdges.Count - 1; xi++)
regions.Add(
new Box(
xEdges[xi],
yEdges[yi],
xEdges[xi + 1] - xEdges[xi],
yEdges[yi + 1] - yEdges[yi]
)
);
return regions;
}
@@ -232,9 +286,14 @@ public static class DrawingSplitter
/// Clip perimeter to a region by walking entities, splitting at split line crossings,
/// and stitching in feature edges. No polygon clipping library needed.
/// </summary>
private static List<Entity> ClipPerimeterToRegion(Shape perimeter, Box region,
List<SplitLine> splitLines, ISplitFeature feature, SplitParameters parameters,
List<Polygon> cutoutPolygons)
private static List<Entity> ClipPerimeterToRegion(
Shape perimeter,
Box region,
List<SplitLine> splitLines,
ISplitFeature feature,
SplitParameters parameters,
List<Polygon> cutoutPolygons
)
{
var boundarySplitLines = GetBoundarySplitLines(region, splitLines);
var entities = new List<Entity>();
@@ -245,7 +304,14 @@ public static class DrawingSplitter
if (entities.Count == 0)
return new List<Entity>();
InsertFeatureEdges(entities, region, boundarySplitLines, feature, parameters, cutoutPolygons);
InsertFeatureEdges(
entities,
region,
boundarySplitLines,
feature,
parameters,
cutoutPolygons
);
// Winding is handled later in AssemblePieces, once connected components
// are known. At this stage the piece may still be multiple disjoint loops.
return entities;
@@ -256,8 +322,10 @@ public static class DrawingSplitter
if (entity is Line line)
{
var clipped = ClipLineToBox(line.StartPoint, line.EndPoint, region);
if (clipped == null) return;
if (clipped.Value.Start.DistanceTo(clipped.Value.End) < Math.Tolerance.Epsilon) return;
if (clipped == null)
return;
if (clipped.Value.Start.DistanceTo(clipped.Value.End) < Math.Tolerance.Epsilon)
return;
entities.Add(new Line(clipped.Value.Start, clipped.Value.End));
return;
}
@@ -279,10 +347,13 @@ public static class DrawingSplitter
{
var edges = new[]
{
new Line(new Vector(region.Left, region.Bottom), new Vector(region.Right, region.Bottom)),
new Line(
new Vector(region.Left, region.Bottom),
new Vector(region.Right, region.Bottom)
),
new Line(new Vector(region.Right, region.Bottom), new Vector(region.Right, region.Top)),
new Line(new Vector(region.Right, region.Top), new Vector(region.Left, region.Top)),
new Line(new Vector(region.Left, region.Top), new Vector(region.Left, region.Bottom))
new Line(new Vector(region.Left, region.Top), new Vector(region.Left, region.Bottom)),
};
var arcs = new List<Arc> { arc };
@@ -308,7 +379,11 @@ public static class DrawingSplitter
foreach (var w in working)
{
var onArc = OpenNest.Math.Angle.IsBetweenRad(
w.Center.AngleTo(pt), w.StartAngle, w.EndAngle, w.IsReversed);
w.Center.AngleTo(pt),
w.StartAngle,
w.EndAngle,
w.IsReversed
);
if (!onArc)
{
replaced.Add(w);
@@ -316,8 +391,10 @@ public static class DrawingSplitter
}
var (first, second) = w.SplitAt(pt);
if (first != null && first.SweepAngle() > Math.Tolerance.Epsilon) replaced.Add(first);
if (second != null && second.SweepAngle() > Math.Tolerance.Epsilon) replaced.Add(second);
if (first != null && first.SweepAngle() > Math.Tolerance.Epsilon)
replaced.Add(first);
if (second != null && second.SweepAngle() > Math.Tolerance.Epsilon)
replaced.Add(second);
}
working = replaced;
}
@@ -345,14 +422,18 @@ public static class DrawingSplitter
{
if (sl.Axis == CutOffAxis.Vertical)
{
if (System.Math.Abs(sl.Position - region.Left) < OpenNest.Math.Tolerance.Epsilon
|| System.Math.Abs(sl.Position - region.Right) < OpenNest.Math.Tolerance.Epsilon)
if (
System.Math.Abs(sl.Position - region.Left) < OpenNest.Math.Tolerance.Epsilon
|| System.Math.Abs(sl.Position - region.Right) < OpenNest.Math.Tolerance.Epsilon
)
result.Add(sl);
}
else
{
if (System.Math.Abs(sl.Position - region.Bottom) < OpenNest.Math.Tolerance.Epsilon
|| System.Math.Abs(sl.Position - region.Top) < OpenNest.Math.Tolerance.Epsilon)
if (
System.Math.Abs(sl.Position - region.Bottom) < OpenNest.Math.Tolerance.Epsilon
|| System.Math.Abs(sl.Position - region.Top) < OpenNest.Math.Tolerance.Epsilon
)
result.Add(sl);
}
}
@@ -381,7 +462,8 @@ public static class DrawingSplitter
var midAngle = (arc.StartAngle + arc.EndAngle) / 2;
return new Vector(
arc.Center.X + arc.Radius * System.Math.Cos(midAngle),
arc.Center.Y + arc.Radius * System.Math.Sin(midAngle));
arc.Center.Y + arc.Radius * System.Math.Sin(midAngle)
);
}
return new Vector(0, 0);
@@ -395,10 +477,14 @@ public static class DrawingSplitter
/// crossing), spanning cutouts (two holes puncturing the line), and
/// normal mid-part splits uniformly.
/// </summary>
private static void InsertFeatureEdges(List<Entity> entities,
Box region, List<SplitLine> boundarySplitLines,
ISplitFeature feature, SplitParameters parameters,
List<Polygon> cutoutPolygons)
private static void InsertFeatureEdges(
List<Entity> entities,
Box region,
List<SplitLine> boundarySplitLines,
ISplitFeature feature,
SplitParameters parameters,
List<Polygon> cutoutPolygons
)
{
foreach (var sl in boundarySplitLines)
{
@@ -411,7 +497,9 @@ public static class DrawingSplitter
var featureResult = feature.GenerateFeatures(sl, extentStart, extentEnd, parameters);
var isNegativeSide = RegionSideOf(region, sl) < 0;
var featureEdge = isNegativeSide ? featureResult.NegativeSideEdge : featureResult.PositiveSideEdge;
var featureEdge = isNegativeSide
? featureResult.NegativeSideEdge
: featureResult.PositiveSideEdge;
// Trim any line segments that cross a cutout — cut lines must never
// travel through a hole.
@@ -427,7 +515,10 @@ public static class DrawingSplitter
/// passed through unchanged; a tighter fix for arcs in feature edges (weld-gap
/// tabs, spike-groove) can be added later if a test demands it.
/// </summary>
private static List<Entity> TrimFeatureEdgeAgainstCutouts(List<Entity> featureEdge, List<Polygon> cutoutPolygons)
private static List<Entity> TrimFeatureEdgeAgainstCutouts(
List<Entity> featureEdge,
List<Polygon> cutoutPolygons
)
{
if (cutoutPolygons.Count == 0 || featureEdge.Count == 0)
return featureEdge;
@@ -456,7 +547,15 @@ public static class DrawingSplitter
var polyLines = poly.ToLines();
foreach (var edge in polyLines)
{
if (TryIntersectSegments(line.StartPoint, line.EndPoint, edge.StartPoint, edge.EndPoint, out var t))
if (
TryIntersectSegments(
line.StartPoint,
line.EndPoint,
edge.StartPoint,
edge.EndPoint,
out var t
)
)
{
if (t > Math.Tolerance.Epsilon && t < 1.0 - Math.Tolerance.Epsilon)
ts.Add(t);
@@ -471,12 +570,14 @@ public static class DrawingSplitter
{
var t0 = ts[i];
var t1 = ts[i + 1];
if (t1 - t0 < Math.Tolerance.Epsilon) continue;
if (t1 - t0 < Math.Tolerance.Epsilon)
continue;
var tMid = (t0 + t1) * 0.5;
var mid = new Vector(
line.StartPoint.X + (line.EndPoint.X - line.StartPoint.X) * tMid,
line.StartPoint.Y + (line.EndPoint.Y - line.StartPoint.Y) * tMid);
line.StartPoint.Y + (line.EndPoint.Y - line.StartPoint.Y) * tMid
);
var insideCutout = false;
foreach (var poly in cutoutPolygons)
@@ -487,14 +588,17 @@ public static class DrawingSplitter
break;
}
}
if (insideCutout) continue;
if (insideCutout)
continue;
var p0 = new Vector(
line.StartPoint.X + (line.EndPoint.X - line.StartPoint.X) * t0,
line.StartPoint.Y + (line.EndPoint.Y - line.StartPoint.Y) * t0);
line.StartPoint.Y + (line.EndPoint.Y - line.StartPoint.Y) * t0
);
var p1 = new Vector(
line.StartPoint.X + (line.EndPoint.X - line.StartPoint.X) * t1,
line.StartPoint.Y + (line.EndPoint.Y - line.StartPoint.Y) * t1);
line.StartPoint.Y + (line.EndPoint.Y - line.StartPoint.Y) * t1
);
segments.Add(new Line(p0, p1));
}
@@ -506,7 +610,13 @@ public static class DrawingSplitter
/// Segment-segment intersection. On hit, returns the parameter t along segment AB
/// (0 = a0, 1 = a1) via <paramref name="tOnA"/>.
/// </summary>
private static bool TryIntersectSegments(Vector a0, Vector a1, Vector b0, Vector b1, out double tOnA)
private static bool TryIntersectSegments(
Vector a0,
Vector a1,
Vector b0,
Vector b1,
out double tOnA
)
{
tOnA = 0;
var rx = a1.X - a0.X;
@@ -523,8 +633,10 @@ public static class DrawingSplitter
var t = (dx * sy - dy * sx) / denom;
var u = (dx * ry - dy * rx) / denom;
if (t < -Math.Tolerance.Epsilon || t > 1 + Math.Tolerance.Epsilon) return false;
if (u < -Math.Tolerance.Epsilon || u > 1 + Math.Tolerance.Epsilon) return false;
if (t < -Math.Tolerance.Epsilon || t > 1 + Math.Tolerance.Epsilon)
return false;
if (u < -Math.Tolerance.Epsilon || u > 1 + Math.Tolerance.Epsilon)
return false;
tOnA = t;
return true;
@@ -532,7 +644,8 @@ public static class DrawingSplitter
private static bool IsCutoutInRegion(Shape cutout, Box region)
{
if (cutout.Entities.Count == 0) return false;
if (cutout.Entities.Count == 0)
return false;
var bb = cutout.BoundingBox;
// Fully contained iff the cutout's bounding box fits inside the region.
return bb.Left >= region.Left - Math.Tolerance.Epsilon
@@ -566,7 +679,11 @@ public static class DrawingSplitter
/// using endpoint connectivity, which produces the correct closed loops — one
/// loop per physically-connected strip of material.
/// </summary>
private static List<Entity> ClipCutoutToRegion(Shape cutout, Box region, List<SplitLine> splitLines)
private static List<Entity> ClipCutoutToRegion(
Shape cutout,
Box region,
List<SplitLine> splitLines
)
{
var entities = new List<Entity>();
foreach (var entity in cutout.Entities)
@@ -583,10 +700,12 @@ public static class DrawingSplitter
private static List<List<Entity>> AssemblePieces(List<Entity> entities)
{
var pieces = new List<List<Entity>>();
if (entities.Count == 0) return pieces;
if (entities.Count == 0)
return pieces;
var shapes = ShapeBuilder.GetShapes(entities);
if (shapes.Count == 0) return pieces;
if (shapes.Count == 0)
return pieces;
// Polygonize every shape once so we can run containment tests.
var polygons = new List<Polygon>(shapes.Count);
@@ -606,13 +725,18 @@ public static class DrawingSplitter
for (var j = 0; j < shapes.Count; j++)
{
if (i == j) continue;
if (polygons[j] == null) continue;
if (polygons[j].Vertices.Count < 3) continue;
if (i == j)
continue;
if (polygons[j] == null)
continue;
if (polygons[j].Vertices.Count < 3)
continue;
var bbB = shapes[j].BoundingBox;
if (!BoxContainsBox(bbB, bbA)) continue;
if (!polygons[j].ContainsPoint(repA)) continue;
if (!BoxContainsBox(bbB, bbA))
continue;
if (!polygons[j].ContainsPoint(repA))
continue;
isHole[i] = true;
break;
@@ -622,14 +746,18 @@ public static class DrawingSplitter
// For each outer, attach the holes that fall inside it.
for (var i = 0; i < shapes.Count; i++)
{
if (isHole[i]) continue;
if (isHole[i])
continue;
var outer = shapes[i];
var outerPoly = polygons[i];
// Enforce perimeter winding = CW.
if (outerPoly != null && outerPoly.Vertices.Count >= 3
&& outerPoly.RotationDirection() != RotationType.CW)
if (
outerPoly != null
&& outerPoly.Vertices.Count >= 3
&& outerPoly.RotationDirection() != RotationType.CW
)
outer.Reverse();
var piece = new List<Entity>();
@@ -637,19 +765,26 @@ public static class DrawingSplitter
for (var j = 0; j < shapes.Count; j++)
{
if (!isHole[j]) continue;
if (polygons[i] == null || polygons[i].Vertices.Count < 3) continue;
if (!isHole[j])
continue;
if (polygons[i] == null || polygons[i].Vertices.Count < 3)
continue;
var bbJ = shapes[j].BoundingBox;
if (!BoxContainsBox(shapes[i].BoundingBox, bbJ)) continue;
if (!BoxContainsBox(shapes[i].BoundingBox, bbJ))
continue;
var rep = FirstVertexOf(shapes[j]);
if (!polygons[i].ContainsPoint(rep)) continue;
if (!polygons[i].ContainsPoint(rep))
continue;
var hole = shapes[j];
var holePoly = polygons[j];
if (holePoly != null && holePoly.Vertices.Count >= 3
&& holePoly.RotationDirection() != RotationType.CCW)
if (
holePoly != null
&& holePoly.Vertices.Count >= 3
&& holePoly.RotationDirection() != RotationType.CCW
)
hole.Reverse();
piece.AddRange(hole.Entities);
@@ -692,7 +827,7 @@ public static class DrawingSplitter
{
Line l => l.StartPoint,
Arc a => a.StartPoint(),
_ => new Vector(0, 0)
_ => new Vector(0, 0),
};
}
@@ -702,7 +837,7 @@ public static class DrawingSplitter
{
Line l => l.EndPoint,
Arc a => a.EndPoint(),
_ => new Vector(0, 0)
_ => new Vector(0, 0),
};
}
@@ -713,7 +848,7 @@ public static class DrawingSplitter
SplitType.Straight => new StraightSplit(),
SplitType.WeldGapTabs => new WeldGapTabSplit(),
SplitType.SpikeGroove => new SpikeGrooveSplit(),
_ => new StraightSplit()
_ => new StraightSplit(),
};
}
}
+6 -1
View File
@@ -18,5 +18,10 @@ public class SplitFeatureResult
public interface ISplitFeature
{
string Name { get; }
SplitFeatureResult GenerateFeatures(SplitLine line, double extentStart, double extentEnd, SplitParameters parameters);
SplitFeatureResult GenerateFeatures(
SplitLine line,
double extentStart,
double extentEnd,
SplitParameters parameters
);
}
+49 -8
View File
@@ -13,7 +13,12 @@ public class SpikeGrooveSplit : ISplitFeature
{
public string Name => "Spike / V-Groove";
public SplitFeatureResult GenerateFeatures(SplitLine line, double extentStart, double extentEnd, SplitParameters parameters)
public SplitFeatureResult GenerateFeatures(
SplitLine line,
double extentStart,
double extentEnd,
SplitParameters parameters
)
{
var extent = extentEnd - extentStart;
var pairCount = parameters.SpikePairCount;
@@ -44,14 +49,37 @@ public class SpikeGrooveSplit : ISplitFeature
pairPositions.Add(extentStart + margin + usable * i / (pairCount - 1));
}
var negEntities = BuildGrooveSide(pairPositions, grooveHalfWidth, grooveDepth, extentStart, extentEnd, pos, isVertical);
var posEntities = BuildSpikeSide(pairPositions, spikeHalfWidth, spikeDepth, extentStart, extentEnd, pos, isVertical);
var negEntities = BuildGrooveSide(
pairPositions,
grooveHalfWidth,
grooveDepth,
extentStart,
extentEnd,
pos,
isVertical
);
var posEntities = BuildSpikeSide(
pairPositions,
spikeHalfWidth,
spikeDepth,
extentStart,
extentEnd,
pos,
isVertical
);
return new SplitFeatureResult(negEntities, posEntities);
}
private static List<Entity> BuildGrooveSide(List<double> pairPositions, double halfWidth, double depth,
double extentStart, double extentEnd, double pos, bool isVertical)
private static List<Entity> BuildGrooveSide(
List<double> pairPositions,
double halfWidth,
double depth,
double extentStart,
double extentEnd,
double pos,
bool isVertical
)
{
var entities = new List<Entity>();
var cursor = extentStart;
@@ -76,8 +104,15 @@ public class SpikeGrooveSplit : ISplitFeature
return entities;
}
private static List<Entity> BuildSpikeSide(List<double> pairPositions, double halfWidth, double depth,
double extentStart, double extentEnd, double pos, bool isVertical)
private static List<Entity> BuildSpikeSide(
List<double> pairPositions,
double halfWidth,
double depth,
double extentStart,
double extentEnd,
double pos,
bool isVertical
)
{
var entities = new List<Entity>();
var cursor = extentEnd;
@@ -103,7 +138,13 @@ public class SpikeGrooveSplit : ISplitFeature
return entities;
}
private static Line MakeLine(double splitAxis1, double along1, double splitAxis2, double along2, bool isVertical)
private static Line MakeLine(
double splitAxis1,
double along1,
double splitAxis2,
double along2,
bool isVertical
)
{
return isVertical
? new Line(new Vector(splitAxis1, along1), new Vector(splitAxis2, along2))
+1 -1
View File
@@ -1,5 +1,5 @@
using OpenNest.Geometry;
using System.Collections.Generic;
using OpenNest.Geometry;
namespace OpenNest;
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using OpenNest.Geometry;
using OpenNest.Math;
using System.Collections.Generic;
namespace OpenNest;
+8 -7
View File
@@ -4,7 +4,7 @@ public enum SplitType
{
Straight,
WeldGapTabs,
SpikeGroove
SpikeGroove,
}
public class SplitParameters
@@ -26,10 +26,11 @@ public class SplitParameters
/// <summary>
/// Max protrusion from the split edge (for auto-fit plate size calculation).
/// </summary>
public double FeatureOverhang => Type switch
{
SplitType.WeldGapTabs => TabHeight,
SplitType.SpikeGroove => System.Math.Max(SpikeDepth, GrooveDepth),
_ => 0
};
public double FeatureOverhang =>
Type switch
{
SplitType.WeldGapTabs => TabHeight,
SplitType.SpikeGroove => System.Math.Max(SpikeDepth, GrooveDepth),
_ => 0,
};
}
+29 -9
View File
@@ -7,16 +7,36 @@ public class StraightSplit : ISplitFeature
{
public string Name => "Straight";
public SplitFeatureResult GenerateFeatures(SplitLine line, double extentStart, double extentEnd, SplitParameters parameters)
public SplitFeatureResult GenerateFeatures(
SplitLine line,
double extentStart,
double extentEnd,
SplitParameters parameters
)
{
var (negEdge, posEdge) = line.Axis == CutOffAxis.Vertical
? (new Line(new Vector(line.Position, extentStart), new Vector(line.Position, extentEnd)),
new Line(new Vector(line.Position, extentEnd), new Vector(line.Position, extentStart)))
: (new Line(new Vector(extentStart, line.Position), new Vector(extentEnd, line.Position)),
new Line(new Vector(extentEnd, line.Position), new Vector(extentStart, line.Position)));
var (negEdge, posEdge) =
line.Axis == CutOffAxis.Vertical
? (
new Line(
new Vector(line.Position, extentStart),
new Vector(line.Position, extentEnd)
),
new Line(
new Vector(line.Position, extentEnd),
new Vector(line.Position, extentStart)
)
)
: (
new Line(
new Vector(extentStart, line.Position),
new Vector(extentEnd, line.Position)
),
new Line(
new Vector(extentEnd, line.Position),
new Vector(extentStart, line.Position)
)
);
return new SplitFeatureResult(
new List<Entity> { negEdge },
new List<Entity> { posEdge });
return new SplitFeatureResult(new List<Entity> { negEdge }, new List<Entity> { posEdge });
}
}
+36 -7
View File
@@ -11,7 +11,12 @@ public class WeldGapTabSplit : ISplitFeature
{
public string Name => "Weld-Gap Tabs";
public SplitFeatureResult GenerateFeatures(SplitLine line, double extentStart, double extentEnd, SplitParameters parameters)
public SplitFeatureResult GenerateFeatures(
SplitLine line,
double extentStart,
double extentEnd,
SplitParameters parameters
)
{
var extent = extentEnd - extentStart;
var tabCount = parameters.TabCount;
@@ -51,18 +56,42 @@ public class WeldGapTabSplit : ISplitFeature
if (tabStart > cursor + OpenNest.Math.Tolerance.Epsilon)
negEntities.Add(new Line(new Vector(pos, cursor), new Vector(pos, tabStart)));
negEntities.Add(new Line(new Vector(pos, tabStart), new Vector(pos + tabDir * tabHeight, tabStart)));
negEntities.Add(new Line(new Vector(pos + tabDir * tabHeight, tabStart), new Vector(pos + tabDir * tabHeight, tabEnd)));
negEntities.Add(new Line(new Vector(pos + tabDir * tabHeight, tabEnd), new Vector(pos, tabEnd)));
negEntities.Add(
new Line(
new Vector(pos, tabStart),
new Vector(pos + tabDir * tabHeight, tabStart)
)
);
negEntities.Add(
new Line(
new Vector(pos + tabDir * tabHeight, tabStart),
new Vector(pos + tabDir * tabHeight, tabEnd)
)
);
negEntities.Add(
new Line(new Vector(pos + tabDir * tabHeight, tabEnd), new Vector(pos, tabEnd))
);
}
else
{
if (tabStart > cursor + OpenNest.Math.Tolerance.Epsilon)
negEntities.Add(new Line(new Vector(cursor, pos), new Vector(tabStart, pos)));
negEntities.Add(new Line(new Vector(tabStart, pos), new Vector(tabStart, pos + tabDir * tabHeight)));
negEntities.Add(new Line(new Vector(tabStart, pos + tabDir * tabHeight), new Vector(tabEnd, pos + tabDir * tabHeight)));
negEntities.Add(new Line(new Vector(tabEnd, pos + tabDir * tabHeight), new Vector(tabEnd, pos)));
negEntities.Add(
new Line(
new Vector(tabStart, pos),
new Vector(tabStart, pos + tabDir * tabHeight)
)
);
negEntities.Add(
new Line(
new Vector(tabStart, pos + tabDir * tabHeight),
new Vector(tabEnd, pos + tabDir * tabHeight)
)
);
negEntities.Add(
new Line(new Vector(tabEnd, pos + tabDir * tabHeight), new Vector(tabEnd, pos))
);
}
cursor = tabEnd;