# 数据
📌 数据说明:广州天河区路网.shp
📌 坐标系:EPSG:3857
📌 坐标系范围:[-20037508.34, -20037508.34, 20037508.34, 20037508.34]
📌 数据范围:[12612071.934997188, 2644615.605161872, 12628768.72360215, 2660183.6516002486]
📌 数据中心点:[12620420.32929967, 2652399.6283810604]
# GeoServer 切图方案GridSet
📌 Gridsets — GeoServer 2.20.x User Manual
geoserver中的格网方案可以理解成ArcMap中的切片方案或金字塔构建方案,它描述了各个显示比例尺下切片的个数、分辨率等等信息。默认情况下,Geoserver自动为地图服务添加名为EPSG900913和EPSG4326的两个格网方案。
格网方案不等同于坐标系统,虽然格网方案必须依托一个明确的坐标系统,才能正确依据坐标信息计算出指定行列号。但到底要构建几层切片、每层切片的分辨率是多少等信息,和坐标系统本身没有关系。
格网方案依托的坐标系统必须和地图服务发布的坐标系统Declared SRS一致,否则会geoserver将不能正确的计算出指定瓦片的行列号。
# 瓦片编号
瓦片生成后,就是一堆图片。怎么对这堆图片进行编号,是目前主流互联网地图商分歧最大的地方。总结起来分为四个流派:
- 谷歌XYZ:Z表示缩放层级;XY的原点在左上角,X从左向右,Y从上向下⬇ [规范]
- TMS:开源产品的标准,Z的定义与谷歌相同;XY的原点在左下角,X从左向右,Y从下向上⬆ [规范]
- QuadTree:微软Bing地图使用的编码规范,Z的定义与谷歌相同,同一层级的瓦片不用XY两个维度表示,而只用一个整数表示,该整数服从四叉树编码规则 [规范]
- 百度XYZ:Z从1开始,在最高级就把地图分为四块瓦片;XY的原点在经度为0纬度位0的位置,X从左向右,Y从下向上⬆。
下图显示了前三个流派在 zoom=1 层级上的瓦片编号结果:
📍 “XYZ”是我们通常用于静态文件系统中用于提供切片服务的各种临时方案的术语。没有标准的元数据机制。尽管最常见的是从顶部向下移动,但对于Y轴方向没有固定的标准。特定的XYZ客户端和服务器可能会或可能无法一起工作。有时也可以使XYZ客户端与TMS或WMTS服务一起使用。
在OpenLayers提供了一个用于调试瓦片的类:ol.layer.Tile + ol.source.TileDebug。可以清晰的看到每一个瓦片的编号。
其它:mapboxgl 中通过 map.showTileBoundaries = true; 开启调试瓦片
网格信息的加载方式与瓦片地图的加载方式类似,在实例化ol.source.TileDebug时,一般需要设置以下两个关键参数。
● projection:地图投影坐标系,设置为瓦片地图的坐标系;
● tileGrid:网格信息,设置为瓦片地图的网格信息,一般由瓦片地图的数据源对象调用getTileGrid方法得到。
# WMTS与TMS
1️⃣ WMTS切片原点:左上角
- WMTS支持 RESTFUL、SOAP 、KVP [url格式对比]
- WMTS可为矩形或正方形
2️⃣ TMS切片原点:左下角
- TMS仅支持RESTFUL
- TMS瓦片固定了为正方形
以Zoom:11为例,GeoServer EPSG:3857切片方案中第11级的像元大小为76.437028,计算数据所在格网行列号公式:
根据计算公式求得我的数据所在格网行列号:
两者之间的唯一区别是y翻转:
y = (2^z) - y - 1
👉 对于这种情况,一些客户端的解决方案有:设置tms:true属性(如leaflet)、构建url时使用/{z}/{x}/{-y}替代/{z}/{x}/{y}(如openlayers、QGIS)等...
# WMTS 服务
请求zoom:11,应得到 11 / 1668 / 888 、11 / 1669 / 888
Openlayers加载WMTS服务(注:不同厂商提供的WMTS服务虽然都基于统一的接口规范,但是每个WMTS服务参数值有时略有不同,如matrixSet
📌注:Geoserver发布服务时的坐标系如果是EPSG:900913,则在填写参数时matrixSet和matrixIds就要是EPSG:900913(尽管EPSG:900913和EPSG:3857是一样的,但写EPSG:3857是请求不到数据的。
<script type="text/javascript">
// 切片方案(0-18级
const projection = ol.proj.get('EPSG:3857');
const projectionExtent = projection.getExtent();
const size = ol.extent.getWidth(projectionExtent) / 256;
const resolutions = new Array(19);
const matrixIds = new Array(19);
for (let z = 0; z < 19; ++z) {
resolutions[z] = size / Math.pow(2, z);
matrixIds[z] = "EPSG:3857:" + z;
}
const layerName = 'cite:tianhe'; // 存储空间:图层名称
// WMTS
var wmtsSource = new ol.source.WMTS({
url: 'http://localhost:8081/geoserver/gwc/service/wmts',
layer: layerName,
matrixSet: 'EPSG:3857',
format: 'image/png', // 默认:'image/jpeg'
projection: projection,
tileGrid: new ol.tilegrid.WMTS({
origin: ol.extent.getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: matrixIds,
}),
style: '',
wrapX: true,
});
var wmtsService = new ol.layer.Tile({
source: wmtsSource
});
var layer_Debug = new ol.layer.Tile({
source: new ol.source.TileDebug({
projection: projection,
tileGrid: wmtsSource.getTileGrid(),
})
})
var map = new ol.Map({
target: 'map',
layers: [ wmtsService, layer_Debug],
view: new ol.View({
projection: 'EPSG:3857',
center: [12620420.32929967, 2652399.6283810604],
zoom: 11,
}),
});
</script>
image/png图像格式适合于分类地图,而image/jpeg则更适合于影像,但由于image/jpeg不支持透明度,所以image/png可用于影像。
建议WMTS服务端提供 image/png 和 image/jpeg 文件格式的瓦片。建议WMTS客户端同时支持这两种格式。由于GetTile操作一次只能提供一个瓦片,所以客户端必须有能力支持透明度,并且能够将同一地理区域的瓦片重叠起来。
GeoServer缓存文件夹gwc中:
geoserver按切片原点为左下角的值存储的,openlayers请求的地址按左上角为原点计算的
👉 在Geoserver的gwc文件夹中,我们可以看见保存gridsets后生成的对应配置文件geowebcache.xml,查看<alignTopLeft>标签设置(参数含义:网格能否运用左上角为原点,默认状况下是左下角为原点 [链接]
# TMS 服务
请求zoom:11,应得到 11 / 1668 / 1159、11 / 1669 / 1159
切片原点变为左下角,所以 {y} → {-y},且openlayers矢量切片大小默认为512,改为256
<script type="text/javascript">
const projection = ol.proj.get('EPSG:3857');
const projectionExtent = projection.getExtent();
const layerName = 'cite:tianhe'; // 工作区:图层名
// TMS
var test = new ol.layer.VectorTile({
declutter: true,
projection: projection,
source: new ol.source.VectorTile({
format: new ol.format.MVT(),
tileSize: 256, // ol默认是512
url: 'http://localhost:8081/geoserver/gwc/service/tms/1.0.0/' + layerName+'@EPSG:3857@pbf/{z}/{x}/{-y}.pbf', // 注意是 -y
}),
})
var layer_Debug = new ol.layer.Tile({
source: new ol.source.TileDebug({
projection: projection,
tileGrid: ol.tilegrid.createXYZ({
extent: projectionExtent ,
maxZoom: 22
}),
template: 'z:{z} x:{x} y:{-y}' // 注意是 -y
})
})
var map = new ol.Map({
target: 'map',
layers: [ test, layer_Debug],
view: new ol.View({
projection: projection,
center: [12620420.32929967, 2652399.6283810604],
// center: ol.proj.transform([113.35, 23.12], 'EPSG:4326', 'EPSG:3857'),
// center: ol.proj.fromLonLat([113.35, 23.12]),
zoom: 11,
}),
});
</script>
GeoServer缓存文件夹gwc中:
📌 注:还可以用其它接口 new ol.source.XYZ
new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'http://localhost/data/{z}/{x}/{y}.png'
})
})
# 参考
瓦片地图原理(OpenLayers默认采用的分辨率和Google在线瓦片地图一样
OL4如何以TMS服务调用WMTS服务的缓存切片(文中有错处
GEOServer-OpenLayer-矢量切片3:PBF格式格式展示(tms服务)
GeoServer官方教程:矢量切片_不睡觉的怪叔叔的博客-CSDN博客
使用GeoServer+OpenLayers发布和调用WMTS、Vector Tile矢量切片服务
openlayers中加载切片原理(文中有错处