123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- import BoundingSphere from './BoundingSphere.js';
- import buildModuleUrl from './buildModuleUrl.js';
- import Cartesian2 from './Cartesian2.js';
- import Cartesian3 from './Cartesian3.js';
- import Cartographic from './Cartographic.js';
- import Check from './Check.js';
- import defaultValue from './defaultValue.js';
- import defined from './defined.js';
- import defineProperties from './defineProperties.js';
- import DeveloperError from './DeveloperError.js';
- import Ellipsoid from './Ellipsoid.js';
- import GeographicTilingScheme from './GeographicTilingScheme.js';
- import Rectangle from './Rectangle.js';
- import Resource from './Resource.js';
- var scratchDiagonalCartesianNE = new Cartesian3();
- var scratchDiagonalCartesianSW = new Cartesian3();
- var scratchDiagonalCartographic = new Cartographic();
- var scratchCenterCartesian = new Cartesian3();
- var scratchSurfaceCartesian = new Cartesian3();
- var scratchBoundingSphere = new BoundingSphere();
- var tilingScheme = new GeographicTilingScheme();
- var scratchCorners = [new Cartographic(), new Cartographic(), new Cartographic(), new Cartographic()];
- var scratchTileXY = new Cartesian2();
- /**
- * A collection of functions for approximating terrain height
- * @private
- */
- var ApproximateTerrainHeights = {};
- /**
- * Initializes the minimum and maximum terrain heights
- * @return {Promise}
- */
- ApproximateTerrainHeights.initialize = function() {
- var initPromise = ApproximateTerrainHeights._initPromise;
- if (defined(initPromise)) {
- return initPromise;
- }
- initPromise = Resource.fetchJson(buildModuleUrl('Assets/approximateTerrainHeights.json'))
- .then(function(json) {
- ApproximateTerrainHeights._terrainHeights = json;
- });
- ApproximateTerrainHeights._initPromise = initPromise;
- return initPromise;
- };
- /**
- * Computes the minimum and maximum terrain heights for a given rectangle
- * @param {Rectangle} rectangle The bounding rectangle
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid
- * @return {{minimumTerrainHeight: Number, maximumTerrainHeight: Number}}
- */
- ApproximateTerrainHeights.getMinimumMaximumHeights = function(rectangle, ellipsoid) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined('rectangle', rectangle);
- if (!defined(ApproximateTerrainHeights._terrainHeights)) {
- throw new DeveloperError('You must call ApproximateTerrainHeights.initialize and wait for the promise to resolve before using this function');
- }
- //>>includeEnd('debug');
- ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
- var xyLevel = getTileXYLevel(rectangle);
- // Get the terrain min/max for that tile
- var minTerrainHeight = ApproximateTerrainHeights._defaultMinTerrainHeight;
- var maxTerrainHeight = ApproximateTerrainHeights._defaultMaxTerrainHeight;
- if (defined(xyLevel)) {
- var key = xyLevel.level + '-' + xyLevel.x + '-' + xyLevel.y;
- var heights = ApproximateTerrainHeights._terrainHeights[key];
- if (defined(heights)) {
- minTerrainHeight = heights[0];
- maxTerrainHeight = heights[1];
- }
- // Compute min by taking the center of the NE->SW diagonal and finding distance to the surface
- ellipsoid.cartographicToCartesian(Rectangle.northeast(rectangle, scratchDiagonalCartographic),
- scratchDiagonalCartesianNE);
- ellipsoid.cartographicToCartesian(Rectangle.southwest(rectangle, scratchDiagonalCartographic),
- scratchDiagonalCartesianSW);
- Cartesian3.midpoint(scratchDiagonalCartesianSW, scratchDiagonalCartesianNE, scratchCenterCartesian);
- var surfacePosition = ellipsoid.scaleToGeodeticSurface(scratchCenterCartesian, scratchSurfaceCartesian);
- if (defined(surfacePosition)) {
- var distance = Cartesian3.distance(scratchCenterCartesian, surfacePosition);
- minTerrainHeight = Math.min(minTerrainHeight, -distance);
- } else {
- minTerrainHeight = ApproximateTerrainHeights._defaultMinTerrainHeight;
- }
- }
- minTerrainHeight = Math.max(ApproximateTerrainHeights._defaultMinTerrainHeight, minTerrainHeight);
- return {
- minimumTerrainHeight: minTerrainHeight,
- maximumTerrainHeight: maxTerrainHeight
- };
- };
- /**
- * Computes the bounding sphere based on the tile heights in the rectangle
- * @param {Rectangle} rectangle The bounding rectangle
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid
- * @return {BoundingSphere} The result bounding sphere
- */
- ApproximateTerrainHeights.getBoundingSphere = function(rectangle, ellipsoid) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined('rectangle', rectangle);
- if (!defined(ApproximateTerrainHeights._terrainHeights)) {
- throw new DeveloperError('You must call ApproximateTerrainHeights.initialize and wait for the promise to resolve before using this function');
- }
- //>>includeEnd('debug');
- ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
- var xyLevel = getTileXYLevel(rectangle);
- // Get the terrain max for that tile
- var maxTerrainHeight = ApproximateTerrainHeights._defaultMaxTerrainHeight;
- if (defined(xyLevel)) {
- var key = xyLevel.level + '-' + xyLevel.x + '-' + xyLevel.y;
- var heights = ApproximateTerrainHeights._terrainHeights[key];
- if (defined(heights)) {
- maxTerrainHeight = heights[1];
- }
- }
- var result = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, 0.0);
- BoundingSphere.fromRectangle3D(rectangle, ellipsoid, maxTerrainHeight, scratchBoundingSphere);
- return BoundingSphere.union(result, scratchBoundingSphere, result);
- };
- function getTileXYLevel(rectangle) {
- Cartographic.fromRadians(rectangle.east, rectangle.north, 0.0, scratchCorners[0]);
- Cartographic.fromRadians(rectangle.west, rectangle.north, 0.0, scratchCorners[1]);
- Cartographic.fromRadians(rectangle.east, rectangle.south, 0.0, scratchCorners[2]);
- Cartographic.fromRadians(rectangle.west, rectangle.south, 0.0, scratchCorners[3]);
- // Determine which tile the bounding rectangle is in
- var lastLevelX = 0, lastLevelY = 0;
- var currentX = 0, currentY = 0;
- var maxLevel = ApproximateTerrainHeights._terrainHeightsMaxLevel;
- var i;
- for(i = 0; i <= maxLevel; ++i) {
- var failed = false;
- for(var j = 0; j < 4; ++j) {
- var corner = scratchCorners[j];
- tilingScheme.positionToTileXY(corner, i, scratchTileXY);
- if (j === 0) {
- currentX = scratchTileXY.x;
- currentY = scratchTileXY.y;
- } else if(currentX !== scratchTileXY.x || currentY !== scratchTileXY.y) {
- failed = true;
- break;
- }
- }
- if (failed) {
- break;
- }
- lastLevelX = currentX;
- lastLevelY = currentY;
- }
- if (i === 0) {
- return undefined;
- }
- return {
- x : lastLevelX,
- y : lastLevelY,
- level : (i > maxLevel) ? maxLevel : (i - 1)
- };
- }
- ApproximateTerrainHeights._terrainHeightsMaxLevel = 6;
- ApproximateTerrainHeights._defaultMaxTerrainHeight = 9000.0;
- ApproximateTerrainHeights._defaultMinTerrainHeight = -100000.0;
- ApproximateTerrainHeights._terrainHeights = undefined;
- ApproximateTerrainHeights._initPromise = undefined;
- defineProperties(ApproximateTerrainHeights, {
- /**
- * Determines if the terrain heights are initialized and ready to use. To initialize the terrain heights,
- * call {@link ApproximateTerrainHeights#initialize} and wait for the returned promise to resolve.
- * @type {Boolean}
- * @readonly
- * @memberof ApproximateTerrainHeights
- */
- initialized: {
- get: function() {
- return defined(ApproximateTerrainHeights._terrainHeights);
- }
- }
- });
- export default ApproximateTerrainHeights;
|