Handle overlapping intercepts in getIntersection,

In a more robust way. Restricting ranges in parameter is not a nice way
to handle endpoint intersections.
This commit is contained in:
hkrish 2014-05-17 13:43:46 +02:00
parent e5e2a8d7d4
commit 6c6ad76c94

View file

@ -229,7 +229,8 @@ PathItem.inject(new function() {
windRight = 0, windRight = 0,
roots = [], roots = [],
abs = Math.abs, abs = Math.abs,
MAX = 1 - TOLERANCE; tMin = TOLERANCE,
tMax = 1 - TOLERANCE;
// Absolutely horizontal curves may return wrong results, since // Absolutely horizontal curves may return wrong results, since
// the curves are monotonic in y direction and this is an // the curves are monotonic in y direction and this is an
// indeterminate state. // indeterminate state.
@ -270,7 +271,8 @@ PathItem.inject(new function() {
var curve = curves[i], var curve = curves[i],
values = curve.values, values = curve.values,
winding = curve.winding, winding = curve.winding,
next = curve.next; next = curve.next,
lastT, lastX0;
// Since the curves are monotone in y direction, we can just // Since the curves are monotone in y direction, we can just
// compare the endpoints of the curve to determine if the // compare the endpoints of the curve to determine if the
// ray from query point along +-x direction will intersect // ray from query point along +-x direction will intersect
@ -278,14 +280,16 @@ PathItem.inject(new function() {
if (winding && (winding === 1 if (winding && (winding === 1
&& y >= values[1] && y <= values[7] && y >= values[1] && y <= values[7]
|| y >= values[7] && y <= values[1]) || y >= values[7] && y <= values[1])
&& Curve.solveCubic(values, 1, y, roots, 0, && Curve.solveCubic(values, 1, y, roots, 0, 1) === 1){
// If the next curve is horizontal, we have to include
// the end of this curve to make sure we won't miss an
// intercept.
!next.winding && next.values[1] === y ? 1 : MAX) === 1){
var t = roots[0], var t = roots[0],
x0 = Curve.evaluate(values, t, 0).x, x0 = Curve.evaluate(values, t, 0).x,
slope = Curve.evaluate(values, t, 1).y; slope = Curve.evaluate(values, t, 1).y;
// Due to numerical precision issues, two consecutive curves
// may register an intercept twice, at t = 1 and 0, if y is
// almost equal to one of the endpoints of the curves.
if (!(lastT && abs(lastX0 - x0) < TOLERANCE
&& ((lastT <= tMin && t >= tMax)
|| (t <= tMin && lastT >= tMax)))) {
// Take care of cases where the curve and the preceding // Take care of cases where the curve and the preceding
// curve merely touches the ray towards +-x direction, but // curve merely touches the ray towards +-x direction, but
// proceeds to the same side of the ray. This essentially is // proceeds to the same side of the ray. This essentially is
@ -303,6 +307,9 @@ PathItem.inject(new function() {
windRight += winding; windRight += winding;
} }
} }
lastT = t;
lastX0 = x0;
}
} }
} }
return Math.max(abs(windLeft), abs(windRight)); return Math.max(abs(windLeft), abs(windRight));