isard 1.6.0 → 1.8.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 (131) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/dist/basemap/furniture.d.ts +20 -2
  3. package/dist/basemap/furniture.js +72 -3
  4. package/dist/basemap/furniture.js.map +1 -1
  5. package/dist/basemap/meshes.d.ts +21 -0
  6. package/dist/basemap/meshes.js +159 -0
  7. package/dist/basemap/meshes.js.map +1 -0
  8. package/dist/basemap/placed.d.ts +13 -0
  9. package/dist/basemap/placed.js +14 -0
  10. package/dist/basemap/placed.js.map +1 -0
  11. package/dist/basemap/trees.d.ts +4 -14
  12. package/dist/basemap/trees.js +12 -93
  13. package/dist/basemap/trees.js.map +1 -1
  14. package/dist/basemap/vectortiles/context.d.ts +4 -2
  15. package/dist/basemap/vectortiles/context.js.map +1 -1
  16. package/dist/basemap/vectortiles/extrusions.d.ts +1 -1
  17. package/dist/basemap/vectortiles/extrusions.js +7 -16
  18. package/dist/basemap/vectortiles/extrusions.js.map +1 -1
  19. package/dist/basemap/vectortiles/furniture.d.ts +19 -0
  20. package/dist/basemap/vectortiles/furniture.js +29 -0
  21. package/dist/basemap/vectortiles/furniture.js.map +1 -0
  22. package/dist/basemap/vectortiles/labels.js +8 -1
  23. package/dist/basemap/vectortiles/labels.js.map +1 -1
  24. package/dist/basemap/vectortiles/lamps.js +11 -76
  25. package/dist/basemap/vectortiles/lamps.js.map +1 -1
  26. package/dist/basemap/vectortiles/placed.d.ts +38 -0
  27. package/dist/basemap/vectortiles/placed.js +143 -0
  28. package/dist/basemap/vectortiles/placed.js.map +1 -0
  29. package/dist/basemap/vectortiles/street-wind.js +4 -6
  30. package/dist/basemap/vectortiles/street-wind.js.map +1 -1
  31. package/dist/basemap/vectortiles/trees.d.ts +2 -9
  32. package/dist/basemap/vectortiles/trees.js +34 -165
  33. package/dist/basemap/vectortiles/trees.js.map +1 -1
  34. package/dist/basemap/vectortiles/vectors.d.ts +4 -5
  35. package/dist/basemap/vectortiles/vectors.js +17 -16
  36. package/dist/basemap/vectortiles/vectors.js.map +1 -1
  37. package/dist/basemap/vectortiles.d.ts +14 -4
  38. package/dist/basemap/vectortiles.js +40 -12
  39. package/dist/basemap/vectortiles.js.map +1 -1
  40. package/dist/basemap/wmts.js +2 -2
  41. package/dist/basemap/wmts.js.map +1 -1
  42. package/dist/basemap.worker.js +2 -2
  43. package/dist/basemap.worker.js.map +18 -14
  44. package/dist/bind/layers.d.ts +10 -3
  45. package/dist/bind/layers.js +11 -4
  46. package/dist/bind/layers.js.map +1 -1
  47. package/dist/data/collada.js +3 -17
  48. package/dist/data/collada.js.map +1 -1
  49. package/dist/data/crs.js +1 -1
  50. package/dist/data/crs.js.map +1 -1
  51. package/dist/data/ifc.js +21 -22
  52. package/dist/data/ifc.js.map +1 -1
  53. package/dist/geoplateforme.d.ts +16 -4
  54. package/dist/geoplateforme.js +26 -4
  55. package/dist/geoplateforme.js.map +1 -1
  56. package/dist/index.d.ts +5 -4
  57. package/dist/index.js +3 -3
  58. package/dist/index.js.map +1 -1
  59. package/dist/isard_bg.wasm +0 -0
  60. package/dist/isard_core_bg.wasm +0 -0
  61. package/dist/isard_grid_bg.wasm +0 -0
  62. package/dist/isard_tess_bg.wasm +0 -0
  63. package/dist/layers/extrusions.js +5 -4
  64. package/dist/layers/extrusions.js.map +1 -1
  65. package/dist/layers/features.d.ts +0 -2
  66. package/dist/layers/features.js +5 -6
  67. package/dist/layers/features.js.map +1 -1
  68. package/dist/layers/layers.d.ts +2 -0
  69. package/dist/layers/layers.js +11 -0
  70. package/dist/layers/layers.js.map +1 -1
  71. package/dist/layers/panoramas.d.ts +32 -10
  72. package/dist/layers/panoramas.js +55 -28
  73. package/dist/layers/panoramas.js.map +1 -1
  74. package/dist/layers/photos.js +5 -6
  75. package/dist/layers/photos.js.map +1 -1
  76. package/dist/layers/trees.js +7 -7
  77. package/dist/layers/trees.js.map +1 -1
  78. package/dist/layers/vectors.d.ts +1 -0
  79. package/dist/layers/vectors.js +23 -8
  80. package/dist/layers/vectors.js.map +1 -1
  81. package/dist/map/frame-loop.d.ts +2 -0
  82. package/dist/map/frame-loop.js +3 -3
  83. package/dist/map/frame-loop.js.map +1 -1
  84. package/dist/map.js +17 -0
  85. package/dist/map.js.map +1 -1
  86. package/dist/panoramax.d.ts +19 -0
  87. package/dist/panoramax.js +48 -3
  88. package/dist/panoramax.js.map +1 -1
  89. package/dist/react/CustomLayer.js +5 -4
  90. package/dist/react/CustomLayer.js.map +1 -1
  91. package/dist/react/Layer.d.ts +1 -1
  92. package/dist/react/Layer.js +6 -5
  93. package/dist/react/Layer.js.map +1 -1
  94. package/dist/react/VectorGeometry.d.ts +18 -9
  95. package/dist/react/VectorGeometry.js +30 -15
  96. package/dist/react/VectorGeometry.js.map +1 -1
  97. package/dist/react/VectorTiles.d.ts +65 -0
  98. package/dist/react/VectorTiles.js +112 -0
  99. package/dist/react/VectorTiles.js.map +1 -0
  100. package/dist/react/context.d.ts +12 -0
  101. package/dist/react/context.js +40 -1
  102. package/dist/react/context.js.map +1 -1
  103. package/dist/react/index.d.ts +7 -1
  104. package/dist/react/index.js +7 -1
  105. package/dist/react/index.js.map +1 -1
  106. package/dist/types.d.ts +2 -0
  107. package/dist/types.js.map +1 -1
  108. package/dist/util/geo.d.ts +8 -0
  109. package/dist/util/geo.js +8 -0
  110. package/dist/util/geo.js.map +1 -1
  111. package/dist/util/gltf.d.ts +18 -1
  112. package/dist/util/gltf.js +26 -1
  113. package/dist/util/gltf.js.map +1 -1
  114. package/dist/util/roofs.d.ts +8 -0
  115. package/dist/util/roofs.js +16 -2
  116. package/dist/util/roofs.js.map +1 -1
  117. package/dist/util/style-floats.d.ts +33 -0
  118. package/dist/util/style-floats.js +34 -0
  119. package/dist/util/style-floats.js.map +1 -0
  120. package/dist/util/sun.js +1 -1
  121. package/dist/util/sun.js.map +1 -1
  122. package/dist/workers/basemap/furniture.d.ts +13 -0
  123. package/dist/workers/basemap/geometry.d.ts +2 -5
  124. package/dist/workers/basemap/labels.d.ts +5 -2
  125. package/dist/workers/basemap/lamps.d.ts +3 -3
  126. package/dist/workers/basemap/tiles.d.ts +2 -0
  127. package/dist/workers/basemap/trees.d.ts +3 -0
  128. package/dist/workers/basemap.worker.d.ts +17 -1
  129. package/dist/workers/basemap.worker.js +12 -1
  130. package/dist/workers/basemap.worker.js.map +1 -1
  131. package/package.json +1 -1
@@ -3,96 +3,18 @@
3
3
  * broadleaved one and a conifer, their trunk and crown flat-shaded in their colors; the style layers they grow on by
4
4
  * default, and the share of conifers in a wood from its data.
5
5
  */
6
- import { bounds, glbOf } from "../util/gltf.js";
7
- /** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank, kind (0 broadleaved, 1
8
- * conifer) */
9
- export const TREE_NUMBERS = 6;
6
+ import { glb, join, revolve } from "./meshes.js";
10
7
  /** Sides of the trunk and of the crown near the view; of the crown far away (a pyramid), of the trunk there */
11
8
  const SIDES = 7;
12
9
  const FAR_SIDES = 4;
13
10
  const FAR_TRUNK_SIDES = 3;
11
+ /** The models' heights (metres): a tree's height from its data scales them by it */
12
+ export const TREE_METRES = { broadleaved: 10.2, conifer: 11 };
14
13
  const DEFAULT_COLORS = {
15
14
  trunk: [0.2, 0.12, 0.07, 1],
16
15
  crown: [0.12, 0.27, 0.08, 1],
17
16
  conifer: [0.05, 0.16, 0.08, 1],
18
17
  };
