@deck.gl/carto 8.8.0-alpha.3 → 8.8.0-alpha.6
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/dist/dist.dev.js +383 -247
- package/dist/es5/api/layer-map.js +7 -5
- package/dist/es5/api/layer-map.js.map +1 -1
- package/dist/es5/layers/carto-layer.js +3 -1
- package/dist/es5/layers/carto-layer.js.map +1 -1
- package/dist/es5/layers/carto-tile-layer.js +17 -12
- package/dist/es5/layers/carto-tile-layer.js.map +1 -1
- package/dist/es5/layers/h3-tile-layer.js +34 -13
- package/dist/es5/layers/h3-tile-layer.js.map +1 -1
- package/dist/es5/layers/h3-tileset-2d.js +21 -11
- package/dist/es5/layers/h3-tileset-2d.js.map +1 -1
- package/dist/es5/layers/quadkey-tile-layer.js +31 -14
- package/dist/es5/layers/quadkey-tile-layer.js.map +1 -1
- package/dist/es5/layers/quadkey-tileset-2d.js.map +1 -1
- package/dist/es5/layers/schema/carto-tile.js +261 -188
- package/dist/es5/layers/schema/carto-tile.js.map +1 -1
- package/dist/es5/layers/spatial-index-tile-layer.js +92 -0
- package/dist/es5/layers/spatial-index-tile-layer.js.map +1 -0
- package/dist/esm/api/layer-map.js +8 -6
- package/dist/esm/api/layer-map.js.map +1 -1
- package/dist/esm/layers/carto-layer.js +3 -1
- package/dist/esm/layers/carto-layer.js.map +1 -1
- package/dist/esm/layers/carto-tile-layer.js +20 -16
- package/dist/esm/layers/carto-tile-layer.js.map +1 -1
- package/dist/esm/layers/h3-tile-layer.js +24 -10
- package/dist/esm/layers/h3-tile-layer.js.map +1 -1
- package/dist/esm/layers/h3-tileset-2d.js +27 -12
- package/dist/esm/layers/h3-tileset-2d.js.map +1 -1
- package/dist/esm/layers/quadkey-tile-layer.js +22 -13
- package/dist/esm/layers/quadkey-tile-layer.js.map +1 -1
- package/dist/esm/layers/quadkey-tileset-2d.js.map +1 -1
- package/dist/esm/layers/schema/carto-tile.js +174 -189
- package/dist/esm/layers/schema/carto-tile.js.map +1 -1
- package/dist/esm/layers/spatial-index-tile-layer.js +57 -0
- package/dist/esm/layers/spatial-index-tile-layer.js.map +1 -0
- package/dist.min.js +4 -4
- package/package.json +7 -4
- package/src/api/layer-map.ts +16 -7
- package/src/layers/carto-layer.ts +18 -5
- package/src/layers/{carto-tile-layer.js → carto-tile-layer.ts} +63 -26
- package/src/layers/h3-tile-layer.ts +78 -0
- package/src/layers/h3-tileset-2d.ts +118 -0
- package/src/layers/quadkey-tile-layer.ts +68 -0
- package/src/layers/{quadkey-tileset-2d.js → quadkey-tileset-2d.ts} +10 -5
- package/src/layers/schema/carto-tile.ts +221 -0
- package/src/layers/spatial-index-tile-layer.ts +49 -0
- package/typed/api/index.d.ts +4 -0
- package/typed/api/index.d.ts.map +1 -0
- package/typed/api/layer-map.d.ts +54 -0
- package/typed/api/layer-map.d.ts.map +1 -0
- package/typed/api/maps-api-common.d.ts +65 -0
- package/typed/api/maps-api-common.d.ts.map +1 -0
- package/typed/api/maps-client.d.ts +18 -0
- package/typed/api/maps-client.d.ts.map +1 -0
- package/typed/api/maps-v3-client.d.ts +45 -0
- package/typed/api/maps-v3-client.d.ts.map +1 -0
- package/typed/api/parseMap.d.ts +11 -0
- package/typed/api/parseMap.d.ts.map +1 -0
- package/typed/basemap.d.ts +10 -0
- package/typed/basemap.d.ts.map +1 -0
- package/typed/config.d.ts +26 -0
- package/typed/config.d.ts.map +1 -0
- package/typed/index.d.ts +12 -0
- package/typed/index.d.ts.map +1 -0
- package/typed/layers/carto-layer.d.ts +98 -0
- package/typed/layers/carto-layer.d.ts.map +1 -0
- package/typed/layers/carto-tile-layer.d.ts +63 -0
- package/typed/layers/carto-tile-layer.d.ts.map +1 -0
- package/typed/layers/h3-tile-layer.d.ts +23 -0
- package/typed/layers/h3-tile-layer.d.ts.map +1 -0
- package/typed/layers/h3-tileset-2d.d.ts +18 -0
- package/typed/layers/h3-tileset-2d.d.ts.map +1 -0
- package/typed/layers/quadkey-tile-layer.d.ts +23 -0
- package/typed/layers/quadkey-tile-layer.d.ts.map +1 -0
- package/typed/layers/quadkey-tileset-2d.d.ts +15 -0
- package/typed/layers/quadkey-tileset-2d.d.ts.map +1 -0
- package/typed/layers/schema/carto-tile.d.ts +44 -0
- package/typed/layers/schema/carto-tile.d.ts.map +1 -0
- package/typed/layers/spatial-index-tile-layer.d.ts +11 -0
- package/typed/layers/spatial-index-tile-layer.d.ts.map +1 -0
- package/typed/package.json +6 -0
- package/typed/style/color-bins-style.d.ts +9 -0
- package/typed/style/color-bins-style.d.ts.map +1 -0
- package/typed/style/color-categories-style.d.ts +10 -0
- package/typed/style/color-categories-style.d.ts.map +1 -0
- package/typed/style/color-continuous-style.d.ts +9 -0
- package/typed/style/color-continuous-style.d.ts.map +1 -0
- package/typed/style/palette.d.ts +7 -0
- package/typed/style/palette.d.ts.map +1 -0
- package/typed/style/utils.d.ts +8 -0
- package/typed/style/utils.d.ts.map +1 -0
- package/typed/utils.d.ts +2 -0
- package/typed/utils.d.ts.map +1 -0
- package/src/layers/h3-tile-layer.js +0 -44
- package/src/layers/h3-tileset-2d.js +0 -82
- package/src/layers/quadkey-tile-layer.js +0 -42
- package/src/layers/schema/carto-tile.js +0 -195
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@deck.gl/carto",
|
|
3
3
|
"description": "CARTO official integration with Deck.gl. Build geospatial applications using CARTO and Deck.gl.",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "8.8.0-alpha.
|
|
5
|
+
"version": "8.8.0-alpha.6",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"files": [
|
|
24
24
|
"dist",
|
|
25
25
|
"src",
|
|
26
|
+
"typed",
|
|
26
27
|
"dist.min.js"
|
|
27
28
|
],
|
|
28
29
|
"sideEffects": false,
|
|
@@ -35,17 +36,19 @@
|
|
|
35
36
|
"@loaders.gl/loader-utils": "^3.2.0-alpha.4",
|
|
36
37
|
"@loaders.gl/mvt": "^3.2.0-alpha.4",
|
|
37
38
|
"@loaders.gl/tiles": "^3.2.0-alpha.4",
|
|
38
|
-
"@luma.gl/constants": "^8.5.
|
|
39
|
-
"@math.gl/web-mercator": "3.6.0-alpha.
|
|
39
|
+
"@luma.gl/constants": "^8.5.13",
|
|
40
|
+
"@math.gl/web-mercator": "3.6.0-alpha.8",
|
|
40
41
|
"cartocolor": "^4.0.2",
|
|
41
42
|
"d3-array": "^2.8.0",
|
|
42
43
|
"d3-color": "^2.0.0",
|
|
43
44
|
"d3-format": "^2.0.0",
|
|
44
45
|
"d3-scale": "^3.2.3",
|
|
46
|
+
"h3-js": "^3.6.0",
|
|
45
47
|
"moment-timezone": "^0.5.33",
|
|
46
48
|
"pbf": "^3.2.1"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
51
|
+
"@loaders.gl/schema": "^3.2.0-alpha.4",
|
|
49
52
|
"@types/d3-array": "^3.0.2",
|
|
50
53
|
"@types/d3-color": "^1.4.2",
|
|
51
54
|
"@types/d3-scale": "^3.0.0"
|
|
@@ -58,5 +61,5 @@
|
|
|
58
61
|
"@deck.gl/layers": "^8.0.0",
|
|
59
62
|
"@loaders.gl/core": "^3.0.0"
|
|
60
63
|
},
|
|
61
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "6885ccab01c91a7632385f566c9377f8ae387e7c"
|
|
62
65
|
}
|
package/src/api/layer-map.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import {format as d3Format} from 'd3-format';
|
|
14
14
|
import moment from 'moment-timezone';
|
|
15
15
|
|
|
16
|
+
import {Layer, _ConstructorOf as ConstructorOf} from '@deck.gl/core';
|
|
16
17
|
import {CPUGridLayer, HeatmapLayer, HexagonLayer} from '@deck.gl/aggregation-layers';
|
|
17
18
|
import {GeoJsonLayer} from '@deck.gl/layers';
|
|
18
19
|
import {H3HexagonLayer, MVTLayer} from '@deck.gl/geo-layers';
|
|
@@ -101,7 +102,7 @@ const defaultProps = {
|
|
|
101
102
|
wrapLongitude: false
|
|
102
103
|
};
|
|
103
104
|
|
|
104
|
-
function mergePropMaps(a = {}, b = {}) {
|
|
105
|
+
function mergePropMaps(a: Record<string, any> = {}, b: Record<string, any> = {}) {
|
|
105
106
|
return {...a, ...b, visConfig: {...a.visConfig, ...b.visConfig}};
|
|
106
107
|
}
|
|
107
108
|
|
|
@@ -109,7 +110,7 @@ export function getLayer(
|
|
|
109
110
|
type: string,
|
|
110
111
|
config,
|
|
111
112
|
dataset
|
|
112
|
-
): {Layer:
|
|
113
|
+
): {Layer: ConstructorOf<Layer>; propMap: any; defaultProps: any} {
|
|
113
114
|
if (type === 'mvt' || type === 'tileset') {
|
|
114
115
|
return getTileLayer(dataset);
|
|
115
116
|
}
|
|
@@ -118,7 +119,11 @@ export function getLayer(
|
|
|
118
119
|
const getPosition = d => d[geoColumn].coordinates;
|
|
119
120
|
|
|
120
121
|
const hexagonId = config.columns?.hex_id;
|
|
121
|
-
|
|
122
|
+
|
|
123
|
+
const layerTypeDefs: Record<
|
|
124
|
+
string,
|
|
125
|
+
{Layer: ConstructorOf<Layer>; propMap?: any; defaultProps?: any}
|
|
126
|
+
> = {
|
|
122
127
|
point: {
|
|
123
128
|
Layer: GeoJsonLayer,
|
|
124
129
|
propMap: {visConfig: {outline: 'stroked'}}
|
|
@@ -146,12 +151,16 @@ export function getLayer(
|
|
|
146
151
|
propMap: {visConfig: {coverage: 'coverage'}},
|
|
147
152
|
defaultProps: {getHexagon: d => d[hexagonId], stroked: false}
|
|
148
153
|
}
|
|
149
|
-
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const layer = layerTypeDefs[type];
|
|
150
157
|
|
|
151
158
|
assert(layer, `Unsupported layer type: ${type}`);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
159
|
+
return {
|
|
160
|
+
...layer,
|
|
161
|
+
propMap: mergePropMaps(sharedPropMap, layer.propMap),
|
|
162
|
+
defaultProps: {...defaultProps, ...layer.defaultProps}
|
|
163
|
+
};
|
|
155
164
|
}
|
|
156
165
|
|
|
157
166
|
function getTileLayer(dataset) {
|
|
@@ -57,10 +57,20 @@ const defaultProps = {
|
|
|
57
57
|
geoColumn: null,
|
|
58
58
|
|
|
59
59
|
// (Array<String>, optional): names of columns to fetch. By default, all columns are fetched.
|
|
60
|
-
columns: {type: 'array', value: null}
|
|
60
|
+
columns: {type: 'array', value: null},
|
|
61
|
+
|
|
62
|
+
// (String, optional): aggregration SQL expression. Only used for spatial index datasets
|
|
63
|
+
aggregationExp: null,
|
|
64
|
+
|
|
65
|
+
// (Number, optional): aggregration resolution level. Only used for spatial index datasets, defaults to 6 for quadkeys, 4 for h3
|
|
66
|
+
aggregationResLevel: null
|
|
61
67
|
};
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
/** All properties supported by CartoLayer. */
|
|
70
|
+
export type CartoLayerProps<DataT = any> = _CartoLayerProps & CompositeLayerProps<DataT>;
|
|
71
|
+
|
|
72
|
+
/** Properties added by CartoLayer. */
|
|
73
|
+
type _CartoLayerProps = {
|
|
64
74
|
/**
|
|
65
75
|
* Either a SQL query or a name of dataset/tileset.
|
|
66
76
|
*/
|
|
@@ -141,9 +151,11 @@ export interface CartoLayerProps<DataT = any> extends CompositeLayerProps<DataT>
|
|
|
141
151
|
onDataError?: (err: unknown) => void;
|
|
142
152
|
|
|
143
153
|
clientId?: string;
|
|
144
|
-
}
|
|
154
|
+
};
|
|
145
155
|
|
|
146
|
-
export default class CartoLayer<
|
|
156
|
+
export default class CartoLayer<ExtraProps = {}> extends CompositeLayer<
|
|
157
|
+
Required<_CartoLayerProps> & ExtraProps
|
|
158
|
+
> {
|
|
147
159
|
static layerName = 'CartoLayer';
|
|
148
160
|
static defaultProps = defaultProps as any;
|
|
149
161
|
|
|
@@ -231,7 +243,7 @@ export default class CartoLayer<DataT = any> extends CompositeLayer<CartoLayerPr
|
|
|
231
243
|
const localConfig = {...getDefaultCredentials(), ...credentials};
|
|
232
244
|
const {apiVersion} = localConfig;
|
|
233
245
|
|
|
234
|
-
let result: FetchLayerDataResult
|
|
246
|
+
let result: Partial<FetchLayerDataResult>;
|
|
235
247
|
if (apiVersion === API_VERSIONS.V1 || apiVersion === API_VERSIONS.V2) {
|
|
236
248
|
result = {
|
|
237
249
|
data: await getDataV2({type, source, credentials: credentials as ClassicCredentials})
|
|
@@ -270,6 +282,7 @@ export default class CartoLayer<DataT = any> extends CompositeLayer<CartoLayerPr
|
|
|
270
282
|
const {uniqueIdProperty} = defaultProps;
|
|
271
283
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
272
284
|
const {data: _notUsed, ...propsNoData} = this.props;
|
|
285
|
+
// @ts-expect-error 'uniqueIdProperty' is specified more than once, so this usage will be overwritten.
|
|
273
286
|
const props = {uniqueIdProperty, ...propsNoData};
|
|
274
287
|
|
|
275
288
|
if (apiVersion === API_VERSIONS.V1 || apiVersion === API_VERSIONS.V2) {
|
|
@@ -2,28 +2,38 @@
|
|
|
2
2
|
import Protobuf from 'pbf';
|
|
3
3
|
import {log} from '@deck.gl/core';
|
|
4
4
|
import {ClipExtension} from '@deck.gl/extensions';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
MVTLayer,
|
|
7
|
+
MVTLayerProps,
|
|
8
|
+
TileLayer,
|
|
9
|
+
_getURLFromTemplate,
|
|
10
|
+
_Tile2DHeader,
|
|
11
|
+
_TileLoadProps as TileLoadProps
|
|
12
|
+
} from '@deck.gl/geo-layers';
|
|
6
13
|
import {GeoJsonLayer} from '@deck.gl/layers';
|
|
7
14
|
import {geojsonToBinary} from '@loaders.gl/gis';
|
|
8
|
-
import {Tile} from './schema/carto-tile';
|
|
9
|
-
import {TILE_FORMATS} from '../api/maps-api-common';
|
|
15
|
+
import {Properties, Tile, TileReader} from './schema/carto-tile';
|
|
16
|
+
import {TileFormat, TILE_FORMATS} from '../api/maps-api-common';
|
|
17
|
+
import {LoaderOptions, LoaderWithParser} from '@loaders.gl/loader-utils';
|
|
18
|
+
import type {BinaryFeatures} from '@loaders.gl/schema';
|
|
19
|
+
import type {Feature} from 'geojson';
|
|
10
20
|
|
|
11
|
-
function parseJSON(arrayBuffer) {
|
|
21
|
+
function parseJSON(arrayBuffer: ArrayBuffer): any {
|
|
12
22
|
return JSON.parse(new TextDecoder().decode(arrayBuffer));
|
|
13
23
|
}
|
|
14
24
|
|
|
15
|
-
function parsePbf(buffer) {
|
|
25
|
+
function parsePbf(buffer: ArrayBuffer): Tile {
|
|
16
26
|
const pbf = new Protobuf(buffer);
|
|
17
|
-
const tile =
|
|
27
|
+
const tile = TileReader.read(pbf);
|
|
18
28
|
return tile;
|
|
19
29
|
}
|
|
20
30
|
|
|
21
|
-
function unpackProperties(properties) {
|
|
31
|
+
function unpackProperties(properties: Properties[]) {
|
|
22
32
|
if (!properties || !properties.length) {
|
|
23
33
|
return [];
|
|
24
34
|
}
|
|
25
35
|
return properties.map(item => {
|
|
26
|
-
const currentRecord = {};
|
|
36
|
+
const currentRecord: Record<string, unknown> = {};
|
|
27
37
|
item.data.forEach(({key, value}) => {
|
|
28
38
|
currentRecord[key] = value;
|
|
29
39
|
});
|
|
@@ -31,7 +41,7 @@ function unpackProperties(properties) {
|
|
|
31
41
|
});
|
|
32
42
|
}
|
|
33
43
|
|
|
34
|
-
function parseCartoTile(arrayBuffer, options) {
|
|
44
|
+
function parseCartoTile(arrayBuffer: ArrayBuffer, options?: LoaderOptions): BinaryFeatures | null {
|
|
35
45
|
if (!arrayBuffer) return null;
|
|
36
46
|
const formatTiles = options && options.cartoTile && options.cartoTile.formatTiles;
|
|
37
47
|
if (formatTiles === TILE_FORMATS.GEOJSON) return geojsonToBinary(parseJSON(arrayBuffer).features);
|
|
@@ -45,13 +55,15 @@ function parseCartoTile(arrayBuffer, options) {
|
|
|
45
55
|
polygons: {...polygons, properties: unpackProperties(polygons.properties)}
|
|
46
56
|
};
|
|
47
57
|
|
|
48
|
-
|
|
58
|
+
// Note: there is slight, difference in `numericProps` type, however geojson/mvtlayer can cope with this
|
|
59
|
+
return data as unknown as BinaryFeatures;
|
|
49
60
|
}
|
|
50
61
|
|
|
51
62
|
const defaultTileFormat = TILE_FORMATS.BINARY;
|
|
52
63
|
|
|
53
|
-
const CartoTileLoader = {
|
|
64
|
+
const CartoTileLoader: LoaderWithParser = {
|
|
54
65
|
name: 'CARTO Tile',
|
|
66
|
+
version: '1',
|
|
55
67
|
id: 'cartoTile',
|
|
56
68
|
module: 'carto',
|
|
57
69
|
extensions: ['pbf'],
|
|
@@ -73,8 +85,29 @@ const defaultProps = {
|
|
|
73
85
|
loaders: [CartoTileLoader]
|
|
74
86
|
};
|
|
75
87
|
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
/** All properties supported by CartoTileLayer. */
|
|
89
|
+
export type CartoTileLayerProps<DataT extends Feature = Feature> = _CartoTileLayerProps &
|
|
90
|
+
MVTLayerProps<DataT>;
|
|
91
|
+
|
|
92
|
+
/** Properties added by CartoTileLayer. */
|
|
93
|
+
type _CartoTileLayerProps = {
|
|
94
|
+
/** Use to override the default tile data format.
|
|
95
|
+
*
|
|
96
|
+
* Possible values are: `TILE_FORMATS.BINARY`, `TILE_FORMATS.GEOJSON` and `TILE_FORMATS.MVT`.
|
|
97
|
+
*
|
|
98
|
+
* Only supported when `apiVersion` is `API_VERSIONS.V3` and `format` is `FORMATS.TILEJSON`.
|
|
99
|
+
*/
|
|
100
|
+
formatTiles?: TileFormat;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export default class CartoTileLayer<
|
|
104
|
+
DataT extends Feature = Feature,
|
|
105
|
+
ExtraProps = {}
|
|
106
|
+
> extends MVTLayer<DataT, Required<_CartoTileLayerProps> & ExtraProps> {
|
|
107
|
+
static layerName = 'CartoTileLayer';
|
|
108
|
+
static defaultProps = defaultProps;
|
|
109
|
+
|
|
110
|
+
getTileData(tile: TileLoadProps) {
|
|
78
111
|
const url = _getURLFromTemplate(this.state.data, tile);
|
|
79
112
|
if (!url) {
|
|
80
113
|
return Promise.reject('Invalid URL');
|
|
@@ -100,25 +133,29 @@ export default class CartoTileLayer extends MVTLayer {
|
|
|
100
133
|
return fetch(url, {propName: 'data', layer: this, loadOptions, signal});
|
|
101
134
|
}
|
|
102
135
|
|
|
103
|
-
renderSubLayers(
|
|
136
|
+
renderSubLayers(
|
|
137
|
+
props: TileLayer['props'] & {
|
|
138
|
+
id: string;
|
|
139
|
+
data: any;
|
|
140
|
+
_offset: number;
|
|
141
|
+
tile: _Tile2DHeader;
|
|
142
|
+
}
|
|
143
|
+
): GeoJsonLayer | null {
|
|
104
144
|
if (props.data === null) {
|
|
105
145
|
return null;
|
|
106
146
|
}
|
|
107
147
|
|
|
108
|
-
props.
|
|
148
|
+
const tileBbox = props.tile.bbox as any;
|
|
149
|
+
const {west, south, east, north} = tileBbox;
|
|
109
150
|
|
|
110
|
-
const {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
151
|
+
const subLayerProps = {
|
|
152
|
+
...props,
|
|
153
|
+
autoHighlight: false,
|
|
154
|
+
extensions: [new ClipExtension(), ...(props.extensions || [])],
|
|
155
|
+
clipBounds: [west, south, east, north]
|
|
156
|
+
};
|
|
115
157
|
|
|
116
|
-
const subLayer = new GeoJsonLayer(
|
|
117
|
-
...props
|
|
118
|
-
});
|
|
158
|
+
const subLayer = new GeoJsonLayer(subLayerProps);
|
|
119
159
|
return subLayer;
|
|
120
160
|
}
|
|
121
161
|
}
|
|
122
|
-
|
|
123
|
-
CartoTileLayer.layerName = 'CartoTileLayer';
|
|
124
|
-
CartoTileLayer.defaultProps = defaultProps;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CompositeLayer,
|
|
3
|
+
CompositeLayerProps,
|
|
4
|
+
Layer,
|
|
5
|
+
LayersList,
|
|
6
|
+
UpdateParameters
|
|
7
|
+
} from '@deck.gl/core';
|
|
8
|
+
import {H3HexagonLayer} from '@deck.gl/geo-layers';
|
|
9
|
+
import H3Tileset2D from './h3-tileset-2d';
|
|
10
|
+
import SpatialIndexTileLayer from './spatial-index-tile-layer';
|
|
11
|
+
|
|
12
|
+
const renderSubLayers = props => {
|
|
13
|
+
const {data} = props;
|
|
14
|
+
const {index} = props.tile;
|
|
15
|
+
if (!data || !data.length) return null;
|
|
16
|
+
|
|
17
|
+
return new H3HexagonLayer(props, {
|
|
18
|
+
getHexagon: d => d.id,
|
|
19
|
+
centerHexagon: index,
|
|
20
|
+
highPrecision: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const defaultProps = {
|
|
25
|
+
aggregationResLevel: 4
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** All properties supported by H3TileLayer. */
|
|
29
|
+
export type H3TileLayerProps<DataT = any> = _H3TileLayerProps<DataT> & CompositeLayerProps<DataT>;
|
|
30
|
+
|
|
31
|
+
// TODO: use type from h3-hexagon-layer when available
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33
|
+
type H3HexagonLayerProps<DataT = any> = Record<string, any>;
|
|
34
|
+
|
|
35
|
+
/** Properties added by H3TileLayer. */
|
|
36
|
+
type _H3TileLayerProps<DataT = any> = H3HexagonLayerProps<DataT> & {
|
|
37
|
+
aggregationResLevel?: number;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default class H3TileLayer<DataT = any, ExtraPropsT = {}> extends CompositeLayer<
|
|
41
|
+
ExtraPropsT & Required<_H3TileLayerProps<DataT>>
|
|
42
|
+
> {
|
|
43
|
+
static layerName = 'H3TileLayer';
|
|
44
|
+
static defaultProps = defaultProps;
|
|
45
|
+
|
|
46
|
+
state!: {
|
|
47
|
+
tileJSON: any;
|
|
48
|
+
data: any;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
initializeState(): void {
|
|
52
|
+
this.setState({data: null, tileJSON: null});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
updateState({changeFlags}: UpdateParameters<this>): void {
|
|
56
|
+
if (changeFlags.dataChanged) {
|
|
57
|
+
let {data} = this.props;
|
|
58
|
+
const tileJSON = data;
|
|
59
|
+
data = (tileJSON as any).tiles;
|
|
60
|
+
this.setState({data, tileJSON});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
renderLayers(): Layer | null | LayersList {
|
|
65
|
+
const {data, tileJSON} = this.state;
|
|
66
|
+
const maxZoom = parseInt(tileJSON.maxresolution);
|
|
67
|
+
return [
|
|
68
|
+
new SpatialIndexTileLayer(this.props, {
|
|
69
|
+
id: `h3-tile-layer-${this.props.id}`,
|
|
70
|
+
data,
|
|
71
|
+
// @ts-expect-error Tileset2D should be generic over TileIndex
|
|
72
|
+
TilesetClass: H3Tileset2D,
|
|
73
|
+
renderSubLayers,
|
|
74
|
+
maxZoom
|
|
75
|
+
})
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import {_Tileset2D as Tileset2D, GeoBoundingBox} from '@deck.gl/geo-layers';
|
|
2
|
+
import {
|
|
3
|
+
polyfill,
|
|
4
|
+
getRes0Indexes,
|
|
5
|
+
geoToH3,
|
|
6
|
+
h3GetResolution,
|
|
7
|
+
h3ToGeoBoundary,
|
|
8
|
+
h3ToParent,
|
|
9
|
+
kRing
|
|
10
|
+
} from 'h3-js';
|
|
11
|
+
|
|
12
|
+
export type H3TileIndex = {i: string};
|
|
13
|
+
|
|
14
|
+
function getHexagonsInBoundingBox(
|
|
15
|
+
{west, north, east, south}: GeoBoundingBox,
|
|
16
|
+
resolution: number
|
|
17
|
+
): string[] {
|
|
18
|
+
if (resolution === 0) {
|
|
19
|
+
return getRes0Indexes();
|
|
20
|
+
}
|
|
21
|
+
if (east - west > 180) {
|
|
22
|
+
// This is a known issue in h3-js: polyfill does not work correctly
|
|
23
|
+
// when longitude span is larger than 180 degrees.
|
|
24
|
+
return getHexagonsInBoundingBox({west, north, east: 0, south}, resolution).concat(
|
|
25
|
+
getHexagonsInBoundingBox({west: 0, north, east, south}, resolution)
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// `polyfill()` fills based on hexagon center, which means tiles vanish
|
|
30
|
+
// prematurely. Get more accurate coverage by oversampling
|
|
31
|
+
const oversample = 2;
|
|
32
|
+
const h3Indices = polyfill(
|
|
33
|
+
[
|
|
34
|
+
[
|
|
35
|
+
[west, north],
|
|
36
|
+
[west, south],
|
|
37
|
+
[east, south],
|
|
38
|
+
[east, north],
|
|
39
|
+
[west, north]
|
|
40
|
+
]
|
|
41
|
+
],
|
|
42
|
+
resolution + oversample,
|
|
43
|
+
true
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
return oversample ? [...new Set(h3Indices.map(i => h3ToParent(i, resolution)))] : h3Indices;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function tileToBoundingBox(index: string): GeoBoundingBox {
|
|
50
|
+
const coordinates = h3ToGeoBoundary(index);
|
|
51
|
+
const latitudes = coordinates.map(c => c[0]);
|
|
52
|
+
const longitudes = coordinates.map(c => c[1]);
|
|
53
|
+
const west = Math.min(...longitudes);
|
|
54
|
+
const south = Math.min(...latitudes);
|
|
55
|
+
const east = Math.max(...longitudes);
|
|
56
|
+
const north = Math.max(...latitudes);
|
|
57
|
+
return {west, south, east, north};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Resolution conversion function. Takes a WebMercatorViewport and returns
|
|
61
|
+
// a H3 resolution such that the screen space size of the hexagons is
|
|
62
|
+
// similar
|
|
63
|
+
// Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
|
|
64
|
+
const BIAS = 2;
|
|
65
|
+
function getHexagonResolution(viewport): number {
|
|
66
|
+
const hexagonScaleFactor = (2 / 3) * viewport.zoom;
|
|
67
|
+
const latitudeScaleFactor = Math.log(1 / Math.cos((Math.PI * viewport.latitude) / 180));
|
|
68
|
+
|
|
69
|
+
// Clip and bias
|
|
70
|
+
return Math.max(0, Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export default class H3Tileset2D extends Tileset2D {
|
|
74
|
+
// @ts-expect-error Tileset2D should be generic over TileIndex
|
|
75
|
+
getTileIndices({viewport, minZoom, maxZoom}): H3TileIndex[] {
|
|
76
|
+
const [east, south, west, north] = viewport.getBounds();
|
|
77
|
+
|
|
78
|
+
let z = getHexagonResolution(viewport);
|
|
79
|
+
let indices: string[];
|
|
80
|
+
if (typeof minZoom === 'number' && Number.isFinite(minZoom) && z < minZoom) {
|
|
81
|
+
z = minZoom;
|
|
82
|
+
}
|
|
83
|
+
if (typeof maxZoom === 'number' && Number.isFinite(maxZoom) && z > maxZoom) {
|
|
84
|
+
z = maxZoom;
|
|
85
|
+
|
|
86
|
+
// Once we are at max zoom, getHexagonsInBoundingBox doesn't work, simply
|
|
87
|
+
// get a ring centered on the hexagon in the viewport center
|
|
88
|
+
const center = geoToH3(viewport.latitude, viewport.longitude, maxZoom);
|
|
89
|
+
indices = kRing(center, 1);
|
|
90
|
+
} else {
|
|
91
|
+
indices = getHexagonsInBoundingBox({west, north, east, south}, z);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return indices.map(i => ({i}));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// @ts-expect-error Tileset2D should be generic over TileIndex
|
|
98
|
+
getTileId({i}: H3TileIndex): string {
|
|
99
|
+
return i;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// @ts-expect-error Tileset2D should be generic over TileIndex
|
|
103
|
+
getTileMetadata({i}: H3TileIndex) {
|
|
104
|
+
return {bbox: tileToBoundingBox(i)};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// @ts-expect-error Tileset2D should be generic over TileIndex
|
|
108
|
+
getTileZoom({i}: H3TileIndex): number {
|
|
109
|
+
return h3GetResolution(i);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// @ts-expect-error Tileset2D should be generic over TileIndex
|
|
113
|
+
getParentIndex(index: H3TileIndex): H3TileIndex {
|
|
114
|
+
const resolution = h3GetResolution(index.i);
|
|
115
|
+
const i = h3ToParent(index.i, resolution - 1);
|
|
116
|
+
return {i};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CompositeLayer,
|
|
3
|
+
CompositeLayerProps,
|
|
4
|
+
Layer,
|
|
5
|
+
LayersList,
|
|
6
|
+
UpdateParameters
|
|
7
|
+
} from '@deck.gl/core';
|
|
8
|
+
import {QuadkeyLayer, QuadkeyLayerProps} from '@deck.gl/geo-layers';
|
|
9
|
+
import QuadkeyTileset2D from './quadkey-tileset-2d';
|
|
10
|
+
import SpatialIndexTileLayer from './spatial-index-tile-layer';
|
|
11
|
+
|
|
12
|
+
const renderSubLayers = props => {
|
|
13
|
+
const {data} = props;
|
|
14
|
+
if (!data || !data.length) return null;
|
|
15
|
+
return new QuadkeyLayer(props, {getQuadkey: d => d.id});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const defaultProps = {
|
|
19
|
+
aggregationResLevel: 6
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** All properties supported by QuadkeyTileLayer. */
|
|
23
|
+
export type QuadkeyTileLayerProps<DataT = any> = _QuadkeyTileLayerProps<DataT> &
|
|
24
|
+
CompositeLayerProps<DataT>;
|
|
25
|
+
|
|
26
|
+
/** Properties added by QuadkeyTileLayer. */
|
|
27
|
+
type _QuadkeyTileLayerProps<DataT> = QuadkeyLayerProps<DataT> & {
|
|
28
|
+
aggregationResLevel?: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default class QuadkeyTileLayer<DataT = any, ExtraProps = {}> extends CompositeLayer<
|
|
32
|
+
ExtraProps & Required<_QuadkeyTileLayerProps<DataT>>
|
|
33
|
+
> {
|
|
34
|
+
static layerName = 'QuadkeyTileLayer';
|
|
35
|
+
static defaultProps = defaultProps;
|
|
36
|
+
|
|
37
|
+
state!: {
|
|
38
|
+
tileJSON: any;
|
|
39
|
+
data: any;
|
|
40
|
+
};
|
|
41
|
+
initializeState(): void {
|
|
42
|
+
this.setState({data: null, tileJSON: null});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
updateState({changeFlags}: UpdateParameters<this>): void {
|
|
46
|
+
if (changeFlags.dataChanged) {
|
|
47
|
+
let {data} = this.props;
|
|
48
|
+
const tileJSON = data;
|
|
49
|
+
data = (tileJSON as any).tiles;
|
|
50
|
+
this.setState({data, tileJSON});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
renderLayers(): Layer | null | LayersList {
|
|
55
|
+
const {data, tileJSON} = this.state;
|
|
56
|
+
const maxZoom = parseInt(tileJSON?.maxresolution);
|
|
57
|
+
return [
|
|
58
|
+
new SpatialIndexTileLayer(this.props, {
|
|
59
|
+
id: `quadkey-tile-layer-${this.props.id}`,
|
|
60
|
+
data,
|
|
61
|
+
// TODO: Tileset2D should be generic over TileIndex type
|
|
62
|
+
TilesetClass: QuadkeyTileset2D as any,
|
|
63
|
+
renderSubLayers,
|
|
64
|
+
maxZoom
|
|
65
|
+
})
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {_Tileset2D as Tileset2D} from '@deck.gl/geo-layers';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type QuadkeyTileIndex = {i: string};
|
|
4
|
+
function tileToQuadkey(tile): QuadkeyTileIndex {
|
|
4
5
|
let index = '';
|
|
5
6
|
for (let z = tile.z; z > 0; z--) {
|
|
6
7
|
let b = 0;
|
|
@@ -13,11 +14,13 @@ function tileToQuadkey(tile) {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export default class QuadkeyTileset2D extends Tileset2D {
|
|
16
|
-
|
|
17
|
+
// @ts-expect-error for spatial indices, TileSet2d should be parametrized by TileIndexT
|
|
18
|
+
getTileIndices(opts): QuadkeyTileIndex[] {
|
|
17
19
|
return super.getTileIndices(opts).map(tileToQuadkey);
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
// @ts-expect-error TileIndex must be generic
|
|
23
|
+
getTileId({i}: QuadkeyTileIndex) {
|
|
21
24
|
return i;
|
|
22
25
|
}
|
|
23
26
|
|
|
@@ -25,11 +28,13 @@ export default class QuadkeyTileset2D extends Tileset2D {
|
|
|
25
28
|
return {};
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
// @ts-expect-error TileIndex must be generic
|
|
32
|
+
getTileZoom({i}: QuadkeyTileIndex) {
|
|
29
33
|
return i.length;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
// @ts-expect-error TileIndex must be generic
|
|
37
|
+
getParentIndex(index: QuadkeyTileIndex) {
|
|
33
38
|
const i = index.i.slice(0, -1);
|
|
34
39
|
return {i};
|
|
35
40
|
}
|