@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.
Files changed (142) hide show
  1. package/README.md +7 -0
  2. package/build/min/package.json +1 -1
  3. package/build/min/src/shaders/_prelude.fragment.glsl.js +2 -2
  4. package/build/min/src/shaders/_prelude.vertex.glsl.js +2 -2
  5. package/build/min/src/shaders/background.fragment.glsl.js +2 -2
  6. package/build/min/src/shaders/background.vertex.glsl.js +1 -1
  7. package/build/min/src/shaders/background_pattern.fragment.glsl.js +2 -2
  8. package/build/min/src/shaders/background_pattern.vertex.glsl.js +1 -1
  9. package/build/min/src/shaders/circle.fragment.glsl.js +2 -2
  10. package/build/min/src/shaders/circle.vertex.glsl.js +2 -2
  11. package/build/min/src/shaders/clipping_mask.fragment.glsl.js +1 -1
  12. package/build/min/src/shaders/clipping_mask.vertex.glsl.js +1 -1
  13. package/build/min/src/shaders/collision_box.fragment.glsl.js +1 -1
  14. package/build/min/src/shaders/collision_box.vertex.glsl.js +1 -1
  15. package/build/min/src/shaders/collision_circle.fragment.glsl.js +1 -1
  16. package/build/min/src/shaders/collision_circle.vertex.glsl.js +1 -1
  17. package/build/min/src/shaders/debug.fragment.glsl.js +1 -1
  18. package/build/min/src/shaders/debug.vertex.glsl.js +1 -1
  19. package/build/min/src/shaders/fill.fragment.glsl.js +2 -2
  20. package/build/min/src/shaders/fill.vertex.glsl.js +2 -2
  21. package/build/min/src/shaders/fill_extrusion.fragment.glsl.js +2 -2
  22. package/build/min/src/shaders/fill_extrusion.vertex.glsl.js +2 -2
  23. package/build/min/src/shaders/fill_extrusion_pattern.fragment.glsl.js +2 -2
  24. package/build/min/src/shaders/fill_extrusion_pattern.vertex.glsl.js +2 -2
  25. package/build/min/src/shaders/fill_outline.fragment.glsl.js +2 -2
  26. package/build/min/src/shaders/fill_outline.vertex.glsl.js +2 -2
  27. package/build/min/src/shaders/fill_outline_pattern.fragment.glsl.js +2 -2
  28. package/build/min/src/shaders/fill_outline_pattern.vertex.glsl.js +2 -2
  29. package/build/min/src/shaders/fill_pattern.fragment.glsl.js +2 -2
  30. package/build/min/src/shaders/fill_pattern.vertex.glsl.js +2 -2
  31. package/build/min/src/shaders/heatmap.fragment.glsl.js +2 -2
  32. package/build/min/src/shaders/heatmap.vertex.glsl.js +2 -2
  33. package/build/min/src/shaders/heatmap_texture.fragment.glsl.js +2 -2
  34. package/build/min/src/shaders/heatmap_texture.vertex.glsl.js +1 -1
  35. package/build/min/src/shaders/hillshade.fragment.glsl.js +2 -2
  36. package/build/min/src/shaders/hillshade.vertex.glsl.js +1 -1
  37. package/build/min/src/shaders/hillshade_prepare.fragment.glsl.js +2 -2
  38. package/build/min/src/shaders/hillshade_prepare.vertex.glsl.js +1 -1
  39. package/build/min/src/shaders/line.fragment.glsl.js +2 -2
  40. package/build/min/src/shaders/line.vertex.glsl.js +2 -2
  41. package/build/min/src/shaders/line_gradient.fragment.glsl.js +2 -2
  42. package/build/min/src/shaders/line_gradient.vertex.glsl.js +2 -2
  43. package/build/min/src/shaders/line_pattern.fragment.glsl.js +2 -2
  44. package/build/min/src/shaders/line_pattern.vertex.glsl.js +2 -2
  45. package/build/min/src/shaders/line_sdf.fragment.glsl.js +2 -2
  46. package/build/min/src/shaders/line_sdf.vertex.glsl.js +2 -2
  47. package/build/min/src/shaders/raster.fragment.glsl.js +2 -2
  48. package/build/min/src/shaders/raster.vertex.glsl.js +1 -1
  49. package/build/min/src/shaders/symbol_icon.fragment.glsl.js +2 -2
  50. package/build/min/src/shaders/symbol_icon.vertex.glsl.js +2 -2
  51. package/build/min/src/shaders/symbol_sdf.fragment.glsl.js +2 -2
  52. package/build/min/src/shaders/symbol_sdf.vertex.glsl.js +2 -2
  53. package/package.json +3 -3
  54. package/src/data/array_types.js +1 -36
  55. package/src/data/bucket/circle_bucket.js +8 -5
  56. package/src/data/bucket/fill_bucket.js +8 -5
  57. package/src/data/bucket/fill_extrusion_bucket.js +8 -5
  58. package/src/data/bucket/heatmap_bucket.js +0 -4
  59. package/src/data/bucket/line_bucket.js +9 -6
  60. package/src/data/bucket/pattern_bucket_features.js +2 -2
  61. package/src/data/bucket/symbol_bucket.js +99 -129
  62. package/src/data/bucket.js +26 -21
  63. package/src/data/dem_data.js +0 -3
  64. package/src/data/feature_index.js +3 -8
  65. package/src/data/program_configuration.js +24 -33
  66. package/src/data/segment.js +0 -4
  67. package/src/render/draw_background.js +3 -3
  68. package/src/render/draw_circle.js +4 -4
  69. package/src/render/draw_fill.js +8 -8
  70. package/src/render/draw_fill_extrusion.js +8 -8
  71. package/src/render/draw_heatmap.js +4 -4
  72. package/src/render/draw_line.js +6 -6
  73. package/src/render/draw_raster.js +6 -6
  74. package/src/render/draw_symbol.js +16 -16
  75. package/src/render/glyph_atlas.js +0 -3
  76. package/src/render/glyph_manager.js +1 -2
  77. package/src/render/image_atlas.js +0 -4
  78. package/src/render/image_manager.js +33 -19
  79. package/src/render/painter.js +13 -14
  80. package/src/render/program/circle_program.js +4 -4
  81. package/src/render/program/fill_extrusion_program.js +1 -1
  82. package/src/render/program/heatmap_program.js +1 -1
  83. package/src/render/program/hillshade_program.js +6 -6
  84. package/src/render/program/line_program.js +3 -3
  85. package/src/render/program/raster_program.js +6 -6
  86. package/src/source/geojson_source.js +15 -24
  87. package/src/source/geojson_worker_source.js +40 -68
  88. package/src/source/geojson_wrapper.js +9 -1
  89. package/src/source/image_source.js +6 -16
  90. package/src/source/query_features.js +4 -5
  91. package/src/source/raster_dem_tile_source.js +45 -64
  92. package/src/source/raster_tile_source.js +1 -6
  93. package/src/source/resources/glyphs.js +2 -2
  94. package/src/source/resources/index.js +3 -9
  95. package/src/source/rtl_text_plugin.js +58 -31
  96. package/src/source/source.js +11 -13
  97. package/src/source/source_cache.js +135 -151
  98. package/src/source/source_state.js +101 -12
  99. package/src/source/tile.js +32 -46
  100. package/src/source/tile_bounds.js +26 -26
  101. package/src/source/tile_id.js +2 -5
  102. package/src/source/vector_tile_source.js +14 -14
  103. package/src/source/vector_tile_worker_source.js +19 -23
  104. package/src/source/worker_tile.js +122 -119
  105. package/src/style/create_style_layer.js +1 -1
  106. package/src/style/pauseable_placement.js +4 -5
  107. package/src/style/properties.js +1 -8
  108. package/src/style/query_utils.js +3 -3
  109. package/src/style/style.js +286 -216
  110. package/src/style/style_layer/circle_style_layer.js +13 -11
  111. package/src/style/style_layer/fill_extrusion_style_layer.js +42 -27
  112. package/src/style/style_layer/fill_style_layer.js +5 -5
  113. package/src/style/style_layer/heatmap_style_layer.js +1 -1
  114. package/src/style/style_layer/hillshade_style_layer.js +1 -1
  115. package/src/style/style_layer/line_style_layer.js +23 -19
  116. package/src/style/style_layer/symbol_style_layer.js +13 -13
  117. package/src/style/style_layer.js +71 -30
  118. package/src/style/style_layer_index.js +16 -41
  119. package/src/symbol/anchor.js +0 -4
  120. package/src/symbol/cross_tile_symbol_index.js +2 -5
  121. package/src/symbol/opacity_state.js +0 -4
  122. package/src/symbol/placement.js +3 -3
  123. package/src/symbol/quads.js +4 -4
  124. package/src/symbol/symbol_layout.js +7 -7
  125. package/src/symbol/transform_text.js +1 -1
  126. package/src/ui/map.js +52 -15
  127. package/src/util/group_layers.js +41 -0
  128. package/src/util/image.js +0 -5
  129. package/src/util/key.js +21 -0
  130. package/src/util/object.js +8 -53
  131. package/src/worker.js +1 -4
  132. package/src/source/resources/images.js +0 -68
  133. package/src/source/worker.js +0 -110
  134. package/src/source/worker_source.js +0 -14
  135. package/src/style-spec/deref.js +0 -51
  136. package/src/style-spec/group_by_layout.js +0 -46
  137. package/src/util/actor.js +0 -108
  138. package/src/util/dispatcher.js +0 -65
  139. package/src/util/global_worker_pool.js +0 -15
  140. package/src/util/transfer_registry.js +0 -168
  141. package/src/util/web_worker_transfer.js +0 -43
  142. package/src/util/worker_pool.js +0 -41
