From 2db7fe7d3b7ee875e1099a22f0af17520696f5d7 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Wed, 7 May 2014 15:31:40 +0000 Subject: When solving the cubic line intersection directly fails, use binary search as a fallback. The cubic line intersection math empirically works 99.99% of the time (fails 3100 out of 1B random tests) but when it fails, an intersection may be missed altogether. The binary search is may not find a solution if the cubic line failed to find any solutions at all, but so far that case hasn't arisen. BUG=skia:2504 TBR=reed@google.com Author: caryclark@google.com Review URL: https://codereview.chromium.org/266063003 git-svn-id: http://skia.googlecode.com/svn/trunk@14614 2bbb7eff-a529-9590-31e7-b0007b416f81 --- tests/PathOpsCubicLineIntersectionTest.cpp | 35 +++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'tests/PathOpsCubicLineIntersectionTest.cpp') diff --git a/tests/PathOpsCubicLineIntersectionTest.cpp b/tests/PathOpsCubicLineIntersectionTest.cpp index 1a2e188589..234a53805f 100644 --- a/tests/PathOpsCubicLineIntersectionTest.cpp +++ b/tests/PathOpsCubicLineIntersectionTest.cpp @@ -49,6 +49,13 @@ static void testFail(skiatest::Reporter* reporter, int iIndex) { } static lineCubic lineCubicTests[] = { + {{{{-634.60540771484375, -481.262939453125}, {266.2696533203125, -752.70867919921875}, + {-751.8370361328125, -317.37921142578125}, {-969.7427978515625, 824.7255859375}}}, + {{{-287.9506133720805678, -557.1376476615772617}, + {-285.9506133720805678, -557.1376476615772617}}}}, + + {{{{36.7184372,0.888650894}, {36.7184372,0.888650894}, {35.1233864,0.554015458}, + {34.5114098,-0.115255356}}}, {{{35.4531212,0}, {31.9375,0}}}}, {{{{421, 378}, {421, 380.209137f}, {418.761414f, 382}, {416, 382}}}, {{{320, 378}, {421, 378.000031f}}}}, @@ -83,6 +90,32 @@ static lineCubic lineCubicTests[] = { static const size_t lineCubicTests_count = SK_ARRAY_COUNT(lineCubicTests); +static int doIntersect(SkIntersections& intersections, const SkDCubic& cubic, const SkDLine& line) { + int result; + bool flipped = false; + if (line[0].fX == line[1].fX) { + double top = line[0].fY; + double bottom = line[1].fY; + flipped = top > bottom; + if (flipped) { + SkTSwap(top, bottom); + } + result = intersections.vertical(cubic, top, bottom, line[0].fX, flipped); + } else if (line[0].fY == line[1].fY) { + double left = line[0].fX; + double right = line[1].fX; + flipped = left > right; + if (flipped) { + SkTSwap(left, right); + } + result = intersections.horizontal(cubic, left, right, line[0].fY, flipped); + } else { + intersections.intersect(cubic, line); + result = intersections.used(); + } + return result; +} + static void testOne(skiatest::Reporter* reporter, int iIndex) { const SkDCubic& cubic = lineCubicTests[iIndex].cubic; SkASSERT(ValidCubic(cubic)); @@ -102,7 +135,7 @@ static void testOne(skiatest::Reporter* reporter, int iIndex) { } if (order1 == 4 && order2 == 2) { SkIntersections i; - int roots = i.intersect(cubic, line); + int roots = doIntersect(i, cubic, line); for (int pt = 0; pt < roots; ++pt) { double tt1 = i[0][pt]; SkDPoint xy1 = cubic.ptAtT(tt1); -- cgit v1.2.3