Merge pull request #3246 from tschaub/tile-cache
Avoid creating unnecessary images in tile layers.
This commit is contained in:
@@ -287,11 +287,7 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
|
||||
/** @type {Array.<ol.Tile>} */
|
||||
var tilesToClear = [];
|
||||
|
||||
var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) {
|
||||
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED;
|
||||
}, tileSource, pixelRatio, projection);
|
||||
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
|
||||
tilesToDrawByZ, getTileIfLoaded);
|
||||
var findLoadedTiles = this.createLoadedTileFinder(tileSource, tilesToDrawByZ);
|
||||
|
||||
var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError();
|
||||
|
||||
|
||||
@@ -128,11 +128,7 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
|
||||
var tilesToDrawByZ = {};
|
||||
tilesToDrawByZ[z] = {};
|
||||
|
||||
var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) {
|
||||
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED;
|
||||
}, tileSource, pixelRatio, projection);
|
||||
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
|
||||
tilesToDrawByZ, getTileIfLoaded);
|
||||
var findLoadedTiles = this.createLoadedTileFinder(tileSource, tilesToDrawByZ);
|
||||
|
||||
var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError();
|
||||
|
||||
|
||||
@@ -85,6 +85,33 @@ ol.renderer.Layer.prototype.forEachLayerAtPixel =
|
||||
ol.renderer.Layer.prototype.hasFeatureAtCoordinate = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* Create a function that adds loaded tiles to the tile lookup.
|
||||
* @param {ol.source.Tile} source Tile source.
|
||||
* @param {Object.<number, Object.<string, ol.Tile>>} tiles Lookup of loaded
|
||||
* tiles by zoom level.
|
||||
* @return {function(number, ol.TileRange):boolean} A function that can be
|
||||
* called with a zoom level and a tile range to add loaded tiles to the
|
||||
* lookup.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Layer.prototype.createLoadedTileFinder = function(source, tiles) {
|
||||
/**
|
||||
* @param {number} zoom Zoom level.
|
||||
* @param {ol.TileRange} tileRange Tile range.
|
||||
* @return {boolean} The tile range is fully loaded.
|
||||
*/
|
||||
return function(zoom, tileRange) {
|
||||
return source.forEachLoadedTile(zoom, tileRange, function(tile) {
|
||||
if (!tiles[zoom]) {
|
||||
tiles[zoom] = {};
|
||||
}
|
||||
tiles[zoom][tile.tileCoord.toString()] = tile;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @return {ol.layer.Layer} Layer.
|
||||
|
||||
@@ -94,6 +94,40 @@ ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a function that adds loaded tiles to the tile lookup.
|
||||
* @param {ol.source.Tile} source Tile source.
|
||||
* @param {Object.<number, Object.<string, ol.Tile>>} tiles Lookup of loaded
|
||||
* tiles by zoom level.
|
||||
* @return {function(number, ol.TileRange):boolean} A function that can be
|
||||
* called with a zoom level and a tile range to add loaded tiles to the
|
||||
* lookup.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.createLoadedTileFinder =
|
||||
function(source, tiles) {
|
||||
var mapRenderer = this.mapRenderer;
|
||||
|
||||
/**
|
||||
* @param {number} zoom Zoom level.
|
||||
* @param {ol.TileRange} tileRange Tile range.
|
||||
* @return {boolean} The tile range is fully loaded.
|
||||
*/
|
||||
return function(zoom, tileRange) {
|
||||
return source.forEachLoadedTile(zoom, tileRange, function(tile) {
|
||||
var loaded = mapRenderer.isTileTextureLoaded(tile);
|
||||
if (loaded) {
|
||||
if (!tiles[zoom]) {
|
||||
tiles[zoom] = {};
|
||||
}
|
||||
tiles[zoom][tile.tileCoord.toString()] = tile;
|
||||
}
|
||||
return loaded;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -190,12 +224,8 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
|
||||
var tilesToDrawByZ = {};
|
||||
tilesToDrawByZ[z] = {};
|
||||
|
||||
var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) {
|
||||
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED &&
|
||||
mapRenderer.isTileTextureLoaded(tile);
|
||||
}, tileSource, pixelRatio, projection);
|
||||
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
|
||||
tilesToDrawByZ, getTileIfLoaded);
|
||||
var findLoadedTiles = this.createLoadedTileFinder(
|
||||
tileSource, tilesToDrawByZ);
|
||||
|
||||
var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError();
|
||||
var allTilesLoaded = true;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
goog.provide('ol.source.TileDebug');
|
||||
|
||||
goog.require('ol.Tile');
|
||||
goog.require('ol.TileCache');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileState');
|
||||
goog.require('ol.dom');
|
||||
@@ -89,42 +88,20 @@ ol.source.TileDebug = function(options) {
|
||||
tileGrid: options.tileGrid
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TileCache}
|
||||
*/
|
||||
this.tileCache_ = new ol.TileCache();
|
||||
|
||||
};
|
||||
goog.inherits(ol.source.TileDebug, ol.source.Tile);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.TileDebug.prototype.canExpireCache = function() {
|
||||
return this.tileCache_.canExpireCache();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.TileDebug.prototype.expireCache = function(usedTiles) {
|
||||
this.tileCache_.expireCache(usedTiles);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.TileDebug.prototype.getTile = function(z, x, y) {
|
||||
var tileCoordKey = this.getKeyZXY(z, x, y);
|
||||
if (this.tileCache_.containsKey(tileCoordKey)) {
|
||||
return /** @type {!ol.DebugTile_} */ (this.tileCache_.get(tileCoordKey));
|
||||
if (this.tileCache.containsKey(tileCoordKey)) {
|
||||
return /** @type {!ol.DebugTile_} */ (this.tileCache.get(tileCoordKey));
|
||||
} else {
|
||||
var tile = new ol.DebugTile_([z, x, y], this.tileGrid);
|
||||
this.tileCache_.set(tileCoordKey, tile);
|
||||
this.tileCache.set(tileCoordKey, tile);
|
||||
return tile;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@ goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.ImageTile');
|
||||
goog.require('ol.TileCache');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileLoadFunctionType');
|
||||
goog.require('ol.TileState');
|
||||
@@ -53,12 +52,6 @@ ol.source.TileImage = function(options) {
|
||||
this.crossOrigin =
|
||||
goog.isDef(options.crossOrigin) ? options.crossOrigin : null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.TileCache}
|
||||
*/
|
||||
this.tileCache = new ol.TileCache();
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.TileLoadFunctionType}
|
||||
@@ -87,22 +80,6 @@ ol.source.TileImage.defaultTileLoadFunction = function(imageTile, src) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.TileImage.prototype.canExpireCache = function() {
|
||||
return this.tileCache.canExpireCache();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.TileImage.prototype.expireCache = function(usedTiles) {
|
||||
this.tileCache.expireCache(usedTiles);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,9 @@ goog.require('goog.events.Event');
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.TileCache');
|
||||
goog.require('ol.TileRange');
|
||||
goog.require('ol.TileState');
|
||||
goog.require('ol.source.Source');
|
||||
goog.require('ol.tilecoord');
|
||||
goog.require('ol.tilegrid.TileGrid');
|
||||
@@ -65,6 +67,12 @@ ol.source.Tile = function(options) {
|
||||
*/
|
||||
this.tileGrid = goog.isDef(options.tileGrid) ? options.tileGrid : null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.TileCache}
|
||||
*/
|
||||
this.tileCache = new ol.TileCache();
|
||||
|
||||
};
|
||||
goog.inherits(ol.source.Tile, ol.source.Source);
|
||||
|
||||
@@ -72,51 +80,47 @@ goog.inherits(ol.source.Tile, ol.source.Source);
|
||||
/**
|
||||
* @return {boolean} Can expire cache.
|
||||
*/
|
||||
ol.source.Tile.prototype.canExpireCache = goog.functions.FALSE;
|
||||
ol.source.Tile.prototype.canExpireCache = function() {
|
||||
return this.tileCache.canExpireCache();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object.<string, ol.TileRange>} usedTiles Used tiles.
|
||||
*/
|
||||
ol.source.Tile.prototype.expireCache = goog.abstractMethod;
|
||||
ol.source.Tile.prototype.expireCache = function(usedTiles) {
|
||||
this.tileCache.expireCache(usedTiles);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Look for loaded tiles over a given tile range and zoom level. Adds
|
||||
* properties to the provided lookup representing key/tile pairs for already
|
||||
* loaded tiles.
|
||||
*
|
||||
* @param {Object.<number, Object.<string, ol.Tile>>} loadedTilesByZ A lookup of
|
||||
* loaded tiles by zoom level.
|
||||
* @param {function(number, number, number): 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.
|
||||
* @param {function(ol.Tile):(boolean|undefined)} callback Called with each
|
||||
* loaded tile. If the callback returns `false`, the tile will not be
|
||||
* considered loaded.
|
||||
* @return {boolean} The tile range is fully covered with loaded tiles.
|
||||
*/
|
||||
ol.source.Tile.prototype.findLoadedTiles = function(loadedTilesByZ,
|
||||
getTileIfLoaded, z, tileRange) {
|
||||
// FIXME this could be more efficient about filling partial holes
|
||||
var fullyCovered = true;
|
||||
var tile, tileCoordKey, x, y;
|
||||
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
ol.source.Tile.prototype.forEachLoadedTile = function(z, tileRange, callback) {
|
||||
var covered = true;
|
||||
var tile, tileCoordKey, loaded;
|
||||
for (var x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (var y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
tileCoordKey = this.getKeyZXY(z, x, y);
|
||||
if (loadedTilesByZ[z] && loadedTilesByZ[z][tileCoordKey]) {
|
||||
continue;
|
||||
}
|
||||
tile = getTileIfLoaded(z, x, y);
|
||||
if (!goog.isNull(tile)) {
|
||||
if (!loadedTilesByZ[z]) {
|
||||
loadedTilesByZ[z] = {};
|
||||
loaded = false;
|
||||
if (this.tileCache.containsKey(tileCoordKey)) {
|
||||
tile = /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey));
|
||||
loaded = tile.getState() === ol.TileState.LOADED;
|
||||
if (loaded) {
|
||||
loaded = (callback(tile) !== false);
|
||||
}
|
||||
loadedTilesByZ[z][tileCoordKey] = tile;
|
||||
} else {
|
||||
fullyCovered = false;
|
||||
}
|
||||
if (!loaded) {
|
||||
covered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fullyCovered;
|
||||
return covered;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ goog.require('goog.events.EventType');
|
||||
goog.require('goog.net.Jsonp');
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.Tile');
|
||||
goog.require('ol.TileCache');
|
||||
goog.require('ol.TileState');
|
||||
goog.require('ol.TileUrlFunction');
|
||||
goog.require('ol.extent');
|
||||
@@ -46,12 +45,6 @@ ol.source.TileUTFGrid = function(options) {
|
||||
*/
|
||||
this.tileUrlFunction_ = ol.TileUrlFunction.nullTileUrlFunction;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!ol.TileCache}
|
||||
*/
|
||||
this.tileCache_ = new ol.TileCache();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string|undefined}
|
||||
@@ -64,22 +57,6 @@ ol.source.TileUTFGrid = function(options) {
|
||||
goog.inherits(ol.source.TileUTFGrid, ol.source.Tile);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.TileUTFGrid.prototype.canExpireCache = function() {
|
||||
return this.tileCache_.canExpireCache();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.TileUTFGrid.prototype.expireCache = function(usedTiles) {
|
||||
this.tileCache_.expireCache(usedTiles);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string|undefined} The template from TileJSON.
|
||||
* @api
|
||||
@@ -195,8 +172,8 @@ ol.source.TileUTFGrid.prototype.handleTileJSONResponse = function(tileJSON) {
|
||||
ol.source.TileUTFGrid.prototype.getTile =
|
||||
function(z, x, y, pixelRatio, projection) {
|
||||
var tileCoordKey = this.getKeyZXY(z, x, y);
|
||||
if (this.tileCache_.containsKey(tileCoordKey)) {
|
||||
return /** @type {!ol.Tile} */ (this.tileCache_.get(tileCoordKey));
|
||||
if (this.tileCache.containsKey(tileCoordKey)) {
|
||||
return /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey));
|
||||
} else {
|
||||
goog.asserts.assert(projection);
|
||||
var tileCoord = [z, x, y];
|
||||
@@ -207,7 +184,7 @@ ol.source.TileUTFGrid.prototype.getTile =
|
||||
goog.isDef(tileUrl) ? tileUrl : '',
|
||||
this.tileGrid.getTileCoordExtent(tileCoord),
|
||||
this.preemptive_);
|
||||
this.tileCache_.set(tileCoordKey, tile);
|
||||
this.tileCache.set(tileCoordKey, tile);
|
||||
return tile;
|
||||
}
|
||||
};
|
||||
@@ -218,8 +195,8 @@ ol.source.TileUTFGrid.prototype.getTile =
|
||||
*/
|
||||
ol.source.TileUTFGrid.prototype.useTile = function(z, x, y) {
|
||||
var tileCoordKey = this.getKeyZXY(z, x, y);
|
||||
if (this.tileCache_.containsKey(tileCoordKey)) {
|
||||
this.tileCache_.get(tileCoordKey);
|
||||
if (this.tileCache.containsKey(tileCoordKey)) {
|
||||
this.tileCache.get(tileCoordKey);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user