isard 1.1.0 → 1.2.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 (216) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/basemap/basemaps.d.ts +1 -1
  3. package/dist/basemap/basemaps.js +2 -2
  4. package/dist/basemap/basemaps.js.map +1 -1
  5. package/dist/basemap/grid.d.ts +5 -5
  6. package/dist/basemap/grid.js +59 -65
  7. package/dist/basemap/grid.js.map +1 -1
  8. package/dist/basemap/mvt.d.ts +1 -1
  9. package/dist/basemap/mvt.js +6 -6
  10. package/dist/basemap/mvt.js.map +1 -1
  11. package/dist/basemap/pmtiles.d.ts +10 -10
  12. package/dist/basemap/pmtiles.js +39 -31
  13. package/dist/basemap/pmtiles.js.map +1 -1
  14. package/dist/basemap/resample.d.ts +2 -2
  15. package/dist/basemap/resample.js +16 -14
  16. package/dist/basemap/resample.js.map +1 -1
  17. package/dist/basemap/terrain.d.ts +3 -3
  18. package/dist/basemap/terrain.js +6 -6
  19. package/dist/basemap/terrain.js.map +1 -1
  20. package/dist/basemap/vectorstyle.d.ts +12 -10
  21. package/dist/basemap/vectorstyle.js +128 -110
  22. package/dist/basemap/vectorstyle.js.map +1 -1
  23. package/dist/basemap/vectortiles.d.ts +11 -11
  24. package/dist/basemap/vectortiles.js +141 -103
  25. package/dist/basemap/vectortiles.js.map +1 -1
  26. package/dist/basemap/wmts.d.ts +3 -3
  27. package/dist/basemap/wmts.js +16 -11
  28. package/dist/basemap/wmts.js.map +1 -1
  29. package/dist/basemap.worker.js +2 -2
  30. package/dist/basemap.worker.js.map +14 -13
  31. package/dist/bind/layers.d.ts +13 -4
  32. package/dist/bind/layers.js +64 -40
  33. package/dist/bind/layers.js.map +1 -1
  34. package/dist/data/crs.d.ts +10 -10
  35. package/dist/data/crs.js +38 -34
  36. package/dist/data/crs.js.map +1 -1
  37. package/dist/data/gpx.d.ts +1 -1
  38. package/dist/data/gpx.js +20 -20
  39. package/dist/data/gpx.js.map +1 -1
  40. package/dist/data/kml.d.ts +1 -1
  41. package/dist/data/kml.js +42 -39
  42. package/dist/data/kml.js.map +1 -1
  43. package/dist/data/topojson.d.ts +1 -1
  44. package/dist/data/topojson.js +15 -10
  45. package/dist/data/topojson.js.map +1 -1
  46. package/dist/data/xml.d.ts +5 -5
  47. package/dist/data/xml.js +19 -18
  48. package/dist/data/xml.js.map +1 -1
  49. package/dist/decoder.worker.js +4 -4
  50. package/dist/decoder.worker.js.map +6 -6
  51. package/dist/engine/decoders.d.ts +2 -2
  52. package/dist/engine/decoders.js +28 -25
  53. package/dist/engine/decoders.js.map +1 -1
  54. package/dist/engine/loader.js +13 -14
  55. package/dist/engine/loader.js.map +1 -1
  56. package/dist/engine/requests.d.ts +1 -1
  57. package/dist/engine/requests.js +19 -16
  58. package/dist/engine/requests.js.map +1 -1
  59. package/dist/engine-loader.d.ts +8 -8
  60. package/dist/engine-loader.js +27 -27
  61. package/dist/engine-loader.js.map +1 -1
  62. package/dist/geoplateforme.d.ts +10 -10
  63. package/dist/geoplateforme.js +22 -20
  64. package/dist/geoplateforme.js.map +1 -1
  65. package/dist/index.d.ts +1 -0
  66. package/dist/index.js.map +1 -1
  67. package/dist/isard_bg.wasm +0 -0
  68. package/dist/isard_core_bg.wasm +0 -0
  69. package/dist/isard_points_bg.wasm +0 -0
  70. package/dist/layers/extrusions.d.ts +1 -1
  71. package/dist/layers/extrusions.js +10 -5
  72. package/dist/layers/extrusions.js.map +1 -1
  73. package/dist/layers/features.d.ts +10 -10
  74. package/dist/layers/features.js +41 -42
  75. package/dist/layers/features.js.map +1 -1
  76. package/dist/layers/glyphs.d.ts +3 -3
  77. package/dist/layers/glyphs.js +34 -40
  78. package/dist/layers/glyphs.js.map +1 -1
  79. package/dist/layers/icons.d.ts +8 -8
  80. package/dist/layers/icons.js +76 -68
  81. package/dist/layers/icons.js.map +1 -1
  82. package/dist/layers/layers.d.ts +1 -1
  83. package/dist/layers/layers.js +33 -29
  84. package/dist/layers/layers.js.map +1 -1
  85. package/dist/layers/panoramas.d.ts +2 -2
  86. package/dist/layers/panoramas.js +52 -41
  87. package/dist/layers/panoramas.js.map +1 -1
  88. package/dist/layers/pointclouds.d.ts +3 -3
  89. package/dist/layers/pointclouds.js +25 -33
  90. package/dist/layers/pointclouds.js.map +1 -1
  91. package/dist/layers/symbols.d.ts +1 -1
  92. package/dist/layers/symbols.js +68 -71
  93. package/dist/layers/symbols.js.map +1 -1
  94. package/dist/map/basemap-layers.d.ts +26 -0
  95. package/dist/map/basemap-layers.js +61 -0
  96. package/dist/map/basemap-layers.js.map +1 -0
  97. package/dist/map/canvas.d.ts +17 -0
  98. package/dist/map/canvas.js +56 -0
  99. package/dist/map/canvas.js.map +1 -0
  100. package/dist/map/checks.d.ts +11 -0
  101. package/dist/map/checks.js +39 -0
  102. package/dist/map/checks.js.map +1 -0
  103. package/dist/map/credits.d.ts +17 -0
  104. package/dist/map/credits.js +34 -0
  105. package/dist/map/credits.js.map +1 -0
  106. package/dist/map/engine-settings.d.ts +15 -0
  107. package/dist/map/engine-settings.js +45 -0
  108. package/dist/map/engine-settings.js.map +1 -0
  109. package/dist/map/engines.d.ts +41 -0
  110. package/dist/map/engines.js +77 -0
  111. package/dist/map/engines.js.map +1 -0
  112. package/dist/map/events.d.ts +14 -0
  113. package/dist/map/events.js +46 -0
  114. package/dist/map/events.js.map +1 -0
  115. package/dist/map/frame-loop.d.ts +61 -0
  116. package/dist/map/frame-loop.js +139 -0
  117. package/dist/map/frame-loop.js.map +1 -0
  118. package/dist/map/hover-pick.d.ts +30 -0
  119. package/dist/map/hover-pick.js +56 -0
  120. package/dist/map/hover-pick.js.map +1 -0
  121. package/dist/map/layer-spec.d.ts +42 -0
  122. package/dist/map/layer-spec.js +34 -0
  123. package/dist/map/layer-spec.js.map +1 -0
  124. package/dist/map/layer-stack.d.ts +36 -0
  125. package/dist/map/layer-stack.js +101 -0
  126. package/dist/map/layer-stack.js.map +1 -0
  127. package/dist/map/overlay-host.d.ts +36 -0
  128. package/dist/map/overlay-host.js +101 -0
  129. package/dist/map/overlay-host.js.map +1 -0
  130. package/dist/map/panorama-host.d.ts +5 -0
  131. package/dist/map/panorama-host.js +32 -0
  132. package/dist/map/panorama-host.js.map +1 -0
  133. package/dist/map/raster-source.d.ts +11 -0
  134. package/dist/map/raster-source.js +26 -0
  135. package/dist/map/raster-source.js.map +1 -0
  136. package/dist/map/symbol-atlases.d.ts +26 -0
  137. package/dist/map/symbol-atlases.js +59 -0
  138. package/dist/map/symbol-atlases.js.map +1 -0
  139. package/dist/map/viewshed.d.ts +5 -0
  140. package/dist/map/viewshed.js +28 -0
  141. package/dist/map/viewshed.js.map +1 -0
  142. package/dist/map/workers.d.ts +46 -0
  143. package/dist/map/workers.js +73 -0
  144. package/dist/map/workers.js.map +1 -0
  145. package/dist/map.d.ts +33 -120
  146. package/dist/map.js +164 -689
  147. package/dist/map.js.map +1 -1
  148. package/dist/react/Control.d.ts +11 -0
  149. package/dist/react/Control.js +18 -0
  150. package/dist/react/Control.js.map +1 -0
  151. package/dist/react/CustomLayer.d.ts +11 -0
  152. package/dist/react/CustomLayer.js +30 -0
  153. package/dist/react/CustomLayer.js.map +1 -0
  154. package/dist/react/IsardMap.d.ts +43 -0
  155. package/dist/react/IsardMap.js +146 -0
  156. package/dist/react/IsardMap.js.map +1 -0
  157. package/dist/react/Layer.d.ts +42 -0
  158. package/dist/react/Layer.js +74 -0
  159. package/dist/react/Layer.js.map +1 -0
  160. package/dist/react/Marker.d.ts +24 -0
  161. package/dist/react/Marker.js +53 -0
  162. package/dist/react/Marker.js.map +1 -0
  163. package/dist/react/Panel.d.ts +11 -0
  164. package/dist/react/Panel.js +37 -0
  165. package/dist/react/Panel.js.map +1 -0
  166. package/dist/react/Popup.d.ts +18 -0
  167. package/dist/react/Popup.js +60 -0
  168. package/dist/react/Popup.js.map +1 -0
  169. package/dist/react/Swipe.d.ts +9 -0
  170. package/dist/react/Swipe.js +41 -0
  171. package/dist/react/Swipe.js.map +1 -0
  172. package/dist/react/Viewshed.d.ts +5 -0
  173. package/dist/react/Viewshed.js +28 -0
  174. package/dist/react/Viewshed.js.map +1 -0
  175. package/dist/react/context.d.ts +32 -0
  176. package/dist/react/context.js +20 -0
  177. package/dist/react/context.js.map +1 -0
  178. package/dist/react/index.d.ts +15 -108
  179. package/dist/react/index.js +10 -397
  180. package/dist/react/index.js.map +1 -1
  181. package/dist/settings.d.ts +5 -9
  182. package/dist/settings.js +17 -15
  183. package/dist/settings.js.map +1 -1
  184. package/dist/types.d.ts +3 -3
  185. package/dist/types.js.map +1 -1
  186. package/dist/ui/controls.js +6 -4
  187. package/dist/ui/controls.js.map +1 -1
  188. package/dist/ui/interaction.d.ts +2 -2
  189. package/dist/ui/interaction.js +8 -7
  190. package/dist/ui/interaction.js.map +1 -1
  191. package/dist/ui/overlay.js +18 -20
  192. package/dist/ui/overlay.js.map +1 -1
  193. package/dist/ui/style.d.ts +1 -1
  194. package/dist/ui/style.js +2 -2
  195. package/dist/ui/style.js.map +1 -1
  196. package/dist/util/animation.d.ts +3 -3
  197. package/dist/util/animation.js +6 -6
  198. package/dist/util/animation.js.map +1 -1
  199. package/dist/util/color.d.ts +1 -1
  200. package/dist/util/color.js +14 -16
  201. package/dist/util/color.js.map +1 -1
  202. package/dist/util/geo.d.ts +6 -6
  203. package/dist/util/geo.js +12 -12
  204. package/dist/util/geo.js.map +1 -1
  205. package/dist/util/guards.d.ts +7 -0
  206. package/dist/util/guards.js +8 -0
  207. package/dist/util/guards.js.map +1 -0
  208. package/dist/util/lru.js.map +1 -1
  209. package/dist/wasm/isard.d.ts +168 -0
  210. package/dist/wasm/isard.js +146 -0
  211. package/dist/wasm/isard_core.d.ts +144 -0
  212. package/dist/wasm/isard_core.js +122 -0
  213. package/dist/workers/basemap.worker.d.ts +3 -3
  214. package/dist/workers/basemap.worker.js +94 -83
  215. package/dist/workers/basemap.worker.js.map +1 -1
  216. package/package.json +1 -1
