自定义地图数据瓦片化请求的一种实现方案

原创 2015年11月23日 22:45:56

自定义地图数据瓦片化请求的一种实现方案

        

一、背景介绍

        之前做一项目,要接入其它公众平台上的数据,显示到地图上,而且要求拖动地图时,能载入地图新区域内的数据,就像现在大部分的地图应用一样,瓦片形式加载。由于数据不是存放于自己的平台,所以这里会出现个问题,数据不是以地图瓦片形式进行保存。

        但是公众平台有提供个接口,可以使用位置和距离的参数,请求这个距离范围内的数据。所以可以将地图进行瓦片分割,再利用此接口请求瓦片所在圆范围内的数据。通过此种方式,实现数据的瓦片化请求和加载。

二、地图瓦片介绍

1.     墨卡托投影

        墨卡托投影(Mercator Projection),又名“等角正轴圆柱投影”,是荷兰地图学家墨卡托(Mercator)在1569年拟定的。他假设地球被围在一个中空的圆柱里,其赤道与圆柱相接触,然后再假想地球中心有一盏灯,把球面上的图形投影到圆柱体上,再把圆柱体展开,这就是一幅标准纬线为零度(即赤道)的“墨卡托投影”绘制出的世界地图。

        由于赤道半径为6378137米,则赤道周长为20037508.3427892米,因此X轴的取值范围:[-20037508.3427892,20037508.3427892]。当纬度φ接近两极,即90°时,Y值趋向于无穷。因此通常把Y轴的取值范围也限定在[-20037508.3427892,20037508.3427892]之间。因此在墨卡托投影坐标系(米)下的坐标范围是:最小为(-20037508.3427892, -20037508.3427892 )到最大坐标为(20037508.3427892, 20037508.3427892)。

 

2.     地理坐标系

        地理经度的取值范围是[-180,180],纬度不可能到达90°,通过纬度取值范围为[20037508.3427892,20037508.3427892],反计算可得到纬度值为85.05112877980659。因此纬度取值范围是[-85.05112877980659,85.05112877980659],地理坐标系(经纬度)对应的范围是:最小地理坐标(-180,-85.05112877980659),最大地理坐标(180, 85.05112877980659)。

 

3.     地面分辨率

        地面分辨率是以一个像素(pixel)代表的地面尺寸(米)。以微软Bing Maps为例,当Level为1时,图片大小为512*512(4个Tile),那么赤道空间分辨率为:赤道周长/512。其他纬度的空间分辨率则为 纬度圈长度/512,极端的北极则为0。Level为2时,赤道的空间分辨率为 赤道周长/1024,其他纬度为 纬度圈长度1024。很明显,Ground Resolution取决于两个参数,缩放级别Level和纬度latitude ,Level决定像素的多少,latitude决定地面距离的长短。

        地面分辨率的公式为,单位:米/像素:

        ground resolution =(cos(latitude * PI/180) * 2 * PI * 6378137 meters) / (256 * 2^level pixels)

        最低地图放大级别(1级),地图是512 x 512像素。每下一个放大级别,地图的高度和宽度分别乘于2:2级是1024 x 1024像素,3级是2048 x 2048像素,4级是4096 x 4096像素,等等。通常而言,地图的宽度和高度可以由以下式子计算得到:

        map width = map height = 256 * 2^level pixels

 

4.     地图瓦片分割

        为了优化地图系统性能,提高地图下载和显示速度,所有地图都被分割成256 x 256像素大小的正方形小块。由于在每个放大级别下的像素数量都不一样,因此地图图片(Tile)的数量也不一样。每个tile都有一个XY坐标值,从左上角的(0, 0)至右下角的(2^level–1, 2^level–1)。例如在3级放大级别下,所有tile的坐标值范围为(0, 0)至(7, 7),如下图:

         已知一个像素的XY坐标值时,我们很容易得到这个像素所在的Tile的XY坐标值:

         tileX = floor(pixelX / 256)          tileY = floor(pixelY / 256)

三、瓦片化请求的实现

