diff --git a/src/data/dem_data.ts b/src/data/dem_data.ts index 241eb6498d1..d764f176eea 100644 --- a/src/data/dem_data.ts +++ b/src/data/dem_data.ts @@ -1,4 +1,4 @@ -import {Float32Image} from '../util/image'; +import {Float32Image, RGBAImage} from '../util/image'; import {warnOnce, clamp} from '../util/util'; import {register} from '../util/web_worker_transfer'; import DemMinMaxQuadTree from './dem_tree'; @@ -6,33 +6,23 @@ import assert from 'assert'; import browser from '../util/browser'; import type {CanonicalTileID} from '../source/tile_id'; -import type {RGBAImage} from '../util/image'; import type {DEMSourceEncoding} from '../source/worker_source'; -// DEMData is a data structure for decoding, backfilling, and storing elevation data for processing in the hillshade shaders -// data can be populated either from a pngraw image tile or from serliazed data sent back from a worker. When data is initially -// loaded from a image tile, we decode the pixel values using the appropriate decoding formula, but we store the -// elevation data as an Int32 value. we add 65536 (2^16) to eliminate negative values and enable the use of -// integer overflow when creating the texture used in the hillshadePrepare step. - -// DEMData also handles the backfilling of data from a tile's neighboring tiles. This is necessary because we use a pixel's 8 -// surrounding pixel values to compute the slope at that pixel, and we cannot accurately calculate the slope at pixels on a -// tile's edge without backfilling from neighboring tiles. +interface UnpackVectors { + mapbox: [number, number, number, number]; + terrarium: [number, number, number, number]; +} -const unpackVectors = { +const unpackVectors: UnpackVectors = { mapbox: [6553.6, 25.6, 0.1, 10000.0], terrarium: [256.0, 1.0, 1.0 / 256.0, 32768.0] -} as const; +}; function unpackMapbox(r: number, g: number, b: number): number { - // unpacking formula for mapbox.terrain-rgb: - // https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb return ((r * 256 * 256 + g * 256.0 + b) / 10.0 - 10000.0); } function unpackTerrarium(r: number, g: number, b: number): number { - // unpacking formula for mapzen terrarium: - // https://aws.amazon.com/public-datasets/terrain/ return ((r * 256 + g + b / 256) - 32768.0); } @@ -41,27 +31,25 @@ export default class DEMData { stride: number; dim: number; borderReady: boolean; - _tree: DemMinMaxQuadTree; + _tree: DemMinMaxQuadTree | null; _modifiedForSources: { [key: string]: Array; }; _timestamp: number; pixels: Uint8Array; floatView: Float32Array; + get tree(): DemMinMaxQuadTree { if (!this._tree) this._buildQuadTree(); - return this._tree; + return this._tree!; } - // RGBAImage data has uniform 1px padding on all sides: square tile edge size defines stride - // and dim is calculated as stride - 2. constructor( uid: number, data: ImageData, sourceEncoding: DEMSourceEncoding, borderReady: boolean = false, ) { - // debugger; this.uid = uid; if (data.height !== data.width) throw new RangeError('DEM tiles must be square'); if (sourceEncoding && sourceEncoding !== "mapbox" && sourceEncoding !== "terrarium") { @@ -78,27 +66,18 @@ export default class DEMData { this._modifiedForSources = {}; if (!borderReady) { - // in order to avoid flashing seams between tiles, here we are initially populating a 1px border of pixels around the image - // with the data of the nearest pixel from the image. this data is eventually replaced when the tile's neighboring - // tiles are loaded and the accurate data can be backfilled using DEMData#backfillBorder for (let x = 0; x < dim; x++) { - // left vertical border values[this._idx(-1, x)] = values[this._idx(0, x)]; - // right vertical border values[this._idx(dim, x)] = values[this._idx(dim - 1, x)]; - // left horizontal border values[this._idx(x, -1)] = values[this._idx(x, 0)]; - // right horizontal border values[this._idx(x, dim)] = values[this._idx(x, dim - 1)]; } - // corners values[this._idx(-1, -1)] = values[this._idx(0, 0)]; values[this._idx(dim, -1)] = values[this._idx(dim - 1, 0)]; values[this._idx(-1, dim)] = values[this._idx(0, dim - 1)]; values[this._idx(dim, dim)] = values[this._idx(dim - 1, dim - 1)]; } - // Convert to float const unpack = sourceEncoding === "terrarium" ? unpackTerrarium : unpackMapbox; for (let i = 0; i < values.length; ++i) { const byteIdx = i * 4; @@ -108,9 +87,8 @@ export default class DEMData { this._timestamp = browser.now(); } - _buildQuadTree() { + _buildQuadTree(): void { assert(!this._tree); - // Construct the implicit sparse quad tree by traversing mips from top to down this._tree = new DemMinMaxQuadTree(this); } @@ -131,7 +109,7 @@ export default class DEMData { return v - p; } - static getUnpackVector(encoding: DEMSourceEncoding) { + static getUnpackVector(encoding: DEMSourceEncoding): [number, number, number, number] { return unpackVectors[encoding]; } @@ -196,7 +174,7 @@ export default class DEMData { } } - onDeserialize() { + onDeserialize(): void { if (this._tree) this._tree.dem = this; } } diff --git a/src/data/evaluation_feature.ts b/src/data/evaluation_feature.ts index 60bdff8b867..b9155712e17 100644 --- a/src/data/evaluation_feature.ts +++ b/src/data/evaluation_feature.ts @@ -5,7 +5,7 @@ import type {VectorTileFeature} from '@mapbox/vector-tile'; export type EvaluationFeature = { readonly type: 0 | 1 | 2 | 3 | 'Unknown' | 'Point' | 'LineString' | 'Polygon'; - readonly id?: any; + readonly id?: number | string | undefined; properties: { [_: string]: any; }; diff --git a/src/data/feature_index.ts b/src/data/feature_index.ts index ed8e9b678e6..dd3335c7d45 100644 --- a/src/data/feature_index.ts +++ b/src/data/feature_index.ts @@ -77,7 +77,7 @@ class FeatureIndex { this.serializedLayersCache = new Map(); } - insert(feature: VectorTileFeature, geometry: Array>, featureIndex: number, sourceLayerIndex: number, bucketIndex: number, layoutVertexArrayOffset: number = 0, envelopePadding: number = 0) { + insert(feature: VectorTileFeature, geometry: Array>, featureIndex: number, sourceLayerIndex: number, bucketIndex: number, layoutVertexArrayOffset: number = 0, envelopePadding: number = 0): void { const key = this.featureIndexArray.length; this.featureIndexArray.emplaceBack(featureIndex, sourceLayerIndex, bucketIndex, layoutVertexArrayOffset); @@ -138,13 +138,13 @@ class FeatureIndex { const matching = this.grid.query(bounds.min.x, bounds.min.y, bounds.max.x, bounds.max.y, queryPredicate); matching.sort(topDownFeatureComparator); - let elevationHelper = null; + let elevationHelper: DEMSampler | null = null; if (transform.elevation && matching.length > 0) { elevationHelper = DEMSampler.create(transform.elevation, this.tileID); } const result: QueryResult = {}; - let previousIndex; + let previousIndex: number | undefined; for (let k = 0; k < matching.length; k++) { const index = matching[k]; @@ -153,7 +153,7 @@ class FeatureIndex { previousIndex = index; const match = this.featureIndexArray.get(index); - let featureGeometry = null; + let featureGeometry: Array> | null = null; if (this.is3DTile) { this.loadMatchingModelFeature(result, match, query, tilespaceGeometry, transform); diff --git a/src/index.ts b/src/index.ts index c62fa0aef84..88a7ac3a1ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,23 +2,23 @@ import {PerformanceUtils} from './util/performance'; import assert from 'assert'; import {supported} from '@mapbox/mapbox-gl-supported'; import {version} from '../package.json'; -import {Map} from './ui/map'; -import NavigationControl from './ui/control/navigation_control'; -import GeolocateControl from './ui/control/geolocate_control'; -import AttributionControl from './ui/control/attribution_control'; -import ScaleControl from './ui/control/scale_control'; -import FullscreenControl from './ui/control/fullscreen_control'; -import Popup from './ui/popup'; -import Marker from './ui/marker'; +import {Map, MapOptions, IControl, ControlPosition, AnimationOptions, CameraOptions, EasingOptions} from './ui/map'; +import NavigationControl, {NavigationControlOptions} from './ui/control/navigation_control'; +import GeolocateControl, {GeolocateControlOptions} from './ui/control/geolocate_control'; +import AttributionControl, {AttributionControlOptions} from './ui/control/attribution_control'; +import ScaleControl, {ScaleControlOptions} from './ui/control/scale_control'; +import FullscreenControl, {FullscreenControlOptions} from './ui/control/fullscreen_control'; +import Popup, {PopupOptions} from './ui/popup'; +import Marker, {MarkerOptions} from './ui/marker'; import Style from './style/style'; -import LngLat, {LngLatBounds} from './geo/lng_lat'; -import Point from '@mapbox/point-geometry'; +import LngLat, {LngLatBounds, LngLatLike, LngLatBoundsLike} from './geo/lng_lat'; +import Point, {PointLike} from '@mapbox/point-geometry'; import MercatorCoordinate from './geo/mercator_coordinate'; -import {Evented} from './util/evented'; +import {Evented, Event, ErrorEvent} from './util/evented'; import config from './util/config'; import {Debug} from './util/debug'; import {isSafari} from './util/util'; -import {setRTLTextPlugin, getRTLTextPluginStatus} from './source/rtl_text_plugin'; +import {setRTLTextPlugin, getRTLTextPluginStatus, PluginStatus} from './source/rtl_text_plugin'; import WorkerPool from './util/worker_pool'; import WorkerClass from './util/worker_class'; import {prewarm, clearPrewarmedResources} from './util/worker_pool_factory'; @@ -27,6 +27,13 @@ import {WorkerPerformanceUtils} from './util/worker_performance_utils'; import {FreeCameraOptions} from './ui/free_camera'; import {getDracoUrl, setDracoUrl, setMeshoptUrl, getMeshoptUrl} from '../3d-style/util/loaders'; import browser from './util/browser'; +import {RequestParameters, RequestTransformFunction, ResourceType} from './util/ajax'; +import {FeatureSelector} from './style/style'; +import {StyleImageInterface} from './style/style_image'; +import {CustomLayerInterface} from './style/style_layer/custom_style_layer'; +import {GeoJSONFeature, TargetFeature} from './util/vectortile_to_geojson'; +import {InteractionEvent} from './ui/interactions'; +import {PaddingOptions} from './geo/edge_insets'; import type {Class} from './types/class'; diff --git a/src/render/draw_fill_extrusion.ts b/src/render/draw_fill_extrusion.ts index ea99f3499b8..8beace6f72c 100644 --- a/src/render/draw_fill_extrusion.ts +++ b/src/render/draw_fill_extrusion.ts @@ -26,10 +26,11 @@ import {calculateGroundShadowFactor} from '../../3d-style/render/shadow_renderer import {RGBAImage} from '../util/image'; import Texture from './texture'; import {Frustum} from '../util/primitives'; -import {mat4} from "gl-matrix"; +import {mat4, vec3} from "gl-matrix"; import {getCutoffParams} from './cutoff'; import {ZoomDependentExpression} from '../style-spec/expression/index'; +import type {OverscaledTileID} from '../source/tile_id'; import type {vec3} from 'gl-matrix'; import type FillExtrusionStyleLayer from '../style/style_layer/fill_extrusion_style_layer'; import type SourceCache from '../source/source_cache'; @@ -37,7 +38,6 @@ import type Painter from './painter'; import type Tile from '../source/tile'; import type {Terrain} from '../terrain/terrain'; import type Context from '../gl/context'; -import type {OverscaledTileID} from '../source/tile_id'; import type { GroundEffect, PartData} from '../data/bucket/fill_extrusion_bucket'; @@ -46,7 +46,7 @@ export default draw; type GroundEffectSubpassType = 'clear' | 'sdf' | 'color'; -function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array) { +function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array): void { const opacity = layer.paint.get('fill-extrusion-opacity'); const context = painter.context; const gl = context.gl; @@ -262,7 +262,7 @@ function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLa } } -function drawExtrusionTiles(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array, depthMode: DepthMode, stencilMode: StencilMode, colorMode: ColorMode, replacementActive: boolean) { +function drawExtrusionTiles(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array, depthMode: DepthMode, stencilMode: StencilMode, colorMode: ColorMode, replacementActive: boolean): void { layer.resetLayerRenderingStats(painter); const context = painter.context; const gl = context.gl; @@ -452,7 +452,7 @@ function drawExtrusionTiles(painter: Painter, source: SourceCache, layer: FillEx if (painter.shadowRenderer) painter.shadowRenderer.useNormalOffset = false; } -function updateReplacement(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array, layerIndex: number) { +function updateReplacement(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array, layerIndex: number): void { for (const coord of coords) { const tile = source.getTile(coord); const bucket: FillExtrusionBucket | null | undefined = (tile.getBucket(layer) as any); @@ -464,7 +464,7 @@ function updateReplacement(painter: Painter, source: SourceCache, layer: FillExt } } -function drawGroundEffect(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array, depthMode: DepthMode, stencilMode: StencilMode, colorMode: ColorMode, cullFaceMode: CullFaceMode, aoPass: boolean, subpass: GroundEffectSubpassType, opacity: number, aoIntensity: number, aoRadius: number, floodLightIntensity: number, floodLightColor: any, attenuation: number, replacementActive: boolean, renderNeighbors: boolean, framebufferCopyTexture?: Texture | null) { +function drawGroundEffect(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array, depthMode: DepthMode, stencilMode: StencilMode, colorMode: ColorMode, cullFaceMode: CullFaceMode, aoPass: boolean, subpass: GroundEffectSubpassType, opacity: number, aoIntensity: number, aoRadius: number, floodLightIntensity: number, floodLightColor: any, attenuation: number, replacementActive: boolean, renderNeighbors: boolean, framebufferCopyTexture?: Texture | null): void { const context = painter.context; const gl = context.gl; const tr = painter.transform; @@ -578,7 +578,7 @@ function drawGroundEffect(painter: Painter, source: SourceCache, layer: FillExtr // Flat roofs array is prepared in the bucket, except for buildings that are on tile borders. // For them, join pieces, calculate joined size here, and then upload data. -function updateBorders(context: Context, source: SourceCache, coord: OverscaledTileID, bucket: FillExtrusionBucket, layer: FillExtrusionStyleLayer, terrain: Terrain | null | undefined, reconcileReplacementState: boolean) { +function updateBorders(context: Context, source: SourceCache, coord: OverscaledTileID, bucket: FillExtrusionBucket, layer: FillExtrusionStyleLayer, terrain: Terrain | null | undefined, reconcileReplacementState: boolean): void { if (bucket.centroidVertexArray.length === 0) { bucket.createCentroidsBuffer(); } diff --git a/src/source/image_source.ts b/src/source/image_source.ts index eecd52874d6..929afba797f 100644 --- a/src/source/image_source.ts +++ b/src/source/image_source.ts @@ -45,7 +45,7 @@ type ImageSourceTexture = { // (0, 1, 0) -> (b * x2, b * y2, b) // (0, 0, 1) -> (c * x3, c * y3, c) // (1, 1, 1) -> (x4, y4, 1) -function basisToPoints(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number) { +function basisToPoints(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): mat3 { const m = [x1, y1, 1, x2, y2, 1, x3, y3, 1]; const s = [x4, y4, 1]; const ma = mat3.adjoint([] as any, m as [number, number, number, number, number, number, number, number, number]); @@ -53,14 +53,14 @@ function basisToPoints(x1: number, y1: number, x2: number, y2: number, x3: numbe return mat3.multiply(m as [number, number, number, number, number, number, number, number, number], m as [number, number, number, number, number, number, number, number, number], [sx, 0, 0, 0, sy, 0, 0, 0, sz]); } -function getTileToTextureTransformMatrix(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number) { +function getTileToTextureTransformMatrix(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): mat3 { const a = basisToPoints(0, 0, 1, 0, 1, 1, 0, 1); const b = basisToPoints(x1, y1, x2, y2, x3, y3, x4, y4); const adjB = mat3.adjoint([] as any, b); return mat3.multiply(a, a, adjB); } -function getTextureToTileTransformMatrix(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number) { +function getTextureToTileTransformMatrix(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): mat3 { const a = basisToPoints(0, 0, 1, 0, 1, 1, 0, 1); const b = basisToPoints(x1, y1, x2, y2, x3, y3, x4, y4); const adjA = mat3.adjoint([] as any, a); @@ -75,7 +75,7 @@ function getPerspectiveTransform(x1: number, y1: number, x2: number, y2: number, ]; } -function isConvex(coords: [ProjectedPoint, ProjectedPoint, ProjectedPoint, ProjectedPoint]) { +function isConvex(coords: [ProjectedPoint, ProjectedPoint, ProjectedPoint, ProjectedPoint]): boolean { const dx1 = coords[1].x - coords[0].x; const dy1 = coords[1].y - coords[0].y; const dx2 = coords[2].x - coords[1].x; @@ -106,7 +106,7 @@ function constrain(coords: Coordinates): Coordinates { constrainCoordinates(coords[3])]; } -function calculateMinAndSize(coords: Coordinates) { +function calculateMinAndSize(coords: Coordinates): [number, number, number, number] { let minX = coords[0][0]; let maxX = minX; let minY = coords[0][1]; @@ -127,7 +127,7 @@ function calculateMinAndSize(coords: Coordinates) { return [minX, minY, maxX - minX, maxY - minY]; } -function calculateMinAndSizeForPoints(coords: ProjectedPoint[]) { +function calculateMinAndSizeForPoints(coords: ProjectedPoint[]): [number, number, number, number] { let minX = coords[0].x; let maxX = minX; let minY = coords[0].y; diff --git a/src/source/load_vector_tile.ts b/src/source/load_vector_tile.ts index 69ea24366f5..dfc4d7e6298 100644 --- a/src/source/load_vector_tile.ts +++ b/src/source/load_vector_tile.ts @@ -24,9 +24,16 @@ export type LoadVectorDataCallback = Callback void; export type LoadVectorData = (params: RequestedTileParameters, callback: LoadVectorDataCallback) => AbortVectorData | undefined; + +interface DedupedRequestEntry { + callbacks: LoadVectorDataCallback[]; + result?: [Error | null, LoadVectorTileResult | null]; + cancel?: () => void; +} + export class DedupedRequest { entries: { - [key: string]: any; + [key: string]: DedupedRequestEntry; }; scheduler: Scheduler | null | undefined;