@@ -12,20 +12,33 @@
12
12
  */
13
13
  import { getCrs } from "../data/crs.js";
14
14
  import { withHeaders } from "../engine/requests.js";
15
+ import { isNumbers, isRecord } from "../util/guards.js";
16
+ const isOrientation = (value) => isRecord(value) && isRecord(value.geometry) && isNumbers(value.geometry.coordinates) && isRecord(value.properties);
17
+ const isCrs = (value) => isRecord(value) &&
18
+ (value.properties === undefined ||
19
+ (isRecord(value.properties) && (value.properties.name === undefined || typeof value.properties.name === 'string')));
20
+ const isOrientations = (value) => isRecord(value) &&
21
+ (value.crs === undefined || isCrs(value.crs)) &&
22
+ Array.isArray(value.features) &&
23
+ value.features.every(isOrientation);
24
+ const isCalibration = (value) => isRecord(value) &&
25
+ (typeof value.id === 'number' || typeof value.id === 'string') &&
26
+ isNumbers(value.rotation) &&
27
+ isNumbers(value.position) &&
28
+ isNumbers(value.projection) &&
29
+ isNumbers(value.size) &&
30
+ (value.distortion === undefined ||
31
+ (isRecord(value.distortion) &&
32
+ isNumbers(value.distortion.pps) &&
33
+ isNumbers(value.distortion.poly357) &&
34
+ (value.distortion.limit === undefined || typeof value.distortion.limit === 'number')));
35
+ const isCalibrations = (value) => Array.isArray(value) && value.every(isCalibration);
15
36
  const RAD = Math.PI / 180;
16
37
  /** 3 × 3 product, row-major */
17
- function times(a, b) {
18
- const out = [];
19
- for (let r = 0; r < 3; r++) {
20
- for (let c = 0; c < 3; c++) {
21
- let sum = 0;
22
- for (let k = 0; k < 3; k++)
23
- sum += (a[r * 3 + k] ?? 0) * (b[k * 3 + c] ?? 0);
24
- out.push(sum);
25
- }
26
- }
27
- return out;
28
- }
38
+ const times = (a, b) => Array.from({ length: 9 }, (_, i) => {
39
+ const [r, c] = [Math.floor(i / 3), i % 3];
40
+ return [0, 1, 2].reduce((sum, k) => sum + (a[r * 3 + k] ?? 0) * (b[k * 3 + c] ?? 0), 0);
41
+ });
29
42
  const rotX = (t) => [1, 0, 0, 0, Math.cos(t), -Math.sin(t), 0, Math.sin(t), Math.cos(t)];
30
43
  const rotY = (t) => [Math.cos(t), 0, Math.sin(t), 0, 1, 0, -Math.sin(t), 0, Math.cos(t)];
31
44
  const rotZ = (t) => [Math.cos(t), -Math.sin(t), 0, Math.sin(t), Math.cos(t), 0, 0, 0, 1];
@@ -34,13 +47,13 @@ const rotZ = (t) => [Math.cos(t), -Math.sin(t), 0, Math.sin(t), Math.cos(t), 0,
34
47
  * `quaternionFromRollPitchHeading`: Ry(-roll) · Rx(-pitch) · Rz(-heading)), turned by the meridian convergence of the
35
48
  * projection (Lambert-93: sin(46.5°) · (3° - longitude))
36
49
  */
37
- export function panoramaRotation(attitude, lon, lambert93) {
50
+ export const panoramaRotation = (attitude, lon, lambert93) => {
38
51
  const vehicle = times(times(rotY(-attitude.roll * RAD), rotX(-attitude.pitch * RAD)), rotZ(-attitude.heading * RAD));
39
52
  const convergence = lambert93 ? Math.sin(46.5 * RAD) * (3 - lon) * RAD : 0;
40
53
  return times(rotZ(convergence), vehicle);
41
- }
54
+ };
42
55
  /** The 25 numbers of a camera for `setPanorama` */
