computeFlyToLocationForRectangle.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import defined from "../Core/defined.js";
  2. import Rectangle from "../Core/Rectangle.js";
  3. import sampleTerrainMostDetailed from "../Core/sampleTerrainMostDetailed.js";
  4. import SceneMode from "./SceneMode.js";
  5. /**
  6. * Computes the final camera location to view a rectangle adjusted for the current terrain.
  7. * If the terrain does not support availability, the height above the ellipsoid is used.
  8. *
  9. * @param {Rectangle} rectangle The rectangle being zoomed to.
  10. * @param {Scene} scene The scene being used.
  11. *
  12. * @returns {Promise<Cartographic>} The optimal location to place the camera so that the entire rectangle is in view.
  13. *
  14. * @private
  15. */
  16. async function computeFlyToLocationForRectangle(rectangle, scene) {
  17. const terrainProvider = scene.terrainProvider;
  18. const mapProjection = scene.mapProjection;
  19. const ellipsoid = mapProjection.ellipsoid;
  20. let positionWithoutTerrain;
  21. const tmp = scene.camera.getRectangleCameraCoordinates(rectangle);
  22. if (scene.mode === SceneMode.SCENE3D) {
  23. positionWithoutTerrain = ellipsoid.cartesianToCartographic(tmp);
  24. } else {
  25. positionWithoutTerrain = mapProjection.unproject(tmp);
  26. }
  27. if (!defined(terrainProvider)) {
  28. return positionWithoutTerrain;
  29. }
  30. // readyPromise has been deprecated; This is here for backwards compatibility
  31. await terrainProvider._readyPromise;
  32. const availability = terrainProvider.availability;
  33. if (!defined(availability) || scene.mode === SceneMode.SCENE2D) {
  34. return positionWithoutTerrain;
  35. }
  36. const cartographics = [
  37. Rectangle.center(rectangle),
  38. Rectangle.southeast(rectangle),
  39. Rectangle.southwest(rectangle),
  40. Rectangle.northeast(rectangle),
  41. Rectangle.northwest(rectangle),
  42. ];
  43. const positionsOnTerrain = await computeFlyToLocationForRectangle._sampleTerrainMostDetailed(
  44. terrainProvider,
  45. cartographics
  46. );
  47. let heightFound = false;
  48. const maxHeight = positionsOnTerrain.reduce(function (currentMax, item) {
  49. if (!defined(item.height)) {
  50. return currentMax;
  51. }
  52. heightFound = true;
  53. return Math.max(item.height, currentMax);
  54. }, -Number.MAX_VALUE);
  55. const finalPosition = positionWithoutTerrain;
  56. if (heightFound) {
  57. finalPosition.height += maxHeight;
  58. }
  59. return finalPosition;
  60. }
  61. //Exposed for testing.
  62. computeFlyToLocationForRectangle._sampleTerrainMostDetailed = sampleTerrainMostDetailed;
  63. export default computeFlyToLocationForRectangle;