@carto/api-client 0.5.0-alpha.9 → 0.5.1-alpha.0
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/CHANGELOG.md +30 -1
- package/build/api-client.cjs +15241 -3358
- package/build/api-client.cjs.map +1 -0
- package/build/api-client.d.cts +528 -181
- package/build/api-client.d.ts +528 -181
- package/build/api-client.js +14685 -2911
- package/build/api-client.js.map +1 -0
- package/build/worker.js +5117 -619
- package/build/worker.js.map +1 -0
- package/package.json +49 -32
- package/src/api/query.ts +2 -1
- package/src/constants-internal.ts +10 -0
- package/src/constants.ts +5 -1
- package/src/deck/get-data-filter-extension-props.ts +27 -9
- package/src/fetch-map/basemap-styles.ts +159 -0
- package/src/fetch-map/basemap.ts +120 -0
- package/src/fetch-map/fetch-map.ts +331 -0
- package/src/fetch-map/index.ts +13 -0
- package/src/fetch-map/layer-map.ts +461 -0
- package/src/fetch-map/parse-map.ts +425 -0
- package/src/fetch-map/source.ts +233 -0
- package/src/fetch-map/types.ts +268 -0
- package/src/fetch-map/utils.ts +69 -0
- package/src/filters/tileFeatures.ts +27 -10
- package/src/filters/tileFeaturesRaster.ts +122 -0
- package/src/index.ts +1 -0
- package/src/models/model.ts +0 -7
- package/src/sources/base-source.ts +4 -2
- package/src/sources/h3-tileset-source.ts +1 -1
- package/src/sources/quadbin-tileset-source.ts +1 -1
- package/src/sources/raster-source.ts +18 -5
- package/src/sources/types.ts +15 -8
- package/src/sources/vector-tileset-source.ts +1 -1
- package/src/spatial-index.ts +3 -84
- package/src/types.ts +16 -2
- package/src/widget-sources/index.ts +1 -0
- package/src/widget-sources/types.ts +1 -3
- package/src/widget-sources/widget-raster-source.ts +14 -0
- package/src/widget-sources/widget-remote-source.ts +16 -91
- package/src/widget-sources/widget-source.ts +9 -25
- package/src/widget-sources/widget-tileset-source-impl.ts +16 -19
- package/src/widget-sources/widget-tileset-source.ts +24 -21
- package/src/workers/widget-tileset-worker.ts +1 -1
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import {LayerType, SCALE_TYPE} from './layer-map.js';
|
|
2
|
+
import {Format, MapType, ProviderType, QueryParameters} from '../types.js';
|
|
3
|
+
import {TilejsonResult, GeojsonResult, JsonResult} from '../sources/types.js';
|
|
4
|
+
|
|
5
|
+
export type VisualChannelField = {
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
colorColumn?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type VisualChannels = {
|
|
12
|
+
colorField?: VisualChannelField;
|
|
13
|
+
colorScale?: SCALE_TYPE;
|
|
14
|
+
|
|
15
|
+
customMarkersField?: VisualChannelField;
|
|
16
|
+
customMarkersScale?: SCALE_TYPE;
|
|
17
|
+
|
|
18
|
+
radiusField?: VisualChannelField;
|
|
19
|
+
radiusScale?: SCALE_TYPE;
|
|
20
|
+
|
|
21
|
+
rotationScale?: SCALE_TYPE;
|
|
22
|
+
rotationField?: VisualChannelField;
|
|
23
|
+
|
|
24
|
+
sizeField?: VisualChannelField;
|
|
25
|
+
sizeScale?: SCALE_TYPE;
|
|
26
|
+
|
|
27
|
+
strokeColorField?: VisualChannelField;
|
|
28
|
+
strokeColorScale?: SCALE_TYPE;
|
|
29
|
+
|
|
30
|
+
heightField?: VisualChannelField;
|
|
31
|
+
heightScale?: SCALE_TYPE;
|
|
32
|
+
|
|
33
|
+
weightField?: VisualChannelField;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type ColorRange = {
|
|
37
|
+
category: string;
|
|
38
|
+
colors: string[];
|
|
39
|
+
colorMap: string[][] | undefined;
|
|
40
|
+
name: string;
|
|
41
|
+
type: string;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type CustomMarkersRange = {
|
|
45
|
+
markerMap: {
|
|
46
|
+
value: string;
|
|
47
|
+
markerUrl?: string;
|
|
48
|
+
}[];
|
|
49
|
+
othersMarker?: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type VisConfig = {
|
|
53
|
+
filled?: boolean;
|
|
54
|
+
opacity?: number;
|
|
55
|
+
enable3d?: boolean;
|
|
56
|
+
|
|
57
|
+
colorAggregation?: any;
|
|
58
|
+
colorRange: ColorRange;
|
|
59
|
+
|
|
60
|
+
customMarkers?: boolean;
|
|
61
|
+
customMarkersRange?: CustomMarkersRange | null;
|
|
62
|
+
customMarkersUrl?: string | null;
|
|
63
|
+
|
|
64
|
+
radius: number;
|
|
65
|
+
radiusRange?: number[];
|
|
66
|
+
|
|
67
|
+
sizeAggregation?: any;
|
|
68
|
+
sizeRange?: any;
|
|
69
|
+
|
|
70
|
+
strokeColorAggregation?: any;
|
|
71
|
+
strokeOpacity?: number;
|
|
72
|
+
strokeColorRange?: ColorRange;
|
|
73
|
+
|
|
74
|
+
heightRange?: any;
|
|
75
|
+
heightAggregation?: any;
|
|
76
|
+
|
|
77
|
+
weightAggregation?: any;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export type TextLabel = {
|
|
81
|
+
field: VisualChannelField | null | undefined;
|
|
82
|
+
alignment?: 'center' | 'bottom' | 'top';
|
|
83
|
+
anchor?: 'middle' | 'start' | 'end';
|
|
84
|
+
size: number;
|
|
85
|
+
color?: number[];
|
|
86
|
+
offset?: [number, number];
|
|
87
|
+
outlineColor?: number[];
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export type MapLayerConfig = {
|
|
91
|
+
columns?: Record<string, any>;
|
|
92
|
+
color?: number[];
|
|
93
|
+
label?: string;
|
|
94
|
+
dataId: string;
|
|
95
|
+
textLabel: TextLabel[];
|
|
96
|
+
visConfig: VisConfig;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export type MapConfigLayer = {
|
|
100
|
+
type: LayerType;
|
|
101
|
+
id: string;
|
|
102
|
+
config: MapLayerConfig;
|
|
103
|
+
visualChannels: VisualChannels;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export interface CustomStyle {
|
|
107
|
+
url?: string;
|
|
108
|
+
style?: any;
|
|
109
|
+
customAttribution?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// TODO replace with more complete type from Builder
|
|
113
|
+
export type KeplerMapConfig = {
|
|
114
|
+
filters: any;
|
|
115
|
+
mapState: any;
|
|
116
|
+
mapStyle: {
|
|
117
|
+
styleType: string;
|
|
118
|
+
visibleLayerGroups: Record<string, boolean>;
|
|
119
|
+
};
|
|
120
|
+
popupSettings: any;
|
|
121
|
+
visState: {
|
|
122
|
+
layers: MapConfigLayer[];
|
|
123
|
+
layerBlending: any;
|
|
124
|
+
interactionConfig: any;
|
|
125
|
+
};
|
|
126
|
+
customBaseMaps?: {
|
|
127
|
+
customStyle?: CustomStyle;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export type BasemapType = 'maplibre' | 'google-maps';
|
|
132
|
+
|
|
133
|
+
export type Basemap = MapLibreBasemap | GoogleBasemap;
|
|
134
|
+
|
|
135
|
+
export type BasemapCommon = {
|
|
136
|
+
/**
|
|
137
|
+
* Type of basemap.
|
|
138
|
+
*/
|
|
139
|
+
type: BasemapType;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Custom attribution for style data if not provided by style definition.
|
|
143
|
+
*/
|
|
144
|
+
attribution?: string;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Properties of the basemap. These properties are specific to the basemap type.
|
|
148
|
+
*/
|
|
149
|
+
props: Record<string, any>;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export type MapLibreBasemap = BasemapCommon & {
|
|
153
|
+
type: 'maplibre';
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* MapLibre map properties.
|
|
157
|
+
*
|
|
158
|
+
* Meant to be passed to directly to `maplibregl.Map` object.
|
|
159
|
+
*/
|
|
160
|
+
props: MapLibreBasemapProps;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Layer groups to be displayed in the basemap.
|
|
164
|
+
*/
|
|
165
|
+
visibleLayerGroups?: Record<string, boolean>;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* If `style` has been filtered by `visibleLayerGroups` then this property contains original style object, so user
|
|
169
|
+
* can use `applyLayerGroupFilters` again with new settings.
|
|
170
|
+
*/
|
|
171
|
+
rawStyle?: string | Record<string, any>;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Cherry-pick of maplibregl Map API props that are supported/provided by fetchMap interface
|
|
175
|
+
export type MapLibreBasemapProps = {
|
|
176
|
+
style: string | Record<string, any>;
|
|
177
|
+
center: [number, number];
|
|
178
|
+
zoom: number;
|
|
179
|
+
pitch?: number;
|
|
180
|
+
bearing?: number;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export type GoogleBasemap = BasemapCommon & {
|
|
184
|
+
type: 'google-maps';
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Google map properties.
|
|
188
|
+
*
|
|
189
|
+
* Meant to be passed to directly to `google.maps.Map` object.
|
|
190
|
+
*/
|
|
191
|
+
props: GoogleBasemapProps;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// Cherry-pick of Google Map API props that are supported/provided by fetchMap interface
|
|
195
|
+
export type GoogleBasemapProps = {
|
|
196
|
+
mapTypeId: string;
|
|
197
|
+
mapId?: string;
|
|
198
|
+
center?: {lat: number; lng: number};
|
|
199
|
+
zoom?: number;
|
|
200
|
+
tilt?: number;
|
|
201
|
+
heading?: number;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export type Dataset = {
|
|
205
|
+
id: string;
|
|
206
|
+
type: MapType;
|
|
207
|
+
source: string;
|
|
208
|
+
cache?: number;
|
|
209
|
+
connectionName: string;
|
|
210
|
+
geoColumn: string;
|
|
211
|
+
data: TilejsonResult | GeojsonResult | JsonResult;
|
|
212
|
+
columns: string[];
|
|
213
|
+
format: Format;
|
|
214
|
+
aggregationExp: string;
|
|
215
|
+
aggregationResLevel: number;
|
|
216
|
+
queryParameters: QueryParameters;
|
|
217
|
+
connectionId?: string;
|
|
218
|
+
providerId: ProviderType;
|
|
219
|
+
createdAt?: string;
|
|
220
|
+
updatedAt?: string;
|
|
221
|
+
label?: string;
|
|
222
|
+
color?: string;
|
|
223
|
+
uniqueIdProperty?: string;
|
|
224
|
+
queryTemplate?: string | null;
|
|
225
|
+
name?: string | null;
|
|
226
|
+
spatialIndex?: string | null;
|
|
227
|
+
exportToBucketAvailable?: boolean;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
export type AttributeType = 'String' | 'Number' | 'Timestamp' | 'Boolean';
|
|
231
|
+
|
|
232
|
+
export type AttributeStatsBase = {
|
|
233
|
+
attribute: string;
|
|
234
|
+
type: AttributeType;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
export type AttributeStatsNumber = AttributeStatsBase & {
|
|
238
|
+
type: 'Number';
|
|
239
|
+
min: number;
|
|
240
|
+
avg: number;
|
|
241
|
+
max: number;
|
|
242
|
+
sum: number;
|
|
243
|
+
quantiles: number[][];
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
export type AttributeStatsTimestamp = AttributeStatsBase & {
|
|
247
|
+
type: 'Timestamp';
|
|
248
|
+
min: string;
|
|
249
|
+
max: string;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
export interface AttributeStatsStringCategory {
|
|
253
|
+
category: string;
|
|
254
|
+
frequency: number;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export type AttributeStatsString = AttributeStatsBase & {
|
|
258
|
+
type: 'String' | 'Boolean';
|
|
259
|
+
categories: AttributeStatsStringCategory[];
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Result of getAttributeStats request to backend.
|
|
264
|
+
*/
|
|
265
|
+
export type AttributeStats =
|
|
266
|
+
| AttributeStatsString
|
|
267
|
+
| AttributeStatsNumber
|
|
268
|
+
| AttributeStatsTimestamp;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type {BinaryFeature} from '@loaders.gl/schema';
|
|
2
|
+
import type {Dataset} from './types.js';
|
|
3
|
+
type Properties = BinaryFeature['properties'];
|
|
4
|
+
type NumericProps = BinaryFeature['numericProps'];
|
|
5
|
+
|
|
6
|
+
// Returns a Proxy object that allows accessing binary data
|
|
7
|
+
// as if it were JSON properties
|
|
8
|
+
export function createBinaryProxy(
|
|
9
|
+
data: {numericProps: NumericProps; properties: Properties[]},
|
|
10
|
+
index: number
|
|
11
|
+
) {
|
|
12
|
+
const {properties, numericProps} = data;
|
|
13
|
+
return new Proxy(properties[index] || {}, {
|
|
14
|
+
get(target, property) {
|
|
15
|
+
if (property in numericProps) {
|
|
16
|
+
return numericProps[property as string].value[index];
|
|
17
|
+
}
|
|
18
|
+
return target[property as any];
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
has(target, property) {
|
|
22
|
+
return property in numericProps || property in target;
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
ownKeys(target) {
|
|
26
|
+
return [...Object.keys(numericProps), ...Reflect.ownKeys(target)];
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
getOwnPropertyDescriptor() {
|
|
30
|
+
return {enumerable: true, configurable: true};
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function scaleIdentity() {
|
|
36
|
+
let unknown: any;
|
|
37
|
+
|
|
38
|
+
function scale(x: any) {
|
|
39
|
+
return x === null ? unknown : x;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
scale.invert = scale;
|
|
43
|
+
|
|
44
|
+
scale.domain = scale.range = (d: any) => d;
|
|
45
|
+
|
|
46
|
+
scale.unknown = (u: any) => {
|
|
47
|
+
if (u) {
|
|
48
|
+
unknown = u;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return unknown;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
scale.copy = () => {
|
|
55
|
+
const scaleCopy = scaleIdentity();
|
|
56
|
+
scaleCopy.unknown(unknown);
|
|
57
|
+
return scaleCopy;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return scale;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function isRemoteCalculationSupported(dataset: Dataset) {
|
|
64
|
+
if (dataset?.type === 'tileset' || dataset.providerId === 'databricks') {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {SpatialFilter, SpatialIndexTile, Tile} from '../types.js';
|
|
1
|
+
import {RasterTile, SpatialFilter, SpatialIndexTile, Tile} from '../types.js';
|
|
2
2
|
import {tileFeaturesGeometries} from './tileFeaturesGeometries.js';
|
|
3
3
|
import {tileFeaturesSpatialIndex} from './tileFeaturesSpatialIndex.js';
|
|
4
4
|
import {TileFormat} from '../constants.js';
|
|
5
5
|
import {DEFAULT_GEO_COLUMN} from '../constants-internal.js';
|
|
6
6
|
import {FeatureData} from '../types-internal.js';
|
|
7
|
-
import {SpatialDataType} from '../sources/types.js';
|
|
7
|
+
import {RasterMetadata, SpatialDataType} from '../sources/types.js';
|
|
8
|
+
import {isRasterTile, tileFeaturesRaster} from './tileFeaturesRaster.js';
|
|
9
|
+
import {assert} from '../utils.js';
|
|
8
10
|
|
|
9
11
|
/** @privateRemarks Source: @carto/react-core */
|
|
10
12
|
export type TileFeatures = {
|
|
@@ -14,12 +16,14 @@ export type TileFeatures = {
|
|
|
14
16
|
spatialDataColumn?: string;
|
|
15
17
|
spatialFilter: SpatialFilter;
|
|
16
18
|
uniqueIdProperty?: string;
|
|
19
|
+
rasterMetadata?: RasterMetadata;
|
|
17
20
|
options?: TileFeatureExtractOptions;
|
|
18
21
|
};
|
|
19
22
|
|
|
20
23
|
/** @privateRemarks Source: @carto/react-core */
|
|
21
24
|
export type TileFeatureExtractOptions = {
|
|
22
25
|
storeGeometry?: boolean;
|
|
26
|
+
uniqueIdProperty?: string;
|
|
23
27
|
};
|
|
24
28
|
|
|
25
29
|
/** @privateRemarks Source: @carto/react-core */
|
|
@@ -30,21 +34,34 @@ export function tileFeatures({
|
|
|
30
34
|
tileFormat,
|
|
31
35
|
spatialDataColumn = DEFAULT_GEO_COLUMN,
|
|
32
36
|
spatialDataType,
|
|
37
|
+
rasterMetadata,
|
|
33
38
|
options = {},
|
|
34
39
|
}: TileFeatures): FeatureData[] {
|
|
35
|
-
if (spatialDataType
|
|
36
|
-
return
|
|
37
|
-
tiles
|
|
40
|
+
if (spatialDataType === 'geo') {
|
|
41
|
+
return tileFeaturesGeometries({
|
|
42
|
+
tiles,
|
|
43
|
+
tileFormat,
|
|
44
|
+
spatialFilter,
|
|
45
|
+
uniqueIdProperty,
|
|
46
|
+
options,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (tiles.some(isRasterTile)) {
|
|
51
|
+
assert(rasterMetadata, 'Missing raster metadata');
|
|
52
|
+
return tileFeaturesRaster({
|
|
53
|
+
tiles: tiles as RasterTile[],
|
|
38
54
|
spatialFilter,
|
|
39
55
|
spatialDataColumn,
|
|
40
56
|
spatialDataType,
|
|
57
|
+
rasterMetadata,
|
|
41
58
|
});
|
|
42
59
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
|
|
61
|
+
return tileFeaturesSpatialIndex({
|
|
62
|
+
tiles: tiles as SpatialIndexTile[],
|
|
46
63
|
spatialFilter,
|
|
47
|
-
|
|
48
|
-
|
|
64
|
+
spatialDataColumn,
|
|
65
|
+
spatialDataType,
|
|
49
66
|
});
|
|
50
67
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cellToChildren as _cellToChildren,
|
|
3
|
+
cellToTile,
|
|
4
|
+
geometryToCells,
|
|
5
|
+
getResolution,
|
|
6
|
+
} from 'quadbin';
|
|
7
|
+
import {RasterTile, SpatialFilter, Tile} from '../types.js';
|
|
8
|
+
import {FeatureData} from '../types-internal.js';
|
|
9
|
+
import {
|
|
10
|
+
RasterMetadata,
|
|
11
|
+
RasterMetadataBand,
|
|
12
|
+
SpatialDataType,
|
|
13
|
+
} from '../sources/types.js';
|
|
14
|
+
|
|
15
|
+
export type TileFeaturesRasterOptions = {
|
|
16
|
+
tiles: RasterTile[];
|
|
17
|
+
spatialFilter: SpatialFilter;
|
|
18
|
+
spatialDataColumn: string;
|
|
19
|
+
spatialDataType: SpatialDataType;
|
|
20
|
+
rasterMetadata: RasterMetadata;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export function tileFeaturesRaster({
|
|
24
|
+
tiles,
|
|
25
|
+
...options
|
|
26
|
+
}: TileFeaturesRasterOptions): FeatureData[] {
|
|
27
|
+
// Cache band metadata for faster lookup while iterating over pixels.
|
|
28
|
+
const metadataByBand: Record<string, RasterMetadataBand & {nodata: number}> =
|
|
29
|
+
{};
|
|
30
|
+
for (const band of options.rasterMetadata.bands) {
|
|
31
|
+
// TODO(cleanup): Remove copy and cast after API is updated to return 'nodata' as a number.
|
|
32
|
+
metadataByBand[band.name] = {...band, nodata: Number(band.nodata)};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Omit empty and invisible tiles for simpler processing and types.
|
|
36
|
+
tiles = tiles.filter(isRasterTileVisible);
|
|
37
|
+
if (tiles.length === 0) return [];
|
|
38
|
+
|
|
39
|
+
// Raster tiles, and all pixels, are quadbin cells. Resolution of a pixel is
|
|
40
|
+
// the resolution of the tile, plus the number of subdivisions. Block size
|
|
41
|
+
// must be square, N x N, where N is a power of two.
|
|
42
|
+
const tileResolution = getResolution(tiles[0].index.q);
|
|
43
|
+
const tileBlockSize = tiles[0].data!.blockSize;
|
|
44
|
+
const cellResolution = tileResolution + BigInt(Math.log2(tileBlockSize));
|
|
45
|
+
|
|
46
|
+
// Compute covering cells for the spatial filter, at same resolution as the
|
|
47
|
+
// raster pixels, to be used as a mask.
|
|
48
|
+
const spatialFilterCells = new Set(
|
|
49
|
+
geometryToCells(options.spatialFilter, cellResolution)
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const data = new Map<bigint, FeatureData>();
|
|
53
|
+
|
|
54
|
+
for (const tile of tiles as Required<RasterTile>[]) {
|
|
55
|
+
const parent = tile.index.q;
|
|
56
|
+
|
|
57
|
+
const children = cellToChildrenSorted(parent, cellResolution);
|
|
58
|
+
|
|
59
|
+
// For each pixel/cell within the spatial filter, create a FeatureData.
|
|
60
|
+
// Order is row-major, starting from NW and ending at SE.
|
|
61
|
+
for (let i = 0; i < children.length; i++) {
|
|
62
|
+
if (!spatialFilterCells.has(children[i])) continue;
|
|
63
|
+
|
|
64
|
+
const cellData: FeatureData = {};
|
|
65
|
+
let cellDataExists = false;
|
|
66
|
+
|
|
67
|
+
for (const band in tile.data.cells.numericProps) {
|
|
68
|
+
const value = tile.data.cells.numericProps[band].value[i];
|
|
69
|
+
const bandMetadata = metadataByBand[band];
|
|
70
|
+
|
|
71
|
+
if (isValidBandValue(value, bandMetadata.nodata)) {
|
|
72
|
+
cellData[band] = tile.data.cells.numericProps[band].value[i];
|
|
73
|
+
cellDataExists = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (cellDataExists) {
|
|
78
|
+
data.set(children[i], cellData);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return Array.from(data.values());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Detects whether a given {@link Tile} is a {@link RasterTile}.
|
|
88
|
+
* @privateRemarks Method of detection is arbitrary, and may be changed.
|
|
89
|
+
*/
|
|
90
|
+
export function isRasterTile(tile: Tile): tile is RasterTile {
|
|
91
|
+
return !!(tile.data as Record<string, unknown>)?.cells;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function isRasterTileVisible(tile: RasterTile): tile is Required<RasterTile> {
|
|
95
|
+
return !!(tile.isVisible && tile.data?.cells?.numericProps);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* For the raster format, children are sorted in row-major order, starting from
|
|
100
|
+
* NW and ending at SE. Order returned by quadbin's cellToChildren() is not
|
|
101
|
+
* defined (and not related to the raster format), so sort explicitly here.
|
|
102
|
+
*/
|
|
103
|
+
function cellToChildrenSorted(parent: bigint, resolution: bigint): bigint[] {
|
|
104
|
+
return _cellToChildren(parent, resolution).sort(
|
|
105
|
+
(cellA: bigint, cellB: bigint) => {
|
|
106
|
+
const tileA = cellToTile(cellA);
|
|
107
|
+
const tileB = cellToTile(cellB);
|
|
108
|
+
if (tileA.y !== tileB.y) {
|
|
109
|
+
return tileA.y > tileB.y ? 1 : -1;
|
|
110
|
+
}
|
|
111
|
+
return tileA.x > tileB.x ? 1 : -1;
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Returns true if the given value is valid (not NaN, not 'nodata')
|
|
118
|
+
* for the given raster band.
|
|
119
|
+
*/
|
|
120
|
+
function isValidBandValue(value: unknown, nodata: number): value is number {
|
|
121
|
+
return Number.isNaN(value) ? false : nodata !== value;
|
|
122
|
+
}
|
package/src/index.ts
CHANGED
package/src/models/model.ts
CHANGED
|
@@ -39,10 +39,7 @@ export interface ModelSource {
|
|
|
39
39
|
queryParameters?: QueryParameters;
|
|
40
40
|
spatialDataColumn?: string;
|
|
41
41
|
spatialDataType?: SpatialDataType;
|
|
42
|
-
spatialFiltersResolution?: number;
|
|
43
42
|
spatialFiltersMode?: SpatialFilterPolyfillMode;
|
|
44
|
-
/** original resolution of the spatial index data as stored in the DW */
|
|
45
|
-
dataResolution?: number;
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
const {V3} = ApiVersion;
|
|
@@ -86,7 +83,6 @@ export function executeModel(props: {
|
|
|
86
83
|
filtersLogicalOperator = 'and',
|
|
87
84
|
spatialDataType = 'geo',
|
|
88
85
|
spatialFiltersMode = 'intersects',
|
|
89
|
-
spatialFiltersResolution = 0,
|
|
90
86
|
} = source;
|
|
91
87
|
|
|
92
88
|
const queryParams: Record<string, unknown> = {
|
|
@@ -118,9 +114,6 @@ export function executeModel(props: {
|
|
|
118
114
|
}
|
|
119
115
|
|
|
120
116
|
if (spatialDataType !== 'geo') {
|
|
121
|
-
if (spatialFiltersResolution > 0) {
|
|
122
|
-
queryParams.spatialFiltersResolution = spatialFiltersResolution;
|
|
123
|
-
}
|
|
124
117
|
queryParams.spatialFiltersMode = spatialFiltersMode;
|
|
125
118
|
}
|
|
126
119
|
|
|
@@ -18,9 +18,8 @@ import {MapType} from '../types.js';
|
|
|
18
18
|
import {APIErrorContext} from '../api/index.js';
|
|
19
19
|
import {getClient} from '../client.js';
|
|
20
20
|
|
|
21
|
-
export const SOURCE_DEFAULTS: SourceOptionalOptions = {
|
|
21
|
+
export const SOURCE_DEFAULTS: Omit<SourceOptionalOptions, 'clientId'> = {
|
|
22
22
|
apiBaseUrl: DEFAULT_API_BASE_URL,
|
|
23
|
-
clientId: getClient(),
|
|
24
23
|
format: 'tilejson',
|
|
25
24
|
headers: {},
|
|
26
25
|
maxLengthURL: DEFAULT_MAX_LENGTH_URL,
|
|
@@ -34,6 +33,7 @@ export async function baseSource<UrlParameters extends Record<string, unknown>>(
|
|
|
34
33
|
const {accessToken, connectionName, cache, ...optionalOptions} = options;
|
|
35
34
|
const mergedOptions = {
|
|
36
35
|
...SOURCE_DEFAULTS,
|
|
36
|
+
clientId: getClient(),
|
|
37
37
|
accessToken,
|
|
38
38
|
connectionName,
|
|
39
39
|
endpoint,
|
|
@@ -80,6 +80,7 @@ export async function baseSource<UrlParameters extends Record<string, unknown>>(
|
|
|
80
80
|
if (format === 'tilejson') {
|
|
81
81
|
const json = await requestWithParameters<TilejsonResult>({
|
|
82
82
|
baseUrl: dataUrl,
|
|
83
|
+
parameters: {client: clientId},
|
|
83
84
|
headers,
|
|
84
85
|
errorContext,
|
|
85
86
|
maxLengthURL,
|
|
@@ -93,6 +94,7 @@ export async function baseSource<UrlParameters extends Record<string, unknown>>(
|
|
|
93
94
|
|
|
94
95
|
return await requestWithParameters<GeojsonResult | JsonResult>({
|
|
95
96
|
baseUrl: dataUrl,
|
|
97
|
+
parameters: {client: clientId},
|
|
96
98
|
headers,
|
|
97
99
|
errorContext,
|
|
98
100
|
maxLengthURL,
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
+
import {baseSource} from './base-source.js';
|
|
5
6
|
import {getTileFormat} from '../utils/getTileFormat.js';
|
|
6
7
|
import {
|
|
7
8
|
WidgetTilesetSource,
|
|
8
9
|
WidgetTilesetSourceResult,
|
|
9
10
|
} from '../widget-sources/index.js';
|
|
10
|
-
import {baseSource} from './base-source.js';
|
|
11
11
|
import type {
|
|
12
12
|
SourceOptions,
|
|
13
13
|
TilejsonResult,
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
+
import {baseSource} from './base-source.js';
|
|
5
6
|
import {getTileFormat} from '../utils/getTileFormat.js';
|
|
6
7
|
import {
|
|
7
8
|
WidgetTilesetSource,
|
|
8
9
|
WidgetTilesetSourceResult,
|
|
9
10
|
} from '../widget-sources/index.js';
|
|
10
|
-
import {baseSource} from './base-source.js';
|
|
11
11
|
import type {
|
|
12
12
|
SourceOptions,
|
|
13
13
|
TilejsonResult,
|
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import {baseSource} from './base-source.js';
|
|
6
|
+
import {getTileFormat} from '../utils/getTileFormat.js';
|
|
7
|
+
import {
|
|
8
|
+
WidgetRasterSource,
|
|
9
|
+
WidgetRasterSourceResult,
|
|
10
|
+
} from '../widget-sources/index.js';
|
|
11
|
+
|
|
6
12
|
import type {
|
|
7
13
|
FilterOptions,
|
|
8
14
|
SourceOptions,
|
|
@@ -18,7 +24,7 @@ type UrlParameters = {
|
|
|
18
24
|
filters?: Record<string, unknown>;
|
|
19
25
|
};
|
|
20
26
|
|
|
21
|
-
export type RasterSourceResponse = TilejsonResult;
|
|
27
|
+
export type RasterSourceResponse = TilejsonResult & WidgetRasterSourceResult;
|
|
22
28
|
|
|
23
29
|
export const rasterSource = async function (
|
|
24
30
|
options: RasterSourceOptions
|
|
@@ -29,9 +35,16 @@ export const rasterSource = async function (
|
|
|
29
35
|
urlParameters.filters = filters;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
|
-
return baseSource<UrlParameters>(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
return baseSource<UrlParameters>('raster', options, urlParameters).then(
|
|
39
|
+
(result) => ({
|
|
40
|
+
...(result as TilejsonResult),
|
|
41
|
+
widgetSource: new WidgetRasterSource({
|
|
42
|
+
...options,
|
|
43
|
+
tileFormat: getTileFormat(result as TilejsonResult),
|
|
44
|
+
spatialDataColumn: 'quadbin',
|
|
45
|
+
spatialDataType: 'quadbin',
|
|
46
|
+
rasterMetadata: (result as TilejsonResult).raster_metadata!,
|
|
47
|
+
}),
|
|
48
|
+
})
|
|
36
49
|
) as Promise<RasterSourceResponse>;
|
|
37
50
|
};
|