mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 03:51:05 -04:00
fix(geometry): treat near-joint contacts as the joint when classifying slides
Drawing data can fix a fillet's center slightly off the tangent normal, so the arc's end sits ~1e-7 past its neighbouring line's end. The slide contact classifier only joined entities within 1e-7, so a contact at that tangent point read as two boundaries, was classified ambiguous and blocked the push. In N26-243 this stopped a part pushed left along another once the parts aligned. Contacts within 1e-6 of a joint now take the joint's tangents; the 1e-7 incidence tolerance is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ba55d5bff0
commit
fa70713bfc
2 files changed
+29
-2
No files matched your search
@@ -36,6 +36,11 @@ namespace OpenNest.Geometry
|
||||
// tangential classification can admit, so keep it far below spacing tolerances.
|
||||
internal const double IncidenceTolerance = 1e-7;
|
||||
|
||||
// Drawing data fixes arc centers to finite precision, so a tangent joint's arc end
|
||||
// can sit a little past its neighbour's end. A contact this close to a joint takes
|
||||
// the joint's tangents; otherwise the neighbour reads as a second boundary there.
|
||||
internal const double JointTolerance = 1e-6;
|
||||
|
||||
private readonly List<Entity> entities;
|
||||
private readonly int[] loopOf;
|
||||
private readonly int[] previous;
|
||||
@@ -254,11 +259,11 @@ namespace OpenNest.Geometry
|
||||
|
||||
private bool StartsNear(int index, Vector point) =>
|
||||
TryEndpoints(entities[index], out var start, out _)
|
||||
&& start.DistanceTo(point) <= IncidenceTolerance;
|
||||
&& start.DistanceTo(point) <= JointTolerance;
|
||||
|
||||
private bool EndsNear(int index, Vector point) =>
|
||||
TryEndpoints(entities[index], out _, out var end)
|
||||
&& end.DistanceTo(point) <= IncidenceTolerance;
|
||||
&& end.DistanceTo(point) <= JointTolerance;
|
||||
|
||||
private bool InRun(int index, int first, int last)
|
||||
{
|
||||
|
||||
@@ -147,6 +147,28 @@ public class SlideContactTests
|
||||
Assert.Equal(double.MaxValue, EntityDistance(cpu, moving, stationary, new Vector(1, 0)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void FilletWithImpreciseCenter_DoesNotBlockSlidingAlongItsTangentLine(bool cpu)
|
||||
{
|
||||
// N26-243: the G-code fixes the fillet center 1.04e-7 off the tangent normal, so
|
||||
// the arc's top lies just past the flat edge's end rather than on the joint.
|
||||
var offset = 1.043e-7;
|
||||
var fillet = new Arc(new Vector(2 - offset, 0.5), System.Math.Sqrt(1 + offset * offset),
|
||||
0, System.Math.Atan2(1, offset), false);
|
||||
var stationary = new List<Entity>
|
||||
{
|
||||
new Line(0, 0, 3, 0),
|
||||
new Line(new Vector(3, 0), fillet.StartPoint()),
|
||||
fillet,
|
||||
new Line(fillet.EndPoint(), new Vector(0, 1.5)),
|
||||
new Line(0, 1.5, 0, 0),
|
||||
};
|
||||
var moving = Rect(1, 1.5, 2, 1).Cast<Entity>().ToList();
|
||||
Assert.Equal(double.MaxValue, EntityDistance(cpu, moving, stationary, new Vector(-1, 0)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
|
||||
Reference in new issue
Block a user