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],
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

View file

@ -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();
}

View file

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