mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-06 17:22:13 -04:00
fix(cutting): check every lead against all other material again
The second delta review compared the filtered checks with the previous implementation on 5,400 generated cases. Rapid checks matched in every case, but 114 lead checks differed: a long lead passing a small circle or arc well over 0.001 away was reported clear, while the native line/circle query, through rounding in its squared terms, reports a contact there. A coordinate limit and a fixed margin cannot bound that cancellation. Lead checks therefore examine every other part's material again, exactly as before the filter; LeadMaterialSnapshot no longer keeps an extent. Rapid checks, including the pre-post review's, keep skipping completed contours more than 0.001 clear of the rapid. The 900000-long lead beside a radius-0.0001 circle is a regression test. Planning a dense 144-part grid now takes about 19 s again (lead checks dominate); a new part order is still found where the old search gave up.
This commit is contained in:
1 parent
8c21c62ec3
commit
ea1270e1e7
4 files changed
+36
-18
No files matched your search
@@ -14,20 +14,12 @@ public sealed class LeadMaterialSnapshot
|
||||
{
|
||||
Rings = rings;
|
||||
Reason = reason;
|
||||
var extent = PostVerificationGeometry.Extent.None;
|
||||
foreach (var ring in rings)
|
||||
foreach (var curve in ring)
|
||||
extent = extent.Union(curve.Extent);
|
||||
Extent = extent;
|
||||
}
|
||||
|
||||
public bool IsComplete => Reason == null;
|
||||
public string Reason { get; }
|
||||
internal IReadOnlyList<PostVerificationGeometry.Curve[]> Rings { get; }
|
||||
|
||||
/// <summary>A conservative extent of every boundary; material lies within it.</summary>
|
||||
internal PostVerificationGeometry.Extent Extent { get; }
|
||||
|
||||
/// <summary>Capture a stable, clean, rotation-baked program, applying location once.
|
||||
/// Unsupported or malformed geometry produces an incomplete snapshot; cancellation throws.</summary>
|
||||
public static LeadMaterialSnapshot Capture(Program cleanProgram, Vector location,
|
||||
|
||||
@@ -84,13 +84,10 @@ public static class LeadPathValidator
|
||||
var failure = CheckMaterial(target, allowed);
|
||||
if (failure != null)
|
||||
return new(true, false, $"Lead motion {i} contacts or enters target material outside its adjacent contour joint ({failure}).");
|
||||
var reach = move.Curve.Extent;
|
||||
foreach (var material in otherMaterials)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
// Material lies within its extent, so a lead well clear of that extent can
|
||||
// neither touch it nor lie inside it.
|
||||
if (ReferenceEquals(material, target) || reach.IsClearOf(material.Extent))
|
||||
if (ReferenceEquals(material, target))
|
||||
continue;
|
||||
if (CheckMaterial(material, null) != null)
|
||||
return new(true, false, "Lead contacts or enters another placed material.");
|
||||
|
||||
@@ -6,8 +6,9 @@ using OpenNest.Geometry;
|
||||
namespace OpenNest.Tests.CuttingPlanning;
|
||||
|
||||
/// <summary>
|
||||
/// The lead and rapid checks skip material and contours whose extents are well clear of the
|
||||
/// motion. These cases sit just inside that skip and must still be checked.
|
||||
/// Rapid checks skip completed contours whose extents are well clear of the motion; lead checks
|
||||
/// examine every other part's material. These cases sit just inside the skip, or show that lead
|
||||
/// checks are never filtered, and must keep the native result.
|
||||
/// </summary>
|
||||
public class NearbyMaterialCheckTests
|
||||
{
|
||||
@@ -80,6 +81,31 @@ public class NearbyMaterialCheckTests
|
||||
Assert.Contains(findings, f => f.Kind == PostVerificationKind.RapidCrossing && f.OtherPartNumber == 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LeadCheck_ExaminesMaterialWellClearOfTheLead()
|
||||
{
|
||||
// A 900000-long lead passes 0.0021 from a radius-0.0001 circle: far more than any skip
|
||||
// margin, yet rounding in the native line/circle query reports a contact. Lead checks keep
|
||||
// that native result rather than skipping the circle.
|
||||
var target = LeadMaterialSnapshot.Capture(LeadPathValidationTests.Rectangle(0, -2, 2, 0.0021), Vector.Zero);
|
||||
var circle = new Program();
|
||||
circle.MoveTo(-1 + 0.0001, 0);
|
||||
circle.Codes.Add(new ArcMove(new Vector(-1 + 0.0001, 0), new Vector(-1, 0), RotationType.CCW));
|
||||
var far = LeadMaterialSnapshot.Capture(circle, Vector.Zero);
|
||||
Assert.True(far.IsComplete, far.Reason);
|
||||
var lead = new Program();
|
||||
lead.MoveTo(-900000, 0.0021);
|
||||
lead.Codes.Add(new LinearMove(0, 0.0021) { Layer = LayerType.Leadin });
|
||||
lead.LineTo(0, -2);
|
||||
var execution = Read(lead);
|
||||
Assert.True(LeadPathValidator.Check(execution, target, [target]).IsClear);
|
||||
|
||||
var result = LeadPathValidator.Check(execution, target, [target, far]);
|
||||
|
||||
Assert.True(result.IsComplete, result.Reason);
|
||||
Assert.False(result.IsClear);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RapidJustOutsideASmallCompletedCircle_IsStillACrossing()
|
||||
{
|
||||
|
||||
@@ -101,10 +101,13 @@ motions, never the nominal entry point alone. Existing lead styles are not
|
||||
shortened, disabled or substituted as a search fallback.
|
||||
|
||||
Every candidate rapid is checked against contours already completed, including
|
||||
earlier holes in the same part. Future contours are not yet obstacles. Rapid and
|
||||
lead checks skip contours and material whose extents are more than 0.001 clear
|
||||
of the motion, ten times the widest band any native contact query allows beyond an
|
||||
extent; anything closer, touching included, gets the full native check. An arc's
|
||||
earlier holes in the same part. Future contours are not yet obstacles. Rapid
|
||||
checks skip completed contours whose extents are more than 0.001 clear of the
|
||||
rapid, ten times the widest band any native contact query allows beyond an
|
||||
extent; anything closer, touching included, gets the full native check. Lead
|
||||
checks examine every other part's material: native line/circle queries can report
|
||||
rounding contacts for long leads far from small circles, and leads keep those
|
||||
results. An arc's
|
||||
extent is its whole supporting circle widened to the distance at which the native
|
||||
contact query still counts it as touched (for a very small arc up to 0.0001 beyond
|
||||
its radius). Nothing is skipped when either extent has a nonfinite bound or reaches
|
||||
|
||||
Reference in new issue
Block a user