import Cartesian2 from "./Cartesian2.js"; import defined from "./defined.js"; import DeveloperError from "./DeveloperError.js"; import sampleTerrain from "./sampleTerrain.js"; const scratchCartesian2 = new Cartesian2(); /** * Initiates a sampleTerrain() request at the maximum available tile level for a terrain dataset. * * @function sampleTerrainMostDetailed * * @param {TerrainProvider} terrainProvider The terrain provider from which to query heights. * @param {Cartographic[]} positions The positions to update with terrain heights. * @returns {Promise.} A promise that resolves to the provided list of positions when terrain the query has completed. This * promise will reject if the terrain provider's `availability` property is undefined. * * @example * // Query the terrain height of two Cartographic positions * const terrainProvider = Cesium.createWorldTerrain(); * const positions = [ * Cesium.Cartographic.fromDegrees(86.925145, 27.988257), * Cesium.Cartographic.fromDegrees(87.0, 28.0) * ]; * const promise = Cesium.sampleTerrainMostDetailed(terrainProvider, positions); * Promise.resolve(promise).then(function(updatedPositions) { * // positions[0].height and positions[1].height have been updated. * // updatedPositions is just a reference to positions. * }); */ function sampleTerrainMostDetailed(terrainProvider, positions) { //>>includeStart('debug', pragmas.debug); if (!defined(terrainProvider)) { throw new DeveloperError("terrainProvider is required."); } if (!defined(positions)) { throw new DeveloperError("positions is required."); } //>>includeEnd('debug'); return terrainProvider.readyPromise.then(function () { const byLevel = []; const maxLevels = []; const availability = terrainProvider.availability; //>>includeStart('debug', pragmas.debug); if (!defined(availability)) { throw new DeveloperError( "sampleTerrainMostDetailed requires a terrain provider that has tile availability." ); } //>>includeEnd('debug'); const promises = []; for (let i = 0; i < positions.length; ++i) { const position = positions[i]; const maxLevel = availability.computeMaximumLevelAtPosition(position); maxLevels[i] = maxLevel; if (maxLevel === 0) { // This is a special case where we have a parent terrain and we are requesting // heights from an area that isn't covered by the top level terrain at all. // This will essentially trigger the loading of the parent terrains root tile terrainProvider.tilingScheme.positionToTileXY( position, 1, scratchCartesian2 ); const promise = terrainProvider.loadTileDataAvailability( scratchCartesian2.x, scratchCartesian2.y, 1 ); if (defined(promise)) { promises.push(promise); } } let atLevel = byLevel[maxLevel]; if (!defined(atLevel)) { byLevel[maxLevel] = atLevel = []; } atLevel.push(position); } return Promise.all(promises) .then(function () { return Promise.all( byLevel.map(function (positionsAtLevel, index) { if (defined(positionsAtLevel)) { return sampleTerrain(terrainProvider, index, positionsAtLevel); } }) ); }) .then(function () { const changedPositions = []; for (let i = 0; i < positions.length; ++i) { const position = positions[i]; const maxLevel = availability.computeMaximumLevelAtPosition(position); if (maxLevel !== maxLevels[i]) { // Now that we loaded the max availability, a higher level has become available changedPositions.push(position); } } if (changedPositions.length > 0) { return sampleTerrainMostDetailed(terrainProvider, changedPositions); } }) .then(function () { return positions; }); }); } export default sampleTerrainMostDetailed;