mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-03 19:22:10 -04:00
fix(irregular): keep exact bounds for line-only part outlines
Orientation bounds were padded by the arc chord tolerance even when the outline has no arcs, so a part that exactly fills the work area after rotation was rejected before packing. Pad only outlines with flattened arcs; footprints and NFPs still use the chord tolerance.
This commit is contained in:
1 parent
c7b4ba4457
commit
25755a8850
1 file changed
+16
-8
@@ -25,7 +25,11 @@ internal sealed class Orientation
|
|||||||
/// <summary>Chord deviation used for arcs; footprints are grown by it to stay conservative.</summary>
|
/// <summary>Chord deviation used for arcs; footprints are grown by it to stay conservative.</summary>
|
||||||
public required double Tolerance { get; init; }
|
public required double Tolerance { get; init; }
|
||||||
|
|
||||||
/// <summary>Outline bounds grown by the tolerance, so they contain the true perimeter.</summary>
|
/// <summary>
|
||||||
|
/// Outline bounds grown by the outline's actual flattening error, so they contain the true
|
||||||
|
/// perimeter: by <see cref="Tolerance"/> when arcs were flattened, not at all for line-only
|
||||||
|
/// outlines, whose vertices are exact. Footprints and NFPs still use <see cref="Tolerance"/>.
|
||||||
|
/// </summary>
|
||||||
public required double MinX { get; init; }
|
public required double MinX { get; init; }
|
||||||
public required double MinY { get; init; }
|
public required double MinY { get; init; }
|
||||||
public required double MaxX { get; init; }
|
public required double MaxX { get; init; }
|
||||||
@@ -96,7 +100,7 @@ internal static class PartCatalog
|
|||||||
var outline = Polygonize(perimeter, angle, tolerance);
|
var outline = Polygonize(perimeter, angle, tolerance);
|
||||||
if (outline.Count < 3)
|
if (outline.Count < 3)
|
||||||
continue;
|
continue;
|
||||||
orientations.Add(MakeOrientation(index, orientations.Count, angle, outline, tolerance));
|
orientations.Add(MakeOrientation(index, orientations.Count, angle, outline, tolerance, perimeter));
|
||||||
}
|
}
|
||||||
|
|
||||||
var area = orientations.Count == 0 ? 0 : System.Math.Abs(Clipper.Area(orientations[0].Outline));
|
var area = orientations.Count == 0 ? 0 : System.Math.Abs(Clipper.Area(orientations[0].Outline));
|
||||||
@@ -123,7 +127,7 @@ internal static class PartCatalog
|
|||||||
return null;
|
return null;
|
||||||
var tolerance = type.Orientations[0].Tolerance;
|
var tolerance = type.Orientations[0].Tolerance;
|
||||||
var outline = Polygonize(type.Perimeter, angle, tolerance);
|
var outline = Polygonize(type.Perimeter, angle, tolerance);
|
||||||
return outline.Count < 3 ? null : MakeOrientation(type.Index, index, angle, outline, tolerance);
|
return outline.Count < 3 ? null : MakeOrientation(type.Index, index, angle, outline, tolerance, type.Perimeter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Shape? ReadPerimeter(PartGeometrySnapshot geometry) =>
|
private static Shape? ReadPerimeter(PartGeometrySnapshot geometry) =>
|
||||||
@@ -163,9 +167,13 @@ internal static class PartCatalog
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Orientation MakeOrientation(int typeIndex, int index, double angle, PathD outline, double tolerance)
|
private static Orientation MakeOrientation(int typeIndex, int index, double angle, PathD outline,
|
||||||
|
double tolerance, Shape perimeter)
|
||||||
{
|
{
|
||||||
var bounds = Clipper.GetBounds(outline);
|
var bounds = Clipper.GetBounds(outline);
|
||||||
|
// Only flattened arcs deviate from the true perimeter; line vertices are exact, so a
|
||||||
|
// line-only part keeps its nominal material bounds and can fill its work area exactly.
|
||||||
|
var padding = perimeter.Entities.All(e => e.Type == EntityType.Line) ? 0 : tolerance;
|
||||||
return new Orientation
|
return new Orientation
|
||||||
{
|
{
|
||||||
TypeIndex = typeIndex,
|
TypeIndex = typeIndex,
|
||||||
@@ -173,10 +181,10 @@ internal static class PartCatalog
|
|||||||
Rotation = angle,
|
Rotation = angle,
|
||||||
Outline = outline,
|
Outline = outline,
|
||||||
Tolerance = tolerance,
|
Tolerance = tolerance,
|
||||||
MinX = bounds.left - tolerance,
|
MinX = bounds.left - padding,
|
||||||
MinY = bounds.top - tolerance, // Clipper RectD: top is the minimum Y.
|
MinY = bounds.top - padding, // Clipper RectD: top is the minimum Y.
|
||||||
MaxX = bounds.right + tolerance,
|
MaxX = bounds.right + padding,
|
||||||
MaxY = bounds.bottom + tolerance,
|
MaxY = bounds.bottom + padding,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user