@carto/api-client 0.5.15-alpha.raster-1 → 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/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-1",
11
+ "version": "0.5.15-alpha.raster-2",
12
12
  "license": "MIT",
13
13
  "publishConfig": {
14
14
  "access": "public"
@@ -15,3 +15,4 @@ export type {
15
15
  export * from './basemap.js';
16
16
  export * from './layer-map.js';
17
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 {
@@ -212,9 +213,20 @@ export function getLayerProps(
212
213
 
213
214
  function domainFromAttribute(
214
215
  attribute: Attribute,
215
- scaleType: ScaleType,
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];
@@ -256,7 +268,7 @@ 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) {
@@ -350,19 +362,22 @@ export function calculateLayerScale(
350
362
  ) {
351
363
  let domain: string[] | number[] = [];
352
364
  let scaleColor: string[] = [];
365
+ const {colors} = range;
353
366
 
354
- if (scaleType !== 'identity') {
355
- const {colorMap, colors} = range;
356
-
357
- if (Array.isArray(colorMap)) {
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;
358
373
  colorMap.forEach(([value, color]) => {
359
374
  (domain as string[]).push(value);
360
375
  scaleColor.push(color);
361
376
  });
362
- } else {
363
- domain = calculateDomain(data, name, scaleType, colors.length);
364
- scaleColor = colors;
365
377
  }
378
+ } else if (scaleType !== 'identity') {
379
+ domain = calculateDomain(data, name, scaleType, colors.length);
380
+ scaleColor = colors;
366
381
 
367
382
  if (scaleType === 'ordinal') {
368
383
  domain = domain.slice(0, scaleColor.length);
@@ -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
- if (colorRange.colorMap) {
381
- return colorRange.colorMap?.map(([value]) => value) || [];
382
- }
383
- return [band.stats.min, band.stats.max];
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) || [];
@@ -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