@deck.gl/carto 9.2.0-alpha.2 → 9.2.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.
- package/dist/api/parse-map.js +1 -1
- package/dist/api/parse-map.js.map +1 -1
- package/dist/cartoPropertiesTile-worker.js +1 -1
- package/dist/cartoRasterTile-worker.js +1 -1
- package/dist/cartoSpatialTile-worker.js +1 -1
- package/dist/cartoVectorTile-worker.js +1 -1
- package/dist/dist.dev.js +67 -49
- package/dist/index.cjs +66 -48
- package/dist/index.cjs.map +3 -3
- package/dist/layers/h3-tileset-2d.d.ts.map +1 -1
- package/dist/layers/h3-tileset-2d.js +16 -5
- package/dist/layers/h3-tileset-2d.js.map +1 -1
- package/dist/layers/heatmap-tile-layer.d.ts +3 -1
- package/dist/layers/heatmap-tile-layer.d.ts.map +1 -1
- package/dist/layers/heatmap-tile-layer.js +69 -35
- package/dist/layers/heatmap-tile-layer.js.map +1 -1
- package/dist/layers/heatmap.d.ts +1 -1
- package/dist/layers/heatmap.d.ts.map +1 -1
- package/dist/layers/heatmap.js +3 -0
- package/dist/layers/heatmap.js.map +1 -1
- package/dist/layers/post-process-utils.d.ts.map +1 -1
- package/dist/layers/post-process-utils.js +2 -1
- package/dist/layers/post-process-utils.js.map +1 -1
- package/dist/layers/raster-layer.d.ts.map +1 -1
- package/dist/layers/raster-layer.js +1 -11
- package/dist/layers/raster-layer.js.map +1 -1
- package/dist/layers/schema/carto-properties-tile-loader.js +1 -1
- package/dist/layers/schema/carto-properties-tile-loader.js.map +1 -1
- package/dist/layers/schema/carto-raster-tile-loader.js +1 -1
- package/dist/layers/schema/carto-raster-tile-loader.js.map +1 -1
- package/dist/layers/schema/carto-spatial-tile-loader.js +1 -1
- package/dist/layers/schema/carto-spatial-tile-loader.js.map +1 -1
- package/dist/layers/schema/carto-vector-tile-loader.js +1 -1
- package/dist/layers/schema/carto-vector-tile-loader.js.map +1 -1
- package/dist.min.js +12 -9
- package/package.json +5 -5
- package/src/api/parse-map.ts +1 -1
- package/src/layers/h3-tileset-2d.ts +18 -5
- package/src/layers/heatmap-tile-layer.ts +78 -35
- package/src/layers/heatmap.ts +3 -0
- package/src/layers/post-process-utils.ts +2 -1
- package/src/layers/raster-layer.ts +1 -12
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "CARTO official integration with Deck.gl. Build geospatial applications using CARTO and Deck.gl.",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "9.2.0-
|
|
6
|
+
"version": "9.2.0-beta.1",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"@loaders.gl/mvt": "^4.2.0",
|
|
50
50
|
"@loaders.gl/schema": "^4.2.0",
|
|
51
51
|
"@loaders.gl/tiles": "^4.2.0",
|
|
52
|
-
"@luma.gl/core": "^9.
|
|
53
|
-
"@luma.gl/shadertools": "^9.
|
|
52
|
+
"@luma.gl/core": "^9.2.0-alpha.5",
|
|
53
|
+
"@luma.gl/shadertools": "^9.2.0-alpha.5",
|
|
54
54
|
"@math.gl/web-mercator": "^4.1.0",
|
|
55
55
|
"@types/d3-array": "^3.0.2",
|
|
56
56
|
"@types/d3-color": "^1.4.2",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"@deck.gl/geo-layers": "^9.1.0",
|
|
74
74
|
"@deck.gl/layers": "^9.1.0",
|
|
75
75
|
"@loaders.gl/core": "^4.2.0",
|
|
76
|
-
"@luma.gl/core": "^9.
|
|
76
|
+
"@luma.gl/core": "^9.2.0-alpha.5"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "84407defece157d45954f66cf191cca3c596ee99"
|
|
79
79
|
}
|
package/src/api/parse-map.ts
CHANGED
|
@@ -92,7 +92,7 @@ function createParametersProp(layerBlending: string, parameters: ColorParameters
|
|
|
92
92
|
parameters.blendColorOperation = parameters.blendAlphaOperation = 'add';
|
|
93
93
|
} else if (layerBlending === 'subtractive') {
|
|
94
94
|
parameters.blendColorSrcFactor = 'one';
|
|
95
|
-
parameters.blendColorDstFactor = 'one-minus-dst
|
|
95
|
+
parameters.blendColorDstFactor = 'one-minus-dst';
|
|
96
96
|
parameters.blendAlphaSrcFactor = 'src-alpha';
|
|
97
97
|
parameters.blendAlphaDstFactor = 'dst-alpha';
|
|
98
98
|
parameters.blendColorOperation = 'subtract';
|
|
@@ -19,11 +19,19 @@ export type H3TileIndex = {i: string};
|
|
|
19
19
|
|
|
20
20
|
const MAX_LATITUDE = 85.051128;
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
/**
|
|
23
|
+
* `polygonToCells()` fills based on hexagon center, this function will
|
|
24
|
+
* pad the bounds such that all cells that overlap the bounds will be included.
|
|
25
|
+
*
|
|
26
|
+
* @param bbox - The bounding box to pad.
|
|
27
|
+
* @param resolution - The resolution of the hexagons.
|
|
28
|
+
* @param scale - The scale of the buffer. 1 is to pad by the max edge length of the tile cell.
|
|
29
|
+
* @returns The padded bounding box.
|
|
30
|
+
*/
|
|
24
31
|
function padBoundingBox(
|
|
25
32
|
{west, north, east, south}: GeoBoundingBox,
|
|
26
|
-
resolution: number
|
|
33
|
+
resolution: number,
|
|
34
|
+
scale: number = 1.0
|
|
27
35
|
): GeoBoundingBox {
|
|
28
36
|
const corners = [
|
|
29
37
|
[north, east],
|
|
@@ -35,7 +43,7 @@ function padBoundingBox(
|
|
|
35
43
|
const cornerEdgeLengths = cornerCells.map(
|
|
36
44
|
c => (Math.max(...originToDirectedEdges(c).map(e => edgeLength(e, UNITS.rads))) * 180) / Math.PI
|
|
37
45
|
);
|
|
38
|
-
const bufferLat = Math.max(...cornerEdgeLengths);
|
|
46
|
+
const bufferLat = Math.max(...cornerEdgeLengths) * scale;
|
|
39
47
|
const bufferLon = Math.min(180, bufferLat / Math.cos((((north + south) / 2) * Math.PI) / 180));
|
|
40
48
|
|
|
41
49
|
return {
|
|
@@ -84,7 +92,12 @@ function tileToBoundingBox(index: string): GeoBoundingBox {
|
|
|
84
92
|
const south = Math.min(...latitudes);
|
|
85
93
|
const east = Math.max(...longitudes);
|
|
86
94
|
const north = Math.max(...latitudes);
|
|
87
|
-
|
|
95
|
+
const bbox = {west, south, east, north};
|
|
96
|
+
|
|
97
|
+
// H3 child cells extend beyond their parent's boundary forming a "snowflake"
|
|
98
|
+
// fractal pattern. The required buffer is approximately 10% of the
|
|
99
|
+
// edge length of the tile cell, add a bit more to be safe.
|
|
100
|
+
return padBoundingBox(bbox, getResolution(index), 0.12);
|
|
88
101
|
}
|
|
89
102
|
|
|
90
103
|
// Resolution conversion function. Takes a WebMercatorViewport and returns
|
|
@@ -6,12 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
import type {ShaderModule} from '@luma.gl/shadertools';
|
|
8
8
|
import {getResolution} from 'quadbin';
|
|
9
|
+
import {getResolution as getH3Resolution, getNumCells} from 'h3-js';
|
|
9
10
|
|
|
10
11
|
import {
|
|
11
12
|
Accessor,
|
|
12
13
|
Color,
|
|
13
14
|
CompositeLayer,
|
|
14
15
|
CompositeLayerProps,
|
|
16
|
+
_deepEqual as deepEqual,
|
|
15
17
|
DefaultProps,
|
|
16
18
|
Layer,
|
|
17
19
|
UpdateParameters
|
|
@@ -21,6 +23,7 @@ import {SolidPolygonLayer} from '@deck.gl/layers';
|
|
|
21
23
|
import {HeatmapProps, heatmap} from './heatmap';
|
|
22
24
|
import {RTTModifier, PostProcessModifier} from './post-process-utils';
|
|
23
25
|
import QuadbinTileLayer, {QuadbinTileLayerProps} from './quadbin-tile-layer';
|
|
26
|
+
import H3TileLayer, {H3TileLayerProps} from './h3-tile-layer';
|
|
24
27
|
import {TilejsonPropType} from './utils';
|
|
25
28
|
import {TilejsonResult} from '@carto/api-client';
|
|
26
29
|
import {_Tile2DHeader as Tile2DHeader} from '@deck.gl/geo-layers';
|
|
@@ -37,7 +40,9 @@ const defaultColorRange: Color[] = [
|
|
|
37
40
|
|
|
38
41
|
const TEXTURE_PROPS: TextureProps = {
|
|
39
42
|
format: 'rgba8unorm',
|
|
40
|
-
|
|
43
|
+
dimension: '2d',
|
|
44
|
+
width: 1,
|
|
45
|
+
height: 1,
|
|
41
46
|
sampler: {
|
|
42
47
|
minFilter: 'linear',
|
|
43
48
|
magFilter: 'linear',
|
|
@@ -46,13 +51,23 @@ const TEXTURE_PROPS: TextureProps = {
|
|
|
46
51
|
}
|
|
47
52
|
};
|
|
48
53
|
/**
|
|
49
|
-
* Computes the unit density
|
|
54
|
+
* Computes the unit density for Quadbin cells.
|
|
55
|
+
* The unit density is the number of cells needed to cover the Earth's surface at a given resolution. It is inversely proportional to the cell area.
|
|
50
56
|
*/
|
|
51
|
-
function
|
|
57
|
+
function unitDensityForQuadbinCell(cell: bigint) {
|
|
52
58
|
const cellResolution = Number(getResolution(cell));
|
|
53
59
|
return Math.pow(4.0, cellResolution);
|
|
54
60
|
}
|
|
55
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Computes the unit density for H3 cells.
|
|
64
|
+
* The unit density is the number of cells needed to cover the Earth's surface at a given resolution. It is inversely proportional to the cell area.
|
|
65
|
+
*/
|
|
66
|
+
function unitDensityForH3Cell(cellId: string) {
|
|
67
|
+
const cellResolution = Number(getH3Resolution(cellId));
|
|
68
|
+
return getNumCells(cellResolution);
|
|
69
|
+
}
|
|
70
|
+
|
|
56
71
|
/**
|
|
57
72
|
* Converts a colorRange array to a flat array with 4 components per color
|
|
58
73
|
*/
|
|
@@ -118,12 +133,15 @@ class RTTSolidPolygonLayer extends RTTModifier(SolidPolygonLayer) {
|
|
|
118
133
|
|
|
119
134
|
draw(this, opts: any) {
|
|
120
135
|
const cell = this.props!.data[0];
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
if (cell) {
|
|
137
|
+
const maxDensity = this.props.elevationScale;
|
|
138
|
+
const {scheme} = this.parent.parent.parent.parent.parent.state;
|
|
139
|
+
const unitDensity =
|
|
140
|
+
scheme === 'h3' ? unitDensityForH3Cell(cell.id) : unitDensityForQuadbinCell(cell.id);
|
|
141
|
+
const densityProps: DensityProps = {factor: unitDensity / maxDensity};
|
|
142
|
+
for (const model of this.state.models) {
|
|
143
|
+
model.shaderInputs.setProps({density: densityProps});
|
|
144
|
+
}
|
|
127
145
|
}
|
|
128
146
|
|
|
129
147
|
super.draw(opts);
|
|
@@ -133,6 +151,9 @@ class RTTSolidPolygonLayer extends RTTModifier(SolidPolygonLayer) {
|
|
|
133
151
|
// Modify QuadbinTileLayer to apply heatmap post process effect
|
|
134
152
|
const PostProcessQuadbinTileLayer = PostProcessModifier(QuadbinTileLayer, heatmap);
|
|
135
153
|
|
|
154
|
+
// Modify H3TileLayer to apply heatmap post process effect
|
|
155
|
+
const PostProcessH3TileLayer = PostProcessModifier(H3TileLayer, heatmap);
|
|
156
|
+
|
|
136
157
|
const defaultProps: DefaultProps<HeatmapTileLayerProps> = {
|
|
137
158
|
data: TilejsonPropType,
|
|
138
159
|
getWeight: {type: 'accessor', value: 1},
|
|
@@ -150,7 +171,7 @@ export type HeatmapTileLayerProps<DataT = unknown> = _HeatmapTileLayerProps<Data
|
|
|
150
171
|
};
|
|
151
172
|
|
|
152
173
|
/** Properties added by HeatmapTileLayer. */
|
|
153
|
-
type _HeatmapTileLayerProps<DataT> = QuadbinTileLayerProps<DataT> &
|
|
174
|
+
type _HeatmapTileLayerProps<DataT> = (QuadbinTileLayerProps<DataT> | H3TileLayerProps<DataT>) &
|
|
154
175
|
HeatmapProps & {
|
|
155
176
|
/**
|
|
156
177
|
* Specified as an array of colors [color1, color2, ...].
|
|
@@ -179,12 +200,14 @@ class HeatmapTileLayer<DataT = any, ExtraProps extends {} = {}> extends Composit
|
|
|
179
200
|
state!: {
|
|
180
201
|
colorTexture?: Texture;
|
|
181
202
|
isLoaded: boolean;
|
|
203
|
+
scheme: string | null;
|
|
182
204
|
tiles: Set<Tile2DHeader>;
|
|
183
205
|
viewportChanged?: boolean;
|
|
184
206
|
};
|
|
185
207
|
initializeState() {
|
|
186
208
|
this.state = {
|
|
187
209
|
isLoaded: false,
|
|
210
|
+
scheme: null,
|
|
188
211
|
tiles: new Set(),
|
|
189
212
|
viewportChanged: false
|
|
190
213
|
};
|
|
@@ -199,9 +222,15 @@ class HeatmapTileLayer<DataT = any, ExtraProps extends {} = {}> extends Composit
|
|
|
199
222
|
updateState(opts: UpdateParameters<this>) {
|
|
200
223
|
const {props, oldProps} = opts;
|
|
201
224
|
super.updateState(opts);
|
|
202
|
-
if (props.colorRange
|
|
225
|
+
if (!deepEqual(props.colorRange, oldProps.colorRange, 2)) {
|
|
203
226
|
this._updateColorTexture(opts);
|
|
204
227
|
}
|
|
228
|
+
|
|
229
|
+
const scheme = props.data && 'scheme' in props.data ? props.data.scheme : null;
|
|
230
|
+
if (this.state.scheme !== scheme) {
|
|
231
|
+
this.setState({scheme});
|
|
232
|
+
this.state.tiles.clear();
|
|
233
|
+
}
|
|
205
234
|
}
|
|
206
235
|
|
|
207
236
|
renderLayers(): Layer {
|
|
@@ -220,15 +249,18 @@ class HeatmapTileLayer<DataT = any, ExtraProps extends {} = {}> extends Composit
|
|
|
220
249
|
...tileLayerProps
|
|
221
250
|
} = this.props;
|
|
222
251
|
|
|
252
|
+
const isH3 = this.state.scheme === 'h3';
|
|
253
|
+
|
|
254
|
+
const cellLayerName = isH3 ? 'hexagon-cell-hifi' : 'cell';
|
|
223
255
|
// Inject modified polygon layer as sublayer into TileLayer
|
|
224
256
|
const subLayerProps = {
|
|
225
257
|
..._subLayerProps,
|
|
226
|
-
|
|
227
|
-
..._subLayerProps?.
|
|
258
|
+
[cellLayerName]: {
|
|
259
|
+
..._subLayerProps?.[cellLayerName],
|
|
228
260
|
_subLayerProps: {
|
|
229
|
-
..._subLayerProps?.
|
|
261
|
+
..._subLayerProps?.[cellLayerName]?._subLayerProps,
|
|
230
262
|
fill: {
|
|
231
|
-
..._subLayerProps?.
|
|
263
|
+
..._subLayerProps?.[cellLayerName]?._subLayerProps?.fill,
|
|
232
264
|
type: RTTSolidPolygonLayer
|
|
233
265
|
}
|
|
234
266
|
}
|
|
@@ -246,21 +278,37 @@ class HeatmapTileLayer<DataT = any, ExtraProps extends {} = {}> extends Composit
|
|
|
246
278
|
|
|
247
279
|
for (const tile of tiles) {
|
|
248
280
|
const cell = tile.content[0];
|
|
249
|
-
const unitDensity =
|
|
281
|
+
const unitDensity = isH3 ? unitDensityForH3Cell(cell.id) : unitDensityForQuadbinCell(cell.id);
|
|
250
282
|
maxDensity = Math.max(tile.userData!.maxWeight * unitDensity, maxDensity);
|
|
251
283
|
tileZ = Math.max(tile.zoom, tileZ);
|
|
252
284
|
}
|
|
253
285
|
|
|
254
|
-
// Between zoom levels the max density will change, but it isn't possible to know by what factor.
|
|
255
|
-
|
|
256
|
-
|
|
286
|
+
// Between zoom levels the max density will change, but it isn't possible to know by what factor.
|
|
287
|
+
// As a heuristic, an estimatedGrowthFactor makes the transitions less obvious.
|
|
288
|
+
// For quadbin, uniform data distributions lead to an estimatedGrowthFactor of 4, while very localized data gives 1.
|
|
289
|
+
// For H3 the same logic applies but the aperture is 7, rather than 4, so a slightly higher estimatedGrowthFactor is used.
|
|
290
|
+
let overzoom: number;
|
|
291
|
+
let estimatedGrowthFactor: number;
|
|
292
|
+
if (isH3) {
|
|
293
|
+
// For H3, we need to account for the viewport zoom to H3 resolution mapping (see getHexagonResolution())
|
|
294
|
+
overzoom = (2 / 3) * this.context.viewport.zoom - tileZ - 2.25;
|
|
295
|
+
estimatedGrowthFactor = 2.2;
|
|
296
|
+
} else {
|
|
297
|
+
overzoom = this.context.viewport.zoom - tileZ;
|
|
298
|
+
estimatedGrowthFactor = 2;
|
|
299
|
+
}
|
|
257
300
|
|
|
258
|
-
maxDensity =
|
|
301
|
+
maxDensity = maxDensity * Math.pow(estimatedGrowthFactor, overzoom);
|
|
259
302
|
if (typeof onMaxDensityChange === 'function') {
|
|
260
303
|
onMaxDensityChange(maxDensity);
|
|
261
304
|
}
|
|
262
|
-
|
|
263
|
-
|
|
305
|
+
const PostProcessTileLayer = isH3 ? PostProcessH3TileLayer : PostProcessQuadbinTileLayer;
|
|
306
|
+
const layerProps = isH3
|
|
307
|
+
? (tileLayerProps as Omit<H3TileLayerProps, 'data'>)
|
|
308
|
+
: (tileLayerProps as Omit<QuadbinTileLayerProps, 'data'>);
|
|
309
|
+
|
|
310
|
+
return new PostProcessTileLayer(
|
|
311
|
+
layerProps,
|
|
264
312
|
this.getSubLayerProps({
|
|
265
313
|
id: 'heatmap',
|
|
266
314
|
data,
|
|
@@ -328,19 +376,14 @@ class HeatmapTileLayer<DataT = any, ExtraProps extends {} = {}> extends Composit
|
|
|
328
376
|
let {colorTexture} = this.state;
|
|
329
377
|
const colors = colorRangeToFlatArray(colorRange);
|
|
330
378
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
data: colors,
|
|
340
|
-
width: colorRange.length,
|
|
341
|
-
height: 1
|
|
342
|
-
});
|
|
343
|
-
}
|
|
379
|
+
colorTexture?.destroy();
|
|
380
|
+
colorTexture = this.context.device.createTexture({
|
|
381
|
+
...TEXTURE_PROPS,
|
|
382
|
+
data: colors,
|
|
383
|
+
width: colorRange.length,
|
|
384
|
+
height: 1
|
|
385
|
+
});
|
|
386
|
+
|
|
344
387
|
this.setState({colorTexture});
|
|
345
388
|
}
|
|
346
389
|
}
|
package/src/layers/heatmap.ts
CHANGED
|
@@ -89,6 +89,9 @@ vec4 heatmap_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) {
|
|
|
89
89
|
color.a = pow(color.a, 1.0 / 2.2);
|
|
90
90
|
color.a *= heatmap.opacity;
|
|
91
91
|
|
|
92
|
+
// Use premultiplied alpha for compatibility with blending in ScreenPass
|
|
93
|
+
color.rgb *= color.a;
|
|
94
|
+
|
|
92
95
|
return color;
|
|
93
96
|
}
|
|
94
97
|
`;
|
|
@@ -145,18 +145,7 @@ export default class RasterLayer<DataT = any, ExtraProps = {}> extends Composite
|
|
|
145
145
|
offset,
|
|
146
146
|
lineWidthScale, // Re-use widthScale prop to pass cell scale,
|
|
147
147
|
highlightedObjectIndex,
|
|
148
|
-
highlightColor
|
|
149
|
-
|
|
150
|
-
// RTT requires blending otherwise opacity < 1 blends with black
|
|
151
|
-
// render target
|
|
152
|
-
parameters: {
|
|
153
|
-
blendColorSrcFactor: 'one',
|
|
154
|
-
blendAlphaSrcFactor: 'one',
|
|
155
|
-
blendColorDstFactor: 'zero',
|
|
156
|
-
blendAlphaDstFactor: 'zero',
|
|
157
|
-
blendColorOperation: 'add',
|
|
158
|
-
blendAlphaOperation: 'add'
|
|
159
|
-
}
|
|
148
|
+
highlightColor
|
|
160
149
|
}
|
|
161
150
|
);
|
|
162
151
|
}
|