从零开始学GeoServer源码五(切片原理及自定义插件支持wms、wmts、tms)

前言:前四篇博文我们讨论了如何搭建GeoServer开发环境,如何调试,以及如何支持自定义插件。我们的最终目的是将MongoDB中影像切片发布出来,使其支持wms、wmts、tms,有了前几篇的铺垫,相信读者或多或少也会有了一些收获。本篇我们就讨论一下,要实现最终的目的,我们还需要做哪些工作。

目录

  • 1.TMS(tiled map service)的分类
  • 2.osgeo tms转为google tms
  • 3.计算总行数
    • 3.1 EPSG:3857
    • 3.2 EPSG:4326
  • 3.对wms的影响
  • 4.切片原理
    • 4.1 计算行列号的范围
    • 4.2 计算切片在画布上的位置
  • 5.总结

1.TMS(tiled map service)的分类

  首先我觉得还是要说一说tms的分类,因为这涉及到我们要做的转换。tms有两种,一种是osgeo这个组织出的,这种tms的原点在左下角。mbtiles中存的影像切片,就是osgeo tms 标准的切片。
从零开始学GeoServer源码五(切片原理及自定义插件支持wms、wmts、tms)_第1张图片
  另一种是google公司出的,这种tms的原点在左上角,和ogc的标准协议wmts的原点是一致的。所以Google、Open Street Maps、ESRI等等,都采用的是这种。
从零开始学GeoServer源码五(切片原理及自定义插件支持wms、wmts、tms)_第2张图片

2.osgeo tms转为google tms

  通过上面两张图的对比,读者可以发现,行号反了,所以交换一下就行。假设原始osgeo tms的行号为 ** y**,层级为zoom。因为只是y值反了,那么只要计算出新的y值,假设为Y
  第一步首先要计算出总行数,假设总行数为:RowSum
综上所述, 最后的转换公式为:

Y=RowSum-y-1 注意:不论行号还是列号,都是从0开始编号的

3.计算总行数

  这里要声明,EPSG:4326和EPSG:3857每一级的行列号总数是不一样的。因为我们本期不是讲分辨率,所以就不展开细讲了,就直接给出结论。

3.1 EPSG:3857

每一级都是正方形,每一级都是瓦片个数都是4n,所以每一级行列总数都是2n ,所以
第0级 1行1列,
第1级 2行2列
第2级 4行4列
第3级 8行8列
。。。

3.2 EPSG:4326

第0级只有一块瓦片,从第1级开始,每一级都是矩形,每一级瓦片个数都是n行m列,m=2*n,所以:
第0级 1行1列,
第1级 1行2列
第2级 2行4列
第3级 4行8列
。。。
所以从第1级开始,每一级总行数都是2n-1 ,总列数都是2 * 2n-1

多提一句,熟悉cesium ion平台上 terrain 的同学都知道,cesium 的 terrain 规则就类似于这种规则,但是它稍稍有点不同,即舍弃掉了原本的第0级,把第1级作为第0级,很巧妙。

3.对wms的影响

首先我们来回顾一下wms的访问流程:

  1. 前端发起一个请求,请求中包括了一个地理范围
  2. 后端拿到这个范围以后计算所需要的行列号的范围
  3. 根据行列号的范围,两层for循环嵌套,拿到对应的切片
  4. 把这些切片拼接到一个画布上
  5. 计算这些切片对应的实际地理范围,一般这个范围都比请求的地理范围要大
  6. 两个范围取交集(李晓晖的博文中不是这么做的,他是平移左上角)
  7. 将取交集后的图片返回

  以上就是整个wms的请求过程,为什么要专门说这里呢?因为坐标原点的不同会导致切片在画布上拼接时,画布y坐标的计算的不同。下面我们来详细讲。

4.切片原理

4.1 计算行列号的范围

  要讲明白切片的拼接,首先就要能理解怎么根据经纬度计算行列号,其实计算行列号的原理很简单,那就是 总距离除以每一块切片所能表示的距离,我们以4326为例,即:

EPSG:4326所表示的经度范围为【-180,180】,纬度范围为【-90,90】
坐标原点是在左上角,即【-180,90】,我们切片大小是256 * 256 像素,那么,行列号就可以表示为:
distance /(256 * resolution)
distance: 当前经度到-180的距离,或者,当前纬度到90的距离
resolution: 分辨率,即每一个像素代表的实际地理距离
256 * resolution: 一块切片所能表示的地理距离
所以,这两个距离相除,得到的比值,就是行号或者列号

  理解上面的原理至关重要,没理解的同学可以多读两遍。有了上面的铺垫,明白了原理,我们就能计算出来行列号的范围,即 leftTile,rightTile,bottomTile,topTile 的值。

4.2 计算切片在画布上的位置

  有了上面的值,我们就能通过简单的加减乘除,来计算出某一切片在画布上的位置了。假如某一切片的行列号为x,y,它在画布上的位置为Px,Py,那么:

Px = (x - leftTile) * 256
Py = (topTile - y) * 256

  两层 for 循环嵌套,不就拼接出来一个画布了吗?

for(int i=leftTile;i<rightTile;i++){
  for(int j=bottomTile;j<topTile;j++){
   	//计算在画布上的位置
  	int Px=(i-leftTile) * 256;
  	int Py=(topTile-j) * 256
  	//在画布上赋值略
  	。。。
  }
}

  如果是osgeo tms,确实是上面这样计算的,但我们是google tms,行号和osgeo tms的行号是反的,所以,我们首先要交换行号:

bottomTile = row_number - 1 - bottomTile;
topTile = row_number- 1 - topTile;

  然后,再来拼接画布,代码也要做出修改。

for(int i=leftTile;i<rightTile;i++){
  for(int j=topTle;j<bottomTile;j++){
   	//计算在画布上的位置
  	int Px=(i-leftTile) * 256;
  	int Py=(j-bottomTile) * 256
  	//在画布上赋值略
  	。。。
  }
}

5.总结

  本节在理解上是有一些难度的,希望不明白的同学能够仔细揣摩,多读几遍,这样才会有收获。有些人可能会有疑问,本文标题不是写的要支持 wmswmtstms 吗,为什么只讲了 wms ,而没有讲 wmtstms?那是因为,wms 是在后端动态拼接(渲染)的,wmtstms 后端只是负责根据行列号和层级查找并返回给前端,具体的拼接(渲染)过程是在前端完成的。因为如果你明白了wms的过程,那么 wmtstms 自然也就明白了,所以这里就不啰嗦了。
  到这里,我们的开发工作基本都完事了,所以下一篇我会讲讲 GeoServer 源码如何打包发布,回见~。

你可能感兴趣的:(GeoServer,geoserver,wms,wmts,tms,切片原理)