Improve fat-line clipping for rare edge cases.

Instead of limiting recursion levels, limit actual call count. Relates to #904
This commit is contained in:
Jürg Lehni 2016-06-10 23:51:56 +02:00
parent 715025725d
commit 41e4c622a3

View file

@ -1549,13 +1549,12 @@ new function() { // Scope for intersection using bezier fat-line clipping
} }
function addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax, function addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax,
uMin, uMax, reverse, recursion) { uMin, uMax, reverse, calls) {
// Avoid deeper recursion. // Avoid deeper recursion, but instead of counting recursion, we count
// NOTE: @iconexperience determined that more than 20 recursions are // the total amount of calls, to avoid massive call-trees as suggested
// needed sometimes, depending on the tDiff threshold values further // by @iconexperience in #904#issuecomment-225283430. See also #565 #899
// below when determining which curve converges the least: #565, #899 if (++calls > 4000)
if (++recursion >= 26) return calls;
return;
// Let P be the first curve and Q be the second // Let P be the first curve and Q be the second
var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7], var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],
getSignedDistance = Line.getSignedDistance, getSignedDistance = Line.getSignedDistance,
@ -1612,27 +1611,28 @@ new function() { // Scope for intersection using bezier fat-line clipping
if (tMaxNew - tMinNew > uMax - uMin) { if (tMaxNew - tMinNew > uMax - uMin) {
var parts = Curve.subdivide(v1, 0.5), var parts = Curve.subdivide(v1, 0.5),
t = (tMinNew + tMaxNew) / 2; t = (tMinNew + tMaxNew) / 2;
addCurveIntersections( calls = addCurveIntersections(
v2, parts[0], c2, c1, locations, param, v2, parts[0], c2, c1, locations, param,
uMin, uMax, tMinNew, t, !reverse, recursion); uMin, uMax, tMinNew, t, !reverse, calls);
addCurveIntersections( calls = addCurveIntersections(
v2, parts[1], c2, c1, locations, param, v2, parts[1], c2, c1, locations, param,
uMin, uMax, t, tMaxNew, !reverse, recursion); uMin, uMax, t, tMaxNew, !reverse, calls);
} else { } else {
var parts = Curve.subdivide(v2, 0.5), var parts = Curve.subdivide(v2, 0.5),
u = (uMin + uMax) / 2; u = (uMin + uMax) / 2;
addCurveIntersections( calls = addCurveIntersections(
parts[0], v1, c2, c1, locations, param, parts[0], v1, c2, c1, locations, param,
uMin, u, tMinNew, tMaxNew, !reverse, recursion); uMin, u, tMinNew, tMaxNew, !reverse, calls);
addCurveIntersections( calls = addCurveIntersections(
parts[1], v1, c2, c1, locations, param, parts[1], v1, c2, c1, locations, param,
u, uMax, tMinNew, tMaxNew, !reverse, recursion); u, uMax, tMinNew, tMaxNew, !reverse, calls);
} }
} else { // Iterate } else { // Iterate
addCurveIntersections(v2, v1, c2, c1, locations, param, calls = addCurveIntersections(v2, v1, c2, c1, locations, param,
uMin, uMax, tMinNew, tMaxNew, !reverse, recursion); uMin, uMax, tMinNew, tMaxNew, !reverse, calls);
} }
} }
return calls;
} }
/** /**