diff --git a/src/path/Curve.js b/src/path/Curve.js
index bb7694e1..eab994ff 100644
--- a/src/path/Curve.js
+++ b/src/path/Curve.js
@@ -402,8 +402,8 @@ var Curve = Base.extend(/** @lends Curve# */{
      * curves
      */
     getIntersections: function(curve) {
-        return Curve.filterIntersections(Curve.getIntersections(
-                this.getValues(), curve.getValues(), this, curve, []));
+        return Curve._filterIntersections(Curve._getIntersections(
+                this.getValues(), curve.getValues(), this, curve, [], {}));
     },
 
     // TODO: adjustThroughPoint
@@ -1317,18 +1317,22 @@ new function() { // Scope for methods that require private functions
 },
 new function() { // Scope for intersection using bezier fat-line clipping
 
-    function addLocation(locations, include, curve1, t1, point1, curve2, t2,
+    function addLocation(locations, param, curve1, t1, point1, curve2, t2,
             point2) {
-        var loc = new CurveLocation(curve1, t1, point1, curve2, t2, point2);
-        if (!include || include(loc)) {
+        var loc = null,
+            tMin = /*#=*/Numerical.TOLERANCE,
+            tMax = 1 - tMin;
+        if (t1 >= (param.startConnected ? tMin : 0)
+                && t1 <= (param.endConnected ? tMax : 1)) {
+            loc = new CurveLocation(curve1, t1, point1, curve2, t2, point2);
+            if (param.adjust)
+                param.adjust(loc);
             locations.push(loc);
-        } else {
-            loc = null;
         }
         return loc;
     }
 
-    function addCurveIntersections(v1, v2, curve1, curve2, locations, include,
+    function addCurveIntersections(v1, v2, curve1, curve2, locations, param,
             tMin, tMax, uMin, uMax, oldTDiff, reverse, recursion) {
         // Avoid deeper recursion.
         // NOTE: @iconexperience determined that more than 20 recursions are
@@ -1391,19 +1395,19 @@ new function() { // Scope for intersection using bezier fat-line clipping
                 var parts = Curve.subdivide(v1, 0.5),
                     t = tMinNew + (tMaxNew - tMinNew) / 2;
                 addCurveIntersections(
-                    v2, parts[0], curve2, curve1, locations, include,
+                    v2, parts[0], curve2, curve1, locations, param,
                     uMin, uMax, tMinNew, t, tDiff, !reverse, recursion);
                 addCurveIntersections(
-                    v2, parts[1], curve2, curve1, locations, include,
+                    v2, parts[1], curve2, curve1, locations, param,
                     uMin, uMax, t, tMaxNew, tDiff, !reverse, recursion);
             } else {
                 var parts = Curve.subdivide(v2, 0.5),
                     t = uMin + (uMax - uMin) / 2;
                 addCurveIntersections(
-                    parts[0], v1, curve2, curve1, locations, include,
+                    parts[0], v1, curve2, curve1, locations, param,
                     uMin, t, tMinNew, tMaxNew, tDiff, !reverse, recursion);
                 addCurveIntersections(
-                    parts[1], v1, curve2, curve1, locations, include,
+                    parts[1], v1, curve2, curve1, locations, param,
                     t, uMax, tMinNew, tMaxNew, tDiff, !reverse, recursion);
             }
         } else if (Math.max(uMax - uMin, tMaxNew - tMinNew) < tolerance) {
@@ -1411,16 +1415,16 @@ new function() { // Scope for intersection using bezier fat-line clipping
             var t1 = tMinNew + (tMaxNew - tMinNew) / 2,
                 t2 = uMin + (uMax - uMin) / 2;
             if (reverse) {
-                addLocation(locations, include,
+                addLocation(locations, param,
                         curve2, t2, Curve.getPoint(v2, t2),
                         curve1, t1, Curve.getPoint(v1, t1));
             } else {
-                addLocation(locations, include,
+                addLocation(locations, param,
                         curve1, t1, Curve.getPoint(v1, t1),
                         curve2, t2, Curve.getPoint(v2, t2));
             }
         } else if (tDiff > /*#=*/Numerical.EPSILON) { // Iterate
-            addCurveIntersections(v2, v1, curve2, curve1, locations, include,
+            addCurveIntersections(v2, v1, curve2, curve1, locations, param,
                     uMin, uMax, tMinNew, tMaxNew, tDiff, !reverse, recursion);
         }
     }
@@ -1534,7 +1538,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
      * and the curve.
      */
     function addCurveLineIntersections(v1, v2, curve1, curve2, locations,
-            include) {
+            param) {
         var flip = Curve.isStraight(v1),
             vc = flip ? v2 : v1,
             vl = flip ? v1 : v2,
@@ -1574,14 +1578,14 @@ new function() { // Scope for intersection using bezier fat-line clipping
                 var tl = Curve.getParameterOf(rvl, x, 0),
                     t1 = flip ? tl : tc,
                     t2 = flip ? tc : tl;
-                addLocation(locations, include,
+                addLocation(locations, param,
                         curve1, t1, Curve.getPoint(v1, t1),
                         curve2, t2, Curve.getPoint(v2, t2));
             }
         }
     }
 
-    function addLineIntersection(v1, v2, curve1, curve2, locations, include) {
+    function addLineIntersection(v1, v2, curve1, curve2, locations, param) {
         var point = Line.intersect(
                 v1[0], v1[1], v1[6], v1[7],
                 v2[0], v2[1], v2[6], v2[7]);
@@ -1590,7 +1594,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
             // since they will be used for sorting
             var x = point.x,
                 y = point.y;
-            addLocation(locations, include,
+            addLocation(locations, param,
                     curve1, Curve.getParameterOf(v1, x, y), point,
                     curve2, Curve.getParameterOf(v2, x, y), point);
         }
@@ -1600,7 +1604,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
      * Code to detect overlaps of intersecting curves by @iconexperience:
      * https://github.com/paperjs/paper.js/issues/648
      */
-    function addOverlap(v1, v2, curve1, curve2, locations, include) {
+    function addOverlap(v1, v2, curve1, curve2, locations, param) {
         var abs = Math.abs,
             tolerance = /*#=*/Numerical.TOLERANCE,
             epsilon = /*#=*/Numerical.EPSILON,
@@ -1670,10 +1674,10 @@ new function() { // Scope for intersection using bezier fat-line clipping
                     t12 = pairs[0][1],
                     t21 = pairs[1][0],
                     t22 = pairs[1][1],
-                    loc1 = addLocation(locations, include,
+                    loc1 = addLocation(locations, param,
                         curve1, t11, Curve.getPoint(v1, t11),
                         curve2, t12, Curve.getPoint(v2, t12), true),
-                    loc2 = addLocation(locations, include,
+                    loc2 = addLocation(locations, param,
                         curve1, t21, Curve.getPoint(v1, t21),
                         curve2, t22, Curve.getPoint(v2, t22), true);
                 if (loc1)
@@ -1690,8 +1694,9 @@ new function() { // Scope for intersection using bezier fat-line clipping
         // We need to provide the original left curve reference to the
         // #getIntersections() calls as it is required to create the resulting
         // CurveLocation objects.
-        getIntersections: function(v1, v2, c1, c2, locations, include) {
-            if (addOverlap(v1, v2, c1, c2, locations, include))
+        _getIntersections: function(v1, v2, curve1, curve2, locations, param) {
+            if (!param.startConnected && !param.endConnected
+                    && addOverlap(v1, v2, curve1, curve2, locations, param))
                 return locations;
             var straight1 = Curve.isStraight(v1),
                 straight2 = Curve.isStraight(v2),
@@ -1700,39 +1705,38 @@ new function() { // Scope for intersection using bezier fat-line clipping
                 c2p1 = new Point(v2[0], v2[1]),
                 c2p2 = new Point(v2[6], v2[7]),
                 tolerance = /*#=*/Numerical.TOLERANCE;
-            // Handle a special case where if both curves start or end at the
-            // same point, the same end-point case will be handled after we
-            // calculate other intersections within the curve.
+            // Handle the special case where the first curve's stat-point
+            // overlaps with the second curve's start- or end-points.
             if (c1p1.isClose(c2p1, tolerance))
-                addLocation(locations, include, c1, 0, c1p1, c2, 0, c1p1);
-            if (c1p1.isClose(c2p2, tolerance))
-                addLocation(locations, include, c1, 0, c1p1, c2, 1, c1p1);
-            // Determine the correct intersection method based on values of
-            // straight1 & 2:
+                addLocation(locations, param, curve1, 0, c1p1, curve2, 0, c1p1);
+            if (!param.startConnected && c1p1.isClose(c2p2, tolerance))
+                addLocation(locations, param, curve1, 0, c1p1, curve2, 1, c1p1);
+            // Determine the correct intersection method based on whether one or
+            // curves are straight lines:
             (straight1 && straight2
                 ? addLineIntersection
                 : straight1 || straight2
                     ? addCurveLineIntersections
                     : addCurveIntersections)(
-                        v1, v2, c1, c2, locations, include,
+                        v1, v2, curve1, curve2, locations, param,
                         // Define the defaults for these parameters of
                         // addCurveIntersections():
                         // tMin, tMax, uMin, uMax, oldTDiff, reverse, recursion
                         0, 1, 0, 1, 0, false, 0);
-            // Handle the special case where c1's end-point overlap with
-            // c2's points.
-            if (c1p2.isClose(c2p1, tolerance))
-                addLocation(locations, include, c1, 1, c1p2, c2, 0, c1p2);
+            // Handle the special case where the first curve's end-point
+            // overlaps with the second curve's start- or end-points.
+            if (!param.endConnected && c1p2.isClose(c2p1, tolerance))
+                addLocation(locations, param, curve1, 1, c1p2, curve2, 0, c1p2);
             if (c1p2.isClose(c2p2, tolerance))
-                addLocation(locations, include, c1, 1, c1p2, c2, 1, c1p2);
+                addLocation(locations, param, curve1, 1, c1p2, curve2, 1, c1p2);
             return locations;
         },
 
-        filterIntersections: function(locations, expand) {
+        _filterIntersections: function(locations, expand) {
             var last = locations.length - 1,
                 tMax = 1 - /*#=*/Numerical.TOLERANCE;
             // Merge intersections very close to the end of a curve to the
-            // beginning of the next curve.
+            // beginning of the next curve, so we can compare them.
             for (var i = last; i >= 0; i--) {
                 var loc = locations[i],
                     next;
diff --git a/src/path/PathItem.Boolean.js b/src/path/PathItem.Boolean.js
index 8c3328f7..039c5abb 100644
--- a/src/path/PathItem.Boolean.js
+++ b/src/path/PathItem.Boolean.js
@@ -76,7 +76,7 @@ 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(Curve.filterIntersections(
+        splitPath(Curve._filterIntersections(
                 _path1._getIntersections(_path2, null, []), true));
         /*
         console.time('inter');
@@ -88,7 +88,7 @@ PathItem.inject(new function() {
             _path2._getIntersections(null, null, locations);
             console.timeEnd('self');
         }
-        splitPath(Curve.filterIntersections(locations, true));
+        splitPath(Curve._filterIntersections(locations, true));
         */
         var chain = [],
             segments = [],
diff --git a/src/path/PathItem.js b/src/path/PathItem.js
index 2a43f215..3dac84a7 100644
--- a/src/path/PathItem.js
+++ b/src/path/PathItem.js
@@ -63,31 +63,30 @@ var PathItem = Item.extend(/** @lends PathItem# */{
         // intersections.
         // NOTE: The hidden argument _matrix is used internally to override the
         // passed path's transformation matrix.
-        return Curve.filterIntersections(this._getIntersections(
+        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,
+        var self = !path, // self-intersections?
+            curves1 = this.getCurves(),
+            curves2 = self ? curves1 : path.getCurves(),
             matrix1 = this._matrix.orNullIfIdentity(),
-            matrix2 = path ? (matrix || path._matrix).orNullIfIdentity()
-                : matrix1,
+            matrix2 = self ? matrix1
+                : (matrix || path._matrix).orNullIfIdentity(),
             length1 = curves1.length,
             length2 = path ? curves2.length : length1,
-            values2 = [],
-            tMin = /*#=*/Numerical.TOLERANCE,
-            tMax = 1 - tMin;
+            values2 = [];
         // First check the bounds of the two paths. If they don't intersect,
         // we don't need to iterate through their curves.
         if (path && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))
-            return [];
+            return locations;
         for (var i = 0; i < length2; i++)
             values2[i] = curves2[i].getValues(matrix2);
         for (var i = 0; i < length1; i++) {
             var curve1 = curves1[i],
-                values1 = path ? curve1.getValues(matrix1) : values2[i];
-            if (!path) {
+                values1 = self ? values2[i] : curve1.getValues(matrix1);
+            if (self) {
                 // First check for self-intersections within the same curve
                 var seg1 = curve1.getSegment1(),
                     seg2 = curve1.getSegment2(),
@@ -103,15 +102,17 @@ var PathItem = Item.extend(/** @lends PathItem# */{
                     // Self intersecting is found by dividing the curve in two
                     // and and then applying the normal curve intersection code.
                     var parts = Curve.subdivide(values1);
-                    Curve.getIntersections(
-                        parts[0], parts[1], curve1, curve1, locations,
-                        function(loc) {
-                            if (loc._parameter <= tMax) {
+                    Curve._getIntersections(
+                        parts[0], parts[1], curve1, curve1, locations, {
+                            // Only possible if there is only one curve:
+                            startConnected: length1 === 1,
+                            // After splitting, the end is always connected:
+                            endConnected: true,
+                            adjust: function(loc) {
                                 // Since the curve was split above, we need to
                                 // adjust the parameters for both locations.
                                 loc._parameter /= 2;
                                 loc._parameter2 = 0.5 + loc._parameter2 / 2;
-                                return true;
                             }
                         }
                     );
@@ -119,20 +120,19 @@ 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++) {
+            for (var j = self ? i + 1 : 0; j < length2; j++) {
                 // There might be already one location from the above
                 // self-intersection check:
                 if (returnFirst && locations.length)
                     break;
-                Curve.getIntersections(
+                // Avoid end point intersections on consecutive curves when
+                // self intersecting.
+                Curve._getIntersections(
                     values1, values2[j], curve1, curves2[j], locations,
-                    // Avoid end point intersections on consecutive curves when
-                    // self intersecting.
-                    !path && (j === i + 1 || j === length2 - 1 && i === 0)
-                        && function(loc) {
-                            var t = loc._parameter;
-                            return t >= tMin && t <= tMax;
-                        }
+                    self ? {
+                        startConnected: j === length2 - 1 && i === 0,
+                        endConnected: j === i + 1
+                    } : {}
                 );
             }
         }