最近了解了一些Map地图相关的知识点,把学习的资料罗列一下:
坐标体系
说明:
- WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。标准的Web墨卡托投影坐标系。
- GCJ02:又称火星坐标系,是由中国国家测绘局制定的地理坐标系统,是由WGS84加密后得到的坐标系。指中国国家测绘局制订的加偏Web墨卡托投影,正式名称为GCJ-02,国内可用的地图多数属于这种坐标系。
- BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标。
地图API
百度
腾讯
- 坐标拾取器
- http://lbs.qq.com/javascript_v2/guide-start.html
- http://lbs.qq.com/javascript_v2/demo.html
- API 逆地址解析(坐标位置描述)
- http://lbs.qq.com/static_v2/guide-getImage.html
- 地址反查(坐标查位置):逆地址解析
- 鼠标移动显示地图坐标信息
- 拖动地图显示地图中心坐标信息
- 周边(圆形区域)检索
- http://lbs.qq.com/javascript_v2/sample/sample-search-circlebounds.html
- http://lbs.qq.com/javascript_v2/doc/maptype.html
- http://lbs.qq.com/javascript_v2/doc/projection.html
高德
国内其他
- 获取地理位置的经纬度直接搜就行了
- https://support.google.com/maps/answer/18539?co=GENIE.Platform%3DDesktop&hl=zh-Hans
- 地理编码转换
NOTE: Google的在Java里面用需要指定证书和代理:
- https://stackoverflow.com/questions/120797/how-do-i-set-the-proxy-to-be-used-by-the-jvm
- https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
网页访问一次,把geo的CA证书保存到本地,然后导入到本地的证书库,加入到应用得启动参数里面:
1 2 3 |
|
各坐标系间的转换
Example:
坐标转换代码:
比例尺
百度
- http://lbsyun.baidu.com/index.php?title=jspopular/guide/widget
- http://developer.baidu.com/map/jsdemo.htm#f0_4
1 2 3 |
|
左下角标注的尺寸包括一个数字加一条线段,就是地图上与那条线等长的距离的实际距离为数字表示的长度。假设长度为一厘米,那就是说那一厘米在地图上同等长度实际是20m的距离,比例为1:2000。
在百度地图API中,平面坐标是以最大级别18级为基准的。就是说在18级平面坐标的一个单位就代表了屏幕上的1个像素 (详细的内容后面讲,可以参考百度地图API详解之地图坐标系统)。
Android里面计算百度比例尺的方式:取两个点获取它们的经纬度,然后算两个点之间的距离。
NOTE: 百度地图SDK还提供了标注工具(PushpinTool),测距工具(DistanceTool)。
Bing
- https://msdn.microsoft.com/en-us/library/aa940990.aspx
- https://blogs.bing.com/maps/2006/02/25/map-control-zoom-levels-gt-resolution
深入了解地图 - 瓦片
- 百度地图API详解之地图坐标系统 ##
- 瓦片地图原理
- Mercator projection
- 国内主要地图瓦片坐标系定义及计算原理
- OpenStreetMap/Google/百度/Bing瓦片地图服务(TMS)
- Google 地图切片URL地址解析
- Tiles à la Google Maps: Coordinates, Tile Bounds and Projection
- 腾讯与百度地图瓦片规则分析
- 百度JavaScript API中经纬度坐标转瓦片坐标bug
- 2017版高德地图瓦片分析
各种tile的地址路径
- https://github.com/CntChen/tile-lnglat-transform
- 各种tile的地址路径 https://github.com/brandonxiang/MapViewer/blob/master/app.js
- https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Java
国内百度腾讯网页端的实现
现在的地图基本都是使用瓦片技术,计算步骤如下:
- 首先,根据投影(墨卡托投影)把 经纬度(度) 转成 平面坐标(m);
- 然后,更具比例尺把 平面坐标 转成 像素坐标;
- 最后,根据坐标的平移把窗口内的瓦片从服务端下载并进行展示。
通过JS代码了解地图的实现:
百度
打开一个百度的应用 http://api.map.baidu.com/lbsapi/getpoint/index.html 然后在调试窗口运行转换经纬度的代码,然后进到对应的代码,打断点,然后艰辛进行与混淆的代码死磕!
1 2 3 4 5 6 7 8 9 |
|
从代码上看还是不难的,但是里面有一堆魔法数字完全不懂。
如果仅仅获取瓦片 https://github.com/CntChen/tile-lnglat-transform/ 推荐使用这个项目。
这里仅仅是经纬度转换为平面坐标(m)的过程。我们在源码中查找 getTilesUrl 在5901行打个断点,然后在回到网页,移动一下地图。接下来,就可以调试整个过程了。
注意标识的两处,是进行层级缩放、计算出瓦片编号的代码。
腾讯
看过了百度的,再看腾讯的。然鹅并没有觉得轻松啊,两种不同的坐标系,做法差别还是挺大的。不过从命名上看腾讯算学术派的了。
- Projection 对象规范 http://lbs.qq.com/javascript_v2/doc/projection.html
- http://lbs.qq.com/javascript_v2/doc/maptype.html
打开 http://lbs.qq.com/javascript_v2/case-run.html#sample-geocoding-reverse ,在 map.qq.com/js/v2.js 的 apiLoad 处打断点进行到真正的map的js文件。
然后查找 fromLatLngToPoint ,再在界面动一下,就可以调试整个过程:
- fromLatLngToPoint
- fromPointToLatLng
调式的时刻可以顺便看看整个调用链,会发现:
- fromDivPixelToLatLng
- fromLatLngToDivPixel
fromDivPixelToLatLng的条用链,以及数据的传递如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
从 坐标计算 经纬度 反过来了:
腾讯的计算过程直接把 转平面坐标和转像素坐标 两个过程合并了。通过 fromLatLngToPoint 得到就是一个 像素坐标 的值,然后通过缩放就可以得到当前层级级别的 像素坐标 。
查找瓦片地址的代码,直接在代码里面查找 x=
在37823处代码都打断点,刷新重新加载瓦片就会进到断点。
然后查看调用链,
详细跟踪的话,会发现,每次加载都会计算左上角和右下角两个点的像素坐标 (窗口的bounds)。计算要加载的瓦片时,直接用最大减最小除以256(每个瓦片的像素),就得到要加载瓦片的编号了。
用了几天比较肤浅的跟了下QQ地图的功能,如果没有混淆应该看起来会爽很多。。。没有很深层次的东西,仅仅是一个源码调试过程的记载,一些理论原理的知识请查完文章中的链接。
其他
–END