I'm developing a small webmap using Openlayers3 and geoserver/geowebcache as backend.
My goal is to support browsers/displays with pixelratio=1, pixelratio=2 and pixelratio=3.
For that I defined in geoserver backend 3 gridsets with tiles sizes 256x256, 512x512 and 768x768. I assume that:
Now, my code is working only for pixelratio=1 and pixelratio=2. But if pixelratio=3 geowebcache returns a error:
geowebcache-cache-result:MISS
geowebcache-miss-reason:request does not align to grid(s) 'grid_512' 'grid_768' 'grid_256'
If pixelratio=3 Openlayers generates such a URL:
http://localhost:8082/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=false&layers=mfn_mwb17%3Amfn_mwb17_0_basemap&TILED=true&WIDTH=768&HEIGHT=768&SRS=EPSG%3A32632&STYLES=&FORMAT_OPTIONS=dpi%3A270&BBOX=536964.8438079988%2C5280880.182948656%2C537609.9638079988%2C5281525.3029486565
Openalayers changes the tiles sizes to 768x768 and DPI to 270 but apparently does not calculate correctly the grid.
The demo map in Geoserver (based on Openlayers2) works with all 3 grid sets.
I'm using geoserver 2.10 and google chrome. This is my code so far. Resolutions and bounds are the same for all 3 grid sets in backend. Any help is appreciated:
<html>
<head>
<title>WMS Tiles</title>
<link rel="stylesheet" href="https://openlayers.org/en/v3.19.1/css/ol.css" type="text/css">
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://openlayers.org/en/v3.19.1/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<script>
console.log("DOMContentLoaded");
try {
var config = {
"bounds": {
"left": 536319.7238079988,
"bottom": 5278944.822948656,
"right": 540150.3790103362,
"top": 5282223.663765706
}
};
var bounds = [config.bounds.left, config.bounds.bottom, config.bounds.right, config.bounds.top];
var resolutions = [2.5199999999999996,
1.2599999999999998,
0.6299999999999999,
0.31499999999999995,
0.15749999999999997,
0.07874999999999999,
0.03937499999999999
];
var projection = new ol.proj.Projection({
code: 'EPSG:32632'
});
var params = {
'VERSION': '1.1.1',
'layers': "mfn_mwb17:mfn_mwb17_0_basemap",
'TILED': true,
'TRANSPARENT': false
};
var tileGrid = new ol.tilegrid.TileGrid({
extent: bounds,
resolutions: resolutions,
origin: [config.bounds.left, config.bounds.bottom],
tileSize: [256, 256]
});
var view = new ol.View({
zoom: 0,
center: ol.extent.getCenter(bounds),
projection: projection,
resolutions: resolutions
});
var map = new ol.Map({
controls: ol.control.defaults(
{
rotate: false,
attributionOptions: {
collapsible: false
}
}
),
view: view,
layers: [
new ol.layer.Tile({
source: new ol.source.TileWMS({
url: "http://localhost:8082/wms",
params: params,
tileGrid: tileGrid,
serverType: 'geoserver'
}),
projection: projection,
extend: bounds
})
],
target: 'map'
});
console.log("no error");
} catch (error) {
console.log("error");
console.log(error);
}
</script>
</body>
</html>
There are a few issues with your code that might be the culprit:
projection
must be configured on the ol.source.TileWMS
instance, not on ol.layer.Tile
.ol.layer.Tile
, use the extent
option, not extend
.Fixing the above two might make your application work, but there are caveats:
When you want to ensure that cached tiles are always used, you have to limit your application to certain pixel ratios. In your case 1, 2 and 3. When using ol.source.TileWMS
with the option serverType: 'geoserver'
configured, requests will always be made using the exact device pixel ratio, which can also be 1.33, 1.5, 6, or many other different values that you do not have tiles for.
To fix this, you will want to configure your source with a tilePixelRatio
instead, and not use the serverType
option - if you continue to use WMS. The tilePixelRatio
could be calculated like this:
var tilePixelRatio = 1;
if (ol.has.DEVICE_PIXEL_RATIO > 2.5) {
tilePixelRatio = 3;
} else if (ol.has.DEVICE_PIXEL_RATIO > 1.5) {
tilePixelRatio = 2;
}
I would recommend to use TMS or WMTS instead. For TMS, things would look like this:
var layerName = 'mfn_mwb17:mfn_mwb17_0_basemap';
var gridset = 'grid_' + (tilePixelRatio * 256);
var layer = new ol.layer.Tile({
extent: bounds,
source: new ol.source.XYZ({
projection: 'EPSG:32632',
tileGrid: tileGrid,
tilePixelRatio: tilePixelRatio,
url: '/geoserver/gwc/service/tms/1.0.0/' + layerName +
'@' + gridset + '@png/{z}/{x}/{-y}.png'
})
});
The above assumes your gridsets are named grid_256
, grid_512
and grid_768
, and all use the same tile matrix set. So they only differ in tile width and height in pixels (256, 512 and 768).