diff --git a/src/path/CurveLocation.js b/src/path/CurveLocation.js index 9aa3fe3f..da288e64 100644 --- a/src/path/CurveLocation.js +++ b/src/path/CurveLocation.js @@ -448,22 +448,27 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ : angle > min || angle < max; } - // Calculate angles for all four tangents at the intersection point, - // using values for getTangentAt() that are almost 0 and 1. - // NOTE: Even though getTangentAt() has code to support 0 and 1 instead - // of tMin and tMax, we still need to use tMin / tMaxx instead, as other - // issues emerge from switching to 0 and 1 in edge cases. - // NOTE: VectorBoolean has code that slowly shifts these points inwards + // Calculate angles for all four tangents at the intersection point. + // If the intersection is on an actual segment, step away from it at + // equal offsets on each curve, to calculate tangential angles that are + // unambiguous. The offset is determined by taking 1/64th of the length + // of the shortest of all involved curves. This appears to work well. + // NOTE: VectorBoolean has code that slowly shifts these offsets inwards // until the resulting tangents are not ambiguous. Do we need this too? - // NOTE: We handle t*Inside here simply by picking t1 / t2 instead of - // tMin / tMax. E.g. if t1Inside is true, c1 will be the same as c2, - // and the code will doe the right thing. + // NOTE: We handle t1 / t2Inside here by getting the tangent at t1 / t2 + // instead of at this calculated offset. // The incomings tangents v1 & v3 are inverted, so that all angles // are pointing outwards in the right direction from the intersection. - var v2 = c2.getTangentAtTime(t1Inside ? t1 : tMin), - v1 = (t1Inside ? v2 : c1.getTangentAtTime(tMax)).negate(), - v4 = c4.getTangentAtTime(t2Inside ? t2 : tMin), - v3 = (t2Inside ? v4 : c3.getTangentAtTime(tMax)).negate(), + var lenghts = []; + if (!t1Inside) + lenghts.push(c1.getLength(), c2.getLength()); + if (!t2Inside) + lenghts.push(c3.getLength(), c4.getLength()); + var offset = Math.min.apply(null, lenghts) / 64; + var v2 = t1Inside ? c2.getTangentAtTime(t1) : c2.getTangentAt(offset), + v1 = (t1Inside ? v2 : c1.getTangentAt(-offset)).negate(), + v4 = t2Inside ? c4.getTangentAtTime(t2) : c4.getTangentAt(offset), + v3 = (t2Inside ? v4 : c3.getTangentAt(-offset)).negate(), // NOTE: For shorter API calls we work with angles in degrees here: a1 = v1.getAngle(), a2 = v2.getAngle(), diff --git a/test/tests/Path_Intersections.js b/test/tests/Path_Intersections.js index 235676fe..3b99b036 100644 --- a/test/tests/Path_Intersections.js +++ b/test/tests/Path_Intersections.js @@ -147,9 +147,8 @@ test('#1066', function() { test('#1074', function() { var path1 = new Path('M349.98644,0c-192.98072,0 -349.98644,157.00255 -349.98644,349.98327c0,35.02687 28.39313,63.42 63.42,63.42c35.02687,0 63.42,-28.39313 63.42,-63.42c0,-123.04114 100.10213,-223.14327 223.14644,-223.14327c35.02687,0 63.42,-28.39313 63.42,-63.42c0,-35.02687 -28.39313,-63.42 -63.42,-63.42z'); var path2 = new Path('M349.98644,0c-35.02687,0 -63.42,28.39313 -63.42,63.42c0,35.02687 28.39313,63.42 63.42,63.42c59.25965,0 118.69687,22.57118 158.98443,60.37584c25.54558,23.97593 65.67775,22.6885 89.64417,-2.84756c23.96959,-25.5424 22.69168,-65.67775 -2.84756,-89.64417c-63.21071,-59.31355 -155.09044,-94.72411 -245.78104,-94.72411z'); - var inters = path1.getIntersections(path2); testIntersection(path1.getIntersections(path2), [ - { point: { x: 349.98644, y: 0 }, index: 0, time: 0 }, - { point: { x: 349.98644, y: 126.84 } , index: 4, time: 0 } + { point: { x: 349.98644, y: 0 }, index: 0, time: 0, crossing: true }, + { point: { x: 349.98644, y: 126.84 } , index: 4, time: 0, crossing: true } ]); });