19
- /** A solid of revolution around the vertical (glTF +Y up), flat-shaded: rings of (height, radius), a point at the
20
- * top when its radius is 0; the triangles' positions and normals, one normal per face */
21
- export const revolve = (rings, sides = SIDES) => {
22
- const at = (k, [h, r]) => {
23
- const a = (k / sides) * Math.PI * 2;
24
- return [Math.cos(a) * r, h, Math.sin(a) * r];
25
- };
26
- const positions = [];
27
- const normals = [];
28
- const face = (a, b, c) => {
29
- const u = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];
30
- const v = [c[0] - a[0], c[1] - a[1], c[2] - a[2]];
31
- const n = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];
32
- const length = Math.hypot(...n);
33
- // A degenerate face (two points at the apex) is left out
34
- if (length === 0)
35
- return;
36
- positions.push(...a, ...b, ...c);
37
- [0, 1, 2].forEach(() => {
38
- normals.push(n[0] / length, n[1] / length, n[2] / length);
39
- });
40
- };
41
- rings.slice(1).forEach((ring, i) => {
42
- const below = rings[i] ?? ring;
43
- Array.from({ length: sides }, (_, k) => k).forEach((k) => {
44
- const [a, b] = [at(k, below), at(k + 1, below)];
45
- const [c, d] = [at(k, ring), at(k + 1, ring)];
46
- // Counter-clockwise seen from outside
47
- face(a, c, b);
48
- face(b, c, d);
49
- });
50
- });
51
- // The bottom closed: seen from below
52
- const base = rings[0];
53
- if (base && base[1] > 0) {
54
- Array.from({ length: sides }, (_, k) => k).forEach((k) => {
55
- face([0, base[0], 0], at(k, base), at(k + 1, base));
56
- });
57
- }
58
- return { positions, normals };
59
- };
60
- /** Parts flat-shaded in their colors as a glTF binary: one mesh of a primitive each, its front +Z
61
- * (`ModelInstance.heading` turns it), standing on its origin */
62
- export const glb = (parts, colors) => {
63
- // The buffer: each part's positions then normals, 4-byte floats
64
- const floats = parts.flatMap((p) => [...p.positions, ...p.normals]);
65
- const bin = new Float32Array(floats);
66
- const views = parts.flatMap((p, i) => {
67
- const before = parts.slice(0, i).reduce((n, q) => n + (q.positions.length + q.normals.length) * 4, 0);
68
- return [
69
- { buffer: 0, byteOffset: before, byteLength: p.positions.length * 4, target: 34962 },
70
- { buffer: 0, byteOffset: before + p.positions.length * 4, byteLength: p.normals.length * 4, target: 34962 },
71
- ];
72
- });
73
- const accessors = parts.flatMap((p, i) => [
74
- { bufferView: i * 2, componentType: 5126, count: p.positions.length / 3, type: 'VEC3', ...bounds(p.positions) },
75
- { bufferView: i * 2 + 1, componentType: 5126, count: p.normals.length / 3, type: 'VEC3' },
76
- ]);
77
- const gltf = {
78
- asset: { version: '2.0', generator: 'isard' },
79
- scene: 0,
80
- scenes: [{ nodes: [0] }],
81
- nodes: [{ mesh: 0 }],
82
- meshes: [
83
- {
84
- primitives: parts.map((_, i) => ({ attributes: { POSITION: i * 2, NORMAL: i * 2 + 1 }, material: i })),
85
- },
86
- ],
87
- materials: colors.map((color) => ({
88
- pbrMetallicRoughness: { baseColorFactor: color, metallicFactor: 0, roughnessFactor: 1 },
89
- })),
90
- accessors,
91
- bufferViews: views,
92
- buffers: [{ byteLength: bin.byteLength }],
93
- };
94
- return glbOf(gltf, new Uint8Array(bin.buffer));
95
- };
96
18
  /**
97
19
  * A broadleaved tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`; `far`: the
98
20
  * same simplified for far away, a few faces (some 30 triangles instead of 100)
@@ -107,7 +29,7 @@ export const treeModel = (colors = {}, far = false) => {
107
29
  const top = revolve([
108
30
  [2.4, 0.8],
109
31
  [5.6, 2.9],
110
- [10.2, 0],
32
+ [TREE_METRES.broadleaved, 0],
111
33
  ], FAR_SIDES);
112
34
  return glb([stem, top], [trunk, crown]);
113
35
  }
@@ -115,15 +37,15 @@ export const treeModel = (colors = {}, far = false) => {
115
37
  revolve([
116
38
  [0, 0.28],
117
39
  [3.2, 0.2],
118
- ]),
40
+ ], SIDES),
119
41
  revolve([
120
42
  [2.4, 0.6],
121
43
  [3.6, 2.4],
122
44
  [5.6, 2.9],
123
45
  [7.8, 2.3],
124
46
  [9.4, 1.1],
125
- [10.2, 0],
126
- ]),
47
+ [TREE_METRES.broadleaved, 0],
48
+ ], SIDES),
127
49
  ];
128
50
  return glb(parts, [trunk, crown]);
129
51
  };
@@ -131,7 +53,7 @@ export const treeModel = (colors = {}, far = false) => {
131
53
  const cone = (base, radius, top) => revolve([
132
54
  [base, radius],
133
55
  [top, 0],
134
- ]);
56
+ ], SIDES);
135
57
  /**
136
58
  * A conifer as a glTF binary, about 11 metres high: a trunk and three cones one over the other in `colors`; `far`: one
137
59
  * pyramid on a trunk of three faces for far away (some 17 triangles instead of 63)
@@ -145,19 +67,16 @@ export const coniferModel = (colors = {}, far = false) => {
145
67
  ], FAR_TRUNK_SIDES);
146
68
  const top = revolve([
147
69
  [1.4, 2.3],
148
- [11, 0],
70
+ [TREE_METRES.conifer, 0],
149
71
  ], FAR_SIDES);
150
72
  return glb([stem, top], [trunk, conifer]);
151
73
  }
152
- const tiers = [cone(1.4, 2.4, 5.4), cone(3.6, 1.9, 8), cone(6, 1.3, 11)];
153
- const crown = {
154
- positions: tiers.flatMap((t) => t.positions),
155
- normals: tiers.flatMap((t) => t.normals),
156
- };
74
+ const tiers = [cone(1.4, 2.4, 5.4), cone(3.6, 1.9, 8), cone(6, 1.3, TREE_METRES.conifer)];
75
+ const crown = join(...tiers);
157
76
  const stem = revolve([
158
77
  [0, 0.24],
159
78
  [2, 0.18],
160
- ]);
79
+ ], SIDES);
161
80
  return glb([stem, crown], [trunk, conifer]);
162
81
  };
163
82
  /** Whether a style layer is OpenMapTiles' grass (the lawns of parks and gardens among it) */
