Optimize Item#intersects() by only checking to see if there are at least one intersection.

This commit is contained in:
Jürg Lehni 2015-08-25 11:45:28 +02:00
parent 7ca8ce3cbb
commit fd1f2e56f8
3 changed files with 22 additions and 15 deletions

View file

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

View file

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

View file

@ -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() {