isard 1.5.0 → 1.7.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 (159) hide show
  1. package/CHANGELOG.md +213 -1
  2. package/README.md +3 -2
  3. package/dist/basemap/furniture.d.ts +26 -0
  4. package/dist/basemap/furniture.js +95 -0
  5. package/dist/basemap/furniture.js.map +1 -0
  6. package/dist/basemap/meshes.d.ts +21 -0
  7. package/dist/basemap/meshes.js +159 -0
  8. package/dist/basemap/meshes.js.map +1 -0
  9. package/dist/basemap/placed.d.ts +13 -0
  10. package/dist/basemap/placed.js +14 -0
  11. package/dist/basemap/placed.js.map +1 -0
  12. package/dist/basemap/trees.d.ts +25 -8
  13. package/dist/basemap/trees.js +77 -105
  14. package/dist/basemap/trees.js.map +1 -1
  15. package/dist/basemap/vectorstyle.d.ts +9 -3
  16. package/dist/basemap/vectorstyle.js +5 -6
  17. package/dist/basemap/vectorstyle.js.map +1 -1
  18. package/dist/basemap/vectortiles/context.d.ts +7 -2
  19. package/dist/basemap/vectortiles/context.js.map +1 -1
  20. package/dist/basemap/vectortiles/extrusions.d.ts +4 -0
  21. package/dist/basemap/vectortiles/extrusions.js +9 -3
  22. package/dist/basemap/vectortiles/extrusions.js.map +1 -1
  23. package/dist/basemap/vectortiles/furniture.d.ts +19 -0
  24. package/dist/basemap/vectortiles/furniture.js +29 -0
  25. package/dist/basemap/vectortiles/furniture.js.map +1 -0
  26. package/dist/basemap/vectortiles/labels.d.ts +3 -0
  27. package/dist/basemap/vectortiles/labels.js +50 -18
  28. package/dist/basemap/vectortiles/labels.js.map +1 -1
  29. package/dist/basemap/vectortiles/lamps.d.ts +23 -0
  30. package/dist/basemap/vectortiles/lamps.js +25 -0
  31. package/dist/basemap/vectortiles/lamps.js.map +1 -0
  32. package/dist/basemap/vectortiles/placed.d.ts +38 -0
  33. package/dist/basemap/vectortiles/placed.js +143 -0
  34. package/dist/basemap/vectortiles/placed.js.map +1 -0
  35. package/dist/basemap/vectortiles/requests.d.ts +4 -0
  36. package/dist/basemap/vectortiles/requests.js +15 -2
  37. package/dist/basemap/vectortiles/requests.js.map +1 -1
  38. package/dist/basemap/vectortiles/street-wind.js +4 -6
  39. package/dist/basemap/vectortiles/street-wind.js.map +1 -1
  40. package/dist/basemap/vectortiles/trees.d.ts +2 -0
  41. package/dist/basemap/vectortiles/trees.js +40 -86
  42. package/dist/basemap/vectortiles/trees.js.map +1 -1
  43. package/dist/basemap/vectortiles/vectors.d.ts +16 -0
  44. package/dist/basemap/vectortiles/vectors.js +76 -11
  45. package/dist/basemap/vectortiles/vectors.js.map +1 -1
  46. package/dist/basemap/vectortiles.d.ts +37 -7
  47. package/dist/basemap/vectortiles.js +78 -17
  48. package/dist/basemap/vectortiles.js.map +1 -1
  49. package/dist/basemap/wmts.js +2 -2
  50. package/dist/basemap/wmts.js.map +1 -1
  51. package/dist/basemap.worker.js +2 -2
  52. package/dist/basemap.worker.js.map +19 -13
  53. package/dist/bind/layers.js +1 -0
  54. package/dist/bind/layers.js.map +1 -1
  55. package/dist/data/collada.d.ts +19 -0
  56. package/dist/data/collada.js +305 -0
  57. package/dist/data/collada.js.map +1 -0
  58. package/dist/data/crs.js +1 -1
  59. package/dist/data/crs.js.map +1 -1
  60. package/dist/data/ifc.d.ts +100 -0
  61. package/dist/data/ifc.js +371 -0
  62. package/dist/data/ifc.js.map +1 -0
  63. package/dist/decoder.worker.js +5 -5
  64. package/dist/decoder.worker.js.map +3 -3
  65. package/dist/formats.d.ts +7 -2
  66. package/dist/formats.js +7 -2
  67. package/dist/formats.js.map +1 -1
  68. package/dist/geoplateforme.d.ts +14 -2
  69. package/dist/geoplateforme.js +24 -2
  70. package/dist/geoplateforme.js.map +1 -1
  71. package/dist/index.d.ts +11 -3
  72. package/dist/index.js +8 -3
  73. package/dist/index.js.map +1 -1
  74. package/dist/isard_bg.wasm +0 -0
  75. package/dist/isard_core_bg.wasm +0 -0
  76. package/dist/isard_grid_bg.wasm +0 -0
  77. package/dist/isard_tess_bg.wasm +0 -0
  78. package/dist/layers/extrusions.d.ts +10 -0
  79. package/dist/layers/extrusions.js +33 -6
  80. package/dist/layers/extrusions.js.map +1 -1
  81. package/dist/layers/features.d.ts +0 -2
  82. package/dist/layers/features.js +5 -6
  83. package/dist/layers/features.js.map +1 -1
  84. package/dist/layers/layers.d.ts +14 -0
  85. package/dist/layers/layers.js +55 -1
  86. package/dist/layers/layers.js.map +1 -1
  87. package/dist/layers/panoramas.d.ts +32 -10
  88. package/dist/layers/panoramas.js +55 -28
  89. package/dist/layers/panoramas.js.map +1 -1
  90. package/dist/layers/photos.d.ts +48 -0
  91. package/dist/layers/photos.js +139 -0
  92. package/dist/layers/photos.js.map +1 -0
  93. package/dist/layers/symbols.d.ts +5 -1
  94. package/dist/layers/symbols.js +111 -32
  95. package/dist/layers/symbols.js.map +1 -1
  96. package/dist/layers/trees.d.ts +28 -0
  97. package/dist/layers/trees.js +51 -0
  98. package/dist/layers/trees.js.map +1 -0
  99. package/dist/layers/vectors.d.ts +29 -2
  100. package/dist/layers/vectors.js +98 -9
  101. package/dist/layers/vectors.js.map +1 -1
  102. package/dist/map/frame-loop.d.ts +2 -0
  103. package/dist/map/frame-loop.js +3 -3
  104. package/dist/map/frame-loop.js.map +1 -1
  105. package/dist/map/layer-spec.d.ts +3 -0
  106. package/dist/map/layer-spec.js +2 -0
  107. package/dist/map/layer-spec.js.map +1 -1
  108. package/dist/map.d.ts +8 -0
  109. package/dist/map.js +32 -2
  110. package/dist/map.js.map +1 -1
  111. package/dist/panoramax.d.ts +55 -0
  112. package/dist/panoramax.js +97 -0
  113. package/dist/panoramax.js.map +1 -0
  114. package/dist/react/Layer.d.ts +1 -0
  115. package/dist/react/Layer.js.map +1 -1
  116. package/dist/react/VectorGeometry.d.ts +22 -8
  117. package/dist/react/VectorGeometry.js +36 -14
  118. package/dist/react/VectorGeometry.js.map +1 -1
  119. package/dist/react/VectorTiles.d.ts +65 -0
  120. package/dist/react/VectorTiles.js +112 -0
  121. package/dist/react/VectorTiles.js.map +1 -0
  122. package/dist/react/context.d.ts +9 -0
  123. package/dist/react/context.js +32 -0
  124. package/dist/react/context.js.map +1 -1
  125. package/dist/react/index.d.ts +7 -1
  126. package/dist/react/index.js +7 -1
  127. package/dist/react/index.js.map +1 -1
  128. package/dist/types.d.ts +2 -0
  129. package/dist/types.js.map +1 -1
  130. package/dist/util/geo.d.ts +8 -0
  131. package/dist/util/geo.js +8 -0
  132. package/dist/util/geo.js.map +1 -1
  133. package/dist/util/gltf.d.ts +26 -0
  134. package/dist/util/gltf.js +52 -0
  135. package/dist/util/gltf.js.map +1 -0
  136. package/dist/util/roofs.d.ts +18 -0
  137. package/dist/util/roofs.js +44 -0
  138. package/dist/util/roofs.js.map +1 -0
  139. package/dist/util/style-floats.d.ts +33 -0
  140. package/dist/util/style-floats.js +34 -0
  141. package/dist/util/style-floats.js.map +1 -0
  142. package/dist/util/sun.js +1 -1
  143. package/dist/util/sun.js.map +1 -1
  144. package/dist/wasm/isard.d.ts +56 -17
  145. package/dist/wasm/isard.js +128 -18
  146. package/dist/wasm/isard_core.d.ts +44 -17
  147. package/dist/wasm/isard_core.js +104 -18
  148. package/dist/wasm/isard_tess.d.ts +6 -3
  149. package/dist/wasm/isard_tess.js +27 -4
  150. package/dist/workers/basemap/furniture.d.ts +13 -0
  151. package/dist/workers/basemap/geometry.d.ts +35 -22
  152. package/dist/workers/basemap/labels.d.ts +18 -2
  153. package/dist/workers/basemap/lamps.d.ts +10 -0
  154. package/dist/workers/basemap/tiles.d.ts +2 -0
  155. package/dist/workers/basemap/trees.d.ts +6 -1
  156. package/dist/workers/basemap.worker.d.ts +58 -2
  157. package/dist/workers/basemap.worker.js +26 -3
  158. package/dist/workers/basemap.worker.js.map +1 -1
  159. package/package.json +1 -1
