Cloudlog/assets/js/Polyline.encoded.js

234 lines
7.0 KiB
JavaScript
Raw Normal View History

2022-10-12 07:44:13 +00:00
/*
* Utility functions to decode/encode numbers and array's of numbers
* to/from strings (Google maps polyline encoding)
*
* Extends the L.Polyline and L.Polygon object with methods to convert
* to and create from these strings.
*
* Jan Pieter Waagmeester <jieter@jieter.nl>
*
* Original code from:
* http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/
* (which is down as of december 2014)
*/
(function () {
'use strict';
var defaultOptions = function (options) {
if (typeof options === 'number') {
// Legacy
options = {
precision: options
};
} else {
options = options || {};
}
options.precision = options.precision || 5;
options.factor = options.factor || Math.pow(10, options.precision);
options.dimension = options.dimension || 2;
return options;
};
var PolylineUtil = {
encode: function (points, options) {
options = defaultOptions(options);
var flatPoints = [];
for (var i = 0, len = points.length; i < len; ++i) {
var point = points[i];
if (options.dimension === 2) {
flatPoints.push(point.lat || point[0]);
flatPoints.push(point.lng || point[1]);
} else {
for (var dim = 0; dim < options.dimension; ++dim) {
flatPoints.push(point[dim]);
}
}
}
return this.encodeDeltas(flatPoints, options);
},
decode: function (encoded, options) {
options = defaultOptions(options);
var flatPoints = this.decodeDeltas(encoded, options);
var points = [];
for (var i = 0, len = flatPoints.length; i + (options.dimension - 1) < len;) {
var point = [];
for (var dim = 0; dim < options.dimension; ++dim) {
point.push(flatPoints[i++]);
}
points.push(point);
}
return points;
},
encodeDeltas: function (numbers, options) {
options = defaultOptions(options);
var lastNumbers = [];
for (var i = 0, len = numbers.length; i < len;) {
for (var d = 0; d < options.dimension; ++d, ++i) {
var num = numbers[i].toFixed(options.precision);
var delta = num - (lastNumbers[d] || 0);
lastNumbers[d] = num;
numbers[i] = delta;
}
}
return this.encodeFloats(numbers, options);
},
decodeDeltas: function (encoded, options) {
options = defaultOptions(options);
var lastNumbers = [];
var numbers = this.decodeFloats(encoded, options);
for (var i = 0, len = numbers.length; i < len;) {
for (var d = 0; d < options.dimension; ++d, ++i) {
numbers[i] = Math.round((lastNumbers[d] = numbers[i] + (lastNumbers[d] || 0)) * options.factor) / options.factor;
}
}
return numbers;
},
encodeFloats: function (numbers, options) {
options = defaultOptions(options);
for (var i = 0, len = numbers.length; i < len; ++i) {
numbers[i] = Math.round(numbers[i] * options.factor);
}
return this.encodeSignedIntegers(numbers);
},
decodeFloats: function (encoded, options) {
options = defaultOptions(options);
var numbers = this.decodeSignedIntegers(encoded);
for (var i = 0, len = numbers.length; i < len; ++i) {
numbers[i] /= options.factor;
}
return numbers;
},
encodeSignedIntegers: function (numbers) {
for (var i = 0, len = numbers.length; i < len; ++i) {
var num = numbers[i];
numbers[i] = (num < 0) ? ~(num << 1) : (num << 1);
}
return this.encodeUnsignedIntegers(numbers);
},
decodeSignedIntegers: function (encoded) {
var numbers = this.decodeUnsignedIntegers(encoded);
for (var i = 0, len = numbers.length; i < len; ++i) {
var num = numbers[i];
numbers[i] = (num & 1) ? ~(num >> 1) : (num >> 1);
}
return numbers;
},
encodeUnsignedIntegers: function (numbers) {
var encoded = '';
for (var i = 0, len = numbers.length; i < len; ++i) {
encoded += this.encodeUnsignedInteger(numbers[i]);
}
return encoded;
},
decodeUnsignedIntegers: function (encoded) {
var numbers = [];
var current = 0;
var shift = 0;
for (var i = 0, len = encoded.length; i < len; ++i) {
var b = encoded.charCodeAt(i) - 63;
current |= (b & 0x1f) << shift;
if (b < 0x20) {
numbers.push(current);
current = 0;
shift = 0;
} else {
shift += 5;
}
}
return numbers;
},
encodeSignedInteger: function (num) {
num = (num < 0) ? ~(num << 1) : (num << 1);
return this.encodeUnsignedInteger(num);
},
// This function is very similar to Google's, but I added
// some stuff to deal with the double slash issue.
encodeUnsignedInteger: function (num) {
var value, encoded = '';
while (num >= 0x20) {
value = (0x20 | (num & 0x1f)) + 63;
encoded += (String.fromCharCode(value));
num >>= 5;
}
value = num + 63;
encoded += (String.fromCharCode(value));
return encoded;
}
};
// Export Node module
if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = PolylineUtil;
}
// Inject functionality into Leaflet
if (typeof L === 'object') {
if (!(L.Polyline.prototype.fromEncoded)) {
L.Polyline.fromEncoded = function (encoded, options) {
return L.polyline(PolylineUtil.decode(encoded), options);
};
}
if (!(L.Polygon.prototype.fromEncoded)) {
L.Polygon.fromEncoded = function (encoded, options) {
return L.polygon(PolylineUtil.decode(encoded), options);
};
}
var encodeMixin = {
encodePath: function () {
return PolylineUtil.encode(this.getLatLngs());
}
};
if (!L.Polyline.prototype.encodePath) {
L.Polyline.include(encodeMixin);
}
if (!L.Polygon.prototype.encodePath) {
L.Polygon.include(encodeMixin);
}
L.PolylineUtil = PolylineUtil;
}
})();