From 1f768c69d22daea20c0cce1e32d3e4e16bf828fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 5 Feb 2017 14:20:43 +0100 Subject: [PATCH] Move private getPeaks() to Curve.getPeaks() It will be of use in the offsetting code as well. --- src/path/Curve.js | 37 +++++++++++++++++++++++++++++++++++++ src/path/CurveLocation.js | 31 +++---------------------------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/path/Curve.js b/src/path/Curve.js index 93118962..478f4b2f 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -1681,6 +1681,43 @@ new function() { // Scope for methods that require private functions getCurvature: function(v, t) { return evaluate(v, t, 3, false).x; + }, + + /** + * Returns the t values for the "peaks" of the curve. The peaks are + * calculated by finding the roots of the dot product of the first and + * second derivative. + * + * Peaks are locations sharing some qualities of curvature extrema but + * are cheaper to compute. They fulfill their purpose here quite well. + * See: + * http://math.stackexchange.com/questions/1954845/bezier-curvature-extrema + * + * @param {Number[]} v the curve values array + * @returns {Number[]} the roots of all found peaks + */ + getPeaks: function(v) { + var x0 = v[0], y0 = v[1], + x1 = v[2], y1 = v[3], + x2 = v[4], y2 = v[5], + x3 = v[6], y3 = v[7], + ax = -x0 + 3 * x1 - 3 * x2 + x3, + bx = 3 * x0 - 6 * x1 + 3 * x2, + cx = -3 * x0 + 3 * x1, + ay = -y0 + 3 * y1 - 3 * y2 + y3, + by = 3 * y0 - 6 * y1 + 3 * y2, + cy = -3 * y0 + 3 * y1, + tMin = /*#=*/Numerical.CURVETIME_EPSILON, + tMax = 1 - tMin, + roots = []; + Numerical.solveCubic( + 9 * (ax * ax + ay * ay), + 9 * (ax * bx + by * ay), + 2 * (bx * bx + by * by) + 3 * (cx * ax + cy * ay), + (cx * bx + by * cy), + // Exclude 0 and 1 as we don't count them as peaks. + roots, tMin, tMax); + return roots.sort(); } }}; }, diff --git a/src/path/CurveLocation.js b/src/path/CurveLocation.js index 6e0c765e..75b6ecde 100644 --- a/src/path/CurveLocation.js +++ b/src/path/CurveLocation.js @@ -437,10 +437,10 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ var offsets = []; function addOffsets(curve, end) { - // Find the largest offset of unambiguous direction on the curve by - // finding their inflections points and "peaks". + // Find the largest offset of unambiguous direction on the curve, + // taking their loops, cusps, inflections, and "peaks" into account. var v = curve.getValues(), - roots = Curve.classify(v).roots || getPeaks(v), + roots = Curve.classify(v).roots || Curve.getPeaks(v), count = roots.length, t = end && count > 1 ? roots[count - 1] : count > 0 ? roots[0] @@ -449,31 +449,6 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ offsets.push(Curve.getLength(v, end ? t : 0, end ? 1 : t) / 2); } - // Peaks are locations sharing some qualities of curvature extrema but - // are cheaper to compute. They fulfill their purpose here quite well. - // See: http://math.stackexchange.com/questions/1954845/bezier-curvature-extrema - function getPeaks(v) { - var x0 = v[0], y0 = v[1], - x1 = v[2], y1 = v[3], - x2 = v[4], y2 = v[5], - x3 = v[6], y3 = v[7], - ax = -x0 + 3 * x1 - 3 * x2 + x3, - bx = 3 * x0 - 6 * x1 + 3 * x2, - cx = -3 * x0 + 3 * x1, - ay = -y0 + 3 * y1 - 3 * y2 + y3, - by = 3 * y0 - 6 * y1 + 3 * y2, - cy = -3 * y0 + 3 * y1, - roots = []; - Numerical.solveCubic( - 9 * (ax * ax + ay * ay), - 9 * (ax * bx + by * ay), - 2 * (bx * bx + by * by) + 3 * (cx * ax + cy * ay), - (cx * bx + by * cy), - // Exclude 0 and 1 as we don't want to use them as peaks. - roots, tMin, tMax); - return roots.sort(); - } - function isInRange(angle, min, max) { return min < max ? angle > min && angle < max