Merge pull request #9778 from ahocevar/faster-getsourcetiles

Return existing source tiles if at target resolution
This commit is contained in:
Andreas Hocevar
2019-07-19 16:55:25 +02:00
committed by GitHub

View File

@@ -179,99 +179,101 @@ class VectorTile extends UrlTile {
* @return {Array<import("../VectorTile").default>} Tile keys. * @return {Array<import("../VectorTile").default>} Tile keys.
*/ */
getSourceTiles(pixelRatio, projection, tile) { getSourceTiles(pixelRatio, projection, tile) {
const sourceTiles = [];
const urlTileCoord = tile.wrappedTileCoord; const urlTileCoord = tile.wrappedTileCoord;
if (urlTileCoord) { const tileGrid = this.getTileGridForProjection(projection);
const tileGrid = this.getTileGridForProjection(projection); const extent = tileGrid.getTileCoordExtent(urlTileCoord);
const extent = tileGrid.getTileCoordExtent(urlTileCoord); const z = urlTileCoord[0];
const z = urlTileCoord[0]; const resolution = tileGrid.getResolution(z);
const resolution = tileGrid.getResolution(z); // make extent 1 pixel smaller so we don't load tiles for < 0.5 pixel render space
// make extent 1 pixel smaller so we don't load tiles for < 0.5 pixel render space bufferExtent(extent, -1 / resolution, extent);
bufferExtent(extent, -1 / resolution, extent); const sourceTileGrid = this.tileGrid;
const sourceTileGrid = this.tileGrid; const sourceExtent = sourceTileGrid.getExtent();
const sourceExtent = sourceTileGrid.getExtent(); if (sourceExtent) {
if (sourceExtent) { getIntersection(extent, sourceExtent, extent);
getIntersection(extent, sourceExtent, extent); }
} const sourceZ = sourceTileGrid.getZForResolution(resolution, 1);
const sourceZ = sourceTileGrid.getZForResolution(resolution, 1); const minZoom = sourceTileGrid.getMinZoom();
const minZoom = sourceTileGrid.getMinZoom();
let loadedZ = sourceZ + 1; const previousSourceTiles = this.sourceTilesByTileKey_[getKey(tile.tileCoord)];
let covered, empty; if (previousSourceTiles && previousSourceTiles.length > 0 && previousSourceTiles[0].tileCoord[0] === sourceZ) {
do { return previousSourceTiles;
--loadedZ; }
covered = true;
empty = true; const sourceTiles = [];
sourceTileGrid.forEachTileCoord(extent, loadedZ, function(sourceTileCoord) { let loadedZ = sourceZ + 1;
const tileKey = getKey(sourceTileCoord); let covered, empty;
let sourceTile; do {
if (tileKey in this.sourceTiles_) { --loadedZ;
sourceTile = this.sourceTiles_[tileKey]; covered = true;
const state = sourceTile.getState(); empty = true;
if (state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) { sourceTileGrid.forEachTileCoord(extent, loadedZ, function(sourceTileCoord) {
empty = empty && state === TileState.EMPTY; const tileKey = getKey(sourceTileCoord);
sourceTiles.push(sourceTile); let sourceTile;
return; if (tileKey in this.sourceTiles_) {
} sourceTile = this.sourceTiles_[tileKey];
} else if (loadedZ === sourceZ) { const state = sourceTile.getState();
const tileUrl = this.tileUrlFunction(sourceTileCoord, pixelRatio, projection); if (state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) {
if (tileUrl !== undefined) { empty = empty && state === TileState.EMPTY;
sourceTile = new this.tileClass(sourceTileCoord, TileState.IDLE, tileUrl, sourceTiles.push(sourceTile);
this.format_, this.tileLoadFunction);
sourceTile.extent = sourceTileGrid.getTileCoordExtent(sourceTileCoord);
sourceTile.projection = projection;
sourceTile.resolution = sourceTileGrid.getResolution(sourceTileCoord[0]);
this.sourceTiles_[tileKey] = sourceTile;
empty = false;
listen(sourceTile, EventType.CHANGE, this.handleTileChange, this);
sourceTile.load();
}
} else {
empty = false;
}
covered = false;
if (!sourceTile) {
return; return;
} }
if (sourceTile.getState() !== TileState.EMPTY && tile.getState() === TileState.IDLE) { } else if (loadedZ === sourceZ) {
tile.loadingSourceTiles++; const tileUrl = this.tileUrlFunction(sourceTileCoord, pixelRatio, projection);
const key = listen(sourceTile, EventType.CHANGE, function() { if (tileUrl !== undefined) {
const state = sourceTile.getState(); sourceTile = new this.tileClass(sourceTileCoord, TileState.IDLE, tileUrl,
const sourceTileKey = getKey(sourceTile.tileCoord); this.format_, this.tileLoadFunction);
if (state === TileState.LOADED || state === TileState.ERROR) { sourceTile.extent = sourceTileGrid.getTileCoordExtent(sourceTileCoord);
if (state === TileState.LOADED) { sourceTile.projection = projection;
unlistenByKey(key); sourceTile.resolution = sourceTileGrid.getResolution(sourceTileCoord[0]);
tile.loadingSourceTiles--; this.sourceTiles_[tileKey] = sourceTile;
delete tile.errorSourceTileKeys[sourceTileKey]; empty = false;
} else if (state === TileState.ERROR) { listen(sourceTile, EventType.CHANGE, this.handleTileChange, this);
tile.errorSourceTileKeys[sourceTileKey] = true; sourceTile.load();
}
if (tile.loadingSourceTiles - Object.keys(tile.errorSourceTileKeys).length === 0) {
tile.hifi = true;
tile.sourceZ = sourceZ;
tile.setState(isEmpty(tile.errorSourceTileKeys) ? TileState.LOADED : TileState.ERROR);
}
}
});
} }
}.bind(this)); } else {
if (!covered) { empty = false;
sourceTiles.length = 0;
} }
} while (!covered && loadedZ > minZoom); covered = false;
if (!empty && tile.getState() === TileState.IDLE) { if (!sourceTile) {
tile.setState(TileState.LOADING); return;
}
if (sourceTile.getState() !== TileState.EMPTY && tile.getState() === TileState.IDLE) {
tile.loadingSourceTiles++;
const key = listen(sourceTile, EventType.CHANGE, function() {
const state = sourceTile.getState();
const sourceTileKey = getKey(sourceTile.tileCoord);
if (state === TileState.LOADED || state === TileState.ERROR) {
if (state === TileState.LOADED) {
unlistenByKey(key);
tile.loadingSourceTiles--;
delete tile.errorSourceTileKeys[sourceTileKey];
} else if (state === TileState.ERROR) {
tile.errorSourceTileKeys[sourceTileKey] = true;
}
if (tile.loadingSourceTiles - Object.keys(tile.errorSourceTileKeys).length === 0) {
tile.hifi = true;
tile.sourceZ = sourceZ;
tile.setState(isEmpty(tile.errorSourceTileKeys) ? TileState.LOADED : TileState.ERROR);
}
}
});
}
}.bind(this));
if (!covered) {
sourceTiles.length = 0;
} }
if (covered || empty) { } while (!covered && loadedZ > minZoom);
tile.hifi = sourceZ === loadedZ; if (!empty && tile.getState() === TileState.IDLE) {
tile.sourceZ = loadedZ; tile.setState(TileState.LOADING);
const previousSourceTiles = this.sourceTilesByTileKey_[getKey(tile.tileCoord)]; }
if (tile.getState() < TileState.LOADED) { if (covered || empty) {
tile.setState(empty ? TileState.EMPTY : TileState.LOADED); tile.hifi = sourceZ === loadedZ;
} else if (!previousSourceTiles || !equals(sourceTiles, previousSourceTiles)) { tile.sourceZ = loadedZ;
this.removeSourceTiles(tile); if (tile.getState() < TileState.LOADED) {
this.addSourceTiles(tile, sourceTiles); tile.setState(empty ? TileState.EMPTY : TileState.LOADED);
} } else if (!previousSourceTiles || !equals(sourceTiles, previousSourceTiles)) {
this.removeSourceTiles(tile);
this.addSourceTiles(tile, sourceTiles);
} }
} }
return sourceTiles; return sourceTiles;