From 447feea1da58c64291c47c2e58e74c77bb5ebdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Tue, 20 Oct 2015 22:03:45 +0200 Subject: [PATCH] Improve Curve#getParameterOf() to first check curve points with zero epsilon. --- src/path/Curve.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/path/Curve.js b/src/path/Curve.js index 56360668..a7cad223 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -667,23 +667,35 @@ statics: { }, getParameterOf: function(v, point) { + // Before solving cubics, compare the beginning and end of the curve + // with zero epsilon: + var p1 = new Point(v[0], v[1]), + p2 = new Point(v[6], v[7]), + epsilon = /*#=*/Numerical.EPSILON, + t = point.isClose(p1, epsilon) ? 0 + : point.isClose(p2, epsilon) ? 1 + : null; + if (t !== null) + return t; + // Solve the cubic for both x- and y-coordinates and consider all found + // solutions, testing with the larger / looser geometric epsilon. var coords = [point.x, point.y], roots = [], - epsilon = /*#=*/Numerical.GEOMETRIC_EPSILON; + geomEpsilon = /*#=*/Numerical.GEOMETRIC_EPSILON; for (var c = 0; c < 2; c++) { var count = Curve.solveCubic(v, c, coords[c], roots, 0, 1); for (var i = 0; i < count; i++) { - var t = roots[i]; - if (point.isClose(Curve.getPoint(v, t), epsilon)) + t = roots[i]; + if (point.isClose(Curve.getPoint(v, t), geomEpsilon)) return t; } } // For very short curves (length ~ 1e-13), the above code will not // necessarily produce any valid roots. As a fall-back, just check the // beginnings and ends at the end so we can still return a valid result. - return point.isClose(new Point(v[0], v[1]), epsilon) ? 0 - : point.isClose(new Point(v[6], v[7]), epsilon) ? 1 - : null; + return point.isClose(p1, geomEpsilon) ? 0 + : point.isClose(p2, geomEpsilon) ? 1 + : null; }, // TODO: Find better name