diff --git a/examples/full-screen.js b/examples/full-screen.js index b5e6b30486..0228a84c5c 100644 --- a/examples/full-screen.js +++ b/examples/full-screen.js @@ -4,6 +4,7 @@ goog.require('goog.debug.Logger.Level'); goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); +goog.require('ol.RendererHints'); goog.require('ol.View2D'); goog.require('ol.source.MapQuestOpenAerial'); @@ -19,6 +20,7 @@ var layer = new ol.layer.TileLayer({ }); var map = new ol.Map({ layers: new ol.Collection([layer]), + renderers: ol.RendererHints.createFromQueryData(), target: 'map', view: new ol.View2D({ center: new ol.Coordinate(0, 0), diff --git a/examples/overlay-and-popup.js b/examples/overlay-and-popup.js index 6e98be100e..1e19bb425b 100644 --- a/examples/overlay-and-popup.js +++ b/examples/overlay-and-popup.js @@ -4,6 +4,7 @@ goog.require('goog.debug.Logger.Level'); goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); +goog.require('ol.RendererHints'); goog.require('ol.View2D'); goog.require('ol.overlay.Overlay'); goog.require('ol.source.MapQuestOpenAerial'); @@ -21,6 +22,7 @@ var layer = new ol.layer.TileLayer({ var map = new ol.Map({ layers: new ol.Collection([layer]), + renderers: ol.RendererHints.createFromQueryData(), target: 'map', view: new ol.View2D({ center: new ol.Coordinate(0, 0), diff --git a/examples/wms-custom-proj.js b/examples/wms-custom-proj.js index 2ab93080fe..b6e910dab2 100644 --- a/examples/wms-custom-proj.js +++ b/examples/wms-custom-proj.js @@ -5,6 +5,7 @@ goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); goog.require('ol.Projection'); +goog.require('ol.RendererHints'); goog.require('ol.View2D'); goog.require('ol.source.TiledWMS'); @@ -56,6 +57,7 @@ var map = new ol.Map({ // proj4js because we do not need any transforms. userProjection: epsg21781, layers: layers, + renderers: ol.RendererHints.createFromQueryData(), target: 'map', view: new ol.View2D({ center: new ol.Coordinate(660000, 190000), diff --git a/src/ol/map.js b/src/ol/map.js index 8b29f45a73..b2f3db7663 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -6,7 +6,9 @@ goog.provide('ol.Map'); goog.provide('ol.MapEventType'); goog.provide('ol.MapProperty'); goog.provide('ol.RendererHint'); +goog.provide('ol.RendererHints'); +goog.require('goog.Uri.QueryData'); goog.require('goog.array'); goog.require('goog.async.AnimationDelay'); goog.require('goog.debug.Logger'); @@ -22,7 +24,6 @@ goog.require('goog.events.KeyHandler.EventType'); goog.require('goog.events.MouseWheelEvent'); goog.require('goog.events.MouseWheelHandler'); goog.require('goog.events.MouseWheelHandler.EventType'); -goog.require('goog.functions'); goog.require('goog.object'); goog.require('ol.BrowserFeature'); goog.require('ol.Collection'); @@ -921,3 +922,20 @@ ol.Map.createInteractions_ = function(mapOptions) { return interactions; }; + + +/** + * @param {goog.Uri.QueryData=} opt_queryData Query data. + * @return {Array.} Renderer hints. + */ +ol.RendererHints.createFromQueryData = function(opt_queryData) { + var queryData = goog.isDef(opt_queryData) ? + opt_queryData : new goog.Uri.QueryData(goog.global.location.search); + if (queryData.containsKey('renderers')) { + return queryData.get('renderers').split(','); + } else if (queryData.containsKey('renderer')) { + return [queryData.get('renderer')]; + } else { + return ol.DEFAULT_RENDERER_HINTS; + } +}; diff --git a/src/ol/renderer/dom/dommaprenderer.js b/src/ol/renderer/dom/dommaprenderer.js index 7822740d5c..befec3767c 100644 --- a/src/ol/renderer/dom/dommaprenderer.js +++ b/src/ol/renderer/dom/dommaprenderer.js @@ -5,7 +5,6 @@ goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('goog.events'); goog.require('goog.events.Event'); -goog.require('goog.functions'); goog.require('goog.style'); goog.require('ol.Coordinate'); goog.require('ol.FrameState'); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 79c4e755a4..cdbfb92305 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -79,69 +79,73 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = return; } + var view2DState = frameState.view2DState; + var tileLayer = this.getTileLayer(); var tileSource = tileLayer.getTileSource(); var tileGrid = tileSource.getTileGrid(); - - var view2DState = frameState.view2DState; var z = tileGrid.getZForResolution(view2DState.resolution); var tileResolution = tileGrid.getResolution(z); + var tileRange = tileGrid.getTileRangeForExtentAndResolution( + frameState.extent, tileResolution); /** @type {Object.>} */ var tilesToDrawByZ = {}; + tilesToDrawByZ[z] = {}; - var tileRange = tileGrid.getTileRangeForExtentAndResolution( - frameState.extent, view2DState.resolution); + var findInterimTiles = function(z, tileRange) { + // FIXME this could be more efficient about filling partial holes + var fullyCovered = true; + var tile, tileCoord, tileCoordKey, x, y; + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { + tileCoord = new ol.TileCoord(z, x, y); + tileCoordKey = tileCoord.toString(); + if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) { + return; + } + tile = tileSource.getTile(tileCoord); + if (!goog.isNull(tile) && tile.getState() == ol.TileState.LOADED) { + if (!tilesToDrawByZ[z]) { + tilesToDrawByZ[z] = {}; + } + tilesToDrawByZ[z][tileCoordKey] = tile; + } else { + fullyCovered = false; + } + } + } + return fullyCovered; + }; var allTilesLoaded = true; + var tile, tileCenter, tileCoord, tileState, x, y; + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { - tilesToDrawByZ[z] = {}; - tileRange.forEachTileCoord(z, function(tileCoord) { + tileCoord = new ol.TileCoord(z, x, y); + tile = tileSource.getTile(tileCoord); + if (goog.isNull(tile)) { + continue; + } - var tile = tileSource.getTile(tileCoord); + tileState = tile.getState(); + if (tileState == ol.TileState.IDLE) { + tileCenter = tileGrid.getTileCoordCenter(tileCoord); + frameState.tileQueue.enqueue(tile, tileCenter, tileResolution); + } else if (tileState == ol.TileState.LOADED) { + tilesToDrawByZ[z][tileCoord.toString()] = tile; + continue; + } else if (tileState == ol.TileState.ERROR) { + continue; + } + + allTilesLoaded = false; + tileGrid.forEachTileCoordParentTileRange(tileCoord, findInterimTiles); - if (goog.isNull(tile)) { - return; } - var tileState = tile.getState(); - if (tileState == ol.TileState.IDLE) { - var tileCenter = tileGrid.getTileCoordCenter(tileCoord); - frameState.tileQueue.enqueue(tile, tileCenter, tileResolution); - } else if (tileState == ol.TileState.LOADED) { - tilesToDrawByZ[z][tile.tileCoord.toString()] = tile; - return; - } else if (tileState == ol.TileState.ERROR) { - return; - } - - allTilesLoaded = false; - - // FIXME this could be more efficient about filling partial holes - tileGrid.forEachTileCoordParentTileRange( - tileCoord, - function(z, tileRange) { - var fullyCovered = true; - tileRange.forEachTileCoord(z, function(tileCoord) { - var tileCoordKey = tileCoord.toString(); - if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) { - return; - } - var tile = tileSource.getTile(tileCoord); - if (!goog.isNull(tile) && - tile.getState() == ol.TileState.LOADED) { - if (!tilesToDrawByZ[z]) { - tilesToDrawByZ[z] = {}; - } - tilesToDrawByZ[z][tileCoordKey] = tile; - } else { - fullyCovered = false; - } - }); - return fullyCovered; - }); - - }, this); + } /** @type {Array.} */ var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number); diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 0a2e6069b3..3a071a686e 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -12,7 +12,6 @@ goog.require('goog.dom.TagName'); goog.require('goog.events'); goog.require('goog.events.Event'); goog.require('goog.events.EventType'); -goog.require('goog.functions'); goog.require('goog.style'); goog.require('goog.webgl'); goog.require('ol.Tile'); diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 8f27749f9c..43f83838fd 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -348,66 +348,73 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = * @type {Object.>} */ var tilesToDrawByZ = {}; + tilesToDrawByZ[z] = {}; + + var findInterimTiles = function(z, tileRange) { + // FIXME this could be more efficient about filling partial holes + var fullyCovered = true; + var tile, tileCoord, tileCoordKey, x, y; + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { + tileCoord = new ol.TileCoord(z, x, y); + tileCoordKey = tileCoord.toString(); + if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) { + return; + } + tile = tileSource.getTile(tileCoord); + if (!goog.isNull(tile) && + tile.getState() == ol.TileState.LOADED && + mapRenderer.isTileTextureLoaded(tile)) { + if (!tilesToDrawByZ[z]) { + tilesToDrawByZ[z] = {}; + } + tilesToDrawByZ[z][tileCoordKey] = tile; + } else { + fullyCovered = false; + } + } + } + return fullyCovered; + }; var tilesToLoad = new goog.structs.PriorityQueue(); var allTilesLoaded = true; + var deltaX, deltaY, priority, tile, tileCenter, tileCoord, tileState, x, y; + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { - tilesToDrawByZ[z] = {}; - tileRange.forEachTileCoord(z, function(tileCoord) { - - var tile = tileSource.getTile(tileCoord); - - if (goog.isNull(tile)) { - return; - } - - var tileState = tile.getState(); - if (tileState == ol.TileState.IDLE) { - var tileCenter = tileGrid.getTileCoordCenter(tileCoord); - frameState.tileQueue.enqueue(tile, tileCenter, tileResolution); - } else if (tileState == ol.TileState.LOADED) { - if (mapRenderer.isTileTextureLoaded(tile)) { - tilesToDrawByZ[z][tileCoord.toString()] = tile; - return; - } else { - var tileCenter = tileGrid.getTileCoordCenter(tileCoord); - var deltaX = tileCenter.x - center.x; - var deltaY = tileCenter.y - center.y; - var priority = Math.sqrt(deltaX * deltaX + deltaY * deltaY); - tilesToLoad.enqueue(priority, tile); + tileCoord = new ol.TileCoord(z, x, y); + tile = tileSource.getTile(tileCoord); + if (goog.isNull(tile)) { + continue; } - } else if (tileState == ol.TileState.ERROR) { - return; + + tileState = tile.getState(); + if (tileState == ol.TileState.IDLE) { + tileCenter = tileGrid.getTileCoordCenter(tileCoord); + frameState.tileQueue.enqueue(tile, tileCenter, tileResolution); + } else if (tileState == ol.TileState.LOADED) { + if (mapRenderer.isTileTextureLoaded(tile)) { + tilesToDrawByZ[z][tileCoord.toString()] = tile; + continue; + } else { + tileCenter = tileGrid.getTileCoordCenter(tileCoord); + deltaX = tileCenter.x - center.x; + deltaY = tileCenter.y - center.y; + priority = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + tilesToLoad.enqueue(priority, tile); + } + } else if (tileState == ol.TileState.ERROR) { + continue; + } + + allTilesLoaded = false; + tileGrid.forEachTileCoordParentTileRange(tileCoord, findInterimTiles); + } - allTilesLoaded = false; - - // FIXME this could be more efficient about filling partial holes - tileGrid.forEachTileCoordParentTileRange( - tileCoord, - function(z, tileRange) { - var fullyCovered = true; - tileRange.forEachTileCoord(z, function(tileCoord) { - var tileCoordKey = tileCoord.toString(); - if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) { - return; - } - var tile = tileSource.getTile(tileCoord); - if (!goog.isNull(tile) && - tile.getState() == ol.TileState.LOADED) { - if (!tilesToDrawByZ[z]) { - tilesToDrawByZ[z] = {}; - } - tilesToDrawByZ[z][tileCoordKey] = tile; - } else { - fullyCovered = false; - } - }); - return fullyCovered; - }); - - }, this); + } /** @type {Array.} */ var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number); diff --git a/src/ol/tilerange.js b/src/ol/tilerange.js index db4d13f051..7c402f00cb 100644 --- a/src/ol/tilerange.js +++ b/src/ol/tilerange.js @@ -28,9 +28,9 @@ ol.TileRange.boundingTileRange = function(var_args) { var tileCoord0 = arguments[0]; var tileRange = new ol.TileRange(tileCoord0.x, tileCoord0.y, tileCoord0.x, tileCoord0.y); - var i; + var i, tileCoord; for (i = 1; i < arguments.length; ++i) { - var tileCoord = arguments[i]; + tileCoord = arguments[i]; goog.asserts.assert(tileCoord.z == tileCoord0.z); tileRange.minX = Math.min(tileRange.minX, tileCoord.x); tileRange.minY = Math.min(tileRange.minY, tileCoord.y); @@ -71,22 +71,6 @@ ol.TileRange.prototype.equals = function(tileRange) { }; -/** - * @param {number} z Z. - * @param {function(this: T, ol.TileCoord)} f Callback. - * @param {T=} opt_obj The object to be used for the value of 'this' within f. - * @template T - */ -ol.TileRange.prototype.forEachTileCoord = function(z, f, opt_obj) { - var x, y; - for (x = this.minX; x <= this.maxX; ++x) { - for (y = this.minY; y <= this.maxY; ++y) { - f.call(opt_obj, new ol.TileCoord(z, x, y)); - } - } -}; - - /** * @inheritDoc * @return {number} Height. diff --git a/test/spec/ol/tilerange.test.js b/test/spec/ol/tilerange.test.js index b9eb37f465..a772a59f16 100644 --- a/test/spec/ol/tilerange.test.js +++ b/test/spec/ol/tilerange.test.js @@ -51,36 +51,6 @@ describe('ol.TileRange', function() { }); }); - describe('forEachTileCoord', function() { - it('iterates as expected', function() { - var tileRange = new ol.TileRange(0, 2, 1, 3); - - var tileCoords = []; - tileRange.forEachTileCoord(5, function(tileCoord) { - tileCoords.push( - new ol.TileCoord(tileCoord.z, tileCoord.x, tileCoord.y)); - }); - - expect(tileCoords.length).toEqual(4); - - expect(tileCoords[0].z).toEqual(5); - expect(tileCoords[0].x).toEqual(0); - expect(tileCoords[0].y).toEqual(2); - - expect(tileCoords[1].z).toEqual(5); - expect(tileCoords[1].x).toEqual(0); - expect(tileCoords[1].y).toEqual(3); - - expect(tileCoords[2].z).toEqual(5); - expect(tileCoords[2].x).toEqual(1); - expect(tileCoords[2].y).toEqual(2); - - expect(tileCoords[3].z).toEqual(5); - expect(tileCoords[3].x).toEqual(1); - expect(tileCoords[3].y).toEqual(3); - }); - }); - describe('getSize', function() { it('returns the expected size', function() { var tileRange = new ol.TileRange(0, 1, 2, 4);