Ответ 1
TL; DR
Добавьте следующие строки после объявления переменной coordinates
:
coordinates = coordinates.map(
pair => { return [pair[0].toFixed(5), pair[1].toFixed(5)]; }
);
Полный ответ
Похоже, вы имеете дело с ошибками округления с плавающей запятой. Вероятно, библиотека, которую вы используете, имеет неправильную реализацию алгоритма Полилиния кодирования полилинии.
В описании алгоритма мы читаем, что закодированная строка, сгенерированная алгоритмом, сохраняет различия между последовательными координатами с использованием чисел с фиксированной точностью (с 5 знаками после запятой). Поэтому важно округлить широту и долготу до 5 знаков после запятой до, вычисляя различия. Без этого шага ошибки округления могут накапливаться. В худшем случае ошибка может увеличиться примерно на 0,000005 град для каждого последующего элемента в закодированном списке.
Официальная реализация алгоритма не приводит к накопленным ошибкам округления. Тем не менее, реализация, найденная в NPM (полилиния пакета), дает неверные результаты, указывающие на недопустимое округление чисел.
Посмотрите нижеприведенные примеры:
Пример 1. Кодирование полилинии с использованием официальной реализации алгоритма
(используя google.maps.geometry.encoding.encodePath
из API JavaScript Карт Google)
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
Пример 2. Кодирование полилинии с использованием полилинии пакетов из НПМ
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
Недопустимый результат: значения 0.000594 и 0.00099 отличаются более чем на 0,000005.
Возможное исправление
Библиотека, которую вы используете, вероятно, не обходила координаты перед вычислением различий.
Например, когда две последовательные точки имеют широту 0.000000
и 0.000006
, разница составляет 0.000006
и округляется до 0.00001
, давая ошибку 0.000004
.
Вы можете обойти координаты вручную, прежде чем передавать их на Polyline.encode()
, например. используя функцию .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