@@ -1 +1 @@
1
- {"version":3,"file":"trees.js","sourceRoot":"","sources":["../../src/basemap/trees.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The trees of a vector map (`VectorTiles.trees`): low-poly trees made here as glTF binaries (no file to download), a\n * broadleaved one and a conifer, their trunk and crown flat-shaded in their colors; the style layers they grow on by\n * default, and the share of conifers in a wood from its data.\n */\n\nimport { bounds, glbOf } from '../util/gltf.ts';\nimport type { Value } from './mvt.ts';\nimport type { StyleLayer } from './vectorstyle.ts';\n\n/** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank, kind (0 broadleaved, 1\n * conifer) */\nexport const TREE_NUMBERS = 6;\n\n/** A point or a vector: x, y, z */\ntype Vec3 = [number, number, number];\n\n/** Sides of the trunk and of the crown near the view; of the crown far away (a pyramid), of the trunk there */\nconst SIDES = 7;\nconst FAR_SIDES = 4;\nconst FAR_TRUNK_SIDES = 3;\n\n/** Colors of the trunk, of the broadleaved crown and of the conifers' (linear RGBA, as glTF's `baseColorFactor`) */\nexport interface TreeColors {\n trunk: [number, number, number, number];\n crown: [number, number, number, number];\n conifer: [number, number, number, number];\n}\n\nconst DEFAULT_COLORS: TreeColors = {\n trunk: [0.2, 0.12, 0.07, 1],\n crown: [0.12, 0.27, 0.08, 1],\n conifer: [0.05, 0.16, 0.08, 1],\n};\n\n/** A solid of revolution around the vertical (glTF +Y up), flat-shaded: rings of (height, radius), a point at the\n * top when its radius is 0; the triangles' positions and normals, one normal per face */\nexport const revolve = (\n rings: [height: number, radius: number][],\n sides = SIDES,\n): { positions: number[]; normals: number[] } => {\n const at = (k: number, [h, r]: [number, number]): Vec3 => {\n const a = (k / sides) * Math.PI * 2;\n\n return [Math.cos(a) * r, h, Math.sin(a) * r];\n };\n const positions: number[] = [];\n const normals: number[] = [];\n const face = (a: Vec3, b: Vec3, c: Vec3) => {\n const u: Vec3 = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];\n const v: Vec3 = [c[0] - a[0], c[1] - a[1], c[2] - a[2]];\n const n: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];\n const length = Math.hypot(...n);\n\n // A degenerate face (two points at the apex) is left out\n if (length === 0) return;\n positions.push(...a, ...b, ...c);\n [0, 1, 2].forEach(() => {\n normals.push(n[0] / length, n[1] / length, n[2] / length);\n });\n };\n\n rings.slice(1).forEach((ring, i) => {\n const below = rings[i] ?? ring;\n\n Array.from({ length: sides }, (_, k) => k).forEach((k) => {\n const [a, b] = [at(k, below), at(k + 1, below)];\n const [c, d] = [at(k, ring), at(k + 1, ring)];\n\n // Counter-clockwise seen from outside\n face(a, c, b);\n face(b, c, d);\n });\n });\n // The bottom closed: seen from below\n const base = rings[0];\n\n if (base && base[1] > 0) {\n Array.from({ length: sides }, (_, k) => k).forEach((k) => {\n face([0, base[0], 0], at(k, base), at(k + 1, base));\n });\n }\n\n return { positions, normals };\n};\n\n/** Parts flat-shaded in their colors as a glTF binary: one mesh of a primitive each, its front +Z\n * (`ModelInstance.heading` turns it), standing on its origin */\nexport const glb = (\n parts: { positions: number[]; normals: number[] }[],\n colors: TreeColors[keyof TreeColors][],\n): Uint8Array<ArrayBuffer> => {\n // The buffer: each part's positions then normals, 4-byte floats\n const floats = parts.flatMap((p) => [...p.positions, ...p.normals]);\n const bin = new Float32Array(floats);\n const views = parts.flatMap((p, i) => {\n const before = parts.slice(0, i).reduce((n, q) => n + (q.positions.length + q.normals.length) * 4, 0);\n\n return [\n { buffer: 0, byteOffset: before, byteLength: p.positions.length * 4, target: 34962 },\n { buffer: 0, byteOffset: before + p.positions.length * 4, byteLength: p.normals.length * 4, target: 34962 },\n ];\n });\n const accessors = parts.flatMap((p, i) => [\n { bufferView: i * 2, componentType: 5126, count: p.positions.length / 3, type: 'VEC3', ...bounds(p.positions) },\n { bufferView: i * 2 + 1, componentType: 5126, count: p.normals.length / 3, type: 'VEC3' },\n ]);\n const gltf = {\n asset: { version: '2.0', generator: 'isard' },\n scene: 0,\n scenes: [{ nodes: [0] }],\n nodes: [{ mesh: 0 }],\n meshes: [\n {\n primitives: parts.map((_, i) => ({ attributes: { POSITION: i * 2, NORMAL: i * 2 + 1 }, material: i })),\n },\n ],\n materials: colors.map((color) => ({\n pbrMetallicRoughness: { baseColorFactor: color, metallicFactor: 0, roughnessFactor: 1 },\n })),\n accessors,\n bufferViews: views,\n buffers: [{ byteLength: bin.byteLength }],\n };\n return glbOf(gltf, new Uint8Array(bin.buffer));\n};\n\n/**\n * A broadleaved tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`; `far`: the\n * same simplified for far away, a few faces (some 30 triangles instead of 100)\n */\nexport const treeModel = (colors: Partial<TreeColors> = {}, far = false): Uint8Array<ArrayBuffer> => {\n const { trunk, crown } = { ...DEFAULT_COLORS, ...colors };\n\n if (far) {\n const stem = revolve(\n [\n [0, 0.3],\n [3, 0.22],\n ],\n FAR_TRUNK_SIDES,\n );\n const top = revolve(\n [\n [2.4, 0.8],\n [5.6, 2.9],\n [10.2, 0],\n ],\n FAR_SIDES,\n );\n\n return glb([stem, top], [trunk, crown]);\n }\n\n const parts = [\n revolve([\n [0, 0.28],\n [3.2, 0.2],\n ]),\n revolve([\n [2.4, 0.6],\n [3.6, 2.4],\n [5.6, 2.9],\n [7.8, 2.3],\n [9.4, 1.1],\n [10.2, 0],\n ]),\n ];\n\n return glb(parts, [trunk, crown]);\n};\n\n/** A cone of the conifers' crown: from `base` metres up, `radius` wide, to its point at `top` */\nconst cone = (base: number, radius: number, top: number) =>\n revolve([\n [base, radius],\n [top, 0],\n ]);\n\n/**\n * A conifer as a glTF binary, about 11 metres high: a trunk and three cones one over the other in `colors`; `far`: one\n * pyramid on a trunk of three faces for far away (some 17 triangles instead of 63)\n */\nexport const coniferModel = (colors: Partial<TreeColors> = {}, far = false): Uint8Array<ArrayBuffer> => {\n const { trunk, conifer } = { ...DEFAULT_COLORS, ...colors };\n\n if (far) {\n const stem = revolve(\n [\n [0, 0.24],\n [2, 0.18],\n ],\n FAR_TRUNK_SIDES,\n );\n const top = revolve(\n [\n [1.4, 2.3],\n [11, 0],\n ],\n FAR_SIDES,\n );\n\n return glb([stem, top], [trunk, conifer]);\n }\n const tiers = [cone(1.4, 2.4, 5.4), cone(3.6, 1.9, 8), cone(6, 1.3, 11)];\n const crown = {\n positions: tiers.flatMap((t) => t.positions),\n normals: tiers.flatMap((t) => t.normals),\n };\n const stem = revolve([\n [0, 0.24],\n [2, 0.18],\n ]);\n\n return glb([stem, crown], [trunk, conifer]);\n};\n\n/** Whether a style layer is OpenMapTiles' grass (the lawns of parks and gardens among it) */\nconst isGrass = (layer: StyleLayer): boolean => layer['source-layer'] === 'landcover' && /grass/i.test(layer.id);\n\n/**\n * Whether trees grow on a style layer by default: the woods and forests of the style's fills (OpenMapTiles'\n * `landcover` wood, PLAN IGN's forests) and the grass of its parks and gardens; not the wooded relief of PLAN IGN,\n * which repeats its forests, nor OpenMapTiles' `park` layer (protected areas and historic sites: a river's banks\n * among them)\n */\nexport const isWoodland = (layer: StyleLayer): boolean =>\n layer.type === 'fill' &&\n layer['source-layer'] !== 'oro_relief' &&\n (/wood|forest|for[eê]t/i.test(layer.id) || isGrass(layer));\n\n/** Default spacing of the trees of a layer (metres): close in woods and forests, apart on grass */\nexport const treeSpacing = (layer: StyleLayer): number => (isGrass(layer) ? 25 : 9);\n\n/**\n * The share of conifers in a wood from its properties: OpenStreetMap's `leaf_type` (needleleaved, broadleaved,\n * mixed), PLAN IGN's `nature` (« conifères », « feuillus », « mixte »); without them, OpenMapTiles' forests a third\n * conifers and its other woods some, the grass of parks none\n */\nexport const coniferShare = (properties: Record<string, Value>): number => {\n const leaf = properties.leaf_type;\n const nature = typeof properties.nature === 'string' ? properties.nature : '';\n\n if (leaf === 'needleleaved' || /conif/i.test(nature)) return 1;\n if (leaf === 'broadleaved' || /feuillu/i.test(nature)) return 0;\n if (leaf === 'mixed' || /mixte/i.test(nature)) return 0.5;\n if (properties.class === 'wood') return properties.subclass === 'forest' ? 0.35 : 0.15;\n\n return 0;\n};\n"]}
1
+ {"version":3,"file":"trees.js","sourceRoot":"","sources":["../../src/basemap/trees.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The trees of a vector map (`VectorTiles.trees`): low-poly trees made here as glTF binaries (no file to download), a\n * broadleaved one and a conifer, their trunk and crown flat-shaded in their colors; the style layers they grow on by\n * default, and the share of conifers in a wood from its data.\n */\n\nimport { glb, join, revolve } from './meshes.ts';\nimport type { Value } from './mvt.ts';\nimport type { StyleLayer } from './vectorstyle.ts';\n\n/** Sides of the trunk and of the crown near the view; of the crown far away (a pyramid), of the trunk there */\nconst SIDES = 7;\nconst FAR_SIDES = 4;\nconst FAR_TRUNK_SIDES = 3;\n\n/** Colors of the trunk, of the broadleaved crown and of the conifers' (linear RGBA, as glTF's `baseColorFactor`) */\nexport interface TreeColors {\n trunk: [number, number, number, number];\n crown: [number, number, number, number];\n conifer: [number, number, number, number];\n}\n\n/** The models' heights (metres): a tree's height from its data scales them by it */\nexport const TREE_METRES = { broadleaved: 10.2, conifer: 11 } as const;\n\nconst DEFAULT_COLORS: TreeColors = {\n trunk: [0.2, 0.12, 0.07, 1],\n crown: [0.12, 0.27, 0.08, 1],\n conifer: [0.05, 0.16, 0.08, 1],\n};\n\n/**\n * A broadleaved tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`; `far`: the\n * same simplified for far away, a few faces (some 30 triangles instead of 100)\n */\nexport const treeModel = (colors: Partial<TreeColors> = {}, far = false): Uint8Array<ArrayBuffer> => {\n const { trunk, crown } = { ...DEFAULT_COLORS, ...colors };\n\n if (far) {\n const stem = revolve(\n [\n [0, 0.3],\n [3, 0.22],\n ],\n FAR_TRUNK_SIDES,\n );\n const top = revolve(\n [\n [2.4, 0.8],\n [5.6, 2.9],\n [TREE_METRES.broadleaved, 0],\n ],\n FAR_SIDES,\n );\n\n return glb([stem, top], [trunk, crown]);\n }\n\n const parts = [\n revolve(\n [\n [0, 0.28],\n [3.2, 0.2],\n ],\n SIDES,\n ),\n revolve(\n [\n [2.4, 0.6],\n [3.6, 2.4],\n [5.6, 2.9],\n [7.8, 2.3],\n [9.4, 1.1],\n [TREE_METRES.broadleaved, 0],\n ],\n SIDES,\n ),\n ];\n\n return glb(parts, [trunk, crown]);\n};\n\n/** A cone of the conifers' crown: from `base` metres up, `radius` wide, to its point at `top` */\nconst cone = (base: number, radius: number, top: number) =>\n revolve(\n [\n [base, radius],\n [top, 0],\n ],\n SIDES,\n );\n\n/**\n * A conifer as a glTF binary, about 11 metres high: a trunk and three cones one over the other in `colors`; `far`: one\n * pyramid on a trunk of three faces for far away (some 17 triangles instead of 63)\n */\nexport const coniferModel = (colors: Partial<TreeColors> = {}, far = false): Uint8Array<ArrayBuffer> => {\n const { trunk, conifer } = { ...DEFAULT_COLORS, ...colors };\n\n if (far) {\n const stem = revolve(\n [\n [0, 0.24],\n [2, 0.18],\n ],\n FAR_TRUNK_SIDES,\n );\n const top = revolve(\n [\n [1.4, 2.3],\n [TREE_METRES.conifer, 0],\n ],\n FAR_SIDES,\n );\n\n return glb([stem, top], [trunk, conifer]);\n }\n const tiers = [cone(1.4, 2.4, 5.4), cone(3.6, 1.9, 8), cone(6, 1.3, TREE_METRES.conifer)];\n const crown = join(...tiers);\n const stem = revolve(\n [\n [0, 0.24],\n [2, 0.18],\n ],\n SIDES,\n );\n\n return glb([stem, crown], [trunk, conifer]);\n};\n\n/** Whether a style layer is OpenMapTiles' grass (the lawns of parks and gardens among it) */\nconst isGrass = (layer: StyleLayer): boolean => layer['source-layer'] === 'landcover' && /grass/i.test(layer.id);\n\n/**\n * Whether trees grow on a style layer by default: the woods and forests of the style's fills (OpenMapTiles'\n * `landcover` wood, PLAN IGN's forests) and the grass of its parks and gardens; not the wooded relief of PLAN IGN,\n * which repeats its forests, nor OpenMapTiles' `park` layer (protected areas and historic sites: a river's banks\n * among them)\n */\nexport const isWoodland = (layer: StyleLayer): boolean =>\n layer.type === 'fill' &&\n layer['source-layer'] !== 'oro_relief' &&\n (/wood|forest|for[eê]t/i.test(layer.id) || isGrass(layer));\n\n/** Default spacing of the trees of a layer (metres): close in woods and forests, apart on grass */\nexport const treeSpacing = (layer: StyleLayer): number => (isGrass(layer) ? 25 : 9);\n\n/**\n * The share of conifers in a wood from its properties: OpenStreetMap's `leaf_type` (needleleaved, broadleaved,\n * mixed), PLAN IGN's `nature` (« conifères », « feuillus », « mixte »); without them, OpenMapTiles' forests a third\n * conifers and its other woods some, the grass of parks none\n */\nexport const coniferShare = (properties: Record<string, Value>): number => {\n const leaf = properties.leaf_type;\n const nature = typeof properties.nature === 'string' ? properties.nature : '';\n\n if (leaf === 'needleleaved' || /conif/i.test(nature)) return 1;\n if (leaf === 'broadleaved' || /feuillu/i.test(nature)) return 0;\n if (leaf === 'mixed' || /mixte/i.test(nature)) return 0.5;\n if (properties.class === 'wood') return properties.subclass === 'forest' ? 0.35 : 0.15;\n\n return 0;\n};\n"]}
@@ -41,6 +41,8 @@ export interface VectorTilesContext {
41
41
  /** The style's sprites among the map's icons (under `iconPrefix`), added once: the labels' icons, the fills'
42
42
  * patterns */
43
43
  addSprites(): Promise<void>;
44
- /** Makes a layer's tiles follow the view, its `requests` aborted when it is destroyed */
45
- followView(update: () => Promise<unknown>, requests: TileRequests, moving: () => unknown): void;
44
+ /** Makes a layer's tiles follow the view, its `requests` aborted when it is destroyed or the layer removed */
45
+ followView(layer: Layer, update: () => Promise<unknown>, requests: TileRequests, moving: () => unknown): void;
46
+ /** Calls `stop` when it is destroyed or the layer removed, once */
47
+ stopWith(layer: Layer, stop: () => void): void;
46
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/context.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * What the layers of a `VectorTiles` (its extrusions, streets' wind, trees, vectors and labels) use of it: built by\n * the instance for its layers only, its own fields staying private.\n */\n\nimport type { LoadedSprite } from '../../layers/icons.ts';\nimport type { Layer, RasterLayer } from '../../layers/layers.ts';\nimport type { GeoMap } from '../../map.ts';\nimport type { BasemapResponse, BasemapWork } from '../../workers/basemap.worker.ts';\nimport type { Style, StyleLayer } from '../vectorstyle.ts';\nimport type { BasemapWorkers } from '../workerpool.ts';\nimport type { TileRequests } from './requests.ts';\nimport type { LoadedStyle } from './style.ts';\n\n/** A renderer sent to the workers: its key, the source's deepest level, its style layers */\nexport interface Renderer {\n key: string;\n maxzoom: number;\n layers: StyleLayer[];\n}\n\nexport interface VectorTilesContext {\n readonly map: GeoMap;\n /** The style once loaded, with its source resolved */\n readonly ready: Promise<LoadedStyle>;\n /** Its raster and label layers, removed with it: a layer made is added to them */\n readonly layers: Layer[];\n /** Called when it is destroyed: a layer adds what stops it (its listeners, its timers) */\n readonly cleanup: (() => void)[];\n /** Prefix of the names of its sprites' images among the map's icons */\n readonly iconPrefix: string;\n /** Whether it was destroyed */\n destroyed(): boolean;\n /** Its first raster layer: the ground its labels follow */\n ground(): RasterLayer | undefined;\n /** A message to every worker of its pool */\n broadcast(message: Parameters<BasemapWorkers['broadcast']>[0]): void;\n /** A work asked of the worker of the vector tile `vz/vx/vy` */\n request(vz: number, vx: number, vy: number, work: BasemapWork, signal?: AbortSignal): Promise<BasemapResponse>;\n /** Sends a renderer of these layers to every worker (again under `again`, restyled) */\n renderer(select: (layer: StyleLayer) => boolean, extra: StyleLayer[], again?: string): Promise<Renderer>;\n /** The style's sprites, kept once all of them came */\n loadSprites(sprite: Style['sprite']): Promise<LoadedSprite[]>;\n /** The style's sprites among the map's icons (under `iconPrefix`), added once: the labels' icons, the fills'\n * patterns */\n addSprites(): Promise<void>;\n /** Makes a layer's tiles follow the view, its `requests` aborted when it is destroyed */\n followView(update: () => Promise<unknown>, requests: TileRequests, moving: () => unknown): void;\n}\n"]}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/context.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * What the layers of a `VectorTiles` (its extrusions, streets' wind, trees, vectors and labels) use of it: built by\n * the instance for its layers only, its own fields staying private.\n */\n\nimport type { LoadedSprite } from '../../layers/icons.ts';\nimport type { Layer, RasterLayer } from '../../layers/layers.ts';\nimport type { GeoMap } from '../../map.ts';\nimport type { BasemapResponse, BasemapWork } from '../../workers/basemap.worker.ts';\nimport type { Style, StyleLayer } from '../vectorstyle.ts';\nimport type { BasemapWorkers } from '../workerpool.ts';\nimport type { TileRequests } from './requests.ts';\nimport type { LoadedStyle } from './style.ts';\n\n/** A renderer sent to the workers: its key, the source's deepest level, its style layers */\nexport interface Renderer {\n key: string;\n maxzoom: number;\n layers: StyleLayer[];\n}\n\nexport interface VectorTilesContext {\n readonly map: GeoMap;\n /** The style once loaded, with its source resolved */\n readonly ready: Promise<LoadedStyle>;\n /** Its raster and label layers, removed with it: a layer made is added to them */\n readonly layers: Layer[];\n /** Called when it is destroyed: a layer adds what stops it (its listeners, its timers) */\n readonly cleanup: (() => void)[];\n /** Prefix of the names of its sprites' images among the map's icons */\n readonly iconPrefix: string;\n /** Whether it was destroyed */\n destroyed(): boolean;\n /** Its first raster layer: the ground its labels follow */\n ground(): RasterLayer | undefined;\n /** A message to every worker of its pool */\n broadcast(message: Parameters<BasemapWorkers['broadcast']>[0]): void;\n /** A work asked of the worker of the vector tile `vz/vx/vy` */\n request(vz: number, vx: number, vy: number, work: BasemapWork, signal?: AbortSignal): Promise<BasemapResponse>;\n /** Sends a renderer of these layers to every worker (again under `again`, restyled) */\n renderer(select: (layer: StyleLayer) => boolean, extra: StyleLayer[], again?: string): Promise<Renderer>;\n /** The style's sprites, kept once all of them came */\n loadSprites(sprite: Style['sprite']): Promise<LoadedSprite[]>;\n /** The style's sprites among the map's icons (under `iconPrefix`), added once: the labels' icons, the fills'\n * patterns */\n addSprites(): Promise<void>;\n /** Makes a layer's tiles follow the view, its `requests` aborted when it is destroyed or the layer removed */\n followView(layer: Layer, update: () => Promise<unknown>, requests: TileRequests, moving: () => unknown): void;\n /** Calls `stop` when it is destroyed or the layer removed, once */\n stopWith(layer: Layer, stop: () => void): void;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  /** The extrusions of a vector basemap (`VectorTiles.extrusions`): its buildings raised, tile by tile around the view */
2
2
  import type { ExtrusionLayer, ExtrusionOptions } from '../../layers/extrusions.ts';
3
- import type { RoofMode } from '../../workers/basemap/geometry.ts';
3
+ import { type RoofMode } from '../../util/roofs.ts';
4
4
  import type { StyleLayer } from '../vectorstyle.ts';
5
5
  import type { VectorTilesContext } from './context.ts';
6
6
  /** The options of `VectorTiles.extrusions` */
@@ -1,22 +1,13 @@
1
1
  /** The extrusions of a vector basemap (`VectorTiles.extrusions`): its buildings raised, tile by tile around the view */
2
- import { isRecord } from "../../util/guards.js";
2
+ import { roofHeightOf, roofShapeOf } from "../../util/roofs.js";
3
3
  import { TileRequests } from "./requests.js";
4
4
  import { isBuildings, isPolygonLayer } from "./style.js";
5
5
  import { MAX_TILES, nearPriority, STREET_ZOOM, tileKey, tilesAround } from "./tiles.js";
6
- /** The first of a feature's properties `names` it has */
7
- const property = (p, names) => isRecord(p) ? names.map((n) => p[n]).find((v) => v !== undefined) : undefined;
8
- /** The roof style of a `RoofMode`: a feature's `roof:shape` (or `roof_shape`), else flat or generated; its
9
- * `roof:height` */
10
- const roofStyle = (mode) => {
11
- const fallback = mode === 'generated' ? 'generated' : 'flat';
12
- return {
13
- roof: (p) => {
14
- const shape = property(p, ['roof:shape', 'roof_shape']);
15
- return typeof shape === 'string' && shape !== 'generated' ? shape : fallback;
16
- },
17
- roofHeight: (p) => Number(property(p, ['roof:height', 'roof_height']) ?? Number.NaN),
18
- };
19
- };
6
+ /** The roof style of a `RoofMode`, as the vector tiles' buildings read theirs (`roofShapeOf`, `roofHeightOf`) */
7
+ const roofStyle = (mode) => ({
8
+ roof: (p) => roofShapeOf(p, mode) ?? 'flat',
9
+ roofHeight: roofHeightOf,
10
+ });
20
11
  export const extrusions = (context, options = {}) => {
21
12
  const { map } = context;
22
13
  const { layers = isBuildings, minZoom = STREET_ZOOM, maxTiles = MAX_TILES, roofs = 'flat', ...style } = options;
@@ -55,7 +46,7 @@ export const extrusions = (context, options = {}) => {
55
46
  });
56
47
  });
