itowns
Version:
A JS/WebGL framework for 3D geospatial data visualization
404 lines (403 loc) • 20.4 kB
TypeScript
export namespace VIEW_EVENTS {
export let LAYERS_INITIALIZED: string;
export let LAYER_REMOVED: string;
export let LAYER_ADDED: string;
export let INITIALIZED: string;
export { COLOR_LAYERS_ORDER_CHANGED };
export let CAMERA_MOVED: string;
export let DISPOSED: string;
}
export default View;
import { COLOR_LAYERS_ORDER_CHANGED } from '../Renderer/ColorLayersOrdering';
/**
* @property {number} id - The id of the view. It's incremented at each new view instance, starting at 0.
* @property {HTMLElement} domElement - The domElement holding the canvas where the view is displayed
* @property {String} referenceCrs - The coordinate reference system of the view
* @property {MainLoop} mainLoop - itowns mainloop scheduling the operations
* @property {THREE.Scene} scene - threejs scene of the view
* @property {Camera} camera - itowns camera (that holds a threejs camera that is directly accessible with View.camera3D)
* @property {THREE.Camera} camera3D - threejs camera that is stored in itowns camera
* @property {THREE.WebGLRenderer} renderer - threejs webglrenderer rendering this view
*/
declare class View extends THREE.EventDispatcher<any> {
/**
* Constructs an Itowns View instance
*
* @example <caption><b>Create a view with a custom Three.js camera.</b></caption>
* var viewerDiv = document.getElementById('viewerDiv');
* var customCamera = itowns.THREE.PerspectiveCamera();
* var view = itowns.View('EPSG:4326', viewerDiv, { camera: { cameraThree: customCamera } });
*
* @example <caption><b>Create a view with an orthographic camera, and grant it with Three.js custom controls.</b></caption>
* var viewerDiv = document.getElementById('viewerDiv');
* var view = itowns.View('EPSG:4326', viewerDiv, { camera: { type: itowns.CAMERA_TYPE.ORTHOGRAPHIC } });
* var customControls = itowns.THREE.OrbitControls(view.camera3D, viewerDiv);
*
* @param {String} crs - The default CRS of Three.js coordinates. Should be a cartesian CRS.
* @param {HTMLElement} viewerDiv - Where to instanciate the Three.js scene in the DOM
* @param {Object} [options] - Optional properties.
* @param {Object} [options.camera] - Options for the camera associated to the view. See {@link Camera} options.
* @param {MainLoop} [options.mainLoop] - {@link MainLoop} instance to use, otherwise a default one will be constructed
* @param {WebGLRenderer|Object} [options.renderer] - {@link WebGLRenderer} instance to use, otherwise
* a default one will be constructed. In this case, if options.renderer is an object, it will be used to
* configure the renderer (see {@link c3DEngine}. If not present, a new <canvas> will be created and
* added to viewerDiv (mutually exclusive with mainLoop)
* @param {Scene} [options.scene3D] - [THREE.Scene](https://threejs.org/docs/#api/en/scenes/Scene) instance to use, otherwise a default one will be constructed
* @param {Color} [options.diffuse] - [THREE.Color](https://threejs.org/docs/?q=color#api/en/math/Color) Diffuse color terrain material.
* This color is applied to terrain if there isn't color layer on terrain extent (by example on pole).
* @param {boolean} [options.enableFocusOnStart=true] - enable focus on dom element on start.
*/
constructor(crs: string, viewerDiv: HTMLElement, options?: {
camera?: Object | undefined;
mainLoop?: MainLoop | undefined;
renderer?: WebGLRenderer | Object;
scene3D?: any;
diffuse?: any;
enableFocusOnStart?: boolean | undefined;
});
domElement: HTMLElement;
id: number;
referenceCrs: string;
mainLoop: MainLoop;
scene: any;
camera: Camera;
_frameRequesters: {};
_resizeListener: () => void;
_changeSources: Set<any>;
isDebugMode: boolean | undefined;
_delayedFrameRequesterRemoval: any[];
_allLayersAreReadyCallback: () => void;
/**
* Get the Threejs renderer used to render this view.
* @returns {THREE.WebGLRenderer} the WebGLRenderer used to render this view.
*/
get renderer(): THREE.WebGLRenderer;
/**
* Get the threejs Camera of this view
* @returns {THREE.Camera} the threejs camera of this view
*/
get camera3D(): THREE.Camera;
/**
* Dispose viewer before delete it.
*
* Method dispose all viewer objects
* - remove control
* - remove all layers
* - remove all frame requester
* - remove all events
* @param {boolean} [clearCache=false] Whether to clear all the caches or not (layers cache, style cache, tilesCache)
*/
dispose(clearCache?: boolean): void;
/**
* Add layer in viewer.
* The layer id must be unique.
*
* The `layer.whenReady` is a promise that resolves when
* the layer is done. This promise is also returned by
* `addLayer` allowing to chain call.
*
* @param {LayerOptions|Layer|GeometryLayer} layer The layer to add in view.
* @param {Layer=} parentLayer it's the layer to which the layer will be attached.
* @return {Promise} a promise resolved with the new layer object when it is fully initialized or rejected if any error occurred.
*/
addLayer(layer: LayerOptions | Layer | GeometryLayer, parentLayer?: Layer | undefined): Promise<any>;
/**
* Removes a specific imagery layer from the current layer list. This removes layers inserted with attach().
* @example
* view.removeLayer('layerId');
* @param {string} layerId The identifier
* @param {boolean} [clearCache=false] Whether to clear all the layer cache or not
* @return {boolean}
*/
removeLayer(layerId: string, clearCache?: boolean): boolean;
/**
* Notifies the scene it needs to be updated due to changes exterior to the
* scene itself (e.g. camera movement).
* non-interactive events (e.g: texture loaded)
* @param {*} changeSource
* @param {boolean} needsRedraw - indicates if notified change requires a full scene redraw.
*/
notifyChange(changeSource?: any, needsRedraw?: boolean): void;
/**
* Get all layers, with an optionnal filter applied.
* The filter method will be called with 2 args:
* - 1st: current layer
* - 2nd: (optional) the geometry layer to which the current layer is attached
* @example
* // get all layers
* view.getLayers();
* // get all color layers
* view.getLayers(layer => layer.isColorLayer);
* // get all elevation layers
* view.getLayers(layer => layer.isElevationLayer);
* // get all geometry layers
* view.getLayers(layer => layer.isGeometryLayer);
* // get one layer with id
* view.getLayers(layer => layer.id === 'itt');
* @param {function(Layer):boolean} filter
* @returns {Array<Layer>}
*/
getLayers(filter: (arg0: Layer) => boolean): Array<Layer>;
/**
* Gets the layer by identifier.
*
* @param {String} layerId The layer identifier
* @return {Layer} The layer by identifier.
*/
getLayerById(layerId: string): Layer;
/**
* @name FrameRequester
* @function
*
* @description
* Method that will be called each time the `MainLoop` updates. This function
* will be given as parameter the delta (in ms) between this update and the
* previous one, and whether or not we just started to render again. This update
* is considered as the "next" update if `view.notifyChange` was called during a
* precedent update. If `view.notifyChange` has been called by something else
* (other micro/macrotask, UI events etc...), then this update is considered as
* being the "first". It can also receive optional arguments, depending on the
* attach point of this function. Currently only `BEFORE_LAYER_UPDATE /
* AFTER_LAYER_UPDATE` attach points provide an additional argument: the layer
* being updated.
* <br><br>
*
* This means that if a `frameRequester` function wants to animate something, it
* should keep on calling `view.notifyChange` until its task is done.
* <br><br>
*
* Implementors of `frameRequester` should keep in mind that this function will
* be potentially called at each frame, thus care should be given about
* performance.
* <br><br>
*
* Typical frameRequesters are controls, module wanting to animate moves or UI
* elements etc... Basically anything that would want to call
* requestAnimationFrame.
*
* @param {number} dt
* @param {boolean} updateLoopRestarted
* @param {...*} args
*/
/**
* Add a frame requester to this view.
*
* FrameRequesters can activate the MainLoop update by calling view.notifyChange.
*
* @param {String} when - decide when the frameRequester should be called during
* the update cycle. Can be any of {@link MAIN_LOOP_EVENTS}.
* @param {FrameRequester} frameRequester - this function will be called at each
* MainLoop update with the time delta between last update, or 0 if the MainLoop
* has just been relaunched.
*/
addFrameRequester(when: string, frameRequester: FrameRequester): void;
/**
* Remove a frameRequester.
* The effective removal will happen either later; at worst it'll be at
* the beginning of the next frame.
*
* @param {String} when - attach point of this requester. Can be any of
* {@link MAIN_LOOP_EVENTS}.
* @param {FrameRequester} frameRequester
*/
removeFrameRequester(when: string, frameRequester: FrameRequester): void;
/**
* Removes all frame requesters.
*/
removeAllFrameRequesters(): void;
/**
* Removes all viewer events.
*/
removeAllEvents(): void;
_listeners: any;
_executeFrameRequestersRemovals(): void;
/**
* Execute a frameRequester.
*
* @param {String} when - attach point of this (these) requester(s). Can be any
* of {@link MAIN_LOOP_EVENTS}.
* @param {Number} dt - delta between this update and the previous one
* @param {boolean} updateLoopRestarted
* @param {...*} args - optional arguments
*/
execFrameRequesters(when: string, dt: number, updateLoopRestarted: boolean, ...args: any[]): void;
/**
* Extract view coordinates from a mouse-event / touch-event
* @param {event} event - event can be a MouseEvent or a TouchEvent
* @param {THREE.Vector2} target - the target to set the view coords in
* @param {number} [touchIdx=0] - finger index when using a TouchEvent
* @return {THREE.Vector2|undefined} - view coordinates (in pixels, 0-0 = top-left of the View).
* If the event is neither a `MouseEvent` nor a `TouchEvent`, the return is `undefined`.
*/
eventToViewCoords(event: Event | undefined, target?: THREE.Vector2, touchIdx?: number): THREE.Vector2 | undefined;
/**
* Extract normalized coordinates (NDC) from a mouse-event / touch-event
* @param {event} event - event can be a MouseEvent or a TouchEvent
* @param {number} touchIdx - finger index when using a TouchEvent (default: 0)
* @return {THREE.Vector2} - NDC coordinates (x and y are [-1, 1])
*/
eventToNormalizedCoords(event: Event | undefined, touchIdx?: number): THREE.Vector2;
/**
* Convert view coordinates to normalized coordinates (NDC)
* @param {THREE.Vector2} viewCoords (in pixels, 0-0 = top-left of the View)
* @param {THREE.Vector2} target
* @return {THREE.Vector2} - NDC coordinates (x and y are [-1, 1])
*/
viewToNormalizedCoords(viewCoords: THREE.Vector2, target?: THREE.Vector2): THREE.Vector2;
/**
* Convert NDC coordinates to view coordinates
* @param {THREE.Vector2} ndcCoords
* @return {THREE.Vector2} - view coordinates (in pixels, 0-0 = top-left of the View)
*/
normalizedToViewCoords(ndcCoords: THREE.Vector2): THREE.Vector2;
/**
* Searches for objects in {@link GeometryLayer} and specified
* `THREE.Object3D`, under the mouse or at a specified coordinates, in this
* view.
*
* @param {Object} mouseOrEvt - Mouse position in window coordinates (from
* the top left corner of the window) or `MouseEvent` or `TouchEvent`.
* @param {number} [radius=0] - The picking will happen in a circle centered
* on mouseOrEvt. This is the radius of this circle, in pixels.
* @param {GeometryLayer|string|Object3D|Array<GeometryLayer|string|Object3D>} [where] - Where to look for
* objects. It can be a single {@link GeometryLayer}, `THREE.Object3D`, ID of a layer or an array of one of these or
* of a mix of these. If no location is specified, it will query on all {@link GeometryLayer} present in this `View`.
*
* @return {Object[]} - An array of objects. Each element contains at least
* an object property which is the `THREE.Object3D` under the cursor. Then
* depending on the queried layer/source, there may be additionnal
* properties (coming from `THREE.Raycaster` for instance).
*
* @example
* view.pickObjectsAt({ x, y })
* view.pickObjectsAt({ x, y }, 1, 'wfsBuilding')
* view.pickObjectsAt({ x, y }, 3, 'wfsBuilding', myLayer)
*/
pickObjectsAt(mouseOrEvt: Object, radius?: number, where?: GeometryLayer | string | Object3D | Array<GeometryLayer | string | Object3D>): Object[];
/**
* Return the current zoom scale at the central point of the view. This
* function compute the scale of a map.
*
* @param {number} pitch - Screen pitch, in millimeters ; 0.28 by default
*
* @return {number} The zoom scale.
*/
getScale(pitch?: number): number;
getScaleFromDistance(pitch?: number, distance?: number): number;
/**
* Given a screen coordinates, get the distance between the projected
* coordinates and the camera associated to this view.
*
* @param {THREE.Vector2} [screenCoord] - The screen coordinate to get the
* distance at. By default this is the middle of the screen.
*
* @return {number} The distance in meters.
*/
getDistanceFromCamera(screenCoord?: THREE.Vector2): number;
/**
* Get, for a specific screen coordinate, the projected distance on the
* surface of the main layer of the view.
*
* @param {number} [pixels=1] - The size, in pixels, to get in meters.
* @param {THREE.Vector2} [screenCoord] - The screen coordinate to get the
* projected distance at. By default, this is the middle of the screen.
*
* @return {number} The projected distance in meters.
*/
getPixelsToMeters(pixels?: number, screenCoord?: THREE.Vector2): number;
getPixelsToMetersFromDistance(pixels?: number, distance?: number): number;
/**
* Get, for a specific screen coordinate, the size in pixels of a projected
* distance on the surface of the main layer of the view.
*
* @param {number} [meters=1] - The size, in meters, to get in pixels.
* @param {THREE.Vector2} [screenCoord] - The screen coordinate to get the
* projected distance at. By default, this is the middle of the screen.
*
* @return {number} The projected distance in pixels.
*/
getMetersToPixels(meters?: number, screenCoord?: THREE.Vector2): number;
getMetersToPixelsFromDistance(meters?: number, distance?: number): number;
/**
* Searches for {@link FeatureGeometry} in {@link ColorLayer}, under the mouse or at
* the specified coordinates, in this view. Combining them per layer and in a Feature
* like format.
*
* @param {Object} mouseOrEvt - Mouse position in window coordinates (from
* the top left corner of the window) or `MouseEvent` or `TouchEvent`.
* @param {number} [radius=3] - The picking will happen in a circle centered
* on mouseOrEvt. This is the radius of this circle, in pixels.
* @param {...ColorLayer|GeometryLayer|string} [where] - The layers to look
* into. If not specified, all {@link ColorLayer} and {@link GeometryLayer}
* layers of this view will be looked in.
*
* @return {Object} - An object, having one property per layer.
* For example, looking for features on layers `wfsBuilding` and `wfsRoads`
* will give an object like `{ wfsBuilding: [...], wfsRoads: [] }`.
* Each property is made of an array, that can be empty or filled with
* Feature like objects composed of:
* - the FeatureGeometry
* - the feature type
* - the style
* - the coordinate if the FeatureGeometry is a point
*
* @example
* view.pickFeaturesAt({ x, y });
* view.pickFeaturesAt({ x, y }, 1, 'wfsBuilding');
* view.pickFeaturesAt({ x, y }, 3, 'wfsBuilding', myLayer);
*/
pickFeaturesAt(mouseOrEvt: Object, radius?: number, ...where?: (ColorLayer | GeometryLayer | string)[]): Object;
readDepthBuffer(x: any, y: any, width: any, height: any, buffer: any): any;
/**
* Returns the world position on the terrain (view's crs: referenceCrs) under view coordinates.
* This position is computed with depth buffer.
*
* @param {THREE.Vector2} mouse position in view coordinates (in pixel), if it's null so it's view's center.
* @param {THREE.Vector3} [target=THREE.Vector3()] target. the result will be copied into this Vector3. If not present a new one will be created.
* @return {THREE.Vector3} the world position on the terrain in view's crs: referenceCrs.
*/
getPickingPositionFromDepth(mouse: THREE.Vector2, target?: THREE.Vector3): THREE.Vector3;
/**
* Returns the world {@link Coordinates} of the terrain at given view coordinates.
*
* @param {THREE.Vector2|event} [mouse] The view coordinates at which the world coordinates must be returned. This
* parameter can also be set to a mouse event from which the view coordinates will be deducted. If not specified,
* it will be defaulted to the view's center coordinates.
* @param {Coordinates} [target] The result will be copied into this {@link Coordinates} in the coordinate reference
* system of the given coordinate. If not specified, a new {@link Coordinates} instance will be created (in the
* view referenceCrs).
*
* @returns {Coordinates} The world {@link Coordinates} of the terrain at the given view coordinates in the
* coordinate reference system of the target or in the view referenceCrs if no target is specified.
*/
pickTerrainCoordinates(mouse?: THREE.Vector2 | (Event | undefined), target?: Coordinates): Coordinates;
/**
* Returns the world {@link Coordinates} of the terrain at given view coordinates.
*
* @param {THREE.Vector2|event} [mouse] The view coordinates at which the world coordinates must be
* returned. This parameter can also be set to a mouse event from
* which the view coordinates will be deducted. If not specified, it
* will be defaulted to the view's center coordinates.
* @param {Coordinates} [target] The result will be copied into this {@link Coordinates}. If not
* specified, a new {@link Coordinates} instance will be created.
*
* @returns {Coordinates} The world {@link Coordinates} of the terrain at the given view coordinates.
*
* @deprecated Use View#pickTerrainCoordinates instead.
*/
pickCoordinates(mouse?: THREE.Vector2 | (Event | undefined), target?: Coordinates): Coordinates;
/**
* Resize the viewer.
*
* @param {number} [width=viewerDiv.clientWidth] - The width to resize the
* viewer with. By default it is the `clientWidth` of the `viewerDiv`.
* @param {number} [height=viewerDiv.clientHeight] - The height to resize
* the viewer with. By default it is the `clientHeight` of the `viewerDiv`.
*/
resize(width?: number, height?: number): void;
#private;
}
import * as THREE from 'three';
import MainLoop from '../Core/MainLoop';
import Camera from '../Renderer/Camera';
import { Coordinates } from '@itowns/geographic';