@deck.gl/geo-layers 8.7.0-alpha.3 → 8.7.0-beta.1

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 (75) hide show
  1. package/dist/dist.dev.js +8074 -4705
  2. package/dist/es5/great-circle-layer/great-circle-layer.js +26 -1
  3. package/dist/es5/great-circle-layer/great-circle-layer.js.map +1 -1
  4. package/dist/es5/h3-layers/h3-cluster-layer.js +149 -87
  5. package/dist/es5/h3-layers/h3-cluster-layer.js.map +1 -1
  6. package/dist/es5/h3-layers/h3-hexagon-layer.js +326 -230
  7. package/dist/es5/h3-layers/h3-hexagon-layer.js.map +1 -1
  8. package/dist/es5/index.js +17 -9
  9. package/dist/es5/index.js.map +1 -1
  10. package/dist/es5/mesh-layer/mesh-layer-vertex.glsl.js +1 -1
  11. package/dist/es5/mesh-layer/mesh-layer.js +153 -132
  12. package/dist/es5/mesh-layer/mesh-layer.js.map +1 -1
  13. package/dist/es5/mvt-layer/coordinate-transform.js +46 -20
  14. package/dist/es5/mvt-layer/coordinate-transform.js.map +1 -1
  15. package/dist/es5/mvt-layer/find-index-binary.js +45 -26
  16. package/dist/es5/mvt-layer/find-index-binary.js.map +1 -1
  17. package/dist/es5/mvt-layer/mvt-layer.js +395 -280
  18. package/dist/es5/mvt-layer/mvt-layer.js.map +1 -1
  19. package/dist/es5/s2-layer/s2-geometry.js +43 -32
  20. package/dist/es5/s2-layer/s2-geometry.js.map +1 -1
  21. package/dist/es5/s2-layer/s2-layer.js +104 -69
  22. package/dist/es5/s2-layer/s2-layer.js.map +1 -1
  23. package/dist/es5/s2-layer/s2-utils.js +27 -28
  24. package/dist/es5/s2-layer/s2-utils.js.map +1 -1
  25. package/dist/es5/terrain-layer/terrain-layer.js +250 -208
  26. package/dist/es5/terrain-layer/terrain-layer.js.map +1 -1
  27. package/dist/es5/tile-3d-layer/tile-3d-layer.js +384 -329
  28. package/dist/es5/tile-3d-layer/tile-3d-layer.js.map +1 -1
  29. package/dist/es5/tile-layer/tile-2d-header.js +182 -118
  30. package/dist/es5/tile-layer/tile-2d-header.js.map +1 -1
  31. package/dist/es5/tile-layer/tile-2d-traversal.js +176 -113
  32. package/dist/es5/tile-layer/tile-2d-traversal.js.map +1 -1
  33. package/dist/es5/tile-layer/tile-layer.js +253 -214
  34. package/dist/es5/tile-layer/tile-layer.js.map +1 -1
  35. package/dist/es5/tile-layer/tileset-2d.js +519 -300
  36. package/dist/es5/tile-layer/tileset-2d.js.map +1 -1
  37. package/dist/es5/tile-layer/utils.js +111 -62
  38. package/dist/es5/tile-layer/utils.js.map +1 -1
  39. package/dist/es5/trips-layer/trips-layer.js +81 -44
  40. package/dist/es5/trips-layer/trips-layer.js.map +1 -1
  41. package/dist/esm/h3-layers/h3-hexagon-layer.js +2 -1
  42. package/dist/esm/h3-layers/h3-hexagon-layer.js.map +1 -1
  43. package/dist/esm/index.js +1 -0
  44. package/dist/esm/index.js.map +1 -1
  45. package/dist/esm/mesh-layer/mesh-layer-vertex.glsl.js +1 -1
  46. package/dist/esm/mesh-layer/mesh-layer-vertex.glsl.js.map +1 -1
  47. package/dist/esm/mesh-layer/mesh-layer.js +2 -8
  48. package/dist/esm/mesh-layer/mesh-layer.js.map +1 -1
  49. package/dist/esm/mvt-layer/coordinate-transform.js +1 -1
  50. package/dist/esm/mvt-layer/coordinate-transform.js.map +1 -1
  51. package/dist/esm/mvt-layer/mvt-layer.js +27 -1
  52. package/dist/esm/mvt-layer/mvt-layer.js.map +1 -1
  53. package/dist/esm/terrain-layer/terrain-layer.js +8 -10
  54. package/dist/esm/terrain-layer/terrain-layer.js.map +1 -1
  55. package/dist/esm/tile-3d-layer/tile-3d-layer.js +2 -1
  56. package/dist/esm/tile-3d-layer/tile-3d-layer.js.map +1 -1
  57. package/dist/esm/tile-layer/tile-layer.js +8 -16
  58. package/dist/esm/tile-layer/tile-layer.js.map +1 -1
  59. package/dist/esm/tile-layer/tileset-2d.js +85 -79
  60. package/dist/esm/tile-layer/tileset-2d.js.map +1 -1
  61. package/dist/esm/tile-layer/utils.js +1 -1
  62. package/dist/esm/tile-layer/utils.js.map +1 -1
  63. package/dist.min.js +2 -2
  64. package/package.json +12 -12
  65. package/src/h3-layers/h3-hexagon-layer.js +2 -1
  66. package/src/{index.js → index.ts} +2 -0
  67. package/src/mesh-layer/mesh-layer-vertex.glsl.js +24 -23
  68. package/src/mesh-layer/mesh-layer.js +5 -4
  69. package/src/mvt-layer/coordinate-transform.js +1 -1
  70. package/src/mvt-layer/mvt-layer.js +17 -1
  71. package/src/terrain-layer/terrain-layer.js +10 -9
  72. package/src/tile-3d-layer/tile-3d-layer.js +10 -2
  73. package/src/tile-layer/tile-layer.js +11 -12
  74. package/src/tile-layer/tileset-2d.js +103 -90
  75. package/src/tile-layer/utils.js +4 -4
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@deck.gl/geo-layers",
3
3
  "description": "deck.gl layers supporting geospatial use cases and GIS formats",
