@mapwhit/tilerenderer 0.52.0 → 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 +8 -5
- package/src/data/bucket/fill_bucket.js +8 -5
- package/src/data/bucket/fill_extrusion_bucket.js +8 -5
- package/src/data/bucket/heatmap_bucket.js +0 -4
- package/src/data/bucket/line_bucket.js +9 -6
- package/src/data/bucket/pattern_bucket_features.js +2 -2
- package/src/data/bucket/symbol_bucket.js +99 -129
- 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 +24 -33
- 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 +122 -119
- 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 +286 -216
- 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 +71 -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 +52 -15
- 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
|
@@ -1,23 +1,84 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SourceFeatureState manages the state and
|
|
2
|
+
* SourceFeatureState manages the state and pending changes
|
|
3
3
|
* to features in a source, separated by source layer.
|
|
4
|
+
* stateChanges and deletedStates batch all changes to the tile (updates and removes, respectively)
|
|
5
|
+
* between coalesce() events. addFeatureState() and removeFeatureState() also update their counterpart's
|
|
6
|
+
* list of changes, such that coalesce() can apply the proper state changes while agnostic to the order of operations.
|
|
7
|
+
* In deletedStates, all null's denote complete removal of state at that scope
|
|
4
8
|
*
|
|
5
9
|
* @private
|
|
6
10
|
*/
|
|
7
11
|
class SourceFeatureState {
|
|
8
12
|
#state = {};
|
|
9
13
|
#stateChanges = {};
|
|
14
|
+
#deletedStates = {};
|
|
10
15
|
|
|
11
|
-
updateState(sourceLayer, feature,
|
|
16
|
+
updateState(sourceLayer, feature, newState) {
|
|
12
17
|
const changes = (this.#stateChanges[sourceLayer] ??= {});
|
|
13
18
|
const featureState = (changes[feature] ??= {});
|
|
14
|
-
Object.assign(featureState,
|
|
19
|
+
Object.assign(featureState, newState);
|
|
20
|
+
|
|
21
|
+
if (this.#deletedStates[sourceLayer] === null) {
|
|
22
|
+
this.#deletedStates[sourceLayer] = {};
|
|
23
|
+
for (const ft in this.#state[sourceLayer]) {
|
|
24
|
+
if (ft !== feature) this.#deletedStates[sourceLayer][ft] = null;
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
const featureDeletionQueued =
|
|
28
|
+
this.#deletedStates[sourceLayer] && this.#deletedStates[sourceLayer][feature] === null;
|
|
29
|
+
if (featureDeletionQueued) {
|
|
30
|
+
this.#deletedStates[sourceLayer][feature] = {};
|
|
31
|
+
for (const prop in this.state[sourceLayer][feature]) {
|
|
32
|
+
if (!newState[prop]) this.#deletedStates[sourceLayer][feature][prop] = null;
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
for (const key in newState) {
|
|
36
|
+
const deletionInQueue = this.#deletedStates[sourceLayer]?.[feature]?.[key] === null;
|
|
37
|
+
if (deletionInQueue) delete this.#deletedStates[sourceLayer][feature][key];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
removeFeatureState(sourceLayer, featureId, key) {
|
|
44
|
+
const sourceLayerDeleted = this.#deletedStates[sourceLayer] === null;
|
|
45
|
+
if (sourceLayerDeleted) return;
|
|
46
|
+
|
|
47
|
+
const feature = String(featureId);
|
|
48
|
+
|
|
49
|
+
this.#deletedStates[sourceLayer] = this.#deletedStates[sourceLayer] || {};
|
|
50
|
+
|
|
51
|
+
if (key && featureId !== undefined) {
|
|
52
|
+
if (this.#deletedStates[sourceLayer][feature] !== null) {
|
|
53
|
+
this.#deletedStates[sourceLayer][feature] = this.#deletedStates[sourceLayer][feature] || {};
|
|
54
|
+
this.#deletedStates[sourceLayer][feature][key] = null;
|
|
55
|
+
}
|
|
56
|
+
} else if (featureId !== undefined) {
|
|
57
|
+
const updateInQueue = this.#stateChanges[sourceLayer]?.[feature];
|
|
58
|
+
if (updateInQueue) {
|
|
59
|
+
this.#deletedStates[sourceLayer][feature] = {};
|
|
60
|
+
for (key in this.#stateChanges[sourceLayer][feature]) this.#deletedStates[sourceLayer][feature][key] = null;
|
|
61
|
+
} else {
|
|
62
|
+
this.#deletedStates[sourceLayer][feature] = null;
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
this.#deletedStates[sourceLayer] = null;
|
|
66
|
+
}
|
|
15
67
|
}
|
|
16
68
|
|
|
17
69
|
getState(sourceLayer, feature) {
|
|
18
70
|
const base = this.#state[sourceLayer];
|
|
19
71
|
const changes = this.#stateChanges[sourceLayer];
|
|
20
|
-
|
|
72
|
+
const reconciledState = Object.assign({}, base?.[feature], changes?.[feature]);
|
|
73
|
+
|
|
74
|
+
//return empty object if the whole source layer is awaiting deletion
|
|
75
|
+
if (this.#deletedStates[sourceLayer] === null) return {};
|
|
76
|
+
if (this.#deletedStates[sourceLayer]) {
|
|
77
|
+
const featureDeletions = this.#deletedStates[sourceLayer][feature];
|
|
78
|
+
if (featureDeletions === null) return {};
|
|
79
|
+
for (const prop in featureDeletions) delete reconciledState[prop];
|
|
80
|
+
}
|
|
81
|
+
return reconciledState;
|
|
21
82
|
}
|
|
22
83
|
|
|
23
84
|
initializeTileState(tile, painter) {
|
|
@@ -25,21 +86,49 @@ class SourceFeatureState {
|
|
|
25
86
|
}
|
|
26
87
|
|
|
27
88
|
coalesceChanges(tiles, painter) {
|
|
28
|
-
|
|
89
|
+
//track changes with full state objects, but only for features that got modified
|
|
90
|
+
const featuresChanged = {};
|
|
29
91
|
for (const sourceLayer in this.#stateChanges) {
|
|
30
92
|
this.#state[sourceLayer] ??= {};
|
|
31
93
|
const layerStates = {};
|
|
32
|
-
for (const
|
|
33
|
-
this.#state[sourceLayer][
|
|
34
|
-
Object.assign(this.#state[sourceLayer][
|
|
35
|
-
layerStates[
|
|
94
|
+
for (const feature in this.#stateChanges[sourceLayer]) {
|
|
95
|
+
if (!this.#state[sourceLayer][feature]) this.#state[sourceLayer][feature] = {};
|
|
96
|
+
Object.assign(this.#state[sourceLayer][feature], this.#stateChanges[sourceLayer][feature]);
|
|
97
|
+
layerStates[feature] = this.#state[sourceLayer][feature];
|
|
98
|
+
}
|
|
99
|
+
featuresChanged[sourceLayer] = layerStates;
|
|
100
|
+
}
|
|
101
|
+
for (const sourceLayer in this.#deletedStates) {
|
|
102
|
+
this.#state[sourceLayer] = this.#state[sourceLayer] || {};
|
|
103
|
+
const layerStates = {};
|
|
104
|
+
|
|
105
|
+
if (this.#deletedStates[sourceLayer] === null) {
|
|
106
|
+
for (const ft in this.#state[sourceLayer]) layerStates[ft] = {};
|
|
107
|
+
this.#state[sourceLayer] = {};
|
|
108
|
+
} else {
|
|
109
|
+
for (const feature in this.#deletedStates[sourceLayer]) {
|
|
110
|
+
const deleteWholeFeatureState = this.#deletedStates[sourceLayer][feature] === null;
|
|
111
|
+
if (deleteWholeFeatureState) this.#state[sourceLayer][feature] = {};
|
|
112
|
+
else {
|
|
113
|
+
for (const key of Object.keys(this.#deletedStates[sourceLayer][feature])) {
|
|
114
|
+
delete this.#state[sourceLayer][feature][key];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
layerStates[feature] = this.#state[sourceLayer][feature];
|
|
118
|
+
}
|
|
36
119
|
}
|
|
37
|
-
|
|
120
|
+
|
|
121
|
+
featuresChanged[sourceLayer] = featuresChanged[sourceLayer] || {};
|
|
122
|
+
Object.assign(featuresChanged[sourceLayer], layerStates);
|
|
38
123
|
}
|
|
39
124
|
this.#stateChanges = {};
|
|
40
|
-
|
|
125
|
+
this.#deletedStates = {};
|
|
41
126
|
|
|
42
|
-
Object.
|
|
127
|
+
if (Object.keys(featuresChanged).length === 0) return;
|
|
128
|
+
|
|
129
|
+
for (const tile of tiles) {
|
|
130
|
+
tile.setFeatureState(featuresChanged, painter);
|
|
131
|
+
}
|
|
43
132
|
}
|
|
44
133
|
}
|
|
45
134
|
|
package/src/source/tile.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
const { deepEqual } = require('../util/object');
|
|
2
2
|
const uniqueId = require('../util/unique_id');
|
|
3
|
-
const {
|
|
3
|
+
const { updateBuckets } = require('../data/bucket');
|
|
4
4
|
const GeoJSONFeature = require('../util/vectortile_to_geojson');
|
|
5
5
|
const featureFilter = require('../style-spec/feature_filter');
|
|
6
6
|
const SymbolBucket = require('../data/bucket/symbol_bucket');
|
|
7
7
|
const { RasterBoundsArray, CollisionBoxArray } = require('../data/array_types');
|
|
8
8
|
const rasterBoundsAttributes = require('../data/raster_bounds_attributes');
|
|
9
9
|
const EXTENT = require('../data/extent');
|
|
10
|
-
const { default: Point } = require('@mapbox/point-geometry');
|
|
11
10
|
const Texture = require('../render/texture');
|
|
12
11
|
const SegmentVector = require('../data/segment');
|
|
13
12
|
const { TriangleIndexArray } = require('../data/index_array_type');
|
|
@@ -30,7 +29,7 @@ class Tile {
|
|
|
30
29
|
this.uid = uniqueId();
|
|
31
30
|
this.uses = 0;
|
|
32
31
|
this.tileSize = size;
|
|
33
|
-
this.buckets =
|
|
32
|
+
this.buckets = new Map();
|
|
34
33
|
this.queryPadding = 0;
|
|
35
34
|
this.hasSymbolBuckets = false;
|
|
36
35
|
|
|
@@ -58,7 +57,7 @@ class Tile {
|
|
|
58
57
|
* @param painter
|
|
59
58
|
* @returns {undefined}
|
|
60
59
|
*/
|
|
61
|
-
loadVectorData(data, painter
|
|
60
|
+
loadVectorData(data, painter) {
|
|
62
61
|
if (this.hasData()) {
|
|
63
62
|
this.unloadVectorData();
|
|
64
63
|
}
|
|
@@ -73,38 +72,26 @@ class Tile {
|
|
|
73
72
|
|
|
74
73
|
if (data.featureIndex) {
|
|
75
74
|
this.latestFeatureIndex = data.featureIndex;
|
|
75
|
+
if (data.vectorTile) {
|
|
76
|
+
// Only vector tiles have `vectorTile`, and they won't update it for `reloadTile`
|
|
77
|
+
this.latestVectorTile = data.vectorTile;
|
|
78
|
+
this.latestFeatureIndex.vectorTile = data.vectorTile;
|
|
79
|
+
} else if (this.latestVectorTile) {
|
|
80
|
+
// If `vectorTile` hasn't updated, hold onto a pointer to the last one we received
|
|
81
|
+
this.latestFeatureIndex.vectorTile = this.latestVectorTile;
|
|
82
|
+
}
|
|
76
83
|
if (data.rawTileData) {
|
|
77
|
-
//
|
|
78
|
-
// 'reloadTile'
|
|
84
|
+
// rawTileData is present only in vector tiles and only in debug mode
|
|
79
85
|
this.latestRawTileData = data.rawTileData;
|
|
80
|
-
this.latestFeatureIndex.rawTileData = data.rawTileData;
|
|
81
|
-
} else if (this.latestRawTileData) {
|
|
82
|
-
// If rawTileData hasn't updated, hold onto a pointer to the last
|
|
83
|
-
// one we received
|
|
84
|
-
this.latestFeatureIndex.rawTileData = this.latestRawTileData;
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
this.collisionBoxArray = data.collisionBoxArray;
|
|
88
|
-
this.buckets = deserializeBucket(data.buckets, painter.style);
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
const buckets = Object.values(this.buckets);
|
|
92
|
-
for (const bucket of buckets) {
|
|
93
|
-
if (bucket instanceof SymbolBucket) {
|
|
94
|
-
this.hasSymbolBuckets = true;
|
|
95
|
-
if (justReloaded) {
|
|
96
|
-
bucket.justReloaded = true;
|
|
97
|
-
} else {
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
90
|
+
updateBuckets(data.buckets, painter.style);
|
|
102
91
|
|
|
103
|
-
this.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
this.queryPadding = Math.max(this.queryPadding, painter.style.getLayer(id).queryRadius(bucket));
|
|
107
|
-
}
|
|
92
|
+
this.buckets = data.buckets;
|
|
93
|
+
this.hasSymbolBuckets = data.hasSymbolBuckets;
|
|
94
|
+
this.queryPadding = data.queryPadding;
|
|
108
95
|
|
|
109
96
|
if (data.imageAtlas) {
|
|
110
97
|
this.imageAtlas = data.imageAtlas;
|
|
@@ -120,10 +107,10 @@ class Tile {
|
|
|
120
107
|
* @private
|
|
121
108
|
*/
|
|
122
109
|
unloadVectorData() {
|
|
123
|
-
for (const bucket of
|
|
110
|
+
for (const bucket of this.buckets.values()) {
|
|
124
111
|
bucket.destroy();
|
|
125
112
|
}
|
|
126
|
-
this.buckets
|
|
113
|
+
this.buckets.clear();
|
|
127
114
|
|
|
128
115
|
this.imageAtlasTexture?.destroy();
|
|
129
116
|
if (this.imageAtlas) {
|
|
@@ -141,12 +128,11 @@ class Tile {
|
|
|
141
128
|
}
|
|
142
129
|
|
|
143
130
|
getBucket(layer) {
|
|
144
|
-
return this.buckets
|
|
131
|
+
return this.buckets.get(layer.id);
|
|
145
132
|
}
|
|
146
133
|
|
|
147
134
|
upload(context) {
|
|
148
|
-
for (const
|
|
149
|
-
const bucket = this.buckets[id];
|
|
135
|
+
for (const bucket of this.buckets.values()) {
|
|
150
136
|
if (bucket.uploadPending()) {
|
|
151
137
|
bucket.upload(context);
|
|
152
138
|
}
|
|
@@ -178,7 +164,7 @@ class Tile {
|
|
|
178
164
|
maxPitchScaleFactor,
|
|
179
165
|
pixelPosMatrix
|
|
180
166
|
) {
|
|
181
|
-
if (!this.latestFeatureIndex?.
|
|
167
|
+
if (!this.latestFeatureIndex?.vectorTile) return {};
|
|
182
168
|
|
|
183
169
|
return this.latestFeatureIndex.query(
|
|
184
170
|
{
|
|
@@ -197,7 +183,7 @@ class Tile {
|
|
|
197
183
|
}
|
|
198
184
|
|
|
199
185
|
querySourceFeatures(result, params) {
|
|
200
|
-
if (!this.latestFeatureIndex?.
|
|
186
|
+
if (!this.latestFeatureIndex?.vectorTile) return;
|
|
201
187
|
|
|
202
188
|
const vtLayers = this.latestFeatureIndex.loadVTLayers();
|
|
203
189
|
|
|
@@ -258,16 +244,17 @@ class Tile {
|
|
|
258
244
|
for (let i = 0; i < maskArray.length; i++) {
|
|
259
245
|
const maskCoord = mask[maskArray[i]];
|
|
260
246
|
const vertexExtent = EXTENT >> maskCoord.z;
|
|
261
|
-
const
|
|
262
|
-
const
|
|
247
|
+
const tlVertexX = maskCoord.x * vertexExtent;
|
|
248
|
+
const tlVertexY = maskCoord.y * vertexExtent;
|
|
249
|
+
const brVertexX = tlVertexX + vertexExtent;
|
|
250
|
+
const brVertexY = tlVertexY + vertexExtent;
|
|
263
251
|
|
|
264
|
-
// not sure why flow is complaining here because it doesn't complain at L401
|
|
265
252
|
const segment = this.segments.prepareSegment(4, maskedBoundsArray, indexArray);
|
|
266
253
|
|
|
267
|
-
maskedBoundsArray.emplaceBack(
|
|
268
|
-
maskedBoundsArray.emplaceBack(
|
|
269
|
-
maskedBoundsArray.emplaceBack(
|
|
270
|
-
maskedBoundsArray.emplaceBack(
|
|
254
|
+
maskedBoundsArray.emplaceBack(tlVertexX, tlVertexY, tlVertexX, tlVertexY);
|
|
255
|
+
maskedBoundsArray.emplaceBack(brVertexX, tlVertexY, brVertexX, tlVertexY);
|
|
256
|
+
maskedBoundsArray.emplaceBack(tlVertexX, brVertexY, tlVertexX, brVertexY);
|
|
257
|
+
maskedBoundsArray.emplaceBack(brVertexX, brVertexY, brVertexX, brVertexY);
|
|
271
258
|
|
|
272
259
|
const offset = segment.vertexLength;
|
|
273
260
|
// 0, 1, 2
|
|
@@ -292,14 +279,13 @@ class Tile {
|
|
|
292
279
|
}
|
|
293
280
|
|
|
294
281
|
setFeatureState(states, painter) {
|
|
295
|
-
if (!this.latestFeatureIndex?.
|
|
282
|
+
if (!this.latestFeatureIndex?.vectorTile || Object.keys(states).length === 0) {
|
|
296
283
|
return;
|
|
297
284
|
}
|
|
298
285
|
|
|
299
286
|
const vtLayers = this.latestFeatureIndex.loadVTLayers();
|
|
300
287
|
|
|
301
|
-
for (const id
|
|
302
|
-
const bucket = this.buckets[id];
|
|
288
|
+
for (const [id, bucket] of this.buckets) {
|
|
303
289
|
// Buckets are grouped by common source-layer
|
|
304
290
|
const sourceLayerId = bucket.layers[0]['sourceLayer'] || '_geojsonTileLayer';
|
|
305
291
|
const sourceLayer = vtLayers[sourceLayerId];
|
|
@@ -3,38 +3,38 @@ const LngLatBounds = require('../geo/lng_lat_bounds');
|
|
|
3
3
|
const { clamp } = require('../util/util');
|
|
4
4
|
|
|
5
5
|
class TileBounds {
|
|
6
|
-
constructor(bounds, minzoom, maxzoom) {
|
|
7
|
-
this.bounds = LngLatBounds
|
|
8
|
-
this.minzoom = minzoom
|
|
9
|
-
this.maxzoom = maxzoom
|
|
6
|
+
constructor(bounds, minzoom = 0, maxzoom = 24) {
|
|
7
|
+
this.bounds = new LngLatBounds(validateBounds(bounds));
|
|
8
|
+
this.minzoom = minzoom;
|
|
9
|
+
this.maxzoom = maxzoom;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (
|
|
15
|
-
|
|
12
|
+
contains({ x, y, z }) {
|
|
13
|
+
const minX = Math.floor(lngX(this.bounds.getWest(), z));
|
|
14
|
+
if (x < minX) return false;
|
|
15
|
+
const maxX = Math.ceil(lngX(this.bounds.getEast(), z));
|
|
16
|
+
if (x >= maxX) return false;
|
|
17
|
+
const minY = Math.floor(latY(this.bounds.getNorth(), z));
|
|
18
|
+
if (y < minY) return false;
|
|
19
|
+
const maxY = Math.ceil(latY(this.bounds.getSouth(), z));
|
|
20
|
+
return y < maxY;
|
|
16
21
|
}
|
|
22
|
+
}
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
maxY: Math.ceil(this.latY(this.bounds.getSouth(), tileID.z))
|
|
24
|
-
};
|
|
25
|
-
const hit = tileID.x >= level.minX && tileID.x < level.maxX && tileID.y >= level.minY && tileID.y < level.maxY;
|
|
26
|
-
return hit;
|
|
27
|
-
}
|
|
24
|
+
function validateBounds(bounds) {
|
|
25
|
+
// make sure the bounds property contains valid longitude and latitudes
|
|
26
|
+
if (!Array.isArray(bounds) || bounds.length !== 4) return [-180, -90, 180, 90];
|
|
27
|
+
return [Math.max(-180, bounds[0]), Math.max(-90, bounds[1]), Math.min(180, bounds[2]), Math.min(90, bounds[3])];
|
|
28
|
+
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
function lngX(lng, zoom) {
|
|
31
|
+
return (lng + 180) * (2 ** zoom / 360);
|
|
32
|
+
}
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
34
|
+
function latY(lat, zoom) {
|
|
35
|
+
const f = clamp(Math.sin((Math.PI / 180) * lat), -0.9999, 0.9999);
|
|
36
|
+
const scale = 2 ** zoom / (2 * Math.PI);
|
|
37
|
+
return 2 ** (zoom - 1) + 0.5 * Math.log((1 + f) / (1 - f)) * -scale;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
module.exports = TileBounds;
|
package/src/source/tile_id.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const { getTileBBox } = require('@mapbox/whoots-js');
|
|
2
2
|
|
|
3
3
|
const assert = require('assert');
|
|
4
|
-
const { register } = require('../util/transfer_registry');
|
|
5
4
|
const Coordinate = require('../geo/coordinate');
|
|
6
5
|
|
|
7
6
|
class CanonicalTileID {
|
|
@@ -140,11 +139,9 @@ function calculateKey(wrap, z, x, y) {
|
|
|
140
139
|
return (dim * dim * wrap + dim * y + x) * 32 + z;
|
|
141
140
|
}
|
|
142
141
|
|
|
143
|
-
register('CanonicalTileID', CanonicalTileID);
|
|
144
|
-
register('OverscaledTileID', OverscaledTileID, { omit: ['posMatrix'] });
|
|
145
|
-
|
|
146
142
|
module.exports = {
|
|
147
143
|
CanonicalTileID,
|
|
148
144
|
UnwrappedTileID,
|
|
149
|
-
OverscaledTileID
|
|
145
|
+
OverscaledTileID,
|
|
146
|
+
calculateKey
|
|
150
147
|
};
|
|
@@ -3,15 +3,14 @@ const { pick } = require('../util/object');
|
|
|
3
3
|
const loadTileJSON = require('./load_tilejson');
|
|
4
4
|
const TileBounds = require('./tile_bounds');
|
|
5
5
|
const browser = require('../util/browser');
|
|
6
|
-
|
|
7
|
-
// register feature index for worker transfer
|
|
8
|
-
require('../data/feature_index');
|
|
6
|
+
const VectorTileWorkerSource = require('./vector_tile_worker_source');
|
|
9
7
|
|
|
10
8
|
class VectorTileSource extends Evented {
|
|
11
|
-
|
|
9
|
+
#worker;
|
|
10
|
+
|
|
11
|
+
constructor(id, options, eventedParent, { resources, layerIndex, showTileBoundaries }) {
|
|
12
12
|
super();
|
|
13
13
|
this.id = id;
|
|
14
|
-
this.dispatcher = dispatcher;
|
|
15
14
|
|
|
16
15
|
this.type = 'vector';
|
|
17
16
|
this.minzoom = 0;
|
|
@@ -20,6 +19,7 @@ class VectorTileSource extends Evented {
|
|
|
20
19
|
this.tileSize = 512;
|
|
21
20
|
this.reparseOverscaled = true;
|
|
22
21
|
this.isTileClipped = true;
|
|
22
|
+
this._showTileBoundaries = showTileBoundaries;
|
|
23
23
|
|
|
24
24
|
Object.assign(this, pick(options, ['url', 'scheme', 'tileSize']));
|
|
25
25
|
this._options = Object.assign({ type: 'vector' }, options);
|
|
@@ -29,6 +29,7 @@ class VectorTileSource extends Evented {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
this.setEventedParent(eventedParent);
|
|
32
|
+
this.#worker = new VectorTileWorkerSource(resources, layerIndex);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
async load() {
|
|
@@ -58,10 +59,6 @@ class VectorTileSource extends Evented {
|
|
|
58
59
|
this.load();
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
serialize() {
|
|
62
|
-
return Object.assign({}, this._options);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
62
|
async loadTile(tile) {
|
|
66
63
|
if (tile.workerID != null && tile.state === 'loading') {
|
|
67
64
|
tile.reloadPromise ??= Promise.withResolvers();
|
|
@@ -86,7 +83,7 @@ class VectorTileSource extends Evented {
|
|
|
86
83
|
throw err;
|
|
87
84
|
}
|
|
88
85
|
const params = {
|
|
89
|
-
response: { data: rawData
|
|
86
|
+
response: { data: rawData },
|
|
90
87
|
uid: tile.uid,
|
|
91
88
|
tileID: tile.tileID,
|
|
92
89
|
zoom: tile.tileID.overscaledZ,
|
|
@@ -95,11 +92,14 @@ class VectorTileSource extends Evented {
|
|
|
95
92
|
source: this.id,
|
|
96
93
|
pixelRatio: browser.devicePixelRatio,
|
|
97
94
|
showCollisionBoxes: this.map.showCollisionBoxes,
|
|
98
|
-
globalState: this.map.getGlobalState()
|
|
95
|
+
globalState: this.map.getGlobalState(),
|
|
96
|
+
painter: this.map.painter
|
|
99
97
|
};
|
|
100
|
-
tile.workerID ??=
|
|
101
|
-
const data = await this.
|
|
102
|
-
|
|
98
|
+
tile.workerID ??= true;
|
|
99
|
+
const data = await this.#worker.loadTile(params);
|
|
100
|
+
if (this._showTileBoundaries) {
|
|
101
|
+
data.rawTileData = rawData;
|
|
102
|
+
}
|
|
103
103
|
tile.loadVectorData(data, this.map.painter);
|
|
104
104
|
} catch (err) {
|
|
105
105
|
if (tile.aborted) {
|
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
const { VectorTile } = require('@mapwhit/vector-tile');
|
|
2
2
|
const Protobuf = require('@mapwhit/pbf');
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
function loadVectorTile(params) {
|
|
6
|
-
if (!params.response) {
|
|
7
|
-
throw new Error('no tile data');
|
|
8
|
-
}
|
|
9
|
-
const { data } = params.response;
|
|
10
|
-
if (!data) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
return {
|
|
14
|
-
vectorTile: new VectorTile(new Protobuf(data))
|
|
15
|
-
};
|
|
16
|
-
}
|
|
3
|
+
const makeWorkerTile = require('./worker_tile');
|
|
17
4
|
|
|
18
5
|
/**
|
|
19
6
|
* The {@link WorkerSource} implementation that supports {@link VectorTileSource}.
|
|
@@ -31,10 +18,22 @@ class VectorTileWorkerSource {
|
|
|
31
18
|
* {@link VectorTileWorkerSource#loadTile}. The default implementation simply
|
|
32
19
|
* loads the pbf at `params.url`.
|
|
33
20
|
*/
|
|
34
|
-
constructor(resources, layerIndex
|
|
21
|
+
constructor(resources, layerIndex) {
|
|
35
22
|
this.resources = resources;
|
|
36
23
|
this.layerIndex = layerIndex;
|
|
37
|
-
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
loadVectorData(params) {
|
|
27
|
+
if (!params.response) {
|
|
28
|
+
throw new Error('no tile data');
|
|
29
|
+
}
|
|
30
|
+
const { data } = params.response;
|
|
31
|
+
if (!data) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
vectorTile: new VectorTile(new Protobuf(data))
|
|
36
|
+
};
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
/**
|
|
@@ -47,13 +46,10 @@ class VectorTileWorkerSource {
|
|
|
47
46
|
if (!response) {
|
|
48
47
|
return;
|
|
49
48
|
}
|
|
50
|
-
const { vectorTile
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const result = await workerTile.parse(vectorTile, this.layerIndex, this.resources);
|
|
55
|
-
if (rawData) {
|
|
56
|
-
result.rawTileData = rawData;
|
|
49
|
+
const { vectorTile } = response;
|
|
50
|
+
const result = await makeWorkerTile(params, vectorTile, this.layerIndex, this.resources);
|
|
51
|
+
if (vectorTile) {
|
|
52
|
+
result.vectorTile = vectorTile;
|
|
57
53
|
}
|
|
58
54
|
return result;
|
|
59
55
|
}
|