isard 1.1.0 → 1.3.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 (254) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/README.md +44 -39
  3. package/dist/basemap/basemaps.d.ts +1 -1
  4. package/dist/basemap/basemaps.js +2 -2
  5. package/dist/basemap/basemaps.js.map +1 -1
  6. package/dist/basemap/grid.d.ts +5 -5
  7. package/dist/basemap/grid.js +59 -65
  8. package/dist/basemap/grid.js.map +1 -1
  9. package/dist/basemap/mvt.d.ts +1 -1
  10. package/dist/basemap/mvt.js +6 -6
  11. package/dist/basemap/mvt.js.map +1 -1
  12. package/dist/basemap/pmtiles.d.ts +10 -10
  13. package/dist/basemap/pmtiles.js +39 -31
  14. package/dist/basemap/pmtiles.js.map +1 -1
  15. package/dist/basemap/pmtileslayer.d.ts +33 -0
  16. package/dist/basemap/pmtileslayer.js +97 -0
  17. package/dist/basemap/pmtileslayer.js.map +1 -0
  18. package/dist/basemap/resample.d.ts +2 -2
  19. package/dist/basemap/resample.js +16 -14
  20. package/dist/basemap/resample.js.map +1 -1
  21. package/dist/basemap/terrain.d.ts +3 -3
  22. package/dist/basemap/terrain.js +6 -6
  23. package/dist/basemap/terrain.js.map +1 -1
  24. package/dist/basemap/trees.d.ts +26 -0
  25. package/dist/basemap/trees.js +141 -0
  26. package/dist/basemap/trees.js.map +1 -0
  27. package/dist/basemap/vectorstyle.d.ts +22 -10
  28. package/dist/basemap/vectorstyle.js +163 -110
  29. package/dist/basemap/vectorstyle.js.map +1 -1
  30. package/dist/basemap/vectortiles.d.ts +70 -47
  31. package/dist/basemap/vectortiles.js +480 -358
  32. package/dist/basemap/vectortiles.js.map +1 -1
  33. package/dist/basemap/wmts.d.ts +3 -3
  34. package/dist/basemap/wmts.js +16 -11
  35. package/dist/basemap/wmts.js.map +1 -1
  36. package/dist/basemap/workerpool.d.ts +17 -0
  37. package/dist/basemap/workerpool.js +194 -0
  38. package/dist/basemap/workerpool.js.map +1 -0
  39. package/dist/basemap.worker.js +2 -2
  40. package/dist/basemap.worker.js.map +21 -13
  41. package/dist/bind/layers.d.ts +13 -4
  42. package/dist/bind/layers.js +64 -40
  43. package/dist/bind/layers.js.map +1 -1
  44. package/dist/data/crs.d.ts +10 -10
  45. package/dist/data/crs.js +38 -34
  46. package/dist/data/crs.js.map +1 -1
  47. package/dist/data/gpx.d.ts +1 -1
  48. package/dist/data/gpx.js +20 -20
  49. package/dist/data/gpx.js.map +1 -1
  50. package/dist/data/kml.d.ts +1 -1
  51. package/dist/data/kml.js +42 -39
  52. package/dist/data/kml.js.map +1 -1
  53. package/dist/data/topojson.d.ts +1 -1
  54. package/dist/data/topojson.js +15 -10
  55. package/dist/data/topojson.js.map +1 -1
  56. package/dist/data/xml.d.ts +5 -5
  57. package/dist/data/xml.js +19 -18
  58. package/dist/data/xml.js.map +1 -1
  59. package/dist/decoder.worker.js +4 -4
  60. package/dist/decoder.worker.js.map +6 -6
  61. package/dist/engine/decoders.d.ts +2 -2
  62. package/dist/engine/decoders.js +28 -25
  63. package/dist/engine/decoders.js.map +1 -1
  64. package/dist/engine/loader.js +13 -14
  65. package/dist/engine/loader.js.map +1 -1
  66. package/dist/engine/requests.d.ts +1 -1
  67. package/dist/engine/requests.js +19 -16
  68. package/dist/engine/requests.js.map +1 -1
  69. package/dist/engine-loader.d.ts +13 -9
  70. package/dist/engine-loader.js +38 -28
  71. package/dist/engine-loader.js.map +1 -1
  72. package/dist/geoplateforme.d.ts +26 -10
  73. package/dist/geoplateforme.js +45 -20
  74. package/dist/geoplateforme.js.map +1 -1
  75. package/dist/index.d.ts +12 -4
  76. package/dist/index.js +9 -2
  77. package/dist/index.js.map +1 -1
  78. package/dist/isard_bg.wasm +0 -0
  79. package/dist/isard_core_bg.wasm +0 -0
  80. package/dist/isard_points_bg.wasm +0 -0
  81. package/dist/isard_tess_bg.wasm +0 -0
  82. package/dist/layers/extrusions.d.ts +1 -1
  83. package/dist/layers/extrusions.js +10 -5
  84. package/dist/layers/extrusions.js.map +1 -1
  85. package/dist/layers/features.d.ts +10 -10
  86. package/dist/layers/features.js +41 -42
  87. package/dist/layers/features.js.map +1 -1
  88. package/dist/layers/glyphs.d.ts +3 -3
  89. package/dist/layers/glyphs.js +34 -40
  90. package/dist/layers/glyphs.js.map +1 -1
  91. package/dist/layers/icons.d.ts +8 -8
  92. package/dist/layers/icons.js +76 -68
  93. package/dist/layers/icons.js.map +1 -1
  94. package/dist/layers/layers.d.ts +1 -1
  95. package/dist/layers/layers.js +42 -29
  96. package/dist/layers/layers.js.map +1 -1
  97. package/dist/layers/panoramas.d.ts +2 -2
  98. package/dist/layers/panoramas.js +52 -41
  99. package/dist/layers/panoramas.js.map +1 -1
  100. package/dist/layers/pointclouds.d.ts +3 -3
  101. package/dist/layers/pointclouds.js +25 -33
  102. package/dist/layers/pointclouds.js.map +1 -1
  103. package/dist/layers/symbols.d.ts +1 -1
  104. package/dist/layers/symbols.js +68 -71
  105. package/dist/layers/symbols.js.map +1 -1
  106. package/dist/layers/vectors.d.ts +60 -0
  107. package/dist/layers/vectors.js +130 -0
  108. package/dist/layers/vectors.js.map +1 -0
  109. package/dist/map/basemap-layers.d.ts +26 -0
  110. package/dist/map/basemap-layers.js +61 -0
  111. package/dist/map/basemap-layers.js.map +1 -0
  112. package/dist/map/canvas.d.ts +17 -0
  113. package/dist/map/canvas.js +56 -0
  114. package/dist/map/canvas.js.map +1 -0
  115. package/dist/map/checks.d.ts +11 -0
  116. package/dist/map/checks.js +39 -0
  117. package/dist/map/checks.js.map +1 -0
  118. package/dist/map/credits.d.ts +17 -0
  119. package/dist/map/credits.js +34 -0
  120. package/dist/map/credits.js.map +1 -0
  121. package/dist/map/engine-settings.d.ts +15 -0
  122. package/dist/map/engine-settings.js +45 -0
  123. package/dist/map/engine-settings.js.map +1 -0
  124. package/dist/map/engines.d.ts +41 -0
  125. package/dist/map/engines.js +77 -0
  126. package/dist/map/engines.js.map +1 -0
  127. package/dist/map/events.d.ts +14 -0
  128. package/dist/map/events.js +46 -0
  129. package/dist/map/events.js.map +1 -0
  130. package/dist/map/frame-loop.d.ts +64 -0
  131. package/dist/map/frame-loop.js +145 -0
  132. package/dist/map/frame-loop.js.map +1 -0
  133. package/dist/map/hover-pick.d.ts +30 -0
  134. package/dist/map/hover-pick.js +56 -0
  135. package/dist/map/hover-pick.js.map +1 -0
  136. package/dist/map/layer-spec.d.ts +42 -0
  137. package/dist/map/layer-spec.js +34 -0
  138. package/dist/map/layer-spec.js.map +1 -0
  139. package/dist/map/layer-stack.d.ts +36 -0
  140. package/dist/map/layer-stack.js +101 -0
  141. package/dist/map/layer-stack.js.map +1 -0
  142. package/dist/map/overlay-host.d.ts +36 -0
  143. package/dist/map/overlay-host.js +101 -0
  144. package/dist/map/overlay-host.js.map +1 -0
  145. package/dist/map/panorama-host.d.ts +5 -0
  146. package/dist/map/panorama-host.js +32 -0
  147. package/dist/map/panorama-host.js.map +1 -0
  148. package/dist/map/raster-source.d.ts +11 -0
  149. package/dist/map/raster-source.js +26 -0
  150. package/dist/map/raster-source.js.map +1 -0
  151. package/dist/map/symbol-atlases.d.ts +26 -0
  152. package/dist/map/symbol-atlases.js +59 -0
  153. package/dist/map/symbol-atlases.js.map +1 -0
  154. package/dist/map/viewshed.d.ts +5 -0
  155. package/dist/map/viewshed.js +28 -0
  156. package/dist/map/viewshed.js.map +1 -0
  157. package/dist/map/workers.d.ts +46 -0
  158. package/dist/map/workers.js +73 -0
  159. package/dist/map/workers.js.map +1 -0
  160. package/dist/map.d.ts +54 -126
  161. package/dist/map.js +227 -698
  162. package/dist/map.js.map +1 -1
  163. package/dist/react/Control.d.ts +11 -0
  164. package/dist/react/Control.js +18 -0
  165. package/dist/react/Control.js.map +1 -0
  166. package/dist/react/CustomLayer.d.ts +11 -0
  167. package/dist/react/CustomLayer.js +30 -0
  168. package/dist/react/CustomLayer.js.map +1 -0
  169. package/dist/react/IsardMap.d.ts +43 -0
  170. package/dist/react/IsardMap.js +147 -0
  171. package/dist/react/IsardMap.js.map +1 -0
  172. package/dist/react/Layer.d.ts +42 -0
  173. package/dist/react/Layer.js +74 -0
  174. package/dist/react/Layer.js.map +1 -0
  175. package/dist/react/Marker.d.ts +24 -0
  176. package/dist/react/Marker.js +53 -0
  177. package/dist/react/Marker.js.map +1 -0
  178. package/dist/react/Panel.d.ts +11 -0
  179. package/dist/react/Panel.js +37 -0
  180. package/dist/react/Panel.js.map +1 -0
  181. package/dist/react/Popup.d.ts +18 -0
  182. package/dist/react/Popup.js +60 -0
  183. package/dist/react/Popup.js.map +1 -0
  184. package/dist/react/Swipe.d.ts +16 -0
  185. package/dist/react/Swipe.js +52 -0
  186. package/dist/react/Swipe.js.map +1 -0
  187. package/dist/react/VectorGeometry.d.ts +35 -0
  188. package/dist/react/VectorGeometry.js +82 -0
  189. package/dist/react/VectorGeometry.js.map +1 -0
  190. package/dist/react/Viewshed.d.ts +5 -0
  191. package/dist/react/Viewshed.js +28 -0
  192. package/dist/react/Viewshed.js.map +1 -0
  193. package/dist/react/context.d.ts +33 -0
  194. package/dist/react/context.js +20 -0
  195. package/dist/react/context.js.map +1 -0
  196. package/dist/react/index.d.ts +16 -108
  197. package/dist/react/index.js +11 -397
  198. package/dist/react/index.js.map +1 -1
  199. package/dist/settings.d.ts +5 -9
  200. package/dist/settings.js +17 -15
  201. package/dist/settings.js.map +1 -1
  202. package/dist/types.d.ts +27 -4
  203. package/dist/types.js.map +1 -1
  204. package/dist/ui/controls.js +6 -4
  205. package/dist/ui/controls.js.map +1 -1
  206. package/dist/ui/interaction.d.ts +2 -2
  207. package/dist/ui/interaction.js +8 -7
  208. package/dist/ui/interaction.js.map +1 -1
  209. package/dist/ui/minimap.d.ts +25 -0
  210. package/dist/ui/minimap.js +90 -0
  211. package/dist/ui/minimap.js.map +1 -0
  212. package/dist/ui/overlay.js +18 -20
  213. package/dist/ui/overlay.js.map +1 -1
  214. package/dist/ui/scale.d.ts +19 -0
  215. package/dist/ui/scale.js +44 -0
  216. package/dist/ui/scale.js.map +1 -0
  217. package/dist/ui/search.d.ts +25 -0
  218. package/dist/ui/search.js +119 -0
  219. package/dist/ui/search.js.map +1 -0
  220. package/dist/ui/style.d.ts +1 -1
  221. package/dist/ui/style.js +19 -2
  222. package/dist/ui/style.js.map +1 -1
  223. package/dist/util/animation.d.ts +3 -3
  224. package/dist/util/animation.js +6 -6
  225. package/dist/util/animation.js.map +1 -1
  226. package/dist/util/color.d.ts +1 -1
  227. package/dist/util/color.js +14 -16
  228. package/dist/util/color.js.map +1 -1
  229. package/dist/util/geo.d.ts +6 -6
  230. package/dist/util/geo.js +12 -12
  231. package/dist/util/geo.js.map +1 -1
  232. package/dist/util/guards.d.ts +7 -0
  233. package/dist/util/guards.js +8 -0
  234. package/dist/util/guards.js.map +1 -0
  235. package/dist/util/lru.js.map +1 -1
  236. package/dist/util/sun.d.ts +11 -0
  237. package/dist/util/sun.js +26 -0
  238. package/dist/util/sun.js.map +1 -0
  239. package/dist/wasm/isard.d.ts +250 -7
  240. package/dist/wasm/isard.js +375 -8
  241. package/dist/wasm/isard_core.d.ts +226 -7
  242. package/dist/wasm/isard_core.js +351 -8
  243. package/dist/wasm/isard_tess.d.ts +109 -0
  244. package/dist/wasm/isard_tess.js +398 -0
  245. package/dist/workers/basemap/geometry.d.ts +72 -0
  246. package/dist/workers/basemap/labels.d.ts +8 -0
  247. package/dist/workers/basemap/raster.d.ts +10 -0
  248. package/dist/workers/basemap/tiles.d.ts +65 -0
  249. package/dist/workers/basemap/trees.d.ts +19 -0
  250. package/dist/workers/basemap.worker.d.ts +126 -22
  251. package/dist/workers/basemap.worker.js +76 -544
  252. package/dist/workers/basemap.worker.js.map +1 -1
  253. package/package.json +5 -4
  254. package/vite.js +10 -2
