Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert mapbox plugin #13390

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 13 additions & 35 deletions src/data/dem_data.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,28 @@
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';
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);
}

Expand All @@ -41,27 +31,25 @@ export default class DEMData {
stride: number;
dim: number;
borderReady: boolean;
_tree: DemMinMaxQuadTree;
_tree: DemMinMaxQuadTree | null;
_modifiedForSources: {
[key: string]: Array<CanonicalTileID>;
};
_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") {
Expand All @@ -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;
Expand All @@ -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);
}

Expand All @@ -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];
}

Expand Down Expand Up @@ -196,7 +174,7 @@ export default class DEMData {
}
}

onDeserialize() {
onDeserialize(): void {
if (this._tree) this._tree.dem = this;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/data/evaluation_feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
8 changes: 4 additions & 4 deletions src/data/feature_index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class FeatureIndex {
this.serializedLayersCache = new Map();
}

insert(feature: VectorTileFeature, geometry: Array<Array<Point>>, featureIndex: number, sourceLayerIndex: number, bucketIndex: number, layoutVertexArrayOffset: number = 0, envelopePadding: number = 0) {
insert(feature: VectorTileFeature, geometry: Array<Array<Point>>, 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);

Expand Down Expand Up @@ -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];

Expand All @@ -153,7 +153,7 @@ class FeatureIndex {
previousIndex = index;

const match = this.featureIndexArray.get(index);
let featureGeometry = null;
let featureGeometry: Array<Array<Point>> | null = null;

if (this.is3DTile) {
this.loadMatchingModelFeature(result, match, query, tilespaceGeometry, transform);
Expand Down
31 changes: 19 additions & 12 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';

Expand Down
14 changes: 7 additions & 7 deletions src/render/draw_fill_extrusion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ 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';
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';
Expand All @@ -46,7 +46,7 @@ export default draw;

type GroundEffectSubpassType = 'clear' | 'sdf' | 'color';

function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array<OverscaledTileID>) {
function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array<OverscaledTileID>): void {
const opacity = layer.paint.get('fill-extrusion-opacity');
const context = painter.context;
const gl = context.gl;
Expand Down Expand Up @@ -262,7 +262,7 @@ function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLa
}
}

function drawExtrusionTiles(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array<OverscaledTileID>, depthMode: DepthMode, stencilMode: StencilMode, colorMode: ColorMode, replacementActive: boolean) {
function drawExtrusionTiles(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array<OverscaledTileID>, depthMode: DepthMode, stencilMode: StencilMode, colorMode: ColorMode, replacementActive: boolean): void {
layer.resetLayerRenderingStats(painter);
const context = painter.context;
const gl = context.gl;
Expand Down Expand Up @@ -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<OverscaledTileID>, layerIndex: number) {
function updateReplacement(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array<OverscaledTileID>, layerIndex: number): void {
for (const coord of coords) {
const tile = source.getTile(coord);
const bucket: FillExtrusionBucket | null | undefined = (tile.getBucket(layer) as any);
Expand All @@ -464,7 +464,7 @@ function updateReplacement(painter: Painter, source: SourceCache, layer: FillExt
}
}

function drawGroundEffect(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array<OverscaledTileID>, 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<OverscaledTileID>, 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;
Expand Down Expand Up @@ -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();
}
Expand Down
12 changes: 6 additions & 6 deletions src/source/image_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,22 @@ 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]);
const [sx, sy, sz] = vec3.transformMat3(s as [number, number, number], s as [number, number, number], ma);
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);
Expand All @@ -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;
Expand Down Expand Up @@ -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];
Expand All @@ -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;
Expand Down
9 changes: 8 additions & 1 deletion src/source/load_vector_tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,16 @@ export type LoadVectorDataCallback = Callback<LoadVectorTileResult | null | unde

export type AbortVectorData = () => 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;

Expand Down