From 36923d668853c0aa6c6b2b994a23c60e31806c2e Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sat, 9 Mar 2013 21:57:35 +0100 Subject: [PATCH 01/23] Added basic ol.parser.polyline module This module will contain the low-level functions for Google's "Encoded Polyline" algorithm. --- src/ol/parser/polyline.js | 35 ++++++++++++++++++++++++ test/spec/ol/parser/polyline.test.js | 41 ++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/ol/parser/polyline.js create mode 100644 test/spec/ol/parser/polyline.test.js diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js new file mode 100644 index 0000000000..ec1d564751 --- /dev/null +++ b/src/ol/parser/polyline.js @@ -0,0 +1,35 @@ +goog.provide('ol.parser.polyline'); + + +/** + * Encode one single signed integer and return an encoded string + * + * @param {number} num Signed integer that should be encoded. + * @return {string} The encoded string. + */ +ol.parser.polyline.encodeSignedInteger = function(num) { + var sgn_num = num << 1; + if (num < 0) + sgn_num = ~(sgn_num); + + return ol.parser.polyline.encodeUnsignedInteger(sgn_num); +}; + + +/** + * Encode one single unsigned integer and return an encoded string + * + * @param {number} num Unsigned integer that should be encoded. + * @return {string} The encoded string. + */ +ol.parser.polyline.encodeUnsignedInteger = function(num) { + var value, encodeString = ''; + while (num >= 0x20) { + value = (0x20 | (num & 0x1f)) + 63; + encodeString += (String.fromCharCode(value)); + num >>= 5; + } + value = num + 63; + encodeString += (String.fromCharCode(value)); + return encodeString; +}; diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js new file mode 100644 index 0000000000..dc41a13052 --- /dev/null +++ b/test/spec/ol/parser/polyline.test.js @@ -0,0 +1,41 @@ +goog.provide('ol.test.parser.polyline'); + +describe('ol.parser.polyline', function() { + + describe('encodeSignedInteger', function() { + it('returns expected value', function() { + var encodeSignedInteger = ol.parser.polyline.encodeSignedInteger; + + expect(encodeSignedInteger(0)).toEqual('?'); + expect(encodeSignedInteger(-1)).toEqual('@'); + expect(encodeSignedInteger(1)).toEqual('A'); + expect(encodeSignedInteger(-2)).toEqual('B'); + expect(encodeSignedInteger(2)).toEqual('C'); + expect(encodeSignedInteger(15)).toEqual(']'); + expect(encodeSignedInteger(-16)).toEqual('^'); + + expect(encodeSignedInteger(16)).toEqual('_@'); + expect(encodeSignedInteger(16 * 32)).toEqual('__@'); + expect(encodeSignedInteger(16 * 32 * 32)).toEqual('___@'); + }); + }); + + describe('encodeUnsignedInteger', function() { + it('returns expected value', function() { + var encodeUnsignedInteger = ol.parser.polyline.encodeUnsignedInteger; + + expect(encodeUnsignedInteger(0)).toEqual('?'); + expect(encodeUnsignedInteger(1)).toEqual('@'); + expect(encodeUnsignedInteger(2)).toEqual('A'); + expect(encodeUnsignedInteger(30)).toEqual(']'); + expect(encodeUnsignedInteger(31)).toEqual('^'); + expect(encodeUnsignedInteger(32)).toEqual('_@'); + + expect(encodeUnsignedInteger(32 * 32)).toEqual('__@'); + expect(encodeUnsignedInteger(5 * 32 * 32)).toEqual('__D'); + expect(encodeUnsignedInteger(32 * 32 * 32)).toEqual('___@'); + }); + }); +}); + +goog.require('ol.parser.polyline'); From e802cc3d56c1fce811ba604f196e3c841b55df25 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sat, 9 Mar 2013 22:40:07 +0100 Subject: [PATCH 02/23] polyline: Added decodeSigned/UnsignedInteger() functions --- src/ol/parser/polyline.js | 33 ++++++++++++++++++++++++++ test/spec/ol/parser/polyline.test.js | 35 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index ec1d564751..03ce9077c3 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -16,6 +16,18 @@ ol.parser.polyline.encodeSignedInteger = function(num) { }; +/** + * Decode one single signed integer from an encoded string + * + * @param {string} encoded An encoded string. + * @return {number} The decoded signed integer. + */ +ol.parser.polyline.decodeSignedInteger = function(encoded) { + var result = ol.parser.polyline.decodeUnsignedInteger(encoded); + return ((result & 1) ? ~(result >> 1) : (result >> 1)); +}; + + /** * Encode one single unsigned integer and return an encoded string * @@ -33,3 +45,24 @@ ol.parser.polyline.encodeUnsignedInteger = function(num) { encodeString += (String.fromCharCode(value)); return encodeString; }; + + +/** + * Decode one single unsigned integer from an encoded string + * + * @param {string} encoded An encoded string. + * @return {number} The decoded unsigned integer. + */ +ol.parser.polyline.decodeUnsignedInteger = function(encoded) { + var result = 0; + var shift = 0; + + var b, i = 0; + do { + b = encoded.charCodeAt(i++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + + return result; +}; diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index dc41a13052..2b96b75373 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -20,6 +20,24 @@ describe('ol.parser.polyline', function() { }); }); + describe('decodeSignedInteger', function() { + it('returns expected value', function() { + var decodeSignedInteger = ol.parser.polyline.decodeSignedInteger; + + expect(decodeSignedInteger('?')).toEqual(0); + expect(decodeSignedInteger('@')).toEqual(-1); + expect(decodeSignedInteger('A')).toEqual(1); + expect(decodeSignedInteger('B')).toEqual(-2); + expect(decodeSignedInteger('C')).toEqual(2); + expect(decodeSignedInteger(']')).toEqual(15); + expect(decodeSignedInteger('^')).toEqual(-16); + + expect(decodeSignedInteger('_@')).toEqual(16); + expect(decodeSignedInteger('__@')).toEqual(16 * 32); + expect(decodeSignedInteger('___@')).toEqual(16 * 32 * 32); + }); + }); + describe('encodeUnsignedInteger', function() { it('returns expected value', function() { var encodeUnsignedInteger = ol.parser.polyline.encodeUnsignedInteger; @@ -36,6 +54,23 @@ describe('ol.parser.polyline', function() { expect(encodeUnsignedInteger(32 * 32 * 32)).toEqual('___@'); }); }); + + describe('decodeUnsignedInteger', function() { + it('returns expected value', function() { + var decodeUnsignedInteger = ol.parser.polyline.decodeUnsignedInteger; + + expect(decodeUnsignedInteger('?')).toEqual(0); + expect(decodeUnsignedInteger('@')).toEqual(1); + expect(decodeUnsignedInteger('A')).toEqual(2); + expect(decodeUnsignedInteger(']')).toEqual(30); + expect(decodeUnsignedInteger('^')).toEqual(31); + expect(decodeUnsignedInteger('_@')).toEqual(32); + + expect(decodeUnsignedInteger('__@')).toEqual(32 * 32); + expect(decodeUnsignedInteger('__D')).toEqual(5 * 32 * 32); + expect(decodeUnsignedInteger('___@')).toEqual(32 * 32 * 32); + }); + }); }); goog.require('ol.parser.polyline'); From 04d764f4f3fee01cabc6c1383ddcb64218dedfea Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sat, 9 Mar 2013 23:17:29 +0100 Subject: [PATCH 03/23] polyline: Added encode/decodeFloat() functions --- src/ol/parser/polyline.js | 27 +++++++++++++++++++ test/spec/ol/parser/polyline.test.js | 40 ++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 03ce9077c3..72b9b9bc6f 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -1,6 +1,33 @@ goog.provide('ol.parser.polyline'); +/** + * Encode one single floating point number and return an encoded string + * + * @param {number} num Floating point number that should be encoded. + * @param {number=} opt_factor The factor by which num will be multiplied. + * The remaining decimal places will get rounded away. + * @return {string} The encoded string. + */ +ol.parser.polyline.encodeFloat = function(num, opt_factor) { + num = Math.round(num * (opt_factor || 1e5)); + return ol.parser.polyline.encodeSignedInteger(num); +}; + + +/** + * Decode one single floating point number from an encoded string + * + * @param {string} encoded An encoded string. + * @param {number=} opt_factor The factor by which the result will be divided. + * @return {number} The decoded floating point number. + */ +ol.parser.polyline.decodeFloat = function(encoded, opt_factor) { + var result = ol.parser.polyline.decodeSignedInteger(encoded); + return result / (opt_factor || 1e5); +}; + + /** * Encode one single signed integer and return an encoded string * diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index 2b96b75373..ac8fa35d13 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -2,6 +2,46 @@ goog.provide('ol.test.parser.polyline'); describe('ol.parser.polyline', function() { + describe('encodeFloat', function() { + it('returns expected value', function() { + var encodeFloat = ol.parser.polyline.encodeFloat; + + expect(encodeFloat(0.00000)).toEqual('?'); + expect(encodeFloat(-0.00001)).toEqual('@'); + expect(encodeFloat(0.00001)).toEqual('A'); + expect(encodeFloat(-0.00002)).toEqual('B'); + expect(encodeFloat(0.00002)).toEqual('C'); + expect(encodeFloat(0.00015)).toEqual(']'); + expect(encodeFloat(-0.00016)).toEqual('^'); + + expect(encodeFloat(-0.1, 10)).toEqual('@'); + expect(encodeFloat(0.1, 10)).toEqual('A'); + + expect(encodeFloat(16 * 32 / 1e5)).toEqual('__@'); + expect(encodeFloat(16 * 32 * 32 / 1e5)).toEqual('___@'); + }); + }); + + describe('decodeFloat', function() { + it('returns expected value', function() { + var decodeFloat = ol.parser.polyline.decodeFloat; + + expect(decodeFloat('?')).toEqual(0.00000); + expect(decodeFloat('@')).toEqual(-0.00001); + expect(decodeFloat('A')).toEqual(0.00001); + expect(decodeFloat('B')).toEqual(-0.00002); + expect(decodeFloat('C')).toEqual(0.00002); + expect(decodeFloat(']')).toEqual(0.00015); + expect(decodeFloat('^')).toEqual(-0.00016); + + expect(decodeFloat('@', 10)).toEqual(-0.1); + expect(decodeFloat('A', 10)).toEqual(0.1); + + expect(decodeFloat('__@')).toEqual(16 * 32 / 1e5); + expect(decodeFloat('___@')).toEqual(16 * 32 * 32 / 1e5); + }); + }); + describe('encodeSignedInteger', function() { it('returns expected value', function() { var encodeSignedInteger = ol.parser.polyline.encodeSignedInteger; From ea227419a369c4b69f27cddc97cd85437a860cec Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 01:03:46 +0100 Subject: [PATCH 04/23] polyline: Added encode/decodeFlatCoordinates() functions --- src/ol/parser/polyline.js | 67 ++++++++++++++++++++++++++++ test/spec/ol/parser/polyline.test.js | 22 +++++++++ 2 files changed, 89 insertions(+) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 72b9b9bc6f..8d76ba7f92 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -1,6 +1,73 @@ goog.provide('ol.parser.polyline'); +/** + * Encode a list of coordinates in a flat array and return an encoded string + * + * @param {Array.} flat_points A flat array of coordinates. + * @param {number=} opt_dimension The dimension of the coordinates in the array. + * @return {string} The encoded string. + */ +ol.parser.polyline.encodeFlatCoordinates = + function(flat_points, opt_dimension) { + var dimension = opt_dimension || 2; + + var last_point = new Array(dimension); + for (var i = 0; i < dimension; ++i) + last_point[i] = 0; + + var encoded = '', flat_points_length = flat_points.length; + for (var i = 0; i < flat_points_length;) { + for (var d = 0; d < dimension; ++d) { + var part = Math.round(flat_points[i++] * 1e5); + var delta = part - last_point[d]; + last_point[d] = part; + + encoded += ol.parser.polyline.encodeSignedInteger(delta); + } + } + + return encoded; +}; + + +/** + * Decode a list of coordinates from an encoded string into a flat array + * + * @param {string} encoded An encoded string. + * @param {number=} opt_dimension The dimension of the coordinates in the + * encoded string. + * @return {Array.} A flat array of coordinates. + */ +ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { + var dimension = opt_dimension || 2; + + var last_point = new Array(dimension); + for (var i = 0; i < dimension; ++i) + last_point[i] = 0; + + var flat_points = new Array(), encoded_length = encoded.length; + for (var i = 0; i < encoded_length;) { + for (var d = 0; d < dimension; ++d) { + var result = 0; + var shift = 0; + + var b; + do { + b = encoded.charCodeAt(i++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + + last_point[d] += (result & 1) ? ~(result >> 1) : (result >> 1); + flat_points.push(last_point[d] / 1e5); + } + } + + return flat_points; +}; + + /** * Encode one single floating point number and return an encoded string * diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index ac8fa35d13..baba3223a6 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -2,6 +2,28 @@ goog.provide('ol.test.parser.polyline'); describe('ol.parser.polyline', function() { + var flat_points = [38.50000, -120.20000, + 40.70000, -120.95000, + 43.25200, -126.45300]; + + describe('encodeFlatCoordinates', function() { + it('returns expected value', function() { + var encodeFlatCoordinates = ol.parser.polyline.encodeFlatCoordinates; + + expect(encodeFlatCoordinates( + flat_points)).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); + }); + }); + + describe('decodeFlatCoordinates', function() { + it('returns expected value', function() { + var decodeFlatCoordinates = ol.parser.polyline.decodeFlatCoordinates; + + expect(decodeFlatCoordinates( + '_p~iF~ps|U_ulLnnqC_mqNvxq`@')).toEqual(flat_points); + }); + }); + describe('encodeFloat', function() { it('returns expected value', function() { var encodeFloat = ol.parser.polyline.encodeFloat; From 76fc372a14482181b8e4804bcf6d66225d32d870 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 16:24:30 +0100 Subject: [PATCH 05/23] polyline: Added missing parenthesis for one-line statements --- src/ol/parser/polyline.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 8d76ba7f92..153d2c1126 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -13,8 +13,9 @@ ol.parser.polyline.encodeFlatCoordinates = var dimension = opt_dimension || 2; var last_point = new Array(dimension); - for (var i = 0; i < dimension; ++i) + for (var i = 0; i < dimension; ++i) { last_point[i] = 0; + } var encoded = '', flat_points_length = flat_points.length; for (var i = 0; i < flat_points_length;) { @@ -43,8 +44,9 @@ ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { var dimension = opt_dimension || 2; var last_point = new Array(dimension); - for (var i = 0; i < dimension; ++i) + for (var i = 0; i < dimension; ++i) { last_point[i] = 0; + } var flat_points = new Array(), encoded_length = encoded.length; for (var i = 0; i < encoded_length;) { @@ -103,8 +105,9 @@ ol.parser.polyline.decodeFloat = function(encoded, opt_factor) { */ ol.parser.polyline.encodeSignedInteger = function(num) { var sgn_num = num << 1; - if (num < 0) + if (num < 0) { sgn_num = ~(sgn_num); + } return ol.parser.polyline.encodeUnsignedInteger(sgn_num); }; From 8bf6627354a007a80061ab475aca0fc0c91b5b47 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 16:28:29 +0100 Subject: [PATCH 06/23] polyline: Renamed variables to camelCase convention --- src/ol/parser/polyline.js | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 153d2c1126..0a204ef4d9 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -4,25 +4,25 @@ goog.provide('ol.parser.polyline'); /** * Encode a list of coordinates in a flat array and return an encoded string * - * @param {Array.} flat_points A flat array of coordinates. + * @param {Array.} flatPoints A flat array of coordinates. * @param {number=} opt_dimension The dimension of the coordinates in the array. * @return {string} The encoded string. */ ol.parser.polyline.encodeFlatCoordinates = - function(flat_points, opt_dimension) { + function(flatPoints, opt_dimension) { var dimension = opt_dimension || 2; - var last_point = new Array(dimension); + var lastPoint = new Array(dimension); for (var i = 0; i < dimension; ++i) { - last_point[i] = 0; + lastPoint[i] = 0; } - var encoded = '', flat_points_length = flat_points.length; - for (var i = 0; i < flat_points_length;) { + var encoded = '', flatPointsLength = flatPoints.length; + for (var i = 0; i < flatPointsLength;) { for (var d = 0; d < dimension; ++d) { - var part = Math.round(flat_points[i++] * 1e5); - var delta = part - last_point[d]; - last_point[d] = part; + var part = Math.round(flatPoints[i++] * 1e5); + var delta = part - lastPoint[d]; + lastPoint[d] = part; encoded += ol.parser.polyline.encodeSignedInteger(delta); } @@ -43,13 +43,13 @@ ol.parser.polyline.encodeFlatCoordinates = ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { var dimension = opt_dimension || 2; - var last_point = new Array(dimension); + var lastPoint = new Array(dimension); for (var i = 0; i < dimension; ++i) { - last_point[i] = 0; + lastPoint[i] = 0; } - var flat_points = new Array(), encoded_length = encoded.length; - for (var i = 0; i < encoded_length;) { + var flatPoints = new Array(), encodedLength = encoded.length; + for (var i = 0; i < encodedLength;) { for (var d = 0; d < dimension; ++d) { var result = 0; var shift = 0; @@ -61,12 +61,12 @@ ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { shift += 5; } while (b >= 0x20); - last_point[d] += (result & 1) ? ~(result >> 1) : (result >> 1); - flat_points.push(last_point[d] / 1e5); + lastPoint[d] += (result & 1) ? ~(result >> 1) : (result >> 1); + flatPoints.push(lastPoint[d] / 1e5); } } - return flat_points; + return flatPoints; }; @@ -104,12 +104,12 @@ ol.parser.polyline.decodeFloat = function(encoded, opt_factor) { * @return {string} The encoded string. */ ol.parser.polyline.encodeSignedInteger = function(num) { - var sgn_num = num << 1; + var signedNum = num << 1; if (num < 0) { - sgn_num = ~(sgn_num); + signedNum = ~(signedNum); } - return ol.parser.polyline.encodeUnsignedInteger(sgn_num); + return ol.parser.polyline.encodeUnsignedInteger(signedNum); }; @@ -132,15 +132,15 @@ ol.parser.polyline.decodeSignedInteger = function(encoded) { * @return {string} The encoded string. */ ol.parser.polyline.encodeUnsignedInteger = function(num) { - var value, encodeString = ''; + var value, encoded = ''; while (num >= 0x20) { value = (0x20 | (num & 0x1f)) + 63; - encodeString += (String.fromCharCode(value)); + encoded += (String.fromCharCode(value)); num >>= 5; } value = num + 63; - encodeString += (String.fromCharCode(value)); - return encodeString; + encoded += (String.fromCharCode(value)); + return encoded; }; From 395942fe8ca927ffc1ab02d587dab091d9aeecfa Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 16:33:44 +0100 Subject: [PATCH 07/23] polyline: Only declare i variable once Javascript only has function-wide scoping... --- src/ol/parser/polyline.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 0a204ef4d9..97254a1913 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -11,14 +11,15 @@ goog.provide('ol.parser.polyline'); ol.parser.polyline.encodeFlatCoordinates = function(flatPoints, opt_dimension) { var dimension = opt_dimension || 2; + var i; var lastPoint = new Array(dimension); - for (var i = 0; i < dimension; ++i) { + for (i = 0; i < dimension; ++i) { lastPoint[i] = 0; } var encoded = '', flatPointsLength = flatPoints.length; - for (var i = 0; i < flatPointsLength;) { + for (i = 0; i < flatPointsLength;) { for (var d = 0; d < dimension; ++d) { var part = Math.round(flatPoints[i++] * 1e5); var delta = part - lastPoint[d]; @@ -42,14 +43,15 @@ ol.parser.polyline.encodeFlatCoordinates = */ ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { var dimension = opt_dimension || 2; + var i; var lastPoint = new Array(dimension); - for (var i = 0; i < dimension; ++i) { + for (i = 0; i < dimension; ++i) { lastPoint[i] = 0; } var flatPoints = new Array(), encodedLength = encoded.length; - for (var i = 0; i < encodedLength;) { + for (i = 0; i < encodedLength;) { for (var d = 0; d < dimension; ++d) { var result = 0; var shift = 0; From 680f3386cea7d433eb600d79d208ce7f7c4850b5 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 16:42:51 +0100 Subject: [PATCH 08/23] test/polyline: Added more test cases from official documentation .. and marked those tests as such. URL of the "Encoded Polyline Algorithm Format" page is https://developers.google.com/maps/documentation/utilities/polylinealgorithm --- test/spec/ol/parser/polyline.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index baba3223a6..cf392bcc85 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -10,6 +10,7 @@ describe('ol.parser.polyline', function() { it('returns expected value', function() { var encodeFlatCoordinates = ol.parser.polyline.encodeFlatCoordinates; + // from the "Encoded Polyline Algorithm Format" page at Google expect(encodeFlatCoordinates( flat_points)).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); }); @@ -19,6 +20,7 @@ describe('ol.parser.polyline', function() { it('returns expected value', function() { var decodeFlatCoordinates = ol.parser.polyline.decodeFlatCoordinates; + // from the "Encoded Polyline Algorithm Format" page at Google expect(decodeFlatCoordinates( '_p~iF~ps|U_ulLnnqC_mqNvxq`@')).toEqual(flat_points); }); @@ -41,6 +43,9 @@ describe('ol.parser.polyline', function() { expect(encodeFloat(16 * 32 / 1e5)).toEqual('__@'); expect(encodeFloat(16 * 32 * 32 / 1e5)).toEqual('___@'); + + // from the "Encoded Polyline Algorithm Format" page at Google + expect(encodeFloat(-179.9832104)).toEqual('`~oia@'); }); }); @@ -61,6 +66,9 @@ describe('ol.parser.polyline', function() { expect(decodeFloat('__@')).toEqual(16 * 32 / 1e5); expect(decodeFloat('___@')).toEqual(16 * 32 * 32 / 1e5); + + // from the "Encoded Polyline Algorithm Format" page at Google + expect(decodeFloat('`~oia@')).toEqual(-179.98321); }); }); From ce619871c206001460b810fb38c8355af3d1368c Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 17:00:37 +0100 Subject: [PATCH 09/23] test/polyline: Added two more test cases for unsigned integers Again taken from the official documentation at Google. --- test/spec/ol/parser/polyline.test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index cf392bcc85..3dd3c0155b 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -122,6 +122,9 @@ describe('ol.parser.polyline', function() { expect(encodeUnsignedInteger(32 * 32)).toEqual('__@'); expect(encodeUnsignedInteger(5 * 32 * 32)).toEqual('__D'); expect(encodeUnsignedInteger(32 * 32 * 32)).toEqual('___@'); + + // from the "Encoded Polyline Algorithm Format" page at Google + expect(encodeUnsignedInteger(174)).toEqual('mD'); }); }); @@ -139,6 +142,9 @@ describe('ol.parser.polyline', function() { expect(decodeUnsignedInteger('__@')).toEqual(32 * 32); expect(decodeUnsignedInteger('__D')).toEqual(5 * 32 * 32); expect(decodeUnsignedInteger('___@')).toEqual(32 * 32 * 32); + + // from the "Encoded Polyline Algorithm Format" page at Google + expect(decodeUnsignedInteger('mD')).toEqual(174); }); }); }); From 78278798bb8ab7350be1557c6ede91e6ccf004ae Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 18:48:49 +0100 Subject: [PATCH 10/23] polyline: Added encode/decodeUnsignedIntegers() functions --- src/ol/parser/polyline.js | 46 ++++++++++++++++++++++++++++ test/spec/ol/parser/polyline.test.js | 23 ++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 97254a1913..96178f82f4 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -72,6 +72,52 @@ ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { }; +/** + * Encode a list of unsigned integers and return an encoded string + * + * @param {Array.} numbers A list of unsigned integers. + * @return {string} The encoded string. + */ +ol.parser.polyline.encodeUnsignedIntegers = function(numbers) { + var encoded = ''; + + var numbersLength = numbers.length; + for (var i = 0; i < numbersLength; ++i) { + encoded += ol.parser.polyline.encodeUnsignedInteger(numbers[i]); + } + + return encoded; +}; + + +/** + * Decode a list of unsigned integers from an encoded string + * + * @param {string} encoded An encoded string. + * @return {Array.} A list of unsigned integers. + */ +ol.parser.polyline.decodeUnsignedIntegers = function(encoded) { + var numbers = new Array(); + + var encodedLength = encoded.length; + for (var i = 0; i < encodedLength;) { + var result = 0; + var shift = 0; + + var b; + do { + b = encoded.charCodeAt(i++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + + numbers.push(result); + } + + return numbers; +}; + + /** * Encode one single floating point number and return an encoded string * diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index 3dd3c0155b..cab296a184 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -26,6 +26,29 @@ describe('ol.parser.polyline', function() { }); }); + + var unsignedIntegers = [0, 30, 1, 31, 32, 2, 174]; + var encodedUnsignedIntegers = '?]@^_@AmD'; + + describe('encodeUnsignedIntegers', function() { + it('returns expected value', function() { + var encodeUnsignedIntegers = ol.parser.polyline.encodeUnsignedIntegers; + + expect(encodeUnsignedIntegers( + unsignedIntegers)).toEqual(encodedUnsignedIntegers); + }); + }); + + describe('decodeUnsignedIntegers', function() { + it('returns expected value', function() { + var decodeUnsignedIntegers = ol.parser.polyline.decodeUnsignedIntegers; + + expect(decodeUnsignedIntegers( + encodedUnsignedIntegers)).toEqual(unsignedIntegers); + }); + }); + + describe('encodeFloat', function() { it('returns expected value', function() { var encodeFloat = ol.parser.polyline.encodeFloat; From cbdaf1035dfcf8b9a6a7ef3cc8857b70e4fce2ff Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 19:05:14 +0100 Subject: [PATCH 11/23] polyline: Added encode/decodeSignedIntegers() functions --- src/ol/parser/polyline.js | 44 ++++++++++++++++++++++++++++ test/spec/ol/parser/polyline.test.js | 22 ++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 96178f82f4..ad49f2d2d8 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -72,6 +72,50 @@ ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { }; +/** + * Encode a list of signed integers and return an encoded string + * + * Attention: This function will modify the passed array! + * + * @param {Array.} numbers A list of signed integers. + * @return {string} The encoded string. + */ +ol.parser.polyline.encodeSignedIntegers = function(numbers) { + var numbersLength = numbers.length; + for (var i = 0; i < numbersLength; ++i) { + var num = numbers[i]; + + var signedNum = num << 1; + if (num < 0) { + signedNum = ~(signedNum); + } + + numbers[i] = signedNum; + } + + return ol.parser.polyline.encodeUnsignedIntegers(numbers); +}; + + +/** + * Decode a list of signed integers from an encoded string + * + * @param {string} encoded An encoded string. + * @return {Array.} A list of signed integers. + */ +ol.parser.polyline.decodeSignedIntegers = function(encoded) { + var numbers = ol.parser.polyline.decodeUnsignedIntegers(encoded); + + var numbersLength = numbers.length; + for (var i = 0; i < numbersLength; ++i) { + var num = numbers[i]; + numbers[i] = (num & 1) ? ~(num >> 1) : (num >> 1); + } + + return numbers; +}; + + /** * Encode a list of unsigned integers and return an encoded string * diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index cab296a184..1e3540c1c3 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -27,6 +27,28 @@ describe('ol.parser.polyline', function() { }); + var signedIntegers = [0, 15, -1, -16, 16, 1]; + var encodedSignedIntegers = '?]@^_@A'; + + describe('encodeSignedIntegers', function() { + it('returns expected value', function() { + var encodeSignedIntegers = ol.parser.polyline.encodeSignedIntegers; + + expect(encodeSignedIntegers( + signedIntegers.slice())).toEqual(encodedSignedIntegers); + }); + }); + + describe('decodeSignedIntegers', function() { + it('returns expected value', function() { + var decodeSignedIntegers = ol.parser.polyline.decodeSignedIntegers; + + expect(decodeSignedIntegers( + encodedSignedIntegers)).toEqual(signedIntegers); + }); + }); + + var unsignedIntegers = [0, 30, 1, 31, 32, 2, 174]; var encodedUnsignedIntegers = '?]@^_@AmD'; From 02707401a38f819c92756b5f9b085a4410786555 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 20:04:54 +0100 Subject: [PATCH 12/23] polyline: Added encode/decodeFloats() functions --- src/ol/parser/polyline.js | 43 ++++++++++++++++++++++++++++ test/spec/ol/parser/polyline.test.js | 25 ++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index ad49f2d2d8..103da8baea 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -72,6 +72,49 @@ ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { }; +/** + * Encode a list of floating point numbers and return an encoded string + * + * Attention: This function will modify the passed array! + * + * @param {Array.} numbers A list of floating point numbers. + * @param {number=} opt_factor The factor by which the numbers will be + * multiplied. The remaining decimal places will get rounded away. + * @return {string} The encoded string. + */ +ol.parser.polyline.encodeFloats = function(numbers, opt_factor) { + var factor = opt_factor || 1e5; + + var numbersLength = numbers.length; + for (var i = 0; i < numbersLength; ++i) { + numbers[i] = Math.round(numbers[i] * factor); + } + + return ol.parser.polyline.encodeSignedIntegers(numbers); +}; + + +/** + * Decode a list of floating point numbers from an encoded string + * + * @param {string} encoded An encoded string. + * @param {number=} opt_factor The factor by which the result will be divided. + * @return {Array.} A list of floating point numbers. + */ +ol.parser.polyline.decodeFloats = function(encoded, opt_factor) { + var factor = opt_factor || 1e5; + + var numbers = ol.parser.polyline.decodeSignedIntegers(encoded); + + var numbersLength = numbers.length; + for (var i = 0; i < numbersLength; ++i) { + numbers[i] /= factor; + } + + return numbers; +}; + + /** * Encode a list of signed integers and return an encoded string * diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index 1e3540c1c3..c73b9bd63b 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -27,6 +27,31 @@ describe('ol.parser.polyline', function() { }); + var floats = [0.00, 0.15, -0.01, -0.16, 0.16, 0.01]; + var smallFloats = [0.00000, 0.00015, -0.00001, -0.00016, 0.00016, 0.00001]; + var encodedFloats = '?]@^_@A'; + + describe('encodeFloats', function() { + it('returns expected value', function() { + var encodeFloats = ol.parser.polyline.encodeFloats; + + expect(encodeFloats(smallFloats.slice())).toEqual(encodedFloats); + expect(encodeFloats(smallFloats.slice(), 1e5)).toEqual(encodedFloats); + expect(encodeFloats(floats.slice(), 1e2)).toEqual(encodedFloats); + }); + }); + + describe('decodeFloats', function() { + it('returns expected value', function() { + var decodeFloats = ol.parser.polyline.decodeFloats; + + expect(decodeFloats(encodedFloats)).toEqual(smallFloats); + expect(decodeFloats(encodedFloats, 1e5)).toEqual(smallFloats); + expect(decodeFloats(encodedFloats, 1e2)).toEqual(floats); + }); + }); + + var signedIntegers = [0, 15, -1, -16, 16, 1]; var encodedSignedIntegers = '?]@^_@A'; From aef15947c81047733f07ff8107305fc624b64429 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 20:44:34 +0100 Subject: [PATCH 13/23] polyline: Added encode/decodeDeltas() functions --- src/ol/parser/polyline.js | 69 ++++++++++++++++++++++++++++ test/spec/ol/parser/polyline.test.js | 19 ++++++++ 2 files changed, 88 insertions(+) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 103da8baea..7303d8e871 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -72,6 +72,75 @@ ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { }; + +/** + * Encode a list of n-dimensional points and return an encoded string + * + * Attention: This function will modify the passed array! + * + * @param {Array.} numbers A list of n-dimensional points. + * @param {number} dimension The dimension of the points in the list. + * @param {number=} opt_factor The factor by which the numbers will be + * multiplied. The remaining decimal places will get rounded away. + * @return {string} The encoded string. + */ +ol.parser.polyline.encodeDeltas = function(numbers, dimension, opt_factor) { + var factor = opt_factor || 1e5; + var d; + + var lastNumbers = new Array(dimension); + for (d = 0; d < dimension; ++d) { + lastNumbers[d] = 0; + } + + var numbersLength = numbers.length; + for (var i = 0; i < numbersLength;) { + for (d = 0; d < dimension; ++d, ++i) { + var num = numbers[i]; + var delta = num - lastNumbers[d]; + lastNumbers[d] = num; + + numbers[i] = delta; + } + } + + return ol.parser.polyline.encodeFloats(numbers, factor); +}; + + +/** + * Decode a list of n-dimensional points from an encoded string + * + * @param {string} encoded An encoded string. + * @param {number} dimension The dimension of the points in the encoded string. + * @param {number=} opt_factor The factor by which the resulting numbers will + * be divided. + * @return {Array.} A list of n-dimensional points. + */ +ol.parser.polyline.decodeDeltas = function(encoded, dimension, opt_factor) { + var factor = opt_factor || 1e5; + var d; + + var lastNumbers = new Array(dimension); + for (d = 0; d < dimension; ++d) { + lastNumbers[d] = 0; + } + + var numbers = ol.parser.polyline.decodeFloats(encoded, factor); + + var numbersLength = numbers.length; + for (var i = 0; i < numbersLength;) { + for (d = 0; d < dimension; ++d, ++i) { + lastNumbers[d] += numbers[i]; + + numbers[i] = lastNumbers[d]; + } + } + + return numbers; +}; + + /** * Encode a list of floating point numbers and return an encoded string * diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index c73b9bd63b..270b263366 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -27,6 +27,25 @@ describe('ol.parser.polyline', function() { }); + describe('encodeDeltas', function() { + it('returns expected value', function() { + var encodeDeltas = ol.parser.polyline.encodeDeltas; + + expect(encodeDeltas( + flat_points.slice(), 2)).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); + }); + }); + + describe('decodeDeltas', function() { + it('returns expected value', function() { + var decodeDeltas = ol.parser.polyline.decodeDeltas; + + expect(decodeDeltas( + '_p~iF~ps|U_ulLnnqC_mqNvxq`@', 2)).toEqual(flat_points); + }); + }); + + var floats = [0.00, 0.15, -0.01, -0.16, 0.16, 0.01]; var smallFloats = [0.00000, 0.00015, -0.00001, -0.00016, 0.00016, 0.00001]; var encodedFloats = '?]@^_@A'; From 6f0812239808d7f020039413024bb9da558c08c3 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 20:45:12 +0100 Subject: [PATCH 14/23] polyline: Used new *Deltas() functions in *FlatCoordinates() --- src/ol/parser/polyline.js | 50 +++------------------------- test/spec/ol/parser/polyline.test.js | 2 +- 2 files changed, 5 insertions(+), 47 deletions(-) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 7303d8e871..f07c979894 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -4,6 +4,8 @@ goog.provide('ol.parser.polyline'); /** * Encode a list of coordinates in a flat array and return an encoded string * + * Attention: This function will modify the passed array! + * * @param {Array.} flatPoints A flat array of coordinates. * @param {number=} opt_dimension The dimension of the coordinates in the array. * @return {string} The encoded string. @@ -11,25 +13,7 @@ goog.provide('ol.parser.polyline'); ol.parser.polyline.encodeFlatCoordinates = function(flatPoints, opt_dimension) { var dimension = opt_dimension || 2; - var i; - - var lastPoint = new Array(dimension); - for (i = 0; i < dimension; ++i) { - lastPoint[i] = 0; - } - - var encoded = '', flatPointsLength = flatPoints.length; - for (i = 0; i < flatPointsLength;) { - for (var d = 0; d < dimension; ++d) { - var part = Math.round(flatPoints[i++] * 1e5); - var delta = part - lastPoint[d]; - lastPoint[d] = part; - - encoded += ol.parser.polyline.encodeSignedInteger(delta); - } - } - - return encoded; + return ol.parser.polyline.encodeDeltas(flatPoints, dimension); }; @@ -43,36 +27,10 @@ ol.parser.polyline.encodeFlatCoordinates = */ ol.parser.polyline.decodeFlatCoordinates = function(encoded, opt_dimension) { var dimension = opt_dimension || 2; - var i; - - var lastPoint = new Array(dimension); - for (i = 0; i < dimension; ++i) { - lastPoint[i] = 0; - } - - var flatPoints = new Array(), encodedLength = encoded.length; - for (i = 0; i < encodedLength;) { - for (var d = 0; d < dimension; ++d) { - var result = 0; - var shift = 0; - - var b; - do { - b = encoded.charCodeAt(i++) - 63; - result |= (b & 0x1f) << shift; - shift += 5; - } while (b >= 0x20); - - lastPoint[d] += (result & 1) ? ~(result >> 1) : (result >> 1); - flatPoints.push(lastPoint[d] / 1e5); - } - } - - return flatPoints; + return ol.parser.polyline.decodeDeltas(encoded, dimension); }; - /** * Encode a list of n-dimensional points and return an encoded string * diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index 270b263366..ae5d0e3de7 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -12,7 +12,7 @@ describe('ol.parser.polyline', function() { // from the "Encoded Polyline Algorithm Format" page at Google expect(encodeFlatCoordinates( - flat_points)).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); + flat_points.slice())).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); }); }); From 8a34eaa4a4e6fec2d5164ca08c605125e92138b7 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 20:46:29 +0100 Subject: [PATCH 15/23] polyline: Removed extra space in encodeFloats() function --- src/ol/parser/polyline.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index f07c979894..615ec24062 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -114,7 +114,7 @@ ol.parser.polyline.encodeFloats = function(numbers, opt_factor) { var numbersLength = numbers.length; for (var i = 0; i < numbersLength; ++i) { - numbers[i] = Math.round(numbers[i] * factor); + numbers[i] = Math.round(numbers[i] * factor); } return ol.parser.polyline.encodeSignedIntegers(numbers); From 4b8a9aaa8f2156a5a2eaabe5a1740e931470517b Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 20:59:15 +0100 Subject: [PATCH 16/23] test/polyline: Renamed flat_points variable to flatPoints --- test/spec/ol/parser/polyline.test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index ae5d0e3de7..1b6620ef05 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -2,9 +2,9 @@ goog.provide('ol.test.parser.polyline'); describe('ol.parser.polyline', function() { - var flat_points = [38.50000, -120.20000, - 40.70000, -120.95000, - 43.25200, -126.45300]; + var flatPoints = [38.50000, -120.20000, + 40.70000, -120.95000, + 43.25200, -126.45300]; describe('encodeFlatCoordinates', function() { it('returns expected value', function() { @@ -12,7 +12,7 @@ describe('ol.parser.polyline', function() { // from the "Encoded Polyline Algorithm Format" page at Google expect(encodeFlatCoordinates( - flat_points.slice())).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); + flatPoints.slice())).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); }); }); @@ -22,7 +22,7 @@ describe('ol.parser.polyline', function() { // from the "Encoded Polyline Algorithm Format" page at Google expect(decodeFlatCoordinates( - '_p~iF~ps|U_ulLnnqC_mqNvxq`@')).toEqual(flat_points); + '_p~iF~ps|U_ulLnnqC_mqNvxq`@')).toEqual(flatPoints); }); }); @@ -32,7 +32,7 @@ describe('ol.parser.polyline', function() { var encodeDeltas = ol.parser.polyline.encodeDeltas; expect(encodeDeltas( - flat_points.slice(), 2)).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); + flatPoints.slice(), 2)).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); }); }); @@ -41,7 +41,7 @@ describe('ol.parser.polyline', function() { var decodeDeltas = ol.parser.polyline.decodeDeltas; expect(decodeDeltas( - '_p~iF~ps|U_ulLnnqC_mqNvxq`@', 2)).toEqual(flat_points); + '_p~iF~ps|U_ulLnnqC_mqNvxq`@', 2)).toEqual(flatPoints); }); }); From f793b69602fe1e2a80efde2301046dc6f779c48f Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 21:05:32 +0100 Subject: [PATCH 17/23] test/polyline: Reset testing data before each test .. instead of using slice() --- test/spec/ol/parser/polyline.test.js | 53 +++++++++++++++++++--------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index 1b6620ef05..5cfb54c12e 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -2,9 +2,29 @@ goog.provide('ol.test.parser.polyline'); describe('ol.parser.polyline', function() { - var flatPoints = [38.50000, -120.20000, - 40.70000, -120.95000, - 43.25200, -126.45300]; + var flatPoints; + var floats, smallFloats, encodedFloats; + var signedIntegers, encodedSignedIntegers; + var unsignedIntegers, encodedUnsignedIntegers; + + // Reset testing data + beforeEach(function() { + flatPoints = [38.50000, -120.20000, + 40.70000, -120.95000, + 43.25200, -126.45300]; + + floats = [0.00, 0.15, -0.01, -0.16, 0.16, 0.01]; + smallFloats = [0.00000, 0.00015, -0.00001, -0.00016, 0.00016, 0.00001]; + encodedFloats = '?]@^_@A'; + + signedIntegers = [0, 15, -1, -16, 16, 1]; + encodedSignedIntegers = '?]@^_@A'; + + unsignedIntegers = [0, 30, 1, 31, 32, 2, 174]; + encodedUnsignedIntegers = '?]@^_@AmD'; + }) + + describe('encodeFlatCoordinates', function() { it('returns expected value', function() { @@ -12,7 +32,7 @@ describe('ol.parser.polyline', function() { // from the "Encoded Polyline Algorithm Format" page at Google expect(encodeFlatCoordinates( - flatPoints.slice())).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); + flatPoints).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); }); }); @@ -27,12 +47,13 @@ describe('ol.parser.polyline', function() { }); + describe('encodeDeltas', function() { it('returns expected value', function() { var encodeDeltas = ol.parser.polyline.encodeDeltas; expect(encodeDeltas( - flatPoints.slice(), 2)).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); + flatPoints, 2)).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); }); }); @@ -46,17 +67,14 @@ describe('ol.parser.polyline', function() { }); - var floats = [0.00, 0.15, -0.01, -0.16, 0.16, 0.01]; - var smallFloats = [0.00000, 0.00015, -0.00001, -0.00016, 0.00016, 0.00001]; - var encodedFloats = '?]@^_@A'; describe('encodeFloats', function() { it('returns expected value', function() { var encodeFloats = ol.parser.polyline.encodeFloats; - expect(encodeFloats(smallFloats.slice())).toEqual(encodedFloats); - expect(encodeFloats(smallFloats.slice(), 1e5)).toEqual(encodedFloats); - expect(encodeFloats(floats.slice(), 1e2)).toEqual(encodedFloats); + expect(encodeFloats(smallFloats).toEqual(encodedFloats); + expect(encodeFloats(smallFloats, 1e5)).toEqual(encodedFloats); + expect(encodeFloats(floats, 1e2)).toEqual(encodedFloats); }); }); @@ -71,15 +89,13 @@ describe('ol.parser.polyline', function() { }); - var signedIntegers = [0, 15, -1, -16, 16, 1]; - var encodedSignedIntegers = '?]@^_@A'; describe('encodeSignedIntegers', function() { it('returns expected value', function() { var encodeSignedIntegers = ol.parser.polyline.encodeSignedIntegers; expect(encodeSignedIntegers( - signedIntegers.slice())).toEqual(encodedSignedIntegers); + signedIntegers).toEqual(encodedSignedIntegers); }); }); @@ -93,10 +109,8 @@ describe('ol.parser.polyline', function() { }); - var unsignedIntegers = [0, 30, 1, 31, 32, 2, 174]; - var encodedUnsignedIntegers = '?]@^_@AmD'; - describe('encodeUnsignedIntegers', function() { + describe('encodeUnsignedIntegers', function() { it('returns expected value', function() { var encodeUnsignedIntegers = ol.parser.polyline.encodeUnsignedIntegers; @@ -115,6 +129,7 @@ describe('ol.parser.polyline', function() { }); + describe('encodeFloat', function() { it('returns expected value', function() { var encodeFloat = ol.parser.polyline.encodeFloat; @@ -161,6 +176,8 @@ describe('ol.parser.polyline', function() { }); }); + + describe('encodeSignedInteger', function() { it('returns expected value', function() { var encodeSignedInteger = ol.parser.polyline.encodeSignedInteger; @@ -197,6 +214,8 @@ describe('ol.parser.polyline', function() { }); }); + + describe('encodeUnsignedInteger', function() { it('returns expected value', function() { var encodeUnsignedInteger = ol.parser.polyline.encodeUnsignedInteger; From 5333d001732a3583a3dbd611059bf0ca57b971af Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 21:07:23 +0100 Subject: [PATCH 18/23] test/polyline: Added encodedFlatPoints to testing data variables DRY... --- test/spec/ol/parser/polyline.test.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index 5cfb54c12e..c73b288de1 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -2,7 +2,7 @@ goog.provide('ol.test.parser.polyline'); describe('ol.parser.polyline', function() { - var flatPoints; + var flatPoints, encodedFlatPoints; var floats, smallFloats, encodedFloats; var signedIntegers, encodedSignedIntegers; var unsignedIntegers, encodedUnsignedIntegers; @@ -12,6 +12,7 @@ describe('ol.parser.polyline', function() { flatPoints = [38.50000, -120.20000, 40.70000, -120.95000, 43.25200, -126.45300]; + encodedFlatPoints = '_p~iF~ps|U_ulLnnqC_mqNvxq`@'; floats = [0.00, 0.15, -0.01, -0.16, 0.16, 0.01]; smallFloats = [0.00000, 0.00015, -0.00001, -0.00016, 0.00016, 0.00001]; @@ -31,8 +32,7 @@ describe('ol.parser.polyline', function() { var encodeFlatCoordinates = ol.parser.polyline.encodeFlatCoordinates; // from the "Encoded Polyline Algorithm Format" page at Google - expect(encodeFlatCoordinates( - flatPoints).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); + expect(encodeFlatCoordinates(flatPoints).toEqual(encodedFlatPoints); }); }); @@ -41,8 +41,7 @@ describe('ol.parser.polyline', function() { var decodeFlatCoordinates = ol.parser.polyline.decodeFlatCoordinates; // from the "Encoded Polyline Algorithm Format" page at Google - expect(decodeFlatCoordinates( - '_p~iF~ps|U_ulLnnqC_mqNvxq`@')).toEqual(flatPoints); + expect(decodeFlatCoordinates(encodedFlatPoints)).toEqual(flatPoints); }); }); @@ -52,8 +51,7 @@ describe('ol.parser.polyline', function() { it('returns expected value', function() { var encodeDeltas = ol.parser.polyline.encodeDeltas; - expect(encodeDeltas( - flatPoints, 2)).toEqual('_p~iF~ps|U_ulLnnqC_mqNvxq`@'); + expect(encodeDeltas(flatPoints, 2)).toEqual(encodedFlatPoints); }); }); @@ -61,8 +59,7 @@ describe('ol.parser.polyline', function() { it('returns expected value', function() { var decodeDeltas = ol.parser.polyline.decodeDeltas; - expect(decodeDeltas( - '_p~iF~ps|U_ulLnnqC_mqNvxq`@', 2)).toEqual(flatPoints); + expect(decodeDeltas(encodedFlatPoints, 2)).toEqual(flatPoints); }); }); From 5d492a22fa6843dfa2c81bb1ac55ad80172c112f Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 10 Mar 2013 21:13:48 +0100 Subject: [PATCH 19/23] test/polyline: Fixed linter problems --- test/spec/ol/parser/polyline.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index c73b288de1..107cde87f4 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -23,7 +23,7 @@ describe('ol.parser.polyline', function() { unsignedIntegers = [0, 30, 1, 31, 32, 2, 174]; encodedUnsignedIntegers = '?]@^_@AmD'; - }) + }); @@ -69,7 +69,7 @@ describe('ol.parser.polyline', function() { it('returns expected value', function() { var encodeFloats = ol.parser.polyline.encodeFloats; - expect(encodeFloats(smallFloats).toEqual(encodedFloats); + expect(encodeFloats(smallFloats)).toEqual(encodedFloats); expect(encodeFloats(smallFloats, 1e5)).toEqual(encodedFloats); expect(encodeFloats(floats, 1e2)).toEqual(encodedFloats); }); @@ -107,7 +107,7 @@ describe('ol.parser.polyline', function() { - describe('encodeUnsignedIntegers', function() { + describe('encodeUnsignedIntegers', function() { it('returns expected value', function() { var encodeUnsignedIntegers = ol.parser.polyline.encodeUnsignedIntegers; From 8b45637e729c3f37f1232eb55c5f8470bed590c6 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Mon, 11 Mar 2013 20:32:18 +0100 Subject: [PATCH 20/23] test/polyline: Added missing brackets --- test/spec/ol/parser/polyline.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index 107cde87f4..e28baf360d 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -32,7 +32,7 @@ describe('ol.parser.polyline', function() { var encodeFlatCoordinates = ol.parser.polyline.encodeFlatCoordinates; // from the "Encoded Polyline Algorithm Format" page at Google - expect(encodeFlatCoordinates(flatPoints).toEqual(encodedFlatPoints); + expect(encodeFlatCoordinates(flatPoints)).toEqual(encodedFlatPoints); }); }); @@ -92,7 +92,7 @@ describe('ol.parser.polyline', function() { var encodeSignedIntegers = ol.parser.polyline.encodeSignedIntegers; expect(encodeSignedIntegers( - signedIntegers).toEqual(encodedSignedIntegers); + signedIntegers)).toEqual(encodedSignedIntegers); }); }); From 8330586ee230e78695fafd8de4558643af845603 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Mon, 11 Mar 2013 20:32:22 +0100 Subject: [PATCH 21/23] test/polyline: Reset testing data manually in encodeFloats test --- test/spec/ol/parser/polyline.test.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/spec/ol/parser/polyline.test.js b/test/spec/ol/parser/polyline.test.js index e28baf360d..62aac783b7 100644 --- a/test/spec/ol/parser/polyline.test.js +++ b/test/spec/ol/parser/polyline.test.js @@ -7,8 +7,7 @@ describe('ol.parser.polyline', function() { var signedIntegers, encodedSignedIntegers; var unsignedIntegers, encodedUnsignedIntegers; - // Reset testing data - beforeEach(function() { + function resetTestingData() { flatPoints = [38.50000, -120.20000, 40.70000, -120.95000, 43.25200, -126.45300]; @@ -23,7 +22,10 @@ describe('ol.parser.polyline', function() { unsignedIntegers = [0, 30, 1, 31, 32, 2, 174]; encodedUnsignedIntegers = '?]@^_@AmD'; - }); + } + + // Reset testing data + beforeEach(resetTestingData); @@ -70,7 +72,10 @@ describe('ol.parser.polyline', function() { var encodeFloats = ol.parser.polyline.encodeFloats; expect(encodeFloats(smallFloats)).toEqual(encodedFloats); + + resetTestingData(); expect(encodeFloats(smallFloats, 1e5)).toEqual(encodedFloats); + expect(encodeFloats(floats, 1e2)).toEqual(encodedFloats); }); }); From 0df5b4cad2c2af73457101cf11ee9737d49a00b2 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Mon, 11 Mar 2013 20:32:25 +0100 Subject: [PATCH 22/23] polyline: Improved decoding loops to be more robust --- src/ol/parser/polyline.js | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index 615ec24062..b2a1de6789 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -213,19 +213,22 @@ ol.parser.polyline.encodeUnsignedIntegers = function(numbers) { ol.parser.polyline.decodeUnsignedIntegers = function(encoded) { var numbers = new Array(); + var current = 0; + var shift = 0; + var encodedLength = encoded.length; - for (var i = 0; i < encodedLength;) { - var result = 0; - var shift = 0; + for (var i = 0; i < encodedLength; ++i) { + var b = encoded.charCodeAt(i) - 63; - var b; - do { - b = encoded.charCodeAt(i++) - 63; - result |= (b & 0x1f) << shift; + current |= (b & 0x1f) << shift; + + if (b < 0x20) { + numbers.push(current); + current = 0; + shift = 0; + } else { shift += 5; - } while (b >= 0x20); - - numbers.push(result); + } } return numbers; @@ -316,12 +319,17 @@ ol.parser.polyline.decodeUnsignedInteger = function(encoded) { var result = 0; var shift = 0; - var b, i = 0; - do { - b = encoded.charCodeAt(i++) - 63; + var encodedLength = encoded.length; + for (var i = 0; i < encodedLength; ++i) { + var b = encoded.charCodeAt(i) - 63; + result |= (b & 0x1f) << shift; + + if (b < 0x20) + break; + shift += 5; - } while (b >= 0x20); + } return result; }; From 1172e58a5068f99346ac092c98fbb6062bfa3685 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Mon, 11 Mar 2013 21:41:32 +0100 Subject: [PATCH 23/23] polyline: Replaced "new Array()" by "[]" --- src/ol/parser/polyline.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/parser/polyline.js b/src/ol/parser/polyline.js index b2a1de6789..c0793d0ccc 100644 --- a/src/ol/parser/polyline.js +++ b/src/ol/parser/polyline.js @@ -211,7 +211,7 @@ ol.parser.polyline.encodeUnsignedIntegers = function(numbers) { * @return {Array.} A list of unsigned integers. */ ol.parser.polyline.decodeUnsignedIntegers = function(encoded) { - var numbers = new Array(); + var numbers = []; var current = 0; var shift = 0;