fix: use chain tolerance for shape building to handle DXF endpoint gaps
DXF files can have endpoint gaps at entity junctions that fall right at the floating-point boundary of Tolerance.Epsilon (0.00001). This caused shapes to not close, resulting in 0 area and 0% utilization in Best-Fit. Added ChainTolerance (0.0001) for endpoint chaining in GetConnected and Shape.IsClosed, keeping the tighter Epsilon for geometric precision. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ namespace OpenNest.Geometry
|
|||||||
if (Entities.Count == 0)
|
if (Entities.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
var tol = Math.Tolerance.ChainTolerance;
|
||||||
var first = Entities[0];
|
var first = Entities[0];
|
||||||
Vector firstStartPoint;
|
Vector firstStartPoint;
|
||||||
Vector firstEndPoint;
|
Vector firstEndPoint;
|
||||||
@@ -65,7 +66,7 @@ namespace OpenNest.Geometry
|
|||||||
case EntityType.Arc:
|
case EntityType.Arc:
|
||||||
var arc = (Arc)geo;
|
var arc = (Arc)geo;
|
||||||
|
|
||||||
if (arc.StartPoint() != endpt)
|
if (arc.StartPoint().DistanceTo(endpt) > tol)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
endpt = arc.EndPoint();
|
endpt = arc.EndPoint();
|
||||||
@@ -77,7 +78,7 @@ namespace OpenNest.Geometry
|
|||||||
case EntityType.Line:
|
case EntityType.Line:
|
||||||
var line = (Line)geo;
|
var line = (Line)geo;
|
||||||
|
|
||||||
if (line.StartPoint != endpt)
|
if (line.StartPoint.DistanceTo(endpt) > tol)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
endpt = line.EndPoint;
|
endpt = line.EndPoint;
|
||||||
@@ -112,7 +113,7 @@ namespace OpenNest.Geometry
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lastEndPoint == firstStartPoint;
|
return lastEndPoint.DistanceTo(firstStartPoint) <= tol;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -339,6 +339,8 @@ namespace OpenNest
|
|||||||
|
|
||||||
internal static Entity GetConnected(Vector pt, IEnumerable<Entity> geometry)
|
internal static Entity GetConnected(Vector pt, IEnumerable<Entity> geometry)
|
||||||
{
|
{
|
||||||
|
var tol = Math.Tolerance.ChainTolerance;
|
||||||
|
|
||||||
foreach (var geo in geometry)
|
foreach (var geo in geometry)
|
||||||
{
|
{
|
||||||
switch (geo.Type)
|
switch (geo.Type)
|
||||||
@@ -346,10 +348,10 @@ namespace OpenNest
|
|||||||
case EntityType.Arc:
|
case EntityType.Arc:
|
||||||
var arc = (Arc)geo;
|
var arc = (Arc)geo;
|
||||||
|
|
||||||
if (arc.StartPoint() == pt)
|
if (arc.StartPoint().DistanceTo(pt) <= tol)
|
||||||
return arc;
|
return arc;
|
||||||
|
|
||||||
if (arc.EndPoint() == pt)
|
if (arc.EndPoint().DistanceTo(pt) <= tol)
|
||||||
{
|
{
|
||||||
arc.Reverse();
|
arc.Reverse();
|
||||||
return arc;
|
return arc;
|
||||||
@@ -360,10 +362,10 @@ namespace OpenNest
|
|||||||
case EntityType.Line:
|
case EntityType.Line:
|
||||||
var line = (Line)geo;
|
var line = (Line)geo;
|
||||||
|
|
||||||
if (line.StartPoint == pt)
|
if (line.StartPoint.DistanceTo(pt) <= tol)
|
||||||
return line;
|
return line;
|
||||||
|
|
||||||
if (line.EndPoint == pt)
|
if (line.EndPoint.DistanceTo(pt) <= tol)
|
||||||
{
|
{
|
||||||
line.Reverse();
|
line.Reverse();
|
||||||
return line;
|
return line;
|
||||||
|
|||||||
@@ -6,6 +6,12 @@ namespace OpenNest.Math
|
|||||||
{
|
{
|
||||||
public const double Epsilon = 0.00001;
|
public const double Epsilon = 0.00001;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tolerance for chaining entity endpoints when building shapes from DXF imports.
|
||||||
|
/// Larger than Epsilon to handle floating-point gaps at entity junctions.
|
||||||
|
/// </summary>
|
||||||
|
public const double ChainTolerance = 0.0001;
|
||||||
|
|
||||||
public static bool IsEqualTo(this double a, double b, double tolerance = Epsilon)
|
public static bool IsEqualTo(this double a, double b, double tolerance = Epsilon)
|
||||||
{
|
{
|
||||||
return System.Math.Abs(b - a) <= tolerance;
|
return System.Math.Abs(b - a) <= tolerance;
|
||||||
|
|||||||
Reference in New Issue
Block a user