isard 0.7.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/dist/basemap.worker.d.ts +7 -1
  3. package/dist/basemap.worker.js +2 -2
  4. package/dist/basemap.worker.js.map +8 -7
  5. package/dist/basemaps.d.ts +3 -3
  6. package/dist/basemaps.js +2 -14
  7. package/dist/basemaps.js.map +1 -1
  8. package/dist/controls.d.ts +4 -3
  9. package/dist/controls.js +0 -8
  10. package/dist/controls.js.map +1 -1
  11. package/dist/decoder.worker.js +4 -4
  12. package/dist/decoder.worker.js.map +6 -5
  13. package/dist/engine-loader.d.ts +12 -5
  14. package/dist/engine-loader.js +36 -5
  15. package/dist/engine-loader.js.map +1 -1
  16. package/dist/geoplateforme.d.ts +51 -1
  17. package/dist/geoplateforme.js +36 -1
  18. package/dist/geoplateforme.js.map +1 -1
  19. package/dist/glyphs.js +2 -1
  20. package/dist/glyphs.js.map +1 -1
  21. package/dist/icons.js +5 -1
  22. package/dist/icons.js.map +1 -1
  23. package/dist/index.d.ts +7 -5
  24. package/dist/index.js +5 -3
  25. package/dist/index.js.map +1 -1
  26. package/dist/interaction.d.ts +2 -0
  27. package/dist/interaction.js +29 -2
  28. package/dist/interaction.js.map +1 -1
  29. package/dist/isard_bg.wasm +0 -0
  30. package/dist/isard_core_bg.wasm +0 -0
  31. package/dist/layers.d.ts +5 -2
  32. package/dist/layers.js +37 -8
  33. package/dist/layers.js.map +1 -1
  34. package/dist/loader.d.ts +2 -0
  35. package/dist/loader.js +10 -0
  36. package/dist/loader.js.map +1 -1
  37. package/dist/map.d.ts +116 -4
  38. package/dist/map.js +245 -13
  39. package/dist/map.js.map +1 -1
  40. package/dist/overlay.d.ts +40 -0
  41. package/dist/overlay.js +119 -0
  42. package/dist/overlay.js.map +1 -1
  43. package/dist/panoramas.d.ts +94 -0
  44. package/dist/panoramas.js +245 -0
  45. package/dist/panoramas.js.map +1 -0
  46. package/dist/pmtiles.js +3 -2
  47. package/dist/pmtiles.js.map +1 -1
  48. package/dist/pointclouds.js +1 -1
  49. package/dist/pointclouds.js.map +1 -1
  50. package/dist/protocol.d.ts +7 -1
  51. package/dist/protocol.js.map +1 -1
  52. package/dist/requests.d.ts +14 -0
  53. package/dist/requests.js +48 -0
  54. package/dist/requests.js.map +1 -0
  55. package/dist/resample.js +2 -1
  56. package/dist/resample.js.map +1 -1
  57. package/dist/style.js +1 -0
  58. package/dist/style.js.map +1 -1
  59. package/dist/terrain.d.ts +0 -5
  60. package/dist/terrain.js +2 -1
  61. package/dist/terrain.js.map +1 -1
  62. package/dist/types.d.ts +40 -8
  63. package/dist/types.js.map +1 -1
  64. package/dist/vectortiles.d.ts +2 -2
  65. package/dist/vectortiles.js +16 -4
  66. package/dist/vectortiles.js.map +1 -1
  67. package/dist/wasm/isard.d.ts +79 -5
  68. package/dist/wasm/isard.js +165 -7
  69. package/dist/wasm/isard_core.d.ts +38 -0
  70. package/dist/wasm/isard_core.js +99 -0
  71. package/dist/wmts.js +2 -1
  72. package/dist/wmts.js.map +1 -1
  73. package/package.json +8 -2
  74. package/vite.d.ts +17 -0
  75. package/vite.js +64 -0
package/dist/map.js CHANGED
@@ -5,17 +5,20 @@
5
5
  * the camera animations in animation.ts.
6
6
  */
7
7
  import { easeTo, flyTo } from "./animation.js";
8
- import { BASEMAPS, basemapName, HILLSHADE, SEA } from "./basemaps.js";
8
+ import { BASEMAPS, HILLSHADE, RENAMED_BASEMAPS, SEA } from "./basemaps.js";
9
9
  import { AttributionControl } from "./controls.js";