57
48
  };
58
- context.followView(update, requests, update);
49
+ context.followView(layer, update, requests, update);
59
50
  return layer;
60
51
  };
61
52
  //# sourceMappingURL=extrusions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extrusions.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/extrusions.ts"],"names":[],"mappings":"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","sourcesContent":["/** The extrusions of a vector basemap (`VectorTiles.extrusions`): its buildings raised, tile by tile around the view */\n\nimport type { ExtrusionLayer, ExtrusionOptions } from '../../layers/extrusions.ts';\nimport { isRecord } from '../../util/guards.ts';\nimport type { RoofMode } from '../../workers/basemap/geometry.ts';\nimport type { BasemapWork, TilePolygons } from '../../workers/basemap.worker.ts';\nimport type { StyleLayer } from '../vectorstyle.ts';\nimport type { VectorTilesContext } from './context.ts';\nimport { TileRequests } from './requests.ts';\nimport { isBuildings, isPolygonLayer } from './style.ts';\nimport { MAX_TILES, nearPriority, STREET_ZOOM, tileKey, tilesAround } from './tiles.ts';\n\n/** The options of `VectorTiles.extrusions` */\nexport type VectorExtrusionOptions<P> = Omit<ExtrusionOptions<P>, 'data'> & {\n layers?: (layer: StyleLayer) => boolean;\n minZoom?: number;\n maxTiles?: number;\n /** The roofs, as `vectors()` makes them: from the tiles' data (`roof:shape`, `roof:height`; flat without),\n * generated where they have none, or flat (the default, unless `roof` is given) */\n roofs?: RoofMode;\n};\n\n/** The first of a feature's properties `names` it has */\nconst property = (p: unknown, names: readonly string[]): unknown =>\n isRecord(p) ? names.map((n) => p[n]).find((v) => v !== undefined) : undefined;\n\n/** The roof style of a `RoofMode`: a feature's `roof:shape` (or `roof_shape`), else flat or generated; its\n * `roof:height` */\nconst roofStyle = <P>(mode: RoofMode): Pick<ExtrusionOptions<P>, 'roof' | 'roofHeight'> => {\n const fallback = mode === 'generated' ? 'generated' : 'flat';\n\n return {\n roof: (p) => {\n const shape = property(p, ['roof:shape', 'roof_shape']);\n\n return typeof shape === 'string' && shape !== 'generated' ? shape : fallback;\n },\n roofHeight: (p) => Number(property(p, ['roof:height', 'roof_height']) ?? Number.NaN),\n };\n};\n\nexport const extrusions = <P = Record<string, unknown>>(\n context: VectorTilesContext,\n options: VectorExtrusionOptions<P> = {},\n): ExtrusionLayer<P> => {\n const { map } = context;\n const { layers = isBuildings, minZoom = STREET_ZOOM, maxTiles = MAX_TILES, roofs = 'flat', ...style } = options;\n const layer = map.addExtrusions<P>(roofs === 'flat' ? style : { ...roofStyle<P>(roofs), ...style });\n const renderer = context.renderer(isPolygonLayer(layers), []);\n\n renderer.catch(() => undefined);\n context.layers.push(layer);\n\n /** The tiles held or asked for, by key */\n const requests = new TileRequests();\n const update = async () => {\n if (context.destroyed()) return;\n\n const { key, maxzoom } = 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\n // Out of view: dropped, or no longer asked for\n requests.keys().forEach((k) => {\n if (keys.has(k)) return;\n requests.drop(k);\n layer.removeTile(k);\n });\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 = { type: 'polygons', key, z, x, y, priority: nearPriority(index) };\n\n requests.ask(\n k,\n (signal) => context.request(z, x, y, work, signal),\n (r) => {\n if (!('polygons' in r)) return;\n\n const tile: TilePolygons = r.polygons;\n\n // The features' properties as the style reads them\n layer.setTile(k, { arrays: tile.arrays, properties: tile.properties as P[] });\n },\n );\n });\n };\n context.followView(update, requests, update);\n\n return layer;\n};\n"]}
