@mapwhit/tilerenderer 0.52.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/build/min/package.json +1 -1
- package/build/min/src/shaders/_prelude.fragment.glsl.js +2 -2
- package/build/min/src/shaders/_prelude.vertex.glsl.js +2 -2
- package/build/min/src/shaders/background.fragment.glsl.js +2 -2
- package/build/min/src/shaders/background.vertex.glsl.js +1 -1
- package/build/min/src/shaders/background_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/background_pattern.vertex.glsl.js +1 -1
- package/build/min/src/shaders/circle.fragment.glsl.js +2 -2
- package/build/min/src/shaders/circle.vertex.glsl.js +2 -2
- package/build/min/src/shaders/clipping_mask.fragment.glsl.js +1 -1
- package/build/min/src/shaders/clipping_mask.vertex.glsl.js +1 -1
- package/build/min/src/shaders/collision_box.fragment.glsl.js +1 -1
- package/build/min/src/shaders/collision_box.vertex.glsl.js +1 -1
- package/build/min/src/shaders/collision_circle.fragment.glsl.js +1 -1
- package/build/min/src/shaders/collision_circle.vertex.glsl.js +1 -1
- package/build/min/src/shaders/debug.fragment.glsl.js +1 -1
- package/build/min/src/shaders/debug.vertex.glsl.js +1 -1
- package/build/min/src/shaders/fill.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_extrusion.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_extrusion.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_extrusion_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_extrusion_pattern.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_outline.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_outline.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_outline_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_outline_pattern.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_pattern.vertex.glsl.js +2 -2
- package/build/min/src/shaders/heatmap.fragment.glsl.js +2 -2
- package/build/min/src/shaders/heatmap.vertex.glsl.js +2 -2
- package/build/min/src/shaders/heatmap_texture.fragment.glsl.js +2 -2
- package/build/min/src/shaders/heatmap_texture.vertex.glsl.js +1 -1
- package/build/min/src/shaders/hillshade.fragment.glsl.js +2 -2
- package/build/min/src/shaders/hillshade.vertex.glsl.js +1 -1
- package/build/min/src/shaders/hillshade_prepare.fragment.glsl.js +2 -2
- package/build/min/src/shaders/hillshade_prepare.vertex.glsl.js +1 -1
- package/build/min/src/shaders/line.fragment.glsl.js +2 -2
- package/build/min/src/shaders/line.vertex.glsl.js +2 -2
- package/build/min/src/shaders/line_gradient.fragment.glsl.js +2 -2
- package/build/min/src/shaders/line_gradient.vertex.glsl.js +2 -2
- package/build/min/src/shaders/line_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/line_pattern.vertex.glsl.js +2 -2
- package/build/min/src/shaders/line_sdf.fragment.glsl.js +2 -2
- package/build/min/src/shaders/line_sdf.vertex.glsl.js +2 -2
- package/build/min/src/shaders/raster.fragment.glsl.js +2 -2
- package/build/min/src/shaders/raster.vertex.glsl.js +1 -1
- package/build/min/src/shaders/symbol_icon.fragment.glsl.js +2 -2
- package/build/min/src/shaders/symbol_icon.vertex.glsl.js +2 -2
- package/build/min/src/shaders/symbol_sdf.fragment.glsl.js +2 -2
- package/build/min/src/shaders/symbol_sdf.vertex.glsl.js +2 -2
- package/package.json +3 -3
- package/src/data/array_types.js +1 -36
- package/src/data/bucket/circle_bucket.js +0 -3
- package/src/data/bucket/fill_bucket.js +0 -3
- package/src/data/bucket/fill_extrusion_bucket.js +0 -3
- package/src/data/bucket/heatmap_bucket.js +0 -4
- package/src/data/bucket/line_bucket.js +1 -4
- package/src/data/bucket/pattern_bucket_features.js +2 -2
- package/src/data/bucket/symbol_bucket.js +87 -126
- package/src/data/bucket.js +26 -21
- package/src/data/dem_data.js +0 -3
- package/src/data/feature_index.js +3 -8
- package/src/data/program_configuration.js +3 -12
- package/src/data/segment.js +0 -4
- package/src/render/draw_background.js +3 -3
- package/src/render/draw_circle.js +4 -4
- package/src/render/draw_fill.js +8 -8
- package/src/render/draw_fill_extrusion.js +8 -8
- package/src/render/draw_heatmap.js +4 -4
- package/src/render/draw_line.js +6 -6
- package/src/render/draw_raster.js +6 -6
- package/src/render/draw_symbol.js +16 -16
- package/src/render/glyph_atlas.js +0 -3
- package/src/render/glyph_manager.js +1 -2
- package/src/render/image_atlas.js +0 -4
- package/src/render/image_manager.js +33 -19
- package/src/render/painter.js +13 -14
- package/src/render/program/circle_program.js +4 -4
- package/src/render/program/fill_extrusion_program.js +1 -1
- package/src/render/program/heatmap_program.js +1 -1
- package/src/render/program/hillshade_program.js +6 -6
- package/src/render/program/line_program.js +3 -3
- package/src/render/program/raster_program.js +6 -6
- package/src/source/geojson_source.js +15 -24
- package/src/source/geojson_worker_source.js +40 -68
- package/src/source/geojson_wrapper.js +9 -1
- package/src/source/image_source.js +6 -16
- package/src/source/query_features.js +4 -5
- package/src/source/raster_dem_tile_source.js +45 -64
- package/src/source/raster_tile_source.js +1 -6
- package/src/source/resources/glyphs.js +2 -2
- package/src/source/resources/index.js +3 -9
- package/src/source/rtl_text_plugin.js +58 -31
- package/src/source/source.js +11 -13
- package/src/source/source_cache.js +135 -151
- package/src/source/source_state.js +101 -12
- package/src/source/tile.js +32 -46
- package/src/source/tile_bounds.js +26 -26
- package/src/source/tile_id.js +2 -5
- package/src/source/vector_tile_source.js +14 -14
- package/src/source/vector_tile_worker_source.js +19 -23
- package/src/source/worker_tile.js +120 -117
- package/src/style/create_style_layer.js +1 -1
- package/src/style/pauseable_placement.js +4 -5
- package/src/style/properties.js +1 -8
- package/src/style/query_utils.js +3 -3
- package/src/style/style.js +263 -195
- package/src/style/style_layer/circle_style_layer.js +13 -11
- package/src/style/style_layer/fill_extrusion_style_layer.js +42 -27
- package/src/style/style_layer/fill_style_layer.js +5 -5
- package/src/style/style_layer/heatmap_style_layer.js +1 -1
- package/src/style/style_layer/hillshade_style_layer.js +1 -1
- package/src/style/style_layer/line_style_layer.js +23 -19
- package/src/style/style_layer/symbol_style_layer.js +13 -13
- package/src/style/style_layer.js +48 -30
- package/src/style/style_layer_index.js +16 -41
- package/src/symbol/anchor.js +0 -4
- package/src/symbol/cross_tile_symbol_index.js +2 -5
- package/src/symbol/opacity_state.js +0 -4
- package/src/symbol/placement.js +3 -3
- package/src/symbol/quads.js +4 -4
- package/src/symbol/symbol_layout.js +7 -7
- package/src/symbol/transform_text.js +1 -1
- package/src/ui/map.js +49 -11
- package/src/util/group_layers.js +41 -0
- package/src/util/image.js +0 -5
- package/src/util/key.js +21 -0
- package/src/util/object.js +8 -53
- package/src/worker.js +1 -4
- package/src/source/resources/images.js +0 -68
- package/src/source/worker.js +0 -110
- package/src/source/worker_source.js +0 -14
- package/src/style-spec/deref.js +0 -51
- package/src/style-spec/group_by_layout.js +0 -46
- package/src/util/actor.js +0 -108
- package/src/util/dispatcher.js +0 -65
- package/src/util/global_worker_pool.js +0 -15
- package/src/util/transfer_registry.js +0 -168
- package/src/util/web_worker_transfer.js +0 -43
- package/src/util/worker_pool.js +0 -41
|
@@ -23,10 +23,11 @@ const padding = 1;
|
|
|
23
23
|
*/
|
|
24
24
|
class ImageManager {
|
|
25
25
|
#loadedState = Promise.withResolvers();
|
|
26
|
+
#imageQueue = new Map();
|
|
26
27
|
constructor() {
|
|
27
|
-
this.images =
|
|
28
|
+
this.images = new Map();
|
|
28
29
|
|
|
29
|
-
this.patterns =
|
|
30
|
+
this.patterns = new Map();
|
|
30
31
|
this.atlasImage = new RGBAImage({ width: 1, height: 1 });
|
|
31
32
|
this.dirty = true;
|
|
32
33
|
}
|
|
@@ -44,22 +45,31 @@ class ImageManager {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
getImage(id) {
|
|
47
|
-
return this.images
|
|
48
|
+
return this.images.get(id);
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
addImage(id, image) {
|
|
51
|
-
assert(!this.images
|
|
52
|
-
|
|
52
|
+
assert(!(this.images.has(id) || this.#imageQueue.has(id)));
|
|
53
|
+
if (image.promise) {
|
|
54
|
+
this.#imageQueue.set(id, image.promise);
|
|
55
|
+
image.promise.then(image => {
|
|
56
|
+
this.#imageQueue.delete(id);
|
|
57
|
+
this.images.set(id, image);
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.images.set(id, image);
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
removeImage(id) {
|
|
56
|
-
assert(this.images
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
assert(this.images.has(id) || this.#imageQueue.has(id));
|
|
66
|
+
this.images.delete(id);
|
|
67
|
+
this.#imageQueue.delete(id);
|
|
68
|
+
this.patterns.delete(id);
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
listImages() {
|
|
62
|
-
return
|
|
72
|
+
return Array.from(this.images.keys());
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
async getImages(ids) {
|
|
@@ -67,11 +77,16 @@ class ImageManager {
|
|
|
67
77
|
|
|
68
78
|
const response = {};
|
|
69
79
|
for (const id of ids) {
|
|
70
|
-
|
|
80
|
+
let image = this.images.get(id);
|
|
81
|
+
if (!image) {
|
|
82
|
+
if (!this.#imageQueue.has(id)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
image = await this.#imageQueue.get(id);
|
|
86
|
+
}
|
|
71
87
|
if (image) {
|
|
72
|
-
// Clone the image so that our own copy of its ArrayBuffer doesn't get transferred.
|
|
73
88
|
response[id] = {
|
|
74
|
-
data: image.data
|
|
89
|
+
data: image.data,
|
|
75
90
|
pixelRatio: image.pixelRatio,
|
|
76
91
|
sdf: image.sdf
|
|
77
92
|
};
|
|
@@ -88,7 +103,7 @@ class ImageManager {
|
|
|
88
103
|
}
|
|
89
104
|
|
|
90
105
|
getPattern(id) {
|
|
91
|
-
const pattern = this.patterns
|
|
106
|
+
const pattern = this.patterns.get(id);
|
|
92
107
|
if (pattern) {
|
|
93
108
|
return pattern.position;
|
|
94
109
|
}
|
|
@@ -102,7 +117,7 @@ class ImageManager {
|
|
|
102
117
|
const h = image.data.height + padding * 2;
|
|
103
118
|
const bin = { w, h, x: 0, y: 0 };
|
|
104
119
|
const position = new ImagePosition(bin, image);
|
|
105
|
-
this.patterns
|
|
120
|
+
this.patterns.set(id, { bin, position });
|
|
106
121
|
this._updatePatternAtlas();
|
|
107
122
|
|
|
108
123
|
return position;
|
|
@@ -122,8 +137,8 @@ class ImageManager {
|
|
|
122
137
|
|
|
123
138
|
_updatePatternAtlas() {
|
|
124
139
|
const bins = [];
|
|
125
|
-
for (const
|
|
126
|
-
bins.push(
|
|
140
|
+
for (const { bin } of this.patterns.values()) {
|
|
141
|
+
bins.push(bin);
|
|
127
142
|
}
|
|
128
143
|
|
|
129
144
|
const { w, h } = potpack(bins);
|
|
@@ -131,11 +146,10 @@ class ImageManager {
|
|
|
131
146
|
const dst = this.atlasImage;
|
|
132
147
|
dst.resize({ width: w ?? 1, height: h ?? 1 });
|
|
133
148
|
|
|
134
|
-
for (const id
|
|
135
|
-
const { bin } = this.patterns[id];
|
|
149
|
+
for (const [id, { bin }] of this.patterns) {
|
|
136
150
|
const x = bin.x + padding;
|
|
137
151
|
const y = bin.y + padding;
|
|
138
|
-
const src = this.images
|
|
152
|
+
const src = this.images.get(id).data;
|
|
139
153
|
const w = src.width;
|
|
140
154
|
const h = src.height;
|
|
141
155
|
|
package/src/render/painter.js
CHANGED
|
@@ -83,8 +83,8 @@ class Painter {
|
|
|
83
83
|
this.context.viewport.set([0, 0, this.width, this.height]);
|
|
84
84
|
|
|
85
85
|
if (this.style) {
|
|
86
|
-
for (const
|
|
87
|
-
|
|
86
|
+
for (const layer of this.style._layers.values()) {
|
|
87
|
+
layer.resize();
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -284,8 +284,7 @@ class Painter {
|
|
|
284
284
|
|
|
285
285
|
this.symbolFadeChange = style.placement.symbolFadeChange(browser.now());
|
|
286
286
|
|
|
287
|
-
const
|
|
288
|
-
const sourceCaches = this.style.sourceCaches;
|
|
287
|
+
const sourceCaches = style._sources;
|
|
289
288
|
|
|
290
289
|
for (const id in sourceCaches) {
|
|
291
290
|
const sourceCache = sourceCaches[id];
|
|
@@ -314,10 +313,11 @@ class Painter {
|
|
|
314
313
|
updateTileMasks(visibleTiles, this.context);
|
|
315
314
|
}
|
|
316
315
|
|
|
316
|
+
const layers = Array.from(style._layers.values());
|
|
317
|
+
|
|
317
318
|
this.opaquePassCutoff = Number.POSITIVE_INFINITY;
|
|
318
|
-
for (let i = 0; i <
|
|
319
|
-
|
|
320
|
-
if (this.style._layers[layerId].is3D()) {
|
|
319
|
+
for (let i = 0; i < layers.length; i++) {
|
|
320
|
+
if (layers[i].is3D()) {
|
|
321
321
|
this.opaquePassCutoff = i;
|
|
322
322
|
break;
|
|
323
323
|
}
|
|
@@ -330,8 +330,7 @@ class Painter {
|
|
|
330
330
|
this.renderPass = 'offscreen';
|
|
331
331
|
this.depthRboNeedsClear = true;
|
|
332
332
|
|
|
333
|
-
for (const
|
|
334
|
-
const layer = this.style._layers[layerId];
|
|
333
|
+
for (const layer of layers) {
|
|
335
334
|
if (!layer.hasOffscreenPass() || layer.isHidden(this.transform.zoom)) continue;
|
|
336
335
|
|
|
337
336
|
const coords = coordsDescending[layer.source];
|
|
@@ -349,14 +348,14 @@ class Painter {
|
|
|
349
348
|
this.clearStencil();
|
|
350
349
|
|
|
351
350
|
this._showOverdrawInspector = options.showOverdrawInspector;
|
|
352
|
-
this.depthRangeFor3D = [0, 1 - (style.
|
|
351
|
+
this.depthRangeFor3D = [0, 1 - (style._layers.size + 2) * this.numSublayers * this.depthEpsilon];
|
|
353
352
|
|
|
354
353
|
// Opaque pass ===============================================
|
|
355
354
|
// Draw opaque layers top-to-bottom first.
|
|
356
355
|
this.renderPass = 'opaque';
|
|
357
356
|
|
|
358
|
-
for (this.currentLayer =
|
|
359
|
-
const layer =
|
|
357
|
+
for (this.currentLayer = layers.length - 1; this.currentLayer >= 0; this.currentLayer--) {
|
|
358
|
+
const layer = layers[this.currentLayer];
|
|
360
359
|
const sourceCache = sourceCaches[layer.source];
|
|
361
360
|
const coords = coordsAscending[layer.source];
|
|
362
361
|
|
|
@@ -368,8 +367,8 @@ class Painter {
|
|
|
368
367
|
// Draw all other layers bottom-to-top.
|
|
369
368
|
this.renderPass = 'translucent';
|
|
370
369
|
|
|
371
|
-
for (this.currentLayer = 0; this.currentLayer <
|
|
372
|
-
const layer =
|
|
370
|
+
for (this.currentLayer = 0; this.currentLayer < layers.length; this.currentLayer++) {
|
|
371
|
+
const layer = layers[this.currentLayer];
|
|
373
372
|
const sourceCache = sourceCaches[layer.source];
|
|
374
373
|
|
|
375
374
|
// For symbol layers in the translucent pass, we add extra tiles to the renderable set
|
|
@@ -14,7 +14,7 @@ const circleUniformValues = (painter, coord, tile, layer) => {
|
|
|
14
14
|
|
|
15
15
|
let pitchWithMap;
|
|
16
16
|
let extrudeScale;
|
|
17
|
-
if (layer.
|
|
17
|
+
if (layer._paint.get('circle-pitch-alignment') === 'map') {
|
|
18
18
|
const pixelRatio = pixelsToTileUnits(tile, 1, transform.zoom);
|
|
19
19
|
pitchWithMap = true;
|
|
20
20
|
extrudeScale = [pixelRatio, pixelRatio];
|
|
@@ -25,12 +25,12 @@ const circleUniformValues = (painter, coord, tile, layer) => {
|
|
|
25
25
|
|
|
26
26
|
return {
|
|
27
27
|
u_camera_to_center_distance: transform.cameraToCenterDistance,
|
|
28
|
-
u_scale_with_map: +(layer.
|
|
28
|
+
u_scale_with_map: +(layer._paint.get('circle-pitch-scale') === 'map'),
|
|
29
29
|
u_matrix: painter.translatePosMatrix(
|
|
30
30
|
coord.posMatrix,
|
|
31
31
|
tile,
|
|
32
|
-
layer.
|
|
33
|
-
layer.
|
|
32
|
+
layer._paint.get('circle-translate'),
|
|
33
|
+
layer._paint.get('circle-translate-anchor')
|
|
34
34
|
),
|
|
35
35
|
u_pitch_with_map: +pitchWithMap,
|
|
36
36
|
u_extrude_scale: extrudeScale
|
|
@@ -29,7 +29,7 @@ const fillExtrusionPatternUniforms = (context, locations) => ({
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
const fillExtrusionUniformValues = (matrix, painter, shouldUseVerticalGradient, opacity) => {
|
|
32
|
-
const light = painter.style.
|
|
32
|
+
const light = painter.style._light;
|
|
33
33
|
const _lp = light.properties.get('position');
|
|
34
34
|
const lightPos = [_lp.x, _lp.y, _lp.z];
|
|
35
35
|
const lightMat = mat3.create();
|
|
@@ -34,7 +34,7 @@ const heatmapTextureUniformValues = (painter, layer, textureUnit, colorRampUnit)
|
|
|
34
34
|
u_world: [gl.drawingBufferWidth, gl.drawingBufferHeight],
|
|
35
35
|
u_image: textureUnit,
|
|
36
36
|
u_color_ramp: colorRampUnit,
|
|
37
|
-
u_opacity: layer.
|
|
37
|
+
u_opacity: layer._paint.get('heatmap-opacity')
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
40
|
|
|
@@ -24,13 +24,13 @@ const hillshadePrepareUniforms = (context, locations) => ({
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
const hillshadeUniformValues = (painter, tile, layer) => {
|
|
27
|
-
const shadow = layer.
|
|
28
|
-
const highlight = layer.
|
|
29
|
-
const accent = layer.
|
|
27
|
+
const shadow = layer._paint.get('hillshade-shadow-color');
|
|
28
|
+
const highlight = layer._paint.get('hillshade-highlight-color');
|
|
29
|
+
const accent = layer._paint.get('hillshade-accent-color');
|
|
30
30
|
|
|
31
|
-
let azimuthal = layer.
|
|
31
|
+
let azimuthal = layer._paint.get('hillshade-illumination-direction') * (Math.PI / 180);
|
|
32
32
|
// modify azimuthal angle by map rotation if light is anchored at the viewport
|
|
33
|
-
if (layer.
|
|
33
|
+
if (layer._paint.get('hillshade-illumination-anchor') === 'viewport') {
|
|
34
34
|
azimuthal -= painter.transform.angle;
|
|
35
35
|
}
|
|
36
36
|
const align = !painter.options.moving;
|
|
@@ -38,7 +38,7 @@ const hillshadeUniformValues = (painter, tile, layer) => {
|
|
|
38
38
|
u_matrix: painter.transform.calculatePosMatrix(tile.tileID.toUnwrapped(), align),
|
|
39
39
|
u_image: 0,
|
|
40
40
|
u_latrange: getTileLatRange(painter, tile.tileID),
|
|
41
|
-
u_light: [layer.
|
|
41
|
+
u_light: [layer._paint.get('hillshade-exaggeration'), azimuthal],
|
|
42
42
|
u_shadow: shadow,
|
|
43
43
|
u_highlight: highlight,
|
|
44
44
|
u_accent: accent
|
|
@@ -75,7 +75,7 @@ const lineSDFUniformValues = (painter, tile, layer, dasharray, crossfade) => {
|
|
|
75
75
|
const lineAtlas = painter.lineAtlas;
|
|
76
76
|
const tileRatio = calculateTileRatio(tile, transform);
|
|
77
77
|
|
|
78
|
-
const round = layer.
|
|
78
|
+
const round = layer._layout.get('line-cap') === 'round';
|
|
79
79
|
|
|
80
80
|
const posA = lineAtlas.getDash(dasharray.from, round);
|
|
81
81
|
const posB = lineAtlas.getDash(dasharray.to, round);
|
|
@@ -102,8 +102,8 @@ function calculateMatrix(painter, tile, layer) {
|
|
|
102
102
|
return painter.translatePosMatrix(
|
|
103
103
|
tile.tileID.posMatrix,
|
|
104
104
|
tile,
|
|
105
|
-
layer.
|
|
106
|
-
layer.
|
|
105
|
+
layer._paint.get('line-translate'),
|
|
106
|
+
layer._paint.get('line-translate-anchor')
|
|
107
107
|
);
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -22,14 +22,14 @@ const rasterUniformValues = (matrix, parentTL, parentScaleBy, fade, layer) => ({
|
|
|
22
22
|
u_scale_parent: parentScaleBy,
|
|
23
23
|
u_buffer_scale: 1,
|
|
24
24
|
u_fade_t: fade.mix,
|
|
25
|
-
u_opacity: fade.opacity * layer.
|
|
25
|
+
u_opacity: fade.opacity * layer._paint.get('raster-opacity'),
|
|
26
26
|
u_image0: 0,
|
|
27
27
|
u_image1: 1,
|
|
28
|
-
u_brightness_low: layer.
|
|
29
|
-
u_brightness_high: layer.
|
|
30
|
-
u_saturation_factor: saturationFactor(layer.
|
|
31
|
-
u_contrast_factor: contrastFactor(layer.
|
|
32
|
-
u_spin_weights: spinWeights(layer.
|
|
28
|
+
u_brightness_low: layer._paint.get('raster-brightness-min'),
|
|
29
|
+
u_brightness_high: layer._paint.get('raster-brightness-max'),
|
|
30
|
+
u_saturation_factor: saturationFactor(layer._paint.get('raster-saturation')),
|
|
31
|
+
u_contrast_factor: contrastFactor(layer._paint.get('raster-contrast')),
|
|
32
|
+
u_spin_weights: spinWeights(layer._paint.get('raster-hue-rotate'))
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
function spinWeights(angle) {
|
|
@@ -2,6 +2,7 @@ const { Event, ErrorEvent, Evented } = require('@mapwhit/events');
|
|
|
2
2
|
|
|
3
3
|
const EXTENT = require('../data/extent');
|
|
4
4
|
const browser = require('../util/browser');
|
|
5
|
+
const GeoJSONWorkerSource = require('./geojson_worker_source');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* A source containing GeoJSON.
|
|
@@ -52,8 +53,9 @@ class GeoJSONSource extends Evented {
|
|
|
52
53
|
#pendingDataEvents = new Set();
|
|
53
54
|
#newData = false;
|
|
54
55
|
#updateInProgress = false;
|
|
56
|
+
#worker;
|
|
55
57
|
|
|
56
|
-
constructor(id, options,
|
|
58
|
+
constructor(id, options, eventedParent, { resources, layerIndex }) {
|
|
57
59
|
super();
|
|
58
60
|
|
|
59
61
|
this.id = id;
|
|
@@ -69,10 +71,9 @@ class GeoJSONSource extends Evented {
|
|
|
69
71
|
this.reparseOverscaled = true;
|
|
70
72
|
this._removed = false;
|
|
71
73
|
|
|
72
|
-
this.dispatcher = dispatcher;
|
|
73
74
|
this.setEventedParent(eventedParent);
|
|
74
75
|
|
|
75
|
-
this.
|
|
76
|
+
this.data = options.data;
|
|
76
77
|
this._options = Object.assign({}, options);
|
|
77
78
|
|
|
78
79
|
if (options.maxzoom !== undefined) this.maxzoom = options.maxzoom;
|
|
@@ -107,6 +108,7 @@ class GeoJSONSource extends Evented {
|
|
|
107
108
|
},
|
|
108
109
|
options.workerOptions
|
|
109
110
|
);
|
|
111
|
+
this.#worker = new GeoJSONWorkerSource(resources, layerIndex);
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
load() {
|
|
@@ -125,7 +127,7 @@ class GeoJSONSource extends Evented {
|
|
|
125
127
|
* @returns {GeoJSONSource} this
|
|
126
128
|
*/
|
|
127
129
|
setData(data) {
|
|
128
|
-
this.
|
|
130
|
+
this.data = data;
|
|
129
131
|
this.#updateData();
|
|
130
132
|
return this;
|
|
131
133
|
}
|
|
@@ -142,7 +144,7 @@ class GeoJSONSource extends Evented {
|
|
|
142
144
|
this.fire(new Event('dataloading', { dataType: 'source' }));
|
|
143
145
|
while (this.#newData) {
|
|
144
146
|
this.#newData = false;
|
|
145
|
-
await this._updateWorkerData(this.
|
|
147
|
+
await this._updateWorkerData(this.data);
|
|
146
148
|
}
|
|
147
149
|
this.#pendingDataEvents.forEach(sourceDataType =>
|
|
148
150
|
this.fire(new Event('data', { dataType: 'source', sourceDataType }))
|
|
@@ -165,13 +167,9 @@ class GeoJSONSource extends Evented {
|
|
|
165
167
|
if (!json) {
|
|
166
168
|
throw new Error('no GeoJSON data');
|
|
167
169
|
}
|
|
168
|
-
const options = { ...this.workerOptions, data:
|
|
169
|
-
this.workerID ??= this.dispatcher.nextWorkerId();
|
|
170
|
+
const options = { ...this.workerOptions, data: json };
|
|
170
171
|
|
|
171
|
-
|
|
172
|
-
// so that other geojson-like source types can easily reuse this
|
|
173
|
-
// implementation
|
|
174
|
-
await this.dispatcher.send(`${this.type}.loadData`, options, this.workerID);
|
|
172
|
+
return await this.#worker.loadData(options);
|
|
175
173
|
}
|
|
176
174
|
|
|
177
175
|
async loadTile(tile) {
|
|
@@ -185,14 +183,15 @@ class GeoJSONSource extends Evented {
|
|
|
185
183
|
source: this.id,
|
|
186
184
|
pixelRatio: browser.devicePixelRatio,
|
|
187
185
|
showCollisionBoxes: this.map.showCollisionBoxes,
|
|
188
|
-
globalState: this.map.getGlobalState()
|
|
186
|
+
globalState: this.map.getGlobalState(),
|
|
187
|
+
justReloaded: tile.workerID != null,
|
|
188
|
+
painter: this.map.painter
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const data = await this.dispatcher.send('loadTile', params, tile.workerID).finally(() => tile.unloadVectorData());
|
|
191
|
+
tile.workerID ??= true;
|
|
192
|
+
const data = await this.#worker.loadTile(params).finally(() => tile.unloadVectorData());
|
|
194
193
|
if (!tile.aborted) {
|
|
195
|
-
tile.loadVectorData(data, this.map.painter
|
|
194
|
+
tile.loadVectorData(data, this.map.painter);
|
|
196
195
|
}
|
|
197
196
|
}
|
|
198
197
|
|
|
@@ -206,14 +205,6 @@ class GeoJSONSource extends Evented {
|
|
|
206
205
|
|
|
207
206
|
onRemove() {
|
|
208
207
|
this._removed = true;
|
|
209
|
-
return this.dispatcher.send('removeSource', { type: this.type, source: this.id }, this.workerID);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
serialize() {
|
|
213
|
-
return Object.assign({}, this._options, {
|
|
214
|
-
type: this.type,
|
|
215
|
-
data: this._data
|
|
216
|
-
});
|
|
217
208
|
}
|
|
218
209
|
|
|
219
210
|
hasTransition() {
|
|
@@ -1,68 +1,14 @@
|
|
|
1
1
|
const rewind = require('@mapwhit/geojson-rewind');
|
|
2
2
|
const GeoJSONWrapper = require('./geojson_wrapper');
|
|
3
|
-
const { fromVectorTileJs } = require('@mapwhit/vt-pbf');
|
|
4
3
|
const { default: Supercluster } = require('supercluster');
|
|
5
4
|
const { default: geojsonvt } = require('geojson-vt');
|
|
6
5
|
const VectorTileWorkerSource = require('./vector_tile_worker_source');
|
|
7
6
|
|
|
8
|
-
function loadGeoJSONTile(params) {
|
|
9
|
-
if (!this._geoJSONIndex) {
|
|
10
|
-
if (!this._createGeoJSONIndex) {
|
|
11
|
-
return; // we couldn't load the file
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
this._geoJSONIndex = this._createGeoJSONIndex();
|
|
16
|
-
} finally {
|
|
17
|
-
this._createGeoJSONIndex = null;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const { z, x, y } = params.tileID.canonical;
|
|
22
|
-
const geoJSONTile = this._geoJSONIndex.getTile(z, x, y);
|
|
23
|
-
if (!geoJSONTile) {
|
|
24
|
-
return; // nothing in the given tile
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const geojsonWrapper = new GeoJSONWrapper(geoJSONTile.features);
|
|
28
|
-
|
|
29
|
-
// Encode the geojson-vt tile into binary vector tile form. This
|
|
30
|
-
// is a convenience that allows `FeatureIndex` to operate the same way
|
|
31
|
-
// across `VectorTileSource` and `GeoJSONSource` data.
|
|
32
|
-
let pbf = fromVectorTileJs(geojsonWrapper);
|
|
33
|
-
if (pbf.byteOffset !== 0 || pbf.byteLength !== pbf.buffer.byteLength) {
|
|
34
|
-
// Compatibility with node Buffer (https://github.com/mapbox/pbf/issues/35)
|
|
35
|
-
pbf = new Uint8Array(pbf);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
vectorTile: geojsonWrapper,
|
|
40
|
-
rawData: pbf.buffer
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
7
|
/**
|
|
45
8
|
* The {@link WorkerSource} implementation that supports {@link GeoJSONSource}.
|
|
46
|
-
* This class is designed to be easily reused to support custom source types
|
|
47
|
-
* for data formats that can be parsed/converted into an in-memory GeoJSON
|
|
48
|
-
* representation. To do so, create it with
|
|
49
|
-
* `new GeoJSONWorkerSource(resources, layerIndex, customLoadGeoJSONFunction)`.
|
|
50
|
-
* For a full example, see [mapbox-gl-topojson](https://github.com/developmentseed/mapbox-gl-topojson).
|
|
51
9
|
*
|
|
52
10
|
*/
|
|
53
11
|
class GeoJSONWorkerSource extends VectorTileWorkerSource {
|
|
54
|
-
/**
|
|
55
|
-
* @param [loadGeoJSON] Optional method for custom loading/parsing of
|
|
56
|
-
* GeoJSON based on parameters passed from the main-thread Source.
|
|
57
|
-
* See {@link GeoJSONWorkerSource#loadGeoJSON}.
|
|
58
|
-
*/
|
|
59
|
-
constructor(resources, layerIndex, loadGeoJSON) {
|
|
60
|
-
super(resources, layerIndex, loadGeoJSONTile);
|
|
61
|
-
if (loadGeoJSON) {
|
|
62
|
-
this.loadGeoJSON = loadGeoJSON;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
12
|
/**
|
|
67
13
|
* Fetches (if appropriate), parses, and index geojson data into tiles. This
|
|
68
14
|
* preparatory method must be called before {@link GeoJSONWorkerSource#loadTile}
|
|
@@ -76,7 +22,7 @@ class GeoJSONWorkerSource extends VectorTileWorkerSource {
|
|
|
76
22
|
* @param callback
|
|
77
23
|
*/
|
|
78
24
|
loadData(params) {
|
|
79
|
-
const data =
|
|
25
|
+
const data = loadJSON(params.data);
|
|
80
26
|
this._geoJSONIndex = null;
|
|
81
27
|
this._createGeoJSONIndex = params.cluster
|
|
82
28
|
? () => {
|
|
@@ -89,20 +35,46 @@ class GeoJSONWorkerSource extends VectorTileWorkerSource {
|
|
|
89
35
|
};
|
|
90
36
|
}
|
|
91
37
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
38
|
+
getTile(tileID) {
|
|
39
|
+
if (!this._geoJSONIndex) {
|
|
40
|
+
if (!this._createGeoJSONIndex) {
|
|
41
|
+
return; // we couldn't load the file
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
this._geoJSONIndex = this._createGeoJSONIndex();
|
|
46
|
+
} finally {
|
|
47
|
+
this._createGeoJSONIndex = null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const { z, x, y } = tileID.canonical;
|
|
51
|
+
return this._geoJSONIndex.getTile(z, x, y);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
loadVectorData({ tileID }) {
|
|
55
|
+
const geoJSONTile = this.getTile(tileID);
|
|
56
|
+
if (!geoJSONTile) {
|
|
57
|
+
return; // nothing in the given tile
|
|
105
58
|
}
|
|
59
|
+
|
|
60
|
+
const vectorTile = new GeoJSONWrapper(geoJSONTile.features);
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
vectorTile
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Fetch and parse GeoJSON according to the given params.
|
|
70
|
+
*
|
|
71
|
+
* @param data Literal GeoJSON data. Must be provided.
|
|
72
|
+
*/
|
|
73
|
+
function loadJSON(data) {
|
|
74
|
+
try {
|
|
75
|
+
return typeof data === 'string' ? JSON.parse(data) : data;
|
|
76
|
+
} catch (e) {
|
|
77
|
+
throw new Error('Input data is not a valid GeoJSON object.');
|
|
106
78
|
}
|
|
107
79
|
}
|
|
108
80
|
|
|
@@ -20,6 +20,14 @@ class FeatureWrapper {
|
|
|
20
20
|
if ('id' in feature && !isNaN(feature.id)) {
|
|
21
21
|
this.id = Number.parseInt(feature.id, 10);
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
// fix geometry - it has to be at least array of 2 points
|
|
25
|
+
if (typeof this._feature.geometry[0] === 'number') {
|
|
26
|
+
this._feature.geometry = [this._feature.geometry];
|
|
27
|
+
if (this._feature.geometry.length === 1) {
|
|
28
|
+
this._feature.geometry.push(this._feature.geometry[0]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
23
31
|
}
|
|
24
32
|
|
|
25
33
|
get type() {
|
|
@@ -27,7 +35,7 @@ class FeatureWrapper {
|
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
get properties() {
|
|
30
|
-
return this._feature.tags;
|
|
38
|
+
return this._feature.tags ?? {};
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
get extent() {
|
|
@@ -2,7 +2,6 @@ const { getCoordinatesCenter } = require('../util/util');
|
|
|
2
2
|
|
|
3
3
|
const { CanonicalTileID } = require('./tile_id');
|
|
4
4
|
const LngLat = require('../geo/lng_lat');
|
|
5
|
-
const { default: Point } = require('@mapbox/point-geometry');
|
|
6
5
|
const { Event, ErrorEvent, Evented } = require('@mapwhit/events');
|
|
7
6
|
const loadImage = require('../util/loader/image');
|
|
8
7
|
const EXTENT = require('../data/extent');
|
|
@@ -44,10 +43,9 @@ class ImageSource extends Evented {
|
|
|
44
43
|
/**
|
|
45
44
|
* @private
|
|
46
45
|
*/
|
|
47
|
-
constructor(id, options,
|
|
46
|
+
constructor(id, options, eventedParent) {
|
|
48
47
|
super();
|
|
49
48
|
this.id = id;
|
|
50
|
-
this.dispatcher = dispatcher;
|
|
51
49
|
this.coordinates = options.coordinates;
|
|
52
50
|
|
|
53
51
|
this.type = 'image';
|
|
@@ -125,10 +123,10 @@ class ImageSource extends Evented {
|
|
|
125
123
|
// tile.
|
|
126
124
|
const tileCoords = cornerZ0Coords.map(coord => {
|
|
127
125
|
const zoomedCoord = coord.zoomTo(centerCoord.zoom);
|
|
128
|
-
return
|
|
129
|
-
Math.round((zoomedCoord.column - centerCoord.column) * EXTENT),
|
|
130
|
-
Math.round((zoomedCoord.row - centerCoord.row) * EXTENT)
|
|
131
|
-
|
|
126
|
+
return {
|
|
127
|
+
x: Math.round((zoomedCoord.column - centerCoord.column) * EXTENT),
|
|
128
|
+
y: Math.round((zoomedCoord.row - centerCoord.row) * EXTENT)
|
|
129
|
+
};
|
|
132
130
|
});
|
|
133
131
|
|
|
134
132
|
this._boundsArray = new RasterBoundsArray();
|
|
@@ -185,21 +183,13 @@ class ImageSource extends Evented {
|
|
|
185
183
|
// single tile.
|
|
186
184
|
if (this.tileID?.equals(tile.tileID.canonical)) {
|
|
187
185
|
this.tiles[String(tile.tileID.wrap)] = tile;
|
|
188
|
-
tile.buckets =
|
|
186
|
+
tile.buckets = new Map();
|
|
189
187
|
} else {
|
|
190
188
|
tile.state = 'errored';
|
|
191
189
|
}
|
|
192
190
|
return Promise.resolve();
|
|
193
191
|
}
|
|
194
192
|
|
|
195
|
-
serialize() {
|
|
196
|
-
return {
|
|
197
|
-
type: 'image',
|
|
198
|
-
url: this.options.url,
|
|
199
|
-
coordinates: this.coordinates
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
193
|
hasTransition() {
|
|
204
194
|
return false;
|
|
205
195
|
}
|
|
@@ -20,14 +20,13 @@ function getPixelPosMatrix(transform, tileID) {
|
|
|
20
20
|
function queryIncludes3DLayer(layers, styleLayers, sourceID) {
|
|
21
21
|
if (layers) {
|
|
22
22
|
for (const layerID of layers) {
|
|
23
|
-
const layer = styleLayers
|
|
23
|
+
const layer = styleLayers.get(layerID);
|
|
24
24
|
if (layer && layer.source === sourceID && layer.type === 'fill-extrusion') {
|
|
25
25
|
return true;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
} else {
|
|
29
|
-
for (const
|
|
30
|
-
const layer = styleLayers[key];
|
|
28
|
+
} else if (styleLayers) {
|
|
29
|
+
for (const layer of styleLayers.values()) {
|
|
31
30
|
if (layer.source === sourceID && layer.type === 'fill-extrusion') {
|
|
32
31
|
return true;
|
|
33
32
|
}
|
|
@@ -129,7 +128,7 @@ function queryRenderedSymbols(styleLayers, sourceCaches, queryGeometry, params,
|
|
|
129
128
|
for (const layerName in result) {
|
|
130
129
|
result[layerName].forEach(featureWrapper => {
|
|
131
130
|
const feature = featureWrapper.feature;
|
|
132
|
-
const layer = styleLayers
|
|
131
|
+
const layer = styleLayers.get(layerName);
|
|
133
132
|
const sourceCache = sourceCaches[layer.source];
|
|
134
133
|
const state = sourceCache.getFeatureState(feature.layer['source-layer'], feature.id);
|
|
135
134
|
feature.source = feature.layer.source;
|