10
10
  import { destroyedEngine, engineUrl, loadEngine, loadFullEngineLater, preloadFullEngine, startTileLoader, } from "./engine-loader.js";
11
11
  import { ExtrusionLayer, extrusionStyle } from "./extrusions.js";
12
12
  import { CircleLayer, circleStyle, FillLayer, fillStyle, LineLayer, lineStyle, } from "./features.js";
13
+ import { IGN_PRESETS } from "./geoplateforme.js";
13
14
  import { Glyphs } from "./glyphs.js";
14
15
  import { equirectangularGrid, gridLoader, gridZooms, resolveGrid } from "./grid.js";
15
16
  import { Icons, readPixels } from "./icons.js";
16
17
  import { Interaction } from "./interaction.js";
17
18
  import { CustomLayer, GroundLayer, ModelLayer, NetworkLayer, RasterLayer, Tiles3dLayer, } from "./layers.js";
19
+ import { loadPanoramas } from "./panoramas.js";
18
20
  import { PointCloudLayer } from "./pointclouds.js";
21
+ import { headerRules, onHeaderRules } from "./requests.js";
19
22
  import { atmosphereSettings, bodySettings, haloSettings, rgb, terrainSettings, } from "./settings.js";
20
23
  import { injectStyle } from "./style.js";
21
24
  import { SymbolLayer, symbolStyle } from "./symbols.js";
@@ -48,11 +51,13 @@ const CORNERS = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
48
51
  const MAX_POLLS = 30;
49
52
  /** The name of a basemap, checked: an unknown one throws */
