谷歌编码的多段线算法格式(编码折线算法)

本文介绍了一种有损压缩算法——多段线编码,用于将坐标数据高效存储为字符串。文章详细阐述了编码过程,包括如何处理有符号整数、使用Base64方案以及如何通过偏移量节省空间。同时提供了编码示例和Java解码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多段线编码是一种有损压缩算法,利用这种算法,您可以将一系列坐标存储为单个字符串。点坐标使用有符号的值编码。如果仅有几个静态点,您可能还希望使用交互式多段线编码实用程序

编码过程使用熟悉的 base64 编码方案将二进制值转换成一系列 ASCII 字符的字符代码:为了确保正确显示这些字符,编码值将先与 63(ASCII 字符“?”)相加,然后再转换成 ASCII。算法也会通过检查每个字节组的最低有效位来检查给定点有无其他字符代码;如果此位设为 1,则说明该点尚未完全构成,后面必须跟其他数据。

此外,为了节省空间,后面的点仅包含与前一个点的偏移(当然,第一个点除外)。所有点都将采用 Base64 方案编码为有符号的整数,因为纬度和经度为有符号的值。多段线内的编码格式需要以合理精度显示分别表示代表纬度和经度的两个坐标。假设最大经度 +/- 180 度精确到 5 位小数(180.00000 至 -180.00000),这就会需要一个 32 位有符号的二进制整数值。

请注意,反斜杠在字符串字面量中将解读为转义字符。此实用程序的任何输出都应在字符串字面量中将反斜杠字符转换为双反斜杠。

下文指定了编码此类有符号的值的步骤。

  1. 假设原始的有符号的值为:
    -179.9832104
  2. 将此十进制值乘以 1e5,然后进行四舍五入,得到的整数值为:
    -17998321
  3. 将十进制值转换成二进制值。请注意,负数值必须使用其二补数计算,具体做法为将二进制值反转,并向结果加 1:
    00000001 00010010 10100001 11110001
    11111110 11101101 01011110 00001110
    11111110 11101101 01011110 00001111
  4. 将二进制值左移一位:
    11111101 11011010 10111100 00011110
  5. 如果原始的十进制值为负数,请反转此编码:
    00000010 00100101 01000011 11100001
  6. 将二进制值以 5 位区块形式分组(从右侧开始):
    00001 00010 01010 10000 11111 00001
  7. 以倒序排列 5 位区块:
    00001 11111 10000 01010 00010 00001
  8. 如果后面有另一个位区块,请使用 0x20 对每个值进行或运算:
    100001 111111 110000 101010 100010 000001
  9. 将每个值转换成十进制值:
    33 63 48 42 34 1
  10. 将每个值加上 63:
    96 126 111 105 97 64
  11. 将每个值转换成其 ASCII 对应字符:
    `~oia@
  12. 下表显示了一些编码点的示例,其中将编码显示为相对于原来的点的一系列偏移。

    示例

    点:(38.5, -120.2)、(40.7, -120.95)、(43.252, -126.453)



    纬度经度E5 纬度E5 经度纬度变化经度变化编码纬度编码经度编码点
    38.5-120.23850000-12020000+3850000-12020000_p~iF~ps|U_p~iF~ps|U
    40.7-120.954070000-12095000+220000-75000_ulLnnqC_ulLnnqC
    43.252-126.4534325200-12645300+255200-550300_mqNvxq`@_mqNvxq`@

    编码折线:_p~iF~ps|U_ulLnnqC_mqNvxq`@


    转自:https://developers.google.com/maps/documentation/utilities/polylinealgorithm?hl=zh-CN


     解码方式很巧妙,只可意会不可言传:

    [java]  view plain  copy
    1. private List<GeoPoint> decodePoly(String encoded) {  
    2.   
    3.     List<GeoPoint> poly = new ArrayList<GeoPoint>();  
    4.     int index = 0, len = encoded.length();  
    5.     int lat = 0, lng = 0;  
    6.   
    7.     while (index < len) {  
    8.         int b, shift = 0, result = 0;  
    9.         do {  
    10.             b = encoded.charAt(index++) - 63;  
    11.             result |= (b & 0x1f) << shift;  
    12.             shift += 5;  
    13.         } while (b >= 0x20);  
    14.         int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));  
    15.         lat += dlat;  
    16.   
    17.         shift = 0;  
    18.         result = 0;  
    19.         do {  
    20.             b = encoded.charAt(index++) - 63;  
    21.             result |= (b & 0x1f) << shift;  
    22.             shift += 5;  
    23.         } while (b >= 0x20);  
    24.         int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));  
    25.         lng += dlng;  
    26.   
    27.         GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6),  
    28.              (int) (((double) lng / 1E5) * 1E6));  
    29.         poly.add(p);  
    30.     }  
    31.   
    32.     return poly;  
    33. }  

    转自:http://jeffreysambells.com/posts/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值