zoukankan      html  css  js  c++  java
  • Google静态地图如何显示两点之间路线3(url过长–路径简化完结篇)

    非智能手机浏览器的URL长度限制更糟糕

    在上一篇Google静态地图-如何显示两点之间路线2(url过长问题)中,利用Google Geocoding API位置路线服务中的折线编码,大大缩短了路线path的字符长度。但是,折线编码也是一长串字符也是有长度的,万一折线编码的长度也太长,也会出现url过长的问题。

    这个问题也是我在开发项目时遇到的问题,手机种类繁多独自开发的的浏览器也是让我头疼的地方。我们来看看日本的三大运营商au,softbank,docomo中一些非智能手机浏览器的情况:

    浏览器 长度
    i-mode(DoCoMo) 512bytes(直接入力時100bytes)
    EZweb(au) 1024文字?
    Yahoo!ケータイ(SoftBank) 端末 a要素 form要素
    DN02※1 300bytes 300bytes
    SH02, SH02_a、SH03, SH03_a 1024bytes 255bytes
    3GC※2 1024bytes 1024bytes

    这是au,softbank,docomo中非智能手机浏览器url长度限制的情况,可以看出url的长度远远小于PC浏览器限制的长度,尤其是i-Mode才520字节(不是绝对,相对于老的手机)…,折线编码的字符长度肯定会超过的,哎,又回到原点了。

    如何优化路线

    该怎么办呢?还记得第一篇google静态地图-如何显示两点之间路线中利用一个一个点坐标连成路线的方法吗,只要把这些点优化舍去一部分点,字符串不就短了~再转成折线编码就更短了,恩,看起来这个想法可行~~

    我们先不考虑如何优化路线,那些从Google Directions API服务中取的一个一个拐点真的是完全路径吗??经过我测试连成路径之后发现,如果路线距离很长,好像拐点个数有限路线上就显示一部分有拐点,后面的就没了。。。结果就是前一部分是曲线后面就是一条直线。。。,汗!完了,看来原来的方法不行了。

    那该怎么办呢,我们回顾下Google静态地图-如何显示两点之间路线2(url过长问题),是利用那个折线编码画出路线的,那我们反过来想想,假如将折线编码转化成一个一个的点坐标,这不就是是完全路径的点集合嘛~~前面那个问题不就解决了。慢!,怎么把折线编码还原成一个一个点坐标集合呢??这不,折线编码其实也是将点集合转换过来的,再转换回去就是了。。。

    http://code.google.com/intl/zh-CN/apis/maps/documentation/utilities/polylinealgorithm.html

    这是如何点集合转化成折线编码的文章,按照上面算法反过来就可以得到点坐标集合了~呵呵,说的轻巧了,本人算法差,惭愧~以下是网上搜索的代码然后加工下。。(其中的List<GLatLng>就是点集合,这是为了程序需要):

     1 /// <summary>
    2 /// 折线编码转点集合
    3 /// eg : szmrE}japXrX`zE
    4 /// decode : 34.646343,133.86943  34.642247,133.834389
    5 /// </summary>
    6 /// <param name="str"></param>
    7 /// <returns></returns>
    8 public static List<GLatLng> DecodePath(string str)
    9 {
    10 int b = str.Length;
    11 decimal dec = str.Length / 2;
    12 //GLatLng[] c = new GLatLng[int.Parse(Math.Floor(dec).ToString())];
    13 List<GLatLng> c = new List<GLatLng>();
    14
    15 int d = 0, e = 0, f = 0, g = 0;
    16
    17 for (; d < b; ++g)
    18 {
    19 int h = 1, n = 0, q;
    20 do
    21 {
    22 q = str.ToCharArray()[d++] - 63 - 1;
    23 h += q << n;
    24 n += 5;
    25 } while (q >= 31);
    26 e += (h & 1) != 0 ? ~(h >> 1) : h >> 1;
    27
    28 h = 1;
    29 n = 0;
    30
    31 do
    32 {
    33 q = str.ToCharArray()[d++] - 63 - 1;
    34 h += q << n;
    35 n += 5;
    36 } while (q >= 31);
    37 f += (h & 1) != 0 ? ~(h >> 1) : h >> 1;
    38 //c[g] = new GLatLng(e * 1.0E-5, f * 1.0E-5);
    39 c.Add(new GLatLng(e * 1.0E-5, f * 1.0E-5));
    40 }
    41
    42 //c.Length = g;
    43 return c;
    44 }

    OK,完整的点集合取出来了,如何优化这些点呢?请看这下面一篇文章,当然要感谢下这篇文章的作者,对我帮助很大~

    作者:阿修的部落格

    文章:如何在Google Static Map上顯示超長路徑?

    里面讲述的很详细,我就简单摘抄几个重要的地方~

    文章中使用的路线算法是道格拉斯-派克爾法(Ramer–Douglas–Peucker algorithm)

    credit: 維基百科

    道格拉斯-派克爾法的做法就是保留頭尾兩點。將頭尾用一條直線連接,接著找出中間每個點距離這個最大的值b,接著保留這個距離頭尾連接起來的直線最遠的點c。然後設定一個容許值,這個容許值必須小於b。再檢查中間每個點到直線的距離,如果距離大於容許值,就保留這個點。然後用c點,把這條路徑分為兩部分,再依照前面的方法一直做下去。

    GDouglasPeuker.js

    如果要在Google Maps API或Google Static Maps API上使用道格拉斯-派克爾法,我們可以直接用Bill Chadwick寫好的GDouglasPeuker.js

    算法已经有人写好了,不过是js版的~我们知道有些非智能手机上不支持javascript的,所以要转成C#, 转成C#版也不难 就类型什么的转换下就好了~我就不贴代码了.

    好了,优化后的点就可以取出来了~为了字符更短,那么就该把这些点集合再一次转化成折线编码,代码我再贴下吧:

     1 /// <summary>
    2 /// 点集合转折线编码
    3 /// eg : 34.646343,133.86943|34.642247,133.834389
    4 /// encode: szmrE}japXrX`zE
    5 /// </summary>
    6 /// <param name="points"></param>
    7 /// <returns></returns>
    8 public static string EncodePoints(List<GLatLng> points)
    9 {
    10 string _result = "";
    11 int plat = 0;
    12 int plng = 0;
    13
    14 foreach (GLatLng item in points)
    15 {
    16 int late5 = (int)Math.Floor(item.Lat * 1e5);
    17 int lnge5 = (int)Math.Floor(item.Lng * 1e5);
    18
    19 int dlat = late5 - plat;
    20 int dlng = lnge5 - plng;
    21
    22 plat = late5;
    23 plng = lnge5;
    24
    25 _result += encodeSignedNumber(dlat) + encodeSignedNumber(dlng);
    26 }
    27
    28 return _result;
    29 }
    30
    31 private static string encodeSignedNumber(int point)
    32 {
    33
    34 int _point_int = point << 1;
    35
    36 if (point < 0)
    37 {
    38 _point_int = ~_point_int;
    39 }
    40 return (encodeNumber(_point_int));
    41 }
    42
    43 private static string encodeNumber(int num)
    44 {
    45 string resultString = "";
    46
    47 while (num >= 0x20)
    48 {
    49 int _block = num & 0x1F;
    50 _block = (_block | 0x20) + 63;
    51 char _result = (char)_block;
    52 resultString += _result;
    53 num >>= 5;
    54 }
    55
    56 resultString += (char)(num + 63);
    57 return resultString;
    58 }

    这样,优化的折线编码就出来了~~只要设置那个什么派克爾法算法设置优化距离大小,就可以随意控制路线拐点的个数了,也就可以控制长度了~~这里还是要再次感谢下阿部的文章~

    对了,介绍个个折线编码实用工具,这里面大家可以添加个个点后转换成折线编码,哦!对了,刚才的链接是中文的,不知道什么原因那个工具不好用了!!我测试了下英文版的是可以的,大家还是去英文版面的吧

    http://code.google.com/intl/en/apis/maps/documentation/utilities/polylineutility.html

    作者:快乐乔巴
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    一致性哈希算法
    Discourse 的标签(Tag)只能是小写的原因
    JIRA 链接 bitbucket 提示错误 Invalid OAuth credentials
    JIRA 如何连接到云平台的 bitbucket
    Apache Druid 能够支持即席查询
    如何在 Discourse 中配置使用 GitHub 登录和创建用户
    Apache Druid 是什么
    Xshell 如何导入 PuTTYgen 生成的 key
    windows下配置Nginx支持php
    laravel连接数据库提示mysql_connect() :Connection refused...
  • 原文地址:https://www.cnblogs.com/chopper/p/2324386.html
Copyright © 2011-2022 走看看