UNPKG

@giro3d/giro3d

Version:

A JS/WebGL framework for 3D geospatial data visualization

604 lines 22.4 kB
import { Color, Raycaster, Vector2, type ColorRepresentation, type Intersection, type Object3D, type Side } from 'three'; import type ColorimetryOptions from '../core/ColorimetryOptions'; import type Context from '../core/Context'; import type ContourLineOptions from '../core/ContourLineOptions'; import type ElevationProvider from '../core/ElevationProvider'; import type ElevationRange from '../core/ElevationRange'; import type Extent from '../core/geographic/Extent'; import type GetElevationOptions from '../core/GetElevationOptions'; import type GetElevationResult from '../core/GetElevationResult'; import type GraticuleOptions from '../core/GraticuleOptions'; import ColorLayer from '../core/layer/ColorLayer'; import ElevationLayer from '../core/layer/ElevationLayer'; import type HasLayers from '../core/layer/HasLayers'; import Layer from '../core/layer/Layer'; import type MemoryUsage from '../core/MemoryUsage'; import { type GetMemoryUsageContext } from '../core/MemoryUsage'; import type Pickable from '../core/picking/Pickable'; import type PickableFeatures from '../core/picking/PickableFeatures'; import type PickOptions from '../core/picking/PickOptions'; import { type MapPickResult } from '../core/picking/PickTilesAt'; import type TerrainOptions from '../core/TerrainOptions'; import type TileGeometry from '../core/TileGeometry'; import TileIndex from '../core/TileIndex'; import TileMesh from '../core/TileMesh'; import type RenderingState from '../renderer/RenderingState'; import type { EntityUserData } from './Entity'; import Entity3D, { type Entity3DEventMap } from './Entity3D'; import type MapLightingOptions from './MapLightingOptions'; /** * The default background color of maps. */ export declare const DEFAULT_MAP_BACKGROUND_COLOR: ColorRepresentation; /** * The default tile subdivision threshold. */ export declare const DEFAULT_SUBDIVISION_THRESHOLD = 1.5; /** * The default number of segments in a map's tile. */ export declare const DEFAULT_MAP_SEGMENTS = 32; /** * Comparison function to order layers. */ export type LayerCompareFn = (a: Layer, b: Layer) => number; export interface MapEventMap extends Entity3DEventMap { /** Fires when a the layer ordering changes. */ 'layer-order-changed': unknown; /** Fires when a layer is added to the map. */ 'layer-added': { layer: Layer; }; /** Fires when a layer is removed from the map. */ 'layer-removed': { layer: Layer; }; /** Fires when elevation data has changed on a specific extent of the map. */ 'elevation-changed': { extent: Extent; }; } export type MapConstructorOptions = { /** * The geographic extent of the map. * * Note: It must have the same CRS as the instance this map will be added to. */ extent: Extent; /** * Maximum tile depth of the map. If `undefined`, there is no limit to the subdivision * of the map. * @defaultValue undefined */ maxSubdivisionLevel?: number; /** * Lighting and shading parameters. * @defaultValue `undefined` (lighting is disabled) */ lighting?: boolean | MapLightingOptions; /** * Enables contour lines. If `undefined` or `false`, contour lines * are not displayed. * * Note: this option has no effect if the map does not contain an elevation layer. * @defaultValue `undefined` (contour lines are disabled) */ contourLines?: boolean | ContourLineOptions; /** * The graticule options. * @defaultValue undefined (graticule is disabled). */ graticule?: boolean | GraticuleOptions; /** * The colorimetry for the whole map. * Those are distinct from the individual layers' own colorimetry. * @defaultValue undefined */ colorimetry?: ColorimetryOptions; /** * The number of geometry segments in each map tile. * The higher the better. It *must* be power of two between `1` included and `256` included. * Note: the number of vertices per tile side is `segments` + 1. * @defaultValue {@link DEFAULT_MAP_SEGMENTS} */ segments?: number; /** * The sidedness of the map surface: * - `FrontSide` will only display the "above ground" side of the map (in cartesian maps), * or the outer shell of the map (in globe settings). * - `BackSide` will only display the "underground" side of the map (in cartesian maps), * or the inner shell of the map (in globe settings). * - `DoubleSide` will display both sides of the map. * @defaultValue `FrontSide` */ side?: Side; /** * Enable or disable depth testing on materials. * @defaultValue true */ depthTest?: boolean; /** * Options for geometric terrain rendering. */ terrain?: boolean | TerrainOptions; /** * If `true`, parts of the map that relate to no-data elevation * values are not displayed. Note: you should only set this value to `true` if * an elevation layer is present, otherwise the map will never be displayed. * @defaultValue false */ discardNoData?: boolean; /** * The optional `Object3D` to use as the root object of this map. * If none provided, a new one will be created. */ object3d?: Object3D; /** * The color of the map when no color layers are present. * @defaultValue {@link DEFAULT_MAP_BACKGROUND_COLOR} */ backgroundColor?: ColorRepresentation; /** * The opacity of the map background. * @defaultValue 1 (opaque) */ backgroundOpacity?: number; /** * Show the map tiles' borders. * @defaultValue false */ showOutline?: boolean; /** * The color of the tile borders. * @defaultValue red */ outlineColor?: ColorRepresentation; /** * The optional elevation range of the map. The map will not be * rendered for elevations outside of this range. * Note: this feature is only useful if an elevation layer is added to this map. * @defaultValue undefined (elevation range is disabled) */ elevationRange?: ElevationRange; /** * Force using texture atlases even when not required. * @defaultValue false */ forceTextureAtlases?: boolean; /** * The threshold before which a map tile is subdivided. * @defaultValue {@link DEFAULT_SUBDIVISION_THRESHOLD} */ subdivisionThreshold?: number; /** * If `true`, the map will cast shadow. * @defaultValue true */ castShadow?: boolean; /** * If `true`, the map will receive shadow. * Note: only available if {@link lighting.mode} is {@link MapLightingMode.LightBased} * @defaultValue true */ receiveShadow?: boolean; }; /** * A map is an {@link Entity3D} that represents a flat surface displaying one or more {@link core.layer.Layer | layer(s)}. * * ## Supported layers * * Maps support various types of layers. * * ### Color layers * * Maps can contain any number of {@link core.layer.ColorLayer | color layers}, as well as any number of {@link core.layer.MaskLayer | mask layers}. * * Color layers are used to display satellite imagery, vector features or any other dataset. * Mask layers are used to mask parts of a map (like an alpha channel). * * ### Elevation layers * * Up to one elevation layer can be added to a map, to provide features related to elevation, such * as terrain deformation, shading, contour lines, etc. Without an elevation layer, the map * will appear like a flat rectangle on the specified extent. * * Note: to benefit from the features given by elevation layers (shading for instance) while keeping * a flat map, disable terrain in the {@link TerrainOptions}. * * 💡 If the {@link TerrainOptions.enableCPUTerrain} is enabled, the elevation data can be sampled * by the {@link getElevation} method. * * ## Picking on maps * * Maps can be picked like any other 3D entity, using the {@link entities.Entity3D#pick | pick()} method. * * However, if {@link TerrainOptions.enableCPUTerrain} is enabled, then the map provides an alternate * methods for: raycasting-based picking, in addition to GPU-based picking. * * ### GPU-based picking * * This is the default method for picking maps. When the user calls {@link entities.Entity3D#pick | pick()}, * the camera's field of view is rendered into a temporary texture, then the pixel(s) around the picked * point are analyzed to determine the location of the picked point. * * The main advantage of this method is that it ignores transparent pixels of the map (such as * no-data elevation pixels, or transparent color layers). * * ### Raycasting-based picking * * 💡 This method requires that {@link TerrainOptions.enableCPUTerrain} is enabled, and that * {@link core.picking.PickOptions.gpuPicking} is disabled. * * This method casts a ray that is then intersected with the map's meshes. The first intersection is * returned. * * The main advantage of this method is that it's much faster and puts less pressure on the GPU. * * ## Lighting and shadows * * The Map currently support two lighting modes: * - the simplified, hillshade model * - the dynamic, light-based model, that uses three.js lights * * Both modes support casting shadows from the Map (on other objects), but only the light-based * mode enables Maps to _receive_ shadows (from itself or other objects). * * @typeParam UserData - The type of the {@link entities.Entity#userData} property. */ declare class Map<UserData extends EntityUserData = EntityUserData> extends Entity3D<MapEventMap, UserData> implements Pickable<MapPickResult>, PickableFeatures<unknown, MapPickResult>, ElevationProvider, HasLayers, MemoryUsage { readonly isMap: true; readonly type: "Map"; readonly hasLayers: true; private readonly _objectOptions; private _segments; private _hasElevationLayer; private readonly _atlasInfo; private _subdivisions; private _colorAtlasDataType; private _imageSize; private _wireframe; private readonly _layers; private readonly _onLayerVisibilityChanged; private readonly _onTileElevationChanged; /** @internal */ readonly level0Nodes: TileMesh[]; /** @internal */ readonly allTiles: Set<TileMesh>; private readonly _layerIndices; private readonly _layerIds; /** @internal */ readonly geometryPool: globalThis.Map<string, TileGeometry>; readonly extent: Extent; readonly maxSubdivisionLevel: number; readonly isPickableFeatures = true; private readonly _materialOptions; /** @internal */ readonly tileIndex: TileIndex<TileMesh>; /** * The global factor that drives SSE (screen space error) computation. The lower this value, the * sooner a tile is subdivided. Note: changing this scale to a value less than 1 can drastically * increase the number of tiles displayed in the scene, and can even lead to WebGL crashes. * * @defaultValue {@link DEFAULT_SUBDIVISION_THRESHOLD} */ subdivisionThreshold: number; getMemoryUsage(context: GetMemoryUsageContext): void; /** * Constructs a Map object. * * @param options - Constructor options. */ constructor(options: MapConstructorOptions); /** * Returns `true` if this map is currently processing data. */ get loading(): boolean; /** * Gets the loading progress (between 0 and 1) of the map. This is the average progress of all * layers in this map. * Note: if no layer is present, this will always be 1. * Note: This value is only meaningful is {@link loading} is `true`. */ get progress(): number; /** * Gets or sets depth testing on materials. */ get depthTest(): boolean; set depthTest(v: boolean); /** * Gets or sets the background opacity. */ get backgroundOpacity(): number; set backgroundOpacity(opacity: number); /** * Gets or sets the terrain options. */ get terrain(): Required<TerrainOptions>; set terrain(terrain: TerrainOptions); /** * Gets or sets the sidedness of the map surface: * - `FrontSide` will only display the "above ground" side of the map (in cartesian maps), * or the outer shell of the map (in globe settings). * - `BackSide` will only display the "underground" side of the map (in cartesian maps), * or the inner shell of the map (in globe settings). * - `DoubleSide` will display both sides of the map. * @defaultValue `FrontSide` */ get side(): Side; set side(newSide: Side); /** * Toggles discard no-data pixels. */ get discardNoData(): boolean; set discardNoData(opacity: boolean); /** * Gets or sets the background color. */ get backgroundColor(): Color; set backgroundColor(c: ColorRepresentation); /** * Gets or sets graticule options. */ get graticule(): Required<GraticuleOptions>; set graticule(opts: GraticuleOptions); private updateObject; private updateObjectOption; /** * Toggles the `.castShadow` property on objects generated by this entity. */ get castShadow(): boolean; set castShadow(v: boolean); /** * Toggles the `.receiveShadow` property on objects generated by this entity. * * Note that map tiles will receive shadows only if {@link lighting} mode is set to {@link MapLightingMode.LightBased}. */ get receiveShadow(): boolean; set receiveShadow(v: boolean); /** * Gets or sets lighting options. */ get lighting(): Required<MapLightingOptions>; set lighting(opts: MapLightingOptions); /** * Gets or sets colorimetry options. */ get colorimetry(): Required<ColorimetryOptions>; set colorimetry(opts: ColorimetryOptions); /** * Gets or sets elevation range. */ get elevationRange(): ElevationRange | null; set elevationRange(range: ElevationRange | null); /** * Shows tile outlines. */ get showTileOutlines(): boolean; set showTileOutlines(show: boolean); /** * Gets or sets tile outline color. */ get tileOutlineColor(): Color; set tileOutlineColor(color: ColorRepresentation); /** * Gets or sets contour line options. */ get contourLines(): Required<ContourLineOptions>; set contourLines(opts: ContourLineOptions); /** * Shows meshes used for raycasting purposes. */ get showColliderMeshes(): boolean; set showColliderMeshes(show: boolean); get segments(): number; set segments(v: number); /** * Displays the map tiles in wireframe. */ get wireframe(): boolean; set wireframe(v: boolean); get imageSize(): Vector2; private subdivideNode; private clearGeometryPool; private updateGeometries; get subdivisions(): { x: number; y: number; }; preprocess(): Promise<void>; private requestNewTile; private onTileElevationChanged; /** * Sets the render state of the map. * * @internal * @param state - The new state. * @returns The function to revert to the previous state. */ setRenderState(state: RenderingState): () => void; pick(coordinates: Vector2, options?: PickOptions): MapPickResult[]; private raycastAtCoordinate; protected getDefaultLightingOptions(): Readonly<Required<MapLightingOptions>>; private pickUsingRaycast; /** * Perform raycasting on visible tiles. * @param raycaster - The THREE raycaster. * @param intersects - The intersections array to populate with intersections. */ raycast(raycaster: Raycaster, intersects: Intersection<TileMesh>[]): void; pickFeaturesFrom(pickedResult: MapPickResult, options?: PickOptions): unknown[]; preUpdate(context: Context, changeSources: Set<unknown>): TileMesh[]; /** * Sort the color layers according to the comparator function. * * @param compareFn - The comparator function. */ sortColorLayers(compareFn: LayerCompareFn): void; /** * Moves the layer closer to the foreground. * * Note: this only applies to color layers. * * @param layer - The layer to move. * @throws If the layer is not present in the map. * @example * map.addLayer(foo); * map.addLayer(bar); * map.addLayer(baz); * // Layers (back to front) : foo, bar, baz * * map.moveLayerUp(foo); * // Layers (back to front) : bar, foo, baz */ moveLayerUp(layer: ColorLayer): void; onRenderingContextRestored(): void; /** * Moves the specified layer after the other layer in the list. * * @param layer - The layer to move. * @param target - The target layer. If `null`, then the layer is put at the * beginning of the layer list. * @throws If the layer is not present in the map. * @example * map.addLayer(foo); * map.addLayer(bar); * map.addLayer(baz); * // Layers (back to front) : foo, bar, baz * * map.insertLayerAfter(foo, baz); * // Layers (back to front) : bar, baz, foo */ insertLayerAfter(layer: ColorLayer, target: ColorLayer | null): void; /** * Moves the layer closer to the background. * * Note: this only applies to color layers. * * @param layer - The layer to move. * @throws If the layer is not present in the map. * @example * map.addLayer(foo); * map.addLayer(bar); * map.addLayer(baz); * // Layers (back to front) : foo, bar, baz * * map.moveLayerDown(baz); * // Layers (back to front) : foo, baz, bar */ moveLayerDown(layer: ColorLayer): void; /** * Returns the position of the layer in the layer list, or -1 if it is not found. * * @param layer - The layer to search. * @returns The index of the layer. */ getIndex(layer: Layer): number; private reorderLayers; contains(obj: unknown): boolean; update(context: Context, node: TileMesh): unknown[] | undefined; private testVisibility; postUpdate(context: Context): void; private registerColorLayer; private updateGlobalMinMax; private registerColorMap; /** * Adds a layer, then returns the created layer. * Before using this method, make sure that the map is added in an instance. * If the extent or the projection of the layer is not provided, * those values will be inherited from the map. * * @param layer - the layer to add * @returns a promise resolving when the layer is ready */ addLayer<TLayer extends Layer>(layer: TLayer): Promise<TLayer>; private onLayerVisibilityChanged; /** * Removes a layer from the map. * * @param layer - the layer to remove * @param options - The options. * @returns `true` if the layer was present, `false` otherwise. */ removeLayer(layer: Layer, options?: { /** If `true`, the layer is also disposed. */ disposeLayer?: boolean; }): boolean; get layerCount(): number; forEachLayer(callback: (layer: Layer) => void): void; /** * Gets all layers that satisfy the filter predicate. * * @param predicate - the optional predicate. * @returns the layers that matched the predicate or all layers if no predicate was provided. */ getLayers(predicate?: (arg0: Layer) => boolean): Layer<import("../core/layer/Layer").LayerEvents, import("../core/layer/Layer").LayerUserData>[]; /** * Gets all color layers in this map. * * @returns the color layers */ getColorLayers(): ColorLayer[]; /** * Gets all elevation layers in this map. * * @returns the elevation layers */ getElevationLayers(): ElevationLayer[]; /** * Disposes this map and associated unmanaged resources. * * Note: By default, layers in this map are not automatically disposed, except when * `disposeLayers` is `true`. * * @param options - Options. * @param options -.disposeLayers If true, layers are also disposed. */ dispose(options?: { disposeLayers?: boolean; }): void; private disposeTile; /** * Returns the minimal and maximal elevation values in this map, in meters. * * If there is no elevation layer present, returns `{ min: 0, max: 0 }`. * * @returns The min/max value. */ getElevationMinMax(): ElevationRange; /** * Sample the elevation at the specified coordinate. * * Note: this method does nothing if {@link TerrainOptions.enableCPUTerrain} is not enabled, * or if no elevation layer is present on the map, or if the sampling coordinate is not inside * the map's extent. * * Note: sampling might return more than one sample for any given coordinate. You can sort them * by {@link entities.ElevationSample.resolution | resolution} to select the best sample for your needs. * @param options - The options. * @param result - The result object to populate with the samples. If none is provided, a new * empty result is created. The existing samples in the array are not removed. Useful to * cumulate samples across different maps. * @returns The {@link GetElevationResult} containing the updated sample array. * If the map has no elevation layer or if {@link TerrainOptions.enableCPUTerrain} is not enabled, * this array is left untouched. */ getElevation(options: GetElevationOptions, result?: GetElevationResult): GetElevationResult; /** * Traverses all tiles in the hierarchy of this entity. * * @param callback - The callback. * @param root - The raversal root. If undefined, the traversal starts at the root * object of this entity. */ traverseTiles(callback: (arg0: TileMesh) => void, root?: Object3D | undefined): void; /** * @param node - The node to subdivide. * @returns True if the node can be subdivided. */ canSubdivide(node: TileMesh): boolean; private testTileSSE; private updateMinMaxDistance; } export declare function isMap(o: unknown): o is Map; export default Map; //# sourceMappingURL=Map.d.ts.map