From 66717868cd2b71b32133cf9737b81baab501f868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 6 Sep 2015 14:10:15 +0200 Subject: [PATCH] Address failing #isLinear() tests. --- src/path/Curve.js | 17 ++++++++++++++--- src/path/Segment.js | 14 +++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/path/Curve.js b/src/path/Curve.js index 848e65af..58f179a3 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -344,7 +344,9 @@ var Curve = Base.extend(/** @lends Curve# */{ /** * 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 line. + * has no handles defined, or that the handles run collinear with the line + * that connects the curve's start and end point, not falling outside of + * the line. * * @return {Boolean} {@true if the curve is linear} * @see Segment#isLinear() @@ -664,8 +666,17 @@ statics: { l = new Point(p2x - p1x, p2y - p1y), h1 = new Point(v[2] - p1x, v[3] - p1y), h2 = new Point(v[4] - p2x, v[5] - p2y); - return l.isZero() ? h1.isZero() && h2.isZero() - : l.isCollinear(h1) && l.isCollinear(h2); + if (l.isZero()) { + return h1.isZero() && h2.isZero(); + } else if (h1.isCollinear(l) && h2.isCollinear(l)) { + // Get the scalar projection of h1 and h2 onto l, and make sure they + // lie within l (note that h2 is reversed) + var div = l.dot(l), + p1 = l.dot(h1) / div, + p2 = l.dot(h2) / div; + return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1; + } + return false; }, isFlatEnough: function(v, tolerance) { diff --git a/src/path/Segment.js b/src/path/Segment.js index 81065070..863d2770 100644 --- a/src/path/Segment.js +++ b/src/path/Segment.js @@ -253,7 +253,8 @@ var Segment = Base.extend(/** @lends Segment# */{ /** * Checks if the curve that starts in this segment appears as a straight * line. This can mean that it has no handles defined, or that the handles - * run collinear with the line. + * run collinear with the line that connects the curve's start and end + * point, not falling outside of the line. * * @return {Boolean} {@true if the curve starting in this segment is linear} * @see Curve#isLinear() @@ -572,8 +573,15 @@ var Segment = Base.extend(/** @lends Segment# */{ var l = seg2._point.subtract(seg1._point), h1 = seg1._handleOut, h2 = seg2._handleIn; - return l.isZero() ? h1.isZero() && h2.isZero() - : l.isCollinear(h1) && l.isCollinear(h2); + if (l.isZero()) { + return h1.isZero() && h2.isZero(); + } else if (h1.isCollinear(l) && h2.isCollinear(l)) { + var div = l.dot(l), + p1 = l.dot(h1) / div, + p2 = l.dot(h2) / div; + return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1; + } + return false; }, isCollinear: function(seg1, seg2, seg3, seg4) {