@carto/api-client 0.5.15-alpha.raster-0 → 0.5.15-alpha.raster-2
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/build/api-client.cjs +88 -15
- package/build/api-client.cjs.map +1 -1
- package/build/api-client.d.cts +62 -14
- package/build/api-client.d.ts +62 -14
- package/build/api-client.js +86 -15
- package/build/api-client.js.map +1 -1
- package/package.json +1 -1
- package/src/fetch-map/basemap-styles.ts +1 -1
- package/src/fetch-map/index.ts +5 -1
- package/src/fetch-map/layer-map.ts +34 -17
- package/src/fetch-map/parse-map.ts +29 -3
- package/src/fetch-map/raster-layer.ts +6 -4
- package/src/fetch-map/utils.ts +56 -0
- package/src/fetch-map/vec-expr-evaluator.ts +0 -12
- package/src/index.ts +0 -5
- package/src/sources/types.ts +52 -11
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"homepage": "https://github.com/CartoDB/carto-api-client#readme",
|
|
9
9
|
"author": "Don McCurdy <donmccurdy@carto.com>",
|
|
10
10
|
"packageManager": "yarn@4.3.1",
|
|
11
|
-
"version": "0.5.15-alpha.raster-
|
|
11
|
+
"version": "0.5.15-alpha.raster-2",
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"publishConfig": {
|
|
14
14
|
"access": "public"
|
|
@@ -92,7 +92,7 @@ export const STYLE_LAYER_GROUPS: StyleLayerGroup[] = [
|
|
|
92
92
|
];
|
|
93
93
|
|
|
94
94
|
export function applyLayerGroupFilters(
|
|
95
|
-
style: any,
|
|
95
|
+
style: any, // this Maplibre/Mapbox style, we don't want to add a dependency on Maplibre
|
|
96
96
|
visibleLayerGroups: Record<StyleLayerGroupSlug, boolean>
|
|
97
97
|
) {
|
|
98
98
|
if (!Array.isArray(style?.layers)) {
|
package/src/fetch-map/index.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
default as BASEMAP,
|
|
3
|
+
applyLayerGroupFilters as _applyLayerGroupFilters,
|
|
4
|
+
} from './basemap-styles.js';
|
|
2
5
|
export {getRasterTileLayerStyleProps as _getRasterTileLayerStyleProps} from './raster-layer.js';
|
|
3
6
|
export {fetchMap} from './fetch-map.js';
|
|
4
7
|
export type {FetchMapOptions, FetchMapResult} from './fetch-map.js';
|
|
@@ -12,3 +15,4 @@ export type {
|
|
|
12
15
|
export * from './basemap.js';
|
|
13
16
|
export * from './layer-map.js';
|
|
14
17
|
export * from './parse-map.js';
|
|
18
|
+
export {getLog10ScaleSteps as _getLog10ScaleSteps} from './utils.js';
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
createBinaryProxy,
|
|
26
26
|
formatDate,
|
|
27
27
|
formatTimestamp,
|
|
28
|
+
getLog10ScaleSteps,
|
|
28
29
|
scaleIdentity,
|
|
29
30
|
} from './utils.js';
|
|
30
31
|
import type {
|
|
@@ -39,7 +40,7 @@ import type {
|
|
|
39
40
|
import type {ProviderType, SchemaField} from '../types.js';
|
|
40
41
|
import {DEFAULT_AGGREGATION_EXP_ALIAS} from '../constants-internal.js';
|
|
41
42
|
import {AggregationTypes} from '../constants.js';
|
|
42
|
-
import type {TilejsonResult} from '../sources/types.js';
|
|
43
|
+
import type {Attribute, TilejsonResult} from '../sources/types.js';
|
|
43
44
|
|
|
44
45
|
export type D3Scale = {
|
|
45
46
|
domain: (d?: any) => any[];
|
|
@@ -211,10 +212,21 @@ export function getLayerProps(
|
|
|
211
212
|
}
|
|
212
213
|
|
|
213
214
|
function domainFromAttribute(
|
|
214
|
-
attribute:
|
|
215
|
-
scaleType: ScaleType,
|
|
215
|
+
attribute: Attribute,
|
|
216
|
+
scaleType: ScaleType | 'log10steps',
|
|
216
217
|
scaleLength: number
|
|
217
|
-
) {
|
|
218
|
+
): number[] | string[] {
|
|
219
|
+
if (
|
|
220
|
+
scaleType === 'log10steps' &&
|
|
221
|
+
attribute.min !== undefined &&
|
|
222
|
+
attribute.max !== undefined
|
|
223
|
+
) {
|
|
224
|
+
return getLog10ScaleSteps({
|
|
225
|
+
min: attribute.min,
|
|
226
|
+
max: attribute.max,
|
|
227
|
+
steps: scaleLength,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
218
230
|
if (scaleType === 'ordinal' || scaleType === 'point') {
|
|
219
231
|
if (!attribute.categories) {
|
|
220
232
|
return [0, 1];
|
|
@@ -225,7 +237,7 @@ function domainFromAttribute(
|
|
|
225
237
|
}
|
|
226
238
|
|
|
227
239
|
if (scaleType === 'quantile' && attribute.quantiles) {
|
|
228
|
-
return attribute.quantiles
|
|
240
|
+
return 'global' in attribute.quantiles
|
|
229
241
|
? attribute.quantiles.global[scaleLength]
|
|
230
242
|
: attribute.quantiles[scaleLength];
|
|
231
243
|
}
|
|
@@ -234,7 +246,7 @@ function domainFromAttribute(
|
|
|
234
246
|
if (scaleType === 'log' && min === 0) {
|
|
235
247
|
min = 1e-5;
|
|
236
248
|
}
|
|
237
|
-
return [min, attribute.max];
|
|
249
|
+
return [min ?? 0, attribute.max ?? 1];
|
|
238
250
|
}
|
|
239
251
|
|
|
240
252
|
function domainFromValues(values: any, scaleType: ScaleType) {
|
|
@@ -256,14 +268,16 @@ function domainFromValues(values: any, scaleType: ScaleType) {
|
|
|
256
268
|
function calculateDomain(
|
|
257
269
|
data: TilejsonResult,
|
|
258
270
|
name: string,
|
|
259
|
-
scaleType: ScaleType,
|
|
271
|
+
scaleType: ScaleType | 'log10steps',
|
|
260
272
|
scaleLength?: number
|
|
261
273
|
) {
|
|
262
274
|
if (data.tilestats) {
|
|
263
275
|
// Tileset data type
|
|
264
276
|
const {attributes} = data.tilestats.layers[0];
|
|
265
277
|
const attribute = attributes.find((a: any) => a.attribute === name);
|
|
266
|
-
|
|
278
|
+
if (attribute) {
|
|
279
|
+
return domainFromAttribute(attribute, scaleType, scaleLength as number);
|
|
280
|
+
}
|
|
267
281
|
}
|
|
268
282
|
|
|
269
283
|
return [0, 1];
|
|
@@ -318,7 +332,7 @@ export function getColorAccessor(
|
|
|
318
332
|
scaleType: ScaleType,
|
|
319
333
|
{aggregation, range}: {aggregation: string; range: any},
|
|
320
334
|
opacity: number | undefined,
|
|
321
|
-
data:
|
|
335
|
+
data: TilejsonResult
|
|
322
336
|
): {accessor: any; scale: any} {
|
|
323
337
|
const scale = calculateLayerScale(
|
|
324
338
|
colorColumn || name,
|
|
@@ -348,19 +362,22 @@ export function calculateLayerScale(
|
|
|
348
362
|
) {
|
|
349
363
|
let domain: string[] | number[] = [];
|
|
350
364
|
let scaleColor: string[] = [];
|
|
365
|
+
const {colors} = range;
|
|
351
366
|
|
|
352
|
-
if (scaleType
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
367
|
+
if (scaleType === 'custom') {
|
|
368
|
+
if (range.uiCustomScaleType === 'logarithmic') {
|
|
369
|
+
domain = calculateDomain(data, name, 'log10steps', colors.length);
|
|
370
|
+
scaleColor = colors;
|
|
371
|
+
} else if (range.colorMap) {
|
|
372
|
+
const {colorMap} = range;
|
|
356
373
|
colorMap.forEach(([value, color]) => {
|
|
357
374
|
(domain as string[]).push(value);
|
|
358
375
|
scaleColor.push(color);
|
|
359
376
|
});
|
|
360
|
-
} else {
|
|
361
|
-
domain = calculateDomain(data, name, scaleType, colors.length);
|
|
362
|
-
scaleColor = colors;
|
|
363
377
|
}
|
|
378
|
+
} else if (scaleType !== 'identity') {
|
|
379
|
+
domain = calculateDomain(data, name, scaleType, colors.length);
|
|
380
|
+
scaleColor = colors;
|
|
364
381
|
|
|
365
382
|
if (scaleType === 'ordinal') {
|
|
366
383
|
domain = domain.slice(0, scaleColor.length);
|
|
@@ -456,7 +473,7 @@ export function getSizeAccessor(
|
|
|
456
473
|
scaleType: ScaleType | undefined,
|
|
457
474
|
aggregation: string | null | undefined,
|
|
458
475
|
range: Iterable<Range> | null | undefined,
|
|
459
|
-
data:
|
|
476
|
+
data: TilejsonResult
|
|
460
477
|
): {accessor: any; scale: any} {
|
|
461
478
|
const scale = scaleType ? SCALE_FUNCS[scaleType]() : identity;
|
|
462
479
|
if (scaleType) {
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
getRasterTileLayerStylePropsRgb,
|
|
37
37
|
getRasterTileLayerStylePropsScaledBand,
|
|
38
38
|
} from './raster-layer.js';
|
|
39
|
+
import type {TilejsonResult} from '../sources/types.js';
|
|
39
40
|
|
|
40
41
|
export type Scale = {
|
|
41
42
|
field: VisualChannelField;
|
|
@@ -257,7 +258,7 @@ function createChannelProps(
|
|
|
257
258
|
layerType: LayerType,
|
|
258
259
|
config: MapLayerConfig,
|
|
259
260
|
visualChannels: VisualChannels,
|
|
260
|
-
data:
|
|
261
|
+
data: TilejsonResult,
|
|
261
262
|
dataset: Dataset
|
|
262
263
|
): {
|
|
263
264
|
channelProps: Record<string, any>;
|
|
@@ -270,15 +271,24 @@ function createChannelProps(
|
|
|
270
271
|
radiusScale,
|
|
271
272
|
strokeColorField,
|
|
272
273
|
strokeColorScale,
|
|
274
|
+
sizeField: strokeWidthField,
|
|
275
|
+
sizeScale: strokeWidthScale,
|
|
273
276
|
weightField,
|
|
274
277
|
} = visualChannels;
|
|
275
278
|
if (layerType === 'raster') {
|
|
279
|
+
const rasterMetadata = data.raster_metadata;
|
|
280
|
+
if (!rasterMetadata) {
|
|
281
|
+
return {
|
|
282
|
+
channelProps: {},
|
|
283
|
+
scales: {},
|
|
284
|
+
};
|
|
285
|
+
}
|
|
276
286
|
const rasterStyleType = config.visConfig.rasterStyleType;
|
|
277
287
|
if (rasterStyleType === 'Rgb') {
|
|
278
288
|
return {
|
|
279
289
|
channelProps: getRasterTileLayerStylePropsRgb({
|
|
280
290
|
layerConfig: config,
|
|
281
|
-
rasterMetadata
|
|
291
|
+
rasterMetadata,
|
|
282
292
|
visualChannels,
|
|
283
293
|
}),
|
|
284
294
|
scales: {},
|
|
@@ -288,7 +298,7 @@ function createChannelProps(
|
|
|
288
298
|
channelProps: getRasterTileLayerStylePropsScaledBand({
|
|
289
299
|
layerConfig: config,
|
|
290
300
|
visualChannels,
|
|
291
|
-
rasterMetadata
|
|
301
|
+
rasterMetadata,
|
|
292
302
|
}),
|
|
293
303
|
scales: {
|
|
294
304
|
...(colorField && {
|
|
@@ -427,6 +437,22 @@ function createChannelProps(
|
|
|
427
437
|
...domainAndRangeFromScale(scale),
|
|
428
438
|
};
|
|
429
439
|
}
|
|
440
|
+
if (strokeWidthField) {
|
|
441
|
+
const {accessor, scale} = getSizeAccessor(
|
|
442
|
+
strokeWidthField,
|
|
443
|
+
strokeWidthScale,
|
|
444
|
+
visConfig.sizeAggregation,
|
|
445
|
+
visConfig.sizeRange,
|
|
446
|
+
data
|
|
447
|
+
);
|
|
448
|
+
result.getLineWidth = accessor;
|
|
449
|
+
scales.lineWidth = updateTriggers.getLineWidth = {
|
|
450
|
+
field: strokeWidthField,
|
|
451
|
+
type: strokeWidthScale || 'identity',
|
|
452
|
+
...domainAndRangeFromScale(scale),
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
|
|
430
456
|
if (heightField && visConfig.enable3d) {
|
|
431
457
|
const {accessor, scale} = getSizeAccessor(
|
|
432
458
|
heightField,
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
VisualChannels,
|
|
14
14
|
} from './types.js';
|
|
15
15
|
import {createColorScale, type ScaleType} from './layer-map.js';
|
|
16
|
+
import {getLog10ScaleSteps} from './utils.js';
|
|
16
17
|
|
|
17
18
|
const UNKNOWN_COLOR = [134, 141, 145];
|
|
18
19
|
|
|
@@ -377,10 +378,11 @@ export function domainFromRasterMetadataBand(
|
|
|
377
378
|
}
|
|
378
379
|
if (scaleType === 'custom') {
|
|
379
380
|
if (colorRange.uiCustomScaleType === 'logarithmic') {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
381
|
+
return getLog10ScaleSteps({
|
|
382
|
+
min: band.stats.min,
|
|
383
|
+
max: band.stats.max,
|
|
384
|
+
steps: colorRange.colors.length,
|
|
385
|
+
});
|
|
384
386
|
} else {
|
|
385
387
|
// actually custom, read colorMap
|
|
386
388
|
return colorRange.colorMap?.map(([value]) => value) || [];
|
package/src/fetch-map/utils.ts
CHANGED
|
@@ -85,3 +85,59 @@ export function formatDate(value: string | number | Date): string {
|
|
|
85
85
|
export function formatTimestamp(value: string | number | Date): string {
|
|
86
86
|
return String(Math.floor(new Date(value).getTime() / 1000));
|
|
87
87
|
}
|
|
88
|
+
|
|
89
|
+
function roundedPow10(exp: number) {
|
|
90
|
+
// Math.pow(10, less than 4) generates "0.0...009999999999999999" instead of "0.0...01"
|
|
91
|
+
// round it ...
|
|
92
|
+
const raw = Math.pow(10, exp);
|
|
93
|
+
if (exp < 0) {
|
|
94
|
+
const shift = Math.pow(10, -exp);
|
|
95
|
+
return Math.round(raw * shift) / shift;
|
|
96
|
+
}
|
|
97
|
+
return raw;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Create domain for D3 threshold scale with logarithmic steps.
|
|
102
|
+
*
|
|
103
|
+
* If min is 0, it starts with max and goes down to fill color scale.
|
|
104
|
+
* If max is Infinity, it starts with 10 and goes up to fill color scale.
|
|
105
|
+
* Othersise it starts on first power of 10 that is greater than min.
|
|
106
|
+
*
|
|
107
|
+
* Generates `steps-1` entries, as this is what d3 threshold scale expects
|
|
108
|
+
*
|
|
109
|
+
* @see https://d3js.org/d3-scale/threshold
|
|
110
|
+
*/
|
|
111
|
+
export function getLog10ScaleSteps({
|
|
112
|
+
min,
|
|
113
|
+
max,
|
|
114
|
+
steps,
|
|
115
|
+
}: {
|
|
116
|
+
min: number;
|
|
117
|
+
max: number;
|
|
118
|
+
steps: number;
|
|
119
|
+
}): number[] {
|
|
120
|
+
if (min === 0) {
|
|
121
|
+
if (max === Infinity) {
|
|
122
|
+
// count aggregations have [0, Infinity]
|
|
123
|
+
// that will yield [10, 100, 1000, ...]
|
|
124
|
+
return [...Array(steps - 1)].map((_v, i) => roundedPow10(i + 1));
|
|
125
|
+
}
|
|
126
|
+
// if stats.min = 0, we only can attempt to start from max and decrease powers until
|
|
127
|
+
// we use all color buckets ...
|
|
128
|
+
const maxLog = Math.log10(max);
|
|
129
|
+
const endExponent = Math.ceil(maxLog);
|
|
130
|
+
const startExponent = endExponent - steps + 1;
|
|
131
|
+
return [...Array(steps - 1)].map((_v, i) =>
|
|
132
|
+
roundedPow10(startExponent + i)
|
|
133
|
+
);
|
|
134
|
+
} else {
|
|
135
|
+
const minLog = Math.log10(min);
|
|
136
|
+
const startExponent =
|
|
137
|
+
Math.ceil(minLog) === minLog ? minLog + 1 : Math.ceil(minLog);
|
|
138
|
+
|
|
139
|
+
return [...Array(steps - 1)].map((_v, i) =>
|
|
140
|
+
roundedPow10(startExponent + i)
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -66,18 +66,6 @@ export function validateVecExprSyntax(
|
|
|
66
66
|
return validate(parsed, context);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
export function createValidationContext(
|
|
70
|
-
validSymbols: string[]
|
|
71
|
-
): Record<string, unknown> {
|
|
72
|
-
return validSymbols.reduce(
|
|
73
|
-
(acc, symbol) => {
|
|
74
|
-
acc[symbol] = 1;
|
|
75
|
-
return acc;
|
|
76
|
-
},
|
|
77
|
-
{} as Record<string, unknown>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
69
|
export type VecExprVecLike =
|
|
82
70
|
| number[]
|
|
83
71
|
| Float32Array
|
package/src/index.ts
CHANGED
|
@@ -2,11 +2,6 @@ export * from './client.js';
|
|
|
2
2
|
export * from './constants.js';
|
|
3
3
|
export * from './deck/index.js';
|
|
4
4
|
export * from './fetch-map/index.js';
|
|
5
|
-
export type {
|
|
6
|
-
LayerDescriptor,
|
|
7
|
-
LayerType,
|
|
8
|
-
_getRasterTileLayerStyleProps,
|
|
9
|
-
} from './fetch-map/index.js';
|
|
10
5
|
export {
|
|
11
6
|
createVecExprEvaluator as _createVecExprEvaluator,
|
|
12
7
|
evaluateVecExpr as _evaluateVecExpr,
|
package/src/sources/types.ts
CHANGED
|
@@ -292,14 +292,64 @@ export interface Tilestats {
|
|
|
292
292
|
|
|
293
293
|
export interface Layer {
|
|
294
294
|
layer: string;
|
|
295
|
+
/** Number of features in the layer. */
|
|
295
296
|
count: number;
|
|
297
|
+
|
|
298
|
+
/** Number of attributes in the layer. */
|
|
296
299
|
attributeCount: number;
|
|
297
300
|
attributes: Attribute[];
|
|
301
|
+
|
|
302
|
+
/** Type of geometry as in geojson geometry type (Point, LineString, Polygon, etc.) */
|
|
303
|
+
geometry?: string;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export interface AttributeCategoryItem {
|
|
307
|
+
category: string;
|
|
308
|
+
frequency: number;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Quantiles by number of buckets.
|
|
313
|
+
*
|
|
314
|
+
* Example:
|
|
315
|
+
* ```ts
|
|
316
|
+
* {
|
|
317
|
+
* // for 3 buckets, first 1/3 of items lies in range [min, 20], second 1/3 is in [20, 40], and last 1/3 is in [40, max]
|
|
318
|
+
* 3: [20, 40],
|
|
319
|
+
* 4: [20, 30, 50], for 4 buckets ...
|
|
320
|
+
* }
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
export interface QuantileStats {
|
|
324
|
+
[bucketCount: number]: number[];
|
|
298
325
|
}
|
|
299
326
|
|
|
300
327
|
export interface Attribute {
|
|
301
|
-
|
|
328
|
+
/**
|
|
329
|
+
* String, Number, Timestamp, Boolean
|
|
330
|
+
*/
|
|
302
331
|
type: string;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Attribute name.
|
|
335
|
+
*/
|
|
336
|
+
attribute: string;
|
|
337
|
+
|
|
338
|
+
// Stats for numeric attributes
|
|
339
|
+
min?: number;
|
|
340
|
+
max?: number;
|
|
341
|
+
sum?: number;
|
|
342
|
+
|
|
343
|
+
/** Quantiles by number of buckets */
|
|
344
|
+
quantiles?:
|
|
345
|
+
| {
|
|
346
|
+
// Quantile stats for numeric attributes in static spatial index tilesets are enclosed in extra global object
|
|
347
|
+
global: QuantileStats;
|
|
348
|
+
}
|
|
349
|
+
| QuantileStats;
|
|
350
|
+
|
|
351
|
+
// Stats for string/boolean attributes
|
|
352
|
+
categories?: AttributeCategoryItem[];
|
|
303
353
|
}
|
|
304
354
|
|
|
305
355
|
export interface VectorLayer {
|
|
@@ -325,17 +375,8 @@ export type RasterMetadataBandStats = {
|
|
|
325
375
|
|
|
326
376
|
/**
|
|
327
377
|
* Quantiles by number of buckets.
|
|
328
|
-
*
|
|
329
|
-
* Example:
|
|
330
|
-
* ```ts
|
|
331
|
-
* {
|
|
332
|
-
* // for 3 buckets, first 1/3 of items lies in range [min, 20], second 1/3 is in [20, 40], and last 1/3 is in [40, max]
|
|
333
|
-
* 3: [20, 40],
|
|
334
|
-
* 4: [20, 30, 50], for 4 buckets ...
|
|
335
|
-
* }
|
|
336
|
-
* ```
|
|
337
378
|
*/
|
|
338
|
-
quantiles?:
|
|
379
|
+
quantiles?: QuantileStats;
|
|
339
380
|
|
|
340
381
|
/**
|
|
341
382
|
* Top values by number of values.
|