我们使用Google的折线解码算法来解码我们的坐标.但在我们的情况下,解码后大多数坐标都是错误的.我们还以更深的精度测试了该过程.
这是我们的代码以及测试坐标错误的日志:
let coordinates = [ [lat, lng], [...], ...];
console.log(coordinates[13347]); // Output: [ 13.44668, 52.47429 ]
let encoded = Polyline.encode(coordinates);
let decoded = Polyline.decode(encoded);
console.log(decoded[13347]); // Output: [ 13.44671, 52.47445 ]
console.log(coordinates.length == decoded.length)// true
Run Code Online (Sandbox Code Playgroud)
在这种情况下,距离是20米这是很多.其他点的距离可达150米甚至更长.
在我的坐标数组中,我们要解码的坐标大约为250.000.
我错过了什么,所以解码/编码过程失败了吗?
TL;DR
在变量声明后添加以下行coordinates:
coordinates = coordinates.map(
pair => { return [pair[0].toFixed(5), pair[1].toFixed(5)]; }
);
Run Code Online (Sandbox Code Playgroud)
完整答案
看来您正在处理浮点舍入错误。您使用的库可能不正确地实现了折线编码算法。
在算法的描述中,我们读到算法生成的编码字符串使用固定精度数字(小数点后 5 位)存储连续坐标之间的差异。因此,在计算差异之前,将纬度和经度四舍五入到小数点后 5 位非常重要。如果没有该步骤,舍入误差可能会累积。在最坏的情况下,对于编码列表中的每个后续项目,误差可能会增加约 0.000005 度。
该算法的官方实现并没有引入累积舍入误差。然而,NPM(包polyline )中的实现给出了错误的结果,表明数字的舍入无效。
请看下面的例子:
(使用google.maps.geometry.encoding.encodePathGoogle 地图 JavaScript API)
coordinates = coordinates.map(
pair => { return [pair[0].toFixed(5), pair[1].toFixed(5)]; }
);
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
无效结果:值 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, 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
Run Code Online (Sandbox Code Playgroud)