isard 1.8.0 → 1.10.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 (235) hide show
  1. package/CHANGELOG.md +82 -1
  2. package/README.md +9 -4
  3. package/dist/basemap/grid.js +2 -5
  4. package/dist/basemap/grid.js.map +1 -1
  5. package/dist/basemap/models/furniture.d.ts +12 -0
  6. package/dist/basemap/{furniture.js → models/furniture.js} +6 -8
  7. package/dist/basemap/models/furniture.js.map +1 -0
  8. package/dist/basemap/{meshes.js → models/meshes.js} +1 -1
  9. package/dist/basemap/models/meshes.js.map +1 -0
  10. package/dist/basemap/models/trees.d.ts +21 -0
  11. package/dist/basemap/{trees.js → models/trees.js} +4 -36
  12. package/dist/basemap/models/trees.js.map +1 -0
  13. package/dist/basemap/placed.d.ts +2 -0
  14. package/dist/basemap/placed.js +2 -0
  15. package/dist/basemap/placed.js.map +1 -1
  16. package/dist/basemap/pmtiles.js +4 -3
  17. package/dist/basemap/pmtiles.js.map +1 -1
  18. package/dist/basemap/pmtileslayer.d.ts +4 -4
  19. package/dist/basemap/pmtileslayer.js +2 -1
  20. package/dist/basemap/pmtileslayer.js.map +1 -1
  21. package/dist/basemap/resample.js +3 -2
  22. package/dist/basemap/resample.js.map +1 -1
  23. package/dist/basemap/terrain.d.ts +5 -0
  24. package/dist/basemap/terrain.js +6 -4
  25. package/dist/basemap/terrain.js.map +1 -1
  26. package/dist/basemap/vectortiles/context.d.ts +3 -2
  27. package/dist/basemap/vectortiles/context.js.map +1 -1
  28. package/dist/basemap/vectortiles/extrusions.js.map +1 -1
  29. package/dist/basemap/vectortiles/furniture.d.ts +3 -3
  30. package/dist/basemap/vectortiles/furniture.js +2 -1
  31. package/dist/basemap/vectortiles/furniture.js.map +1 -1
  32. package/dist/basemap/vectortiles/labels.js +2 -1
  33. package/dist/basemap/vectortiles/labels.js.map +1 -1
  34. package/dist/basemap/vectortiles/lamps.d.ts +3 -3
  35. package/dist/basemap/vectortiles/lamps.js +1 -1
  36. package/dist/basemap/vectortiles/lamps.js.map +1 -1
  37. package/dist/basemap/vectortiles/placed.d.ts +3 -2
  38. package/dist/basemap/vectortiles/placed.js +5 -10
  39. package/dist/basemap/vectortiles/placed.js.map +1 -1
  40. package/dist/basemap/vectortiles/requests.d.ts +8 -1
  41. package/dist/basemap/vectortiles/requests.js +32 -4
  42. package/dist/basemap/vectortiles/requests.js.map +1 -1
  43. package/dist/basemap/vectortiles/street-wind.js +2 -2
  44. package/dist/basemap/vectortiles/street-wind.js.map +1 -1
  45. package/dist/basemap/vectortiles/style.js +7 -8
  46. package/dist/basemap/vectortiles/style.js.map +1 -1
  47. package/dist/basemap/vectortiles/tiles.d.ts +1 -3
  48. package/dist/basemap/vectortiles/tiles.js +1 -1
  49. package/dist/basemap/vectortiles/tiles.js.map +1 -1
  50. package/dist/basemap/vectortiles/trees.d.ts +4 -4
  51. package/dist/basemap/vectortiles/trees.js +2 -1
  52. package/dist/basemap/vectortiles/trees.js.map +1 -1
  53. package/dist/basemap/vectortiles/vectors.d.ts +9 -3
  54. package/dist/basemap/vectortiles/vectors.js +26 -2
  55. package/dist/basemap/vectortiles/vectors.js.map +1 -1
  56. package/dist/basemap/vectortiles.d.ts +8 -6
  57. package/dist/basemap/vectortiles.js +7 -4
  58. package/dist/basemap/vectortiles.js.map +1 -1
  59. package/dist/basemap/wmts.js +3 -4
  60. package/dist/basemap/wmts.js.map +1 -1
  61. package/dist/basemap/{trees.d.ts → woods.d.ts} +2 -19
  62. package/dist/basemap/woods.js +38 -0
  63. package/dist/basemap/woods.js.map +1 -0
  64. package/dist/basemap/workerpool.d.ts +1 -1
  65. package/dist/basemap/workerpool.js +3 -3
  66. package/dist/basemap/workerpool.js.map +1 -1
  67. package/dist/basemap.worker.js +2 -2
  68. package/dist/basemap.worker.js.map +23 -22
  69. package/dist/bind/layers.js +3 -0
  70. package/dist/bind/layers.js.map +1 -1
  71. package/dist/data/collada.js +4 -4
  72. package/dist/data/collada.js.map +1 -1
  73. package/dist/data/ifc.js +6 -11
  74. package/dist/data/ifc.js.map +1 -1
  75. package/dist/data/tileset.d.ts +21 -0
  76. package/dist/data/tileset.js +101 -0
  77. package/dist/data/tileset.js.map +1 -0
  78. package/dist/decoder.worker.js +5 -5
  79. package/dist/decoder.worker.js.map +7 -6
  80. package/dist/decoding/decoders.js.map +1 -0
  81. package/dist/{engine → decoding}/loader.js +2 -2
  82. package/dist/decoding/loader.js.map +1 -0
  83. package/dist/{engine → decoding}/protocol.d.ts +1 -1
  84. package/dist/decoding/protocol.js.map +1 -0
  85. package/dist/engine-loader.d.ts +3 -3
  86. package/dist/engine-loader.js +12 -5
  87. package/dist/engine-loader.js.map +1 -1
  88. package/dist/geoplateforme.d.ts +2 -1
  89. package/dist/geoplateforme.js +6 -8
  90. package/dist/geoplateforme.js.map +1 -1
  91. package/dist/index.d.ts +15 -7
  92. package/dist/index.js +9 -3
  93. package/dist/index.js.map +1 -1
  94. package/dist/isard_bg.wasm +0 -0
  95. package/dist/isard_core_bg.wasm +0 -0
  96. package/dist/isard_tess_bg.wasm +0 -0
  97. package/dist/layers/custom.d.ts +56 -0
  98. package/dist/layers/custom.js +93 -0
  99. package/dist/layers/custom.js.map +1 -0
  100. package/dist/layers/extrusions.d.ts +4 -2
  101. package/dist/layers/extrusions.js +2 -1
  102. package/dist/layers/extrusions.js.map +1 -1
  103. package/dist/layers/features.d.ts +3 -14
  104. package/dist/layers/features.js +4 -25
  105. package/dist/layers/features.js.map +1 -1
  106. package/dist/layers/flow.d.ts +3 -3
  107. package/dist/layers/flow.js +3 -4
  108. package/dist/layers/flow.js.map +1 -1
  109. package/dist/layers/glyphs.js +5 -3
  110. package/dist/layers/glyphs.js.map +1 -1
  111. package/dist/layers/ground.d.ts +57 -0
  112. package/dist/layers/ground.js +78 -0
  113. package/dist/layers/ground.js.map +1 -0
  114. package/dist/layers/icons.js +8 -6
  115. package/dist/layers/icons.js.map +1 -1
  116. package/dist/layers/layers.d.ts +2 -199
  117. package/dist/layers/layers.js +2 -469
  118. package/dist/layers/layers.js.map +1 -1
  119. package/dist/layers/models.d.ts +48 -0
  120. package/dist/layers/models.js +111 -0
  121. package/dist/layers/models.js.map +1 -0
  122. package/dist/layers/network.d.ts +26 -0
  123. package/dist/layers/network.js +127 -0
  124. package/dist/layers/network.js.map +1 -0
  125. package/dist/layers/panoramas.d.ts +2 -11
  126. package/dist/layers/panoramas.js +19 -9
  127. package/dist/layers/panoramas.js.map +1 -1
  128. package/dist/layers/photos.d.ts +4 -7
  129. package/dist/layers/photos.js +3 -4
  130. package/dist/layers/photos.js.map +1 -1
  131. package/dist/layers/pointclouds.d.ts +3 -2
  132. package/dist/layers/pointclouds.js +3 -3
  133. package/dist/layers/pointclouds.js.map +1 -1
  134. package/dist/layers/raster.d.ts +9 -0
  135. package/dist/layers/raster.js +24 -0
  136. package/dist/layers/raster.js.map +1 -0
  137. package/dist/layers/symbols.d.ts +2 -2
  138. package/dist/layers/symbols.js +2 -1
  139. package/dist/layers/symbols.js.map +1 -1
  140. package/dist/layers/tiles3d.d.ts +20 -0
  141. package/dist/layers/tiles3d.js +69 -0
  142. package/dist/layers/tiles3d.js.map +1 -0
  143. package/dist/layers/trees.d.ts +5 -7
  144. package/dist/layers/trees.js +2 -1
  145. package/dist/layers/trees.js.map +1 -1
  146. package/dist/layers/vectors.d.ts +3 -0
  147. package/dist/layers/vectors.js +4 -0
  148. package/dist/layers/vectors.js.map +1 -1
  149. package/dist/map/basemap-layers.js +1 -1
  150. package/dist/map/basemap-layers.js.map +1 -1
  151. package/dist/map/engine-settings.d.ts +1 -1
  152. package/dist/map/engine-settings.js +1 -1
  153. package/dist/map/engine-settings.js.map +1 -1
  154. package/dist/map/engines.js.map +1 -1
  155. package/dist/map/layer-spec.d.ts +7 -13
  156. package/dist/map/layer-spec.js.map +1 -1
  157. package/dist/map/workers.js +3 -4
  158. package/dist/map/workers.js.map +1 -1
  159. package/dist/map.d.ts +25 -58
  160. package/dist/map.js +61 -53
  161. package/dist/map.js.map +1 -1
  162. package/dist/panoramax.js +6 -8
  163. package/dist/panoramax.js.map +1 -1
  164. package/dist/react/CustomLayer.d.ts +1 -1
  165. package/dist/react/CustomLayer.js.map +1 -1
  166. package/dist/react/Layer.d.ts +5 -1
  167. package/dist/react/Layer.js.map +1 -1
  168. package/dist/react/VectorGeometry.d.ts +4 -0
  169. package/dist/react/VectorGeometry.js +6 -3
  170. package/dist/react/VectorGeometry.js.map +1 -1
  171. package/dist/react/VectorTiles.d.ts +2 -2
  172. package/dist/react/VectorTiles.js +1 -1
  173. package/dist/react/VectorTiles.js.map +1 -1
  174. package/dist/types.d.ts +16 -4
  175. package/dist/types.js.map +1 -1
  176. package/dist/ui/controls.js +2 -1
  177. package/dist/ui/controls.js.map +1 -1
  178. package/dist/ui/interaction.d.ts +4 -0
  179. package/dist/ui/interaction.js +59 -7
  180. package/dist/ui/interaction.js.map +1 -1
  181. package/dist/ui/minimap.js +1 -1
  182. package/dist/ui/minimap.js.map +1 -1
  183. package/dist/ui/overlay.js +3 -3
  184. package/dist/ui/overlay.js.map +1 -1
  185. package/dist/ui/search.js +1 -1
  186. package/dist/ui/search.js.map +1 -1
  187. package/dist/util/animation.js +3 -2
  188. package/dist/util/animation.js.map +1 -1
  189. package/dist/util/color.d.ts +10 -0
  190. package/dist/util/color.js +29 -9
  191. package/dist/util/color.js.map +1 -1
  192. package/dist/util/fetch.d.ts +5 -0
  193. package/dist/util/fetch.js +11 -0
  194. package/dist/util/fetch.js.map +1 -0
  195. package/dist/util/geo.d.ts +5 -0
  196. package/dist/util/geo.js +8 -2
  197. package/dist/util/geo.js.map +1 -1
  198. package/dist/util/math.d.ts +3 -0
  199. package/dist/util/math.js +4 -0
  200. package/dist/util/math.js.map +1 -0
  201. package/dist/util/requests.js.map +1 -0
  202. package/dist/util/roofs.d.ts +0 -2
  203. package/dist/util/roofs.js +0 -3
  204. package/dist/util/roofs.js.map +1 -1
  205. package/dist/wasm/isard.d.ts +18 -1
  206. package/dist/wasm/isard.js +28 -2
  207. package/dist/wasm/isard_core.d.ts +13 -1
  208. package/dist/wasm/isard_core.js +20 -2
  209. package/dist/workers/basemap/geometry.d.ts +9 -19
  210. package/dist/workers/{basemap.worker.d.ts → basemap/protocol.d.ts} +32 -23
  211. package/dist/workers/basemap/street.d.ts +4 -2
  212. package/dist/workers/basemap/tiles.d.ts +1 -3
  213. package/dist/workers/basemap/trees.d.ts +2 -2
  214. package/package.json +1 -1
  215. package/dist/basemap/furniture.d.ts +0 -26
  216. package/dist/basemap/furniture.js.map +0 -1
  217. package/dist/basemap/meshes.js.map +0 -1
  218. package/dist/basemap/trees.js.map +0 -1
  219. package/dist/engine/decoders.js.map +0 -1
  220. package/dist/engine/loader.js.map +0 -1
  221. package/dist/engine/protocol.js.map +0 -1
  222. package/dist/engine/requests.js.map +0 -1
  223. package/dist/workers/basemap/furniture.d.ts +0 -13
  224. package/dist/workers/basemap/labels.d.ts +0 -24
  225. package/dist/workers/basemap/lamps.d.ts +0 -10
  226. package/dist/workers/basemap/raster.d.ts +0 -10
  227. package/dist/workers/basemap.worker.js +0 -221
  228. package/dist/workers/basemap.worker.js.map +0 -1
  229. /package/dist/basemap/{meshes.d.ts → models/meshes.d.ts} +0 -0
  230. /package/dist/{engine → decoding}/decoders.d.ts +0 -0
  231. /package/dist/{engine → decoding}/decoders.js +0 -0
  232. /package/dist/{engine → decoding}/loader.d.ts +0 -0
  233. /package/dist/{engine → decoding}/protocol.js +0 -0
  234. /package/dist/{engine → util}/requests.d.ts +0 -0
  235. /package/dist/{engine → util}/requests.js +0 -0
