| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 | import defined from "./defined.js";import DeveloperError from "./DeveloperError.js";import IndexDatatype from "./IndexDatatype.js";import CesiumMath from "./Math.js";/** * Provides terrain or other geometry for the surface of an ellipsoid.  The surface geometry is * organized into a pyramid of tiles according to a {@link TilingScheme}.  This type describes an * interface and is not intended to be instantiated directly. * * @alias TerrainProvider * @constructor * * @see EllipsoidTerrainProvider * @see CesiumTerrainProvider * @see VRTheWorldTerrainProvider * @see GoogleEarthEnterpriseTerrainProvider */function TerrainProvider() {  DeveloperError.throwInstantiationError();}Object.defineProperties(TerrainProvider.prototype, {  /**   * Gets an event that is raised when the terrain provider encounters an asynchronous error..  By subscribing   * to the event, you will be notified of the error and can potentially recover from it.  Event listeners   * are passed an instance of {@link TileProviderError}.   * @memberof TerrainProvider.prototype   * @type {Event<TerrainProvider.ErrorEvent>}   * @readonly   */  errorEvent: {    get: DeveloperError.throwInstantiationError,  },  /**   * Gets the credit to display when this terrain provider is active.  Typically this is used to credit   * the source of the terrain. This function should   * not be called before {@link TerrainProvider#ready} returns true.   * @memberof TerrainProvider.prototype   * @type {Credit}   * @readonly   */  credit: {    get: DeveloperError.throwInstantiationError,  },  /**   * Gets the tiling scheme used by the provider.  This function should   * not be called before {@link TerrainProvider#ready} returns true.   * @memberof TerrainProvider.prototype   * @type {TilingScheme}   * @readonly   */  tilingScheme: {    get: DeveloperError.throwInstantiationError,  },  /**   * Gets a value indicating whether or not the provider is ready for use.   * @memberof TerrainProvider.prototype   * @type {Boolean}   * @readonly   */  ready: {    get: DeveloperError.throwInstantiationError,  },  /**   * Gets a promise that resolves to true when the provider is ready for use.   * @memberof TerrainProvider.prototype   * @type {Promise.<Boolean>}   * @readonly   */  readyPromise: {    get: DeveloperError.throwInstantiationError,  },  /**   * Gets a value indicating whether or not the provider includes a water mask.  The water mask   * indicates which areas of the globe are water rather than land, so they can be rendered   * as a reflective surface with animated waves.  This function should not be   * called before {@link TerrainProvider#ready} returns true.   * @memberof TerrainProvider.prototype   * @type {Boolean}   * @readonly   */  hasWaterMask: {    get: DeveloperError.throwInstantiationError,  },  /**   * Gets a value indicating whether or not the requested tiles include vertex normals.   * This function should not be called before {@link TerrainProvider#ready} returns true.   * @memberof TerrainProvider.prototype   * @type {Boolean}   * @readonly   */  hasVertexNormals: {    get: DeveloperError.throwInstantiationError,  },  /**   * Gets an object that can be used to determine availability of terrain from this provider, such as   * at points and in rectangles.  This function should not be called before   * {@link TerrainProvider#ready} returns true.  This property may be undefined if availability   * information is not available.   * @memberof TerrainProvider.prototype   * @type {TileAvailability}   * @readonly   */  availability: {    get: DeveloperError.throwInstantiationError,  },});const regularGridIndicesCache = [];/** * Gets a list of indices for a triangle mesh representing a regular grid.  Calling * this function multiple times with the same grid width and height returns the * same list of indices.  The total number of vertices must be less than or equal * to 65536. * * @param {Number} width The number of vertices in the regular grid in the horizontal direction. * @param {Number} height The number of vertices in the regular grid in the vertical direction. * @returns {Uint16Array|Uint32Array} The list of indices. Uint16Array gets returned for 64KB or less and Uint32Array for 4GB or less. */TerrainProvider.getRegularGridIndices = function (width, height) {  //>>includeStart('debug', pragmas.debug);  if (width * height >= CesiumMath.FOUR_GIGABYTES) {    throw new DeveloperError(      "The total number of vertices (width * height) must be less than 4,294,967,296."    );  }  //>>includeEnd('debug');  let byWidth = regularGridIndicesCache[width];  if (!defined(byWidth)) {    regularGridIndicesCache[width] = byWidth = [];  }  let indices = byWidth[height];  if (!defined(indices)) {    if (width * height < CesiumMath.SIXTY_FOUR_KILOBYTES) {      indices = byWidth[height] = new Uint16Array(        (width - 1) * (height - 1) * 6      );    } else {      indices = byWidth[height] = new Uint32Array(        (width - 1) * (height - 1) * 6      );    }    addRegularGridIndices(width, height, indices, 0);  }  return indices;};const regularGridAndEdgeIndicesCache = [];/** * @private */TerrainProvider.getRegularGridIndicesAndEdgeIndices = function (width, height) {  //>>includeStart('debug', pragmas.debug);  if (width * height >= CesiumMath.FOUR_GIGABYTES) {    throw new DeveloperError(      "The total number of vertices (width * height) must be less than 4,294,967,296."    );  }  //>>includeEnd('debug');  let byWidth = regularGridAndEdgeIndicesCache[width];  if (!defined(byWidth)) {    regularGridAndEdgeIndicesCache[width] = byWidth = [];  }  let indicesAndEdges = byWidth[height];  if (!defined(indicesAndEdges)) {    const indices = TerrainProvider.getRegularGridIndices(width, height);    const edgeIndices = getEdgeIndices(width, height);    const westIndicesSouthToNorth = edgeIndices.westIndicesSouthToNorth;    const southIndicesEastToWest = edgeIndices.southIndicesEastToWest;    const eastIndicesNorthToSouth = edgeIndices.eastIndicesNorthToSouth;    const northIndicesWestToEast = edgeIndices.northIndicesWestToEast;    indicesAndEdges = byWidth[height] = {      indices: indices,      westIndicesSouthToNorth: westIndicesSouthToNorth,      southIndicesEastToWest: southIndicesEastToWest,      eastIndicesNorthToSouth: eastIndicesNorthToSouth,      northIndicesWestToEast: northIndicesWestToEast,    };  }  return indicesAndEdges;};const regularGridAndSkirtAndEdgeIndicesCache = [];/** * @private */TerrainProvider.getRegularGridAndSkirtIndicesAndEdgeIndices = function (  width,  height) {  //>>includeStart('debug', pragmas.debug);  if (width * height >= CesiumMath.FOUR_GIGABYTES) {    throw new DeveloperError(      "The total number of vertices (width * height) must be less than 4,294,967,296."    );  }  //>>includeEnd('debug');  let byWidth = regularGridAndSkirtAndEdgeIndicesCache[width];  if (!defined(byWidth)) {    regularGridAndSkirtAndEdgeIndicesCache[width] = byWidth = [];  }  let indicesAndEdges = byWidth[height];  if (!defined(indicesAndEdges)) {    const gridVertexCount = width * height;    const gridIndexCount = (width - 1) * (height - 1) * 6;    const edgeVertexCount = width * 2 + height * 2;    const edgeIndexCount = Math.max(0, edgeVertexCount - 4) * 6;    const vertexCount = gridVertexCount + edgeVertexCount;    const indexCount = gridIndexCount + edgeIndexCount;    const edgeIndices = getEdgeIndices(width, height);    const westIndicesSouthToNorth = edgeIndices.westIndicesSouthToNorth;    const southIndicesEastToWest = edgeIndices.southIndicesEastToWest;    const eastIndicesNorthToSouth = edgeIndices.eastIndicesNorthToSouth;    const northIndicesWestToEast = edgeIndices.northIndicesWestToEast;    const indices = IndexDatatype.createTypedArray(vertexCount, indexCount);    addRegularGridIndices(width, height, indices, 0);    TerrainProvider.addSkirtIndices(      westIndicesSouthToNorth,      southIndicesEastToWest,      eastIndicesNorthToSouth,      northIndicesWestToEast,      gridVertexCount,      indices,      gridIndexCount    );    indicesAndEdges = byWidth[height] = {      indices: indices,      westIndicesSouthToNorth: westIndicesSouthToNorth,      southIndicesEastToWest: southIndicesEastToWest,      eastIndicesNorthToSouth: eastIndicesNorthToSouth,      northIndicesWestToEast: northIndicesWestToEast,      indexCountWithoutSkirts: gridIndexCount,    };  }  return indicesAndEdges;};/** * @private */TerrainProvider.addSkirtIndices = function (  westIndicesSouthToNorth,  southIndicesEastToWest,  eastIndicesNorthToSouth,  northIndicesWestToEast,  vertexCount,  indices,  offset) {  let vertexIndex = vertexCount;  offset = addSkirtIndices(    westIndicesSouthToNorth,    vertexIndex,    indices,    offset  );  vertexIndex += westIndicesSouthToNorth.length;  offset = addSkirtIndices(    southIndicesEastToWest,    vertexIndex,    indices,    offset  );  vertexIndex += southIndicesEastToWest.length;  offset = addSkirtIndices(    eastIndicesNorthToSouth,    vertexIndex,    indices,    offset  );  vertexIndex += eastIndicesNorthToSouth.length;  addSkirtIndices(northIndicesWestToEast, vertexIndex, indices, offset);};function getEdgeIndices(width, height) {  const westIndicesSouthToNorth = new Array(height);  const southIndicesEastToWest = new Array(width);  const eastIndicesNorthToSouth = new Array(height);  const northIndicesWestToEast = new Array(width);  let i;  for (i = 0; i < width; ++i) {    northIndicesWestToEast[i] = i;    southIndicesEastToWest[i] = width * height - 1 - i;  }  for (i = 0; i < height; ++i) {    eastIndicesNorthToSouth[i] = (i + 1) * width - 1;    westIndicesSouthToNorth[i] = (height - i - 1) * width;  }  return {    westIndicesSouthToNorth: westIndicesSouthToNorth,    southIndicesEastToWest: southIndicesEastToWest,    eastIndicesNorthToSouth: eastIndicesNorthToSouth,    northIndicesWestToEast: northIndicesWestToEast,  };}function addRegularGridIndices(width, height, indices, offset) {  let index = 0;  for (let j = 0; j < height - 1; ++j) {    for (let i = 0; i < width - 1; ++i) {      const upperLeft = index;      const lowerLeft = upperLeft + width;      const lowerRight = lowerLeft + 1;      const upperRight = upperLeft + 1;      indices[offset++] = upperLeft;      indices[offset++] = lowerLeft;      indices[offset++] = upperRight;      indices[offset++] = upperRight;      indices[offset++] = lowerLeft;      indices[offset++] = lowerRight;      ++index;    }    ++index;  }}function addSkirtIndices(edgeIndices, vertexIndex, indices, offset) {  let previousIndex = edgeIndices[0];  const length = edgeIndices.length;  for (let i = 1; i < length; ++i) {    const index = edgeIndices[i];    indices[offset++] = previousIndex;    indices[offset++] = index;    indices[offset++] = vertexIndex;    indices[offset++] = vertexIndex;    indices[offset++] = index;    indices[offset++] = vertexIndex + 1;    previousIndex = index;    ++vertexIndex;  }  return offset;}/** * Specifies the quality of terrain created from heightmaps.  A value of 1.0 will * ensure that adjacent heightmap vertices are separated by no more than * {@link Globe.maximumScreenSpaceError} screen pixels and will probably go very slowly. * A value of 0.5 will cut the estimated level zero geometric error in half, allowing twice the * screen pixels between adjacent heightmap vertices and thus rendering more quickly. * @type {Number} */TerrainProvider.heightmapTerrainQuality = 0.25;/** * Determines an appropriate geometric error estimate when the geometry comes from a heightmap. * * @param {Ellipsoid} ellipsoid The ellipsoid to which the terrain is attached. * @param {Number} tileImageWidth The width, in pixels, of the heightmap associated with a single tile. * @param {Number} numberOfTilesAtLevelZero The number of tiles in the horizontal direction at tile level zero. * @returns {Number} An estimated geometric error. */TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap = function (  ellipsoid,  tileImageWidth,  numberOfTilesAtLevelZero) {  return (    (ellipsoid.maximumRadius *      2 *      Math.PI *      TerrainProvider.heightmapTerrainQuality) /    (tileImageWidth * numberOfTilesAtLevelZero)  );};/** * Requests the geometry for a given tile.  This function should not be called before * {@link TerrainProvider#ready} returns true.  The result must include terrain data and * may optionally include a water mask and an indication of which child tiles are available. * @function * * @param {Number} x The X coordinate of the tile for which to request geometry. * @param {Number} y The Y coordinate of the tile for which to request geometry. * @param {Number} level The level of the tile for which to request geometry. * @param {Request} [request] The request object. Intended for internal use only. * * @returns {Promise.<TerrainData>|undefined} A promise for the requested geometry.  If this method *          returns undefined instead of a promise, it is an indication that too many requests are already *          pending and the request will be retried later. */TerrainProvider.prototype.requestTileGeometry =  DeveloperError.throwInstantiationError;/** * Gets the maximum geometric error allowed in a tile at a given level.  This function should not be * called before {@link TerrainProvider#ready} returns true. * @function * * @param {Number} level The tile level for which to get the maximum geometric error. * @returns {Number} The maximum geometric error. */TerrainProvider.prototype.getLevelMaximumGeometricError =  DeveloperError.throwInstantiationError;/** * Determines whether data for a tile is available to be loaded. * @function * * @param {Number} x The X coordinate of the tile for which to request geometry. * @param {Number} y The Y coordinate of the tile for which to request geometry. * @param {Number} level The level of the tile for which to request geometry. * @returns {Boolean|undefined} Undefined if not supported by the terrain provider, otherwise true or false. */TerrainProvider.prototype.getTileDataAvailable =  DeveloperError.throwInstantiationError;/** * Makes sure we load availability data for a tile * @function * * @param {Number} x The X coordinate of the tile for which to request geometry. * @param {Number} y The Y coordinate of the tile for which to request geometry. * @param {Number} level The level of the tile for which to request geometry. * @returns {undefined|Promise<void>} Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded */TerrainProvider.prototype.loadTileDataAvailability =  DeveloperError.throwInstantiationError;export default TerrainProvider;/** * A function that is called when an error occurs. * @callback TerrainProvider.ErrorEvent * * @this TerrainProvider * @param {TileProviderError} err An object holding details about the error that occurred. */
 |