diff --git a/src/ol/source/WMTS.js b/src/ol/source/WMTS.js index 5a98758886..e378d9e02c 100644 --- a/src/ol/source/WMTS.js +++ b/src/ol/source/WMTS.js @@ -451,20 +451,39 @@ export function optionsFromCapabilities(wmtsCap, config) { const wrapX = false; const switchOriginXY = projection.getAxisOrientation().substr(0, 2) == 'ne'; - const matrix0 = matrixSetObj.TileMatrix[0]; + let matrix = matrixSetObj.TileMatrix[0]; + + // create default matrixLimit + let selectedMatrixLimit = { + MinTileCol: 0, + MinTileRow: 0, + // substract one to end up at tile top left + MaxTileCol: matrix.MatrixWidth - 1, + MaxTileRow: matrix.MatrixHeight - 1, + }; + + //in case of matrix limits, use matrix limits to calculate extent + if (matrixLimits) { + selectedMatrixLimit = matrixLimits[matrixLimits.length - 1]; + matrix = matrixSetObj.TileMatrix.find( + (value) => value.Identifier === selectedMatrixLimit.TileMatrix + ); + } + const resolution = - (matrix0.ScaleDenominator * 0.00028) / projection.getMetersPerUnit(); // WMTS 1.0.0: standardized rendering pixel size + (matrix.ScaleDenominator * 0.00028) / projection.getMetersPerUnit(); // WMTS 1.0.0: standardized rendering pixel size const origin = switchOriginXY - ? [matrix0.TopLeftCorner[1], matrix0.TopLeftCorner[0]] - : matrix0.TopLeftCorner; - const tileSpanX = matrix0.TileWidth * resolution; - const tileSpanY = matrix0.TileHeight * resolution; + ? [matrix.TopLeftCorner[1], matrix.TopLeftCorner[0]] + : matrix.TopLeftCorner; + const tileSpanX = matrix.TileWidth * resolution; + const tileSpanY = matrix.TileHeight * resolution; const extent = [ - origin[0], - origin[1] - tileSpanY * matrix0.MatrixHeight, - origin[0] + tileSpanX * matrix0.MatrixWidth, - origin[1], + origin[0] + tileSpanX * selectedMatrixLimit.MinTileCol, + // add one to get proper bottom/right coordinate + origin[1] - tileSpanY * (1 + selectedMatrixLimit.MaxTileRow), + origin[0] + tileSpanX * (1 + selectedMatrixLimit.MaxTileCol), + origin[1] - tileSpanY * selectedMatrixLimit.MinTileRow, ]; if (projection.getExtent() === null) { diff --git a/test/spec/ol/format/wmts/capabilities_wgs84.xml b/test/spec/ol/format/wmts/capabilities_wgs84.xml index 489ff5f5c8..67bbc0cfc9 100644 --- a/test/spec/ol/format/wmts/capabilities_wgs84.xml +++ b/test/spec/ol/format/wmts/capabilities_wgs84.xml @@ -38,103 +38,124 @@ default image/png + + inspire_quad + + + + + Mean depth full coverage with land coverage + + mean_atlas_land + + -36.0 15.0 + 43.0 90.0 + + + 14.999942759061003 -36.0 + 90.0 42.999938986416 + + + image/png inspire_quad 0 0 - 1 + 0 0 - 2 + 1 1 0 - 2 - 0 - 4 + 0 + 1 + 2 2 0 - 4 - 0 - 8 + 1 + 3 + 4 3 0 - 8 - 0 - 16 + 3 + 6 + 9 4 0 - 16 - 0 - 32 + 6 + 12 + 19 5 0 - 32 - 0 - 64 + 13 + 25 + 39 6 0 - 64 - 0 - 128 + 26 + 51 + 79 7 0 - 128 - 0 - 256 + 53 + 102 + 158 8 0 - 256 - 0 - 512 + 106 + 204 + 317 9 0 - 512 - 0 - 1024 + 213 + 409 + 634 10 0 - 1024 - 0 - 2048 + 426 + 819 + 1268 11 0 - 2048 - 0 - 4096 + 853 + 1638 + 2537 12 0 - 4096 - 0 - 8192 + 1706 + 3276 + 5074 - + InspireCRS84Quad diff --git a/test/spec/ol/source/wmts.test.js b/test/spec/ol/source/wmts.test.js index 569ec55fd4..fae0de95e8 100644 --- a/test/spec/ol/source/wmts.test.js +++ b/test/spec/ol/source/wmts.test.js @@ -404,6 +404,51 @@ describe('ol.source.WMTS', function () { expectDelta(extent[2], 180); expectDelta(extent[3], 90); }); + + it('returns correct bounding box for a layer restricted by TileMatrixSetLink', function () { + const options = optionsFromCapabilities(capabilities, { + layer: 'mean_atlas_land', + matrixSet: 'inspire_quad', + requestEncoding: 'REST', + }); + + expect(options.urls).to.be.an('array'); + expect(options.urls).to.have.length(1); + expect(options.urls[0]).to.be.eql( + 'https://example.com/wmts/mean_atlas_land/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png' + ); + + expect(options.layer).to.be.eql('mean_atlas_land'); + + expect(options.matrixSet).to.be.eql('inspire_quad'); + + expect(options.format).to.be.eql('image/png'); + + expect(options.projection).to.be.a(Projection); + expect(options.projection).to.be.eql(getProjection('EPSG:4326')); + + expect(options.requestEncoding).to.be.eql('REST'); + + expect(options.tileGrid).to.be.a(WMTSTileGrid); + expect(options.style).to.be.eql('default'); + + const extent = options.tileGrid.getExtent(); + + // calculate with of one tile, this will be used as tolerance for result extent + const tile_width = + ((68247.34668319306 * 0.00028) / + getProjection('EPSG:4326').getMetersPerUnit()) * + 256; + + // compare with delta, due to rounding not the exact bounding box is returned... + const expectDelta = (value, expected) => + expect(Math.abs(value - expected)).to.below(tile_width + 1e-10); + + expectDelta(extent[0], -36); + expectDelta(extent[1], 15); + expectDelta(extent[2], 43); + expectDelta(extent[3], 90); + }); }); describe('#setUrls()', function () {