@@ -1,20 +1,31 @@
1
1
  /**
2
- * The trees of a vector map (`VectorTiles.trees`): a low-poly tree made here as a glTF binary (no file to download),
3
- * its trunk and its crown flat-shaded in their colors, and the style layers they grow on by default.
2
+ * The trees of a vector map (`VectorTiles.trees`): low-poly trees made here as glTF binaries (no file to download), a
3
+ * broadleaved one and a conifer, their trunk and crown flat-shaded in their colors; the style layers they grow on by
4
+ * default, and the share of conifers in a wood from its data.
4
5
  */
6
+ import type { Value } from './mvt.ts';
5
7
  import type { StyleLayer } from './vectorstyle.ts';
6
- /** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank */
7
- export declare const TREE_NUMBERS = 5;
8
- /** Colors of the trunk and of the crown (linear RGBA, as glTF's `baseColorFactor`) */
8
+ /** Colors of the trunk, of the broadleaved crown and of the conifers' (linear RGBA, as glTF's `baseColorFactor`) */
9
9
  export interface TreeColors {
10
10
  trunk: [number, number, number, number];
11
11
  crown: [number, number, number, number];
12
+ conifer: [number, number, number, number];
12
13
  }
14
+ /** The models' heights (metres): a tree's height from its data scales them by it */
15
+ export declare const TREE_METRES: {
16
+ readonly broadleaved: 10.2;
17
+ readonly conifer: 11;
18
+ };
13
19
  /**
14
- * A tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`, one mesh of two primitives,
15
- * its front +Z (`ModelInstance.heading` turns it), standing on its origin
20
+ * A broadleaved tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`; `far`: the
21
+ * same simplified for far away, a few faces (some 30 triangles instead of 100)
16
22
  */
