isard 0.8.0 → 1.1.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 (180) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/{basemaps.d.ts → basemap/basemaps.d.ts} +4 -4
  3. package/dist/{basemaps.js → basemap/basemaps.js} +3 -15
  4. package/dist/basemap/basemaps.js.map +1 -0
  5. package/dist/{grid.d.ts → basemap/grid.d.ts} +1 -1
  6. package/dist/{grid.js → basemap/grid.js} +2 -2
  7. package/dist/basemap/grid.js.map +1 -0
  8. package/dist/basemap/mvt.js.map +1 -0
  9. package/dist/{pmtiles.d.ts → basemap/pmtiles.d.ts} +6 -0
  10. package/dist/{pmtiles.js → basemap/pmtiles.js} +2 -2
  11. package/dist/basemap/pmtiles.js.map +1 -0
  12. package/dist/{resample.d.ts → basemap/resample.d.ts} +9 -0
  13. package/dist/{resample.js → basemap/resample.js} +2 -2
  14. package/dist/basemap/resample.js.map +1 -0
  15. package/dist/{terrain.js → basemap/terrain.js} +1 -1
  16. package/dist/basemap/terrain.js.map +1 -0
  17. package/dist/{vectorstyle.js → basemap/vectorstyle.js} +1 -1
  18. package/dist/basemap/vectorstyle.js.map +1 -0
  19. package/dist/{vectortiles.d.ts → basemap/vectortiles.d.ts} +9 -9
  20. package/dist/{vectortiles.js → basemap/vectortiles.js} +19 -8
  21. package/dist/basemap/vectortiles.js.map +1 -0
  22. package/dist/{wmts.js → basemap/wmts.js} +3 -3
  23. package/dist/basemap/wmts.js.map +1 -0
  24. package/dist/basemap.worker.js +2 -2
  25. package/dist/basemap.worker.js.map +10 -10
  26. package/dist/bind/layers.d.ts +37 -0
  27. package/dist/bind/layers.js +130 -0
  28. package/dist/bind/layers.js.map +1 -0
  29. package/dist/{crs.d.ts → data/crs.d.ts} +1 -1
  30. package/dist/data/crs.js.map +1 -0
  31. package/dist/{gpx.d.ts → data/gpx.d.ts} +1 -1
  32. package/dist/data/gpx.js.map +1 -0
  33. package/dist/{kml.d.ts → data/kml.d.ts} +1 -1
  34. package/dist/data/kml.js.map +1 -0
  35. package/dist/{topojson.d.ts → data/topojson.d.ts} +1 -1
  36. package/dist/data/topojson.js.map +1 -0
  37. package/dist/data/xml.js.map +1 -0
  38. package/dist/decoder.worker.js +1 -1
  39. package/dist/decoder.worker.js.map +4 -4
  40. package/dist/{decoders.d.ts → engine/decoders.d.ts} +1 -1
  41. package/dist/engine/decoders.js.map +1 -0
  42. package/dist/{loader.d.ts → engine/loader.d.ts} +1 -1
  43. package/dist/{loader.js → engine/loader.js} +4 -0
  44. package/dist/engine/loader.js.map +1 -0
  45. package/dist/{protocol.d.ts → engine/protocol.d.ts} +1 -1
  46. package/dist/engine/protocol.js +3 -0
  47. package/dist/engine/protocol.js.map +1 -0
  48. package/dist/engine/requests.js.map +1 -0
  49. package/dist/engine-loader.d.ts +16 -5
  50. package/dist/engine-loader.js +39 -8
  51. package/dist/engine-loader.js.map +1 -1
  52. package/dist/formats.d.ts +3 -3
  53. package/dist/formats.js +3 -3
  54. package/dist/formats.js.map +1 -1
  55. package/dist/geoplateforme.d.ts +53 -3
  56. package/dist/geoplateforme.js +35 -1
  57. package/dist/geoplateforme.js.map +1 -1
  58. package/dist/index.d.ts +32 -32
  59. package/dist/index.js +19 -19
  60. package/dist/index.js.map +1 -1
  61. package/dist/isard_bg.wasm +0 -0
  62. package/dist/isard_core_bg.wasm +0 -0
  63. package/dist/layers/extrusions.js.map +1 -0
  64. package/dist/{features.js → layers/features.js} +3 -3
  65. package/dist/layers/features.js.map +1 -0
  66. package/dist/{glyphs.d.ts → layers/glyphs.d.ts} +3 -3
  67. package/dist/{glyphs.js → layers/glyphs.js} +11 -1
  68. package/dist/layers/glyphs.js.map +1 -0
  69. package/dist/{icons.d.ts → layers/icons.d.ts} +2 -2
  70. package/dist/{icons.js → layers/icons.js} +8 -1
  71. package/dist/layers/icons.js.map +1 -0
  72. package/dist/{layers.d.ts → layers/layers.d.ts} +11 -5
  73. package/dist/{layers.js → layers/layers.js} +17 -6
  74. package/dist/layers/layers.js.map +1 -0
  75. package/dist/{panoramas.d.ts → layers/panoramas.d.ts} +1 -1
  76. package/dist/{panoramas.js → layers/panoramas.js} +2 -2
  77. package/dist/layers/panoramas.js.map +1 -0
  78. package/dist/{pointclouds.d.ts → layers/pointclouds.d.ts} +2 -2
  79. package/dist/{pointclouds.js → layers/pointclouds.js} +1 -1
  80. package/dist/layers/pointclouds.js.map +1 -0
  81. package/dist/{symbols.d.ts → layers/symbols.d.ts} +2 -2
  82. package/dist/{symbols.js → layers/symbols.js} +1 -1
  83. package/dist/layers/symbols.js.map +1 -0
  84. package/dist/map.d.ts +93 -12
  85. package/dist/map.js +119 -28
  86. package/dist/map.js.map +1 -1
  87. package/dist/projections.d.ts +3 -3
  88. package/dist/projections.js +2 -2
  89. package/dist/projections.js.map +1 -1
  90. package/dist/react/index.d.ts +119 -0
  91. package/dist/react/index.js +409 -0
  92. package/dist/react/index.js.map +1 -0
  93. package/dist/settings.d.ts +1 -1
  94. package/dist/settings.js +2 -2
  95. package/dist/settings.js.map +1 -1
  96. package/dist/types.d.ts +16 -12
  97. package/dist/types.js +1 -0
  98. package/dist/types.js.map +1 -1
  99. package/dist/{controls.d.ts → ui/controls.d.ts} +5 -4
  100. package/dist/{controls.js → ui/controls.js} +0 -8
  101. package/dist/ui/controls.js.map +1 -0
  102. package/dist/{interaction.d.ts → ui/interaction.d.ts} +7 -3
  103. package/dist/{interaction.js → ui/interaction.js} +1 -1
  104. package/dist/ui/interaction.js.map +1 -0
  105. package/dist/{overlay.d.ts → ui/overlay.d.ts} +2 -2
  106. package/dist/ui/overlay.js.map +1 -0
  107. package/dist/ui/style.js.map +1 -0
  108. package/dist/{animation.d.ts → util/animation.d.ts} +6 -2
  109. package/dist/util/animation.js.map +1 -0
  110. package/dist/util/color.js.map +1 -0
  111. package/dist/util/geo.js.map +1 -0
  112. package/dist/util/lru.js.map +1 -0
  113. package/dist/{basemap.worker.d.ts → workers/basemap.worker.d.ts} +14 -4
  114. package/dist/workers/basemap.worker.js +647 -0
  115. package/dist/workers/basemap.worker.js.map +1 -0
  116. package/package.json +31 -2
  117. package/vite.d.ts +17 -0
  118. package/vite.js +64 -0
  119. package/dist/animation.js.map +0 -1
  120. package/dist/basemaps.js.map +0 -1
  121. package/dist/color.js.map +0 -1
  122. package/dist/controls.js.map +0 -1
  123. package/dist/crs.js.map +0 -1
  124. package/dist/decoders.js.map +0 -1
  125. package/dist/extrusions.js.map +0 -1
  126. package/dist/features.js.map +0 -1
  127. package/dist/geo.js.map +0 -1
  128. package/dist/glyphs.js.map +0 -1
  129. package/dist/gpx.js.map +0 -1
  130. package/dist/grid.js.map +0 -1
  131. package/dist/icons.js.map +0 -1
  132. package/dist/interaction.js.map +0 -1
  133. package/dist/kml.js.map +0 -1
  134. package/dist/layers.js.map +0 -1
  135. package/dist/loader.js.map +0 -1
  136. package/dist/lru.js.map +0 -1
  137. package/dist/mvt.js.map +0 -1
  138. package/dist/overlay.js.map +0 -1
  139. package/dist/panoramas.js.map +0 -1
  140. package/dist/pmtiles.js.map +0 -1
  141. package/dist/pointclouds.js.map +0 -1
  142. package/dist/protocol.js +0 -2
  143. package/dist/protocol.js.map +0 -1
  144. package/dist/requests.js.map +0 -1
  145. package/dist/resample.js.map +0 -1
  146. package/dist/style.js.map +0 -1
  147. package/dist/symbols.js.map +0 -1
  148. package/dist/terrain.js.map +0 -1
  149. package/dist/topojson.js.map +0 -1
  150. package/dist/vectorstyle.js.map +0 -1
  151. package/dist/vectortiles.js.map +0 -1
  152. package/dist/wmts.js.map +0 -1
  153. package/dist/xml.js.map +0 -1
  154. /package/dist/{mvt.d.ts → basemap/mvt.d.ts} +0 -0
  155. /package/dist/{mvt.js → basemap/mvt.js} +0 -0
  156. /package/dist/{terrain.d.ts → basemap/terrain.d.ts} +0 -0
  157. /package/dist/{vectorstyle.d.ts → basemap/vectorstyle.d.ts} +0 -0
  158. /package/dist/{wmts.d.ts → basemap/wmts.d.ts} +0 -0
  159. /package/dist/{crs.js → data/crs.js} +0 -0
  160. /package/dist/{gpx.js → data/gpx.js} +0 -0
  161. /package/dist/{kml.js → data/kml.js} +0 -0
  162. /package/dist/{topojson.js → data/topojson.js} +0 -0
  163. /package/dist/{xml.d.ts → data/xml.d.ts} +0 -0
  164. /package/dist/{xml.js → data/xml.js} +0 -0
  165. /package/dist/{decoders.js → engine/decoders.js} +0 -0
  166. /package/dist/{requests.d.ts → engine/requests.d.ts} +0 -0
  167. /package/dist/{requests.js → engine/requests.js} +0 -0
  168. /package/dist/{extrusions.d.ts → layers/extrusions.d.ts} +0 -0
  169. /package/dist/{extrusions.js → layers/extrusions.js} +0 -0
  170. /package/dist/{features.d.ts → layers/features.d.ts} +0 -0
  171. /package/dist/{overlay.js → ui/overlay.js} +0 -0
  172. /package/dist/{style.d.ts → ui/style.d.ts} +0 -0
  173. /package/dist/{style.js → ui/style.js} +0 -0
  174. /package/dist/{animation.js → util/animation.js} +0 -0
  175. /package/dist/{color.d.ts → util/color.d.ts} +0 -0
  176. /package/dist/{color.js → util/color.js} +0 -0
  177. /package/dist/{geo.d.ts → util/geo.d.ts} +0 -0
  178. /package/dist/{geo.js → util/geo.js} +0 -0
  179. /package/dist/{lru.d.ts → util/lru.d.ts} +0 -0
  180. /package/dist/{lru.js → util/lru.js} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decoders.js","sourceRoot":"","sources":["../../src/engine/decoders.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Optional decoders of the worker, loaded on first use from configurable URLs (the official builds three.js and\n * Cesium use): Draco geometry (`KHR_draco_mesh_compression`) and KTX2 / Basis Universal textures (`KHR_texture_basisu`),\n * transcoded to the best compressed format the GPU supports.\n */\nimport type { CompressedTexture, DracoGeometry, DracoRequest, TextureFormats } from '../wasm/isard.js';\n\n/**\n * Base URLs of the decoders (each ending with `/`).\n *\n * The decoders are Emscripten builds published as classic scripts: the worker fetches the script and runs it with\n * `new Function`, so a Content Security Policy must allow `'unsafe-eval'` in `script-src` (or `worker-src`) for 3D\n * Tiles that use Draco or KTX2. They are fetched from the default CDNs; to self-host them (offline, locked-down\n * networks, no third-party requests), copy the four files (`draco_wasm_wrapper_gltf.js`, `draco_decoder_gltf.wasm`\n * from the Draco release, `basis_transcoder.js`, `basis_transcoder.wasm` from three.js's `examples/jsm/libs/basis/`)\n * to your server and give their folders in `GeoMapOptions.decoders`.\n */\nexport interface DecoderUrls {\n /** Folder of `draco_wasm_wrapper_gltf.js` and `draco_decoder_gltf.wasm` (and, for Draco point clouds, of the full\n * decoder `draco_wasm_wrapper.js` and `draco_decoder.wasm`) */\n draco: string;\n /** Folder of `basis_transcoder.js` and `basis_transcoder.wasm` */\n basis: string;\n}\n\nexport const DEFAULT_DECODERS: DecoderUrls = {\n draco: 'https://www.gstatic.com/draco/versioned/decoders/1.5.7/',\n basis: 'https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/libs/basis/',\n};\n\n// ── Draco (the subset of its Emscripten API used here) ──\n\ninterface DracoStatus {\n ok(): boolean;\n error_msg(): string;\n}\ninterface DracoMesh {\n num_points(): number;\n num_faces(): number;\n}\ninterface DracoAttribute {\n num_components(): number;\n}\ninterface DracoDecoder {\n DecodeArrayToMesh(data: Int8Array, size: number, mesh: DracoMesh): DracoStatus;\n DecodeArrayToPointCloud(data: Int8Array, size: number, cloud: DracoMesh): DracoStatus;\n GetAttributeByUniqueId(mesh: DracoMesh, id: number): DracoAttribute;\n GetAttributeDataArrayForAllPoints(\n mesh: DracoMesh,\n attribute: DracoAttribute,\n type: number,\n bytes: number,\n pointer: number,\n ): boolean;\n GetTrianglesUInt32Array(mesh: DracoMesh, bytes: number, pointer: number): boolean;\n}\ninterface DracoModule {\n Decoder: new () => DracoDecoder;\n Mesh: new () => DracoMesh;\n PointCloud: new () => DracoMesh;\n DT_FLOAT32: number;\n HEAPF32: Float32Array;\n HEAPU32: Uint32Array;\n _malloc(bytes: number): number;\n _free(pointer: number): void;\n destroy(object: object): void;\n}\n\n// ── Basis Universal transcoder ──\n\ninterface KTX2File {\n isValid(): boolean;\n getLevels(): number;\n getHasAlpha(): boolean;\n startTranscoding(): boolean;\n getImageLevelInfo(level: number, layer: number, face: number): { origWidth: number; origHeight: number };\n getImageTranscodedSizeInBytes(level: number, layer: number, face: number, format: number): number;\n transcodeImage(\n target: Uint8Array,\n level: number,\n layer: number,\n face: number,\n format: number,\n alphaForOpaque: number,\n channel0: number,\n channel1: number,\n ): boolean;\n close(): void;\n delete(): void;\n}\ninterface BasisModule {\n initializeBasis(): void;\n KTX2File: new (data: Uint8Array) => KTX2File;\n}\n\ntype Factory<T> = (options: { wasmBinary: ArrayBuffer }) => Promise<T>;\n\n/** Loads an Emscripten factory published as a classic script (module workers have no importScripts); needs\n * `'unsafe-eval'` under a Content Security Policy (see `DecoderUrls`) */\nasync function factory<T>(url: string, name: string): Promise<Factory<T>> {\n const source = await (await fetch(url)).text();\n return new Function(`${source}\\nreturn ${name};`)() as Factory<T>;\n}\n\nasync function instantiate<T>(base: string, script: string, wasm: string, name: string): Promise<T> {\n const [create, binary] = await Promise.all([\n factory<T>(`${base}${script}`, name),\n fetch(`${base}${wasm}`).then((r) => r.arrayBuffer()),\n ]);\n return create({ wasmBinary: binary });\n}\n\nlet draco: Promise<DracoModule> | undefined;\n/** The full Draco decoder: the glTF build decodes meshes only, not the point clouds */\nlet dracoPoints: Promise<DracoModule> | undefined;\nlet basis: Promise<BasisModule> | undefined;\n\n/** Decodes the Draco primitives of a tile (their points alone for point clouds) */\nexport async function decodeDraco(urls: DecoderUrls, requests: DracoRequest[]): Promise<DracoGeometry[]> {\n const meshes = requests.some((r) => !r.points);\n if (meshes) {\n draco ??= instantiate<DracoModule>(\n urls.draco,\n 'draco_wasm_wrapper_gltf.js',\n 'draco_decoder_gltf.wasm',\n 'DracoDecoderModule',\n );\n }\n if (requests.some((r) => r.points)) {\n dracoPoints ??= instantiate<DracoModule>(\n urls.draco,\n 'draco_wasm_wrapper.js',\n 'draco_decoder.wasm',\n 'DracoDecoderModule',\n );\n }\n const [forMeshes, forPoints] = await Promise.all([meshes ? draco : undefined, dracoPoints]);\n return requests.map((request) => {\n const module = (request.points ? forPoints : forMeshes) as DracoModule;\n const decoder = new module.Decoder();\n const mesh = request.points ? new module.PointCloud() : new module.Mesh();\n try {\n const data = new Int8Array(request.data.buffer, request.data.byteOffset, request.data.byteLength);\n const status = request.points\n ? decoder.DecodeArrayToPointCloud(data, data.byteLength, mesh)\n : decoder.DecodeArrayToMesh(data, data.byteLength, mesh);\n if (!status.ok()) throw new Error(`Draco: ${status.error_msg()}`);\n const floats = (id: number): Float32Array => {\n const attribute = decoder.GetAttributeByUniqueId(mesh, id);\n const count = mesh.num_points() * attribute.num_components();\n const pointer = module._malloc(count * 4);\n try {\n decoder.GetAttributeDataArrayForAllPoints(mesh, attribute, module.DT_FLOAT32, count * 4, pointer);\n return module.HEAPF32.slice(pointer / 4, pointer / 4 + count);\n } finally {\n module._free(pointer);\n }\n };\n if (request.points) {\n const geometry: DracoGeometry = {\n mesh: request.mesh,\n primitive: request.primitive,\n positions: floats(request.position),\n };\n if (request.color !== undefined) geometry.colors = floats(request.color);\n if (request.normal !== undefined) geometry.normals = floats(request.normal);\n return geometry;\n }\n const count = mesh.num_faces() * 3;\n const pointer = module._malloc(count * 4);\n let indices: Uint32Array;\n try {\n decoder.GetTrianglesUInt32Array(mesh, count * 4, pointer);\n indices = module.HEAPU32.slice(pointer / 4, pointer / 4 + count);\n } finally {\n module._free(pointer);\n }\n const geometry: DracoGeometry = {\n mesh: request.mesh,\n primitive: request.primitive,\n positions: floats(request.position),\n indices,\n };\n if (request.uv !== undefined) geometry.uvs = floats(request.uv);\n return geometry;\n } finally {\n module.destroy(mesh);\n module.destroy(decoder);\n }\n });\n}\n\n/** Basis target format and WebGL internal format, best first */\nfunction target(formats: TextureFormats, alpha: boolean): { basis: number; gl: number } {\n if (formats.astc) return { basis: 10, gl: 0x93b0 }; // ASTC 4×4\n if (formats.bptc) return { basis: 6, gl: 0x8e8c }; // BC7\n if (formats.etc) return alpha ? { basis: 1, gl: 0x9278 } : { basis: 0, gl: 0x9274 }; // ETC2 RGBA / ETC1 as ETC2 RGB\n if (formats.s3tc) return alpha ? { basis: 3, gl: 0x83f3 } : { basis: 2, gl: 0x83f0 }; // BC3 / BC1\n return { basis: 13, gl: 0x8058 }; // RGBA8, uncompressed\n}\n\n/** Transcodes a KTX2 image for the GPU */\nexport async function transcodeKtx2(\n urls: DecoderUrls,\n formats: TextureFormats,\n bytes: Uint8Array,\n): Promise<CompressedTexture> {\n basis ??= instantiate<BasisModule>(urls.basis, 'basis_transcoder.js', 'basis_transcoder.wasm', 'BASIS').then((m) => {\n m.initializeBasis();\n return m;\n });\n const module = await basis;\n const file = new module.KTX2File(bytes);\n try {\n if (!file.isValid() || !file.startTranscoding()) throw new Error('KTX2: invalid file');\n const { basis: format, gl } = target(formats, file.getHasAlpha());\n const levels: CompressedTexture['levels'] = [];\n for (let level = 0; level < file.getLevels(); level++) {\n const { origWidth: width, origHeight: height } = file.getImageLevelInfo(level, 0, 0);\n const data = new Uint8Array(file.getImageTranscodedSizeInBytes(level, 0, 0, format));\n if (!file.transcodeImage(data, level, 0, 0, format, 0, -1, -1)) throw new Error('KTX2: transcoding failed');\n levels.push({ width, height, data });\n }\n return { format: gl, levels };\n } finally {\n file.close();\n file.delete();\n }\n}\n"]}
