@deck.gl/geo-layers 8.8.0-beta.2 → 8.8.0-beta.5

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 (116) hide show
  1. package/dist/dist.dev.js +1892 -1657
  2. package/dist/es5/geohash-layer/geohash-layer.js +71 -0
  3. package/dist/es5/geohash-layer/geohash-layer.js.map +1 -0
  4. package/dist/es5/geohash-layer/geohash-utils.js +77 -0
  5. package/dist/es5/geohash-layer/geohash-utils.js.map +1 -0
  6. package/dist/es5/h3-layers/h3-cluster-layer.js +7 -0
  7. package/dist/es5/h3-layers/h3-cluster-layer.js.map +1 -1
  8. package/dist/es5/h3-layers/h3-hexagon-layer.js +3 -0
  9. package/dist/es5/h3-layers/h3-hexagon-layer.js.map +1 -1
  10. package/dist/es5/index.js +16 -0
  11. package/dist/es5/index.js.map +1 -1
  12. package/dist/es5/mvt-layer/mvt-layer.js.map +1 -1
  13. package/dist/es5/quadkey-layer/quadkey-layer.js.map +1 -1
  14. package/dist/es5/s2-layer/s2-layer.js.map +1 -1
  15. package/dist/es5/terrain-layer/terrain-layer.js +57 -34
  16. package/dist/es5/terrain-layer/terrain-layer.js.map +1 -1
  17. package/dist/es5/tile-3d-layer/tile-3d-layer.js.map +1 -1
  18. package/dist/es5/tile-layer/tile-layer.js +4 -2
  19. package/dist/es5/tile-layer/tile-layer.js.map +1 -1
  20. package/dist/es5/tile-layer/tileset-2d.js +38 -1
  21. package/dist/es5/tile-layer/tileset-2d.js.map +1 -1
  22. package/dist/es5/tile-layer/utils.js +46 -12
  23. package/dist/es5/tile-layer/utils.js.map +1 -1
  24. package/dist/es5/trips-layer/trips-layer.js.map +1 -1
  25. package/dist/esm/geohash-layer/geohash-layer.js +29 -0
  26. package/dist/esm/geohash-layer/geohash-layer.js.map +1 -0
  27. package/dist/esm/geohash-layer/geohash-utils.js +56 -0
  28. package/dist/esm/geohash-layer/geohash-utils.js.map +1 -0
  29. package/dist/esm/h3-layers/h3-cluster-layer.js +5 -0
  30. package/dist/esm/h3-layers/h3-cluster-layer.js.map +1 -1
  31. package/dist/esm/h3-layers/h3-hexagon-layer.js +4 -0
  32. package/dist/esm/h3-layers/h3-hexagon-layer.js.map +1 -1
  33. package/dist/esm/index.js +2 -0
  34. package/dist/esm/index.js.map +1 -1
  35. package/dist/esm/mvt-layer/mvt-layer.js.map +1 -1
  36. package/dist/esm/quadkey-layer/quadkey-layer.js.map +1 -1
  37. package/dist/esm/s2-layer/s2-layer.js.map +1 -1
  38. package/dist/esm/terrain-layer/terrain-layer.js +35 -13
  39. package/dist/esm/terrain-layer/terrain-layer.js.map +1 -1
  40. package/dist/esm/tile-3d-layer/tile-3d-layer.js.map +1 -1
  41. package/dist/esm/tile-layer/tile-layer.js +6 -2
  42. package/dist/esm/tile-layer/tile-layer.js.map +1 -1
  43. package/dist/esm/tile-layer/tileset-2d.js +36 -3
  44. package/dist/esm/tile-layer/tileset-2d.js.map +1 -1
  45. package/dist/esm/tile-layer/utils.js +36 -0
  46. package/dist/esm/tile-layer/utils.js.map +1 -1
  47. package/dist/esm/trips-layer/trips-layer.js.map +1 -1
  48. package/dist.min.js +2 -2
  49. package/package.json +2 -2
  50. package/src/geohash-layer/geohash-layer.ts +39 -0
  51. package/src/geohash-layer/geohash-utils.ts +54 -0
  52. package/src/h3-layers/h3-cluster-layer.ts +5 -0
  53. package/src/h3-layers/h3-hexagon-layer.ts +5 -9
  54. package/src/index.ts +5 -0
  55. package/src/mvt-layer/mvt-layer.ts +1 -0
  56. package/src/quadkey-layer/quadkey-layer.ts +1 -0
  57. package/src/s2-layer/s2-layer.ts +1 -0
  58. package/src/terrain-layer/{terrain-layer.js → terrain-layer.ts} +120 -37
  59. package/src/tile-3d-layer/tile-3d-layer.ts +5 -4
  60. package/src/tile-layer/tile-layer.ts +4 -2
  61. package/src/tile-layer/tileset-2d.ts +41 -5
  62. package/src/tile-layer/utils.ts +44 -0
  63. package/src/trips-layer/trips-layer.ts +1 -0
  64. package/typed/geohash-layer/geohash-layer.d.ts +21 -0
  65. package/typed/geohash-layer/geohash-layer.d.ts.map +1 -0
  66. package/typed/geohash-layer/geohash-utils.d.ts +3 -0
  67. package/typed/geohash-layer/geohash-utils.d.ts.map +1 -0
  68. package/typed/h3-layers/h3-cluster-layer.d.ts +1 -0
  69. package/typed/h3-layers/h3-cluster-layer.d.ts.map +1 -1
  70. package/typed/h3-layers/h3-hexagon-layer.d.ts +2 -9
  71. package/typed/h3-layers/h3-hexagon-layer.d.ts.map +1 -1
  72. package/typed/index.d.ts +5 -0
  73. package/typed/index.d.ts.map +1 -1
  74. package/typed/mvt-layer/mvt-layer.d.ts +1 -0
  75. package/typed/mvt-layer/mvt-layer.d.ts.map +1 -1
  76. package/typed/quadkey-layer/quadkey-layer.d.ts +1 -0
  77. package/typed/quadkey-layer/quadkey-layer.d.ts.map +1 -1
  78. package/typed/s2-layer/s2-layer.d.ts +1 -0
  79. package/typed/s2-layer/s2-layer.d.ts.map +1 -1
  80. package/typed/terrain-layer/terrain-layer.d.ts +62 -26
  81. package/typed/terrain-layer/terrain-layer.d.ts.map +1 -1
  82. package/typed/tile-3d-layer/tile-3d-layer.d.ts +4 -3
  83. package/typed/tile-3d-layer/tile-3d-layer.d.ts.map +1 -1
  84. package/typed/tile-layer/tile-layer.d.ts +2 -4
  85. package/typed/tile-layer/tile-layer.d.ts.map +1 -1
  86. package/typed/tile-layer/tileset-2d.d.ts +10 -2
  87. package/typed/tile-layer/tileset-2d.d.ts.map +1 -1
  88. package/typed/tile-layer/utils.d.ts +14 -0
  89. package/typed/tile-layer/utils.d.ts.map +1 -1
  90. package/typed/trips-layer/trips-layer.d.ts +1 -0
  91. package/typed/trips-layer/trips-layer.d.ts.map +1 -1
  92. package/typed/geo-cell-layer/GeoCellLayer.js +0 -49
  93. package/typed/great-circle-layer/great-circle-layer.js +0 -29
  94. package/typed/h3-layers/h3-cluster-layer.js +0 -33
  95. package/typed/h3-layers/h3-hexagon-layer.js +0 -251
  96. package/typed/index.js +0 -33
  97. package/typed/mesh-layer/mesh-layer-fragment.glsl.js +0 -55
  98. package/typed/mesh-layer/mesh-layer-vertex.glsl.js +0 -80
  99. package/typed/mesh-layer/mesh-layer.js +0 -110
  100. package/typed/mvt-layer/coordinate-transform.js +0 -41
  101. package/typed/mvt-layer/find-index-binary.js +0 -96
  102. package/typed/mvt-layer/mvt-layer.js +0 -297
  103. package/typed/quadkey-layer/quadkey-layer.js +0 -18
  104. package/typed/quadkey-layer/quadkey-utils.js +0 -26
  105. package/typed/s2-layer/s2-geometry.js +0 -123
  106. package/typed/s2-layer/s2-layer.js +0 -37
  107. package/typed/s2-layer/s2-utils.js +0 -88
  108. package/typed/terrain-layer/terrain-layer.js +0 -226
  109. package/typed/tile-3d-layer/tile-3d-layer.js +0 -294
  110. package/typed/tile-layer/tile-2d-header.js +0 -113
  111. package/typed/tile-layer/tile-2d-traversal.js +0 -181
  112. package/typed/tile-layer/tile-layer.js +0 -192
  113. package/typed/tile-layer/tileset-2d.js +0 -399
  114. package/typed/tile-layer/types.js +0 -1
  115. package/typed/tile-layer/utils.js +0 -197
  116. package/typed/trips-layer/trips-layer.js +0 -92
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.8.0-beta.2",
5
+ "version": "8.8.0-beta.5",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
@@ -54,5 +54,5 @@
54
54
  "@loaders.gl/core": "^3.0.0",