@@ -0,0 +1,101 @@
1
+ /**
2
+ * The drawing order of a map's layers, kept beside the engine's: the layers waiting for the engine with 3D Tiles are
3
+ * in the order but not in the engine yet, and the order recreates the layers in a new engine after a context loss.
4
+ */
5
+ import { report } from "./checks.js";
6
+ /** A map's layers in drawing order, bottom first, and those kept on top */
7
+ export class LayerStack {
8
+ /** Layers in drawing order (bottom first), to recreate them after a context loss */
9
+ layers = [];
10
+ /** Layers new layers go under */
11
+ onTop = new Set();
12
+ engine;
13
+ /** `engine`: the map's engine of the moment */
14
+ constructor(engine) {
15
+ this.engine = engine;
16
+ }
17
+ has(layer) {
18
+ return this.layers.includes(layer);
19
+ }
20
+ /** Puts a new layer on top, under the layers kept on top (the basemap's labels) */
21
+ add(layer) {
22
+ this.layers.push(layer);
23
+ const top = this.layers.find((l) => this.onTop.has(l) && l !== layer);
24
+ if (top)
25
+ this.move(layer, top);
26
+ }
27
+ /** Forgets a removed layer */
28
+ forget(layer) {
29
+ this.unlist(layer);
30
+ this.onTop.delete(layer);
31
+ }
32
+ /** Moves a layer under `before`, or on top of all */
33
+ move(layer, before) {
34
+ this.unlist(layer);
35
+ const index = before ? this.layers.indexOf(before) : -1;
36
+ const at = index < 0 ? this.layers.length : index;
37
+ this.layers.splice(at, 0, layer);
38
+ if (layer.id >= 0)
39
+ this.engine().moveLayer(layer.id, this.engineIndex(at));
40
+ }
41
+ /** A layer made again in the engine under a new id: `old` removed, the new one moved to the layer's place */
42
+ replace(layer, old) {
43
+ const engine = this.engine();
44
+ engine.removeLayer(old);
45
+ const index = this.layers.indexOf(layer);
46
+ if (index >= 0)
47
+ engine.moveLayer(layer.id, this.engineIndex(index));
48
+ }
49
+ /** Moves a layer under all the others */
50
+ toBottom(layer) {
51
+ this.engine().moveLayer(layer.id, 0);
52
+ this.unlist(layer);
53
+ this.layers.unshift(layer);
54
+ }
55
+ /** Creates the layers in a new engine, in order, but those still `waiting` (for the engine with 3D Tiles); a layer
56
+ * that fails is reported and left out */
57
+ reattach(engine, waiting) {
58
+ // No layer refers to an id of the old engine while the others are created
59
+ this.layers.forEach((layer) => {
60
+ layer.forgetEngine();
61
+ });
62
+ this.layers.forEach((layer) => {
63
+ if (waiting(layer))
64
+ return;
65
+ try {
66
+ layer.attach(engine);
67
+ }
68
+ catch (error) {
69
+ report(error);
70
+ }
71
+ });
72
+ // Links between layers, once every layer has its new id (buildings colored by a network above them)
73
+ this.layers.forEach((layer) => {
74
+ if (layer.id < 0)
75
+ return;
76
+ try {
77
+ layer.relink(engine);
78
+ }
79
+ catch (error) {
80
+ report(error);
81
+ }
82
+ });
83
+ }
84
+ /** Frees what the layers hold beside the engine (custom layers' WebGL objects, models' data) */
85
+ dispose() {
86
+ this.layers.forEach((layer) => {
87
+ layer.dispose();
88
+ });
89
+ }
90
+ /** Takes a layer out of the drawing order (to put it back elsewhere, or for good) */
91
+ unlist(layer) {
92
+ const index = this.layers.indexOf(layer);
93
+ if (index >= 0)
94
+ this.layers.splice(index, 1);
95
+ }
96
+ /** Index in the engine of the layer at `index`: the layers waiting for the engine with 3D Tiles are not in it yet */
97
+ engineIndex(index) {
98
+ return this.layers.slice(0, index).filter((layer) => layer.id >= 0).length;
99
+ }
100
+ }
101
+ //# sourceMappingURL=layer-stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer-stack.js","sourceRoot":"","sources":["../../src/map/layer-stack.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The drawing order of a map's layers, kept beside the engine's: the layers waiting for the engine with 3D Tiles are\n * in the order but not in the engine yet, and the order recreates the layers in a new engine after a context loss.\n */\n\nimport type { Layer } from '../layers/layers.ts';\nimport type { Engine } from '../wasm/isard.js';\nimport { report } from './checks.ts';\n\n/** A map's layers in drawing order, bottom first, and those kept on top */\nexport class LayerStack {\n /** Layers in drawing order (bottom first), to recreate them after a context loss */\n readonly layers: Layer[] = [];\n /** Layers new layers go under */\n readonly onTop = new Set<Layer>();\n private readonly engine: () => Engine;\n\n /** `engine`: the map's engine of the moment */\n constructor(engine: () => Engine) {\n this.engine = engine;\n }\n\n has(layer: Layer): boolean {\n return this.layers.includes(layer);\n }\n\n /** Puts a new layer on top, under the layers kept on top (the basemap's labels) */\n add(layer: Layer): void {\n this.layers.push(layer);\n\n const top = this.layers.find((l) => this.onTop.has(l) && l !== layer);\n\n if (top) this.move(layer, top);\n }\n\n /** Forgets a removed layer */\n forget(layer: Layer): void {\n this.unlist(layer);\n this.onTop.delete(layer);\n }\n\n /** Moves a layer under `before`, or on top of all */\n move(layer: Layer, before: Layer | undefined): void {\n this.unlist(layer);\n\n const index = before ? this.layers.indexOf(before) : -1;\n const at = index < 0 ? this.layers.length : index;\n\n this.layers.splice(at, 0, layer);\n if (layer.id >= 0) this.engine().moveLayer(layer.id, this.engineIndex(at));\n }\n\n /** A layer made again in the engine under a new id: `old` removed, the new one moved to the layer's place */\n replace(layer: Layer, old: number): void {\n const engine = this.engine();\n\n engine.removeLayer(old);\n\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) engine.moveLayer(layer.id, this.engineIndex(index));\n }\n\n /** Moves a layer under all the others */\n toBottom(layer: Layer): void {\n this.engine().moveLayer(layer.id, 0);\n this.unlist(layer);\n this.layers.unshift(layer);\n }\n\n /** Creates the layers in a new engine, in order, but those still `waiting` (for the engine with 3D Tiles); a layer\n * that fails is reported and left out */\n reattach(engine: Engine, waiting: (layer: Layer) => boolean): void {\n // No layer refers to an id of the old engine while the others are created\n this.layers.forEach((layer) => {\n layer.forgetEngine();\n });\n this.layers.forEach((layer) => {\n if (waiting(layer)) return;\n try {\n layer.attach(engine);\n } catch (error) {\n report(error);\n }\n });\n // Links between layers, once every layer has its new id (buildings colored by a network above them)\n this.layers.forEach((layer) => {\n if (layer.id < 0) return;\n try {\n layer.relink(engine);\n } catch (error) {\n report(error);\n }\n });\n }\n\n /** Frees what the layers hold beside the engine (custom layers' WebGL objects, models' data) */\n dispose(): void {\n this.layers.forEach((layer) => {\n layer.dispose();\n });\n }\n\n /** Takes a layer out of the drawing order (to put it back elsewhere, or for good) */\n private unlist(layer: Layer): void {\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) this.layers.splice(index, 1);\n }\n\n /** Index in the engine of the layer at `index`: the layers waiting for the engine with 3D Tiles are not in it yet */\n private engineIndex(index: number): number {\n return this.layers.slice(0, index).filter((layer) => layer.id >= 0).length;\n }\n}\n"]}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * What the map shows over its canvas, in its container: the markers and popups (placed after every frame) and the
3
+ * controls in the four corners.
4
+ */
5
+ import type { GeoMap } from '../map.ts';
6
+ import type { Point } from '../types.ts';
7
+ import type { Control, ControlPosition } from '../ui/controls.ts';
8
+ import type { Positioned } from '../ui/overlay.ts';
9
+ /** The map's container: its canvas, the element of the markers and popups over it, the corners of the controls */
10
+ export declare class OverlayHost {
11
+ /** Canvas size in CSS pixels, kept on resize so placing overlays never reads the layout */
12
+ size: Point;
13
+ private readonly container;
14
+ private readonly canvas;
15
+ /** The map the controls are added to */
16
+ private readonly map;
17
+ /** Markers and popups, over the canvas */
18
+ private readonly overlay;
19
+ private readonly corners;
20
+ private readonly controls;
21
+ private readonly positioned;
22
+ /** Puts the canvas, the overlay and the corners in `container` */
23
+ constructor(container: HTMLElement, canvas: HTMLCanvasElement, map: GeoMap);
24
+ /** Adds a control in a corner; controls stack from the corner inward */
25
+ addControl(control: Control, position: ControlPosition): void;
26
+ removeControl(control: Control): void;
27
+ /** Shows a marker or popup, placed after every frame from now on */
28
+ attach(item: Positioned, element: HTMLElement): void;
29
+ detach(item: Positioned, element: HTMLElement): void;
30
+ /** Places one overlay now (it moved) */
31
+ position(item: Positioned): void;
32
+ /** Places every overlay for the frame just drawn (camera, relief altitudes): all in one pass, transforms only */
33
+ positionAll(): void;
34
+ /** Removes the controls, then the canvas, the overlay and the corners from the container */
35
+ destroy(): void;
36
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * What the map shows over its canvas, in its container: the markers and popups (placed after every frame) and the
3
+ * controls in the four corners.
4
+ */
5
+ import { injectStyle } from "../ui/style.js";
6
+ const CORNERS = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
7
+ /** The map's container: its canvas, the element of the markers and popups over it, the corners of the controls */
8
+ export class OverlayHost {
9
+ /** Canvas size in CSS pixels, kept on resize so placing overlays never reads the layout */
10
+ size = [0, 0];
11
+ container;
12
+ canvas;
13
+ /** The map the controls are added to */
14
+ map;
15
+ /** Markers and popups, over the canvas */
16
+ overlay;
17
+ corners;
18
+ controls = new Map();
19
+ positioned = new Set();
20
+ /** Puts the canvas, the overlay and the corners in `container` */
21
+ constructor(container, canvas, map) {
22
+ this.container = container;
23
+ this.canvas = canvas;
24
+ this.map = map;
25
+ // Overlays and controls are positioned against the container
26
+ injectStyle(container.ownerDocument);
27
+ if (getComputedStyle(container).position === 'static')
28
+ container.style.position = 'relative';
29
+ container.classList.add('isard-map');
30
+ this.overlay = document.createElement('div');
31
+ this.overlay.className = 'isard-overlay';
32
+ const corner = (position) => {
33
+ const element = document.createElement('div');
34
+ element.className = `isard-ctrl-${position}`;
35
+ return element;
36
+ };
37
+ this.corners = {
38
+ 'top-left': corner('top-left'),
39
+ 'top-right': corner('top-right'),
40
+ 'bottom-left': corner('bottom-left'),
41
+ 'bottom-right': corner('bottom-right'),
42
+ };
43
+ container.append(canvas, this.overlay, ...CORNERS.map((position) => this.corners[position]));
44
+ }
45
+ /** Adds a control in a corner; controls stack from the corner inward */
46
+ addControl(control, position) {
47
+ if (this.controls.has(control))
48
+ return;
49
+ const element = control.onAdd(this.map);
50
+ element.classList.add('isard-ctrl');
51
+ // In the bottom corners the first control added stays lowest, as in MapLibre
52
+ if (position.startsWith('bottom'))
53
+ this.corners[position].prepend(element);
54
+ else
55
+ this.corners[position].append(element);
56
+ this.controls.set(control, element);
57
+ }
58
+ removeControl(control) {
59
+ const element = this.controls.get(control);
60
+ if (!element)
61
+ return;
62
+ this.controls.delete(control);
63
+ control.onRemove(this.map);
64
+ element.remove();
65
+ }
66
+ /** Shows a marker or popup, placed after every frame from now on */
67
+ attach(item, element) {
68
+ this.overlay.append(element);
69
+ this.positioned.add(item);
70
+ item.position(this.size);
71
+ }
72
+ detach(item, element) {
73
+ this.positioned.delete(item);
74
+ element.remove();
75
+ }
76
+ /** Places one overlay now (it moved) */
77
+ position(item) {
78
+ if (this.positioned.has(item))
79
+ item.position(this.size);
80
+ }
81
+ /** Places every overlay for the frame just drawn (camera, relief altitudes): all in one pass, transforms only */
82
+ positionAll() {
83
+ this.positioned.forEach((item) => {
84
+ item.position(this.size);
85
+ });
86
+ }
87
+ /** Removes the controls, then the canvas, the overlay and the corners from the container */
88
+ destroy() {
89
+ [...this.controls.keys()].forEach((control) => {
90
+ this.removeControl(control);
91
+ });
92
+ this.positioned.clear();
93
+ this.canvas.remove();
94
+ this.overlay.remove();
95
+ CORNERS.forEach((position) => {
96
+ this.corners[position].remove();
97
+ });
98
+ this.container.classList.remove('isard-map');
99
+ }
100
+ }
101
+ //# sourceMappingURL=overlay-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-host.js","sourceRoot":"","sources":["../../src/map/overlay-host.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What the map shows over its canvas, in its container: the markers and popups (placed after every frame) and the\n * controls in the four corners.\n */\n\nimport type { GeoMap } from '../map.ts';\nimport type { Point } from '../types.ts';\nimport type { Control, ControlPosition } from '../ui/controls.ts';\nimport type { Positioned } from '../ui/overlay.ts';\nimport { injectStyle } from '../ui/style.ts';\n\nconst CORNERS: readonly ControlPosition[] = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];\n\n/** The map's container: its canvas, the element of the markers and popups over it, the corners of the controls */\nexport class OverlayHost {\n /** Canvas size in CSS pixels, kept on resize so placing overlays never reads the layout */\n size: Point = [0, 0];\n private readonly container: HTMLElement;\n private readonly canvas: HTMLCanvasElement;\n /** The map the controls are added to */\n private readonly map: GeoMap;\n /** Markers and popups, over the canvas */\n private readonly overlay: HTMLDivElement;\n private readonly corners: Record<ControlPosition, HTMLDivElement>;\n private readonly controls = new Map<Control, HTMLElement>();\n private readonly positioned = new Set<Positioned>();\n\n /** Puts the canvas, the overlay and the corners in `container` */\n constructor(container: HTMLElement, canvas: HTMLCanvasElement, map: GeoMap) {\n this.container = container;\n this.canvas = canvas;\n this.map = map;\n // Overlays and controls are positioned against the container\n injectStyle(container.ownerDocument);\n if (getComputedStyle(container).position === 'static') container.style.position = 'relative';\n container.classList.add('isard-map');\n this.overlay = document.createElement('div');\n this.overlay.className = 'isard-overlay';\n\n const corner = (position: ControlPosition) => {\n const element = document.createElement('div');\n\n element.className = `isard-ctrl-${position}`;\n\n return element;\n };\n\n this.corners = {\n 'top-left': corner('top-left'),\n 'top-right': corner('top-right'),\n 'bottom-left': corner('bottom-left'),\n 'bottom-right': corner('bottom-right'),\n };\n container.append(canvas, this.overlay, ...CORNERS.map((position) => this.corners[position]));\n }\n\n /** Adds a control in a corner; controls stack from the corner inward */\n addControl(control: Control, position: ControlPosition): void {\n if (this.controls.has(control)) return;\n\n const element = control.onAdd(this.map);\n\n element.classList.add('isard-ctrl');\n // In the bottom corners the first control added stays lowest, as in MapLibre\n if (position.startsWith('bottom')) this.corners[position].prepend(element);\n else this.corners[position].append(element);\n this.controls.set(control, element);\n }\n\n removeControl(control: Control): void {\n const element = this.controls.get(control);\n\n if (!element) return;\n this.controls.delete(control);\n control.onRemove(this.map);\n element.remove();\n }\n\n /** Shows a marker or popup, placed after every frame from now on */\n attach(item: Positioned, element: HTMLElement): void {\n this.overlay.append(element);\n this.positioned.add(item);\n item.position(this.size);\n }\n\n detach(item: Positioned, element: HTMLElement): void {\n this.positioned.delete(item);\n element.remove();\n }\n\n /** Places one overlay now (it moved) */\n position(item: Positioned): void {\n if (this.positioned.has(item)) item.position(this.size);\n }\n\n /** Places every overlay for the frame just drawn (camera, relief altitudes): all in one pass, transforms only */\n positionAll(): void {\n this.positioned.forEach((item) => {\n item.position(this.size);\n });\n }\n\n /** Removes the controls, then the canvas, the overlay and the corners from the container */\n destroy(): void {\n [...this.controls.keys()].forEach((control) => {\n this.removeControl(control);\n });\n this.positioned.clear();\n this.canvas.remove();\n this.overlay.remove();\n CORNERS.forEach((position) => {\n this.corners[position].remove();\n });\n this.container.classList.remove('isard-map');\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ /** What the street-level panoramas need of the map: its engine, its street-level eye, its clicks, keys and wheel. */
2
+ import type { PanoramaHost } from '../layers/panoramas.ts';
3
+ import type { GeoMap } from '../map.ts';
4
+ /** The panoramas' host on a map; `geoidHeight` from the class of the map's engine */
5
+ export declare const panoramaHost: (map: GeoMap, geoidHeight: (lon: number, lat: number) => number) => PanoramaHost;
@@ -0,0 +1,32 @@
1
+ /** What the street-level panoramas need of the map: its engine, its street-level eye, its clicks, keys and wheel. */
2
+ /** The panoramas' host on a map; `geoidHeight` from the class of the map's engine */
3
+ export const panoramaHost = (map, geoidHeight) => ({
4
+ setPanorama: (...args) => {
5
+ map.engine.setPanorama(...args);
6
+ map.requestRender();
7
+ },
8
+ setPanoramaImage: (index, image) => map.engine.setPanoramaImage(index, image),
9
+ clearPanorama: () => map.engine.clearPanorama(),
10
+ geoidHeight,
11
+ firstPerson: () => map.firstPerson,
12
+ setFirstPerson: (view) => map.setFirstPerson(view),
13
+ elevationAt: (lonLat) => map.elevationAt(lonLat),
14
+ listen: (click, key, wheel) => {
15
+ const off = map.on('click', ({ lonLat }) => click(lonLat));
16
+ const container = map.getContainer();
17
+ // Before the map's own wheel (its zoom, the eye's field of view)
18
+ const onWheel = (e) => {
19
+ e.preventDefault();
20
+ e.stopImmediatePropagation();
21
+ wheel(e);
22
+ };
23
+ container.addEventListener('keydown', key);
24
+ container.addEventListener('wheel', onWheel, { capture: true, passive: false });
25
+ return () => {
26
+ off();
27
+ container.removeEventListener('keydown', key);
28
+ container.removeEventListener('wheel', onWheel, { capture: true });
29
+ };
30
+ },
31
+ });
32
+ //# sourceMappingURL=panorama-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panorama-host.js","sourceRoot":"","sources":["../../src/map/panorama-host.ts"],"names":[],"mappings":"AAAA,qHAAqH;AAKrH,qFAAqF;AACrF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,WAAiD,EAAgB,EAAE,CAAC,CAAC;IAC7G,WAAW,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE;QACvB,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;QAChC,GAAG,CAAC,aAAa,EAAE,CAAC;IACtB,CAAC;IACD,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC;IAC7E,aAAa,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE;IAC/C,WAAW;IACX,WAAW,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW;IAClC,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC;IAChD,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3D,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QACrC,iEAAiE;QACjE,MAAM,OAAO,GAAG,CAAC,CAAa,EAAE,EAAE;YAChC,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,CAAC,CAAC,wBAAwB,EAAE,CAAC;YAC7B,KAAK,CAAC,CAAC,CAAC,CAAC;QACX,CAAC,CAAC;QAEF,SAAS,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC3C,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAEhF,OAAO,GAAG,EAAE;YACV,GAAG,EAAE,CAAC;YACN,SAAS,CAAC,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC9C,SAAS,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["/** What the street-level panoramas need of the map: its engine, its street-level eye, its clicks, keys and wheel. */\n\nimport type { PanoramaHost } from '../layers/panoramas.ts';\nimport type { GeoMap } from '../map.ts';\n\n/** The panoramas' host on a map; `geoidHeight` from the class of the map's engine */\nexport const panoramaHost = (map: GeoMap, geoidHeight: (lon: number, lat: number) => number): PanoramaHost => ({\n setPanorama: (...args) => {\n map.engine.setPanorama(...args);\n map.requestRender();\n },\n setPanoramaImage: (index, image) => map.engine.setPanoramaImage(index, image),\n clearPanorama: () => map.engine.clearPanorama(),\n geoidHeight,\n firstPerson: () => map.firstPerson,\n setFirstPerson: (view) => map.setFirstPerson(view),\n elevationAt: (lonLat) => map.elevationAt(lonLat),\n listen: (click, key, wheel) => {\n const off = map.on('click', ({ lonLat }) => click(lonLat));\n const container = map.getContainer();\n // Before the map's own wheel (its zoom, the eye's field of view)\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n e.stopImmediatePropagation();\n wheel(e);\n };\n\n container.addEventListener('keydown', key);\n container.addEventListener('wheel', onWheel, { capture: true, passive: false });\n\n return () => {\n off();\n container.removeEventListener('keydown', key);\n container.removeEventListener('wheel', onWheel, { capture: true });\n };\n },\n});\n"]}
@@ -0,0 +1,11 @@
1
+ /** Where a raster layer's tiles come from: a PMTiles archive, Web Mercator tiles, or tiles reprojected from a grid. */
2
+ import { type RemoteReprojection } from '../basemap/grid.ts';
3
+ import type { RasterOptions } from '../types.ts';
4
+ /** The loader of a raster layer's tiles (none: the engine fetches them) and its zooms, in Web Mercator levels */
5
+ export interface RasterSource {
6
+ loader: RasterOptions['loader'];
7
+ minZoom: number;
8
+ maxZoom: number;
9
+ }
10
+ /** The loader of a raster layer's tiles and its zooms; `remote` reprojects in the workers */
11
+ export declare const rasterSource: (options: RasterOptions, remote: RemoteReprojection) => RasterSource;
@@ -0,0 +1,26 @@
1
+ /** Where a raster layer's tiles come from: a PMTiles archive, Web Mercator tiles, or tiles reprojected from a grid. */
2
+ import { equirectangularGrid, gridLoader, gridZooms, resolveGrid } from "../basemap/grid.js";
3
+ import { pmtilesRasterLoader } from "../basemap/pmtileslayer.js";
4
+ /** The loader of a raster layer's tiles and its zooms; `remote` reprojects in the workers */
5
+ export const rasterSource = (options, remote) => {
6
+ const { url, grid = 'mercator', size } = options;
7
+ const { minZoom = 0, maxZoom = 19 } = options;
8
+ // A PMTiles archive (`pmtiles://…`): its tiles read by range requests
9
+ const loader = options.loader ?? pmtilesRasterLoader(url, size ?? 256);
10
+ if (grid === 'mercator' || loader)
11
+ return { loader, minZoom, maxZoom };
12
+ if (grid === 'equirectangular') {
13
+ // `minZoom` and `maxZoom` are levels of the source: its level n has the pixel size of Mercator level n + 1 at the
14
+ // equator
15
+ const reprojected = gridLoader(url, resolveGrid(equirectangularGrid(minZoom, maxZoom)), size ?? 256, remote);
16
+ return { loader: reprojected, minZoom: minZoom + 1, maxZoom: maxZoom + 1 };
17
+ }
18
+ const resolved = resolveGrid(grid);
19
+ const zooms = gridZooms(resolved);
20
+ return {
21
+ loader: gridLoader(url, resolved, size ?? 256, remote),
22
+ minZoom: options.minZoom ?? zooms.minZoom,
23
+ maxZoom: options.maxZoom ?? zooms.maxZoom,
24
+ };
25
+ };
26
+ //# sourceMappingURL=raster-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raster-source.js","sourceRoot":"","sources":["../../src/map/raster-source.ts"],"names":[],"mappings":"AAAA,uHAAuH;AAEvH,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,SAAS,EAA2B,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtH,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAUjE,6FAA6F;AAC7F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAsB,EAAE,MAA0B,EAAgB,EAAE;IAC/F,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,UAAU,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACjD,MAAM,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAC9C,sEAAsE;IACtE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,mBAAmB,CAAC,GAAG,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;IAEvE,IAAI,IAAI,KAAK,UAAU,IAAI,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IACvE,IAAI,IAAI,KAAK,iBAAiB,EAAE,CAAC;QAC/B,kHAAkH;QAClH,UAAU;QACV,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,IAAI,IAAI,GAAG,EAAE,MAAM,CAAC,CAAC;QAE7G,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,EAAE,CAAC;IAC7E,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAElC,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,IAAI,GAAG,EAAE,MAAM,CAAC;QACtD,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO;QACzC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO;KAC1C,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/** Where a raster layer's tiles come from: a PMTiles archive, Web Mercator tiles, or tiles reprojected from a grid. */\n\nimport { equirectangularGrid, gridLoader, gridZooms, type RemoteReprojection, resolveGrid } from '../basemap/grid.ts';\nimport { pmtilesRasterLoader } from '../basemap/pmtileslayer.ts';\nimport type { RasterOptions } from '../types.ts';\n\n/** The loader of a raster layer's tiles (none: the engine fetches them) and its zooms, in Web Mercator levels */\nexport interface RasterSource {\n loader: RasterOptions['loader'];\n minZoom: number;\n maxZoom: number;\n}\n\n/** The loader of a raster layer's tiles and its zooms; `remote` reprojects in the workers */\nexport const rasterSource = (options: RasterOptions, remote: RemoteReprojection): RasterSource => {\n const { url, grid = 'mercator', size } = options;\n const { minZoom = 0, maxZoom = 19 } = options;\n // A PMTiles archive (`pmtiles://…`): its tiles read by range requests\n const loader = options.loader ?? pmtilesRasterLoader(url, size ?? 256);\n\n if (grid === 'mercator' || loader) return { loader, minZoom, maxZoom };\n if (grid === 'equirectangular') {\n // `minZoom` and `maxZoom` are levels of the source: its level n has the pixel size of Mercator level n + 1 at the\n // equator\n const reprojected = gridLoader(url, resolveGrid(equirectangularGrid(minZoom, maxZoom)), size ?? 256, remote);\n\n return { loader: reprojected, minZoom: minZoom + 1, maxZoom: maxZoom + 1 };\n }\n\n const resolved = resolveGrid(grid);\n const zooms = gridZooms(resolved);\n\n return {\n loader: gridLoader(url, resolved, size ?? 256, remote),\n minZoom: options.minZoom ?? zooms.minZoom,\n maxZoom: options.maxZoom ?? zooms.maxZoom,\n };\n};\n"]}
@@ -0,0 +1,26 @@
1
+ /** The atlases of a map's symbol layers, the glyphs and the icons: created on first use, moved to each new engine. */
2
+ import { Glyphs } from '../layers/glyphs.ts';
3
+ import { Icons, type ImageOptions, type Pixels } from '../layers/icons.ts';
4
+ import type { Engine } from '../wasm/isard.js';
5
+ /** The glyphs and icons of a map */
6
+ export declare class SymbolAtlases {
7
+ #private;
8
+ private readonly canvas;
9
+ private readonly glyphsUrl;
10
+ private readonly engine;
11
+ /** `canvas`: the engine's; `glyphsUrl`: the map's option; `engine`: the map's engine of the moment */
12
+ constructor(canvas: HTMLCanvasElement, glyphsUrl: string | undefined, engine: () => Engine);
13
+ /** The glyphs of the symbol layers, loaded on first use */
14
+ get glyphs(): Glyphs;
15
+ /** The icons of the symbol layers: the application's images and the vector basemaps' sprites */
16
+ get icons(): Icons;
17
+ /** An image for the icons, from its pixels or from an image; one without pixels throws */
18
+ addImage(name: string, image: Pixels | (CanvasImageSource & {
19
+ width: number;
20
+ height: number;
21
+ }), options: ImageOptions): void;
22
+ hasImage(name: string): boolean;
23
+ removeImage(name: string): void;
24
+ /** Uploads the atlases made so far to a new engine (after a context loss, or the one left once the map is gone) */
25
+ attach(engine: Engine): void;
26
+ }
@@ -0,0 +1,59 @@
1
+ /** The atlases of a map's symbol layers, the glyphs and the icons: created on first use, moved to each new engine. */
2
+ import { Glyphs } from "../layers/glyphs.js";
3
+ import { Icons, readPixels } from "../layers/icons.js";
4
+ /** The largest texture the canvas's WebGL context takes, undefined if unknown: the atlases stay within it */
5
+ const maxTextureSize = (canvas) => {
6
+ const gl = canvas.getContext('webgl2');
7
+ const max = gl?.getParameter(gl.MAX_TEXTURE_SIZE);
8
+ return typeof max === 'number' ? max : undefined;
9
+ };
10
+ /** The glyphs and icons of a map */
11
+ export class SymbolAtlases {
12
+ canvas;
13
+ glyphsUrl;
14
+ engine;
15
+ #glyphs;
16
+ #icons;
17
+ /** `canvas`: the engine's; `glyphsUrl`: the map's option; `engine`: the map's engine of the moment */
18
+ constructor(canvas, glyphsUrl, engine) {
19
+ this.canvas = canvas;
20
+ this.glyphsUrl = glyphsUrl;
21
+ this.engine = engine;
22
+ }
23
+ /** The glyphs of the symbol layers, loaded on first use */
24
+ get glyphs() {
25
+ if (!this.#glyphs) {
26
+ // The engine's context: the atlas stays within its texture size limit
27
+ this.#glyphs = new Glyphs(this.glyphsUrl, maxTextureSize(this.canvas));
28
+ this.#glyphs.attach(this.engine());
29
+ }
30
+ return this.#glyphs;
31
+ }
32
+ /** The icons of the symbol layers: the application's images and the vector basemaps' sprites */
33
+ get icons() {
34
+ if (!this.#icons) {
35
+ this.#icons = new Icons(maxTextureSize(this.canvas));
36
+ this.#icons.attach(this.engine());
37
+ }
38
+ return this.#icons;
39
+ }
40
+ /** An image for the icons, from its pixels or from an image; one without pixels throws */
41
+ addImage(name, image, options) {
42
+ const pixels = 'data' in image ? image : readPixels(image);
43
+ if (!pixels)
44
+ throw new Error(`isard: the image ${name} has no pixels`);
45
+ this.icons.add(name, pixels, options);
46
+ }
47
+ hasImage(name) {
48
+ return this.#icons?.has(name) ?? false;
49
+ }
50
+ removeImage(name) {
51
+ this.#icons?.remove(name);
52
+ }
53
+ /** Uploads the atlases made so far to a new engine (after a context loss, or the one left once the map is gone) */
54
+ attach(engine) {
55
+ this.#glyphs?.attach(engine);
56
+ this.#icons?.attach(engine);
57
+ }
58
+ }
59
+ //# sourceMappingURL=symbol-atlases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol-atlases.js","sourceRoot":"","sources":["../../src/map/symbol-atlases.ts"],"names":[],"mappings":"AAAA,sHAAsH;AAEtH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAkC,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGvF,6GAA6G;AAC7G,MAAM,cAAc,GAAG,CAAC,MAAyB,EAAsB,EAAE;IACvE,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,EAAE,EAAE,YAAY,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC;IAElD,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACnD,CAAC,CAAC;AAEF,oCAAoC;AACpC,MAAM,OAAO,aAAa;IACP,MAAM,CAAoB;IAC1B,SAAS,CAAqB;IAC9B,MAAM,CAAe;IACtC,OAAO,CAAqB;IAC5B,MAAM,CAAoB;IAE1B,sGAAsG;IACtG,YAAY,MAAyB,EAAE,SAA6B,EAAE,MAAoB;QACxF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,2DAA2D;IAC3D,IAAI,MAAM;QACR,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,sEAAsE;YACtE,IAAI,CAAC,OAAO,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACvE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,gGAAgG;IAChG,IAAI,KAAK;QACP,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACrD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,0FAA0F;IAC1F,QAAQ,CACN,IAAY,EACZ,KAAuE,EACvE,OAAqB;QAErB,MAAM,MAAM,GAAG,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAE3D,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,gBAAgB,CAAC,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;IACzC,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,mHAAmH;IACnH,MAAM,CAAC,MAAc;QACnB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;CACF","sourcesContent":["/** The atlases of a map's symbol layers, the glyphs and the icons: created on first use, moved to each new engine. */\n\nimport { Glyphs } from '../layers/glyphs.ts';\nimport { Icons, type ImageOptions, type Pixels, readPixels } from '../layers/icons.ts';\nimport type { Engine } from '../wasm/isard.js';\n\n/** The largest texture the canvas's WebGL context takes, undefined if unknown: the atlases stay within it */\nconst maxTextureSize = (canvas: HTMLCanvasElement): number | undefined => {\n const gl = canvas.getContext('webgl2');\n const max = gl?.getParameter(gl.MAX_TEXTURE_SIZE);\n\n return typeof max === 'number' ? max : undefined;\n};\n\n/** The glyphs and icons of a map */\nexport class SymbolAtlases {\n private readonly canvas: HTMLCanvasElement;\n private readonly glyphsUrl: string | undefined;\n private readonly engine: () => Engine;\n #glyphs: Glyphs | undefined;\n #icons: Icons | undefined;\n\n /** `canvas`: the engine's; `glyphsUrl`: the map's option; `engine`: the map's engine of the moment */\n constructor(canvas: HTMLCanvasElement, glyphsUrl: string | undefined, engine: () => Engine) {\n this.canvas = canvas;\n this.glyphsUrl = glyphsUrl;\n this.engine = engine;\n }\n\n /** The glyphs of the symbol layers, loaded on first use */\n get glyphs(): Glyphs {\n if (!this.#glyphs) {\n // The engine's context: the atlas stays within its texture size limit\n this.#glyphs = new Glyphs(this.glyphsUrl, maxTextureSize(this.canvas));\n this.#glyphs.attach(this.engine());\n }\n\n return this.#glyphs;\n }\n\n /** The icons of the symbol layers: the application's images and the vector basemaps' sprites */\n get icons(): Icons {\n if (!this.#icons) {\n this.#icons = new Icons(maxTextureSize(this.canvas));\n this.#icons.attach(this.engine());\n }\n\n return this.#icons;\n }\n\n /** An image for the icons, from its pixels or from an image; one without pixels throws */\n addImage(\n name: string,\n image: Pixels | (CanvasImageSource & { width: number; height: number }),\n options: ImageOptions,\n ): void {\n const pixels = 'data' in image ? image : readPixels(image);\n\n if (!pixels) throw new Error(`isard: the image ${name} has no pixels`);\n this.icons.add(name, pixels, options);\n }\n\n hasImage(name: string): boolean {\n return this.#icons?.has(name) ?? false;\n }\n\n removeImage(name: string): void {\n this.#icons?.remove(name);\n }\n\n /** Uploads the atlases made so far to a new engine (after a context loss, or the one left once the map is gone) */\n attach(engine: Engine): void {\n this.#glyphs?.attach(engine);\n this.#icons?.attach(engine);\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ /** The viewshed's observers given to the engine, in the arrays it reads. */
2
+ import type { ViewshedOptions } from '../types.ts';
3
+ import type { Engine } from '../wasm/isard.js';
4
+ /** Sets the viewshed of the engine, or clears it without observers; true if one is set (a frame to draw) */
5
+ export declare const applyViewshed: (engine: Engine, options: ViewshedOptions | readonly ViewshedOptions[] | undefined) => boolean;
@@ -0,0 +1,28 @@
1
+ /** The viewshed's observers given to the engine, in the arrays it reads. */
2
+ import { rgb } from "../settings.js";
3
+ /** The observers of a viewshed option: none, one, or several */
4
+ const observersOf = (options) => {
5
+ if (!options)
6
+ return [];
7
+ return 'position' in options ? [options] : options;
8
+ };
9
+ /** Sets the viewshed of the engine, or clears it without observers; true if one is set (a frame to draw) */
10
+ export const applyViewshed = (engine, options) => {
11
+ const observers = observersOf(options);
12
+ const [first] = observers;
13
+ if (!first) {
14
+ engine.clearViewshed();
15
+ return false;
16
+ }
17
+ engine.setViewshed(new Float64Array(observers.flatMap((o) => [
18
+ o.position[0],
19
+ o.position[1],
20
+ o.height ?? 1.7,
21
+ o.range ?? 1000,
22
+ ...(o.direction === undefined
23
+ ? [Number.NaN, 0, 0, 0]
24
+ : [o.direction, o.tilt ?? 0, o.fov ?? 60, o.verticalFov ?? 40]),
25
+ ])), new Float32Array(rgb(first.visibleColor ?? '#2f9e44')), new Float32Array(rgb(first.hiddenColor ?? '#e03131')), first.opacity ?? 0.7, new Float32Array(first.coneColor ? rgb(first.coneColor) : []));
26
+ return true;
27
+ };
28
+ //# sourceMappingURL=viewshed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewshed.js","sourceRoot":"","sources":["../../src/map/viewshed.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAE5E,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAIrC,gEAAgE;AAChE,MAAM,WAAW,GAAG,CAAC,OAAiE,EAA8B,EAAE;IACpH,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,OAAO,UAAU,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACrD,CAAC,CAAC;AAEF,4GAA4G;AAC5G,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAAc,EACd,OAAiE,EACxD,EAAE;IACX,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAE1B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,CAAC,aAAa,EAAE,CAAC;QAEvB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,CAAC,WAAW,CAChB,IAAI,YAAY,CACd,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACvB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,MAAM,IAAI,GAAG;QACf,CAAC,CAAC,KAAK,IAAI,IAAI;QACf,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS;YAC3B,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;KAClE,CAAC,CACH,EACD,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,SAAS,CAAC,CAAC,EACtD,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC,EACrD,KAAK,CAAC,OAAO,IAAI,GAAG,EACpB,IAAI,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAC9D,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC,CAAC","sourcesContent":["/** The viewshed's observers given to the engine, in the arrays it reads. */\n\nimport { rgb } from '../settings.ts';\nimport type { ViewshedOptions } from '../types.ts';\nimport type { Engine } from '../wasm/isard.js';\n\n/** The observers of a viewshed option: none, one, or several */\nconst observersOf = (options: ViewshedOptions | readonly ViewshedOptions[] | undefined): readonly ViewshedOptions[] => {\n if (!options) return [];\n\n return 'position' in options ? [options] : options;\n};\n\n/** Sets the viewshed of the engine, or clears it without observers; true if one is set (a frame to draw) */\nexport const applyViewshed = (\n engine: Engine,\n options: ViewshedOptions | readonly ViewshedOptions[] | undefined,\n): boolean => {\n const observers = observersOf(options);\n const [first] = observers;\n\n if (!first) {\n engine.clearViewshed();\n\n return false;\n }\n engine.setViewshed(\n new Float64Array(\n observers.flatMap((o) => [\n o.position[0],\n o.position[1],\n o.height ?? 1.7,\n o.range ?? 1000,\n ...(o.direction === undefined\n ? [Number.NaN, 0, 0, 0]\n : [o.direction, o.tilt ?? 0, o.fov ?? 60, o.verticalFov ?? 40]),\n ]),\n ),\n new Float32Array(rgb(first.visibleColor ?? '#2f9e44')),\n new Float32Array(rgb(first.hiddenColor ?? '#e03131')),\n first.opacity ?? 0.7,\n new Float32Array(first.coneColor ? rgb(first.coneColor) : []),\n );\n\n return true;\n};\n"]}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * A map's workers: the pool drawing vector tiles, shared by the map's `VectorTiles`, which also decodes the relief and
3
+ * reprojects rasters off the page; and the loaders of the relief, one per tile source.
4
+ */
5
+ import type { RemoteReprojection } from '../basemap/grid.ts';
6
+ import { type PngEncoding } from '../basemap/terrain.ts';
7
+ import { BasemapWorkers } from '../basemap/workerpool.ts';
8
+ import type { TerrainLoader } from '../settings.ts';
9
+ import type { GeoMapOptions } from '../types.ts';
10
+ /** The workers of a map, created on first use */
11
+ export declare class MapWorkers {
12
+ /** URL of the workers' script */
13
+ readonly url: string | URL;
14
+ private readonly workers;
15
+ /** The map is destroyed: nothing more is sent to the workers */
16
+ private readonly gone;
17
+ /** Whose requests the workers' answer (cancelled together) */
18
+ private readonly owner;
19
+ /** The shared pool, created on first use */
20
+ private shared;
21
+ /** The loaders of the relief by encoding, URL and floor: the same loader for the same tiles (the engine keeps its
22
+ * tiles when only the exaggeration changes) */
23
+ private readonly terrainLoaders;
24
+ /** `workers`: the map's option (false or 0, no worker); `owner`: the map */
25
+ constructor(url: string | URL, workers: GeoMapOptions['workers'], gone: () => boolean, owner: object);
26
+ /**
27
+ * The workers for a `VectorTiles`: the shared pool, or a pool of its own (`own`, to stop with it) when it asks for
28
+ * another count or URL
29
+ */
30
+ pool(count?: number, url?: string | URL): {
31
+ pool: BasemapWorkers;
32
+ own: boolean;
33
+ };
34
+ /** Stops the shared pool */
35
+ terminate(): void;
36
+ /** Rasters reprojected by the workers (in the page without them) */
37
+ readonly remoteReprojection: RemoteReprojection;
38
+ /** The loader of the relief tiles of `url` in a PNG encoding (one per URL, encoding and floor) */
39
+ readonly terrainLoader: (url: string, encoding: PngEncoding, floor?: number) => TerrainLoader;
40
+ private readonly remoteHeights;
41
+ /**
42
+ * The workers decoding the relief and reprojecting rasters: the shared pool, unless the map has no workers
43
+ * (`workers: false` or 0, or none in this browser): that is done in the page then
44
+ */
45
+ private decodingPool;
46
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * A map's workers: the pool drawing vector tiles, shared by the map's `VectorTiles`, which also decodes the relief and
3
+ * reprojects rasters off the page; and the loaders of the relief, one per tile source.
4
+ */
5
+ import { encodedTerrainLoader } from "../basemap/terrain.js";
6
+ import { BasemapWorkers, defaultWorkerCount } from "../basemap/workerpool.js";
7
+ /** The workers of a map, created on first use */
8
+ export class MapWorkers {
9
+ /** URL of the workers' script */
10
+ url;
11
+ workers;
12
+ /** The map is destroyed: nothing more is sent to the workers */
13
+ gone;
14
+ /** Whose requests the workers' answer (cancelled together) */
15
+ owner;
16
+ /** The shared pool, created on first use */
17
+ shared;
18
+ /** The loaders of the relief by encoding, URL and floor: the same loader for the same tiles (the engine keeps its
19
+ * tiles when only the exaggeration changes) */
20
+ terrainLoaders = new Map();
21
+ /** `workers`: the map's option (false or 0, no worker); `owner`: the map */
22
+ constructor(url, workers, gone, owner) {
23
+ this.url = url;
24
+ this.workers = workers;
25
+ this.gone = gone;
26
+ this.owner = owner;
27
+ }
28
+ /**
29
+ * The workers for a `VectorTiles`: the shared pool, or a pool of its own (`own`, to stop with it) when it asks for
30
+ * another count or URL
31
+ */
32
+ pool(count, url) {
33
+ const shared = defaultWorkerCount();
34
+ const workers = Math.max(1, count ?? shared);
35
+ const workerUrl = url ?? this.url;
36
+ if (workers === shared && String(workerUrl) === String(this.url)) {
37
+ this.shared ??= new BasemapWorkers(shared, this.url);
38
+ return { pool: this.shared, own: false };
39
+ }
40
+ return { pool: new BasemapWorkers(workers, workerUrl), own: true };
41
+ }
42
+ /** Stops the shared pool */
43
+ terminate() {
44
+ this.shared?.terminate();
45
+ this.shared = undefined;
46
+ }
47
+ /** Rasters reprojected by the workers (in the page without them) */
48
+ remoteReprojection = (job, tile, signal) => this.decodingPool()?.reproject(job, tile, signal, this.owner);
49
+ /** The loader of the relief tiles of `url` in a PNG encoding (one per URL, encoding and floor) */
50
+ terrainLoader = (url, encoding, floor) => {
51
+ const key = `${encoding} ${floor ?? ''} ${url}`;
52
+ const cached = this.terrainLoaders.get(key);
53
+ if (cached)
54
+ return cached;
55
+ const loader = encodedTerrainLoader(url, encoding, floor, this.remoteHeights);
56
+ this.terrainLoaders.set(key, loader);
57
+ return loader;
58
+ };
59
+ remoteHeights = (url, encoding, floor, tile, signal) => this.decodingPool()?.heights(url, encoding, floor, tile, signal, this.owner);
60
+ /**
61
+ * The workers decoding the relief and reprojecting rasters: the shared pool, unless the map has no workers
62
+ * (`workers: false` or 0, or none in this browser): that is done in the page then
63
+ */
64
+ decodingPool() {
65
+ const workers = this.workers;
66
+ if (this.gone() || workers === false || (workers !== undefined && workers <= 0))
67
+ return undefined;
68
+ if (typeof Worker === 'undefined' || typeof OffscreenCanvas === 'undefined')
69
+ return undefined;
70
+ return this.pool().pool;
71
+ }
72
+ }
73
+ //# sourceMappingURL=workers.js.map