diff --git a/src/item/Item.js b/src/item/Item.js index d505e8e6..8e3718d5 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -1684,11 +1684,10 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ intersects: function(item, _matrix) { if (!(item instanceof Item)) return false; - // TODO: Optimize getIntersections(): We don't need all intersections - // when we're just curious about whether they intersect or not. Pass on - // an argument that let's it bail out after the first intersection. - return this._asPathItem().getIntersections(item._asPathItem(), - _matrix || item._matrix).length > 0; + // Tell _getIntersections to return as soon as some intersections are + // found, because all we care for here is there are some or none: + return this._asPathItem()._getIntersections(item._asPathItem(), + _matrix || item._matrix, [], true).length > 0; }, /** diff --git a/src/path/PathItem.Boolean.js b/src/path/PathItem.Boolean.js index c4e51c9b..ab8b5b04 100644 --- a/src/path/PathItem.Boolean.js +++ b/src/path/PathItem.Boolean.js @@ -77,7 +77,8 @@ PathItem.inject(new function() { _path2.reverse(); // Split curves at intersections on both paths. Note that for self // intersection, _path2 will be null and getIntersections() handles it. - splitPath(_path1.getIntersections(_path2, null, true)); + splitPath(Curve.filterIntersections( + _path1._getIntersections(_path2, null, []), true)); var chain = [], segments = [], @@ -538,7 +539,7 @@ PathItem.inject(new function() { // the correct contour to traverse next. w3 = t1.cross(t3), w4 = t1.cross(t4); - if (Math.abs(w3 * w4) > Numerical.EPSILON) { + if (Math.abs(w3 * w4) > /*#=*/Numerical.EPSILON) { // Do not attempt to switch contours if we aren't // sure that there is a possible candidate. var curve = w3 < w4 ? c3 : c4, @@ -603,7 +604,8 @@ PathItem.inject(new function() { ? startInterSeg : seg)._handleIn); } else { path.lastSegment._handleOut.set(0, 0); - console.error('Boolean operation results in open path!'); + console.error('Boolean operation results in open path, length =', + path._segments.length); } path.setClosed(true); // Add the path to the result, while avoiding stray segments and diff --git a/src/path/PathItem.js b/src/path/PathItem.js index b08aa23b..b44c23b9 100644 --- a/src/path/PathItem.js +++ b/src/path/PathItem.js @@ -59,19 +59,21 @@ var PathItem = Item.extend(/** @lends PathItem# */{ * } * } */ - getIntersections: function(path, _matrix, _expand) { + getIntersections: function(path, _matrix) { // NOTE: For self-intersection, path is null. This means you can also // just call path.getIntersections() without an argument to get self // intersections. // NOTE: The hidden argument _matrix is used internally to override the // passed path's transformation matrix. - if (this === path) - path = null; - var locations = [], - curves1 = this.getCurves(), + return Curve.filterIntersections(this._getIntersections( + this !== path ? path : null, _matrix, [])); + }, + + _getIntersections: function(path, matrix, locations, returnFirst) { + var curves1 = this.getCurves(), curves2 = path ? path.getCurves() : curves1, matrix1 = this._matrix.orNullIfIdentity(), - matrix2 = path ? (_matrix || path._matrix).orNullIfIdentity() + matrix2 = path ? (matrix || path._matrix).orNullIfIdentity() : matrix1, length1 = curves1.length, length2 = path ? curves2.length : length1, @@ -120,6 +122,10 @@ var PathItem = Item.extend(/** @lends PathItem# */{ // Check for intersections with other curves. For self intersection, // we can start at i + 1 instead of 0 for (var j = path ? 0 : i + 1; j < length2; j++) { + // There might be already one location from the above + // self-intersection check: + if (returnFirst && locations.length) + break; Curve.getIntersections( values1, values2[j], curve1, curves2[j], locations, // Avoid end point intersections on consecutive curves when @@ -132,7 +138,7 @@ var PathItem = Item.extend(/** @lends PathItem# */{ ); } } - return Curve.filterIntersections(locations, _expand); + return locations; }, _asPathItem: function() {