diff --git a/src/basic/Line.js b/src/basic/Line.js index 13e45dd4..42ec32dd 100644 --- a/src/basic/Line.js +++ b/src/basic/Line.js @@ -113,8 +113,9 @@ var Line = Base.extend(/** @lends Line# */{ point.x, point.y, true)); }, - isCollinear: function(line) { - return Point.isCollinear(this._vx, this._vy, line._vx, line._vy); + isCollinear: function(line, sameDir) { + return Point.isCollinear(this._vx, this._vy, line._vx, line._vy, + sameDir); }, isOrthogonal: function(line) { diff --git a/src/basic/Point.js b/src/basic/Point.js index 55f0265b..f8202465 100644 --- a/src/basic/Point.js +++ b/src/basic/Point.js @@ -704,8 +704,9 @@ var Point = Base.extend(/** @lends Point# */{ * @return {Boolean} {@true it is collinear} */ isCollinear: function(/* point */) { - var point = Point.read(arguments); - return Point.isCollinear(this.x, this.y, point.x, point.y); + var point = Point.read(arguments), + sameDir = Base.read(arguments); + return Point.isCollinear(this.x, this.y, point.x, point.y, sameDir); }, // TODO: Remove version with typo after a while (deprecated June 2015) @@ -917,14 +918,16 @@ var Point = Base.extend(/** @lends Point# */{ return new Point(Math.random(), Math.random()); }, - isCollinear: function(x1, y1, x2, y2) { + isCollinear: function(x1, y1, x2, y2, sameDir) { // NOTE: We use normalized vectors so that the epsilon comparison is // reliable. We could instead scale the epsilon based on the vector // length. But instead of normalizing the vectors before calculating // the cross product, we can scale the epsilon accordingly. + var d2 = x2 * x2 + y2 * y2; return Math.abs(x1 * y2 - y1 * x2) - <= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2)) - * /*#=*/Numerical.TRIGONOMETRIC_EPSILON; + <= Math.sqrt((x1 * x1 + y1 * y1) * d2) + * /*#=*/Numerical.TRIGONOMETRIC_EPSILON + && (!sameDir || (x1 * x2 + y1 * y2) / d2 >= 0); }, isOrthogonal: function(x1, y1, x2, y2) { diff --git a/src/path/Curve.js b/src/path/Curve.js index 083eb3c0..694fb874 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -949,9 +949,9 @@ statics: { * @param {Curve} curve the other curve to check against * @return {Boolean} {@true if the two lines are collinear} */ - isCollinear: function(curve) { + isCollinear: function(curve, sameDir) { return curve && this.isStraight() && curve.isStraight() - && this.getLine().isCollinear(curve.getLine()); + && this.getLine().isCollinear(curve.getLine(), sameDir); }, /** diff --git a/src/path/Path.js b/src/path/Path.js index 3384c8c0..46a79466 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -1032,7 +1032,10 @@ var Path = PathItem.extend(/** @lends Path# */{ var curve = curves[i]; if (!curve.hasHandles() && (curve.getLength() < /*#=*/Numerical.GEOMETRIC_EPSILON - || curve.isCollinear(curve.getNext()))) + // Pass true for sameDir, as we can only remove straight + // curves if they point in the same direction as the next + // curve, not 180° in the opposite direction. + || curve.isCollinear(curve.getNext(), true))) curve.remove(); } return this;