我们正在使用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
在这种情况下,距离是20米这是很多。其他点的距离可达150米甚至更长。
在我的坐标数组中,我们要解码的坐标大约为250.000。
我是否遗漏了某些内容,因此解码/编码过程难以解决?
答案 0 :(得分:3)
<强> TL; DR 强>
声明coordinates
变量后添加以下行:
coordinates = coordinates.map(
pair => { return [pair[0].toFixed(5), pair[1].toFixed(5)]; }
);
完整答案
看起来你正在处理浮点舍入错误。您使用的库可能不正确地实现Polyline encoding algorithm。
在算法的描述中,我们读到算法生成的编码字符串使用固定精度数字(小数点后5位)存储连续坐标之间的差异。因此,在计算差异之前,将纬度和经度四舍五入为小数点前5位非常重要。如果没有该步骤,则可能累积舍入误差。在最坏的情况下,编码列表中的每个后续项目的误差可能会增加约0.000005度。
该算法的官方实现不会引入累积舍入误差。但是,在NPM(package polyline)中找到的实现给出了不正确的结果,表明数字的舍入无效。
请看下面的例子:
(使用Google Maps JavaScript API中的google.maps.geometry.encoding.encodePath
)
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
结果无效:值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
答案 1 :(得分:1)
折线编码是有损的:
https://developers.google.com/maps/documentation/utilities/polylinealgorithm(Polyline encoding is a *lossy* compression algorithm that allows you to store a series of coordinates as a single string
如何使用自己的编码方案?上面的页面还显示了Google使用的编码方案。也许你可以在空间和准确性之间寻找权衡。