arcgis瓦片通过gwc插件发布后,penlayers调用出现tileCol与tileRow范围计算不对的问题
下好的瓦片文件(我下了11-17级),文件的组织其实是按照瓦片的级别、行、列号来组织的。
WMS请求中由Bbox的参数控制(BBOX=139.5703125%2C-50.262451171875%2C156.4453125%2C-35.474853515625),包含了最小x、最小y、最大x、最大y信息;WMTS请求中由TILEMATRIX、TILEROW、TILECOL这三个参数控制,代表的是瓦片的级别、行、列号(TileMatrix=EPSG%3A3857_tumen_gaode_map:4&TileCol=28203&TileRow=12044))。
怎么控制地图客户端对不同级别、不同行、列的瓦图访问呢?
计算原理参考
现有写的通用的计算瓦片TileMatrix、TileCol、TileRow如下:
var lev = 20;
jilinMapTile:function(){
//对应瓦片的投影坐标
var projection = ol.proj.get('EPSG:3857');
//该投影坐标的全图范围[-20037508.342789244, -20037508.342789244, 20037508.342789244, 20037508.342789244]
var projectionExtent = projection.getExtent();
//如果把该投影的所有范围都放到宽256像素的图幅里,屏幕上一像素等于实际中size长(156543.03392804097m,即比例尺*每个像素的屏幕长度)
var size = ol.extent.getWidth(projectionExtent) / 256;
//resolutions是切片方案信息,这里有20个级别的切片,地图屏幕上1像素代表的实际距离是resolution
var resolutions = new Array(lev);
var matrixIds = new Array(lev);
for (var z = 0; z < lev; z++) {
resolutions[z] = size / Math.pow(2, z);
matrixIds[z] = "EPSG:3857_jilinMap:"+z;
}
// var map = new ol.Map({
// layers: [
var layer = new ol.layer.Tile({
opacity: 1,
id:"gaode",
source: new ol.source.WMTS({
url: 'http://122.137.242.12:7881/geowebcache/service/wmts?',
layer: 'jilinMap',
matrixSet: 'EPSG:3857_jilinMap',
format: 'image/png',
projection: projection,
tileGrid: new ol.tilegrid.WMTS({
origin: ol.extent.getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: matrixIds
}),
style: 'default',
wrapX: true
}),
})
// ],
// target: 'map',
// controls: ol.control.defaults({
// attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
// collapsible: false
// })
// }),
// view: new ol.View({
// center: ol.proj.transform([126.579, 43.812], 'EPSG:4326', 'EPSG:3857'),
// projection: 'EPSG:3857',
// zoom: 12
// })
// });
return layer;
},
计算不当会出现Unknown TILEMATRIX
或Column xx is out of range
的报错。
Unknown TILEMATRIX
是因为瓦片的级别没设置对。
比如我下了7个级别,lev就应该是7。
Column xx is out of range
是因为行列号没有计算对。
debug时发现resolutions的值是:
0: 156543.03392804097
1: 78271.51696402048
2: 39135.75848201024
3: 19567.87924100512
4: 9783.93962050256
5: 4891.96981025128
6: 2445.98490512564
而我发布的瓦片文件里切片信息是这样的:
<LODInfos xsi:type="typens:ArrayOfLODInfo">
<LODInfo xsi:type="typens:LODInfo">
<LevelID>0</LevelID>
<Scale>288895.27714399999</Scale>
<Resolution>76.437028285073239</Resolution>
</LODInfo>
<LODInfo xsi:type="typens:LODInfo">
<LevelID>1</LevelID>
<Scale>144447.638572</Scale>
<Resolution>38.21851414253662</Resolution>
</LODInfo>
<LODInfo xsi:type="typens:LODInfo">
<LevelID>2</LevelID>
<Scale>72223.819285999998</Scale>
<Resolution>19.10925707126831</Resolution>
</LODInfo>
<LODInfo xsi:type="typens:LODInfo">
<LevelID>3</LevelID>
<Scale>36111.909642999999</Scale>
<Resolution>9.5546285356341549</Resolution>
</LODInfo>
<LODInfo xsi:type="typens:LODInfo">
<LevelID>4</LevelID>
<Scale>18055.954822</Scale>
<Resolution>4.7773142679493699</Resolution>
</LODInfo>
<LODInfo xsi:type="typens:LODInfo">
<LevelID>5</LevelID>
<Scale>9027.9774109999998</Scale>
<Resolution>2.3886571339746849</Resolution>
</LODInfo>
<LODInfo xsi:type="typens:LODInfo">
<LevelID>6</LevelID>
<Scale>4513.9887049999998</Scale>
<Resolution>1.1943285668550503</Resolution>
</LODInfo>
LevelID本该是11到17,但通过gwc服务发布报错,显示400,就按这里改了。
显然对不上,resolutions的值需要这样才对:
0: 76.43702828517625
1: 38.21851414258813
2: 19.109257071294063
3: 9.554628535647032
4: 4.777314267823516
5: 2.388657133911758
6: 1.194328566955879
按照现有的算法算下来,lev=20,如下:
0: 156543.03392804097
1: 78271.51696402048
2: 39135.75848201024
3: 19567.87924100512
4: 9783.93962050256
5: 4891.96981025128
6: 2445.98490512564
7: 1222.99245256282
8: 611.49622628141
9: 305.748113140705
10: 152.8740565703525
11: 76.43702828517625
12: 38.21851414258813
13: 19.109257071294063
14: 9.554628535647032
15: 4.777314267823516
16: 2.388657133911758
17: 1.194328566955879
18: 0.5971642834779395
19: 0.29858214173896974
算法里的循环需要作以下修改即可:
for (var z = 11; z < 18; z++) {
resolutions[z] = size / Math.pow(2, z);
matrixIds[z] = "EPSG:3857_jilinMap:"+(z-11);
}
总体来说,就是下载的瓦片文件里配置的分片信息与openlayers里的resolutions应该对的上。