17
- export declare const treeModel: (colors?: Partial<TreeColors>) => Uint8Array<ArrayBuffer>;
23
+ export declare const treeModel: (colors?: Partial<TreeColors>, far?: boolean) => Uint8Array<ArrayBuffer>;
24
+ /**
25
+ * A conifer as a glTF binary, about 11 metres high: a trunk and three cones one over the other in `colors`; `far`: one
26
+ * pyramid on a trunk of three faces for far away (some 17 triangles instead of 63)
27
+ */
28
+ export declare const coniferModel: (colors?: Partial<TreeColors>, far?: boolean) => Uint8Array<ArrayBuffer>;
18
29
  /**
19
30
  * Whether trees grow on a style layer by default: the woods and forests of the style's fills (OpenMapTiles'
20
31
  * `landcover` wood, PLAN IGN's forests) and the grass of its parks and gardens; not the wooded relief of PLAN IGN,
@@ -24,3 +35,9 @@ export declare const treeModel: (colors?: Partial<TreeColors>) => Uint8Array<Arr
24
35
  export declare const isWoodland: (layer: StyleLayer) => boolean;
25
36
  /** Default spacing of the trees of a layer (metres): close in woods and forests, apart on grass */
26
37
  export declare const treeSpacing: (layer: StyleLayer) => number;
38
+ /**
39
+ * The share of conifers in a wood from its properties: OpenStreetMap's `leaf_type` (needleleaved, broadleaved,
40
+ * mixed), PLAN IGN's `nature` (« conifères », « feuillus », « mixte »); without them, OpenMapTiles' forests a third
41
+ * conifers and its other woods some, the grass of parks none
42
+ */
43
+ export declare const coniferShare: (properties: Record<string, Value>) => number;
@@ -1,129 +1,83 @@
1
1
  /**
2
- * The trees of a vector map (`VectorTiles.trees`): a low-poly tree made here as a glTF binary (no file to download),
3
- * its trunk and its crown flat-shaded in their colors, and the style layers they grow on by default.
2
+ * The trees of a vector map (`VectorTiles.trees`): low-poly trees made here as glTF binaries (no file to download), a
3
+ * broadleaved one and a conifer, their trunk and crown flat-shaded in their colors; the style layers they grow on by
4
+ * default, and the share of conifers in a wood from its data.
4
5
  */
5
- /** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank */
6
- export const TREE_NUMBERS = 5;
7
- /** Sides of the trunk and of the crown */
6
+ import { glb, join, revolve } from "./meshes.js";
7
+ /** Sides of the trunk and of the crown near the view; of the crown far away (a pyramid), of the trunk there */
8
8
  const SIDES = 7;
9
+ const FAR_SIDES = 4;
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 };
9
13
  const DEFAULT_COLORS = {
10
14
  trunk: [0.2, 0.12, 0.07, 1],
11
15
  crown: [0.12, 0.27, 0.08, 1],
12
- };
13
- /** A solid of revolution around the vertical (glTF +Y up), flat-shaded: rings of (height, radius), a point at the
14
- * top when its radius is 0; the triangles' positions and normals, one normal per face */
15
- const revolve = (rings) => {
16
- const at = (k, [h, r]) => {
17
- const a = (k / SIDES) * Math.PI * 2;
18
- return [Math.cos(a) * r, h, Math.sin(a) * r];
19
- };
20
- const positions = [];
21
- const normals = [];
22
- const face = (a, b, c) => {
23
- const u = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];
24
- const v = [c[0] - a[0], c[1] - a[1], c[2] - a[2]];
25
- 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]];
26
- const length = Math.hypot(...n);
27
- // A degenerate face (two points at the apex) is left out
28
- if (length === 0)
29
- return;
30
- positions.push(...a, ...b, ...c);
31
- [0, 1, 2].forEach(() => {
32
- normals.push(n[0] / length, n[1] / length, n[2] / length);
33
- });
34
- };
35
- rings.slice(1).forEach((ring, i) => {
36
- const below = rings[i] ?? ring;
37
- Array.from({ length: SIDES }, (_, k) => k).forEach((k) => {
38
- const [a, b] = [at(k, below), at(k + 1, below)];
39
- const [c, d] = [at(k, ring), at(k + 1, ring)];
40
- // Counter-clockwise seen from outside
41
- face(a, c, b);
42
- face(b, c, d);
43
- });
44
- });
45
- // The bottom closed: seen from below
46
- const base = rings[0];
47
- if (base && base[1] > 0) {
48
- Array.from({ length: SIDES }, (_, k) => k).forEach((k) => {
49
- face([0, base[0], 0], at(k, base), at(k + 1, base));
50
- });
51
- }
52
- return { positions, normals };
53
- };
54
- /** Lowest and highest of interleaved x, y, z (glTF needs them on positions) */
55
- const bounds = (xyz) => {
56
- const axes = [0, 1, 2].map((a) => xyz.filter((_, i) => i % 3 === a));
57
- return { min: axes.map((v) => Math.min(...v)), max: axes.map((v) => Math.max(...v)) };
16
+ conifer: [0.05, 0.16, 0.08, 1],
58
17
  };
