isard 0.7.0 → 0.8.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 (64) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/basemap.worker.d.ts +7 -1
  3. package/dist/basemap.worker.js +2 -2
  4. package/dist/basemap.worker.js.map +8 -7
  5. package/dist/decoder.worker.js +4 -4
  6. package/dist/decoder.worker.js.map +6 -5
  7. package/dist/engine-loader.d.ts +1 -1
  8. package/dist/engine-loader.js.map +1 -1
  9. package/dist/geoplateforme.js +2 -1
  10. package/dist/geoplateforme.js.map +1 -1
  11. package/dist/glyphs.js +2 -1
  12. package/dist/glyphs.js.map +1 -1
  13. package/dist/icons.js +5 -1
  14. package/dist/icons.js.map +1 -1
  15. package/dist/index.d.ts +4 -2
  16. package/dist/index.js +3 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/interaction.d.ts +2 -0
  19. package/dist/interaction.js +29 -2
  20. package/dist/interaction.js.map +1 -1
  21. package/dist/isard_bg.wasm +0 -0
  22. package/dist/isard_core_bg.wasm +0 -0
  23. package/dist/layers.d.ts +2 -0
  24. package/dist/layers.js +22 -4
  25. package/dist/layers.js.map +1 -1
  26. package/dist/loader.d.ts +2 -0
  27. package/dist/loader.js +10 -0
  28. package/dist/loader.js.map +1 -1
  29. package/dist/map.d.ts +38 -1
  30. package/dist/map.js +153 -2
  31. package/dist/map.js.map +1 -1
  32. package/dist/overlay.d.ts +40 -0
  33. package/dist/overlay.js +119 -0
  34. package/dist/overlay.js.map +1 -1
  35. package/dist/panoramas.d.ts +94 -0
  36. package/dist/panoramas.js +245 -0
  37. package/dist/panoramas.js.map +1 -0
  38. package/dist/pmtiles.js +3 -2
  39. package/dist/pmtiles.js.map +1 -1
  40. package/dist/pointclouds.js +1 -1
  41. package/dist/pointclouds.js.map +1 -1
  42. package/dist/protocol.d.ts +7 -1
  43. package/dist/protocol.js.map +1 -1
  44. package/dist/requests.d.ts +14 -0
  45. package/dist/requests.js +48 -0
  46. package/dist/requests.js.map +1 -0
  47. package/dist/resample.js +2 -1
  48. package/dist/resample.js.map +1 -1
  49. package/dist/style.js +1 -0
  50. package/dist/style.js.map +1 -1
  51. package/dist/terrain.d.ts +0 -5
  52. package/dist/terrain.js +2 -1
  53. package/dist/terrain.js.map +1 -1
  54. package/dist/types.d.ts +29 -1
  55. package/dist/types.js.map +1 -1
  56. package/dist/vectortiles.js +12 -1
  57. package/dist/vectortiles.js.map +1 -1
  58. package/dist/wasm/isard.d.ts +79 -5
  59. package/dist/wasm/isard.js +165 -7
  60. package/dist/wasm/isard_core.d.ts +38 -0
  61. package/dist/wasm/isard_core.js +99 -0
  62. package/dist/wmts.js +2 -1
  63. package/dist/wmts.js.map +1 -1
  64. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panoramas.js","sourceRoot":"","sources":["../src/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 './crs.ts';\nimport { withHeaders } from './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"]}
