import { Env , FlatTheme , FontCatalogConfig , MapEnv , PostEffects , TextStyleDefinition , Theme , Value } from "@here/harp-datasource-protocol" ; import { ViewRanges } from "@here/harp-datasource-protocol/lib/ViewRanges" ; import { EarthConstants , GeoBox , GeoBoxExtentLike , GeoCoordinates , GeoPolygon , isGeoBoxExtentLike , isGeoCoordinatesLike , isVector3Like , mercatorProjection , OrientedBox3 , Projection , ProjectionType , TilingScheme , Vector3Like } from "@here/harp-geoutils" ; import { GeoCoordLike } from "@here/harp-geoutils/lib/coordinates/GeoCoordLike" ; import { assert , getOptionValue , LoggerManager , LogLevel , PerformanceTimer , TaskQueue , UriResolver } from "@here/harp-utils" ; import * as THREE from "three" ; import { AnimatedExtrusionHandler } from "./AnimatedExtrusionHandler" ; import { BackgroundDataSource } from "./BackgroundDataSource" ; import { CameraMovementDetector } from "./CameraMovementDetector" ; import { CameraUtils } from "./CameraUtils" ; import { ClipPlanesEvaluator , createDefaultClipPlanesEvaluator } from "./ClipPlanesEvaluator" ; import { IMapAntialiasSettings , IMapRenderingManager , MapRenderingManager } from "./composing" ; import { ConcurrentDecoderFacade } from "./ConcurrentDecoderFacade" ; import { ConcurrentTilerFacade } from "./ConcurrentTilerFacade" ; import { CopyrightInfo } from "./copyrights/CopyrightInfo" ; import { DataSource } from "./DataSource" ; import { ElevationProvider } from "./ElevationProvider" ; import { ElevationRangeSource } from "./ElevationRangeSource" ; import { EventDispatcher } from "./EventDispatcher" ; import { DEFAULT_FOV_CALCULATION , FovCalculation , MAX_FOV_DEG , MIN_FOV_DEG } from "./FovCalculation" ; import { FrustumIntersection } from "./FrustumIntersection" ; import { overlayOnElevation } from "./geometry/overlayOnElevation" ; import { TileGeometryManager } from "./geometry/TileGeometryManager" ; import { MapViewImageCache } from "./image/MapViewImageCache" ; import { IntersectParams } from "./IntersectParams" ; import { MapAnchors } from "./MapAnchors" ; import { MapViewEnvironment } from "./MapViewEnvironment" ; import { MapViewFog } from "./MapViewFog" ; import { MapViewTaskScheduler } from "./MapViewTaskScheduler" ; import { MapViewThemeManager } from "./MapViewThemeManager" ; import { PickHandler , PickResult } from "./PickHandler" ; import { PoiManager } from "./poi/PoiManager" ; import { PoiTableManager } from "./poi/PoiTableManager" ; import { PolarTileDataSource } from "./PolarTileDataSource" ; import { ScreenProjector } from "./ScreenProjector" ; import { FrameStats , PerformanceStatistics } from "./Statistics" ; import { MapViewState } from "./text/MapViewState" ; import { TextElement } from "./text/TextElement" ; import { TextElementsRenderer } from "./text/TextElementsRenderer" ; import { TextElementsRendererOptions } from "./text/TextElementsRendererOptions" ; import { Tile } from "./Tile" ; import { TileObjectRenderer } from "./TileObjectsRenderer" ; import { MapViewUtils } from "./Utils" ; import { ResourceComputationType , VisibleTileSet , VisibleTileSetOptions } from "./VisibleTileSet" ; declare const process ; const isProduction = process . env . NODE_ENV === "production" ; if ( isProduction ) { LoggerManager . instance . setLogLevelForAll ( LogLevel . Error ) ; } else { LoggerManager . instance . setLogLevelForAll ( LogLevel . Log ) ; } export enum TileTaskGroups { FETCH_AND_DECODE = "fetch" , CREATE = "create" } export enum MapViewEventNames { /** Called before this `MapView` starts to render a new frame. */ Update = "update" , /** Called when the WebGL canvas is resized. */ Resize = "resize" , /** Called when the frame is about to be rendered. */ Render = "render" , /** Called after a frame has been rendered. */ AfterRender = "didrender" , /** Called after the first frame has been rendered. */ FirstFrame = "first-render" , /**
     * Called when the rendered frame was complete, i.e. all the necessary tiles and resources
     * are loaded and rendered.
     */ FrameComplete = "frame-complete" , /** Called when the theme has been loaded with the internal  ThemeLoader .  ThemeLoaded = "theme-loaded" , /** Called when the animation mode has started. */ AnimationStarted = "animation-started" , /** Called when the animation mode has stopped. */ AnimationFinished = "animation-finished" , /** Called when a camera interaction has been detected. */ MovementStarted = "movement-started" , /** Called when a camera interaction has been stopped. */ MovementFinished = "movement-finished" , /** Called when a data source has been connected or failed to connect. */ DataSourceConnect = "datasource-connect" , /** Emitted when copyright info of rendered map has been changed. */ CopyrightChanged = "copyright-changed" , /** Called when the WebGL context is lost. */ ContextLost = "webglcontext-lost" , /** Called when the WebGL context is restored. */ ContextRestored = "webglcontext-restored" , /** Called when camera position has been changed. */ CameraPositionChanged = "camera-changed" , /** Called when dispose has been called, before any cleanup is done. */ Dispose = "dispose" } const logger = LoggerManager . instance . create ( "MapView" ) ; const DEFAULT_CAM_NEAR_PLANE = 0.1 ; const DEFAULT_CAM_FAR_PLANE = 4000000 ; const DEFAULT_MIN_ZOOM_LEVEL = 1 ; /**
 * Default maximum zoom level.
 */ const DEFAULT_MAX_ZOOM_LEVEL = 20 ; /**
 * Default minimum camera height.
 */ const DEFAULT_MIN_CAMERA_HEIGHT = 20 ; /**
 * Style set used by  PolarTileDataSource by default.
  const DEFAULT_POLAR_STYLE_SET_NAME = "polar" ; /**
 * The type of `RenderEvent`.
 */ export interface RenderEvent extends THREE . Event { type : MapViewEventNames ; time ? : number ; } const cache = { vector2 : [ new THREE . Vector2 ( ) ] , vector3 : [ new THREE . Vector3 ( ) , new THREE . Vector3 ( ) , new THREE . Vector3 ( ) ] , rayCaster : new THREE . Raycaster ( ) , groundPlane : new THREE . Plane ( ) , groundSphere : new THREE . Sphere ( undefined , EarthConstants . EQUATORIAL_RADIUS ) , matrix4 : [ new THREE . Matrix4 ( ) , new THREE . Matrix4 ( ) ] , transform : [ { position : new THREE . Vector3 ( ) , xAxis : new THREE . Vector3 ( ) , yAxis : new THREE . Vector3 ( ) , zAxis : new THREE . Vector3 ( ) } ] , color : new THREE . Color ( ) } ; see https export enum MapViewPowerPreference { /** Default value. */ Default = "default" , /** Lower power mode, used to conserve energy. */ LowPower = "low-power" , /** Maximum performance. */ HighPerformance = "high-performance" } /**
 * User configuration for the  MapView .
  export interface MapViewOptions extends TextElementsRendererOptions , Partial < LookAtParams > { /**
     * The canvas element used to render the scene.
     */ canvas : HTMLCanvasElement ; /**
     * Optional WebGL Rendering Context.
     * (https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext)
     */ context ? : WebGLRenderingContext ; /**
     * `true` if the canvas contains an alpha (transparency) buffer or not. Default is `false`.
     */ alpha ? : boolean ; default addBackgroundDatasource ? : boolean ; default enableNativeWebglAntialias ? : boolean ; /**
     * Antialias settings for the map rendering. It is better to disable the native antialiasing if
     * the custom antialiasing is enabled.
     */ customAntialiasSettings ? : IMapAntialiasSettings ; /**
     * `Projection` used by the `MapView`.
     *
     * The default value is [[mercatorProjection]].
     */ projection ? : Projection ; /**
     * The URL of the script that the decoder worker runs. The default URL is
     * `./decoder.bundle.js`.
     *
     * Relative URIs are resolved to full URL using the document's base URL
     * (see: https://www.w3.org/TR/WD-html40-970917/htmlweb.html#h-5.1.2).
     */ decoderUrl ? : string ; /**
     * The number of Web Workers used to decode data. The default is
     * CLAMP(`navigator.hardwareConcurrency` - 1, 1, 2).
     */ decoderCount ? : number ; /**
     * The  {@link @here/harp-datasource-protocol#Theme} used by Mapview.
     *
     * This Theme can be one of the following:
     *  - `string` : the URI of the theme file used to style this map
     *  - `Theme` : the `Theme` object already loaded
     *  - `Promise<Theme>` : the future `Theme` object
     *  - `undefined` : the theme is not yet set up, but can be set later. Rendering waits until
     *     the theme is set.
     *
     * **Note:** Layers that use a theme do not render any content until that theme is available.
     *
     * Relative URIs are resolved to full URL using the document's base URL
     * (see: https://www.w3.org/TR/WD-html40-970917/htmlweb.html#h-5.1.2).
     *
     * Custom URIs (of theme itself and of resources referenced by theme) may be resolved with help
     * of [[uriResolver]].
     *
     *  see ThemeLoader . load for details how theme is loaded
      theme ? : string | Theme | FlatTheme | Promise < Theme > ; see {@link @here/harp-utils#UriResolver} See {@link @here/harp-utils#PrefixMapUriResolver} uriResolver ? : UriResolver ; /**
     * The minimum zoom level; default is `1`.
     */ minZoomLevel ? : number ; /**
     * Determines the minimum camera height, in meters.
     */ minCameraHeight ? : number ; /**
     * The maximum zoom level. The default is `14`.
     */ maxZoomLevel ? : number ; /**
     * User-defined camera clipping planes distance evaluator.
     * If not defined,  TiltViewClipPlanesEvaluator will be used by  MapView .
     *
     *  default TiltViewClipPlanesEvaluator clipPlanesEvaluator ? : ClipPlanesEvaluator ; default extendedFrustumCulling ? : boolean ; default maxVisibleDataSourceTiles ? : number ; default tileCacheSize ? : number ; see resourceComputationType ? : ResourceComputationType ; /**
     * Limits the number of reduced zoom levels (lower detail)
     * to be searched for fallback tiles.
     *
     * When zooming in, newly elected tiles may have not
     * yet loaded.  MapView searches through
     * the tile cache for tiles ready to be displayed in
     * lower zoom levels. The tiles may be
     * located shallower in the quadtree.
     *
     * To disable a cache search, set the value to `0`.
     *
     *  default quadTreeSearchDistanceUp ? : number ; /**
     * Limits the number of higher zoom levels (more detailed)
     * to be searched for fallback tiles.
     *
     * When zooming out, newly elected tiles may have not
     * yet loaded.  MapView searches through
     * the tile cache for tiles ready to be displayed in
     * higher zoom levels. These tiles may be
     * located deeper in the quadtree.
     *
     * To disable a cache search, set the value to `0`.
     *
     *  default quadTreeSearchDistanceDown ? : number ; /**
     * Set to `true` to measure performance statistics.
     */ enableStatistics ? : boolean ; /**
     * Preserve the buffers until they are cleared manually or overwritten.
     *
     * Set to `true` in order to copy  MapView canvas contents
     * to an image or another canvas.
     *
     *  default see https preserveDrawingBuffer ? : boolean ; deprecated enableRoadPicking ? : boolean ; /**
     * Set to `true` to allow picking of technique information associated with objects.
     */ enablePickTechnique ? : boolean ; /**
     * Maximum timeout, in milliseconds, before a [[MOVEMENT_FINISHED_EVENT]] is sent after the
     * latest frame with a camera movement. The default is 300ms.
     */ movementThrottleTimeout ? : number ; /**
     * How to calculate the Field of View, if not specified, then
     * [[DEFAULT_FOV_CALCULATION]] is used.
     */ fovCalculation ? : FovCalculation ; languages ? : string [ ] ; note politicalView ? : string ; default pixelRatio ? : number ; note note default dynamicPixelRatio ? : number ; /**
     * Set maximum FPS (Frames Per Second). If VSync in enabled, the specified number may not be
     * reached, but instead the next smaller number than `maxFps` that is equal to the refresh rate
     * divided by an integer number.
     *
     * E.g.: If the monitors refresh rate is set to 60hz, and if `maxFps` is set to a value of `40`
     * (60hz/1.5), the actual used FPS may be 30 (60hz/2). For displays that have a refresh rate of
     * 60hz, good values for `maxFps` are 30, 20, 15, 12, 10, 6, 3 and 1. A value of `0` is ignored.
     */ maxFps ? : number ; default tileWrappingEnabled ? : boolean ; /**
     * Set tiling scheme for [[BackgroundDataSource]]
     */ backgroundTilingScheme ? : TilingScheme ; /**
     * Should be the  PolarTileDataSource used on spherical projection.
     * Default is `true`.
      enablePolarDataSource ? : boolean ; /**
     * The name of the [[StyleSet]] used by  PolarTileDataSource * to evaluate for the decoding.
     * Default is `"polar"`.
      polarStyleSetName ? : string ; /**
     * Storage level offset of regular tiles from reference datasource to align
     *  PolarTileDataSource tiles to.
     * Default is `-1`.
      polarGeometryLevelOffset ? : number ; /**
     * Hint for the WebGL implementation on which power mode to prefer.
     */ powerPreference ? : MapViewPowerPreference ; /**
     * Set to `true` to allow rendering scene synchronously.
     *
     * By calling `renderSync()` scene draws immediately, opposite to default case when
     * `update` method requests redraw and waits for the next animation frame.
     *
     * You need to set up your own render loop controller.
     * Event `MapViewEventNames.Update` fired when  MapView requests for an redraw.
     * E.g.: When tiles loaded asynchronously and ready for rendering.
     *
     *  note default synchronousRendering ? : boolean ; default enableMixedLod ? : boolean ; beta default lodMinTilePixelSize ? : number ; default enableShadows ? : boolean ; default beta throttlingEnabled ? : boolean ; /**
     * If set, the view will constrained within the given bounds in geo coordinates.
     */ maxBounds ? : GeoBox ; } /**
 * Default settings used by  MapView collected in one place.
 *  internal const MapViewDefaults = { projection : mercatorProjection , addBackgroundDatasource : true , maxVisibleDataSourceTiles : 100 , extendedFrustumCulling : true , tileCacheSize : 200 , resourceComputationType : ResourceComputationType . EstimationInMb , quadTreeSearchDistanceUp : 3 , quadTreeSearchDistanceDown : 2 , pixelRatio : typeof window !== "undefined" && window . devicePixelRatio !== undefined ? window . devicePixelRatio : 1.0 , target : new GeoCoordinates ( 25 , 0 ) , zoomLevel : 5 , tilt : 0 , heading : 0 , theme : { } , maxTilesPerFrame : 0 } ; /**
 * Parameters for  {@link (MapView.lookAt:WITH_PARAMS)} .
  export interface LookAtParams { note If the given point is not on the ground (altitude != 0)  MapView will do a
     * raycasting internally to find a target on the ground.
     *
     * As a consequence  MapView . target and  MapView . zoomLevel * will not match the values
     * that were passed into the  {@link (MapView.lookAt:WITH_PARAMS)} method.
     *  default `new GeoCoordinates(25, 0)` in  MapView . constructor context.
     *  default MapView . target in  {@link (MapView.lookAt:WITH_PARAMS)} context.
      target : GeoCoordLike ; /**
     * Fit MapView to these boundaries.
     *
     * If specified, `zoomLevel` and `distance` parameters are ignored and `lookAt` calculates best
     * `zoomLevel` to fit given bounds.
     *
     * * if `bounds` is  {@link @here/harp-geoutils#GeoBox} , then `lookAt`
     *   use  LookAtParams . target or `bounds.target` and
     *   ensure whole box is visible
     *
     * * if `bounds` is  {@link @here/harp-geoutils#GeoPolygon} , then `lookAt`
     *   use `bounds.getCentroid()` and ensure whole polygon is visible
     *
     * * if `bounds` is  {@link @here/harp-geoutils#GeoBoxExtentLike} ,
     *   then `lookAt` will use  LookAtParams . target or
     *   current  MapView . target and ensure whole extents are visible
     *
     * * if `bounds` is [[GeoCoordLike]][], then `lookAt` will use  LookAtParams . target or
     *   calculated `target` as center of world box covering given points and ensure all points are
     *   visible
     *
     * Note in sphere projection some points are not visible if you specify bounds that span more
     * than 180 degrees in any direction.
     *
     *  see {@link (MapView.lookAt:WITH_PARAMS)} for details on how `bounds`
     *      interact with `target` parameter
      bounds : GeoBox | GeoBoxExtentLike | GeoCoordLike [ ] | GeoPolygon ; default distance : number ; note default 5 in  MapView . constructor context.
     *  default MapView . zoomLevel in  {@link (MapView.lookAt:WITH_PARAMS)} context.
      zoomLevel : number ; default 0 in  MapView . constructor context.
     *  default MapView . tilt in  {@link (MapView.lookAt:WITH_PARAMS)} context.
     *  note tilt : number ; default 0 in  MapView . constructor context.
     *  default MapView . heading in  {@link (MapView.lookAt:WITH_PARAMS)} context.
      heading : number ; } /**
 * The core class of the library to call in order to create a map visualization. It needs to be
 * linked to datasources.
 */ export class MapView extends EventDispatcher { /**
     * Keep the events here to avoid a global reference to MapView (and thus prevent garbage collection).
     */ private readonly UPDATE_EVENT : RenderEvent = { type : MapViewEventNames . Update } ; private readonly RENDER_EVENT : RenderEvent = { type : MapViewEventNames . Render } ; private readonly DID_RENDER_EVENT : RenderEvent = { type : MapViewEventNames . AfterRender } ; private readonly FIRST_FRAME_EVENT : RenderEvent = { type : MapViewEventNames . FirstFrame } ; private readonly FRAME_COMPLETE_EVENT : RenderEvent = { type : MapViewEventNames . FrameComplete } ; private readonly THEME_LOADED_EVENT : RenderEvent = { type : MapViewEventNames . ThemeLoaded } ; private readonly ANIMATION_STARTED_EVENT : RenderEvent = { type : MapViewEventNames . AnimationStarted } ; private readonly ANIMATION_FINISHED_EVENT : RenderEvent = { type : MapViewEventNames . AnimationFinished } ; private readonly MOVEMENT_STARTED_EVENT : RenderEvent = { type : MapViewEventNames . MovementStarted } ; private readonly MOVEMENT_FINISHED_EVENT : RenderEvent = { type : MapViewEventNames . MovementFinished } ; private readonly CONTEXT_LOST_EVENT : RenderEvent = { type : MapViewEventNames . ContextLost } ; private readonly CONTEXT_RESTORED_EVENT : RenderEvent = { type : MapViewEventNames . ContextRestored } ; private readonly COPYRIGHT_CHANGED_EVENT : RenderEvent = { type : MapViewEventNames . CopyrightChanged } ; private readonly DISPOSE_EVENT : RenderEvent = { type : MapViewEventNames . Dispose } ; /**
     * The instance of  MapRenderingManager managing the rendering of the map. It is a public
     * property to allow access and modification of some parameters of the rendering process at
     * runtime.
      readonly mapRenderingManager : IMapRenderingManager ; private m_renderLabels : boolean = true ; private m_movementFinishedUpdateTimerId ? : any ; private m_postEffects ? : PostEffects ; private readonly m_screenProjector : ScreenProjector ; private m_visibleTiles : VisibleTileSet ; private readonly m_tileObjectRenderer : TileObjectRenderer ; private m_elevationSource ? : DataSource ; private m_elevationRangeSource ? : ElevationRangeSource ; private m_elevationProvider ? : ElevationProvider ; private m_visibleTileSetLock : boolean = false ; private readonly m_tileGeometryManager : TileGeometryManager ; private m_tileWrappingEnabled : boolean = true ; private m_zoomLevel : number = DEFAULT_MIN_ZOOM_LEVEL ; private m_minZoomLevel : number = DEFAULT_MIN_ZOOM_LEVEL ; private m_maxZoomLevel : number = DEFAULT_MAX_ZOOM_LEVEL ; private readonly m_minCameraHeight : number = DEFAULT_MIN_CAMERA_HEIGHT ; private m_geoMaxBounds ? : GeoBox ; private m_worldMaxBounds ? : THREE . Box3 | OrientedBox3 ; private readonly m_camera : THREE . PerspectiveCamera ; /**
     * Relative to eye camera.
     *
     * This camera is internal camera used to improve precision
     * when rendering geometries.
     */ private readonly m_rteCamera = new THREE . PerspectiveCamera ( ) ; private m_yaw = 0 ; private m_pitch = 0 ; private m_roll = 0 ; private m_targetDistance = 0 ; private m_targetGeoPos = GeoCoordinates . fromObject ( MapViewDefaults . target ! ) ; private readonly m_targetWorldPos = new THREE . Vector3 ( ) ; private readonly m_viewRanges : ViewRanges = { near : DEFAULT_CAM_NEAR_PLANE , far : DEFAULT_CAM_FAR_PLANE , minimum : DEFAULT_CAM_NEAR_PLANE , maximum : DEFAULT_CAM_FAR_PLANE } ; private m_pointOfView ? : THREE . PerspectiveCamera ; private m_pixelToWorld ? : number ; private m_pixelRatio ? : number ; /** Default scene for map objects and map anchors */ private readonly m_scene : THREE . Scene = new THREE . Scene ( ) ; /** Separate scene for overlay map anchors */ private readonly m_overlayScene : THREE . Scene = new THREE . Scene ( ) ; /** Root node of [[m_scene]] that gets cleared every frame. */ private readonly m_sceneRoot = new THREE . Object3D ( ) ; /** Root node of [[m_overlayScene]] that gets cleared every frame. */ private readonly m_overlaySceneRoot = new THREE . Object3D ( ) ; private readonly m_mapAnchors : MapAnchors = new MapAnchors ( ) ; private m_animationCount : number = 0 ; private m_animationFrameHandle : number | undefined ; private m_drawing : boolean = false ; private m_updatePending : boolean = false ; private readonly m_renderer : THREE . WebGLRenderer ; private m_frameNumber = 0 ; private m_textElementsRenderer : TextElementsRenderer ; private m_forceCameraAspect : number | undefined = undefined ; private m_taskSchedulerTimeout : any = undefined ; private readonly m_tileDataSources : DataSource [ ] = [ ] ; private readonly m_connectedDataSources = new Set < string > ( ) ; private readonly m_failedDataSources = new Set < string > ( ) ; private readonly m_polarDataSource ? : PolarTileDataSource ; private readonly m_enablePolarDataSource : boolean = true ; private readonly m_raycaster = new THREE . Raycaster ( ) ; private readonly m_plane = new THREE . Plane ( new THREE . Vector3 ( 0 , 0 , 1 ) ) ; private readonly m_sphere = new THREE . Sphere ( undefined , EarthConstants . EQUATORIAL_RADIUS ) ; private readonly m_options : MapViewOptions ; private readonly m_visibleTileSetOptions : VisibleTileSetOptions ; private readonly m_uriResolver ? : UriResolver ; private m_previousFrameTimeStamp ? : number ; private m_firstFrameRendered = false ; private m_firstFrameComplete = false ; private readonly handleRequestAnimationFrame : ( frameStartTime : number ) => void ; private readonly m_pickHandler : PickHandler ; private readonly m_userImageCache : MapViewImageCache = new MapViewImageCache ( ) ; private readonly m_env : MapEnv = new MapEnv ( { } ) ; private readonly m_poiManager : PoiManager = new PoiManager ( this ) ; private readonly m_poiTableManager : PoiTableManager = new PoiTableManager ( this ) ; private readonly m_collisionDebugCanvas : HTMLCanvasElement | undefined ; private readonly m_movementDetector : CameraMovementDetector ; private m_thisFrameTilesChanged : boolean | undefined ; private m_lastTileIds : string = "" ; private m_languages : string [ ] | undefined ; private m_politicalView : string | undefined ; private m_copyrightInfo : CopyrightInfo [ ] = [ ] ; private readonly m_animatedExtrusionHandler : AnimatedExtrusionHandler ; private m_enableMixedLod : boolean | undefined ; private readonly m_lodMinTilePixelSize : number | undefined ; private m_taskScheduler : MapViewTaskScheduler ; private readonly m_themeManager : MapViewThemeManager ; private readonly m_sceneEnvironment : MapViewEnvironment ; private m_disposed = false ; param options constructor ( options ) { super ( ) ; this . m_options = { ... options } ; this . m_uriResolver = this . m_options . uriResolver ; if ( this . m_options . minZoomLevel !== undefined ) { this . m_minZoomLevel = this . m_options . minZoomLevel ; } if ( this . m_options . maxZoomLevel !== undefined ) { this . m_maxZoomLevel = this . m_options . maxZoomLevel ; } if ( this . m_options . minCameraHeight !== undefined ) { this . m_minCameraHeight = this . m_options . minCameraHeight ; } if ( this . m_options . maxBounds !== undefined ) { this . m_geoMaxBounds = this . m_options . maxBounds ; } if ( this . m_options . decoderUrl !== undefined ) { ConcurrentDecoderFacade . defaultScriptUrl = this . m_uriResolver ? this . m_uriResolver . resolveUri ( this . m_options . decoderUrl ) : this . m_options . decoderUrl ; } if ( this . m_options . decoderCount !== undefined ) { ConcurrentDecoderFacade . defaultWorkerCount = this . m_options . decoderCount ; } this . m_visibleTileSetOptions = { ... MapViewDefaults , clipPlanesEvaluator : options . clipPlanesEvaluator !== undefined ? options . clipPlanesEvaluator : createDefaultClipPlanesEvaluator ( ) } ; if ( options . projection !== undefined ) { this . m_visibleTileSetOptions . projection = options . projection ; } if ( options . extendedFrustumCulling !== undefined ) { this . m_visibleTileSetOptions . extendedFrustumCulling = options . extendedFrustumCulling ; } if ( options . maxVisibleDataSourceTiles !== undefined ) { this . m_visibleTileSetOptions . maxVisibleDataSourceTiles = options . maxVisibleDataSourceTiles ; } if ( options . tileCacheSize !== undefined ) { this . m_visibleTileSetOptions . tileCacheSize = options . tileCacheSize ; } if ( options . resourceComputationType !== undefined ) { this . m_visibleTileSetOptions . resourceComputationType = options . resourceComputationType ; } if ( options . quadTreeSearchDistanceUp !== undefined ) { this . m_visibleTileSetOptions . quadTreeSearchDistanceUp = options . quadTreeSearchDistanceUp ; } if ( options . quadTreeSearchDistanceDown !== undefined ) { this . m_visibleTileSetOptions . quadTreeSearchDistanceDown = options . quadTreeSearchDistanceDown ; } if ( options . enablePolarDataSource !== undefined ) { this . m_enablePolarDataSource = options . enablePolarDataSource ; } this . m_pixelRatio = options . pixelRatio ; this . m_options . maxFps = this . m_options . maxFps ?? 0 ; this . m_options . enableStatistics = this . m_options . enableStatistics === true ; this . m_languages = this . m_options . languages ; this . m_politicalView = this . m_options . politicalView ; this . handleRequestAnimationFrame = this . renderLoop . bind ( this ) ; if ( this . m_options . tileWrappingEnabled !== undefined ) { this . m_tileWrappingEnabled = this . m_options . tileWrappingEnabled ; } this . setupStats ( this . m_options . enableStatistics ) ; this . canvas . addEventListener ( "webglcontextlost" , this . onWebGLContextLost ) ; this . canvas . addEventListener ( "webglcontextrestored" , this . onWebGLContextRestored ) ; this . m_renderer = new ( ( THREE as any ) . WebGL1Renderer ?? THREE . WebGLRenderer ) ( { canvas : this . canvas , context : this . m_options . context , antialias : this . nativeWebglAntialiasEnabled , alpha : this . m_options . alpha , preserveDrawingBuffer : this . m_options . preserveDrawingBuffer === true , powerPreference : this . m_options . powerPreference === undefined ? MapViewPowerPreference . Default : this . m_options . powerPreference } ) ; this . m_renderer . autoClear = false ; this . m_renderer . debug . checkShaderErrors = ! isProduction ; this . m_renderer . info . autoReset = false ; this . m_tileObjectRenderer = new TileObjectRenderer ( this . m_env , this . m_renderer ) ; this . setupRenderer ( this . m_tileObjectRenderer ) ; this . m_options . fovCalculation = this . m_options . fovCalculation === undefined ? DEFAULT_FOV_CALCULATION : this . m_options . fovCalculation ; this . m_options . fovCalculation . fov = THREE . MathUtils . clamp ( this . m_options . fovCalculation ! . fov , MIN_FOV_DEG , MAX_FOV_DEG ) ; const { width , height } = this . getCanvasClientSize ( ) ; const aspect = width / height ; this . m_camera = new THREE . PerspectiveCamera ( this . m_options . fovCalculation . fov , aspect , DEFAULT_CAM_NEAR_PLANE , DEFAULT_CAM_FAR_PLANE ) ; this . m_camera . up . set ( 0 , 0 , 1 ) ; this . setFovOnCamera ( this . m_options . fovCalculation , height ) ; this . projection . projectPoint ( this . m_targetGeoPos , this . m_targetWorldPos ) ; this . m_scene . add ( this . m_camera ) ; this . m_screenProjector = new ScreenProjector ( this . m_camera ) ; this . m_taskScheduler = new MapViewTaskScheduler ( this . maxFps ) ; this . m_tileGeometryManager = new TileGeometryManager ( this ) ; if ( options . enableMixedLod !== undefined ) { this . m_enableMixedLod = options . enableMixedLod ; } if ( options . lodMinTilePixelSize !== undefined ) { this . m_lodMinTilePixelSize = options . lodMinTilePixelSize ; } this . m_visibleTiles = this . createVisibleTileSet ( ) ; this . m_sceneEnvironment = new MapViewEnvironment ( this , options ) ; this . setupCamera ( ) ; this . m_pickHandler = new PickHandler ( this , this . m_rteCamera , this . m_options . enablePickTechnique === true ) ; this . m_movementDetector = new CameraMovementDetector ( this . m_options . movementThrottleTimeout , ( ) => this . movementStarted ( ) , ( ) => this . movementFinished ( ) ) ; const mapPassAntialiasSettings = this . m_options . customAntialiasSettings ; this . mapRenderingManager = new MapRenderingManager ( width , height , this . m_options . dynamicPixelRatio , mapPassAntialiasSettings ) ; this . m_animatedExtrusionHandler = new AnimatedExtrusionHandler ( this ) ; if ( this . m_enablePolarDataSource ) { const styleSetName = options . polarStyleSetName !== undefined ? options . polarStyleSetName : DEFAULT_POLAR_STYLE_SET_NAME ; this . m_polarDataSource = new PolarTileDataSource ( { styleSetName , geometryLevelOffset : options . polarGeometryLevelOffset } ) ; this . updatePolarDataSource ( ) ; } this . m_taskScheduler . addEventListener ( MapViewEventNames . Update , ( ) => { this . update ( ) ; } ) ; if ( options . throttlingEnabled !== undefined ) { this . m_taskScheduler . throttlingEnabled = options . throttlingEnabled ; } this . m_themeManager = new MapViewThemeManager ( this , this . m_uriResolver ) ; this . m_textElementsRenderer = this . createTextRenderer ( ) ; this . setTheme ( getOptionValue ( this . m_options . theme , MapViewDefaults . theme ) ) ; this . update ( ) ; } returns get lights ( ) : THREE . Light [ ] { return this . m_sceneEnvironment . lights ; } get taskQueue ( ) : TaskQueue { return this . m_taskScheduler . taskQueue ; } returns get renderLabels ( ) { return this . m_renderLabels ; } param value set renderLabels ( value ) { this . m_renderLabels = value ; } returns get delayLabelsUntilMovementFinished ( ) { return this . textElementsRenderer . delayLabelsUntilMovementFinished ; } param value set delayLabelsUntilMovementFinished ( value ) { this . textElementsRenderer . delayLabelsUntilMovementFinished = value ; } hidden The  TextElementsRenderer select the visible  TextElement s and renders them.
      get textElementsRenderer ( ) : TextElementsRenderer { return this . m_textElementsRenderer ; } hidden The  CameraMovementDetector detects camera movements. Made available for performance
     * measurements.
      get cameraMovementDetector ( ) : CameraMovementDetector { return this . m_movementDetector ; } /**
     * The  AnimatedExtrusionHandler controls animated extrusion effect
     * of the extruded objects in the  Tile get animatedExtrusionHandler ( ) : AnimatedExtrusionHandler { return this . m_animatedExtrusionHandler ; } deprecated get tileGeometryManager ( ) : TileGeometryManager | undefined { return this . m_tileGeometryManager ; } get enableMixedLod ( ) : boolean | undefined { return this . m_enableMixedLod ; } set enableMixedLod ( enableMixedLod ) { if ( this . m_enableMixedLod === enableMixedLod ) { return ; } this . m_enableMixedLod = enableMixedLod ; this . createVisibleTileSet ( ) ; this . update ( ) ; } get tileWrappingEnabled ( ) : boolean { return this . m_tileWrappingEnabled ; } set tileWrappingEnabled ( enabled ) { if ( this . projection . type === ProjectionType . Spherical ) { logger . warn ( "Setting this with spherical projection has no affect. Was this intended?" ) ; return ; } if ( enabled !== this . m_tileWrappingEnabled ) { this . m_tileWrappingEnabled = enabled ; this . createVisibleTileSet ( ) ; } this . update ( ) ; } @override
     *
     *  param freeContext remarks dispose ( freeContext = true ) { this . DISPOSE_EVENT . time = Date . now ( ) ; this . dispatchEvent ( this . DISPOSE_EVENT ) ; this . m_disposed = true ; if ( this . m_movementFinishedUpdateTimerId ) { clearTimeout ( this . m_movementFinishedUpdateTimerId ) ; this . m_movementFinishedUpdateTimerId = undefined ; } if ( this . m_animationFrameHandle !== undefined ) { cancelAnimationFrame ( this . m_animationFrameHandle ) ; this . m_animationFrameHandle = undefined ; } this . canvas . removeEventListener ( "webglcontextlost" , this . onWebGLContextLost ) ; this . canvas . removeEventListener ( "webglcontextrestored" , this . onWebGLContextRestored ) ; for ( const dataSource of this . m_tileDataSources ) { dataSource . dispose ( ) ; } this . m_visibleTiles . clearTileCache ( ) ; this . m_textElementsRenderer . clearRenderStates ( ) ; this . m_renderer . dispose ( ) ; if ( freeContext ) { this . m_renderer . forceContextLoss ( ) ; } this . m_themeManager . dispose ( ) ; this . m_tileGeometryManager . clear ( ) ; this . m_movementDetector . dispose ( ) ; ConcurrentDecoderFacade . destroyIfTerminated ( ) ; ConcurrentTilerFacade . destroyIfTerminated ( ) ; this . m_taskScheduler . clearQueuedTasks ( ) ; super . dispose ( ) ; } /**
     * Is `true` if dispose() as been called on `MapView`.
     */ get disposed ( ) : boolean { return this . m_disposed ; } /**
     * The way the cache usage is computed, either based on size in MB (mega bytes) or in number of
     * tiles.
     */ get resourceComputationType ( ) : ResourceComputationType { return this . m_visibleTiles . resourceComputationType ; } set resourceComputationType ( value ) { this . m_visibleTiles . resourceComputationType = value ; } /**
     * Returns the cache size.
     */ getCacheSize ( ) { return this . m_visibleTiles . getDataSourceCacheSize ( ) ; } param size param numVisibleTiles setCacheSize ( size , numVisibleTiles ? ) { this . m_visibleTiles . setDataSourceCacheSize ( size ) ; numVisibleTiles = numVisibleTiles !== undefined ? numVisibleTiles : size / 2 ; this . m_visibleTiles . setNumberOfVisibleTiles ( Math . floor ( numVisibleTiles ) ) ; this . m_themeManager . updateCache ( ) ; this . m_textElementsRenderer . invalidateCache ( ) ; this . update ( ) ; } /**
     * Specifies whether extended frustum culling is enabled or disabled.
     */ get extendedFrustumCulling ( ) : boolean { return this . m_options . extendedFrustumCulling !== undefined ? this . m_visibleTileSetOptions . extendedFrustumCulling : true ; } /**
     * Enable of disable extended frustum culling.
     */ set extendedFrustumCulling ( value ) { this . m_visibleTileSetOptions . extendedFrustumCulling = value ; } /**
     * Returns the status of frustum culling after each update.
     */ get lockVisibleTileSet ( ) : boolean { return this . m_visibleTileSetLock ; } /**
     * Enable of disable frustum culling after each update.
     */ set lockVisibleTileSet ( value ) { this . m_visibleTileSetLock = value ; } /**
     * Gets the optional camera used to render the scene.
     */ get pointOfView ( ) : THREE . PerspectiveCamera | undefined { return this . m_pointOfView ; } /**
     * Sets the optional camera used to render the scene.
     */ set pointOfView ( pointOfView ) { this . m_pointOfView = pointOfView ; this . update ( ) ; } param postEffectsFile loadPostEffects ( postEffectsFile ) { fetch ( postEffectsFile ) . then ( response => response . json ( ) ) . then ( ( postEffects ) => { this . m_postEffects = postEffects ; this . setPostEffects ( ) ; } ) ; } /**
     * The abstraction of the  MapRenderingManager API for post effects.
      get postEffects ( ) : PostEffects | undefined { return this . m_postEffects ; } set postEffects ( postEffects ) { this . m_postEffects = postEffects ; this . setPostEffects ( ) ; } deprecated get theme ( ) : Theme { return this . m_themeManager . theme ; } deprecated set theme ( theme ) { this . setTheme ( theme ) ; } /**
     * Changes the `Theme`used by this `MapView`to style map elements.
     */ async setTheme ( theme ) { const newTheme = await this . m_themeManager . setTheme ( theme ) ; this . THEME_LOADED_EVENT . time = Date . now ( ) ; this . dispatchEvent ( this . THEME_LOADED_EVENT ) ; this . update ( ) ; return newTheme ; } /**
     * Returns the currently set `Theme` as a `Promise` as it might be still loading/updating.
     */ async getTheme ( ) { return await this . m_themeManager . getTheme ( ) ; } /**
     *  {@link @here/harp-utils#UriResolver} used to resolve application/deployment
     * specific `URI`s into actual `URLs` that can be loaded with `fetch`.
      get uriResolver ( ) : UriResolver | undefined { return this . m_uriResolver ; } /**
     * Gets the value of the forced custom camera aspect.
     * Every time a frame is rendered, `MapView` resets the camera aspect.
     *
     * You can disable this behavior by setting the value to `undefined`.
     */ get forceCameraAspect ( ) : number | undefined { return this . m_forceCameraAspect ; } /**
     * Sets the custom forced camera aspect ratio to use while rendering.
     */ set forceCameraAspect ( aspect ) { this . m_forceCameraAspect = aspect ; } /**
     * Lists the ISO 639-1 language codes for DataSources to use.
     */ get languages ( ) : string [ ] | undefined { return this . m_languages ; } /**
     * Sets the list of ISO 639-1 language codes for DataSources to use.
     */ set languages ( languages ) { this . m_languages = languages ; this . m_tileDataSources . forEach ( ( dataSource ) => { dataSource . setLanguages ( this . m_languages ) ; } ) ; this . update ( ) ; } note return get politicalView ( ) : string | undefined { return this . m_politicalView ; } note param pov set politicalView ( pov ) { if ( this . m_politicalView === pov ) { return ; } this . m_politicalView = pov ; this . m_tileDataSources . forEach ( ( dataSource ) => { dataSource . setPoliticalView ( pov ) ; } ) ; } get copyrightInfo ( ) : CopyrightInfo [ ] { return this . m_copyrightInfo ; } hidden set disableFading ( disable ) { this . m_textElementsRenderer . disableFading = disable ; } get disableFading ( ) : boolean { return this . m_textElementsRenderer . disableFading ; } hidden get frameNumber ( ) : number { return this . m_frameNumber ; } hidden resetFrameNumber ( ) { this . m_frameNumber = 0 ; this . m_previousFrameTimeStamp = undefined ; } see example param type param listener addEventListener ( type , listener ) ; addEventListener ( type , listener ) { super . addEventListener ( type , listener ) ; } see example param type param listener removeEventListener ( type , listener ? ) ; removeEventListener ( type , listener ? ) { super . removeEventListener ( type , listener ) ; } /**
     * The HTML canvas element used by this `MapView`.
     */ get canvas ( ) : HTMLCanvasElement { return this . m_options . canvas ; } /**
     * The HTML canvas element used by this `MapView`.
     */ get collisionDebugCanvas ( ) : HTMLCanvasElement | undefined { return this . m_collisionDebugCanvas ; } /**
     * The THREE.js scene used by this `MapView`.
     */ get scene ( ) : THREE . Scene { return this . m_scene ; } /**
     * The THREE.js overlay scene
     */ get overlayScene ( ) : THREE . Scene { return this . m_overlayScene ; } internal get sceneEnvironment ( ) : MapViewEnvironment { return this . m_sceneEnvironment ; } remarks When modifying the camera all derived properties like:
     * -  MapView . target * -  MapView . zoomLevel * -  MapView . tilt * -  MapView . heading * could change.
     * These properties are cached internally and will only be updated in the next animation frame.
     * FIXME: Unfortunately THREE.js is not dispatching any events when camera properties change
     * so we should have an API for enforcing update of cached values.
      get camera ( ) : THREE . PerspectiveCamera { return this . m_camera ; } /**
     * The THREE.js `WebGLRenderer` used by this scene.
     */ get renderer ( ) : THREE . WebGLRenderer { return this . m_renderer ; } /**
     * The color used to clear the view.
     */ get clearColor ( ) { const rendererClearColor = this . m_renderer . getClearColor ( cache . color ) ; return rendererClearColor !== undefined ? rendererClearColor . getHex ( ) : 0 ; } /**
     * The color used to clear the view.
     */ set clearColor ( color ) { this . m_renderer . setClearColor ( color ) ; } /**
     * The alpha used to clear the view.
     */ get clearAlpha ( ) { const rendererClearAlpha = this . m_renderer . getClearAlpha ( ) ; return rendererClearAlpha !== undefined ? rendererClearAlpha : 0 ; } /**
     * The alpha used to clear the view.
     */ set clearAlpha ( alpha ) { this . m_renderer . setClearAlpha ( alpha ) ; } /**
     * The projection used to project geo coordinates to world coordinates.
     */ get projection ( ) : Projection { return this . m_visibleTileSetOptions . projection ; } param projection - The  {@link @here/harp-geoutils#Projection} instance to use.
      set projection ( projection ) { const tilt = this . tilt ; const heading = this . heading ; this . m_visibleTileSetOptions . projection = projection ; this . updatePolarDataSource ( ) ; this . clearTileCache ( ) ; this . textElementsRenderer . clearRenderStates ( ) ; this . m_visibleTiles = this . createVisibleTileSet ( ) ; this . geoMaxBounds = this . geoMaxBounds ; this . lookAtImpl ( { tilt , heading } ) ; } /**
     * Get camera clipping planes evaluator used.
     */ get clipPlanesEvaluator ( ) : ClipPlanesEvaluator { return this . m_visibleTileSetOptions . clipPlanesEvaluator ; } /**
     * Changes the clip planes evaluator at run time.
     */ set clipPlanesEvaluator ( clipPlanesEvaluator ) { this . m_visibleTileSetOptions . clipPlanesEvaluator = clipPlanesEvaluator ; } deprecated Use  CameraUtils . getFocalLength get focalLength ( ) : number { const focalLength = CameraUtils . getFocalLength ( this . m_camera ) ?? 0 ; return focalLength ; } remarks This point is not necessarily on the ground, i.e.:
     *  - if the tilt is high and projection is  {@link @here/harp-geoutils#sphereProjection} `
     *  - if the camera was modified directly and is not pointing to the ground.
     * In any case the projection of the target point will be in the center of the screen.
     *
     *  returns get target ( ) : GeoCoordinates { return this . m_targetGeoPos ; } internal remarks note returns get worldTarget ( ) : THREE . Vector3 { return this . m_targetWorldPos ; } internal note returns get targetDistance ( ) : number { return this . m_targetDistance ; } remarks note internal get viewRanges ( ) : ViewRanges { return this . m_viewRanges ; } internal get geoCenter ( ) : GeoCoordinates { return this . projection . unprojectPoint ( this . m_camera . position ) . normalized ( ) ; } remarks set geoCenter ( geoCenter ) { if ( geoCenter . altitude !== undefined ) { this . projection . projectPoint ( geoCenter , this . m_camera . position ) ; } else { const altitude = this . geoCenter . altitude ; this . projection . projectPoint ( new GeoCoordinates ( geoCenter . latitude , geoCenter . longitude , altitude ) , this . m_camera . position ) ; } this . update ( ) ; } /**
     * The node in this MapView's scene containing the user  MapAnchor s.
     *
     *  remarks get mapAnchors ( ) : MapAnchors { return this . m_mapAnchors ; } /**
     * The position in world coordinates of the center of the scene.
     */ get worldCenter ( ) : THREE . Vector3 { return this . m_camera . position ; } /**
     * Get the [[PickHandler]] for this `mapView`.
     */ get pickHandler ( ) : PickHandler { return this . m_pickHandler ; } internal Get the  ImageCache that belongs to this `MapView`.
     *
     * Images stored in this cache are primarily used for POIs (icons) and they are used with the
     * current theme. Although images can be explicitly added and removed from the cache, it is
     * advised not to remove images from this cache. If an image that is part of client code
     * should be removed at any point other than changing the theme, the  useImageCache * should be used instead.
      get imageCache ( ) : MapViewImageCache { return this . m_themeManager . imageCache ; } /**
     * Get the  ImageCache for user images that belongs to this `MapView`.
     *
     * Images added to this cache can be removed if no longer required.
      get userImageCache ( ) : MapViewImageCache { return this . m_userImageCache ; } hidden internal Get the  PoiManager that belongs to this `MapView`.
      get poiManager ( ) : PoiManager { return this . m_poiManager ; } hidden Get the array of  PoiTableManager that belongs to this `MapView`.
      get poiTableManager ( ) : PoiTableManager { return this . m_poiTableManager ; } /**
     * The minimum camera height in meters.
     */ get minCameraHeight ( ) : number { return this . m_minCameraHeight ; } /**
     * The minimum zoom level.
     */ get minZoomLevel ( ) : number { return this . m_minZoomLevel ; } /**
     * The minimum zoom level.
     */ set minZoomLevel ( zoomLevel ) { this . m_minZoomLevel = zoomLevel ; this . update ( ) ; } /**
     * The maximum zoom level. Default is 14.
     */ get maxZoomLevel ( ) : number { return this . m_maxZoomLevel ; } /**
     * The maximum zoom level.
     */ set maxZoomLevel ( zoomLevel ) { this . m_maxZoomLevel = zoomLevel ; this . update ( ) ; } /**
     * The view's maximum bounds in geo coordinates if any.
     */ get geoMaxBounds ( ) : GeoBox | undefined { return this . m_geoMaxBounds ; } remarks set geoMaxBounds ( bounds ) { this . m_geoMaxBounds = bounds ; this . m_worldMaxBounds = this . m_geoMaxBounds ? this . projection . projectBox ( this . m_geoMaxBounds , this . projection . type === ProjectionType . Planar ? new THREE . Box3 ( ) : new OrientedBox3 ( ) ) : undefined ; } hidden internal get worldMaxBounds ( ) : THREE . Box3 | OrientedBox3 | undefined { return this . m_worldMaxBounds ; } /**
     * Returns the zoom level for the given camera setup.
     */ get zoomLevel ( ) : number { return this . m_zoomLevel ; } set zoomLevel ( zoomLevel ) { this . lookAtImpl ( { zoomLevel } ) ; } /**
     * Returns tilt angle in degrees.
     */ get tilt ( ) : number { return THREE . MathUtils . radToDeg ( this . m_pitch ) ; } param tilt set tilt ( tilt ) { this . lookAtImpl ( { tilt } ) ; } /**
     * Returns heading angle in degrees.
     */ get heading ( ) : number { return - THREE . MathUtils . radToDeg ( this . m_yaw ) ; } param heading set heading ( heading ) { this . lookAtImpl ( { heading } ) ; } /**
     * Environment used to evaluate dynamic scene expressions.
     */ get env ( ) : Env { return this . m_env ; } remarks Actual storage level of the rendered data also depends
     * on  DataSource . storageLevelOffset .
      get storageLevel ( ) : number { return THREE . MathUtils . clamp ( Math . floor ( this . m_zoomLevel ) , this . m_minZoomLevel , this . m_maxZoomLevel ) ; } /**
     * Returns height of the viewport in pixels.
     */ get viewportHeight ( ) : number { return this . canvas . height ; } default get nativeWebglAntialiasEnabled ( ) : boolean { return this . m_options . enableNativeWebglAntialias === undefined ? this . pixelRatio < 2.0 : this . m_options . enableNativeWebglAntialias ; } /**
     * Returns  DataSource s displayed by this `MapView`.
      get dataSources ( ) : DataSource [ ] { return this . m_tileDataSources ; } remarks param fovCalculation setFovCalculation ( fovCalculation ) { this . m_options . fovCalculation = fovCalculation ; this . updateCameras ( ) ; } /**
     * Returns the unique  DataSource matching the given name.
      getDataSourceByName ( dataSourceName ) { return this . m_tileDataSources . find ( ds => ds . name === dataSourceName ) ; } /**
     * Returns the array of  DataSource s referring to the same [[StyleSet]].
      getDataSourcesByStyleSetName ( styleSetName ) { return this . m_tileDataSources . filter ( ds => ds . styleSetName === styleSetName ) ; } /**
     * Returns true if the specified  DataSource is enabled.
      isDataSourceEnabled ( dataSource ) { return ( dataSource . enabled && dataSource . ready ( ) && this . m_connectedDataSources . has ( dataSource . name ) && dataSource . isVisible ( this . zoomLevel ) ) ; } /**
     * Adds a new  DataSource to this `MapView`.
     *
     *  remarks `MapView` needs at least one  DataSource to display something.
     *  param dataSource async addDataSource ( dataSource ) { const twinDataSource = this . getDataSourceByName ( dataSource . name ) ; if ( twinDataSource !== undefined ) { throw new Error ( `A DataSource with the name "${ dataSource . name }" already exists in this MapView.` ) ; } dataSource . attach ( this ) ; dataSource . setEnableElevationOverlay ( this . m_elevationProvider !== undefined ) ; const conflictingDataSource = this . m_tileDataSources . find ( ds => ds . addGroundPlane === true && ! ( ds instanceof BackgroundDataSource ) ) ; if ( dataSource . addGroundPlane === true && conflictingDataSource !== undefined ) { console . warn ( `The DataSources ${ dataSource . name } and ${ conflictingDataSource . name } both have a ground plane added, this will cause problems with the fallback logic, see HARP-14728 & HARP-15488.` ) ; } this . m_tileDataSources . push ( dataSource ) ; this . m_sceneEnvironment ?. updateBackgroundDataSource ( ) ; try { await dataSource . connect ( ) ; const alreadyRemoved = ! this . m_tileDataSources . includes ( dataSource ) ; if ( alreadyRemoved ) { return ; } dataSource . addEventListener ( MapViewEventNames . Update , ( ) => { this . update ( ) ; } ) ; const theme = await this . getTheme ( ) ; dataSource . setLanguages ( this . m_languages ) ; if ( theme !== undefined && theme . styles !== undefined ) { await dataSource . setTheme ( theme ) ; } this . m_connectedDataSources . add ( dataSource . name ) ; this . dispatchEvent ( { type : MapViewEventNames . DataSourceConnect , dataSourceName : dataSource . name } ) ; this . update ( ) ; } catch ( error ) { logger . error ( `Failed to connect to datasource ${ dataSource . name }: ${ ( error as Error ) . message ?? error }` ) ; this . m_failedDataSources . add ( dataSource . name ) ; this . dispatchEvent ( { type : MapViewEventNames . DataSourceConnect , dataSourceName : dataSource . name , error } ) ; } } /**
     * Removes  DataSource from this `MapView`.
     *
     *  param dataSource removeDataSource ( dataSource ) { const dsIndex = this . m_tileDataSources . indexOf ( dataSource ) ; if ( dsIndex === - 1 ) { return ; } dataSource . detach ( this ) ; this . m_visibleTiles . removeDataSource ( dataSource ) ; this . m_tileDataSources . splice ( dsIndex , 1 ) ; this . m_connectedDataSources . delete ( dataSource . name ) ; this . m_failedDataSources . delete ( dataSource . name ) ; this . m_sceneEnvironment . updateBackgroundDataSource ( ) ; this . update ( ) ; } /**
     * Access the `VisibleTileSet` to get access to all current datasources and their visible tiles.
     */ get visibleTileSet ( ) : VisibleTileSet { return this . m_visibleTiles ; } param textElements - Array of  TextElement to be added.
      addOverlayText ( textElements ) { this . m_textElementsRenderer . addOverlayText ( textElements ) ; this . update ( ) ; } param textElements - Array of  TextElement to be added.
      clearOverlayText ( ) { this . m_textElementsRenderer . clearOverlayText ( ) ; } remarks #### Note on `target` and `bounds`
     *
     * If `bounds` are specified, `zoomLevel` and `distance` parameters are ignored and `lookAt`
     * calculates best zoomLevel (and possibly target) to fit given bounds.
     *
     * Following table shows how relation between `bounds` and target.
     *
     * | `bounds`             | `target`    | actual `target`
     * | ------               | ------      | --------
     * |  {@link @here/harp-geoutils#GeoBox} | _defined_   | `params.target` is used
     * |  {@link @here/harp-geoutils#GeoBox} | `undefined` | `bounds.center` is used as new `target`
     * |  {@link @here/harp-geoutils#GeoBoxExtentLike} | `undefined` | current `MapView.target` is used
     * |  {@link @here/harp-geoutils#GeoBoxExtentLike} | _defined_   | `params.target` is used
     * | [[GeoCoordLike]][]   | `undefined` | new `target` is calculated as center of world box covering given points
     * | [[GeoCoordLike]][]   | _defined_   | `params.target` is used and zoomLevel is adjusted to view all given geo points
     *
     * In each case, `lookAt` finds minimum `zoomLevel` that covers given extents or geo points.
     *
     * With flat projection, if `bounds` represents points on both sides of anti-meridian, and
     *  MapViewOptions . tileWrappingEnabled is used, `lookAt` will use this knowledge and find
     * minimal view that may cover "next" or "previous" world.
     *
     * With sphere projection if `bounds` represents points on both sides of globe, best effort
     * method is used to find best `target``.
     *
     * #### Examples
     *
     * ```typescript
     * mapView.lookAt({heading: 90})
     *     // look east retaining current `target`, `zoomLevel` and `tilt`
     *
     * mapView.lookAt({lat: 40.707, lng: -74.01})
     *    // look at Manhattan, New York retaining other view params
     *
     * mapView.lookAt(bounds: { latitudeSpan: 10, longitudeSpan: 10})
     *    // look at current `target`, but extending zoomLevel so we see 10 degrees of lat/long span
     * ```
     *
     *  see More param params -  LookAtParams *
     * {@labels WITH_PARAMS}
      lookAt ( params ) ; remarks param target param distance param tiltDeg default param headingDeg default deprecated Use lookAt version with  LookAtParams object parameter.
      lookAt ( target , distance , tiltDeg ? , headingDeg ? ) ; lookAt ( targetOrParams , distance ? , tiltDeg ? , headingDeg ? ) { if ( isGeoCoordinatesLike ( targetOrParams ) ) { const zoomLevel = distance !== undefined ? MapViewUtils . calculateZoomLevelFromDistance ( this , distance ) : undefined ; const params = { target : targetOrParams , zoomLevel , tilt : tiltDeg , heading : headingDeg } ; this . lookAtImpl ( params ) ; } else if ( typeof targetOrParams === "object" ) { this . lookAtImpl ( targetOrParams as Partial < LookAtParams > ) ; } } /**
     * Moves the camera to the specified  {@link @here/harp-geoutils#GeoCoordinates} ,
     * sets the desired `zoomLevel` and
     * adjusts the yaw and pitch.
     *
     *  remarks The pitch of the camera is
     * always curbed so that the camera cannot
     * look above the horizon. This paradigm is necessary
     * in  {@link @here/harp-map-controls#MapControls} , where the center of
     * the screen is used for the orbiting interaction (3 fingers / right mouse button).
     *
     *  param geoPos param zoomLevel param yawDeg param pitchDeg deprecated Use  {@link (MapView.lookAt:WITH_PARAMS)} instead.
      setCameraGeolocationAndZoom ( geoPos , zoomLevel , yawDeg = 0 , pitchDeg = 0 ) { this . geoCenter = geoPos ; let limitedPitch = Math . min ( MapViewUtils . MAX_TILT_DEG , pitchDeg ) ; if ( this . projection . type === ProjectionType . Spherical ) { const maxPitchRadWithCurvature = Math . asin ( EarthConstants . EQUATORIAL_RADIUS / ( MapViewUtils . calculateDistanceToGroundFromZoomLevel ( this , zoomLevel ) + EarthConstants . EQUATORIAL_RADIUS ) ) ; const maxPitchDegWithCurvature = THREE . MathUtils . radToDeg ( maxPitchRadWithCurvature ) ; limitedPitch = Math . min ( limitedPitch , maxPitchDegWithCurvature ) ; } MapViewUtils . zoomOnTargetPosition ( this , 0 , 0 , zoomLevel ) ; MapViewUtils . setRotation ( this , yawDeg , limitedPitch ) ; this . update ( ) ; } remarks param name param value setDynamicProperty ( name , value ) { if ( name . startsWith ( "$" ) ) { throw new Error ( `failed to update the value of the dynamic property '${ name }'` ) ; } this . m_env . entries [ name ] = value ; this . update ( ) ; } /**
     * Removes the given dynamic property from this  MapView .
     *
     *  remarks param name removeDynamicProperty ( name ) { if ( name . startsWith ( "$" ) ) { throw new Error ( `failed to remove the dynamic property '${ name }'` ) ; } delete this . m_env . entries [ name ] ; this . update ( ) ; } /**
     * Returns `true` if this `MapView` is constantly redrawing the scene.
     */ get animating ( ) : boolean { return this . m_animationCount > 0 ; } /**
     * Begin animating the scene.
     */ beginAnimation ( ) { if ( this . m_animationCount ++ === 0 ) { this . update ( ) ; this . ANIMATION_STARTED_EVENT . time = Date . now ( ) ; this . dispatchEvent ( this . ANIMATION_STARTED_EVENT ) ; } } /**
     * Stop animating the scene.
     */ endAnimation ( ) { if ( this . m_animationCount > 0 ) { -- this . m_animationCount ; } if ( this . m_animationCount === 0 ) { this . ANIMATION_FINISHED_EVENT . time = Date . now ( ) ; this . dispatchEvent ( this . ANIMATION_FINISHED_EVENT ) ; } } /**
     * Returns `true` if the camera moved in the last frame.
     */ get cameraIsMoving ( ) { return this . m_movementDetector . cameraIsMoving ; } deprecated This should only be used for the internal handling of the render loop,
     * if you use your own RenderLoop use  MapView in combination with
     *  MapViewEventNames . FrameComplete get isDynamicFrame ( ) : boolean { return ( ! this . m_visibleTiles . allVisibleTilesLoaded || this . m_themeManager . isUpdating ( ) || this . cameraIsMoving || this . animating || this . m_updatePending || this . m_animatedExtrusionHandler . isAnimating || this . m_textElementsRenderer . isUpdatePending || this . m_textElementsRenderer . loading ) ; } /**
     * Returns the ratio between a pixel and a world unit for the current camera (in the center of
     * the camera projection).
     */ get pixelToWorld ( ) : number { if ( this . m_pixelToWorld === undefined ) { assert ( this . m_options . fovCalculation !== undefined ) ; const lookAtDistance = this . m_targetDistance ; const focalLength = CameraUtils . getFocalLength ( this . m_camera ) ; assert ( focalLength !== undefined ) ; this . m_pixelToWorld = CameraUtils . convertScreenToWorldSize ( focalLength ! , lookAtDistance , 1 ) ; } return this . m_pixelToWorld ; } /**
     * Returns the ratio between a world and a pixel unit for the current camera (in the center of
     * the camera projection).
     */ get worldToPixel ( ) { return 1.0 / this . pixelToWorld ; } get pixelRatio ( ) : number { if ( this . m_pixelRatio !== undefined ) { return this . m_pixelRatio ; } return typeof window !== "undefined" && window . devicePixelRatio !== undefined ? window . devicePixelRatio : 1.0 ; } remarks note memberof set pixelRatio ( pixelRatio ) { this . m_pixelRatio = pixelRatio ; if ( this . renderer . getPixelRatio ( ) !== this . pixelRatio ) { this . renderer . setPixelRatio ( this . pixelRatio ) ; } } remarks set maxFps ( value ) { this . m_options . maxFps = value ; this . m_taskScheduler . maxFps = value ; } get maxFps ( ) : number { return this . m_options . maxFps as number ; } remarks note note default set dynamicPixelRatio ( ratio ) { this . mapRenderingManager . lowResPixelRatio = ratio ; } get dynamicPixelRatio ( ) : number | undefined { return this . mapRenderingManager . lowResPixelRatio ; } param pos - The position as a  {@link @here/harp-geoutils#GeoCoordLike} or
     *  https world position.
     *  returns getScreenPosition ( pos ) { if ( isVector3Like ( pos ) ) { cache . vector3 [ 0 ] . copy ( pos ) ; } else { this . projection . projectPoint ( GeoCoordinates . fromObject ( pos ) , cache . vector3 [ 0 ] ) ; } const p = this . m_screenProjector . project ( cache . vector3 [ 0 ] ) ; if ( p !== undefined ) { const { width , height } = this . getCanvasClientSize ( ) ; p . x = p . x + width / 2 ; p . y = height - ( p . y + height / 2 ) ; } return p ; } getWorldPositionAt ( x , y , fallback ) ; getWorldPositionAt ( x , y , fallback ? ) ; remarks param x param y param fallback getWorldPositionAt ( x , y , fallback ? ) { this . m_raycaster . setFromCamera ( this . getNormalizedScreenCoordinates ( x , y ) , this . m_camera ) ; const worldPos = this . projection . type === ProjectionType . Spherical ? this . m_raycaster . ray . intersectSphere ( this . m_sphere , cache . vector3 [ 0 ] ) : this . m_raycaster . ray . intersectPlane ( this . m_plane , cache . vector3 [ 0 ] ) ; if ( worldPos === null && fallback === true ) { const cosAlpha = this . m_camera . getWorldDirection ( cache . vector3 [ 0 ] ) . dot ( this . m_raycaster . ray . direction ) ; return cache . vector3 [ 0 ] . copy ( this . m_raycaster . ray . direction ) . multiplyScalar ( this . m_camera . far / cosAlpha ) . add ( this . m_camera . position ) ; } return worldPos ; } /**
     * Same as  MapView . getGeoCoordinatesAt but always returning a geo coordinate.
      getGeoCoordinatesAt ( x , y , fallback ) ; /**
     * Returns the  {@link @here/harp-geoutils#GeoCoordinates} from the
     * given screen position.
     *
     *  remarks If `fallback !== true` the return value can be `null`, in case the camera has a high tilt
     * and the given `(x, y)` value is not intersecting the ground plane.
     * If `fallback === true` the return value will always exist but it might not be on the earth
     * surface.
     * If  MapView . tileWrappingEnabled is `true` the returned geo coordinates will have a
     * longitude clamped to [-180,180] degrees.
     * The returned geo coordinates are not normalized so that a map object placed at that position
     * will be below the (x,y) screen coordinates, regardless which world repetition was on screen.
     *
     *  param x param y param fallback returns getGeoCoordinatesAt ( x , y , fallback ? ) ; getGeoCoordinatesAt ( x , y , fallback ? ) { const worldPosition = this . getWorldPositionAt ( x , y , fallback ) ; if ( ! worldPosition ) { return null ; } const geoPos = this . projection . unprojectPoint ( worldPosition ) ; if ( ! this . tileWrappingEnabled && this . projection . type === ProjectionType . Planar ) { geoPos . longitude = THREE . MathUtils . clamp ( geoPos . longitude , - 180 , 180 ) ; } return geoPos ; } param x param y getNormalizedScreenCoordinates ( x , y ) { const { width , height } = this . getCanvasClientSize ( ) ; return new THREE . Vector3 ( ( x / width ) * 2 - 1 , - ( ( y / height ) * 2 ) + 1 , 0 ) ; } remarks Limited to objects that THREE.js can raycast, the solid lines
     * that get their geometry in the shader cannot be tested
     * for intersection.
     *
     * Note, if a  DataSource adds an [[Object3D]]
     * to a  Tile , it will be only pickable once
     *  MapView . render has been called, this is because
     *  MapView . render method creates the
     * internal three.js root [[Object3D]] which is used in the [[PickHandler]] internally.
     * This method will not test for intersection custom objects added to the scene by for
     * example calling directly the [[scene.add]] method from THREE.
     *
     *  param x param y param parameters - The intersection test behaviour may be adjusted by providing an instance
     * of  IntersectParams .
     *  returns intersectMapObjects ( x , y , parameters ? ) { return this . m_pickHandler . intersectMapObjects ( x , y , parameters ) ; } param width param height resize ( width , height ) { this . m_renderer . setSize ( width , height , false ) ; if ( this . m_renderer . getPixelRatio ( ) !== this . pixelRatio ) { this . m_renderer . setPixelRatio ( this . pixelRatio ) ; } if ( this . mapRenderingManager !== undefined ) { this . mapRenderingManager . setSize ( width , height ) ; } if ( this . collisionDebugCanvas !== undefined ) { this . collisionDebugCanvas . width = width ; this . collisionDebugCanvas . height = height ; } this . updateCameras ( ) ; this . update ( ) ; this . dispatchEvent ( { type : MapViewEventNames . Resize , size : { width , height } } ) ; } remarks note Before using this method, set `synchronousRendering` to `true`
     * in the  MapViewOptions param frameStartTime renderSync ( frameStartTime ? ) { if ( frameStartTime === undefined ) { frameStartTime = PerformanceTimer . now ( ) ; } this . render ( frameStartTime ) ; } /**
     * Requests a redraw of the scene.
     */ update ( ) { if ( this . disposed ) { logger . warn ( "update(): MapView has been disposed of." ) ; return ; } this . dispatchEvent ( this . UPDATE_EVENT ) ; if ( this . m_updatePending ) { return ; } this . m_updatePending = true ; this . startRenderLoop ( ) ; } /**
     * Returns `true` if an update has already been requested, such that after a currently rendering
     * frame, the next frame will be rendered immediately.
     */ get updatePending ( ) : boolean { return this . m_updatePending ; } deprecated requestUpdateIfNeeded ( ) { this . update ( ) ; } remarks Remove the  Tile objects created by cacheable
     *  DataSource s. If a  DataSource name is
     * provided, this method restricts the eviction the  DataSource with the given name.
     *
     *  param dataSourceName - The name of the  DataSource .
     *  param filter clearTileCache ( dataSourceName ? , filter ? ) { if ( this . m_visibleTiles === undefined ) { return ; } if ( dataSourceName !== undefined ) { const dataSource = this . getDataSourceByName ( dataSourceName ) ; if ( dataSource ) { this . m_visibleTiles . clearTileCache ( dataSource , filter ) ; dataSource . clearCache ( ) ; } } else { this . m_visibleTiles . clearTileCache ( undefined , filter ) ; this . m_tileDataSources . forEach ( dataSource => dataSource . clearCache ( ) ) ; } if ( this . m_elevationProvider !== undefined ) { this . m_elevationProvider . clearCache ( ) ; } } param fun forEachVisibleTile ( fun ) { this . m_visibleTiles . forEachVisibleTile ( fun ) ; } param visitor forEachCachedTile ( visitor ) { this . m_visibleTiles . forEachCachedTile ( visitor ) ; } remarks param dataSource - If passed, only the tiles from this  DataSource instance
     * are processed. If `undefined`, tiles from all  DataSource s are processed.
     *  param filter markTilesDirty ( dataSource ? , filter ? ) { this . m_visibleTiles . markTilesDirty ( dataSource , filter ) ; this . update ( ) ; } remarks Only a single elevation source is possible per  MapView .
     * If the terrain-datasource is merged with this repository, we could internally construct
     * the  ElevationRangeSource and the  ElevationProvider * and access would be granted to
     * the application when it asks for it, to simplify the API.
     *
     *  param elevationSource param elevationRangeSource param elevationProvider async setElevationSource ( elevationSource , elevationRangeSource , elevationProvider ) { if ( this . m_elevationSource && this . m_elevationSource !== elevationSource ) { this . removeDataSource ( this . m_elevationSource ) ; } const isPresent = this . m_tileDataSources . includes ( elevationSource ) ; if ( ! isPresent ) { await this . addDataSource ( elevationSource ) ; } this . m_elevationSource = elevationSource ; this . m_elevationRangeSource = elevationRangeSource ; if ( ! this . m_elevationRangeSource . ready ( ) ) { await this . m_elevationRangeSource . connect ( ) ; } this . m_elevationProvider = elevationProvider ; this . dataSources . forEach ( dataSource => { dataSource . setEnableElevationOverlay ( true ) ; } ) ; this . m_tileGeometryManager . setTileUpdateCallback ( ( tile ) => { overlayOnElevation ( tile ) ; } ) ; this . clearTileCache ( ) ; } param elevationSource clearElevationSource ( elevationSource ) { this . removeDataSource ( elevationSource ) ; this . m_elevationSource = undefined ; this . m_elevationRangeSource = undefined ; this . m_elevationProvider = undefined ; this . dataSources . forEach ( dataSource => { dataSource . setEnableElevationOverlay ( false ) ; } ) ; this . m_tileGeometryManager . setTileUpdateCallback ( undefined ) ; this . clearTileCache ( ) ; } /**
     * Public access to  MapViewFog allowing to toggle it by setting its `enabled` property.
      get fog ( ) : MapViewFog { return this . m_sceneEnvironment . fog ; } private setPostEffects ( ) { this . mapRenderingManager . bloom . enabled = false ; this . mapRenderingManager . outline . enabled = false ; this . mapRenderingManager . vignette . enabled = false ; this . mapRenderingManager . sepia . enabled = false ; if ( this . m_postEffects !== undefined ) { if ( this . m_postEffects . bloom !== undefined ) { this . mapRenderingManager . bloom = this . m_postEffects . bloom ; } if ( this . m_postEffects . outline !== undefined ) { this . mapRenderingManager . outline . enabled = this . m_postEffects . outline . enabled ; this . mapRenderingManager . updateOutline ( this . m_postEffects . outline ) ; } if ( this . m_postEffects . vignette !== undefined ) { this . mapRenderingManager . vignette = this . m_postEffects . vignette ; } if ( this . m_postEffects . sepia !== undefined ) { this . mapRenderingManager . sepia = this . m_postEffects . sepia ; } } } /**
     * Returns the elevation provider.
     */ get elevationProvider ( ) : ElevationProvider | undefined { return this . m_elevationProvider ; } beta get throttlingEnabled ( ) : boolean { return this . m_taskScheduler . throttlingEnabled === true ; } beta set throttlingEnabled ( enabled ) { this . m_taskScheduler . throttlingEnabled = enabled ; } get shadowsEnabled ( ) : boolean { return this . m_options . enableShadows === true ; } set shadowsEnabled ( enabled ) { if ( this . m_renderer . shadowMap === undefined || enabled === this . m_renderer . shadowMap . enabled ) { return ; } this . m_options . enableShadows = enabled ; this . m_renderer . shadowMap . enabled = enabled ; this . m_renderer . shadowMap . type = THREE . PCFSoftShadowMap ; this . clearTileCache ( ) ; } private extractAttitude ( ) { const camera = this . m_camera ; const projection = this . projection ; const cameraPos = cache . vector3 [ 1 ] ; const transform = cache . transform [ 0 ] ; const tangentSpaceMatrix = cache . matrix4 [ 1 ] ; cameraPos . setFromMatrixPosition ( camera . matrixWorld ) ; projection . localTangentSpace ( this . m_targetGeoPos , transform ) ; tangentSpaceMatrix . makeBasis ( transform . xAxis , transform . yAxis , transform . zAxis ) ; cache . matrix4 [ 0 ] . copy ( tangentSpaceMatrix ) . invert ( ) . multiply ( camera . matrixWorld ) ; transform . xAxis . setFromMatrixColumn ( cache . matrix4 [ 0 ] , 0 ) ; transform . yAxis . setFromMatrixColumn ( cache . matrix4 [ 0 ] , 1 ) ; transform . zAxis . setFromMatrixColumn ( cache . matrix4 [ 0 ] , 2 ) ; let yaw = 0 ; let pitch = 0 ; let roll = 0 ; const epsilon = 1e-10 ; const d = transform . zAxis . dot ( cameraPos . set ( 0 , 0 , 1 ) ) ; if ( d < 1.0 - epsilon ) { if ( d > - 1.0 + epsilon ) { yaw = Math . atan2 ( transform . zAxis . x , - transform . zAxis . y ) ; pitch = Math . acos ( transform . zAxis . z ) ; roll = Math . atan2 ( transform . xAxis . x , transform . yAxis . z ) ; } else { yaw = - Math . atan2 ( - transform . yAxis . x , transform . xAxis . x ) ; pitch = 180 ; roll = 0 ; } } else { yaw = Math . atan2 ( - transform . yAxis . x , transform . xAxis . x ) ; pitch = 0.0 ; roll = 0.0 ; } return { yaw , pitch , roll } ; } private lookAtImpl ( params ) { const tilt = Math . min ( getOptionValue ( params . tilt , this . tilt ) , MapViewUtils . MAX_TILT_DEG ) ; const heading = getOptionValue ( params . heading , this . heading ) ; const distance = params . zoomLevel !== undefined ? MapViewUtils . calculateDistanceFromZoomLevel ( this , THREE . MathUtils . clamp ( params . zoomLevel , this . m_minZoomLevel , this . m_maxZoomLevel ) ) : params . distance !== undefined ? params . distance : this . m_targetDistance ; let target ; if ( params . bounds !== undefined ) { let geoPoints ; if ( params . bounds instanceof GeoBox ) { target = params . target ? GeoCoordinates . fromObject ( params . target ) : params . bounds . center ; geoPoints = MapViewUtils . geoBoxToGeoPoints ( params . bounds ) ; } else if ( params . bounds instanceof GeoPolygon ) { target = params . bounds . getCentroid ( ) ; geoPoints = params . bounds . coordinates ; } else if ( isGeoBoxExtentLike ( params . bounds ) ) { target = params . target ? GeoCoordinates . fromObject ( params . target ) : this . target ; const box = GeoBox . fromCenterAndExtents ( target , params . bounds ) ; geoPoints = MapViewUtils . geoBoxToGeoPoints ( box ) ; } else if ( Array . isArray ( params . bounds ) ) { geoPoints = params . bounds ; if ( params . target !== undefined ) { target = GeoCoordinates . fromObject ( params . target ) ; } } else { throw Error ( "#lookAt: Invalid 'bounds' value" ) ; } if ( ! ( params . bounds instanceof GeoBox || params . bounds instanceof GeoPolygon ) && this . m_tileWrappingEnabled && this . projection . type === ProjectionType . Planar ) { geoPoints = MapViewUtils . wrapGeoPointsToScreen ( geoPoints , target ! ) ; } const worldPoints = geoPoints . map ( point => this . projection . projectPoint ( GeoCoordinates . fromObject ( point ) , new THREE . Vector3 ( ) ) ) ; const worldTarget = new THREE . Vector3 ( ) ; if ( target ! === undefined ) { const box = new THREE . Box3 ( ) . setFromPoints ( worldPoints ) ; box . getCenter ( worldTarget ) ; this . projection . scalePointToSurface ( worldTarget ) ; target = this . projection . unprojectPoint ( worldTarget ) ; } else { this . projection . projectPoint ( target , worldTarget ) ; } if ( params . zoomLevel !== undefined || params . distance !== undefined ) { return this . lookAtImpl ( { tilt , heading , distance , target } ) ; } return this . lookAtImpl ( MapViewUtils . getFitBoundsLookAtParams ( target , worldTarget , worldPoints , { tilt , heading , minDistance : MapViewUtils . calculateDistanceFromZoomLevel ( this , this . maxZoomLevel ) , projection : this . projection , camera : this . camera } ) ) ; } target = params . target !== undefined ? GeoCoordinates . fromObject ( params . target ) : this . target ; MapViewUtils . getCameraRotationAtTarget ( this . projection , target , - heading , tilt , this . camera . quaternion ) ; MapViewUtils . getCameraPositionFromTargetCoordinates ( target , distance , - heading , tilt , this . projection , this . camera . position ) ; this . camera . updateMatrixWorld ( true ) ; this . updateLookAtSettings ( ) ; this . update ( ) ; } /**
     * Plug-in PolarTileDataSource for spherical projection and plug-out otherwise
     */ private updatePolarDataSource ( ) { const dataSource = this . m_polarDataSource ; if ( this . m_enablePolarDataSource === true && dataSource !== undefined ) { const twinDataSource = this . getDataSourceByName ( dataSource . name ) ; if ( this . projection . type === ProjectionType . Spherical ) { if ( twinDataSource === undefined ) { this . addDataSource ( dataSource ) ; } } else { if ( twinDataSource !== undefined ) { this . removeDataSource ( dataSource ) ; } } } } remarks param viewRanges - optional parameter that supplies new view ranges, most importantly
     * near/far clipping planes distance. If parameter is not provided view ranges will be
     * calculated from [[ClipPlaneEvaluator]] used in  VisibleTileSet .
      private updateCameras ( viewRanges ? ) { this . m_camera . updateMatrixWorld ( false ) ; this . updateLookAtSettings ( ) ; const { width , height } = this . m_renderer . getSize ( cache . vector2 [ 0 ] ) ; this . m_camera . aspect = this . m_forceCameraAspect !== undefined ? this . m_forceCameraAspect : width / height ; this . setFovOnCamera ( this . m_options . fovCalculation ! , height ) ; const projectionScale = this . projection . getScaleFactor ( this . camera . position ) ; const maxGeometryHeightScaled = projectionScale * this . m_tileDataSources . reduce ( ( r , ds ) => Math . max ( r , ds . maxGeometryHeight ) , 0 ) ; const minGeometryHeightScaled = projectionScale * this . m_tileDataSources . reduce ( ( r , ds ) => Math . min ( r , ds . minGeometryHeight ) , 0 ) ; Object . assign ( this . m_viewRanges , viewRanges === undefined ? this . m_visibleTiles . updateClipPlanes ( maxGeometryHeightScaled , minGeometryHeightScaled ) : viewRanges ) ; this . m_camera . near = this . m_viewRanges . near ; this . m_camera . far = this . m_viewRanges . far ; this . m_camera . updateProjectionMatrix ( ) ; this . m_rteCamera . copy ( this . m_camera ) ; this . m_rteCamera . position . setScalar ( 0 ) ; this . m_rteCamera . updateMatrixWorld ( true ) ; this . m_textElementsRenderer ?. updateCamera ( ) ; this . m_screenProjector . update ( this . camera , width , height ) ; this . m_pixelToWorld = undefined ; this . m_sceneEnvironment . update ( ) ; } /**
     * Derive the look at settings (i.e. target, zoom, ...) from the current camera.
     */ private updateLookAtSettings ( ) { let { target , distance , final } = MapViewUtils . getTargetAndDistance ( this . projection , this . camera , this . elevationProvider ) ; if ( ! final ) { this . update ( ) ; } if ( this . geoMaxBounds ) { ( { target , distance } = MapViewUtils . constrainTargetAndDistanceToViewBounds ( target , distance , this ) ) ; } this . m_targetWorldPos . copy ( target ) ; this . m_targetGeoPos = this . projection . unprojectPoint ( this . m_targetWorldPos ) ; this . m_targetDistance = distance ; this . m_zoomLevel = MapViewUtils . calculateZoomLevelFromDistance ( this , this . m_targetDistance ) ; const { yaw , pitch , roll } = this . extractAttitude ( ) ; this . m_yaw = yaw ; this . m_pitch = pitch ; this . m_roll = roll ; } /**
     * Update `Env` instance used for style `Expr` evaluations.
     */ private updateEnv ( ) { this . m_env . entries . $zoom = this . m_zoomLevel ; this . m_env . entries . $pixelToMeters = this . pixelToWorld ; this . m_env . entries . $frameNumber = this . m_frameNumber ; } param vector param result public ndcToView ( vector , result ) { result . set ( vector . x , vector . y , vector . z ) . applyMatrix4 ( this . camera . projectionMatrixInverse ) . applyMatrix4 ( this . m_rteCamera . matrixWorld ) ; return result ; } param frameStartTime private renderLoop ( frameStartTime ) { if ( this . m_options . synchronousRendering === true || this . disposed ) { return ; } if ( this . maxFps === 0 ) { this . render ( frameStartTime ) ; } else { const fudgeTimeInMs = 3 ; const frameInterval = 1000 / this . maxFps ; const previousFrameTime = this . m_previousFrameTimeStamp === undefined ? 0 : this . m_previousFrameTimeStamp ; const targetTime = previousFrameTime + frameInterval - fudgeTimeInMs ; if ( frameStartTime >= targetTime ) { this . render ( frameStartTime ) ; } } if ( this . isDynamicFrame ) { this . m_animationFrameHandle = requestAnimationFrame ( this . handleRequestAnimationFrame ) ; } else { this . m_animationFrameHandle = undefined ; } } /**
     * Start render loop if not already running.
     */ private startRenderLoop ( ) { if ( this . m_animationFrameHandle !== undefined || this . m_options . synchronousRendering ) { return ; } this . m_animationFrameHandle = requestAnimationFrame ( this . handleRequestAnimationFrame ) ; } /**
     * Returns the list of the enabled data sources.
     */ private getEnabledTileDataSources ( ) { const enabledDataSources = [ ] ; for ( const dataSource of this . m_tileDataSources ) { if ( this . isDataSourceEnabled ( dataSource ) ) { enabledDataSources . push ( dataSource ) ; } } return enabledDataSources ; } /**
     * Renders the current frame.
     */ private render ( frameStartTime ) { if ( this . m_drawing ) { return ; } if ( this . disposed ) { logger . warn ( "render(): MapView has been disposed of." ) ; return ; } this . RENDER_EVENT . time = frameStartTime ; this . dispatchEvent ( this . RENDER_EVENT ) ; this . m_tileObjectRenderer . prepareRender ( ) ; ++ this . m_frameNumber ; let currentFrameEvent ; const stats = PerformanceStatistics . instance ; const gatherStatistics = stats . enabled ; if ( gatherStatistics ) { currentFrameEvent = stats . currentFrame ; if ( this . m_previousFrameTimeStamp !== undefined ) { const timeSincePreviousFrame = frameStartTime - this . m_previousFrameTimeStamp ; currentFrameEvent . setValue ( "render.fps" , 1000 / timeSincePreviousFrame ) ; } stats . storeAndClearFrameInfo ( ) ; currentFrameEvent = currentFrameEvent as FrameStats ; currentFrameEvent . setValue ( "renderCount.frameNumber" , this . m_frameNumber ) ; } this . m_previousFrameTimeStamp = frameStartTime ; let setupTime ; let cullTime ; let textPlacementTime ; let drawTime ; let textDrawTime ; let endTime ; this . m_renderer . info . reset ( ) ; this . m_updatePending = false ; this . m_thisFrameTilesChanged = undefined ; this . m_drawing = true ; if ( this . m_renderer . getPixelRatio ( ) !== this . pixelRatio ) { this . m_renderer . setPixelRatio ( this . pixelRatio ) ; } this . updateCameras ( ) ; this . updateEnv ( ) ; this . m_renderer . clear ( ) ; this . m_sceneRoot . children . length = 0 ; this . m_overlaySceneRoot . children . length = 0 ; if ( gatherStatistics ) { setupTime = PerformanceTimer . now ( ) ; } if ( ! this . lockVisibleTileSet ) { const viewRangesStatus = this . m_visibleTiles . updateRenderList ( this . storageLevel , Math . floor ( this . zoomLevel ) , this . getEnabledTileDataSources ( ) , this . m_frameNumber , this . m_elevationRangeSource ) ; if ( viewRangesStatus . viewRangesChanged ) { this . updateCameras ( viewRangesStatus . viewRanges ) ; } } if ( gatherStatistics ) { cullTime = PerformanceTimer . now ( ) ; } const renderList = this . m_visibleTiles . dataSourceTileList ; renderList . forEach ( ( { zoomLevel , renderedTiles } ) => { renderedTiles . forEach ( tile => { this . m_tileObjectRenderer . render ( tile , zoomLevel , this . zoomLevel , this . m_camera . position , this . m_sceneRoot ) ; tile . frameNumLastVisible = this . m_frameNumber ; } ) ; } ) ; this . m_mapAnchors . update ( this . projection , this . camera . position , this . m_sceneRoot , this . m_overlaySceneRoot ) ; this . m_animatedExtrusionHandler . update ( this . zoomLevel ) ; if ( currentFrameEvent !== undefined ) { currentFrameEvent . addValue ( "renderCount.numTilesRendered" , 0 ) ; currentFrameEvent . addValue ( "renderCount.numTilesVisible" , 0 ) ; currentFrameEvent . addValue ( "renderCount.numTilesLoading" , 0 ) ; renderList . forEach ( ( { zoomLevel , renderedTiles , visibleTiles , numTilesLoading } ) => { currentFrameEvent ! . addValue ( "renderCount.numTilesRendered" , renderedTiles . size ) ; currentFrameEvent ! . addValue ( "renderCount.numTilesVisible" , visibleTiles . length ) ; currentFrameEvent ! . addValue ( "renderCount.numTilesLoading" , numTilesLoading ) ; } ) ; } if ( this . m_movementDetector . checkCameraMoved ( this , frameStartTime ) ) { const { latitude , longitude , altitude } = this . geoCenter ; this . dispatchEvent ( { type : MapViewEventNames . CameraPositionChanged , latitude , longitude , altitude , yaw : this . m_yaw , pitch : this . m_pitch , roll : this . m_roll , tilt : this . tilt , heading : this . heading , zoom : this . zoomLevel } ) ; } const camera = this . m_pointOfView !== undefined ? this . m_pointOfView : this . m_rteCamera ; if ( this . renderLabels && ! this . m_pointOfView ) { this . m_textElementsRenderer . placeText ( renderList , frameStartTime ) ; } if ( gatherStatistics ) { textPlacementTime = PerformanceTimer . now ( ) ; } this . mapRenderingManager . render ( this . m_renderer , this . m_scene , camera , ! this . isDynamicFrame ) ; if ( gatherStatistics ) { drawTime = PerformanceTimer . now ( ) ; } if ( this . renderLabels && ! this . m_pointOfView ) { this . m_textElementsRenderer . renderText ( this . m_viewRanges . maximum ) ; } if ( this . m_overlaySceneRoot . children . length > 0 ) { this . m_renderer . render ( this . m_overlayScene , camera ) ; } if ( gatherStatistics ) { textDrawTime = PerformanceTimer . now ( ) ; } if ( ! this . m_firstFrameRendered ) { this . m_firstFrameRendered = true ; if ( gatherStatistics ) { stats . appResults . set ( "firstFrame" , frameStartTime ) ; } this . FIRST_FRAME_EVENT . time = frameStartTime ; this . dispatchEvent ( this . FIRST_FRAME_EVENT ) ; } this . m_visibleTiles . disposePendingTiles ( ) ; this . m_drawing = false ; this . checkCopyrightUpdates ( ) ; if ( this . m_taskSchedulerTimeout !== undefined ) { clearTimeout ( this . m_taskSchedulerTimeout ) ; } this . m_taskSchedulerTimeout = setTimeout ( ( ) => { this . m_taskSchedulerTimeout = undefined ; this . m_taskScheduler . processPending ( frameStartTime ) ; } , 0 ) ; if ( currentFrameEvent !== undefined ) { endTime = PerformanceTimer . now ( ) ; const frameRenderTime = endTime - frameStartTime ; currentFrameEvent . setValue ( "render.setupTime" , setupTime ! - frameStartTime ) ; currentFrameEvent . setValue ( "render.cullTime" , cullTime ! - setupTime ! ) ; currentFrameEvent . setValue ( "render.textPlacementTime" , textPlacementTime ! - cullTime ! ) ; currentFrameEvent . setValue ( "render.drawTime" , drawTime ! - textPlacementTime ! ) ; currentFrameEvent . setValue ( "render.textDrawTime" , textDrawTime ! - drawTime ! ) ; currentFrameEvent . setValue ( "render.cleanupTime" , endTime - textDrawTime ! ) ; currentFrameEvent . setValue ( "render.frameRenderTime" , frameRenderTime ) ; currentFrameEvent . setValue ( "render.fullFrameTime" , frameRenderTime ) ; currentFrameEvent . setValue ( "render.geometryCreationTime" , 0 ) ; stats . addWebGLInfo ( this . m_renderer . info ) ; stats . addMemoryInfo ( ) ; } this . DID_RENDER_EVENT . time = frameStartTime ; this . dispatchEvent ( this . DID_RENDER_EVENT ) ; if ( ! this . isDynamicFrame ) { if ( this . m_firstFrameComplete === false ) { this . m_firstFrameComplete = true ; if ( gatherStatistics ) { stats . appResults . set ( "firstFrameComplete" , frameStartTime ) ; } } this . FRAME_COMPLETE_EVENT . time = frameStartTime ; this . dispatchEvent ( this . FRAME_COMPLETE_EVENT ) ; } } private setupCamera ( ) { assert ( this . m_visibleTiles !== undefined ) ; this . m_options . target = GeoCoordinates . fromObject ( getOptionValue ( this . m_options . target , MapViewDefaults . target ) ) ; ( this . m_options . target as GeoCoordinates ) . altitude = 0 ; this . m_options . tilt = getOptionValue ( this . m_options . tilt , MapViewDefaults . tilt ) ; this . m_options . heading = getOptionValue ( this . m_options . heading , MapViewDefaults . heading ) ; this . m_options . zoomLevel = getOptionValue ( this . m_options . zoomLevel , MapViewDefaults . zoomLevel ) ; this . lookAtImpl ( this . m_options ) ; const { width , height } = this . getCanvasClientSize ( ) ; this . resize ( width , height ) ; } private createVisibleTileSet ( ) { assert ( this . m_tileGeometryManager !== undefined ) ; if ( this . m_visibleTiles ) { this . m_visibleTiles . clearTileCache ( ) ; this . m_visibleTiles . disposePendingTiles ( ) ; } const enableMixedLod = this . m_enableMixedLod === undefined ? this . projection . type === ProjectionType . Spherical : this . m_enableMixedLod ; this . m_visibleTiles = new VisibleTileSet ( new FrustumIntersection ( this . m_camera , this , this . m_visibleTileSetOptions . extendedFrustumCulling , this . m_tileWrappingEnabled , enableMixedLod , this . m_lodMinTilePixelSize ) , this . m_tileGeometryManager , this . m_visibleTileSetOptions , this . taskQueue ) ; return this . m_visibleTiles ; } private movementStarted ( ) { this . m_textElementsRenderer . movementStarted ( ) ; this . MOVEMENT_STARTED_EVENT . time = Date . now ( ) ; this . dispatchEvent ( this . MOVEMENT_STARTED_EVENT ) ; } private movementFinished ( ) { this . m_textElementsRenderer . movementFinished ( ) ; this . MOVEMENT_FINISHED_EVENT . time = Date . now ( ) ; this . dispatchEvent ( this . MOVEMENT_FINISHED_EVENT ) ; if ( ! this . animating ) { if ( this . m_movementFinishedUpdateTimerId !== undefined ) { clearTimeout ( this . m_movementFinishedUpdateTimerId ) ; } this . m_movementFinishedUpdateTimerId = setTimeout ( ( ) => { this . m_movementFinishedUpdateTimerId = undefined ; this . update ( ) ; } , 0 ) ; } } /**
     * Check if the set of visible tiles changed since the last frame.
     *
     * May be called multiple times per frame.
     *
     * Equality is computed by creating a string containing the IDs of the tiles.
     */ private checkIfTilesChanged ( ) { if ( this . m_thisFrameTilesChanged !== undefined ) { return this . m_thisFrameTilesChanged ; } const renderList = this . m_visibleTiles . dataSourceTileList ; const tileIdList = [ ] ; tileIdList . length = 0 ; renderList . forEach ( ( { dataSource , renderedTiles } ) => { renderedTiles . forEach ( tile => { tileIdList . push ( dataSource . name + "-" + tile . tileKey . mortonCode ( ) ) ; } ) ; } ) ; tileIdList . sort ( ) ; const newTileIds = tileIdList . join ( "#" ) ; if ( newTileIds !== this . m_lastTileIds ) { this . m_lastTileIds = newTileIds ; this . m_thisFrameTilesChanged = true ; } else { this . m_thisFrameTilesChanged = false ; } return this . m_thisFrameTilesChanged ; } private checkCopyrightUpdates ( ) { if ( ! this . checkIfTilesChanged ( ) ) { return ; } const newCopyrightInfo = this . getRenderedTilesCopyrightInfo ( ) ; if ( newCopyrightInfo === this . m_copyrightInfo ) { return ; } if ( newCopyrightInfo . length === this . m_copyrightInfo . length ) { let allEqual = true ; for ( let i = 0 ; i < newCopyrightInfo . length ; i ++ ) { const a = newCopyrightInfo [ i ] ; const b = this . m_copyrightInfo [ i ] ; if ( a . label !== b . label ) { allEqual = false ; break ; } } if ( allEqual ) { return ; } } this . m_copyrightInfo = newCopyrightInfo ; this . dispatchEvent ( this . COPYRIGHT_CHANGED_EVENT ) ; } private getRenderedTilesCopyrightInfo ( ) { let result = [ ] ; for ( const tileList of this . m_visibleTiles . dataSourceTileList ) { for ( const tile of tileList . renderedTiles . values ( ) ) { const tileCopyrightInfo = tile . copyrightInfo ; if ( tileCopyrightInfo === undefined || tileCopyrightInfo . length === 0 ) { continue ; } result = CopyrightInfo . mergeArrays ( result , tileCopyrightInfo ) ; } } return result ; } private setupStats ( enable ) { new PerformanceStatistics ( enable , 1000 ) ; } private setupRenderer ( tileObjectRenderer ) { this . m_scene . add ( this . m_sceneRoot ) ; this . m_overlayScene . add ( this . m_overlaySceneRoot ) ; this . shadowsEnabled = this . m_options . enableShadows ?? false ; tileObjectRenderer . setupRenderer ( ) ; } private createTextRenderer ( ) { return new TextElementsRenderer ( new MapViewState ( this , this . checkIfTilesChanged . bind ( this ) ) , this . m_screenProjector , this . m_poiManager , this . m_renderer , [ this . imageCache , this . userImageCache ] , this . m_options ) ; } internal param fontCatalogs param textStyles param defaultTextStyle public async resetTextRenderer ( fontCatalogs ? , textStyles ? , defaultTextStyle ? ) { await this . m_textElementsRenderer . updateFontCatalogs ( fontCatalogs ) ; await this . m_textElementsRenderer . updateTextStyles ( textStyles , defaultTextStyle ) ; this . update ( ) ; } /**
     * Default handler for webglcontextlost event.
     *
     * Note: The renderer `this.m_renderer` may not be initialized when this function is called.
     */ private readonly onWebGLContextLost = ( event ) => { this . dispatchEvent ( this . CONTEXT_LOST_EVENT ) ; logger . warn ( "WebGL context lost" , event ) ; } ; /**
     * Default handler for webglcontextrestored event.
     *
     * Note: The renderer `this.m_renderer` may not be initialized when this function is called.
     */ private readonly onWebGLContextRestored = ( event ) => { this . dispatchEvent ( this . CONTEXT_RESTORED_EVENT ) ; if ( this . m_renderer !== undefined ) { this . textElementsRenderer . restoreRenderers ( this . m_renderer ) ; this . getTheme ( ) . then ( theme => { this . m_sceneEnvironment . updateClearColor ( theme . clearColor , theme . clearAlpha ) ; this . update ( ) ; } ) ; } logger . warn ( "WebGL context restored" , event ) ; } ; param fovCalculation param height private setFovOnCamera ( fovCalculation , height ) { const fovRad = THREE . MathUtils . degToRad ( fovCalculation . fov ) ; if ( fovCalculation . type === "fixed" ) { CameraUtils . setVerticalFov ( this . m_camera , fovRad , height ) ; return ; } let focalLength = CameraUtils . getFocalLength ( this . m_camera ) ; if ( focalLength === undefined ) { CameraUtils . setVerticalFov ( this . m_camera , fovRad , height ) ; focalLength = CameraUtils . getFocalLength ( this . m_camera ) ; } CameraUtils . setFocalLength ( this . m_camera , focalLength ! , height ) ; } /**
     * Get canvas client size in css/client pixels.
     *
     * Supports canvases not attached to DOM, which have 0 as `clientWidth` and `clientHeight` by
     * calculating it from actual canvas size and current pixel ratio.
     */ private getCanvasClientSize ( ) { const { clientWidth , clientHeight } = this . canvas ; if ( clientWidth === 0 || clientHeight === 0 || typeof clientWidth !== "number" || typeof clientHeight !== "number" ) { const pixelRatio = this . m_renderer . getPixelRatio ( ) ; return { width : Math . round ( this . canvas . width / pixelRatio ) , height : Math . round ( this . canvas . height / pixelRatio ) } ; } else { return { width : clientWidth , height : clientHeight } ; } } }