说明:番外篇是对正篇矢量切片(Vector tile)中提到的一些值得继续延伸的关注点继续进行探索和学习,所涉及的内容以解决实际问题为主要导向。javascript
1、新的需求?html
在完成了矢量切片的工做后,新的需求出现了, 也就是我在上一篇中所提到的:我所拥有的历史数据都是基于某一个特定的Projection,那么如何利用GeoServer以及OpenLayers去制定一个针对特定坐标系的矢量切片呢?java
其实很简单,回顾一下咱们上一篇文章是如何实现并调用矢量切片的:git
发布数据 --> 配置参数【选择数据格式(GeoJSON/TopoJSON/MapBox Vector tile(MVT))、选择tile size(256*256)、选择gridsets】 --> 预览数据 --> OL3调用数据github
那在哪个环节会出问题?web
1)数据发布和切片的生成:你能够把数据想象成为蛋糕,不一样坐标系下的数据就是不一样形状的蛋糕,按照同一种方法去切割不一样形状的蛋糕,那确定会出问题。json
面对不一样形状的蛋糕,也应该采起不一样的策略去制定切法框架
2)数据调用:每一块不一样形状的蛋糕在完成切片后,留下的最小存在单元的形状也确定是不同的,若是是椭圆,所切出来的小块确定是有着平滑边缘的蛋糕块,而五角星的每一小块颇有多是有着尖锐边缘的蛋糕块,因此咱们想要把切出来的蛋糕块完美的放在某一个容器中端出来,那这个容器确定须要和蛋糕块的形状契合,因此,在调用数据的时候,也须要为数据提供一个契合的数据框架。学习
经过上述分析,咱们已经知道了应该在哪里进行补充工做了,那么接下来就让咱们一块儿去实现吧。编码
2、基于某一个特定的坐标系实现的矢量切片
首先在发布数据时,咱们应当找到当下准备发布数据的坐标系信息,你能够经过ArcGIS加载该数据来查看,在此我使用的是深圳市绿道数据,基于EPSG:4490,即China Geodetic Coordinate System 2000。
1) 进入GeoServer的发布数据页面
还记得在发布数据过程当中,为切片数据配置的页面吗?咱们须要在页面上完成数据格式(GeoJSON/TopoJSON/MapBox Vector tile(MVT))、tile size(256*256)、gridsets等配置。
但这里要注意的是,你会发现在gridset这一栏里默认的只有EPSG:4326和EPSG:900913的切片格网方案,而我这里使用的数据是EPSG:4490,蛋糕形状变了, 切的刀法也应该有所变化。因此咱们须要针对EPSG:4490定制一个切蛋糕方案:
2)自定义gridset
从GeoServer面板左边的菜单栏中进入Tile Caching的Gridsets子菜单,而后在Gridsets的管理页面中选择新建一个gridset,接下来你就能看到这样一个页面:
在这个页面,你有不少参数须要配置,配置完以后点击保存便可:
- Name
- Coordinate Reference System : 与之对应的坐标系编码
- Gridset bounds:范围(会影响到切片的参数)
- tile size:256*256
- Tile Matrix Set:根据你的数据和须要设置缩放级别
最后,在上一个配置参数的页面,将新配置的gridset添加进去
好了,咱们如今已经用合适而恰当的方法把蛋糕切好了,接下来咱们须要为这些数据蛋糕找到合适的容器。
3、在OL3中自定义坐标系
1)OpenLayers中的坐标系
在OpenLayers3中,提供了好几种默认已经定义好的坐标系,这其中就有咱们熟悉的EPSG:4326,EPSG:900913 or EPSG:3857等等,可以保证通常状况下的使用,但对于特定需求,可能就须要借助外力的帮助,而这个外力就是:Proj4js
2)Proj4js
在github上,关于Proj4js的定义是这样的:
Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.
// Proj4js主要是一个用来将点坐标从源坐标系统转换到另外一个目标坐标系统的JS库,包括基准转换
Originally a port of PROJ.4 and GCTCP C it is a part of the MetaCRS group of projects.
// 本项目起源于PROJ.4和GCTCP C
PS:定义中提到的基准转换,应该是大地测量学里面的术语,我也不是很了解,稍微查了一下资料,在此做为冷知识补充一下:
咱们一般所说的坐标系统,是由坐标系和基准构成的,所谓的基准指的是为了描述空间位置而定义的点、线、面,在大地测量中,基准指的是描述地球形状的地球椭球参数。
回到正题,这里是Proj4js在github中的地址:https://github.com/proj4js/proj4js, 在proj4js中提到了两种用途:
1)转换坐标点;
//其中fromProjection是源坐标系,toProjection指的是目标坐标系
//若是你没有提供fromProjection,则默认fromProjection为WGS84坐标系
//fromProjection,toProjection等参数能够是ol中的projection对象,也能够是一个WKT String
proj4(promProjection,toProjection,coordinates);
2)定义命名一个自定义坐标系统
//定义一个新的坐标系统
proj4.defs('WGS84', "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees");
须要补充一点,在Proj4js中已经预约义了几种projection:
- 'EPSG:4326' or 'WGS84'
- 'EPSG:4269'
- 'EPSG:3857' or 'EPSG:3785' or 'GOOGLE' or 'EPSG:900913' or 'EPSG:102113'
根据文档中的介绍,咱们使用Proj4js去定义一个新的ol3中的projection对象:
a)首先,和全部的JS库同样,请不要忘记在页面完成对库的引用,
<script type="text/javascript" src="lib/proj4js/dist/proj4.js"></script>
b)其次,在你的JS文件中加入如下代码:
function loadVectorTile_4490(){
//定义EPSG:4490,具体的字符串参数你能够在:http://epsg.io中查询到,只需输入你的projection的EPSG码或者坐标系的名称
//便可得到相应坐标系的字符串参数,直接将其复制到代码中便可
proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs");
//得到定义的坐标系
var projection4490 = new ol.proj.get('EPSG:4490');
//给定义的坐标系统限定范围,此处4490的范围与4326相似,由于他们的单位都是degree
projection4490.setExtent([-180,-90,180,90]);
var layerName2 = 'szdata:greenway';
var layerProjection2 = '4490';
//矢量切片图层 var vectorTile_GreenWay = new ol.layer.VectorTile({ title:"深圳绿道-VectorTile", style: new ol.style.Style({
stroke: new ol.style.Stroke({
color:'#548B54'
})
}), projection: projection4490,
//矢量切片数据 source: new ol.source.VectorTile({
projeciton: projection4490, format: new ol.format.GeoJSON(), tileGrid: ol.tilegrid.createXYZ({
extent: ol.proj.get('EPSG:4490').getExtent(),
maxZoom: 13 }),
tilePixelRatio:1,
//发出获取切片的请求
tileUrlFunction: function(tileCoord){
return '/geoserver/gwc/service/tms/1.0.0/' +layerName+'@EPSG%3A'+layerProjection+'@geojson/'+(tileCoord[0]-1) + '/'+tileCoord[1] + '/' + (Math.pow(2,tileCoord[0]-1)+tileCoord[2]) + '.geojson'; }
})
});
//须要注意的是,要给view设定一个合适的Projection属性,否则数据没法正常显示
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM();
}),
vectorTile_GreenWay
],
view: new ol.View({
//view中的projection
projection: projection4490,
center: [114.15, 22.65]
})
});
}
c) 其实最后的实现很简单,只不过在上一篇文章的内容中添加了一个Proj4js定义新坐标系的内容,实现过程也比预想要顺利,所以做为一个小番外添加进来,也是对上一篇文章末尾提到的问题进行一个补充。实现结果以下: