Improve Curve#getParameterOf() to first check curve points with zero epsilon.

This commit is contained in:
Jürg Lehni 2015-10-20 22:03:45 +02:00
parent 60109e897a
commit 447feea1da

View file

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