UNPKG

itowns

Version:

A JS/WebGL framework for 3D geospatial data visualization

274 lines (215 loc) 9.91 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.updateLayeredMaterialNodeImagery = updateLayeredMaterialNodeImagery; exports.updateLayeredMaterialNodeElevation = updateLayeredMaterialNodeElevation; exports.removeLayeredMaterialNodeLayer = removeLayeredMaterialNodeLayer; exports.SIZE_DIAGONAL_TEXTURE = exports.SIZE_TEXTURE_TILE = void 0; var _LayerUpdateStrategy = require("../Layer/LayerUpdateStrategy"); var _LayerUpdateState = _interopRequireDefault(require("../Layer/LayerUpdateState")); var _handlerNodeError = _interopRequireDefault(require("./handlerNodeError")); var SIZE_TEXTURE_TILE = 256; exports.SIZE_TEXTURE_TILE = SIZE_TEXTURE_TILE; var SIZE_DIAGONAL_TEXTURE = Math.pow(2 * (SIZE_TEXTURE_TILE * SIZE_TEXTURE_TILE), 0.5); exports.SIZE_DIAGONAL_TEXTURE = SIZE_DIAGONAL_TEXTURE; function materialCommandQueuePriorityFunction(material) { // We know that 'node' is visible because commands can only be // issued for visible nodes. // TODO: need priorization of displayed nodes // Then prefer displayed node over non-displayed one return material.visible ? 100 : 10; } function refinementCommandCancellationFn(cmd) { if (!cmd.requester.parent || !cmd.requester.material) { return true; } // Cancel the command if the tile already has a better texture. // This is only needed for elevation layers, because we may have several // concurrent layers but we can only use one texture. if (cmd.layer.isElevationLayer && cmd.requester.material.getElevationLayer() && cmd.targetLevel <= cmd.requester.material.getElevationLayer().level) { return true; } // Cancel the command if the layer was removed between command scheduling and command execution if (!cmd.requester.layerUpdateState[cmd.layer.id] || !cmd.layer.source._featuresCaches[cmd.layer.crs]) { return true; } return !cmd.requester.material.visible; } function buildCommand(view, layer, extentsSource, extentsDestination, requester) { return { view: view, layer: layer, extentsSource: extentsSource, extentsDestination: extentsDestination, requester: requester, priority: materialCommandQueuePriorityFunction(requester.material), earlyDropFunction: refinementCommandCancellationFn }; } function updateLayeredMaterialNodeImagery(context, layer, node, parent) { var material = node.material; if (!parent || !material) { return; } var extentsDestination = node.getExtentsByProjection(layer.crs); var zoom = extentsDestination[0].zoom; if (zoom > layer.zoom.max || zoom < layer.zoom.min) { return; } var nodeLayer = material.getLayer(layer.id); // Initialisation if (node.layerUpdateState[layer.id] === undefined) { node.layerUpdateState[layer.id] = new _LayerUpdateState["default"](); if (!layer.source.extentInsideLimit(node.extent, zoom)) { // we also need to check that tile's parent doesn't have a texture for this layer, // because even if this tile is outside of the layer, it could inherit it's // parent texture if (!(!layer.noTextureParentOutsideLimit && parent.material && parent.material.getLayer && parent.material.getLayer(layer.id))) { node.layerUpdateState[layer.id].noMoreUpdatePossible(); return; } } if (!nodeLayer) { // Create new raster node nodeLayer = layer.setupRasterNode(node); // Init the node by parent var parentLayer = parent.material && parent.material.getLayer(layer.id); nodeLayer.initFromParent(parentLayer, extentsDestination); } // Proposed new process, two separate processes: // * FIRST PASS: initNodeXXXFromParent and get out of the function // * SECOND PASS: Fetch best texture // The two-step allows you to filter out unnecessary requests // Indeed in the second pass, their state (not visible or not displayed) can block them to fetch if (nodeLayer.level >= layer.source.zoom.min) { context.view.notifyChange(node, false); return; } } // Node is hidden, no need to update it if (!material.visible) { return; } // An update is pending / or impossible -> abort if (!layer.visible || !node.layerUpdateState[layer.id].canTryUpdate()) { return; } if (nodeLayer.level >= extentsDestination[0].zoom) { // default decision method node.layerUpdateState[layer.id].noMoreUpdatePossible(); return; } // is fetching data from this layer disabled? if (layer.frozen) { return; } var failureParams = node.layerUpdateState[layer.id].failureParams; var destinationLevel = extentsDestination[0].zoom || node.level; var targetLevel = (0, _LayerUpdateStrategy.chooseNextLevelToFetch)(layer.updateStrategy.type, node, destinationLevel, nodeLayer.level, layer, failureParams); if (!layer.source.isVectorSource && targetLevel <= nodeLayer.level || targetLevel > destinationLevel) { if (failureParams.lowestLevelError != Infinity) { // this is the highest level found in case of error. node.layerUpdateState[layer.id].noMoreUpdatePossible(); } return; } else if (!layer.source.extentInsideLimit(node.extent, targetLevel)) { node.layerUpdateState[layer.id].noData({ targetLevel: targetLevel }); context.view.notifyChange(node, false); return; } var extentsSource = extentsDestination.map(function (e) { return e.tiledExtentParent(targetLevel); }); node.layerUpdateState[layer.id].newTry(); var command = buildCommand(context.view, layer, extentsSource, extentsDestination, node); return context.scheduler.execute(command).then(function (result) { // Does nothing if the layer has been removed while command was being or waiting to be executed if (!node.layerUpdateState[layer.id]) { return; } // TODO: Handle error : result is undefined in provider. throw error var pitchs = extentsDestination.map(function (ext, i) { return ext.offsetToParent(result[i].extent, nodeLayer.offsetScales[i]); }); nodeLayer.setTextures(result, pitchs); node.layerUpdateState[layer.id].success(); }, function (err) { return (0, _handlerNodeError["default"])(err, node, layer, targetLevel, context.view); }); } function updateLayeredMaterialNodeElevation(context, layer, node, parent) { var material = node.material; if (!parent || !material) { return; } // TODO: we need either // - compound or exclusive layers // - support for multiple elevation layers // Elevation is currently handled differently from color layers. // This is caused by a LayeredMaterial limitation: only 1 elevation texture // can be used (where a tile can have N textures x M layers) var extentsDestination = node.getExtentsByProjection(layer.crs); var zoom = extentsDestination[0].zoom; if (zoom > layer.zoom.max || zoom < layer.zoom.min) { return; } // Init elevation layer, and inherit from parent if possible var nodeLayer = material.getElevationLayer(); if (!nodeLayer) { nodeLayer = layer.setupRasterNode(node); } if (node.layerUpdateState[layer.id] === undefined) { node.layerUpdateState[layer.id] = new _LayerUpdateState["default"](); var parentLayer = parent.material && parent.material.getLayer(layer.id); nodeLayer.initFromParent(parentLayer, extentsDestination); if (nodeLayer.level >= layer.source.zoom.min) { context.view.notifyChange(node, false); return; } } // Possible conditions to *not* update the elevation texture if (layer.frozen || !material.visible || !node.layerUpdateState[layer.id].canTryUpdate()) { return; } var failureParams = node.layerUpdateState[layer.id].failureParams; var targetLevel = (0, _LayerUpdateStrategy.chooseNextLevelToFetch)(layer.updateStrategy.type, node, extentsDestination[0].zoom, nodeLayer.level, layer, failureParams); if (targetLevel <= nodeLayer.level || targetLevel > extentsDestination[0].zoom) { node.layerUpdateState[layer.id].noMoreUpdatePossible(); return; } else if (!layer.source.extentInsideLimit(node.extent, targetLevel)) { node.layerUpdateState[layer.id].noData({ targetLevel: targetLevel }); context.view.notifyChange(node, false); return; } var extentsSource = extentsDestination.map(function (e) { return e.tiledExtentParent(targetLevel); }); node.layerUpdateState[layer.id].newTry(); var command = buildCommand(context.view, layer, extentsSource, extentsDestination, node); return context.scheduler.execute(command).then(function (result) { // Does nothing if the layer has been removed while command was being or waiting to be executed if (!node.layerUpdateState[layer.id]) { return; } // Do not apply the new texture if its level is < than the current // one. This is only needed for elevation layers, because we may // have several concurrent layers but we can only use one texture. if (targetLevel <= nodeLayer.level) { node.layerUpdateState[layer.id].noMoreUpdatePossible(); return; } var pitchs = extentsDestination.map(function (ext, i) { return ext.offsetToParent(result[i].extent, nodeLayer.offsetScales[i]); }); nodeLayer.setTextures(result, pitchs); node.layerUpdateState[layer.id].success(); }, function (err) { return (0, _handlerNodeError["default"])(err, node, layer, targetLevel, context.view); }); } function removeLayeredMaterialNodeLayer(layerId) { return function (node) { if (node.material && node.material.removeLayer) { node.material.removeLayer(layerId); if (node.material.elevationLayerIds[0] == layerId) { node.setBBoxZ(0, 0); } } if (node.layerUpdateState && node.layerUpdateState[layerId]) { delete node.layerUpdateState[layerId]; } }; }