4
4
  "license": "MIT",
5
- "version": "8.7.0-alpha.3",
5
+ "version": "8.7.0-beta.1",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
@@ -29,18 +29,18 @@
29
29
  "prepublishOnly": "npm run build-bundle && npm run build-bundle -- --env.dev"
30
30
  },
31
31
  "dependencies": {
32
- "@loaders.gl/3d-tiles": "^3.0.8",
33
- "@loaders.gl/gis": "^3.0.8",
34
- "@loaders.gl/loader-utils": "^3.0.8",
35
- "@loaders.gl/mvt": "^3.0.8",
36
- "@loaders.gl/terrain": "^3.0.8",
37
- "@loaders.gl/tiles": "^3.0.8",
32
+ "@loaders.gl/3d-tiles": "^3.1.5",
33
+ "@loaders.gl/gis": "^3.1.5",
34
+ "@loaders.gl/loader-utils": "^3.1.5",
35
+ "@loaders.gl/mvt": "^3.1.5",
36
+ "@loaders.gl/terrain": "^3.1.5",
37
+ "@loaders.gl/tiles": "^3.1.5",
38
38
  "@luma.gl/experimental": "^8.5.10",
39
- "@math.gl/culling": "^3.5.4",
40
- "@math.gl/web-mercator": "^3.5.4",
39
+ "@math.gl/core": "^3.5.6",
40
+ "@math.gl/culling": "^3.5.6",
41
+ "@math.gl/web-mercator": "^3.5.6",
41
42
  "h3-js": "^3.6.0",
42
- "long": "^3.2.0",
43
- "math.gl": "^3.5.4"
43
+ "long": "^3.2.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@deck.gl/core": "^8.0.0",
@@ -49,5 +49,5 @@
49
49
  "@deck.gl/mesh-layers": "^8.0.0",
50
50
  "@loaders.gl/core": "^3.0.0"
51
51
  },
52
- "gitHead": "03fd8c4caae96d66bd651cb76e11a6d05acf8f8c"
52
+ "gitHead": "0297ca9d2c85d980b075e2af4cfbeb75e31db55a"
53
53
  }
@@ -8,7 +8,7 @@ import {
8
8
  edgeLength,
9
9
  UNITS
10
10
  } from 'h3-js';
11
- import {lerp} from 'math.gl';
11
+ import {lerp} from '@math.gl/core';
12
12
  import {CompositeLayer, createIterable} from '@deck.gl/core';