@@ -2,8 +2,8 @@
2
2
  * Pool of decoding workers for 3D Tiles content and point clouds. The engine calls `load`, `loadPoints` and `abort`
3
3
  * (`TileLoaderLike`); the main thread then only uploads the decoded arrays to the GPU.
4
4
  */
5
+ import type { DecodedTile, TextureFormats, TileLoaderLike } from '../wasm/isard.js';
5
6
  import type { DecoderUrls } from './decoders.ts';
6
- import type { DecodedTile, TextureFormats, TileLoaderLike } from './wasm/isard.js';
7
7
  export declare class TileLoader implements TileLoaderLike {
8
8
  private readonly module;
9
9
  private readonly workerUrl;
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Pool of decoding workers for 3D Tiles content and point clouds. The engine calls `load`, `loadPoints` and `abort`
3
+ * (`TileLoaderLike`); the main thread then only uploads the decoded arrays to the GPU.
4
+ */
1
5
  import { headerRules, onHeaderRules } from "./requests.js";
2
6
  export class TileLoader {
3
7
  module;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/engine/loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pool of decoding workers for 3D Tiles content and point clouds. The engine calls `load`, `loadPoints` and `abort`\n * (`TileLoaderLike`); the main thread then only uploads the decoded arrays to the GPU.\n */\n\nimport type { DecodedTile, TextureFormats, TileLoaderLike } from '../wasm/isard.js';\nimport type { DecoderUrls } from './decoders.ts';\nimport type { WorkerReply, WorkerRequest } from './protocol.ts';\nimport { headerRules, onHeaderRules } from './requests.ts';\n\ninterface Pending {\n resolve: (result: DecodedTile | Uint8Array<ArrayBuffer>) => void;\n reject: (error: Error) => void;\n worker: Worker;\n}\n\nexport class TileLoader implements TileLoaderLike {\n private workers: Worker[] = [];\n /** Requests in flight per worker */\n private readonly busy = new Map<Worker, number>();\n private readonly pending = new Map<number, Pending>();\n /** Every worker failed: why */\n private failed: Error | undefined;\n /** The page's request headers, sent to the workers as they change */\n private readonly unfollow = onHeaderRules((rules) => {\n for (const worker of this.workers) this.send(worker, { type: 'headers', rules });\n });\n\n constructor(\n private readonly module: WebAssembly.Module,\n private readonly workerUrl: string | URL,\n private readonly size: number,\n private readonly decoders: DecoderUrls,\n private readonly formats: TextureFormats,\n /** URL of the point cloud module, for the workers */\n private readonly points: string = '',\n ) {}\n\n /** Called by the engine: fetch and decode off the main thread, on the least busy worker */\n load(\n id: number,\n url: string,\n transform: Float64Array,\n yUp: boolean,\n reload: boolean,\n priority?: 'high' | 'low',\n ): Promise<DecodedTile> {\n if (this.failed) return Promise.reject(this.failed);\n const worker = this.leastBusy();\n this.busy.set(worker, (this.busy.get(worker) ?? 0) + 1);\n return new Promise((resolve, reject) => {\n this.pending.set(id, { resolve: resolve as Pending['resolve'], reject, worker });\n this.send(worker, { type: 'load', id, url, transform, yUp, reload, ...(priority ? { priority } : {}) });\n });\n }\n\n /** Called by the engine: the points of a COPC node, fetched (a range request) and decoded off the main thread */\n loadPoints(\n id: number,\n url: string,\n offset: number,\n size: number,\n laz: Uint8Array,\n layout: Float64Array,\n grid: Float64Array,\n count: number,\n priority?: 'high' | 'low',\n ): Promise<Uint8Array<ArrayBuffer>> {\n if (this.failed) return Promise.reject(this.failed);\n const worker = this.leastBusy();\n this.busy.set(worker, (this.busy.get(worker) ?? 0) + 1);\n return new Promise((resolve, reject) => {\n this.pending.set(id, { resolve: resolve as Pending['resolve'], reject, worker });\n const message = { type: 'points', id, url, offset, size, laz, layout, grid, count } as const;\n this.send(worker, { ...message, ...(priority ? { priority } : {}) });\n });\n }\n\n abort(id: number): void {\n const pending = this.pending.get(id);\n if (pending) this.send(pending.worker, { type: 'abort', id });\n }\n\n destroy(): void {\n this.unfollow();\n for (const worker of this.workers) worker.terminate();\n this.workers = [];\n this.busy.clear();\n for (const { reject } of this.pending.values()) reject(new Error('loader destroyed'));\n this.pending.clear();\n }\n\n /** Workers start with the first tile: a map without 3D Tiles costs nothing */\n private leastBusy(): Worker {\n if (this.workers.length === 0) {\n for (let i = 0; i < this.size; i++) {\n const worker = new Worker(this.workerUrl, { type: 'module' });\n worker.onmessage = (event: MessageEvent<WorkerReply>) => this.receive(worker, event.data);\n // A worker that fails to load (a bundler serving it from elsewhere) or to read a message fails its requests\n worker.onerror = (event) => {\n event.preventDefault();\n this.fail(worker, `the decoding worker ${this.workerUrl} failed${event.message ? `: ${event.message}` : ''}`);\n };\n worker.onmessageerror = () =>\n this.fail(worker, `the decoding worker ${this.workerUrl} sent an unreadable message`);\n const { module, decoders, formats, points } = this;\n this.send(worker, { type: 'init', module, decoders, formats, points });\n const rules = headerRules();\n if (rules.length > 0) this.send(worker, { type: 'headers', rules });\n this.workers.push(worker);\n this.busy.set(worker, 0);\n }\n }\n let best = this.workers[0] as Worker;\n for (const worker of this.workers) {\n if ((this.busy.get(worker) ?? 0) < (this.busy.get(best) ?? 0)) best = worker;\n }\n return best;\n }\n\n private send(worker: Worker, message: WorkerRequest): void {\n worker.postMessage(message);\n }\n\n private receive(worker: Worker, reply: WorkerReply): void {\n this.busy.set(worker, Math.max(0, (this.busy.get(worker) ?? 1) - 1));\n const pending = this.pending.get(reply.id);\n if (!pending) return;\n this.pending.delete(reply.id);\n if (reply.type === 'tile') pending.resolve(reply.tile);\n else if (reply.type === 'points') pending.resolve(reply.vertices);\n else if (reply.aborted) pending.reject(new DOMException(`tile ${reply.id} aborted`, 'AbortError'));\n else pending.reject(new Error(reply.error));\n }\n\n /** Rejects the requests of a failed worker */\n private fail(worker: Worker, message: string): void {\n const error = new Error(\n `isard: ${message}. If a bundler moves the worker, give its URL in the \\`workerUrl\\` option (see \"With a bundler\" in the guide)`,\n );\n for (const [id, pending] of this.pending) {\n if (pending.worker !== worker) continue;\n this.pending.delete(id);\n pending.reject(error);\n }\n // Out of the pool: when none is left, the next requests fail at once\n worker.terminate();\n this.workers = this.workers.filter((w) => w !== worker);\n this.busy.delete(worker);\n if (this.workers.length === 0) this.failed = error;\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  /** Messages between the main thread and the decoding workers */
2
+ import type { DecodedTile, TextureFormats } from '../wasm/isard.js';
2
3
  import type { DecoderUrls } from './decoders.ts';
3
4
  import type { HeaderRules } from './requests.ts';
4
- import type { DecodedTile, TextureFormats } from './wasm/isard.js';
5
5
  export type WorkerRequest =
6
6
  /** The page's request headers (`setRequestHeaders`) */
7
7
  {
@@ -0,0 +1,3 @@
1
+ /** Messages between the main thread and the decoding workers */
2
+ export {};
3
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/engine/protocol.ts"],"names":[],"mappings":"AAAA,gEAAgE","sourcesContent":["/** Messages between the main thread and the decoding workers */\n\nimport type { DecodedTile, TextureFormats } from '../wasm/isard.js';\nimport type { DecoderUrls } from './decoders.ts';\nimport type { HeaderRules } from './requests.ts';\n\nexport type WorkerRequest =\n /** The page's request headers (`setRequestHeaders`) */\n | { type: 'headers'; rules: HeaderRules }\n | {\n type: 'init';\n module: WebAssembly.Module;\n decoders: DecoderUrls;\n formats: TextureFormats;\n /** URL of the point cloud module (`isard_points_bg.wasm`), loaded with the first COPC chunk */\n points: string;\n }\n | {\n type: 'load';\n id: number;\n url: string;\n transform: Float64Array;\n yUp: boolean;\n reload: boolean;\n priority?: 'high' | 'low';\n }\n | {\n type: 'points';\n id: number;\n url: string;\n offset: number;\n size: number;\n laz: Uint8Array;\n layout: Float64Array;\n grid: Float64Array;\n count: number;\n priority?: 'high' | 'low';\n }\n | { type: 'abort'; id: number };\n\nexport type WorkerReply =\n | { type: 'tile'; id: number; tile: DecodedTile }\n | { type: 'points'; id: number; vertices: Uint8Array<ArrayBuffer> }\n | { type: 'error'; id: number; error: string; aborted: boolean };\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests.js","sourceRoot":"","sources":["../../src/engine/requests.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,IAAI,KAAK,GAAgB,EAAE,CAAC;AAC5B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAgC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,OAAgC;IAChF,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;IACjD,IAAI,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC;IACpF,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IAC7C,cAAc,CAAC,IAAI,CAAC,CAAC;IACrB,KAAK,MAAM,QAAQ,IAAI,SAAS;QAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;AACpD,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,WAAW;IACzB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,cAAc,CAAC,IAAiB;IAC9C,KAAK,GAAG,IAAI,CAAC;AACf,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,aAAa,CAAC,QAAsC;IAClE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,WAAW,CAAwB,GAAiB,EAAE,IAAQ;IAC5E,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,IAAK,EAAQ,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,QAAQ;QAAE,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1G,OAAO,EAAE,GAAG,CAAC,IAAI,IAAK,EAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;AAC7C,CAAC","sourcesContent":["/**\n * Headers added to the requests of the page by URL prefix: an access token for private sources (a Géoplateforme\n * private stream, a server behind single sign-on), on every request isard makes, from the page, its workers (vector\n * tiles, 3D Tiles and point clouds) and its engine (raster tiles, tilesets): `setRequestHeaders(prefix, headers)`,\n * again with a new token when it is renewed. The rules of a URL are merged, the longest prefix last (it wins).\n */\n\n/** Rules: a URL prefix and its headers, the shortest prefix first */\nexport type HeaderRules = [prefix: string, headers: Record<string, string>][];\n\nlet rules: HeaderRules = [];\nconst listeners = new Set<(rules: HeaderRules) => void>();\n\n/**\n * Adds `headers` to every request isard makes to a URL starting with `prefix` (in the page and its workers), or with\n * no headers, stops: `setRequestHeaders('https://data.geopf.fr/private/', { Authorization: 'Bearer …' })`. The\n * server must allow these headers (CORS). For the whole page: every map, the ones to come too\n */\nexport function setRequestHeaders(prefix: string, headers?: Record<string, string>): void {\n const kept = rules.filter(([p]) => p !== prefix);\n if (headers && Object.keys(headers).length > 0) kept.push([prefix, { ...headers }]);\n kept.sort(([p], [q]) => p.length - q.length);\n setHeaderRules(kept);\n for (const listener of listeners) listener(rules);\n}\n\n/** @internal The rules now */\nexport function headerRules(): HeaderRules {\n return rules;\n}\n\n/** @internal The rules, from the page (a worker's copy) */\nexport function setHeaderRules(next: HeaderRules): void {\n rules = next;\n}\n\n/** @internal Follows the rules (the workers and engines of a map); returns the function that stops */\nexport function onHeaderRules(listener: (rules: HeaderRules) => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\n/** @internal `init` with the headers of the rules matching `url` (unchanged when none does) */\nexport function withHeaders<T extends RequestInit>(url: string | URL, init?: T): T {\n const href = String(url);\n const matching = rules.filter(([prefix]) => href.startsWith(prefix));\n if (matching.length === 0) return init ?? ({} as T);\n const headers = new Headers(init?.headers);\n for (const [, set] of matching) for (const [name, value] of Object.entries(set)) headers.set(name, value);\n return { ...(init ?? ({} as T)), headers };\n}\n"]}
@@ -1,4 +1,8 @@
1
- import { TileLoader } from './loader.ts';
1
+ /**
2
+ * The two builds of the engine, downloaded, compiled and instantiated once per page; the decoding workers of 3D Tiles
3
+ * that run the full one; the engine of a destroyed map.
4
+ */
5
+ import { TileLoader } from './engine/loader.ts';
2
6
  import type { GeoMapOptions } from './types.ts';
3
7
  import type { Camera, Engine } from './wasm/isard.js';
4
8
  /** The class of an engine build: its constructor and its static `customMatrix` (custom layers) */
@@ -10,8 +14,15 @@ export interface Bindings {
10
14
  }
11
15
  /** `core`: the engine without 3D Tiles; `full`: with them */
12
16
  export type EngineKind = 'core' | 'full';
13
- /** Where a build of the engine is loaded from: the option, or next to the module */
14
- export declare function engineUrl(kind: EngineKind, options: Pick<GeoMapOptions, 'wasmUrl' | 'coreWasmUrl'>): string | URL;
17
+ /** The files a map loads at run time, next to the module unless given elsewhere */
18
+ export type AssetFile = 'isard_bg.wasm' | 'isard_core_bg.wasm' | 'isard_points_bg.wasm' | 'decoder.worker.js' | 'basemap.worker.js';
19
+ /**
20
+ * Where a file of isard is loaded from: its own option, else in the folder `assetsUrl` (the option, or the page's
21
+ * as `isard/vite` sets it), else next to the module (`import.meta.url`)
22
+ */
23
+ export declare function assetUrl(file: AssetFile, explicit: string | URL | undefined, assetsUrl?: string | URL): string | URL;
24
+ /** Where a build of the engine is loaded from: the option, the assets' folder, or next to the module */
25
+ export declare function engineUrl(kind: EngineKind, options: Pick<GeoMapOptions, 'wasmUrl' | 'coreWasmUrl' | 'assetsUrl'>): string | URL;
15
26
  /** A build compiled and instantiated with its bindings (once per page, unless it failed) */
16
27
  export declare function loadEngine(kind: EngineKind, url: string | URL): Promise<Bindings>;
17
28
  /** The full engine for a map on the core one, resolved in a task of its own, not in the one that instantiated it:
@@ -22,10 +33,10 @@ export declare function loadFullEngineLater(url: string | URL): Promise<Bindings
22
33
  export declare function preloadFullEngine(url: string | URL, wanted: () => boolean): void;
23
34
  /** Where the workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder): the option, or next
24
35
  * to the module; absolute, the workers being elsewhere */
25
- export declare function pointsUrl(options: Pick<GeoMapOptions, 'pointsWasmUrl'>): string;
36
+ export declare function pointsUrl(options: Pick<GeoMapOptions, 'pointsWasmUrl' | 'assetsUrl'>): string;
26
37
  /** The decoding workers of 3D Tiles and point clouds, running the full engine's module, unless turned off (`workers:
27
38
  * false` or 0, or no workers in this environment) */
28
- export declare function startTileLoader(module: WebAssembly.Module, options: Pick<GeoMapOptions, 'workers' | 'workerUrl' | 'decoders' | 'pointsWasmUrl'>, engine: Engine): TileLoader | undefined;
39
+ export declare function startTileLoader(module: WebAssembly.Module, options: Pick<GeoMapOptions, 'workers' | 'workerUrl' | 'decoders' | 'pointsWasmUrl' | 'assetsUrl'>, engine: Engine): TileLoader | undefined;
29
40
  /** The engine of a destroyed map: every method a no-op returning undefined, but the camera (the last one) and the
30
41
  * bounds, which late callers read */
31
42
  export declare function destroyedEngine(camera: Camera): Engine;
@@ -2,9 +2,9 @@
2
2
  * The two builds of the engine, downloaded, compiled and instantiated once per page; the decoding workers of 3D Tiles
3
3
  * that run the full one; the engine of a destroyed map.
4
4
  */
5
- import { DEFAULT_DECODERS } from "./decoders.js";
6
- import { TileLoader } from "./loader.js";
7
- import { defaultWorkerCount } from "./vectortiles.js";
5
+ import { defaultWorkerCount } from "./basemap/vectortiles.js";
6
+ import { DEFAULT_DECODERS } from "./engine/decoders.js";
7
+ import { TileLoader } from "./engine/loader.js";
8
8
  /** The two builds of the engine, each compiled once per page: `core` without 3D Tiles (a third smaller), loaded by
9
9
  * every map; `full` with them, loaded for the first 3D Tiles layer, its module shared with the decoding workers. The
10
10
  * core engine has the same API but the 3D Tiles methods: its class is typed as the full one. */
@@ -19,11 +19,42 @@ export function forgetEngines() {
19
19
  delete modules[kind];
20
20
  }
21
21
  }
22
- /** Where a build of the engine is loaded from: the option, or next to the module */
22
+ /** The folder the assets are served from for the whole page, as `isard/vite` sets it; undefined: next to the module */
23
+ function pageAssets() {
24
+ const url = globalThis.isardAssetsUrl;
25
+ return typeof url === 'string' ? url : undefined;
26
+ }
27
+ /**
28
+ * Where a file of isard is loaded from: its own option, else in the folder `assetsUrl` (the option, or the page's
29
+ * as `isard/vite` sets it), else next to the module (`import.meta.url`)
30
+ */
31
+ export function assetUrl(file, explicit, assetsUrl) {
32
+ if (explicit)
33
+ return explicit;
34
+ const folder = assetsUrl ?? pageAssets();
35
+ if (folder) {
36
+ const base = typeof document === 'undefined' ? undefined : document.baseURI;
37
+ const dir = String(folder).endsWith('/') ? String(folder) : `${String(folder)}/`;
38
+ return new URL(file, base ? new URL(dir, base) : dir);
39
+ }
40
+ switch (file) {
41
+ case 'isard_bg.wasm':
42
+ return new URL('./isard_bg.wasm', import.meta.url);
43
+ case 'isard_core_bg.wasm':
44
+ return new URL('./isard_core_bg.wasm', import.meta.url);
45
+ case 'isard_points_bg.wasm':
46
+ return new URL('./isard_points_bg.wasm', import.meta.url);
47
+ case 'decoder.worker.js':
48
+ return new URL('./decoder.worker.js', import.meta.url);
49
+ default:
50
+ return new URL('./basemap.worker.js', import.meta.url);
51
+ }
52
+ }
53
+ /** Where a build of the engine is loaded from: the option, the assets' folder, or next to the module */
23
54
  export function engineUrl(kind, options) {
24
55
  return kind === 'full'
25
- ? (options.wasmUrl ?? new URL('./isard_bg.wasm', import.meta.url))
26
- : (options.coreWasmUrl ?? new URL('./isard_core_bg.wasm', import.meta.url));
56
+ ? assetUrl('isard_bg.wasm', options.wasmUrl, options.assetsUrl)
57
+ : assetUrl('isard_core_bg.wasm', options.coreWasmUrl, options.assetsUrl);
27
58
  }
28
59
  /** Downloads and compiles a build (once per page, unless it failed: a later call tries again) */
29
60
  function compileEngine(kind, url) {
@@ -90,7 +121,7 @@ async function compile(url) {
90
121
  /** Where the workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder): the option, or next
91
122
  * to the module; absolute, the workers being elsewhere */
92
123
  export function pointsUrl(options) {
93
- const url = options.pointsWasmUrl ?? new URL('./isard_points_bg.wasm', import.meta.url);
124
+ const url = assetUrl('isard_points_bg.wasm', options.pointsWasmUrl, options.assetsUrl);
94
125
  const base = typeof document === 'undefined' ? undefined : document.baseURI;
95
126
  return base ? new URL(url, base).href : String(url);
96
127
  }
@@ -101,7 +132,7 @@ export function startTileLoader(module, options, engine) {
101
132
  const workers = count ?? defaultWorkerCount();
102
133
  if (workers === false || workers <= 0 || typeof Worker === 'undefined')
103
134
  return undefined;
104
- return new TileLoader(module, workerUrl ?? new URL('./decoder.worker.js', import.meta.url), workers, { ...DEFAULT_DECODERS, ...decoders }, engine.textureFormats(), pointsUrl(options));
135
+ return new TileLoader(module, assetUrl('decoder.worker.js', workerUrl, options.assetsUrl), workers, { ...DEFAULT_DECODERS, ...decoders }, engine.textureFormats(), pointsUrl(options));
105
136
  }
106
137
  /** The engine of a destroyed map: every method a no-op returning undefined, but the camera (the last one) and the
107
138
  * bounds, which late callers read */
@@ -1 +1 @@
1
- {"version":3,"file":"engine-loader.js","sourceRoot":"","sources":["../src/engine-loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAmBtD;;gGAEgG;AAChG,MAAM,OAAO,GAA2D,EAAE,CAAC;AAC3E;wFACwF;AACxF,MAAM,OAAO,GAA+E,EAAE,CAAC;AAE/F,mDAAmD;AACnD,MAAM,UAAU,aAAa;IAC3B,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,CAAU,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACrB,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,SAAS,CAAC,IAAgB,EAAE,OAAuD;IACjG,OAAO,IAAI,KAAK,MAAM;QACpB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI,GAAG,CAAC,sBAAsB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,iGAAiG;AACjG,SAAS,aAAa,CAAC,IAAgB,EAAE,GAAiB;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACtD,gEAAgE;QAChE,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,UAAU,CAAC,IAAgB,EAAE,GAAiB;IAC5D,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE;QAC1B,gFAAgF;QAChF,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC3C,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC;YACxB,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;SAC7E,CAAC,CAAC;QACH,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;QACnD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAgC,EAAE,CAAC;IACvE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAC5B,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;oDACoD;AACpD,MAAM,UAAU,mBAAmB,CAAC,GAAiB;IACnD,OAAO,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,CACjC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,OAAO,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CACzF,CAAC;AACJ,CAAC;AAED;uCACuC;AACvC,MAAM,UAAU,iBAAiB,CAAC,GAAiB,EAAE,MAAqB;IACxE,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,MAAM,EAAE;YAAE,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAClE,CAAC,CAAC;IACF,IAAI,OAAO,mBAAmB,KAAK,UAAU;QAAE,mBAAmB,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;;QACxF,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,GAAiB;IACtC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,GAAG,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACtG,IAAI,CAAC;QACH,OAAO,MAAM,WAAW,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;QAC5C,OAAO,WAAW,CAAC,OAAO,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED;0DAC0D;AAC1D,MAAM,UAAU,SAAS,CAAC,OAA6C;IACrE,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxF,MAAM,IAAI,GAAG,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;IAC5E,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACtD,CAAC;AAED;qDACqD;AACrD,MAAM,UAAU,eAAe,CAC7B,MAA0B,EAC1B,OAAoF,EACpF,MAAc;IAEd,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IACxD,MAAM,OAAO,GAAG,KAAK,IAAI,kBAAkB,EAAE,CAAC;IAC9C,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,IAAI,CAAC,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IACzF,OAAO,IAAI,UAAU,CACnB,MAAM,EACN,SAAS,IAAI,IAAI,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAC5D,OAAO,EACP,EAAE,GAAG,gBAAgB,EAAE,GAAG,QAAQ,EAAE,EACpC,MAAM,CAAC,cAAc,EAAE,EACvB,SAAS,CAAC,OAAO,CAAC,CACnB,CAAC;AACJ,CAAC;AAED;qCACqC;AACrC,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,IAAI,KAAK,CACd,EAAE,EACF;QACE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;YACf,IAAI,IAAI,KAAK,QAAQ;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC;YAC3C,IAAI,IAAI,KAAK,QAAQ;gBAAE,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACxE,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC;QACzB,CAAC;KACF,CACQ,CAAC;AACd,CAAC","sourcesContent":["/**\n * The two builds of the engine, downloaded, compiled and instantiated once per page; the decoding workers of 3D Tiles\n * that run the full one; the engine of a destroyed map.\n */\nimport { DEFAULT_DECODERS } from './decoders.ts';\nimport { TileLoader } from './loader.ts';\nimport type { GeoMapOptions } from './types.ts';\nimport { defaultWorkerCount } from './vectortiles.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\n/** The class of an engine build: its constructor and its static `customMatrix` (custom layers) */\nexport type EngineClass = (new (\n canvas: HTMLCanvasElement,\n redraw: () => void,\n) => Engine) &\n Pick<typeof Engine, 'customMatrix' | 'geoidHeight'>;\n\n/** An engine loaded: its compiled module and its class */\nexport interface Bindings {\n module: WebAssembly.Module;\n Engine: EngineClass;\n}\n\n/** `core`: the engine without 3D Tiles; `full`: with them */\nexport type EngineKind = 'core' | 'full';\n\n/** The two builds of the engine, each compiled once per page: `core` without 3D Tiles (a third smaller), loaded by\n * every map; `full` with them, loaded for the first 3D Tiles layer, its module shared with the decoding workers. The\n * core engine has the same API but the 3D Tiles methods: its class is typed as the full one. */\nconst engines: { core?: Promise<Bindings>; full?: Promise<Bindings> } = {};\n/** The modules compiled (downloaded and compiled off the main thread, not instantiated): `tiles3d: 'preload'`\n * compiles the full engine ahead, its first 3D Tiles layer then only instantiates it */\nconst modules: { core?: Promise<WebAssembly.Module>; full?: Promise<WebAssembly.Module> } = {};\n\n/** @internal Forgets the engines loaded (tests) */\nexport function forgetEngines(): void {\n for (const kind of ['core', 'full'] as const) {\n delete engines[kind];\n delete modules[kind];\n }\n}\n\n/** Where a build of the engine is loaded from: the option, or next to the module */\nexport function engineUrl(kind: EngineKind, options: Pick<GeoMapOptions, 'wasmUrl' | 'coreWasmUrl'>): string | URL {\n return kind === 'full'\n ? (options.wasmUrl ?? new URL('./isard_bg.wasm', import.meta.url))\n : (options.coreWasmUrl ?? new URL('./isard_core_bg.wasm', import.meta.url));\n}\n\n/** Downloads and compiles a build (once per page, unless it failed: a later call tries again) */\nfunction compileEngine(kind: EngineKind, url: string | URL): Promise<WebAssembly.Module> {\n const compiled = modules[kind];\n if (compiled) return compiled;\n const compiling = compile(url).catch((error: unknown) => {\n // A later call tries again (a network error, a wrong URL fixed)\n delete modules[kind];\n throw error;\n });\n modules[kind] = compiling;\n return compiling;\n}\n\n/** A build compiled and instantiated with its bindings (once per page, unless it failed) */\nexport function loadEngine(kind: EngineKind, url: string | URL): Promise<Bindings> {\n const loaded = engines[kind];\n if (loaded) return loaded;\n const loading = (async () => {\n // The bindings by dynamic import: an application bundles the ones it loads only\n const [module, bindings] = await Promise.all([\n compileEngine(kind, url),\n kind === 'core' ? import('./wasm/isard_core.js') : import('./wasm/isard.js'),\n ]);\n await bindings.default({ module_or_path: module });\n return { module, Engine: bindings.Engine as unknown as EngineClass };\n })().catch((error: unknown) => {\n delete engines[kind];\n throw error;\n });\n engines[kind] = loading;\n return loading;\n}\n\n/** The full engine for a map on the core one, resolved in a task of its own, not in the one that instantiated it:\n * the map rebuilt on it there, two shorter tasks */\nexport function loadFullEngineLater(url: string | URL): Promise<Bindings> {\n return loadEngine('full', url).then(\n (bindings) => new Promise<Bindings>((resolve) => setTimeout(() => resolve(bindings), 0)),\n );\n}\n\n/** Downloads and compiles the full engine when the page is idle, without running it; a failure is left to the first\n * 3D Tiles layer, which tries again */\nexport function preloadFullEngine(url: string | URL, wanted: () => boolean): void {\n const start = () => {\n if (wanted()) compileEngine('full', url).catch(() => undefined);\n };\n if (typeof requestIdleCallback === 'function') requestIdleCallback(start, { timeout: 2000 });\n else setTimeout(start, 0);\n}\n\nasync function compile(url: string | URL): Promise<WebAssembly.Module> {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`isard: failed to load the engine from ${url}: ${response.status}`);\n try {\n return await WebAssembly.compileStreaming(response.clone());\n } catch {\n // Servers that do not send application/wasm\n return WebAssembly.compile(await response.arrayBuffer());\n }\n}\n\n/** Where the workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder): the option, or next\n * to the module; absolute, the workers being elsewhere */\nexport function pointsUrl(options: Pick<GeoMapOptions, 'pointsWasmUrl'>): string {\n const url = options.pointsWasmUrl ?? new URL('./isard_points_bg.wasm', import.meta.url);\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n return base ? new URL(url, base).href : String(url);\n}\n\n/** The decoding workers of 3D Tiles and point clouds, running the full engine's module, unless turned off (`workers:\n * false` or 0, or no workers in this environment) */\nexport function startTileLoader(\n module: WebAssembly.Module,\n options: Pick<GeoMapOptions, 'workers' | 'workerUrl' | 'decoders' | 'pointsWasmUrl'>,\n engine: Engine,\n): TileLoader | undefined {\n const { workers: count, workerUrl, decoders } = options;\n const workers = count ?? defaultWorkerCount();\n if (workers === false || workers <= 0 || typeof Worker === 'undefined') return undefined;\n return new TileLoader(\n module,\n workerUrl ?? new URL('./decoder.worker.js', import.meta.url),\n workers,\n { ...DEFAULT_DECODERS, ...decoders },\n engine.textureFormats(),\n pointsUrl(options),\n );\n}\n\n/** The engine of a destroyed map: every method a no-op returning undefined, but the camera (the last one) and the\n * bounds, which late callers read */\nexport function destroyedEngine(camera: Camera): Engine {\n return new Proxy(\n {},\n {\n get: (_, name) => {\n if (name === 'camera') return () => camera;\n if (name === 'bounds') return () => Float64Array.of(-180, -85, 180, 85);\n return () => undefined;\n },\n },\n ) as Engine;\n}\n"]}
1
+ {"version":3,"file":"engine-loader.js","sourceRoot":"","sources":["../src/engine-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The two builds of the engine, downloaded, compiled and instantiated once per page; the decoding workers of 3D Tiles\n * that run the full one; the engine of a destroyed map.\n */\n\nimport { defaultWorkerCount } from './basemap/vectortiles.ts';\nimport { DEFAULT_DECODERS } from './engine/decoders.ts';\nimport { TileLoader } from './engine/loader.ts';\nimport type { GeoMapOptions } from './types.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\n/** The class of an engine build: its constructor and its static `customMatrix` (custom layers) */\nexport type EngineClass = (new (\n canvas: HTMLCanvasElement,\n redraw: () => void,\n) => Engine) &\n Pick<typeof Engine, 'customMatrix' | 'geoidHeight'>;\n\n/** An engine loaded: its compiled module and its class */\nexport interface Bindings {\n module: WebAssembly.Module;\n Engine: EngineClass;\n}\n\n/** `core`: the engine without 3D Tiles; `full`: with them */\nexport type EngineKind = 'core' | 'full';\n\n/** The two builds of the engine, each compiled once per page: `core` without 3D Tiles (a third smaller), loaded by\n * every map; `full` with them, loaded for the first 3D Tiles layer, its module shared with the decoding workers. The\n * core engine has the same API but the 3D Tiles methods: its class is typed as the full one. */\nconst engines: { core?: Promise<Bindings>; full?: Promise<Bindings> } = {};\n/** The modules compiled (downloaded and compiled off the main thread, not instantiated): `tiles3d: 'preload'`\n * compiles the full engine ahead, its first 3D Tiles layer then only instantiates it */\nconst modules: { core?: Promise<WebAssembly.Module>; full?: Promise<WebAssembly.Module> } = {};\n\n/** @internal Forgets the engines loaded (tests) */\nexport function forgetEngines(): void {\n for (const kind of ['core', 'full'] as const) {\n delete engines[kind];\n delete modules[kind];\n }\n}\n\n/** The files a map loads at run time, next to the module unless given elsewhere */\nexport type AssetFile =\n | 'isard_bg.wasm'\n | 'isard_core_bg.wasm'\n | 'isard_points_bg.wasm'\n | 'decoder.worker.js'\n | 'basemap.worker.js';\n\n/** The folder the assets are served from for the whole page, as `isard/vite` sets it; undefined: next to the module */\nfunction pageAssets(): string | undefined {\n const url = (globalThis as { isardAssetsUrl?: unknown }).isardAssetsUrl;\n return typeof url === 'string' ? url : undefined;\n}\n\n/**\n * Where a file of isard is loaded from: its own option, else in the folder `assetsUrl` (the option, or the page's\n * as `isard/vite` sets it), else next to the module (`import.meta.url`)\n */\nexport function assetUrl(file: AssetFile, explicit: string | URL | undefined, assetsUrl?: string | URL): string | URL {\n if (explicit) return explicit;\n const folder = assetsUrl ?? pageAssets();\n if (folder) {\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n const dir = String(folder).endsWith('/') ? String(folder) : `${String(folder)}/`;\n return new URL(file, base ? new URL(dir, base) : dir);\n }\n switch (file) {\n case 'isard_bg.wasm':\n return new URL('./isard_bg.wasm', import.meta.url);\n case 'isard_core_bg.wasm':\n return new URL('./isard_core_bg.wasm', import.meta.url);\n case 'isard_points_bg.wasm':\n return new URL('./isard_points_bg.wasm', import.meta.url);\n case 'decoder.worker.js':\n return new URL('./decoder.worker.js', import.meta.url);\n default:\n return new URL('./basemap.worker.js', import.meta.url);\n }\n}\n\n/** Where a build of the engine is loaded from: the option, the assets' folder, or next to the module */\nexport function engineUrl(\n kind: EngineKind,\n options: Pick<GeoMapOptions, 'wasmUrl' | 'coreWasmUrl' | 'assetsUrl'>,\n): string | URL {\n return kind === 'full'\n ? assetUrl('isard_bg.wasm', options.wasmUrl, options.assetsUrl)\n : assetUrl('isard_core_bg.wasm', options.coreWasmUrl, options.assetsUrl);\n}\n\n/** Downloads and compiles a build (once per page, unless it failed: a later call tries again) */\nfunction compileEngine(kind: EngineKind, url: string | URL): Promise<WebAssembly.Module> {\n const compiled = modules[kind];\n if (compiled) return compiled;\n const compiling = compile(url).catch((error: unknown) => {\n // A later call tries again (a network error, a wrong URL fixed)\n delete modules[kind];\n throw error;\n });\n modules[kind] = compiling;\n return compiling;\n}\n\n/** A build compiled and instantiated with its bindings (once per page, unless it failed) */\nexport function loadEngine(kind: EngineKind, url: string | URL): Promise<Bindings> {\n const loaded = engines[kind];\n if (loaded) return loaded;\n const loading = (async () => {\n // The bindings by dynamic import: an application bundles the ones it loads only\n const [module, bindings] = await Promise.all([\n compileEngine(kind, url),\n kind === 'core' ? import('./wasm/isard_core.js') : import('./wasm/isard.js'),\n ]);\n await bindings.default({ module_or_path: module });\n return { module, Engine: bindings.Engine as unknown as EngineClass };\n })().catch((error: unknown) => {\n delete engines[kind];\n throw error;\n });\n engines[kind] = loading;\n return loading;\n}\n\n/** The full engine for a map on the core one, resolved in a task of its own, not in the one that instantiated it:\n * the map rebuilt on it there, two shorter tasks */\nexport function loadFullEngineLater(url: string | URL): Promise<Bindings> {\n return loadEngine('full', url).then(\n (bindings) => new Promise<Bindings>((resolve) => setTimeout(() => resolve(bindings), 0)),\n );\n}\n\n/** Downloads and compiles the full engine when the page is idle, without running it; a failure is left to the first\n * 3D Tiles layer, which tries again */\nexport function preloadFullEngine(url: string | URL, wanted: () => boolean): void {\n const start = () => {\n if (wanted()) compileEngine('full', url).catch(() => undefined);\n };\n if (typeof requestIdleCallback === 'function') requestIdleCallback(start, { timeout: 2000 });\n else setTimeout(start, 0);\n}\n\nasync function compile(url: string | URL): Promise<WebAssembly.Module> {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`isard: failed to load the engine from ${url}: ${response.status}`);\n try {\n return await WebAssembly.compileStreaming(response.clone());\n } catch {\n // Servers that do not send application/wasm\n return WebAssembly.compile(await response.arrayBuffer());\n }\n}\n\n/** Where the workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder): the option, or next\n * to the module; absolute, the workers being elsewhere */\nexport function pointsUrl(options: Pick<GeoMapOptions, 'pointsWasmUrl' | 'assetsUrl'>): string {\n const url = assetUrl('isard_points_bg.wasm', options.pointsWasmUrl, options.assetsUrl);\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n return base ? new URL(url, base).href : String(url);\n}\n\n/** The decoding workers of 3D Tiles and point clouds, running the full engine's module, unless turned off (`workers:\n * false` or 0, or no workers in this environment) */\nexport function startTileLoader(\n module: WebAssembly.Module,\n options: Pick<GeoMapOptions, 'workers' | 'workerUrl' | 'decoders' | 'pointsWasmUrl' | 'assetsUrl'>,\n engine: Engine,\n): TileLoader | undefined {\n const { workers: count, workerUrl, decoders } = options;\n const workers = count ?? defaultWorkerCount();\n if (workers === false || workers <= 0 || typeof Worker === 'undefined') return undefined;\n return new TileLoader(\n module,\n assetUrl('decoder.worker.js', workerUrl, options.assetsUrl),\n workers,\n { ...DEFAULT_DECODERS, ...decoders },\n engine.textureFormats(),\n pointsUrl(options),\n );\n}\n\n/** The engine of a destroyed map: every method a no-op returning undefined, but the camera (the last one) and the\n * bounds, which late callers read */\nexport function destroyedEngine(camera: Camera): Engine {\n return new Proxy(\n {},\n {\n get: (_, name) => {\n if (name === 'camera') return () => camera;\n if (name === 'bounds') return () => Float64Array.of(-180, -85, 180, 85);\n return () => undefined;\n },\n },\n ) as Engine;\n}\n"]}
package/dist/formats.d.ts CHANGED
@@ -6,6 +6,6 @@
6
6
  * map.addLines({ data: parseGpx(await (await fetch('track.gpx')).text()), color: '#0057b8' });
7
7
  * ```
8
8
  */
9
- export { parseGpx } from './gpx.ts';
10
- export { parseKml } from './kml.ts';
11
- export { parseTopoJson, type TopoGeometry, type Topology } from './topojson.ts';
9
+ export { parseGpx } from './data/gpx.ts';
10
+ export { parseKml } from './data/kml.ts';
11
+ export { parseTopoJson, type TopoGeometry, type Topology } from './data/topojson.ts';
package/dist/formats.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * map.addLines({ data: parseGpx(await (await fetch('track.gpx')).text()), color: '#0057b8' });
7
7
  * ```
8
8
  */
9
- export { parseGpx } from "./gpx.js";
10
- export { parseKml } from "./kml.js";
11
- export { parseTopoJson } from "./topojson.js";
9
+ export { parseGpx } from "./data/gpx.js";
10
+ export { parseKml } from "./data/kml.js";
11
+ export { parseTopoJson } from "./data/topojson.js";
12
12
  //# sourceMappingURL=formats.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"formats.js","sourceRoot":"","sources":["../src/formats.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,aAAa,EAAoC,MAAM,eAAe,CAAC","sourcesContent":["/**\n * `isard/formats`: KML, GPX and TopoJSON read into GeoJSON feature collections, for the feature layers.\n *\n * ```ts\n * import { parseGpx } from 'isard/formats';\n * map.addLines({ data: parseGpx(await (await fetch('track.gpx')).text()), color: '#0057b8' });\n * ```\n */\nexport { parseGpx } from './gpx.ts';\nexport { parseKml } from './kml.ts';\nexport { parseTopoJson, type TopoGeometry, type Topology } from './topojson.ts';\n"]}
1
+ {"version":3,"file":"formats.js","sourceRoot":"","sources":["../src/formats.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAoC,MAAM,oBAAoB,CAAC","sourcesContent":["/**\n * `isard/formats`: KML, GPX and TopoJSON read into GeoJSON feature collections, for the feature layers.\n *\n * ```ts\n * import { parseGpx } from 'isard/formats';\n * map.addLines({ data: parseGpx(await (await fetch('track.gpx')).text()), color: '#0057b8' });\n * ```\n */\nexport { parseGpx } from './data/gpx.ts';\nexport { parseKml } from './data/kml.ts';\nexport { parseTopoJson, type TopoGeometry, type Topology } from './data/topojson.ts';\n"]}
@@ -3,9 +3,10 @@
3
3
  * GeoJSON. Its basemaps, hillshade, terrain model and vector styles are named options of the map (`'ign-plan'`,
4
4
  * `hillshade`, `terrain: 'ign'`, `PLAN_STYLES`); the rasters credit the IGN by themselves.
5
5
  */
6
- import type { FeatureCollection, Properties } from './features.ts';
7
- import type { TileGrid } from './grid.ts';
8
- import type { RasterOptions } from './types.ts';
6
+ import type { TileGrid } from './basemap/grid.ts';
7
+ import type { ExtrusionOptions } from './layers/extrusions.ts';
8
+ import type { FeatureCollection, Properties } from './layers/features.ts';
9
+ import type { RasterOptions, Tiles3dOptions } from './types.ts';
9
10
  /** Credits of the Géoplateforme's data: its basemaps, hillshade, terrain model, rasters and features */
10
11
  export declare const IGN_ATTRIBUTION = "<a href=\"https://www.ign.fr/\">\u00A9 IGN</a> \u2013 <a href=\"https://geoservices.ign.fr/\">G\u00E9oplateforme</a>";
11
12
  /**
@@ -50,3 +51,52 @@ export declare function geoplateformeWfs<P = Properties>(typeName: string, [west
50
51
  signal?: AbortSignal;
51
52
  srsName?: string;
52
53
  }): Promise<FeatureCollection<P>>;
54
+ /** Map presets over France, the IGN's data in a word: spread into `GeoMap.create`'s options or named by `preset` */
55
+ export declare const IGN_PRESETS: {
56
+ /** PLAN IGN (vector, grey) seen from above */
57
+ readonly ign: {
58
+ readonly basemap: "ign-plan-grey-vector";
59
+ readonly projection: "mercator";
60
+ };
61
+ /** PLAN IGN over the IGN relief (RGE ALTI), for 3D: buildings, meshes, viewsheds */
62
+ readonly 'ign-3d': {
63
+ readonly basemap: "ign-plan-grey-vector";
64
+ readonly terrain: {
65
+ readonly model: "ign";
66
+ };
67
+ readonly projection: "mercator";
68
+ readonly pitch: 55;
69
+ };
70
+ /** The IGN orthophotos over the IGN relief */
71
+ readonly 'ign-ortho-3d': {
72
+ readonly basemap: "ign-ortho";
73
+ readonly terrain: {
74
+ readonly model: "ign";
75
+ };
76
+ readonly projection: "mercator";
77
+ readonly pitch: 55;
78
+ };
79
+ };
80
+ /** A preset of `IGN_PRESETS` by name */
81
+ export type IgnPreset = keyof typeof IGN_PRESETS;
82
+ /** The IGN's Bâtiments 3D (France, 3D Tiles 1.1): its tileset */
83
+ export declare const BATIMENTS_3D_URL = "https://prd-ign-mut-bat3.s3.sbg.io.cloud.ovh.net/tileset.json";
84
+ /**
85
+ * The IGN's Bâtiments 3D as a 3D Tiles layer, ready for `map.addTiles3d`: their heights are altitudes (NGF-IGN69),
86
+ * raised by the geoid onto the IGN relief; untextured, colored and shaded; picked with their BD TOPO attributes
87
+ * (`cleabs`, `hauteur`, `nature`, `usage_1`…). Its server sends no CORS headers yet: from a page of another origin,
88
+ * through a proxy (`url`)
89
+ */
90
+ export declare function batiments3d(options?: Partial<Tiles3dOptions>): Tiles3dOptions;
91
+ /** What a building of the BD TOPO gives its extrusion */
92
+ export interface BdTopoBuilding {
93
+ hauteur: number | null;
94
+ }
95
+ /**
96
+ * The BD TOPO buildings of a box (west, south, east, north, degrees) as an extrusion layer, ready for
97
+ * `map.addExtrusions`: from the Géoplateforme's WFS, raised to their `hauteur` (`defaultHeight` without one)
98
+ */
99
+ export declare function bdtopoBuildings(box: [number, number, number, number], options?: Partial<ExtrusionOptions<BdTopoBuilding>> & {
100
+ defaultHeight?: number;
101
+ signal?: AbortSignal;
102
+ }): Promise<ExtrusionOptions<BdTopoBuilding>>;
@@ -1,4 +1,9 @@
1
- import { withHeaders } from "./requests.js";
1
+ /**
2
+ * The Géoplateforme's data (IGN, France; open, no key): its WMTS and WMS rasters as raster layers, its WFS features as
3
+ * GeoJSON. Its basemaps, hillshade, terrain model and vector styles are named options of the map (`'ign-plan'`,
4
+ * `hillshade`, `terrain: 'ign'`, `PLAN_STYLES`); the rasters credit the IGN by themselves.
5
+ */
6
+ import { withHeaders } from "./engine/requests.js";
2
7
  /** Credits of the Géoplateforme's data: its basemaps, hillshade, terrain model, rasters and features */
3
8
  export const IGN_ATTRIBUTION = '<a href="https://www.ign.fr/">© IGN</a> – <a href="https://geoservices.ign.fr/">Géoplateforme</a>';
4
9
  /** France (metropolitan, Corsica included) in longitudes and latitudes, where the Géoplateforme's Lambert-93 layers
@@ -112,4 +117,33 @@ export async function geoplateformeWfs(typeName, [west, south, east, north], opt
112
117
  .filter((f) => f.id === undefined || (!seen.has(f.id) && seen.add(f.id) !== undefined));
113
118
  return { ...first, features };
114
119
  }
120
+ /** Map presets over France, the IGN's data in a word: spread into `GeoMap.create`'s options or named by `preset` */
121
+ export const IGN_PRESETS = {
122
+ /** PLAN IGN (vector, grey) seen from above */
123
+ ign: { basemap: 'ign-plan-grey-vector', projection: 'mercator' },
124
+ /** PLAN IGN over the IGN relief (RGE ALTI), for 3D: buildings, meshes, viewsheds */
125
+ 'ign-3d': { basemap: 'ign-plan-grey-vector', terrain: { model: 'ign' }, projection: 'mercator', pitch: 55 },
126
+ /** The IGN orthophotos over the IGN relief */
127
+ 'ign-ortho-3d': { basemap: 'ign-ortho', terrain: { model: 'ign' }, projection: 'mercator', pitch: 55 },
128
+ };
129
+ /** The IGN's Bâtiments 3D (France, 3D Tiles 1.1): its tileset */
130
+ export const BATIMENTS_3D_URL = 'https://prd-ign-mut-bat3.s3.sbg.io.cloud.ovh.net/tileset.json';
131
+ /**
132
+ * The IGN's Bâtiments 3D as a 3D Tiles layer, ready for `map.addTiles3d`: their heights are altitudes (NGF-IGN69),
133
+ * raised by the geoid onto the IGN relief; untextured, colored and shaded; picked with their BD TOPO attributes
134
+ * (`cleabs`, `hauteur`, `nature`, `usage_1`…). Its server sends no CORS headers yet: from a page of another origin,
135
+ * through a proxy (`url`)
136
+ */
137
+ export function batiments3d(options = {}) {
138
+ return { url: BATIMENTS_3D_URL, geoid: true, color: '#e4e1d8', maxScreenSpaceError: 16, ...options };
139
+ }
140
+ /**
141
+ * The BD TOPO buildings of a box (west, south, east, north, degrees) as an extrusion layer, ready for
142
+ * `map.addExtrusions`: from the Géoplateforme's WFS, raised to their `hauteur` (`defaultHeight` without one)
143
+ */
144
+ export async function bdtopoBuildings(box, options = {}) {
145
+ const { defaultHeight = 6, signal, ...style } = options;
146
+ const data = await geoplateformeWfs('BDTOPO_V3:batiment', box, signal ? { signal } : {});
147
+ return { data, height: (p) => p.hauteur ?? defaultHeight, color: '#e4e1d8', ...style };
148
+ }
115
149
  //# sourceMappingURL=geoplateforme.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"geoplateforme.js","sourceRoot":"","sources":["../src/geoplateforme.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The Géoplateforme's data (IGN, France; open, no key): its WMTS and WMS rasters as raster layers, its WFS features as\n * GeoJSON. Its basemaps, hillshade, terrain model and vector styles are named options of the map (`'ign-plan'`,\n * `hillshade`, `terrain: 'ign'`, `PLAN_STYLES`); the rasters credit the IGN by themselves.\n */\nimport type { FeatureCollection, Properties } from './features.ts';\nimport type { TileGrid, TileMatrix } from './grid.ts';\nimport { withHeaders } from './requests.ts';\nimport type { RasterOptions } from './types.ts';\n\n/** Credits of the Géoplateforme's data: its basemaps, hillshade, terrain model, rasters and features */\nexport const IGN_ATTRIBUTION =\n '<a href=\"https://www.ign.fr/\">© IGN</a> – <a href=\"https://geoservices.ign.fr/\">Géoplateforme</a>';\n\n/** France (metropolitan, Corsica included) in longitudes and latitudes, where the Géoplateforme's Lambert-93 layers\n * lie */\nconst FRANCE: [number, number, number, number] = [-5.5, 41, 10, 51.5];\n\n/**\n * The Géoplateforme's Lambert-93 tile matrix sets of 5 and 10 cm (`2154_10cm_6_20`, `2154_5cm_6_22`…: one pyramid,\n * 209 715.2 m per pixel at level 0, halved at each level, from the corner (0, 12 000 000)), levels `min` to `max`, over\n * France\n */\nexport function lambert93Grid(name: string, min: number, max: number): TileGrid {\n const matrices: TileMatrix[] = [];\n for (let level = min; level <= max; level += 1) {\n matrices.push({ id: level, resolution: 209715.2 / 2 ** level, origin: [0, 12000000] });\n }\n return { crs: 'EPSG:2154', matrices, bounds: FRANCE, name };\n}\n\n/**\n * A layer of the Géoplateforme's WMTS as raster options for `addRaster`, crediting the IGN:\n * `geoplateformeWmts('ORTHOIMAGERY.ORTHOPHOTOS', { format: 'image/jpeg' })`. The layer names are those of its\n * capabilities (https://data.geopf.fr/wmts?SERVICE=WMTS&REQUEST=GetCapabilities). In its Web Mercator grid (`PM`) by\n * default; a Lambert-93 layer in its matrix set (`matrixSet: '2154_10cm_6_20'`, a set of 5 or 10 cm, read from the\n * capabilities) or another `grid` (from `wmtsGrid`, its set named) is reprojected by the map\n */\nexport function geoplateformeWmts(\n layer: string,\n options: { format?: string; style?: string; matrixSet?: string } & Omit<RasterOptions, 'url'> = {},\n): RasterOptions {\n const { format = 'image/png', style = 'normal', matrixSet, ...raster } = options;\n const set = (typeof raster.grid === 'object' ? raster.grid.name : undefined) ?? matrixSet ?? 'PM';\n const lambert = /^2154_(?:5|10)cm_(\\d+)_(\\d+)$/.exec(set);\n if (lambert && raster.grid === undefined) raster.grid = lambert93Grid(set, Number(lambert[1]), Number(lambert[2]));\n else if (set !== 'PM' && raster.grid === undefined) {\n throw new Error(`isard: the grid of the matrix set ${set}: wmtsGrid(capabilities, '${layer}', '${set}')`);\n }\n return {\n ...(raster.grid === undefined ? { maxZoom: 19 } : {}),\n attribution: IGN_ATTRIBUTION,\n ...raster,\n url:\n `https://data.geopf.fr/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&STYLE=${encodeURIComponent(style)}` +\n `&TILEMATRIXSET=${encodeURIComponent(set)}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}` +\n `&LAYER=${encodeURIComponent(layer)}&FORMAT=${format}`,\n };\n}\n\n/**\n * Layers of the Géoplateforme's WMS (raster, `wms-r`) as raster options for `addRaster`, crediting the IGN: 256 px\n * images of each tile, transparent where empty. `geoplateformeWms('CADASTRALPARCELS.PARCELLAIRE_EXPRESS')`. Asked for\n * in EPSG:3857, or in `crs` (`'EPSG:2154'`: the box of each tile in Lambert-93, at the tile's `size`, reprojected by\n * the map; `'EPSG:4326'` is asked for as CRS:84, longitude first)\n */\nexport function geoplateformeWms(\n layers: string,\n options: { format?: string; styles?: string; crs?: string } & Omit<RasterOptions, 'url'> = {},\n): RasterOptions {\n const { format = 'image/png', styles = '', crs = 'EPSG:3857', ...raster } = options;\n const projected = crs !== 'EPSG:3857';\n // WMS 1.3 puts the latitude first in EPSG:4326; {bbox} is x, y\n const asked = crs === 'EPSG:4326' ? 'CRS:84' : crs;\n return {\n maxZoom: 20,\n attribution: IGN_ATTRIBUTION,\n ...(projected ? { grid: { crs, ...(crs === 'EPSG:2154' ? { bounds: FRANCE } : {}) } } : {}),\n ...raster,\n url:\n `https://data.geopf.fr/wms-r/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&CRS=${asked}&BBOX={bbox}` +\n // Reprojected, the image of each tile at its size\n `&${projected ? 'WIDTH={width}&HEIGHT={height}' : 'WIDTH=256&HEIGHT=256'}&TRANSPARENT=TRUE` +\n `&LAYERS=${encodeURIComponent(layers)}` +\n `&STYLES=${encodeURIComponent(styles)}&FORMAT=${format}`,\n };\n}\n\n/** Features the Géoplateforme's WFS returns per request at most */\nconst WFS_PAGE = 5000;\n\n/**\n * Features of the Géoplateforme's WFS in a box (west, south, east, north, degrees), as GeoJSON in longitudes and\n * latitudes: `await geoplateformeWfs('BDTOPO_V3:batiment', [2.41, 48.84, 2.43, 48.85])`. At most `count` features\n * (default 50 000), asked by pages of 5000: the first one tells how many there are, the others are asked together.\n * The type names are those of its capabilities (BD TOPO, ADMIN EXPRESS…). With `srsName` (`'EPSG:2154'`), the\n * features come in that CRS (the box stays in degrees), the collection naming it in its `crs` member: the feature\n * layers reproject it by themselves\n */\nexport async function geoplateformeWfs<P = Properties>(\n typeName: string,\n [west, south, east, north]: [number, number, number, number],\n options: { count?: number; signal?: AbortSignal; srsName?: string } = {},\n): Promise<FeatureCollection<P>> {\n const limit = Math.max(1, options.count ?? 50_000);\n const page = async (start: number, count: number) => {\n const url = new URL('https://data.geopf.fr/wfs/ows');\n url.search = new URLSearchParams({\n SERVICE: 'WFS',\n VERSION: '2.0.0',\n REQUEST: 'GetFeature',\n TYPENAMES: typeName,\n OUTPUTFORMAT: 'application/json',\n SRSNAME: options.srsName ?? 'EPSG:4326',\n // WFS 2.0 in EPSG:4326: latitude first\n BBOX: `${south},${west},${north},${east},urn:ogc:def:crs:EPSG::4326`,\n COUNT: String(count),\n // The first page as a single request always was\n ...(start > 0 ? { STARTINDEX: String(start) } : {}),\n }).toString();\n const response = await fetch(url, withHeaders(url, options.signal ? { signal: options.signal } : {}));\n if (!response.ok) throw new Error(`isard: ${typeName}: ${response.status}`);\n return response.json() as Promise<FeatureCollection<P> & { numberMatched?: number | string }>;\n };\n const first = await page(0, Math.min(WFS_PAGE, limit));\n const matched = Number(first.numberMatched);\n const total = Math.min(Number.isFinite(matched) ? matched : 0, limit);\n if (first.features.length < WFS_PAGE || total <= first.features.length) return first;\n const starts: number[] = [];\n for (let start = first.features.length; start < total; start += WFS_PAGE) starts.push(start);\n const rest = await Promise.all(starts.map((start) => page(start, Math.min(WFS_PAGE, total - start))));\n // Pages may overlap where the server's order shifts: each feature once, by its id\n const seen = new Set<unknown>();\n const features = [first, ...rest]\n .flatMap((r) => r.features)\n .filter((f) => f.id === undefined || (!seen.has(f.id) && seen.add(f.id) !== undefined));\n return { ...first, features };\n}\n"]}
1
+ {"version":3,"file":"geoplateforme.js","sourceRoot":"","sources":["../src/geoplateforme.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The Géoplateforme's data (IGN, France; open, no key): its WMTS and WMS rasters as raster layers, its WFS features as\n * GeoJSON. Its basemaps, hillshade, terrain model and vector styles are named options of the map (`'ign-plan'`,\n * `hillshade`, `terrain: 'ign'`, `PLAN_STYLES`); the rasters credit the IGN by themselves.\n */\n\nimport type { TileGrid, TileMatrix } from './basemap/grid.ts';\nimport { withHeaders } from './engine/requests.ts';\nimport type { ExtrusionOptions } from './layers/extrusions.ts';\nimport type { FeatureCollection, Properties } from './layers/features.ts';\nimport type { GeoMapOptions, RasterOptions, Tiles3dOptions } from './types.ts';\n\n/** Credits of the Géoplateforme's data: its basemaps, hillshade, terrain model, rasters and features */\nexport const IGN_ATTRIBUTION =\n '<a href=\"https://www.ign.fr/\">© IGN</a> – <a href=\"https://geoservices.ign.fr/\">Géoplateforme</a>';\n\n/** France (metropolitan, Corsica included) in longitudes and latitudes, where the Géoplateforme's Lambert-93 layers\n * lie */\nconst FRANCE: [number, number, number, number] = [-5.5, 41, 10, 51.5];\n\n/**\n * The Géoplateforme's Lambert-93 tile matrix sets of 5 and 10 cm (`2154_10cm_6_20`, `2154_5cm_6_22`…: one pyramid,\n * 209 715.2 m per pixel at level 0, halved at each level, from the corner (0, 12 000 000)), levels `min` to `max`, over\n * France\n */\nexport function lambert93Grid(name: string, min: number, max: number): TileGrid {\n const matrices: TileMatrix[] = [];\n for (let level = min; level <= max; level += 1) {\n matrices.push({ id: level, resolution: 209715.2 / 2 ** level, origin: [0, 12000000] });\n }\n return { crs: 'EPSG:2154', matrices, bounds: FRANCE, name };\n}\n\n/**\n * A layer of the Géoplateforme's WMTS as raster options for `addRaster`, crediting the IGN:\n * `geoplateformeWmts('ORTHOIMAGERY.ORTHOPHOTOS', { format: 'image/jpeg' })`. The layer names are those of its\n * capabilities (https://data.geopf.fr/wmts?SERVICE=WMTS&REQUEST=GetCapabilities). In its Web Mercator grid (`PM`) by\n * default; a Lambert-93 layer in its matrix set (`matrixSet: '2154_10cm_6_20'`, a set of 5 or 10 cm, read from the\n * capabilities) or another `grid` (from `wmtsGrid`, its set named) is reprojected by the map\n */\nexport function geoplateformeWmts(\n layer: string,\n options: { format?: string; style?: string; matrixSet?: string } & Omit<RasterOptions, 'url'> = {},\n): RasterOptions {\n const { format = 'image/png', style = 'normal', matrixSet, ...raster } = options;\n const set = (typeof raster.grid === 'object' ? raster.grid.name : undefined) ?? matrixSet ?? 'PM';\n const lambert = /^2154_(?:5|10)cm_(\\d+)_(\\d+)$/.exec(set);\n if (lambert && raster.grid === undefined) raster.grid = lambert93Grid(set, Number(lambert[1]), Number(lambert[2]));\n else if (set !== 'PM' && raster.grid === undefined) {\n throw new Error(`isard: the grid of the matrix set ${set}: wmtsGrid(capabilities, '${layer}', '${set}')`);\n }\n return {\n ...(raster.grid === undefined ? { maxZoom: 19 } : {}),\n attribution: IGN_ATTRIBUTION,\n ...raster,\n url:\n `https://data.geopf.fr/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&STYLE=${encodeURIComponent(style)}` +\n `&TILEMATRIXSET=${encodeURIComponent(set)}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}` +\n `&LAYER=${encodeURIComponent(layer)}&FORMAT=${format}`,\n };\n}\n\n/**\n * Layers of the Géoplateforme's WMS (raster, `wms-r`) as raster options for `addRaster`, crediting the IGN: 256 px\n * images of each tile, transparent where empty. `geoplateformeWms('CADASTRALPARCELS.PARCELLAIRE_EXPRESS')`. Asked for\n * in EPSG:3857, or in `crs` (`'EPSG:2154'`: the box of each tile in Lambert-93, at the tile's `size`, reprojected by\n * the map; `'EPSG:4326'` is asked for as CRS:84, longitude first)\n */\nexport function geoplateformeWms(\n layers: string,\n options: { format?: string; styles?: string; crs?: string } & Omit<RasterOptions, 'url'> = {},\n): RasterOptions {\n const { format = 'image/png', styles = '', crs = 'EPSG:3857', ...raster } = options;\n const projected = crs !== 'EPSG:3857';\n // WMS 1.3 puts the latitude first in EPSG:4326; {bbox} is x, y\n const asked = crs === 'EPSG:4326' ? 'CRS:84' : crs;\n return {\n maxZoom: 20,\n attribution: IGN_ATTRIBUTION,\n ...(projected ? { grid: { crs, ...(crs === 'EPSG:2154' ? { bounds: FRANCE } : {}) } } : {}),\n ...raster,\n url:\n `https://data.geopf.fr/wms-r/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&CRS=${asked}&BBOX={bbox}` +\n // Reprojected, the image of each tile at its size\n `&${projected ? 'WIDTH={width}&HEIGHT={height}' : 'WIDTH=256&HEIGHT=256'}&TRANSPARENT=TRUE` +\n `&LAYERS=${encodeURIComponent(layers)}` +\n `&STYLES=${encodeURIComponent(styles)}&FORMAT=${format}`,\n };\n}\n\n/** Features the Géoplateforme's WFS returns per request at most */\nconst WFS_PAGE = 5000;\n\n/**\n * Features of the Géoplateforme's WFS in a box (west, south, east, north, degrees), as GeoJSON in longitudes and\n * latitudes: `await geoplateformeWfs('BDTOPO_V3:batiment', [2.41, 48.84, 2.43, 48.85])`. At most `count` features\n * (default 50 000), asked by pages of 5000: the first one tells how many there are, the others are asked together.\n * The type names are those of its capabilities (BD TOPO, ADMIN EXPRESS…). With `srsName` (`'EPSG:2154'`), the\n * features come in that CRS (the box stays in degrees), the collection naming it in its `crs` member: the feature\n * layers reproject it by themselves\n */\nexport async function geoplateformeWfs<P = Properties>(\n typeName: string,\n [west, south, east, north]: [number, number, number, number],\n options: { count?: number; signal?: AbortSignal; srsName?: string } = {},\n): Promise<FeatureCollection<P>> {\n const limit = Math.max(1, options.count ?? 50_000);\n const page = async (start: number, count: number) => {\n const url = new URL('https://data.geopf.fr/wfs/ows');\n url.search = new URLSearchParams({\n SERVICE: 'WFS',\n VERSION: '2.0.0',\n REQUEST: 'GetFeature',\n TYPENAMES: typeName,\n OUTPUTFORMAT: 'application/json',\n SRSNAME: options.srsName ?? 'EPSG:4326',\n // WFS 2.0 in EPSG:4326: latitude first\n BBOX: `${south},${west},${north},${east},urn:ogc:def:crs:EPSG::4326`,\n COUNT: String(count),\n // The first page as a single request always was\n ...(start > 0 ? { STARTINDEX: String(start) } : {}),\n }).toString();\n const response = await fetch(url, withHeaders(url, options.signal ? { signal: options.signal } : {}));\n if (!response.ok) throw new Error(`isard: ${typeName}: ${response.status}`);\n return response.json() as Promise<FeatureCollection<P> & { numberMatched?: number | string }>;\n };\n const first = await page(0, Math.min(WFS_PAGE, limit));\n const matched = Number(first.numberMatched);\n const total = Math.min(Number.isFinite(matched) ? matched : 0, limit);\n if (first.features.length < WFS_PAGE || total <= first.features.length) return first;\n const starts: number[] = [];\n for (let start = first.features.length; start < total; start += WFS_PAGE) starts.push(start);\n const rest = await Promise.all(starts.map((start) => page(start, Math.min(WFS_PAGE, total - start))));\n // Pages may overlap where the server's order shifts: each feature once, by its id\n const seen = new Set<unknown>();\n const features = [first, ...rest]\n .flatMap((r) => r.features)\n .filter((f) => f.id === undefined || (!seen.has(f.id) && seen.add(f.id) !== undefined));\n return { ...first, features };\n}\n\n/** Map presets over France, the IGN's data in a word: spread into `GeoMap.create`'s options or named by `preset` */\nexport const IGN_PRESETS = {\n /** PLAN IGN (vector, grey) seen from above */\n ign: { basemap: 'ign-plan-grey-vector', projection: 'mercator' },\n /** PLAN IGN over the IGN relief (RGE ALTI), for 3D: buildings, meshes, viewsheds */\n 'ign-3d': { basemap: 'ign-plan-grey-vector', terrain: { model: 'ign' }, projection: 'mercator', pitch: 55 },\n /** The IGN orthophotos over the IGN relief */\n 'ign-ortho-3d': { basemap: 'ign-ortho', terrain: { model: 'ign' }, projection: 'mercator', pitch: 55 },\n} as const satisfies Record<string, GeoMapOptions>;\n\n/** A preset of `IGN_PRESETS` by name */\nexport type IgnPreset = keyof typeof IGN_PRESETS;\n\n/** The IGN's Bâtiments 3D (France, 3D Tiles 1.1): its tileset */\nexport const BATIMENTS_3D_URL = 'https://prd-ign-mut-bat3.s3.sbg.io.cloud.ovh.net/tileset.json';\n\n/**\n * The IGN's Bâtiments 3D as a 3D Tiles layer, ready for `map.addTiles3d`: their heights are altitudes (NGF-IGN69),\n * raised by the geoid onto the IGN relief; untextured, colored and shaded; picked with their BD TOPO attributes\n * (`cleabs`, `hauteur`, `nature`, `usage_1`…). Its server sends no CORS headers yet: from a page of another origin,\n * through a proxy (`url`)\n */\nexport function batiments3d(options: Partial<Tiles3dOptions> = {}): Tiles3dOptions {\n return { url: BATIMENTS_3D_URL, geoid: true, color: '#e4e1d8', maxScreenSpaceError: 16, ...options };\n}\n\n/** What a building of the BD TOPO gives its extrusion */\nexport interface BdTopoBuilding {\n hauteur: number | null;\n}\n\n/**\n * The BD TOPO buildings of a box (west, south, east, north, degrees) as an extrusion layer, ready for\n * `map.addExtrusions`: from the Géoplateforme's WFS, raised to their `hauteur` (`defaultHeight` without one)\n */\nexport async function bdtopoBuildings(\n box: [number, number, number, number],\n options: Partial<ExtrusionOptions<BdTopoBuilding>> & { defaultHeight?: number; signal?: AbortSignal } = {},\n): Promise<ExtrusionOptions<BdTopoBuilding>> {\n const { defaultHeight = 6, signal, ...style } = options;\n const data = await geoplateformeWfs<BdTopoBuilding>('BDTOPO_V3:batiment', box, signal ? { signal } : {});\n return { data, height: (p) => p.hauteur ?? defaultHeight, color: '#e4e1d8', ...style };\n}\n"]}