50
53
  function checkBasemap(basemap) {
51
- const name = basemapName(basemap);
52
- if (name !== 'none' && !(name in VECTOR_BASEMAPS) && !(name in BASEMAPS)) {
54
+ const renamed = RENAMED_BASEMAPS[basemap];
55
+ if (renamed)
56
+ throw new Error(`isard: the basemap '${basemap}' is now named '${renamed}'`);
57
+ if (basemap !== 'none' && !(basemap in VECTOR_BASEMAPS) && !(basemap in BASEMAPS)) {
53
58
  throw new Error(`isard: unknown basemap '${basemap}'`);
54
59
  }
55
- return name;
60
+ return basemap;
56
61
  }
57
62
  /** A map (see `GeoMap.create`); layers take it as their host */
58
63
  export class GeoMap {
@@ -138,13 +143,17 @@ export class GeoMap {
138
143
  basemapPool;
139
144
  /** Stops watching the device pixel ratio */
140
145
  unwatchRatio;
146
+ /** Stops following the page's request headers (`setRequestHeaders`) */
147
+ unwatchHeaders = () => undefined;
141
148
  /** Stops listening to the canvas's context loss and restoration */
142
149
  unwatchContext;
143
150
  /** The loaders of the relief by encoding, URL and floor: the same loader for the same tiles (the engine keeps its
144
151
  * tiles when only the exaggeration changes) */
145
152
  terrainLoaders = new Map();
146
153
  /** Loads the engine (once per page) and creates a map filling `container` */
147
- static async create(container, options = {}) {
154
+ static async create(container, given = {}) {
155
+ // A preset under the options given
156
+ const options = given.preset ? { ...IGN_PRESETS[given.preset], ...given } : given;
148
157
  // With 3D Tiles from the start when asked, or when only that engine's URL is given (as before the core engine)
149
158
  const full = options.tiles3d === true || (options.wasmUrl !== undefined && options.coreWasmUrl === undefined);
150
159
  // Before anything is created
@@ -162,7 +171,7 @@ export class GeoMap {
162
171
  this.tiles3dModule = tiles3dModule;
163
172
  this.tiles3dOptions = { ...options };
164
173
  this.glyphsUrl = options.glyphs;
165
- this.basemapWorkerUrl = options.basemapWorkerUrl;
174
+ this.basemapWorkerUrl = options.basemapWorkerUrl ?? defaultWorkerUrl(options.assetsUrl);
166
175
  this.basemapTileSize = options.basemapTileSize;
167
176
  this.container = container;
168
177
  this.canvas = document.createElement('canvas');
@@ -202,6 +211,8 @@ export class GeoMap {
202
211
  globeColor: this.earth ? SEA['osm-positron'] : rgb(body.color),
203
212
  };
204
213
  this.#engine = this.createEngine();
214
+ // Once it has an engine: a map whose creation failed before is not left following them
215
+ this.unwatchHeaders = onHeaderRules((rules) => sendHeaders(this.#engine, rules));
205
216
  // The browser may take the GPU away (driver reset, background tab on mobile): the map waits, then rebuilds
206
217
  const lost = (event) => {
207
218
  event.preventDefault();
@@ -256,6 +267,7 @@ export class GeoMap {
256
267
  // The body first: the layers' shaders may take its size
257
268
  const { radius, flattening, atmosphere: air, relief } = this.settings.body;
258
269
  engine.setBody(radius, flattening, haloSettings(air), ...relief);
270
+ sendHeaders(engine, headerRules());
259
271
  const { zoomRange, maxPitch, globe, sky, atmosphere, terrain, loading, background, globeColor } = this.settings;
260
272
  engine.setZoomRange(...zoomRange);
261
273
  engine.setMaxPitch(maxPitch);
@@ -349,8 +361,68 @@ export class GeoMap {
349
361
  report(error);
350
362
  }
351
363
  }
364
+ this.applySwipe();
365
+ // A street-level eye stays one in the new engine
366
+ if (this.#firstPerson)
367
+ this.setFirstPerson(this.#firstPerson);
368
+ // What the old engine drew over the scene: the viewshed, the panoramas shown
369
+ if (this.viewshed)
370
+ this.setViewshed(this.viewshed);
371
+ for (const set of this.panoramaSets)
372
+ if (set.current)
373
+ void set.show(set.current.index).catch(report);
352
374
  this.resize();
353
375
  }
376
+ /** The street-level eye, while there is one (`setFirstPerson`) */
377
+ #firstPerson;
378
+ /** The street-level eye, if the camera is one */
379
+ get firstPerson() {
380
+ return this.#firstPerson;
381
+ }
382
+ /**
383
+ * Puts the camera at street level: an eye `height` metres above the ground, looking `bearing` and `pitch`, the
384
+ * drag turning it around (the wheel narrows or widens its field of view); undefined gives back the camera turning
385
+ * around a point, above where the eye stood, facing the same way
386
+ */
387
+ setFirstPerson(view) {
388
+ if (!view) {
389
+ const was = this.#firstPerson;
390
+ this.#firstPerson = undefined;
391
+ if (was)
392
+ this.setCamera({ center: was.lonLat, zoom: 18, pitch: 60, bearing: was.bearing });
393
+ return;
394
+ }
395
+ const eye = {
396
+ height: 1.7,
397
+ pitch: 90,
398
+ fov: 75,
399
+ ...view,
400
+ lonLat: [view.lonLat[0], view.lonLat[1]],
401
+ };
402
+ eye.pitch = Math.max(1, Math.min(179, eye.pitch));
403
+ eye.fov = Math.max(10, Math.min(140, eye.fov));
404
+ eye.bearing = ((eye.bearing % 360) + 360) % 360;
405
+ this.#firstPerson = eye;
406
+ this.engine.setFirstPerson(eye.lonLat[0], eye.lonLat[1], eye.height, eye.bearing, eye.pitch, eye.fov);
407
+ this.requestRender();
408
+ }
409
+ /** The swipe set (`setSwipe`), applied again with the layers' ids of a new engine */
410
+ swipe;
411
+ /**
412
+ * Compares two states of a place: `layers` shown on one side of a vertical line only, at `position` CSS pixels
413
+ * from the left of the map (left of it by default, `side: 'right'` for the other), the layers beneath them on the
414
+ * other side. Set again as the line moves (a slider, a drag); undefined stops
415
+ */
416
+ setSwipe(options) {
417
+ this.swipe = options && options.layers.length > 0 ? { ...options, layers: [...options.layers] } : undefined;
418
+ this.applySwipe();
419
+ this.requestRender();
420
+ }
421
+ applySwipe() {
422
+ const s = this.swipe;
423
+ const ids = Uint32Array.from((s?.layers ?? []).filter((l) => l.id >= 0), (l) => l.id);
424
+ this.engine.setSwipe(s && ids.length > 0 ? s.position : Number.NaN, s?.side === 'right', ids);
425
+ }
354
426
  /** @internal Forgets a removed layer */
355
427
  detach(layer) {
356
428
  this.unlist(layer);
@@ -368,7 +440,7 @@ export class GeoMap {
368
440
  if (index >= 0)
369
441
  this.layers.splice(index, 1);
370
442
  }
371
- add(layer) {
443
+ addLayer(layer) {
372
444
  // On the core engine, a 3D Tiles layer or a model waits for the engine with 3D Tiles: it is created with the
373
445
  // others on it
374
446
  if (layer.needsFullEngine && !this.tiles3dModule)
@@ -439,6 +511,37 @@ export class GeoMap {
439
511
  }
440
512
  }
441
513
  // ── Camera ──
514
+ /**
515
+ * The camera's methods together: `get`, `set`, `easeTo`, `flyTo`, `bounds`, `firstPerson` and `setFirstPerson`
516
+ * (street level), `project`, `unproject`; the same as the map's own (`getCamera`, `setCamera`…)
517
+ */
518
+ camera = {
519
+ get: () => this.getCamera(),
520
+ set: (camera) => this.setCamera(camera),
521
+ easeTo: (camera, options) => this.easeTo(camera, options),
522
+ flyTo: (camera, options) => this.flyTo(camera, options),
523
+ bounds: () => this.getBounds(),
524
+ firstPerson: () => this.firstPerson,
525
+ setFirstPerson: (view) => this.setFirstPerson(view),
526
+ project: (lonLat, height) => this.project(lonLat, height),
527
+ unproject: (point) => this.unproject(point),
528
+ };
529
+ /**
530
+ * What lies under a point or at a position, together: `feature` (`pickFeature`), `surface` (`pickSurface`),
531
+ * `surfaceAt`, `elevationAt`, `metersPerPixel`
532
+ */
533
+ query = {
534
+ feature: (point, options) => this.pickFeature(point, options),
535
+ surface: (point) => this.pickSurface(point),
536
+ surfaceAt: (lonLat) => this.surfaceAt(lonLat),
537
+ elevationAt: (lonLat) => this.elevationAt(lonLat),
538
+ metersPerPixel: (point) => this.metersPerPixel(point),
539
+ };
540
+ /** What is drawn over the scene, together: `viewshed` (`setViewshed`), `swipe` (`setSwipe`) */
541
+ effects = {
542
+ viewshed: (options) => this.setViewshed(options),
543
+ swipe: (options) => this.setSwipe(options),
544
+ };
442
545
  getCamera() {
443
546
  return this.frameCamera ?? this.engine.camera();
444
547
  }
@@ -515,7 +618,10 @@ export class GeoMap {
515
618
  * (`direction`): the relief, extrusions, 3D Tiles and models hide what lies behind them (only what the map has
516
619
  * loaded for its view). Several observers (16 at most): what any of them sees is seen, what is hidden from all those
517
620
  * that reach it is hidden, in the colors and opacity of the first. Undefined or none removes it */
621
+ /** The viewshed set, set again in a new engine */
622
+ viewshed;
518
623
  setViewshed(options) {
624
+ this.viewshed = options;
519
625
  let observers = [];
520
626
  if (options)
521
627
  observers = 'position' in options ? [options] : options;
@@ -643,6 +749,77 @@ export class GeoMap {
643
749
  unproject(point) {
644
750
  return this.engine.ground(point[0], point[1]);
645
751
  }
752
+ /**
753
+ * Street-level panoramas (oriented images of a vehicle's cameras, the iTowns immersive format): their positions
754
+ * and calibrations loaded, none shown until `show`, which projects one onto the scene around it
755
+ */
756
+ async addPanoramas(options) {
757
+ // Drawn by the engine with 3D Tiles: loaded first if needed
758
+ if (!this.tiles3dModule) {
759
+ this.upgrade();
760
+ await this.upgrading;
761
+ if (!this.tiles3dModule)
762
+ throw new Error('isard: panoramas need the engine with 3D Tiles, which failed to load');
763
+ }
764
+ const host = {
765
+ setPanorama: (...args) => {
766
+ this.engine.setPanorama(...args);
767
+ this.requestRender();
768
+ },
769
+ setPanoramaImage: (index, image) => this.engine.setPanoramaImage(index, image),
770
+ clearPanorama: () => this.engine.clearPanorama(),
771
+ geoidHeight: (lon, lat) => this.engineClass.geoidHeight(lon, lat),
772
+ firstPerson: () => this.firstPerson,
773
+ setFirstPerson: (view) => this.setFirstPerson(view),
774
+ elevationAt: (lonLat) => this.elevationAt(lonLat),
775
+ listen: (click, key, wheel) => {
776
+ const off = this.on('click', ({ lonLat }) => click(lonLat));
777
+ const container = this.getContainer();
778
+ // Before the map's own wheel (its zoom, the eye's field of view)
779
+ const onWheel = (e) => {
780
+ e.preventDefault();
781
+ e.stopImmediatePropagation();
782
+ wheel(e);
783
+ };
784
+ container.addEventListener('keydown', key);
785
+ container.addEventListener('wheel', onWheel, { capture: true, passive: false });
786
+ return () => {
787
+ off();
788
+ container.removeEventListener('keydown', key);
789
+ container.removeEventListener('wheel', onWheel, { capture: true });
790
+ };
791
+ },
792
+ };
793
+ const panoramas = await loadPanoramas(host, options);
794
+ this.panoramaSets.add(panoramas);
795
+ return panoramas;
796
+ }
797
+ /** The panorama sets, their panorama shown again in a new engine */
798
+ panoramaSets = new Set();
799
+ /** Altitude of the relief at a position, in metres (exaggeration included): from the copy of its tiles the map
800
+ * keeps, as fine as the tiles loaded there; undefined without relief or where none is loaded yet */
801
+ elevationAt(lonLat) {
802
+ return this.engine.elevationAt(lonLat[0], lonLat[1]);
803
+ }
804
+ /** Metres on the ground per CSS pixel at a screen point (default the center of the map), across the screen: for a
805
+ * scale bar; undefined above the horizon */
806
+ metersPerPixel(point) {
807
+ const [x, y] = point ?? [this.canvas.clientWidth / 2, this.canvas.clientHeight / 2];
808
+ const a = this.unproject([x - 0.5, y]);
809
+ const b = this.unproject([x + 0.5, y]);
810
+ if (!a || !b)
811
+ return undefined;
812
+ // Haversine, on the mean radius of the body
813
+ const rad = Math.PI / 180;
814
+ const [dLat, dLon] = [(b[1] - a[1]) * rad, (b[0] - a[0]) * rad];
815
+ const h = Math.sin(dLat / 2) ** 2 + Math.cos(a[1] * rad) * Math.cos(b[1] * rad) * Math.sin(dLon / 2) ** 2;
816
+ return 2 * this.settings.body.radius * Math.asin(Math.min(1, Math.sqrt(h)));
817
+ }
818
+ /** Whether a double click zooms in (Shift: out), on by default: off while a drawing takes double clicks */
819
+ setDoubleClickZoom(enabled) {
820
+ if (this.interaction)
821
+ this.interaction.doubleClickZoom = enabled;
822
+ }
646
823
  /** What is drawn under a screen point (CSS pixels), on the relief or standing on it (a roof, a wall, a mesh): its
647
824
  * position and its height above the relief, in metres; undefined where nothing was drawn. The last frame's scene is
648
825
  * drawn again and read back, waiting for the GPU (a stall): for clicks and drags */
@@ -698,7 +875,7 @@ export class GeoMap {
698
875
  }
699
876
  // ── Layers ──
700
877
  /** Replaces the basemap and the IGN hillshade, under the other layers (hillshade by default: 0, none). The former
701
- * names of the Géoplateforme basemaps (`LegacyBasemap`) are taken under their new ones */
878
+ * names of the Géoplateforme basemaps throw, naming the new ones */
702
879
  setBasemap(basemap, hillshade = 0) {
703
880
  const name = checkBasemap(basemap);
704
881
  if (this.basemap && this.hasLayer(this.basemap))
@@ -776,7 +953,52 @@ export class GeoMap {
776
953
  const { halo = 0, haloOpacity = 0.11, ramp, unreachedColor = 'rgba(140, 140, 140, 0.25)', fade = 0 } = options;
777
954
  const style = { width, max, contour, opacity, halo, haloOpacity, ramp, unreachedColor, fade };
778
955
  validateNetwork(nodes, edges);
779
- return this.add(new NetworkLayer(this, { nodes, edges, lines }, costs, style, edgeWidths));
956
+ return this.addLayer(new NetworkLayer(this, { nodes, edges, lines }, costs, style, edgeWidths));
957
+ }
958
+ /**
959
+ * A layer from its description, as an application's configuration gives it: `{ type, ...options }`, the options of
960
+ * the `add…` method of that type (`'lines'` for `addLines`, `'tiles3d'` for `addTiles3d`…); `before` to go under
961
+ * another layer. The layer's `ready` resolves once the map has drawn it
962
+ */
963
+ add(spec) {
964
+ switch (spec.type) {
965
+ case 'lines':
966
+ return this.addLines(spec);
967
+ case 'circles':
968
+ return this.addCircles(spec);
969
+ case 'fills':
970
+ return this.addFills(spec);
971
+ case 'symbols':
972
+ return this.addSymbols(spec);
973
+ case 'extrusions':
974
+ return this.addExtrusions(spec);
975
+ case 'raster':
976
+ return this.addRaster(spec);
977
+ case 'ground':
978
+ return this.addGround(spec);
979
+ case 'network':
980
+ return this.addNetwork(spec);
981
+ case 'tiles3d':
982
+ return this.addTiles3d(spec);
983
+ case 'pointcloud':
984
+ return this.addPointCloud(spec);
985
+ case 'models':
986
+ return this.addModels(spec);
987
+ default:
988
+ throw new Error(`isard: no layer of type ${String(spec.type)}`);
989
+ }
990
+ }
991
+ /** @internal Resolves once the map is idle (everything in view loaded and drawn) */
992
+ whenIdle() {
993
+ if (this.gone)
994
+ return Promise.resolve();
995
+ return new Promise((resolve) => {
996
+ const off = this.on('idle', () => {
997
+ off();
998
+ resolve();
999
+ });
1000
+ this.requestRender();
1001
+ });
780
1002
  }
781
1003
  /** Lines from GeoJSON (line strings, and polygon outlines), styled per feature */
782
1004
  addLines(options) {
@@ -864,7 +1086,7 @@ export class GeoMap {
864
1086
  * when it asks for another count or URL
865
1087
  */
866
1088
  basemapWorkers(count, url) {
867
- const sharedUrl = this.basemapWorkerUrl ?? defaultWorkerUrl();
1089
+ const sharedUrl = this.basemapWorkerUrl;
868
1090
  const shared = defaultWorkerCount();
869
1091
  const workers = Math.max(1, count ?? shared);
870
1092
  const workerUrl = url ?? sharedUrl;
@@ -900,15 +1122,20 @@ export class GeoMap {
900
1122
  };
901
1123
  /** Adds a layer, under `before` if given */
902
1124
  place(layer, before) {
903
- this.add(layer);
1125
+ this.addLayer(layer);
904
1126
  if (before)
905
1127
  this.moveLayer(layer, before);
906
1128
  return layer;
907
1129
  }
908
1130
  /** Textured meshes in 3D Tiles (photogrammetry, buildings), drawn with depth over the basemap */
909
1131
  addTiles3d(options) {
910
- const { url, maxScreenSpaceError = 16, opacity = 1, pointSize } = options;
911
- return this.add(new Tiles3dLayer(this, url, { maxScreenSpaceError, opacity, ...(pointSize !== undefined ? { pointSize } : {}) }));
1132
+ const { url, maxScreenSpaceError = 16, opacity = 1, pointSize, color, geoid = false } = options;
1133
+ return this.addLayer(new Tiles3dLayer(this, url, geoid, {
1134
+ maxScreenSpaceError,
1135
+ opacity,
1136
+ ...(pointSize !== undefined ? { pointSize } : {}),
1137
+ ...(color !== undefined ? { color } : {}),
1138
+ }));
912
1139
  }
913
1140
  /**
914
1141
  * A point cloud (see `PointCloudOptions`): a COPC file read by range requests (IGN's LiDAR HD…), or 3D Tiles
@@ -1077,6 +1304,7 @@ export class GeoMap {
1077
1304
  this.basemapPool = undefined;
1078
1305
  this.unwatchRatio?.();
1079
1306
  this.unwatchRatio = undefined;
1307
+ this.unwatchHeaders();
1080
1308
  this.resizeObserver.disconnect();
1081
1309
  this.interaction?.destroy();
1082
1310
  this.loader?.destroy();
@@ -1103,4 +1331,8 @@ export class GeoMap {
1103
1331
  listeners.clear();
1104
1332
  }
1105
1333
  }
1334
+ /** The page's request headers to an engine (its own requests: raster tiles, tilesets, point clouds) */
1335
+ function sendHeaders(engine, rules) {
1336
+ engine.setRequestHeaders(rules.map(([prefix]) => prefix), Uint32Array.from(rules, ([, headers]) => Object.keys(headers).length), rules.flatMap(([, headers]) => Object.entries(headers).flat()));
1337
+ }
1106
1338
  //# sourceMappingURL=map.js.map