@tileflow/core 0.1.0-alpha.4 → 0.1.0-alpha.41
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/LICENSE +201 -0
- package/README.md +318 -26
- package/THIRD_PARTY_NOTICES.md +444 -0
- package/dist/3d-CzLTD0RK.d.ts +1092 -0
- package/dist/3d.d.ts +1 -0
- package/dist/3d.js +12660 -0
- package/dist/browser.d.ts +2278 -0
- package/dist/browser.js +21826 -0
- package/dist/build.d.ts +595 -0
- package/dist/build.js +29737 -0
- package/dist/capture-shot-ChPQvPyi.d.ts +291 -0
- package/dist/capture.d.ts +9 -0
- package/dist/capture.js +510 -0
- package/dist/config-reference.json +40527 -0
- package/dist/icon-composition-HUh_Lj8Z.d.ts +2516 -0
- package/dist/index.d.ts +1805 -162
- package/dist/index.js +26400 -3488
- package/dist/manifest-types-DnhSJjCM.d.ts +902 -0
- package/dist/manifest.d.ts +9 -0
- package/dist/manifest.js +449 -0
- package/dist/native-profile.d.ts +206 -0
- package/dist/native-profile.js +9339 -0
- package/dist/native.d.ts +365 -0
- package/dist/native.js +5970 -0
- package/dist/runtime.d.ts +1 -0
- package/dist/runtime.js +1445 -0
- package/dist/worker/camera-tile-worker.global.js +20 -0
- package/docs/application-tile-reading.md +86 -0
- package/docs/authoring-model.md +269 -0
- package/docs/boundary-areas-and-choropleths.md +217 -0
- package/docs/buildings-3d.md +608 -0
- package/docs/camera-moves-and-tile-cache.md +112 -0
- package/docs/capture-scenes.md +40 -0
- package/docs/capture-shots.md +173 -0
- package/docs/cartographic-defaults.md +210 -0
- package/docs/compiled-style-performance.md +286 -0
- package/docs/data-is-separate-from-design.md +610 -0
- package/docs/depth-markers.md +65 -0
- package/docs/dynamic-style-images.md +100 -0
- package/docs/globe-atmosphere.md +113 -0
- package/docs/hosted-session-authorization.md +106 -0
- package/docs/map-and-terrain-examples.md +156 -0
- package/docs/map-emphasis.md +89 -0
- package/docs/native-artifact-profile.md +152 -0
- package/docs/native-resource-urls.md +369 -0
- package/docs/nautical-marks.md +308 -0
- package/docs/public-api-and-browser-subpath.md +101 -0
- package/docs/route-drawing.md +191 -0
- package/docs/shared-visual-primitives.md +101 -0
- package/docs/street-lights.md +127 -0
- package/docs/street-sky.md +156 -0
- package/docs/style-states.md +73 -0
- package/docs/sun-and-light.md +167 -0
- package/docs/theme-transitions-and-blends.md +317 -0
- package/docs/themes-and-module-styles.md +156 -0
- package/docs/trees-3d.md +295 -0
- package/package.json +67 -8
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Boundary areas and choropleths
|
|
2
|
+
|
|
3
|
+
Tileflow's Boundaries tileset holds administrative and neighbourhood areas worldwide, from
|
|
4
|
+
countries down to districts and neighbourhoods. A map declares it with `boundaryAreas`, and
|
|
5
|
+
`boundaryChoropleth()` colors its areas from an application's values: unemployment by
|
|
6
|
+
municipality, sales by county, election results by district.
|
|
7
|
+
|
|
8
|
+
Boundaries is a separate product from World. World's border lines stay in the `boundaries` module;
|
|
9
|
+
`boundaryAreas` adds the areas themselves, each with a stable ID and official codes to join data
|
|
10
|
+
to.
|
|
11
|
+
|
|
12
|
+
## What the tileset contains
|
|
13
|
+
|
|
14
|
+
The `boundaries` family comes from OpenStreetMap under the
|
|
15
|
+
[Open Database License](https://opendatacommons.org/licenses/odbl/1-0/). Its source carries the
|
|
16
|
+
attribution `© OpenStreetMap contributors`, which MapLibre shows whenever a layer drawn from it is
|
|
17
|
+
on screen. The attribution is fixed by the family and cannot be replaced.
|
|
18
|
+
|
|
19
|
+
It has two layers, from zoom 0 to 12:
|
|
20
|
+
|
|
21
|
+
- `boundary_area`: one polygon per area and class. Its outline is the boundary line.
|
|
22
|
+
- `boundary_label`: one point per area and class, with `name` and `name:<language>`.
|
|
23
|
+
|
|
24
|
+
Polygons carry the properties needed to filter and join them:
|
|
25
|
+
|
|
26
|
+
| Property | Content |
|
|
27
|
+
| ------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| feature ID | The area's registry ID. It survives releases while the area exists. |
|
|
29
|
+
| `class` | `country`, `dependency`, `region`, `province_or_county`, `municipality`, `district` or `neighbourhood`. |
|
|
30
|
+
| `class_tier` | `primary` for the level that covers a country with that class, otherwise `secondary`. |
|
|
31
|
+
| `admin_level` | OpenStreetMap's `admin_level`. |
|
|
32
|
+
| `admin_depth` | Depth in the country's administrative chain, from 0 for the country. Neighbourhoods have none. |
|
|
33
|
+
| `ref` | The official code with its scheme, such as `ES:INE:28079` or `US:GEOID:36061`; otherwise ISO 3166-2, or ISO 3166-1 for countries. |
|
|
34
|
+
| `iso_3166_1` | The country's ISO 3166-1 alpha-2 code. |
|
|
35
|
+
|
|
36
|
+
Labels and the release's lookup table also carry `iso_3166_2`, `nuts`, `wikidata` and names.
|
|
37
|
+
|
|
38
|
+
One area can serve several classes. Berlin, for example, is a region, a district and a
|
|
39
|
+
municipality: the tileset draws it once per class, with the same ID and the `ref` of each class.
|
|
40
|
+
Filter a choropleth by class so that only one of those features is visible.
|
|
41
|
+
|
|
42
|
+
Each class appears from a fixed zoom: countries and dependencies from 0, regions from 3, provinces
|
|
43
|
+
and counties from 6 (secondary ones from 7), municipalities from 8, districts from 10 and
|
|
44
|
+
neighbourhoods from 11. `tileflowBoundaryAreasV1Schema.classMinzoom` lists them.
|
|
45
|
+
|
|
46
|
+
## Declare the source
|
|
47
|
+
|
|
48
|
+
<!-- docs:check -->
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import {defineMap} from '@tileflow/core';
|
|
52
|
+
import {streets} from '@tileflow/maps';
|
|
53
|
+
|
|
54
|
+
export default defineMap({
|
|
55
|
+
id: 'municipal-indicators',
|
|
56
|
+
version: 1,
|
|
57
|
+
extends: streets,
|
|
58
|
+
boundaryAreas: {family: 'boundaries'},
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The compiled style gains the vector source `tileflow-boundaries`, which reads
|
|
63
|
+
`https://api.tileflow.dev/tiles/boundaries/tiles.json` (or the same path under the API base URL
|
|
64
|
+
passed to the compiler). `url` replaces it with a compatible TileJSON or a `pmtiles://` archive,
|
|
65
|
+
such as a local copy for offline development; the attribution stays the same. `false` removes
|
|
66
|
+
Boundaries inherited from a parent map.
|
|
67
|
+
|
|
68
|
+
## Color areas from values in the style
|
|
69
|
+
|
|
70
|
+
`values` compiles rows into the style. Rows join by `id` (the registry ID), `ref` or `iso_3166_1`,
|
|
71
|
+
the keys the polygons carry. This example colors municipalities in the Community of Madrid by
|
|
72
|
+
their INE code, the code Spanish statistics publish:
|
|
73
|
+
|
|
74
|
+
<!-- docs:check -->
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import {boundaryChoropleth, choroplethScale, defineMap} from '@tileflow/core';
|
|
78
|
+
import {streets} from '@tileflow/maps';
|
|
79
|
+
|
|
80
|
+
// Rows as a statistics office publishes them: an INE municipality code and a rate.
|
|
81
|
+
const unemployment = [
|
|
82
|
+
{ine: '28079', rate: 9.8},
|
|
83
|
+
{ine: '28005', rate: 12.4},
|
|
84
|
+
{ine: '28006', rate: 6.1},
|
|
85
|
+
{ine: '28058', rate: 13.7},
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
export default defineMap({
|
|
89
|
+
id: 'madrid-unemployment',
|
|
90
|
+
version: 1,
|
|
91
|
+
extends: streets,
|
|
92
|
+
boundaryAreas: {family: 'boundaries'},
|
|
93
|
+
overlays: {
|
|
94
|
+
unemployment: boundaryChoropleth({
|
|
95
|
+
id: 'unemployment',
|
|
96
|
+
classes: ['municipality'],
|
|
97
|
+
countries: ['ES'],
|
|
98
|
+
scale: choroplethScale.step('#fef0d9', [
|
|
99
|
+
[8, '#fdcc8a'],
|
|
100
|
+
[10, '#fc8d59'],
|
|
101
|
+
[12, '#d7301f'],
|
|
102
|
+
]),
|
|
103
|
+
missingColor: '#d9d9d9',
|
|
104
|
+
outline: {color: '#ffffff', width: 0.75},
|
|
105
|
+
values: {
|
|
106
|
+
joinBy: 'ref',
|
|
107
|
+
rows: unemployment.map(({ine, rate}) => ({key: `ES:INE:${ine}`, value: rate})),
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Municipalities under 8 % are pale, those from 12 % dark red, and municipalities without a row
|
|
115
|
+
gray. The overlay adds the layers `unemployment-fill` and `unemployment-outline` below the
|
|
116
|
+
basemap's labels. Their minimum zoom defaults to the first zoom of the selected classes, here 8.
|
|
117
|
+
|
|
118
|
+
A choropleth accepts these options:
|
|
119
|
+
|
|
120
|
+
- `classes` (required), `tiers` and `countries` filter the areas;
|
|
121
|
+
- `minzoom` and `maxzoom` limit the zooms;
|
|
122
|
+
- `scale` sets the colors, `missingColor` the color of areas without a value (transparent by
|
|
123
|
+
default) and `opacity` the fill opacity (0.8 by default);
|
|
124
|
+
- `outline` draws the boundary lines;
|
|
125
|
+
- `placement` positions the layers among the basemap's like any overlay (`below-labels` by
|
|
126
|
+
default).
|
|
127
|
+
|
|
128
|
+
## Choose a color scale
|
|
129
|
+
|
|
130
|
+
`choroplethScale` builds validated scales:
|
|
131
|
+
|
|
132
|
+
- `step(base, stops)`: `base` below the first threshold, then one color from each threshold on;
|
|
133
|
+
- `linear(stops)`: colors interpolated between stops and clamped beyond them;
|
|
134
|
+
- `categories({value: color})`: one color per string value.
|
|
135
|
+
|
|
136
|
+
Stops are `[value, color]` pairs in increasing order, at most 64. A numeric scale gives
|
|
137
|
+
`missingColor` to any area whose value is not a number; a category scale gives it to unknown
|
|
138
|
+
categories. `choroplethColorExpression(scale, input, missingColor)` returns the same MapLibre
|
|
139
|
+
expression for any input, for use in layers of your own.
|
|
140
|
+
|
|
141
|
+
## Update values at run time with feature-state
|
|
142
|
+
|
|
143
|
+
Omit `values` and the choropleth reads the feature-state key `value` (or `state`). Set it from the
|
|
144
|
+
application with `createBoundaryFeatureState` from `@tileflow/core/browser` and the map instance:
|
|
145
|
+
|
|
146
|
+
<!-- docs:check -->
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
import {createBoundaryFeatureState, type TileflowFeatureStateMap} from '@tileflow/core/browser';
|
|
150
|
+
|
|
151
|
+
// A MapLibre map, such as the one `<Map onLoad>` passes in React.
|
|
152
|
+
export function showRates(map: TileflowFeatureStateMap, rates: ReadonlyMap<number, number>) {
|
|
153
|
+
const state = createBoundaryFeatureState(map);
|
|
154
|
+
state.set({joinBy: 'id', rows: [...rates].map(([key, value]) => ({key, value}))});
|
|
155
|
+
return state;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`set` replaces the previous values and removes those no longer present. Values survive a style
|
|
160
|
+
reload, such as a theme change: the controller sets them again once the source is back. `clear`
|
|
161
|
+
removes them, and `dispose` also stops following the map. `labels: true` also sets the values on
|
|
162
|
+
`boundary_label`, for labels styled by value.
|
|
163
|
+
|
|
164
|
+
Feature-state is keyed by the source's feature ID, the registry ID by default. To key it by
|
|
165
|
+
official code instead, declare `boundaryAreas: {family: 'boundaries', promoteId: 'ref'}` and set
|
|
166
|
+
rows with `joinBy: 'ref'`. A map that promotes `ref` cannot also join values by `id`; compilation
|
|
167
|
+
fails with `TF_BOUNDARY_CHOROPLETH_JOIN`.
|
|
168
|
+
|
|
169
|
+
In React, `useBoundaryFeatureState(map, values, options)` from `@tileflow/react` keeps
|
|
170
|
+
feature-state equal to `values`; see the
|
|
171
|
+
[React README](https://github.com/tileflow/tileflow-sdk/blob/main/packages/react/README.md).
|
|
172
|
+
|
|
173
|
+
## Join by codes the polygons do not carry
|
|
174
|
+
|
|
175
|
+
Rows keyed by `iso_3166_2`, `nuts` or `wikidata`, or keyed by `ref` while feature-state uses
|
|
176
|
+
registry IDs, go through the release's lookup table, `boundaries-lookup.csv.gz`, with one row per
|
|
177
|
+
area and class. Decompress it and parse it with `parseBoundaryLookupCsv`; `joinBoundaryRows`
|
|
178
|
+
then re-keys the rows:
|
|
179
|
+
|
|
180
|
+
<!-- docs:check -->
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
import {createBoundaryLookup, joinBoundaryRows, parseBoundaryLookupCsv} from '@tileflow/core';
|
|
184
|
+
|
|
185
|
+
export async function regionsByNuts(csvGzipUrl: string, rows: {nuts: string; value: number}[]) {
|
|
186
|
+
const response = await fetch(csvGzipUrl);
|
|
187
|
+
if (!response.ok || !response.body) throw new Error(`Lookup table failed: ${response.status}`);
|
|
188
|
+
const text = await new Response(
|
|
189
|
+
response.body.pipeThrough(new DecompressionStream('gzip')),
|
|
190
|
+
).text();
|
|
191
|
+
const lookup = createBoundaryLookup(parseBoundaryLookupCsv(text));
|
|
192
|
+
const joined = joinBoundaryRows(
|
|
193
|
+
rows.map(({nuts, value}) => ({key: nuts, value})),
|
|
194
|
+
{joinBy: 'nuts', lookup, classes: ['region']},
|
|
195
|
+
);
|
|
196
|
+
if (joined.unmatched.length > 0) console.warn('Unmatched NUTS codes', joined.unmatched);
|
|
197
|
+
return joined;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The result has the same `{joinBy, rows}` shape that `values` and `set` accept, keyed by `id` or,
|
|
202
|
+
with `to: 'ref'`, by `ref`. It also lists the keys it could not use:
|
|
203
|
+
|
|
204
|
+
- `unmatched`: keys no area has;
|
|
205
|
+
- `ambiguous`: keys shared by more than one area, which are left out;
|
|
206
|
+
- `duplicates`: keys repeated in the rows, where the last row wins.
|
|
207
|
+
|
|
208
|
+
ISO 3166, NUTS and Wikidata codes are compared upper-cased; `ref` is compared as written, so a
|
|
209
|
+
customer's bare INE code needs its `ES:INE:` prefix.
|
|
210
|
+
|
|
211
|
+
## Limits
|
|
212
|
+
|
|
213
|
+
- Values compiled into the style grow it with every row. Use feature-state for large or changing
|
|
214
|
+
data.
|
|
215
|
+
- The `boundaries-official` family, with one official source per country and level, is not yet
|
|
216
|
+
available.
|
|
217
|
+
- Tile URLs and the lookup table do not establish redistribution rights beyond the ODbL.
|