diff --git a/externs/olx.js b/externs/olx.js index 33c38bf9cc..42cc2d2a67 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -6479,7 +6479,8 @@ olx.tilegrid; * origins: (Array.|undefined), * resolutions: !Array., * tileSize: (number|undefined), - * tileSizes: (Array.|undefined)}} + * tileSizes: (Array.|undefined), + * widths: (Array.|undefined)}} * @api */ olx.tilegrid.TileGridOptions; @@ -6535,13 +6536,23 @@ olx.tilegrid.TileGridOptions.prototype.tileSize; olx.tilegrid.TileGridOptions.prototype.tileSizes; +/** + * Widths in tiles. If given, the array length should match the length of the + * `resolutions` array, i.e. each resolution will have a number of tile columns. + * @type {Array.|undefined} + * @api + */ +olx.tilegrid.TileGridOptions.prototype.widths; + + /** * @typedef {{origin: (ol.Coordinate|undefined), * origins: (Array.|undefined), * resolutions: !Array., * matrixIds: !Array., * tileSize: (number|undefined), - * tileSizes: (Array.|undefined)}} + * tileSizes: (Array.|undefined), + * widths: (Array.|undefined)}} * @api */ olx.tilegrid.WMTSOptions; @@ -6595,6 +6606,15 @@ olx.tilegrid.WMTSOptions.prototype.tileSize; olx.tilegrid.WMTSOptions.prototype.tileSizes; +/** + * Widths in tiles. If given, the array length should match the length of the + * `resolutions` array, i.e. each resolution will have a number of tile columns. + * @type {Array.|undefined} + * @api + */ +olx.tilegrid.WMTSOptions.prototype.widths; + + /** * @typedef {{extent: (ol.Extent|undefined), * maxZoom: (number|undefined), diff --git a/src/ol/attribution.js b/src/ol/attribution.js index d234c36515..aeeb7bdf12 100644 --- a/src/ol/attribution.js +++ b/src/ol/attribution.js @@ -77,8 +77,8 @@ ol.Attribution.prototype.intersectsAnyTileRange = if (testTileRange.intersects(tileRange)) { return true; } - var extentTileRange = tileGrid.getTileRangeForExtentAndZ( - ol.tilegrid.extentFromProjection(projection), parseInt(zKey, 10)); + var extentTileRange = tileGrid.getTileRange( + parseInt(zKey, 10), projection); var width = extentTileRange.getWidth(); if (tileRange.minX < extentTileRange.minX || tileRange.maxX > extentTileRange.maxX) { diff --git a/src/ol/source/tilesource.js b/src/ol/source/tilesource.js index 78c81d8071..bdb602a7d3 100644 --- a/src/ol/source/tilesource.js +++ b/src/ol/source/tilesource.js @@ -224,12 +224,11 @@ ol.source.Tile.prototype.getWrapXTileCoord = function(tileCoord, opt_projection) { var projection = goog.isDef(opt_projection) ? opt_projection : this.getProjection(); - if (goog.isDef(this.wrapX_) && projection.isGlobal()) { - var tileGrid = this.getTileGridForProjection(projection); - var extent = ol.tilegrid.extentFromProjection(projection); + var tileGrid = this.getTileGridForProjection(projection); + if (goog.isDef(this.wrapX_) && tileGrid.isGlobal(tileCoord[0], projection)) { return this.wrapX_ ? - ol.tilecoord.wrapX(tileCoord, tileGrid, extent) : - ol.tilecoord.clipX(tileCoord, tileGrid, extent); + ol.tilecoord.wrapX(tileCoord, tileGrid, projection) : + ol.tilecoord.clipX(tileCoord, tileGrid, projection); } else { return tileCoord; } diff --git a/src/ol/tilecoord.js b/src/ol/tilecoord.js index 1ddc43b005..03e451ab94 100644 --- a/src/ol/tilecoord.js +++ b/src/ol/tilecoord.js @@ -143,15 +143,15 @@ ol.tilecoord.toString = function(tileCoord) { /** * @param {ol.TileCoord} tileCoord Tile coordinate. * @param {ol.tilegrid.TileGrid} tilegrid Tile grid. - * @param {ol.Extent} extent Extent. + * @param {ol.proj.Projection} projection Projection. * @return {ol.TileCoord} Tile coordinate. */ ol.tilecoord.wrapX = (function() { var tmpTileCoord = [0, 0, 0]; - return function(tileCoord, tileGrid, extent) { + return function(tileCoord, tileGrid, projection) { var z = tileCoord[0]; var x = tileCoord[1]; - var tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z); + var tileRange = tileGrid.getTileRange(z, projection); if (x < tileRange.minX || x > tileRange.maxX) { x = goog.math.modulo(x, tileRange.getWidth()); return ol.tilecoord.createOrUpdate(z, x, tileCoord[2], tmpTileCoord); @@ -164,11 +164,12 @@ ol.tilecoord.wrapX = (function() { /** * @param {ol.TileCoord} tileCoord Tile coordinate. * @param {ol.tilegrid.TileGrid} tileGrid Tile grid. - * @param {ol.Extent} extent Extent. + * @param {ol.proj.Projection} projection Projection. * @return {ol.TileCoord} Tile coordinate. */ -ol.tilecoord.clipX = function(tileCoord, tileGrid, extent) { +ol.tilecoord.clipX = function(tileCoord, tileGrid, projection) { + var z = tileCoord[0]; var x = tileCoord[1]; - var tileRange = tileGrid.getTileRangeForExtentAndZ(extent, tileCoord[0]); + var tileRange = tileGrid.getTileRange(z, projection); return (x < tileRange.minX || x > tileRange.maxX) ? null : tileCoord; }; diff --git a/src/ol/tilegrid/tilegrid.js b/src/ol/tilegrid/tilegrid.js index 1e0039770c..8169dc1c06 100644 --- a/src/ol/tilegrid/tilegrid.js +++ b/src/ol/tilegrid/tilegrid.js @@ -92,6 +92,16 @@ ol.tilegrid.TileGrid = function(options) { (!goog.isDef(this.tileSize_) && !goog.isNull(this.tileSizes_)) || (goog.isDef(this.tileSize_) && goog.isNull(this.tileSizes_))); + /** + * @private + * @type {Array.} + */ + this.widths_ = null; + if (goog.isDef(options.widths)) { + this.widths_ = options.widths; + goog.asserts.assert(this.widths_.length == this.resolutions_.length); + } + }; @@ -373,6 +383,25 @@ ol.tilegrid.TileGrid.prototype.getTileCoordResolution = function(tileCoord) { }; +/** + * @param {number} z Zoom level. + * @param {ol.proj.Projection} projection Projection. + * @param {ol.TileRange=} opt_tileRange Tile range. + * @return {ol.TileRange} Tile range. + */ +ol.tilegrid.TileGrid.prototype.getTileRange = + function(z, projection, opt_tileRange) { + var projectionExtentTileRange = this.getTileRangeForExtentAndZ( + ol.tilegrid.extentFromProjection(projection), z); + var width = this.getWidth(z); + if (!goog.isDef(width)) { + width = projectionExtentTileRange.getWidth(); + } + return ol.TileRange.createOrUpdate( + 0, width - 1, 0, projectionExtentTileRange.getHeight(), opt_tileRange); +}; + + /** * @param {number} z Z. * @return {number} Tile size. @@ -389,6 +418,19 @@ ol.tilegrid.TileGrid.prototype.getTileSize = function(z) { }; +/** + * @param {number} z Zoom level. + * @return {number|undefined} Width for the specified zoom level or `undefined` + * if unknown. + */ +ol.tilegrid.TileGrid.prototype.getWidth = function(z) { + if (!goog.isNull(this.widths_)) { + goog.asserts.assert(this.minZoom <= z && z <= this.maxZoom); + return this.widths_[z]; + } +}; + + /** * @param {number} resolution Resolution. * @return {number} Z. @@ -399,6 +441,26 @@ ol.tilegrid.TileGrid.prototype.getZForResolution = function(resolution) { }; +/** + * @param {number} z Zoom level. + * @param {ol.proj.Projection} projection Projection. + * @return {boolean} Whether the tile grid is defined for the whole globe when + * used with the provided `projection` at zoom level `z`. + */ +ol.tilegrid.TileGrid.prototype.isGlobal = function(z, projection) { + var width = this.getWidth(z); + if (goog.isDef(width)) { + var projTileGrid = ol.tilegrid.getForProjection(projection); + var projExtent = projection.getExtent(); + return this.getTileSize(z) * width == + projTileGrid.getTileSize(z) * + projTileGrid.getTileRangeForExtentAndZ(projExtent, z).getWidth(); + } else { + return projection.isGlobal(); + } +}; + + /** * @param {ol.proj.Projection} projection Projection. * @return {ol.tilegrid.TileGrid} Default tile grid for the passed projection. @@ -433,10 +495,17 @@ ol.tilegrid.createForExtent = var resolutions = ol.tilegrid.resolutionsFromExtent( extent, opt_maxZoom, tileSize); + var widths = new Array(resolutions.length); + var extentWidth = ol.extent.getWidth(extent); + for (var z = resolutions.length - 1; z >= 0; --z) { + widths[z] = extentWidth / tileSize / resolutions[z]; + } + return new ol.tilegrid.TileGrid({ origin: ol.extent.getCorner(extent, corner), resolutions: resolutions, - tileSize: tileSize + tileSize: tileSize, + widths: widths }); }; diff --git a/src/ol/tilegrid/wmtstilegrid.js b/src/ol/tilegrid/wmtstilegrid.js index 228d25715a..9f381c1682 100644 --- a/src/ol/tilegrid/wmtstilegrid.js +++ b/src/ol/tilegrid/wmtstilegrid.js @@ -34,7 +34,8 @@ ol.tilegrid.WMTS = function(options) { origins: options.origins, resolutions: options.resolutions, tileSize: options.tileSize, - tileSizes: options.tileSizes + tileSizes: options.tileSizes, + widths: options.widths }); }; @@ -77,6 +78,8 @@ ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet = var origins = []; /** @type {!Array.} */ var tileSizes = []; + /** @type {!Array.} */ + var widths = []; var supportedCRSPropName = 'SupportedCRS'; var matrixIdsPropName = 'TileMatrix'; @@ -112,12 +115,14 @@ ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet = var tileHeight = elt[tileHeightPropName]; goog.asserts.assert(tileWidth == tileHeight); tileSizes.push(tileWidth); + widths.push(elt['MatrixWidth']); }); return new ol.tilegrid.WMTS({ origins: origins, resolutions: resolutions, matrixIds: matrixIds, - tileSizes: tileSizes + tileSizes: tileSizes, + widths: widths }); };