diff --git a/src/ol/renderer/canvas/TileLayer.js b/src/ol/renderer/canvas/TileLayer.js index 55df226224..a8e35dbe2a 100644 --- a/src/ol/renderer/canvas/TileLayer.js +++ b/src/ol/renderer/canvas/TileLayer.js @@ -63,12 +63,6 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { * @type {import("../../TileRange.js").default} */ this.tmpTileRange_ = new TileRange(0, 0, 0, 0); - - /** - * @protected - * @type {number} - */ - this.zDirection = 0; } /** @@ -151,8 +145,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer { const tileSource = tileLayer.getSource(); const sourceRevision = tileSource.getRevision(); const tileGrid = tileSource.getTileGridForProjection(projection); - const zDirection = tileSource.zDirection === undefined ? this.zDirection : tileSource.zDirection; - const z = tileGrid.getZForResolution(viewResolution, zDirection); + const z = tileGrid.getZForResolution(viewResolution, tileSource.zDirection); const tileResolution = tileGrid.getResolution(z); let extent = frameState.extent; diff --git a/src/ol/renderer/canvas/VectorTileLayer.js b/src/ol/renderer/canvas/VectorTileLayer.js index f0e24828df..bd75664e9e 100644 --- a/src/ol/renderer/canvas/VectorTileLayer.js +++ b/src/ol/renderer/canvas/VectorTileLayer.js @@ -113,8 +113,6 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { */ this.tmpTransform_ = createTransform(); - // Use nearest lower resolution. - this.zDirection = 1; } /** diff --git a/src/ol/source/BingMaps.js b/src/ol/source/BingMaps.js index 3d4ea68ab3..ab0012c110 100644 --- a/src/ol/source/BingMaps.js +++ b/src/ol/source/BingMaps.js @@ -269,7 +269,8 @@ class BingMaps extends TileImage { const attributions = []; const viewState = frameState.viewState; const tileGrid = this.getTileGrid(); - const tileCoord = tileGrid.getTileCoordForCoordAndResolution(viewState.center, viewState.resolution); + const z = tileGrid.getZForResolution(viewState.resolution, this.zDirection); + const tileCoord = tileGrid.getTileCoordForCoordAndZ(viewState.center, z); const zoom = tileCoord[0]; resource.imageryProviders.map(function(imageryProvider) { let intersecting = false; diff --git a/src/ol/source/IIIF.js b/src/ol/source/IIIF.js index c13ad657c2..70d616a268 100644 --- a/src/ol/source/IIIF.js +++ b/src/ol/source/IIIF.js @@ -40,8 +40,8 @@ import TileImage from './TileImage.js'; * @property {string} [url] Base URL of the IIIF Image service. * This should be the same as the IIIF Image ID. * @property {Versions} [version=Versions.VERSION2] Service's IIIF Image API version. - * @property {number} [zDirection] Indicate which resolution should be used - * by a renderer if the views resolution does not match any resolution of the tile source. + * @property {number} [zDirection=0] Indicate which resolution should be used + * by a renderer if the view resolution does not match any resolution of the tile source. * If 0, the nearest resolution will be used. If 1, the nearest lower resolution * will be used. If -1, the nearest higher resolution will be used. */ diff --git a/src/ol/source/Tile.js b/src/ol/source/Tile.js index c311e88d69..6e99ed0c79 100644 --- a/src/ol/source/Tile.js +++ b/src/ol/source/Tile.js @@ -24,6 +24,7 @@ import {wrapX, getForProjection as getTileGridForProjection} from '../tilegrid.j * @property {boolean} [wrapX=true] * @property {number} [transition] * @property {string} [key] + * @property {number} [zDirection=0] */ @@ -110,9 +111,9 @@ class TileSource extends Source { * by a renderer if the views resolution does not match any resolution of the tile source. * If 0, the nearest resolution will be used. If 1, the nearest lower resolution * will be used. If -1, the nearest higher resolution will be used. - * @type {number=} + * @type {number} */ - this.zDirection; + this.zDirection = options.zDirection ? options.zDirection : 0; } /** diff --git a/src/ol/source/TileDebug.js b/src/ol/source/TileDebug.js index 0335e1d244..127fb23f3f 100644 --- a/src/ol/source/TileDebug.js +++ b/src/ol/source/TileDebug.js @@ -80,6 +80,11 @@ class LabeledTile extends Tile { * @property {import("../proj.js").ProjectionLike} [projection='EPSG:3857'] Optional projection. * @property {import("../tilegrid/TileGrid.js").default} [tileGrid] Tile grid. * @property {boolean} [wrapX=true] Whether to wrap the world horizontally. + * @property {number} [zDirection=0] Set to `1` when debugging `VectorTile` sources with + * a default configuration. Indicates which resolution should be used by a renderer if + * the view resolution does not match any resolution of the tile source. If 0, the nearest + * resolution will be used. If 1, the nearest lower resolution will be used. If -1, the + * nearest higher resolution will be used. */ @@ -106,7 +111,8 @@ class TileDebug extends XYZ { opaque: false, projection: options.projection, tileGrid: options.tileGrid, - wrapX: options.wrapX !== undefined ? options.wrapX : true + wrapX: options.wrapX !== undefined ? options.wrapX : true, + zDirection: options.zDirection }); } diff --git a/src/ol/source/TileImage.js b/src/ol/source/TileImage.js index 94bf260375..4508f05724 100644 --- a/src/ol/source/TileImage.js +++ b/src/ol/source/TileImage.js @@ -52,6 +52,10 @@ import {getForProjection as getTileGridForProjection} from '../tilegrid.js'; * @property {number} [transition] Duration of the opacity transition for rendering. * To disable the opacity transition, pass `transition: 0`. * @property {string} [key] Optional tile key for proper cache fetching + * @property {number} [zDirection=0] Indicate which resolution should be used + * by a renderer if the view resolution does not match any resolution of the tile source. + * If 0, the nearest resolution will be used. If 1, the nearest lower resolution + * will be used. If -1, the nearest higher resolution will be used. */ @@ -84,7 +88,8 @@ class TileImage extends UrlTile { wrapX: options.wrapX, transition: options.transition, key: options.key, - attributionsCollapsible: options.attributionsCollapsible + attributionsCollapsible: options.attributionsCollapsible, + zDirection: options.zDirection }); /** diff --git a/src/ol/source/TileWMS.js b/src/ol/source/TileWMS.js index 33ba9c0705..2f3e266c5c 100644 --- a/src/ol/source/TileWMS.js +++ b/src/ol/source/TileWMS.js @@ -168,7 +168,8 @@ class TileWMS extends TileImage { tileGrid = this.getTileGridForProjection(projectionObj); } - const tileCoord = tileGrid.getTileCoordForCoordAndResolution(coordinate, resolution); + const z = tileGrid.getZForResolution(resolution, this.zDirection); + const tileCoord = tileGrid.getTileCoordForCoordAndZ(coordinate, z); if (tileGrid.getResolutions().length <= tileCoord[0]) { return undefined; diff --git a/src/ol/source/UTFGrid.js b/src/ol/source/UTFGrid.js index 521151f494..7fa19888de 100644 --- a/src/ol/source/UTFGrid.js +++ b/src/ol/source/UTFGrid.js @@ -385,8 +385,8 @@ class UTFGrid extends TileSource { forDataAtCoordinateAndResolution( coordinate, resolution, callback, opt_request) { if (this.tileGrid) { - const tileCoord = this.tileGrid.getTileCoordForCoordAndResolution( - coordinate, resolution); + const z = this.tileGrid.getZForResolution(resolution, this.zDirection); + const tileCoord = this.tileGrid.getTileCoordForCoordAndZ(coordinate, z); const tile = /** @type {!CustomTile} */(this.getTile( tileCoord[0], tileCoord[1], tileCoord[2], 1, this.getProjection())); tile.forDataAtCoordinate(coordinate, callback, opt_request); diff --git a/src/ol/source/UrlTile.js b/src/ol/source/UrlTile.js index f08b358ee2..b01cc974c1 100644 --- a/src/ol/source/UrlTile.js +++ b/src/ol/source/UrlTile.js @@ -25,6 +25,7 @@ import {getKeyZXY} from '../tilecoord.js'; * @property {boolean} [wrapX=true] * @property {number} [transition] * @property {string} [key] + * @property {number} [zDirection=0] */ @@ -51,7 +52,8 @@ class UrlTile extends TileSource { wrapX: options.wrapX, transition: options.transition, key: options.key, - attributionsCollapsible: options.attributionsCollapsible + attributionsCollapsible: options.attributionsCollapsible, + zDirection: options.zDirection }); /** diff --git a/src/ol/source/VectorTile.js b/src/ol/source/VectorTile.js index d3d1621b04..5ad0f341b2 100644 --- a/src/ol/source/VectorTile.js +++ b/src/ol/source/VectorTile.js @@ -64,6 +64,10 @@ import {equals} from '../array.js'; * When set to `false`, only one world * will be rendered. When set to `true`, tiles will be wrapped horizontally to * render multiple worlds. + * @property {number} [zDirection=1] Indicate which resolution should be used + * by a renderer if the view resolution does not match any resolution of the tile source. + * If 0, the nearest resolution will be used. If 1, the nearest lower resolution + * will be used. If -1, the nearest higher resolution will be used. */ @@ -109,7 +113,8 @@ class VectorTile extends UrlTile { url: options.url, urls: options.urls, wrapX: options.wrapX === undefined ? true : options.wrapX, - transition: options.transition + transition: options.transition, + zDirection: options.zDirection === undefined ? 1 : options.zDirection }); /** diff --git a/src/ol/source/XYZ.js b/src/ol/source/XYZ.js index 3f759372e1..6c550057a5 100644 --- a/src/ol/source/XYZ.js +++ b/src/ol/source/XYZ.js @@ -41,6 +41,10 @@ import {createXYZ, extentFromProjection} from '../tilegrid.js'; * @property {boolean} [wrapX=true] Whether to wrap the world horizontally. * @property {number} [transition] Duration of the opacity transition for rendering. * To disable the opacity transition, pass `transition: 0`. + * @property {number} [zDirection=0] Indicate which resolution should be used + * by a renderer if the view resolution does not match any resolution of the tile source. + * If 0, the nearest resolution will be used. If 1, the nearest lower resolution + * will be used. If -1, the nearest higher resolution will be used. */ @@ -94,7 +98,8 @@ class XYZ extends TileImage { urls: options.urls, wrapX: options.wrapX !== undefined ? options.wrapX : true, transition: options.transition, - attributionsCollapsible: options.attributionsCollapsible + attributionsCollapsible: options.attributionsCollapsible, + zDirection: options.zDirection }); } diff --git a/src/ol/source/Zoomify.js b/src/ol/source/Zoomify.js index f7c34ebf97..5a5bd2efa1 100644 --- a/src/ol/source/Zoomify.js +++ b/src/ol/source/Zoomify.js @@ -114,8 +114,8 @@ export class CustomTile extends ImageTile { * @property {number} [transition] Duration of the opacity transition for rendering. * To disable the opacity transition, pass `transition: 0`. * @property {number} [tileSize=256] Tile size. Same tile size is used for all zoom levels. - * @property {number} [zDirection] Indicate which resolution should be used - * by a renderer if the views resolution does not match any resolution of the tile source. + * @property {number} [zDirection=0] Indicate which resolution should be used + * by a renderer if the view resolution does not match any resolution of the tile source. * If 0, the nearest resolution will be used. If 1, the nearest lower resolution * will be used. If -1, the nearest higher resolution will be used. */ diff --git a/test/spec/ol/renderer/canvas/tilelayer.test.js b/test/spec/ol/renderer/canvas/tilelayer.test.js index a24dc6f622..d326d9d7d0 100644 --- a/test/spec/ol/renderer/canvas/tilelayer.test.js +++ b/test/spec/ol/renderer/canvas/tilelayer.test.js @@ -86,6 +86,17 @@ describe('ol.renderer.canvas.TileLayer', function() { done(); }); }); + + it('respects the source\'s zDirection setting', function(done) { + layer.getSource().zDirection = 1; + map.getView().setZoom(5.8); // would lead to z6 tile request with the default zDirection + map.once('rendercomplete', function() { + const tileCache = layer.getSource().tileCache; + const keys = tileCache.getKeys(); + expect(keys.some(key => key.startsWith('6/'))).to.be(false); + done(); + }); + }); }); }); diff --git a/test/spec/ol/renderer/canvas/vectortilelayer.test.js b/test/spec/ol/renderer/canvas/vectortilelayer.test.js index 4ae5fbdfb8..68ef7c72e1 100644 --- a/test/spec/ol/renderer/canvas/vectortilelayer.test.js +++ b/test/spec/ol/renderer/canvas/vectortilelayer.test.js @@ -101,7 +101,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() { it('creates a new instance', function() { const renderer = new CanvasVectorTileLayerRenderer(layer); expect(renderer).to.be.a(CanvasVectorTileLayerRenderer); - expect(renderer.zDirection).to.be(1); + expect(renderer.getLayer()).to.equal(layer); }); it('does not render replays for pure image rendering', function() { diff --git a/test/spec/ol/source/vectortile.test.js b/test/spec/ol/source/vectortile.test.js index 896396fdbf..96416e8cc9 100644 --- a/test/spec/ol/source/vectortile.test.js +++ b/test/spec/ol/source/vectortile.test.js @@ -26,6 +26,10 @@ describe('ol.source.VectorTile', function() { expect(source.format_).to.equal(format); }); + it('sets the default zDirection on the instance', function() { + expect(source.zDirection).to.be(1); + }); + it('uses ol.VectorTile as default tileClass', function() { expect(source.tileClass).to.equal(VectorTile); }); diff --git a/test/spec/ol/source/xyz.test.js b/test/spec/ol/source/xyz.test.js index d6ab713ce6..9b7304b22c 100644 --- a/test/spec/ol/source/xyz.test.js +++ b/test/spec/ol/source/xyz.test.js @@ -20,6 +20,13 @@ describe('ol.source.XYZ', function() { expect(source).to.be.an(TileSource); }); + it('can be constructed with a custom zDirection', function() { + const source = new XYZ({ + zDirection: -1 + }); + expect(source.zDirection).to.be(-1); + }); + it('can be constructed with a custom tile grid', function() { const tileGrid = createXYZ(); const tileSource = new XYZ({