@@ -0,0 +1,111 @@
1
+ /** glTF models drawn at many positions as a layer: their instances, their glow, their highlight */
2
+ import { parseColor } from "../util/color.js";
3
+ import { Layer } from "./layers.js";
4
+ /** The numbers of instances for the engine: longitude, latitude, altitude, heading, pitch, roll, scale */
5
+ const instanceNumbers = (instances) => {
6
+ const out = new Float64Array(instances.length * 7);
7
+ instances.forEach(({ lonLat, altitude = 0, heading = 0, pitch = 0, roll = 0, scale = 1 }, i) => {
8
+ out.set([lonLat[0], lonLat[1], altitude, heading, pitch, roll, scale], i * 7);
9
+ });
10
+ return out;
11
+ };
12
+ /** A glTF model drawn at positions, in one instanced draw; `pickFeature` gives the instance's index */
13
+ export class ModelLayer extends Layer {
14
+ url;
15
+ /** The `blob:` URL of the page's bytes, revoked once the layer is gone */
16
+ blob;
17
+ instances;
18
+ /** Its glow at night (`setGlow`) */
19
+ glow;
20
+ /** Its feature highlighted (`setHighlight`) */
21
+ highlight;
22
+ ground;
23
+ /** @internal */
24
+ constructor(map, options) {
25
+ super(map);
26
+ const { url, data } = options;
27
+ if (data) {
28
+ this.blob = URL.createObjectURL(new Blob([data], { type: 'model/gltf-binary' }));
29
+ this.url = this.blob;
30
+ }
31
+ else if (url) {
32
+ // Against the page: the decoding workers fetch it, and a relative URL would be theirs
33
+ const base = typeof document === 'undefined' ? undefined : document.baseURI;
34
+ this.url = base ? new URL(url, base).href : url;
35
+ }
36
+ else {
37
+ throw new Error('isard: a model needs a url or data');
38
+ }
39
+ this.instances = instanceNumbers(options.instances);
40
+ this.ground = options.altitudeReference !== 'sea';
41
+ }
42
+ /** @internal The engine with 3D Tiles decodes and draws the models */
43
+ get needsFullEngine() {
44
+ return true;
45
+ }
46
+ /** Replaces the instances (and what their altitudes are above, kept if not given) */
47
+ setInstances(instances, altitudeReference) {
48
+ this.instances = instanceNumbers(instances);
49
+ if (altitudeReference)
50
+ this.ground = altitudeReference === 'ground';
51
+ // Kept for its creation while the engine with 3D Tiles loads
52
+ if (this.id < 0)
53
+ return;
54
+ this.map.engine.setModelInstances(this.id, this.instances, this.ground);
55
+ this.map.requestRender();
56
+ }
57
+ /** Lights at night the part of the model from `from` metres above its foot (a street lamp's head) in a CSS color;
58
+ * none without a color */
59
+ setGlow(from, color) {
60
+ this.glow = color === undefined ? undefined : { from, color };
61
+ if (this.id < 0)
62
+ return;
63
+ this.sendGlow(this.map.engine, this.id);
64
+ this.map.requestRender();
65
+ }
66
+ /** Highlights a feature of the model (an IFC model's element, `hit.index` of a pick) in a CSS color (amber by
67
+ * default); none without a feature */
68
+ setHighlight(feature, color = '#ffb000') {
69
+ this.highlight = feature === undefined ? undefined : { feature, color };
70
+ if (this.id < 0)
71
+ return;
72
+ this.sendHighlight(this.map.engine, this.id);
73
+ this.map.requestRender();
74
+ }
75
+ sendHighlight(engine, id) {
76
+ const [r = 0, g = 0, b = 0] = this.highlight ? parseColor(this.highlight.color) : [];
77
+ engine.setModelHighlight(id, this.highlight ? this.highlight.feature : Number.NaN, r, g, b);
78
+ }
79
+ sendGlow(engine, id) {
80
+ const [r = 0, g = 0, b = 0] = this.glow ? parseColor(this.glow.color) : [];
81
+ engine.setModelGlow(id, this.glow ? this.glow.from : Number.NaN, r, g, b);
82
+ }
83
+ /** @internal The instances as the engine takes them (`instanceNumbers`: seven numbers each), above the ground */
84
+ setInstanceNumbers(numbers) {
85
+ this.instances = numbers;
86
+ this.ground = true;
87
+ if (this.id < 0)
88
+ return;
89
+ this.map.engine.setModelInstances(this.id, this.instances, this.ground);
90
+ this.map.requestRender();
91
+ }
92
+ remove() {
93
+ super.remove();
94
+ this.dispose();
95
+ }
96
+ /** @internal */
97
+ dispose() {
98
+ if (this.blob)
99
+ URL.revokeObjectURL(this.blob);
100
+ }
101
+ /** @internal */
102
+ create(engine) {
103
+ const id = engine.addModels(this.url, this.instances, this.ground);
104
+ if (this.glow)
105
+ this.sendGlow(engine, id);
106
+ if (this.highlight)
107
+ this.sendHighlight(engine, id);
108
+ return id;
109
+ }
110
+ }
111
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/layers/models.ts"],"names":[],"mappings":"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","sourcesContent":["/** glTF models drawn at many positions as a layer: their instances, their glow, their highlight */\n\nimport type { LayerHost, LonLat, Placement } from '../types.ts';\nimport { parseColor } from '../util/color.ts';\nimport type { Engine } from '../wasm/isard.js';\nimport { Layer } from './layers.ts';\n\n/** Where and how a model stands */\nexport interface ModelInstance {\n lonLat: LonLat;\n /** Metres above the ground (or above the ellipsoid, `altitudeReference: 'sea'`); 0 by default */\n altitude?: number;\n /** Degrees clockwise from the north of the model's front (glTF +Z); 0 by default */\n heading?: number;\n /** Degrees, nose up */\n pitch?: number;\n /** Degrees, right side down */\n roll?: number;\n /** 1 by default: the model's metres */\n scale?: number;\n}\n\nexport interface ModelOptions extends Placement {\n /** URL of a glTF binary (`.glb`): meshes, textures, Draco, meshopt, KTX2, as in 3D Tiles; or its bytes (`data`) */\n url?: string;\n data?: ArrayBuffer | ArrayBufferView<ArrayBuffer>;\n instances: readonly ModelInstance[];\n /** What the altitudes are above: `'ground'` (the relief, the default) or `'sea'` (the ellipsoid) */\n altitudeReference?: 'ground' | 'sea';\n}\n\n/** The numbers of instances for the engine: longitude, latitude, altitude, heading, pitch, roll, scale */\nconst instanceNumbers = (instances: readonly ModelInstance[]): Float64Array => {\n const out = new Float64Array(instances.length * 7);\n\n instances.forEach(({ lonLat, altitude = 0, heading = 0, pitch = 0, roll = 0, scale = 1 }, i) => {\n out.set([lonLat[0], lonLat[1], altitude, heading, pitch, roll, scale], i * 7);\n });\n\n return out;\n};\n\n/** A glTF model drawn at positions, in one instanced draw; `pickFeature` gives the instance's index */\nexport class ModelLayer extends Layer {\n private readonly url: string;\n /** The `blob:` URL of the page's bytes, revoked once the layer is gone */\n private readonly blob: string | undefined;\n private instances: Float64Array;\n /** Its glow at night (`setGlow`) */\n private glow: { from: number; color: string } | undefined;\n /** Its feature highlighted (`setHighlight`) */\n private highlight: { feature: number; color: string } | undefined;\n private ground: boolean;\n\n /** @internal */\n constructor(map: LayerHost, options: ModelOptions) {\n super(map);\n\n const { url, data } = options;\n\n if (data) {\n this.blob = URL.createObjectURL(new Blob([data], { type: 'model/gltf-binary' }));\n this.url = this.blob;\n } else if (url) {\n // Against the page: the decoding workers fetch it, and a relative URL would be theirs\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n\n this.url = base ? new URL(url, base).href : url;\n } else {\n throw new Error('isard: a model needs a url or data');\n }\n this.instances = instanceNumbers(options.instances);\n this.ground = options.altitudeReference !== 'sea';\n }\n\n /** @internal The engine with 3D Tiles decodes and draws the models */\n override get needsFullEngine(): boolean {\n return true;\n }\n\n /** Replaces the instances (and what their altitudes are above, kept if not given) */\n setInstances(instances: readonly ModelInstance[], altitudeReference?: 'ground' | 'sea'): void {\n this.instances = instanceNumbers(instances);\n if (altitudeReference) this.ground = altitudeReference === 'ground';\n // Kept for its creation while the engine with 3D Tiles loads\n if (this.id < 0) return;\n this.map.engine.setModelInstances(this.id, this.instances, this.ground);\n this.map.requestRender();\n }\n\n /** Lights at night the part of the model from `from` metres above its foot (a street lamp's head) in a CSS color;\n * none without a color */\n setGlow(from: number, color?: string): void {\n this.glow = color === undefined ? undefined : { from, color };\n if (this.id < 0) return;\n this.sendGlow(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n /** Highlights a feature of the model (an IFC model's element, `hit.index` of a pick) in a CSS color (amber by\n * default); none without a feature */\n setHighlight(feature?: number, color = '#ffb000'): void {\n this.highlight = feature === undefined ? undefined : { feature, color };\n if (this.id < 0) return;\n this.sendHighlight(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n private sendHighlight(engine: Engine, id: number): void {\n const [r = 0, g = 0, b = 0] = this.highlight ? parseColor(this.highlight.color) : [];\n\n engine.setModelHighlight(id, this.highlight ? this.highlight.feature : Number.NaN, r, g, b);\n }\n\n private sendGlow(engine: Engine, id: number): void {\n const [r = 0, g = 0, b = 0] = this.glow ? parseColor(this.glow.color) : [];\n\n engine.setModelGlow(id, this.glow ? this.glow.from : Number.NaN, r, g, b);\n }\n\n /** @internal The instances as the engine takes them (`instanceNumbers`: seven numbers each), above the ground */\n setInstanceNumbers(numbers: Float64Array): void {\n this.instances = numbers;\n this.ground = true;\n if (this.id < 0) return;\n this.map.engine.setModelInstances(this.id, this.instances, this.ground);\n this.map.requestRender();\n }\n\n override remove(): void {\n super.remove();\n this.dispose();\n }\n\n /** @internal */\n override dispose(): void {\n if (this.blob) URL.revokeObjectURL(this.blob);\n }\n\n /** @internal */\n protected create(engine: Engine): number {\n const id = engine.addModels(this.url, this.instances, this.ground);\n\n if (this.glow) this.sendGlow(engine, id);\n if (this.highlight) this.sendHighlight(engine, id);\n\n return id;\n }\n}\n"]}
@@ -0,0 +1,26 @@
1
+ /** A line network colored by a value per node (travel times, water depths…) as a layer */
2
+ import type { NetworkStyle } from '../types.ts';
3
+ import type { NetworkStats } from '../wasm/isard.js';
4
+ import { Layer } from './layers.ts';
5
+ /** Line network colored by a value per node (travel time, water depth…) */
6
+ export declare class NetworkLayer extends Layer {
7
+ private geometry;
8
+ private costs;
9
+ private style;
10
+ private edgeWidths;
11
+ private values;
12
+ /** Node and line positions in Mercator, kept for a context loss: f32 offsets from an origin (exact to the centimetre
13
+ * across a region, half the memory of f64) */
14
+ private kept;
15
+ /** One value per node, in node order; negative (or 1e30 and above) = unreached. Costs one texture upload, drawn
16
+ * next frame. */
17
+ setValues(values: Float32Array): void;
18
+ /** Costs of the edges, A → B then B → A (see `NetworkOptions.costs`), when the way the network is travelled
19
+ * changes; undefined: values interpolated along the edges. The geometry stays on the graphics card. */
20
+ setCosts(costs: Float32Array | undefined): void;
21
+ setStyle(style: Partial<NetworkStyle>): void;
22
+ /** Width factor of each edge (undefined: 1 for all) */
23
+ setEdgeWidths(widths: Float32Array | undefined): void;
24
+ /** Pieces in all and drawn in the last frame */
25
+ stats(): NetworkStats | undefined;
26
+ }
@@ -0,0 +1,127 @@
1
+ /** A line network colored by a value per node (travel times, water depths…) as a layer */
2
+ import { parseColor, rampTexels } from "../util/color.js";
3
+ import { mercatorX, mercatorY } from "../util/geo.js";
4
+ import { stops } from "./features.js";
5
+ import { Layer } from "./layers.js";
6
+ /** Line network colored by a value per node (travel time, water depth…) */
7
+ export class NetworkLayer extends Layer {
8
+ geometry;
9
+ costs;
10
+ style;
11
+ edgeWidths;
12
+ values;
13
+ /** Node and line positions in Mercator, kept for a context loss: f32 offsets from an origin (exact to the centimetre
14
+ * across a region, half the memory of f64) */
15
+ kept;
16
+ /** @internal */
17
+ constructor(map, geometry, costs, style, edgeWidths) {
18
+ super(map);
19
+ this.geometry = geometry;
20
+ this.costs = costs;
21
+ this.style = style;
22
+ this.edgeWidths = edgeWidths;
23
+ }
24
+ /** One value per node, in node order; negative (or 1e30 and above) = unreached. Costs one texture upload, drawn
25
+ * next frame. */
26
+ setValues(values) {
27
+ this.values = values;
28
+ this.map.engine.setNetworkValues(this.id, values);
29
+ this.map.requestRender();
30
+ }
31
+ /** Costs of the edges, A → B then B → A (see `NetworkOptions.costs`), when the way the network is travelled
32
+ * changes; undefined: values interpolated along the edges. The geometry stays on the graphics card. */
33
+ setCosts(costs) {
34
+ this.costs = costs;
35
+ this.map.engine.setNetworkCosts(this.id, costs);
36
+ this.map.requestRender();
37
+ }
38
+ setStyle(style) {
39
+ const ramp = this.style.ramp;
40
+ this.style = { ...this.style, ...style };
41
+ this.map.engine.setNetworkStyle(this.id, networkStyle(this.style));
42
+ if (this.style.ramp !== ramp)
43
+ this.map.engine.setNetworkRamp(this.id, this.style.ramp && rampTexels(this.style.ramp).rgba);
44
+ this.map.requestRender();
45
+ }
46
+ /** Width factor of each edge (undefined: 1 for all) */
47
+ setEdgeWidths(widths) {
48
+ this.edgeWidths = widths;
49
+ this.map.engine.setNetworkScales(this.id, widths);
50
+ this.map.requestRender();
51
+ }
52
+ /** Pieces in all and drawn in the last frame */
53
+ stats() {
54
+ return this.map.engine.networkStats(this.id);
55
+ }
56
+ /** @internal */
57
+ create(engine) {
58
+ const { nodes, edges, lines } = this.geometry;
59
+ const mercator = (() => {
60
+ if (this.kept) {
61
+ const { origin, nodes: n, lines: l } = this.kept;
62
+ return { nodes: unpack(n, origin), lines: l && unpack(l, origin) };
63
+ }
64
+ // Mercator here: Math.tan and Math.log run natively, several times faster than in WebAssembly
65
+ const projected = { nodes: mercatorPoints(nodes), lines: lines && mercatorPoints(lines.points) };
66
+ const origin = [projected.nodes[0] ?? 0, projected.nodes[1] ?? 0];
67
+ this.kept = {
68
+ origin,
69
+ nodes: pack(projected.nodes, origin),
70
+ lines: projected.lines && pack(projected.lines, origin),
71
+ };
72
+ // The degrees are not needed again: millions of points for a region
73
+ this.geometry = { nodes: EMPTY, edges, lines: lines && { start: lines.start, points: EMPTY } };
74
+ return projected;
75
+ })();
76
+ const id = engine.addNetwork(mercator.nodes, edges, lines?.start, mercator.lines, this.costs, networkStyle(this.style));
77
+ if (this.style.ramp)
78
+ engine.setNetworkRamp(id, rampTexels(this.style.ramp).rgba);
79
+ if (this.edgeWidths)
80
+ engine.setNetworkScales(id, this.edgeWidths);
81
+ if (this.values)
82
+ engine.setNetworkValues(id, this.values);
83
+ return id;
84
+ }
85
+ }
86
+ /** The 25 numbers of a network style for the engine */
87
+ const networkStyle = (style) => {
88
+ const { width, halo, max, contour, opacity, haloOpacity, unreachedColor, fade } = style;
89
+ return Float32Array.from([
90
+ ...stops(width),
91
+ ...stops(halo),
92
+ max,
93
+ contour,
94
+ opacity,
95
+ haloOpacity,
96
+ ...parseColor(unreachedColor),
97
+ fade,
98
+ ]);
99
+ };
100
+ const EMPTY = new Float64Array(0);
101
+ /** Interleaved points as f32 offsets from an origin, and back */
102
+ const pack = (points, [ox, oy]) => {
103
+ const out = new Float32Array(points.length);
104
+ for (let i = 0; i < points.length; i += 2) {
105
+ out[i] = (points[i] ?? 0) - ox;
106
+ out[i + 1] = (points[i + 1] ?? 0) - oy;
107
+ }
108
+ return out;
109
+ };
110
+ const unpack = (points, [ox, oy]) => {
111
+ const out = new Float64Array(points.length);
112
+ for (let i = 0; i < points.length; i += 2) {
113
+ out[i] = (points[i] ?? 0) + ox;
114
+ out[i + 1] = (points[i + 1] ?? 0) + oy;
115
+ }
116
+ return out;
117
+ };
118
+ /** Longitudes and latitudes (degrees, interleaved) to Mercator [0, 1], y towards the south */
119
+ const mercatorPoints = (lonLat) => {
120
+ const out = new Float64Array(lonLat.length);
121
+ for (let i = 0; i < lonLat.length; i += 2) {
122
+ out[i] = mercatorX(lonLat[i] ?? 0);
123
+ out[i + 1] = mercatorY(lonLat[i + 1] ?? 0);
124
+ }
125
+ return out;
126
+ };
127
+ //# sourceMappingURL=network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/layers/network.ts"],"names":[],"mappings":"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","sourcesContent":["/** A line network colored by a value per node (travel times, water depths…) as a layer */\n\nimport type { LayerHost, NetworkOptions, NetworkStyle } from '../types.ts';\nimport { parseColor, rampTexels } from '../util/color.ts';\nimport { mercatorX, mercatorY } from '../util/geo.ts';\nimport type { Engine, NetworkStats } from '../wasm/isard.js';\nimport { stops } from './features.ts';\nimport { Layer } from './layers.ts';\n\n/** Line network colored by a value per node (travel time, water depth…) */\nexport class NetworkLayer extends Layer {\n private values: Float32Array | undefined;\n /** Node and line positions in Mercator, kept for a context loss: f32 offsets from an origin (exact to the centimetre\n * across a region, half the memory of f64) */\n private kept: { origin: [number, number]; nodes: Float32Array; lines: Float32Array | undefined } | undefined;\n\n /** @internal */\n constructor(\n map: LayerHost,\n private geometry: { nodes: Float64Array; edges: Uint32Array; lines: NetworkOptions['lines'] | undefined },\n private costs: Float32Array | undefined,\n private style: NetworkStyle,\n private edgeWidths: Float32Array | undefined,\n ) {\n super(map);\n }\n\n /** One value per node, in node order; negative (or 1e30 and above) = unreached. Costs one texture upload, drawn\n * next frame. */\n setValues(values: Float32Array): void {\n this.values = values;\n this.map.engine.setNetworkValues(this.id, values);\n this.map.requestRender();\n }\n\n /** Costs of the edges, A → B then B → A (see `NetworkOptions.costs`), when the way the network is travelled\n * changes; undefined: values interpolated along the edges. The geometry stays on the graphics card. */\n setCosts(costs: Float32Array | undefined): void {\n this.costs = costs;\n this.map.engine.setNetworkCosts(this.id, costs);\n this.map.requestRender();\n }\n\n setStyle(style: Partial<NetworkStyle>): void {\n const ramp = this.style.ramp;\n\n this.style = { ...this.style, ...style };\n this.map.engine.setNetworkStyle(this.id, networkStyle(this.style));\n if (this.style.ramp !== ramp)\n this.map.engine.setNetworkRamp(this.id, this.style.ramp && rampTexels(this.style.ramp).rgba);\n this.map.requestRender();\n }\n\n /** Width factor of each edge (undefined: 1 for all) */\n setEdgeWidths(widths: Float32Array | undefined): void {\n this.edgeWidths = widths;\n this.map.engine.setNetworkScales(this.id, widths);\n this.map.requestRender();\n }\n\n /** Pieces in all and drawn in the last frame */\n stats(): NetworkStats | undefined {\n return this.map.engine.networkStats(this.id);\n }\n\n /** @internal */\n protected create(engine: Engine): number {\n const { nodes, edges, lines } = this.geometry;\n const mercator = ((): { nodes: Float64Array; lines: Float64Array | undefined } => {\n if (this.kept) {\n const { origin, nodes: n, lines: l } = this.kept;\n\n return { nodes: unpack(n, origin), lines: l && unpack(l, origin) };\n }\n\n // Mercator here: Math.tan and Math.log run natively, several times faster than in WebAssembly\n const projected = { nodes: mercatorPoints(nodes), lines: lines && mercatorPoints(lines.points) };\n const origin: [number, number] = [projected.nodes[0] ?? 0, projected.nodes[1] ?? 0];\n\n this.kept = {\n origin,\n nodes: pack(projected.nodes, origin),\n lines: projected.lines && pack(projected.lines, origin),\n };\n // The degrees are not needed again: millions of points for a region\n this.geometry = { nodes: EMPTY, edges, lines: lines && { start: lines.start, points: EMPTY } };\n\n return projected;\n })();\n const id = engine.addNetwork(\n mercator.nodes,\n edges,\n lines?.start,\n mercator.lines,\n this.costs,\n networkStyle(this.style),\n );\n\n if (this.style.ramp) engine.setNetworkRamp(id, rampTexels(this.style.ramp).rgba);\n if (this.edgeWidths) engine.setNetworkScales(id, this.edgeWidths);\n if (this.values) engine.setNetworkValues(id, this.values);\n\n return id;\n }\n}\n\n/** The 25 numbers of a network style for the engine */\nconst networkStyle = (style: NetworkStyle): Float32Array => {\n const { width, halo, max, contour, opacity, haloOpacity, unreachedColor, fade } = style;\n\n return Float32Array.from([\n ...stops(width),\n ...stops(halo),\n max,\n contour,\n opacity,\n haloOpacity,\n ...parseColor(unreachedColor),\n fade,\n ]);\n};\n\nconst EMPTY = new Float64Array(0);\n\n/** Interleaved points as f32 offsets from an origin, and back */\nconst pack = (points: Float64Array, [ox, oy]: [number, number]): Float32Array => {\n const out = new Float32Array(points.length);\n\n for (let i = 0; i < points.length; i += 2) {\n out[i] = (points[i] ?? 0) - ox;\n out[i + 1] = (points[i + 1] ?? 0) - oy;\n }\n\n return out;\n};\n\nconst unpack = (points: Float32Array, [ox, oy]: [number, number]): Float64Array => {\n const out = new Float64Array(points.length);\n\n for (let i = 0; i < points.length; i += 2) {\n out[i] = (points[i] ?? 0) + ox;\n out[i + 1] = (points[i + 1] ?? 0) + oy;\n }\n\n return out;\n};\n\n/** Longitudes and latitudes (degrees, interleaved) to Mercator [0, 1], y towards the south */\nconst mercatorPoints = (lonLat: Float64Array): Float64Array => {\n const out = new Float64Array(lonLat.length);\n\n for (let i = 0; i < lonLat.length; i += 2) {\n out[i] = mercatorX(lonLat[i] ?? 0);\n out[i + 1] = mercatorY(lonLat[i + 1] ?? 0);\n }\n\n return out;\n};\n"]}
@@ -60,17 +60,6 @@ export interface PanoramaHost {
60
60
  * map's own); returns what stops */
61
61
  listen(click: (lonLat: LonLat | undefined) => void, key: (e: KeyboardEvent) => void, wheel: (e: WheelEvent) => void): () => void;
62
62
  }
63
- interface Attitude {
64
- heading: number;
65
- pitch: number;
66
- roll: number;
67
- }
68
- /**
69
- * The panorama frame to east, north, up (row-major): the vehicle's attitude in the CRS's grid (iTowns'
70
- * `quaternionFromRollPitchHeading`: Ry(-roll) · Rx(-pitch) · Rz(-heading)), turned by the meridian convergence of the
71
- * projection (Lambert-93: sin(46.5°) · (3° - longitude))
72
- */
73
- export declare const panoramaRotation: (attitude: Attitude, lon: number, lambert93: boolean) => number[];
74
63
  /** The numbers of a 360° photo's camera facing `heading` (its frame east, north, up): x right, y down, z ahead; no
75
64
  * focal (the engine's sign of an equirectangular image) */
76
65
  export declare const photoCamera: (heading: number) => number[];
@@ -111,6 +100,8 @@ export declare class Panoramas {
111
100
  go(index: number, bearing?: number): Promise<void>;
112
101
  /** Ends the walk: the panorama hidden, the camera turning around a point again, above where the eye stood */
113
102
  exit(): void;
103
+ /** Removes the panoramas from the map: the walk ended (the eye back above the map), the panorama shown hidden */
104
+ remove(): void;
114
105
  }
115
106
  /** Loads a set of panoramas: a vehicle's (their positions and attitudes, the calibration of their cameras), or 360°
116
107
  * photos */
@@ -12,9 +12,11 @@
12
12
  * ```
13
13
  */
14
14
  import { getCrs } from "../data/crs.js";
15
- import { withHeaders } from "../engine/requests.js";
15
+ import { fetchOk } from "../util/fetch.js";
16
16
  import { RAD } from "../util/geo.js";
17
17
  import { isNumbers, isRecord } from "../util/guards.js";
18
+ import { clamp } from "../util/math.js";
19
+ import { withHeaders } from "../util/requests.js";
18
20
  const isOrientation = (value) => isRecord(value) && isRecord(value.geometry) && isNumbers(value.geometry.coordinates) && isRecord(value.properties);
19
21
  const isCrs = (value) => isRecord(value) &&
20
22
  (value.properties === undefined ||
@@ -48,7 +50,7 @@ const rotZ = (t) => [Math.cos(t), -Math.sin(t), 0, Math.sin(t), Math.cos(t), 0,
48
50
  * `quaternionFromRollPitchHeading`: Ry(-roll) · Rx(-pitch) · Rz(-heading)), turned by the meridian convergence of the
49
51
  * projection (Lambert-93: sin(46.5°) · (3° - longitude))
50
52
  */
51
- export const panoramaRotation = (attitude, lon, lambert93) => {
53
+ const panoramaRotation = (attitude, lon, lambert93) => {
52
54
  const vehicle = times(times(rotY(-attitude.roll * RAD), rotX(-attitude.pitch * RAD)), rotZ(-attitude.heading * RAD));
53
55
  const convergence = lambert93 ? Math.sin(46.5 * RAD) * (3 - lon) * RAD : 0;
54
56
  return times(rotZ(convergence), vehicle);
@@ -96,6 +98,8 @@ export class Panoramas {
96
98
  /** The panorama shown, if any */
97
99
  current;
98
100
  shown = 0;
101
+ /** @internal What forgets it once it is removed (the map's sets of panoramas) */
102
+ whenRemoved = [];
99
103
  /** @internal */
100
104
  constructor(host, look, list, source) {
101
105
  this.host = host;
@@ -125,9 +129,7 @@ export class Panoramas {
125
129
  const { backgroundDistance, opacity } = this.look;
126
130
  this.host.setPanorama(pano.lonLat[0], pano.lonLat[1], pano.height, Float64Array.from(this.source.rotation(index)), Float64Array.from(this.source.cameras(index)), backgroundDistance, opacity);
127
131
  const images = Promise.all(this.source.images(index).map(async (src, k) => {
128
- const response = await fetch(src, withHeaders(src, { signal: controller.signal }));
129
- if (!response.ok)
130
- throw new Error(`isard: panorama image ${src}: ${response.status}`);
132
+ const response = await fetchOk(src, withHeaders(src, { signal: controller.signal }));
131
133
  const blob = await response.blob();
132
134
  if (controller.signal.aborted)
133
135
  return;
@@ -204,7 +206,7 @@ export class Panoramas {
204
206
  return nearest;
205
207
  const [east, north] = [(p.lonLat[0] - here.lonLat[0]) * cos, p.lonLat[1] - here.lonLat[1]];
206
208
  const d = Math.hypot(east, north);
207
- const off = Math.acos(Math.max(-1, Math.min(1, (east * Math.sin(look) + north * Math.cos(look)) / (d || 1))));
209
+ const off = Math.acos(clamp((east * Math.sin(look) + north * Math.cos(look)) / (d || 1), -1, 1));
208
210
  return off < 60 * RAD && d < nearest.distance ? { best: p, distance: d } : nearest;
209
211
  }, { distance: Number.POSITIVE_INFINITY }).best;
210
212
  }
@@ -231,6 +233,16 @@ export class Panoramas {
231
233
  this.hide();
232
234
  this.host.setFirstPerson(undefined);
233
235
  }
236
+ /** Removes the panoramas from the map: the walk ended (the eye back above the map), the panorama shown hidden */
237
+ remove() {
238
+ if (this.stopWalking)
239
+ this.exit();
240
+ else
241
+ this.hide();
242
+ this.whenRemoved.splice(0).forEach((forget) => {
243
+ forget();
244
+ });
245
+ }
234
246
  }
235
247
  /** Loads a set of panoramas: a vehicle's (their positions and attitudes, the calibration of their cameras), or 360°
236
248
  * photos */
@@ -255,9 +267,7 @@ export const loadPanoramas = async (host, options) => {
255
267
  });
256
268
  }
257
269
  const json = async (src, is) => {
258
- const response = await fetch(src, withHeaders(src));
259
- if (!response.ok)
260
- throw new Error(`isard: ${src}: ${response.status}`);
270
+ const response = await fetchOk(src, withHeaders(src));
261
271
  const value = await response.json();
262
272
  if (!is(value))
263
273
  throw new Error(`isard: ${src}: unexpected content`);
@@ -1 +1 @@
1
- {"version":3,"file":"panoramas.js","sourceRoot":"","sources":["../../src/layers/panoramas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Street-level panoramas projected onto the scene around the panorama shown: the oriented images of a vehicle's\n * cameras around each of its positions (Stereopolis, the iTowns immersive examples: their positions and attitudes as\n * GeoJSON points, Lambert-93 by default, altitudes NGF-IGN69 raised by the RAF20 geoid onto the IGN relief; the\n * calibration of the cameras as JSON, rotation and position in the panorama frame, intrinsics, MicMac's radial\n * distortion; the images from a URL template with `{cameraId}` and `{panoId}`), or 360° photos (`photos`: one\n * equirectangular image each, where it was taken and the way its middle faces: Panoramax's).\n *\n * ```ts\n * const panoramas = await map.addPanoramas({ url, orientationsUrl, calibrationUrl });\n * await panoramas.show(panoramas.nearest([2.3345, 48.8505]).index);\n * ```\n */\nimport { getCrs } from '../data/crs.ts';\nimport { withHeaders } from '../engine/requests.ts';\nimport type { FirstPersonView, LonLat } from '../types.ts';\nimport { RAD } from '../util/geo.ts';\nimport { isNumbers, isRecord } from '../util/guards.ts';\n\n/** What the panoramas of either kind take */\ninterface PanoramaLook {\n /** Radius of the sphere around the panorama its images are a backdrop on, metres (default 1000) */\n backgroundDistance?: number;\n /** 0-1 (default 1) */\n opacity?: number;\n}\n\n/** A 360° photo (an equirectangular image): where it was taken and the way its middle faces */\nexport interface PanoramaPhoto {\n /** Its image (JPEG, PNG), its middle the photo's `heading`, its top straight up */\n url: string;\n lonLat: LonLat;\n /** Degrees clockwise from north of its middle (0 by default) */\n heading?: number;\n /** Metres of its camera above the ground (2.5 by default) */\n height?: number;\n id?: number | string;\n}\n\n/** 360° photos as panoramas (`photos`, in the order of their walk) */\nexport interface PhotoPanoramaOptions extends PanoramaLook {\n photos: readonly PanoramaPhoto[];\n}\n\n/** A vehicle's calibrated cameras around each of its positions (Stereopolis) */\nexport interface CalibratedPanoramaOptions extends PanoramaLook {\n /** URL of an image: `{cameraId}` and `{panoId}` replaced by a camera's id and a panorama's */\n url: string;\n /** GeoJSON points: each panorama's position, and its `id`, `heading`, `pitch`, `roll` (degrees) in properties */\n orientationsUrl: string;\n /** JSON array of the cameras: `id`, `rotation` (row-major), `position`, `projection`, `size`, `distortion` */\n calibrationUrl: string;\n /** CRS of the positions (default the GeoJSON's `crs` member, else `EPSG:2154`) */\n crs?: string;\n /** Altitudes above the geoid (NGF-IGN69), raised by the RAF20 geoid onto the IGN relief (default true in\n * Lambert-93) */\n geoid?: boolean;\n}\n\nexport type PanoramaOptions = CalibratedPanoramaOptions | PhotoPanoramaOptions;\n\n/** A panorama: where it is and which way the vehicle faced */\nexport interface Panorama {\n index: number;\n id: number | string;\n lonLat: LonLat;\n /** Metres above the ellipsoid */\n height: number;\n /** Degrees clockwise from north */\n heading: number;\n}\n\n/** What the map gives the panoramas */\nexport interface PanoramaHost {\n setPanorama(\n lon: number,\n lat: number,\n height: number,\n rotation: Float64Array,\n cameras: Float64Array,\n radius: number,\n opacity: number,\n ): void;\n setPanoramaImage(index: number, image: ImageBitmap): void;\n clearPanorama(): void;\n geoidHeight(lon: number, lat: number): number;\n /** The street-level eye, and setting it (undefined: back to the camera turning around a point) */\n firstPerson(): Readonly<Required<FirstPersonView>> | undefined;\n setFirstPerson(view: FirstPersonView | undefined): void;\n elevationAt(lonLat: LonLat): number | undefined;\n /** Follows the clicks on the map (with the ground clicked), the keys typed on it and its wheel (taken from the\n * map's own); returns what stops */\n listen(\n click: (lonLat: LonLat | undefined) => void,\n key: (e: KeyboardEvent) => void,\n wheel: (e: WheelEvent) => void,\n ): () => void;\n}\n\ninterface Calibration {\n id: number | string;\n rotation: number[];\n position: number[];\n projection: number[];\n size: number[];\n distortion?: { pps: number[]; poly357: number[]; limit?: number };\n}\n\ninterface Orientations {\n crs?: { properties?: { name?: string } };\n features: { geometry: { coordinates: number[] }; properties: Record<string, unknown> }[];\n}\n\nconst isOrientation = (value: unknown): value is Orientations['features'][number] =>\n isRecord(value) && isRecord(value.geometry) && isNumbers(value.geometry.coordinates) && isRecord(value.properties);\n\nconst isCrs = (value: unknown): value is Orientations['crs'] =>\n isRecord(value) &&\n (value.properties === undefined ||\n (isRecord(value.properties) && (value.properties.name === undefined || typeof value.properties.name === 'string')));\n\nconst isOrientations = (value: unknown): value is Orientations =>\n isRecord(value) &&\n (value.crs === undefined || isCrs(value.crs)) &&\n Array.isArray(value.features) &&\n value.features.every(isOrientation);\n\nconst isCalibration = (value: unknown): value is Calibration =>\n isRecord(value) &&\n (typeof value.id === 'number' || typeof value.id === 'string') &&\n isNumbers(value.rotation) &&\n isNumbers(value.position) &&\n isNumbers(value.projection) &&\n isNumbers(value.size) &&\n (value.distortion === undefined ||\n (isRecord(value.distortion) &&\n isNumbers(value.distortion.pps) &&\n isNumbers(value.distortion.poly357) &&\n (value.distortion.limit === undefined || typeof value.distortion.limit === 'number')));\n\nconst isCalibrations = (value: unknown): value is Calibration[] => Array.isArray(value) && value.every(isCalibration);\n\ninterface Attitude {\n heading: number;\n pitch: number;\n roll: number;\n}\n\n/** 3 × 3 product, row-major */\nconst times = (a: number[], b: number[]): number[] =>\n Array.from({ length: 9 }, (_, i) => {\n const [r, c] = [Math.floor(i / 3), i % 3];\n\n return [0, 1, 2].reduce((sum, k) => sum + (a[r * 3 + k] ?? 0) * (b[k * 3 + c] ?? 0), 0);\n });\n\nconst rotX = (t: number) => [1, 0, 0, 0, Math.cos(t), -Math.sin(t), 0, Math.sin(t), Math.cos(t)];\nconst rotY = (t: number) => [Math.cos(t), 0, Math.sin(t), 0, 1, 0, -Math.sin(t), 0, Math.cos(t)];\nconst rotZ = (t: number) => [Math.cos(t), -Math.sin(t), 0, Math.sin(t), Math.cos(t), 0, 0, 0, 1];\n\n/**\n * The panorama frame to east, north, up (row-major): the vehicle's attitude in the CRS's grid (iTowns'\n * `quaternionFromRollPitchHeading`: Ry(-roll) · Rx(-pitch) · Rz(-heading)), turned by the meridian convergence of the\n * projection (Lambert-93: sin(46.5°) · (3° - longitude))\n */\nexport const panoramaRotation = (attitude: Attitude, lon: number, lambert93: boolean): number[] => {\n const vehicle = times(times(rotY(-attitude.roll * RAD), rotX(-attitude.pitch * RAD)), rotZ(-attitude.heading * RAD));\n const convergence = lambert93 ? Math.sin(46.5 * RAD) * (3 - lon) * RAD : 0;\n\n return times(rotZ(convergence), vehicle);\n};\n\n/** The 25 numbers of a camera for `setPanorama` */\nconst cameraNumbers = (c: Calibration): number[] => {\n const p = c.projection;\n const d = c.distortion;\n\n return [\n ...c.rotation.slice(0, 9),\n ...c.position.slice(0, 3),\n p[0] ?? 1,\n p[4] ?? 1,\n p[2] ?? 0,\n p[5] ?? 0,\n p[1] ?? 0,\n c.size[0] ?? 1,\n c.size[1] ?? 1,\n d?.pps[0] ?? 0,\n d?.pps[1] ?? 0,\n d?.poly357[0] ?? 0,\n d?.poly357[1] ?? 0,\n d?.poly357[2] ?? 0,\n d?.limit ?? 0,\n ];\n};\n\n/** What shows a panorama of a set (its index): its frame to east, north, up (row-major), its cameras' numbers\n * (`cameraNumbers`, 25 each), their images' URLs */\ninterface PanoramaSource {\n rotation(index: number): number[];\n cameras(index: number): number[];\n images(index: number): string[];\n}\n\n/** The numbers of a 360° photo's camera facing `heading` (its frame east, north, up): x right, y down, z ahead; no\n * focal (the engine's sign of an equirectangular image) */\nexport const photoCamera = (heading: number): number[] => {\n const h = heading * RAD;\n\n return [\n ...[Math.cos(h), -Math.sin(h), 0],\n ...[0, 0, -1],\n ...[Math.sin(h), Math.cos(h), 0],\n ...[0, 0, 0],\n ...[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],\n ];\n};\n\n/** The panoramas of a set, one shown at a time */\nexport class Panoramas {\n /** The panorama shown, if any */\n current: Panorama | undefined;\n private shown = 0;\n\n /** @internal */\n constructor(\n private readonly host: PanoramaHost,\n private readonly look: Required<PanoramaLook>,\n readonly list: readonly Panorama[],\n private readonly source: PanoramaSource,\n ) {}\n\n /** The panorama nearest to a position */\n nearest(lonLat: LonLat): Panorama | undefined {\n const cos = Math.cos(lonLat[1] * RAD);\n\n return this.list.reduce<{ best?: Panorama; distance: number }>(\n (nearest, p) => {\n const d = ((p.lonLat[0] - lonLat[0]) * cos) ** 2 + (p.lonLat[1] - lonLat[1]) ** 2;\n\n return d < nearest.distance ? { best: p, distance: d } : nearest;\n },\n { distance: Number.POSITIVE_INFINITY },\n ).best;\n }\n\n /** Shows a panorama (its index in `list`): projected as soon as its first image arrives, the others after */\n async show(index: number): Promise<void> {\n const pano = this.list[index];\n\n if (!pano) return;\n\n const shown = ++this.shown;\n // The images of the panorama shown before: no longer downloaded nor decoded\n const controller = new AbortController();\n\n this.loading?.abort();\n this.loading = controller;\n this.current = pano;\n\n const { backgroundDistance, opacity } = this.look;\n\n this.host.setPanorama(\n pano.lonLat[0],\n pano.lonLat[1],\n pano.height,\n Float64Array.from(this.source.rotation(index)),\n Float64Array.from(this.source.cameras(index)),\n backgroundDistance,\n opacity,\n );\n const images = Promise.all(\n this.source.images(index).map(async (src, k) => {\n const response = await fetch(src, withHeaders(src, { signal: controller.signal }));\n\n if (!response.ok) throw new Error(`isard: panorama image ${src}: ${response.status}`);\n\n const blob = await response.blob();\n\n if (controller.signal.aborted) return;\n\n const image = await createImageBitmap(blob, { premultiplyAlpha: 'none' });\n\n // Another panorama shown since: this image is not its\n if (shown === this.shown) this.host.setPanoramaImage(k, image);\n image.close();\n }),\n );\n\n // Another panorama shown, or this one hidden, meanwhile: not a failure\n await images.catch((error: unknown) => {\n if (!controller.signal.aborted) throw error;\n });\n }\n\n /** The downloads of the panorama shown, aborted by the next one shown or by `hide` */\n private loading: AbortController | undefined;\n\n /** Hides the panorama shown */\n hide(): void {\n this.shown++;\n this.loading?.abort();\n this.current = undefined;\n this.host.clearPanorama();\n }\n\n /** Stops the walk (`enter`) */\n private stopWalking: (() => void) | undefined;\n\n /**\n * Street-level walk from panorama to panorama (the iTowns immersive view): the eye on a panorama, the drag\n * turning it; a click goes to the panorama nearest to the clicked point, the wheel to the nearest one ahead (or\n * behind), Z and S (or Page Up and Page Down) to the next and the previous ones. Starts on the panorama `index`,\n * else the one nearest to `near`\n */\n async enter(start: { index?: number; near?: LonLat } = {}): Promise<void> {\n const first = start.index ?? (start.near && this.nearest(start.near)?.index) ?? 0;\n\n this.stopWalking?.();\n this.stopWalking = this.host.listen(\n (lonLat) => {\n const target = lonLat && this.nearest(lonLat);\n\n if (target && target !== this.current) this.go(target.index).catch(report);\n },\n (e) => {\n const step = { z: 1, Z: 1, PageUp: 1, s: -1, S: -1, PageDown: -1 }[e.key];\n\n if (!step || !this.current) return;\n e.preventDefault();\n this.go((this.current.index + step + this.list.length) % this.list.length).catch(report);\n },\n (e) => {\n // One step per notch, the next ones once it is shown\n if (this.moving || e.deltaY === 0) return;\n\n const target = this.ahead(e.deltaY < 0);\n\n if (target) {\n this.moving = true;\n this.go(target.index)\n .catch(report)\n .finally(() => {\n this.moving = false;\n });\n }\n },\n );\n await this.go(first, this.list[first]?.heading);\n }\n\n /** A step of the wheel under way */\n private moving = false;\n\n /** The nearest panorama ahead of the eye (within 60° of where it looks), or behind it */\n ahead(forward = true): Panorama | undefined {\n const eye = this.host.firstPerson();\n const here = this.current;\n\n if (!eye || !here) return undefined;\n\n const cos = Math.cos(here.lonLat[1] * RAD);\n const look = (eye.bearing + (forward ? 0 : 180)) * RAD;\n\n return this.list.reduce<{ best?: Panorama; distance: number }>(\n (nearest, p) => {\n if (p === here) return nearest;\n\n const [east, north] = [(p.lonLat[0] - here.lonLat[0]) * cos, p.lonLat[1] - here.lonLat[1]];\n const d = Math.hypot(east, north);\n const off = Math.acos(Math.max(-1, Math.min(1, (east * Math.sin(look) + north * Math.cos(look)) / (d || 1))));\n\n return off < 60 * RAD && d < nearest.distance ? { best: p, distance: d } : nearest;\n },\n { distance: Number.POSITIVE_INFINITY },\n ).best;\n }\n\n /** Goes to a panorama during the walk, the eye looking the same way (or `bearing`) */\n async go(index: number, bearing?: number): Promise<void> {\n const pano = this.list[index];\n\n if (!pano) return;\n\n const eye = this.host.firstPerson();\n // The eye at the panorama's cameras, above the ground there\n const ground = this.host.elevationAt(pano.lonLat);\n\n this.host.setFirstPerson({\n lonLat: pano.lonLat,\n height: ground === undefined ? 2.5 : Math.max(0.5, pano.height - ground),\n bearing: bearing ?? eye?.bearing ?? pano.heading,\n ...(eye ? { pitch: eye.pitch, fov: eye.fov } : {}),\n });\n await this.show(index);\n }\n\n /** Ends the walk: the panorama hidden, the camera turning around a point again, above where the eye stood */\n exit(): void {\n this.stopWalking?.();\n this.stopWalking = undefined;\n this.hide();\n this.host.setFirstPerson(undefined);\n }\n}\n\n/** Loads a set of panoramas: a vehicle's (their positions and attitudes, the calibration of their cameras), or 360°\n * photos */\nexport const loadPanoramas = async (host: PanoramaHost, options: PanoramaOptions): Promise<Panoramas> => {\n const look = { backgroundDistance: options.backgroundDistance ?? 1000, opacity: options.opacity ?? 1 };\n\n if ('photos' in options) {\n const photos = options.photos;\n const list = photos.map((photo, index) => ({\n index,\n id: photo.id ?? index,\n lonLat: photo.lonLat,\n // Above the ground there as the relief has it (the ellipsoid without one)\n height: (host.elevationAt(photo.lonLat) ?? 0) + (photo.height ?? 2.5),\n heading: photo.heading ?? 0,\n }));\n // Their frame east, north, up: the camera turned to the photo's heading\n const identity = [1, 0, 0, 0, 1, 0, 0, 0, 1];\n\n return new Panoramas(host, look, list, {\n rotation: () => identity,\n cameras: (i) => photoCamera(photos[i]?.heading ?? 0),\n images: (i) => [photos[i]?.url ?? ''],\n });\n }\n\n const json = async <T>(src: string, is: (value: unknown) => value is T): Promise<T> => {\n const response = await fetch(src, withHeaders(src));\n\n if (!response.ok) throw new Error(`isard: ${src}: ${response.status}`);\n\n const value: unknown = await response.json();\n\n if (!is(value)) throw new Error(`isard: ${src}: unexpected content`);\n\n return value;\n };\n const [orientations, cameras] = await Promise.all([\n json(options.orientationsUrl, isOrientations),\n json(options.calibrationUrl, isCalibrations),\n ]);\n const crsName = options.crs ?? orientations.crs?.properties?.name ?? 'EPSG:2154';\n const lambert93 = /2154/.test(crsName);\n const crs = getCrs(crsName);\n const geoid = options.geoid ?? lambert93;\n const list: Panorama[] = [];\n const attitudes: Attitude[] = [];\n\n orientations.features.forEach((feature) => {\n const [x = 0, y = 0, z = 0] = feature.geometry.coordinates;\n const [lon = 0, lat = 0] = crs.inverse([x, y]);\n const p = feature.properties;\n const number = (key: string) => {\n const value = p[key];\n\n return typeof value === 'number' ? value : 0;\n };\n\n attitudes.push({ heading: number('heading'), pitch: number('pitch'), roll: number('roll') });\n list.push({\n index: list.length,\n id: typeof p.id === 'number' || typeof p.id === 'string' ? p.id : list.length,\n lonLat: [lon, lat],\n height: z + (geoid ? host.geoidHeight(lon, lat) : 0),\n heading: number('heading'),\n });\n });\n\n const numbers = cameras.flatMap(cameraNumbers);\n\n return new Panoramas(host, look, list, {\n rotation: (i) =>\n panoramaRotation(attitudes[i] ?? { heading: 0, pitch: 0, roll: 0 }, list[i]?.lonLat[0] ?? 0, lambert93),\n cameras: () => numbers,\n images: (i) =>\n cameras.map((camera) =>\n options.url.replaceAll('{cameraId}', String(camera.id)).replaceAll('{panoId}', String(list[i]?.id ?? i)),\n ),\n });\n};\n\n/** A step of the walk that failed (an image not found): told, the walk going on */\nconst report = (error: unknown): void => {\n console.warn('isard: panorama', error);\n};\n"]}
1
+ {"version":3,"file":"panoramas.js","sourceRoot":"","sources":["../../src/layers/panoramas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Street-level panoramas projected onto the scene around the panorama shown: the oriented images of a vehicle's\n * cameras around each of its positions (Stereopolis, the iTowns immersive examples: their positions and attitudes as\n * GeoJSON points, Lambert-93 by default, altitudes NGF-IGN69 raised by the RAF20 geoid onto the IGN relief; the\n * calibration of the cameras as JSON, rotation and position in the panorama frame, intrinsics, MicMac's radial\n * distortion; the images from a URL template with `{cameraId}` and `{panoId}`), or 360° photos (`photos`: one\n * equirectangular image each, where it was taken and the way its middle faces: Panoramax's).\n *\n * ```ts\n * const panoramas = await map.addPanoramas({ url, orientationsUrl, calibrationUrl });\n * await panoramas.show(panoramas.nearest([2.3345, 48.8505]).index);\n * ```\n */\nimport { getCrs } from '../data/crs.ts';\nimport type { FirstPersonView, LonLat } from '../types.ts';\nimport { fetchOk } from '../util/fetch.ts';\nimport { RAD } from '../util/geo.ts';\nimport { isNumbers, isRecord } from '../util/guards.ts';\nimport { clamp } from '../util/math.ts';\nimport { withHeaders } from '../util/requests.ts';\n\n/** What the panoramas of either kind take */\ninterface PanoramaLook {\n /** Radius of the sphere around the panorama its images are a backdrop on, metres (default 1000) */\n backgroundDistance?: number;\n /** 0-1 (default 1) */\n opacity?: number;\n}\n\n/** A 360° photo (an equirectangular image): where it was taken and the way its middle faces */\nexport interface PanoramaPhoto {\n /** Its image (JPEG, PNG), its middle the photo's `heading`, its top straight up */\n url: string;\n lonLat: LonLat;\n /** Degrees clockwise from north of its middle (0 by default) */\n heading?: number;\n /** Metres of its camera above the ground (2.5 by default) */\n height?: number;\n id?: number | string;\n}\n\n/** 360° photos as panoramas (`photos`, in the order of their walk) */\nexport interface PhotoPanoramaOptions extends PanoramaLook {\n photos: readonly PanoramaPhoto[];\n}\n\n/** A vehicle's calibrated cameras around each of its positions (Stereopolis) */\nexport interface CalibratedPanoramaOptions extends PanoramaLook {\n /** URL of an image: `{cameraId}` and `{panoId}` replaced by a camera's id and a panorama's */\n url: string;\n /** GeoJSON points: each panorama's position, and its `id`, `heading`, `pitch`, `roll` (degrees) in properties */\n orientationsUrl: string;\n /** JSON array of the cameras: `id`, `rotation` (row-major), `position`, `projection`, `size`, `distortion` */\n calibrationUrl: string;\n /** CRS of the positions (default the GeoJSON's `crs` member, else `EPSG:2154`) */\n crs?: string;\n /** Altitudes above the geoid (NGF-IGN69), raised by the RAF20 geoid onto the IGN relief (default true in\n * Lambert-93) */\n geoid?: boolean;\n}\n\nexport type PanoramaOptions = CalibratedPanoramaOptions | PhotoPanoramaOptions;\n\n/** A panorama: where it is and which way the vehicle faced */\nexport interface Panorama {\n index: number;\n id: number | string;\n lonLat: LonLat;\n /** Metres above the ellipsoid */\n height: number;\n /** Degrees clockwise from north */\n heading: number;\n}\n\n/** What the map gives the panoramas */\nexport interface PanoramaHost {\n setPanorama(\n lon: number,\n lat: number,\n height: number,\n rotation: Float64Array,\n cameras: Float64Array,\n radius: number,\n opacity: number,\n ): void;\n setPanoramaImage(index: number, image: ImageBitmap): void;\n clearPanorama(): void;\n geoidHeight(lon: number, lat: number): number;\n /** The street-level eye, and setting it (undefined: back to the camera turning around a point) */\n firstPerson(): Readonly<Required<FirstPersonView>> | undefined;\n setFirstPerson(view: FirstPersonView | undefined): void;\n elevationAt(lonLat: LonLat): number | undefined;\n /** Follows the clicks on the map (with the ground clicked), the keys typed on it and its wheel (taken from the\n * map's own); returns what stops */\n listen(\n click: (lonLat: LonLat | undefined) => void,\n key: (e: KeyboardEvent) => void,\n wheel: (e: WheelEvent) => void,\n ): () => void;\n}\n\ninterface Calibration {\n id: number | string;\n rotation: number[];\n position: number[];\n projection: number[];\n size: number[];\n distortion?: { pps: number[]; poly357: number[]; limit?: number };\n}\n\ninterface Orientations {\n crs?: { properties?: { name?: string } };\n features: { geometry: { coordinates: number[] }; properties: Record<string, unknown> }[];\n}\n\nconst isOrientation = (value: unknown): value is Orientations['features'][number] =>\n isRecord(value) && isRecord(value.geometry) && isNumbers(value.geometry.coordinates) && isRecord(value.properties);\n\nconst isCrs = (value: unknown): value is Orientations['crs'] =>\n isRecord(value) &&\n (value.properties === undefined ||\n (isRecord(value.properties) && (value.properties.name === undefined || typeof value.properties.name === 'string')));\n\nconst isOrientations = (value: unknown): value is Orientations =>\n isRecord(value) &&\n (value.crs === undefined || isCrs(value.crs)) &&\n Array.isArray(value.features) &&\n value.features.every(isOrientation);\n\nconst isCalibration = (value: unknown): value is Calibration =>\n isRecord(value) &&\n (typeof value.id === 'number' || typeof value.id === 'string') &&\n isNumbers(value.rotation) &&\n isNumbers(value.position) &&\n isNumbers(value.projection) &&\n isNumbers(value.size) &&\n (value.distortion === undefined ||\n (isRecord(value.distortion) &&\n isNumbers(value.distortion.pps) &&\n isNumbers(value.distortion.poly357) &&\n (value.distortion.limit === undefined || typeof value.distortion.limit === 'number')));\n\nconst isCalibrations = (value: unknown): value is Calibration[] => Array.isArray(value) && value.every(isCalibration);\n\ninterface Attitude {\n heading: number;\n pitch: number;\n roll: number;\n}\n\n/** 3 × 3 product, row-major */\nconst times = (a: number[], b: number[]): number[] =>\n Array.from({ length: 9 }, (_, i) => {\n const [r, c] = [Math.floor(i / 3), i % 3];\n\n return [0, 1, 2].reduce((sum, k) => sum + (a[r * 3 + k] ?? 0) * (b[k * 3 + c] ?? 0), 0);\n });\n\nconst rotX = (t: number) => [1, 0, 0, 0, Math.cos(t), -Math.sin(t), 0, Math.sin(t), Math.cos(t)];\nconst rotY = (t: number) => [Math.cos(t), 0, Math.sin(t), 0, 1, 0, -Math.sin(t), 0, Math.cos(t)];\nconst rotZ = (t: number) => [Math.cos(t), -Math.sin(t), 0, Math.sin(t), Math.cos(t), 0, 0, 0, 1];\n\n/**\n * The panorama frame to east, north, up (row-major): the vehicle's attitude in the CRS's grid (iTowns'\n * `quaternionFromRollPitchHeading`: Ry(-roll) · Rx(-pitch) · Rz(-heading)), turned by the meridian convergence of the\n * projection (Lambert-93: sin(46.5°) · (3° - longitude))\n */\nconst panoramaRotation = (attitude: Attitude, lon: number, lambert93: boolean): number[] => {\n const vehicle = times(times(rotY(-attitude.roll * RAD), rotX(-attitude.pitch * RAD)), rotZ(-attitude.heading * RAD));\n const convergence = lambert93 ? Math.sin(46.5 * RAD) * (3 - lon) * RAD : 0;\n\n return times(rotZ(convergence), vehicle);\n};\n\n/** The 25 numbers of a camera for `setPanorama` */\nconst cameraNumbers = (c: Calibration): number[] => {\n const p = c.projection;\n const d = c.distortion;\n\n return [\n ...c.rotation.slice(0, 9),\n ...c.position.slice(0, 3),\n p[0] ?? 1,\n p[4] ?? 1,\n p[2] ?? 0,\n p[5] ?? 0,\n p[1] ?? 0,\n c.size[0] ?? 1,\n c.size[1] ?? 1,\n d?.pps[0] ?? 0,\n d?.pps[1] ?? 0,\n d?.poly357[0] ?? 0,\n d?.poly357[1] ?? 0,\n d?.poly357[2] ?? 0,\n d?.limit ?? 0,\n ];\n};\n\n/** What shows a panorama of a set (its index): its frame to east, north, up (row-major), its cameras' numbers\n * (`cameraNumbers`, 25 each), their images' URLs */\ninterface PanoramaSource {\n rotation(index: number): number[];\n cameras(index: number): number[];\n images(index: number): string[];\n}\n\n/** The numbers of a 360° photo's camera facing `heading` (its frame east, north, up): x right, y down, z ahead; no\n * focal (the engine's sign of an equirectangular image) */\nexport const photoCamera = (heading: number): number[] => {\n const h = heading * RAD;\n\n return [\n ...[Math.cos(h), -Math.sin(h), 0],\n ...[0, 0, -1],\n ...[Math.sin(h), Math.cos(h), 0],\n ...[0, 0, 0],\n ...[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],\n ];\n};\n\n/** The panoramas of a set, one shown at a time */\nexport class Panoramas {\n /** The panorama shown, if any */\n current: Panorama | undefined;\n private shown = 0;\n /** @internal What forgets it once it is removed (the map's sets of panoramas) */\n readonly whenRemoved: (() => void)[] = [];\n\n /** @internal */\n constructor(\n private readonly host: PanoramaHost,\n private readonly look: Required<PanoramaLook>,\n readonly list: readonly Panorama[],\n private readonly source: PanoramaSource,\n ) {}\n\n /** The panorama nearest to a position */\n nearest(lonLat: LonLat): Panorama | undefined {\n const cos = Math.cos(lonLat[1] * RAD);\n\n return this.list.reduce<{ best?: Panorama; distance: number }>(\n (nearest, p) => {\n const d = ((p.lonLat[0] - lonLat[0]) * cos) ** 2 + (p.lonLat[1] - lonLat[1]) ** 2;\n\n return d < nearest.distance ? { best: p, distance: d } : nearest;\n },\n { distance: Number.POSITIVE_INFINITY },\n ).best;\n }\n\n /** Shows a panorama (its index in `list`): projected as soon as its first image arrives, the others after */\n async show(index: number): Promise<void> {\n const pano = this.list[index];\n\n if (!pano) return;\n\n const shown = ++this.shown;\n // The images of the panorama shown before: no longer downloaded nor decoded\n const controller = new AbortController();\n\n this.loading?.abort();\n this.loading = controller;\n this.current = pano;\n\n const { backgroundDistance, opacity } = this.look;\n\n this.host.setPanorama(\n pano.lonLat[0],\n pano.lonLat[1],\n pano.height,\n Float64Array.from(this.source.rotation(index)),\n Float64Array.from(this.source.cameras(index)),\n backgroundDistance,\n opacity,\n );\n const images = Promise.all(\n this.source.images(index).map(async (src, k) => {\n const response = await fetchOk(src, withHeaders(src, { signal: controller.signal }));\n\n const blob = await response.blob();\n\n if (controller.signal.aborted) return;\n\n const image = await createImageBitmap(blob, { premultiplyAlpha: 'none' });\n\n // Another panorama shown since: this image is not its\n if (shown === this.shown) this.host.setPanoramaImage(k, image);\n image.close();\n }),\n );\n\n // Another panorama shown, or this one hidden, meanwhile: not a failure\n await images.catch((error: unknown) => {\n if (!controller.signal.aborted) throw error;\n });\n }\n\n /** The downloads of the panorama shown, aborted by the next one shown or by `hide` */\n private loading: AbortController | undefined;\n\n /** Hides the panorama shown */\n hide(): void {\n this.shown++;\n this.loading?.abort();\n this.current = undefined;\n this.host.clearPanorama();\n }\n\n /** Stops the walk (`enter`) */\n private stopWalking: (() => void) | undefined;\n\n /**\n * Street-level walk from panorama to panorama (the iTowns immersive view): the eye on a panorama, the drag\n * turning it; a click goes to the panorama nearest to the clicked point, the wheel to the nearest one ahead (or\n * behind), Z and S (or Page Up and Page Down) to the next and the previous ones. Starts on the panorama `index`,\n * else the one nearest to `near`\n */\n async enter(start: { index?: number; near?: LonLat } = {}): Promise<void> {\n const first = start.index ?? (start.near && this.nearest(start.near)?.index) ?? 0;\n\n this.stopWalking?.();\n this.stopWalking = this.host.listen(\n (lonLat) => {\n const target = lonLat && this.nearest(lonLat);\n\n if (target && target !== this.current) this.go(target.index).catch(report);\n },\n (e) => {\n const step = { z: 1, Z: 1, PageUp: 1, s: -1, S: -1, PageDown: -1 }[e.key];\n\n if (!step || !this.current) return;\n e.preventDefault();\n this.go((this.current.index + step + this.list.length) % this.list.length).catch(report);\n },\n (e) => {\n // One step per notch, the next ones once it is shown\n if (this.moving || e.deltaY === 0) return;\n\n const target = this.ahead(e.deltaY < 0);\n\n if (target) {\n this.moving = true;\n this.go(target.index)\n .catch(report)\n .finally(() => {\n this.moving = false;\n });\n }\n },\n );\n await this.go(first, this.list[first]?.heading);\n }\n\n /** A step of the wheel under way */\n private moving = false;\n\n /** The nearest panorama ahead of the eye (within 60° of where it looks), or behind it */\n ahead(forward = true): Panorama | undefined {\n const eye = this.host.firstPerson();\n const here = this.current;\n\n if (!eye || !here) return undefined;\n\n const cos = Math.cos(here.lonLat[1] * RAD);\n const look = (eye.bearing + (forward ? 0 : 180)) * RAD;\n\n return this.list.reduce<{ best?: Panorama; distance: number }>(\n (nearest, p) => {\n if (p === here) return nearest;\n\n const [east, north] = [(p.lonLat[0] - here.lonLat[0]) * cos, p.lonLat[1] - here.lonLat[1]];\n const d = Math.hypot(east, north);\n const off = Math.acos(clamp((east * Math.sin(look) + north * Math.cos(look)) / (d || 1), -1, 1));\n\n return off < 60 * RAD && d < nearest.distance ? { best: p, distance: d } : nearest;\n },\n { distance: Number.POSITIVE_INFINITY },\n ).best;\n }\n\n /** Goes to a panorama during the walk, the eye looking the same way (or `bearing`) */\n async go(index: number, bearing?: number): Promise<void> {\n const pano = this.list[index];\n\n if (!pano) return;\n\n const eye = this.host.firstPerson();\n // The eye at the panorama's cameras, above the ground there\n const ground = this.host.elevationAt(pano.lonLat);\n\n this.host.setFirstPerson({\n lonLat: pano.lonLat,\n height: ground === undefined ? 2.5 : Math.max(0.5, pano.height - ground),\n bearing: bearing ?? eye?.bearing ?? pano.heading,\n ...(eye ? { pitch: eye.pitch, fov: eye.fov } : {}),\n });\n await this.show(index);\n }\n\n /** Ends the walk: the panorama hidden, the camera turning around a point again, above where the eye stood */\n exit(): void {\n this.stopWalking?.();\n this.stopWalking = undefined;\n this.hide();\n this.host.setFirstPerson(undefined);\n }\n\n /** Removes the panoramas from the map: the walk ended (the eye back above the map), the panorama shown hidden */\n remove(): void {\n if (this.stopWalking) this.exit();\n else this.hide();\n this.whenRemoved.splice(0).forEach((forget) => {\n forget();\n });\n }\n}\n\n/** Loads a set of panoramas: a vehicle's (their positions and attitudes, the calibration of their cameras), or 360°\n * photos */\nexport const loadPanoramas = async (host: PanoramaHost, options: PanoramaOptions): Promise<Panoramas> => {\n const look = { backgroundDistance: options.backgroundDistance ?? 1000, opacity: options.opacity ?? 1 };\n\n if ('photos' in options) {\n const photos = options.photos;\n const list = photos.map((photo, index) => ({\n index,\n id: photo.id ?? index,\n lonLat: photo.lonLat,\n // Above the ground there as the relief has it (the ellipsoid without one)\n height: (host.elevationAt(photo.lonLat) ?? 0) + (photo.height ?? 2.5),\n heading: photo.heading ?? 0,\n }));\n // Their frame east, north, up: the camera turned to the photo's heading\n const identity = [1, 0, 0, 0, 1, 0, 0, 0, 1];\n\n return new Panoramas(host, look, list, {\n rotation: () => identity,\n cameras: (i) => photoCamera(photos[i]?.heading ?? 0),\n images: (i) => [photos[i]?.url ?? ''],\n });\n }\n\n const json = async <T>(src: string, is: (value: unknown) => value is T): Promise<T> => {\n const response = await fetchOk(src, withHeaders(src));\n\n const value: unknown = await response.json();\n\n if (!is(value)) throw new Error(`isard: ${src}: unexpected content`);\n\n return value;\n };\n const [orientations, cameras] = await Promise.all([\n json(options.orientationsUrl, isOrientations),\n json(options.calibrationUrl, isCalibrations),\n ]);\n const crsName = options.crs ?? orientations.crs?.properties?.name ?? 'EPSG:2154';\n const lambert93 = /2154/.test(crsName);\n const crs = getCrs(crsName);\n const geoid = options.geoid ?? lambert93;\n const list: Panorama[] = [];\n const attitudes: Attitude[] = [];\n\n orientations.features.forEach((feature) => {\n const [x = 0, y = 0, z = 0] = feature.geometry.coordinates;\n const [lon = 0, lat = 0] = crs.inverse([x, y]);\n const p = feature.properties;\n const number = (key: string) => {\n const value = p[key];\n\n return typeof value === 'number' ? value : 0;\n };\n\n attitudes.push({ heading: number('heading'), pitch: number('pitch'), roll: number('roll') });\n list.push({\n index: list.length,\n id: typeof p.id === 'number' || typeof p.id === 'string' ? p.id : list.length,\n lonLat: [lon, lat],\n height: z + (geoid ? host.geoidHeight(lon, lat) : 0),\n heading: number('heading'),\n });\n });\n\n const numbers = cameras.flatMap(cameraNumbers);\n\n return new Panoramas(host, look, list, {\n rotation: (i) =>\n panoramaRotation(attitudes[i] ?? { heading: 0, pitch: 0, roll: 0 }, list[i]?.lonLat[0] ?? 0, lambert93),\n cameras: () => numbers,\n images: (i) =>\n cameras.map((camera) =>\n options.url.replaceAll('{cameraId}', String(camera.id)).replaceAll('{panoId}', String(list[i]?.id ?? i)),\n ),\n });\n};\n\n/** A step of the walk that failed (an image not found): told, the walk going on */\nconst report = (error: unknown): void => {\n console.warn('isard: panorama', error);\n};\n"]}
@@ -3,10 +3,10 @@
3
3
  * the 3D map: a flat photo on a frame across its field of view, a 360° photo (equirectangular) on a band curved round
4
4
  * its camera, each pixel where the camera saw it. Seen from where it was taken, it lies over the buildings it shows.
5
5
  */
6
- import type { LonLat } from '../types.ts';
7
- import type { Layer, ModelLayer, ModelOptions } from './layers.ts';
6
+ import type { LonLat, Placement } from '../types.ts';
7
+ import type { ModelLayer, ModelOptions } from './models.ts';
8
8
  /** The options of `GeoMap.addPhoto` */
9
- export interface PhotoOptions {
9
+ export interface PhotoOptions extends Placement {
10
10
  /** The image (JPEG or PNG); or its bytes (`data`) */
11
11
  url?: string;
12
12
  data?: ArrayBuffer | ArrayBufferView<ArrayBuffer>;
@@ -24,7 +24,6 @@ export interface PhotoOptions {
24
24
  height?: number;
25
25
  /** Metres from its camera to the photo drawn (15 by default) */
26
26
  distance?: number;
27
- before?: Layer;
28
27
  }
29
28
  /** A photo's surface: positions (glTF: x left, y up, z ahead, metres from its foot), image coordinates, triangles */
30
29
  export interface PhotoMesh {
@@ -43,6 +42,4 @@ export declare const imageSize: (bytes: Uint8Array) => [width: number, height: n
43
42
  /** A photo as a glTF binary: its surface (`photoMesh`) textured by its image, unlit, both sides drawn */
44
43
  export declare const photoModel: (image: Uint8Array, options?: Omit<PhotoOptions, "lonLat">) => Uint8Array<ArrayBuffer>;
45
44
  /** The photo's layer (`addModels`: the map's), its image read */
46
- export declare const addPhoto: (addModels: (options: ModelOptions & {
47
- before?: Layer;
48
- }) => ModelLayer, options: PhotoOptions) => Promise<ModelLayer>;
45
+ export declare const addPhoto: (addModels: (options: ModelOptions) => ModelLayer, options: PhotoOptions) => Promise<ModelLayer>;