13
13
  import {ColumnLayer, PolygonLayer} from '@deck.gl/layers';
14
14
 
@@ -304,6 +304,7 @@ export default class H3HexagonLayer extends CompositeLayer {
304
304
  forwardProps,
305
305
  this.getSubLayerProps({
306
306
  id: 'hexagon-cell',
307
+ flatShading: true,
307
308
  updateTriggers: forwardProps.updateTriggers
308
309
  }),
309
310
  {
@@ -28,3 +28,5 @@ export {default as H3HexagonLayer} from './h3-layers/h3-hexagon-layer';
28
28
  export {default as Tile3DLayer} from './tile-3d-layer/tile-3d-layer';
29
29
  export {default as TerrainLayer} from './terrain-layer/terrain-layer';
30
30
  export {default as MVTLayer} from './mvt-layer/mvt-layer';
31
+
32
+ export {getURLFromTemplate as _getURLFromTemplate} from './tile-layer/utils';
@@ -26,12 +26,18 @@ out vec3 normals_commonspace;
26
26
  out vec4 position_commonspace;
27
27
  out vec4 vColor;
28
28
 
29
- void main(void) {
30
- // https://github.com/Esri/i3s-spec/blob/master/docs/1.7/geometryUVRegion.cmn.md
31
- vec2 uv = fract(texCoords) * (uvRegions.zw - uvRegions.xy) + uvRegions.xy;
29
+ vec2 applyUVRegion(vec2 uv) {
30
+ #ifdef HAS_UV_REGIONS
31
+ // https://github.com/Esri/i3s-spec/blob/master/docs/1.7/geometryUVRegion.cmn.md
32
+ return fract(uv) * (uvRegions.zw - uvRegions.xy) + uvRegions.xy;
33
+ #else
34
+ return uv;
35
+ #endif
36
+ }
32
37
 
38
+ void main(void) {
39
+ vec2 uv = applyUVRegion(texCoords);
33
40
  geometry.uv = uv;
34
- geometry.uv = texCoords;
35
41
 
36
42
  if (u_pickFeatureIds) {
37
43
  geometry.pickingColor = featureIdsPickingColors;
@@ -39,26 +45,9 @@ void main(void) {
39
45
  geometry.pickingColor = instancePickingColors;
40
46
  }
41
47
 
42
- #ifdef MODULE_PBR
43
- // set PBR data
44
- #ifdef HAS_NORMALS
45
- pbr_vNormal = project_normal(instanceModelMatrix * normals);
46
- geometry.normal = pbr_vNormal;
47
- #endif
48
-
49
- #ifdef HAS_UV
50
- pbr_vUV = uv;
51
- #else
52
- pbr_vUV = vec2(0., 0.);
53
- #endif
54
- geometry.uv = pbr_vUV;
55
- #endif
56
-
57
48
  vTexCoord = uv;
58
49
  cameraPosition = project_uCameraPosition;
59
- normals_commonspace = project_normal(instanceModelMatrix * normals);
60
50
  vColor = vec4(colors * instanceColors.rgb, instanceColors.a);
61
- geometry.normal = normals_commonspace;
62
51
 
63
52
  vec3 pos = (instanceModelMatrix * positions) * sizeScale;
64
53
  vec3 projectedPosition = project_position(positions);
@@ -66,13 +55,25 @@ void main(void) {
66
55
  gl_Position = project_common_position_to_clipspace(position_commonspace);
67
56
 
68
57
  geometry.position = position_commonspace;
58
+ normals_commonspace = project_normal(instanceModelMatrix * normals);
59
+ geometry.normal = normals_commonspace;
60
+
61
+ DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
69
62
 
70
63
  #ifdef MODULE_PBR
71
64
  // set PBR data
72
65
  pbr_vPosition = geometry.position.xyz;
73
- #endif
66
+ #ifdef HAS_NORMALS
67
+ pbr_vNormal = geometry.normal;
68
+ #endif
74
69
 
75
- DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
70
+ #ifdef HAS_UV
71
+ pbr_vUV = uv;
72
+ #else
73
+ pbr_vUV = vec2(0., 0.);
74
+ #endif
75
+ geometry.uv = pbr_vUV;
76
+ #endif
76
77
 
77
78
  DECKGL_FILTER_COLOR(vColor, geometry);
78
79
  }
@@ -11,9 +11,6 @@ function validateGeometryAttributes(attributes) {
11
11
  if (!hasColorAttribute) {
12
12
  attributes.colors = {constant: true, value: new Float32Array([1, 1, 1])};
13
13
  }
14
- if (!attributes.uvRegions) {
15
- attributes.uvRegions = {constant: true, value: new Float32Array([0, 0, 1, 1])};
16
- }
17
14
  }
18
15
 
19
16
  const defaultProps = {
@@ -76,7 +73,11 @@ export default class _MeshLayer extends SimpleMeshLayer {
76
73
  ...this.getShaders(),
77
74
  id,
78
75
  geometry: mesh,
79
- defines: {...shaders.defines, ...materialParser?.defines},
76
+ defines: {
77
+ ...shaders.defines,
78
+ ...materialParser?.defines,
79
+ HAS_UV_REGIONS: mesh.attributes.uvRegions
80
+ },
80
81
  parameters: materialParser?.parameters,
81
82
  isInstanced: true
82
83
  });
@@ -1,4 +1,4 @@
1
- import {lerp} from 'math.gl';
1
+ import {lerp} from '@math.gl/core';
2
2
 
3
3
  const availableTransformations = {
4
4
  Point,
@@ -1,5 +1,5 @@
1
1
  import {log} from '@deck.gl/core';
2
- import {Matrix4} from 'math.gl';
2
+ import {Matrix4} from '@math.gl/core';
3
3
  import {MVTWorkerLoader} from '@loaders.gl/mvt';
4
4
  import {binaryToGeojson} from '@loaders.gl/gis';
5
5
  import {COORDINATE_SYSTEM} from '@deck.gl/core';
@@ -43,6 +43,10 @@ export default class MVTLayer extends TileLayer {
43
43
  super.updateState({props, oldProps, context, changeFlags});
44
44
  this._setWGS84PropertyForTiles();
45
45
  }
46
+ const {highlightColor} = props;
47
+ if (highlightColor !== oldProps.highlightColor && Array.isArray(highlightColor)) {
48
+ this.setState({highlightColor});
49
+ }
46
50
  }
47
51
 
48
52
  /* eslint-disable complexity */
@@ -167,12 +171,17 @@ export default class MVTLayer extends TileLayer {
167
171
  newHoveredFeatureId = getFeatureUniqueId(hoveredFeature, uniqueIdProperty);
168
172
  newHoveredFeatureLayerName = getFeatureLayerName(hoveredFeature);
169
173
  }
174
+ let {highlightColor} = this.props;
175
+ if (typeof highlightColor === 'function') {
176
+ highlightColor = highlightColor(info);
177
+ }
170
178
 
171
179
  if (
172
180
  hoveredFeatureId !== newHoveredFeatureId ||
173
181
  hoveredFeatureLayerName !== newHoveredFeatureLayerName
174
182
  ) {
175
183
  this.setState({
184
+ highlightColor,
176
185
  hoveredFeatureId: newHoveredFeatureId,
177
186
  hoveredFeatureLayerName: newHoveredFeatureLayerName
178
187
  });
@@ -195,6 +204,13 @@ export default class MVTLayer extends TileLayer {
195
204
  return info;
196
205
  }
197
206
 
207
+ getSubLayerPropsByTile(tile) {
208
+ return {
209
+ highlightedObjectIndex: this.getHighlightedObjectIndex(tile),
210
+ highlightColor: this.state.highlightColor
211
+ };
212
+ }
213
+
198
214
  getHighlightedObjectIndex(tile) {
199
215
  const {hoveredFeatureId, hoveredFeatureLayerName} = this.state;
200
216
  const {uniqueIdProperty, highlightedFeatureId, binary} = this.props;
@@ -20,7 +20,7 @@
20
20
 
21
21
  import {CompositeLayer, log} from '@deck.gl/core';
22
22
  import {SimpleMeshLayer} from '@deck.gl/mesh-layers';
23
- import {WebMercatorViewport, COORDINATE_SYSTEM} from '@deck.gl/core';
23
+ import {COORDINATE_SYSTEM} from '@deck.gl/core';
24
24
  import {TerrainWorkerLoader} from '@loaders.gl/terrain';
25
25
  import TileLayer from '../tile-layer/tile-layer';
26
26
  import {urlType, getURLFromTemplate} from '../tile-layer/utils';
@@ -123,17 +123,17 @@ export default class TerrainLayer extends CompositeLayer {
123
123
 
124
124
  getTiledTerrainData(tile) {
125
125
  const {elevationData, fetch, texture, elevationDecoder, meshMaxError} = this.props;
126
+ const {viewport} = this.context;
126
127
  const dataUrl = getURLFromTemplate(elevationData, tile);
127
128
  const textureUrl = getURLFromTemplate(texture, tile);
128
129
 
129
- const {bbox, signal, z} = tile;
130
- const viewport = new WebMercatorViewport({
131
- longitude: (bbox.west + bbox.east) / 2,
132
- latitude: (bbox.north + bbox.south) / 2,
133
- zoom: z
134
- });
135
- const bottomLeft = viewport.projectFlat([bbox.west, bbox.south]);
136
- const topRight = viewport.projectFlat([bbox.east, bbox.north]);
130
+ const {bbox, signal} = tile;
131
+ const bottomLeft = viewport.isGeospatial
132
+ ? viewport.projectFlat([bbox.west, bbox.south])
133
+ : [bbox.left, bbox.bottom];
134
+ const topRight = viewport.isGeospatial
135
+ ? viewport.projectFlat([bbox.east, bbox.north])
136
+ : [bbox.right, bbox.top];
137
137
  const bounds = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]];
138
138
 
139
139
  const terrain = this.loadTerrain({
@@ -165,6 +165,7 @@ export default class TerrainLayer extends CompositeLayer {
165
165
  data: DUMMY_DATA,
166
166
  mesh,
167
167
  texture,
168
+ _instanced: false,
168
169
  coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
169
170
  getPosition: d => [0, 0, 0],
170
171
  getColor: color
@@ -262,7 +262,15 @@ export default class Tile3DLayer extends CompositeLayer {
262
262
 
263
263
  _makeSimpleMeshLayer(tileHeader, oldLayer) {
264
264
  const content = tileHeader.content;
265
- const {attributes, indices, modelMatrix, cartographicOrigin, material, featureIds} = content;
265
+ const {
266
+ attributes,
267
+ indices,
268
+ modelMatrix,
269
+ cartographicOrigin,
270
+ coordinateSystem = COORDINATE_SYSTEM.METER_OFFSETS,
271
+ material,
272
+ featureIds
273
+ } = content;
266
274
  const {_getMeshColor} = this.props;
267
275
 
268
276
  const geometry =
@@ -288,7 +296,7 @@ export default class Tile3DLayer extends CompositeLayer {
288
296
  pbrMaterial: material,
289
297
  modelMatrix,
290
298
  coordinateOrigin: cartographicOrigin,
291
- coordinateSystem: COORDINATE_SYSTEM.METER_OFFSETS,
299
+ coordinateSystem,
292
300
  featureIds,
293
301
  _offset: 0
294
302
  }
@@ -144,18 +144,14 @@ export default class TileLayer extends CompositeLayer {
144
144
  this.props.onTileLoad(tile);
145
145
  tile.layers = null;
146
146
 
147
- if (tile.isVisible) {
148
- this.setNeedsUpdate();
149
- }
147
+ this.setNeedsUpdate();
150
148
  }
151
149
 
152
150
  _onTileError(error, tile) {
153
151
  this.props.onTileError(error);
154
152
  tile.layers = null;
155
153
 
156
- if (tile.isVisible) {
157
- this.setNeedsUpdate();
158
- }
154
+ this.setNeedsUpdate();
159
155
  }
160
156
 
161
157
  _onTileUnload(tile) {
@@ -183,8 +179,8 @@ export default class TileLayer extends CompositeLayer {
183
179
  return this.props.renderSubLayers(props);
184
180
  }
185
181
 
186
- getHighlightedObjectIndex() {
187
- return -1;
182
+ getSubLayerPropsByTile(tile) {
183
+ return null;
188
184
  }
189
185
 
190
186
  getPickingInfo({info, sourceLayer}) {
@@ -200,7 +196,7 @@ export default class TileLayer extends CompositeLayer {
200
196
 
201
197
  renderLayers() {
202
198
  return this.state.tileset.tiles.map(tile => {
203
- const highlightedObjectIndex = this.getHighlightedObjectIndex(tile);
199
+ const subLayerProps = this.getSubLayerPropsByTile(tile);
204
200
  // cache the rendered layer in the tile
205
201
  if (!tile.isLoaded && !tile.content) {
206
202
  // nothing to show
@@ -215,14 +211,17 @@ export default class TileLayer extends CompositeLayer {
215
211
  tile.layers = flatten(layers, Boolean).map(layer =>
216
212
  layer.clone({
217
213
  tile,
218
- highlightedObjectIndex
214
+ ...subLayerProps
219
215
  })
220
216
  );
221
217
  } else if (
218
+ subLayerProps &&
222
219
  tile.layers[0] &&
223
- tile.layers[0].props.highlightedObjectIndex !== highlightedObjectIndex
220
+ Object.keys(subLayerProps).some(
221
+ propName => tile.layers[0].props[propName] !== subLayerProps[propName]
222
+ )
224
223
  ) {
225
- tile.layers = tile.layers.map(layer => layer.clone({highlightedObjectIndex}));
224
+ tile.layers = tile.layers.map(layer => layer.clone(subLayerProps));
226
225
  }
227
226
  return tile.layers;
228
227
  });
@@ -1,10 +1,11 @@
1
1
  import Tile2DHeader from './tile-2d-header';
2
2
  import {getTileIndices, tileToBoundingBox} from './utils';
3
3
  import {RequestScheduler} from '@loaders.gl/loader-utils';
4
- import {Matrix4} from 'math.gl';
4
+ import {Matrix4} from '@math.gl/core';
5
5
 
6
- const TILE_STATE_UNKNOWN = 0;
7
- const TILE_STATE_VISIBLE = 1;
6
+ // bit masks
7
+ const TILE_STATE_VISITED = 1;
8
+ const TILE_STATE_VISIBLE = 2;
8
9
  /*
9
10
  show cached parent tile if children are loading
10
11
  +-----------+ +-----+ +-----+-----+
@@ -23,10 +24,6 @@ const TILE_STATE_VISIBLE = 1;
23
24
  +-------+---- --> |
24
25
  | | |
25
26
  */
26
- const TILE_STATE_PLACEHOLDER = 3;
27
- const TILE_STATE_HIDDEN = 4;
28
- // tiles that should be displayed in the current viewport
29
- const TILE_STATE_SELECTED = 5;
30
27
 
31
28
  export const STRATEGY_NEVER = 'never';
32
29
  export const STRATEGY_REPLACE = 'no-overlap';
@@ -34,6 +31,12 @@ export const STRATEGY_DEFAULT = 'best-available';
34
31
 
35
32
  const DEFAULT_CACHE_SCALE = 5;
36
33
 
34
+ const STRATEGIES = {
35
+ [STRATEGY_DEFAULT]: updateTileStateDefault,
36
+ [STRATEGY_REPLACE]: updateTileStateReplace,
37
+ [STRATEGY_NEVER]: () => {}
38
+ };
39
+
37
40
  /**
38
41
  * Manages loading and purging of tiles data. This class caches recently visited tiles
39
42
  * and only create new tiles if they are present.
@@ -153,6 +156,7 @@ export default class Tileset2D {
153
156
 
154
157
  // Update tile states
155
158
  const changed = this.updateTileStates();
159
+ this._pruneRequests();
156
160
 
157
161
  if (this._dirty) {
158
162
  // cache size is either the user defined maxSize or 5 * number of current tiles in the viewport.
@@ -201,46 +205,63 @@ export default class Tileset2D {
201
205
 
202
206
  // Returns true if any tile's visibility changed
203
207
  updateTileStates() {
204
- this._updateTileStates(this.selectedTiles);
208
+ const refinementStrategy = this.opts.refinementStrategy || STRATEGY_DEFAULT;
205
209
 
206
- const {maxRequests} = this.opts;
210
+ const visibilities = new Array(this._cache.size);
211
+ let i = 0;
212
+ // Reset state
213
+ for (const tile of this._cache.values()) {
214
+ // save previous state
215
+ visibilities[i++] = tile.isVisible;
216
+ tile.isSelected = false;
217
+ tile.isVisible = false;
218
+ }
219
+ for (const tile of this._selectedTiles) {
220
+ tile.isSelected = true;
221
+ tile.isVisible = true;
222
+ }
207
223
 
208
- const abortCandidates = [];
209
- let ongoingRequestCount = 0;
210
- let changed = false;
224
+ // Strategy-specific state logic
225
+ (typeof refinementStrategy === 'function'
226
+ ? refinementStrategy
227
+ : STRATEGIES[refinementStrategy])(Array.from(this._cache.values()));
228
+
229
+ i = 0;
230
+ // Check if any visibility has changed
211
231
  for (const tile of this._cache.values()) {
212
- const isVisible = Boolean(tile.state & TILE_STATE_VISIBLE);
213
- if (tile.isVisible !== isVisible) {
214
- changed = true;
215
- tile.isVisible = isVisible;
232
+ if (visibilities[i++] !== tile.isVisible) {
233
+ return true;
216
234
  }
235
+ }
236
+
237
+ return false;
238
+ }
239
+
240
+ /* Private methods */
217
241
 
218
- // isSelected used in request scheduler
219
- tile.isSelected = tile.state === TILE_STATE_SELECTED;
242
+ _pruneRequests() {
243
+ const {maxRequests} = this.opts;
220
244
 
245
+ const abortCandidates = [];
246
+ let ongoingRequestCount = 0;
247
+ for (const tile of this._cache.values()) {
221
248
  // Keep track of all the ongoing requests
222
249
  if (tile.isLoading) {
223
250
  ongoingRequestCount++;
224
- if (!tile.isSelected) {
251
+ if (!tile.isSelected && !tile.isVisible) {
225
252
  abortCandidates.push(tile);
226
253
  }
227
254
  }
228
255
  }
229
256
 
230
- if (maxRequests > 0) {
231
- while (ongoingRequestCount > maxRequests && abortCandidates.length > 0) {
232
- // There are too many ongoing requests, so abort some that are unselected
233
- const tile = abortCandidates.shift();
234
- tile.abort();
235
- ongoingRequestCount--;
236
- }
257
+ while (maxRequests > 0 && ongoingRequestCount > maxRequests && abortCandidates.length > 0) {
258
+ // There are too many ongoing requests, so abort some that are unselected
259
+ const tile = abortCandidates.shift();
260
+ tile.abort();
261
+ ongoingRequestCount--;
237
262
  }
238
-
239
- return changed;
240
263
  }
241
264
 
242
- /* Private methods */
243
-
244
265
  // This needs to be called every time some tiles have been added/removed from cache
245
266
  _rebuildTree() {
246
267
  const {_cache} = this;
@@ -261,40 +282,6 @@ export default class Tileset2D {
261
282
  }
262
283
  }
263
284
 
264
- // A selected tile is always visible.
265
- // Never show two overlapping tiles.
266
- // If a selected tile is loading, try showing a cached ancester with the closest z
267
- // If a selected tile is loading, and no ancester is shown - try showing cached
268
- // descendants with the closest z
269
- _updateTileStates(selectedTiles) {
270
- const {_cache} = this;
271
- const refinementStrategy = this.opts.refinementStrategy || STRATEGY_DEFAULT;
272
-
273
- // Reset states
274
- for (const tile of _cache.values()) {
275
- tile.state = TILE_STATE_UNKNOWN;
276
- }
277
-
278
- // For all the selected && pending tiles:
279
- // - pick the closest ancestor as placeholder
280
- // - if no ancestor is visible, pick the closest children as placeholder
281
- for (const tile of selectedTiles) {
282
- tile.state = TILE_STATE_SELECTED;
283
- }
284
-
285
- if (refinementStrategy === STRATEGY_NEVER) {
286
- return;
287
- }
288
- for (const tile of selectedTiles) {
289
- getPlaceholderInAncestors(tile, refinementStrategy);
290
- }
291
- for (const tile of selectedTiles) {
292
- if (needsPlaceholder(tile)) {
293
- getPlaceholderInChildren(tile);
294
- }
295
- }
296
- }
297
-
298
285
  /**
299
286
  * Clear tiles that are not visible when the cache is full
300
287
  */
@@ -375,44 +362,70 @@ export default class Tileset2D {
375
362
  }
376
363
  }
377
364
 
378
- // A selected tile needs placeholder from its children if
379
- // - it is not loaded
380
- // - none of its ancestors is visible and loaded
381
- function needsPlaceholder(tile) {
382
- let t = tile;
383
- while (t) {
384
- if (t.state & (TILE_STATE_VISIBLE === 0)) {
385
- return true;
386
- }
387
- if (t.isLoaded) {
388
- return false;
365
+ /* -- Refinement strategies --*/
366
+ /* eslint-disable max-depth */
367
+
368
+ // For all the selected && pending tiles:
369
+ // - pick the closest ancestor as placeholder
370
+ // - if no ancestor is visible, pick the closest children as placeholder
371
+ function updateTileStateDefault(allTiles) {
372
+ for (const tile of allTiles) {
373
+ tile.state = 0;
374
+ }
375
+ for (const tile of allTiles) {
376
+ if (tile.isSelected && !getPlaceholderInAncestors(tile)) {
377
+ getPlaceholderInChildren(tile);
389
378
  }
390
- t = t.parent;
391
379
  }
392
- return true;
380
+ for (const tile of allTiles) {
381
+ tile.isVisible = Boolean(tile.state & TILE_STATE_VISIBLE);
382
+ }
393
383
  }
394
384
 
395
- function getPlaceholderInAncestors(tile, refinementStrategy) {
396
- let parent;
397
- let state = TILE_STATE_PLACEHOLDER;
398
- while ((parent = tile.parent)) {
399
- if (tile.isLoaded) {
400
- // If a tile is loaded, mark all its ancestors as hidden
401
- state = TILE_STATE_HIDDEN;
402
- if (refinementStrategy === STRATEGY_DEFAULT) {
403
- return;
385
+ // Until a selected tile and all its selected siblings are loaded, use the closest ancestor as placeholder
386
+ function updateTileStateReplace(allTiles) {
387
+ for (const tile of allTiles) {
388
+ tile.state = 0;
389
+ }
390
+ for (const tile of allTiles) {
391
+ if (tile.isSelected) {
392
+ getPlaceholderInAncestors(tile);
393
+ }
394
+ }
395
+ // Always process parents first
396
+ const sortedTiles = Array.from(allTiles).sort((t1, t2) => t1.z - t2.z);
397
+ for (const tile of sortedTiles) {
398
+ tile.isVisible = Boolean(tile.state & TILE_STATE_VISIBLE);
399
+
400
+ if (tile.isVisible || tile.state & TILE_STATE_VISITED) {
401
+ // If the tile is rendered, or if the tile has been explicitly hidden, hide all of its children
402
+ for (const child of tile.children) {
403
+ child.state = TILE_STATE_VISITED;
404
404
  }
405
+ } else if (tile.isSelected) {
406
+ getPlaceholderInChildren(tile);
407
+ }
408
+ }
409
+ }
410
+
411
+ // Walk up the tree until we find one ancestor that is loaded. Returns true if successful.
412
+ function getPlaceholderInAncestors(tile) {
413
+ while (tile) {
414
+ if (tile.isLoaded || tile.content) {
415
+ tile.state |= TILE_STATE_VISIBLE;
416
+ return true;
405
417
  }
406
- parent.state = Math.max(parent.state, state);
407
- tile = parent;
418
+ tile = tile.parent;
408
419
  }
420
+ return false;
409
421
  }
410
422
 
411
423
  // Recursively set children as placeholder
412
424
  function getPlaceholderInChildren(tile) {
413
425
  for (const child of tile.children) {
414
- child.state = Math.max(child.state, TILE_STATE_PLACEHOLDER);
415
- if (!child.isLoaded) {
426
+ if (child.isLoaded || child.content) {
427
+ child.state |= TILE_STATE_VISIBLE;
428
+ } else {
416
429
  getPlaceholderInChildren(child);
417
430
  }
418
431
  }
@@ -65,10 +65,10 @@ export function getURLFromTemplate(template, properties) {
65
65
 
66
66
  const {x, y, z} = properties;
67
67
  return template
68
- .replace('{x}', x)
69
- .replace('{y}', y)
70
- .replace('{z}', z)
71
- .replace('{-y}', Math.pow(2, z) - y - 1);
68
+ .replace(/\{x\}/g, x)
69
+ .replace(/\{y\}/g, y)
70
+ .replace(/\{z\}/g, z)
71
+ .replace(/\{-y\}/g, Math.pow(2, z) - y - 1);
72
72
  }
73
73
 
74
74
  /**