59
18
  /**
60
- * A tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`, one mesh of two primitives,
61
- * its front +Z (`ModelInstance.heading` turns it), standing on its origin
19
+ * A broadleaved tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`; `far`: the
20
+ * same simplified for far away, a few faces (some 30 triangles instead of 100)
62
21
  */
63
- export const treeModel = (colors = {}) => {
22
+ export const treeModel = (colors = {}, far = false) => {
64
23
  const { trunk, crown } = { ...DEFAULT_COLORS, ...colors };
24
+ if (far) {
25
+ const stem = revolve([
26
+ [0, 0.3],
27
+ [3, 0.22],
28
+ ], FAR_TRUNK_SIDES);
29
+ const top = revolve([
30
+ [2.4, 0.8],
31
+ [5.6, 2.9],
32
+ [TREE_METRES.broadleaved, 0],
33
+ ], FAR_SIDES);
34
+ return glb([stem, top], [trunk, crown]);
35
+ }
65
36
  const parts = [
66
37
  revolve([
67
38
  [0, 0.28],
68
39
  [3.2, 0.2],
69
- ]),
40
+ ], SIDES),
70
41
  revolve([
71
42
  [2.4, 0.6],
72
43
  [3.6, 2.4],
73
44
  [5.6, 2.9],
74
45
  [7.8, 2.3],
75
46
  [9.4, 1.1],
76
- [10.2, 0],
77
- ]),
47
+ [TREE_METRES.broadleaved, 0],
48
+ ], SIDES),
78
49
  ];
79
- // The buffer: each part's positions then normals, 4-byte floats
80
- const floats = parts.flatMap((p) => [...p.positions, ...p.normals]);
81
- const bin = new Float32Array(floats);
82
- const views = parts.flatMap((p, i) => {
83
- const before = parts.slice(0, i).reduce((n, q) => n + (q.positions.length + q.normals.length) * 4, 0);
84
- return [
85
- { buffer: 0, byteOffset: before, byteLength: p.positions.length * 4, target: 34962 },
86
- { buffer: 0, byteOffset: before + p.positions.length * 4, byteLength: p.normals.length * 4, target: 34962 },
87
- ];
88
- });
89
- const accessors = parts.flatMap((p, i) => [
90
- { bufferView: i * 2, componentType: 5126, count: p.positions.length / 3, type: 'VEC3', ...bounds(p.positions) },
91
- { bufferView: i * 2 + 1, componentType: 5126, count: p.normals.length / 3, type: 'VEC3' },
92
- ]);
93
- const gltf = {
94
- asset: { version: '2.0', generator: 'isard' },
95
- scene: 0,
96
- scenes: [{ nodes: [0] }],
97
- nodes: [{ mesh: 0 }],
98
- meshes: [
99
- {
100
- primitives: parts.map((_, i) => ({ attributes: { POSITION: i * 2, NORMAL: i * 2 + 1 }, material: i })),
101
- },
102
- ],
103
- materials: [trunk, crown].map((color) => ({
104
- pbrMetallicRoughness: { baseColorFactor: color, metallicFactor: 0, roughnessFactor: 1 },
105
- })),
106
- accessors,
107
- bufferViews: views,
108
- buffers: [{ byteLength: bin.byteLength }],
109
- };
110
- // The chunks padded to 4 bytes: the JSON with spaces, the binary with zeros
111
- const json = new TextEncoder().encode(JSON.stringify(gltf));
112
- const jsonLength = Math.ceil(json.length / 4) * 4;
113
- const binLength = Math.ceil(bin.byteLength / 4) * 4;
114
- const out = new Uint8Array(12 + 8 + jsonLength + 8 + binLength);
115
- const view = new DataView(out.buffer);
116
- view.setUint32(0, 0x46546c67, true);
117
- view.setUint32(4, 2, true);
118
- view.setUint32(8, out.length, true);
119
- view.setUint32(12, jsonLength, true);
120
- view.setUint32(16, 0x4e4f534a, true);
121
- out.fill(0x20, 20, 20 + jsonLength);
122
- out.set(json, 20);
123
- view.setUint32(20 + jsonLength, binLength, true);
124
- view.setUint32(24 + jsonLength, 0x004e4942, true);
125
- out.set(new Uint8Array(bin.buffer), 28 + jsonLength);
126
- return out;
50
+ return glb(parts, [trunk, crown]);
51
+ };
52
+ /** A cone of the conifers' crown: from `base` metres up, `radius` wide, to its point at `top` */
53
+ const cone = (base, radius, top) => revolve([
54
+ [base, radius],
55
+ [top, 0],
56
+ ], SIDES);
57
+ /**
58
+ * A conifer as a glTF binary, about 11 metres high: a trunk and three cones one over the other in `colors`; `far`: one
59
+ * pyramid on a trunk of three faces for far away (some 17 triangles instead of 63)
60
+ */
61
+ export const coniferModel = (colors = {}, far = false) => {
62
+ const { trunk, conifer } = { ...DEFAULT_COLORS, ...colors };
63
+ if (far) {
64
+ const stem = revolve([
65
+ [0, 0.24],
66
+ [2, 0.18],
67
+ ], FAR_TRUNK_SIDES);
68
+ const top = revolve([
69
+ [1.4, 2.3],
70
+ [TREE_METRES.conifer, 0],
71
+ ], FAR_SIDES);
72
+ return glb([stem, top], [trunk, conifer]);
73
+ }
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);
76
+ const stem = revolve([
77
+ [0, 0.24],
78
+ [2, 0.18],
79
+ ], SIDES);
80
+ return glb([stem, crown], [trunk, conifer]);
127
81
  };
