Fix imprecision in Numerical.findRoot()

Results can be slightly outside of the range.
Close #1149
This commit is contained in:
Jürg Lehni 2016-09-24 15:39:09 -04:00
parent 80f6dbb5e3
commit 6dd7cc5b6a
2 changed files with 26 additions and 17 deletions

View file

@ -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);
},
/**

View file

@ -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);