55
55
  "@luma.gl/core": "^8.0.0"
56
56
  },
57
- "gitHead": "d9bae59d015387c547366465d75d80950c60a34e"
57
+ "gitHead": "20b7becdb467aa917c17c9517461bf62ecc48b12"
58
58
  }
@@ -0,0 +1,39 @@
1
+ import {AccessorFunction} from '@deck.gl/core';
2
+ import GeoCellLayer from '../geo-cell-layer/GeoCellLayer';
3
+ import {getGeohashPolygon} from './geohash-utils';
4
+
5
+ const defaultProps = {
6
+ getGeohash: {type: 'accessor', value: d => d.geohash}
7
+ };
8
+
9
+ /**
10
+ * Properties of `GeohashLayer`.
11
+ */
12
+ type GeohashLayerProps<DataT = any> = {
13
+ /**
14
+ * Called for each data object to retrieve the geohash string identifier.
15
+ *
16
+ * By default, it reads `geohash` property of data object.
17
+ */
18
+ getGeohash?: AccessorFunction<DataT, string>;
19
+ };
20
+
21
+ /** Render filled and/or stroked polygons based on the [Geohash](https://en.wikipedia.org/wiki/Geohash) geospatial indexing system. */
22
+ export default class GeohashLayer<DataT = any, ExtraProps = {}> extends GeoCellLayer<
23
+ DataT,
24
+ Required<GeohashLayerProps> & ExtraProps
25
+ > {
26
+ static layerName = 'GeohashLayer';
27
+ static defaultProps: any = defaultProps;
28
+
29
+ indexToBounds(): Partial<GeoCellLayer['props']> | null {
30
+ const {data, getGeohash} = this.props;
31
+
32
+ return {
33
+ data,
34
+ _normalize: false,
35
+ positionFormat: 'XY',
36
+ getPolygon: (x: DataT, objectInfo) => getGeohashPolygon(getGeohash(x, objectInfo))
37
+ };
38
+ }
39
+ }
@@ -0,0 +1,54 @@
1
+ const BASE32_CODES = '0123456789bcdefghjkmnpqrstuvwxyz';
2
+ const BASE32_CODES_DICT = {};
3
+ for (let i = 0; i < BASE32_CODES.length; i++) {
4
+ BASE32_CODES_DICT[BASE32_CODES.charAt(i)] = i;
5
+ }
6
+
7
+ const MIN_LAT = -90;
8
+ const MAX_LAT = 90;
9
+ const MIN_LON = -180;
10
+ const MAX_LON = 180;
11
+
12
+ // Adapted from ngeohash decode_bbox
13
+ export function getGeohashBounds(geohash: string): number[] {
14
+ let isLon = true;
15
+ let maxLat = MAX_LAT;
16
+ let minLat = MIN_LAT;
17
+ let maxLon = MAX_LON;
18
+ let minLon = MIN_LON;
19
+ let mid: number;
20
+
21
+ let hashValue = 0;
22
+ for (let i = 0, l = geohash.length; i < l; i++) {
23
+ const code = geohash[i].toLowerCase();
24
+ hashValue = BASE32_CODES_DICT[code];
25
+
26
+ for (let bits = 4; bits >= 0; bits--) {
27
+ const bit = (hashValue >> bits) & 1;
28
+ if (isLon) {
29
+ mid = (maxLon + minLon) / 2;
30
+ if (bit === 1) {
31
+ minLon = mid;
32
+ } else {
33
+ maxLon = mid;
34
+ }
35
+ } else {
36
+ mid = (maxLat + minLat) / 2;
37
+ if (bit === 1) {
38
+ minLat = mid;
39
+ } else {
40
+ maxLat = mid;
41
+ }
42
+ }
43
+ isLon = !isLon;
44
+ }
45
+ }
46
+
47
+ return [minLat, minLon, maxLat, maxLon];
48
+ }
49
+
50
+ export function getGeohashPolygon(geohash: string): number[] {
51
+ const [s, w, n, e] = getGeohashBounds(geohash);
52
+
53
+ return [e, n, e, s, w, s, w, n, e, n];
54
+ }
@@ -1,6 +1,7 @@
1
1
  import {h3SetToMultiPolygon, H3IndexInput} from 'h3-js';
