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
This commit is contained in:
Jürg Lehni 2016-09-20 17:59:56 -04:00
parent 56cfdd9ab6
commit 0af4c5c0f1
3 changed files with 26 additions and 10 deletions

View file

@ -476,15 +476,15 @@ var Curve = Base.extend(/** @lends Curve# */{
left = parts[0], left = parts[0],
right = parts[1], right = parts[1],
setHandles = _setHandles || this.hasHandles(), setHandles = _setHandles || this.hasHandles(),
segment1 = this._segment1, seg1 = this._segment1,
segment2 = this._segment2, seg2 = this._segment2,
path = this._path; path = this._path;
if (setHandles) { if (setHandles) {
// Adjust the handles on the existing segments. The new segment // Adjust the handles on the existing segments. The new segment
// will be inserted between the existing segment1 and segment2: // will be inserted between the existing segment1 and segment2:
// Convert absolute -> relative // Convert absolute -> relative
segment1._handleOut._set(left[2] - left[0], left[3] - left[1]); seg1._handleOut._set(left[2] - left[0], left[3] - left[1]);
segment2._handleIn._set(right[4] - right[6],right[5] - right[7]); seg2._handleIn._set(right[4] - right[6],right[5] - right[7]);
} }
// Create the new segment: // Create the new segment:
var x = left[6], y = left[7], 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)); setHandles && new Point(right[2] - x, right[3] - y));
// Insert it in the segments list, if needed: // Insert it in the segments list, if needed:
if (path) { 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, // the end if this curve is a closing curve of a closed path,
// as with segment2.index it would be inserted at 0. // 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: // The newly inserted segment is the start of the next curve:
res = this.getNext(); res = this.getNext();
} else { } else {
@ -1015,6 +1015,21 @@ statics: /** @lends Curve */{
|| !this._segment2._handleIn.isZero(); || !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 * 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 * it has no handles defined, or that the handles run collinear with the

View file

@ -1212,7 +1212,7 @@ var Path = PathItem.extend(/** @lends Path# */{
// any collinear neighboring curves regardless of their orientation. // any collinear neighboring curves regardless of their orientation.
// This serves as a reliable way to remove linear overlaps but only // This serves as a reliable way to remove linear overlaps but only
// as long as the lines are truly overlapping. // 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()))) || simplify && curve.isCollinear(curve.getNext())))
curve.remove(); curve.remove();
} }

View file

@ -1017,12 +1017,13 @@ PathItem.inject(new function() {
var seg = overlaps[i]._segment, var seg = overlaps[i]._segment,
prev = seg.getPrevious(), prev = seg.getPrevious(),
next = seg.getNext(); next = seg.getNext();
if (seg._path && hasOverlap(prev) && hasOverlap(next)) { if (hasOverlap(prev) && hasOverlap(next)) {
seg.remove(); seg.remove();
prev._handleOut._set(0, 0); prev._handleOut._set(0, 0);
next._handleIn._set(0, 0); next._handleIn._set(0, 0);
var curve = prev.getCurve(); // If the curve that is left has no length,
if (curve.isStraight() && curve.getLength() === 0) { // remove it altogether.
if (!prev.getCurve().hasLength()) {
// Transfer handleIn when removing segment: // Transfer handleIn when removing segment:
next._handleIn.set(prev._handleIn); next._handleIn.set(prev._handleIn);
prev.remove(); prev.remove();