From 6dd7cc5b6a22117afcff4b6c39f9a0ca3feed755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sat, 24 Sep 2016 15:39:09 -0400 Subject: [PATCH] Fix imprecision in Numerical.findRoot() Results can be slightly outside of the range. Close #1149 --- src/util/Numerical.js | 9 ++++++--- test/tests/Curve.js | 34 ++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/util/Numerical.js b/src/util/Numerical.js index fe6cd0dc..fa239e06 100644 --- a/src/util/Numerical.js +++ b/src/util/Numerical.js @@ -216,8 +216,10 @@ var Numerical = new function() { nx = x - dx; // See if we can trust the Newton-Raphson result. If not we use // bisection to find another candidate for Newton's method. - if (abs(dx) < tolerance) - return nx; + if (abs(dx) < tolerance) { + x = nx; + break; + } // Update the root-bounding interval and test for containment of // the candidate. If candidate is outside the root-bounding // interval, use bisection instead. @@ -234,7 +236,8 @@ var Numerical = new function() { } // Return the best result even though we haven't gotten close // enough to the root... (In paper.js this never seems to happen). - return x; + // But make sure, that it actually is within the given range [a, b] + return clamp(x, a, b); }, /** diff --git a/test/tests/Curve.js b/test/tests/Curve.js index 946941ed..81bc5aa8 100644 --- a/test/tests/Curve.js +++ b/test/tests/Curve.js @@ -192,6 +192,25 @@ test('Curve#getTimeAt() with straight curve', function() { equals(t, 0.3869631475722452); }); +test('Curve#getTimeAt() with straight curve', function() { + // #1000: + var curve = new Curve([ + 1584.4999999999998, 1053.2499999999995, + 1584.4999999999998,1053.2499999999995, + 1520.5,1053.2499999999995, + 1520.5,1053.2499999999995 + ]); + var offset = 63.999999999999716; + equals(function() { return offset < curve.length; }, true); + equals(function() { return curve.getTimeAt(offset); }, 1); +}); + +test('Curve#getTimeAt() with offset at end of curve', function() { + // #1149: + var curve = [-7500, 0, -7500, 4142.135623730952, -4142.135623730952, 7500, 0, 7500]; + equals(Curve.getTimeAt(curve, 11782.625235553916), 1); +}); + test('Curve#getLocationAt()', function() { var curve = new Path([ [[0, 0], [0, 0], [100, 0]], @@ -248,7 +267,7 @@ test('Curve#isLinear()', function() { }); test('Curve#getTimeOf()', function() { - // For issue #708: + // #708: var path = new Path.Rectangle({ center: new Point(300, 100), size: new Point(100, 100), @@ -275,19 +294,6 @@ test('Curve#getTimeOf()', function() { } }); -test('Curve#getTimeAt() with straight curve', function() { - // #1000: - var curve = new Curve([ - 1584.4999999999998, 1053.2499999999995, - 1584.4999999999998,1053.2499999999995, - 1520.5,1053.2499999999995, - 1520.5,1053.2499999999995 - ]); - var offset = 63.999999999999716; - equals(function() { return offset < curve.length; }, true); - equals(function() { return curve.getTimeAt(offset); }, 1); -}); - test('Curve#getPartLength() with straight curve', function() { var curve = new Curve([0, 0, 0, 0, 64, 0, 64, 0]); equals(function() { return curve.getPartLength(0.0, 0.25); }, 10);