TL;DR
Add the following lines after the declaration of the coordinates
variable:
coordinates = coordinates.map(
pair => { return [pair[0].toFixed(5), pair[1].toFixed(5)]; }
);
Full answer
It looks like you're dealing with floating point rounding errors. Probably the library you use has incorrect implementation of the Polyline encoding algorithm.
In the description of the algorithm we read that the encoded string generated by the algorithm stores the differences between consecutive coordinates using fixed-precision numbers (with 5 decimal places). Therefore it is important to round the latitude and longitude to 5 decimal places before computing the differences. Without that step, the rounding errors may accumulate. In the worst case error may increase by about 0.000005 deg for each subsequent item in the encoded list.
The official implementation of the algorithm does not introduce accumulated rounding errors. However, the implementation found in NPM (package polyline) gives incorrect results that indicate the invalid rounding of numbers.
Please look at the examples bellow:
Example 1. Encoding a polyline using official implementation of the algorithm
(using google.maps.geometry.encoding.encodePath
from the Google Maps JavaScript API)
originalList = [];
for (var i = 0; i < 100; ++i)
originalList.push(
new google.maps.LatLng(6 * i / 1000000, 0)
);
// originalList looks like: [[0.000000,0],[0.000006,0],[0.000012,0],[0.000018,0], ..., [0.000594,0]];
// (but with LatLng objects instead of 2-element arrays)
console.log(originalList[99].lat()) // 0.000594
var encodedList = google.maps.geometry.encoding.encodePath(originalList)
var decodedList = google.maps.geometry.encoding.decodePath(encodedList)
console.log(decodedList[99].lat()) // 0.00059
let Polyline = require('polyline');
var originalList = [];
for (var i = 0; i < 100; ++i)
originalList.push(
[6 * i / 1000000, 0]
);
// again: originalList == [[0.000000,0],[0.000006,0],[0.000012,0],[0.000018,0], ..., [0.000594,0]];
console.log(originalList[99][0]) // 0.000594
var encodedList = Polyline.encode(originalList);
var decodedList = Polyline.decode(encodedList);
console.log(decodedList[99][0]) // 0.00099
Invalid result: the values 0.000594 and 0.00099 differ by more than 0.000005.
Possible fix
The library that you're using probably doesn't round the coordinates before computing the differences.
For example when two consecutive points have latitudes 0.000000
and 0.000006
, the difference is 0.000006
and it is rounded to 0.00001
giving error of 0.000004
.
You may want to round the coordinates manually, before passing them to Polyline.encode()
, eg. using the function .toFixed(5)
:
let Polyline = require('polyline');
var originalList = [];
for (var i = 0; i < 100; ++i)
originalList.push(
[(6 * i / 1000000).toFixed(5), 0]
);
// before rounding: [[ 0.000000,0],[ 0.000006,0],[ 0.000012,0],[ 0.000018,0], ..., [ 0.000594,0]];
// after rounding: [['0.00000',0],['0.00001',0],['0.00001',0],['0.00002',0], ..., ['0.00059',0]];
console.log(originalList[99][0]) // 0.00059
var encodedList = Polyline.encode(originalList);
var decodedList = Polyline.decode(encodedList);
console.log(decodedList[99][0]) // 0.00059