From b96f58cfd771855480f585f58c60162ac727d727 Mon Sep 17 00:00:00 2001 From: oceanful <35951082+oceanful@users.noreply.github.com> Date: Fri, 17 May 2019 15:25:50 -0700 Subject: [PATCH] Improve intersection precision to reduce false positives. (#9) --- bugs_test.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ clipper.go | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/bugs_test.go b/bugs_test.go index c5f14c3..ff23ece 100644 --- a/bugs_test.go +++ b/bugs_test.go @@ -287,6 +287,55 @@ func TestResweepingIntersectingEndpoints(t *T) { }.verify(t) } +func TestIntersectionFalsePositives(t *T) { + testCases{ + { + op: polyclip.INTERSECTION, + subject: polyclip.Polygon{{ + {100.0000001, 100}, + {98.48077539970159, 117.36481778405785}, + {98.48077539970159, 82.63518221594214}, + }}, + clipping: polyclip.Polygon{{ + {100.0000001, 100}, + {100, 99.99999885699484}, + {99.9999999, 100.00000000000001}, + {100, 100.00000114300516}, + {100.0000001, 100}, + }}, + result: polyclip.Polygon{{ + {100.0000001, 100}, + {100, 99.99999885699484}, + {99.9999999, 100.00000000000001}, + {100, 100.00000114300516}, + {100.0000001, 100}, + }}, + }, + { + op: polyclip.INTERSECTION, + subject: polyclip.Polygon{{ + {100.00000001, 100}, + {98.48077531106888, 117.36481776842952}, + {98.48077531106888, 82.63518223157048}, + }}, + clipping: polyclip.Polygon{{ + {100.00000001, 100}, + {100, 99.99999988569955}, + {99.99999999, 100.00000000000001}, + {100, 100.00000011430046}, + {100.00000001, 100}, + }}, + result: polyclip.Polygon{{ + {100.00000001, 100}, + {100, 99.99999988569955}, + {99.99999999, 100.00000000000001}, + {100, 100.00000011430046}, + {100.00000001, 100}, + }}, + }, + }.verify(t) +} + func TestCorruptionResistanceFromFloatingPointImprecision(t *T) { testCases{ { diff --git a/clipper.go b/clipper.go index 0f9410f..e5dfe56 100644 --- a/clipper.go +++ b/clipper.go @@ -303,7 +303,7 @@ func findIntersection(seg0, seg1 segment, tryBothDirections bool) (int, Point, P d0 := Point{seg0.end.X - p0.X, seg0.end.Y - p0.Y} p1 := seg1.start d1 := Point{seg1.end.X - p1.X, seg1.end.Y - p1.Y} - sqrEpsilon := 1e-15 // was originally 1e-3, which is very prone to false positives + sqrEpsilon := 1e-21 // was originally 1e-3, which is very prone to false positives E := Point{p1.X - p0.X, p1.Y - p0.Y} kross := d0.X*d1.Y - d0.Y*d1.X sqrKross := kross * kross