From 614c781f2902e0d0d354db5f85b1ffa160cbf033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 12 Jun 2016 17:07:43 +0200 Subject: [PATCH] Put the recursion cap back into fat-line clipping code. But use a higher value, and have it work in conjunction with call-count cap. Relates to #1074 --- src/path/Curve.js | 25 +++++++++++++------------ test/tests/Path_Intersections.js | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/path/Curve.js b/src/path/Curve.js index 8e9a7797..456f3510 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -1549,11 +1549,12 @@ new function() { // Scope for intersection using bezier fat-line clipping } function addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax, - uMin, uMax, flip, calls) { - // Avoid deeper recursion, but instead of counting recursion, we count - // the total amount of calls, to avoid massive call-trees as suggested - // by @iconexperience in #904#issuecomment-225283430. See also #565 #899 - if (++calls > 4096) + uMin, uMax, flip, recursion, calls) { + // Avoid deeper recursion, by counting the total amount of recursions, + // as well as the total amount of calls, to avoid massive call-trees as + // suggested by @iconexperience in #904#issuecomment-225283430. + // See also: #565 #899 #1074 + if (++recursion >= 48 || ++calls > 4096) return calls; // Let P be the first curve and Q be the second var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7], @@ -1613,24 +1614,24 @@ new function() { // Scope for intersection using bezier fat-line clipping t = (tMinNew + tMaxNew) / 2; calls = addCurveIntersections( v2, parts[0], c2, c1, locations, param, - uMin, uMax, tMinNew, t, !flip, calls); + uMin, uMax, tMinNew, t, !flip, recursion, calls); calls = addCurveIntersections( v2, parts[1], c2, c1, locations, param, - uMin, uMax, t, tMaxNew, !flip, calls); + uMin, uMax, t, tMaxNew, !flip, recursion, calls); } else { var parts = Curve.subdivide(v2, 0.5), u = (uMin + uMax) / 2; calls = addCurveIntersections( parts[0], v1, c2, c1, locations, param, - uMin, u, tMinNew, tMaxNew, !flip, calls); + uMin, u, tMinNew, tMaxNew, !flip, recursion, calls); calls = addCurveIntersections( parts[1], v1, c2, c1, locations, param, - u, uMax, tMinNew, tMaxNew, !flip, calls); + u, uMax, tMinNew, tMaxNew, !flip, recursion, calls); } } else { // Iterate calls = addCurveIntersections( v2, v1, c2, c1, locations, param, - uMin, uMax, tMinNew, tMaxNew, !flip, calls); + uMin, uMax, tMinNew, tMaxNew, !flip, recursion, calls); } } return calls; @@ -1851,8 +1852,8 @@ new function() { // Scope for intersection using bezier fat-line clipping v1, v2, c1, c2, locations, param, // Define the defaults for these parameters of // addCurveIntersections(): - // tMin, tMax, uMin, uMax, reverse, recursion - 0, 1, 0, 1, 0, 0); + // tMin, tMax, uMin, uMax, flip, recursion, calls + 0, 1, 0, 1, 0, 0, 0); // We're done if we handle lines and found one intersection already: // #805#issuecomment-148503018 if (straight && locations.length > before) diff --git a/test/tests/Path_Intersections.js b/test/tests/Path_Intersections.js index 28fa9ae3..235676fe 100644 --- a/test/tests/Path_Intersections.js +++ b/test/tests/Path_Intersections.js @@ -20,8 +20,10 @@ function testIntersection(intersections, results) { var name = 'intersections[' + i + ']'; equals(inter.point, new Point(values.point), name + '.point'); equals(inter.index, values.index, name + '.index'); - equals(inter.time, values.time || 0, name + '.time'); - equals(inter.isCrossing(), values.crossing || false, name + '.isCrossing()'); + if (values.time != null) + equals(inter.time, values.time, name + '.time'); + if (values.crossing != null) + equals(inter.isCrossing(), values.crossing, name + '.isCrossing()'); } } @@ -122,7 +124,7 @@ test('#904', function() { { point: { x: 347.65684, y: 270.43159 }, index: 0, time: 0, crossing: false }, { point: { x: 383.05787, y: 179.36393 }, index: 0, time: 0.99583, crossing: true } ]); -}) +}); test('#1066', function() { var path1 = new paper.Path({ @@ -141,3 +143,13 @@ test('#1066', function() { { point: { x: 230.44479, y: 216.05441 }, index: 0, time: 0.63642, crossing: true } ]); }); + +test('#1074', function() { + var path1 = new Path('M349.98644,0c-192.98072,0 -349.98644,157.00255 -349.98644,349.98327c0,35.02687 28.39313,63.42 63.42,63.42c35.02687,0 63.42,-28.39313 63.42,-63.42c0,-123.04114 100.10213,-223.14327 223.14644,-223.14327c35.02687,0 63.42,-28.39313 63.42,-63.42c0,-35.02687 -28.39313,-63.42 -63.42,-63.42z'); + var path2 = new Path('M349.98644,0c-35.02687,0 -63.42,28.39313 -63.42,63.42c0,35.02687 28.39313,63.42 63.42,63.42c59.25965,0 118.69687,22.57118 158.98443,60.37584c25.54558,23.97593 65.67775,22.6885 89.64417,-2.84756c23.96959,-25.5424 22.69168,-65.67775 -2.84756,-89.64417c-63.21071,-59.31355 -155.09044,-94.72411 -245.78104,-94.72411z'); + var inters = path1.getIntersections(path2); + testIntersection(path1.getIntersections(path2), [ + { point: { x: 349.98644, y: 0 }, index: 0, time: 0 }, + { point: { x: 349.98644, y: 126.84 } , index: 4, time: 0 } + ]); +});