itowns
Version:
A JS/WebGL framework for 3D geospatial data visualization
80 lines (77 loc) • 3.26 kB
JavaScript
import { EMPTY_TEXTURE_ZOOM } from "../Renderer/RasterTile.js";
/**
* This modules implements various layer update strategies.
*
* Default strategy is STRATEGY_MIN_NETWORK_TRAFFIC which aims
* to reduce the amount of network traffic.
*/
export const STRATEGY_MIN_NETWORK_TRAFFIC = 0;
export const STRATEGY_GROUP = 1;
export const STRATEGY_PROGRESSIVE = 2;
export const STRATEGY_DICHOTOMY = 3;
function _minimizeNetworkTraffic(node, nodeLevel, currentLevel, source) {
// TO DO source.isVectorTileSource is a temp fix for pendingSubdivision.
// see issue https://github.com/iTowns/itowns/issues/2214
if (node.pendingSubdivision && !source.isVectorTileSource) {
return currentLevel;
}
return nodeLevel;
}
// Maps nodeLevel to groups defined in layer's options
// eg with groups = [3, 7, 12]:
// * nodeLevel = 2 -> 3
// * nodeLevel = 4 -> 3
// * nodeLevel = 7 -> 7
// * nodeLevel = 15 -> 12
function _group(nodeLevel, options) {
const f = options.groups.filter(val => val <= nodeLevel);
return f.length ? f[f.length - 1] : options.groups[0];
}
function _progressive(nodeLevel, currentLevel, options) {
return Math.min(nodeLevel, currentLevel + (options.increment || 1));
}
// Load textures at mid-point between current level and node's level.
// This produces smoother transitions and a single fetch updates multiple
// tiles thanks to caching.
function _dichotomy(nodeLevel, currentLevel) {
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
if (currentLevel == EMPTY_TEXTURE_ZOOM) {
return options.zoom ? options.zoom.min : 0;
}
return Math.min(nodeLevel, Math.ceil((currentLevel + nodeLevel) / 2));
}
export function chooseNextLevelToFetch(strategy, node) {
let nodeLevel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : node.level;
let currentLevel = arguments.length > 3 ? arguments[3] : undefined;
let layer = arguments.length > 4 ? arguments[4] : undefined;
let failureParams = arguments.length > 5 ? arguments[5] : undefined;
let nextLevelToFetch;
const maxZoom = layer.source.zoom ? layer.source.zoom.max : Infinity;
if (failureParams.lowestLevelError != Infinity) {
nextLevelToFetch = _dichotomy(failureParams.lowestLevelError, currentLevel, layer.source);
nextLevelToFetch = failureParams.lowestLevelError == nextLevelToFetch ? nextLevelToFetch - 1 : nextLevelToFetch;
if (strategy == STRATEGY_GROUP) {
nextLevelToFetch = _group(nextLevelToFetch, layer.updateStrategy.options);
}
} else {
switch (strategy) {
case STRATEGY_GROUP:
nextLevelToFetch = _group(nodeLevel, layer.updateStrategy.options);
break;
case STRATEGY_PROGRESSIVE:
{
nextLevelToFetch = _progressive(nodeLevel, currentLevel, layer.updateStrategy.options);
break;
}
case STRATEGY_DICHOTOMY:
nextLevelToFetch = _dichotomy(nodeLevel, currentLevel, layer.source);
break;
// default strategy
case STRATEGY_MIN_NETWORK_TRAFFIC:
default:
nextLevelToFetch = _minimizeNetworkTraffic(node, nodeLevel, currentLevel, layer.source);
}
nextLevelToFetch = Math.min(nextLevelToFetch, maxZoom);
}
return nextLevelToFetch;
}