From 0af4c5c0f182a393519590133f99081bfd92b8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Tue, 20 Sep 2016 17:59:56 -0400 Subject: [PATCH] Introduce Curve#hasLength() as an optimized check for curve-length. And use it where it make sense. Relates to https://github.com/paperjs/paper.js/issues/1109#issuecomment-234352266 --- src/path/Curve.js | 27 +++++++++++++++++++++------ src/path/Path.js | 2 +- src/path/PathItem.Boolean.js | 7 ++++--- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/path/Curve.js b/src/path/Curve.js index 41d5d328..5004bc30 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -476,15 +476,15 @@ var Curve = Base.extend(/** @lends Curve# */{ left = parts[0], right = parts[1], setHandles = _setHandles || this.hasHandles(), - segment1 = this._segment1, - segment2 = this._segment2, + seg1 = this._segment1, + seg2 = this._segment2, path = this._path; if (setHandles) { // Adjust the handles on the existing segments. The new segment // will be inserted between the existing segment1 and segment2: // Convert absolute -> relative - segment1._handleOut._set(left[2] - left[0], left[3] - left[1]); - segment2._handleIn._set(right[4] - right[6],right[5] - right[7]); + seg1._handleOut._set(left[2] - left[0], left[3] - left[1]); + seg2._handleIn._set(right[4] - right[6],right[5] - right[7]); } // Create the new segment: var x = left[6], y = left[7], @@ -493,10 +493,10 @@ var Curve = Base.extend(/** @lends Curve# */{ setHandles && new Point(right[2] - x, right[3] - y)); // Insert it in the segments list, if needed: if (path) { - // By inserting at segment1.index + 1, we make sure to insert at + // By inserting at seg1.index + 1, we make sure to insert at // the end if this curve is a closing curve of a closed path, // as with segment2.index it would be inserted at 0. - path.insert(segment1._index + 1, segment); + path.insert(seg1._index + 1, segment); // The newly inserted segment is the start of the next curve: res = this.getNext(); } else { @@ -1015,6 +1015,21 @@ statics: /** @lends Curve */{ || !this._segment2._handleIn.isZero(); }, + /** + * Checks if this curve has any length. + * + * @param {Number} [epsilon=0] the epsilon against which to compare the + * curve's length + * @return {Boolean} {@true if the curve is longer than the given epsilon} + */ + hasLength: function(epsilon) { + var seg1 = this._segment1, + seg2 = this._segment2; + return (!seg1._point.equals(seg2._point) + || seg1.hasHandles() || seg2.hasHandles()) + && this.getLength() > (epsilon || 0); + }, + /** * Checks if this curve appears as a straight line. This can mean that * it has no handles defined, or that the handles run collinear with the diff --git a/src/path/Path.js b/src/path/Path.js index 78328479..348d0572 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -1212,7 +1212,7 @@ var Path = PathItem.extend(/** @lends Path# */{ // any collinear neighboring curves regardless of their orientation. // This serves as a reliable way to remove linear overlaps but only // as long as the lines are truly overlapping. - if (!curve.hasHandles() && (curve.getLength() < tolerance + if (!curve.hasHandles() && (!curve.hasLength(tolerance) || simplify && curve.isCollinear(curve.getNext()))) curve.remove(); } diff --git a/src/path/PathItem.Boolean.js b/src/path/PathItem.Boolean.js index 2bf83305..a28f93ed 100644 --- a/src/path/PathItem.Boolean.js +++ b/src/path/PathItem.Boolean.js @@ -1017,12 +1017,13 @@ PathItem.inject(new function() { var seg = overlaps[i]._segment, prev = seg.getPrevious(), next = seg.getNext(); - if (seg._path && hasOverlap(prev) && hasOverlap(next)) { + if (hasOverlap(prev) && hasOverlap(next)) { seg.remove(); prev._handleOut._set(0, 0); next._handleIn._set(0, 0); - var curve = prev.getCurve(); - if (curve.isStraight() && curve.getLength() === 0) { + // If the curve that is left has no length, + // remove it altogether. + if (!prev.getCurve().hasLength()) { // Transfer handleIn when removing segment: next._handleIn.set(prev._handleIn); prev.remove();