├── 2023-07-lerc-dem-color-ramp.webp
├── README.md
├── index.deck.html
├── index.html
├── package-lock.json
├── package.json
└── src
├── cogs.ts
├── delatin.ts
├── index.deck.gl.ts
├── index.ts
├── quadkey.ts
└── ramp.ts
/2023-07-lerc-dem-color-ramp.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blacha/lerc-cog-maplibre/9da9c859009c1bfb7d4828ebf5bcebea6bec543e/2023-07-lerc-dem-color-ramp.webp
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LERC COGs as Maplibre DEM source
2 |
3 | 
4 |
5 | Grab some elevation data eg https://data.linz.govt.nz/layer/107436-taranaki-lidar-1m-dem-2021/
6 |
7 | Make VRT
8 |
9 | ```bash
10 | gdalbuildvrt ../BJ29.vrt *.tif
11 | ```
12 |
13 | Create a 3857 LERC COG
14 |
15 | ```bash
16 | gdal_translate -of COG \
17 | -co TILING_SCHEME=GoogleMapsCompatible \
18 | -co NUM_THREADS=ALL_CPUS \
19 | -co BIGTIFF=NO \
20 | -co ADD_ALPHA=YES \
21 | -co BLOCKSIZE=256 \
22 | -co SPARSE_OK=YES \
23 | -co compress=lerc -co max_z_error=0.01 \ # 1cm of error
24 | BJ29.vrt BJ29.lerc.cog.tiff
25 | ```
26 |
27 | bundle everything
28 | ```bash
29 | npm i
30 | npm run bundle
31 | ```
32 |
33 | Start a local webserver
34 | ```bash
35 | serve .
36 | open http://localhost:3000
37 | ```
38 |
--------------------------------------------------------------------------------
/index.deck.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DeckGL example
6 |
7 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | LERC Terrain
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dem-map",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "dem-map",
9 | "version": "1.0.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "@basemaps/geo": "^6.40.0",
13 | "@basemaps/tiler": "^6.40.0",
14 | "@chunkd/source-url": "^6.0.0",
15 | "@cogeotiff/core": "^7.2.1",
16 | "@deck.gl/core": "^8.9.21",
17 | "@deck.gl/geo-layers": "^8.9.21",
18 | "esbuild": "^0.18.11",
19 | "lerc": "^4.0.1",
20 | "maplibre-gl": "^3.2.0"
21 | }
22 | },
23 | "node_modules/@babel/runtime": {
24 | "version": "7.22.6",
25 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
26 | "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
27 | "dependencies": {
28 | "regenerator-runtime": "^0.13.11"
29 | },
30 | "engines": {
31 | "node": ">=6.9.0"
32 | }
33 | },
34 | "node_modules/@basemaps/geo": {
35 | "version": "6.40.0",
36 | "resolved": "https://registry.npmjs.org/@basemaps/geo/-/geo-6.40.0.tgz",
37 | "integrity": "sha512-bhd8Vb4GXyV9XWC1gXg7Hpv/hkvu17wPHfIi7jQiCk20JCvDOql4X0HqbDJDow26AJd7VeWXiLQ/310jXHOREg==",
38 | "dependencies": {
39 | "@linzjs/tile-matrix-set": "^0.0.1"
40 | },
41 | "engines": {
42 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
43 | }
44 | },
45 | "node_modules/@basemaps/tiler": {
46 | "version": "6.40.0",
47 | "resolved": "https://registry.npmjs.org/@basemaps/tiler/-/tiler-6.40.0.tgz",
48 | "integrity": "sha512-zRm6bS9DFM2PbRWwwY0uO/I+cTycI0fUX/T3NwqPd/bTDuRn3TvGYG5oRlqMlttxOtVB4GOjyMarXDTZigJe0Q==",
49 | "dependencies": {
50 | "@basemaps/geo": "^6.40.0",
51 | "@cogeotiff/core": "^7.2.0",
52 | "@linzjs/metrics": "^6.32.1"
53 | },
54 | "engines": {
55 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
56 | }
57 | },
58 | "node_modules/@chunkd/core": {
59 | "version": "6.0.0",
60 | "resolved": "https://registry.npmjs.org/@chunkd/core/-/core-6.0.0.tgz",
61 | "integrity": "sha512-3s11Z4c/4GI6a6U7RWeh5R3Wf/kxcQtSCOy1RK/D3ZPWCDoHkiNkTSCtXUodZWkkHmIhvBl5qdOJEpVDt2B+qQ==",
62 | "engines": {
63 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
64 | }
65 | },
66 | "node_modules/@chunkd/source-url": {
67 | "version": "6.0.0",
68 | "resolved": "https://registry.npmjs.org/@chunkd/source-url/-/source-url-6.0.0.tgz",
69 | "integrity": "sha512-BXKweOJu+bNmDcgqfDUqmMKVln+TrmSFZSSJeLpBVGPg4x8CqemESgUaFVORyER9o4Fhq8MDcLsfdApqDSXsIg==",
70 | "dependencies": {
71 | "@chunkd/core": "^6.0.0",
72 | "node-fetch": "^2.6.0"
73 | },
74 | "engines": {
75 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
76 | }
77 | },
78 | "node_modules/@cogeotiff/core": {
79 | "version": "7.2.1",
80 | "resolved": "https://registry.npmjs.org/@cogeotiff/core/-/core-7.2.1.tgz",
81 | "integrity": "sha512-jA2AvDUFriRNcttMsz8dZxvDw25iNC/iRJWu4ayMIDcY3gJ9jZ1u0AUU9vOSk/o3eIBrMq2aIF17sRZjSIMphw==",
82 | "dependencies": {
83 | "@chunkd/core": "^10.0.0",
84 | "ieee754": "^1.1.13"
85 | },
86 | "engines": {
87 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
88 | }
89 | },
90 | "node_modules/@cogeotiff/core/node_modules/@chunkd/core": {
91 | "version": "10.3.0",
92 | "resolved": "https://registry.npmjs.org/@chunkd/core/-/core-10.3.0.tgz",
93 | "integrity": "sha512-a284uWnisLtDbMBMRMPHWsHConhcozOUmRKhw27FXbleuvoqYAHlwE7nfSFFOg6ho1wWhbEIyVfh/nTz8kLkOA==",
94 | "engines": {
95 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
96 | }
97 | },
98 | "node_modules/@deck.gl/core": {
99 | "version": "8.9.21",
100 | "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-8.9.21.tgz",
101 | "integrity": "sha512-kyPOEkl90T5agiNhIPCool03/4MMQXKoNqSurdXtJS7+xU9FVf7/biTrLxVxWCfF8kqRgxX6sJ4m2PKUwRjV0A==",
102 | "dependencies": {
103 | "@babel/runtime": "^7.0.0",
104 | "@loaders.gl/core": "^3.4.2",
105 | "@loaders.gl/images": "^3.4.2",
106 | "@luma.gl/constants": "^8.5.20",
107 | "@luma.gl/core": "^8.5.20",
108 | "@luma.gl/webgl": "^8.5.20",
109 | "@math.gl/core": "^3.6.2",
110 | "@math.gl/sun": "^3.6.2",
111 | "@math.gl/web-mercator": "^3.6.2",
112 | "@probe.gl/env": "^3.5.0",
113 | "@probe.gl/log": "^3.5.0",
114 | "@probe.gl/stats": "^3.5.0",
115 | "gl-matrix": "^3.0.0",
116 | "math.gl": "^3.6.2",
117 | "mjolnir.js": "^2.7.0"
118 | }
119 | },
120 | "node_modules/@deck.gl/extensions": {
121 | "version": "8.9.21",
122 | "resolved": "https://registry.npmjs.org/@deck.gl/extensions/-/extensions-8.9.21.tgz",
123 | "integrity": "sha512-GIVeRG8K7uJfiKktfsFlgMv5kwKWPEgFkYsxxr/NY6UnqNRgAn9B+aH6YgJ4Hu22xwjUTOtzrX6BrSnsQI3kOg==",
124 | "peer": true,
125 | "dependencies": {
126 | "@babel/runtime": "^7.0.0",
127 | "@luma.gl/shadertools": "^8.5.20"
128 | },
129 | "peerDependencies": {
130 | "@deck.gl/core": "^8.0.0",
131 | "@luma.gl/constants": "^8.0.0",
132 | "@luma.gl/core": "^8.0.0",
133 | "@math.gl/core": "^3.6.2",
134 | "@math.gl/web-mercator": "^3.6.2",
135 | "gl-matrix": "^3.0.0"
136 | }
137 | },
138 | "node_modules/@deck.gl/geo-layers": {
139 | "version": "8.9.21",
140 | "resolved": "https://registry.npmjs.org/@deck.gl/geo-layers/-/geo-layers-8.9.21.tgz",
141 | "integrity": "sha512-JS01acqO6weF9MUAdT/GVGABMHbkWKB/ZRinJ0HBqOyiZNpJ9k8SpwCiBP8jDwYfQ9Ziz8SGFNU/DmtNI9Vgxg==",
142 | "dependencies": {
143 | "@babel/runtime": "^7.0.0",
144 | "@loaders.gl/3d-tiles": "^3.4.2",
145 | "@loaders.gl/gis": "^3.4.2",
146 | "@loaders.gl/loader-utils": "^3.4.2",
147 | "@loaders.gl/mvt": "^3.4.2",
148 | "@loaders.gl/schema": "^3.4.2",
149 | "@loaders.gl/terrain": "^3.4.2",
150 | "@loaders.gl/tiles": "^3.4.2",
151 | "@loaders.gl/wms": "^3.4.2",
152 | "@luma.gl/constants": "^8.5.20",
153 | "@luma.gl/experimental": "^8.5.20",
154 | "@math.gl/core": "^3.6.2",
155 | "@math.gl/culling": "^3.6.2",
156 | "@math.gl/web-mercator": "^3.6.2",
157 | "@types/geojson": "^7946.0.8",
158 | "h3-js": "^3.7.0",
159 | "long": "^3.2.0"
160 | },
161 | "peerDependencies": {
162 | "@deck.gl/core": "^8.0.0",
163 | "@deck.gl/extensions": "^8.0.0",
164 | "@deck.gl/layers": "^8.0.0",
165 | "@deck.gl/mesh-layers": "^8.0.0",
166 | "@loaders.gl/core": "^3.4.2",
167 | "@luma.gl/core": "^8.0.0"
168 | }
169 | },
170 | "node_modules/@deck.gl/layers": {
171 | "version": "8.9.21",
172 | "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-8.9.21.tgz",
173 | "integrity": "sha512-tNxbBhFcc81mBaSK+zNxvhlmZmQNuYmUJMWymWMq5vz5MLTE6hHNjLY5n181ZSYspHDA/7tsjXXZ5c/+MGru2g==",
174 | "peer": true,
175 | "dependencies": {
176 | "@babel/runtime": "^7.0.0",
177 | "@loaders.gl/images": "^3.4.2",
178 | "@loaders.gl/schema": "^3.4.2",
179 | "@luma.gl/constants": "^8.5.20",
180 | "@mapbox/tiny-sdf": "^2.0.5",
181 | "@math.gl/core": "^3.6.2",
182 | "@math.gl/polygon": "^3.6.2",
183 | "@math.gl/web-mercator": "^3.6.2",
184 | "earcut": "^2.2.4"
185 | },
186 | "peerDependencies": {
187 | "@deck.gl/core": "^8.0.0",
188 | "@loaders.gl/core": "^3.4.2",
189 | "@luma.gl/core": "^8.0.0"
190 | }
191 | },
192 | "node_modules/@deck.gl/mesh-layers": {
193 | "version": "8.9.21",
194 | "resolved": "https://registry.npmjs.org/@deck.gl/mesh-layers/-/mesh-layers-8.9.21.tgz",
195 | "integrity": "sha512-alTRtuZADvz18txumJeE/cTJQ6I1DqYDHGGFHA/FlKA3kYcy91Te4evHSok/+k8xlNyzf26cjgs9EoHAbUDpuQ==",
196 | "peer": true,
197 | "dependencies": {
198 | "@babel/runtime": "^7.0.0",
199 | "@loaders.gl/gltf": "^3.4.2",
200 | "@luma.gl/constants": "^8.5.20",
201 | "@luma.gl/experimental": "^8.5.20",
202 | "@luma.gl/shadertools": "^8.5.20"
203 | },
204 | "peerDependencies": {
205 | "@deck.gl/core": "^8.0.0",
206 | "@luma.gl/core": "^8.0.0"
207 | }
208 | },
209 | "node_modules/@esbuild/android-arm": {
210 | "version": "0.18.11",
211 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz",
212 | "integrity": "sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==",
213 | "cpu": [
214 | "arm"
215 | ],
216 | "optional": true,
217 | "os": [
218 | "android"
219 | ],
220 | "engines": {
221 | "node": ">=12"
222 | }
223 | },
224 | "node_modules/@esbuild/android-arm64": {
225 | "version": "0.18.11",
226 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.11.tgz",
227 | "integrity": "sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==",
228 | "cpu": [
229 | "arm64"
230 | ],
231 | "optional": true,
232 | "os": [
233 | "android"
234 | ],
235 | "engines": {
236 | "node": ">=12"
237 | }
238 | },
239 | "node_modules/@esbuild/android-x64": {
240 | "version": "0.18.11",
241 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.11.tgz",
242 | "integrity": "sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==",
243 | "cpu": [
244 | "x64"
245 | ],
246 | "optional": true,
247 | "os": [
248 | "android"
249 | ],
250 | "engines": {
251 | "node": ">=12"
252 | }
253 | },
254 | "node_modules/@esbuild/darwin-arm64": {
255 | "version": "0.18.11",
256 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.11.tgz",
257 | "integrity": "sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==",
258 | "cpu": [
259 | "arm64"
260 | ],
261 | "optional": true,
262 | "os": [
263 | "darwin"
264 | ],
265 | "engines": {
266 | "node": ">=12"
267 | }
268 | },
269 | "node_modules/@esbuild/darwin-x64": {
270 | "version": "0.18.11",
271 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.11.tgz",
272 | "integrity": "sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==",
273 | "cpu": [
274 | "x64"
275 | ],
276 | "optional": true,
277 | "os": [
278 | "darwin"
279 | ],
280 | "engines": {
281 | "node": ">=12"
282 | }
283 | },
284 | "node_modules/@esbuild/freebsd-arm64": {
285 | "version": "0.18.11",
286 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.11.tgz",
287 | "integrity": "sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==",
288 | "cpu": [
289 | "arm64"
290 | ],
291 | "optional": true,
292 | "os": [
293 | "freebsd"
294 | ],
295 | "engines": {
296 | "node": ">=12"
297 | }
298 | },
299 | "node_modules/@esbuild/freebsd-x64": {
300 | "version": "0.18.11",
301 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.11.tgz",
302 | "integrity": "sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==",
303 | "cpu": [
304 | "x64"
305 | ],
306 | "optional": true,
307 | "os": [
308 | "freebsd"
309 | ],
310 | "engines": {
311 | "node": ">=12"
312 | }
313 | },
314 | "node_modules/@esbuild/linux-arm": {
315 | "version": "0.18.11",
316 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.11.tgz",
317 | "integrity": "sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==",
318 | "cpu": [
319 | "arm"
320 | ],
321 | "optional": true,
322 | "os": [
323 | "linux"
324 | ],
325 | "engines": {
326 | "node": ">=12"
327 | }
328 | },
329 | "node_modules/@esbuild/linux-arm64": {
330 | "version": "0.18.11",
331 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.11.tgz",
332 | "integrity": "sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==",
333 | "cpu": [
334 | "arm64"
335 | ],
336 | "optional": true,
337 | "os": [
338 | "linux"
339 | ],
340 | "engines": {
341 | "node": ">=12"
342 | }
343 | },
344 | "node_modules/@esbuild/linux-ia32": {
345 | "version": "0.18.11",
346 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.11.tgz",
347 | "integrity": "sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==",
348 | "cpu": [
349 | "ia32"
350 | ],
351 | "optional": true,
352 | "os": [
353 | "linux"
354 | ],
355 | "engines": {
356 | "node": ">=12"
357 | }
358 | },
359 | "node_modules/@esbuild/linux-loong64": {
360 | "version": "0.18.11",
361 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.11.tgz",
362 | "integrity": "sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==",
363 | "cpu": [
364 | "loong64"
365 | ],
366 | "optional": true,
367 | "os": [
368 | "linux"
369 | ],
370 | "engines": {
371 | "node": ">=12"
372 | }
373 | },
374 | "node_modules/@esbuild/linux-mips64el": {
375 | "version": "0.18.11",
376 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.11.tgz",
377 | "integrity": "sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==",
378 | "cpu": [
379 | "mips64el"
380 | ],
381 | "optional": true,
382 | "os": [
383 | "linux"
384 | ],
385 | "engines": {
386 | "node": ">=12"
387 | }
388 | },
389 | "node_modules/@esbuild/linux-ppc64": {
390 | "version": "0.18.11",
391 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.11.tgz",
392 | "integrity": "sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==",
393 | "cpu": [
394 | "ppc64"
395 | ],
396 | "optional": true,
397 | "os": [
398 | "linux"
399 | ],
400 | "engines": {
401 | "node": ">=12"
402 | }
403 | },
404 | "node_modules/@esbuild/linux-riscv64": {
405 | "version": "0.18.11",
406 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.11.tgz",
407 | "integrity": "sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==",
408 | "cpu": [
409 | "riscv64"
410 | ],
411 | "optional": true,
412 | "os": [
413 | "linux"
414 | ],
415 | "engines": {
416 | "node": ">=12"
417 | }
418 | },
419 | "node_modules/@esbuild/linux-s390x": {
420 | "version": "0.18.11",
421 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.11.tgz",
422 | "integrity": "sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==",
423 | "cpu": [
424 | "s390x"
425 | ],
426 | "optional": true,
427 | "os": [
428 | "linux"
429 | ],
430 | "engines": {
431 | "node": ">=12"
432 | }
433 | },
434 | "node_modules/@esbuild/linux-x64": {
435 | "version": "0.18.11",
436 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.11.tgz",
437 | "integrity": "sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==",
438 | "cpu": [
439 | "x64"
440 | ],
441 | "optional": true,
442 | "os": [
443 | "linux"
444 | ],
445 | "engines": {
446 | "node": ">=12"
447 | }
448 | },
449 | "node_modules/@esbuild/netbsd-x64": {
450 | "version": "0.18.11",
451 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.11.tgz",
452 | "integrity": "sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==",
453 | "cpu": [
454 | "x64"
455 | ],
456 | "optional": true,
457 | "os": [
458 | "netbsd"
459 | ],
460 | "engines": {
461 | "node": ">=12"
462 | }
463 | },
464 | "node_modules/@esbuild/openbsd-x64": {
465 | "version": "0.18.11",
466 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.11.tgz",
467 | "integrity": "sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==",
468 | "cpu": [
469 | "x64"
470 | ],
471 | "optional": true,
472 | "os": [
473 | "openbsd"
474 | ],
475 | "engines": {
476 | "node": ">=12"
477 | }
478 | },
479 | "node_modules/@esbuild/sunos-x64": {
480 | "version": "0.18.11",
481 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.11.tgz",
482 | "integrity": "sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==",
483 | "cpu": [
484 | "x64"
485 | ],
486 | "optional": true,
487 | "os": [
488 | "sunos"
489 | ],
490 | "engines": {
491 | "node": ">=12"
492 | }
493 | },
494 | "node_modules/@esbuild/win32-arm64": {
495 | "version": "0.18.11",
496 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.11.tgz",
497 | "integrity": "sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==",
498 | "cpu": [
499 | "arm64"
500 | ],
501 | "optional": true,
502 | "os": [
503 | "win32"
504 | ],
505 | "engines": {
506 | "node": ">=12"
507 | }
508 | },
509 | "node_modules/@esbuild/win32-ia32": {
510 | "version": "0.18.11",
511 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.11.tgz",
512 | "integrity": "sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==",
513 | "cpu": [
514 | "ia32"
515 | ],
516 | "optional": true,
517 | "os": [
518 | "win32"
519 | ],
520 | "engines": {
521 | "node": ">=12"
522 | }
523 | },
524 | "node_modules/@esbuild/win32-x64": {
525 | "version": "0.18.11",
526 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.11.tgz",
527 | "integrity": "sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==",
528 | "cpu": [
529 | "x64"
530 | ],
531 | "optional": true,
532 | "os": [
533 | "win32"
534 | ],
535 | "engines": {
536 | "node": ">=12"
537 | }
538 | },
539 | "node_modules/@linzjs/metrics": {
540 | "version": "6.32.1",
541 | "resolved": "https://registry.npmjs.org/@linzjs/metrics/-/metrics-6.32.1.tgz",
542 | "integrity": "sha512-QC2qYaYJkY2lnjHv6DGW3dbKkGO/ksyXMswhI6Mi27qcQxOi+gC8/Pac51op8/E4d/hmHyULCdCsCHKC2uTiLw==",
543 | "engines": {
544 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
545 | }
546 | },
547 | "node_modules/@linzjs/tile-matrix-set": {
548 | "version": "0.0.1",
549 | "resolved": "https://registry.npmjs.org/@linzjs/tile-matrix-set/-/tile-matrix-set-0.0.1.tgz",
550 | "integrity": "sha512-qGyk/PUw6JWdYzHh4RHi3NUDdBCVJLQuT3HJbDwWZQF9bsqZcBSv8Irtd7Gu3U8WdyTNtazxh2eUxKRG7IzqYQ=="
551 | },
552 | "node_modules/@loaders.gl/3d-tiles": {
553 | "version": "3.4.6",
554 | "resolved": "https://registry.npmjs.org/@loaders.gl/3d-tiles/-/3d-tiles-3.4.6.tgz",
555 | "integrity": "sha512-oM+wOg/HeYl8249Eq3fLT6L2ZU1wFXdXcyUsenaUubxuCKbWk/mwFyqHq3NINcy7K56TUlEXwxpaiRiIhZa9WA==",
556 | "dependencies": {
557 | "@loaders.gl/draco": "3.4.6",
558 | "@loaders.gl/gltf": "3.4.6",
559 | "@loaders.gl/loader-utils": "3.4.6",
560 | "@loaders.gl/math": "3.4.6",
561 | "@loaders.gl/tiles": "3.4.6",
562 | "@math.gl/core": "^3.5.1",
563 | "@math.gl/geospatial": "^3.5.1",
564 | "long": "^5.2.1"
565 | },
566 | "peerDependencies": {
567 | "@loaders.gl/core": "^3.4.0"
568 | }
569 | },
570 | "node_modules/@loaders.gl/3d-tiles/node_modules/long": {
571 | "version": "5.2.3",
572 | "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
573 | "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
574 | },
575 | "node_modules/@loaders.gl/core": {
576 | "version": "3.4.6",
577 | "resolved": "https://registry.npmjs.org/@loaders.gl/core/-/core-3.4.6.tgz",
578 | "integrity": "sha512-9nang7w+McOg3ZippyFNz0+FuJu4bSkQkwpnIjUEr61JUiwpmRy5IakZP/LnmhZuzCy5+lDFj921md/l8Tduaw==",
579 | "dependencies": {
580 | "@babel/runtime": "^7.3.1",
581 | "@loaders.gl/loader-utils": "3.4.6",
582 | "@loaders.gl/worker-utils": "3.4.6",
583 | "@probe.gl/log": "^4.0.1"
584 | }
585 | },
586 | "node_modules/@loaders.gl/core/node_modules/@probe.gl/env": {
587 | "version": "4.0.4",
588 | "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-4.0.4.tgz",
589 | "integrity": "sha512-sYNGqesDfWD6dFP5oNZtTeFA4Z6ak5T4a8BNPdNhoqy7PK9w70JHrb6mv+RKWqKXq33KiwCDWL7fYxx2HuEH2w==",
590 | "dependencies": {
591 | "@babel/runtime": "^7.0.0"
592 | }
593 | },
594 | "node_modules/@loaders.gl/core/node_modules/@probe.gl/log": {
595 | "version": "4.0.4",
596 | "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-4.0.4.tgz",
597 | "integrity": "sha512-WpmXl6njlBMwrm8HBh/b4kSp/xnY1VVmeT4PWUKF+RkVbFuKQbsU11dA1IxoMd7gSY+5DGIwxGfAv1H5OMzA4A==",
598 | "dependencies": {
599 | "@babel/runtime": "^7.0.0",
600 | "@probe.gl/env": "4.0.4"
601 | }
602 | },
603 | "node_modules/@loaders.gl/draco": {
604 | "version": "3.4.6",
605 | "resolved": "https://registry.npmjs.org/@loaders.gl/draco/-/draco-3.4.6.tgz",
606 | "integrity": "sha512-FoxmvM0ojT1B5yntyQ/mzrWN55XyOOqPiie99Bs8yLj9+eNAfQoviMfrED1uS6gYVJEHNBmH9wibNaa1LjMTmw==",
607 | "dependencies": {
608 | "@babel/runtime": "^7.3.1",
609 | "@loaders.gl/loader-utils": "3.4.6",
610 | "@loaders.gl/schema": "3.4.6",
611 | "@loaders.gl/worker-utils": "3.4.6",
612 | "draco3d": "1.5.5"
613 | }
614 | },
615 | "node_modules/@loaders.gl/gis": {
616 | "version": "3.4.6",
617 | "resolved": "https://registry.npmjs.org/@loaders.gl/gis/-/gis-3.4.6.tgz",
618 | "integrity": "sha512-DKG1oBjz7KYe/VInST3Hsnzo+E3cAv9cOvS6EA34YRMSb1T4xOmdvTpoN6x5/WZU7VBTK376F7TidMNskKOMoA==",
619 | "dependencies": {
620 | "@loaders.gl/loader-utils": "3.4.6",
621 | "@loaders.gl/schema": "3.4.6",
622 | "@mapbox/vector-tile": "^1.3.1",
623 | "@math.gl/polygon": "^3.5.1",
624 | "pbf": "^3.2.1"
625 | }
626 | },
627 | "node_modules/@loaders.gl/gltf": {
628 | "version": "3.4.6",
629 | "resolved": "https://registry.npmjs.org/@loaders.gl/gltf/-/gltf-3.4.6.tgz",
630 | "integrity": "sha512-BB2Hkz8dTr6IbgccGb6y9QYdXyqbi5L8qIlEldA3P7f36y9EN1JVTBUxyF8hHqPt3YKgJ0RKX9F2YLRrhWT1gw==",
631 | "dependencies": {
632 | "@loaders.gl/draco": "3.4.6",
633 | "@loaders.gl/images": "3.4.6",
634 | "@loaders.gl/loader-utils": "3.4.6",
635 | "@loaders.gl/textures": "3.4.6",
636 | "@math.gl/core": "^3.5.1"
637 | }
638 | },
639 | "node_modules/@loaders.gl/images": {
640 | "version": "3.4.6",
641 | "resolved": "https://registry.npmjs.org/@loaders.gl/images/-/images-3.4.6.tgz",
642 | "integrity": "sha512-zwM6lXATGxxIe27X1gPyqcgXb6ql9gPkoNlb5pWOrF1D8DrFFjTJSLV9p6WGrVKMZKeioJ2PK8ZnkeRiOYkveA==",
643 | "dependencies": {
644 | "@loaders.gl/loader-utils": "3.4.6"
645 | }
646 | },
647 | "node_modules/@loaders.gl/loader-utils": {
648 | "version": "3.4.6",
649 | "resolved": "https://registry.npmjs.org/@loaders.gl/loader-utils/-/loader-utils-3.4.6.tgz",
650 | "integrity": "sha512-AN56Tvomas7bOZlrMEDforJWwS6DuXXFT/MsxOR/2vvzhutLDxYSuG4dZ9g5ejqJkiboDLAL3aghXXWekyToaw==",
651 | "dependencies": {
652 | "@babel/runtime": "^7.3.1",
653 | "@loaders.gl/worker-utils": "3.4.6",
654 | "@probe.gl/stats": "^4.0.1"
655 | }
656 | },
657 | "node_modules/@loaders.gl/loader-utils/node_modules/@probe.gl/stats": {
658 | "version": "4.0.4",
659 | "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-4.0.4.tgz",
660 | "integrity": "sha512-SDuSY/D4yDL6LQDa69l/GCcnZLRiGYdyvYkxWb0CgnzTPdPrcdrzGkzkvpC3zsA4fEFw2smlDje370QGHwlisg==",
661 | "dependencies": {
662 | "@babel/runtime": "^7.0.0"
663 | }
664 | },
665 | "node_modules/@loaders.gl/math": {
666 | "version": "3.4.6",
667 | "resolved": "https://registry.npmjs.org/@loaders.gl/math/-/math-3.4.6.tgz",
668 | "integrity": "sha512-FC+BSp6NqMH372wkVS92yb+YIP2a26Mi1nEj8eiyRadxkQoyZ2bKH2kxoNX40yCo1xk/ZyX2v8wYq3ZNS+9fIg==",
669 | "dependencies": {
670 | "@loaders.gl/images": "3.4.6",
671 | "@loaders.gl/loader-utils": "3.4.6",
672 | "@math.gl/core": "^3.5.1"
673 | }
674 | },
675 | "node_modules/@loaders.gl/mvt": {
676 | "version": "3.4.6",
677 | "resolved": "https://registry.npmjs.org/@loaders.gl/mvt/-/mvt-3.4.6.tgz",
678 | "integrity": "sha512-fzZjuY5mS7p3IBu5MSyiHAvRUz2MEX1w0tRW/AlNiBn3SaEKqt8rei7Fir7QTNxK5qEBoTUDr5jOg1wH9SCC7Q==",
679 | "dependencies": {
680 | "@loaders.gl/gis": "3.4.6",
681 | "@loaders.gl/loader-utils": "3.4.6",
682 | "@loaders.gl/schema": "3.4.6",
683 | "@math.gl/polygon": "^3.5.1",
684 | "pbf": "^3.2.1"
685 | }
686 | },
687 | "node_modules/@loaders.gl/schema": {
688 | "version": "3.4.6",
689 | "resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-3.4.6.tgz",
690 | "integrity": "sha512-uvToDknGCEL0TIZY1Rn76lQ0m22kUtVxE0HbgfgzwkT7dlXeT92F5yD4VVVL8qTX4oqh2xUySPQIaiAqdkGCvg==",
691 | "dependencies": {
692 | "@types/geojson": "^7946.0.7"
693 | }
694 | },
695 | "node_modules/@loaders.gl/terrain": {
696 | "version": "3.4.6",
697 | "resolved": "https://registry.npmjs.org/@loaders.gl/terrain/-/terrain-3.4.6.tgz",
698 | "integrity": "sha512-Ki/t1wtroBqvPf1XxKdVKWjZ8BwEw4mxIHbWg+vRauxU7T3m85Bfp1KMF49E8jAa5HGikenD2Qumf5jC66GNSQ==",
699 | "dependencies": {
700 | "@babel/runtime": "^7.3.1",
701 | "@loaders.gl/images": "3.4.6",
702 | "@loaders.gl/loader-utils": "3.4.6",
703 | "@loaders.gl/schema": "3.4.6",
704 | "@mapbox/martini": "^0.2.0"
705 | }
706 | },
707 | "node_modules/@loaders.gl/textures": {
708 | "version": "3.4.6",
709 | "resolved": "https://registry.npmjs.org/@loaders.gl/textures/-/textures-3.4.6.tgz",
710 | "integrity": "sha512-eeYFD0kWwkKwUWQ/sNHMP0wDiG2XsTWPY4rWV9RZRY955p+7q11Xoksqc3M4g8/DJ5+gYnBHyJMM3Tg4cG5Uhg==",
711 | "dependencies": {
712 | "@loaders.gl/images": "3.4.6",
713 | "@loaders.gl/loader-utils": "3.4.6",
714 | "@loaders.gl/schema": "3.4.6",
715 | "@loaders.gl/worker-utils": "3.4.6",
716 | "ktx-parse": "^0.0.4",
717 | "texture-compressor": "^1.0.2"
718 | }
719 | },
720 | "node_modules/@loaders.gl/tiles": {
721 | "version": "3.4.6",
722 | "resolved": "https://registry.npmjs.org/@loaders.gl/tiles/-/tiles-3.4.6.tgz",
723 | "integrity": "sha512-Tl9H9Gt8p8ZOJGdWjkdAHXjyr3UAArimC/DRRHbP70Zpipgo/qgSfYPbkGih20dvuoj4uuNe9pwSrk9ctmpxMg==",
724 | "dependencies": {
725 | "@loaders.gl/loader-utils": "3.4.6",
726 | "@loaders.gl/math": "3.4.6",
727 | "@math.gl/core": "^3.5.1",
728 | "@math.gl/culling": "^3.5.1",
729 | "@math.gl/geospatial": "^3.5.1",
730 | "@math.gl/web-mercator": "^3.5.1",
731 | "@probe.gl/stats": "^4.0.1"
732 | },
733 | "peerDependencies": {
734 | "@loaders.gl/core": "^3.4.0"
735 | }
736 | },
737 | "node_modules/@loaders.gl/tiles/node_modules/@probe.gl/stats": {
738 | "version": "4.0.4",
739 | "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-4.0.4.tgz",
740 | "integrity": "sha512-SDuSY/D4yDL6LQDa69l/GCcnZLRiGYdyvYkxWb0CgnzTPdPrcdrzGkzkvpC3zsA4fEFw2smlDje370QGHwlisg==",
741 | "dependencies": {
742 | "@babel/runtime": "^7.0.0"
743 | }
744 | },
745 | "node_modules/@loaders.gl/wms": {
746 | "version": "3.4.6",
747 | "resolved": "https://registry.npmjs.org/@loaders.gl/wms/-/wms-3.4.6.tgz",
748 | "integrity": "sha512-LkVaIM36Nqp8rTmeSVnHxHXdq8NRjnoXC0bSoDW3WzClYIcQmMf43zHzi2zQf0Y1O/DH+6oLo9ueOtGKc8VfLA==",
749 | "dependencies": {
750 | "@babel/runtime": "^7.3.1",
751 | "@loaders.gl/images": "3.4.6",
752 | "@loaders.gl/loader-utils": "3.4.6",
753 | "@loaders.gl/schema": "3.4.6",
754 | "@loaders.gl/xml": "3.4.6",
755 | "@turf/rewind": "^5.1.5",
756 | "deep-strict-equal": "^0.2.0",
757 | "lerc": "^4.0.1"
758 | }
759 | },
760 | "node_modules/@loaders.gl/worker-utils": {
761 | "version": "3.4.6",
762 | "resolved": "https://registry.npmjs.org/@loaders.gl/worker-utils/-/worker-utils-3.4.6.tgz",
763 | "integrity": "sha512-1Ns2d5HbJ22u9PDfEqoDWhg2F3zyYZUCQBmfmSW9Yuxblt2M0pRyB01VvAhPCnLovldvesHu+o16FsgkqieybQ==",
764 | "dependencies": {
765 | "@babel/runtime": "^7.3.1"
766 | }
767 | },
768 | "node_modules/@loaders.gl/xml": {
769 | "version": "3.4.6",
770 | "resolved": "https://registry.npmjs.org/@loaders.gl/xml/-/xml-3.4.6.tgz",
771 | "integrity": "sha512-kB3R2Wz9d/UEDka5Fhjv/MoIXK2dB57J7nQIXmFpdCVJKPUIm9aZXyqODcCMNoufSR2PI5uqxJ12a14vV3WZsQ==",
772 | "dependencies": {
773 | "@babel/runtime": "^7.3.1",
774 | "@loaders.gl/loader-utils": "3.4.6",
775 | "@loaders.gl/schema": "3.4.6",
776 | "fast-xml-parser": "^4.1.3"
777 | }
778 | },
779 | "node_modules/@luma.gl/constants": {
780 | "version": "8.5.20",
781 | "resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-8.5.20.tgz",
782 | "integrity": "sha512-5yG+ybkUZ4j6kLPWMZjN4Hun2yLB0MyEpNCRKAUN9/yS9UIWA7unyVxjSf2vnE7k/7dywtxlbXegASNFgNVGxw=="
783 | },
784 | "node_modules/@luma.gl/core": {
785 | "version": "8.5.20",
786 | "resolved": "https://registry.npmjs.org/@luma.gl/core/-/core-8.5.20.tgz",
787 | "integrity": "sha512-xJr96G6vhYcznYHC84fbeOG3fgNM4lFwj9bd0VPcg/Kfe8otUeN1Hl0AKHCCtNn48PiMSg3LKbaiRfNUMhaffQ==",
788 | "dependencies": {
789 | "@babel/runtime": "^7.0.0",
790 | "@luma.gl/constants": "8.5.20",
791 | "@luma.gl/engine": "8.5.20",
792 | "@luma.gl/gltools": "8.5.20",
793 | "@luma.gl/shadertools": "8.5.20",
794 | "@luma.gl/webgl": "8.5.20"
795 | }
796 | },
797 | "node_modules/@luma.gl/engine": {
798 | "version": "8.5.20",
799 | "resolved": "https://registry.npmjs.org/@luma.gl/engine/-/engine-8.5.20.tgz",
800 | "integrity": "sha512-+0ryJ/4gL1pWaEgZimY21jUPt1LYiO6Cqte8TNUprCfAHoAStsuzD7jwgEqnM6jJOUEdIxQ3w0z3Dzw/0KIE+w==",
801 | "dependencies": {
802 | "@babel/runtime": "^7.0.0",
803 | "@luma.gl/constants": "8.5.20",
804 | "@luma.gl/gltools": "8.5.20",
805 | "@luma.gl/shadertools": "8.5.20",
806 | "@luma.gl/webgl": "8.5.20",
807 | "@math.gl/core": "^3.5.0",
808 | "@probe.gl/env": "^3.5.0",
809 | "@probe.gl/stats": "^3.5.0",
810 | "@types/offscreencanvas": "^2019.7.0"
811 | }
812 | },
813 | "node_modules/@luma.gl/experimental": {
814 | "version": "8.5.20",
815 | "resolved": "https://registry.npmjs.org/@luma.gl/experimental/-/experimental-8.5.20.tgz",
816 | "integrity": "sha512-V1Jp68rYMPtwMdf+50r3NSYsGV3srjwZ+lcK2ew4DshjedDbYwLqTGMWcOyBhY3K3aCl2LH3Fhn0hAY+3NTLGA==",
817 | "dependencies": {
818 | "@luma.gl/constants": "8.5.20",
819 | "@math.gl/core": "^3.5.0",
820 | "earcut": "^2.0.6"
821 | },
822 | "peerDependencies": {
823 | "@loaders.gl/gltf": "^3.0.0",
824 | "@loaders.gl/images": "^3.0.0",
825 | "@luma.gl/engine": "^8.4.0",
826 | "@luma.gl/gltools": "^8.4.0",
827 | "@luma.gl/shadertools": "^8.4.0",
828 | "@luma.gl/webgl": "^8.4.0"
829 | }
830 | },
831 | "node_modules/@luma.gl/gltools": {
832 | "version": "8.5.20",
833 | "resolved": "https://registry.npmjs.org/@luma.gl/gltools/-/gltools-8.5.20.tgz",
834 | "integrity": "sha512-5pP6ph9FSX5gHiVWQM1DmYRUnriklzKUG9yaqlQsKEqCFsOcKB0EfK3MfBVXIfsOdP/1bJZ9Dlz/zV19soWVhg==",
835 | "dependencies": {
836 | "@babel/runtime": "^7.0.0",
837 | "@luma.gl/constants": "8.5.20",
838 | "@probe.gl/env": "^3.5.0",
839 | "@probe.gl/log": "^3.5.0",
840 | "@types/offscreencanvas": "^2019.7.0"
841 | }
842 | },
843 | "node_modules/@luma.gl/shadertools": {
844 | "version": "8.5.20",
845 | "resolved": "https://registry.npmjs.org/@luma.gl/shadertools/-/shadertools-8.5.20.tgz",
846 | "integrity": "sha512-q1lrCZy1ncIFb4mMjsYgISLzNP6eMnhLUY+Oltj/qjAMcPEssCeHN2+XGfP/CVtU+O7sC+5JY2bQGaTs6HQ/Qw==",
847 | "dependencies": {
848 | "@babel/runtime": "^7.0.0",
849 | "@math.gl/core": "^3.5.0"
850 | }
851 | },
852 | "node_modules/@luma.gl/webgl": {
853 | "version": "8.5.20",
854 | "resolved": "https://registry.npmjs.org/@luma.gl/webgl/-/webgl-8.5.20.tgz",
855 | "integrity": "sha512-p/kt9KztywH4l+09XHoZ4cPFOoE7xlZXIBMT8rxRVgfe1w0lvi7QYh4tOG7gk+iixQ34EyDQacoHCsabdpmqQg==",
856 | "dependencies": {
857 | "@babel/runtime": "^7.0.0",
858 | "@luma.gl/constants": "8.5.20",
859 | "@luma.gl/gltools": "8.5.20",
860 | "@probe.gl/env": "^3.5.0",
861 | "@probe.gl/stats": "^3.5.0"
862 | }
863 | },
864 | "node_modules/@mapbox/geojson-rewind": {
865 | "version": "0.5.2",
866 | "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz",
867 | "integrity": "sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==",
868 | "dependencies": {
869 | "get-stream": "^6.0.1",
870 | "minimist": "^1.2.6"
871 | },
872 | "bin": {
873 | "geojson-rewind": "geojson-rewind"
874 | }
875 | },
876 | "node_modules/@mapbox/jsonlint-lines-primitives": {
877 | "version": "2.0.2",
878 | "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz",
879 | "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==",
880 | "engines": {
881 | "node": ">= 0.6"
882 | }
883 | },
884 | "node_modules/@mapbox/martini": {
885 | "version": "0.2.0",
886 | "resolved": "https://registry.npmjs.org/@mapbox/martini/-/martini-0.2.0.tgz",
887 | "integrity": "sha512-7hFhtkb0KTLEls+TRw/rWayq5EeHtTaErgm/NskVoXmtgAQu/9D299aeyj6mzAR/6XUnYRp2lU+4IcrYRFjVsQ=="
888 | },
889 | "node_modules/@mapbox/point-geometry": {
890 | "version": "0.1.0",
891 | "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
892 | "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ=="
893 | },
894 | "node_modules/@mapbox/tiny-sdf": {
895 | "version": "2.0.6",
896 | "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz",
897 | "integrity": "sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA=="
898 | },
899 | "node_modules/@mapbox/unitbezier": {
900 | "version": "0.0.1",
901 | "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz",
902 | "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw=="
903 | },
904 | "node_modules/@mapbox/vector-tile": {
905 | "version": "1.3.1",
906 | "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz",
907 | "integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==",
908 | "dependencies": {
909 | "@mapbox/point-geometry": "~0.1.0"
910 | }
911 | },
912 | "node_modules/@mapbox/whoots-js": {
913 | "version": "3.1.0",
914 | "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz",
915 | "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==",
916 | "engines": {
917 | "node": ">=6.0.0"
918 | }
919 | },
920 | "node_modules/@maplibre/maplibre-gl-style-spec": {
921 | "version": "19.2.1",
922 | "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.2.1.tgz",
923 | "integrity": "sha512-ZVT5QlkVhlxlPav+ca0NO3Moc7EzbHDO2FXW4ic3Q0Vm+TDUw9I8A2EBws7xUUQZf7HQB3kQ+3Jsh5mFLRD4GQ==",
924 | "dependencies": {
925 | "@mapbox/jsonlint-lines-primitives": "~2.0.2",
926 | "@mapbox/point-geometry": "^0.1.0",
927 | "@mapbox/unitbezier": "^0.0.1",
928 | "@types/mapbox__point-geometry": "^0.1.2",
929 | "json-stringify-pretty-compact": "^3.0.0",
930 | "minimist": "^1.2.8",
931 | "rw": "^1.3.3",
932 | "sort-object": "^3.0.3"
933 | },
934 | "bin": {
935 | "gl-style-format": "dist/gl-style-format.mjs",
936 | "gl-style-migrate": "dist/gl-style-migrate.mjs",
937 | "gl-style-validate": "dist/gl-style-validate.mjs"
938 | }
939 | },
940 | "node_modules/@math.gl/core": {
941 | "version": "3.6.3",
942 | "resolved": "https://registry.npmjs.org/@math.gl/core/-/core-3.6.3.tgz",
943 | "integrity": "sha512-jBABmDkj5uuuE0dTDmwwss7Cup5ZwQ6Qb7h1pgvtkEutTrhkcv8SuItQNXmF45494yIHeoGue08NlyeY6wxq2A==",
944 | "dependencies": {
945 | "@babel/runtime": "^7.12.0",
946 | "@math.gl/types": "3.6.3",
947 | "gl-matrix": "^3.4.0"
948 | }
949 | },
950 | "node_modules/@math.gl/culling": {
951 | "version": "3.6.3",
952 | "resolved": "https://registry.npmjs.org/@math.gl/culling/-/culling-3.6.3.tgz",
953 | "integrity": "sha512-3UERXHbaPlM6pnTk2MI7LeQ5CoelDZzDzghTTcv+HdQCZsT/EOEuEdYimETHtSxiyiOmsX2Un65UBLYT/rbKZg==",
954 | "dependencies": {
955 | "@babel/runtime": "^7.12.0",
956 | "@math.gl/core": "3.6.3",
957 | "gl-matrix": "^3.4.0"
958 | }
959 | },
960 | "node_modules/@math.gl/geospatial": {
961 | "version": "3.6.3",
962 | "resolved": "https://registry.npmjs.org/@math.gl/geospatial/-/geospatial-3.6.3.tgz",
963 | "integrity": "sha512-6xf657lJnaecSarSzn02t0cnsCSkWb+39m4+im96v20dZTrLCWZ2glDQVzfuL91meDnDXjH4oyvynp12Mj5MFg==",
964 | "dependencies": {
965 | "@babel/runtime": "^7.12.0",
966 | "@math.gl/core": "3.6.3",
967 | "gl-matrix": "^3.4.0"
968 | }
969 | },
970 | "node_modules/@math.gl/polygon": {
971 | "version": "3.6.3",
972 | "resolved": "https://registry.npmjs.org/@math.gl/polygon/-/polygon-3.6.3.tgz",
973 | "integrity": "sha512-FivQ1ZnYcAss1wVifOkHP/ZnlfQy1IL/769uzNtiHxwUbW0kZG3yyOZ9I7fwyzR5Hvqt3ErJKHjSYZr0uVlz5g==",
974 | "dependencies": {
975 | "@math.gl/core": "3.6.3"
976 | }
977 | },
978 | "node_modules/@math.gl/sun": {
979 | "version": "3.6.3",
980 | "resolved": "https://registry.npmjs.org/@math.gl/sun/-/sun-3.6.3.tgz",
981 | "integrity": "sha512-mrx6CGYYeTNSQttvcw0KVUy+35YDmnjMqpO/o0t06Vcghrt0HNruB/ScRgUSbJrgkbOg1Vcqm23HBd++clzQzw==",
982 | "dependencies": {
983 | "@babel/runtime": "^7.12.0"
984 | }
985 | },
986 | "node_modules/@math.gl/types": {
987 | "version": "3.6.3",
988 | "resolved": "https://registry.npmjs.org/@math.gl/types/-/types-3.6.3.tgz",
989 | "integrity": "sha512-3uWLVXHY3jQxsXCr/UCNPSc2BG0hNUljhmOBt9l+lNFDp7zHgm0cK2Tw4kj2XfkJy4TgwZTBGwRDQgWEbLbdTA=="
990 | },
991 | "node_modules/@math.gl/web-mercator": {
992 | "version": "3.6.3",
993 | "resolved": "https://registry.npmjs.org/@math.gl/web-mercator/-/web-mercator-3.6.3.tgz",
994 | "integrity": "sha512-UVrkSOs02YLehKaehrxhAejYMurehIHPfFQvPFZmdJHglHOU4V2cCUApTVEwOksvCp161ypEqVp+9H6mGhTTcw==",
995 | "dependencies": {
996 | "@babel/runtime": "^7.12.0",
997 | "gl-matrix": "^3.4.0"
998 | }
999 | },
1000 | "node_modules/@probe.gl/env": {
1001 | "version": "3.6.0",
1002 | "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-3.6.0.tgz",
1003 | "integrity": "sha512-4tTZYUg/8BICC3Yyb9rOeoKeijKbZHRXBEKObrfPmX4sQmYB15ZOUpoVBhAyJkOYVAM8EkPci6Uw5dLCwx2BEQ==",
1004 | "dependencies": {
1005 | "@babel/runtime": "^7.0.0"
1006 | }
1007 | },
1008 | "node_modules/@probe.gl/log": {
1009 | "version": "3.6.0",
1010 | "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-3.6.0.tgz",
1011 | "integrity": "sha512-hjpyenpEvOdowgZ1qMeCJxfRD4JkKdlXz0RC14m42Un62NtOT+GpWyKA4LssT0+xyLULCByRAtG2fzZorpIAcA==",
1012 | "dependencies": {
1013 | "@babel/runtime": "^7.0.0",
1014 | "@probe.gl/env": "3.6.0"
1015 | }
1016 | },
1017 | "node_modules/@probe.gl/stats": {
1018 | "version": "3.6.0",
1019 | "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-3.6.0.tgz",
1020 | "integrity": "sha512-JdALQXB44OP4kUBN/UrQgzbJe4qokbVF4Y8lkIA8iVCFnjVowWIgkD/z/0QO65yELT54tTrtepw1jScjKB+rhQ==",
1021 | "dependencies": {
1022 | "@babel/runtime": "^7.0.0"
1023 | }
1024 | },
1025 | "node_modules/@turf/boolean-clockwise": {
1026 | "version": "5.1.5",
1027 | "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-5.1.5.tgz",
1028 | "integrity": "sha512-FqbmEEOJ4rU4/2t7FKx0HUWmjFEVqR+NJrFP7ymGSjja2SQ7Q91nnBihGuT+yuHHl6ElMjQ3ttsB/eTmyCycxA==",
1029 | "dependencies": {
1030 | "@turf/helpers": "^5.1.5",
1031 | "@turf/invariant": "^5.1.5"
1032 | }
1033 | },
1034 | "node_modules/@turf/clone": {
1035 | "version": "5.1.5",
1036 | "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-5.1.5.tgz",
1037 | "integrity": "sha512-//pITsQ8xUdcQ9pVb4JqXiSqG4dos5Q9N4sYFoWghX21tfOV2dhc5TGqYOhnHrQS7RiKQL1vQ48kIK34gQ5oRg==",
1038 | "dependencies": {
1039 | "@turf/helpers": "^5.1.5"
1040 | }
1041 | },
1042 | "node_modules/@turf/helpers": {
1043 | "version": "5.1.5",
1044 | "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-5.1.5.tgz",
1045 | "integrity": "sha512-/lF+JR+qNDHZ8bF9d+Cp58nxtZWJ3sqFe6n3u3Vpj+/0cqkjk4nXKYBSY0azm+GIYB5mWKxUXvuP/m0ZnKj1bw=="
1046 | },
1047 | "node_modules/@turf/invariant": {
1048 | "version": "5.2.0",
1049 | "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-5.2.0.tgz",
1050 | "integrity": "sha512-28RCBGvCYsajVkw2EydpzLdcYyhSA77LovuOvgCJplJWaNVyJYH6BOR3HR9w50MEkPqb/Vc/jdo6I6ermlRtQA==",
1051 | "dependencies": {
1052 | "@turf/helpers": "^5.1.5"
1053 | }
1054 | },
1055 | "node_modules/@turf/meta": {
1056 | "version": "5.2.0",
1057 | "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-5.2.0.tgz",
1058 | "integrity": "sha512-ZjQ3Ii62X9FjnK4hhdsbT+64AYRpaI8XMBMcyftEOGSmPMUVnkbvuv3C9geuElAXfQU7Zk1oWGOcrGOD9zr78Q==",
1059 | "dependencies": {
1060 | "@turf/helpers": "^5.1.5"
1061 | }
1062 | },
1063 | "node_modules/@turf/rewind": {
1064 | "version": "5.1.5",
1065 | "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-5.1.5.tgz",
1066 | "integrity": "sha512-Gdem7JXNu+G4hMllQHXRFRihJl3+pNl7qY+l4qhQFxq+hiU1cQoVFnyoleIqWKIrdK/i2YubaSwc3SCM7N5mMw==",
1067 | "dependencies": {
1068 | "@turf/boolean-clockwise": "^5.1.5",
1069 | "@turf/clone": "^5.1.5",
1070 | "@turf/helpers": "^5.1.5",
1071 | "@turf/invariant": "^5.1.5",
1072 | "@turf/meta": "^5.1.5"
1073 | }
1074 | },
1075 | "node_modules/@types/geojson": {
1076 | "version": "7946.0.10",
1077 | "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
1078 | "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA=="
1079 | },
1080 | "node_modules/@types/hammerjs": {
1081 | "version": "2.0.41",
1082 | "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz",
1083 | "integrity": "sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA=="
1084 | },
1085 | "node_modules/@types/mapbox__point-geometry": {
1086 | "version": "0.1.2",
1087 | "resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.2.tgz",
1088 | "integrity": "sha512-D0lgCq+3VWV85ey1MZVkE8ZveyuvW5VAfuahVTQRpXFQTxw03SuIf1/K4UQ87MMIXVKzpFjXFiFMZzLj2kU+iA=="
1089 | },
1090 | "node_modules/@types/mapbox__vector-tile": {
1091 | "version": "1.3.0",
1092 | "resolved": "https://registry.npmjs.org/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.0.tgz",
1093 | "integrity": "sha512-kDwVreQO5V4c8yAxzZVQLE5tyWF+IPToAanloQaSnwfXmIcJ7cyOrv8z4Ft4y7PsLYmhWXmON8MBV8RX0Rgr8g==",
1094 | "dependencies": {
1095 | "@types/geojson": "*",
1096 | "@types/mapbox__point-geometry": "*",
1097 | "@types/pbf": "*"
1098 | }
1099 | },
1100 | "node_modules/@types/offscreencanvas": {
1101 | "version": "2019.7.0",
1102 | "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz",
1103 | "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg=="
1104 | },
1105 | "node_modules/@types/pbf": {
1106 | "version": "3.0.2",
1107 | "resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.2.tgz",
1108 | "integrity": "sha512-EDrLIPaPXOZqDjrkzxxbX7UlJSeQVgah3i0aA4pOSzmK9zq3BIh7/MZIQxED7slJByvKM4Gc6Hypyu2lJzh3SQ=="
1109 | },
1110 | "node_modules/argparse": {
1111 | "version": "1.0.10",
1112 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
1113 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
1114 | "dependencies": {
1115 | "sprintf-js": "~1.0.2"
1116 | }
1117 | },
1118 | "node_modules/arr-union": {
1119 | "version": "3.1.0",
1120 | "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
1121 | "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==",
1122 | "engines": {
1123 | "node": ">=0.10.0"
1124 | }
1125 | },
1126 | "node_modules/assign-symbols": {
1127 | "version": "1.0.0",
1128 | "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
1129 | "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==",
1130 | "engines": {
1131 | "node": ">=0.10.0"
1132 | }
1133 | },
1134 | "node_modules/buf-compare": {
1135 | "version": "1.0.1",
1136 | "resolved": "https://registry.npmjs.org/buf-compare/-/buf-compare-1.0.1.tgz",
1137 | "integrity": "sha512-Bvx4xH00qweepGc43xFvMs5BKASXTbHaHm6+kDYIK9p/4iFwjATQkmPKHQSgJZzKbAymhztRbXUf1Nqhzl73/Q==",
1138 | "engines": {
1139 | "node": ">=0.10.0"
1140 | }
1141 | },
1142 | "node_modules/bytewise": {
1143 | "version": "1.1.0",
1144 | "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz",
1145 | "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==",
1146 | "dependencies": {
1147 | "bytewise-core": "^1.2.2",
1148 | "typewise": "^1.0.3"
1149 | }
1150 | },
1151 | "node_modules/bytewise-core": {
1152 | "version": "1.2.3",
1153 | "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz",
1154 | "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==",
1155 | "dependencies": {
1156 | "typewise-core": "^1.2"
1157 | }
1158 | },
1159 | "node_modules/core-assert": {
1160 | "version": "0.2.1",
1161 | "resolved": "https://registry.npmjs.org/core-assert/-/core-assert-0.2.1.tgz",
1162 | "integrity": "sha512-IG97qShIP+nrJCXMCgkNZgH7jZQ4n8RpPyPeXX++T6avR/KhLhgLiHKoEn5Rc1KjfycSfA9DMa6m+4C4eguHhw==",
1163 | "dependencies": {
1164 | "buf-compare": "^1.0.0",
1165 | "is-error": "^2.2.0"
1166 | },
1167 | "engines": {
1168 | "node": ">=0.10.0"
1169 | }
1170 | },
1171 | "node_modules/deep-strict-equal": {
1172 | "version": "0.2.0",
1173 | "resolved": "https://registry.npmjs.org/deep-strict-equal/-/deep-strict-equal-0.2.0.tgz",
1174 | "integrity": "sha512-3daSWyvZ/zwJvuMGlzG1O+Ow0YSadGfb3jsh9xoCutv2tWyB9dA4YvR9L9/fSdDZa2dByYQe+TqapSGUrjnkoA==",
1175 | "dependencies": {
1176 | "core-assert": "^0.2.0"
1177 | },
1178 | "engines": {
1179 | "node": ">=0.10.0"
1180 | }
1181 | },
1182 | "node_modules/draco3d": {
1183 | "version": "1.5.5",
1184 | "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.5.tgz",
1185 | "integrity": "sha512-JVuNV0EJzD3LBYhGyIXJLeBID/EVtmFO1ZNhAYflTgiMiAJlbhXQmRRda/azjc8MRVMHh0gqGhiqHUo5dIXM8Q=="
1186 | },
1187 | "node_modules/earcut": {
1188 | "version": "2.2.4",
1189 | "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
1190 | "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="
1191 | },
1192 | "node_modules/esbuild": {
1193 | "version": "0.18.11",
1194 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.11.tgz",
1195 | "integrity": "sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==",
1196 | "hasInstallScript": true,
1197 | "bin": {
1198 | "esbuild": "bin/esbuild"
1199 | },
1200 | "engines": {
1201 | "node": ">=12"
1202 | },
1203 | "optionalDependencies": {
1204 | "@esbuild/android-arm": "0.18.11",
1205 | "@esbuild/android-arm64": "0.18.11",
1206 | "@esbuild/android-x64": "0.18.11",
1207 | "@esbuild/darwin-arm64": "0.18.11",
1208 | "@esbuild/darwin-x64": "0.18.11",
1209 | "@esbuild/freebsd-arm64": "0.18.11",
1210 | "@esbuild/freebsd-x64": "0.18.11",
1211 | "@esbuild/linux-arm": "0.18.11",
1212 | "@esbuild/linux-arm64": "0.18.11",
1213 | "@esbuild/linux-ia32": "0.18.11",
1214 | "@esbuild/linux-loong64": "0.18.11",
1215 | "@esbuild/linux-mips64el": "0.18.11",
1216 | "@esbuild/linux-ppc64": "0.18.11",
1217 | "@esbuild/linux-riscv64": "0.18.11",
1218 | "@esbuild/linux-s390x": "0.18.11",
1219 | "@esbuild/linux-x64": "0.18.11",
1220 | "@esbuild/netbsd-x64": "0.18.11",
1221 | "@esbuild/openbsd-x64": "0.18.11",
1222 | "@esbuild/sunos-x64": "0.18.11",
1223 | "@esbuild/win32-arm64": "0.18.11",
1224 | "@esbuild/win32-ia32": "0.18.11",
1225 | "@esbuild/win32-x64": "0.18.11"
1226 | }
1227 | },
1228 | "node_modules/extend-shallow": {
1229 | "version": "2.0.1",
1230 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
1231 | "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
1232 | "dependencies": {
1233 | "is-extendable": "^0.1.0"
1234 | },
1235 | "engines": {
1236 | "node": ">=0.10.0"
1237 | }
1238 | },
1239 | "node_modules/fast-xml-parser": {
1240 | "version": "4.2.5",
1241 | "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz",
1242 | "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==",
1243 | "funding": [
1244 | {
1245 | "type": "paypal",
1246 | "url": "https://paypal.me/naturalintelligence"
1247 | },
1248 | {
1249 | "type": "github",
1250 | "url": "https://github.com/sponsors/NaturalIntelligence"
1251 | }
1252 | ],
1253 | "dependencies": {
1254 | "strnum": "^1.0.5"
1255 | },
1256 | "bin": {
1257 | "fxparser": "src/cli/cli.js"
1258 | }
1259 | },
1260 | "node_modules/geojson-vt": {
1261 | "version": "3.2.1",
1262 | "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz",
1263 | "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg=="
1264 | },
1265 | "node_modules/get-stream": {
1266 | "version": "6.0.1",
1267 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
1268 | "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
1269 | "engines": {
1270 | "node": ">=10"
1271 | },
1272 | "funding": {
1273 | "url": "https://github.com/sponsors/sindresorhus"
1274 | }
1275 | },
1276 | "node_modules/get-value": {
1277 | "version": "2.0.6",
1278 | "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
1279 | "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==",
1280 | "engines": {
1281 | "node": ">=0.10.0"
1282 | }
1283 | },
1284 | "node_modules/gl-matrix": {
1285 | "version": "3.4.3",
1286 | "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
1287 | "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
1288 | },
1289 | "node_modules/global-prefix": {
1290 | "version": "3.0.0",
1291 | "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
1292 | "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
1293 | "dependencies": {
1294 | "ini": "^1.3.5",
1295 | "kind-of": "^6.0.2",
1296 | "which": "^1.3.1"
1297 | },
1298 | "engines": {
1299 | "node": ">=6"
1300 | }
1301 | },
1302 | "node_modules/h3-js": {
1303 | "version": "3.7.2",
1304 | "resolved": "https://registry.npmjs.org/h3-js/-/h3-js-3.7.2.tgz",
1305 | "integrity": "sha512-LPjlHSwB9zQZrMqKloCZmmmt3yZzIK7nqPcXqwU93zT3TtYG6jP4tZBzAPouxut7lLjdFbMQ75wRBiKfpsnY7w==",
1306 | "engines": {
1307 | "node": ">=4",
1308 | "npm": ">=3",
1309 | "yarn": ">=1.3.0"
1310 | }
1311 | },
1312 | "node_modules/hammerjs": {
1313 | "version": "2.0.8",
1314 | "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
1315 | "integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==",
1316 | "engines": {
1317 | "node": ">=0.8.0"
1318 | }
1319 | },
1320 | "node_modules/ieee754": {
1321 | "version": "1.2.1",
1322 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
1323 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
1324 | "funding": [
1325 | {
1326 | "type": "github",
1327 | "url": "https://github.com/sponsors/feross"
1328 | },
1329 | {
1330 | "type": "patreon",
1331 | "url": "https://www.patreon.com/feross"
1332 | },
1333 | {
1334 | "type": "consulting",
1335 | "url": "https://feross.org/support"
1336 | }
1337 | ]
1338 | },
1339 | "node_modules/image-size": {
1340 | "version": "0.7.5",
1341 | "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.5.tgz",
1342 | "integrity": "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g==",
1343 | "bin": {
1344 | "image-size": "bin/image-size.js"
1345 | },
1346 | "engines": {
1347 | "node": ">=6.9.0"
1348 | }
1349 | },
1350 | "node_modules/ini": {
1351 | "version": "1.3.8",
1352 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
1353 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
1354 | },
1355 | "node_modules/is-error": {
1356 | "version": "2.2.2",
1357 | "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz",
1358 | "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg=="
1359 | },
1360 | "node_modules/is-extendable": {
1361 | "version": "0.1.1",
1362 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
1363 | "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
1364 | "engines": {
1365 | "node": ">=0.10.0"
1366 | }
1367 | },
1368 | "node_modules/is-plain-object": {
1369 | "version": "2.0.4",
1370 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
1371 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
1372 | "dependencies": {
1373 | "isobject": "^3.0.1"
1374 | },
1375 | "engines": {
1376 | "node": ">=0.10.0"
1377 | }
1378 | },
1379 | "node_modules/isexe": {
1380 | "version": "2.0.0",
1381 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
1382 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
1383 | },
1384 | "node_modules/isobject": {
1385 | "version": "3.0.1",
1386 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
1387 | "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
1388 | "engines": {
1389 | "node": ">=0.10.0"
1390 | }
1391 | },
1392 | "node_modules/json-stringify-pretty-compact": {
1393 | "version": "3.0.0",
1394 | "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz",
1395 | "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA=="
1396 | },
1397 | "node_modules/kdbush": {
1398 | "version": "4.0.2",
1399 | "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz",
1400 | "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="
1401 | },
1402 | "node_modules/kind-of": {
1403 | "version": "6.0.3",
1404 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
1405 | "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
1406 | "engines": {
1407 | "node": ">=0.10.0"
1408 | }
1409 | },
1410 | "node_modules/ktx-parse": {
1411 | "version": "0.0.4",
1412 | "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-0.0.4.tgz",
1413 | "integrity": "sha512-LY3nrmfXl+wZZdPxgJ3ZmLvG+wkOZZP3/dr4RbQj1Pk3Qwz44esOOSFFVQJcNWpXAtiNIC66WgXufX/SYgYz6A=="
1414 | },
1415 | "node_modules/lerc": {
1416 | "version": "4.0.1",
1417 | "resolved": "https://registry.npmjs.org/lerc/-/lerc-4.0.1.tgz",
1418 | "integrity": "sha512-b351eOjY3DKm1H2hDVhXswsd2RCK6bgREBK6Z639ctClOuYXTi9a44l8yO3zm1pYM2o4WrriloTAKgyrb/0EyA=="
1419 | },
1420 | "node_modules/long": {
1421 | "version": "3.2.0",
1422 | "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
1423 | "integrity": "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==",
1424 | "engines": {
1425 | "node": ">=0.6"
1426 | }
1427 | },
1428 | "node_modules/maplibre-gl": {
1429 | "version": "3.2.0",
1430 | "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-3.2.0.tgz",
1431 | "integrity": "sha512-TOo/cV9r8Xy3ngbJtY6JUC7rpjpObrsdO5pt14l5OIw4gY1v5XnxWP16VDSe0zRoncFfDCEBDmRwhfEFwtlbvw==",
1432 | "dependencies": {
1433 | "@mapbox/geojson-rewind": "^0.5.2",
1434 | "@mapbox/jsonlint-lines-primitives": "^2.0.2",
1435 | "@mapbox/point-geometry": "^0.1.0",
1436 | "@mapbox/tiny-sdf": "^2.0.6",
1437 | "@mapbox/unitbezier": "^0.0.1",
1438 | "@mapbox/vector-tile": "^1.3.1",
1439 | "@mapbox/whoots-js": "^3.1.0",
1440 | "@maplibre/maplibre-gl-style-spec": "^19.2.1",
1441 | "@types/geojson": "^7946.0.10",
1442 | "@types/mapbox__point-geometry": "^0.1.2",
1443 | "@types/mapbox__vector-tile": "^1.3.0",
1444 | "@types/pbf": "^3.0.2",
1445 | "earcut": "^2.2.4",
1446 | "geojson-vt": "^3.2.1",
1447 | "gl-matrix": "^3.4.3",
1448 | "global-prefix": "^3.0.0",
1449 | "kdbush": "^4.0.2",
1450 | "murmurhash-js": "^1.0.0",
1451 | "pbf": "^3.2.1",
1452 | "potpack": "^2.0.0",
1453 | "quickselect": "^2.0.0",
1454 | "supercluster": "^8.0.1",
1455 | "tinyqueue": "^2.0.3",
1456 | "vt-pbf": "^3.1.3"
1457 | },
1458 | "engines": {
1459 | "node": ">=16.14.0",
1460 | "npm": ">=8.1.0"
1461 | },
1462 | "funding": {
1463 | "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1"
1464 | }
1465 | },
1466 | "node_modules/math.gl": {
1467 | "version": "3.6.3",
1468 | "resolved": "https://registry.npmjs.org/math.gl/-/math.gl-3.6.3.tgz",
1469 | "integrity": "sha512-Yq9CyECvSDox9+5ETi2+x1bGTY5WvGUGL3rJfC4KPoCZAM51MGfrCm6rIn4yOJUVfMPs2a5RwMD+yGS/n1g3gg==",
1470 | "dependencies": {
1471 | "@math.gl/core": "3.6.3"
1472 | }
1473 | },
1474 | "node_modules/minimist": {
1475 | "version": "1.2.8",
1476 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
1477 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
1478 | "funding": {
1479 | "url": "https://github.com/sponsors/ljharb"
1480 | }
1481 | },
1482 | "node_modules/mjolnir.js": {
1483 | "version": "2.7.1",
1484 | "resolved": "https://registry.npmjs.org/mjolnir.js/-/mjolnir.js-2.7.1.tgz",
1485 | "integrity": "sha512-72BeUWgTv2cj5aZQKpwL8caNUFhXZ9bDm1hxpNj70XJQ62IBnTZmtv/WPxJvtaVNhzNo+D2U8O6ryNI0zImYcw==",
1486 | "dependencies": {
1487 | "@types/hammerjs": "^2.0.41",
1488 | "hammerjs": "^2.0.8"
1489 | },
1490 | "engines": {
1491 | "node": ">= 4",
1492 | "npm": ">= 3"
1493 | }
1494 | },
1495 | "node_modules/murmurhash-js": {
1496 | "version": "1.0.0",
1497 | "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz",
1498 | "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw=="
1499 | },
1500 | "node_modules/node-fetch": {
1501 | "version": "2.6.12",
1502 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
1503 | "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
1504 | "dependencies": {
1505 | "whatwg-url": "^5.0.0"
1506 | },
1507 | "engines": {
1508 | "node": "4.x || >=6.0.0"
1509 | },
1510 | "peerDependencies": {
1511 | "encoding": "^0.1.0"
1512 | },
1513 | "peerDependenciesMeta": {
1514 | "encoding": {
1515 | "optional": true
1516 | }
1517 | }
1518 | },
1519 | "node_modules/pbf": {
1520 | "version": "3.2.1",
1521 | "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz",
1522 | "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==",
1523 | "dependencies": {
1524 | "ieee754": "^1.1.12",
1525 | "resolve-protobuf-schema": "^2.1.0"
1526 | },
1527 | "bin": {
1528 | "pbf": "bin/pbf"
1529 | }
1530 | },
1531 | "node_modules/potpack": {
1532 | "version": "2.0.0",
1533 | "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.0.0.tgz",
1534 | "integrity": "sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw=="
1535 | },
1536 | "node_modules/protocol-buffers-schema": {
1537 | "version": "3.6.0",
1538 | "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
1539 | "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="
1540 | },
1541 | "node_modules/quickselect": {
1542 | "version": "2.0.0",
1543 | "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
1544 | "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
1545 | },
1546 | "node_modules/regenerator-runtime": {
1547 | "version": "0.13.11",
1548 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
1549 | "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
1550 | },
1551 | "node_modules/resolve-protobuf-schema": {
1552 | "version": "2.1.0",
1553 | "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
1554 | "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
1555 | "dependencies": {
1556 | "protocol-buffers-schema": "^3.3.1"
1557 | }
1558 | },
1559 | "node_modules/rw": {
1560 | "version": "1.3.3",
1561 | "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
1562 | "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
1563 | },
1564 | "node_modules/set-value": {
1565 | "version": "2.0.1",
1566 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
1567 | "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
1568 | "dependencies": {
1569 | "extend-shallow": "^2.0.1",
1570 | "is-extendable": "^0.1.1",
1571 | "is-plain-object": "^2.0.3",
1572 | "split-string": "^3.0.1"
1573 | },
1574 | "engines": {
1575 | "node": ">=0.10.0"
1576 | }
1577 | },
1578 | "node_modules/sort-asc": {
1579 | "version": "0.2.0",
1580 | "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz",
1581 | "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==",
1582 | "engines": {
1583 | "node": ">=0.10.0"
1584 | }
1585 | },
1586 | "node_modules/sort-desc": {
1587 | "version": "0.2.0",
1588 | "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.2.0.tgz",
1589 | "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==",
1590 | "engines": {
1591 | "node": ">=0.10.0"
1592 | }
1593 | },
1594 | "node_modules/sort-object": {
1595 | "version": "3.0.3",
1596 | "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-3.0.3.tgz",
1597 | "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==",
1598 | "dependencies": {
1599 | "bytewise": "^1.1.0",
1600 | "get-value": "^2.0.2",
1601 | "is-extendable": "^0.1.1",
1602 | "sort-asc": "^0.2.0",
1603 | "sort-desc": "^0.2.0",
1604 | "union-value": "^1.0.1"
1605 | },
1606 | "engines": {
1607 | "node": ">=0.10.0"
1608 | }
1609 | },
1610 | "node_modules/split-string": {
1611 | "version": "3.1.0",
1612 | "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
1613 | "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
1614 | "dependencies": {
1615 | "extend-shallow": "^3.0.0"
1616 | },
1617 | "engines": {
1618 | "node": ">=0.10.0"
1619 | }
1620 | },
1621 | "node_modules/split-string/node_modules/extend-shallow": {
1622 | "version": "3.0.2",
1623 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
1624 | "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==",
1625 | "dependencies": {
1626 | "assign-symbols": "^1.0.0",
1627 | "is-extendable": "^1.0.1"
1628 | },
1629 | "engines": {
1630 | "node": ">=0.10.0"
1631 | }
1632 | },
1633 | "node_modules/split-string/node_modules/is-extendable": {
1634 | "version": "1.0.1",
1635 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
1636 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
1637 | "dependencies": {
1638 | "is-plain-object": "^2.0.4"
1639 | },
1640 | "engines": {
1641 | "node": ">=0.10.0"
1642 | }
1643 | },
1644 | "node_modules/sprintf-js": {
1645 | "version": "1.0.3",
1646 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
1647 | "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
1648 | },
1649 | "node_modules/strnum": {
1650 | "version": "1.0.5",
1651 | "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
1652 | "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
1653 | },
1654 | "node_modules/supercluster": {
1655 | "version": "8.0.1",
1656 | "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz",
1657 | "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==",
1658 | "dependencies": {
1659 | "kdbush": "^4.0.2"
1660 | }
1661 | },
1662 | "node_modules/texture-compressor": {
1663 | "version": "1.0.2",
1664 | "resolved": "https://registry.npmjs.org/texture-compressor/-/texture-compressor-1.0.2.tgz",
1665 | "integrity": "sha512-dStVgoaQ11mA5htJ+RzZ51ZxIZqNOgWKAIvtjLrW1AliQQLCmrDqNzQZ8Jh91YealQ95DXt4MEduLzJmbs6lig==",
1666 | "dependencies": {
1667 | "argparse": "^1.0.10",
1668 | "image-size": "^0.7.4"
1669 | },
1670 | "bin": {
1671 | "texture-compressor": "bin/texture-compressor.js"
1672 | }
1673 | },
1674 | "node_modules/tinyqueue": {
1675 | "version": "2.0.3",
1676 | "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz",
1677 | "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA=="
1678 | },
1679 | "node_modules/tr46": {
1680 | "version": "0.0.3",
1681 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
1682 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
1683 | },
1684 | "node_modules/typewise": {
1685 | "version": "1.0.3",
1686 | "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz",
1687 | "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==",
1688 | "dependencies": {
1689 | "typewise-core": "^1.2.0"
1690 | }
1691 | },
1692 | "node_modules/typewise-core": {
1693 | "version": "1.2.0",
1694 | "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz",
1695 | "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg=="
1696 | },
1697 | "node_modules/union-value": {
1698 | "version": "1.0.1",
1699 | "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
1700 | "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
1701 | "dependencies": {
1702 | "arr-union": "^3.1.0",
1703 | "get-value": "^2.0.6",
1704 | "is-extendable": "^0.1.1",
1705 | "set-value": "^2.0.1"
1706 | },
1707 | "engines": {
1708 | "node": ">=0.10.0"
1709 | }
1710 | },
1711 | "node_modules/vt-pbf": {
1712 | "version": "3.1.3",
1713 | "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz",
1714 | "integrity": "sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==",
1715 | "dependencies": {
1716 | "@mapbox/point-geometry": "0.1.0",
1717 | "@mapbox/vector-tile": "^1.3.1",
1718 | "pbf": "^3.2.1"
1719 | }
1720 | },
1721 | "node_modules/webidl-conversions": {
1722 | "version": "3.0.1",
1723 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
1724 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
1725 | },
1726 | "node_modules/whatwg-url": {
1727 | "version": "5.0.0",
1728 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
1729 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
1730 | "dependencies": {
1731 | "tr46": "~0.0.3",
1732 | "webidl-conversions": "^3.0.0"
1733 | }
1734 | },
1735 | "node_modules/which": {
1736 | "version": "1.3.1",
1737 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
1738 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
1739 | "dependencies": {
1740 | "isexe": "^2.0.0"
1741 | },
1742 | "bin": {
1743 | "which": "bin/which"
1744 | }
1745 | }
1746 | }
1747 | }
1748 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dem-map",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "npx esbuild --bundle --outfile=./dist/index.js src/index.ts --platform=browser",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@basemaps/geo": "^6.40.0",
15 | "@basemaps/tiler": "^6.40.0",
16 | "@chunkd/middleware": "^11.0.0",
17 | "@chunkd/source-http": "^11.0.0",
18 | "@cogeotiff/core": "^8.0.0",
19 | "@deck.gl/core": "^8.9.21",
20 | "@deck.gl/geo-layers": "^8.9.21",
21 | "esbuild": "^0.18.11",
22 | "lerc": "^4.0.1",
23 | "maplibre-gl": "^3.2.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/cogs.ts:
--------------------------------------------------------------------------------
1 | import { GoogleTms } from "@basemaps/geo";
2 | import { CompositionTiff, Tiler } from "@basemaps/tiler";
3 | import { SourceCache, SourceChunk } from "@chunkd/middleware";
4 | import { SourceView } from '@chunkd/source';
5 | import { SourceHttp } from "@chunkd/source-http";
6 | import { CogTiff } from "@cogeotiff/core";
7 | import { QuadKey } from "./quadkey.js";
8 | import { ramp } from "./ramp.js";
9 |
10 | export const Cogs = {
11 | 'Taranaki2021': [
12 | [11, 2012, 1267],
13 | [11, 2013, 1266],
14 | [11, 2013, 1267],
15 | [11, 2013, 1268],
16 | [11, 2014, 1265],
17 | [11, 2014, 1266],
18 | [11, 2014, 1267],
19 | [11, 2014, 1268],
20 | [11, 2014, 1269],
21 | [11, 2015, 1265],
22 | [11, 2015, 1266],
23 | [11, 2015, 1267],
24 | [11, 2015, 1268],
25 | [11, 2015, 1269],
26 | [11, 2016, 1264],
27 | [11, 2016, 1265],
28 | [11, 2016, 1266],
29 | [11, 2016, 1267],
30 | [11, 2016, 1268],
31 | [11, 2016, 1269],
32 | [11, 2016, 1270],
33 | [11, 2017, 1263],
34 | [11, 2017, 1264],
35 | [11, 2017, 1265],
36 | [11, 2017, 1266],
37 | [11, 2017, 1267],
38 | [11, 2017, 1268],
39 | [11, 2017, 1269],
40 | [11, 2017, 1270],
41 | [11, 2017, 1271],
42 | [11, 2018, 1263],
43 | [11, 2018, 1264],
44 | [11, 2018, 1265],
45 | [11, 2018, 1266],
46 | [11, 2018, 1267],
47 | [11, 2018, 1268],
48 | [11, 2018, 1269],
49 | [11, 2018, 1270],
50 | [11, 2018, 1271],
51 | [11, 2019, 1265],
52 | [11, 2019, 1266],
53 | [11, 2019, 1269],
54 | [12, 4025, 2533],
55 | [12, 4025, 2536],
56 | [12, 4027, 2538],
57 | [12, 4038, 2537],
58 | [12, 4038, 2540],
59 | [13, 8051, 5065],
60 | [13, 8051, 5074],
61 | [13, 8053, 5076],
62 | [13, 8054, 5063],
63 | [13, 8055, 5062],
64 | [13, 8055, 5063],
65 | [13, 8062, 5080],
66 | [13, 8063, 5080],
67 | [13, 8063, 5081],
68 | [13, 8066, 5084],
69 | [13, 8067, 5084],
70 | [13, 8067, 5085],
71 | [13, 8076, 5068],
72 | [13, 8076, 5082],
73 | [13, 8076, 5083],
74 | [13, 8078, 5080],
75 | ].map(f => QuadKey.fromTile(f[0], f[1], f[2]))
76 | }
77 | const cache = new SourceCache({ size: 64 * 1024 * 1024})
78 | window['sourceCache'] = cache;
79 |
80 | const chunk = new SourceChunk( {size: 64 * 1024 })
81 |
82 | function createTiff(path) {
83 | const source = new SourceView(new SourceHttp(path), [chunk, cache]);
84 | (source as any).uri = source.url.href;
85 | return CogTiff.create(source)
86 | }
87 |
88 | const tiffs = new Map>();
89 | declare const Lerc: any; // FIXME typing
90 |
91 | const emptyBuffer = (type) => {
92 | const raw = new Uint8ClampedArray(256 * 256 * 4)
93 | if (type === 'mapbox') {
94 | for (let i = 0; i < 256 * 256; i++) {
95 | const offset = i * 4;
96 | raw[offset + 3] = 255
97 |
98 | /** mapbox */
99 | const base = -10_000;
100 | const interval = 0.1;
101 |
102 | const v = (0 - base) / interval
103 | raw[offset + 0] = Math.floor(v / 256 / 256) % 256
104 | raw[offset + 1] = Math.floor(v / 256) % 256
105 | raw[offset + 2] = v % 256
106 | }
107 | return createImageBitmap(new ImageData(raw, 256, 256));;
108 | }
109 |
110 | return createImageBitmap(new ImageData(raw, 256, 256));
111 | }
112 |
113 | const googleTiler = new Tiler(GoogleTms);
114 |
115 | export async function lercToBuffer(url: string): Promise<{ buffer: Float32Array, width: number, height: number } | null> {
116 | const urlParts = url.split('@');
117 | const cogParts = urlParts[0].split('#');
118 | const cogName = cogParts[0].slice('cog+lerc:'.length + 2)
119 | let method = 'mapbox'
120 | if (cogParts[1]) method = cogParts[1]
121 |
122 | const path = urlParts[urlParts.length - 1].split('/')
123 | const z = Number(path[0]);
124 | const x = Number(path[1]);
125 | const y = Number(path[2]);
126 |
127 | const cogs = Cogs[cogName]
128 | if (cogs == null) return null;
129 | const targetTile = QuadKey.fromTile(z, x, y);
130 |
131 | for (const cogQk of cogs) {
132 | if (!targetTile.startsWith(cogQk)) continue;
133 |
134 | const cog = tiffs.get(cogQk) ?? createTiff(`${cogName}/${QuadKey.toZxy(cogQk)}.tiff`)
135 | tiffs.set(cogQk, cog);
136 |
137 | return cog.then(async (tiff) => {
138 | await Lerc.load()
139 |
140 | const tileId = `${z}-${x}-${y}.lerc`
141 | const result = await googleTiler.tile([tiff], x, y, z)
142 |
143 | if (result.length !== 1) {
144 | console.log('non1 result', tileId);
145 | return null
146 | }
147 | const comp = result[0] as CompositionTiff;
148 |
149 | const tile = await tiff.images[comp.source.imageId].getTile(comp.source.x, comp.source.y);
150 | if (tile == null) {
151 | console.log('empty tile', tileId)
152 | return null
153 | }
154 |
155 |
156 | const decoded = Lerc.decode(tile.bytes)
157 |
158 | return { buffer: decoded.pixels[0], width: decoded.width, height: decoded.height }
159 | })
160 | }
161 | return null;
162 | }
163 |
164 | export async function lercToImage(url: string): Promise {
165 | const urlParts = url.split('@');
166 | const cogParts = urlParts[0].split('#');
167 | const cogName = cogParts[0].slice('cog+lerc:'.length + 2)
168 | let method = 'mapbox'
169 | if (cogParts[1]) method = cogParts[1]
170 |
171 | const path = urlParts[urlParts.length - 1].split('/')
172 | const z = Number(path[0]);
173 | const x = Number(path[1]);
174 | const y = Number(path[2]);
175 |
176 | const cogs = Cogs[cogName]
177 | if (cogs == null) return null;
178 |
179 | const tileId = `${z}-${x}-${y}.lerc`
180 |
181 | const ret = await lercToBuffer(url);
182 | if (ret == null) return emptyBuffer(method);
183 | console.time('create:elevation:' + method + ':' + tileId)
184 |
185 | // Convert the DEM into a RGBA picture
186 | const raw = new Uint8ClampedArray(ret.width * ret.height * 4);
187 | const buf = ret.buffer;
188 |
189 | for (let i = 0; i < buf.length; i++) {
190 | let px = buf[i]
191 |
192 | if (method === 'ramp') {
193 | const offset = i * 4;
194 |
195 | const color = ramp.get(px);
196 | raw[offset + 0] = color[0]
197 | raw[offset + 1] = color[1]
198 | raw[offset + 2] = color[2]
199 | raw[offset + 3] = color[3]
200 | continue;
201 | }
202 |
203 | // COG's NoData is -9999, TODO extract this from the LERC metadata
204 | if (px === -9999 || px == 0) px = 0; // NO_DATA ignore
205 | const offset = i * 4;
206 | // Set alpha to full!
207 | raw[offset + 3] = 255
208 |
209 | /** mapbox */
210 | const base = -10_000;
211 | const interval = 0.1;
212 |
213 | const v = (px - base) / interval
214 | raw[offset + 0] = Math.floor(v / 256 / 256) % 256
215 | raw[offset + 1] = Math.floor(v / 256) % 256
216 | raw[offset + 2] = v % 256
217 |
218 | /** terrarium */
219 | // const v = px + 32768;
220 | // raw[offset] = (Math.floor(v / 256));
221 | // raw[offset + 1] = (Math.floor(v % 256));
222 | // raw[offset + 2] = (Math.floor((v - Math.floor(v)) * 256));
223 | }
224 |
225 | console.timeEnd('create:elevation:' + method + ':' + tileId)
226 | return await createImageBitmap(new ImageData(raw, ret.width, ret.height));
227 | }
--------------------------------------------------------------------------------
/src/delatin.ts:
--------------------------------------------------------------------------------
1 | // ISC License
2 |
3 | // Copyright(c) 2019, Michael Fogleman, Vladimir Agafonkin
4 |
5 | // Permission to use, copy, modify, and / or distribute this software for any purpose
6 | // with or without fee is hereby granted, provided that the above copyright notice
7 | // and this permission notice appear in all copies.
8 |
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10 | // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
11 | // FITNESS.IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
13 | // OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
14 | // TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
15 | // THIS SOFTWARE.
16 |
17 | // @ts-nocheck
18 |
19 | /* eslint-disable complexity, max-params, max-statements, max-depth, no-constant-condition */
20 | export default class Delatin {
21 | constructor(data, width, height = width) {
22 | this.data = data; // height data
23 | this.width = width;
24 | this.height = height;
25 |
26 | this.coords = []; // vertex coordinates (x, y)
27 | this.triangles = []; // mesh triangle indices
28 |
29 | // additional triangle data
30 | this._halfedges = [];
31 | this._candidates = [];
32 | this._queueIndices = [];
33 |
34 | this._queue = []; // queue of added triangles
35 | this._errors = [];
36 | this._rms = [];
37 | this._pending = []; // triangles pending addition to queue
38 | this._pendingLen = 0;
39 |
40 | this._rmsSum = 0;
41 |
42 | const x1 = width - 1;
43 | const y1 = height - 1;
44 | const p0 = this._addPoint(0, 0);
45 | const p1 = this._addPoint(x1, 0);
46 | const p2 = this._addPoint(0, y1);
47 | const p3 = this._addPoint(x1, y1);
48 |
49 | // add initial two triangles
50 | const t0 = this._addTriangle(p3, p0, p2, -1, -1, -1);
51 | this._addTriangle(p0, p3, p1, t0, -1, -1);
52 | this._flush();
53 | }
54 |
55 | // refine the mesh until its maximum error gets below the given one
56 | run(maxError = 1) {
57 | while (this.getMaxError() > maxError) {
58 | this.refine();
59 | }
60 | }
61 |
62 | // refine the mesh with a single point
63 | refine() {
64 | this._step();
65 | this._flush();
66 | }
67 |
68 | // max error of the current mesh
69 | getMaxError() {
70 | return this._errors[0];
71 | }
72 |
73 | // root-mean-square deviation of the current mesh
74 | getRMSD() {
75 | return this._rmsSum > 0 ? Math.sqrt(this._rmsSum / (this.width * this.height)) : 0;
76 | }
77 |
78 | // height value at a given position
79 | heightAt(x, y) {
80 | return this.data[this.width * y + x];
81 | }
82 |
83 | // rasterize and queue all triangles that got added or updated in _step
84 | _flush() {
85 | const coords = this.coords;
86 | for (let i = 0; i < this._pendingLen; i++) {
87 | const t = this._pending[i];
88 | // rasterize triangle to find maximum pixel error
89 | const a = 2 * this.triangles[t * 3 + 0];
90 | const b = 2 * this.triangles[t * 3 + 1];
91 | const c = 2 * this.triangles[t * 3 + 2];
92 | this._findCandidate(
93 | coords[a],
94 | coords[a + 1],
95 | coords[b],
96 | coords[b + 1],
97 | coords[c],
98 | coords[c + 1],
99 | t
100 | );
101 | }
102 | this._pendingLen = 0;
103 | }
104 |
105 | // rasterize a triangle, find its max error, and queue it for processing
106 | _findCandidate(p0x, p0y, p1x, p1y, p2x, p2y, t) {
107 | // triangle bounding box
108 | const minX = Math.min(p0x, p1x, p2x);
109 | const minY = Math.min(p0y, p1y, p2y);
110 | const maxX = Math.max(p0x, p1x, p2x);
111 | const maxY = Math.max(p0y, p1y, p2y);
112 |
113 | // forward differencing variables
114 | let w00 = orient(p1x, p1y, p2x, p2y, minX, minY);
115 | let w01 = orient(p2x, p2y, p0x, p0y, minX, minY);
116 | let w02 = orient(p0x, p0y, p1x, p1y, minX, minY);
117 | const a01 = p1y - p0y;
118 | const b01 = p0x - p1x;
119 | const a12 = p2y - p1y;
120 | const b12 = p1x - p2x;
121 | const a20 = p0y - p2y;
122 | const b20 = p2x - p0x;
123 |
124 | // pre-multiplied z values at vertices
125 | const a = orient(p0x, p0y, p1x, p1y, p2x, p2y);
126 | const z0 = this.heightAt(p0x, p0y) / a;
127 | const z1 = this.heightAt(p1x, p1y) / a;
128 | const z2 = this.heightAt(p2x, p2y) / a;
129 |
130 | // iterate over pixels in bounding box
131 | let maxError = 0;
132 | let mx = 0;
133 | let my = 0;
134 | let rms = 0;
135 | for (let y = minY; y <= maxY; y++) {
136 | // compute starting offset
137 | let dx = 0;
138 | if (w00 < 0 && a12 !== 0) {
139 | dx = Math.max(dx, Math.floor(-w00 / a12));
140 | }
141 | if (w01 < 0 && a20 !== 0) {
142 | dx = Math.max(dx, Math.floor(-w01 / a20));
143 | }
144 | if (w02 < 0 && a01 !== 0) {
145 | dx = Math.max(dx, Math.floor(-w02 / a01));
146 | }
147 |
148 | let w0 = w00 + a12 * dx;
149 | let w1 = w01 + a20 * dx;
150 | let w2 = w02 + a01 * dx;
151 |
152 | let wasInside = false;
153 |
154 | for (let x = minX + dx; x <= maxX; x++) {
155 | // check if inside triangle
156 | if (w0 >= 0 && w1 >= 0 && w2 >= 0) {
157 | wasInside = true;
158 |
159 | // compute z using barycentric coordinates
160 | const z = z0 * w0 + z1 * w1 + z2 * w2;
161 | const dz = Math.abs(z - this.heightAt(x, y));
162 | rms += dz * dz;
163 | if (dz > maxError) {
164 | maxError = dz;
165 | mx = x;
166 | my = y;
167 | }
168 | } else if (wasInside) {
169 | break;
170 | }
171 |
172 | w0 += a12;
173 | w1 += a20;
174 | w2 += a01;
175 | }
176 |
177 | w00 += b12;
178 | w01 += b20;
179 | w02 += b01;
180 | }
181 |
182 | if ((mx === p0x && my === p0y) || (mx === p1x && my === p1y) || (mx === p2x && my === p2y)) {
183 | maxError = 0;
184 | }
185 |
186 | // update triangle metadata
187 | this._candidates[2 * t] = mx;
188 | this._candidates[2 * t + 1] = my;
189 | this._rms[t] = rms;
190 |
191 | // add triangle to priority queue
192 | this._queuePush(t, maxError, rms);
193 | }
194 |
195 | // process the next triangle in the queue, splitting it with a new point
196 | _step() {
197 | // pop triangle with highest error from priority queue
198 | const t = this._queuePop();
199 |
200 | const e0 = t * 3 + 0;
201 | const e1 = t * 3 + 1;
202 | const e2 = t * 3 + 2;
203 |
204 | const p0 = this.triangles[e0];
205 | const p1 = this.triangles[e1];
206 | const p2 = this.triangles[e2];
207 |
208 | const ax = this.coords[2 * p0];
209 | const ay = this.coords[2 * p0 + 1];
210 | const bx = this.coords[2 * p1];
211 | const by = this.coords[2 * p1 + 1];
212 | const cx = this.coords[2 * p2];
213 | const cy = this.coords[2 * p2 + 1];
214 | const px = this._candidates[2 * t];
215 | const py = this._candidates[2 * t + 1];
216 |
217 | const pn = this._addPoint(px, py);
218 |
219 | if (orient(ax, ay, bx, by, px, py) === 0) {
220 | this._handleCollinear(pn, e0);
221 | } else if (orient(bx, by, cx, cy, px, py) === 0) {
222 | this._handleCollinear(pn, e1);
223 | } else if (orient(cx, cy, ax, ay, px, py) === 0) {
224 | this._handleCollinear(pn, e2);
225 | } else {
226 | const h0 = this._halfedges[e0];
227 | const h1 = this._halfedges[e1];
228 | const h2 = this._halfedges[e2];
229 |
230 | const t0 = this._addTriangle(p0, p1, pn, h0, -1, -1, e0);
231 | const t1 = this._addTriangle(p1, p2, pn, h1, -1, t0 + 1);
232 | const t2 = this._addTriangle(p2, p0, pn, h2, t0 + 2, t1 + 1);
233 |
234 | this._legalize(t0);
235 | this._legalize(t1);
236 | this._legalize(t2);
237 | }
238 | }
239 |
240 | // add coordinates for a new vertex
241 | _addPoint(x, y) {
242 | const i = this.coords.length >> 1;
243 | this.coords.push(x, y);
244 | return i;
245 | }
246 |
247 | // add or update a triangle in the mesh
248 | _addTriangle(a, b, c, ab, bc, ca, e = this.triangles.length) {
249 | const t = e / 3; // new triangle index
250 |
251 | // add triangle vertices
252 | this.triangles[e + 0] = a;
253 | this.triangles[e + 1] = b;
254 | this.triangles[e + 2] = c;
255 |
256 | // add triangle halfedges
257 | this._halfedges[e + 0] = ab;
258 | this._halfedges[e + 1] = bc;
259 | this._halfedges[e + 2] = ca;
260 |
261 | // link neighboring halfedges
262 | if (ab >= 0) {
263 | this._halfedges[ab] = e + 0;
264 | }
265 | if (bc >= 0) {
266 | this._halfedges[bc] = e + 1;
267 | }
268 | if (ca >= 0) {
269 | this._halfedges[ca] = e + 2;
270 | }
271 |
272 | // init triangle metadata
273 | this._candidates[2 * t + 0] = 0;
274 | this._candidates[2 * t + 1] = 0;
275 | this._queueIndices[t] = -1;
276 | this._rms[t] = 0;
277 |
278 | // add triangle to pending queue for later rasterization
279 | this._pending[this._pendingLen++] = t;
280 |
281 | // return first halfedge index
282 | return e;
283 | }
284 |
285 | _legalize(a) {
286 | // if the pair of triangles doesn't satisfy the Delaunay condition
287 | // (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
288 | // then do the same check/flip recursively for the new pair of triangles
289 | //
290 | // pl pl
291 | // /||\ / \
292 | // al/ || \bl al/ \a
293 | // / || \ / \
294 | // / a||b \ flip /___ar___\
295 | // p0\ || /p1 => p0\---bl---/p1
296 | // \ || / \ /
297 | // ar\ || /br b\ /br
298 | // \||/ \ /
299 | // pr pr
300 |
301 | const b = this._halfedges[a];
302 |
303 | if (b < 0) {
304 | return;
305 | }
306 |
307 | const a0 = a - (a % 3);
308 | const b0 = b - (b % 3);
309 | const al = a0 + ((a + 1) % 3);
310 | const ar = a0 + ((a + 2) % 3);
311 | const bl = b0 + ((b + 2) % 3);
312 | const br = b0 + ((b + 1) % 3);
313 | const p0 = this.triangles[ar];
314 | const pr = this.triangles[a];
315 | const pl = this.triangles[al];
316 | const p1 = this.triangles[bl];
317 | const coords = this.coords;
318 |
319 | if (
320 | !inCircle(
321 | coords[2 * p0],
322 | coords[2 * p0 + 1],
323 | coords[2 * pr],
324 | coords[2 * pr + 1],
325 | coords[2 * pl],
326 | coords[2 * pl + 1],
327 | coords[2 * p1],
328 | coords[2 * p1 + 1]
329 | )
330 | ) {
331 | return;
332 | }
333 |
334 | const hal = this._halfedges[al];
335 | const har = this._halfedges[ar];
336 | const hbl = this._halfedges[bl];
337 | const hbr = this._halfedges[br];
338 |
339 | this._queueRemove(a0 / 3);
340 | this._queueRemove(b0 / 3);
341 |
342 | const t0 = this._addTriangle(p0, p1, pl, -1, hbl, hal, a0);
343 | const t1 = this._addTriangle(p1, p0, pr, t0, har, hbr, b0);
344 |
345 | this._legalize(t0 + 1);
346 | this._legalize(t1 + 2);
347 | }
348 |
349 | // handle a case where new vertex is on the edge of a triangle
350 | _handleCollinear(pn, a) {
351 | const a0 = a - (a % 3);
352 | const al = a0 + ((a + 1) % 3);
353 | const ar = a0 + ((a + 2) % 3);
354 | const p0 = this.triangles[ar];
355 | const pr = this.triangles[a];
356 | const pl = this.triangles[al];
357 | const hal = this._halfedges[al];
358 | const har = this._halfedges[ar];
359 |
360 | const b = this._halfedges[a];
361 |
362 | if (b < 0) {
363 | const t0 = this._addTriangle(pn, p0, pr, -1, har, -1, a0);
364 | const t1 = this._addTriangle(p0, pn, pl, t0, -1, hal);
365 | this._legalize(t0 + 1);
366 | this._legalize(t1 + 2);
367 | return;
368 | }
369 |
370 | const b0 = b - (b % 3);
371 | const bl = b0 + ((b + 2) % 3);
372 | const br = b0 + ((b + 1) % 3);
373 | const p1 = this.triangles[bl];
374 | const hbl = this._halfedges[bl];
375 | const hbr = this._halfedges[br];
376 |
377 | this._queueRemove(b0 / 3);
378 |
379 | const t0 = this._addTriangle(p0, pr, pn, har, -1, -1, a0);
380 | const t1 = this._addTriangle(pr, p1, pn, hbr, -1, t0 + 1, b0);
381 | const t2 = this._addTriangle(p1, pl, pn, hbl, -1, t1 + 1);
382 | const t3 = this._addTriangle(pl, p0, pn, hal, t0 + 2, t2 + 1);
383 |
384 | this._legalize(t0);
385 | this._legalize(t1);
386 | this._legalize(t2);
387 | this._legalize(t3);
388 | }
389 |
390 | // priority queue methods
391 |
392 | _queuePush(t, error, rms) {
393 | const i = this._queue.length;
394 | this._queueIndices[t] = i;
395 | this._queue.push(t);
396 | this._errors.push(error);
397 | this._rmsSum += rms;
398 | this._queueUp(i);
399 | }
400 |
401 | _queuePop() {
402 | const n = this._queue.length - 1;
403 | this._queueSwap(0, n);
404 | this._queueDown(0, n);
405 | return this._queuePopBack();
406 | }
407 |
408 | _queuePopBack() {
409 | const t = this._queue.pop();
410 | this._errors.pop();
411 | this._rmsSum -= this._rms[t];
412 | this._queueIndices[t] = -1;
413 | return t;
414 | }
415 |
416 | _queueRemove(t) {
417 | const i = this._queueIndices[t];
418 | if (i < 0) {
419 | const it = this._pending.indexOf(t);
420 | if (it !== -1) {
421 | this._pending[it] = this._pending[--this._pendingLen];
422 | } else {
423 | throw new Error('Broken triangulation (something went wrong).');
424 | }
425 | return;
426 | }
427 | const n = this._queue.length - 1;
428 | if (n !== i) {
429 | this._queueSwap(i, n);
430 | if (!this._queueDown(i, n)) {
431 | this._queueUp(i);
432 | }
433 | }
434 | this._queuePopBack();
435 | }
436 |
437 | _queueLess(i, j) {
438 | return this._errors[i] > this._errors[j];
439 | }
440 |
441 | _queueSwap(i, j) {
442 | const pi = this._queue[i];
443 | const pj = this._queue[j];
444 | this._queue[i] = pj;
445 | this._queue[j] = pi;
446 | this._queueIndices[pi] = j;
447 | this._queueIndices[pj] = i;
448 | const e = this._errors[i];
449 | this._errors[i] = this._errors[j];
450 | this._errors[j] = e;
451 | }
452 |
453 | _queueUp(j0) {
454 | let j = j0;
455 | while (true) {
456 | const i = (j - 1) >> 1;
457 | if (i === j || !this._queueLess(j, i)) {
458 | break;
459 | }
460 | this._queueSwap(i, j);
461 | j = i;
462 | }
463 | }
464 |
465 | _queueDown(i0, n) {
466 | let i = i0;
467 | while (true) {
468 | const j1 = 2 * i + 1;
469 | if (j1 >= n || j1 < 0) {
470 | break;
471 | }
472 | const j2 = j1 + 1;
473 | let j = j1;
474 | if (j2 < n && this._queueLess(j2, j1)) {
475 | j = j2;
476 | }
477 | if (!this._queueLess(j, i)) {
478 | break;
479 | }
480 | this._queueSwap(i, j);
481 | i = j;
482 | }
483 | return i > i0;
484 | }
485 | }
486 |
487 | function orient(ax, ay, bx, by, cx, cy) {
488 | return (bx - cx) * (ay - cy) - (by - cy) * (ax - cx);
489 | }
490 |
491 | function inCircle(ax, ay, bx, by, cx, cy, px, py) {
492 | const dx = ax - px;
493 | const dy = ay - py;
494 | const ex = bx - px;
495 | const ey = by - py;
496 | const fx = cx - px;
497 | const fy = cy - py;
498 |
499 | const ap = dx * dx + dy * dy;
500 | const bp = ex * ex + ey * ey;
501 | const cp = fx * fx + fy * fy;
502 |
503 | return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0;
504 | }
505 |
--------------------------------------------------------------------------------
/src/index.deck.gl.ts:
--------------------------------------------------------------------------------
1 | import { Deck } from '@deck.gl/core/typed';
2 | import { MapView } from '@deck.gl/core';
3 | import { TerrainLayer, TileLayer } from '@deck.gl/geo-layers/typed';
4 | import { BitmapLayer, PathLayer } from '@deck.gl/layers';
5 | import { GeoJsonLayer, ArcLayer } from '@deck.gl/layers';
6 | import * as terrain from '@loaders.gl/terrain'
7 | import { GoogleTms } from '@basemaps/geo';
8 | import { Tiler } from '@basemaps/tiler';
9 | import { lercToBuffer, lercToImage } from './cogs.js';
10 | import Martini from '@mapbox/martini'
11 | import Delatin from './delatin.js'
12 | export type TypedArray =
13 | | Int8Array
14 | | Uint8Array
15 | | Int16Array
16 | | Uint16Array
17 | | Int32Array
18 | | Uint32Array
19 | | Uint8ClampedArray
20 | | Float32Array
21 | | Float64Array;
22 | const martini = new Martini(257)
23 | type BoundingBox = [[number, number, number], [number, number, number]];
24 | export type MeshAttribute = {
25 | value: TypedArray;
26 | size: number;
27 | byteOffset?: number;
28 | byteStride?: number;
29 | normalized?: boolean;
30 | }
31 | export type MeshAttributes = Record;
32 |
33 | ;
34 | /**
35 | * Get the (axis aligned) bounding box of a mesh
36 | * @param attributes
37 | * @returns array of two vectors representing the axis aligned bounding box
38 | */
39 | // eslint-disable-next-line complexity
40 | export function getMeshBoundingBox(attributes: MeshAttributes): BoundingBox {
41 | let minX = Infinity;
42 | let minY = Infinity;
43 | let minZ = Infinity;
44 | let maxX = -Infinity;
45 | let maxY = -Infinity;
46 | let maxZ = -Infinity;
47 |
48 | const positions = attributes.POSITION ? attributes.POSITION.value : [];
49 | const len = positions && positions.length;
50 |
51 | for (let i = 0; i < len; i += 3) {
52 | const x = positions[i];
53 | const y = positions[i + 1];
54 | const z = positions[i + 2];
55 |
56 | minX = x < minX ? x : minX;
57 | minY = y < minY ? y : minY;
58 | minZ = z < minZ ? z : minZ;
59 |
60 | maxX = x > maxX ? x : maxX;
61 | maxY = y > maxY ? y : maxY;
62 | maxZ = z > maxZ ? z : maxZ;
63 | }
64 | return [
65 | [minX, minY, minZ],
66 | [maxX, maxY, maxZ]
67 | ];
68 | }
69 |
70 | const COUNTRIES =
71 | 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_admin_0_scale_rank.geojson'; //eslint-disable-line
72 |
73 | const googleTiler = new Tiler(GoogleTms);
74 |
75 | function getMeshAttributes(
76 | vertices,
77 | terrain: Float32Array ,
78 | width: number,
79 | height: number,
80 | bounds?: number[]
81 | ) {
82 | const gridSize = width ;
83 | const numOfVerticies = vertices.length / 2;
84 | // vec3. x, y in pixels, z in meters
85 | const positions = new Float32Array(numOfVerticies * 3);
86 | // vec2. 1 to 1 relationship with position. represents the uv on the texture image. 0,0 to 1,1.
87 | const texCoords = new Float32Array(numOfVerticies * 2);
88 |
89 | const [minX, minY, maxX, maxY] = bounds || [0, 0, width, height];
90 | const xScale = (maxX - minX) / width;
91 | const yScale = (maxY - minY) / height;
92 |
93 | for (let i = 0; i < numOfVerticies; i++) {
94 | const x = vertices[i * 2];
95 | const y = vertices[i * 2 + 1];
96 | const pixelIdx = y * gridSize + x;
97 |
98 | positions[3 * i + 0] = x * xScale + minX;
99 | positions[3 * i + 1] = -y * yScale + maxY;
100 | positions[3 * i + 2] = terrain[pixelIdx];
101 |
102 | texCoords[2 * i + 0] = x / width;
103 | texCoords[2 * i + 1] = y / height;
104 | }
105 |
106 | return {
107 | POSITION: {value: positions, size: 3},
108 | TEXCOORD_0: {value: texCoords, size: 2},
109 | // NORMAL: {},// - optional, but creates the high poly look with lighting
110 | };
111 | }
112 |
113 |
114 | const tileLayer = new TileLayer({
115 | // https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_servers
116 | data: 'https://Taranaki2021#ramp@{z}/{x}/{y}',
117 |
118 | minZoom: 0,
119 | maxZoom: 22,
120 | tileSize: 256,
121 |
122 | async getTileData(props) {
123 | // console.log(props)
124 |
125 | return await lercToImage(props.url?.replace('https', 'cog+lerc'))
126 | // const ret = await fetch(props.url!)
127 | // if (ret.ok) return ret.arrayBuffer();
128 | // return null;
129 | },
130 |
131 | renderSubLayers: props => {
132 | // console.log(props)
133 | const {
134 | bbox: {west, south, east, north}
135 | } = props.tile;
136 |
137 | return new BitmapLayer(props, {
138 | data: null,
139 | image: props.data,
140 | bounds: [west, south, east, north]
141 | });
142 | }
143 | });
144 |
145 | export function renderToDom() {
146 | const app = document.querySelector('#app');
147 | const layer = new TerrainLayer({
148 | id: 'terrain',
149 |
150 | // getTileData(props) {
151 | // console.log('getTile', props)
152 | // },
153 |
154 | async fetch(url, context) {
155 | if (url.startsWith('https')) return fetch(url);
156 |
157 | const buf = await lercToBuffer(url);
158 | if (buf == null) {
159 | console.log('Nothing');
160 | throw Error('Missing')
161 | }
162 | const width = buf.width;
163 | const height = buf.height;
164 |
165 | // const tin = new Delatin(buf.buffer, width + 1, height+ 1);
166 | // tin.run(10);
167 | // // @ts-expect-error
168 | // const {coords, triangles} = tin;
169 | // const vertices = coords;
170 | const terrain = new Float32Array((buf.width + 1) * (buf.height + 1));
171 | for (let i = 0, y = 0; y < height; y++) {
172 | for (let x = 0; x < width; x++, i++) {
173 | // const val = buf.buffer[i];
174 | terrain[i + y] = buf.buffer[i];
175 |
176 | }
177 | }
178 | for (let i = (buf.width + 1) * buf.width, x = 0; x < buf.width; x++, i++) {
179 | terrain[i] = terrain[i - buf.width - 1];
180 | }
181 | // backfill right border
182 | for (let i = buf.height, y = 0; y < buf.height + 1; y++, i += buf.height + 1) {
183 | terrain[i] = terrain[i - 1];
184 | }
185 |
186 | const tile = martini.createTile(terrain);
187 | const {vertices, triangles} = tile.getMesh();
188 |
189 | let attributes = getMeshAttributes(vertices, buf.buffer, width, height);
190 | const boundingBox = getMeshBoundingBox(attributes);
191 | console.log(url, width, height)
192 |
193 | // console.log(url, buf.buffer, attributes)
194 | return {
195 | // Data return by this loader implementation
196 | loaderData: {
197 | header: {}
198 | },
199 | header: {
200 | vertexCount: triangles.length,
201 | boundingBox
202 | },
203 | mode: 4, // TRIANGLES
204 | indices: {value: Uint32Array.from(triangles), size: 1},
205 | attributes
206 | };
207 | },
208 | minZoom: 0,
209 | maxZoom: 23,
210 | strategy: 'no-overlap',
211 | elevationDecoder: {
212 | rScaler: 6553.6,
213 | gScaler: 25.6,
214 | bScaler: 0.1,
215 | offset: -10000
216 | },
217 | elevationData: 'cog+lerc://Taranaki2021#@{z}/{x}/{y}',
218 | texture: 'https://basemaps.linz.govt.nz/v1/tiles/aerial/WebMercatorQuad/{z}/{x}/{y}.webp?api=c01h3e17kjsw5evq8ndjxbda80e',
219 | wireframe : false,
220 | color: [255, 255, 255]
221 | });
222 |
223 | const deck = new Deck({
224 | canvas: 'deck-canvas',
225 | initialViewState: {
226 | latitude: -39.333,
227 | longitude: 174.0416,
228 | zoom: 11
229 | },
230 | controller: true,
231 | layers: [
232 | layer,
233 | // tileLayer,
234 | new GeoJsonLayer({
235 | id: 'base-map',
236 | data: COUNTRIES,
237 | // Styles
238 | stroked: true,
239 | filled: true,
240 | lineWidthMinPixels: 2,
241 | opacity: 0.4,
242 | getLineColor: [60, 60, 60],
243 | getFillColor: [200, 200, 200]
244 | }),
245 | ]
246 | })
247 | console.log(deck)
248 | }
249 |
250 | document.addEventListener('DOMContentLoaded', renderToDom);
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import m from 'maplibre-gl';
2 | import { lercToImage } from './cogs.js';
3 |
4 | const cancel = { cancel() { } };
5 |
6 | m.addProtocol('cog+lerc', (req, cb) => {
7 | if (req.type !== 'image') throw new Error('Invalid request type: ' + req.type)
8 |
9 | lercToImage(req.url).then(buf => {
10 | if (buf) return cb(null, buf);
11 | return cb(new Error('Failed'), null);
12 | })
13 | return cancel
14 | })
15 |
16 | document.addEventListener('DOMContentLoaded', async () => {
17 | const main = document.querySelector('#main');
18 | if (main == null) throw new Error('Failed to find #main')
19 |
20 | const style = {
21 | version: 8,
22 | sources: {
23 | linz: {
24 | type: 'raster',
25 | tiles: ['https://basemaps.linz.govt.nz/v1/tiles/aerial/WebMercatorQuad/{z}/{x}/{y}.webp?api=c01h3e17kjsw5evq8ndjxbda80e'],
26 | tileSize: 256,
27 | },
28 | raster: {
29 | type: 'raster',
30 | tiles: ['cog+lerc://Taranaki2021#ramp@{z}/{x}/{y}'],
31 | tileSize: 256,
32 | minzoom: 10,
33 | maxzoom: 18,
34 | },
35 | // TODO why do we need both a hillshade and terrain source
36 | // ref : https://maplibre.org/maplibre-gl-js/docs/examples/3d-terrain/
37 | hillshadeSource: {
38 | type: 'raster-dem',
39 | tiles: ['cog+lerc://Taranaki2021#mapbox@{z}/{x}/{y}'],
40 | tileSize: 256,
41 | encoding: 'mapbox'
42 | },
43 | terrainSource: {
44 | type: 'raster-dem',
45 | tiles: ['cog+lerc://Taranaki2021#mapbox@{z}/{x}/{y}'],
46 | tileSize: 256,
47 | encoding: 'mapbox'
48 | },
49 | },
50 | layers: [
51 | { id: 'linz', type: 'raster', source: 'linz' },
52 | ],
53 | terrain: {
54 | source: 'terrainSource', exaggeration: 1
55 | }
56 | } as any
57 |
58 |
59 | const map = new m.Map({
60 | container: 'main',
61 | zoom: 10,
62 | center: [174.0416, -39.333],
63 | hash: true,
64 | style,
65 | });
66 |
67 | map.addControl(
68 | new m.NavigationControl({
69 | visualizePitch: true,
70 | showZoom: true,
71 | showCompass: true
72 | })
73 | );
74 |
75 | map.addControl(
76 | new m.TerrainControl({
77 | source: 'terrainSource',
78 | exaggeration: 1
79 | })
80 | );
81 |
82 |
83 | document.querySelector('#color-ramp')?.addEventListener('click', () => {
84 | const ramp = map.getLayer('ramp')
85 | if (ramp) {
86 | map.removeLayer('ramp')
87 | } else {
88 | map.addLayer({ id: 'ramp', type: 'raster', source: 'raster' }, map.getLayer('hillshade') ? 'hillshade' : undefined)
89 | }
90 | })
91 |
92 | document.querySelector('#hillshade')?.addEventListener('click', () => {
93 | const shade = map.getLayer('hillshade')
94 | if (shade) {
95 | map.removeLayer('hillshade')
96 | } else {
97 | map.addLayer({
98 | id: 'hillshade',
99 | type: 'hillshade',
100 | source: 'hillshadeSource',
101 | layout: { visibility: 'visible' },
102 | paint: {
103 | 'hillshade-shadow-color': '#473B24'
104 | }
105 | })
106 | }
107 | })
108 | // map.showTileBoundaries = true
109 | window['map'] = map;
110 | })
111 |
--------------------------------------------------------------------------------
/src/quadkey.ts:
--------------------------------------------------------------------------------
1 |
2 | const CHAR_0 = '0'.charCodeAt(0);
3 | const CHAR_1 = '1'.charCodeAt(0);
4 | const CHAR_2 = '2'.charCodeAt(0);
5 | const CHAR_3 = '3'.charCodeAt(0);
6 |
7 | export const QuadKey = {
8 | /**
9 | * Convert a tile location to a quadkey
10 | * @param tile tile to covert
11 | */
12 | fromTile(z: number, x: number, y: number): string {
13 | let quadKey = '';
14 | for (let zI = z; zI > 0; zI--) {
15 | let b = CHAR_0;
16 | const mask = 1 << (zI - 1);
17 | if ((x & mask) !== 0) b++;
18 | if ((y & mask) !== 0) b += 2;
19 | quadKey += String.fromCharCode(b);
20 | }
21 | return quadKey;
22 | },
23 |
24 | toZxy(qk: string): string {
25 | const tile = this.toTile(qk);
26 | return `${tile.z}-${tile.x}-${tile.y}`
27 | },
28 |
29 | /**
30 | * Convert a quadkey to a XYZ Tile location
31 | * @param quadKey quadkey to convert
32 | */
33 | toTile(quadKey: string): { z: number, x: number, y: number } {
34 | let x = 0;
35 | let y = 0;
36 | const z = quadKey.length;
37 |
38 | for (let i = z; i > 0; i--) {
39 | const mask = 1 << (i - 1);
40 | const q = quadKey.charCodeAt(z - i);
41 | if (q === CHAR_1) x |= mask;
42 | if (q === CHAR_2) y |= mask;
43 | if (q === CHAR_3) {
44 | x |= mask;
45 | y |= mask;
46 | }
47 | }
48 | return { x, y, z };
49 | },
50 | };
--------------------------------------------------------------------------------
/src/ramp.ts:
--------------------------------------------------------------------------------
1 |
2 | export class ColorRamp {
3 | noData: { v: number, color: [number, number, number, number] };
4 | ramps: { v: number, color: [number, number, number, number] }[] = []
5 | constructor(ramp: string, noDataValue: number) {
6 | const ramps = ramp.split('\n')
7 |
8 | for (const ramp of ramps) {
9 | const parts = ramp.trim().split(' ')
10 | if (parts[0] == 'nv') {
11 | this.noData = { v: noDataValue, color: parts.slice(1).map(Number) as [number, number, number, number] }
12 | continue;
13 | }
14 | const numbers = parts.map(Number)
15 | this.ramps.push({ v: numbers[0], color: numbers.slice(1) as [number, number, number, number] });
16 | }
17 | }
18 |
19 | get(num:number): [number, number, number, number] {
20 | if (num === this.noData.v) return this.noData.color;
21 |
22 | const first = this.ramps[0];
23 | if (num < first[0]) return first[0].color
24 |
25 | for (let i = 0; i < this.ramps.length - 1; i++) {
26 | const ramp = this.ramps[i];
27 | const rampNext = this.ramps[i + 1];
28 | if (num >= rampNext.v) continue;
29 | if (num < ramp.v) continue
30 | if (ramp.v == num) return ramp.color;
31 |
32 | const range = rampNext.v - ramp.v
33 | const offset = num - ramp.v;
34 | const scale = offset / range;
35 |
36 | const r = Math.round((rampNext.color[0] - ramp.color[0]) * scale + ramp.color[0])
37 | const g = Math.round((rampNext.color[1] - ramp.color[1]) * scale + ramp.color[1])
38 | const b = Math.round((rampNext.color[2] - ramp.color[2]) * scale + ramp.color[2])
39 | const a = Math.round((rampNext.color[3] - ramp.color[3]) * scale + ramp.color[3])
40 |
41 | return [r, g, b, a]
42 | }
43 | return this.ramps[this.ramps.length - 1].color
44 | }
45 | }
46 |
47 | // Stolen from https://github.com/andrewharvey/srtm-stylesheets/blob/master/stylesheets/color-ramps/srtm-Australia-color-ramp.gdaldem.txt
48 | export const ramp = new ColorRamp(`nv 0 0 0 0
49 | -8764 0 0 0 255
50 | -4000 3 45 85 255
51 | -100 0 101 199 255
52 | 0 192 224 255 255
53 | 1 108 220 108 255
54 | 55 50 180 50 255
55 | 390 240 250 150 255
56 | 835 190 185 135 255
57 | 1114 180 128 107 255
58 | 1392 235 220 175 255
59 | 2000 215 200 244 255
60 | 4000 255 0 255 255`, -9999)
--------------------------------------------------------------------------------