All files / engine/Source/Core sampleTerrainMostDetailed.js

97.56% Statements 40/41
90% Branches 18/20
100% Functions 2/2
97.43% Lines 38/39

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133          1x                                                                       9x 6x     9x 1x   8x 1x       7x 7x   7x     7x 1x           6x 6x 10x 10x 10x 10x       2x         2x         2x         10x 10x 6x   10x     6x 6x   6x 6x                 5x 5x 9x 9x   9x   4x       5x 2x             5x      
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.
 * @param {boolean} [rejectOnTileFail=false] If true, for a failed terrain tile request the promise will be rejected. If false, returned heights will be undefined.
 * @returns {Promise<Cartographic[]>} 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 = await Cesium.createWorldTerrainAsync();
 * const positions = [
 *     Cesium.Cartographic.fromDegrees(86.925145, 27.988257),
 *     Cesium.Cartographic.fromDegrees(87.0, 28.0)
 * ];
 * const updatedPositions = await Cesium.sampleTerrainMostDetailed(terrainProvider, positions);
 * // positions[0].height and positions[1].height have been updated.
 * // updatedPositions is just a reference to positions.
 *
 * // To handle tile errors, pass true for the rejectOnTileFail parameter.
 * try {
 *    const updatedPositions = await Cesium.sampleTerrainMostDetailed(terrainProvider, positions, true);
 * } catch (error) {
 *   // A tile request error occurred.
 * }
 */
async function sampleTerrainMostDetailed(
  terrainProvider,
  positions,
  rejectOnTileFail,
) {
  if (!defined(rejectOnTileFail)) {
    rejectOnTileFail = false;
  }
  //>>includeStart('debug', pragmas.debug);
  if (!defined(terrainProvider)) {
    throw new DeveloperError("terrainProvider is required.");
  }
  if (!defined(positions)) {
    throw new DeveloperError("positions is required.");
  }
  //>>includeEnd('debug');
 
  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,
      );
      Iif (defined(promise)) {
        promises.push(promise);
      }
    }
 
    let atLevel = byLevel[maxLevel];
    if (!defined(atLevel)) {
      byLevel[maxLevel] = atLevel = [];
    }
    atLevel.push(position);
  }
 
  await Promise.all(promises);
  await Promise.all(
    byLevel.map(function (positionsAtLevel, index) {
      Eif (defined(positionsAtLevel)) {
        return sampleTerrain(
          terrainProvider,
          index,
          positionsAtLevel,
          rejectOnTileFail,
        );
      }
    }),
  );
  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) {
    await sampleTerrainMostDetailed(
      terrainProvider,
      changedPositions,
      rejectOnTileFail,
    );
  }
 
  return positions;
}
export default sampleTerrainMostDetailed;