package/dist/pmtiles.js CHANGED
@@ -5,6 +5,7 @@
5
5
  * workers (vector tiles of a style source `pmtiles://…`, as MapLibre's protocol names them).
6
6
  */
7
7
  import { Lru } from "./lru.js";
8
+ import { withHeaders } from "./requests.js";
8
9
  const HEADER = 127;
9
10
  /** The header and the root directory lie within the first 16 KB of the file */
10
11
  const FIRST = 16384;
@@ -180,10 +181,10 @@ export class PMTiles {
180
181
  }
181
182
  if (this.whole)
182
183
  return (await this.whole).subarray(offset, offset + length);
183
- const response = await fetch(this.source, {
184
+ const response = await fetch(this.source, withHeaders(this.source, {
184
185
  headers: { Range: `bytes=${offset}-${offset + Math.max(length, 1) - 1}` },
185
186
  ...(signal ? { signal } : {}),
186
- });
187
+ }));
187
188
  if (!response.ok)
188
189
  throw new Error(`${this.source}: HTTP ${response.status}`);
189
190
  if (response.status === 206)
@@ -1 +1 @@
1
- {"version":3,"file":"pmtiles.js","sourceRoot":"","sources":["../src/pmtiles.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PMTiles v3 archives: one file of tiles read by HTTP range requests (or from a `Blob`), as Protomaps publishes them.\n * The header and root directory in one request, the leaf directories as needed (kept in a small cache), each tile in\n * its own range; gzip through `DecompressionStream`. The same reader in the page (raster tiles) and in the basemap\n * workers (vector tiles of a style source `pmtiles://…`, as MapLibre's protocol names them).\n */\nimport { Lru } from './lru.ts';\n\n/** What a PMTiles archive's tiles are */\nexport type PmtilesTileType = 'unknown' | 'mvt' | 'png' | 'jpeg' | 'webp' | 'avif';\n\n/** The header of a PMTiles archive (v3) */\nexport interface PmtilesHeader {\n rootDirectoryOffset: number;\n rootDirectoryLength: number;\n metadataOffset: number;\n metadataLength: number;\n leafDirectoryOffset: number;\n leafDirectoryLength: number;\n tileDataOffset: number;\n tileDataLength: number;\n /** 1 none, 2 gzip, 3 brotli, 4 zstd (only none and gzip are read) */\n internalCompression: number;\n tileCompression: number;\n tileType: PmtilesTileType;\n minZoom: number;\n maxZoom: number;\n /** `[west, south, east, north]`, degrees */\n bounds: [number, number, number, number];\n center: [lon: number, lat: number, zoom: number];\n}\n\n/** An entry of a directory: a run of tiles (`runLength` > 0) or a leaf directory (0) */\nexport interface PmtilesEntry {\n tileId: number;\n offset: number;\n length: number;\n runLength: number;\n}\n\nconst HEADER = 127;\n/** The header and the root directory lie within the first 16 KB of the file */\nconst FIRST = 16384;\nconst TYPES: PmtilesTileType[] = ['unknown', 'mvt', 'png', 'jpeg', 'webp', 'avif'];\n\n/** Tiles before level z: (4^z - 1) / 3 */\nconst levelStart = (z: number) => (4 ** z - 1) / 3;\n\n/** The tile id of z/x/y: the tiles of the lower levels, then the position along the level's Hilbert curve */\nexport function zxyToTileId(z: number, x: number, y: number): number {\n if (z > 26) throw new Error(`isard: PMTiles level ${z} past 26`);\n const n = 2 ** z;\n if (x < 0 || y < 0 || x >= n || y >= n) throw new Error(`isard: PMTiles tile ${z}/${x}/${y} out of its level`);\n let [px, py] = [x, y];\n let d = 0;\n for (let s = n / 2; s >= 1; s /= 2) {\n const rx = (px & s) > 0 ? 1 : 0;\n const ry = (py & s) > 0 ? 1 : 0;\n d += s * s * ((3 * rx) ^ ry);\n if (ry === 0) {\n if (rx === 1) [px, py] = [s - 1 - px, s - 1 - py];\n [px, py] = [py, px];\n }\n }\n return levelStart(z) + d;\n}\n\n/** The z/x/y of a tile id (the inverse of `zxyToTileId`) */\nexport function tileIdToZxy(id: number): [z: number, x: number, y: number] {\n let z = 0;\n while (levelStart(z + 1) <= id) z += 1;\n const n = 2 ** z;\n let t = id - levelStart(z);\n let [x, y] = [0, 0];\n for (let s = 1; s < n; s *= 2) {\n // Arithmetic, not bitwise: positions pass 32 bits past level 16\n const rx = Math.floor(t / 2) % 2;\n const ry = (t % 2) ^ rx;\n if (ry === 0) {\n if (rx === 1) [x, y] = [s - 1 - x, s - 1 - y];\n [x, y] = [y, x];\n }\n x += s * rx;\n y += s * ry;\n t = Math.floor(t / 4);\n }\n return [z, x, y];\n}\n\n/** A reader of unsigned varints past 32 bits (tile ids reach 2^52) */\nclass Varints {\n pos = 0;\n constructor(private readonly bytes: Uint8Array) {}\n next(): number {\n let value = 0;\n let scale = 1;\n for (;;) {\n const b = this.bytes[this.pos++];\n if (b === undefined) throw new Error('isard: PMTiles directory truncated');\n value += (b & 0x7f) * scale;\n if (b < 0x80) return value;\n scale *= 128;\n if (scale > 2 ** 63) throw new Error('isard: PMTiles varint too long');\n }\n }\n}\n\n/** The entries of a directory (decompressed) */\nexport function parseDirectory(bytes: Uint8Array): PmtilesEntry[] {\n const v = new Varints(bytes);\n const count = v.next();\n if (count > bytes.length) throw new Error('isard: PMTiles directory larger than its bytes');\n const entries: PmtilesEntry[] = [];\n let id = 0;\n for (let i = 0; i < count; i += 1) {\n id += v.next();\n entries.push({ tileId: id, offset: 0, length: 0, runLength: 1 });\n }\n for (const e of entries) e.runLength = v.next();\n for (const e of entries) e.length = v.next();\n entries.forEach((e, i) => {\n const value = v.next();\n const previous = entries[i - 1];\n // 0 after the first: right after the previous entry's bytes\n e.offset = value === 0 && previous ? previous.offset + previous.length : value - 1;\n });\n return entries;\n}\n\n/** The entry holding a tile id: its run of tiles, or the leaf directory it falls in; undefined if none */\nexport function findEntry(entries: readonly PmtilesEntry[], id: number): PmtilesEntry | undefined {\n let [lo, hi] = [0, entries.length - 1];\n while (lo <= hi) {\n const mid = (lo + hi) >> 1;\n const e = entries[mid] as PmtilesEntry;\n if (e.tileId === id) return e;\n if (e.tileId < id) lo = mid + 1;\n else hi = mid - 1;\n }\n const e = entries[hi];\n if (!e) return undefined;\n if (e.runLength === 0 || id - e.tileId < e.runLength) return e;\n return undefined;\n}\n\n/** The header of an archive from its first bytes */\nexport function parseHeader(bytes: Uint8Array): PmtilesHeader {\n if (bytes.length < HEADER || String.fromCharCode(...bytes.subarray(0, 7)) !== 'PMTiles') {\n throw new Error('isard: not a PMTiles archive');\n }\n if (bytes[7] !== 3) throw new Error(`isard: PMTiles version ${bytes[7]} (only 3 is read)`);\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const u64 = (at: number) => Number(view.getBigUint64(at, true));\n const deg = (at: number) => view.getInt32(at, true) / 1e7;\n return {\n rootDirectoryOffset: u64(8),\n rootDirectoryLength: u64(16),\n metadataOffset: u64(24),\n metadataLength: u64(32),\n leafDirectoryOffset: u64(40),\n leafDirectoryLength: u64(48),\n tileDataOffset: u64(56),\n tileDataLength: u64(64),\n internalCompression: view.getUint8(97),\n tileCompression: view.getUint8(98),\n tileType: TYPES[view.getUint8(99)] ?? 'unknown',\n minZoom: view.getUint8(100),\n maxZoom: view.getUint8(101),\n bounds: [deg(102), deg(106), deg(110), deg(114)],\n center: [deg(119), deg(123), view.getUint8(118)],\n };\n}\n\n/** Bytes as they are stored, decompressed (1: none, 2: gzip; 0, unknown, is read as none) */\nexport async function decompress(bytes: Uint8Array, compression: number): Promise<Uint8Array> {\n if (compression === 0 || compression === 1) return bytes;\n if (compression !== 2) {\n throw new Error(`isard: PMTiles compression ${compression === 3 ? 'brotli' : 'zstd'} is not read (gzip only)`);\n }\n const stream = new Blob([bytes as Uint8Array<ArrayBuffer>]).stream().pipeThrough(new DecompressionStream('gzip'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\n/** Past this, a whole file sent for a range request (a server ignoring ranges) is an error rather than kept */\nconst WHOLE_FILE_MAX = 64 * 1024 * 1024;\n\n/** A PMTiles archive at a URL (range requests) or in a `Blob` (a dropped file) */\nexport class PMTiles {\n private head: Promise<{ header: PmtilesHeader; root: PmtilesEntry[] }> | undefined;\n /** The leaf directories read, by offset */\n private readonly leaves = new Lru<number, Promise<PmtilesEntry[]>>(64);\n /** The whole file, when the server answered a range request with it (small files, `blob:` URLs) */\n private whole: Promise<Uint8Array> | undefined;\n\n constructor(readonly source: string | Blob) {}\n\n /** `length` bytes from `offset` */\n private async range(offset: number, length: number, signal?: AbortSignal): Promise<Uint8Array> {\n if (typeof this.source !== 'string') {\n return new Uint8Array(await this.source.slice(offset, offset + length).arrayBuffer());\n }\n if (this.whole) return (await this.whole).subarray(offset, offset + length);\n const response = await fetch(this.source, {\n headers: { Range: `bytes=${offset}-${offset + Math.max(length, 1) - 1}` },\n ...(signal ? { signal } : {}),\n });\n if (!response.ok) throw new Error(`${this.source}: HTTP ${response.status}`);\n if (response.status === 206) return new Uint8Array(await response.arrayBuffer());\n // The whole file: kept, when small enough, for the next ranges\n const size = Number(response.headers.get('Content-Length'));\n if (size > WHOLE_FILE_MAX) {\n await response.body?.cancel();\n throw new Error(`${this.source}: the server ignores range requests (HTTP 206 expected)`);\n }\n const whole = response.arrayBuffer().then((b) => new Uint8Array(b));\n this.whole = whole;\n whole.catch(() => {\n this.whole = undefined;\n });\n return (await whole).subarray(offset, offset + length);\n }\n\n private load() {\n this.head ??= (async () => {\n const first = await this.range(0, FIRST);\n const header = parseHeader(first);\n const { rootDirectoryOffset: o, rootDirectoryLength: n } = header;\n const raw = o + n <= first.length ? first.subarray(o, o + n) : await this.range(o, n);\n const root = parseDirectory(await decompress(raw, header.internalCompression));\n return { header, root };\n })();\n // A failure is not kept: asked again next time\n this.head.catch(() => {\n this.head = undefined;\n });\n return this.head;\n }\n\n /** The archive's header */\n async header(): Promise<PmtilesHeader> {\n return (await this.load()).header;\n }\n\n /** The archive's JSON metadata (`vector_layers`, `attribution`, `name`…); `{}` if it has none */\n async metadata(): Promise<Record<string, unknown>> {\n const { header } = await this.load();\n if (header.metadataLength === 0) return {};\n const raw = await this.range(header.metadataOffset, header.metadataLength);\n const text = new TextDecoder().decode(await decompress(raw, header.internalCompression));\n const value: unknown = JSON.parse(text);\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\n }\n\n private leaf(header: PmtilesHeader, entry: PmtilesEntry): Promise<PmtilesEntry[]> {\n const offset = header.leafDirectoryOffset + entry.offset;\n let leaf = this.leaves.get(offset);\n if (!leaf) {\n leaf = this.range(offset, entry.length).then(async (raw) =>\n parseDirectory(await decompress(raw, header.internalCompression)),\n );\n leaf.catch(() => this.leaves.delete(offset));\n this.leaves.set(offset, leaf);\n }\n return leaf;\n }\n\n /** The bytes of tile z/x/y, decompressed (a vector tile ungzipped); undefined where the archive has none */\n async tile(z: number, x: number, y: number, signal?: AbortSignal): Promise<Uint8Array | undefined> {\n const { header, root } = await this.load();\n if (z < header.minZoom || z > header.maxZoom) return undefined;\n const id = zxyToTileId(z, x, y);\n let entries = root;\n // The root, then at most three levels of leaves\n for (let depth = 0; depth < 4; depth += 1) {\n const entry = findEntry(entries, id);\n if (!entry) return undefined;\n if (entry.runLength > 0) {\n const raw = await this.range(header.tileDataOffset + entry.offset, entry.length, signal);\n return decompress(raw, header.tileCompression);\n }\n entries = await this.leaf(header, entry);\n }\n throw new Error('isard: PMTiles directories nested too deep');\n }\n}\n\n/** The archives opened, by URL: one reader (and its directory cache) per archive in a page or worker */\nconst archives = new Lru<string, PMTiles>(16);\n\n/** The reader of an archive URL (without `pmtiles://`), shared */\nexport function pmtiles(url: string): PMTiles {\n let archive = archives.get(url);\n if (!archive) {\n archive = new PMTiles(url);\n archives.set(url, archive);\n }\n return archive;\n}\n\n/** The archive URL of a `pmtiles://` URL, absolute (relative to the page), or undefined for another URL */\nexport function pmtilesUrl(url: string, base?: string): string | undefined {\n if (!url.startsWith('pmtiles://')) return undefined;\n const inner = url.slice('pmtiles://'.length);\n const from = base ?? (globalThis as { location?: { href: string } }).location?.href;\n try {\n return from ? new URL(inner, from).href : inner;\n } catch {\n return inner;\n }\n}\n\n/** A tile URL `pmtiles://<archive>/{z}/{x}/{y}` (with its numbers in) read from its archive: its bytes, undefined\n * where there is none; undefined too (`false`) for a URL that is not one */\nexport function pmtilesTile(url: string, signal?: AbortSignal): Promise<Uint8Array | undefined> | false {\n const match = /^pmtiles:\\/\\/(.+)\\/(\\d+)\\/(\\d+)\\/(\\d+)$/.exec(url);\n if (!match) return false;\n const [, archive = '', z, x, y] = match;\n return pmtiles(archive).tile(Number(z), Number(x), Number(y), signal);\n}\n"]}
1
+ {"version":3,"file":"pmtiles.js","sourceRoot":"","sources":["../src/pmtiles.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PMTiles v3 archives: one file of tiles read by HTTP range requests (or from a `Blob`), as Protomaps publishes them.\n * The header and root directory in one request, the leaf directories as needed (kept in a small cache), each tile in\n * its own range; gzip through `DecompressionStream`. The same reader in the page (raster tiles) and in the basemap\n * workers (vector tiles of a style source `pmtiles://…`, as MapLibre's protocol names them).\n */\nimport { Lru } from './lru.ts';\nimport { withHeaders } from './requests.ts';\n\n/** What a PMTiles archive's tiles are */\nexport type PmtilesTileType = 'unknown' | 'mvt' | 'png' | 'jpeg' | 'webp' | 'avif';\n\n/** The header of a PMTiles archive (v3) */\nexport interface PmtilesHeader {\n rootDirectoryOffset: number;\n rootDirectoryLength: number;\n metadataOffset: number;\n metadataLength: number;\n leafDirectoryOffset: number;\n leafDirectoryLength: number;\n tileDataOffset: number;\n tileDataLength: number;\n /** 1 none, 2 gzip, 3 brotli, 4 zstd (only none and gzip are read) */\n internalCompression: number;\n tileCompression: number;\n tileType: PmtilesTileType;\n minZoom: number;\n maxZoom: number;\n /** `[west, south, east, north]`, degrees */\n bounds: [number, number, number, number];\n center: [lon: number, lat: number, zoom: number];\n}\n\n/** An entry of a directory: a run of tiles (`runLength` > 0) or a leaf directory (0) */\nexport interface PmtilesEntry {\n tileId: number;\n offset: number;\n length: number;\n runLength: number;\n}\n\nconst HEADER = 127;\n/** The header and the root directory lie within the first 16 KB of the file */\nconst FIRST = 16384;\nconst TYPES: PmtilesTileType[] = ['unknown', 'mvt', 'png', 'jpeg', 'webp', 'avif'];\n\n/** Tiles before level z: (4^z - 1) / 3 */\nconst levelStart = (z: number) => (4 ** z - 1) / 3;\n\n/** The tile id of z/x/y: the tiles of the lower levels, then the position along the level's Hilbert curve */\nexport function zxyToTileId(z: number, x: number, y: number): number {\n if (z > 26) throw new Error(`isard: PMTiles level ${z} past 26`);\n const n = 2 ** z;\n if (x < 0 || y < 0 || x >= n || y >= n) throw new Error(`isard: PMTiles tile ${z}/${x}/${y} out of its level`);\n let [px, py] = [x, y];\n let d = 0;\n for (let s = n / 2; s >= 1; s /= 2) {\n const rx = (px & s) > 0 ? 1 : 0;\n const ry = (py & s) > 0 ? 1 : 0;\n d += s * s * ((3 * rx) ^ ry);\n if (ry === 0) {\n if (rx === 1) [px, py] = [s - 1 - px, s - 1 - py];\n [px, py] = [py, px];\n }\n }\n return levelStart(z) + d;\n}\n\n/** The z/x/y of a tile id (the inverse of `zxyToTileId`) */\nexport function tileIdToZxy(id: number): [z: number, x: number, y: number] {\n let z = 0;\n while (levelStart(z + 1) <= id) z += 1;\n const n = 2 ** z;\n let t = id - levelStart(z);\n let [x, y] = [0, 0];\n for (let s = 1; s < n; s *= 2) {\n // Arithmetic, not bitwise: positions pass 32 bits past level 16\n const rx = Math.floor(t / 2) % 2;\n const ry = (t % 2) ^ rx;\n if (ry === 0) {\n if (rx === 1) [x, y] = [s - 1 - x, s - 1 - y];\n [x, y] = [y, x];\n }\n x += s * rx;\n y += s * ry;\n t = Math.floor(t / 4);\n }\n return [z, x, y];\n}\n\n/** A reader of unsigned varints past 32 bits (tile ids reach 2^52) */\nclass Varints {\n pos = 0;\n constructor(private readonly bytes: Uint8Array) {}\n next(): number {\n let value = 0;\n let scale = 1;\n for (;;) {\n const b = this.bytes[this.pos++];\n if (b === undefined) throw new Error('isard: PMTiles directory truncated');\n value += (b & 0x7f) * scale;\n if (b < 0x80) return value;\n scale *= 128;\n if (scale > 2 ** 63) throw new Error('isard: PMTiles varint too long');\n }\n }\n}\n\n/** The entries of a directory (decompressed) */\nexport function parseDirectory(bytes: Uint8Array): PmtilesEntry[] {\n const v = new Varints(bytes);\n const count = v.next();\n if (count > bytes.length) throw new Error('isard: PMTiles directory larger than its bytes');\n const entries: PmtilesEntry[] = [];\n let id = 0;\n for (let i = 0; i < count; i += 1) {\n id += v.next();\n entries.push({ tileId: id, offset: 0, length: 0, runLength: 1 });\n }\n for (const e of entries) e.runLength = v.next();\n for (const e of entries) e.length = v.next();\n entries.forEach((e, i) => {\n const value = v.next();\n const previous = entries[i - 1];\n // 0 after the first: right after the previous entry's bytes\n e.offset = value === 0 && previous ? previous.offset + previous.length : value - 1;\n });\n return entries;\n}\n\n/** The entry holding a tile id: its run of tiles, or the leaf directory it falls in; undefined if none */\nexport function findEntry(entries: readonly PmtilesEntry[], id: number): PmtilesEntry | undefined {\n let [lo, hi] = [0, entries.length - 1];\n while (lo <= hi) {\n const mid = (lo + hi) >> 1;\n const e = entries[mid] as PmtilesEntry;\n if (e.tileId === id) return e;\n if (e.tileId < id) lo = mid + 1;\n else hi = mid - 1;\n }\n const e = entries[hi];\n if (!e) return undefined;\n if (e.runLength === 0 || id - e.tileId < e.runLength) return e;\n return undefined;\n}\n\n/** The header of an archive from its first bytes */\nexport function parseHeader(bytes: Uint8Array): PmtilesHeader {\n if (bytes.length < HEADER || String.fromCharCode(...bytes.subarray(0, 7)) !== 'PMTiles') {\n throw new Error('isard: not a PMTiles archive');\n }\n if (bytes[7] !== 3) throw new Error(`isard: PMTiles version ${bytes[7]} (only 3 is read)`);\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const u64 = (at: number) => Number(view.getBigUint64(at, true));\n const deg = (at: number) => view.getInt32(at, true) / 1e7;\n return {\n rootDirectoryOffset: u64(8),\n rootDirectoryLength: u64(16),\n metadataOffset: u64(24),\n metadataLength: u64(32),\n leafDirectoryOffset: u64(40),\n leafDirectoryLength: u64(48),\n tileDataOffset: u64(56),\n tileDataLength: u64(64),\n internalCompression: view.getUint8(97),\n tileCompression: view.getUint8(98),\n tileType: TYPES[view.getUint8(99)] ?? 'unknown',\n minZoom: view.getUint8(100),\n maxZoom: view.getUint8(101),\n bounds: [deg(102), deg(106), deg(110), deg(114)],\n center: [deg(119), deg(123), view.getUint8(118)],\n };\n}\n\n/** Bytes as they are stored, decompressed (1: none, 2: gzip; 0, unknown, is read as none) */\nexport async function decompress(bytes: Uint8Array, compression: number): Promise<Uint8Array> {\n if (compression === 0 || compression === 1) return bytes;\n if (compression !== 2) {\n throw new Error(`isard: PMTiles compression ${compression === 3 ? 'brotli' : 'zstd'} is not read (gzip only)`);\n }\n const stream = new Blob([bytes as Uint8Array<ArrayBuffer>]).stream().pipeThrough(new DecompressionStream('gzip'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\n/** Past this, a whole file sent for a range request (a server ignoring ranges) is an error rather than kept */\nconst WHOLE_FILE_MAX = 64 * 1024 * 1024;\n\n/** A PMTiles archive at a URL (range requests) or in a `Blob` (a dropped file) */\nexport class PMTiles {\n private head: Promise<{ header: PmtilesHeader; root: PmtilesEntry[] }> | undefined;\n /** The leaf directories read, by offset */\n private readonly leaves = new Lru<number, Promise<PmtilesEntry[]>>(64);\n /** The whole file, when the server answered a range request with it (small files, `blob:` URLs) */\n private whole: Promise<Uint8Array> | undefined;\n\n constructor(readonly source: string | Blob) {}\n\n /** `length` bytes from `offset` */\n private async range(offset: number, length: number, signal?: AbortSignal): Promise<Uint8Array> {\n if (typeof this.source !== 'string') {\n return new Uint8Array(await this.source.slice(offset, offset + length).arrayBuffer());\n }\n if (this.whole) return (await this.whole).subarray(offset, offset + length);\n const response = await fetch(\n this.source,\n withHeaders(this.source, {\n headers: { Range: `bytes=${offset}-${offset + Math.max(length, 1) - 1}` },\n ...(signal ? { signal } : {}),\n }),\n );\n if (!response.ok) throw new Error(`${this.source}: HTTP ${response.status}`);\n if (response.status === 206) return new Uint8Array(await response.arrayBuffer());\n // The whole file: kept, when small enough, for the next ranges\n const size = Number(response.headers.get('Content-Length'));\n if (size > WHOLE_FILE_MAX) {\n await response.body?.cancel();\n throw new Error(`${this.source}: the server ignores range requests (HTTP 206 expected)`);\n }\n const whole = response.arrayBuffer().then((b) => new Uint8Array(b));\n this.whole = whole;\n whole.catch(() => {\n this.whole = undefined;\n });\n return (await whole).subarray(offset, offset + length);\n }\n\n private load() {\n this.head ??= (async () => {\n const first = await this.range(0, FIRST);\n const header = parseHeader(first);\n const { rootDirectoryOffset: o, rootDirectoryLength: n } = header;\n const raw = o + n <= first.length ? first.subarray(o, o + n) : await this.range(o, n);\n const root = parseDirectory(await decompress(raw, header.internalCompression));\n return { header, root };\n })();\n // A failure is not kept: asked again next time\n this.head.catch(() => {\n this.head = undefined;\n });\n return this.head;\n }\n\n /** The archive's header */\n async header(): Promise<PmtilesHeader> {\n return (await this.load()).header;\n }\n\n /** The archive's JSON metadata (`vector_layers`, `attribution`, `name`…); `{}` if it has none */\n async metadata(): Promise<Record<string, unknown>> {\n const { header } = await this.load();\n if (header.metadataLength === 0) return {};\n const raw = await this.range(header.metadataOffset, header.metadataLength);\n const text = new TextDecoder().decode(await decompress(raw, header.internalCompression));\n const value: unknown = JSON.parse(text);\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\n }\n\n private leaf(header: PmtilesHeader, entry: PmtilesEntry): Promise<PmtilesEntry[]> {\n const offset = header.leafDirectoryOffset + entry.offset;\n let leaf = this.leaves.get(offset);\n if (!leaf) {\n leaf = this.range(offset, entry.length).then(async (raw) =>\n parseDirectory(await decompress(raw, header.internalCompression)),\n );\n leaf.catch(() => this.leaves.delete(offset));\n this.leaves.set(offset, leaf);\n }\n return leaf;\n }\n\n /** The bytes of tile z/x/y, decompressed (a vector tile ungzipped); undefined where the archive has none */\n async tile(z: number, x: number, y: number, signal?: AbortSignal): Promise<Uint8Array | undefined> {\n const { header, root } = await this.load();\n if (z < header.minZoom || z > header.maxZoom) return undefined;\n const id = zxyToTileId(z, x, y);\n let entries = root;\n // The root, then at most three levels of leaves\n for (let depth = 0; depth < 4; depth += 1) {\n const entry = findEntry(entries, id);\n if (!entry) return undefined;\n if (entry.runLength > 0) {\n const raw = await this.range(header.tileDataOffset + entry.offset, entry.length, signal);\n return decompress(raw, header.tileCompression);\n }\n entries = await this.leaf(header, entry);\n }\n throw new Error('isard: PMTiles directories nested too deep');\n }\n}\n\n/** The archives opened, by URL: one reader (and its directory cache) per archive in a page or worker */\nconst archives = new Lru<string, PMTiles>(16);\n\n/** The reader of an archive URL (without `pmtiles://`), shared */\nexport function pmtiles(url: string): PMTiles {\n let archive = archives.get(url);\n if (!archive) {\n archive = new PMTiles(url);\n archives.set(url, archive);\n }\n return archive;\n}\n\n/** The archive URL of a `pmtiles://` URL, absolute (relative to the page), or undefined for another URL */\nexport function pmtilesUrl(url: string, base?: string): string | undefined {\n if (!url.startsWith('pmtiles://')) return undefined;\n const inner = url.slice('pmtiles://'.length);\n const from = base ?? (globalThis as { location?: { href: string } }).location?.href;\n try {\n return from ? new URL(inner, from).href : inner;\n } catch {\n return inner;\n }\n}\n\n/** A tile URL `pmtiles://<archive>/{z}/{x}/{y}` (with its numbers in) read from its archive: its bytes, undefined\n * where there is none; undefined too (`false`) for a URL that is not one */\nexport function pmtilesTile(url: string, signal?: AbortSignal): Promise<Uint8Array | undefined> | false {\n const match = /^pmtiles:\\/\\/(.+)\\/(\\d+)\\/(\\d+)\\/(\\d+)$/.exec(url);\n if (!match) return false;\n const [, archive = '', z, x, y] = match;\n return pmtiles(archive).tile(Number(z), Number(x), Number(y), signal);\n}\n"]}
@@ -214,7 +214,7 @@ export class PointCloudLayer extends Layer {
214
214
  apply(engine, id) {
215
215
  const s = this.style;
216
216
  if (this.format === '3dtiles') {
217
- engine.setTiles3dStyle(id, s.maxScreenSpaceError, 1, s.pointSize);
217
+ engine.setTiles3dStyle(id, s.maxScreenSpaceError, 1, s.pointSize, new Float32Array());
218
218
  return;
219
219
  }
220
220
  const rate = this.options.requestsPerSecond ?? (/^https?:\/\/data\.geopf\.fr\//.test(this.url) ? 8 : 0);
@@ -1 +1 @@
1
- {"version":3,"file":"pointclouds.js","sourceRoot":"","sources":["../src/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 './crs.ts';\nimport { type Feature, parseColor, type Ramp, rampTexels } from './features.ts';\nimport { Layer } from './layers.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';\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);\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/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 './crs.ts';\nimport { type Feature, parseColor, type Ramp, rampTexels } from './features.ts';\nimport { Layer } from './layers.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';\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,7 +1,13 @@
1
1
  /** Messages between the main thread and the decoding workers */
2
2
  import type { DecoderUrls } from './decoders.ts';
3
+ import type { HeaderRules } from './requests.ts';
3
4
  import type { DecodedTile, TextureFormats } from './wasm/isard.js';
4
- export type WorkerRequest = {
5
+ export type WorkerRequest =
6
+ /** The page's request headers (`setRequestHeaders`) */
7
+ {
8
+ type: 'headers';
9
+ rules: HeaderRules;
10
+ } | {
5
11
  type: 'init';
6
12
  module: WebAssembly.Module;
7
13
  decoders: DecoderUrls;
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"","sourcesContent":["/** Messages between the main thread and the decoding workers */\nimport type { DecoderUrls } from './decoders.ts';\nimport type { DecodedTile, TextureFormats } from './wasm/isard.js';\n\nexport type WorkerRequest =\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"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"","sourcesContent":["/** Messages between the main thread and the decoding workers */\nimport type { DecoderUrls } from './decoders.ts';\nimport type { HeaderRules } from './requests.ts';\nimport type { DecodedTile, TextureFormats } from './wasm/isard.js';\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,14 @@
1
+ /**
2
+ * Headers added to the requests of the page by URL prefix: an access token for private sources (a Géoplateforme
3
+ * private stream, a server behind single sign-on), on every request isard makes, from the page, its workers (vector
4
+ * tiles, 3D Tiles and point clouds) and its engine (raster tiles, tilesets): `setRequestHeaders(prefix, headers)`,
5
+ * again with a new token when it is renewed. The rules of a URL are merged, the longest prefix last (it wins).
6
+ */
7
+ /** Rules: a URL prefix and its headers, the shortest prefix first */
8
+ export type HeaderRules = [prefix: string, headers: Record<string, string>][];
9
+ /**
10
+ * Adds `headers` to every request isard makes to a URL starting with `prefix` (in the page and its workers), or with
11
+ * no headers, stops: `setRequestHeaders('https://data.geopf.fr/private/', { Authorization: 'Bearer …' })`. The
12
+ * server must allow these headers (CORS). For the whole page: every map, the ones to come too
13
+ */
14
+ export declare function setRequestHeaders(prefix: string, headers?: Record<string, string>): void;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Headers added to the requests of the page by URL prefix: an access token for private sources (a Géoplateforme
3
+ * private stream, a server behind single sign-on), on every request isard makes, from the page, its workers (vector
4
+ * tiles, 3D Tiles and point clouds) and its engine (raster tiles, tilesets): `setRequestHeaders(prefix, headers)`,
5
+ * again with a new token when it is renewed. The rules of a URL are merged, the longest prefix last (it wins).
6
+ */
7
+ let rules = [];
8
+ const listeners = new Set();
9
+ /**
10
+ * Adds `headers` to every request isard makes to a URL starting with `prefix` (in the page and its workers), or with
11
+ * no headers, stops: `setRequestHeaders('https://data.geopf.fr/private/', { Authorization: 'Bearer …' })`. The
12
+ * server must allow these headers (CORS). For the whole page: every map, the ones to come too
13
+ */
14
+ export function setRequestHeaders(prefix, headers) {
15
+ const kept = rules.filter(([p]) => p !== prefix);
16
+ if (headers && Object.keys(headers).length > 0)
17
+ kept.push([prefix, { ...headers }]);
18
+ kept.sort(([p], [q]) => p.length - q.length);
19
+ setHeaderRules(kept);
20
+ for (const listener of listeners)
21
+ listener(rules);
22
+ }
23
+ /** @internal The rules now */
24
+ export function headerRules() {
25
+ return rules;
26
+ }
27
+ /** @internal The rules, from the page (a worker's copy) */
28
+ export function setHeaderRules(next) {
29
+ rules = next;
30
+ }
31
+ /** @internal Follows the rules (the workers and engines of a map); returns the function that stops */
32
+ export function onHeaderRules(listener) {
33
+ listeners.add(listener);
34
+ return () => listeners.delete(listener);
35
+ }
36
+ /** @internal `init` with the headers of the rules matching `url` (unchanged when none does) */
37
+ export function withHeaders(url, init) {
38
+ const href = String(url);
39
+ const matching = rules.filter(([prefix]) => href.startsWith(prefix));
40
+ if (matching.length === 0)
41
+ return init ?? {};
42
+ const headers = new Headers(init?.headers);
43
+ for (const [, set] of matching)
44
+ for (const [name, value] of Object.entries(set))
45
+ headers.set(name, value);
46
+ return { ...(init ?? {}), headers };
47
+ }
48
+ //# sourceMappingURL=requests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests.js","sourceRoot":"","sources":["../src/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"]}
package/dist/resample.js CHANGED
@@ -8,6 +8,7 @@
8
8
  * premultiplied). This code knows no projection.
9
9
  */
10
10
  import { Lru } from "./lru.js";
11
+ import { withHeaders } from "./requests.js";
11
12
  /** Source images kept decoded (by the page, or shared by the workers of a pool): the neighbours of a tile share them */
12
13
  export const SOURCE_CACHE = 96;
13
14
  /**
@@ -114,7 +115,7 @@ export function resampler(cached = SOURCE_CACHE) {
114
115
  let image = cache.get(url);
115
116
  if (!image) {
116
117
  image = (async () => {
117
- const response = await fetch(url);
118
+ const response = await fetch(url, withHeaders(url));
118
119
  if (response.status === 404 || response.status === 204 || response.status === 410)
119
120
  return null;
120
121
  if (!response.ok)
@@ -1 +1 @@
1
- {"version":3,"file":"resample.js","sourceRoot":"","sources":["../src/resample.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Raster reprojection, the drawing half: a Web Mercator tile drawn from the source images it spans (tiles of another\n * grid, or one image of a WMS), in a worker of the map (OffscreenCanvas) or in the page when the map has no workers.\n * The page plans each tile (`grid.ts`): which images, where they go in a mosaic, and a mesh of control points giving,\n * for the corners of 16 × 16 cells of the tile, the mosaic pixel under them. Here the images are fetched (kept for the\n * neighbouring tiles), drawn into the mosaic, and every pixel of the tile sampled from it, its source position\n * interpolated within its cell (bilinear), its color between the four nearest source pixels (bilinear, alpha\n * premultiplied). This code knows no projection.\n */\nimport { Lru } from './lru.ts';\n\n/** Source images kept decoded (by the page, or shared by the workers of a pool): the neighbours of a tile share them */\nexport const SOURCE_CACHE = 96;\n\n/** A source image and the rectangle of the mosaic it covers (pixels) */\nexport interface Placed {\n url: string;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** How to draw a Mercator tile of `size` pixels: the mosaic of the source images, and the mesh of `n` × `n` cells\n * ((n + 1)² points, rows from the north, x then y): the mosaic position of each corner, NaN where the source CRS has\n * none */\nexport interface Job {\n size: number;\n width: number;\n height: number;\n sources: Placed[];\n n: number;\n mesh: Float32Array;\n}\n\n/**\n * Samples the pixels of a `size` × `size` tile (RGBA, straight alpha) from a mosaic of `width` × `height` (RGBA,\n * straight alpha) through the mesh of a job. Pixels whose position falls outside the mosaic, or on a NaN, stay\n * transparent; the mosaic's edge fades over half a pixel\n */\nexport function resample(\n source: Uint8ClampedArray,\n width: number,\n height: number,\n mesh: Float32Array,\n n: number,\n size: number,\n): Uint8ClampedArray<ArrayBuffer> {\n const out = new Uint8ClampedArray(size * size * 4);\n const cell = size / n;\n const stride = n + 1;\n for (let row = 0; row < size; row += 1) {\n const fy = (row + 0.5) / cell;\n const j = Math.min(n - 1, Math.floor(fy));\n const ty = fy - j;\n for (let col = 0; col < size; col += 1) {\n const fx = (col + 0.5) / cell;\n const i = Math.min(n - 1, Math.floor(fx));\n const tx = fx - i;\n const a = 2 * (j * stride + i);\n const b = a + 2 * stride;\n // The corners of the cell, then the position in it\n const w00 = (1 - tx) * (1 - ty);\n const w10 = tx * (1 - ty);\n const w01 = (1 - tx) * ty;\n const w11 = tx * ty;\n const u =\n w00 * (mesh[a] as number) +\n w10 * (mesh[a + 2] as number) +\n w01 * (mesh[b] as number) +\n w11 * (mesh[b + 2] as number);\n const v =\n w00 * (mesh[a + 1] as number) +\n w10 * (mesh[a + 3] as number) +\n w01 * (mesh[b + 1] as number) +\n w11 * (mesh[b + 3] as number);\n // Pixel centers at half pixels: the four around (u, v)\n const sx = u - 0.5;\n const sy = v - 0.5;\n if (!(sx > -1 && sy > -1 && sx < width && sy < height)) continue;\n const x0 = Math.floor(sx);\n const y0 = Math.floor(sy);\n const kx = sx - x0;\n const ky = sy - y0;\n let r = 0;\n let g = 0;\n let bl = 0;\n let alpha = 0;\n for (let k = 0; k < 4; k += 1) {\n const x = x0 + (k & 1);\n const y = y0 + (k >> 1);\n if (x < 0 || y < 0 || x >= width || y >= height) continue;\n const p = 4 * (y * width + x);\n const wa = (k & 1 ? kx : 1 - kx) * (k >> 1 ? ky : 1 - ky) * (source[p + 3] as number);\n r += wa * (source[p] as number);\n g += wa * (source[p + 1] as number);\n bl += wa * (source[p + 2] as number);\n alpha += wa;\n }\n if (alpha <= 0) continue;\n const q = 4 * (row * size + col);\n out[q] = r / alpha;\n out[q + 1] = g / alpha;\n out[q + 2] = bl / alpha;\n out[q + 3] = alpha;\n }\n }\n return out;\n}\n\n/** Draws a planned tile: its image, null where the source has nothing; rejects on errors */\nexport type DrawJob = (job: Job, signal: AbortSignal) => Promise<ImageBitmap | null>;\n\n/**\n * Draws planned tiles, keeping `cached` source images decoded. A missing source image (404, 204, 410) leaves its part\n * empty; a tile with no source at all is missing; other errors reject (retried by the engine). In the page, or in a\n * worker of the map (`close` frees the images kept)\n */\nexport function resampler(cached = SOURCE_CACHE): { draw: DrawJob; close: () => void; cache: { capacity: number } } {\n type Image = Promise<ImageBitmap | null>;\n /** Tiles being drawn from each source image: an evicted one is closed once none is */\n const users = new Map<Image, number>();\n const evicted = new Set<Image>();\n const close = (image: Image) => {\n evicted.delete(image);\n image.then(\n (bitmap) => bitmap?.close(),\n () => undefined,\n );\n };\n /** Freed now, or once the tiles drawing from it are done */\n const drop = (image: Image) => {\n if (users.has(image)) evicted.add(image);\n else close(image);\n };\n // Source images by URL: a request is shared by the tiles that need it, its signal is not theirs\n const cache = new Lru<string, Image>(cached, drop);\n const release = (image: Image) => {\n const count = (users.get(image) ?? 1) - 1;\n if (count > 0) users.set(image, count);\n else {\n users.delete(image);\n if (evicted.has(image)) close(image);\n }\n };\n const fetchImage = (url: string): Image => {\n let image = cache.get(url);\n if (!image) {\n image = (async () => {\n const response = await fetch(url);\n if (response.status === 404 || response.status === 204 || response.status === 410) return null;\n if (!response.ok) throw new Error(`isard: ${response.status} for a raster to reproject`);\n return createImageBitmap(await response.blob());\n })();\n // A failure is not kept: the engine's retry fetches again\n image.catch(() => cache.delete(url));\n cache.set(url, image);\n }\n users.set(image, (users.get(image) ?? 0) + 1);\n return image;\n };\n const draw: DrawJob = async (job, signal) => {\n const pending = job.sources.map((s) => [s, fetchImage(s.url)] as const);\n try {\n const images = await Promise.all(pending.map(async ([s, image]) => [s, await image] as const));\n signal.throwIfAborted();\n if (!images.some(([, image]) => image)) return null;\n const canvas = new OffscreenCanvas(job.width, job.height);\n const context = canvas.getContext('2d', { willReadFrequently: true });\n if (!context) throw new Error('isard: no 2D canvas to reproject the tiles');\n for (const [s, image] of images) if (image) context.drawImage(image, s.x, s.y, s.w, s.h);\n const mosaic = context.getImageData(0, 0, job.width, job.height).data;\n const pixels = resample(mosaic, job.width, job.height, job.mesh, job.n, job.size);\n return createImageBitmap(new ImageData(pixels, job.size, job.size), { premultiplyAlpha: 'none' });\n } finally {\n for (const [, image] of pending) release(image);\n }\n };\n return {\n draw,\n cache,\n close: () => {\n for (const image of cache.values()) drop(image);\n cache.clear();\n },\n };\n}\n"]}
1
+ {"version":3,"file":"resample.js","sourceRoot":"","sources":["../src/resample.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Raster reprojection, the drawing half: a Web Mercator tile drawn from the source images it spans (tiles of another\n * grid, or one image of a WMS), in a worker of the map (OffscreenCanvas) or in the page when the map has no workers.\n * The page plans each tile (`grid.ts`): which images, where they go in a mosaic, and a mesh of control points giving,\n * for the corners of 16 × 16 cells of the tile, the mosaic pixel under them. Here the images are fetched (kept for the\n * neighbouring tiles), drawn into the mosaic, and every pixel of the tile sampled from it, its source position\n * interpolated within its cell (bilinear), its color between the four nearest source pixels (bilinear, alpha\n * premultiplied). This code knows no projection.\n */\nimport { Lru } from './lru.ts';\nimport { withHeaders } from './requests.ts';\n\n/** Source images kept decoded (by the page, or shared by the workers of a pool): the neighbours of a tile share them */\nexport const SOURCE_CACHE = 96;\n\n/** A source image and the rectangle of the mosaic it covers (pixels) */\nexport interface Placed {\n url: string;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** How to draw a Mercator tile of `size` pixels: the mosaic of the source images, and the mesh of `n` × `n` cells\n * ((n + 1)² points, rows from the north, x then y): the mosaic position of each corner, NaN where the source CRS has\n * none */\nexport interface Job {\n size: number;\n width: number;\n height: number;\n sources: Placed[];\n n: number;\n mesh: Float32Array;\n}\n\n/**\n * Samples the pixels of a `size` × `size` tile (RGBA, straight alpha) from a mosaic of `width` × `height` (RGBA,\n * straight alpha) through the mesh of a job. Pixels whose position falls outside the mosaic, or on a NaN, stay\n * transparent; the mosaic's edge fades over half a pixel\n */\nexport function resample(\n source: Uint8ClampedArray,\n width: number,\n height: number,\n mesh: Float32Array,\n n: number,\n size: number,\n): Uint8ClampedArray<ArrayBuffer> {\n const out = new Uint8ClampedArray(size * size * 4);\n const cell = size / n;\n const stride = n + 1;\n for (let row = 0; row < size; row += 1) {\n const fy = (row + 0.5) / cell;\n const j = Math.min(n - 1, Math.floor(fy));\n const ty = fy - j;\n for (let col = 0; col < size; col += 1) {\n const fx = (col + 0.5) / cell;\n const i = Math.min(n - 1, Math.floor(fx));\n const tx = fx - i;\n const a = 2 * (j * stride + i);\n const b = a + 2 * stride;\n // The corners of the cell, then the position in it\n const w00 = (1 - tx) * (1 - ty);\n const w10 = tx * (1 - ty);\n const w01 = (1 - tx) * ty;\n const w11 = tx * ty;\n const u =\n w00 * (mesh[a] as number) +\n w10 * (mesh[a + 2] as number) +\n w01 * (mesh[b] as number) +\n w11 * (mesh[b + 2] as number);\n const v =\n w00 * (mesh[a + 1] as number) +\n w10 * (mesh[a + 3] as number) +\n w01 * (mesh[b + 1] as number) +\n w11 * (mesh[b + 3] as number);\n // Pixel centers at half pixels: the four around (u, v)\n const sx = u - 0.5;\n const sy = v - 0.5;\n if (!(sx > -1 && sy > -1 && sx < width && sy < height)) continue;\n const x0 = Math.floor(sx);\n const y0 = Math.floor(sy);\n const kx = sx - x0;\n const ky = sy - y0;\n let r = 0;\n let g = 0;\n let bl = 0;\n let alpha = 0;\n for (let k = 0; k < 4; k += 1) {\n const x = x0 + (k & 1);\n const y = y0 + (k >> 1);\n if (x < 0 || y < 0 || x >= width || y >= height) continue;\n const p = 4 * (y * width + x);\n const wa = (k & 1 ? kx : 1 - kx) * (k >> 1 ? ky : 1 - ky) * (source[p + 3] as number);\n r += wa * (source[p] as number);\n g += wa * (source[p + 1] as number);\n bl += wa * (source[p + 2] as number);\n alpha += wa;\n }\n if (alpha <= 0) continue;\n const q = 4 * (row * size + col);\n out[q] = r / alpha;\n out[q + 1] = g / alpha;\n out[q + 2] = bl / alpha;\n out[q + 3] = alpha;\n }\n }\n return out;\n}\n\n/** Draws a planned tile: its image, null where the source has nothing; rejects on errors */\nexport type DrawJob = (job: Job, signal: AbortSignal) => Promise<ImageBitmap | null>;\n\n/**\n * Draws planned tiles, keeping `cached` source images decoded. A missing source image (404, 204, 410) leaves its part\n * empty; a tile with no source at all is missing; other errors reject (retried by the engine). In the page, or in a\n * worker of the map (`close` frees the images kept)\n */\nexport function resampler(cached = SOURCE_CACHE): { draw: DrawJob; close: () => void; cache: { capacity: number } } {\n type Image = Promise<ImageBitmap | null>;\n /** Tiles being drawn from each source image: an evicted one is closed once none is */\n const users = new Map<Image, number>();\n const evicted = new Set<Image>();\n const close = (image: Image) => {\n evicted.delete(image);\n image.then(\n (bitmap) => bitmap?.close(),\n () => undefined,\n );\n };\n /** Freed now, or once the tiles drawing from it are done */\n const drop = (image: Image) => {\n if (users.has(image)) evicted.add(image);\n else close(image);\n };\n // Source images by URL: a request is shared by the tiles that need it, its signal is not theirs\n const cache = new Lru<string, Image>(cached, drop);\n const release = (image: Image) => {\n const count = (users.get(image) ?? 1) - 1;\n if (count > 0) users.set(image, count);\n else {\n users.delete(image);\n if (evicted.has(image)) close(image);\n }\n };\n const fetchImage = (url: string): Image => {\n let image = cache.get(url);\n if (!image) {\n image = (async () => {\n const response = await fetch(url, withHeaders(url));\n if (response.status === 404 || response.status === 204 || response.status === 410) return null;\n if (!response.ok) throw new Error(`isard: ${response.status} for a raster to reproject`);\n return createImageBitmap(await response.blob());\n })();\n // A failure is not kept: the engine's retry fetches again\n image.catch(() => cache.delete(url));\n cache.set(url, image);\n }\n users.set(image, (users.get(image) ?? 0) + 1);\n return image;\n };\n const draw: DrawJob = async (job, signal) => {\n const pending = job.sources.map((s) => [s, fetchImage(s.url)] as const);\n try {\n const images = await Promise.all(pending.map(async ([s, image]) => [s, await image] as const));\n signal.throwIfAborted();\n if (!images.some(([, image]) => image)) return null;\n const canvas = new OffscreenCanvas(job.width, job.height);\n const context = canvas.getContext('2d', { willReadFrequently: true });\n if (!context) throw new Error('isard: no 2D canvas to reproject the tiles');\n for (const [s, image] of images) if (image) context.drawImage(image, s.x, s.y, s.w, s.h);\n const mosaic = context.getImageData(0, 0, job.width, job.height).data;\n const pixels = resample(mosaic, job.width, job.height, job.mesh, job.n, job.size);\n return createImageBitmap(new ImageData(pixels, job.size, job.size), { premultiplyAlpha: 'none' });\n } finally {\n for (const [, image] of pending) release(image);\n }\n };\n return {\n draw,\n cache,\n close: () => {\n for (const image of cache.values()) drop(image);\n cache.clear();\n },\n };\n}\n"]}
package/dist/style.js CHANGED
@@ -54,6 +54,7 @@ const CSS = `
54
54
  .isard-marker-stem { position: absolute; z-index: -1; width: 2px; margin-left: -1px; transform-origin: top center; background: var(--isard-marker-color); opacity: 0.8; pointer-events: none; }
55
55
  .isard-marker-stem::after { content: ""; position: absolute; bottom: -3px; left: -2px; width: 6px; height: 6px; border-radius: 50%; background: inherit; }
56
56
  .isard-marker-pin { display: block; color: var(--isard-marker-color); filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.35)); }
57
+ .isard-panel { position: absolute; top: 0; left: 0; transform-origin: 0 0; pointer-events: auto; will-change: transform; }
57
58
  .isard-popup {
58
59
  position: absolute; top: 0; left: 0; display: flex; pointer-events: none; will-change: transform; z-index: 1;
59
60
  color: var(--isard-popup-fg);
package/dist/style.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","sourceRoot":"","sources":["../src/style.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkHX,CAAC;AAEF,MAAM,MAAM,GAAG,IAAI,OAAO,EAAY,CAAC;AAEvC,mHAAmH;AACnH,MAAM,UAAU,WAAW,CAAC,GAAa;IACvC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO;IAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChB,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACzC,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;IACzB,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;IACxB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC","sourcesContent":["/**\n * Styles of the DOM overlays (markers, popups, controls), injected once per document so the package needs no CSS\n * file. Colors are custom properties, defaults on the root with no specificity: an application restyles them on any\n * element around the map (its container's class may be replaced by a framework: nothing depends on it).\n */\n\nconst CSS = `\n:where(:root) {\n --isard-ctrl-bg: #fff;\n --isard-ctrl-fg: #333;\n --isard-ctrl-hover: rgb(0 0 0 / 0.05);\n --isard-ctrl-active: #1d2433;\n --isard-ctrl-active-fg: #fff;\n --isard-ctrl-border: #ddd;\n --isard-ctrl-shadow: 0 0 0 2px rgb(0 0 0 / 0.1);\n --isard-popup-bg: #fff;\n --isard-popup-fg: #1d2433;\n --isard-marker-color: #3a6fd8;\n --isard-attrib-bg: rgb(255 255 255 / 0.5);\n --isard-attrib-fg: rgb(0 0 0 / 0.75);\n --isard-focus: #3a6fd8;\n}\n.isard-canvas:focus { outline: none; }\n.isard-canvas:focus-visible { outline: 2px solid var(--isard-focus); outline-offset: -2px; }\n.isard-overlay { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 1; }\n.isard-ctrl-top-left, .isard-ctrl-top-right, .isard-ctrl-bottom-left, .isard-ctrl-bottom-right {\n position: absolute; pointer-events: none; z-index: 2;\n}\n.isard-ctrl-top-left { top: 0; left: 0; }\n.isard-ctrl-top-right { top: 0; right: 0; }\n.isard-ctrl-bottom-left { bottom: 0; left: 0; }\n.isard-ctrl-bottom-right { bottom: 0; right: 0; }\n.isard-ctrl { clear: both; pointer-events: auto; transform: translate(0, 0); }\n.isard-ctrl-top-left .isard-ctrl { float: left; margin: 10px 0 0 10px; }\n.isard-ctrl-top-right .isard-ctrl { float: right; margin: 10px 10px 0 0; }\n.isard-ctrl-bottom-left .isard-ctrl { float: left; margin: 0 0 10px 10px; }\n.isard-ctrl-bottom-right .isard-ctrl { float: right; margin: 0 10px 10px 0; }\n.isard-ctrl-group { background: var(--isard-ctrl-bg); border-radius: 4px; box-shadow: var(--isard-ctrl-shadow); }\n.isard-ctrl-group button {\n display: block; width: 29px; height: 29px; padding: 0; margin: 0; border: 0; box-sizing: border-box;\n background: transparent; color: var(--isard-ctrl-fg); cursor: pointer; font: inherit;\n}\n.isard-ctrl-group button + button { border-top: 1px solid var(--isard-ctrl-border); }\n.isard-ctrl-group button:first-child { border-radius: 4px 4px 0 0; }\n.isard-ctrl-group button:last-child { border-radius: 0 0 4px 4px; }\n.isard-ctrl-group button:only-child { border-radius: inherit; }\n.isard-ctrl-group button:hover { background-color: var(--isard-ctrl-hover); }\n.isard-ctrl-group button:focus-visible { outline: 2px solid var(--isard-ctrl-active); outline-offset: -2px; }\n.isard-ctrl-group button.active { background: var(--isard-ctrl-active); color: var(--isard-ctrl-active-fg); }\n.isard-ctrl-group button svg { display: block; margin: auto; pointer-events: none; }\n.isard-ctrl-compass svg { transition: transform 0.05s; }\n.isard-marker { position: absolute; top: 0; left: 0; pointer-events: auto; will-change: transform; }\n.isard-marker-draggable { cursor: grab; touch-action: none; }\n.isard-marker-dragging { cursor: grabbing; }\n.isard-marker-stem { position: absolute; z-index: -1; width: 2px; margin-left: -1px; transform-origin: top center; background: var(--isard-marker-color); opacity: 0.8; pointer-events: none; }\n.isard-marker-stem::after { content: \"\"; position: absolute; bottom: -3px; left: -2px; width: 6px; height: 6px; border-radius: 50%; background: inherit; }\n.isard-marker-pin { display: block; color: var(--isard-marker-color); filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.35)); }\n.isard-popup {\n position: absolute; top: 0; left: 0; display: flex; pointer-events: none; will-change: transform; z-index: 1;\n color: var(--isard-popup-fg);\n}\n.isard-popup-anchor-top, .isard-popup-anchor-top-left, .isard-popup-anchor-top-right { flex-direction: column; }\n.isard-popup-anchor-bottom, .isard-popup-anchor-bottom-left, .isard-popup-anchor-bottom-right {\n flex-direction: column-reverse;\n}\n.isard-popup-anchor-left { flex-direction: row; }\n.isard-popup-anchor-right { flex-direction: row-reverse; }\n.isard-popup-tip { width: 0; height: 0; border: 10px solid transparent; z-index: 1; }\n.isard-popup-anchor-top .isard-popup-tip { align-self: center; border-top: none; border-bottom-color: var(--isard-popup-bg); }\n.isard-popup-anchor-top-left .isard-popup-tip {\n align-self: flex-start; border-top: none; border-left: none; border-bottom-color: var(--isard-popup-bg);\n}\n.isard-popup-anchor-top-right .isard-popup-tip {\n align-self: flex-end; border-top: none; border-right: none; border-bottom-color: var(--isard-popup-bg);\n}\n.isard-popup-anchor-bottom .isard-popup-tip { align-self: center; border-bottom: none; border-top-color: var(--isard-popup-bg); }\n.isard-popup-anchor-bottom-left .isard-popup-tip {\n align-self: flex-start; border-bottom: none; border-left: none; border-top-color: var(--isard-popup-bg);\n}\n.isard-popup-anchor-bottom-right .isard-popup-tip {\n align-self: flex-end; border-bottom: none; border-right: none; border-top-color: var(--isard-popup-bg);\n}\n.isard-popup-anchor-left .isard-popup-tip { align-self: center; border-left: none; border-right-color: var(--isard-popup-bg); }\n.isard-popup-anchor-right .isard-popup-tip { align-self: center; border-right: none; border-left-color: var(--isard-popup-bg); }\n.isard-popup-content {\n position: relative; padding: 12px 14px; border-radius: 4px; background: var(--isard-popup-bg);\n box-shadow: 0 1px 4px rgb(0 0 0 / 0.2); pointer-events: auto; overflow-wrap: break-word;\n}\n.isard-popup-has-close .isard-popup-content { padding-right: 26px; }\n.isard-popup-anchor-top-left .isard-popup-content { border-top-left-radius: 0; }\n.isard-popup-anchor-top-right .isard-popup-content { border-top-right-radius: 0; }\n.isard-popup-anchor-bottom-left .isard-popup-content { border-bottom-left-radius: 0; }\n.isard-popup-anchor-bottom-right .isard-popup-content { border-bottom-right-radius: 0; }\n.isard-popup-close {\n position: absolute; top: 0; right: 0; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 0 4px 0 4px;\n background: transparent; color: inherit; font: 18px/22px system-ui, sans-serif; cursor: pointer;\n}\n.isard-popup-close:hover { background: rgb(0 0 0 / 0.05); }\n.isard-popup-close:focus-visible, .isard-attrib-button:focus-visible, .isard-attrib a:focus-visible {\n outline: 2px solid var(--isard-focus); outline-offset: -2px;\n}\n.isard-attrib {\n display: flex; align-items: center; gap: 4px; padding: 0 5px; border-radius: 4px; background: var(--isard-attrib-bg);\n color: var(--isard-attrib-fg); font: 12px/20px system-ui, sans-serif;\n}\n.isard-ctrl-bottom-right .isard-ctrl.isard-attrib, .isard-ctrl-bottom-left .isard-ctrl.isard-attrib { margin-bottom: 0; }\n.isard-ctrl-bottom-right .isard-ctrl.isard-attrib { margin-right: 0; border-radius: 4px 0 0 0; }\n.isard-ctrl-bottom-left .isard-ctrl.isard-attrib { margin-left: 0; border-radius: 0 4px 0 0; }\n.isard-attrib a { color: inherit; text-decoration: none; }\n.isard-attrib a:hover { text-decoration: underline; }\n.isard-attrib-button {\n display: none; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 12px; flex: none;\n background: var(--isard-ctrl-bg); color: var(--isard-ctrl-fg); cursor: pointer;\n}\n.isard-attrib-button svg { display: block; margin: auto; }\n.isard-ctrl.isard-attrib.isard-attrib-compact { min-height: 24px; padding: 2px; border-radius: 12px; margin: 0 10px 10px; }\n.isard-attrib-compact .isard-attrib-button { display: block; }\n.isard-attrib-compact .isard-attrib-inner { display: none; padding: 0 6px 0 2px; }\n.isard-attrib-compact.isard-attrib-open { background: var(--isard-ctrl-bg); }\n.isard-attrib-compact.isard-attrib-open .isard-attrib-inner { display: block; }\n`;\n\nconst styled = new WeakSet<Document>();\n\n/** Adds the overlay styles to a document, once; first in the head so application rules win at equal specificity */\nexport function injectStyle(doc: Document): void {\n if (styled.has(doc)) return;\n styled.add(doc);\n const style = doc.createElement('style');\n style.dataset.isard = '';\n style.textContent = CSS;\n doc.head.prepend(style);\n}\n"]}
1
+ {"version":3,"file":"style.js","sourceRoot":"","sources":["../src/style.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmHX,CAAC;AAEF,MAAM,MAAM,GAAG,IAAI,OAAO,EAAY,CAAC;AAEvC,mHAAmH;AACnH,MAAM,UAAU,WAAW,CAAC,GAAa;IACvC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO;IAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChB,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACzC,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;IACzB,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;IACxB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC","sourcesContent":["/**\n * Styles of the DOM overlays (markers, popups, controls), injected once per document so the package needs no CSS\n * file. Colors are custom properties, defaults on the root with no specificity: an application restyles them on any\n * element around the map (its container's class may be replaced by a framework: nothing depends on it).\n */\n\nconst CSS = `\n:where(:root) {\n --isard-ctrl-bg: #fff;\n --isard-ctrl-fg: #333;\n --isard-ctrl-hover: rgb(0 0 0 / 0.05);\n --isard-ctrl-active: #1d2433;\n --isard-ctrl-active-fg: #fff;\n --isard-ctrl-border: #ddd;\n --isard-ctrl-shadow: 0 0 0 2px rgb(0 0 0 / 0.1);\n --isard-popup-bg: #fff;\n --isard-popup-fg: #1d2433;\n --isard-marker-color: #3a6fd8;\n --isard-attrib-bg: rgb(255 255 255 / 0.5);\n --isard-attrib-fg: rgb(0 0 0 / 0.75);\n --isard-focus: #3a6fd8;\n}\n.isard-canvas:focus { outline: none; }\n.isard-canvas:focus-visible { outline: 2px solid var(--isard-focus); outline-offset: -2px; }\n.isard-overlay { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 1; }\n.isard-ctrl-top-left, .isard-ctrl-top-right, .isard-ctrl-bottom-left, .isard-ctrl-bottom-right {\n position: absolute; pointer-events: none; z-index: 2;\n}\n.isard-ctrl-top-left { top: 0; left: 0; }\n.isard-ctrl-top-right { top: 0; right: 0; }\n.isard-ctrl-bottom-left { bottom: 0; left: 0; }\n.isard-ctrl-bottom-right { bottom: 0; right: 0; }\n.isard-ctrl { clear: both; pointer-events: auto; transform: translate(0, 0); }\n.isard-ctrl-top-left .isard-ctrl { float: left; margin: 10px 0 0 10px; }\n.isard-ctrl-top-right .isard-ctrl { float: right; margin: 10px 10px 0 0; }\n.isard-ctrl-bottom-left .isard-ctrl { float: left; margin: 0 0 10px 10px; }\n.isard-ctrl-bottom-right .isard-ctrl { float: right; margin: 0 10px 10px 0; }\n.isard-ctrl-group { background: var(--isard-ctrl-bg); border-radius: 4px; box-shadow: var(--isard-ctrl-shadow); }\n.isard-ctrl-group button {\n display: block; width: 29px; height: 29px; padding: 0; margin: 0; border: 0; box-sizing: border-box;\n background: transparent; color: var(--isard-ctrl-fg); cursor: pointer; font: inherit;\n}\n.isard-ctrl-group button + button { border-top: 1px solid var(--isard-ctrl-border); }\n.isard-ctrl-group button:first-child { border-radius: 4px 4px 0 0; }\n.isard-ctrl-group button:last-child { border-radius: 0 0 4px 4px; }\n.isard-ctrl-group button:only-child { border-radius: inherit; }\n.isard-ctrl-group button:hover { background-color: var(--isard-ctrl-hover); }\n.isard-ctrl-group button:focus-visible { outline: 2px solid var(--isard-ctrl-active); outline-offset: -2px; }\n.isard-ctrl-group button.active { background: var(--isard-ctrl-active); color: var(--isard-ctrl-active-fg); }\n.isard-ctrl-group button svg { display: block; margin: auto; pointer-events: none; }\n.isard-ctrl-compass svg { transition: transform 0.05s; }\n.isard-marker { position: absolute; top: 0; left: 0; pointer-events: auto; will-change: transform; }\n.isard-marker-draggable { cursor: grab; touch-action: none; }\n.isard-marker-dragging { cursor: grabbing; }\n.isard-marker-stem { position: absolute; z-index: -1; width: 2px; margin-left: -1px; transform-origin: top center; background: var(--isard-marker-color); opacity: 0.8; pointer-events: none; }\n.isard-marker-stem::after { content: \"\"; position: absolute; bottom: -3px; left: -2px; width: 6px; height: 6px; border-radius: 50%; background: inherit; }\n.isard-marker-pin { display: block; color: var(--isard-marker-color); filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.35)); }\n.isard-panel { position: absolute; top: 0; left: 0; transform-origin: 0 0; pointer-events: auto; will-change: transform; }\n.isard-popup {\n position: absolute; top: 0; left: 0; display: flex; pointer-events: none; will-change: transform; z-index: 1;\n color: var(--isard-popup-fg);\n}\n.isard-popup-anchor-top, .isard-popup-anchor-top-left, .isard-popup-anchor-top-right { flex-direction: column; }\n.isard-popup-anchor-bottom, .isard-popup-anchor-bottom-left, .isard-popup-anchor-bottom-right {\n flex-direction: column-reverse;\n}\n.isard-popup-anchor-left { flex-direction: row; }\n.isard-popup-anchor-right { flex-direction: row-reverse; }\n.isard-popup-tip { width: 0; height: 0; border: 10px solid transparent; z-index: 1; }\n.isard-popup-anchor-top .isard-popup-tip { align-self: center; border-top: none; border-bottom-color: var(--isard-popup-bg); }\n.isard-popup-anchor-top-left .isard-popup-tip {\n align-self: flex-start; border-top: none; border-left: none; border-bottom-color: var(--isard-popup-bg);\n}\n.isard-popup-anchor-top-right .isard-popup-tip {\n align-self: flex-end; border-top: none; border-right: none; border-bottom-color: var(--isard-popup-bg);\n}\n.isard-popup-anchor-bottom .isard-popup-tip { align-self: center; border-bottom: none; border-top-color: var(--isard-popup-bg); }\n.isard-popup-anchor-bottom-left .isard-popup-tip {\n align-self: flex-start; border-bottom: none; border-left: none; border-top-color: var(--isard-popup-bg);\n}\n.isard-popup-anchor-bottom-right .isard-popup-tip {\n align-self: flex-end; border-bottom: none; border-right: none; border-top-color: var(--isard-popup-bg);\n}\n.isard-popup-anchor-left .isard-popup-tip { align-self: center; border-left: none; border-right-color: var(--isard-popup-bg); }\n.isard-popup-anchor-right .isard-popup-tip { align-self: center; border-right: none; border-left-color: var(--isard-popup-bg); }\n.isard-popup-content {\n position: relative; padding: 12px 14px; border-radius: 4px; background: var(--isard-popup-bg);\n box-shadow: 0 1px 4px rgb(0 0 0 / 0.2); pointer-events: auto; overflow-wrap: break-word;\n}\n.isard-popup-has-close .isard-popup-content { padding-right: 26px; }\n.isard-popup-anchor-top-left .isard-popup-content { border-top-left-radius: 0; }\n.isard-popup-anchor-top-right .isard-popup-content { border-top-right-radius: 0; }\n.isard-popup-anchor-bottom-left .isard-popup-content { border-bottom-left-radius: 0; }\n.isard-popup-anchor-bottom-right .isard-popup-content { border-bottom-right-radius: 0; }\n.isard-popup-close {\n position: absolute; top: 0; right: 0; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 0 4px 0 4px;\n background: transparent; color: inherit; font: 18px/22px system-ui, sans-serif; cursor: pointer;\n}\n.isard-popup-close:hover { background: rgb(0 0 0 / 0.05); }\n.isard-popup-close:focus-visible, .isard-attrib-button:focus-visible, .isard-attrib a:focus-visible {\n outline: 2px solid var(--isard-focus); outline-offset: -2px;\n}\n.isard-attrib {\n display: flex; align-items: center; gap: 4px; padding: 0 5px; border-radius: 4px; background: var(--isard-attrib-bg);\n color: var(--isard-attrib-fg); font: 12px/20px system-ui, sans-serif;\n}\n.isard-ctrl-bottom-right .isard-ctrl.isard-attrib, .isard-ctrl-bottom-left .isard-ctrl.isard-attrib { margin-bottom: 0; }\n.isard-ctrl-bottom-right .isard-ctrl.isard-attrib { margin-right: 0; border-radius: 4px 0 0 0; }\n.isard-ctrl-bottom-left .isard-ctrl.isard-attrib { margin-left: 0; border-radius: 0 4px 0 0; }\n.isard-attrib a { color: inherit; text-decoration: none; }\n.isard-attrib a:hover { text-decoration: underline; }\n.isard-attrib-button {\n display: none; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 12px; flex: none;\n background: var(--isard-ctrl-bg); color: var(--isard-ctrl-fg); cursor: pointer;\n}\n.isard-attrib-button svg { display: block; margin: auto; }\n.isard-ctrl.isard-attrib.isard-attrib-compact { min-height: 24px; padding: 2px; border-radius: 12px; margin: 0 10px 10px; }\n.isard-attrib-compact .isard-attrib-button { display: block; }\n.isard-attrib-compact .isard-attrib-inner { display: none; padding: 0 6px 0 2px; }\n.isard-attrib-compact.isard-attrib-open { background: var(--isard-ctrl-bg); }\n.isard-attrib-compact.isard-attrib-open .isard-attrib-inner { display: block; }\n`;\n\nconst styled = new WeakSet<Document>();\n\n/** Adds the overlay styles to a document, once; first in the head so application rules win at equal specificity */\nexport function injectStyle(doc: Document): void {\n if (styled.has(doc)) return;\n styled.add(doc);\n const style = doc.createElement('style');\n style.dataset.isard = '';\n style.textContent = CSS;\n doc.head.prepend(style);\n}\n"]}