diff --git a/.gitignore b/.gitignore index 2f70f4f045..7c37802ad3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,7 @@ /build/gh-pages /build/check-requires-timestamp /build/jsdoc-*-timestamp -/build/lint-spec-timestamp -/build/lint-src-timestamp +/build/lint-timestamp /build/ol.css /build/ol.js /build/ol-all.js diff --git a/build.py b/build.py index 9494b18f1b..c0e7e7c1b8 100755 --- a/build.py +++ b/build.py @@ -229,15 +229,15 @@ def serve_precommit(t): t.run('%(JAVA)s', '-jar', PLOVR_JAR, 'serve', 'build/ol-all.json', 'test/test.json') -virtual('lint', 'build/lint-src-timestamp', 'build/lint-spec-timestamp', 'build/check-requires-timestamp') +virtual('lint', 'build/lint-timestamp', 'build/check-requires-timestamp') -@target('build/lint-src-timestamp', SRC, INTERNAL_SRC, EXTERNAL_SRC, EXAMPLES_SRC, precious=True) +@target('build/lint-timestamp', SRC, INTERNAL_SRC, EXTERNAL_SRC, EXAMPLES_SRC, SPEC, precious=True) def build_lint_src_timestamp(t): limited_doc_files = [path for path in ifind('externs', 'build/src/external/externs') if path.endswith('.js')] - t.run('%(GJSLINT)s', '--strict', '--limited_doc_files=%s' % (','.join(limited_doc_files),), t.newer(SRC, INTERNAL_SRC, EXTERNAL_SRC, EXAMPLES_SRC)) + t.run('%(GJSLINT)s', '--strict', '--limited_doc_files=%s' % (','.join(limited_doc_files),), t.newer(t.dependencies)) t.touch() @@ -331,12 +331,6 @@ def build_check_requires_timestamp(t): t.touch() -@target('build/lint-spec-timestamp', SPEC, precious=True) -def build_lint_spec_timestamp(t): - t.run('%(GJSLINT)s', t.newer(SPEC)) - t.touch() - - virtual('plovr', PLOVR_JAR) diff --git a/build/ol-whitespace.json b/build/ol-whitespace.json index aebd93fa65..77cdb397c2 100644 --- a/build/ol-whitespace.json +++ b/build/ol-whitespace.json @@ -33,5 +33,7 @@ // Note: we can't have a (function(){%output%})() output wrapper with // WHITESPACE and SIMPLE modes. See this link for explanations: // https://groups.google.com/forum/#!topic/plovr/gQyZEa2NpsU - "output-wrapper": "%output%" + "output-wrapper": "%output%", + + "pretty-print": true } diff --git a/examples/canvas-tiles.html b/examples/canvas-tiles.html index 7340cdc3fc..5dbdde1af5 100644 --- a/examples/canvas-tiles.html +++ b/examples/canvas-tiles.html @@ -21,10 +21,12 @@ DOM WebGL + Canvas
+
diff --git a/examples/canvas-tiles.js b/examples/canvas-tiles.js index 31cd1515d9..ecec31b88b 100644 --- a/examples/canvas-tiles.js +++ b/examples/canvas-tiles.js @@ -41,3 +41,10 @@ var domMap = new ol.Map({ }); domMap.bindTo('layers', webglMap); domMap.bindTo('view', webglMap); + +var canvasMap = new ol.Map({ + renderer: ol.RendererHint.DOM, + target: 'canvasMap' +}); +canvasMap.bindTo('layers', webglMap); +canvasMap.bindTo('view', webglMap); diff --git a/examples/epsg-4326.js b/examples/epsg-4326.js index ba95c06146..c6d48eb4ed 100644 --- a/examples/epsg-4326.js +++ b/examples/epsg-4326.js @@ -11,22 +11,12 @@ goog.require('ol.source.TiledWMS'); var epsg4326 = ol.projection.getFromCode('EPSG:4326'); -// We give the single image source a set of resolutions. This prevents the -// source from requesting images of arbitrary resolutions. -var projectionExtent = epsg4326.getExtent(); -var maxResolution = Math.max( - projectionExtent.maxX - projectionExtent.minX, - projectionExtent.maxY - projectionExtent.minY) / 256; -var resolutions = new Array(10); -for (var i = 0; i < 10; ++i) { - resolutions[i] = maxResolution / Math.pow(2.0, i); -} - var layers = new ol.Collection([ new ol.layer.TileLayer({ source: new ol.source.TiledWMS({ url: 'http://vmap0.tiles.osgeo.org/wms/vmap0', crossOrigin: null, + version: '1.1.1', params: { 'LAYERS': 'basic', 'FORMAT': 'image/jpeg' diff --git a/examples/wms-custom-proj.js b/examples/wms-custom-proj.js index 479114e3f5..19d03ca493 100644 --- a/examples/wms-custom-proj.js +++ b/examples/wms-custom-proj.js @@ -19,8 +19,10 @@ var epsg21781 = new ol.Projection('EPSG:21781', ol.ProjectionUnits.METERS, new ol.Extent(485869.5728, 76443.1884, 837076.5648, 299941.7864)); ol.projection.addProjection(epsg21781); -// We give the single image source a set of resolutions. This prevents the -// source from requesting images of arbitrary resolutions. +// We could give the single image source a set of resolutions. This prevents the +// source from requesting images of arbitrary resolutions. To try it, uncomment +// the block below and the resolutions option in the SingleImageWMS config. +/* var projectionExtent = epsg21781.getExtent(); var maxResolution = Math.max(projectionExtent.getWidth(), projectionExtent.getHeight()) / 256; @@ -28,6 +30,7 @@ var resolutions = new Array(10); for (var i = 0; i < 10; ++i) { resolutions[i] = maxResolution / Math.pow(2.0, i); } +*/ var extent = new ol.Extent(420000, 30000, 900000, 350000); var layers = new ol.Collection([ @@ -42,20 +45,18 @@ var layers = new ol.Collection([ 'LAYERS': 'ch.swisstopo.pixelkarte-farbe-pk1000.noscale', 'FORMAT': 'image/jpeg' }, - projection: epsg21781, extent: extent }) }), new ol.layer.ImageLayer({ source: new ol.source.SingleImageWMS({ + //resolutions: resolutions, url: 'http://wms.geo.admin.ch/', attributions: [new ol.Attribution( '© ' + '' + 'National parks / geo.admin.ch')], - params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'}, - projection: epsg21781, - resolutions: resolutions + params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'} }) }) ]); diff --git a/src/objectliterals.exports b/src/objectliterals.exports index dd819ccd2d..3f0a1e984d 100644 --- a/src/objectliterals.exports +++ b/src/objectliterals.exports @@ -133,6 +133,7 @@ @exportObjectLiteralProperty ol.source.TiledWMSOptions.crossOrigin null|string|undefined @exportObjectLiteralProperty ol.source.TiledWMSOptions.extent ol.Extent|undefined @exportObjectLiteralProperty ol.source.TiledWMSOptions.tileGrid ol.tilegrid.TileGrid|undefined +@exportObjectLiteralProperty ol.source.TiledWMSOptions.transparent boolean|undefined @exportObjectLiteralProperty ol.source.TiledWMSOptions.maxZoom number|undefined @exportObjectLiteralProperty ol.source.TiledWMSOptions.projection ol.Projection|undefined @exportObjectLiteralProperty ol.source.TiledWMSOptions.url string|undefined diff --git a/src/ol/control/scalelinecontrol.js b/src/ol/control/scalelinecontrol.js index a2144e502c..02fb5bcf26 100644 --- a/src/ol/control/scalelinecontrol.js +++ b/src/ol/control/scalelinecontrol.js @@ -168,11 +168,13 @@ ol.control.ScaleLine.prototype.updateElement_ = function(frameState) { this.toEPSG4326_ = null; cosLatitude = Math.cos(goog.math.toRadians(center.y)); pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180; + projectionUnits = ol.ProjectionUnits.METERS; - } else if (projectionUnits == ol.ProjectionUnits.METERS && + } else if ((projectionUnits == ol.ProjectionUnits.FEET || + projectionUnits == ol.ProjectionUnits.METERS) && this.units_ == ol.control.ScaleLineUnits.DEGREES) { - // Convert pointResolution from meters to degrees + // Convert pointResolution from meters or feet to degrees if (goog.isNull(this.toEPSG4326_)) { this.toEPSG4326_ = ol.projection.getTransform( projection, ol.projection.getFromCode('EPSG:4326')); @@ -180,20 +182,26 @@ ol.control.ScaleLine.prototype.updateElement_ = function(frameState) { var vertex = [center.x, center.y]; vertex = this.toEPSG4326_(vertex, vertex, 2); cosLatitude = Math.cos(goog.math.toRadians(vertex[1])); - pointResolution *= 180 / (Math.PI * cosLatitude * ol.sphere.NORMAL.radius); + var radius = ol.sphere.NORMAL.radius; + if (projectionUnits == ol.ProjectionUnits.FEET) { + radius /= 0.3048; + } + pointResolution *= 180 / (Math.PI * cosLatitude * radius); + projectionUnits = ol.ProjectionUnits.DEGREES; } else { this.toEPSG4326_ = null; - goog.asserts.assert( - ((this.units_ == ol.control.ScaleLineUnits.METRIC || - this.units_ == ol.control.ScaleLineUnits.IMPERIAL) && - projectionUnits == ol.ProjectionUnits.METERS) || - (this.units_ == ol.control.ScaleLineUnits.DEGREES && - projectionUnits == ol.ProjectionUnits.DEGREES)); } + goog.asserts.assert( + ((this.units_ == ol.control.ScaleLineUnits.METRIC || + this.units_ == ol.control.ScaleLineUnits.IMPERIAL) && + projectionUnits == ol.ProjectionUnits.METERS) || + (this.units_ == ol.control.ScaleLineUnits.DEGREES && + projectionUnits == ol.ProjectionUnits.DEGREES)); + var nominalCount = this.minWidth_ * pointResolution; var suffix = ''; if (this.units_ == ol.control.ScaleLineUnits.DEGREES) { diff --git a/src/ol/imageurlfunction.js b/src/ol/imageurlfunction.js index ca55704f72..4af4b0a5d2 100644 --- a/src/ol/imageurlfunction.js +++ b/src/ol/imageurlfunction.js @@ -1,31 +1,28 @@ goog.provide('ol.ImageUrlFunction'); goog.provide('ol.ImageUrlFunctionType'); -goog.require('goog.uri.utils'); goog.require('ol.Extent'); goog.require('ol.Size'); +goog.require('ol.source.wms'); /** - * @typedef {function(ol.Extent, ol.Size): (string|undefined)} + * @typedef {function(ol.Extent, ol.Size, ol.Projection): (string|undefined)} */ ol.ImageUrlFunctionType; /** * @param {string} baseUrl Base URL (may have query data). - * @param {string} axisOrientation Axis orientation. + * @param {Object.} params WMS parameters. + * @param {string=} opt_version WMS version. * @return {ol.ImageUrlFunctionType} Image URL function. */ -ol.ImageUrlFunction.createBboxParam = function(baseUrl, axisOrientation) { - return function(extent, size) { - var bboxValues = axisOrientation.substr(0, 2) == 'ne' ? - [extent.minY, extent.minX, extent.maxY, extent.maxX] : - [extent.minX, extent.minY, extent.maxX, extent.maxY]; - return goog.uri.utils.appendParams(baseUrl, - 'BBOX', bboxValues.join(','), - 'HEIGHT', size.height, - 'WIDTH', size.width); +ol.ImageUrlFunction.createWMSParams = + function(baseUrl, params, opt_version) { + return function(extent, size, projection) { + return ol.source.wms.getUrl( + baseUrl, params, extent, size, projection, opt_version); }; }; diff --git a/src/ol/projection.js b/src/ol/projection.js index 91d00d3fd5..bf6586e7ee 100644 --- a/src/ol/projection.js +++ b/src/ol/projection.js @@ -28,6 +28,7 @@ ol.HAVE_PROJ4JS = ol.ENABLE_PROJ4JS && typeof Proj4js == 'object'; */ ol.ProjectionUnits = { DEGREES: 'degrees', + FEET: 'ft', METERS: 'm' }; @@ -67,6 +68,12 @@ ol.Projection = function(code, units, extent, opt_axisOrientation) { this.axisOrientation_ = goog.isDef(opt_axisOrientation) ? opt_axisOrientation : 'enu'; + /** + * @private + * @type {ol.tilegrid.TileGrid} + */ + this.defaultTileGrid_ = null; + }; @@ -110,6 +117,22 @@ ol.Projection.prototype.getAxisOrientation = function() { }; +/** + * @return {ol.tilegrid.TileGrid} The default tile grid. + */ +ol.Projection.prototype.getDefaultTileGrid = function() { + return this.defaultTileGrid_; +}; + + +/** + * @param {ol.tilegrid.TileGrid} tileGrid The default tile grid. + */ +ol.Projection.prototype.setDefaultTileGrid = function(tileGrid) { + this.defaultTileGrid_ = tileGrid; +}; + + /** * @constructor @@ -168,7 +191,13 @@ ol.Proj4jsProjection_.prototype.getPointResolution = var height = ol.sphere.NORMAL.haversineDistance( new ol.Coordinate(vertices[4], vertices[5]), new ol.Coordinate(vertices[6], vertices[7])); - return (width + height) / 2; + var pointResolution = (width + height) / 2; + if (this.getUnits() == ol.ProjectionUnits.FEET) { + // The radius of the normal sphere is defined in meters, so we must + // convert back to feet. + pointResolution /= 0.3048; + } + return pointResolution; } }; diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index fa62818db7..1465f7f544 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -79,7 +79,8 @@ ol.renderer.canvas.ImageLayer.prototype.renderFrame = var hints = frameState.viewHints; if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { - image = imageSource.getImage(frameState.extent, viewResolution); + image = imageSource.getImage( + frameState.extent, viewResolution, view2DState.projection); if (!goog.isNull(image)) { var imageState = image.getState(); if (imageState == ol.ImageState.IDLE) { diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 9c338b7818..1374457df6 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -1,4 +1,3 @@ -// FIXME don't redraw tiles if not needed // FIXME find correct globalCompositeOperation // FIXME optimize :-) @@ -51,6 +50,12 @@ ol.renderer.canvas.TileLayer = function(mapRenderer, tileLayer) { */ this.transform_ = goog.vec.Mat4.createNumber(); + /** + * @private + * @type {Array.} + */ + this.renderedTiles_ = null; + }; goog.inherits(ol.renderer.canvas.TileLayer, ol.renderer.canvas.Layer); @@ -86,20 +91,25 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = function(frameState, layerState) { var view2DState = frameState.view2DState; + var projection = view2DState.projection; var tileLayer = this.getTileLayer(); var tileSource = tileLayer.getTileSource(); var tileSourceKey = goog.getUid(tileSource).toString(); var tileGrid = tileSource.getTileGrid(); + if (goog.isNull(tileGrid)) { + tileGrid = ol.tilegrid.getForProjection(projection); + } var z = tileGrid.getZForResolution(view2DState.resolution); var tileSize = tileGrid.getTileSize(z); var tileResolution = tileGrid.getResolution(z); var tileRange = tileGrid.getTileRangeForExtentAndResolution( frameState.extent, tileResolution); + var tileRangeWidth = tileRange.getWidth(); + var tileRangeHeight = tileRange.getHeight(); var canvasSize = new ol.Size( - tileSize.width * tileRange.getWidth(), - tileSize.height * tileRange.getHeight()); + tileSize.width * tileRangeWidth, tileSize.height * tileRangeHeight); var canvas, context; if (goog.isNull(this.canvas_)) { @@ -111,6 +121,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = this.canvas_ = canvas; this.canvasSize_ = canvasSize; this.context_ = context; + this.renderedTiles_ = new Array(tileRangeWidth * tileRangeHeight); } else { canvas = this.canvas_; context = this.context_; @@ -118,22 +129,21 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = canvas.width = canvasSize.width; canvas.height = canvasSize.height; this.canvasSize_ = canvasSize; + this.renderedTiles_ = new Array(tileRangeWidth * tileRangeHeight); } } - context.clearRect(0, 0, canvasSize.width, canvasSize.height); - /** * @type {Object.>} */ var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; - var isLoaded = function(tile) { + var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) { return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED; - }; + }, tileSource, tileGrid, projection); var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, - tilesToDrawByZ, isLoaded); + tilesToDrawByZ, getTileIfLoaded); var allTilesLoaded = true; var tile, tileCenter, tileCoord, tileState, x, y; @@ -141,7 +151,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = for (y = tileRange.minY; y <= tileRange.maxY; ++y) { tileCoord = new ol.TileCoord(z, x, y); - tile = tileSource.getTile(tileCoord); + tile = tileSource.getTile(tileCoord, tileGrid, projection); if (goog.isNull(tile)) { continue; } @@ -169,9 +179,12 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = /** @type {Array.} */ var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number); goog.array.sort(zs); + var opaque = tileSource.getOpaque(); var origin = tileGrid.getTileCoordExtent( new ol.TileCoord(z, tileRange.minX, tileRange.maxY)).getTopLeft(); - var currentZ, i, scale, tileCoordKey, tileExtent, tilesToDraw; + var currentZ, i, index, scale, tileCoordKey, tileExtent, tilesToDraw; + var ix, iy, interimTileExtent, interimTileRange, maxX, maxY, minX, minY; + var height, width; for (i = 0; i < zs.length; ++i) { currentZ = zs[i]; tileSize = tileGrid.getTileSize(currentZ); @@ -179,28 +192,50 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = if (currentZ == z) { for (tileCoordKey in tilesToDraw) { tile = tilesToDraw[tileCoordKey]; - context.drawImage( - tile.getImage(), - tileSize.width * (tile.tileCoord.x - tileRange.minX), - tileSize.height * (tileRange.maxY - tile.tileCoord.y)); + tileCoord = tile.tileCoord; + index = (tileCoord.y - tileRange.minY) * tileRangeWidth + + (tileCoord.x - tileRange.minX); + if (this.renderedTiles_[index] != tile) { + x = tileSize.width * (tile.tileCoord.x - tileRange.minX); + y = tileSize.height * (tileRange.maxY - tile.tileCoord.y); + if (!opaque) { + context.clearRect(x, y, tileSize.width, tileSize.height); + } + context.drawImage(tile.getImage(), x, y); + this.renderedTiles_[index] = tile; + } } } else { scale = tileGrid.getResolution(currentZ) / tileResolution; for (tileCoordKey in tilesToDraw) { tile = tilesToDraw[tileCoordKey]; tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord); - context.drawImage( - tile.getImage(), - (tileExtent.minX - origin.x) / tileResolution, - (origin.y - tileExtent.maxY) / tileResolution, - scale * tileSize.width, - scale * tileSize.height); + x = (tileExtent.minX - origin.x) / tileResolution; + y = (origin.y - tileExtent.maxY) / tileResolution; + width = scale * tileSize.width; + height = scale * tileSize.height; + if (!opaque) { + context.clearRect(x, y, width, height); + } + context.drawImage(tile.getImage(), x, y, width, height); + interimTileRange = + tileGrid.getTileRangeForExtentAndZ(tileExtent, z); + minX = Math.max(interimTileRange.minX, tileRange.minX); + maxX = Math.min(interimTileRange.maxX, tileRange.maxX); + minY = Math.max(interimTileRange.minY, tileRange.minY); + maxY = Math.min(interimTileRange.maxY, tileRange.maxY); + for (ix = minX; ix <= maxX; ++ix) { + for (iy = minY; iy <= maxY; ++iy) { + this.renderedTiles_[(iy - tileRange.minY) * tileRangeWidth + + (ix - tileRange.minX)] = undefined; + } + } } } } this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); - tileSource.useLowResolutionTiles(z, frameState.extent); + tileSource.useLowResolutionTiles(z, frameState.extent, tileGrid); this.scheduleExpireCache(frameState, tileSource); var transform = this.transform_; diff --git a/src/ol/renderer/dom/domimagelayerrenderer.js b/src/ol/renderer/dom/domimagelayerrenderer.js index 769b944848..4b9ae54332 100644 --- a/src/ol/renderer/dom/domimagelayerrenderer.js +++ b/src/ol/renderer/dom/domimagelayerrenderer.js @@ -67,7 +67,8 @@ ol.renderer.dom.ImageLayer.prototype.renderFrame = var hints = frameState.viewHints; if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { - var image_ = imageSource.getImage(frameState.extent, viewResolution); + var image_ = imageSource.getImage( + frameState.extent, viewResolution, view2DState.projection); if (!goog.isNull(image_)) { var imageState = image_.getState(); if (imageState == ol.ImageState.IDLE) { diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 22cfd29744..afe7463db1 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -79,11 +79,15 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = } var view2DState = frameState.view2DState; + var projection = view2DState.projection; var tileLayer = this.getTileLayer(); var tileSource = tileLayer.getTileSource(); var tileSourceKey = goog.getUid(tileSource).toString(); var tileGrid = tileSource.getTileGrid(); + if (goog.isNull(tileGrid)) { + tileGrid = ol.tilegrid.getForProjection(projection); + } var z = tileGrid.getZForResolution(view2DState.resolution); var tileResolution = tileGrid.getResolution(z); var tileRange = tileGrid.getTileRangeForExtentAndResolution( @@ -93,11 +97,11 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; - var isLoaded = function(tile) { + var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) { return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED; - }; + }, tileSource, tileGrid, projection); var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, - tilesToDrawByZ, isLoaded); + tilesToDrawByZ, getTileIfLoaded); var allTilesLoaded = true; var tile, tileCenter, tileCoord, tileState, x, y; @@ -105,7 +109,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = for (y = tileRange.minY; y <= tileRange.maxY; ++y) { tileCoord = new ol.TileCoord(z, x, y); - tile = tileSource.getTile(tileCoord); + tile = tileSource.getTile(tileCoord, tileGrid, projection); if (goog.isNull(tile)) { continue; } @@ -216,7 +220,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = } this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); - tileSource.useLowResolutionTiles(z, frameState.extent); + tileSource.useLowResolutionTiles(z, frameState.extent, tileGrid); this.scheduleExpireCache(frameState, tileSource); }; diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index f1477ac8d7..6a6f1d4aff 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -258,3 +258,20 @@ ol.renderer.Layer.prototype.updateWantedTiles = } wantedTiles[tileSourceKey][coordKey] = true; }; + + +/** + * @param {function(ol.Tile): boolean} isLoadedFunction Function to + * determine if the tile is loaded. + * @param {ol.source.TileSource} tileSource Tile source. + * @param {ol.tilegrid.TileGrid} tileGrid Tile grid. + * @param {ol.Projection} projection Projection. + * @return {function(ol.TileCoord): ol.Tile} Returns a tile if it is loaded. + */ +ol.renderer.Layer.prototype.createGetTileIfLoadedFunction = + function(isLoadedFunction, tileSource, tileGrid, projection) { + return function(tileCoord) { + var tile = tileSource.getTile(tileCoord, tileGrid, projection); + return isLoadedFunction(tile) ? tile : null; + }; +}; diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index b0edbca02c..46d2246c85 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -160,7 +160,8 @@ ol.renderer.webgl.ImageLayer.prototype.renderFrame = var hints = frameState.viewHints; if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { - var image_ = imageSource.getImage(frameState.extent, viewResolution); + var image_ = imageSource.getImage( + frameState.extent, viewResolution, view2DState.projection); if (!goog.isNull(image_)) { var imageState = image_.getState(); if (imageState == ol.ImageState.IDLE) { diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 39d736c435..4059509e0a 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -281,12 +281,16 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = var gl = mapRenderer.getGL(); var view2DState = frameState.view2DState; + var projection = view2DState.projection; var center = view2DState.center; var tileLayer = this.getTileLayer(); var tileSource = tileLayer.getTileSource(); var tileSourceKey = goog.getUid(tileSource).toString(); var tileGrid = tileSource.getTileGrid(); + if (goog.isNull(tileGrid)) { + tileGrid = ol.tilegrid.getForProjection(projection); + } var z = tileGrid.getZForResolution(view2DState.resolution); var tileResolution = tileGrid.getResolution(z); var tileRange = tileGrid.getTileRangeForExtentAndResolution( @@ -365,12 +369,12 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; - var isLoaded = function(tile) { + var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) { return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED && mapRenderer.isTileTextureLoaded(tile); - }; + }, tileSource, tileGrid, projection); var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, - tilesToDrawByZ, isLoaded); + tilesToDrawByZ, getTileIfLoaded); var tilesToLoad = new goog.structs.PriorityQueue(); @@ -380,7 +384,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = for (y = tileRange.minY; y <= tileRange.maxY; ++y) { tileCoord = new ol.TileCoord(z, x, y); - tile = tileSource.getTile(tileCoord); + tile = tileSource.getTile(tileCoord, tileGrid, projection); if (goog.isNull(tile)) { continue; } @@ -459,7 +463,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = } this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); - tileSource.useLowResolutionTiles(z, frameState.extent); + tileSource.useLowResolutionTiles(z, frameState.extent, tileGrid); this.scheduleExpireCache(frameState, tileSource); goog.vec.Mat4.makeIdentity(this.texCoordMatrix_); diff --git a/src/ol/source/bingmapssource.js b/src/ol/source/bingmapssource.js index 7cd7a27155..430e548a1b 100644 --- a/src/ol/source/bingmapssource.js +++ b/src/ol/source/bingmapssource.js @@ -23,6 +23,7 @@ goog.require('ol.tilegrid.XYZ'); ol.source.BingMaps = function(bingMapsOptions) { goog.base(this, { + opaque: true, projection: ol.projection.getFromCode('EPSG:3857') }); diff --git a/src/ol/source/debugtilesource.js b/src/ol/source/debugtilesource.js index e553081ae3..d9ab21ad80 100644 --- a/src/ol/source/debugtilesource.js +++ b/src/ol/source/debugtilesource.js @@ -90,6 +90,7 @@ ol.source.DebugTileSource = function(options) { goog.base(this, { extent: options.extent, + opaque: false, projection: options.projection, tileGrid: options.tileGrid }); diff --git a/src/ol/source/imagesource.js b/src/ol/source/imagesource.js index 879a007d5c..70c980afb2 100644 --- a/src/ol/source/imagesource.js +++ b/src/ol/source/imagesource.js @@ -76,12 +76,13 @@ goog.inherits(ol.source.ImageSource, ol.source.Source); * @param {ol.Extent} extent Extent. * @param {number} resolution Resolution. * @param {ol.Size} size Size. + * @param {ol.Projection} projection Projection. * @return {ol.Image} Single image. */ ol.source.ImageSource.prototype.createImage = - function(extent, resolution, size) { + function(extent, resolution, size, projection) { var image = null; - var imageUrl = this.imageUrlFunction(extent, size); + var imageUrl = this.imageUrlFunction(extent, size, projection); if (goog.isDef(imageUrl)) { image = new ol.Image( extent, resolution, imageUrl, this.crossOrigin_, @@ -109,6 +110,7 @@ ol.source.ImageSource.prototype.findNearestResolution = /** * @param {ol.Extent} extent Extent. * @param {number} resolution Resolution. + * @param {ol.Projection} projection Projection. * @return {ol.Image} Single image. */ ol.source.ImageSource.prototype.getImage = goog.abstractMethod; diff --git a/src/ol/source/imagetilesource.js b/src/ol/source/imagetilesource.js index d47b9215e5..b9fd30f9ea 100644 --- a/src/ol/source/imagetilesource.js +++ b/src/ol/source/imagetilesource.js @@ -7,7 +7,6 @@ goog.require('ol.ImageTile'); goog.require('ol.Projection'); goog.require('ol.Tile'); goog.require('ol.TileCache'); -goog.require('ol.TileCoord'); goog.require('ol.TileUrlFunction'); goog.require('ol.TileUrlFunctionType'); goog.require('ol.source.TileSource'); @@ -18,6 +17,7 @@ goog.require('ol.tilegrid.TileGrid'); * @typedef {{attributions: (Array.|undefined), * crossOrigin: (null|string|undefined), * extent: (ol.Extent|undefined), + * opaque: (boolean|undefined), * projection: (ol.Projection|undefined), * tileGrid: (ol.tilegrid.TileGrid|undefined), * tileUrlFunction: (ol.TileUrlFunctionType|undefined)}} @@ -36,6 +36,7 @@ ol.source.ImageTileSource = function(options) { goog.base(this, { attributions: options.attributions, extent: options.extent, + opaque: options.opaque, projection: options.projection, tileGrid: options.tileGrid }); @@ -84,12 +85,15 @@ ol.source.ImageTileSource.prototype.expireCache = function(usedTiles) { /** * @inheritDoc */ -ol.source.ImageTileSource.prototype.getTile = function(tileCoord) { +ol.source.ImageTileSource.prototype.getTile = + function(tileCoord, tileGrid, projection) { var key = tileCoord.toString(); if (this.tileCache_.containsKey(key)) { return /** @type {ol.Tile} */ (this.tileCache_.get(key)); } else { - var tileUrl = this.getTileCoordUrl(tileCoord); + goog.asserts.assert(tileGrid); + goog.asserts.assert(projection); + var tileUrl = this.tileUrlFunction(tileCoord, tileGrid, projection); var tile; if (goog.isDef(tileUrl)) { tile = new ol.ImageTile(tileCoord, tileUrl, this.crossOrigin_); @@ -102,15 +106,6 @@ ol.source.ImageTileSource.prototype.getTile = function(tileCoord) { }; -/** - * @param {ol.TileCoord} tileCoord Tile coordinate. - * @return {string|undefined} Tile URL. - */ -ol.source.ImageTileSource.prototype.getTileCoordUrl = function(tileCoord) { - return this.tileUrlFunction(tileCoord); -}; - - /** * @inheritDoc */ diff --git a/src/ol/source/mapquestsource.js b/src/ol/source/mapquestsource.js index 08fb316632..ae12b33a25 100644 --- a/src/ol/source/mapquestsource.js +++ b/src/ol/source/mapquestsource.js @@ -26,6 +26,7 @@ ol.source.MapQuestOSM = function() { goog.base(this, { attributions: attributions, + opaque: true, maxZoom: 28, url: 'http://otile{1-4}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg' }); @@ -54,6 +55,7 @@ ol.source.MapQuestOpenAerial = function() { goog.base(this, { attributions: attributions, maxZoom: 18, + opaque: true, url: 'http://oatile{1-4}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg' }); diff --git a/src/ol/source/openstreetmapsource.js b/src/ol/source/openstreetmapsource.js index 8bbfaf5742..258fe22637 100644 --- a/src/ol/source/openstreetmapsource.js +++ b/src/ol/source/openstreetmapsource.js @@ -18,6 +18,7 @@ ol.source.OpenStreetMap = function() { goog.base(this, { attributions: [attribution], + opaque: true, maxZoom: 18, url: 'http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png' }); diff --git a/src/ol/source/singleimagewmssource.js b/src/ol/source/singleimagewmssource.js index ac369e1079..0a8ea8d66c 100644 --- a/src/ol/source/singleimagewmssource.js +++ b/src/ol/source/singleimagewmssource.js @@ -1,11 +1,9 @@ goog.provide('ol.source.SingleImageWMS'); -goog.require('goog.uri.utils'); goog.require('ol.Extent'); goog.require('ol.Image'); goog.require('ol.ImageUrlFunction'); goog.require('ol.Size'); -goog.require('ol.projection'); goog.require('ol.source.ImageSource'); @@ -16,45 +14,16 @@ goog.require('ol.source.ImageSource'); * @param {ol.source.SingleImageWMSOptions} options Options. */ ol.source.SingleImageWMS = function(options) { - - var projection = ol.projection.createProjection( - options.projection, 'EPSG:3857'); - var projectionExtent = projection.getExtent(); - - var extent = goog.isDef(options.extent) ? - options.extent : projectionExtent; - - var version = goog.isDef(options.version) ? - options.version : '1.3'; - - var baseParams = { - 'SERVICE': 'WMS', - 'VERSION': version, - 'REQUEST': 'GetMap', - 'STYLES': '', - 'FORMAT': 'image/png', - 'TRANSPARENT': true - }; - baseParams[version >= '1.3' ? 'CRS' : 'SRS'] = projection.getCode(); - goog.object.extend(baseParams, options.params); - - var axisOrientation = projection.getAxisOrientation(); - var imageUrlFunction; - if (options.url) { - var url = goog.uri.utils.appendParamsFromMap( - options.url, baseParams); - imageUrlFunction = - ol.ImageUrlFunction.createBboxParam(url, axisOrientation); - } else { - imageUrlFunction = - ol.ImageUrlFunction.nullImageUrlFunction; - } + var imageUrlFunction = goog.isDef(options.url) ? + ol.ImageUrlFunction.createWMSParams( + options.url, options.params, options.version) : + ol.ImageUrlFunction.nullImageUrlFunction; goog.base(this, { attributions: options.attributions, crossOrigin: options.crossOrigin, - extent: extent, - projection: projection, + extent: options.extent, + projection: options.projection, resolutions: options.resolutions, imageUrlFunction: imageUrlFunction }); @@ -80,7 +49,7 @@ goog.inherits(ol.source.SingleImageWMS, ol.source.ImageSource); * @inheritDoc */ ol.source.SingleImageWMS.prototype.getImage = - function(extent, resolution) { + function(extent, resolution, projection) { resolution = this.findNearestResolution(resolution); var image = this.image_; @@ -97,6 +66,6 @@ ol.source.SingleImageWMS.prototype.getImage = var height = extent.getHeight() / resolution; var size = new ol.Size(width, height); - this.image_ = this.createImage(extent, resolution, size); + this.image_ = this.createImage(extent, resolution, size, projection); return this.image_; }; diff --git a/src/ol/source/source.js b/src/ol/source/source.js index c56ec4d257..2bc657b57c 100644 --- a/src/ol/source/source.js +++ b/src/ol/source/source.js @@ -38,7 +38,8 @@ ol.source.Source = function(sourceOptions) { * @type {ol.Extent} */ this.extent_ = goog.isDef(sourceOptions.extent) ? - sourceOptions.extent : sourceOptions.projection.getExtent(); + sourceOptions.extent : goog.isDef(sourceOptions.projection) ? + sourceOptions.projection.getExtent() : null; /** * @private diff --git a/src/ol/source/stamensource.js b/src/ol/source/stamensource.js index 46f87d83df..90355bf1e5 100644 --- a/src/ol/source/stamensource.js +++ b/src/ol/source/stamensource.js @@ -85,6 +85,7 @@ ol.source.Stamen = function(stamenOptions) { goog.base(this, { attributions: [attribution], maxZoom: config.maxZoom, + opaque: false, url: 'http://{a-d}.tile.stamen.com/' + layer + '/{z}/{x}/{y}.' + config.type }); diff --git a/src/ol/source/staticimagesource.js b/src/ol/source/staticimagesource.js index eafa205eb1..b1d15bcbe0 100644 --- a/src/ol/source/staticimagesource.js +++ b/src/ol/source/staticimagesource.js @@ -19,6 +19,7 @@ ol.source.StaticImage = function(options) { var imageExtent = options.imageExtent; var imageSize = options.imageSize; var imageResolution = imageExtent.getHeight() / imageSize.height; + var projection = goog.isDef(options.projection) ? options.projection : null; goog.base(this, { attributions: options.attributions, @@ -33,7 +34,8 @@ ol.source.StaticImage = function(options) { * @private * @type {ol.Image} */ - this.image_ = this.createImage(imageExtent, imageResolution, imageSize); + this.image_ = this.createImage( + imageExtent, imageResolution, imageSize, projection); }; goog.inherits(ol.source.StaticImage, ol.source.ImageSource); @@ -42,7 +44,8 @@ goog.inherits(ol.source.StaticImage, ol.source.ImageSource); /** * @inheritDoc */ -ol.source.StaticImage.prototype.getImage = function(extent, resolution) { +ol.source.StaticImage.prototype.getImage = + function(extent, resolution, projection) { if (extent.intersects(this.image_.getExtent())) { return this.image_; } @@ -55,7 +58,7 @@ ol.source.StaticImage.prototype.getImage = function(extent, resolution) { * @return {ol.ImageUrlFunctionType} Function. */ ol.source.StaticImage.createImageFunction = function(url) { - return function(extent, size) { + return function(extent, size, projection) { return url; }; }; diff --git a/src/ol/source/tiledwmssource.js b/src/ol/source/tiledwmssource.js index 9c7eb5ec8c..ebc8e7ab8c 100644 --- a/src/ol/source/tiledwmssource.js +++ b/src/ol/source/tiledwmssource.js @@ -4,12 +4,9 @@ goog.provide('ol.source.TiledWMS'); goog.require('goog.array'); -goog.require('goog.object'); -goog.require('goog.uri.utils'); goog.require('ol.Extent'); goog.require('ol.TileCoord'); goog.require('ol.TileUrlFunction'); -goog.require('ol.projection'); goog.require('ol.source.ImageTileSource'); @@ -20,61 +17,40 @@ goog.require('ol.source.ImageTileSource'); * @param {ol.source.TiledWMSOptions} tiledWMSOptions options. */ ol.source.TiledWMS = function(tiledWMSOptions) { - var projection = ol.projection.createProjection( - tiledWMSOptions.projection, 'EPSG:3857'); - var projectionExtent = projection.getExtent(); - - var extent = goog.isDef(tiledWMSOptions.extent) ? - tiledWMSOptions.extent : projectionExtent; - - var version = goog.isDef(tiledWMSOptions.version) ? - tiledWMSOptions.version : '1.3'; - var tileGrid; if (goog.isDef(tiledWMSOptions.tileGrid)) { tileGrid = tiledWMSOptions.tileGrid; - } else { - tileGrid = ol.tilegrid.createForProjection(projection, - tiledWMSOptions.maxZoom); } + var version = tiledWMSOptions.version; - var baseParams = { - 'SERVICE': 'WMS', - 'VERSION': version, - 'REQUEST': 'GetMap', - 'STYLES': '', - 'FORMAT': 'image/png', - 'TRANSPARENT': true - }; - baseParams[version >= '1.3' ? 'CRS' : 'SRS'] = projection.getCode(); - goog.object.extend(baseParams, tiledWMSOptions.params); - - var axisOrientation = projection.getAxisOrientation(); var tileUrlFunction; if (tiledWMSOptions.urls) { var tileUrlFunctions = goog.array.map( tiledWMSOptions.urls, function(url) { - url = goog.uri.utils.appendParamsFromMap(url, baseParams); - return ol.TileUrlFunction.createBboxParam( - url, tileGrid, axisOrientation); + return ol.TileUrlFunction.createWMSParams( + url, tiledWMSOptions.params, version); }); tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions( tileUrlFunctions); } else if (tiledWMSOptions.url) { - var url = goog.uri.utils.appendParamsFromMap( - tiledWMSOptions.url, baseParams); - tileUrlFunction = - ol.TileUrlFunction.createBboxParam(url, tileGrid, axisOrientation); + tileUrlFunction = ol.TileUrlFunction.createWMSParams( + tiledWMSOptions.url, tiledWMSOptions.params, version); } else { tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction; } + var transparent = goog.isDef(tiledWMSOptions.transparent) ? + tiledWMSOptions.transparent : true; + var extent = tiledWMSOptions.extent; - var tileCoordTransform = function(tileCoord) { + var tileCoordTransform = function(tileCoord, tileGrid, projection) { if (tileGrid.getResolutions().length <= tileCoord.z) { return null; } var x = tileCoord.x; var tileExtent = tileGrid.getTileCoordExtent(tileCoord); + var projectionExtent = projection.getExtent(); + var extent = goog.isDef(tiledWMSOptions.extent) ? + tiledWMSOptions.extent : projectionExtent; // FIXME do we want a wrapDateLine param? The code below will break maps // with projections that do not span the whole world width. if (extent.minX === projectionExtent.minX && @@ -96,8 +72,9 @@ ol.source.TiledWMS = function(tiledWMSOptions) { attributions: tiledWMSOptions.attributions, crossOrigin: tiledWMSOptions.crossOrigin, extent: extent, - tileGrid: tileGrid, - projection: projection, + tileGrid: tiledWMSOptions.tileGrid, + opaque: !transparent, + projection: tiledWMSOptions.projection, tileUrlFunction: ol.TileUrlFunction.withTileCoordTransform( tileCoordTransform, tileUrlFunction) }); diff --git a/src/ol/source/tilesource.js b/src/ol/source/tilesource.js index c250951e7e..92bd61caf3 100644 --- a/src/ol/source/tilesource.js +++ b/src/ol/source/tilesource.js @@ -15,6 +15,7 @@ goog.require('ol.tilegrid.TileGrid'); /** * @typedef {{attributions: (Array.|undefined), * extent: (ol.Extent|undefined), + * opaque: (boolean|undefined), * projection: (ol.Projection|undefined), * tileGrid: (ol.tilegrid.TileGrid|undefined)}} */ @@ -35,6 +36,13 @@ ol.source.TileSource = function(tileSourceOptions) { projection: tileSourceOptions.projection }); + /** + * @private + * @type {boolean} + */ + this.opaque_ = goog.isDef(tileSourceOptions.opaque) ? + tileSourceOptions.opaque : false; + /** * @protected * @type {ol.tilegrid.TileGrid} @@ -65,14 +73,14 @@ ol.source.TileSource.prototype.expireCache = goog.abstractMethod; * * @param {Object.>} loadedTilesByZ A lookup of * loaded tiles by zoom level. - * @param {function(ol.Tile): boolean} isLoaded A function to determine if a - * tile is fully loaded. + * @param {function(ol.TileCoord): ol.Tile} getTileIfLoaded A function that + * returns the tile only if it is fully loaded. * @param {number} z Zoom level. * @param {ol.TileRange} tileRange Tile range. * @return {boolean} The tile range is fully covered with loaded tiles. */ ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ, - isLoaded, z, tileRange) { + getTileIfLoaded, z, tileRange) { // FIXME this could be more efficient about filling partial holes var fullyCovered = true; var tile, tileCoord, tileCoordKey, x, y; @@ -83,8 +91,8 @@ ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ, if (loadedTilesByZ[z] && loadedTilesByZ[z][tileCoordKey]) { continue; } - tile = this.getTile(tileCoord); - if (isLoaded(tile)) { + tile = getTileIfLoaded(tileCoord); + if (!goog.isNull(tile)) { if (!loadedTilesByZ[z]) { loadedTilesByZ[z] = {}; } @@ -98,6 +106,14 @@ ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ, }; +/** + * @return {boolean} Opaque. + */ +ol.source.TileSource.prototype.getOpaque = function() { + return this.opaque_; +}; + + /** * @inheritDoc */ @@ -108,6 +124,8 @@ ol.source.TileSource.prototype.getResolutions = function() { /** * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {ol.tilegrid.TileGrid=} opt_tileGrid Tile grid. + * @param {ol.Projection=} opt_projection Projection. * @return {ol.Tile} Tile. */ ol.source.TileSource.prototype.getTile = goog.abstractMethod; @@ -124,9 +142,10 @@ ol.source.TileSource.prototype.getTileGrid = function() { /** * @param {number} z Z. * @param {ol.Extent} extent Extent. + * @param {ol.tilegrid.TileGrid} tileGrid Tile grid. */ -ol.source.TileSource.prototype.useLowResolutionTiles = function(z, extent) { - var tileGrid = this.getTileGrid(); +ol.source.TileSource.prototype.useLowResolutionTiles = + function(z, extent, tileGrid) { var tileRange, x, y, zKey; // FIXME this should loop up to tileGrid's minZ when implemented for (; z >= 0; --z) { diff --git a/src/ol/source/wms.js b/src/ol/source/wms.js new file mode 100644 index 0000000000..0fff2f8e25 --- /dev/null +++ b/src/ol/source/wms.js @@ -0,0 +1,37 @@ +goog.provide('ol.source.wms'); + + +/** + * @param {string} baseUrl WMS base url. + * @param {Object.} params Request parameters. + * @param {ol.Extent} extent Extent. + * @param {ol.Size} size Size. + * @param {ol.Projection} projection Projection. + * @param {string=} opt_version WMS version. Default is '1.3.0'. + * @return {string} WMS GetMap request URL. + */ +ol.source.wms.getUrl = + function(baseUrl, params, extent, size, projection, opt_version) { + var version = goog.isDef(opt_version) ? opt_version : '1.3.0'; + var wms13 = version >= '1.3'; + var axisOrientation = projection.getAxisOrientation(); + var bboxValues = (wms13 && axisOrientation.substr(0, 2) == 'ne') ? + [extent.minY, extent.minX, extent.maxY, extent.maxX] : + [extent.minX, extent.minY, extent.maxX, extent.maxY]; + var baseParams = { + 'SERVICE': 'WMS', + 'VERSION': version, + 'REQUEST': 'GetMap', + 'FORMAT': 'image/png', + 'TRANSPARENT': true, + 'WIDTH': size.width, + 'HEIGHT': size.height, + 'BBOX': bboxValues.join(',') + }; + goog.object.extend(baseParams, params); + baseParams[wms13 ? 'CRS' : 'SRS'] = projection.getCode(); + //TODO: Provide our own appendParams function to avoid this empty string hack + var stylesParam = 'STYLES'; + baseParams[stylesParam] = params[stylesParam] || new String(''); + return goog.uri.utils.appendParamsFromMap(baseUrl, baseParams); +}; diff --git a/src/ol/tilegrid/tilegrid.js b/src/ol/tilegrid/tilegrid.js index 415557d93e..bcbbe26bd6 100644 --- a/src/ol/tilegrid/tilegrid.js +++ b/src/ol/tilegrid/tilegrid.js @@ -20,6 +20,12 @@ goog.require('ol.array'); ol.DEFAULT_TILE_SIZE = 256; +/** + * @define {number} Default maximum zoom for default tile grids. + */ +ol.DEFAULT_MAX_ZOOM = 42; + + /** * @constructor @@ -89,8 +95,7 @@ ol.tilegrid.TileGrid = function(tileGridOptions) { /** * @param {ol.TileCoord} tileCoord Tile coordinate. - * @param {function(this: T, number, ol.TileRange): boolean} callback - * Callback. + * @param {function(this: T, number, ol.TileRange): boolean} callback Callback. * @param {T=} opt_obj Object. * @template T */ @@ -328,7 +333,21 @@ ol.tilegrid.TileGrid.prototype.getZForResolution = function(resolution) { /** * @param {ol.Projection} projection Projection. - * @param {number=} opt_maxZoom Maximum zoom level (optional). Default is 18. + * @return {ol.tilegrid.TileGrid} Default tile grid for the passed projection. + */ +ol.tilegrid.getForProjection = function(projection) { + var tileGrid = projection.getDefaultTileGrid(); + if (goog.isNull(tileGrid)) { + tileGrid = ol.tilegrid.createForProjection(projection); + projection.setDefaultTileGrid(tileGrid); + } + return tileGrid; +}; + + +/** + * @param {ol.Projection} projection Projection. + * @param {number=} opt_maxZoom Maximum zoom level. * @param {ol.Size=} opt_tileSize Tile size. * @return {ol.tilegrid.TileGrid} TileGrid instance. */ @@ -339,7 +358,7 @@ ol.tilegrid.createForProjection = projectionExtent.maxX - projectionExtent.minX, projectionExtent.maxY - projectionExtent.minY); var maxZoom = goog.isDef(opt_maxZoom) ? - opt_maxZoom : 18; + opt_maxZoom : ol.DEFAULT_MAX_ZOOM; var tileSize = goog.isDef(opt_tileSize) ? opt_tileSize : new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE); var resolutions = new Array(maxZoom + 1); diff --git a/src/ol/tileurlfunction.js b/src/ol/tileurlfunction.js index d64c57ec9e..4e09acc976 100644 --- a/src/ol/tileurlfunction.js +++ b/src/ol/tileurlfunction.js @@ -3,13 +3,14 @@ goog.provide('ol.TileUrlFunctionType'); goog.require('goog.array'); goog.require('goog.math'); -goog.require('goog.uri.utils'); goog.require('ol.TileCoord'); +goog.require('ol.source.wms'); goog.require('ol.tilegrid.TileGrid'); /** - * @typedef {function(ol.TileCoord): (string|undefined)} + * @typedef {function(ol.TileCoord, ol.tilegrid.TileGrid, ol.Projection): + * (string|undefined)} */ ol.TileUrlFunctionType; @@ -59,12 +60,12 @@ ol.TileUrlFunction.createFromTemplates = function(templates) { * @return {ol.TileUrlFunctionType} Tile URL function. */ ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) { - return function(tileCoord) { + return function(tileCoord, tileGrid, projection) { if (goog.isNull(tileCoord)) { return undefined; } else { var index = goog.math.modulo(tileCoord.hash(), tileUrlFunctions.length); - return tileUrlFunctions[index](tileCoord); + return tileUrlFunctions[index](tileCoord, tileGrid, projection); } }; }; @@ -72,25 +73,20 @@ ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) { /** * @param {string} baseUrl Base URL (may have query data). - * @param {ol.tilegrid.TileGrid} tileGrid Tile grid. - * @param {string} axisOrientation Axis orientation. + * @param {Object.} params WMS parameters. + * @param {string=} opt_version WMS version. * @return {ol.TileUrlFunctionType} Tile URL function. */ -ol.TileUrlFunction.createBboxParam = - function(baseUrl, tileGrid, axisOrientation) { - return function(tileCoord) { +ol.TileUrlFunction.createWMSParams = + function(baseUrl, params, opt_version) { + return function(tileCoord, tileGrid, projection) { if (goog.isNull(tileCoord)) { return undefined; } else { - var tileExtent = tileGrid.getTileCoordExtent(tileCoord); - var bboxValues = axisOrientation.substr(0, 2) == 'ne' ? - [tileExtent.minY, tileExtent.minX, tileExtent.maxY, tileExtent.maxX] : - [tileExtent.minX, tileExtent.minY, tileExtent.maxX, tileExtent.maxY]; - var tileSize = tileGrid.getTileSize(tileCoord.z); - return goog.uri.utils.appendParams(baseUrl, - 'BBOX', bboxValues.join(','), - 'HEIGHT', tileSize.height, - 'WIDTH', tileSize.width); + var size = tileGrid.getTileSize(tileCoord.z); + var extent = tileGrid.getTileCoordExtent(tileCoord); + return ol.source.wms.getUrl( + baseUrl, params, extent, size, projection, opt_version); } }; }; @@ -106,18 +102,19 @@ ol.TileUrlFunction.nullTileUrlFunction = function(tileCoord) { /** - * @param {function(ol.TileCoord): ol.TileCoord} transformFn - * Transform.function. + * @param {function(ol.TileCoord, ol.tilegrid.TileGrid, ol.Projection): + * ol.TileCoord} transformFn Transform.function. * @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL function. * @return {ol.TileUrlFunctionType} Tile URL function. */ ol.TileUrlFunction.withTileCoordTransform = function(transformFn, tileUrlFunction) { - return function(tileCoord) { + return function(tileCoord, tileGrid, projection) { if (goog.isNull(tileCoord)) { return undefined; } else { - return tileUrlFunction(transformFn(tileCoord)); + return tileUrlFunction( + transformFn(tileCoord, tileGrid, projection), tileGrid, projection); } }; }; diff --git a/test/spec/ol/ellipsoid.test.js b/test/spec/ol/ellipsoid.test.js index 9692792ecd..6dd8310d93 100644 --- a/test/spec/ol/ellipsoid.test.js +++ b/test/spec/ol/ellipsoid.test.js @@ -325,15 +325,16 @@ describe('ol.Ellipsoid', function() { it('returns the same distances as Chris Veness\'s reference implementation', function() { - var e, i, v; - for (i = 0; i < expected.length; ++i) { - e = expected[i]; - v = ol.ellipsoid.WGS84.vincenty(e.c1, e.c2, 1e-12, 100); - expect(v.distance).toRoughlyEqual(e.vincentyDistance, 1e-8); - expect(v.finalBearing).toRoughlyEqual(e.vincentyFinalBearing, 1e-9); - expect(v.initialBearing).toRoughlyEqual(e.vincentyInitialBearing, 1e-9); - } - }); + var e, i, v; + for (i = 0; i < expected.length; ++i) { + e = expected[i]; + v = ol.ellipsoid.WGS84.vincenty(e.c1, e.c2, 1e-12, 100); + expect(v.distance).toRoughlyEqual(e.vincentyDistance, 1e-8); + expect(v.finalBearing).toRoughlyEqual(e.vincentyFinalBearing, 1e-9); + expect(v.initialBearing).toRoughlyEqual( + e.vincentyInitialBearing, 1e-9); + } + }); }); @@ -341,14 +342,14 @@ describe('ol.Ellipsoid', function() { it('returns the same distances as Chris Veness\'s reference implementation', function() { - var e, i, vincentyDistance; - for (i = 0; i < expected.length; ++i) { - e = expected[i]; - vincentyDistance = - ol.ellipsoid.WGS84.vincentyDistance(e.c1, e.c2, 1e-12, 100); - expect(vincentyDistance).toRoughlyEqual(e.vincentyDistance, 1e-8); - } - }); + var e, i, vincentyDistance; + for (i = 0; i < expected.length; ++i) { + e = expected[i]; + vincentyDistance = + ol.ellipsoid.WGS84.vincentyDistance(e.c1, e.c2, 1e-12, 100); + expect(vincentyDistance).toRoughlyEqual(e.vincentyDistance, 1e-8); + } + }); }); @@ -356,15 +357,15 @@ describe('ol.Ellipsoid', function() { it('returns the same distances as Chris Veness\'s reference implementation', function() { - var e, i, vincentyFinalBearing; - for (i = 0; i < expected.length; ++i) { - e = expected[i]; - vincentyFinalBearing = - ol.ellipsoid.WGS84.vincentyFinalBearing(e.c1, e.c2, 1e-12, 100); - expect(vincentyFinalBearing).toRoughlyEqual( - e.vincentyFinalBearing, 1e-9); - } - }); + var e, i, vincentyFinalBearing; + for (i = 0; i < expected.length; ++i) { + e = expected[i]; + vincentyFinalBearing = + ol.ellipsoid.WGS84.vincentyFinalBearing(e.c1, e.c2, 1e-12, 100); + expect(vincentyFinalBearing).toRoughlyEqual( + e.vincentyFinalBearing, 1e-9); + } + }); }); @@ -372,15 +373,15 @@ describe('ol.Ellipsoid', function() { it('returns the same distances as Chris Veness\'s reference implementation', function() { - var e, i, vincentyInitialBearing; - for (i = 0; i < expected.length; ++i) { - e = expected[i]; - vincentyInitialBearing = - ol.ellipsoid.WGS84.vincentyInitialBearing(e.c1, e.c2, 1e-12, 100); - expect(vincentyInitialBearing).toRoughlyEqual( - e.vincentyInitialBearing, 1e-9); - } - }); + var e, i, vincentyInitialBearing; + for (i = 0; i < expected.length; ++i) { + e = expected[i]; + vincentyInitialBearing = ol.ellipsoid.WGS84.vincentyInitialBearing( + e.c1, e.c2, 1e-12, 100); + expect(vincentyInitialBearing).toRoughlyEqual( + e.vincentyInitialBearing, 1e-9); + } + }); }); diff --git a/test/spec/ol/parser/ogc/wmscapabilities.test.js b/test/spec/ol/parser/ogc/wmscapabilities.test.js index 579898a1f4..a69ac29e87 100644 --- a/test/spec/ol/parser/ogc/wmscapabilities.test.js +++ b/test/spec/ol/parser/ogc/wmscapabilities.test.js @@ -3,10 +3,10 @@ goog.provide('ol.test.parser.ogc.WMSCapabilities'); describe('test WMSCapabilities', function() { describe('test getVersion', function() { var snippet = '' + - ''; + 'xmlns="http://www.opengis.net/wms">' + + ''; var snippet2 = '' + - ''; + ''; it('Version taken from document', function() { var parser = new ol.parser.ogc.WMSCapabilities(); var data = parser.read(snippet); @@ -28,7 +28,7 @@ describe('test WMSCapabilities', function() { expect(version).toEqual('1.3.0'); }); var msg = 'defaultVersion returned if no version specified in options ' + - 'and no version on the format'; + 'and no version on the format'; it(msg, function() { var version = parser.getVersion(null); expect(version).toEqual('1.1.1'); diff --git a/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1.test.js b/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1.test.js index 7d91002fbb..fd2f05c1eb 100644 --- a/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1.test.js +++ b/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1.test.js @@ -57,8 +57,8 @@ describe('ol.parser.ogc.wmscapabilities_v1_1_1', function() { expect(getfeatureinfo.post.href).toEqual(post); expect(capability.layers).toBeTruthy(); expect(capability.layers.length).toEqual(22); - var infoFormats = ['text/plain', 'text/html', - 'application/vnd.ogc.gml']; + var infoFormats = + ['text/plain', 'text/html', 'application/vnd.ogc.gml']; expect(layer.infoFormats).toEqual(infoFormats); expect(layer.name).toEqual('tiger:tiger_roads'); expect(layer.prefix).toEqual('tiger'); @@ -66,13 +66,13 @@ describe('ol.parser.ogc.wmscapabilities_v1_1_1', function() { var abstr = 'Highly simplified road layout of Manhattan in New York..'; expect(layer['abstract']).toEqual(abstr); var bbox = [-74.08769307536667, 40.660618924633326, - -73.84653192463333, 40.90178007536667]; + -73.84653192463333, 40.90178007536667]; expect(layer.llbbox).toEqual(bbox); expect(layer.styles.length).toEqual(1); expect(layer.styles[0].name).toEqual('tiger_roads'); var legend = 'http://publicus.opengeo.org:80/geoserver/wms/' + - 'GetLegendGraphic?VERSION=1.0.0&FORMAT=image/png&WIDTH=20&' + - 'HEIGHT=20&LAYER=tiger:tiger_roads'; + 'GetLegendGraphic?VERSION=1.0.0&FORMAT=image/png&WIDTH=20&' + + 'HEIGHT=20&LAYER=tiger:tiger_roads'; expect(layer.styles[0].legend.href).toEqual(legend); expect(layer.styles[0].legend.format).toEqual('image/png'); expect(layer.queryable).toBeTruthy(); @@ -168,28 +168,28 @@ describe('ol.parser.ogc.wmscapabilities_v1_1_1', function() { expect(elevation['default']).toEqual('0'); expect(elevation.nearestVal).toBeTruthy(); expect(elevation.multipleVal).toBeFalsy(); - expect(elevation.values).toEqual(['0', '1000', '3000', '5000', - '10000']); + expect(elevation.values).toEqual( + ['0', '1000', '3000', '5000', '10000']); }); }); }); describe('test contact info', function() { - it('Test contact info', function() { - var obj, service, contactinfo, personPrimary, addr; - runs(function() { - var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/' + - 'ogcsample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - service = obj.service; - contactinfo = service.contactInformation; - personPrimary = contactinfo.personPrimary; - addr = contactinfo.contactAddress; - }); - }); - waitsFor(function() { + it('Test contact info', function() { + var obj, service, contactinfo, personPrimary, addr; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/' + + 'ogcsample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + service = obj.service; + contactinfo = service.contactInformation; + personPrimary = contactinfo.personPrimary; + addr = contactinfo.contactAddress; + }); + }); + waitsFor(function() { return (obj !== undefined); }, 'XHR timeout', 1000); runs(function() { diff --git a/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.test.js b/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.test.js index 517daa762c..d2d1faf355 100644 --- a/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.test.js +++ b/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.test.js @@ -25,7 +25,7 @@ describe('ol.parser.ogc.wmscapabilities_v1_1_1_wmsc', function() { runs(function() { expect(tilesets.length).toEqual(2); var bbox = [-13697515.466796875, 5165920.118906248, - -13619243.94984375, 5244191.635859374]; + -13619243.94984375, 5244191.635859374]; expect(tileset.bbox['EPSG:900913'].bbox).toEqual(bbox); expect(tileset.format).toEqual('image/png'); expect(tileset.height).toEqual(256); @@ -33,14 +33,14 @@ describe('ol.parser.ogc.wmscapabilities_v1_1_1_wmsc', function() { expect(tileset.layers).toEqual('medford:hydro'); expect(tileset.srs['EPSG:900913']).toBeTruthy(); var resolutions = [156543.03390625, 78271.516953125, 39135.7584765625, - 19567.87923828125, 9783.939619140625, 4891.9698095703125, - 2445.9849047851562, 1222.9924523925781, 611.4962261962891, - 305.74811309814453, 152.87405654907226, 76.43702827453613, - 38.218514137268066, 19.109257068634033, 9.554628534317017, - 4.777314267158508, 2.388657133579254, 1.194328566789627, - 0.5971642833948135, 0.29858214169740677, 0.14929107084870338, - 0.07464553542435169, 0.037322767712175846, 0.018661383856087923, - 0.009330691928043961, 0.004665345964021981]; + 19567.87923828125, 9783.939619140625, 4891.9698095703125, + 2445.9849047851562, 1222.9924523925781, 611.4962261962891, + 305.74811309814453, 152.87405654907226, 76.43702827453613, + 38.218514137268066, 19.109257068634033, 9.554628534317017, + 4.777314267158508, 2.388657133579254, 1.194328566789627, + 0.5971642833948135, 0.29858214169740677, 0.14929107084870338, + 0.07464553542435169, 0.037322767712175846, 0.018661383856087923, + 0.009330691928043961, 0.004665345964021981]; expect(tileset.resolutions).toEqual(resolutions); expect(tileset.styles).toEqual(''); }); diff --git a/test/spec/ol/parser/ogc/wmscapabilities_v1_3_0.test.js b/test/spec/ol/parser/ogc/wmscapabilities_v1_3_0.test.js index 8ddac8875a..b73ff2ff8f 100644 --- a/test/spec/ol/parser/ogc/wmscapabilities_v1_3_0.test.js +++ b/test/spec/ol/parser/ogc/wmscapabilities_v1_3_0.test.js @@ -100,8 +100,8 @@ describe('ol.parser.ogc.wmscapabilities_v1_3_0', function() { expect(elevation['default']).toEqual('0'); expect(elevation.nearestVal).toBeTruthy(); expect(elevation.multipleVal).toBeFalsy(); - expect(elevation.values).toEqual(['0', '1000', '3000', '5000', - '10000']); + expect(elevation.values).toEqual( + ['0', '1000', '3000', '5000', '10000']); expect(contactinfo).toBeTruthy(); expect(personPrimary).toBeTruthy(); expect(personPrimary.person).toEqual('Jeff Smith'); diff --git a/test/spec/ol/parser/ogc/wmtscapabilities_v1_0_0.test.js b/test/spec/ol/parser/ogc/wmtscapabilities_v1_0_0.test.js index 2f5a012fe2..57077d340e 100644 --- a/test/spec/ol/parser/ogc/wmtscapabilities_v1_0_0.test.js +++ b/test/spec/ol/parser/ogc/wmtscapabilities_v1_0_0.test.js @@ -110,10 +110,10 @@ describe('ol.parser.ogc.wmtscapabilities_v1_0_0', function() { expect(layer.resourceUrls.tile.hasOwnProperty(format)).toBeTruthy(); expect(layer.resourceUrls.tile[format].length).toEqual(2); var tpl = 'http://a.example.com/wmts/coastlines/{TileMatrix}/' + - '{TileRow}/{TileCol}.png'; + '{TileRow}/{TileCol}.png'; expect(layer.resourceUrls.tile[format][0]).toEqual(tpl); tpl = 'http://b.example.com/wmts/coastlines/{TileMatrix}/' + - '{TileRow}/{TileCol}.png'; + '{TileRow}/{TileCol}.png'; expect(layer.resourceUrls.tile[format][1]).toEqual(tpl); expect(layer.resourceUrls.hasOwnProperty('FeatureInfo')).toBeTruthy(); format = 'application/gml+xml; version=3.1'; @@ -121,7 +121,7 @@ describe('ol.parser.ogc.wmtscapabilities_v1_0_0', function() { .toBeTruthy(); expect(layer.resourceUrls.FeatureInfo[format].length).toEqual(1); tpl = 'http://www.example.com/wmts/coastlines/{TileMatrixSet}/' + - '{TileMatrix}/{TileRow}/{TileCol}/{J}/{I}.xml'; + '{TileMatrix}/{TileRow}/{TileCol}/{J}/{I}.xml'; expect(layer.resourceUrls.FeatureInfo[format][0]).toEqual(tpl); expect(dimensions.length).toEqual(1); expect(dimensions[0].title).toEqual('Time'); diff --git a/test/spec/ol/projection.epsg3857.test.js b/test/spec/ol/projection.epsg3857.test.js index 3ba62dfa41..7963cdcf71 100644 --- a/test/spec/ol/projection.epsg3857.test.js +++ b/test/spec/ol/projection.epsg3857.test.js @@ -16,15 +16,15 @@ describe('ol.projection.EPSG3857', function() { it('returns the correct point scale at the latitude of Toronto', function() { - // @see http://msdn.microsoft.com/en-us/library/aa940990.aspx - var epsg3857 = ol.projection.getFromCode('EPSG:3857'); - var epsg4326 = ol.projection.getFromCode('EPSG:4326'); - var resolution = 19.11; - var point = ol.projection.transform( - new ol.Coordinate(0, 43.65), epsg4326, epsg3857); - expect(epsg3857.getPointResolution(resolution, point)). - toRoughlyEqual(19.11 * Math.cos(Math.PI * 43.65 / 180), 1e-9); - }); + // @see http://msdn.microsoft.com/en-us/library/aa940990.aspx + var epsg3857 = ol.projection.getFromCode('EPSG:3857'); + var epsg4326 = ol.projection.getFromCode('EPSG:4326'); + var resolution = 19.11; + var point = ol.projection.transform( + new ol.Coordinate(0, 43.65), epsg4326, epsg3857); + expect(epsg3857.getPointResolution(resolution, point)). + toRoughlyEqual(19.11 * Math.cos(Math.PI * 43.65 / 180), 1e-9); + }); it('returns the correct point scale at various latitudes', function() { // @see http://msdn.microsoft.com/en-us/library/aa940990.aspx diff --git a/test/spec/ol/resolutionconstraint.test.js b/test/spec/ol/resolutionconstraint.test.js index 4ed0ea48aa..08ca26e701 100644 --- a/test/spec/ol/resolutionconstraint.test.js +++ b/test/spec/ol/resolutionconstraint.test.js @@ -7,9 +7,8 @@ describe('ol.ResolutionConstraint', function() { var resolutionConstraint; beforeEach(function() { - resolutionConstraint = - ol.ResolutionConstraint.createSnapToResolutions( - [1000, 500, 250, 100]); + resolutionConstraint = ol.ResolutionConstraint.createSnapToResolutions( + [1000, 500, 250, 100]); }); describe('delta 0', function() { diff --git a/test/spec/ol/source/tilesource.test.js b/test/spec/ol/source/tilesource.test.js index 53f2dd05bb..a03229a8fd 100644 --- a/test/spec/ol/source/tilesource.test.js +++ b/test/spec/ol/source/tilesource.test.js @@ -14,10 +14,6 @@ describe('ol.source.TileSource', function() { describe('#findLoadedTiles()', function() { - function isLoaded(tile) { - return !goog.isNull(tile) && tile.getState() === ol.TileState.LOADED; - } - it('adds no tiles if none are already loaded', function() { // a source with no loaded tiles var source = new ol.test.source.MockTileSource({}); @@ -25,7 +21,13 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 3); - source.findLoadedTiles(loadedTilesByZ, isLoaded, 3, range); + + function getTileIfLoaded(tileCoord) { + var tile = source.getTile(tileCoord, null, null); + return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? + tile : null; + } + source.findLoadedTiles(loadedTilesByZ, getTileIfLoaded, 3, range); var keys = goog.object.getKeys(loadedTilesByZ); expect(keys.length).toBe(0); @@ -41,7 +43,13 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 0); - source.findLoadedTiles(loadedTilesByZ, isLoaded, 0, range); + + function getTileIfLoaded(tileCoord) { + var tile = source.getTile(tileCoord, null, null); + return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? + tile : null; + } + source.findLoadedTiles(loadedTilesByZ, getTileIfLoaded, 0, range); var keys = goog.object.getKeys(loadedTilesByZ); expect(keys.length).toBe(1); var tile = loadedTilesByZ['0']['0/0/0']; @@ -59,7 +67,13 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); + + function getTileIfLoaded(tileCoord) { + var tile = source.getTile(tileCoord, null, null); + return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? + tile : null; + } + source.findLoadedTiles(loadedTilesByZ, getTileIfLoaded, 1, range); var keys = goog.object.getKeys(loadedTilesByZ); expect(keys.length).toBe(1); var tile = loadedTilesByZ['1']['1/0/0']; @@ -79,7 +93,13 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - var loaded = source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); + function getTileIfLoaded(tileCoord) { + var tile = source.getTile(tileCoord, null, null); + return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? + tile : null; + } + var loaded = source.findLoadedTiles( + loadedTilesByZ, getTileIfLoaded, 1, range); expect(loaded).toBe(true); }); @@ -98,7 +118,14 @@ describe('ol.source.TileSource', function() { }; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - var loaded = source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); + + function getTileIfLoaded(tileCoord) { + var tile = source.getTile(tileCoord, null, null); + return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? + tile : null; + } + var loaded = source.findLoadedTiles( + loadedTilesByZ, getTileIfLoaded, 1, range); expect(loaded).toBe(true); }); @@ -114,7 +141,14 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - var loaded = source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); + + function getTileIfLoaded(tileCoord) { + var tile = source.getTile(tileCoord, null, null); + return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? + tile : null; + } + var loaded = source.findLoadedTiles( + loadedTilesByZ, getTileIfLoaded, 1, range); expect(loaded).toBe(false); }); @@ -132,7 +166,14 @@ describe('ol.source.TileSource', function() { }; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - var loaded = source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); + + function getTileIfLoaded(tileCoord) { + var tile = source.getTile(tileCoord, null, null); + return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? + tile : null; + } + var loaded = source.findLoadedTiles( + loadedTilesByZ, getTileIfLoaded, 1, range); expect(loaded).toBe(false); }); diff --git a/test/spec/ol/source/xyz.test.js b/test/spec/ol/source/xyz.test.js index bf968d4c86..e53ad17f86 100644 --- a/test/spec/ol/source/xyz.test.js +++ b/test/spec/ol/source/xyz.test.js @@ -2,7 +2,7 @@ goog.provide('ol.test.source.XYZ'); describe('ol.source.XYZ', function() { - describe('getTileCoordUrl', function() { + describe('tileUrlFunction', function() { var xyzTileSource, tileGrid; @@ -18,59 +18,59 @@ describe('ol.source.XYZ', function() { var coordinate = new ol.Coordinate(829330.2064098881, 5933916.615134273); var tileUrl; - tileUrl = xyzTileSource.getTileCoordUrl( + tileUrl = xyzTileSource.tileUrlFunction( tileGrid.getTileCoordForCoordAndZ(coordinate, 0)); expect(tileUrl).toEqual('0/0/0'); - tileUrl = xyzTileSource.getTileCoordUrl( + tileUrl = xyzTileSource.tileUrlFunction( tileGrid.getTileCoordForCoordAndZ(coordinate, 1)); expect(tileUrl).toEqual('1/1/0'); - tileUrl = xyzTileSource.getTileCoordUrl( + tileUrl = xyzTileSource.tileUrlFunction( tileGrid.getTileCoordForCoordAndZ(coordinate, 2)); expect(tileUrl).toEqual('2/2/1'); - tileUrl = xyzTileSource.getTileCoordUrl( + tileUrl = xyzTileSource.tileUrlFunction( tileGrid.getTileCoordForCoordAndZ(coordinate, 3)); expect(tileUrl).toEqual('3/4/2'); - tileUrl = xyzTileSource.getTileCoordUrl( + tileUrl = xyzTileSource.tileUrlFunction( tileGrid.getTileCoordForCoordAndZ(coordinate, 4)); expect(tileUrl).toEqual('4/8/5'); - tileUrl = xyzTileSource.getTileCoordUrl( + tileUrl = xyzTileSource.tileUrlFunction( tileGrid.getTileCoordForCoordAndZ(coordinate, 5)); expect(tileUrl).toEqual('5/16/11'); - tileUrl = xyzTileSource.getTileCoordUrl( + tileUrl = xyzTileSource.tileUrlFunction( tileGrid.getTileCoordForCoordAndZ(coordinate, 6)); expect(tileUrl).toEqual('6/33/22'); }); describe('wrap x', function() { it('returns the expected URL', function() { - var tileUrl = xyzTileSource.getTileCoordUrl( + var tileUrl = xyzTileSource.tileUrlFunction( new ol.TileCoord(6, -31, -23)); expect(tileUrl).toEqual('6/33/22'); - tileUrl = xyzTileSource.getTileCoordUrl(new ol.TileCoord(6, 33, -23)); + tileUrl = xyzTileSource.tileUrlFunction(new ol.TileCoord(6, 33, -23)); expect(tileUrl).toEqual('6/33/22'); - tileUrl = xyzTileSource.getTileCoordUrl(new ol.TileCoord(6, 97, -23)); + tileUrl = xyzTileSource.tileUrlFunction(new ol.TileCoord(6, 97, -23)); expect(tileUrl).toEqual('6/33/22'); }); }); describe('crop y', function() { it('returns the expected URL', function() { - var tileUrl = xyzTileSource.getTileCoordUrl( + var tileUrl = xyzTileSource.tileUrlFunction( new ol.TileCoord(6, 33, -87)); expect(tileUrl).toBeUndefined(); - tileUrl = xyzTileSource.getTileCoordUrl(new ol.TileCoord(6, 33, -23)); + tileUrl = xyzTileSource.tileUrlFunction(new ol.TileCoord(6, 33, -23)); expect(tileUrl).toEqual('6/33/22'); - tileUrl = xyzTileSource.getTileCoordUrl(new ol.TileCoord(6, 33, 41)); + tileUrl = xyzTileSource.tileUrlFunction(new ol.TileCoord(6, 33, 41)); expect(tileUrl).toBeUndefined(); }); }); diff --git a/test/spec/ol/tilegrid.test.js b/test/spec/ol/tilegrid.test.js index 3c24a17167..5c254dd47f 100644 --- a/test/spec/ol/tilegrid.test.js +++ b/test/spec/ol/tilegrid.test.js @@ -169,16 +169,16 @@ describe('ol.tilegrid.TileGrid', function() { expect(grid).toBeA(ol.tilegrid.TileGrid); var resolutions = grid.getResolutions(); - expect(resolutions.length).toBe(19); + expect(resolutions.length).toBe(ol.DEFAULT_MAX_ZOOM + 1); }); it('accepts a number of zoom levels', function() { var projection = ol.projection.getFromCode('EPSG:3857'); - var grid = ol.tilegrid.createForProjection(projection, 22); + var grid = ol.tilegrid.createForProjection(projection, 18); expect(grid).toBeA(ol.tilegrid.TileGrid); var resolutions = grid.getResolutions(); - expect(resolutions.length).toBe(23); + expect(resolutions.length).toBe(19); }); it('accepts a big number of zoom levels', function() { @@ -192,6 +192,28 @@ describe('ol.tilegrid.TileGrid', function() { }); + describe('getForProjection', function() { + + it('gets the default tile grid for a projection', function() { + var projection = ol.projection.getFromCode('EPSG:3857'); + var grid = ol.tilegrid.getForProjection(projection); + expect(grid).toBeA(ol.tilegrid.TileGrid); + + var resolutions = grid.getResolutions(); + expect(resolutions.length).toBe(ol.DEFAULT_MAX_ZOOM + 1); + expect(grid.getTileSize().toString()).toBe('(256 x 256)'); + }); + + it('stores the default tile grid on a projection', function() { + var projection = ol.projection.getFromCode('EPSG:3857'); + var grid = ol.tilegrid.getForProjection(projection); + var gridAgain = ol.tilegrid.getForProjection(projection); + + expect(grid).toBe(gridAgain); + }); + + }); + describe('getTileCoordFromCoordAndZ', function() { describe('Y North, X East', function() { diff --git a/test/spec/ol/tileurlfunction.test.js b/test/spec/ol/tileurlfunction.test.js index 62f245f5c9..d411ed4e24 100644 --- a/test/spec/ol/tileurlfunction.test.js +++ b/test/spec/ol/tileurlfunction.test.js @@ -51,8 +51,8 @@ describe('ol.TileUrlFunction', function() { describe('createFromTileUrlFunctions', function() { it('creates expected URL', function() { var tileUrl = ol.TileUrlFunction.createFromTileUrlFunctions([ - ol.TileUrlFunction.createFromTemplate('a'), - ol.TileUrlFunction.createFromTemplate('b') + ol.TileUrlFunction.createFromTemplate('a'), + ol.TileUrlFunction.createFromTemplate('b') ]); var tileUrl1 = tileUrl(new ol.TileCoord(1, 0, 0)); var tileUrl2 = tileUrl(new ol.TileCoord(1, 0, 1)); @@ -61,7 +61,7 @@ describe('ol.TileUrlFunction', function() { }); }); - describe('createBboxParam', function() { + describe('createWMSParams', function() { var tileGrid; beforeEach(function() { tileGrid = new ol.tilegrid.XYZ({ @@ -70,24 +70,26 @@ describe('ol.TileUrlFunction', function() { }); it('creates expected URL', function() { var epsg3857 = ol.projection.getFromCode('EPSG:3857'); - var tileUrlFunction = ol.TileUrlFunction.createBboxParam( - 'http://wms?foo=bar', tileGrid, epsg3857.getAxisOrientation()); + var tileUrlFunction = ol.TileUrlFunction.createWMSParams( + 'http://wms?foo=bar', {}); var tileCoord = new ol.TileCoord(1, 0, 0); - var tileUrl = tileUrlFunction(tileCoord); - var expected = 'http://wms?foo=bar&BBOX=-20037508.342789244' + - '%2C20037508.342789244%2C0%2C40075016.68557849' + - '&HEIGHT=256&WIDTH=256'; + var tileUrl = tileUrlFunction(tileCoord, tileGrid, epsg3857); + var expected = 'http://wms?foo=bar&SERVICE=WMS&VERSION=1.3.0&' + + 'REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&WIDTH=256&' + + 'HEIGHT=256&BBOX=-20037508.342789244%2C20037508.342789244%2C0%2C' + + '40075016.68557849&CRS=EPSG%3A3857&STYLES='; expect(tileUrl).toEqual(expected); }); it('creates expected URL respecting axis orientation', function() { var epsg4326 = ol.projection.getFromCode('EPSG:4326'); - var tileUrlFunction = ol.TileUrlFunction.createBboxParam( - 'http://wms?foo=bar', tileGrid, epsg4326.getAxisOrientation()); + var tileUrlFunction = ol.TileUrlFunction.createWMSParams( + 'http://wms?foo=bar', {}); var tileCoord = new ol.TileCoord(1, 0, 0); - var tileUrl = tileUrlFunction(tileCoord); - var expected = 'http://wms?foo=bar&BBOX=20037508.342789244' + - '%2C-20037508.342789244%2C40075016.68557849%2C0' + - '&HEIGHT=256&WIDTH=256'; + var tileUrl = tileUrlFunction(tileCoord, tileGrid, epsg4326); + var expected = 'http://wms?foo=bar&SERVICE=WMS&VERSION=1.3.0&' + + 'REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&WIDTH=256&' + + 'HEIGHT=256&BBOX=20037508.342789244%2C-20037508.342789244%2C' + + '40075016.68557849%2C0&CRS=EPSG%3A4326&STYLES='; expect(tileUrl).toEqual(expected); }); }); diff --git a/test/spec/ol/view2d.test.js b/test/spec/ol/view2d.test.js index 392c149e13..d78e17dad4 100644 --- a/test/spec/ol/view2d.test.js +++ b/test/spec/ol/view2d.test.js @@ -18,21 +18,21 @@ describe('ol.View2D', function() { describe('with maxResolution, numZoomLevels, and zoomFactor options', function() { - it('gives a correct resolution constraint function', function() { - var options = { - maxResolution: 81, - numZoomLevels: 4, - zoomFactor: 3 - }; - var fn = ol.View2D.createConstraints_(options).resolution; - expect(fn(82, 0)).toEqual(81); - expect(fn(81, 0)).toEqual(81); - expect(fn(27, 0)).toEqual(27); - expect(fn(9, 0)).toEqual(9); - expect(fn(3, 0)).toEqual(3); - expect(fn(2, 0)).toEqual(3); - }); - }); + it('gives a correct resolution constraint function', function() { + var options = { + maxResolution: 81, + numZoomLevels: 4, + zoomFactor: 3 + }; + var fn = ol.View2D.createConstraints_(options).resolution; + expect(fn(82, 0)).toEqual(81); + expect(fn(81, 0)).toEqual(81); + expect(fn(27, 0)).toEqual(27); + expect(fn(9, 0)).toEqual(9); + expect(fn(3, 0)).toEqual(3); + expect(fn(2, 0)).toEqual(3); + }); + }); describe('with resolutions', function() { it('gives a correct resolution constraint function', function() {