43
- function cameraNumbers(c) {
56
+ const cameraNumbers = (c) => {
44
57
  const p = c.projection;
45
58
  const d = c.distortion;
46
59
  return [
@@ -60,7 +73,7 @@ function cameraNumbers(c) {
60
73
  d?.poly357[2] ?? 0,
61
74
  d?.limit ?? 0,
62
75
  ];
63
- }
76
+ };
64
77
  /** The panoramas of a set, one shown at a time */
65
78
  export class Panoramas {
66
79
  host;
@@ -84,14 +97,10 @@ export class Panoramas {
84
97
  /** The panorama nearest to a position */
85
98
  nearest(lonLat) {
86
99
  const cos = Math.cos(lonLat[1] * RAD);
87
- let best;
88
- let distance = Number.POSITIVE_INFINITY;
89
- for (const p of this.list) {
100
+ return this.list.reduce((nearest, p) => {
90
101
  const d = ((p.lonLat[0] - lonLat[0]) * cos) ** 2 + (p.lonLat[1] - lonLat[1]) ** 2;
91
- if (d < distance)
92
- [best, distance] = [p, d];
93
- }
94
- return best;
102
+ return d < nearest.distance ? { best: p, distance: d } : nearest;
103
+ }, { distance: Number.POSITIVE_INFINITY }).best;
95
104
  }
96
105
  /** Shows a panorama (its index in `list`): projected as soon as its first image arrives, the others after */
97
106
  async show(index) {
@@ -167,18 +176,14 @@ export class Panoramas {
167
176
  return undefined;
168
177
  const cos = Math.cos(here.lonLat[1] * RAD);
169
178
  const look = (eye.bearing + (forward ? 0 : 180)) * RAD;
170
- let best;
171
- let distance = Number.POSITIVE_INFINITY;
172
- for (const p of this.list) {
179
+ return this.list.reduce((nearest, p) => {
173
180
  if (p === here)
174
- continue;
181
+ return nearest;
175
182
  const [east, north] = [(p.lonLat[0] - here.lonLat[0]) * cos, p.lonLat[1] - here.lonLat[1]];
176
183
  const d = Math.hypot(east, north);
177
184
  const off = Math.acos(Math.max(-1, Math.min(1, (east * Math.sin(look) + north * Math.cos(look)) / (d || 1))));
178
- if (off < 60 * RAD && d < distance)
179
- [best, distance] = [p, d];
180
- }
181
- return best;
185
+ return off < 60 * RAD && d < nearest.distance ? { best: p, distance: d } : nearest;
186
+ }, { distance: Number.POSITIVE_INFINITY }).best;
182
187
  }
183
188
  /** Goes to a panorama during the walk, the eye looking the same way (or `bearing`) */
184
189
  async go(index, bearing) {
@@ -205,16 +210,19 @@ export class Panoramas {
205
210
  }
206
211
  }
207
212
  /** Loads a set of panoramas: their positions and attitudes, the calibration of their cameras */
208
- export async function loadPanoramas(host, options) {
209
- const json = async (src) => {
213
+ export const loadPanoramas = async (host, options) => {
214
+ const json = async (src, is) => {
210
215
  const response = await fetch(src, withHeaders(src));
211
216
  if (!response.ok)
212
217
  throw new Error(`isard: ${src}: ${response.status}`);
213
- return (await response.json());
218
+ const value = await response.json();
219
+ if (!is(value))
220
+ throw new Error(`isard: ${src}: unexpected content`);
221
+ return value;
214
222
  };
215
223
  const [orientations, cameras] = await Promise.all([
216
- json(options.orientationsUrl),
217
- json(options.calibrationUrl),
224
+ json(options.orientationsUrl, isOrientations),
225
+ json(options.calibrationUrl, isCalibrations),
218
226
  ]);
219
227
  const crsName = options.crs ?? orientations.crs?.properties?.name ?? 'EPSG:2154';
220
228
  const lambert93 = /2154/.test(crsName);
@@ -222,24 +230,27 @@ export async function loadPanoramas(host, options) {
222
230
  const geoid = options.geoid ?? lambert93;
223
231
  const list = [];
224
232
  const attitudes = [];
225
- for (const feature of orientations.features) {
233
+ orientations.features.forEach((feature) => {
226
234
  const [x = 0, y = 0, z = 0] = feature.geometry.coordinates;
227
235
  const [lon = 0, lat = 0] = crs.inverse([x, y]);
228
236
  const p = feature.properties;
229
- const number = (key) => (typeof p[key] === 'number' ? p[key] : 0);
237
+ const number = (key) => {
238
+ const value = p[key];
239
+ return typeof value === 'number' ? value : 0;
240
+ };
230
241
  attitudes.push({ heading: number('heading'), pitch: number('pitch'), roll: number('roll') });
231
242
  list.push({
232
243
  index: list.length,
233
- id: p.id ?? list.length,
244
+ id: typeof p.id === 'number' || typeof p.id === 'string' ? p.id : list.length,
234
245
  lonLat: [lon, lat],
235
246
  height: z + (geoid ? host.geoidHeight(lon, lat) : 0),
236
247
  heading: number('heading'),
237
248
  });
238
- }
249
+ });
239
250
  return new Panoramas(host, {
240
251
  url: options.url,
241
252
  backgroundDistance: options.backgroundDistance ?? 1000,
242
253
  opacity: options.opacity ?? 1,
243
254
  }, list, attitudes, cameras, lambert93);
244
- }
255
+ };
245
256
  //# sourceMappingURL=panoramas.js.map
@@ -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: the oriented images of a vehicle's cameras around each of its positions (Stereopolis, the\n * iTowns immersive examples), projected onto the scene around the panorama shown. Their positions and attitudes come\n * as 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}`.\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';\n\nexport interface PanoramaOptions {\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 /** 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 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 Attitude {\n heading: number;\n pitch: number;\n roll: number;\n}\n\nconst RAD = Math.PI / 180;\n\n/** 3 × 3 product, row-major */\nfunction times(a: number[], b: number[]): number[] {\n const out: number[] = [];\n for (let r = 0; r < 3; r++) {\n for (let c = 0; c < 3; c++) {\n let sum = 0;\n for (let k = 0; k < 3; k++) sum += (a[r * 3 + k] ?? 0) * (b[k * 3 + c] ?? 0);\n out.push(sum);\n }\n }\n return out;\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 function 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 return times(rotZ(convergence), vehicle);\n}\n\n/** The 25 numbers of a camera for `setPanorama` */\nfunction cameraNumbers(c: Calibration): number[] {\n const p = c.projection;\n const d = c.distortion;\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/** 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 options: Required<Pick<PanoramaOptions, 'url' | 'backgroundDistance' | 'opacity'>>,\n readonly list: readonly Panorama[],\n private readonly attitudes: readonly Attitude[],\n private readonly cameras: readonly Calibration[],\n private readonly lambert93: boolean,\n ) {}\n\n /** The panorama nearest to a position */\n nearest(lonLat: LonLat): Panorama | undefined {\n const cos = Math.cos(lonLat[1] * RAD);\n let best: Panorama | undefined;\n let distance = Number.POSITIVE_INFINITY;\n for (const p of this.list) {\n const d = ((p.lonLat[0] - lonLat[0]) * cos) ** 2 + (p.lonLat[1] - lonLat[1]) ** 2;\n if (d < distance) [best, distance] = [p, d];\n }\n return 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 const attitude = this.attitudes[index];\n if (!pano || !attitude) return;\n const shown = ++this.shown;\n this.current = pano;\n const rotation = panoramaRotation(attitude, pano.lonLat[0], this.lambert93);\n const { url, backgroundDistance, opacity } = this.options;\n this.host.setPanorama(\n pano.lonLat[0],\n pano.lonLat[1],\n pano.height,\n Float64Array.from(rotation),\n Float64Array.from(this.cameras.flatMap(cameraNumbers)),\n backgroundDistance,\n opacity,\n );\n await Promise.all(\n this.cameras.map(async (camera, k) => {\n const src = url.replaceAll('{cameraId}', String(camera.id)).replaceAll('{panoId}', String(pano.id));\n const response = await fetch(src, withHeaders(src));\n if (!response.ok) throw new Error(`isard: panorama image ${src}: ${response.status}`);\n const image = await createImageBitmap(await response.blob(), { premultiplyAlpha: 'none' });\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\n /** Hides the panorama shown */\n hide(): void {\n this.shown++;\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 this.stopWalking?.();\n this.stopWalking = this.host.listen(\n (lonLat) => {\n const target = lonLat && this.nearest(lonLat);\n if (target && target !== this.current) void this.go(target.index);\n },\n (e) => {\n const step = { z: 1, Z: 1, PageUp: 1, s: -1, S: -1, PageDown: -1 }[e.key];\n if (!step || !this.current) return;\n e.preventDefault();\n void this.go((this.current.index + step + this.list.length) % this.list.length);\n },\n (e) => {\n // One step per notch, the next ones once it is shown\n if (this.moving || e.deltaY === 0) return;\n const target = this.ahead(e.deltaY < 0);\n if (target) {\n this.moving = true;\n void this.go(target.index).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 if (!eye || !here) return undefined;\n const cos = Math.cos(here.lonLat[1] * RAD);\n const look = (eye.bearing + (forward ? 0 : 180)) * RAD;\n let best: Panorama | undefined;\n let distance = Number.POSITIVE_INFINITY;\n for (const p of this.list) {\n if (p === here) continue;\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 if (off < 60 * RAD && d < distance) [best, distance] = [p, d];\n }\n return 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 if (!pano) return;\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 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: their positions and attitudes, the calibration of their cameras */\nexport async function loadPanoramas(host: PanoramaHost, options: PanoramaOptions): Promise<Panoramas> {\n const json = async <T>(src: string) => {\n const response = await fetch(src, withHeaders(src));\n if (!response.ok) throw new Error(`isard: ${src}: ${response.status}`);\n return (await response.json()) as T;\n };\n const [orientations, cameras] = await Promise.all([\n json<{\n crs?: { properties?: { name?: string } };\n features: { geometry: { coordinates: number[] }; properties: Record<string, unknown> }[];\n }>(options.orientationsUrl),\n json<Calibration[]>(options.calibrationUrl),\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 for (const feature of orientations.features) {\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) => (typeof p[key] === 'number' ? (p[key] as number) : 0);\n attitudes.push({ heading: number('heading'), pitch: number('pitch'), roll: number('roll') });\n list.push({\n index: list.length,\n id: (p.id as number | string | undefined) ?? list.length,\n lonLat: [lon, lat],\n height: z + (geoid ? host.geoidHeight(lon, lat) : 0),\n heading: number('heading'),\n });\n }\n return new Panoramas(\n host,\n {\n url: options.url,\n backgroundDistance: options.backgroundDistance ?? 1000,\n opacity: options.opacity ?? 1,\n },\n list,\n attitudes,\n cameras,\n lambert93,\n );\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: the oriented images of a vehicle's cameras around each of its positions (Stereopolis, the\n * iTowns immersive examples), projected onto the scene around the panorama shown. Their positions and attitudes come\n * as 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}`.\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 { isNumbers, isRecord } from '../util/guards.ts';\n\nexport interface PanoramaOptions {\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 /** 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 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\nconst RAD = Math.PI / 180;\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/** 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 options: Required<Pick<PanoramaOptions, 'url' | 'backgroundDistance' | 'opacity'>>,\n readonly list: readonly Panorama[],\n private readonly attitudes: readonly Attitude[],\n private readonly cameras: readonly Calibration[],\n private readonly lambert93: boolean,\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 const attitude = this.attitudes[index];\n\n if (!pano || !attitude) return;\n\n const shown = ++this.shown;\n\n this.current = pano;\n\n const rotation = panoramaRotation(attitude, pano.lonLat[0], this.lambert93);\n const { url, backgroundDistance, opacity } = this.options;\n\n this.host.setPanorama(\n pano.lonLat[0],\n pano.lonLat[1],\n pano.height,\n Float64Array.from(rotation),\n Float64Array.from(this.cameras.flatMap(cameraNumbers)),\n backgroundDistance,\n opacity,\n );\n await Promise.all(\n this.cameras.map(async (camera, k) => {\n const src = url.replaceAll('{cameraId}', String(camera.id)).replaceAll('{panoId}', String(pano.id));\n const response = await fetch(src, withHeaders(src));\n\n if (!response.ok) throw new Error(`isard: panorama image ${src}: ${response.status}`);\n\n const image = await createImageBitmap(await response.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\n /** Hides the panorama shown */\n hide(): void {\n this.shown++;\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) void this.go(target.index);\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 void this.go((this.current.index + step + this.list.length) % this.list.length);\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 void this.go(target.index).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: their positions and attitudes, the calibration of their cameras */\nexport const loadPanoramas = async (host: PanoramaHost, options: PanoramaOptions): Promise<Panoramas> => {\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 return new Panoramas(\n host,\n {\n url: options.url,\n backgroundDistance: options.backgroundDistance ?? 1000,\n opacity: options.opacity ?? 1,\n },\n list,\n attitudes,\n cameras,\n lambert93,\n );\n};\n"]}
@@ -73,14 +73,14 @@ export declare const CLASSIFICATIONS: Readonly<Record<number, Readonly<Required<
73
73
  /** The default ramp of the altitudes, low to high */
74
74
  export declare const ELEVATION_RAMP: Ramp;
75
75
  /** The colors of the 256 classes (RGBA, alpha 0 hides one) */
76
- export declare function classPalette(overrides?: Record<number, ClassStyle>): Uint8Array;
76
+ export declare const classPalette: (overrides?: Record<number, ClassStyle>) => Uint8Array;
77
77
  /** What a WKT says of a CRS: its EPSG code (projected first), the metres of a unit of z */
78
- export declare function wktCrs(wkt: string): {
78
+ export declare const wktCrs: (wkt: string) => {
79
79
  code: number | undefined;
80
80
  verticalScale: number | undefined;
81
81
  };
82
82
  /** The CRS of a COPC file for the engine, from its WKT and the options */
83
- export declare function pointCloudCrs(wkt: string | undefined, options: Pick<PointCloudOptions, 'crs' | 'geoid' | 'verticalScale'>): PointCloudCrs;
83
+ export declare const pointCloudCrs: (wkt: string | undefined, options: Pick<PointCloudOptions, "crs" | "geoid" | "verticalScale">) => PointCloudCrs;
84
84
  /** A point cloud (`GeoMap.addPointCloud`): COPC or 3D Tiles points; `pickFeature` gives a COPC point's attributes */
85
85
  export declare class PointCloudLayer extends Layer {
86
86
  readonly url: string;
@@ -44,7 +44,7 @@ export const ELEVATION_RAMP = [
44
44
  [1, '#d7191c'],
45
45
  ];
46
46
  /** The colors of the 256 classes (RGBA, alpha 0 hides one) */
47
- export function classPalette(overrides = {}) {
47
+ export const classPalette = (overrides = {}) => {
48
48
  const out = new Uint8Array(256 * 4);
49
49
  for (let code = 0; code < 256; code += 1) {
50
50
  const base = CLASSIFICATIONS[code] ?? { color: '#c8c8c8', visible: true };
@@ -53,9 +53,9 @@ export function classPalette(overrides = {}) {
53
53
  out.set([r * 255, g * 255, b * 255, (own.visible ?? base.visible) ? 255 : 0], code * 4);
54
54
  }
55
55
  return out;
56
- }
56
+ };
57
57
  /** The section of a WKT opening with one of `keywords` (`PROJCS[…]`), from its keyword to its closing bracket */
58
- function section(wkt, keywords) {
58
+ const section = (wkt, keywords) => {
59
59
  for (const keyword of keywords) {
60
60
  const start = wkt.indexOf(`${keyword}[`);
61
61
  if (start < 0)
@@ -69,53 +69,47 @@ function section(wkt, keywords) {
69
69
  }
70
70
  }
71
71
  return undefined;
72
- }
72
+ };
73
73
  /** The EPSG code a WKT section ends with (its own `AUTHORITY`, or `ID` in WKT2), the last of its nested ones */
74
- function lastCode(part) {
74
+ const lastCode = (part) => {
75
75
  const codes = [...part.matchAll(/(?:AUTHORITY|ID)\[\s*"EPSG"\s*,\s*"?(\d+)"?\s*\]/g)];
76
76
  const last = codes.at(-1)?.[1];
77
77
  return last === undefined ? undefined : Number(last);
78
- }
78
+ };
79
79
  /** The factor of the last `UNIT` (`LENGTHUNIT` in WKT2) of a WKT section */
80
- function lastUnit(part) {
80
+ const lastUnit = (part) => {
81
81
  const units = [...(part ?? '').matchAll(/(?:LENGTH)?UNIT\[\s*"[^"]*"\s*,\s*([\d.eE+-]+)/g)];
82
82
  const factor = Number(units.at(-1)?.[1]);
83
83
  return Number.isFinite(factor) && factor > 0 ? factor : undefined;
84
- }
84
+ };
85
85
  /** What a WKT says of a CRS: its EPSG code (projected first), the metres of a unit of z */
86
- export function wktCrs(wkt) {
86
+ export const wktCrs = (wkt) => {
87
87
  const projected = section(wkt, ['PROJCS', 'PROJCRS']);
88
88
  const geographic = section(wkt, ['GEOGCS', 'GEOGCRS']);
89
- let code = lastCode(projected ?? geographic ?? '');
90
- if (code === undefined && /Lambert[- ]93/i.test(wkt))
91
- code = 2154;
89
+ const code = lastCode(projected ?? geographic ?? '') ?? (/Lambert[- ]93/i.test(wkt) ? 2154 : undefined);
92
90
  const vertical = section(wkt, ['VERT_CS', 'VERTCRS']);
93
91
  const verticalScale = lastUnit(vertical ?? projected);
94
92
  return { code, verticalScale };
95
- }
93
+ };
96
94
  /** Whether the altitudes of a CRS are NGF-IGN69 by default: Lambert-93 and the CC zones */
97
95
  const FRENCH = (code) => code === 2154 || (code !== undefined && code >= 3942 && code <= 3950);
98
96
  /** The CRS of a COPC file for the engine, from its WKT and the options */
99
- export function pointCloudCrs(wkt, options) {
97
+ export const pointCloudCrs = (wkt, options) => {
100
98
  const parsed = wkt ? wktCrs(wkt) : { code: undefined, verticalScale: undefined };
101
- let crs;
102
- let code = parsed.code;
103
- if (options.crs !== undefined) {
104
- crs = getCrs(options.crs);
105
- if (typeof options.crs === 'string')
106
- code = epsgCode(options.crs) ?? code;
107
- }
108
- else if (code !== undefined) {
99
+ const crs = (() => {
100
+ if (options.crs !== undefined)
101
+ return getCrs(options.crs);
102
+ const code = parsed.code;
103
+ if (code === undefined)
104
+ throw new Error('the file names no CRS: give it as `crs`');
109
105
  try {
110
- crs = getCrs(`EPSG:${code}`);
106
+ return getCrs(`EPSG:${code}`);
111
107
  }
112
108
  catch {
113
109
  throw new Error(`the CRS of the file, EPSG:${code}, is not built in: give it as \`crs\` (proj4('EPSG:${code}'))`);
114
110
  }
115
- }
116
- else {
117
- throw new Error('the file names no CRS: give it as `crs`');
118
- }
111
+ })();
112
+ const code = typeof options.crs === 'string' ? (epsgCode(options.crs) ?? parsed.code) : parsed.code;
119
113
  const inverse = (xy) => {
120
114
  const out = new Float64Array(xy.length);
121
115
  for (let i = 0; i + 1 < xy.length; i += 2) {
@@ -130,17 +124,15 @@ export function pointCloudCrs(wkt, options) {
130
124
  geoid: options.geoid ?? (FRENCH(code) || /IGN69|NGF/.test(wkt ?? '')),
131
125
  verticalScale: options.verticalScale ?? parsed.verticalScale ?? 1,
132
126
  };
133
- }
127
+ };
134
128
  /** The style numbers of the engine (`setPointCloudStyle`) */
135
- function styleNumbers(s, rate) {
129
+ const styleNumbers = (s, rate) => {
136
130
  const colors = ['rgb', 'classification', 'elevation', 'intensity'];
137
- let edl;
138
- if (s.edl)
139
- edl = s.edl === true ? {} : s.edl;
131
+ const edl = s.edl === true ? {} : s.edl || undefined;
140
132
  const [emin = Number.NaN, emax = Number.NaN] = s.elevationRange ?? [];
141
133
  const [imin = Number.NaN, imax = Number.NaN] = s.intensityRange ?? [];
142
134
  return Float64Array.of(s.colorBy ? colors.indexOf(s.colorBy) : -1, s.pointSize, s.maxPointSize, s.sizeMode === 'fixed' ? 0 : 1, s.shape === 'square' ? 0 : 1, edl ? (edl.strength ?? 1) : 0, edl?.radius ?? 1.4, emin, emax, imin, imax, s.maxScreenSpaceError, s.pointBudget, rate);
143
- }
135
+ };
144
136
  /** A point cloud (`GeoMap.addPointCloud`): COPC or 3D Tiles points; `pickFeature` gives a COPC point's attributes */
145
137
  export class PointCloudLayer extends Layer {
146
138
  url;
@@ -1 +1 @@
1
- {"version":3,"file":"pointclouds.js","sourceRoot":"","sources":["../../src/layers/pointclouds.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Point clouds: a COPC file (Cloud Optimized Point Cloud: LAZ 1.4 with an octree, read by HTTP range requests, as the\n * IGN distributes LiDAR HD) or a 3D Tiles point cloud (`.pnts`, glTF points), drawn by the engine with 3D Tiles. The\n * COPC file's CRS comes from its WKT (built-in CRSs, or registered ones: `registerCrs`) or the `crs` option; altitudes\n * in NGF-IGN69 (Lambert-93, the CC zones) are raised by the RAF20 geoid height onto the ellipsoid of the relief and\n * the 3D Tiles.\n */\nimport { type Crs, type CrsLike, epsgCode, getCrs } from '../data/crs.ts';\nimport type { LayerHost } from '../types.ts';\nimport type {\n Engine,\n PointCloudCrs,\n PointCloudInfo,\n PointCloudPoint,\n PointCloudStats,\n Tiles3dStats,\n} from '../wasm/isard.js';\nimport { type Feature, parseColor, type Ramp, rampTexels } from './features.ts';\nimport { Layer } from './layers.ts';\n\n/** What the points are colored by */\nexport type PointColor = 'rgb' | 'classification' | 'elevation' | 'intensity';\n\n/** The look of a class of points */\nexport interface ClassStyle {\n /** CSS color */\n color?: string;\n /** false hides the class */\n visible?: boolean;\n}\n\nexport interface PointCloudStyle {\n /** By RGB (files with colors), class (the ASPRS palette, `classifications`), altitude (`elevationRamp` over\n * `elevationRange`) or intensity (grey over `intensityRange`). Default: RGB when the file has colors, else class */\n colorBy?: PointColor;\n /** CSS pixels: the size of the points, or the smallest with `sizeMode: 'adaptive'` (default 2) */\n pointSize: number;\n /** CSS pixels: the largest adaptive size (default 4) */\n maxPointSize: number;\n /** `'adaptive'` (default): the spacing of the points of the finest level drawn there, at their distance (the\n * nearer, the larger, no gap); `'fixed'`: `pointSize` everywhere */\n sizeMode: 'adaptive' | 'fixed';\n /** `'circle'` (default) or `'square'` */\n shape: 'circle' | 'square';\n /** Eye-Dome Lighting: points shaded by the depth of their neighbours on screen, their relief read without normals\n * nor colors (default false; `strength` 1, `radius` 1.4 CSS pixels) */\n edl: boolean | { strength?: number; radius?: number };\n /** Colors and visibility by class code, over the defaults (ASPRS, and IGN's LiDAR HD classes 64 to 67; the noise\n * 7 and 18 and the artefacts 65 hidden): `{ 2: { color: '#a0522d' }, 66: { visible: false } }` */\n classifications: Record<number, ClassStyle>;\n /** Altitudes (metres, the file's vertical datum) mapped onto the ramp; default the file's lowest and highest */\n elevationRange?: [min: number, max: number];\n /** Colors from the lowest altitude (0) to the highest (1) */\n elevationRamp: Ramp;\n /** Intensities mapped from black to white; default the bulk of the first node's (2nd to 98th percentile) */\n intensityRange?: [min: number, max: number];\n /** CSS pixels: a node is refined while the spacing of its points covers more on screen (default 1.5; lower is finer\n * and heavier). For 3D Tiles, their screen-space error (default 16) */\n maxScreenSpaceError: number;\n /** Points drawn at most, the nearest and the coarsest first (default 3 000 000) */\n pointBudget: number;\n}\n\nexport interface PointCloudOptions extends Partial<PointCloudStyle> {\n /** A COPC file (`.copc.laz`) or a 3D Tiles `tileset.json` of points */\n url: string;\n /** Default: `'3dtiles'` for a `.json` URL, else `'copc'` */\n format?: 'copc' | '3dtiles';\n /** The CRS of a COPC file without a WKT, or whose CRS is not built in (`proj4('EPSG:2992')`) */\n crs?: CrsLike;\n /** Its altitudes are above the geoid (NGF-IGN69), raised by the RAF20 geoid height; default for Lambert-93 and the\n * CC zones */\n geoid?: boolean;\n /** Metres of a unit of z; default the vertical unit of the WKT (a US survey foot…), else that of x and y */\n verticalScale?: number;\n /** Requests a second at most: 8 by default for the Géoplateforme (data.geopf.fr allows 10), no limit elsewhere */\n requestsPerSecond?: number;\n}\n\n/** The default classes: ASPRS LAS 1.4, then IGN's LiDAR HD (64 permanent structures, 65 artefacts, 66 virtual points,\n * 67 miscellaneous buildings) */\nexport const CLASSIFICATIONS: Readonly<Record<number, Readonly<Required<ClassStyle>>>> = {\n 0: { color: '#a6a6a6', visible: true },\n 1: { color: '#c8c8c8', visible: true },\n 2: { color: '#b08458', visible: true },\n 3: { color: '#9ccc65', visible: true },\n 4: { color: '#5aa83f', visible: true },\n 5: { color: '#2e7d32', visible: true },\n 6: { color: '#e57352', visible: true },\n 7: { color: '#ff00ff', visible: false },\n 8: { color: '#ff0000', visible: true },\n 9: { color: '#3d8fd6', visible: true },\n 10: { color: '#8e6bb0', visible: true },\n 11: { color: '#7a7a7a', visible: true },\n 12: { color: '#ffe680', visible: true },\n 13: { color: '#ffff00', visible: true },\n 14: { color: '#ffc800', visible: true },\n 15: { color: '#c89600', visible: true },\n 16: { color: '#ff9632', visible: true },\n 17: { color: '#b48cc8', visible: true },\n 18: { color: '#ff00ff', visible: false },\n 64: { color: '#8c6e5a', visible: true },\n 65: { color: '#ff00ff', visible: false },\n 66: { color: '#5a6ec8', visible: true },\n 67: { color: '#e6966e', visible: true },\n};\n\n/** The default ramp of the altitudes, low to high */\nexport const ELEVATION_RAMP: Ramp = [\n [0, '#2b83ba'],\n [0.25, '#abdda4'],\n [0.5, '#ffffbf'],\n [0.75, '#fdae61'],\n [1, '#d7191c'],\n];\n\n/** The colors of the 256 classes (RGBA, alpha 0 hides one) */\nexport function classPalette(overrides: Record<number, ClassStyle> = {}): Uint8Array {\n const out = new Uint8Array(256 * 4);\n for (let code = 0; code < 256; code += 1) {\n const base = CLASSIFICATIONS[code] ?? { color: '#c8c8c8', visible: true };\n const own = overrides[code] ?? {};\n const [r = 0, g = 0, b = 0] = parseColor(own.color ?? base.color);\n out.set([r * 255, g * 255, b * 255, (own.visible ?? base.visible) ? 255 : 0], code * 4);\n }\n return out;\n}\n\n/** The section of a WKT opening with one of `keywords` (`PROJCS[…]`), from its keyword to its closing bracket */\nfunction section(wkt: string, keywords: string[]): string | undefined {\n for (const keyword of keywords) {\n const start = wkt.indexOf(`${keyword}[`);\n if (start < 0) continue;\n let depth = 0;\n for (let i = start + keyword.length; i < wkt.length; i += 1) {\n if (wkt[i] === '[') depth += 1;\n else if (wkt[i] === ']' && --depth === 0) return wkt.slice(start, i + 1);\n }\n }\n return undefined;\n}\n\n/** The EPSG code a WKT section ends with (its own `AUTHORITY`, or `ID` in WKT2), the last of its nested ones */\nfunction lastCode(part: string): number | undefined {\n const codes = [...part.matchAll(/(?:AUTHORITY|ID)\\[\\s*\"EPSG\"\\s*,\\s*\"?(\\d+)\"?\\s*\\]/g)];\n const last = codes.at(-1)?.[1];\n return last === undefined ? undefined : Number(last);\n}\n\n/** The factor of the last `UNIT` (`LENGTHUNIT` in WKT2) of a WKT section */\nfunction lastUnit(part: string | undefined): number | undefined {\n const units = [...(part ?? '').matchAll(/(?:LENGTH)?UNIT\\[\\s*\"[^\"]*\"\\s*,\\s*([\\d.eE+-]+)/g)];\n const factor = Number(units.at(-1)?.[1]);\n return Number.isFinite(factor) && factor > 0 ? factor : undefined;\n}\n\n/** What a WKT says of a CRS: its EPSG code (projected first), the metres of a unit of z */\nexport function wktCrs(wkt: string): { code: number | undefined; verticalScale: number | undefined } {\n const projected = section(wkt, ['PROJCS', 'PROJCRS']);\n const geographic = section(wkt, ['GEOGCS', 'GEOGCRS']);\n let code = lastCode(projected ?? geographic ?? '');\n if (code === undefined && /Lambert[- ]93/i.test(wkt)) code = 2154;\n const vertical = section(wkt, ['VERT_CS', 'VERTCRS']);\n const verticalScale = lastUnit(vertical ?? projected);\n return { code, verticalScale };\n}\n\n/** Whether the altitudes of a CRS are NGF-IGN69 by default: Lambert-93 and the CC zones */\nconst FRENCH = (code: number | undefined) => code === 2154 || (code !== undefined && code >= 3942 && code <= 3950);\n\n/** The CRS of a COPC file for the engine, from its WKT and the options */\nexport function pointCloudCrs(\n wkt: string | undefined,\n options: Pick<PointCloudOptions, 'crs' | 'geoid' | 'verticalScale'>,\n): PointCloudCrs {\n const parsed = wkt ? wktCrs(wkt) : { code: undefined, verticalScale: undefined };\n let crs: Crs;\n let code = parsed.code;\n if (options.crs !== undefined) {\n crs = getCrs(options.crs);\n if (typeof options.crs === 'string') code = epsgCode(options.crs) ?? code;\n } else if (code !== undefined) {\n try {\n crs = getCrs(`EPSG:${code}`);\n } catch {\n throw new Error(`the CRS of the file, EPSG:${code}, is not built in: give it as \\`crs\\` (proj4('EPSG:${code}'))`);\n }\n } else {\n throw new Error('the file names no CRS: give it as `crs`');\n }\n const inverse = (xy: Float64Array) => {\n const out = new Float64Array(xy.length);\n for (let i = 0; i + 1 < xy.length; i += 2) {\n const [lon = Number.NaN, lat = Number.NaN] = crs.inverse([xy[i] as number, xy[i + 1] as number]);\n out[i] = lon;\n out[i + 1] = lat;\n }\n return out;\n };\n return {\n inverse,\n geoid: options.geoid ?? (FRENCH(code) || /IGN69|NGF/.test(wkt ?? '')),\n verticalScale: options.verticalScale ?? parsed.verticalScale ?? 1,\n };\n}\n\n/** The style numbers of the engine (`setPointCloudStyle`) */\nfunction styleNumbers(s: PointCloudStyle, rate: number): Float64Array {\n const colors: PointColor[] = ['rgb', 'classification', 'elevation', 'intensity'];\n let edl: { strength?: number; radius?: number } | undefined;\n if (s.edl) edl = s.edl === true ? {} : s.edl;\n const [emin = Number.NaN, emax = Number.NaN] = s.elevationRange ?? [];\n const [imin = Number.NaN, imax = Number.NaN] = s.intensityRange ?? [];\n return Float64Array.of(\n s.colorBy ? colors.indexOf(s.colorBy) : -1,\n s.pointSize,\n s.maxPointSize,\n s.sizeMode === 'fixed' ? 0 : 1,\n s.shape === 'square' ? 0 : 1,\n edl ? (edl.strength ?? 1) : 0,\n edl?.radius ?? 1.4,\n emin,\n emax,\n imin,\n imax,\n s.maxScreenSpaceError,\n s.pointBudget,\n rate,\n );\n}\n\n/** A point cloud (`GeoMap.addPointCloud`): COPC or 3D Tiles points; `pickFeature` gives a COPC point's attributes */\nexport class PointCloudLayer extends Layer {\n readonly url: string;\n readonly format: 'copc' | '3dtiles';\n private style: PointCloudStyle;\n private readonly options: PointCloudOptions;\n\n /** @internal */\n constructor(map: LayerHost, options: PointCloudOptions) {\n super(map);\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 this.url = base ? new URL(options.url, base).href : options.url;\n this.format = options.format ?? (/\\.json(?:[?#]|$)/i.test(options.url) ? '3dtiles' : 'copc');\n this.options = options;\n const tiles = this.format === '3dtiles';\n this.style = {\n ...(options.colorBy ? { colorBy: options.colorBy } : {}),\n pointSize: options.pointSize ?? 2,\n maxPointSize: options.maxPointSize ?? 4,\n sizeMode: options.sizeMode ?? 'adaptive',\n shape: options.shape ?? 'circle',\n edl: options.edl ?? false,\n classifications: options.classifications ?? {},\n ...(options.elevationRange ? { elevationRange: options.elevationRange } : {}),\n elevationRamp: options.elevationRamp ?? ELEVATION_RAMP,\n ...(options.intensityRange ? { intensityRange: options.intensityRange } : {}),\n maxScreenSpaceError: options.maxScreenSpaceError ?? (tiles ? 16 : 1.5),\n pointBudget: options.pointBudget ?? 3_000_000,\n };\n }\n\n /** @internal Drawn by the engine with 3D Tiles (the point cloud module loads with the first one) */\n override get needsFullEngine(): boolean {\n return true;\n }\n\n /** Changes the style, the rest kept */\n setStyle(style: Partial<PointCloudStyle>): void {\n this.style = { ...this.style, ...style };\n // Kept for its creation while the engine with 3D Tiles loads\n if (this.id < 0) return;\n this.apply(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n getStyle(): Readonly<PointCloudStyle> {\n return this.style;\n }\n\n /** Loading counters; undefined once removed and while the engine with 3D Tiles loads */\n stats(): PointCloudStats | Tiles3dStats | undefined {\n if (this.id < 0) return undefined;\n return this.format === '3dtiles' ? this.map.engine.tiles3dStats(this.id) : this.map.engine.pointCloudStats(this.id);\n }\n\n /** What a COPC file says of itself (points, format, CRS, center, altitudes), once its head is read */\n info(): PointCloudInfo | undefined {\n return this.id < 0 || this.format === '3dtiles' ? undefined : this.map.engine.pointCloudInfo(this.id);\n }\n\n /** @internal The point picked (`pickFeature`, 'hoverfeature'): a Point at its longitude, latitude and height, its\n * attributes as properties */\n featureAt(index: number): Feature<PointCloudPoint> | undefined {\n if (this.id < 0 || this.format === '3dtiles') return undefined;\n const point = this.map.engine.pointCloudPoint(this.id, index);\n if (!point) return undefined;\n return {\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [...point.lonLat, point.height] },\n properties: point,\n };\n }\n\n private apply(engine: Engine, id: number): void {\n const s = this.style;\n if (this.format === '3dtiles') {\n engine.setTiles3dStyle(id, s.maxScreenSpaceError, 1, s.pointSize, new Float32Array());\n return;\n }\n const rate = this.options.requestsPerSecond ?? (/^https?:\\/\\/data\\.geopf\\.fr\\//.test(this.url) ? 8 : 0);\n engine.setPointCloudStyle(\n id,\n styleNumbers(s, rate),\n classPalette(s.classifications),\n rampTexels(s.elevationRamp).rgba,\n );\n }\n\n /** @internal */\n protected create(engine: Engine): number {\n const id =\n this.format === '3dtiles'\n ? engine.addTiles3d(this.url, this.style.maxScreenSpaceError)\n : engine.addPointCloud(this.url, (wkt) => pointCloudCrs(wkt, this.options));\n this.apply(engine, id);\n return id;\n }\n}\n"]}
1
+ {"version":3,"file":"pointclouds.js","sourceRoot":"","sources":["../../src/layers/pointclouds.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Point clouds: a COPC file (Cloud Optimized Point Cloud: LAZ 1.4 with an octree, read by HTTP range requests, as the\n * IGN distributes LiDAR HD) or a 3D Tiles point cloud (`.pnts`, glTF points), drawn by the engine with 3D Tiles. The\n * COPC file's CRS comes from its WKT (built-in CRSs, or registered ones: `registerCrs`) or the `crs` option; altitudes\n * in NGF-IGN69 (Lambert-93, the CC zones) are raised by the RAF20 geoid height onto the ellipsoid of the relief and\n * the 3D Tiles.\n */\nimport { type Crs, type CrsLike, epsgCode, getCrs } from '../data/crs.ts';\nimport type { LayerHost } from '../types.ts';\nimport type {\n Engine,\n PointCloudCrs,\n PointCloudInfo,\n PointCloudPoint,\n PointCloudStats,\n Tiles3dStats,\n} from '../wasm/isard.js';\nimport { type Feature, parseColor, type Ramp, rampTexels } from './features.ts';\nimport { Layer } from './layers.ts';\n\n/** What the points are colored by */\nexport type PointColor = 'rgb' | 'classification' | 'elevation' | 'intensity';\n\n/** The look of a class of points */\nexport interface ClassStyle {\n /** CSS color */\n color?: string;\n /** false hides the class */\n visible?: boolean;\n}\n\nexport interface PointCloudStyle {\n /** By RGB (files with colors), class (the ASPRS palette, `classifications`), altitude (`elevationRamp` over\n * `elevationRange`) or intensity (grey over `intensityRange`). Default: RGB when the file has colors, else class */\n colorBy?: PointColor;\n /** CSS pixels: the size of the points, or the smallest with `sizeMode: 'adaptive'` (default 2) */\n pointSize: number;\n /** CSS pixels: the largest adaptive size (default 4) */\n maxPointSize: number;\n /** `'adaptive'` (default): the spacing of the points of the finest level drawn there, at their distance (the\n * nearer, the larger, no gap); `'fixed'`: `pointSize` everywhere */\n sizeMode: 'adaptive' | 'fixed';\n /** `'circle'` (default) or `'square'` */\n shape: 'circle' | 'square';\n /** Eye-Dome Lighting: points shaded by the depth of their neighbours on screen, their relief read without normals\n * nor colors (default false; `strength` 1, `radius` 1.4 CSS pixels) */\n edl: boolean | { strength?: number; radius?: number };\n /** Colors and visibility by class code, over the defaults (ASPRS, and IGN's LiDAR HD classes 64 to 67; the noise\n * 7 and 18 and the artefacts 65 hidden): `{ 2: { color: '#a0522d' }, 66: { visible: false } }` */\n classifications: Record<number, ClassStyle>;\n /** Altitudes (metres, the file's vertical datum) mapped onto the ramp; default the file's lowest and highest */\n elevationRange?: [min: number, max: number];\n /** Colors from the lowest altitude (0) to the highest (1) */\n elevationRamp: Ramp;\n /** Intensities mapped from black to white; default the bulk of the first node's (2nd to 98th percentile) */\n intensityRange?: [min: number, max: number];\n /** CSS pixels: a node is refined while the spacing of its points covers more on screen (default 1.5; lower is finer\n * and heavier). For 3D Tiles, their screen-space error (default 16) */\n maxScreenSpaceError: number;\n /** Points drawn at most, the nearest and the coarsest first (default 3 000 000) */\n pointBudget: number;\n}\n\nexport interface PointCloudOptions extends Partial<PointCloudStyle> {\n /** A COPC file (`.copc.laz`) or a 3D Tiles `tileset.json` of points */\n url: string;\n /** Default: `'3dtiles'` for a `.json` URL, else `'copc'` */\n format?: 'copc' | '3dtiles';\n /** The CRS of a COPC file without a WKT, or whose CRS is not built in (`proj4('EPSG:2992')`) */\n crs?: CrsLike;\n /** Its altitudes are above the geoid (NGF-IGN69), raised by the RAF20 geoid height; default for Lambert-93 and the\n * CC zones */\n geoid?: boolean;\n /** Metres of a unit of z; default the vertical unit of the WKT (a US survey foot…), else that of x and y */\n verticalScale?: number;\n /** Requests a second at most: 8 by default for the Géoplateforme (data.geopf.fr allows 10), no limit elsewhere */\n requestsPerSecond?: number;\n}\n\n/** The default classes: ASPRS LAS 1.4, then IGN's LiDAR HD (64 permanent structures, 65 artefacts, 66 virtual points,\n * 67 miscellaneous buildings) */\nexport const CLASSIFICATIONS: Readonly<Record<number, Readonly<Required<ClassStyle>>>> = {\n 0: { color: '#a6a6a6', visible: true },\n 1: { color: '#c8c8c8', visible: true },\n 2: { color: '#b08458', visible: true },\n 3: { color: '#9ccc65', visible: true },\n 4: { color: '#5aa83f', visible: true },\n 5: { color: '#2e7d32', visible: true },\n 6: { color: '#e57352', visible: true },\n 7: { color: '#ff00ff', visible: false },\n 8: { color: '#ff0000', visible: true },\n 9: { color: '#3d8fd6', visible: true },\n 10: { color: '#8e6bb0', visible: true },\n 11: { color: '#7a7a7a', visible: true },\n 12: { color: '#ffe680', visible: true },\n 13: { color: '#ffff00', visible: true },\n 14: { color: '#ffc800', visible: true },\n 15: { color: '#c89600', visible: true },\n 16: { color: '#ff9632', visible: true },\n 17: { color: '#b48cc8', visible: true },\n 18: { color: '#ff00ff', visible: false },\n 64: { color: '#8c6e5a', visible: true },\n 65: { color: '#ff00ff', visible: false },\n 66: { color: '#5a6ec8', visible: true },\n 67: { color: '#e6966e', visible: true },\n};\n\n/** The default ramp of the altitudes, low to high */\nexport const ELEVATION_RAMP: Ramp = [\n [0, '#2b83ba'],\n [0.25, '#abdda4'],\n [0.5, '#ffffbf'],\n [0.75, '#fdae61'],\n [1, '#d7191c'],\n];\n\n/** The colors of the 256 classes (RGBA, alpha 0 hides one) */\nexport const classPalette = (overrides: Record<number, ClassStyle> = {}): Uint8Array => {\n const out = new Uint8Array(256 * 4);\n\n for (let code = 0; code < 256; code += 1) {\n const base = CLASSIFICATIONS[code] ?? { color: '#c8c8c8', visible: true };\n const own = overrides[code] ?? {};\n const [r = 0, g = 0, b = 0] = parseColor(own.color ?? base.color);\n\n out.set([r * 255, g * 255, b * 255, (own.visible ?? base.visible) ? 255 : 0], code * 4);\n }\n\n return out;\n};\n\n/** The section of a WKT opening with one of `keywords` (`PROJCS[…]`), from its keyword to its closing bracket */\nconst section = (wkt: string, keywords: string[]): string | undefined => {\n for (const keyword of keywords) {\n const start = wkt.indexOf(`${keyword}[`);\n\n if (start < 0) continue;\n\n let depth = 0;\n\n for (let i = start + keyword.length; i < wkt.length; i += 1) {\n if (wkt[i] === '[') depth += 1;\n else if (wkt[i] === ']' && --depth === 0) return wkt.slice(start, i + 1);\n }\n }\n\n return undefined;\n};\n\n/** The EPSG code a WKT section ends with (its own `AUTHORITY`, or `ID` in WKT2), the last of its nested ones */\nconst lastCode = (part: string): number | undefined => {\n const codes = [...part.matchAll(/(?:AUTHORITY|ID)\\[\\s*\"EPSG\"\\s*,\\s*\"?(\\d+)\"?\\s*\\]/g)];\n const last = codes.at(-1)?.[1];\n\n return last === undefined ? undefined : Number(last);\n};\n\n/** The factor of the last `UNIT` (`LENGTHUNIT` in WKT2) of a WKT section */\nconst lastUnit = (part: string | undefined): number | undefined => {\n const units = [...(part ?? '').matchAll(/(?:LENGTH)?UNIT\\[\\s*\"[^\"]*\"\\s*,\\s*([\\d.eE+-]+)/g)];\n const factor = Number(units.at(-1)?.[1]);\n\n return Number.isFinite(factor) && factor > 0 ? factor : undefined;\n};\n\n/** What a WKT says of a CRS: its EPSG code (projected first), the metres of a unit of z */\nexport const wktCrs = (wkt: string): { code: number | undefined; verticalScale: number | undefined } => {\n const projected = section(wkt, ['PROJCS', 'PROJCRS']);\n const geographic = section(wkt, ['GEOGCS', 'GEOGCRS']);\n const code = lastCode(projected ?? geographic ?? '') ?? (/Lambert[- ]93/i.test(wkt) ? 2154 : undefined);\n const vertical = section(wkt, ['VERT_CS', 'VERTCRS']);\n const verticalScale = lastUnit(vertical ?? projected);\n\n return { code, verticalScale };\n};\n\n/** Whether the altitudes of a CRS are NGF-IGN69 by default: Lambert-93 and the CC zones */\nconst FRENCH = (code: number | undefined) => code === 2154 || (code !== undefined && code >= 3942 && code <= 3950);\n\n/** The CRS of a COPC file for the engine, from its WKT and the options */\nexport const pointCloudCrs = (\n wkt: string | undefined,\n options: Pick<PointCloudOptions, 'crs' | 'geoid' | 'verticalScale'>,\n): PointCloudCrs => {\n const parsed = wkt ? wktCrs(wkt) : { code: undefined, verticalScale: undefined };\n const crs = ((): Crs => {\n if (options.crs !== undefined) return getCrs(options.crs);\n\n const code = parsed.code;\n\n if (code === undefined) throw new Error('the file names no CRS: give it as `crs`');\n try {\n return getCrs(`EPSG:${code}`);\n } catch {\n throw new Error(`the CRS of the file, EPSG:${code}, is not built in: give it as \\`crs\\` (proj4('EPSG:${code}'))`);\n }\n })();\n const code = typeof options.crs === 'string' ? (epsgCode(options.crs) ?? parsed.code) : parsed.code;\n const inverse = (xy: Float64Array) => {\n const out = new Float64Array(xy.length);\n\n for (let i = 0; i + 1 < xy.length; i += 2) {\n const [lon = Number.NaN, lat = Number.NaN] = crs.inverse([xy[i] as number, xy[i + 1] as number]);\n\n out[i] = lon;\n out[i + 1] = lat;\n }\n\n return out;\n };\n\n return {\n inverse,\n geoid: options.geoid ?? (FRENCH(code) || /IGN69|NGF/.test(wkt ?? '')),\n verticalScale: options.verticalScale ?? parsed.verticalScale ?? 1,\n };\n};\n\n/** The style numbers of the engine (`setPointCloudStyle`) */\nconst styleNumbers = (s: PointCloudStyle, rate: number): Float64Array => {\n const colors: PointColor[] = ['rgb', 'classification', 'elevation', 'intensity'];\n const edl: { strength?: number; radius?: number } | undefined = s.edl === true ? {} : s.edl || undefined;\n const [emin = Number.NaN, emax = Number.NaN] = s.elevationRange ?? [];\n const [imin = Number.NaN, imax = Number.NaN] = s.intensityRange ?? [];\n\n return Float64Array.of(\n s.colorBy ? colors.indexOf(s.colorBy) : -1,\n s.pointSize,\n s.maxPointSize,\n s.sizeMode === 'fixed' ? 0 : 1,\n s.shape === 'square' ? 0 : 1,\n edl ? (edl.strength ?? 1) : 0,\n edl?.radius ?? 1.4,\n emin,\n emax,\n imin,\n imax,\n s.maxScreenSpaceError,\n s.pointBudget,\n rate,\n );\n};\n\n/** A point cloud (`GeoMap.addPointCloud`): COPC or 3D Tiles points; `pickFeature` gives a COPC point's attributes */\nexport class PointCloudLayer extends Layer {\n readonly url: string;\n readonly format: 'copc' | '3dtiles';\n private style: PointCloudStyle;\n private readonly options: PointCloudOptions;\n\n /** @internal */\n constructor(map: LayerHost, options: PointCloudOptions) {\n super(map);\n\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(options.url, base).href : options.url;\n this.format = options.format ?? (/\\.json(?:[?#]|$)/i.test(options.url) ? '3dtiles' : 'copc');\n this.options = options;\n\n const tiles = this.format === '3dtiles';\n\n this.style = {\n ...(options.colorBy ? { colorBy: options.colorBy } : {}),\n pointSize: options.pointSize ?? 2,\n maxPointSize: options.maxPointSize ?? 4,\n sizeMode: options.sizeMode ?? 'adaptive',\n shape: options.shape ?? 'circle',\n edl: options.edl ?? false,\n classifications: options.classifications ?? {},\n ...(options.elevationRange ? { elevationRange: options.elevationRange } : {}),\n elevationRamp: options.elevationRamp ?? ELEVATION_RAMP,\n ...(options.intensityRange ? { intensityRange: options.intensityRange } : {}),\n maxScreenSpaceError: options.maxScreenSpaceError ?? (tiles ? 16 : 1.5),\n pointBudget: options.pointBudget ?? 3_000_000,\n };\n }\n\n /** @internal Drawn by the engine with 3D Tiles (the point cloud module loads with the first one) */\n override get needsFullEngine(): boolean {\n return true;\n }\n\n /** Changes the style, the rest kept */\n setStyle(style: Partial<PointCloudStyle>): void {\n this.style = { ...this.style, ...style };\n // Kept for its creation while the engine with 3D Tiles loads\n if (this.id < 0) return;\n this.apply(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n getStyle(): Readonly<PointCloudStyle> {\n return this.style;\n }\n\n /** Loading counters; undefined once removed and while the engine with 3D Tiles loads */\n stats(): PointCloudStats | Tiles3dStats | undefined {\n if (this.id < 0) return undefined;\n\n return this.format === '3dtiles' ? this.map.engine.tiles3dStats(this.id) : this.map.engine.pointCloudStats(this.id);\n }\n\n /** What a COPC file says of itself (points, format, CRS, center, altitudes), once its head is read */\n info(): PointCloudInfo | undefined {\n return this.id < 0 || this.format === '3dtiles' ? undefined : this.map.engine.pointCloudInfo(this.id);\n }\n\n /** @internal The point picked (`pickFeature`, 'hoverfeature'): a Point at its longitude, latitude and height, its\n * attributes as properties */\n featureAt(index: number): Feature<PointCloudPoint> | undefined {\n if (this.id < 0 || this.format === '3dtiles') return undefined;\n\n const point = this.map.engine.pointCloudPoint(this.id, index);\n\n if (!point) return undefined;\n\n return {\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [...point.lonLat, point.height] },\n properties: point,\n };\n }\n\n private apply(engine: Engine, id: number): void {\n const s = this.style;\n\n if (this.format === '3dtiles') {\n engine.setTiles3dStyle(id, s.maxScreenSpaceError, 1, s.pointSize, new Float32Array());\n\n return;\n }\n\n const rate = this.options.requestsPerSecond ?? (/^https?:\\/\\/data\\.geopf\\.fr\\//.test(this.url) ? 8 : 0);\n\n engine.setPointCloudStyle(\n id,\n styleNumbers(s, rate),\n classPalette(s.classifications),\n rampTexels(s.elevationRamp).rgba,\n );\n }\n\n /** @internal */\n protected create(engine: Engine): number {\n const id =\n this.format === '3dtiles'\n ? engine.addTiles3d(this.url, this.style.maxScreenSpaceError)\n : engine.addPointCloud(this.url, (wkt) => pointCloudCrs(wkt, this.options));\n\n this.apply(engine, id);\n\n return id;\n }\n}\n"]}
@@ -103,4 +103,4 @@ export declare class SymbolLayer<P = Properties> extends Layer {
103
103
  private send;
104
104
  private sendLayer;
105
105
  }
106
- export declare function symbolStyle<P>(options: SymbolOptions<P>): SymbolStyle<P>;
106
+ export declare const symbolStyle: <P>(options: SymbolOptions<P>) => SymbolStyle<P>;