isard 1.3.0 → 1.5.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.
Files changed (97) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/README.md +23 -6
  3. package/dist/basemap/basemaps.js +1 -0
  4. package/dist/basemap/basemaps.js.map +1 -1
  5. package/dist/basemap/vectortiles/context.d.ts +43 -0
  6. package/dist/basemap/vectortiles/context.js +6 -0
  7. package/dist/basemap/vectortiles/context.js.map +1 -0
  8. package/dist/basemap/vectortiles/extrusions.d.ts +11 -0
  9. package/dist/basemap/vectortiles/extrusions.js +46 -0
  10. package/dist/basemap/vectortiles/extrusions.js.map +1 -0
  11. package/dist/basemap/vectortiles/labels.d.ts +22 -0
  12. package/dist/basemap/vectortiles/labels.js +225 -0
  13. package/dist/basemap/vectortiles/labels.js.map +1 -0
  14. package/dist/basemap/vectortiles/requests.d.ts +24 -0
  15. package/dist/basemap/vectortiles/requests.js +61 -0
  16. package/dist/basemap/vectortiles/requests.js.map +1 -0
  17. package/dist/basemap/vectortiles/street-wind.d.ts +19 -0
  18. package/dist/basemap/vectortiles/street-wind.js +133 -0
  19. package/dist/basemap/vectortiles/street-wind.js.map +1 -0
  20. package/dist/basemap/vectortiles/style.d.ts +47 -0
  21. package/dist/basemap/vectortiles/style.js +141 -0
  22. package/dist/basemap/vectortiles/style.js.map +1 -0
  23. package/dist/basemap/vectortiles/tiles.d.ts +34 -0
  24. package/dist/basemap/vectortiles/tiles.js +62 -0
  25. package/dist/basemap/vectortiles/tiles.js.map +1 -0
  26. package/dist/basemap/vectortiles/trees.d.ts +19 -0
  27. package/dist/basemap/vectortiles/trees.js +93 -0
  28. package/dist/basemap/vectortiles/trees.js.map +1 -0
  29. package/dist/basemap/vectortiles/vectors.d.ts +20 -0
  30. package/dist/basemap/vectortiles/vectors.js +167 -0
  31. package/dist/basemap/vectortiles/vectors.js.map +1 -0
  32. package/dist/basemap/vectortiles.d.ts +34 -75
  33. package/dist/basemap/vectortiles.js +70 -654
  34. package/dist/basemap/vectortiles.js.map +1 -1
  35. package/dist/basemap/workerpool.js +33 -5
  36. package/dist/basemap/workerpool.js.map +1 -1
  37. package/dist/basemap.worker.js +2 -2
  38. package/dist/basemap.worker.js.map +8 -5
  39. package/dist/bind/layers.js +10 -0
  40. package/dist/bind/layers.js.map +1 -1
  41. package/dist/decoder.worker.js +5 -4
  42. package/dist/decoder.worker.js.map +8 -6
  43. package/dist/engine/decoders.d.ts +4 -8
  44. package/dist/engine/decoders.js +29 -2
  45. package/dist/engine/decoders.js.map +1 -1
  46. package/dist/engine-loader.d.ts +4 -1
  47. package/dist/engine-loader.js +9 -0
  48. package/dist/engine-loader.js.map +1 -1
  49. package/dist/grid-module.d.ts +44 -0
  50. package/dist/grid-module.js +63 -0
  51. package/dist/grid-module.js.map +1 -0
  52. package/dist/grids.d.ts +51 -0
  53. package/dist/grids.js +88 -0
  54. package/dist/grids.js.map +1 -0
  55. package/dist/index.d.ts +10 -1
  56. package/dist/index.js +3 -1
  57. package/dist/index.js.map +1 -1
  58. package/dist/isard_bg.wasm +0 -0
  59. package/dist/isard_core_bg.wasm +0 -0
  60. package/dist/isard_grid_bg.wasm +0 -0
  61. package/dist/layers/flow.d.ts +118 -0
  62. package/dist/layers/flow.js +263 -0
  63. package/dist/layers/flow.js.map +1 -0
  64. package/dist/layers/panoramas.d.ts +2 -0
  65. package/dist/layers/panoramas.js +27 -6
  66. package/dist/layers/panoramas.js.map +1 -1
  67. package/dist/layers/symbols.d.ts +2 -0
  68. package/dist/layers/symbols.js +2 -1
  69. package/dist/layers/symbols.js.map +1 -1
  70. package/dist/map/layer-spec.d.ts +4 -1
  71. package/dist/map/layer-spec.js +2 -0
  72. package/dist/map/layer-spec.js.map +1 -1
  73. package/dist/map/workers.d.ts +4 -0
  74. package/dist/map/workers.js +38 -0
  75. package/dist/map/workers.js.map +1 -1
  76. package/dist/map.d.ts +14 -0
  77. package/dist/map.js +19 -1
  78. package/dist/map.js.map +1 -1
  79. package/dist/react/Layer.d.ts +2 -0
  80. package/dist/react/Layer.js.map +1 -1
  81. package/dist/types.d.ts +7 -3
  82. package/dist/types.js.map +1 -1
  83. package/dist/util/read.d.ts +4 -0
  84. package/dist/util/read.js +28 -0
  85. package/dist/util/read.js.map +1 -0
  86. package/dist/wasm/isard.d.ts +55 -0
  87. package/dist/wasm/isard.js +112 -1
  88. package/dist/wasm/isard_core.d.ts +55 -0
  89. package/dist/wasm/isard_core.js +112 -1
  90. package/dist/wasm/isard_grid.d.ts +101 -0
  91. package/dist/wasm/isard_grid.js +375 -0
  92. package/dist/workers/basemap/street.d.ts +19 -0
  93. package/dist/workers/basemap.worker.d.ts +21 -0
  94. package/dist/workers/basemap.worker.js +23 -4
  95. package/dist/workers/basemap.worker.js.map +1 -1
  96. package/package.json +2 -1
  97. package/vite.js +3 -2
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The tiles of the vector layers (`VectorTiles`): the tiles around the view, their keys, the order they are asked
3
+ * for in, and the defaults the layers share.
4
+ */
5
+ import { mercatorX, mercatorY } from "../../util/geo.js";
6
+ /** Street level: the zoom the extrusions, the streets' wind and the trees start at by default */
7
+ export const STREET_ZOOM = 15;
8
+ /** Tiles of a layer that follows the view, by default (the extrusions', the labels') */
9
+ export const MAX_TILES = 36;
10
+ /** Tiles nearest to the center asked for first: the others wait (for the raster tiles, for instance) */
11
+ export const NEAR_TILES = 4;
12
+ /** Milliseconds between two updates of the tiles of a layer while the camera moves */
13
+ export const VECTOR_MOVE_REFRESH_MS = 250;
14
+ /** A tile's key, `z/x/y` */
15
+ export const tileKey = (z, x, y) => `${z}/${x}/${y}`;
16
+ /** The tile of a key `z/x/y` (zeros for the numbers it lacks) */
17
+ export const parseTileKey = (key) => {
18
+ const [z = 0, x = 0, y = 0] = key.split('/').map(Number);
19
+ return [z, x, y];
20
+ };
21
+ /** The tiles of the engine's flat list of z, x, y triples */
22
+ export const tileTriples = (list) => Array.from({ length: Math.floor(list.length / 3) }, (_, i) => [list[i * 3] ?? 0, list[i * 3 + 1] ?? 0, list[i * 3 + 2] ?? 0]);
23
+ /** The priority of the `index`th tile asked for, the nearest first: `near` for the first `NEAR_TILES`, `far` after */
24
+ export const nearPriority = (index, near = 'auto', far = 'low') => index < NEAR_TILES ? near : far;
25
+ /** A tile's column at level `z` brought back into the world (the columns past the antimeridian are those of its other
26
+ * side) */
27
+ export const wrapColumn = (x, z) => {
28
+ const n = 2 ** z;
29
+ return ((x % n) + n) % n;
30
+ };
31
+ /**
32
+ * The tiles of level `z` in view, within a window around the center (a tilted view's bounds reach far), the
33
+ * `maxTiles` nearest to the center first. Across the antimeridian, the window's columns go on round the world (the
34
+ * view's bounds, which stop at ±180°, no longer limit them)
35
+ */
36
+ export const tilesAround = (map, camera, z, maxTiles) => {
37
+ const n = 2 ** z;
38
+ const [west, south, east, north] = map.getBounds();
39
+ const tx = (lon) => Math.floor(mercatorX(lon) * n);
40
+ const ty = (lat) => Math.floor(mercatorY(lat) * n);
41
+ const [cx, cy] = [mercatorX(camera.center[0]) * n, mercatorY(camera.center[1]) * n];
42
+ const reach = Math.ceil(Math.sqrt(maxTiles)) + 2;
43
+ const [left, right] = [Math.floor(cx) - reach, Math.floor(cx) + reach];
44
+ const across = left < 0 || right > n - 1;
45
+ const [x0, x1] = across ? [left, right] : [Math.max(left, tx(west)), Math.min(right, tx(east))];
46
+ const [y0, y1] = [Math.max(0, ty(north), Math.floor(cy) - reach), Math.min(n - 1, ty(south), Math.floor(cy) + reach)];
47
+ const wanted = Array.from({ length: Math.max(0, y1 - y0 + 1) }, (_, j) => y0 + j).flatMap((y) => Array.from({ length: Math.max(0, x1 - x0 + 1) }, (_, i) => [x0 + i, y]));
48
+ wanted.sort((a, b) => Math.hypot(a[0] + 0.5 - cx, a[1] + 0.5 - cy) - Math.hypot(b[0] + 0.5 - cx, b[1] + 0.5 - cy));
49
+ // Each tile once (at a low level, the window can go round the whole world)
50
+ const seen = new Set();
51
+ return wanted
52
+ .map(([x, y]) => [wrapColumn(x, z), y])
53
+ .filter(([x, y]) => {
54
+ const k = `${x}/${y}`;
55
+ if (seen.has(k))
56
+ return false;
57
+ seen.add(k);
58
+ return true;
59
+ })
60
+ .slice(0, maxTiles);
61
+ };
62
+ //# sourceMappingURL=tiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiles.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/tiles.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The tiles of the vector layers (`VectorTiles`): the tiles around the view, their keys, the order they are asked\n * for in, and the defaults the layers share.\n */\n\nimport type { GeoMap } from '../../map.ts';\nimport { mercatorX, mercatorY } from '../../util/geo.ts';\nimport type { Camera } from '../../wasm/isard.js';\nimport type { Priority } from '../../workers/basemap.worker.ts';\n\n/** A tile: its level and its column and row at that level */\nexport type TileTriple = [z: number, x: number, y: number];\n\n/** Street level: the zoom the extrusions, the streets' wind and the trees start at by default */\nexport const STREET_ZOOM = 15;\n\n/** Tiles of a layer that follows the view, by default (the extrusions', the labels') */\nexport const MAX_TILES = 36;\n\n/** Tiles nearest to the center asked for first: the others wait (for the raster tiles, for instance) */\nexport const NEAR_TILES = 4;\n\n/** Milliseconds between two updates of the tiles of a layer while the camera moves */\nexport const VECTOR_MOVE_REFRESH_MS = 250;\n\n/** A tile's key, `z/x/y` */\nexport const tileKey = (z: number, x: number, y: number): string => `${z}/${x}/${y}`;\n\n/** The tile of a key `z/x/y` (zeros for the numbers it lacks) */\nexport const parseTileKey = (key: string): TileTriple => {\n const [z = 0, x = 0, y = 0] = key.split('/').map(Number);\n\n return [z, x, y];\n};\n\n/** The tiles of the engine's flat list of z, x, y triples */\nexport const tileTriples = (list: Uint32Array): TileTriple[] =>\n Array.from(\n { length: Math.floor(list.length / 3) },\n (_, i): TileTriple => [list[i * 3] ?? 0, list[i * 3 + 1] ?? 0, list[i * 3 + 2] ?? 0],\n );\n\n/** The priority of the `index`th tile asked for, the nearest first: `near` for the first `NEAR_TILES`, `far` after */\nexport const nearPriority = (index: number, near: Priority = 'auto', far: Priority = 'low'): Priority =>\n index < NEAR_TILES ? near : far;\n\n/** A tile's column at level `z` brought back into the world (the columns past the antimeridian are those of its other\n * side) */\nexport const wrapColumn = (x: number, z: number): number => {\n const n = 2 ** z;\n\n return ((x % n) + n) % n;\n};\n\n/**\n * The tiles of level `z` in view, within a window around the center (a tilted view's bounds reach far), the\n * `maxTiles` nearest to the center first. Across the antimeridian, the window's columns go on round the world (the\n * view's bounds, which stop at ±180°, no longer limit them)\n */\nexport const tilesAround = (map: GeoMap, camera: Camera, z: number, maxTiles: number): [x: number, y: number][] => {\n const n = 2 ** z;\n const [west, south, east, north] = map.getBounds();\n const tx = (lon: number) => Math.floor(mercatorX(lon) * n);\n const ty = (lat: number) => Math.floor(mercatorY(lat) * n);\n const [cx, cy] = [mercatorX(camera.center[0]) * n, mercatorY(camera.center[1]) * n];\n const reach = Math.ceil(Math.sqrt(maxTiles)) + 2;\n const [left, right] = [Math.floor(cx) - reach, Math.floor(cx) + reach];\n const across = left < 0 || right > n - 1;\n const [x0, x1] = across ? [left, right] : [Math.max(left, tx(west)), Math.min(right, tx(east))];\n const [y0, y1] = [Math.max(0, ty(north), Math.floor(cy) - reach), Math.min(n - 1, ty(south), Math.floor(cy) + reach)];\n const wanted = Array.from({ length: Math.max(0, y1 - y0 + 1) }, (_, j) => y0 + j).flatMap((y) =>\n Array.from({ length: Math.max(0, x1 - x0 + 1) }, (_, i): [number, number] => [x0 + i, y]),\n );\n\n wanted.sort((a, b) => Math.hypot(a[0] + 0.5 - cx, a[1] + 0.5 - cy) - Math.hypot(b[0] + 0.5 - cx, b[1] + 0.5 - cy));\n\n // Each tile once (at a low level, the window can go round the whole world)\n const seen = new Set<string>();\n\n return wanted\n .map(([x, y]): [number, number] => [wrapColumn(x, z), y])\n .filter(([x, y]) => {\n const k = `${x}/${y}`;\n\n if (seen.has(k)) return false;\n seen.add(k);\n\n return true;\n })\n .slice(0, maxTiles);\n};\n"]}
@@ -0,0 +1,19 @@
1
+ /** The trees of a vector basemap (`VectorTiles.trees`): 3D models scattered by the workers over its woods and grass */
2
+ import type { Layer, ModelLayer } from '../../layers/layers.ts';
3
+ import { type TreeColors } from '../trees.ts';
4
+ import type { StyleLayer } from '../vectorstyle.ts';
5
+ import type { VectorTilesContext } from './context.ts';
6
+ /** The options of `VectorTiles.trees` */
7
+ export interface TreesOptions {
8
+ layers?: (layer: StyleLayer) => boolean;
9
+ spacing?: number | ((layer: StyleLayer) => number);
10
+ minZoom?: number;
11
+ maxTiles?: number;
12
+ maxTrees?: number;
13
+ maxInstances?: number;
14
+ colors?: Partial<TreeColors>;
15
+ url?: string;
16
+ data?: ArrayBuffer | ArrayBufferView<ArrayBuffer>;
17
+ before?: Layer;
18
+ }
19
+ export declare const trees: (context: VectorTilesContext, options?: TreesOptions) => ModelLayer;
@@ -0,0 +1,93 @@
1
+ /** The trees of a vector basemap (`VectorTiles.trees`): 3D models scattered by the workers over its woods and grass */
2
+ import { isWoodland, TREE_NUMBERS, treeModel, treeSpacing } from "../trees.js";
3
+ import { TileRequests } from "./requests.js";
4
+ import { nearPriority, STREET_ZOOM, tileKey, tilesAround } from "./tiles.js";
5
+ /** Metres around the view's center where every tree is drawn at zoom 16 (twice as far a zoom level out) */
6
+ const TREES_NEAR_METRES = 350;
7
+ /** Metres in a degree of latitude (and of longitude at the equator), near enough for the trees' distances */
8
+ const METRES_PER_DEGREE = 111320;
9
+ export const trees = (context, options = {}) => {
10
+ const { map } = context;
11
+ const { layers = isWoodland, spacing = treeSpacing, minZoom = STREET_ZOOM, maxTiles = 9, maxTrees = 30000, maxInstances = 25000, } = options;
12
+ const model = options.url ? { url: options.url } : { data: options.data ?? treeModel(options.colors) };
13
+ const layer = map.addModels({
14
+ ...model,
15
+ instances: [],
16
+ ...(options.before ? { before: options.before } : {}),
17
+ });
18
+ const renderer = context.renderer((l) => l.type === 'fill' && layers(l), []);
19
+ renderer.catch(() => undefined);
20
+ context.layers.push(layer);
21
+ /** The tiles held or asked for, by key, and the trees of those that came */
22
+ const requests = new TileRequests();
23
+ const found = new Map();
24
+ /** The trees drawn to the engine (longitude, latitude, altitude, heading, pitch, roll, scale each): all of them
25
+ * near the view's center, past `near` metres those of a rank under (near / distance)², at most `maxInstances` */
26
+ const send = () => {
27
+ const { center, zoom } = map.getCamera();
28
+ const near = TREES_NEAR_METRES * 2 ** (16 - zoom);
29
+ const cos = Math.cos((center[1] * Math.PI) / 180);
30
+ const chosen = [];
31
+ found.forEach((t) => {
32
+ for (let i = 0; i < t.length / TREE_NUMBERS; i += 1) {
33
+ const dx = ((t[i * TREE_NUMBERS] ?? 0) - center[0]) * METRES_PER_DEGREE * cos;
34
+ const dy = ((t[i * TREE_NUMBERS + 1] ?? 0) - center[1]) * METRES_PER_DEGREE;
35
+ const far = (dx * dx + dy * dy) / (near * near);
36
+ const score = (t[i * TREE_NUMBERS + 4] ?? 0) * Math.max(1, far);
37
+ if (score < 1)
38
+ chosen.push([score, t, i]);
39
+ }
40
+ });
41
+ if (chosen.length > maxInstances)
42
+ chosen.sort((a, b) => a[0] - b[0]).splice(maxInstances);
43
+ const out = new Float64Array(chosen.length * 7);
44
+ chosen.forEach(([, t, i], k) => {
45
+ const at = i * TREE_NUMBERS;
46
+ out.set([t[at] ?? 0, t[at + 1] ?? 0, 0, t[at + 3] ?? 0, 0, 0, t[at + 2] ?? 1], k * 7);
47
+ });
48
+ layer.setInstanceNumbers(out);
49
+ };
50
+ const update = async () => {
51
+ if (context.destroyed())
52
+ return;
53
+ const { key, maxzoom, layers: list } = await renderer;
54
+ const camera = map.getCamera();
55
+ const z = maxzoom;
56
+ const wanted = camera.zoom < minZoom ? [] : tilesAround(map, camera, z, maxTiles);
57
+ const keys = new Set(wanted.map(([x, y]) => tileKey(z, x, y)));
58
+ const metres = list.map((l) => (typeof spacing === 'number' ? spacing : spacing(l)));
59
+ const dropped = requests.keys().filter((k) => !keys.has(k));
60
+ // Out of view: dropped, or no longer asked for
61
+ dropped.forEach((k) => {
62
+ requests.drop(k);
63
+ found.delete(k);
64
+ });
65
+ // Dense around the new center
66
+ send();
67
+ wanted.forEach(([x, y], index) => {
68
+ const k = tileKey(z, x, y);
69
+ if (requests.has(k))
70
+ return;
71
+ const work = {
72
+ type: 'trees',
73
+ key,
74
+ z,
75
+ x,
76
+ y,
77
+ spacing: metres,
78
+ maxTrees,
79
+ priority: nearPriority(index),
80
+ };
81
+ requests.ask(k, (signal) => context.request(z, x, y, work, signal), (r) => {
82
+ if (!('trees' in r))
83
+ return;
84
+ found.set(k, r.trees);
85
+ send();
86
+ });
87
+ });
88
+ };
89
+ // While the camera moves, the trees drawn follow its center (dense near it)
90
+ context.followView(update, requests, send);
91
+ return layer;
92
+ };
93
+ //# sourceMappingURL=trees.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trees.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/trees.ts"],"names":[],"mappings":"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","sourcesContent":["/** The trees of a vector basemap (`VectorTiles.trees`): 3D models scattered by the workers over its woods and grass */\n\nimport type { Layer, ModelLayer } from '../../layers/layers.ts';\nimport type { BasemapWork } from '../../workers/basemap.worker.ts';\nimport { isWoodland, TREE_NUMBERS, type TreeColors, treeModel, treeSpacing } from '../trees.ts';\nimport type { StyleLayer } from '../vectorstyle.ts';\nimport type { VectorTilesContext } from './context.ts';\nimport { TileRequests } from './requests.ts';\nimport { nearPriority, STREET_ZOOM, tileKey, tilesAround } from './tiles.ts';\n\n/** Metres around the view's center where every tree is drawn at zoom 16 (twice as far a zoom level out) */\nconst TREES_NEAR_METRES = 350;\n\n/** Metres in a degree of latitude (and of longitude at the equator), near enough for the trees' distances */\nconst METRES_PER_DEGREE = 111320;\n\n/** The options of `VectorTiles.trees` */\nexport interface TreesOptions {\n layers?: (layer: StyleLayer) => boolean;\n spacing?: number | ((layer: StyleLayer) => number);\n minZoom?: number;\n maxTiles?: number;\n maxTrees?: number;\n maxInstances?: number;\n colors?: Partial<TreeColors>;\n url?: string;\n data?: ArrayBuffer | ArrayBufferView<ArrayBuffer>;\n before?: Layer;\n}\n\nexport const trees = (context: VectorTilesContext, options: TreesOptions = {}): ModelLayer => {\n const { map } = context;\n const {\n layers = isWoodland,\n spacing = treeSpacing,\n minZoom = STREET_ZOOM,\n maxTiles = 9,\n maxTrees = 30000,\n maxInstances = 25000,\n } = options;\n const model = options.url ? { url: options.url } : { data: options.data ?? treeModel(options.colors) };\n const layer = map.addModels({\n ...model,\n instances: [],\n ...(options.before ? { before: options.before } : {}),\n });\n const renderer = context.renderer((l) => l.type === 'fill' && layers(l), []);\n\n renderer.catch(() => undefined);\n context.layers.push(layer);\n\n /** The tiles held or asked for, by key, and the trees of those that came */\n const requests = new TileRequests();\n const found = new Map<string, Float64Array>();\n /** The trees drawn to the engine (longitude, latitude, altitude, heading, pitch, roll, scale each): all of them\n * near the view's center, past `near` metres those of a rank under (near / distance)², at most `maxInstances` */\n const send = () => {\n const { center, zoom } = map.getCamera();\n const near = TREES_NEAR_METRES * 2 ** (16 - zoom);\n const cos = Math.cos((center[1] * Math.PI) / 180);\n const chosen: [score: number, tile: Float64Array, i: number][] = [];\n\n found.forEach((t) => {\n for (let i = 0; i < t.length / TREE_NUMBERS; i += 1) {\n const dx = ((t[i * TREE_NUMBERS] ?? 0) - center[0]) * METRES_PER_DEGREE * cos;\n const dy = ((t[i * TREE_NUMBERS + 1] ?? 0) - center[1]) * METRES_PER_DEGREE;\n const far = (dx * dx + dy * dy) / (near * near);\n const score = (t[i * TREE_NUMBERS + 4] ?? 0) * Math.max(1, far);\n\n if (score < 1) chosen.push([score, t, i]);\n }\n });\n if (chosen.length > maxInstances) chosen.sort((a, b) => a[0] - b[0]).splice(maxInstances);\n\n const out = new Float64Array(chosen.length * 7);\n\n chosen.forEach(([, t, i], k) => {\n const at = i * TREE_NUMBERS;\n\n out.set([t[at] ?? 0, t[at + 1] ?? 0, 0, t[at + 3] ?? 0, 0, 0, t[at + 2] ?? 1], k * 7);\n });\n layer.setInstanceNumbers(out);\n };\n const update = async () => {\n if (context.destroyed()) return;\n\n const { key, maxzoom, layers: list } = await renderer;\n const camera = map.getCamera();\n const z = maxzoom;\n const wanted = camera.zoom < minZoom ? [] : tilesAround(map, camera, z, maxTiles);\n const keys = new Set(wanted.map(([x, y]) => tileKey(z, x, y)));\n const metres = list.map((l) => (typeof spacing === 'number' ? spacing : spacing(l)));\n const dropped = requests.keys().filter((k) => !keys.has(k));\n\n // Out of view: dropped, or no longer asked for\n dropped.forEach((k) => {\n requests.drop(k);\n found.delete(k);\n });\n // Dense around the new center\n send();\n wanted.forEach(([x, y], index) => {\n const k = tileKey(z, x, y);\n\n if (requests.has(k)) return;\n\n const work: BasemapWork = {\n type: 'trees',\n key,\n z,\n x,\n y,\n spacing: metres,\n maxTrees,\n priority: nearPriority(index),\n };\n\n requests.ask(\n k,\n (signal) => context.request(z, x, y, work, signal),\n (r) => {\n if (!('trees' in r)) return;\n found.set(k, r.trees);\n send();\n },\n );\n });\n };\n // While the camera moves, the trees drawn follow its center (dense near it)\n context.followView(update, requests, send);\n\n return layer;\n};\n"]}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The vector layer of a vector basemap (`VectorTiles.vectors`): its fills, lines and buildings cut by the workers
3
+ * into geometry the engine draws, the tiles following the view, and how its style layers are read for the engine.
4
+ */
5
+ import type { Layer } from '../../layers/layers.ts';
6
+ import type { VectorLayer } from '../../layers/vectors.ts';
7
+ import { type Json, type StyleLayer } from '../vectorstyle.ts';
8
+ import type { VectorTilesContext } from './context.ts';
9
+ /**
10
+ * A `line-dasharray` as the engine takes it: two dashes and gaps in line widths (an odd count repeated, as the
11
+ * canvas's `setLineDash`; past four, the first four), zeros for a solid line
12
+ */
13
+ export declare const dashes: (value: Json | undefined, zoom: number) => [number, number, number, number];
14
+ /** The options of `VectorTiles.vectors` */
15
+ export interface VectorsOptions {
16
+ layers?: (layer: StyleLayer) => boolean;
17
+ streets?: (layer: StyleLayer) => boolean;
18
+ before?: Layer;
19
+ }
20
+ export declare const vectors: (context: VectorTilesContext, options?: VectorsOptions) => VectorLayer;
@@ -0,0 +1,167 @@
1
+ /**
2
+ * The vector layer of a vector basemap (`VectorTiles.vectors`): its fills, lines and buildings cut by the workers
3
+ * into geometry the engine draws, the tiles following the view, and how its style layers are read for the engine.
4
+ */
5
+ import { evaluate, isExpression, vectorKind, zoomOnly } from "../vectorstyle.js";
6
+ import { TileRequests } from "./requests.js";
7
+ import { nearPriority, parseTileKey, tileKey, tileTriples } from "./tiles.js";
8
+ /** The deepest level `vectors()` cuts its tiles at: past the source's deepest level, its tiles cut again into deeper
9
+ * ones (overzoom, as MapLibre does) down to level 18, their filters and styles those of their level, smaller tiles
10
+ * drawn in a closer view; past it, the tiles of that level stretched */
11
+ const OVERZOOM_LEVEL = 18;
12
+ /** The deepest level of the tiles of `vectors()` over a source whose deepest is `maxzoom` */
13
+ const deepestLevel = (maxzoom) => Math.max(maxzoom, OVERZOOM_LEVEL);
14
+ /**
15
+ * A `line-dasharray` as the engine takes it: two dashes and gaps in line widths (an odd count repeated, as the
16
+ * canvas's `setLineDash`; past four, the first four), zeros for a solid line
17
+ */
18
+ export const dashes = (value, zoom) => {
19
+ const v = isExpression(value) ? evaluate(value, { zoom, properties: {}, type: 'Unknown' }) : value;
20
+ const list = Array.isArray(v) ? v.map(Number).filter((d) => Number.isFinite(d) && d >= 0) : [];
21
+ const even = list.length % 2 === 1 ? [...list, ...list] : list;
22
+ const [a = 0, b = 0, c = 0, d = 0] = even.length >= 2 && even.some((x) => x > 0) ? even : [];
23
+ return [a, b, c, d];
24
+ };
25
+ /** Whether a style layer draws streets, which glow at night: its id names a road (OpenMapTiles' styles, PLAN IGN's),
26
+ * not its casing, a railway, a path or a tunnel */
27
+ const isStreet = (layer) => /road|highway|street|motorway|trunk|primary|secondary|tertiary|minor|routier/i.test(layer.id) &&
28
+ !/casing|outline|rail|path|track|ferry|tunnel|pier|area|pattern|label/i.test(layer.id);
29
+ /** A `line-cap` as the engine draws it, at the camera's zoom (MapLibre's default: butt) */
30
+ const lineCap = (value, zoom) => {
31
+ const v = isExpression(value) ? evaluate(value, { zoom, properties: {}, type: 'Unknown' }) : value;
32
+ return v === 'round' || v === 'square' ? v : 'butt';
33
+ };
34
+ export const vectors = (context, options = {}) => {
35
+ const { map } = context;
36
+ const { layers = () => true, streets = isStreet, before } = options;
37
+ const vector = map.addVectorLayer(before);
38
+ const state = { renderer: context.renderer((l) => vectorKind(l) !== undefined && layers(l), []), update: 0, style: 0 };
39
+ state.renderer.catch(() => undefined);
40
+ context.layers.push(vector);
41
+ const sublayers = (list) => {
42
+ const zoom = map.getCamera().zoom;
43
+ return list.map((l) => ({
44
+ id: l.id,
45
+ sourceLayer: l['source-layer'],
46
+ kind: vectorKind(l) ?? 'fill',
47
+ minZoom: l.minzoom ?? 0,
48
+ maxZoom: l.maxzoom ?? 24,
49
+ visible: l.layout?.visibility !== 'none',
50
+ opacity: zoomOnly(l.paint?.[`${l.type}-opacity`], 1) ?? 1,
51
+ cap: lineCap(l.layout?.['line-cap'], zoom),
52
+ lit: l.type === 'line' && streets(l),
53
+ dash: l.type === 'line' ? dashes(l.paint?.['line-dasharray'], zoom) : [0, 0, 0, 0],
54
+ }));
55
+ };
56
+ /** The tiles held or asked for, by `z/x/y` */
57
+ const requests = new TileRequests();
58
+ /** A tile's geometry, or its styles alone, asked of the worker of its tile of the source's level (which keeps the
59
+ * decoded tile its deeper tiles are cut from) */
60
+ const ask = ({ key, maxzoom }, [z, x, y], styles, priority, signal) => {
61
+ const d = Math.max(0, z - maxzoom);
62
+ const work = { type: 'vectors', key, z, x, y, deepest: deepestLevel(maxzoom), priority };
63
+ // The geometry made ready for the GPU in the workers, with the prisms the relief needs
64
+ return context.request(z - d, Math.floor(x / 2 ** d), Math.floor(y / 2 ** d), styles ? { ...work, styles } : { ...work, prism: map.hasRelief }, signal);
65
+ };
66
+ // The workers tessellate the tiles (the main thread only uploads them), once they know the module
67
+ context.broadcast({ type: 'tess', url: map.tessUrl });
68
+ /** Asks the workers again for the styles of a tile held, under the current style; the tile's geometry stays as it
69
+ * is */
70
+ const restyleTile = async (renderer, k) => {
71
+ const r = await ask(renderer, parseTileKey(k), true, 'auto').catch(() => undefined);
72
+ if (r && 'styles' in r)
73
+ vector.setTileStyles(k, r.styles);
74
+ };
75
+ const update = async () => {
76
+ if (context.destroyed())
77
+ return;
78
+ const generation = ++state.update;
79
+ const { key, maxzoom, layers: list } = await state.renderer;
80
+ vector.setSublayers(sublayers(state.own ?? list));
81
+ const wanted = tileTriples(map.engine.vectorTilesInView(0, deepestLevel(maxzoom)));
82
+ const keys = new Set(wanted.map((t) => tileKey(...t)));
83
+ const loads = wanted.flatMap((t, index) => {
84
+ const k = tileKey(...t);
85
+ if (requests.has(k))
86
+ return [];
87
+ const style = state.style;
88
+ return [
89
+ requests.ask(k, (signal) => ask({ key, maxzoom }, t, false, nearPriority(index, 'high', 'auto'), signal), async (r) => {
90
+ if (!('vectors' in r))
91
+ return;
92
+ vector.setTile(k, r.vectors);
93
+ // Cut under a style changed since: its styles asked for again
94
+ if (style !== state.style)
95
+ await restyleTile(await state.renderer, k);
96
+ }),
97
+ ];
98
+ });
99
+ // Out of view: those still asked for go at once, those drawn once their replacements are there (no hole). The
100
+ // drawn ones are those the engine shows, held or not (a recut forgets what it held, not what is drawn)
101
+ const drop = (drawn) => {
102
+ const shown = new Set(vector.tileKeys);
103
+ const known = new Set([...requests.keys(), ...(drawn ? shown : [])]);
104
+ known.forEach((k) => {
105
+ if (keys.has(k) || shown.has(k) !== drawn)
106
+ return;
107
+ requests.drop(k);
108
+ vector.removeTile(k);
109
+ });
110
+ };
111
+ drop(false);
112
+ await Promise.all(loads);
113
+ // A later update (the view moved again meanwhile) drops for its own view: these keys are no longer the view
114
+ if (!context.destroyed() && generation === state.update)
115
+ drop(true);
116
+ };
117
+ const refresh = () => {
118
+ update().catch(() => undefined);
119
+ };
120
+ /** The style layers changed: the workers' copy, then the styles of the tiles held */
121
+ const restyle = async (list) => {
122
+ state.own = list;
123
+ state.style++;
124
+ state.renderer = state.renderer.then(({ key }) => context.renderer(() => false, list, key));
125
+ const renderer = await state.renderer;
126
+ vector.setSublayers(sublayers(list));
127
+ await Promise.all(vector.tileKeys.map((k) => restyleTile(renderer, k)));
128
+ };
129
+ vector.restyle = (id, group, name, value) => {
130
+ state.renderer
131
+ .then(({ layers: list }) => {
132
+ const next = (state.own ?? list).map((l) => l.id === id ? { ...l, [group]: { ...l[group], [name]: value } } : l);
133
+ // Visibility and dashes are the engine's: the tiles stay as they are
134
+ if ((group === 'layout' && name === 'visibility') || name === 'line-dasharray') {
135
+ state.own = next;
136
+ vector.setSublayers(sublayers(next));
137
+ return undefined;
138
+ }
139
+ // An outline added or taken away: a feature more or less in each tile, cut again
140
+ if (name === 'fill-outline-color' || name === 'fill-antialias') {
141
+ state.own = next;
142
+ state.style++;
143
+ state.renderer = state.renderer.then(({ key }) => context.renderer(() => false, next, key));
144
+ vector.setSublayers(sublayers(next));
145
+ vector.recut?.();
146
+ return undefined;
147
+ }
148
+ return restyle(next);
149
+ })
150
+ .catch(() => undefined);
151
+ };
152
+ vector.recut = () => {
153
+ requests.abortAll();
154
+ refresh();
155
+ };
156
+ vector.styled = state.renderer.then(({ layers: list }) => {
157
+ if (!context.destroyed())
158
+ vector.setSublayers(sublayers(state.own ?? list));
159
+ });
160
+ // Reported by the style's `ready`
161
+ vector.styled.catch(() => undefined);
162
+ // While the camera moves, the tiles follow it (as the labels do: a long drag or flight does not leave the view of
163
+ // its start drawn)
164
+ context.followView(update, requests, update);
165
+ return vector;
166
+ };
167
+ //# sourceMappingURL=vectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vectors.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/vectors.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The vector layer of a vector basemap (`VectorTiles.vectors`): its fills, lines and buildings cut by the workers\n * into geometry the engine draws, the tiles following the view, and how its style layers are read for the engine.\n */\n\nimport type { Layer } from '../../layers/layers.ts';\nimport type { VectorLayer, VectorSublayer } from '../../layers/vectors.ts';\nimport type { BasemapWork, Priority } from '../../workers/basemap.worker.ts';\nimport { evaluate, isExpression, type Json, type StyleLayer, vectorKind, zoomOnly } from '../vectorstyle.ts';\nimport type { Renderer, VectorTilesContext } from './context.ts';\nimport { TileRequests } from './requests.ts';\nimport { nearPriority, parseTileKey, type TileTriple, tileKey, tileTriples } from './tiles.ts';\n\n/** The deepest level `vectors()` cuts its tiles at: past the source's deepest level, its tiles cut again into deeper\n * ones (overzoom, as MapLibre does) down to level 18, their filters and styles those of their level, smaller tiles\n * drawn in a closer view; past it, the tiles of that level stretched */\nconst OVERZOOM_LEVEL = 18;\n\n/** The deepest level of the tiles of `vectors()` over a source whose deepest is `maxzoom` */\nconst deepestLevel = (maxzoom: number): number => Math.max(maxzoom, OVERZOOM_LEVEL);\n\n/**\n * A `line-dasharray` as the engine takes it: two dashes and gaps in line widths (an odd count repeated, as the\n * canvas's `setLineDash`; past four, the first four), zeros for a solid line\n */\nexport const dashes = (value: Json | undefined, zoom: number): [number, number, number, number] => {\n const v = isExpression(value) ? evaluate(value, { zoom, properties: {}, type: 'Unknown' }) : value;\n const list = Array.isArray(v) ? v.map(Number).filter((d) => Number.isFinite(d) && d >= 0) : [];\n const even = list.length % 2 === 1 ? [...list, ...list] : list;\n const [a = 0, b = 0, c = 0, d = 0] = even.length >= 2 && even.some((x) => x > 0) ? even : [];\n\n return [a, b, c, d];\n};\n\n/** Whether a style layer draws streets, which glow at night: its id names a road (OpenMapTiles' styles, PLAN IGN's),\n * not its casing, a railway, a path or a tunnel */\nconst isStreet = (layer: StyleLayer): boolean =>\n /road|highway|street|motorway|trunk|primary|secondary|tertiary|minor|routier/i.test(layer.id) &&\n !/casing|outline|rail|path|track|ferry|tunnel|pier|area|pattern|label/i.test(layer.id);\n\n/** A `line-cap` as the engine draws it, at the camera's zoom (MapLibre's default: butt) */\nconst lineCap = (value: Json | undefined, zoom: number): 'butt' | 'round' | 'square' => {\n const v = isExpression(value) ? evaluate(value, { zoom, properties: {}, type: 'Unknown' }) : value;\n\n return v === 'round' || v === 'square' ? v : 'butt';\n};\n\n/** The options of `VectorTiles.vectors` */\nexport interface VectorsOptions {\n layers?: (layer: StyleLayer) => boolean;\n streets?: (layer: StyleLayer) => boolean;\n before?: Layer;\n}\n\nexport const vectors = (context: VectorTilesContext, options: VectorsOptions = {}): VectorLayer => {\n const { map } = context;\n const { layers = () => true, streets = isStreet, before } = options;\n const vector = map.addVectorLayer(before);\n const state: {\n renderer: Promise<Renderer>;\n /** The style layers as the application changed them (`setPaintProperty`…): a copy, its style left as it is */\n own?: StyleLayer[];\n /** Bumped by each update: only the last one drops the tiles out of its view */\n update: number;\n /** Bumped by each restyle: a tile cut under an older style is restyled once it is there */\n style: number;\n } = { renderer: context.renderer((l) => vectorKind(l) !== undefined && layers(l), []), update: 0, style: 0 };\n\n state.renderer.catch(() => undefined);\n context.layers.push(vector);\n\n const sublayers = (list: StyleLayer[]): VectorSublayer[] => {\n const zoom = map.getCamera().zoom;\n\n return list.map((l) => ({\n id: l.id,\n sourceLayer: l['source-layer'],\n kind: vectorKind(l) ?? 'fill',\n minZoom: l.minzoom ?? 0,\n maxZoom: l.maxzoom ?? 24,\n visible: l.layout?.visibility !== 'none',\n opacity: zoomOnly(l.paint?.[`${l.type}-opacity`], 1) ?? 1,\n cap: lineCap(l.layout?.['line-cap'], zoom),\n lit: l.type === 'line' && streets(l),\n dash: l.type === 'line' ? dashes(l.paint?.['line-dasharray'], zoom) : [0, 0, 0, 0],\n }));\n };\n\n /** The tiles held or asked for, by `z/x/y` */\n const requests = new TileRequests();\n /** A tile's geometry, or its styles alone, asked of the worker of its tile of the source's level (which keeps the\n * decoded tile its deeper tiles are cut from) */\n const ask = (\n { key, maxzoom }: { key: string; maxzoom: number },\n [z, x, y]: TileTriple,\n styles: boolean,\n priority: Priority,\n signal?: AbortSignal,\n ) => {\n const d = Math.max(0, z - maxzoom);\n const work: BasemapWork = { type: 'vectors', key, z, x, y, deepest: deepestLevel(maxzoom), priority };\n\n // The geometry made ready for the GPU in the workers, with the prisms the relief needs\n return context.request(\n z - d,\n Math.floor(x / 2 ** d),\n Math.floor(y / 2 ** d),\n styles ? { ...work, styles } : { ...work, prism: map.hasRelief },\n signal,\n );\n };\n\n // The workers tessellate the tiles (the main thread only uploads them), once they know the module\n context.broadcast({ type: 'tess', url: map.tessUrl });\n /** Asks the workers again for the styles of a tile held, under the current style; the tile's geometry stays as it\n * is */\n const restyleTile = async (renderer: { key: string; maxzoom: number }, k: string) => {\n const r = await ask(renderer, parseTileKey(k), true, 'auto').catch(() => undefined);\n\n if (r && 'styles' in r) vector.setTileStyles(k, r.styles);\n };\n const update = async () => {\n if (context.destroyed()) return;\n\n const generation = ++state.update;\n const { key, maxzoom, layers: list } = await state.renderer;\n\n vector.setSublayers(sublayers(state.own ?? list));\n\n const wanted = tileTriples(map.engine.vectorTilesInView(0, deepestLevel(maxzoom)));\n const keys = new Set(wanted.map((t) => tileKey(...t)));\n const loads = wanted.flatMap((t, index) => {\n const k = tileKey(...t);\n\n if (requests.has(k)) return [];\n\n const style = state.style;\n\n return [\n requests.ask(\n k,\n (signal) => ask({ key, maxzoom }, t, false, nearPriority(index, 'high', 'auto'), signal),\n async (r) => {\n if (!('vectors' in r)) return;\n vector.setTile(k, r.vectors);\n // Cut under a style changed since: its styles asked for again\n if (style !== state.style) await restyleTile(await state.renderer, k);\n },\n ),\n ];\n });\n // Out of view: those still asked for go at once, those drawn once their replacements are there (no hole). The\n // drawn ones are those the engine shows, held or not (a recut forgets what it held, not what is drawn)\n const drop = (drawn: boolean) => {\n const shown = new Set(vector.tileKeys);\n const known = new Set([...requests.keys(), ...(drawn ? shown : [])]);\n\n known.forEach((k) => {\n if (keys.has(k) || shown.has(k) !== drawn) return;\n requests.drop(k);\n vector.removeTile(k);\n });\n };\n\n drop(false);\n await Promise.all(loads);\n // A later update (the view moved again meanwhile) drops for its own view: these keys are no longer the view\n if (!context.destroyed() && generation === state.update) drop(true);\n };\n const refresh = () => {\n update().catch(() => undefined);\n };\n /** The style layers changed: the workers' copy, then the styles of the tiles held */\n const restyle = async (list: StyleLayer[]) => {\n state.own = list;\n state.style++;\n state.renderer = state.renderer.then(({ key }) => context.renderer(() => false, list, key));\n\n const renderer = await state.renderer;\n\n vector.setSublayers(sublayers(list));\n await Promise.all(vector.tileKeys.map((k) => restyleTile(renderer, k)));\n };\n\n vector.restyle = (id, group, name, value) => {\n state.renderer\n .then(({ layers: list }) => {\n const next = (state.own ?? list).map((l) =>\n l.id === id ? { ...l, [group]: { ...l[group], [name]: value } } : l,\n );\n\n // Visibility and dashes are the engine's: the tiles stay as they are\n if ((group === 'layout' && name === 'visibility') || name === 'line-dasharray') {\n state.own = next;\n vector.setSublayers(sublayers(next));\n\n return undefined;\n }\n // An outline added or taken away: a feature more or less in each tile, cut again\n if (name === 'fill-outline-color' || name === 'fill-antialias') {\n state.own = next;\n state.style++;\n state.renderer = state.renderer.then(({ key }) => context.renderer(() => false, next, key));\n vector.setSublayers(sublayers(next));\n vector.recut?.();\n\n return undefined;\n }\n\n return restyle(next);\n })\n .catch(() => undefined);\n };\n vector.recut = () => {\n requests.abortAll();\n refresh();\n };\n vector.styled = state.renderer.then(({ layers: list }) => {\n if (!context.destroyed()) vector.setSublayers(sublayers(state.own ?? list));\n });\n // Reported by the style's `ready`\n vector.styled.catch(() => undefined);\n\n // While the camera moves, the tiles follow it (as the labels do: a long drag or flight does not leave the view of\n // its start drawn)\n context.followView(update, requests, update);\n\n return vector;\n};\n"]}
@@ -7,34 +7,23 @@
7
7
  *
