mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-14 18:21:55 -04:00
fix(clamps): judge tiny keep-outs tolerance-free in interactive fill
InteractiveClamps.MaterialInKeepOut flattened a sub-tolerance keep-out with the 0.001 polygon tolerance and called a part covering a 1e-5 clamp clear, so the fill safety net could pass it. Keep-outs below the tolerance now use KeepOutOverlap. Adds the 1e-5 zone sweep through every fill strategy and a push (characterization; both already stay clear). PM b0062c73-40ef-440e-8efb-b94908f7c2d1
This commit is contained in:
1 parent
8f0c0692fd
commit
9b5885e5a2
2 files changed
+60
No files matched your search
@@ -1,5 +1,7 @@
|
||||
using OpenNest.CNC;
|
||||
using OpenNest.Engine.Fill;
|
||||
using OpenNest.Engine.Jobs;
|
||||
using OpenNest.Engine.Jobs.Placement;
|
||||
using OpenNest.Engine.NestingEngines.Default;
|
||||
using OpenNest.Engine.NestingEngines.Rectangles;
|
||||
using OpenNest.Geometry;
|
||||
@@ -131,4 +133,57 @@ public class TinyClampZoneTests
|
||||
|
||||
Assert.Equal(overlaps, ClampViolations(job, result).Count > 0);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(7.5, 0.0, true)]
|
||||
[InlineData(6.0, 0.0, false)]
|
||||
[InlineData(8.00001, 0.0, false)]
|
||||
[InlineData(3.0, 0.0, false)]
|
||||
public void InteractiveKeepOutTestJudgesATinyClamp(double x, double y, bool overlaps)
|
||||
{
|
||||
var drawing = new Drawing("square", SquareProgram());
|
||||
var part = new Part(drawing, new Vector(x, y));
|
||||
Assert.Equal(overlaps, InteractiveClamps.MaterialInKeepOut(part, new Box(8, 0, Tiny, Tiny)));
|
||||
}
|
||||
private static Plate TinyZonePlate()
|
||||
{
|
||||
var plate = new Plate(new Size(10, 12)); // zero edge and part spacing
|
||||
plate.ClampZones.Add(TinyZone);
|
||||
return plate;
|
||||
}
|
||||
|
||||
// Positive-area overlap with the zone, admitting 1e-9 of floating closure (a ten
|
||||
// thousandth of the zone): a push that stops flush on the zone is clear.
|
||||
private static bool EntersTinyZone(Part part) =>
|
||||
System.Math.Min(part.BoundingBox.Right, 8 + Tiny) - System.Math.Max(part.BoundingBox.Left, 8) > 1e-9
|
||||
&& System.Math.Min(part.BoundingBox.Top, Tiny) - System.Math.Max(part.BoundingBox.Bottom, 0) > 1e-9;
|
||||
|
||||
[Theory]
|
||||
[InlineData("Fill")]
|
||||
[InlineData("Strip")]
|
||||
[InlineData("Vertical Remnant")]
|
||||
[InlineData("Horizontal Remnant")]
|
||||
public void InteractiveFillNeverCoversATinyClamp(string strategy)
|
||||
{
|
||||
var plate = TinyZonePlate();
|
||||
var item = new NestItem { Drawing = new Drawing("square", SquareProgram()), Quantity = 30 };
|
||||
|
||||
var parts = PlateFillService.FillItem(strategy, plate, item, plate.WorkArea(), null,
|
||||
System.Threading.CancellationToken.None);
|
||||
|
||||
Assert.NotEmpty(parts);
|
||||
Assert.DoesNotContain(parts, EntersTinyZone);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PushDownStopsBeforeCoveringATinyClamp()
|
||||
{
|
||||
var plate = TinyZonePlate();
|
||||
var mover = new Part(new Drawing("square", SquareProgram()), new Vector(7.5, 5));
|
||||
plate.Parts.Add(mover);
|
||||
|
||||
Compactor.Push(new List<Part> { mover }, plate, PushDirection.Down);
|
||||
|
||||
Assert.False(EntersTinyZone(mover), $"pushed to ({mover.Location.X:R},{mover.Location.Y:R})");
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,11 @@ internal static class InteractiveClamps
|
||||
var partProfile = new ShapeProfile(PartGeometry.GetPartEntities(part));
|
||||
if (partProfile.Perimeter == null)
|
||||
return true;
|
||||
// A keep-out below the polygon tolerance collapses in the tolerant test and would
|
||||
// read as clear (PM b0062c73); judge it tolerance-free instead.
|
||||
if (KeepOutOverlap.NeedsToleranceFreeTest(keepOut))
|
||||
return KeepOutOverlap.MaterialEnters(partProfile.Perimeter.ToPolygonWithTolerance(0.001),
|
||||
HolePolygons(partProfile), keepOut);
|
||||
var zoneProfile = new ShapeProfile(RectangleEntities(keepOut));
|
||||
if (zoneProfile.Perimeter == null)
|
||||
return true;
|
||||
|
||||
Reference in new issue
Block a user