@carto/api-client 0.4.0-alpha.6 → 0.4.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 +8 -0
- package/build/api/query.d.ts +1 -1
- package/build/api-client.cjs +221 -35
- package/build/api-client.cjs.map +1 -1
- package/build/api-client.modern.js +229 -51
- package/build/api-client.modern.js.map +1 -1
- package/build/models/model.d.ts +7 -1
- package/build/sources/types.d.ts +36 -41
- package/build/spatial-index.d.ts +11 -0
- package/build/utils.d.ts +1 -1
- package/build/widget-sources/types.d.ts +8 -1
- package/build/widget-sources/widget-base-source.d.ts +0 -1
- package/package.json +2 -3
- package/src/api/query.ts +1 -2
- package/src/models/model.ts +47 -24
- package/src/sources/h3-query-source.ts +7 -1
- package/src/sources/h3-table-source.ts +6 -1
- package/src/sources/quadbin-query-source.ts +6 -1
- package/src/sources/quadbin-table-source.ts +6 -1
- package/src/sources/types.ts +41 -45
- package/src/sources/vector-query-source.ts +4 -1
- package/src/sources/vector-table-source.ts +5 -1
- package/src/spatial-index.ts +119 -0
- package/src/utils.ts +1 -1
- package/src/widget-sources/types.ts +9 -1
- package/src/widget-sources/widget-base-source.ts +185 -19
package/build/models/model.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Filter, FilterLogicalOperator, MapType, QueryParameters, SpatialFilter } from '../types.js';
|
|
2
2
|
import { ModelRequestOptions } from './common.js';
|
|
3
3
|
import { ApiVersion } from '../constants.js';
|
|
4
|
+
import { SpatialDataType, SpatialFilterPolyfillMode } from '../sources/types.js';
|
|
4
5
|
/** @internalRemarks Source: @carto/react-api */
|
|
5
6
|
declare const AVAILABLE_MODELS: readonly ["category", "histogram", "formula", "pick", "timeseries", "range", "scatterplot", "table"];
|
|
6
7
|
export type Model = (typeof AVAILABLE_MODELS)[number];
|
|
@@ -14,9 +15,14 @@ export interface ModelSource {
|
|
|
14
15
|
data: string;
|
|
15
16
|
filters?: Record<string, Filter>;
|
|
16
17
|
filtersLogicalOperator?: FilterLogicalOperator;
|
|
17
|
-
geoColumn?: string;
|
|
18
18
|
spatialFilter?: SpatialFilter;
|
|
19
19
|
queryParameters?: QueryParameters;
|
|
20
|
+
spatialDataColumn?: string;
|
|
21
|
+
spatialDataType?: SpatialDataType;
|
|
22
|
+
spatialFiltersResolution?: number;
|
|
23
|
+
spatialFiltersMode?: SpatialFilterPolyfillMode;
|
|
24
|
+
/** original resolution of the spatial index data as stored in the DW */
|
|
25
|
+
dataResolution?: number;
|
|
20
26
|
}
|
|
21
27
|
/**
|
|
22
28
|
* Execute a SQL model request.
|
package/build/sources/types.d.ts
CHANGED
|
@@ -38,6 +38,30 @@ export type SourceOptionalOptions = {
|
|
|
38
38
|
* @default {@link DEFAULT_MAX_LENGTH_URL}
|
|
39
39
|
*/
|
|
40
40
|
maxLengthURL?: number;
|
|
41
|
+
/**
|
|
42
|
+
* The column name and the type of geospatial support.
|
|
43
|
+
*
|
|
44
|
+
* If not present, defaults to `'geom'` for generic queries, `'quadbin'` for Quadbin sources and `'h3'` for H3 sources.
|
|
45
|
+
*/
|
|
46
|
+
spatialDataColumn?: string;
|
|
47
|
+
/**
|
|
48
|
+
* The type of geospatial support. Defaults to `'geo'`.
|
|
49
|
+
*/
|
|
50
|
+
spatialDataType?: SpatialDataType;
|
|
51
|
+
/**
|
|
52
|
+
* Relative resolution of a tile. Higher values increase density and data size. At `tileResolution = 1`, tile geometry is
|
|
53
|
+
* quantized to a 1024x1024 grid. Increasing or decreasing the resolution will increase or decrease the dimensions of
|
|
54
|
+
* the quantization grid proportionately.
|
|
55
|
+
*
|
|
56
|
+
* Supported `tileResolution` values, with corresponding grid sizes:
|
|
57
|
+
*
|
|
58
|
+
* - 0.25: 256x256
|
|
59
|
+
* - 0.5: 512x512
|
|
60
|
+
* - 1: 1024x1024
|
|
61
|
+
* - 2: 2048x2048
|
|
62
|
+
* - 4: 4096x4096
|
|
63
|
+
*/
|
|
64
|
+
tileResolution?: TileResolution;
|
|
41
65
|
};
|
|
42
66
|
export type SourceOptions = SourceRequiredOptions & Partial<SourceOptionalOptions>;
|
|
43
67
|
export type AggregationOptions = {
|
|
@@ -55,6 +79,10 @@ export type AggregationOptions = {
|
|
|
55
79
|
* @default 6 for quadbin and 4 for h3 sources
|
|
56
80
|
*/
|
|
57
81
|
aggregationResLevel?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Original resolution of the spatial index data as stored in the DW
|
|
84
|
+
*/
|
|
85
|
+
dataResolution?: number;
|
|
58
86
|
};
|
|
59
87
|
export type FilterOptions = {
|
|
60
88
|
/**
|
|
@@ -63,28 +91,8 @@ export type FilterOptions = {
|
|
|
63
91
|
filters?: Filters;
|
|
64
92
|
};
|
|
65
93
|
export type QuerySourceOptions = {
|
|
66
|
-
/**
|
|
67
|
-
* The column name and the type of geospatial support.
|
|
68
|
-
*
|
|
69
|
-
* If not present, defaults to `'geom'` for generic queries, `'quadbin'` for Quadbin sources and `'h3'` for H3 sources.
|
|
70
|
-
*/
|
|
71
|
-
spatialDataColumn?: string;
|
|
72
|
-
/** SQL query. */
|
|
94
|
+
/** Full SQL query with query paremeter placeholders (if any). */
|
|
73
95
|
sqlQuery: string;
|
|
74
|
-
/**
|
|
75
|
-
* Relative resolution of a tile. Higher values increase density and data size. At `tileResolution = 1`, tile geometry is
|
|
76
|
-
* quantized to a 1024x1024 grid. Increasing or decreasing the resolution will increase or decrease the dimensions of
|
|
77
|
-
* the quantization grid proportionately.
|
|
78
|
-
*
|
|
79
|
-
* Supported `tileResolution` values, with corresponding grid sizes:
|
|
80
|
-
*
|
|
81
|
-
* - 0.25: 256x256
|
|
82
|
-
* - 0.5: 512x512
|
|
83
|
-
* - 1: 1024x1024
|
|
84
|
-
* - 2: 2048x2048
|
|
85
|
-
* - 4: 4096x4096
|
|
86
|
-
*/
|
|
87
|
-
tileResolution?: TileResolution;
|
|
88
96
|
/**
|
|
89
97
|
* Values for named or positional paramteres in the query.
|
|
90
98
|
*
|
|
@@ -116,26 +124,6 @@ export type TableSourceOptions = {
|
|
|
116
124
|
* Fully qualified name of table.
|
|
117
125
|
*/
|
|
118
126
|
tableName: string;
|
|
119
|
-
/**
|
|
120
|
-
* The column name and the type of geospatial support.
|
|
121
|
-
*
|
|
122
|
-
* If not present, defaults to `'geom'` for generic tables, `'quadbin'` for Quadbin sources and `'h3'` for H3 sources.
|
|
123
|
-
*/
|
|
124
|
-
spatialDataColumn?: string;
|
|
125
|
-
/**
|
|
126
|
-
* Relative resolution of a tile. Higher values increase density and data size. At `tileResolution = 1`, tile geometry is
|
|
127
|
-
* quantized to a 1024x1024 grid. Increasing or decreasing the resolution will increase or decrease the dimensions of
|
|
128
|
-
* the quantization grid proportionately.
|
|
129
|
-
*
|
|
130
|
-
* Supported `tileResolution` values, with corresponding grid sizes:
|
|
131
|
-
*
|
|
132
|
-
* - 0.25: 256x256
|
|
133
|
-
* - 0.5: 512x512
|
|
134
|
-
* - 1: 1024x1024
|
|
135
|
-
* - 2: 2048x2048
|
|
136
|
-
* - 4: 4096x4096
|
|
137
|
-
*/
|
|
138
|
-
tileResolution?: TileResolution;
|
|
139
127
|
};
|
|
140
128
|
export type TilesetSourceOptions = {
|
|
141
129
|
/**
|
|
@@ -152,6 +140,13 @@ export type ColumnsOption = {
|
|
|
152
140
|
columns?: string[];
|
|
153
141
|
};
|
|
154
142
|
export type SpatialDataType = 'geo' | 'h3' | 'quadbin';
|
|
143
|
+
/**
|
|
144
|
+
* Strategy used for covering spatial filter geometry with spatial indexes.
|
|
145
|
+
* See https://docs.carto.com/data-and-analysis/analytics-toolbox-for-bigquery/sql-reference/quadbin#quadbin_polyfill_mode
|
|
146
|
+
* or https://docs.carto.com/data-and-analysis/analytics-toolbox-for-bigquery/sql-reference/h3#h3_polyfill_mode for more information.
|
|
147
|
+
* @internalRemarks Source: cloud-native maps-api
|
|
148
|
+
* */
|
|
149
|
+
export type SpatialFilterPolyfillMode = 'center' | 'intersects' | 'contains';
|
|
155
150
|
export type TilejsonMapInstantiation = MapInstantiation & {
|
|
156
151
|
tilejson: {
|
|
157
152
|
url: string[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ModelSource } from './models/model';
|
|
2
|
+
import type { AggregationOptions } from './sources/types';
|
|
3
|
+
import type { ViewState } from './widget-sources';
|
|
4
|
+
export declare function getSpatialFiltersResolution({ source, viewState, }: {
|
|
5
|
+
source: Partial<ModelSource & AggregationOptions>;
|
|
6
|
+
viewState?: ViewState;
|
|
7
|
+
}): number | undefined;
|
|
8
|
+
export declare function getHexagonResolution(viewport: {
|
|
9
|
+
zoom: number;
|
|
10
|
+
latitude: number;
|
|
11
|
+
}, tileSize: number): number;
|
package/build/utils.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ type Row<T> = Record<string, T> | Record<string, T>[] | T[] | T;
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function normalizeObjectKeys<T, R extends Row<T>>(el: R): R;
|
|
16
16
|
/** @internalRemarks Source: @carto/react-core */
|
|
17
|
-
export declare function assert(condition: unknown, message: string):
|
|
17
|
+
export declare function assert(condition: unknown, message: string): asserts condition;
|
|
18
18
|
/**
|
|
19
19
|
* @internalRemarks Source: @carto/react-core
|
|
20
20
|
* @internal
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import { TileResolution } from '../sources/types';
|
|
1
|
+
import { SpatialFilterPolyfillMode, TileResolution } from '../sources/types';
|
|
2
2
|
import { GroupDateType, SortColumnType, SortDirection, SpatialFilter } from '../types';
|
|
3
3
|
/******************************************************************************
|
|
4
4
|
* WIDGET API REQUESTS
|
|
5
5
|
*/
|
|
6
|
+
export interface ViewState {
|
|
7
|
+
zoom: number;
|
|
8
|
+
latitude: number;
|
|
9
|
+
longitude: number;
|
|
10
|
+
}
|
|
6
11
|
/** Common options for {@link WidgetBaseSource} requests. */
|
|
7
12
|
interface BaseRequestOptions {
|
|
8
13
|
spatialFilter?: SpatialFilter;
|
|
14
|
+
spatialFiltersMode?: SpatialFilterPolyfillMode;
|
|
9
15
|
abortController?: AbortController;
|
|
10
16
|
filterOwner?: string;
|
|
17
|
+
viewState?: ViewState;
|
|
11
18
|
}
|
|
12
19
|
/** Options for {@link WidgetBaseSource#getCategories}. */
|
|
13
20
|
export interface CategoryRequestOptions extends BaseRequestOptions {
|
|
@@ -5,7 +5,6 @@ import { SourceOptions } from '../sources/index.js';
|
|
|
5
5
|
import { ApiVersion } from '../constants.js';
|
|
6
6
|
export interface WidgetBaseSourceProps extends Omit<SourceOptions, 'filters'> {
|
|
7
7
|
apiVersion?: ApiVersion;
|
|
8
|
-
geoColumn?: string;
|
|
9
8
|
filters?: Record<string, Filter>;
|
|
10
9
|
filtersLogicalOperator?: FilterLogicalOperator;
|
|
11
10
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"repository": "github:CartoDB/carto-api-client",
|
|
5
5
|
"author": "Don McCurdy <donmccurdy@carto.com>",
|
|
6
6
|
"packageManager": "yarn@4.3.1",
|
|
7
|
-
"version": "0.4.
|
|
7
|
+
"version": "0.4.1-alpha.0",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"access": "public",
|
|
@@ -98,6 +98,5 @@
|
|
|
98
98
|
"vite": "^5.2.10",
|
|
99
99
|
"vitest": "1.6.0",
|
|
100
100
|
"vue": "^3.4.27"
|
|
101
|
-
}
|
|
102
|
-
"stableVersion": "0.3.1"
|
|
101
|
+
}
|
|
103
102
|
}
|
package/src/api/query.ts
CHANGED
|
@@ -12,8 +12,7 @@ import {buildQueryUrl} from './endpoints';
|
|
|
12
12
|
import {requestWithParameters} from './request-with-parameters';
|
|
13
13
|
import {APIErrorContext} from './carto-api-error';
|
|
14
14
|
|
|
15
|
-
export type QueryOptions = SourceOptions &
|
|
16
|
-
Omit<QuerySourceOptions, 'spatialDataColumn'>;
|
|
15
|
+
export type QueryOptions = SourceOptions & QuerySourceOptions;
|
|
17
16
|
type UrlParameters = {q: string; queryParameters?: string};
|
|
18
17
|
|
|
19
18
|
export const query = async function (
|
package/src/models/model.ts
CHANGED
|
@@ -7,9 +7,10 @@ import {
|
|
|
7
7
|
SpatialFilter,
|
|
8
8
|
} from '../types.js';
|
|
9
9
|
import {$TODO} from '../types-internal.js';
|
|
10
|
-
import {assert} from '../utils.js';
|
|
10
|
+
import {assert, isPureObject} from '../utils.js';
|
|
11
11
|
import {ModelRequestOptions, makeCall} from './common.js';
|
|
12
12
|
import {ApiVersion} from '../constants.js';
|
|
13
|
+
import {SpatialDataType, SpatialFilterPolyfillMode} from '../sources/types.js';
|
|
13
14
|
|
|
14
15
|
/** @internalRemarks Source: @carto/react-api */
|
|
15
16
|
const AVAILABLE_MODELS = [
|
|
@@ -35,9 +36,14 @@ export interface ModelSource {
|
|
|
35
36
|
data: string;
|
|
36
37
|
filters?: Record<string, Filter>;
|
|
37
38
|
filtersLogicalOperator?: FilterLogicalOperator;
|
|
38
|
-
geoColumn?: string;
|
|
39
39
|
spatialFilter?: SpatialFilter;
|
|
40
40
|
queryParameters?: QueryParameters;
|
|
41
|
+
spatialDataColumn?: string;
|
|
42
|
+
spatialDataType?: SpatialDataType;
|
|
43
|
+
spatialFiltersResolution?: number;
|
|
44
|
+
spatialFiltersMode?: SpatialFilterPolyfillMode;
|
|
45
|
+
/** original resolution of the spatial index data as stored in the DW */
|
|
46
|
+
dataResolution?: number;
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
const {V3} = ApiVersion;
|
|
@@ -79,50 +85,51 @@ export function executeModel(props: {
|
|
|
79
85
|
data,
|
|
80
86
|
filters,
|
|
81
87
|
filtersLogicalOperator = 'and',
|
|
82
|
-
|
|
88
|
+
spatialDataType = 'geo',
|
|
89
|
+
spatialFiltersMode = 'intersects',
|
|
90
|
+
spatialFiltersResolution = 0,
|
|
83
91
|
} = source;
|
|
84
92
|
|
|
85
|
-
const
|
|
86
|
-
? JSON.stringify(source.queryParameters)
|
|
87
|
-
: '';
|
|
88
|
-
|
|
89
|
-
const queryParams: Record<string, string> = {
|
|
93
|
+
const queryParams: Record<string, unknown> = {
|
|
90
94
|
type,
|
|
91
95
|
client: clientId,
|
|
92
96
|
source: data,
|
|
93
|
-
params
|
|
94
|
-
queryParameters,
|
|
95
|
-
filters
|
|
97
|
+
params,
|
|
98
|
+
queryParameters: source.queryParameters || '',
|
|
99
|
+
filters,
|
|
96
100
|
filtersLogicalOperator,
|
|
97
101
|
};
|
|
98
102
|
|
|
103
|
+
const spatialDataColumn = source.spatialDataColumn || DEFAULT_GEO_COLUMN;
|
|
104
|
+
|
|
99
105
|
// Picking Model API requires 'spatialDataColumn'.
|
|
100
106
|
if (model === 'pick') {
|
|
101
|
-
queryParams.spatialDataColumn =
|
|
107
|
+
queryParams.spatialDataColumn = spatialDataColumn;
|
|
102
108
|
}
|
|
103
109
|
|
|
104
|
-
// API supports multiple filters, we apply it only to
|
|
110
|
+
// API supports multiple filters, we apply it only to spatialDataColumn
|
|
105
111
|
const spatialFilters = source.spatialFilter
|
|
106
|
-
? {[
|
|
112
|
+
? {[spatialDataColumn]: source.spatialFilter}
|
|
107
113
|
: undefined;
|
|
108
114
|
|
|
109
115
|
if (spatialFilters) {
|
|
110
|
-
queryParams.spatialFilters = JSON.stringify(spatialFilters);
|
|
116
|
+
queryParams.spatialFilters = spatialFilters; // JSON.stringify(spatialFilters);
|
|
117
|
+
queryParams.spatialDataColumn = spatialDataColumn;
|
|
118
|
+
queryParams.spatialDataType = spatialDataType;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (spatialDataType !== 'geo') {
|
|
122
|
+
if (spatialFiltersResolution > 0) {
|
|
123
|
+
queryParams.spatialFiltersResolution = spatialFiltersResolution;
|
|
124
|
+
}
|
|
125
|
+
queryParams.spatialFiltersMode = spatialFiltersMode;
|
|
111
126
|
}
|
|
112
127
|
|
|
113
128
|
const urlWithSearchParams =
|
|
114
|
-
url + '?' +
|
|
129
|
+
url + '?' + objectToURLSearchParams(queryParams).toString();
|
|
115
130
|
const isGet = urlWithSearchParams.length <= REQUEST_GET_MAX_URL_LENGTH;
|
|
116
131
|
if (isGet) {
|
|
117
132
|
url = urlWithSearchParams;
|
|
118
|
-
} else {
|
|
119
|
-
// undo the JSON.stringify, @TODO find a better pattern
|
|
120
|
-
queryParams.params = params as $TODO;
|
|
121
|
-
queryParams.filters = filters as $TODO;
|
|
122
|
-
queryParams.queryParameters = source.queryParameters as $TODO;
|
|
123
|
-
if (spatialFilters) {
|
|
124
|
-
queryParams.spatialFilters = spatialFilters as $TODO;
|
|
125
|
-
}
|
|
126
133
|
}
|
|
127
134
|
return makeCall({
|
|
128
135
|
url,
|
|
@@ -134,3 +141,19 @@ export function executeModel(props: {
|
|
|
134
141
|
},
|
|
135
142
|
});
|
|
136
143
|
}
|
|
144
|
+
|
|
145
|
+
function objectToURLSearchParams(object: Record<string, unknown>) {
|
|
146
|
+
const params = new URLSearchParams();
|
|
147
|
+
for (const key in object) {
|
|
148
|
+
if (isPureObject(object[key])) {
|
|
149
|
+
params.append(key, JSON.stringify(object[key]));
|
|
150
|
+
} else if (Array.isArray(object[key])) {
|
|
151
|
+
params.append(key, JSON.stringify(object[key]));
|
|
152
|
+
} else if (object[key] === null) {
|
|
153
|
+
params.append(key, 'null');
|
|
154
|
+
} else if (object[key] !== undefined) {
|
|
155
|
+
params.append(key, String(object[key]));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return params;
|
|
159
|
+
}
|
|
@@ -19,6 +19,7 @@ export type H3QuerySourceOptions = SourceOptions &
|
|
|
19
19
|
QuerySourceOptions &
|
|
20
20
|
AggregationOptions &
|
|
21
21
|
FilterOptions;
|
|
22
|
+
|
|
22
23
|
type UrlParameters = {
|
|
23
24
|
aggregationExp: string;
|
|
24
25
|
aggregationResLevel?: string;
|
|
@@ -59,7 +60,12 @@ export const h3QuerySource = async function (
|
|
|
59
60
|
return baseSource<UrlParameters>('query', options, urlParameters).then(
|
|
60
61
|
(result) => ({
|
|
61
62
|
...(result as TilejsonResult),
|
|
62
|
-
widgetSource: new WidgetQuerySource(
|
|
63
|
+
widgetSource: new WidgetQuerySource({
|
|
64
|
+
...options,
|
|
65
|
+
// NOTE: passing redundant spatialDataColumn here to apply the default value 'h3'
|
|
66
|
+
spatialDataColumn,
|
|
67
|
+
spatialDataType: 'h3',
|
|
68
|
+
}),
|
|
63
69
|
})
|
|
64
70
|
);
|
|
65
71
|
};
|
|
@@ -55,7 +55,12 @@ export const h3TableSource = async function (
|
|
|
55
55
|
return baseSource<UrlParameters>('table', options, urlParameters).then(
|
|
56
56
|
(result) => ({
|
|
57
57
|
...(result as TilejsonResult),
|
|
58
|
-
widgetSource: new WidgetTableSource(
|
|
58
|
+
widgetSource: new WidgetTableSource({
|
|
59
|
+
...options,
|
|
60
|
+
// NOTE: passing redundant spatialDataColumn here to apply the default value 'h3'
|
|
61
|
+
spatialDataColumn,
|
|
62
|
+
spatialDataType: 'h3',
|
|
63
|
+
}),
|
|
59
64
|
})
|
|
60
65
|
);
|
|
61
66
|
};
|
|
@@ -60,7 +60,12 @@ export const quadbinQuerySource = async function (
|
|
|
60
60
|
return baseSource<UrlParameters>('query', options, urlParameters).then(
|
|
61
61
|
(result) => ({
|
|
62
62
|
...(result as TilejsonResult),
|
|
63
|
-
widgetSource: new WidgetQuerySource(
|
|
63
|
+
widgetSource: new WidgetQuerySource({
|
|
64
|
+
...options,
|
|
65
|
+
// NOTE: passing redundant spatialDataColumn here to apply the default value 'quadbin'
|
|
66
|
+
spatialDataColumn,
|
|
67
|
+
spatialDataType: 'quadbin',
|
|
68
|
+
}),
|
|
64
69
|
})
|
|
65
70
|
);
|
|
66
71
|
};
|
|
@@ -56,7 +56,12 @@ export const quadbinTableSource = async function (
|
|
|
56
56
|
return baseSource<UrlParameters>('table', options, urlParameters).then(
|
|
57
57
|
(result) => ({
|
|
58
58
|
...(result as TilejsonResult),
|
|
59
|
-
widgetSource: new WidgetTableSource(
|
|
59
|
+
widgetSource: new WidgetTableSource({
|
|
60
|
+
...options,
|
|
61
|
+
// NOTE: passing redundant spatialDataColumn here to apply the default value 'quadbin'
|
|
62
|
+
spatialDataColumn,
|
|
63
|
+
spatialDataType: 'quadbin',
|
|
64
|
+
}),
|
|
60
65
|
})
|
|
61
66
|
);
|
|
62
67
|
};
|
package/src/sources/types.ts
CHANGED
|
@@ -47,6 +47,33 @@ export type SourceOptionalOptions = {
|
|
|
47
47
|
* @default {@link DEFAULT_MAX_LENGTH_URL}
|
|
48
48
|
*/
|
|
49
49
|
maxLengthURL?: number;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The column name and the type of geospatial support.
|
|
53
|
+
*
|
|
54
|
+
* If not present, defaults to `'geom'` for generic queries, `'quadbin'` for Quadbin sources and `'h3'` for H3 sources.
|
|
55
|
+
*/
|
|
56
|
+
spatialDataColumn?: string;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The type of geospatial support. Defaults to `'geo'`.
|
|
60
|
+
*/
|
|
61
|
+
spatialDataType?: SpatialDataType;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Relative resolution of a tile. Higher values increase density and data size. At `tileResolution = 1`, tile geometry is
|
|
65
|
+
* quantized to a 1024x1024 grid. Increasing or decreasing the resolution will increase or decrease the dimensions of
|
|
66
|
+
* the quantization grid proportionately.
|
|
67
|
+
*
|
|
68
|
+
* Supported `tileResolution` values, with corresponding grid sizes:
|
|
69
|
+
*
|
|
70
|
+
* - 0.25: 256x256
|
|
71
|
+
* - 0.5: 512x512
|
|
72
|
+
* - 1: 1024x1024
|
|
73
|
+
* - 2: 2048x2048
|
|
74
|
+
* - 4: 4096x4096
|
|
75
|
+
*/
|
|
76
|
+
tileResolution?: TileResolution;
|
|
50
77
|
};
|
|
51
78
|
|
|
52
79
|
export type SourceOptions = SourceRequiredOptions &
|
|
@@ -68,6 +95,11 @@ export type AggregationOptions = {
|
|
|
68
95
|
* @default 6 for quadbin and 4 for h3 sources
|
|
69
96
|
*/
|
|
70
97
|
aggregationResLevel?: number;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Original resolution of the spatial index data as stored in the DW
|
|
101
|
+
*/
|
|
102
|
+
dataResolution?: number;
|
|
71
103
|
};
|
|
72
104
|
|
|
73
105
|
export type FilterOptions = {
|
|
@@ -78,31 +110,9 @@ export type FilterOptions = {
|
|
|
78
110
|
};
|
|
79
111
|
|
|
80
112
|
export type QuerySourceOptions = {
|
|
81
|
-
/**
|
|
82
|
-
* The column name and the type of geospatial support.
|
|
83
|
-
*
|
|
84
|
-
* If not present, defaults to `'geom'` for generic queries, `'quadbin'` for Quadbin sources and `'h3'` for H3 sources.
|
|
85
|
-
*/
|
|
86
|
-
spatialDataColumn?: string;
|
|
87
|
-
|
|
88
|
-
/** SQL query. */
|
|
113
|
+
/** Full SQL query with query paremeter placeholders (if any). */
|
|
89
114
|
sqlQuery: string;
|
|
90
115
|
|
|
91
|
-
/**
|
|
92
|
-
* Relative resolution of a tile. Higher values increase density and data size. At `tileResolution = 1`, tile geometry is
|
|
93
|
-
* quantized to a 1024x1024 grid. Increasing or decreasing the resolution will increase or decrease the dimensions of
|
|
94
|
-
* the quantization grid proportionately.
|
|
95
|
-
*
|
|
96
|
-
* Supported `tileResolution` values, with corresponding grid sizes:
|
|
97
|
-
*
|
|
98
|
-
* - 0.25: 256x256
|
|
99
|
-
* - 0.5: 512x512
|
|
100
|
-
* - 1: 1024x1024
|
|
101
|
-
* - 2: 2048x2048
|
|
102
|
-
* - 4: 4096x4096
|
|
103
|
-
*/
|
|
104
|
-
tileResolution?: TileResolution;
|
|
105
|
-
|
|
106
116
|
/**
|
|
107
117
|
* Values for named or positional paramteres in the query.
|
|
108
118
|
*
|
|
@@ -135,28 +145,6 @@ export type TableSourceOptions = {
|
|
|
135
145
|
* Fully qualified name of table.
|
|
136
146
|
*/
|
|
137
147
|
tableName: string;
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* The column name and the type of geospatial support.
|
|
141
|
-
*
|
|
142
|
-
* If not present, defaults to `'geom'` for generic tables, `'quadbin'` for Quadbin sources and `'h3'` for H3 sources.
|
|
143
|
-
*/
|
|
144
|
-
spatialDataColumn?: string;
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Relative resolution of a tile. Higher values increase density and data size. At `tileResolution = 1`, tile geometry is
|
|
148
|
-
* quantized to a 1024x1024 grid. Increasing or decreasing the resolution will increase or decrease the dimensions of
|
|
149
|
-
* the quantization grid proportionately.
|
|
150
|
-
*
|
|
151
|
-
* Supported `tileResolution` values, with corresponding grid sizes:
|
|
152
|
-
*
|
|
153
|
-
* - 0.25: 256x256
|
|
154
|
-
* - 0.5: 512x512
|
|
155
|
-
* - 1: 1024x1024
|
|
156
|
-
* - 2: 2048x2048
|
|
157
|
-
* - 4: 4096x4096
|
|
158
|
-
*/
|
|
159
|
-
tileResolution?: TileResolution;
|
|
160
148
|
};
|
|
161
149
|
|
|
162
150
|
export type TilesetSourceOptions = {
|
|
@@ -177,6 +165,14 @@ export type ColumnsOption = {
|
|
|
177
165
|
|
|
178
166
|
export type SpatialDataType = 'geo' | 'h3' | 'quadbin';
|
|
179
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Strategy used for covering spatial filter geometry with spatial indexes.
|
|
170
|
+
* See https://docs.carto.com/data-and-analysis/analytics-toolbox-for-bigquery/sql-reference/quadbin#quadbin_polyfill_mode
|
|
171
|
+
* or https://docs.carto.com/data-and-analysis/analytics-toolbox-for-bigquery/sql-reference/h3#h3_polyfill_mode for more information.
|
|
172
|
+
* @internalRemarks Source: cloud-native maps-api
|
|
173
|
+
* */
|
|
174
|
+
export type SpatialFilterPolyfillMode = 'center' | 'intersects' | 'contains';
|
|
175
|
+
|
|
180
176
|
export type TilejsonMapInstantiation = MapInstantiation & {
|
|
181
177
|
tilejson: {url: string[]};
|
|
182
178
|
};
|
|
@@ -64,7 +64,10 @@ export const vectorQuerySource = async function (
|
|
|
64
64
|
return baseSource<UrlParameters>('query', options, urlParameters).then(
|
|
65
65
|
(result) => ({
|
|
66
66
|
...(result as TilejsonResult),
|
|
67
|
-
widgetSource: new WidgetQuerySource(
|
|
67
|
+
widgetSource: new WidgetQuerySource({
|
|
68
|
+
...options,
|
|
69
|
+
spatialDataType: 'geo',
|
|
70
|
+
}),
|
|
68
71
|
})
|
|
69
72
|
);
|
|
70
73
|
};
|
|
@@ -22,6 +22,7 @@ export type VectorTableSourceOptions = SourceOptions &
|
|
|
22
22
|
TableSourceOptions &
|
|
23
23
|
FilterOptions &
|
|
24
24
|
ColumnsOption;
|
|
25
|
+
|
|
25
26
|
type UrlParameters = {
|
|
26
27
|
columns?: string;
|
|
27
28
|
filters?: Record<string, unknown>;
|
|
@@ -58,7 +59,10 @@ export const vectorTableSource = async function (
|
|
|
58
59
|
return baseSource<UrlParameters>('table', options, urlParameters).then(
|
|
59
60
|
(result) => ({
|
|
60
61
|
...(result as TilejsonResult),
|
|
61
|
-
widgetSource: new WidgetTableSource(
|
|
62
|
+
widgetSource: new WidgetTableSource({
|
|
63
|
+
...options,
|
|
64
|
+
spatialDataType: 'geo',
|
|
65
|
+
}),
|
|
62
66
|
})
|
|
63
67
|
);
|
|
64
68
|
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_AGGREGATION_RES_LEVEL_H3,
|
|
3
|
+
DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN,
|
|
4
|
+
} from './constants-internal';
|
|
5
|
+
import type {ModelSource} from './models/model';
|
|
6
|
+
import type {AggregationOptions} from './sources/types';
|
|
7
|
+
import {assert} from './utils';
|
|
8
|
+
import type {ViewState} from './widget-sources';
|
|
9
|
+
|
|
10
|
+
const DEFAULT_TILE_SIZE = 512;
|
|
11
|
+
const QUADBIN_ZOOM_MAX_OFFSET = 4;
|
|
12
|
+
|
|
13
|
+
export function getSpatialFiltersResolution({
|
|
14
|
+
source,
|
|
15
|
+
viewState,
|
|
16
|
+
}: {
|
|
17
|
+
source: Partial<ModelSource & AggregationOptions>;
|
|
18
|
+
viewState?: ViewState;
|
|
19
|
+
}) {
|
|
20
|
+
assert(
|
|
21
|
+
viewState,
|
|
22
|
+
'viewState prop is required to compute automatic spatialFiltersResolution when using spatialFilter with spatial indexes. Either pass a `spatialFiltersResolution` prop or a `viewState` prop to avoid this error'
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const dataResolution = source.dataResolution ?? Number.MAX_VALUE;
|
|
26
|
+
|
|
27
|
+
const aggregationResLevel =
|
|
28
|
+
source.aggregationResLevel ??
|
|
29
|
+
(source.spatialDataType === 'h3'
|
|
30
|
+
? DEFAULT_AGGREGATION_RES_LEVEL_H3
|
|
31
|
+
: DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN);
|
|
32
|
+
|
|
33
|
+
const aggregationResLevelOffset = Math.max(
|
|
34
|
+
0,
|
|
35
|
+
Math.floor(aggregationResLevel)
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const currentZoomInt = Math.ceil(viewState.zoom);
|
|
39
|
+
if (source.spatialDataType === 'h3') {
|
|
40
|
+
const tileSize = DEFAULT_TILE_SIZE;
|
|
41
|
+
const maxResolutionForZoom =
|
|
42
|
+
maxH3SpatialFiltersResolutions.find(
|
|
43
|
+
([zoom]) => zoom === currentZoomInt
|
|
44
|
+
)?.[1] ?? Math.max(0, currentZoomInt - 3);
|
|
45
|
+
|
|
46
|
+
const maxSpatialFiltersResolution = maxResolutionForZoom
|
|
47
|
+
? Math.min(dataResolution, maxResolutionForZoom)
|
|
48
|
+
: dataResolution;
|
|
49
|
+
|
|
50
|
+
const hexagonResolution =
|
|
51
|
+
getHexagonResolution(viewState, tileSize) + aggregationResLevelOffset;
|
|
52
|
+
|
|
53
|
+
return Math.min(hexagonResolution, maxSpatialFiltersResolution);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (source.spatialDataType === 'quadbin') {
|
|
57
|
+
const maxResolutionForZoom = currentZoomInt + QUADBIN_ZOOM_MAX_OFFSET;
|
|
58
|
+
const maxSpatialFiltersResolution = Math.min(
|
|
59
|
+
dataResolution,
|
|
60
|
+
maxResolutionForZoom
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const quadsResolution =
|
|
64
|
+
Math.floor(viewState.zoom) + aggregationResLevelOffset;
|
|
65
|
+
return Math.min(quadsResolution, maxSpatialFiltersResolution);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const maxH3SpatialFiltersResolutions = [
|
|
72
|
+
[20, 14],
|
|
73
|
+
[19, 13],
|
|
74
|
+
[18, 12],
|
|
75
|
+
[17, 11],
|
|
76
|
+
[16, 10],
|
|
77
|
+
[15, 9],
|
|
78
|
+
[14, 8],
|
|
79
|
+
[13, 7],
|
|
80
|
+
[12, 7],
|
|
81
|
+
[11, 7],
|
|
82
|
+
[10, 6],
|
|
83
|
+
[9, 6],
|
|
84
|
+
[8, 5],
|
|
85
|
+
[7, 4],
|
|
86
|
+
[6, 4],
|
|
87
|
+
[5, 3],
|
|
88
|
+
[4, 2],
|
|
89
|
+
[3, 1],
|
|
90
|
+
[2, 1],
|
|
91
|
+
[1, 0],
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
// stolen from https://github.com/visgl/deck.gl/blob/master/modules/carto/src/layers/h3-tileset-2d.ts
|
|
95
|
+
|
|
96
|
+
// Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
|
|
97
|
+
const BIAS = 2;
|
|
98
|
+
|
|
99
|
+
// Resolution conversion function. Takes a WebMercatorViewport and returns
|
|
100
|
+
// a H3 resolution such that the screen space size of the hexagons is
|
|
101
|
+
// similar
|
|
102
|
+
export function getHexagonResolution(
|
|
103
|
+
viewport: {zoom: number; latitude: number},
|
|
104
|
+
tileSize: number
|
|
105
|
+
): number {
|
|
106
|
+
// Difference in given tile size compared to deck's internal 512px tile size,
|
|
107
|
+
// expressed as an offset to the viewport zoom.
|
|
108
|
+
const zoomOffset = Math.log2(tileSize / DEFAULT_TILE_SIZE);
|
|
109
|
+
const hexagonScaleFactor = (2 / 3) * (viewport.zoom - zoomOffset);
|
|
110
|
+
const latitudeScaleFactor = Math.log(
|
|
111
|
+
1 / Math.cos((Math.PI * viewport.latitude) / 180)
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// Clip and bias
|
|
115
|
+
return Math.max(
|
|
116
|
+
0,
|
|
117
|
+
Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS)
|
|
118
|
+
);
|
|
119
|
+
}
|