@deck.gl/carto 9.1.8 → 9.1.10
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/fetch-map.d.ts.map +1 -1
- package/dist/api/fetch-map.js +1 -0
- package/dist/api/fetch-map.js.map +1 -1
- package/dist/api/parse-map.d.ts.map +1 -1
- package/dist/api/parse-map.js.map +1 -1
- package/dist/cartoPropertiesTile-worker.js +9 -1
- package/dist/cartoRasterTile-worker.js +9 -1
- package/dist/cartoSpatialTile-worker.js +9 -1
- package/dist/cartoVectorTile-worker.js +9 -1
- package/dist/dist.dev.js +475 -141
- package/dist/index.cjs +429 -142
- package/dist/index.cjs.map +4 -4
- package/dist/layers/cluster-tile-layer.d.ts.map +1 -1
- package/dist/layers/cluster-tile-layer.js +6 -5
- package/dist/layers/cluster-tile-layer.js.map +1 -1
- package/dist/layers/cluster-utils.d.ts.map +1 -1
- package/dist/layers/cluster-utils.js +3 -28
- package/dist/layers/cluster-utils.js.map +1 -1
- package/dist/layers/h3-tile-layer.d.ts.map +1 -1
- package/dist/layers/h3-tile-layer.js +5 -5
- package/dist/layers/h3-tile-layer.js.map +1 -1
- package/dist/layers/heatmap-tile-layer.d.ts.map +1 -1
- package/dist/layers/heatmap-tile-layer.js +5 -1
- package/dist/layers/heatmap-tile-layer.js.map +1 -1
- package/dist/layers/label-utils.d.ts +7 -0
- package/dist/layers/label-utils.d.ts.map +1 -0
- package/dist/layers/label-utils.js +218 -0
- package/dist/layers/label-utils.js.map +1 -0
- package/dist/layers/point-label-layer.d.ts +6 -0
- package/dist/layers/point-label-layer.d.ts.map +1 -1
- package/dist/layers/point-label-layer.js +13 -1
- package/dist/layers/point-label-layer.js.map +1 -1
- package/dist/layers/quadbin-tile-layer.d.ts.map +1 -1
- package/dist/layers/quadbin-tile-layer.js +5 -5
- package/dist/layers/quadbin-tile-layer.js.map +1 -1
- package/dist/layers/raster-tile-layer.d.ts.map +1 -1
- package/dist/layers/raster-tile-layer.js +7 -6
- package/dist/layers/raster-tile-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-tile.d.ts +3 -1
- package/dist/layers/schema/carto-tile.d.ts.map +1 -1
- package/dist/layers/schema/carto-tile.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/layers/schema/spatialjson-utils.d.ts +4 -7
- package/dist/layers/schema/spatialjson-utils.d.ts.map +1 -1
- package/dist/layers/schema/spatialjson-utils.js.map +1 -1
- package/dist/layers/utils.d.ts +3 -2
- package/dist/layers/utils.d.ts.map +1 -1
- package/dist/layers/utils.js +28 -7
- package/dist/layers/utils.js.map +1 -1
- package/dist/layers/vector-tile-layer.d.ts +12 -4
- package/dist/layers/vector-tile-layer.d.ts.map +1 -1
- package/dist/layers/vector-tile-layer.js +76 -35
- package/dist/layers/vector-tile-layer.js.map +1 -1
- package/dist/utils.d.ts +6 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +53 -0
- package/dist/utils.js.map +1 -1
- package/dist.min.js +12 -12
- package/package.json +2 -2
- package/src/api/fetch-map.ts +2 -0
- package/src/api/parse-map.ts +2 -0
- package/src/layers/cluster-tile-layer.ts +7 -5
- package/src/layers/cluster-utils.ts +3 -29
- package/src/layers/h3-tile-layer.ts +6 -6
- package/src/layers/heatmap-tile-layer.ts +9 -1
- package/src/layers/label-utils.ts +304 -0
- package/src/layers/point-label-layer.ts +18 -1
- package/src/layers/quadbin-tile-layer.ts +6 -6
- package/src/layers/raster-tile-layer.ts +7 -6
- package/src/layers/schema/carto-tile.ts +3 -1
- package/src/layers/schema/spatialjson-utils.ts +4 -3
- package/src/layers/utils.ts +31 -7
- package/src/layers/vector-tile-layer.ts +100 -42
- package/src/utils.ts +79 -0
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.1.
|
|
6
|
+
"version": "9.1.10",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"@loaders.gl/core": "^4.2.0",
|
|
76
76
|
"@luma.gl/core": "^9.1.5"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "f0dc529ad3196bcdbf4acb842c7aa81ca13cb689"
|
|
79
79
|
}
|
package/src/api/fetch-map.ts
CHANGED
package/src/api/parse-map.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
+
/* eslint-disable no-shadow */
|
|
6
|
+
|
|
5
7
|
import {GeoJsonLayer, GeoJsonLayerProps} from '@deck.gl/layers';
|
|
6
8
|
import {
|
|
7
9
|
TileLayer,
|
|
@@ -38,7 +40,7 @@ import {DEFAULT_TILE_SIZE} from '../constants';
|
|
|
38
40
|
import QuadbinTileset2D from './quadbin-tileset-2d';
|
|
39
41
|
import {getQuadbinPolygon} from './quadbin-utils';
|
|
40
42
|
import CartoSpatialTileLoader from './schema/carto-spatial-tile-loader';
|
|
41
|
-
import {
|
|
43
|
+
import {TilejsonPropType, mergeLoadOptions} from './utils';
|
|
42
44
|
import type {TilejsonResult} from '@carto/api-client';
|
|
43
45
|
|
|
44
46
|
registerLoaders([CartoSpatialTileLoader]);
|
|
@@ -216,11 +218,11 @@ export default class ClusterTileLayer<
|
|
|
216
218
|
static defaultProps = defaultProps;
|
|
217
219
|
|
|
218
220
|
getLoadOptions(): any {
|
|
219
|
-
const loadOptions = super.getLoadOptions() || {};
|
|
220
221
|
const tileJSON = this.props.data as TilejsonResult;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
222
|
+
return mergeLoadOptions(super.getLoadOptions(), {
|
|
223
|
+
fetch: {headers: {Authorization: `Bearer ${tileJSON.accessToken}`}},
|
|
224
|
+
cartoSpatialTile: {scheme: 'quadbin'}
|
|
225
|
+
});
|
|
224
226
|
}
|
|
225
227
|
|
|
226
228
|
renderLayers(): Layer | null | LayersList {
|
|
@@ -6,6 +6,7 @@ import {cellToParent} from 'quadbin';
|
|
|
6
6
|
import {_Tile2DHeader as Tile2DHeader} from '@deck.gl/geo-layers';
|
|
7
7
|
import {Accessor, log} from '@deck.gl/core';
|
|
8
8
|
import {BinaryFeatureCollection} from '@loaders.gl/schema';
|
|
9
|
+
import {createBinaryPointFeature, createEmptyBinary} from '../utils';
|
|
9
10
|
|
|
10
11
|
export type Aggregation = 'any' | 'average' | 'count' | 'min' | 'max' | 'sum';
|
|
11
12
|
export type AggregationProperties<FeaturePropertiesT> = {
|
|
@@ -137,15 +138,6 @@ export function computeAggregationStats<FeaturePropertiesT>(
|
|
|
137
138
|
return stats;
|
|
138
139
|
}
|
|
139
140
|
|
|
140
|
-
const EMPTY_UINT16ARRAY = new Uint16Array();
|
|
141
|
-
const EMPTY_BINARY_PROPS = {
|
|
142
|
-
positions: {value: new Float32Array(), size: 2},
|
|
143
|
-
properties: [],
|
|
144
|
-
numericProps: {},
|
|
145
|
-
featureIds: {value: EMPTY_UINT16ARRAY, size: 1},
|
|
146
|
-
globalFeatureIds: {value: EMPTY_UINT16ARRAY, size: 1}
|
|
147
|
-
};
|
|
148
|
-
|
|
149
141
|
type BinaryFeatureCollectionWithStats<FeaturePropertiesT> = Omit<
|
|
150
142
|
BinaryFeatureCollection,
|
|
151
143
|
'points'
|
|
@@ -168,25 +160,7 @@ export function clustersToBinary<FeaturePropertiesT>(
|
|
|
168
160
|
}
|
|
169
161
|
|
|
170
162
|
return {
|
|
171
|
-
|
|
172
|
-
points: {
|
|
173
|
-
type: 'Point',
|
|
174
|
-
positions: {value: positions, size: 2},
|
|
175
|
-
properties: data,
|
|
176
|
-
numericProps: {},
|
|
177
|
-
featureIds: {value: featureIds, size: 1},
|
|
178
|
-
globalFeatureIds: {value: featureIds, size: 1}
|
|
179
|
-
},
|
|
180
|
-
lines: {
|
|
181
|
-
type: 'LineString',
|
|
182
|
-
pathIndices: {value: EMPTY_UINT16ARRAY, size: 1},
|
|
183
|
-
...EMPTY_BINARY_PROPS
|
|
184
|
-
},
|
|
185
|
-
polygons: {
|
|
186
|
-
type: 'Polygon',
|
|
187
|
-
polygonIndices: {value: EMPTY_UINT16ARRAY, size: 1},
|
|
188
|
-
primitivePolygonIndices: {value: EMPTY_UINT16ARRAY, size: 1},
|
|
189
|
-
...EMPTY_BINARY_PROPS
|
|
190
|
-
}
|
|
163
|
+
...createEmptyBinary(),
|
|
164
|
+
points: createBinaryPointFeature(positions, featureIds, featureIds, {}, data)
|
|
191
165
|
};
|
|
192
166
|
}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import {CompositeLayer, CompositeLayerProps,
|
|
5
|
+
import {CompositeLayer, CompositeLayerProps, DefaultProps} from '@deck.gl/core';
|
|
6
6
|
import {H3HexagonLayer, H3HexagonLayerProps} from '@deck.gl/geo-layers';
|
|
7
7
|
import H3Tileset2D, {getHexagonResolution} from './h3-tileset-2d';
|
|
8
8
|
import SpatialIndexTileLayer, {SpatialIndexTileLayerProps} from './spatial-index-tile-layer';
|
|
9
9
|
import type {TilejsonResult} from '@carto/api-client';
|
|
10
|
-
import {
|
|
10
|
+
import {TilejsonPropType, mergeLoadOptions} from './utils';
|
|
11
11
|
import {DEFAULT_TILE_SIZE} from '../constants';
|
|
12
12
|
|
|
13
13
|
export const renderSubLayers = props => {
|
|
@@ -47,11 +47,11 @@ export default class H3TileLayer<DataT = any, ExtraPropsT extends {} = {}> exten
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
getLoadOptions(): any {
|
|
50
|
-
const loadOptions = super.getLoadOptions() || {};
|
|
51
50
|
const tileJSON = this.props.data as TilejsonResult;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
return mergeLoadOptions(super.getLoadOptions(), {
|
|
52
|
+
fetch: {headers: {Authorization: `Bearer ${tileJSON.accessToken}`}},
|
|
53
|
+
cartoSpatialTile: {scheme: 'h3'}
|
|
54
|
+
});
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
renderLayers(): SpatialIndexTileLayer | null {
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-shadow */
|
|
6
|
+
|
|
5
7
|
import type {ShaderModule} from '@luma.gl/shadertools';
|
|
6
8
|
import {getResolution} from 'quadbin';
|
|
7
9
|
|
|
@@ -235,7 +237,13 @@ class HeatmapTileLayer<DataT = any, ExtraProps extends {} = {}> extends Composit
|
|
|
235
237
|
|
|
236
238
|
let tileZ = 0;
|
|
237
239
|
let maxDensity = 0;
|
|
238
|
-
const
|
|
240
|
+
const loadedTiles = [...this.state.tiles].filter(t => t.content);
|
|
241
|
+
const visibleTiles = loadedTiles.filter(t => t.isVisible);
|
|
242
|
+
|
|
243
|
+
// As deck.gl initially marks tiles as hidden, use hidden tiles as fallback for calculation.
|
|
244
|
+
// This avoids an ugly flash/glitch at startup when layer is first rendered
|
|
245
|
+
const tiles = visibleTiles.length ? visibleTiles : loadedTiles;
|
|
246
|
+
|
|
239
247
|
for (const tile of tiles) {
|
|
240
248
|
const cell = tile.content[0];
|
|
241
249
|
const unitDensity = unitDensityForCell(cell.id);
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import {GeoBoundingBox} from '@deck.gl/geo-layers';
|
|
2
|
+
import {TypedArray} from '@loaders.gl/loader-utils';
|
|
3
|
+
import {BinaryPointFeature, BinaryLineFeature, BinaryPolygonFeature} from '@loaders.gl/schema';
|
|
4
|
+
import {copyNumericProps, createBinaryPointFeature, initializeNumericProps} from '../utils';
|
|
5
|
+
|
|
6
|
+
type Vec2 = [number, number] | TypedArray;
|
|
7
|
+
type TileBBox = GeoBoundingBox;
|
|
8
|
+
type Properties = BinaryPointFeature['properties'];
|
|
9
|
+
type LineInfo = {index: number; length: number};
|
|
10
|
+
|
|
11
|
+
export function createPointsFromLines(
|
|
12
|
+
lines: BinaryLineFeature,
|
|
13
|
+
uniqueIdProperty?: string
|
|
14
|
+
): BinaryPointFeature | null {
|
|
15
|
+
const hasNumericUniqueId = uniqueIdProperty ? uniqueIdProperty in lines.numericProps : false;
|
|
16
|
+
const idToLineInfo = new Map<string | number | undefined, LineInfo>();
|
|
17
|
+
|
|
18
|
+
// First pass: find the longest line for each unique ID
|
|
19
|
+
// If we don't have a uniqueIdProperty, treat each line as unique
|
|
20
|
+
for (let i = 0; i < lines.pathIndices.value.length - 1; i++) {
|
|
21
|
+
const pathIndex = lines.pathIndices.value[i];
|
|
22
|
+
const featureId = lines.featureIds.value[pathIndex];
|
|
23
|
+
let uniqueId: string | number | undefined;
|
|
24
|
+
|
|
25
|
+
if (uniqueIdProperty === undefined) {
|
|
26
|
+
uniqueId = featureId;
|
|
27
|
+
} else if (hasNumericUniqueId) {
|
|
28
|
+
uniqueId = lines.numericProps[uniqueIdProperty].value[pathIndex];
|
|
29
|
+
} else if (lines.properties[featureId] && uniqueIdProperty in lines.properties[featureId]) {
|
|
30
|
+
uniqueId = lines.properties[featureId][uniqueIdProperty];
|
|
31
|
+
} else {
|
|
32
|
+
uniqueId = undefined;
|
|
33
|
+
}
|
|
34
|
+
const length = getLineLength(lines, i);
|
|
35
|
+
if (!idToLineInfo.has(uniqueId) || length > idToLineInfo.get(uniqueId)!.length) {
|
|
36
|
+
idToLineInfo.set(uniqueId, {index: i, length});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const positions: number[] = [];
|
|
41
|
+
const properties: Properties = [];
|
|
42
|
+
const featureIds: number[] = [];
|
|
43
|
+
const globalFeatureIds: number[] = [];
|
|
44
|
+
const numericProps = initializeNumericProps(idToLineInfo.size, lines.numericProps);
|
|
45
|
+
|
|
46
|
+
// Second pass: create points for the longest line of each unique ID
|
|
47
|
+
let pointIndex = 0;
|
|
48
|
+
for (const [_, {index}] of idToLineInfo) {
|
|
49
|
+
const midpoint = getLineMidpoint(lines, index);
|
|
50
|
+
positions.push(...midpoint);
|
|
51
|
+
|
|
52
|
+
const pathIndex = lines.pathIndices.value[index];
|
|
53
|
+
const featureId = lines.featureIds.value[pathIndex];
|
|
54
|
+
featureIds.push(pointIndex);
|
|
55
|
+
properties.push(lines.properties[featureId]);
|
|
56
|
+
globalFeatureIds.push(lines.globalFeatureIds.value[pathIndex]);
|
|
57
|
+
copyNumericProps(lines.numericProps, numericProps, pathIndex, pointIndex);
|
|
58
|
+
pointIndex++;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return createBinaryPointFeature(
|
|
62
|
+
positions,
|
|
63
|
+
featureIds,
|
|
64
|
+
globalFeatureIds,
|
|
65
|
+
numericProps,
|
|
66
|
+
properties
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function createPointsFromPolygons(
|
|
71
|
+
polygons: Required<BinaryPolygonFeature>,
|
|
72
|
+
tileBbox: TileBBox,
|
|
73
|
+
props: any
|
|
74
|
+
): BinaryPointFeature {
|
|
75
|
+
const {west, south, east, north} = tileBbox;
|
|
76
|
+
const tileArea = (east - west) * (north - south);
|
|
77
|
+
const minPolygonArea = tileArea * 0.0001; // 0.1% threshold
|
|
78
|
+
|
|
79
|
+
const positions: number[] = [];
|
|
80
|
+
const properties: Properties = [];
|
|
81
|
+
const featureIds: number[] = [];
|
|
82
|
+
const globalFeatureIds: number[] = [];
|
|
83
|
+
const numericProps = initializeNumericProps(
|
|
84
|
+
polygons.polygonIndices.value.length - 1,
|
|
85
|
+
polygons.numericProps
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// Process each polygon
|
|
89
|
+
let pointIndex = 0;
|
|
90
|
+
let triangleIndex = 0;
|
|
91
|
+
const {extruded} = props;
|
|
92
|
+
for (let i = 0; i < polygons.polygonIndices.value.length - 1; i++) {
|
|
93
|
+
const startIndex = polygons.polygonIndices.value[i];
|
|
94
|
+
const endIndex = polygons.polygonIndices.value[i + 1];
|
|
95
|
+
|
|
96
|
+
// Skip small polygons
|
|
97
|
+
if (getPolygonArea(polygons, i) < minPolygonArea) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const centroid = getPolygonCentroid(polygons, i);
|
|
102
|
+
let maxArea = -1;
|
|
103
|
+
let largestTriangleCenter: [number, number] = [0, 0];
|
|
104
|
+
let centroidIsInside = false;
|
|
105
|
+
|
|
106
|
+
// Scan triangles until we find ones that don't belong to this polygon
|
|
107
|
+
while (triangleIndex < polygons.triangles.value.length) {
|
|
108
|
+
const i1 = polygons.triangles.value[triangleIndex];
|
|
109
|
+
|
|
110
|
+
// If we've moved past the current polygon's triangles, break
|
|
111
|
+
if (i1 >= endIndex) {
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// If we've already found a triangle containing the centroid, skip the rest
|
|
116
|
+
if (centroidIsInside) {
|
|
117
|
+
triangleIndex += 3;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const i2 = polygons.triangles.value[triangleIndex + 1];
|
|
122
|
+
const i3 = polygons.triangles.value[triangleIndex + 2];
|
|
123
|
+
const v1 = polygons.positions.value.subarray(
|
|
124
|
+
i1 * polygons.positions.size,
|
|
125
|
+
i1 * polygons.positions.size + polygons.positions.size
|
|
126
|
+
);
|
|
127
|
+
const v2 = polygons.positions.value.subarray(
|
|
128
|
+
i2 * polygons.positions.size,
|
|
129
|
+
i2 * polygons.positions.size + polygons.positions.size
|
|
130
|
+
);
|
|
131
|
+
const v3 = polygons.positions.value.subarray(
|
|
132
|
+
i3 * polygons.positions.size,
|
|
133
|
+
i3 * polygons.positions.size + polygons.positions.size
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
if (isPointInTriangle(centroid, v1, v2, v3)) {
|
|
137
|
+
centroidIsInside = true;
|
|
138
|
+
} else {
|
|
139
|
+
const area = getTriangleArea(v1, v2, v3);
|
|
140
|
+
if (area > maxArea) {
|
|
141
|
+
maxArea = area;
|
|
142
|
+
largestTriangleCenter = [(v1[0] + v2[0] + v3[0]) / 3, (v1[1] + v2[1] + v3[1]) / 3];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
triangleIndex += 3;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const labelPoint = centroidIsInside ? centroid : largestTriangleCenter;
|
|
150
|
+
if (isPointInBounds(labelPoint, tileBbox)) {
|
|
151
|
+
positions.push(...labelPoint);
|
|
152
|
+
const featureId = polygons.featureIds.value[startIndex];
|
|
153
|
+
if (extruded) {
|
|
154
|
+
const elevation = props.getElevation(undefined, {
|
|
155
|
+
data: polygons,
|
|
156
|
+
index: featureId
|
|
157
|
+
});
|
|
158
|
+
positions.push(elevation * props.elevationScale);
|
|
159
|
+
}
|
|
160
|
+
properties.push(polygons.properties[featureId]);
|
|
161
|
+
featureIds.push(pointIndex);
|
|
162
|
+
globalFeatureIds.push(polygons.globalFeatureIds.value[startIndex]);
|
|
163
|
+
copyNumericProps(polygons.numericProps, numericProps, startIndex, pointIndex);
|
|
164
|
+
pointIndex++;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Trim numeric properties arrays to actual size
|
|
169
|
+
if (polygons.numericProps) {
|
|
170
|
+
Object.keys(numericProps).forEach(prop => {
|
|
171
|
+
numericProps[prop].value = numericProps[prop].value.slice(0, pointIndex);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return createBinaryPointFeature(
|
|
176
|
+
positions,
|
|
177
|
+
featureIds,
|
|
178
|
+
globalFeatureIds,
|
|
179
|
+
numericProps,
|
|
180
|
+
properties,
|
|
181
|
+
extruded ? 3 : 2
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Helper functions
|
|
186
|
+
function getPolygonArea(polygons: Required<BinaryPolygonFeature>, index: number): number {
|
|
187
|
+
const {
|
|
188
|
+
positions: {value: positions, size},
|
|
189
|
+
polygonIndices: {value: indices},
|
|
190
|
+
triangles: {value: triangles}
|
|
191
|
+
} = polygons;
|
|
192
|
+
|
|
193
|
+
const startIndex = indices[index];
|
|
194
|
+
const endIndex = indices[index + 1];
|
|
195
|
+
let area = 0;
|
|
196
|
+
let triangleIndex = 0;
|
|
197
|
+
|
|
198
|
+
// Find first triangle of this polygon
|
|
199
|
+
// Note: this assumes tirnagles and polygon indices are sorted.
|
|
200
|
+
// This is true for the current implementation of geojsonToBinary
|
|
201
|
+
while (triangleIndex < triangles.length) {
|
|
202
|
+
const i1 = triangles[triangleIndex];
|
|
203
|
+
if (i1 >= startIndex) break;
|
|
204
|
+
triangleIndex += 3;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Process triangles until we hit the next polygon
|
|
208
|
+
while (triangleIndex < triangles.length) {
|
|
209
|
+
const i1 = triangles[triangleIndex];
|
|
210
|
+
if (i1 >= endIndex) break;
|
|
211
|
+
|
|
212
|
+
const i2 = triangles[triangleIndex + 1];
|
|
213
|
+
const i3 = triangles[triangleIndex + 2];
|
|
214
|
+
const v1 = positions.subarray(i1 * size, i1 * size + size);
|
|
215
|
+
const v2 = positions.subarray(i2 * size, i2 * size + size);
|
|
216
|
+
const v3 = positions.subarray(i3 * size, i3 * size + size);
|
|
217
|
+
|
|
218
|
+
area += getTriangleArea(v1, v2, v3);
|
|
219
|
+
triangleIndex += 3;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return area;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function isPointInBounds([x, y]: [number, number], {west, east, south, north}: TileBBox): boolean {
|
|
226
|
+
return x >= west && x < east && y >= south && y < north;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function isPointInTriangle(p: Vec2, v1: Vec2, v2: Vec2, v3: Vec2): boolean {
|
|
230
|
+
const area = Math.abs((v2[0] - v1[0]) * (v3[1] - v1[1]) - (v3[0] - v1[0]) * (v2[1] - v1[1])) / 2;
|
|
231
|
+
const area1 = Math.abs((v1[0] - p[0]) * (v2[1] - p[1]) - (v2[0] - p[0]) * (v1[1] - p[1])) / 2;
|
|
232
|
+
const area2 = Math.abs((v2[0] - p[0]) * (v3[1] - p[1]) - (v3[0] - p[0]) * (v2[1] - p[1])) / 2;
|
|
233
|
+
const area3 = Math.abs((v3[0] - p[0]) * (v1[1] - p[1]) - (v1[0] - p[0]) * (v3[1] - p[1])) / 2;
|
|
234
|
+
|
|
235
|
+
// Account for floating point precision
|
|
236
|
+
return Math.abs(area - (area1 + area2 + area3)) < 1e-10;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function getTriangleArea([x1, y1]: Vec2, [x2, y2]: Vec2, [x3, y3]: Vec2): number {
|
|
240
|
+
return Math.abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function getPolygonCentroid(polygons: BinaryPolygonFeature, index: number): [number, number] {
|
|
244
|
+
const {
|
|
245
|
+
positions: {value: positions, size}
|
|
246
|
+
} = polygons;
|
|
247
|
+
const startIndex = size * polygons.polygonIndices.value[index];
|
|
248
|
+
const endIndex = size * polygons.polygonIndices.value[index + 1];
|
|
249
|
+
|
|
250
|
+
let minX = Infinity;
|
|
251
|
+
let minY = Infinity;
|
|
252
|
+
let maxX = -Infinity;
|
|
253
|
+
let maxY = -Infinity;
|
|
254
|
+
|
|
255
|
+
for (let i = startIndex; i < endIndex; i += size) {
|
|
256
|
+
const [x, y] = positions.subarray(i, i + 2);
|
|
257
|
+
minX = Math.min(minX, x);
|
|
258
|
+
minY = Math.min(minY, y);
|
|
259
|
+
maxX = Math.max(maxX, x);
|
|
260
|
+
maxY = Math.max(maxY, y);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return [(minX + maxX) / 2, (minY + maxY) / 2];
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function getSegmentLength(lines: BinaryLineFeature, index: number): number {
|
|
267
|
+
const {
|
|
268
|
+
positions: {value}
|
|
269
|
+
} = lines;
|
|
270
|
+
const [x1, y1, x2, y2] = value.subarray(index, index + 4);
|
|
271
|
+
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function getLineLength(lines: BinaryLineFeature, index: number): number {
|
|
275
|
+
const {
|
|
276
|
+
positions: {size}
|
|
277
|
+
} = lines;
|
|
278
|
+
const startIndex = size * lines.pathIndices.value[index];
|
|
279
|
+
const endIndex = size * lines.pathIndices.value[index + 1];
|
|
280
|
+
let length = 0;
|
|
281
|
+
for (let j = startIndex; j < endIndex; j += size) {
|
|
282
|
+
length += getSegmentLength(lines, j);
|
|
283
|
+
}
|
|
284
|
+
return length;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function getLineMidpoint(lines: BinaryLineFeature, index: number): [number, number] {
|
|
288
|
+
const {
|
|
289
|
+
positions: {value: positions},
|
|
290
|
+
pathIndices: {value: pathIndices}
|
|
291
|
+
} = lines;
|
|
292
|
+
const startIndex = pathIndices[index] * 2;
|
|
293
|
+
const endIndex = pathIndices[index + 1] * 2;
|
|
294
|
+
const numPoints = (endIndex - startIndex) / 2;
|
|
295
|
+
|
|
296
|
+
if (numPoints === 2) {
|
|
297
|
+
// For lines with only two vertices, interpolate between them
|
|
298
|
+
const [x1, y1, x2, y2] = positions.subarray(startIndex, startIndex + 4);
|
|
299
|
+
return [(x1 + x2) / 2, (y1 + y2) / 2];
|
|
300
|
+
}
|
|
301
|
+
// For lines with multiple vertices, use the middle vertex
|
|
302
|
+
const midPointIndex = startIndex + Math.floor(numPoints / 2) * 2;
|
|
303
|
+
return [positions[midPointIndex], positions[midPointIndex + 1]];
|
|
304
|
+
}
|
|
@@ -9,13 +9,15 @@ import {
|
|
|
9
9
|
CompositeLayerProps,
|
|
10
10
|
DefaultProps,
|
|
11
11
|
Layer,
|
|
12
|
-
LayersList
|
|
12
|
+
LayersList,
|
|
13
|
+
log
|
|
13
14
|
} from '@deck.gl/core';
|
|
14
15
|
import {
|
|
15
16
|
TextLayer,
|
|
16
17
|
TextLayerProps,
|
|
17
18
|
_TextBackgroundLayer as TextBackgroundLayer
|
|
18
19
|
} from '@deck.gl/layers';
|
|
20
|
+
import VectorTileLayer from './vector-tile-layer';
|
|
19
21
|
|
|
20
22
|
const [LEFT, TOP, RIGHT, BOTTOM] = [0, 1, 2, 3];
|
|
21
23
|
|
|
@@ -97,6 +99,12 @@ type _PointLabelLayerProps<DataT> = TextLayerProps<DataT> & {
|
|
|
97
99
|
secondarySizeScale?: number;
|
|
98
100
|
};
|
|
99
101
|
|
|
102
|
+
/**
|
|
103
|
+
* PointLabelLayer is a layer that renders point labels.
|
|
104
|
+
* It is a composite layer that renders a primary and secondary label.
|
|
105
|
+
* It behaves like a TextLayer except that getTextSize is **not supported**
|
|
106
|
+
* and the text size for the primary label must be set with **sizeScale**.
|
|
107
|
+
*/
|
|
100
108
|
export default class PointLabelLayer<
|
|
101
109
|
DataT = any,
|
|
102
110
|
ExtraProps extends {} = {}
|
|
@@ -194,6 +202,15 @@ export default class PointLabelLayer<
|
|
|
194
202
|
updateTriggers
|
|
195
203
|
} = this.props;
|
|
196
204
|
|
|
205
|
+
if (sizeScale < 2) {
|
|
206
|
+
const propName = (this.parent as VectorTileLayer)?.props?.textSizeScale
|
|
207
|
+
? 'textSizeScale'
|
|
208
|
+
: 'sizeScale';
|
|
209
|
+
log.warn(
|
|
210
|
+
`${propName} has small value (${sizeScale}). Note getTextSize is not supported on PointLabelLayer`
|
|
211
|
+
)();
|
|
212
|
+
}
|
|
213
|
+
|
|
197
214
|
return new EnhancedTextLayer(
|
|
198
215
|
this.getSubLayerProps({
|
|
199
216
|
id,
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import {CompositeLayer, CompositeLayerProps,
|
|
5
|
+
import {CompositeLayer, CompositeLayerProps, DefaultProps} from '@deck.gl/core';
|
|
6
6
|
import QuadbinLayer, {QuadbinLayerProps} from './quadbin-layer';
|
|
7
7
|
import QuadbinTileset2D from './quadbin-tileset-2d';
|
|
8
8
|
import SpatialIndexTileLayer, {SpatialIndexTileLayerProps} from './spatial-index-tile-layer';
|
|
9
9
|
import {hexToBigInt} from 'quadbin';
|
|
10
10
|
import type {TilejsonResult} from '@carto/api-client';
|
|
11
|
-
import {
|
|
11
|
+
import {TilejsonPropType, mergeLoadOptions} from './utils';
|
|
12
12
|
import {DEFAULT_TILE_SIZE} from '../constants';
|
|
13
13
|
|
|
14
14
|
export const renderSubLayers = props => {
|
|
@@ -43,11 +43,11 @@ export default class QuadbinTileLayer<
|
|
|
43
43
|
static defaultProps = defaultProps;
|
|
44
44
|
|
|
45
45
|
getLoadOptions(): any {
|
|
46
|
-
const loadOptions = super.getLoadOptions() || {};
|
|
47
46
|
const tileJSON = this.props.data as TilejsonResult;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
return mergeLoadOptions(super.getLoadOptions(), {
|
|
48
|
+
fetch: {headers: {Authorization: `Bearer ${tileJSON.accessToken}`}},
|
|
49
|
+
cartoSpatialTile: {scheme: 'quadbin'}
|
|
50
|
+
});
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
renderLayers(): SpatialIndexTileLayer | null {
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import RasterLayer, {RasterLayerProps} from './raster-layer';
|
|
14
14
|
import QuadbinTileset2D from './quadbin-tileset-2d';
|
|
15
15
|
import type {TilejsonResult} from '@carto/api-client';
|
|
16
|
-
import {
|
|
16
|
+
import {TilejsonPropType, mergeLoadOptions} from './utils';
|
|
17
17
|
import {DEFAULT_TILE_SIZE} from '../constants';
|
|
18
18
|
import {TileLayer, TileLayerProps} from '@deck.gl/geo-layers';
|
|
19
19
|
import {copy, PostProcessModifier} from './post-process-utils';
|
|
@@ -62,10 +62,10 @@ export default class RasterTileLayer<
|
|
|
62
62
|
static defaultProps = defaultProps;
|
|
63
63
|
|
|
64
64
|
getLoadOptions(): any {
|
|
65
|
-
const loadOptions = super.getLoadOptions() || {};
|
|
66
65
|
const tileJSON = this.props.data as TilejsonResult;
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
return mergeLoadOptions(super.getLoadOptions(), {
|
|
67
|
+
fetch: {headers: {Authorization: `Bearer ${tileJSON.accessToken}`}}
|
|
68
|
+
});
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
renderLayers(): Layer | null | LayersList {
|
|
@@ -74,6 +74,7 @@ export default class RasterTileLayer<
|
|
|
74
74
|
|
|
75
75
|
const {tiles: data, minzoom: minZoom, maxzoom: maxZoom, raster_metadata: metadata} = tileJSON;
|
|
76
76
|
const SubLayerClass = this.getSubLayerClass('tile', PostProcessTileLayer);
|
|
77
|
+
const loadOptions = this.getLoadOptions();
|
|
77
78
|
return new SubLayerClass(this.props, {
|
|
78
79
|
id: `raster-tile-layer-${this.props.id}`,
|
|
79
80
|
data,
|
|
@@ -83,8 +84,8 @@ export default class RasterTileLayer<
|
|
|
83
84
|
minZoom,
|
|
84
85
|
maxZoom,
|
|
85
86
|
loadOptions: {
|
|
86
|
-
|
|
87
|
-
...
|
|
87
|
+
...loadOptions,
|
|
88
|
+
cartoRasterTile: {...loadOptions?.cartoRasterTile, metadata}
|
|
88
89
|
}
|
|
89
90
|
});
|
|
90
91
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import {readPackedTypedArray} from './fast-pbf';
|
|
6
|
+
import {TypedArray} from '@loaders.gl/loader-utils';
|
|
6
7
|
|
|
7
8
|
// KeyValueObject ========================================
|
|
8
9
|
interface KeyValueObject {
|
|
@@ -88,7 +89,8 @@ class FieldsReader {
|
|
|
88
89
|
// NumericProp ========================================
|
|
89
90
|
|
|
90
91
|
export interface NumericProp {
|
|
91
|
-
value:
|
|
92
|
+
value: TypedArray;
|
|
93
|
+
size: number;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
class NumericPropReader {
|
|
@@ -3,17 +3,18 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import {bigIntToHex} from 'quadbin';
|
|
6
|
+
import {BinaryPointFeature} from '@loaders.gl/schema';
|
|
6
7
|
|
|
7
8
|
export type IndexScheme = 'h3' | 'quadbin';
|
|
8
9
|
type TypedArray = Float32Array | Float64Array;
|
|
9
10
|
|
|
10
11
|
export type Indices = {value: BigUint64Array};
|
|
11
|
-
export type NumericProps =
|
|
12
|
-
export type Properties =
|
|
12
|
+
export type NumericProps = BinaryPointFeature['numericProps'];
|
|
13
|
+
export type Properties = BinaryPointFeature['properties'];
|
|
13
14
|
export type Cells = {
|
|
14
15
|
indices: Indices;
|
|
15
16
|
numericProps: NumericProps;
|
|
16
|
-
properties: Properties
|
|
17
|
+
properties: Properties;
|
|
17
18
|
};
|
|
18
19
|
export type SpatialBinary = {scheme?: IndexScheme; cells: Cells};
|
|
19
20
|
export type SpatialJson = {
|