From 31d9e1cd6eb847e53c766d82313cfdc7e17d24d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 6 Sep 2015 17:56:12 +0200 Subject: [PATCH] Implement Curve#isLinear() to check for parametrical linearity. Along with some unit tests for it. --- src/path/Curve.js | 128 +++++++++++++++++++++++++------------------- test/tests/Curve.js | 12 +++++ 2 files changed, 84 insertions(+), 56 deletions(-) diff --git a/src/path/Curve.js b/src/path/Curve.js index e2e36cad..03558218 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -797,8 +797,8 @@ statics: { * @type Rectangle * @ignore */ -}), new function() { // Injection scope for tests - function isStraight(l, h1, h2) { +}), Base.each({ // Injection scope for tests both as instance and static methods + isStraight: function(l, h1, h2) { if (h1.isZero() && h2.isZero()) { // No handles. return true; @@ -814,63 +814,79 @@ statics: { return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1; } return false; + }, + + isLinear: function(l, h1, h2) { + var third = l.divide(3); + return h1.equals(third) && h2.negate().equals(third); } +}, function(test, name) { + this[name] = function() { + var seg1 = this._segment1, + seg2 = this._segment2; + return test(seg2._point.subtract(seg1._point), + seg1._handleOut, seg2._handleIn); + }; - return /** @lends Curve# */{ - /** - * {@grouptitle Tests} - * - * Checks if this curve has any curve handles set. - * - * @return {Boolean} {@true if the curve has handles set} - * @see Curve#handle1 - * @see Curve#handle2 - * @see Segment#hasHandles() - * @see Path#hasHandles() - */ - hasHandles: function() { - return !this._segment1._handleOut.isZero() - || !this._segment2._handleIn.isZero(); - }, - - /** - * 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 that connects the curve's start and end point, not falling - * outside of the line. - * - * @return {Boolean} {@true if the curve is straight} - */ - isStraight: function() { - var seg1 = this._segment1, - seg2 = this._segment2; - return isStraight(seg2._point.subtract(seg1._point), - seg1._handleOut, seg2._handleIn); - }, - - /** - * Checks if the the two curves describe straight lines that are - * collinear, meaning they run in parallel. - * - * @param {Curve} curve the other curve to check against - * @return {Boolean} {@true if the two lines are collinear} - */ - isCollinear: function(curve) { - return this.isStraight() && curve.isStraight() - && this.getVector().isCollinear(curve.getVector()); - }, - - statics: { - isStraight: function(v) { - var p1x = v[0], p1y = v[1], - p2x = v[6], p2y = v[7]; - return isStraight(new Point(p2x - p1x, p2y - p1y), - new Point(v[2] - p1x, v[3] - p1y), - new Point(v[4] - p2x, v[5] - p2y)); - } - } - } + this.statics[name] = function(v) { + var p1x = v[0], p1y = v[1], + p2x = v[6], p2y = v[7]; + return test(new Point(p2x - p1x, p2y - p1y), + new Point(v[2] - p1x, v[3] - p1y), + new Point(v[4] - p2x, v[5] - p2y)); + }; }, /** @lends Curve# */{ + statics: {}, // Filled in the loop above + + /** + * {@grouptitle Tests} + * + * Checks if this curve has any curve handles set. + * + * @return {Boolean} {@true if the curve has handles set} + * @see Curve#handle1 + * @see Curve#handle2 + * @see Segment#hasHandles() + * @see Path#hasHandles() + */ + hasHandles: function() { + return !this._segment1._handleOut.isZero() + || !this._segment2._handleIn.isZero(); + }, + + /** + * 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 that connects the curve's start and end point, not falling + * outside of the line. + * + * @name Curve#isStraight + * @function + * @return {Boolean} {@true if the curve is straight} + */ + + /** + * Checks if this curve is parametrically linear, meaning that its + * handles are positioned at 1/3 and 2/3 of the total length of the + * straight curve. + * + * @name Curve#isLinear + * @function + * @return {Boolean} {@true if the curve is parametrically linear} + */ + + /** + * Checks if the the two curves describe straight lines that are + * collinear, meaning they run in parallel. + * + * @param {Curve} curve the other curve to check against + * @return {Boolean} {@true if the two lines are collinear} + */ + isCollinear: function(curve) { + return this.isStraight() && curve.isStraight() + && this.getVector().isCollinear(curve.getVector()); + } +}), /** @lends Curve# */{ // Explicitly deactivate the creation of beans, as we have functions here // that look like bean getters but actually read arguments. // See #getParameterOf(), #getLocationOf(), #getNearestLocation(), ... diff --git a/test/tests/Curve.js b/test/tests/Curve.js index a154dc5e..2e79f27e 100644 --- a/test/tests/Curve.js +++ b/test/tests/Curve.js @@ -211,3 +211,15 @@ test('Curve#isStraight()', function() { return new Curve([100, 100], null, [-50, -50], [100, 100]).isStraight(); }, false); }); + +test('Curve#isLinear()', function() { + equals(function() { + return new Curve([100, 100], [100 / 3, 100 / 3], [-100 / 3, -100 / 3], [200, 200]).isLinear(); + }, true); + equals(function() { + return new Curve([100, 100], null, null, [100, 100]).isLinear(); + }, true); + equals(function() { + return new Curve([100, 100], null, null, [200, 200]).isLinear(); + }, false); +});