8
8
  * Any subset of the style can be drawn on its own raster layer (`raster({ layers })`), at its own place in the stack:
9
9
  * rivers from the basemap's data over a flood layer, for instance, restyled with `extraLayers`.
10
+ *
11
+ * The layers other than the raster ones are made in `vectortiles/` (one module each), from what they use of the
12
+ * instance (`VectorTilesContext`); the style's loading is in `vectortiles/style.ts`.
10
13
  */
11
- import type { ExtrusionLayer, ExtrusionOptions } from '../layers/extrusions.ts';
12
- import type { Feature, Size } from '../layers/features.ts';
13
- import type { Layer, ModelLayer, RasterLayer } from '../layers/layers.ts';
14
+ import type { ExtrusionLayer } from '../layers/extrusions.ts';
15
+ import type { ModelLayer, RasterLayer } from '../layers/layers.ts';
14
16
  import type { SymbolLayer } from '../layers/symbols.ts';
15
17
  import type { VectorLayer } from '../layers/vectors.ts';
16
18
  import type { GeoMap } from '../map.ts';
17
- import { type TreeColors } from './trees.ts';
18
- import { type Json, type LabelCandidate, type RasterSource, type Style, type StyleLayer } from './vectorstyle.ts';
19
- /** OpenFreeMap's styles: OpenStreetMap data in the OpenMapTiles schema, worldwide, free and without a key */
20
- export declare const OPENFREEMAP_STYLES: {
21
- readonly positron: "https://tiles.openfreemap.org/styles/positron";
22
- readonly liberty: "https://tiles.openfreemap.org/styles/liberty";
23
- readonly bright: "https://tiles.openfreemap.org/styles/bright";
24
- };
25
- /** PLAN.IGN vector styles of the Géoplateforme (France) */
26
- export declare const PLAN_STYLES: {
27
- readonly standard: "https://data.geopf.fr/annexes/ressources/vectorTiles/styles/PLAN.IGN/standard.json";
28
- readonly grey: "https://data.geopf.fr/annexes/ressources/vectorTiles/styles/PLAN.IGN/gris.json";
29
- };
30
- /** Vector basemaps by name (see `BasemapName`) */
31
- export declare const VECTOR_BASEMAPS: {
32
- readonly 'osm-positron': "https://tiles.openfreemap.org/styles/positron";
33
- readonly 'osm-liberty': "https://tiles.openfreemap.org/styles/liberty";
34
- readonly 'osm-bright': "https://tiles.openfreemap.org/styles/bright";
35
- readonly 'ign-plan-vector': "https://data.geopf.fr/annexes/ressources/vectorTiles/styles/PLAN.IGN/standard.json";
36
- readonly 'ign-plan-grey-vector': "https://data.geopf.fr/annexes/ressources/vectorTiles/styles/PLAN.IGN/gris.json";
37
- };
19
+ import type { LabelCandidate, Style, StyleLayer } from './vectorstyle.ts';
20
+ import { type VectorExtrusionOptions } from './vectortiles/extrusions.ts';
21
+ import { type LabelsOptions, size, tileLabels } from './vectortiles/labels.ts';
22
+ import { type StreetWindLayer, type StreetWindOptions } from './vectortiles/street-wind.ts';
23
+ import { type LoadedStyle, OPENFREEMAP_STYLES, PLAN_STYLES, styleAttribution, VECTOR_BASEMAPS } from './vectortiles/style.ts';
24
+ import { type TreesOptions } from './vectortiles/trees.ts';
25
+ import { dashes, type VectorsOptions } from './vectortiles/vectors.ts';
26
+ export { dashes, OPENFREEMAP_STYLES, PLAN_STYLES, size, styleAttribution, tileLabels, VECTOR_BASEMAPS };
38
27
  export interface VectorTilesOptions {
39
28
  /** A style URL or object (default OpenFreeMap's Positron) */
40
29
  style?: string | Style;
@@ -48,15 +37,6 @@ export interface VectorTilesOptions {
48
37
  * IGN's for PLAN.IGN's) */
49
38
  attribution?: string;
50
39
  }