1
+ {"version":3,"file":"extrusions.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/extrusions.ts"],"names":[],"mappings":"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","sourcesContent":["/** The extrusions of a vector basemap (`VectorTiles.extrusions`): its buildings raised, tile by tile around the view */\n\nimport type { ExtrusionLayer, ExtrusionOptions } from '../../layers/extrusions.ts';\nimport { type RoofMode, roofHeightOf, roofShapeOf } from '../../util/roofs.ts';\nimport type { BasemapWork, TilePolygons } from '../../workers/basemap.worker.ts';\nimport type { StyleLayer } from '../vectorstyle.ts';\nimport type { VectorTilesContext } from './context.ts';\nimport { TileRequests } from './requests.ts';\nimport { isBuildings, isPolygonLayer } from './style.ts';\nimport { MAX_TILES, nearPriority, STREET_ZOOM, tileKey, tilesAround } from './tiles.ts';\n\n/** The options of `VectorTiles.extrusions` */\nexport type VectorExtrusionOptions<P> = Omit<ExtrusionOptions<P>, 'data'> & {\n layers?: (layer: StyleLayer) => boolean;\n minZoom?: number;\n maxTiles?: number;\n /** The roofs, as `vectors()` makes them: from the tiles' data (`roof:shape`, `roof:height`; flat without),\n * generated where they have none, or flat (the default, unless `roof` is given) */\n roofs?: RoofMode;\n};\n\n/** The roof style of a `RoofMode`, as the vector tiles' buildings read theirs (`roofShapeOf`, `roofHeightOf`) */\nconst roofStyle = <P>(mode: RoofMode): Pick<ExtrusionOptions<P>, 'roof' | 'roofHeight'> => ({\n roof: (p) => roofShapeOf(p, mode) ?? 'flat',\n roofHeight: roofHeightOf,\n});\n\nexport const extrusions = <P = Record<string, unknown>>(\n context: VectorTilesContext,\n options: VectorExtrusionOptions<P> = {},\n): ExtrusionLayer<P> => {\n const { map } = context;\n const { layers = isBuildings, minZoom = STREET_ZOOM, maxTiles = MAX_TILES, roofs = 'flat', ...style } = options;\n const layer = map.addExtrusions<P>(roofs === 'flat' ? style : { ...roofStyle<P>(roofs), ...style });\n const renderer = context.renderer(isPolygonLayer(layers), []);\n\n renderer.catch(() => undefined);\n context.layers.push(layer);\n\n /** The tiles held or asked for, by key */\n const requests = new TileRequests();\n const update = async () => {\n if (context.destroyed()) return;\n\n const { key, maxzoom } = 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\n // Out of view: dropped, or no longer asked for\n requests.keys().forEach((k) => {\n if (keys.has(k)) return;\n requests.drop(k);\n layer.removeTile(k);\n });\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 = { type: 'polygons', key, z, x, y, priority: nearPriority(index) };\n\n requests.ask(\n k,\n (signal) => context.request(z, x, y, work, signal),\n (r) => {\n if (!('polygons' in r)) return;\n\n const tile: TilePolygons = r.polygons;\n\n // The features' properties as the style reads them\n layer.setTile(k, { arrays: tile.arrays, properties: tile.properties as P[] });\n },\n );\n });\n };\n context.followView(layer, update, requests, update);\n\n return layer;\n};\n"]}
@@ -0,0 +1,19 @@
1
+ /** The street furniture of a vector basemap (`VectorTiles.furniture`): 3D models placed by the workers from its
2
+ * points of interest of the street (bus shelters, waste baskets, post boxes, drinking fountains, bicycle racks), each
3
+ * facing its street, and benches along the pedestrian streets and the parks' paths */
4
+ import type { Layer, ModelLayer } from '../../layers/layers.ts';
5
+ import type { VectorTilesContext } from './context.ts';
6
+ /** The options of `VectorTiles.furniture` */
7
+ export interface FurnitureOptions {
8
+ /** From this zoom on (default 16.5) */
9
+ minZoom?: number;
10
+ maxTiles?: number;
11
+ /** Pieces in a tile at most (default 20000) */
12
+ maxObjects?: number;
13
+ /** Pieces drawn at most (default 12000) */
14
+ maxInstances?: number;
15
+ before?: Layer;
16
+ }
17
+ /** The layers of the street furniture, a kind each (`FURNITURE`'s order: shelters, bins, post boxes, fountains, racks,
18
+ * benches): the first holds the others (`Layer.companions`) */
19
+ export declare const furniture: (context: VectorTilesContext, options?: FurnitureOptions) => ModelLayer;
@@ -0,0 +1,29 @@
1
+ /** The street furniture of a vector basemap (`VectorTiles.furniture`): 3D models placed by the workers from its
2
+ * points of interest of the street (bus shelters, waste baskets, post boxes, drinking fountains, bicycle racks), each
3
+ * facing its street, and benches along the pedestrian streets and the parks' paths */
4
+ import { FURNITURE, FURNITURE_MODELS } from "../furniture.js";
5
+ import { placed } from "./placed.js";
6
+ /** Metres around the ground under the camera where every piece is drawn at zoom 17 (twice as far a zoom level out);
7
+ * past them, fewer and fewer */
8
+ const FURNITURE_NEAR_METRES = 160;
9
+ /** The layers of the street furniture, a kind each (`FURNITURE`'s order: shelters, bins, post boxes, fountains, racks,
10
+ * benches): the first holds the others (`Layer.companions`) */
11
+ export const furniture = (context, options = {}) => {
12
+ const { minZoom = 16.5, maxTiles = 9, maxObjects = 20000, maxInstances = 12000 } = options;
13
+ const model = (kind) => ({ data: FURNITURE_MODELS[kind]() });
14
+ const [layer] = placed(context, {
15
+ // A model per kind, in the workers' order
16
+ models: [model(FURNITURE[0]), ...FURNITURE.slice(1).map(model)],
17
+ // The source of the style's buildings and streets: OpenMapTiles' layers read from its tiles
18
+ layers: (l) => l.type === 'line' || l.type === 'fill',
19
+ work: (key, z, x, y, priority) => ({ type: 'furniture', key, z, x, y, maxObjects, priority }),
20
+ read: (r) => ('furniture' in r ? r.furniture : undefined),
21
+ near: [FURNITURE_NEAR_METRES, 17],
22
+ minZoom,
23
+ maxTiles,
24
+ maxInstances,
25
+ ...(options.before && { before: options.before }),
26
+ });
27
+ return layer;
28
+ };
29
+ //# sourceMappingURL=furniture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"furniture.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/furniture.ts"],"names":[],"mappings":"AAAA;;sFAEsF;AAGtF,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;gCACgC;AAChC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAclC;+DAC+D;AAC/D,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAA2B,EAAE,UAA4B,EAAE,EAAc,EAAE;IACnG,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,QAAQ,GAAG,CAAC,EAAE,UAAU,GAAG,KAAK,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAC3F,MAAM,KAAK,GAAG,CAAC,IAAgC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACzF,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE;QAC9B,0CAA0C;QAC1C,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC/D,4FAA4F;QAC5F,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;QACrD,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;QAC7F,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QACzD,IAAI,EAAE,CAAC,qBAAqB,EAAE,EAAE,CAAC;QACjC,OAAO;QACP,QAAQ;QACR,YAAY;QACZ,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;KAClD,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC,CAAC","sourcesContent":["/** The street furniture of a vector basemap (`VectorTiles.furniture`): 3D models placed by the workers from its\n * points of interest of the street (bus shelters, waste baskets, post boxes, drinking fountains, bicycle racks), each\n * facing its street, and benches along the pedestrian streets and the parks' paths */\n\nimport type { Layer, ModelLayer } from '../../layers/layers.ts';\nimport { FURNITURE, FURNITURE_MODELS } from '../furniture.ts';\nimport type { VectorTilesContext } from './context.ts';\nimport { placed } from './placed.ts';\n\n/** Metres around the ground under the camera where every piece is drawn at zoom 17 (twice as far a zoom level out);\n * past them, fewer and fewer */\nconst FURNITURE_NEAR_METRES = 160;\n\n/** The options of `VectorTiles.furniture` */\nexport interface FurnitureOptions {\n /** From this zoom on (default 16.5) */\n minZoom?: number;\n maxTiles?: number;\n /** Pieces in a tile at most (default 20000) */\n maxObjects?: number;\n /** Pieces drawn at most (default 12000) */\n maxInstances?: number;\n before?: Layer;\n}\n\n/** The layers of the street furniture, a kind each (`FURNITURE`'s order: shelters, bins, post boxes, fountains, racks,\n * benches): the first holds the others (`Layer.companions`) */\nexport const furniture = (context: VectorTilesContext, options: FurnitureOptions = {}): ModelLayer => {\n const { minZoom = 16.5, maxTiles = 9, maxObjects = 20000, maxInstances = 12000 } = options;\n const model = (kind: (typeof FURNITURE)[number]) => ({ data: FURNITURE_MODELS[kind]() });\n const [layer] = placed(context, {\n // A model per kind, in the workers' order\n models: [model(FURNITURE[0]), ...FURNITURE.slice(1).map(model)],\n // The source of the style's buildings and streets: OpenMapTiles' layers read from its tiles\n layers: (l) => l.type === 'line' || l.type === 'fill',\n work: (key, z, x, y, priority) => ({ type: 'furniture', key, z, x, y, maxObjects, priority }),\n read: (r) => ('furniture' in r ? r.furniture : undefined),\n near: [FURNITURE_NEAR_METRES, 17],\n minZoom,\n maxTiles,\n maxInstances,\n ...(options.before && { before: options.before }),\n });\n\n return layer;\n};\n"]}
@@ -154,6 +154,9 @@ export const labels = (context, options = {}) => {
154
154
  if (raised !== occluded) {
155
155
  occluded = raised;
156
156
  symbol.setStyle({ occluded, height: occluded ? (p) => p.height ?? 0 : 0 });
157
+ // The labels asked again, with their heights or without
158
+ tiles.clear();
159
+ shown = '';
157
160
  }
158
161
  const run = ++generation;
159
162
  const camera = map.getCamera();
@@ -201,6 +204,7 @@ export const labels = (context, options = {}) => {
201
204
  y,
202
205
  priority: nearPriority(index),
203
206
  ...(deeper === undefined ? {} : { zoom: Number(deeper) }),
207
+ ...(occluded ? { roofs: true } : {}),
204
208
  };
205
209
  const p = context.request(tz, x, y, work).then((r) => tileLabels('labels' in r ? r.labels : []), () => {
206
210
  // A network error is not kept: the tile is asked for again on the next update
@@ -240,7 +244,10 @@ export const labels = (context, options = {}) => {
240
244
  refresh();
241
245
  }, LABELS_MOVE_REFRESH_MS);
242
246
  };
243
- context.cleanup.push(map.on('move', schedule), map.on('moveend', refresh), () => {
247
+ const [offMove, offEnd] = [map.on('move', schedule), map.on('moveend', refresh)];
248
+ context.stopWith(symbol, () => {
249
+ offMove();
250
+ offEnd();
244
251
  clearTimeout(timer);
245
252
  clearTimeout(retry);
246
253
  });
@@ -1 +1 @@
1
- {"version":3,"file":"labels.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/labels.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The labels of a vector basemap (`VectorTiles.labels`): the label candidates the workers list for each vector tile in\n * view, shaped in the page once per tile, placed by the engine in a symbol layer of their own.\n */\n\nimport { ExtrusionLayer } from '../../layers/extrusions.ts';\nimport type { Feature, Size } from '../../layers/features.ts';\nimport type { Layer } from '../../layers/layers.ts';\nimport type { SymbolLayer } from '../../layers/symbols.ts';\nimport { VectorLayer } from '../../layers/vectors.ts';\nimport type { Anchor } from '../../ui/overlay.ts';\nimport { isRecord } from '../../util/guards.ts';\nimport { Lru } from '../../util/lru.ts';\nimport type { BasemapWork } from '../../workers/basemap.worker.ts';\nimport type { Json, LabelCandidate, StyleLayer } from '../vectorstyle.ts';\nimport type { VectorTilesContext } from './context.ts';\nimport { styleFonts } from './style.ts';\nimport { MAX_TILES, nearPriority, parseTileKey, tileKey, tilesAround, tileTriples } from './tiles.ts';\n\n/** Pause before the labels of tiles that failed are asked for again, when no move brings an update (ms) */\nconst RETRY_LABELS_MS = 3000;\n\n/** Milliseconds between two updates of the labels while the camera moves */\nconst LABELS_MOVE_REFRESH_MS = 250;\n\n/** Vector tiles' labels kept, shaped, the least recently used dropped past it */\nconst CACHED_TILES = 256;\n\n/** Text or icon size of a style (a number, legacy stops, or the stops of a zoom expression made by the worker) as a\n * size for the symbol layer */\nexport const size = (value: Json, fallback = 16): Size => {\n const stop = (s: Json): [number, number] => {\n const [z, v] = Array.isArray(s) ? s : [];\n\n return [Number(z), Number(v)];\n };\n\n if (typeof value === 'number') return value;\n if (Array.isArray(value) && value.length > 0 && value.every(Array.isArray)) return value.map(stop);\n if (isRecord(value) && Array.isArray(value.stops)) return value.stops.map(stop);\n\n return fallback;\n};\n\n/** The anchors of the symbol layer */\nconst ANCHORS: ReadonlySet<string> = new Set<Anchor>([\n 'center',\n 'top',\n 'bottom',\n 'left',\n 'right',\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n]);\n\nconst isAnchor = (value: string | undefined): value is Anchor => value !== undefined && ANCHORS.has(value);\n\n/** A style's anchor (`text-anchor`, `icon-anchor`) for the symbol layer: `center` if it is none */\nconst anchor = (value: string | undefined): Anchor => (isAnchor(value) ? value : 'center');\n\n/** The labels of a vector tile: features by style layer (its index in the style), the higher layers first */\ntype TileLabels = [layer: number, features: Feature<LabelCandidate>[]][];\n\n/** Where a candidate is labelled: the line around a text that follows it, a short line along a line's direction (its\n * middle the anchor), or its point */\nconst geometryOf = (p: LabelCandidate): Feature<LabelCandidate>['geometry'] => {\n const { path, along } = p;\n\n if (path) {\n return {\n type: 'LineString',\n coordinates: Array.from({ length: path.length / 2 }, (_, i) => [path[i * 2] ?? 0, path[i * 2 + 1] ?? 0]),\n };\n }\n if (along) {\n return {\n type: 'LineString',\n coordinates: [\n [p.lon - along[0] / 2, p.lat - along[1] / 2],\n [p.lon + along[0] / 2, p.lat + along[1] / 2],\n ],\n };\n }\n\n return { type: 'Point', coordinates: [p.lon, p.lat] };\n};\n\n/** A tile's label candidates as features, by style layer */\nexport const tileLabels = (candidates: readonly LabelCandidate[]): TileLabels => {\n const byLayer = new Map<number, Feature<LabelCandidate>[]>();\n\n candidates.forEach((p) => {\n const feature: Feature<LabelCandidate> = {\n type: 'Feature',\n properties: p,\n geometry: geometryOf(p),\n };\n const list = byLayer.get(p.layer);\n\n if (list) list.push(feature);\n else byLayer.set(p.layer, [feature]);\n });\n\n return [...byLayer].sort((a, b) => b[0] - a[0]);\n};\n\n/** The key of a vector tile's labels: `z/x/y`, then `@zoom` when they are those of a deeper zoom than the tile's */\nconst labelsKey = (z: number, x: number, y: number, zoom: number): string =>\n `${tileKey(z, x, y)}${zoom > z ? `@${zoom}` : ''}`;\n\n/** Whether a layer of the basemap raises its buildings: its extrusions, or a style layer `fill-extrusion` of its\n * vectors shown */\nconst raisesBuildings = (layer: Layer): boolean =>\n layer instanceof ExtrusionLayer ||\n (layer instanceof VectorLayer && layer.layers.some((l) => l.kind === 'extrusion' && l.visible));\n\n/** The options of `VectorTiles.labels` */\nexport interface LabelsOptions {\n layers?: (layer: StyleLayer) => boolean;\n maxTiles?: number;\n /** Hidden by the solids before them (the buildings, the trees, the models) and lifted onto the roofs (default: when\n * these tiles raise buildings; `true` for buildings raised by others, a `<VectorGeometry>` of the same style) */\n occluded?: boolean;\n}\n\nexport const labels = (context: VectorTilesContext, options: LabelsOptions = {}): SymbolLayer<LabelCandidate> => {\n const { map } = context;\n const { layers = () => true, maxTiles = MAX_TILES } = options;\n const symbol = map.addSymbols<LabelCandidate>({\n data: [],\n text: (p) => p.text,\n font: (p) => p.font,\n size: (p) => size(p.size),\n color: (p) => p.color,\n haloColor: (p) => p.haloColor,\n haloWidth: (p) => p.haloWidth,\n anchor: (p) => anchor(p.anchor),\n offset: (p) => p.offset,\n maxWidth: (p) => p.maxWidth,\n lineHeight: (p) => p.lineHeight,\n overlap: (p) => p.overlap,\n placement: (p) => (p.textAlong ? 'line' : 'point'),\n textOptional: (p) => p.textOptional === true,\n icon: (p) => (p.icon ? context.iconPrefix + p.icon.image : ''),\n iconSize: (p) => size(p.icon?.size ?? 1, 1),\n iconAnchor: (p) => anchor(p.icon?.anchor),\n iconOffset: (p) => p.icon?.offset ?? [0, 0],\n iconRotate: (p) => p.icon?.rotate ?? 0,\n iconRotationAlignment: (p) => p.icon?.alignment ?? 'viewport',\n iconOverlap: (p) => p.icon?.overlap ?? false,\n iconOptional: (p) => p.icon?.optional ?? false,\n iconTextFit: (p) => p.icon?.fit ?? 'none',\n iconTextFitPadding: (p) => p.icon?.padding ?? [0, 0, 0, 0],\n iconColor: (p) => p.icon?.color ?? '#000',\n iconOpacity: (p) => p.icon?.opacity ?? 1,\n });\n\n map.keepOnTop(symbol);\n context.layers.push(symbol);\n\n const renderer = context.ready.then(async ({ style }) => {\n // The style's fonts from its own glyphs\n if (style.glyphs) map.glyphs.register(style.glyphs, styleFonts(style));\n\n // Its icons from its sprites, before the first labels\n const icons = style.layers.some((l) => l.type === 'symbol' && l.layout?.['icon-image'] !== undefined);\n\n if (icons) await context.addSprites();\n\n // With the buildings: a label in one stands on its roof\n return context.renderer((l) => (l.type === 'symbol' && layers(l)) || l.type === 'fill-extrusion', []);\n });\n\n renderer.catch(() => undefined);\n\n /** The labels of the tiles, as features by style layer, the higher layers first: each list is given to the symbol\n * layer as a group, shaped once while the tile is kept */\n const tiles = new Lru<string, Promise<TileLabels>>(CACHED_TILES);\n let generation = 0;\n /** The tiles whose labels are shown */\n let shown = '';\n /** The update asked again after tiles failed */\n let retry = 0;\n /** The labels hidden by the buildings the basemap raises, those in one standing on its roof */\n let occluded = false;\n const update = async () => {\n if (context.destroyed()) return;\n\n const { key, maxzoom } = await renderer;\n const others = context.layers.filter((l) => l !== symbol);\n\n // Its vectors' style layers known first\n await Promise.all(others.map((l) => (l instanceof VectorLayer ? l.styled : undefined)));\n\n const raised = options.occluded ?? others.some(raisesBuildings);\n\n if (raised !== occluded) {\n occluded = raised;\n symbol.setStyle({ occluded, height: occluded ? (p) => p.height ?? 0 : 0 });\n }\n\n const run = ++generation;\n const camera = map.getCamera();\n const zoom = Math.max(0, Math.min(Math.floor(camera.zoom), 24));\n const ground = context.ground();\n const groundTiles = ground && map.hasLayer(ground) ? tileTriples(map.engine.wantedTiles(ground.id)) : [];\n const keys: string[] = [];\n\n if (groundTiles.length > 0) {\n // The ground's tiles, the nearest first: a tile so many levels coarser than the finest in view has its\n // labels of a zoom as many under the view's, past the source's deepest level those of that level at the zoom\n const top = groundTiles.reduce((t, [z]) => Math.max(t, z), 0);\n\n groundTiles.forEach(([z, x, y]) => {\n if (keys.length >= maxTiles) return;\n\n const at = Math.max(0, zoom - (top - z));\n const tz = Math.min(at, maxzoom, z);\n const shift = 2 ** (z - tz);\n const key = labelsKey(tz, Math.floor(x / shift), Math.floor(y / shift), at);\n\n if (!keys.includes(key)) keys.push(key);\n });\n } else {\n const z = Math.min(zoom, maxzoom);\n const wanted = tilesAround(map, camera, z, maxTiles);\n\n // Past the source's deepest level, its tiles' labels at the zoom of the view (the layers of the deeper zooms)\n keys.push(...wanted.map(([x, y]) => labelsKey(z, x, y, zoom)));\n }\n\n // The same tiles as the labels shown: nothing to do\n const set = keys.join(' ');\n\n if (set === shown) return;\n\n const lists = await Promise.all(\n keys.map((k, index) => {\n const cached = tiles.get(k);\n\n if (cached) return cached;\n\n const [tile = '', deeper] = k.split('@');\n const [tz, x, y] = parseTileKey(tile);\n // The nearest tiles first: the others wait for the raster tiles\n const work: BasemapWork = {\n type: 'labels',\n key,\n z: tz,\n x,\n y,\n priority: nearPriority(index),\n ...(deeper === undefined ? {} : { zoom: Number(deeper) }),\n };\n const p = context.request(tz, x, y, work).then(\n (r) => tileLabels('labels' in r ? r.labels : []),\n () => {\n // A network error is not kept: the tile is asked for again on the next update\n tiles.delete(k);\n\n return [];\n },\n );\n\n // A bounded cache of tiles' labels, the least recently used dropped\n tiles.set(k, p);\n\n return p;\n }),\n );\n\n if (run !== generation || context.destroyed()) return;\n // A tile that failed is missing: the next update asks for it again, after a pause if no move brings one\n shown = keys.every((k) => tiles.has(k)) ? set : '';\n if (shown === '' && !retry) {\n retry = window.setTimeout(() => {\n retry = 0;\n refresh();\n }, RETRY_LABELS_MS);\n }\n\n // The labels of the higher style layers first: they win the collisions; for each style layer, the tiles nearest\n // to the center first\n const layerIds = [...new Set(lists.flatMap((list) => list.map(([layer]) => layer)))].sort((a, b) => b - a);\n const groups = layerIds.flatMap((layer) =>\n lists.map((list) => list.find(([l]) => l === layer)?.[1]).filter((group) => group !== undefined),\n );\n\n symbol.setGroups(groups);\n };\n // The style failed to load: reported by `ready`\n const refresh = () => {\n update().catch(() => undefined);\n };\n let timer = 0;\n const schedule = () => {\n if (timer) return;\n timer = window.setTimeout(() => {\n timer = 0;\n refresh();\n }, LABELS_MOVE_REFRESH_MS);\n };\n\n context.cleanup.push(map.on('move', schedule), map.on('moveend', refresh), () => {\n clearTimeout(timer);\n clearTimeout(retry);\n });\n refresh();\n\n return symbol;\n};\n"]}
1
+ {"version":3,"file":"labels.js","sourceRoot":"","sources":["../../../src/basemap/vectortiles/labels.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The labels of a vector basemap (`VectorTiles.labels`): the label candidates the workers list for each vector tile in\n * view, shaped in the page once per tile, placed by the engine in a symbol layer of their own.\n */\n\nimport { ExtrusionLayer } from '../../layers/extrusions.ts';\nimport type { Feature, Size } from '../../layers/features.ts';\nimport type { Layer } from '../../layers/layers.ts';\nimport type { SymbolLayer } from '../../layers/symbols.ts';\nimport { VectorLayer } from '../../layers/vectors.ts';\nimport type { Anchor } from '../../ui/overlay.ts';\nimport { isRecord } from '../../util/guards.ts';\nimport { Lru } from '../../util/lru.ts';\nimport type { BasemapWork } from '../../workers/basemap.worker.ts';\nimport type { Json, LabelCandidate, StyleLayer } from '../vectorstyle.ts';\nimport type { VectorTilesContext } from './context.ts';\nimport { styleFonts } from './style.ts';\nimport { MAX_TILES, nearPriority, parseTileKey, tileKey, tilesAround, tileTriples } from './tiles.ts';\n\n/** Pause before the labels of tiles that failed are asked for again, when no move brings an update (ms) */\nconst RETRY_LABELS_MS = 3000;\n\n/** Milliseconds between two updates of the labels while the camera moves */\nconst LABELS_MOVE_REFRESH_MS = 250;\n\n/** Vector tiles' labels kept, shaped, the least recently used dropped past it */\nconst CACHED_TILES = 256;\n\n/** Text or icon size of a style (a number, legacy stops, or the stops of a zoom expression made by the worker) as a\n * size for the symbol layer */\nexport const size = (value: Json, fallback = 16): Size => {\n const stop = (s: Json): [number, number] => {\n const [z, v] = Array.isArray(s) ? s : [];\n\n return [Number(z), Number(v)];\n };\n\n if (typeof value === 'number') return value;\n if (Array.isArray(value) && value.length > 0 && value.every(Array.isArray)) return value.map(stop);\n if (isRecord(value) && Array.isArray(value.stops)) return value.stops.map(stop);\n\n return fallback;\n};\n\n/** The anchors of the symbol layer */\nconst ANCHORS: ReadonlySet<string> = new Set<Anchor>([\n 'center',\n 'top',\n 'bottom',\n 'left',\n 'right',\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n]);\n\nconst isAnchor = (value: string | undefined): value is Anchor => value !== undefined && ANCHORS.has(value);\n\n/** A style's anchor (`text-anchor`, `icon-anchor`) for the symbol layer: `center` if it is none */\nconst anchor = (value: string | undefined): Anchor => (isAnchor(value) ? value : 'center');\n\n/** The labels of a vector tile: features by style layer (its index in the style), the higher layers first */\ntype TileLabels = [layer: number, features: Feature<LabelCandidate>[]][];\n\n/** Where a candidate is labelled: the line around a text that follows it, a short line along a line's direction (its\n * middle the anchor), or its point */\nconst geometryOf = (p: LabelCandidate): Feature<LabelCandidate>['geometry'] => {\n const { path, along } = p;\n\n if (path) {\n return {\n type: 'LineString',\n coordinates: Array.from({ length: path.length / 2 }, (_, i) => [path[i * 2] ?? 0, path[i * 2 + 1] ?? 0]),\n };\n }\n if (along) {\n return {\n type: 'LineString',\n coordinates: [\n [p.lon - along[0] / 2, p.lat - along[1] / 2],\n [p.lon + along[0] / 2, p.lat + along[1] / 2],\n ],\n };\n }\n\n return { type: 'Point', coordinates: [p.lon, p.lat] };\n};\n\n/** A tile's label candidates as features, by style layer */\nexport const tileLabels = (candidates: readonly LabelCandidate[]): TileLabels => {\n const byLayer = new Map<number, Feature<LabelCandidate>[]>();\n\n candidates.forEach((p) => {\n const feature: Feature<LabelCandidate> = {\n type: 'Feature',\n properties: p,\n geometry: geometryOf(p),\n };\n const list = byLayer.get(p.layer);\n\n if (list) list.push(feature);\n else byLayer.set(p.layer, [feature]);\n });\n\n return [...byLayer].sort((a, b) => b[0] - a[0]);\n};\n\n/** The key of a vector tile's labels: `z/x/y`, then `@zoom` when they are those of a deeper zoom than the tile's */\nconst labelsKey = (z: number, x: number, y: number, zoom: number): string =>\n `${tileKey(z, x, y)}${zoom > z ? `@${zoom}` : ''}`;\n\n/** Whether a layer of the basemap raises its buildings: its extrusions, or a style layer `fill-extrusion` of its\n * vectors shown */\nconst raisesBuildings = (layer: Layer): boolean =>\n layer instanceof ExtrusionLayer ||\n (layer instanceof VectorLayer && layer.layers.some((l) => l.kind === 'extrusion' && l.visible));\n\n/** The options of `VectorTiles.labels` */\nexport interface LabelsOptions {\n layers?: (layer: StyleLayer) => boolean;\n maxTiles?: number;\n /** Hidden by the solids before them (the buildings, the trees, the models) and lifted onto the roofs (default: when\n * these tiles raise buildings; `true` for buildings raised by others, a `<VectorGeometry>` of the same style) */\n occluded?: boolean;\n}\n\nexport const labels = (context: VectorTilesContext, options: LabelsOptions = {}): SymbolLayer<LabelCandidate> => {\n const { map } = context;\n const { layers = () => true, maxTiles = MAX_TILES } = options;\n const symbol = map.addSymbols<LabelCandidate>({\n data: [],\n text: (p) => p.text,\n font: (p) => p.font,\n size: (p) => size(p.size),\n color: (p) => p.color,\n haloColor: (p) => p.haloColor,\n haloWidth: (p) => p.haloWidth,\n anchor: (p) => anchor(p.anchor),\n offset: (p) => p.offset,\n maxWidth: (p) => p.maxWidth,\n lineHeight: (p) => p.lineHeight,\n overlap: (p) => p.overlap,\n placement: (p) => (p.textAlong ? 'line' : 'point'),\n textOptional: (p) => p.textOptional === true,\n icon: (p) => (p.icon ? context.iconPrefix + p.icon.image : ''),\n iconSize: (p) => size(p.icon?.size ?? 1, 1),\n iconAnchor: (p) => anchor(p.icon?.anchor),\n iconOffset: (p) => p.icon?.offset ?? [0, 0],\n iconRotate: (p) => p.icon?.rotate ?? 0,\n iconRotationAlignment: (p) => p.icon?.alignment ?? 'viewport',\n iconOverlap: (p) => p.icon?.overlap ?? false,\n iconOptional: (p) => p.icon?.optional ?? false,\n iconTextFit: (p) => p.icon?.fit ?? 'none',\n iconTextFitPadding: (p) => p.icon?.padding ?? [0, 0, 0, 0],\n iconColor: (p) => p.icon?.color ?? '#000',\n iconOpacity: (p) => p.icon?.opacity ?? 1,\n });\n\n map.keepOnTop(symbol);\n context.layers.push(symbol);\n\n const renderer = context.ready.then(async ({ style }) => {\n // The style's fonts from its own glyphs\n if (style.glyphs) map.glyphs.register(style.glyphs, styleFonts(style));\n\n // Its icons from its sprites, before the first labels\n const icons = style.layers.some((l) => l.type === 'symbol' && l.layout?.['icon-image'] !== undefined);\n\n if (icons) await context.addSprites();\n\n // With the buildings: a label in one stands on its roof\n return context.renderer((l) => (l.type === 'symbol' && layers(l)) || l.type === 'fill-extrusion', []);\n });\n\n renderer.catch(() => undefined);\n\n /** The labels of the tiles, as features by style layer, the higher layers first: each list is given to the symbol\n * layer as a group, shaped once while the tile is kept */\n const tiles = new Lru<string, Promise<TileLabels>>(CACHED_TILES);\n let generation = 0;\n /** The tiles whose labels are shown */\n let shown = '';\n /** The update asked again after tiles failed */\n let retry = 0;\n /** The labels hidden by the buildings the basemap raises, those in one standing on its roof */\n let occluded = false;\n const update = async () => {\n if (context.destroyed()) return;\n\n const { key, maxzoom } = await renderer;\n const others = context.layers.filter((l) => l !== symbol);\n\n // Its vectors' style layers known first\n await Promise.all(others.map((l) => (l instanceof VectorLayer ? l.styled : undefined)));\n\n const raised = options.occluded ?? others.some(raisesBuildings);\n\n if (raised !== occluded) {\n occluded = raised;\n symbol.setStyle({ occluded, height: occluded ? (p) => p.height ?? 0 : 0 });\n // The labels asked again, with their heights or without\n tiles.clear();\n shown = '';\n }\n\n const run = ++generation;\n const camera = map.getCamera();\n const zoom = Math.max(0, Math.min(Math.floor(camera.zoom), 24));\n const ground = context.ground();\n const groundTiles = ground && map.hasLayer(ground) ? tileTriples(map.engine.wantedTiles(ground.id)) : [];\n const keys: string[] = [];\n\n if (groundTiles.length > 0) {\n // The ground's tiles, the nearest first: a tile so many levels coarser than the finest in view has its\n // labels of a zoom as many under the view's, past the source's deepest level those of that level at the zoom\n const top = groundTiles.reduce((t, [z]) => Math.max(t, z), 0);\n\n groundTiles.forEach(([z, x, y]) => {\n if (keys.length >= maxTiles) return;\n\n const at = Math.max(0, zoom - (top - z));\n const tz = Math.min(at, maxzoom, z);\n const shift = 2 ** (z - tz);\n const key = labelsKey(tz, Math.floor(x / shift), Math.floor(y / shift), at);\n\n if (!keys.includes(key)) keys.push(key);\n });\n } else {\n const z = Math.min(zoom, maxzoom);\n const wanted = tilesAround(map, camera, z, maxTiles);\n\n // Past the source's deepest level, its tiles' labels at the zoom of the view (the layers of the deeper zooms)\n keys.push(...wanted.map(([x, y]) => labelsKey(z, x, y, zoom)));\n }\n\n // The same tiles as the labels shown: nothing to do\n const set = keys.join(' ');\n\n if (set === shown) return;\n\n const lists = await Promise.all(\n keys.map((k, index) => {\n const cached = tiles.get(k);\n\n if (cached) return cached;\n\n const [tile = '', deeper] = k.split('@');\n const [tz, x, y] = parseTileKey(tile);\n // The nearest tiles first: the others wait for the raster tiles\n const work: BasemapWork = {\n type: 'labels',\n key,\n z: tz,\n x,\n y,\n priority: nearPriority(index),\n ...(deeper === undefined ? {} : { zoom: Number(deeper) }),\n ...(occluded ? { roofs: true } : {}),\n };\n const p = context.request(tz, x, y, work).then(\n (r) => tileLabels('labels' in r ? r.labels : []),\n () => {\n // A network error is not kept: the tile is asked for again on the next update\n tiles.delete(k);\n\n return [];\n },\n );\n\n // A bounded cache of tiles' labels, the least recently used dropped\n tiles.set(k, p);\n\n return p;\n }),\n );\n\n if (run !== generation || context.destroyed()) return;\n // A tile that failed is missing: the next update asks for it again, after a pause if no move brings one\n shown = keys.every((k) => tiles.has(k)) ? set : '';\n if (shown === '' && !retry) {\n retry = window.setTimeout(() => {\n retry = 0;\n refresh();\n }, RETRY_LABELS_MS);\n }\n\n // The labels of the higher style layers first: they win the collisions; for each style layer, the tiles nearest\n // to the center first\n const layerIds = [...new Set(lists.flatMap((list) => list.map(([layer]) => layer)))].sort((a, b) => b - a);\n const groups = layerIds.flatMap((layer) =>\n lists.map((list) => list.find(([l]) => l === layer)?.[1]).filter((group) => group !== undefined),\n );\n\n symbol.setGroups(groups);\n };\n // The style failed to load: reported by `ready`\n const refresh = () => {\n update().catch(() => undefined);\n };\n let timer = 0;\n const schedule = () => {\n if (timer) return;\n timer = window.setTimeout(() => {\n timer = 0;\n refresh();\n }, LABELS_MOVE_REFRESH_MS);\n };\n\n const [offMove, offEnd] = [map.on('move', schedule), map.on('moveend', refresh)];\n\n context.stopWith(symbol, () => {\n offMove();\n offEnd();\n clearTimeout(timer);\n clearTimeout(retry);\n });\n refresh();\n\n return symbol;\n};\n"]}