2
2
 
3
3
  import {AccessorFunction, createIterable, UpdateParameters, DefaultProps} from '@deck.gl/core';
4
+ import {H3HexagonLayer} from '@deck.gl/geo-layers';
4
5
  import GeoCellLayer, {GeoCellLayerProps} from '../geo-cell-layer/GeoCellLayer';
5
6
 
6
7
  const defaultProps: DefaultProps<H3ClusterLayerProps> = {
@@ -28,6 +29,10 @@ export default class H3ClusterLayer<DataT = any, ExtraProps = {}> extends GeoCel
28
29
  static layerName = 'H3ClusterLayer';
29
30
  static defaultProps = defaultProps;
30
31
 
32
+ initializeState(): void {
33
+ H3HexagonLayer._checkH3Lib();
34
+ }
35
+
31
36
  updateState({props, changeFlags}: UpdateParameters<this>): void {
32
37
  if (
33
38
  changeFlags.dataChanged ||
@@ -143,15 +143,7 @@ type _H3HexagonLayerProps<DataT> = {
143
143
  };
144
144
 
145
145
  /**
146
- * A subclass of HexagonLayer that uses H3 hexagonIds in data objects
147
- * rather than centroid lat/longs. The shape of each hexagon is determined
148
- * based on a single "center" hexagon, which can be selected by passing in
149
- * a center lat/lon pair. If not provided, the map center will be used.
150
- *
151
- * Also sets the `hexagonId` field in the onHover/onClick callback's info
152
- * objects. Since this is calculated using math, hexagonId will be present
153
- * even when no corresponding hexagon is in the data set. You can check
154
- * index !== -1 to see if picking matches an actual object.
146
+ * Render hexagons from the [H3](https://h3geo.org/) geospatial indexing system.
155
147
  */
156
148
  export default class H3HexagonLayer<DataT = any, ExtraPropsT = {}> extends CompositeLayer<
157
149
  ExtraPropsT & Required<_H3HexagonLayerProps<DataT> & Required<PolygonLayerProps<DataT>>>
@@ -159,7 +151,11 @@ export default class H3HexagonLayer<DataT = any, ExtraPropsT = {}> extends Compo
159
151
  static defaultProps = defaultProps;
160
152
  static layerName = 'H3HexagonLayer';
161
153
 
154
+ // See `main/bundle.ts`
155
+ static _checkH3Lib = () => {};
156
+
162
157
  initializeState() {
158
+ H3HexagonLayer._checkH3Lib();
163
159
  this.state = {
164
160
  edgeLengthKM: 0,
165
161
  resolution: -1
package/src/index.ts CHANGED
@@ -29,7 +29,9 @@ export {default as H3HexagonLayer} from './h3-layers/h3-hexagon-layer';
29
29
  export {default as Tile3DLayer} from './tile-3d-layer/tile-3d-layer';
30
30
  export {default as TerrainLayer} from './terrain-layer/terrain-layer';
31
31
  export {default as MVTLayer} from './mvt-layer/mvt-layer';
32
+ export {default as GeohashLayer} from './geohash-layer/geohash-layer';
32
33
 
34
+ export {default as _GeoCellLayer} from './geo-cell-layer/GeoCellLayer';
33
35
  export {getURLFromTemplate as _getURLFromTemplate} from './tile-layer/utils';
34
36
  export {default as _Tileset2D} from './tile-layer/tileset-2d';
35
37
  export {default as _Tile2DHeader} from './tile-layer/tile-2d-header';
@@ -43,4 +45,7 @@ export type {TileLayerProps} from './tile-layer/tile-layer';
43
45
  export type {GeoBoundingBox} from './tile-layer/types';
44
46
  export type {QuadkeyLayerProps} from './quadkey-layer/quadkey-layer';
45
47
  export type {TileLoadProps as _TileLoadProps} from './tile-layer/types';
48
+ export type {TerrainLayerProps} from './terrain-layer/terrain-layer';
49
+ export type {Tile3DLayerProps} from './tile-3d-layer/tile-3d-layer';
46
50
  export type {MVTLayerProps} from './mvt-layer/mvt-layer';
51
+ export type {GeoCellLayerProps as _GeoCellLayerProps} from './geo-cell-layer/GeoCellLayer';
@@ -85,6 +85,7 @@ export type _MVTLayerProps = {
85
85
 
86
86
  type ContentWGS84Cache = {_contentWGS84?: Feature[]};
87
87
 
88
+ /** Render data formatted as [Mapbox Vector Tiles](https://docs.mapbox.com/vector-tiles/specification/). */
88
89
  export default class MVTLayer<DataT extends Feature = Feature, ExtraProps = {}> extends TileLayer<
89
90
  ParsedMvtTile,
90
91
  Required<_MVTLayerProps> & ExtraProps
@@ -19,6 +19,7 @@ type _QuadkeyLayerProps<DataT> = {
19
19
  getQuadkey?: AccessorFunction<DataT, string>;
20
20
  };
21
21
 
22
+ /** Render filled and/or stroked polygons based on the [Quadkey](https://towardsdatascience.com/geospatial-indexing-with-quadkeys-d933dff01496) geospatial indexing system. */
22
23
  export default class QuadkeyLayer<DataT = any, ExtraProps = {}> extends GeoCellLayer<
23
24
  DataT,
24
25
  Required<_QuadkeyLayerProps<DataT>> & ExtraProps
@@ -39,6 +39,7 @@ type _S2LayerProps<DataT> = {
39
39
  getS2Token?: AccessorFunction<DataT, string>;
40
40
  };
41
41
 
42
+ /** Render filled and/or stroked polygons based on the [S2](http://s2geometry.io/) geospatial indexing system. */
42
43
  export default class S2Layer<DataT = any, ExtraProps = {}> extends GeoCellLayer<
43
44
  DataT,
44
45
  Required<_S2LayerProps<DataT>> & ExtraProps
@@ -18,16 +18,30 @@
18
18
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  // THE SOFTWARE.
20
20
 
21
- import {CompositeLayer, log} from '@deck.gl/core';
21
+ import {
22
+ Color,
23
+ CompositeLayer,
24
+ CompositeLayerProps,
25
+ DefaultProps,
26
+ Layer,
27
+ LayersList,
28
+ log,
29
+ Material,
30
+ Texture,
31
+ UpdateParameters
32
+ } from '@deck.gl/core';
22
33
  import {SimpleMeshLayer} from '@deck.gl/mesh-layers';
23
34
  import {COORDINATE_SYSTEM} from '@deck.gl/core';
35
+ import type {MeshAttributes} from '@loaders.gl/schema';
24
36
  import {TerrainWorkerLoader} from '@loaders.gl/terrain';
25
- import TileLayer from '../tile-layer/tile-layer';
37
+ import TileLayer, {TileLayerProps} from '../tile-layer/tile-layer';
38
+ import Tile2DHeader from '../tile-layer/tile-2d-header';
39
+ import {Bounds, GeoBoundingBox, TileBoundingBox, TileLoadProps, ZRange} from '../tile-layer/types';
26
40
  import {urlType, getURLFromTemplate} from '../tile-layer/utils';
27
41
 
28
42
  const DUMMY_DATA = [1];
29
43
 
30
- const defaultProps = {
44
+ const defaultProps: DefaultProps<TerrainLayerProps> = {
31
45
  ...TileLayer.defaultProps,
32
46
  // Image url that encodes height data
33
47
  elevationData: urlType,
@@ -58,22 +72,73 @@ const defaultProps = {
58
72
  loaders: [TerrainWorkerLoader]
59
73
  };
60
74
 
75
+ type URLTemplate = string | string[];
76
+
61
77
  // Turns array of templates into a single string to work around shallow change
62
- function urlTemplateToUpdateTrigger(template) {
78
+ function urlTemplateToUpdateTrigger(template: URLTemplate | null): string {
63
79
  if (Array.isArray(template)) {
64
80
  return template.join(';');
65
81
  }
66
- return template;
82
+ return template || '';
67
83
  }
68
84
 
69
- /**
70
- * state: {
71
- * isTiled: True renders TileLayer of many SimpleMeshLayers, false renders one SimpleMeshLayer
72
- * terrain: Mesh object. Only defined when isTiled is false.
73
- * }
74
- */
75
- export default class TerrainLayer extends CompositeLayer {
76
- updateState({props, oldProps}) {
85
+ type ElevationDecoder = {rScaler: number; gScaler: number; bScaler: number; offset: number};
86
+ type TerrainLoadProps = {
87
+ bounds: Bounds;
88
+ elevationData: string | null;
89
+ elevationDecoder: ElevationDecoder;
90
+ meshMaxError: number;
91
+ signal?: AbortSignal;
92
+ };
93
+
94
+ type MeshAndTexture = [MeshAttributes | null, Texture | null];
95
+
96
+ /** All properties supported by TerrainLayer */
97
+ export type TerrainLayerProps = _TerrainLayerProps &
98
+ TileLayerProps<MeshAndTexture> &
99
+ CompositeLayerProps;
100
+
101
+ /** Props added by the TerrainLayer */
102
+ type _TerrainLayerProps = {
103
+ /** Image url that encodes height data. **/
104
+ elevationData: URLTemplate;
105
+
106
+ /** Image url to use as texture. **/
107
+ texture?: URLTemplate | null;
108
+
109
+ /** Martini error tolerance in meters, smaller number -> more detailed mesh. **/
110
+ meshMaxError?: number;
111
+
112
+ /** Bounding box of the terrain image, [minX, minY, maxX, maxY] in world coordinates. **/
113
+ bounds?: Bounds | null;
114
+
115
+ /** Color to use if texture is unavailable. **/
116
+ color?: Color;
117
+
118
+ /** Object to decode height data, from (r, g, b) to height in meters. **/
119
+ elevationDecoder?: ElevationDecoder;
120
+
121
+ /** Whether to render the mesh in wireframe mode. **/
122
+ wireframe?: boolean;
123
+
124
+ /** Material props for lighting effect. **/
125
+ material?: Material;
126
+ };
127
+
128
+ /** Render mesh surfaces from height map images. */
129
+ export default class TerrainLayer<ExtraPropsT = {}> extends CompositeLayer<
130
+ ExtraPropsT & Required<_TerrainLayerProps & Required<TileLayerProps<MeshAndTexture>>>
131
+ > {
132
+ static defaultProps = defaultProps;
133
+ static layerName = 'TerrainLayer';
134
+
135
+ state!: {
136
+ isTiled?: boolean;
137
+ terrain: MeshAttributes;
138
+ zRange?: ZRange | null;
139
+ };
140
+
141
+ updateState({props, oldProps}: UpdateParameters<this>): void {
77
142
  const elevationDataChanged = props.elevationData !== oldProps.elevationData;
78
143
  if (elevationDataChanged) {
79
144
  const {elevationData} = props;
@@ -92,17 +157,25 @@ export default class TerrainLayer extends CompositeLayer {
92
157
  props.bounds !== oldProps.bounds;
93
158
 
94
159
  if (!this.state.isTiled && shouldReload) {
95
- const terrain = this.loadTerrain(props);
160
+ // When state.isTiled, elevationData cannot be an array
161
+ const terrain = this.loadTerrain(props as TerrainLoadProps);
96
162
  this.setState({terrain});
97
163
  }
98
164
 
99
165
  // TODO - remove in v9
166
+ // @ts-ignore
100
167
  if (props.workerUrl) {
101
168
  log.removed('workerUrl', 'loadOptions.terrain.workerUrl')();
102
169
  }
103
170
  }
104
171
 
105
- loadTerrain({elevationData, bounds, elevationDecoder, meshMaxError, signal}) {
172
+ loadTerrain({
173
+ elevationData,
174
+ bounds,
175
+ elevationDecoder,
176
+ meshMaxError,
177
+ signal
178
+ }: TerrainLoadProps): Promise<MeshAttributes> | null {
106
179
  if (!elevationData) {
107
180
  return null;
108
181
  }
@@ -121,20 +194,25 @@ export default class TerrainLayer extends CompositeLayer {
121
194
  return fetch(elevationData, {propName: 'elevationData', layer: this, loadOptions, signal});
122
195
  }
123
196
 
124
- getTiledTerrainData(tile) {
197
+ getTiledTerrainData(tile: TileLoadProps): Promise<MeshAndTexture> {
125
198
  const {elevationData, fetch, texture, elevationDecoder, meshMaxError} = this.props;
126
199
  const {viewport} = this.context;
127
200
  const dataUrl = getURLFromTemplate(elevationData, tile);
128
- const textureUrl = getURLFromTemplate(texture, tile);
201
+ const textureUrl = texture && getURLFromTemplate(texture, tile);
129
202
 
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
- const bounds = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]];
203
+ const {signal} = tile;
204
+ let bottomLeft = [0, 0] as [number, number];
205
+ let topRight = [0, 0] as [number, number];
206
+ if (viewport.isGeospatial) {
207
+ const bbox = tile.bbox as GeoBoundingBox;
208
+ bottomLeft = viewport.projectFlat([bbox.west, bbox.south]);
209
+ topRight = viewport.projectFlat([bbox.east, bbox.north]);
210
+ } else {
211
+ const bbox = tile.bbox as Exclude<TileBoundingBox, GeoBoundingBox>;
212
+ bottomLeft = [bbox.left, bbox.bottom];
213
+ topRight = [bbox.right, bbox.top];
214
+ }
215
+ const bounds: Bounds = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]];
138
216
 
139
217
  const terrain = this.loadTerrain({
140
218
  elevationData: dataUrl,
@@ -151,9 +229,17 @@ export default class TerrainLayer extends CompositeLayer {
151
229
  return Promise.all([terrain, surface]);
152
230
  }
153
231
 
154
- renderSubLayers(props) {
232
+ renderSubLayers(
233
+ props: TileLayerProps<MeshAndTexture> & {
234
+ id: string;
235
+ data: MeshAndTexture;
236
+ tile: Tile2DHeader<MeshAndTexture>;
237
+ }
238
+ ) {
155
239
  const SubLayerClass = this.getSubLayerClass('mesh', SimpleMeshLayer);
156
- const {data, color} = props;
240
+
241
+ const {color, wireframe, material} = this.props;
242
+ const {data} = props;
157
243
 
158
244
  if (!data) {
159
245
  return null;
@@ -168,12 +254,14 @@ export default class TerrainLayer extends CompositeLayer {
168
254
  _instanced: false,
169
255
  coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
170
256
  getPosition: d => [0, 0, 0],
171
- getColor: color
257
+ getColor: color,
258
+ wireframe,
259
+ material
172
260
  });
173
261
  }
174
262
 
175
263
  // Update zRange of viewport
176
- onViewportLoad(tiles) {
264
+ onViewportLoad(tiles?: Tile2DHeader<MeshAndTexture>[]): void {
177
265
  if (!tiles) {
178
266
  return;
179
267
  }
@@ -183,6 +271,7 @@ export default class TerrainLayer extends CompositeLayer {
183
271
  .map(tile => tile.content)
184
272
  .filter(Boolean)
185
273
  .map(arr => {
274
+ // @ts-ignore
186
275
  const bounds = arr[0].header.boundingBox;
187
276
  return bounds.map(bound => bound[2]);
188
277
  });
@@ -197,7 +286,7 @@ export default class TerrainLayer extends CompositeLayer {
197
286
  }
198
287
  }
199
288
 
200
- renderLayers() {
289
+ renderLayers(): Layer | null | LayersList {
201
290
  const {
202
291
  color,
203
292
  material,
@@ -220,14 +309,11 @@ export default class TerrainLayer extends CompositeLayer {
220
309
  } = this.props;
221
310
 
222
311
  if (this.state.isTiled) {
223
- return new TileLayer(
312
+ return new TileLayer<MeshAndTexture>(
224
313
  this.getSubLayerProps({
225
314
  id: 'tiles'
226
315
  }),
227
316
  {
228
- wireframe,
229
- color,
230
- material,
231
317
  getTileData: this.getTiledTerrainData.bind(this),
232
318
  renderSubLayers: this.renderSubLayers.bind(this),
233
319
  updateTriggers: {
@@ -273,6 +359,3 @@ export default class TerrainLayer extends CompositeLayer {
273
359
  );
274
360
  }
275
361
  }
276
-
277
- TerrainLayer.layerName = 'TerrainLayer';
278
- TerrainLayer.defaultProps = defaultProps;
@@ -28,7 +28,7 @@ import {Tiles3DLoader} from '@loaders.gl/3d-tiles';
28
28
 
29
29
  const SINGLE_DATA = [0];
30
30
 
31
- const defaultProps: DefaultProps<Tile3dLayerProps> = {
31
+ const defaultProps: DefaultProps<Tile3DLayerProps> = {
32
32
  getPointColor: {type: 'accessor', value: [0, 0, 0, 255]},
33
33
  pointSize: 1.0,
34
34
 
@@ -44,10 +44,10 @@ const defaultProps: DefaultProps<Tile3dLayerProps> = {
44
44
  };
45
45
 
46
46
  /** All properties supported by Tile3DLayer */
47
- export type Tile3dLayerProps<DataT = any> = _Tile3dLayerProps<DataT> & CompositeLayerProps<DataT>;
47
+ export type Tile3DLayerProps<DataT = any> = _Tile3DLayerProps<DataT> & CompositeLayerProps<DataT>;
48
48
 
49
49
  /** Props added by the Tile3DLayer */
50
- type _Tile3dLayerProps<DataT> = {
50
+ type _Tile3DLayerProps<DataT> = {
51
51
  /** Color Accessor for point clouds. **/
52
52
  getPointColor?: Accessor<DataT, Color>;
53
53
 
@@ -75,8 +75,9 @@ type _Tile3dLayerProps<DataT> = {
75
75
  _getMeshColor?: (tile: Tile3D) => Color;
76
76
  };
77
77
 
78
+ /** Render 3d tiles data formatted according to the [3D Tiles Specification](https://www.opengeospatial.org/standards/3DTiles) and [`ESRI I3S`](https://github.com/Esri/i3s-spec) */
78
79
  export default class Tile3DLayer<DataT = any, ExtraPropsT = {}> extends CompositeLayer<
79
- ExtraPropsT & Required<_Tile3dLayerProps<DataT>>
80
+ ExtraPropsT & Required<_Tile3DLayerProps<DataT>>
80
81
  > {
81
82
  static defaultProps = defaultProps as any;
82
83
  static layerName = 'Tile3DLayer';
@@ -7,6 +7,7 @@ import {
7
7
  PickingInfo,
8
8
  GetPickingInfoParams,
9
9
  DefaultProps,
10
+ FilterContext,
10
11
  _flatten as flatten
11
12
  } from '@deck.gl/core';
12
13
  import {GeoJsonLayer} from '@deck.gl/layers';
@@ -352,7 +353,8 @@ export default class TileLayer<DataT = any, ExtraPropsT = {}> extends CompositeL
352
353
  });
353
354
  }
354
355
 
355
- filterSubLayer({layer}) {
356
- return layer.props.tile.isVisible;
356
+ filterSubLayer({layer, cullRect}: FilterContext) {
357
+ const {tile} = (layer as Layer<{tile: Tile2DHeader}>).props;
358
+ return this.state.tileset.isTileVisible(tile, cullRect);
357
359
  }
358
360
  }
@@ -1,10 +1,11 @@
1
1
  import Tile2DHeader from './tile-2d-header';
2
- import {getTileIndices, tileToBoundingBox} from './utils';
2
+ import {getTileIndices, tileToBoundingBox, getCullBounds} from './utils';
3
3
  import {RequestScheduler} from '@loaders.gl/loader-utils';
4
- import {Matrix4} from '@math.gl/core';
4
+ import {Matrix4, equals} from '@math.gl/core';
5
5
  import {Viewport} from '@deck.gl/core';
6
6
  import {Bounds, TileIndex, ZRange} from './types';
7
7
  import {TileLayerProps} from './tile-layer';
8
+ import {_memoize as memoize} from '@deck.gl/core';
8
9
 
9
10
  // bit masks
10
11
  const TILE_STATE_VISITED = 1;
@@ -78,6 +79,7 @@ export default class Tileset2D {
78
79
 
79
80
  private _cacheByteSize: number;
80
81
  private _viewport: Viewport | null;
82
+ private _zRange?: ZRange;
81
83
  private _selectedTiles: Tile2DHeader[] | null;
82
84
  private _frameNumber: number;
83
85
  private _modelMatrix: Matrix4;
@@ -184,12 +186,18 @@ export default class Tileset2D {
184
186
  ): number {
185
187
  const modelMatrixAsMatrix4 = new Matrix4(modelMatrix);
186
188
  const isModelMatrixNew = !modelMatrixAsMatrix4.equals(this._modelMatrix);
187
- if (!this._viewport || !viewport.equals(this._viewport) || isModelMatrixNew) {
189
+ if (
190
+ !this._viewport ||
191
+ !viewport.equals(this._viewport) ||
192
+ !equals(this._zRange, zRange) ||
193
+ isModelMatrixNew
194
+ ) {
188
195
  if (isModelMatrixNew) {
189
196
  this._modelMatrixInverse = modelMatrixAsMatrix4.clone().invert();
190
197
  this._modelMatrix = modelMatrixAsMatrix4;
191
198
  }
192
199
  this._viewport = viewport;
200
+ this._zRange = zRange;
193
201
  const tileIndices = this.getTileIndices({
194
202
  viewport,
195
203
  maxZoom: this._maxZoom,
@@ -225,6 +233,32 @@ export default class Tileset2D {
225
233
  return this._frameNumber;
226
234
  }
227
235
 
236
+ isTileVisible(
237
+ tile: Tile2DHeader,
238
+ cullRect?: {x: number; y: number; width: number; height: number}
239
+ ): boolean {
240
+ if (!tile.isVisible) {
241
+ return false;
242
+ }
243
+
244
+ if (cullRect && this._viewport) {
245
+ const [minX, minY, maxX, maxY] = getCullBounds({
246
+ viewport: this._viewport,
247
+ z: this._zRange,
248
+ cullRect
249
+ });
250
+ const {bbox} = tile;
251
+ if ('west' in bbox) {
252
+ return bbox.west < maxX && bbox.east > minX && bbox.south < maxY && bbox.north > minY;
253
+ }
254
+ // top/bottom could be swapped depending on the indexing system
255
+ const y0 = Math.min(bbox.top, bbox.bottom);
256
+ const y1 = Math.max(bbox.top, bbox.bottom);
257
+ return bbox.left < maxX && bbox.right > minX && y0 < maxY && y1 > minY;
258
+ }
259
+ return true;
260
+ }
261
+
228
262
  /* Public interface for subclassing */
229
263
 
230
264
  /** Returns array of tile indices in the current viewport */
@@ -321,7 +355,9 @@ export default class Tileset2D {
321
355
 
322
356
  /* Private methods */
323
357
 
324
- _pruneRequests(): void {
358
+ private _getCullBounds = memoize(getCullBounds);
359
+
360
+ private _pruneRequests(): void {
325
361
  const {maxRequests} = this.opts;
326
362
 
327
363
  const abortCandidates: Tile2DHeader[] = [];
@@ -345,7 +381,7 @@ export default class Tileset2D {
345
381
  }
346
382
 
347
383
  // This needs to be called every time some tiles have been added/removed from cache
348
- _rebuildTree() {
384
+ private _rebuildTree() {
349
385
  const {_cache} = this;
350
386
 
351
387
  // Reset states
@@ -127,6 +127,50 @@ function getBoundingBox(viewport: Viewport, zRange: number[] | null, extent: Bou
127
127
  ];
128
128
  }
129
129
 
130
+ /** Get culling bounds in world space */
131
+ export function getCullBounds({
132
+ viewport,
133
+ z,
134
+ cullRect
135
+ }: {
136
+ /** Current viewport */
137
+ viewport: Viewport;
138
+ /** Current z range */
139
+ z: ZRange | number | undefined;
140
+ /** Culling rectangle in screen space */
141
+ cullRect: {x: number; y: number; width: number; height: number};
142
+ }): [number, number, number, number] {
143
+ const x = cullRect.x - viewport.x;
144
+ const y = cullRect.y - viewport.y;
145
+ const {width, height} = cullRect;
146
+
147
+ if (!Array.isArray(z)) {
148
+ const unprojectOption = {targetZ: z || 0};
149
+
150
+ const topLeft = viewport.unproject([x, y], unprojectOption);
151
+ const topRight = viewport.unproject([x + width, y], unprojectOption);
152
+ const bottomLeft = viewport.unproject([x, y + height], unprojectOption);
153
+ const bottomRight = viewport.unproject([x + width, y + height], unprojectOption);
154
+
155
+ return [
156
+ Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
157
+ Math.min(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1]),
158
+ Math.max(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
159
+ Math.max(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1])
160
+ ];
161
+ }
162
+
163
+ const bounds0 = getCullBounds({viewport, z: z[0], cullRect});
164
+ const bounds1 = getCullBounds({viewport, z: z[1], cullRect});
165
+
166
+ return [
167
+ Math.min(bounds0[0], bounds1[0]),
168
+ Math.min(bounds0[1], bounds1[1]),
169
+ Math.max(bounds0[2], bounds1[2]),
170
+ Math.max(bounds0[3], bounds1[3])
171
+ ];
172
+ }
173
+
130
174
  function getIndexingCoords(bbox: Bounds, scale: number, modelMatrixInverse?: Matrix4): Bounds {
131
175
  if (modelMatrixInverse) {
132
176
  const transformedTileIndex = transformBox(bbox, modelMatrixInverse).map(
@@ -55,6 +55,7 @@ type _TripsLayerProps<DataT = any> = {
55
55
  getTimestamps?: AccessorFunction<DataT, NumericArray>;
56
56
  };
57
57
 
58
+ /** Render animated paths that represent vehicle trips. */
58
59
  export default class TripsLayer<DataT = any, ExtraProps = {}> extends PathLayer<
59
60
  DataT,
60
61
  Required<_TripsLayerProps> & ExtraProps