128
82
  /** Whether a style layer is OpenMapTiles' grass (the lawns of parks and gardens among it) */
129
83
  const isGrass = (layer) => layer['source-layer'] === 'landcover' && /grass/i.test(layer.id);
@@ -138,4 +92,22 @@ export const isWoodland = (layer) => layer.type === 'fill' &&
138
92
  (/wood|forest|for[eê]t/i.test(layer.id) || isGrass(layer));
139
93
  /** Default spacing of the trees of a layer (metres): close in woods and forests, apart on grass */
140
94
  export const treeSpacing = (layer) => (isGrass(layer) ? 25 : 9);
95
+ /**
96
+ * The share of conifers in a wood from its properties: OpenStreetMap's `leaf_type` (needleleaved, broadleaved,
97
+ * mixed), PLAN IGN's `nature` (« conifères », « feuillus », « mixte »); without them, OpenMapTiles' forests a third
98
+ * conifers and its other woods some, the grass of parks none
99
+ */
100
+ export const coniferShare = (properties) => {
101
+ const leaf = properties.leaf_type;
102
+ const nature = typeof properties.nature === 'string' ? properties.nature : '';
103
+ if (leaf === 'needleleaved' || /conif/i.test(nature))
104
+ return 1;
105
+ if (leaf === 'broadleaved' || /feuillu/i.test(nature))
106
+ return 0;
107
+ if (leaf === 'mixed' || /mixte/i.test(nature))
108
+ return 0.5;
109
+ if (properties.class === 'wood')
110
+ return properties.subclass === 'forest' ? 0.35 : 0.15;
111
+ return 0;
112
+ };
141
113
  //# sourceMappingURL=trees.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"trees.js","sourceRoot":"","sources":["../../src/basemap/trees.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAK9B,0CAA0C;AAC1C,MAAM,KAAK,GAAG,CAAC,CAAC;AAQhB,MAAM,cAAc,GAAe;IACjC,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;CAC7B,CAAC;AAEF;yFACyF;AACzF,MAAM,OAAO,GAAG,CAAC,KAAyC,EAA8C,EAAE;IACxG,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAmB,EAAQ,EAAE;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QAEpC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC;IACF,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,CAAC,CAAO,EAAE,CAAO,EAAE,CAAO,EAAE,EAAE;QACzC,MAAM,CAAC,GAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,GAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,GAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClG,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAEhC,yDAAyD;QACzD,IAAI,MAAM,KAAK,CAAC;YAAE,OAAO;QACzB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAE/B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACvD,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAE9C,sCAAsC;YACtC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACd,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,qCAAqC;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAEtB,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACvD,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,GAAG,CAAC,GAAa,EAAoC,EAAE;IACjE,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAErE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AACxF,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,SAA8B,EAAE,EAA2B,EAAE;IACrF,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1D,MAAM,KAAK,GAAG;QACZ,OAAO,CAAC;YACN,CAAC,CAAC,EAAE,IAAI,CAAC;YACT,CAAC,GAAG,EAAE,GAAG,CAAC;SACX,CAAC;QACF,OAAO,CAAC;YACN,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,IAAI,EAAE,CAAC,CAAC;SACV,CAAC;KACH,CAAC;IACF,gEAAgE;IAChE,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAEtG,OAAO;YACL,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE;YACpF,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE;SAC5G,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE;QAC/G,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;KAC1F,CAAC,CAAC;IACH,MAAM,IAAI,GAAG;QACX,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE;QAC7C,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACpB,MAAM,EAAE;YACN;gBACE,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;aACvG;SACF;QACD,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACxC,oBAAoB,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE;SACxF,CAAC,CAAC;QACH,SAAS;QACT,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC;KAC1C,CAAC;IACF,4EAA4E;IAC5E,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEtC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACrC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,GAAG,UAAU,CAAC,CAAC;IACpC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAClB,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IAClD,GAAG,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,UAAU,CAAC,CAAC;IAErD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,6FAA6F;AAC7F,MAAM,OAAO,GAAG,CAAC,KAAiB,EAAW,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,WAAW,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAEjH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAW,EAAE,CACvD,KAAK,CAAC,IAAI,KAAK,MAAM;IACrB,KAAK,CAAC,cAAc,CAAC,KAAK,YAAY;IACtC,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAE7D,mGAAmG;AACnG,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAiB,EAAU,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["/**\n * The trees of a vector map (`VectorTiles.trees`): a low-poly tree made here as a glTF binary (no file to download),\n * its trunk and its crown flat-shaded in their colors, and the style layers they grow on by default.\n */\n\nimport type { StyleLayer } from './vectorstyle.ts';\n\n/** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank */\nexport const TREE_NUMBERS = 5;\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 */\nconst SIDES = 7;\n\n/** Colors of the trunk and of the crown (linear RGBA, as glTF's `baseColorFactor`) */\nexport interface TreeColors {\n trunk: [number, number, number, number];\n crown: [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};\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 */\nconst revolve = (rings: [height: number, radius: number][]): { 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/** Lowest and highest of interleaved x, y, z (glTF needs them on positions) */\nconst bounds = (xyz: number[]): { min: number[]; max: number[] } => {\n const axes = [0, 1, 2].map((a) => xyz.filter((_, i) => i % 3 === a));\n\n return { min: axes.map((v) => Math.min(...v)), max: axes.map((v) => Math.max(...v)) };\n};\n\n/**\n * A tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`, one mesh of two primitives,\n * its front +Z (`ModelInstance.heading` turns it), standing on its origin\n */\nexport const treeModel = (colors: Partial<TreeColors> = {}): Uint8Array<ArrayBuffer> => {\n const { trunk, crown } = { ...DEFAULT_COLORS, ...colors };\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 // 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: [trunk, crown].map((color) => ({\n pbrMetallicRoughness: { baseColorFactor: color, metallicFactor: 0, roughnessFactor: 1 },\n })),\n accessors,\n bufferViews: views,\n buffers: [{ byteLength: bin.byteLength }],\n };\n // The chunks padded to 4 bytes: the JSON with spaces, the binary with zeros\n const json = new TextEncoder().encode(JSON.stringify(gltf));\n const jsonLength = Math.ceil(json.length / 4) * 4;\n const binLength = Math.ceil(bin.byteLength / 4) * 4;\n const out = new Uint8Array(12 + 8 + jsonLength + 8 + binLength);\n const view = new DataView(out.buffer);\n\n view.setUint32(0, 0x46546c67, true);\n view.setUint32(4, 2, true);\n view.setUint32(8, out.length, true);\n view.setUint32(12, jsonLength, true);\n view.setUint32(16, 0x4e4f534a, true);\n out.fill(0x20, 20, 20 + jsonLength);\n out.set(json, 20);\n view.setUint32(20 + jsonLength, binLength, true);\n view.setUint32(24 + jsonLength, 0x004e4942, true);\n out.set(new Uint8Array(bin.buffer), 28 + jsonLength);\n\n return out;\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"]}
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"]}
@@ -70,10 +70,15 @@ export interface LabelCandidate {
70
70
  lat: number;
71
71
  /** On a line: the direction there (degrees of longitude and latitude) */
72
72
  along?: [number, number];
73
+ /** A text along a line: the line around it (longitudes and latitudes interleaved), as long before it as after it,
74
+ * for the text to follow its bends */
75
+ path?: number[];
73
76
  /** Its text runs along the line (`symbol-placement: line`, `text-rotation-alignment` not `viewport`) */
74
77
  textAlong?: boolean;
75
78
  textOptional?: boolean;
76
79
  icon?: CandidateIcon;
80
+ /** Metres over the ground: a point in a building of the style's, on its roof */
81
+ height?: number;
77
82
  font: string;
78
83
  size: Json;
79
84
  color: string;
@@ -100,10 +105,11 @@ export declare const css: ([r, g, b, a]: [number, number, number, number]) => st
100
105
  export declare const isExpression: (e: unknown) => e is Json[];
101
106
  export declare const evaluate: (e: Json, ctx: Context) => unknown;
102
107
  /** The kind of geometry a style layer is drawn with as vectors (`vectors()`: backgrounds as fills, extrusions raised
103
- * into blocks); undefined for the others (symbols, circles, rasters) and for the layers drawn with a pattern (their
104
- * images are the raster path's) */
105
- export declare const vectorKind: (layer: StyleLayer) => "fill" | "line" | "extrusion" | undefined;
108
+ * into blocks, circles); undefined for the others (symbols, rasters) */
109
+ export declare const vectorKind: (layer: StyleLayer) => "fill" | "line" | "extrusion" | "circle" | undefined;
106
110
  export declare const filter: (f: Json | undefined, ctx: Context) => boolean;