@@ -1,23 +1,84 @@
1
1
  /**
2
- * SourceFeatureState manages the state and state changes
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, state) {
16
+ updateState(sourceLayer, feature, newState) {
12
17
  const changes = (this.#stateChanges[sourceLayer] ??= {});
13
18
  const featureState = (changes[feature] ??= {});
14
- Object.assign(featureState, state);
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
- return Object.assign({}, base?.[feature], changes?.[feature]);
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
- const changes = {};
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 id in this.#stateChanges[sourceLayer]) {
33
- this.#state[sourceLayer][id] ??= {};
34
- Object.assign(this.#state[sourceLayer][id], this.#stateChanges[sourceLayer][id]);
35
- layerStates[id] = this.#state[sourceLayer][id];
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
- changes[sourceLayer] = layerStates;
120
+
121
+ featuresChanged[sourceLayer] = featuresChanged[sourceLayer] || {};
122
+ Object.assign(featuresChanged[sourceLayer], layerStates);
38
123
  }
39
124
  this.#stateChanges = {};
40
- if (Object.keys(changes).length === 0) return;
125
+ this.#deletedStates = {};
41
126
 
42
- Object.values(tiles).forEach(tile => tile.setFeatureState(changes, painter));
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
 
@@ -1,13 +1,12 @@
1
1
  const { deepEqual } = require('../util/object');
2
2
  const uniqueId = require('../util/unique_id');
3
- const { deserialize: deserializeBucket } = require('../data/bucket');
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, justReloaded) {
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
- // Only vector tiles have rawTileData, and they won't update it for
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
- this.hasSymbolBuckets = false;
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.queryPadding = 0;
104
- for (const id in this.buckets) {
105
- const bucket = this.buckets[id];
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 Object.values(this.buckets)) {
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[layer.id];
131
+ return this.buckets.get(layer.id);
145
132
  }
146
133
 
147
134
  upload(context) {
148
- for (const id in this.buckets) {
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?.rawTileData) return {};
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?.rawTileData) return;
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 tlVertex = new Point(maskCoord.x * vertexExtent, maskCoord.y * vertexExtent);
262
- const brVertex = new Point(tlVertex.x + vertexExtent, tlVertex.y + vertexExtent);
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(tlVertex.x, tlVertex.y, tlVertex.x, tlVertex.y);
268
- maskedBoundsArray.emplaceBack(brVertex.x, tlVertex.y, brVertex.x, tlVertex.y);
269
- maskedBoundsArray.emplaceBack(tlVertex.x, brVertex.y, tlVertex.x, brVertex.y);
270
- maskedBoundsArray.emplaceBack(brVertex.x, brVertex.y, brVertex.x, brVertex.y);
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?.rawTileData || Object.keys(states).length === 0) {
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 in this.buckets) {
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.convert(this.validateBounds(bounds));
8
- this.minzoom = minzoom || 0;
9
- this.maxzoom = maxzoom || 24;
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
- validateBounds(bounds) {
13
- // make sure the bounds property contains valid longitude and latitudes
14
- if (!Array.isArray(bounds) || bounds.length !== 4) return [-180, -90, 180, 90];
15
- return [Math.max(-180, bounds[0]), Math.max(-90, bounds[1]), Math.min(180, bounds[2]), Math.min(90, bounds[3])];
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
- contains(tileID) {
19
- const level = {
20
- minX: Math.floor(this.lngX(this.bounds.getWest(), tileID.z)),
21
- minY: Math.floor(this.latY(this.bounds.getNorth(), tileID.z)),
22
- maxX: Math.ceil(this.lngX(this.bounds.getEast(), tileID.z)),
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
- lngX(lng, zoom) {
30
- return (lng + 180) * (2 ** zoom / 360);
31
- }
30
+ function lngX(lng, zoom) {
31
+ return (lng + 180) * (2 ** zoom / 360);
32
+ }
32
33
 
33
- latY(lat, zoom) {
34
- const f = clamp(Math.sin((Math.PI / 180) * lat), -0.9999, 0.9999);
35
- const scale = 2 ** zoom / (2 * Math.PI);
36
- return 2 ** (zoom - 1) + 0.5 * Math.log((1 + f) / (1 - f)) * -scale;
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;
@@ -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
- constructor(id, options, dispatcher, eventedParent) {
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.slice() },
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 ??= this.dispatcher.nextWorkerId();
101
- const data = await this.dispatcher.send('loadTile', params, tile.workerID);
102
- data.rawTileData = rawData;
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 WorkerTile = require('./worker_tile');
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, loadVectorData = loadVectorTile) {
21
+ constructor(resources, layerIndex) {
35
22
  this.resources = resources;
36
23
  this.layerIndex = layerIndex;
37
- this.loadVectorData = loadVectorData;
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, rawData } = response;
51
- const workerTile = new WorkerTile(params);
52
- workerTile.globalState = params.globalState;
53
- workerTile.vectorTile = vectorTile;
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
  }