(转)咫尺数据 之 WEBGIS瓦片地图解密与获取(二)

   在上一篇文章中,细致介绍了瓦片数据在webgis中的组织结构,得知了瓦片数据文件的组织其实是按照瓦片的级别、行、列号来组织的。如果给定一个坐标(一般为经纬度坐标),我们该怎样计算出所需瓦片的行列号呢?我们在这一节中就来探讨瓦片行列号的换算关系。在继续下文之前,我们需要搞清楚几个webgis中的基础概念,且看下文详述。

 地图中的比例尺(Scale)分辨率(Resolution)  ”

      在用arcgis切完图之后,打开发布的服务或者打开config.xml配置文件,即可看到切图的相关配置,如下图所示:

      在上图中,levels表示该套切图共有7个层级,每一个层级中又有Resolution和Scale两个参数,它们分别代表该层级下的分辨率和比例尺。比例尺即为地图上的一厘米代表实际上的多少厘米。分辨率即为在当前地图范围内,1个像素代表多少地图单位,地图单位取决于当前的空间参考。可见分辨率跟dpi(dpi代表每英寸的像素数)有关系,也跟地图的单位有关系。

 屏幕上1像素代表的实际距离(分辨率)  ”

       现在来看下分辨率计算的原理,假设地图的坐标单位是米,dpi为96,即1英寸=96像素。1英寸=2.54厘米,也就是说96个像素=2.54厘米,换算成米后,即1个像素=0.0254 / 96米。如果当前层级下的地图比例尺为1:125000000,则代表图上1米等于实地125000000米,那么1个像素代表的实际距离为125000000*0.0254/96 = 33072.9166666667米。

 瓦片行列号换算原理  ”

在计算地图上某点所对应的瓦片行数时,有如下计算步骤:首先已知一个瓦片的实际长度是lrealTileSize(注意这里的单位不是像素,而是实际距离单位),再计算出当前屏幕某点距离瓦片原点的实际距离lreal,然后用实际距离lreal除以一个瓦片的实际长度lrealTileSize就可以得到瓦片的列数,即col=floor(lreal/lrealTileSize)。

       假设,地图切图的原点坐标为(x0,y0),瓦片的大小是tileSize,地图分辨率为res,则计算地图上点(x,y)所在的瓦片行列号公式为:

      col  = Math.floor((x – x0)/( tileSize*res))

       row = Math.floor((y – y0)/( tileSize*res))

       注,Math.floor(number)函数返回小于number的最大整数。即浮点数向下取整。


       在实际webgis系统中,我们需要得到画布的高度和宽度以及此时需要显示的地图的几何范围,还要知道当前需要显示的地图层级,在确定了这些需求后,既可以计算需要加载的瓦片行列号范围。

       假设画布宽为cvWidth,高为cvHeight,当前地图坐标系下的地图左下角坐标为extentX_min,extentY_min,右上角坐标为extentX_max,extentY_max。

具体计算流程如下所示:

计算请求地理范围的中心点坐标(centerGeoPt)

       比如当前要加载经纬度为(lng,lat),需要将其转为平面坐标值,计算过程在本文附带源码中,不在此处做详细论述。

计算出画布范围内所对应的地理范围(min_x,min_y,max_x,max_y)

       根据当前地图层级,得到分辨率res(即1个像素代表的实际距离大小),用上步中得到的centerGeoPt的x坐标加上或者减去半个画布的宽度就可以得到max_x和min_x的值,即min_x = centerGeoPt.x – cvWidth*res/2;max_x = centerGeoPt.x + cvWidth*res /2。同理可得min_y与max_y的值。示意图如下所示:

计算瓦片起始行列号

       在得到上步的地理范围后,再计算起始瓦片的行列号就会容易很多。起始瓦片的行列号计算公式分别如下所示:

列号:tileLeftTopX =Math.floor((Math.abs(min_x-extentX_min))/res* tileSize);

行号:tileLeftTopY =Math.floor((Math.abs(max_y-extentY_max))/res* tileSize);

计算实际地理范围

       此前得到的地理范围只是画布对应的地理范围,当计算出这个范围所需的瓦片后,这些瓦片所覆盖的地理范围不一定就是画布对应的地理范围,如下图所示。这时,就需要再计算出瓦片覆盖的实际地理范围。

实际地理范围计算公式:

realmin_x = tileLeftTopX * res* tileSize + extentX_min;

realmax_y= extentY_max- tileLeftTopY * res* tileSize;

计算左上角偏移像素

       如上图所示,左上角瓦片与画布左上角是存在offset_x与offset_y这两个偏移值的,所以我们需要计算出这两个值(注意,这里是像素值哦),以便在画布加载瓦片的时候使用。计算公式如下所示:

offset_x= ((realmin_x- min_x )/res);

offset_y = ((realmax_y – max_y )/res);

计算瓦片个数(x,y轴上的瓦片个数)

计算公式如下所示:

tileNum_x = Math.ceil((cvWidth + Math.abs(offset_x))/tileSize);

tileNum_y = Math.ceil((cvHeight + Math.abs(offset_y))/tileSize);

注,Math.ceil(number)函数返回大于number的最小整数。即浮点数向上取整。

 绘制瓦片

       我们在前面用了不少篇幅来讨论了瓦片换算的整个计算原理,现在终于可以来实现算法绘制瓦片了!

绘制代码这里需要说明下使用方法,在main.js中就是整个瓦片换算的算法实现,而config.js是有关于当前坐标系下(EPSG:3857,就是webgis中常用的墨卡托投影坐标系)的各个层级的比例尺及分辨率的设置参数。在MapTiles目录中存放了0至5,6个层级的地图瓦片数据。

       感兴趣的读者可以在main.js中修改地图中心经纬度与地图显示层级的参数值,可以观察地图变化,如下图所示:

 本期文章附带源码下载地址

链接:http://pan.baidu.com/s/1i526MXn  

密码:ahda

本文转自微信公众号:OpenGiser的文章

你可能感兴趣的:((转)咫尺数据 之 WEBGIS瓦片地图解密与获取(二))