1.     地图的瓦片化分割

        项目中使用的是百度地图,通过百度地图SDK的接口,可监听地图状态的变化。这里做了个控制,只有地图放大到一定的缩放层级后,才开始执行地图状态变化后的进一步处理。

         这里地图状态改变后,将经纬度转化为我们需要使用的地图瓦片。

        由于现在每个地图服务商都有自己的一套坐标系,所以我们需要将经纬度转成真实的GPS经纬度。百度地图的SDK只提供了真实GPS转百度坐标的,但是由于在方圆距离不是很大的区域内,百度坐标与真实坐标的偏移向量大致相等,所以我们可以通过以下方式将百度坐标转成真实坐标。

        得到真实的GPS坐标后,划分地图瓦片的规则就跟用的什么地图没有什么关系了,这里我用了微软Bing Maps的一套计算规则,通过TileSystem类,计算地图瓦片,这里我设置默认的缩放层级为12,瓦片Tile的大小为256X256,可以计算出瓦片所在圆的半径,使用实际的值分析了下(因为经纬度的不同,分割出来的瓦片实际大小会不同,但是在距离相近的区域内,这个偏差也可以忽略),大多都是6000米不到,所以我这里直接使用6000米作为请求的距离半径,也避免出现请求的盲区。TileSystem详细的计算方法会在结尾给出。

        计算完后,发消息通知执行后续的请求操作。

        这里使用的一个请求队列RequestsQueue以及一个请求线程SquareVideoTileLoader,单独负责地图数据的请求。执行drawTile(tile),是为了将瓦片中心点在地图上显示出来,测试瓦片计算是否正确,实际项目中则不需要执行drawTile(tile)。下图为计算出来的地图瓦片中心点截图。

        瓦片请求线程管理的核心代码见下图,将要请求的瓦片tile传入线程类中加入队列,如果线程处于wait状态,则唤醒线程,开始工作。

        请求线程的run方法的代码见下图,在请求队列为空,或者地图界面不可时,挂起线程,减少CPU资源的消耗。请求返回的数据,通过注册的监听回调,返回请求数据。

        onTileLoadCompleted中,处理请求返回的数据,保存已经完成请求的瓦片tile,下次不再请求该瓦片;使用ArrayMap,数据ID为key,保存请求下来的数据,过滤相邻瓦片所在的圆的相交区域的重复数据。

        至此,我们就完成了瓦片请求的全部流程了。

        再看下图中地图上的加载效果,先载入了地图左上方区域的数据,再载入了中间区域的数据(这里受限于平台数据不平均分布,无法更好的展示拖动地图后,加载地图新区域内的数据的效果)。

四、总结

        目前大部分地图app,都是使用瓦片的方式进行地图的加载,这也说明,瓦片化加载的优势,可以分块加载显示,而不是需要等全部的数据下载完后再显示。这样,用户等待的时间就少了很多,有效提高了用户体验。

        本文介绍的只是一种原始数据不以瓦片形式保存的情况下,实现瓦片化请求的实现方案。在一定程度上能提高用户体验,但缺点也很明显,就是可能会请求返回重复的数据。虽然可以缩小瓦片区域范围,以减少重复数据的数量,但这样又大大提高了请求的次数,所以需要根据项目实际的数据分布,制定一个合适的瓦片大小。


注:本文参考了博文GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)里的一些内容,在此感谢博主。

转载请声明原文地址:http://blog.csdn.net/sagittarius1988/article/details/50002449

版权声明:本文为博主原创文章,未经博主允许不得转载。

带你剖析WebGis的世界奥秘----瓦片式加载地图

WebGIS应用程序的页面能够通过HTML、JSP、ASP或任何任何类型的Web页文件构成,其特殊之处在于,它的请求提交的方法并不是通过常用的 “超链接”形式,而是使用鼠标与Web浏览器上地图进行的,...

cocos2d-x 学习笔记——瓦片地图TiledMap

cocos2d-x 学习笔记——瓦片地图TiledMap

腾讯与百度地图瓦片规则分析

腾讯地图瓦片与Google的地图瓦片切割方法相同,只不过腾讯地图瓦片完全遵循TMS标准,Google地图瓦片则是TMS的一种变种。 1.Google 地图瓦片的坐标原点在左上角【85.0511287...

Cocos2d-x使用瓦片地图

图所示的复杂地图可以使用瓦片地图技术,瓦片地图是用一些小图片(瓦片)拼接而成,这样可以大大地减少内存消耗。如图11-6所示的瓦片地图,只需要如图所示的三个瓦片就可以了。                ...

Google地图瓦片拼图算法解析

客户端地图拼图算法解析 概述:主要是阐述如何将瓦片地图图片拼接成完整地图的一些概念以及相关算法。 基本概念: 地图瓦片地址:http://mt2.google.cn/vt/l...

WebGIS前端瓦片地图显示原理及实现

目前,有很多WebGIS开发包,ArcGIS API for JS、OpenLayers、LeafLetjs等为我们从事WebGIS开发的人封装了很多强大的功能。我们很方便的使用这些库的时候,也让我们...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

学习使用Bing Maps Silverlight Control(四):添加自定义瓦片图层

5 自定义瓦片源 1、使用LocationRectTileSource自定义加载使用quadkey的瓦片源 就以必应在线地图为例,在控件中加载海南附近的必应地图(简体中文)。 首先,...

iOS 使用高德地图SDK 加载谷歌地图切片

甲方需求:需要用谷歌的地图资源 而谷歌地图iOS和安卓的SDK早已不在墙内   高德和谷歌的地图经纬度算法一致 谷歌地图比较新更新比较及时 这也是甲方一定要谷歌的原因吧。言归正传:本文主要使用了 瓦片...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:自定义地图数据瓦片化请求的一种实现方案
举报原因:
原因补充:

(最多只允许输入30个字)