111
+ /** Whether an expression reads the zoom (a filter that does holds at some zooms only) */
112
+ export declare const usesZoom: (e: Json | undefined) => boolean;
107
113
  /** Whether a value depends on the feature (else only on the zoom, evaluated once per tile) */
108
114
  export declare const isFeatureDependent: (e: Json | undefined) => boolean;
109
115
  /** A `{token}` text field (or an expression) to the text of a feature */
@@ -396,17 +396,14 @@ export const evaluate = (e, ctx) => {
396
396
  // ── Filters ──
397
397
  const LEGACY_COMPARISONS = new Set(['==', '!=', '<', '<=', '>', '>=']);
398
398
  /** The kind of geometry a style layer is drawn with as vectors (`vectors()`: backgrounds as fills, extrusions raised
399
- * into blocks); undefined for the others (symbols, circles, rasters) and for the layers drawn with a pattern (their
400
- * images are the raster path's) */
399
+ * into blocks, circles); undefined for the others (symbols, rasters) */
401
400
  export const vectorKind = (layer) => {
402
- const paint = layer.paint ?? {};
403
- if (['fill-pattern', 'line-pattern', 'fill-extrusion-pattern', 'background-pattern'].some((k) => k in paint)) {
404
- return undefined;
405
- }
406
401
  if (layer.type === 'line')
407
402
  return 'line';
408
403
  if (layer.type === 'fill-extrusion')
409
404
  return 'extrusion';
405
+ if (layer.type === 'circle')
406
+ return 'circle';
410
407
  return layer.type === 'fill' || layer.type === 'background' ? 'fill' : undefined;
411
408
  };
412
409
  /** Whether a filter (not `all`, `any`, `none`) is in the legacy form: `["==", "key", value]`, `["in", "key", a, b]`,
@@ -478,6 +475,8 @@ export const filter = (f, ctx) => {
478
475
  return true;
479
476
  return compile(f)(ctx);
480
477
  };
478
+ /** Whether an expression reads the zoom (a filter that does holds at some zooms only) */
479
+ export const usesZoom = (e) => Array.isArray(e) && (e[0] === 'zoom' || e.some(usesZoom));
481
480
  /** The operators that read the feature */
482
481
  const FEATURE_OPERATORS = new Set(['get', 'has', '!has', 'geometry-type', 'properties', 'id']);
483
482
  /** Whether a value depends on the feature (else only on the zoom, evaluated once per tile) */