51
- /** The credits of a known style: OpenFreeMap's, PLAN.IGN's */
52
- export declare const styleAttribution: (style: string | Style) => string | undefined;
53
- /** Text or icon size of a style (a number, legacy stops, or the stops of a zoom expression made by the worker) as a
54
- * size for the symbol layer */
55
- export declare const size: (value: Json, fallback?: number) => Size;
56
- /** The labels of a vector tile: features by style layer (its index in the style), the higher layers first */
57
- type TileLabels = [layer: number, features: Feature<LabelCandidate>[]][];
58
- /** A tile's label candidates as features, by style layer */
59
- export declare const tileLabels: (candidates: readonly LabelCandidate[]) => TileLabels;
60
40
  export declare class VectorTiles {
61
41
  private readonly map;
62
42
  private readonly pool;
@@ -75,23 +55,18 @@ export declare class VectorTiles {
75
55
  private readonly layers;
76
56
  /** Its first raster layer: the ground its labels follow */
77
57
  private ground;
58
+ /** What its layers made in `vectortiles/` use of it */
59
+ private readonly context;
78
60
  /** The style once loaded, with its source resolved */
79
- readonly ready: Promise<{
80
- style: Style;
81
- tiles: string;
82
- maxzoom: number;
83
- rasters: Record<string, RasterSource>;
84
- }>;
61
+ readonly ready: Promise<LoadedStyle>;
85
62
  /**
86
63
  * Its workers are the map's (shared by every `VectorTiles` of the map, a vector tile decoded once for all of them),
87
64
  * unless `workers` or `workerUrl` asks for others than the map's: then it has workers of its own
88
65
  */
89
66
  constructor(map: GeoMap, options?: VectorTilesOptions);
90
- private load;
91
- /** The fonts of the style's labels, for its glyphs (the first of each `text-font`, as the workers take it) */
92
- private static fonts;
93
67
  /** The style's sprites (their JSON and their images), loaded once, for the fill patterns and the icons */
94
68
  private sprites;
69
+ /** The style's sprites, kept once all of them came: one that failed is asked for again by the next layer */
95
70
  private loadSprites;
96
71
  /** Prefix of the names of its sprites' images among the map's icons */
97
72
  private get iconPrefix();
@@ -118,11 +93,19 @@ export declare class VectorTiles {
118
93
  * the source's deepest level, the `maxTiles` nearest to the center, from `minZoom` on (15 by default); the tiles
119
94
  * leaving the view are dropped.
120
95
  */
121
- extrusions<P = Record<string, unknown>>(options?: Omit<ExtrusionOptions<P>, 'data'> & {
122
- layers?: (layer: StyleLayer) => boolean;
123
- minZoom?: number;
124
- maxTiles?: number;
125
- }): ExtrusionLayer<P>;
96
+ extrusions<P = Record<string, unknown>>(options?: VectorExtrusionOptions<P>): ExtrusionLayer<P>;
97
+ /**
98
+ * The wind through the streets around the view, as particles at street level (`height`, default 3 metres) between
99
+ * the style's buildings (`layers`, default its `building` and `bati_surf` layers): their footprints laid on a grid of
100
+ * `cell` metres (default 4) over a square of `size` metres (default 1200) around the view's center, the flow of the
101
+ * air round them a potential flow (it goes round the blocks and faster through the narrow streets; no wake behind
102
+ * them), computed in a worker by the grid module from street level (`minZoom`, default 15) and again when the view
103
+ * leaves the square's middle. `wind` is the wind far away (east and north, m/s, default a light breeze from the
104
+ * south-west); `setWind` changes it at once (the flow is linear in it: nothing computed again), from a model's hour
105
+ * (`windAt`) for instance; `computed` resolves once the first square's flow is there. The other options are the flow
106
+ * layer's (`addFlow`)
107
+ */
108
+ streetWind(options?: StreetWindOptions): StreetWindLayer;
126
109
  /**
127
110
  * Trees on the style's woods, forests and grass (or the fill layers `layers` keeps) as 3D models, from street level
128
111
  * (`minZoom`, default 15): the workers scatter them over the polygons of the vector tiles around the view, `spacing`
@@ -133,18 +116,7 @@ export declare class VectorTiles {
133
116
  * 25000); at most `maxTiles` tiles (default 9) and `maxTrees` trees in each (default 30000). The models load the
134
117
  * engine with 3D Tiles.
135
118
  */
136
- trees(options?: {
137
- layers?: (layer: StyleLayer) => boolean;
138
- spacing?: number | ((layer: StyleLayer) => number);
139
- minZoom?: number;
140
- maxTiles?: number;
141
- maxTrees?: number;
142
- maxInstances?: number;
143
- colors?: Partial<TreeColors>;
144
- url?: string;
145
- data?: ArrayBuffer | ArrayBufferView<ArrayBuffer>;
146
- before?: Layer;
147
- }): ModelLayer;
119
+ trees(options?: TreesOptions): ModelLayer;
148
120
  /**
149
121
  * A layer drawing the style's fills, lines and buildings (or those `layers` keeps; backgrounds as fills, the
150
122
  * `fill-extrusion` layers raised into buildings by their height and base height) as geometry instead of images: the
@@ -160,11 +132,7 @@ export declare class VectorTiles {
160
132
  * styles and small devices. At night (`setSun`) the line layers `streets` keeps glow (by default those whose id names
161
133
  * a road, not its casing, a railway, a path or a tunnel).
162
134
  */
163
- vectors(options?: {
164
- layers?: (layer: StyleLayer) => boolean;
165
- streets?: (layer: StyleLayer) => boolean;
166
- before?: Layer;
167
- }): VectorLayer;
135
+ vectors(options?: VectorsOptions): VectorLayer;
168
136
  /**
169
137
  * A symbol layer with the labels of the style's symbol layers (or those `layers` keeps), updated as the view
170
138
  * moves: the labels of the vector tiles in view, the higher style layers placed first. With a raster layer of
@@ -172,21 +140,12 @@ export declare class VectorTiles {
172
140
  * away, with the few labels of a lower zoom, as near the camera it takes the fine ones. Without, the tiles around
173
141
  * the center at the zoom of the view. It stays above the layers added after it unless one is moved over it.
174
142
  */
175
- labels(options?: {
176
- layers?: (layer: StyleLayer) => boolean;
177
- maxTiles?: number;
178
- }): SymbolLayer<LabelCandidate>;
143
+ labels(options?: LabelsOptions): SymbolLayer<LabelCandidate>;
179
144
  /**
180
145
  * Makes a layer's tiles follow the view: `update` now and where the camera stops (`moveend`), `moving` every
181
- * `VECTOR_MOVE_REFRESH_MS` while it moves; the requests `held` aborted when destroyed
146
+ * `VECTOR_MOVE_REFRESH_MS` while it moves; the `requests` aborted when destroyed
182
147
  */
183
148
  private followView;
184
149
  /** Stops its workers' work and removes its raster and label layers from the map (those still there) */
185
150
  destroy(): void;
186
151
  }
187
- /**
188
- * A `line-dasharray` as the engine takes it: two dashes and gaps in line widths (an odd count repeated, as the
189
- * canvas's `setLineDash`; past four, the first four), zeros for a solid line
190
- */
191
- export declare const dashes: (value: Json | undefined, zoom: number) => [number, number, number, number];
192
- export {};