isard 1.8.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/CHANGELOG.md +82 -1
  2. package/README.md +9 -4
  3. package/dist/basemap/grid.js +2 -5
  4. package/dist/basemap/grid.js.map +1 -1
  5. package/dist/basemap/models/furniture.d.ts +12 -0
  6. package/dist/basemap/{furniture.js → models/furniture.js} +6 -8
  7. package/dist/basemap/models/furniture.js.map +1 -0
  8. package/dist/basemap/{meshes.js → models/meshes.js} +1 -1
  9. package/dist/basemap/models/meshes.js.map +1 -0
  10. package/dist/basemap/models/trees.d.ts +21 -0
  11. package/dist/basemap/{trees.js → models/trees.js} +4 -36
  12. package/dist/basemap/models/trees.js.map +1 -0
  13. package/dist/basemap/placed.d.ts +2 -0
  14. package/dist/basemap/placed.js +2 -0
  15. package/dist/basemap/placed.js.map +1 -1
  16. package/dist/basemap/pmtiles.js +4 -3
  17. package/dist/basemap/pmtiles.js.map +1 -1
  18. package/dist/basemap/pmtileslayer.d.ts +4 -4
  19. package/dist/basemap/pmtileslayer.js +2 -1
  20. package/dist/basemap/pmtileslayer.js.map +1 -1
  21. package/dist/basemap/resample.js +3 -2
  22. package/dist/basemap/resample.js.map +1 -1
  23. package/dist/basemap/terrain.d.ts +5 -0
  24. package/dist/basemap/terrain.js +6 -4
  25. package/dist/basemap/terrain.js.map +1 -1
  26. package/dist/basemap/vectortiles/context.d.ts +3 -2
  27. package/dist/basemap/vectortiles/context.js.map +1 -1
  28. package/dist/basemap/vectortiles/extrusions.js.map +1 -1
  29. package/dist/basemap/vectortiles/furniture.d.ts +3 -3
  30. package/dist/basemap/vectortiles/furniture.js +2 -1
  31. package/dist/basemap/vectortiles/furniture.js.map +1 -1
  32. package/dist/basemap/vectortiles/labels.js +2 -1
  33. package/dist/basemap/vectortiles/labels.js.map +1 -1
  34. package/dist/basemap/vectortiles/lamps.d.ts +3 -3
  35. package/dist/basemap/vectortiles/lamps.js +1 -1
  36. package/dist/basemap/vectortiles/lamps.js.map +1 -1
  37. package/dist/basemap/vectortiles/placed.d.ts +3 -2
  38. package/dist/basemap/vectortiles/placed.js +5 -10
  39. package/dist/basemap/vectortiles/placed.js.map +1 -1
  40. package/dist/basemap/vectortiles/requests.d.ts +8 -1
  41. package/dist/basemap/vectortiles/requests.js +32 -4
  42. package/dist/basemap/vectortiles/requests.js.map +1 -1
  43. package/dist/basemap/vectortiles/street-wind.js +2 -2
  44. package/dist/basemap/vectortiles/street-wind.js.map +1 -1
  45. package/dist/basemap/vectortiles/style.js +7 -8
  46. package/dist/basemap/vectortiles/style.js.map +1 -1
  47. package/dist/basemap/vectortiles/tiles.d.ts +1 -3
  48. package/dist/basemap/vectortiles/tiles.js +1 -1
  49. package/dist/basemap/vectortiles/tiles.js.map +1 -1
  50. package/dist/basemap/vectortiles/trees.d.ts +4 -4
  51. package/dist/basemap/vectortiles/trees.js +2 -1
  52. package/dist/basemap/vectortiles/trees.js.map +1 -1
  53. package/dist/basemap/vectortiles/vectors.d.ts +9 -3
  54. package/dist/basemap/vectortiles/vectors.js +26 -2
  55. package/dist/basemap/vectortiles/vectors.js.map +1 -1
  56. package/dist/basemap/vectortiles.d.ts +8 -6
  57. package/dist/basemap/vectortiles.js +7 -4
  58. package/dist/basemap/vectortiles.js.map +1 -1
  59. package/dist/basemap/wmts.js +3 -4
  60. package/dist/basemap/wmts.js.map +1 -1
  61. package/dist/basemap/{trees.d.ts → woods.d.ts} +2 -19
  62. package/dist/basemap/woods.js +38 -0
  63. package/dist/basemap/woods.js.map +1 -0
  64. package/dist/basemap/workerpool.d.ts +1 -1
  65. package/dist/basemap/workerpool.js +3 -3
  66. package/dist/basemap/workerpool.js.map +1 -1
  67. package/dist/basemap.worker.js +2 -2
  68. package/dist/basemap.worker.js.map +23 -22
  69. package/dist/bind/layers.js +3 -0
  70. package/dist/bind/layers.js.map +1 -1
  71. package/dist/data/collada.js +4 -4
  72. package/dist/data/collada.js.map +1 -1
  73. package/dist/data/ifc.js +6 -11
  74. package/dist/data/ifc.js.map +1 -1
  75. package/dist/data/tileset.d.ts +21 -0
  76. package/dist/data/tileset.js +101 -0
  77. package/dist/data/tileset.js.map +1 -0
  78. package/dist/decoder.worker.js +5 -5
  79. package/dist/decoder.worker.js.map +7 -6
  80. package/dist/decoding/decoders.js.map +1 -0
  81. package/dist/{engine → decoding}/loader.js +2 -2
  82. package/dist/decoding/loader.js.map +1 -0
  83. package/dist/{engine → decoding}/protocol.d.ts +1 -1
  84. package/dist/decoding/protocol.js.map +1 -0
  85. package/dist/engine-loader.d.ts +3 -3
  86. package/dist/engine-loader.js +12 -5
  87. package/dist/engine-loader.js.map +1 -1
  88. package/dist/geoplateforme.d.ts +2 -1
  89. package/dist/geoplateforme.js +6 -8
  90. package/dist/geoplateforme.js.map +1 -1
  91. package/dist/index.d.ts +15 -7
  92. package/dist/index.js +9 -3
  93. package/dist/index.js.map +1 -1
  94. package/dist/isard_bg.wasm +0 -0
  95. package/dist/isard_core_bg.wasm +0 -0
  96. package/dist/isard_tess_bg.wasm +0 -0
  97. package/dist/layers/custom.d.ts +56 -0
  98. package/dist/layers/custom.js +93 -0
  99. package/dist/layers/custom.js.map +1 -0
  100. package/dist/layers/extrusions.d.ts +4 -2
  101. package/dist/layers/extrusions.js +2 -1
  102. package/dist/layers/extrusions.js.map +1 -1
  103. package/dist/layers/features.d.ts +3 -14
  104. package/dist/layers/features.js +4 -25
  105. package/dist/layers/features.js.map +1 -1
  106. package/dist/layers/flow.d.ts +3 -3
  107. package/dist/layers/flow.js +3 -4
  108. package/dist/layers/flow.js.map +1 -1
  109. package/dist/layers/glyphs.js +5 -3
  110. package/dist/layers/glyphs.js.map +1 -1
  111. package/dist/layers/ground.d.ts +57 -0
  112. package/dist/layers/ground.js +78 -0
  113. package/dist/layers/ground.js.map +1 -0
  114. package/dist/layers/icons.js +8 -6
  115. package/dist/layers/icons.js.map +1 -1
  116. package/dist/layers/layers.d.ts +2 -199
  117. package/dist/layers/layers.js +2 -469
  118. package/dist/layers/layers.js.map +1 -1
  119. package/dist/layers/models.d.ts +48 -0
  120. package/dist/layers/models.js +111 -0
  121. package/dist/layers/models.js.map +1 -0
  122. package/dist/layers/network.d.ts +26 -0
  123. package/dist/layers/network.js +127 -0
  124. package/dist/layers/network.js.map +1 -0
  125. package/dist/layers/panoramas.d.ts +2 -11
  126. package/dist/layers/panoramas.js +19 -9
  127. package/dist/layers/panoramas.js.map +1 -1
  128. package/dist/layers/photos.d.ts +4 -7
  129. package/dist/layers/photos.js +3 -4
  130. package/dist/layers/photos.js.map +1 -1
  131. package/dist/layers/pointclouds.d.ts +3 -2
  132. package/dist/layers/pointclouds.js +3 -3
  133. package/dist/layers/pointclouds.js.map +1 -1
  134. package/dist/layers/raster.d.ts +9 -0
  135. package/dist/layers/raster.js +24 -0
  136. package/dist/layers/raster.js.map +1 -0
  137. package/dist/layers/symbols.d.ts +2 -2
  138. package/dist/layers/symbols.js +2 -1
  139. package/dist/layers/symbols.js.map +1 -1
  140. package/dist/layers/tiles3d.d.ts +20 -0
  141. package/dist/layers/tiles3d.js +69 -0
  142. package/dist/layers/tiles3d.js.map +1 -0
  143. package/dist/layers/trees.d.ts +5 -7
  144. package/dist/layers/trees.js +2 -1
  145. package/dist/layers/trees.js.map +1 -1
  146. package/dist/layers/vectors.d.ts +3 -0
  147. package/dist/layers/vectors.js +4 -0
  148. package/dist/layers/vectors.js.map +1 -1
  149. package/dist/map/basemap-layers.js +1 -1
  150. package/dist/map/basemap-layers.js.map +1 -1
  151. package/dist/map/engine-settings.d.ts +1 -1
  152. package/dist/map/engine-settings.js +1 -1
  153. package/dist/map/engine-settings.js.map +1 -1
  154. package/dist/map/engines.js.map +1 -1
  155. package/dist/map/layer-spec.d.ts +7 -13
  156. package/dist/map/layer-spec.js.map +1 -1
  157. package/dist/map/workers.js +3 -4
  158. package/dist/map/workers.js.map +1 -1
  159. package/dist/map.d.ts +25 -58
  160. package/dist/map.js +61 -53
  161. package/dist/map.js.map +1 -1
  162. package/dist/panoramax.js +6 -8
  163. package/dist/panoramax.js.map +1 -1
  164. package/dist/react/CustomLayer.d.ts +1 -1
  165. package/dist/react/CustomLayer.js.map +1 -1
  166. package/dist/react/Layer.d.ts +5 -1
  167. package/dist/react/Layer.js.map +1 -1
  168. package/dist/react/VectorGeometry.d.ts +4 -0
  169. package/dist/react/VectorGeometry.js +6 -3
  170. package/dist/react/VectorGeometry.js.map +1 -1
  171. package/dist/react/VectorTiles.d.ts +2 -2
  172. package/dist/react/VectorTiles.js +1 -1
  173. package/dist/react/VectorTiles.js.map +1 -1
  174. package/dist/types.d.ts +16 -4
  175. package/dist/types.js.map +1 -1
  176. package/dist/ui/controls.js +2 -1
  177. package/dist/ui/controls.js.map +1 -1
  178. package/dist/ui/interaction.d.ts +4 -0
  179. package/dist/ui/interaction.js +59 -7
  180. package/dist/ui/interaction.js.map +1 -1
  181. package/dist/ui/minimap.js +1 -1
  182. package/dist/ui/minimap.js.map +1 -1
  183. package/dist/ui/overlay.js +3 -3
  184. package/dist/ui/overlay.js.map +1 -1
  185. package/dist/ui/search.js +1 -1
  186. package/dist/ui/search.js.map +1 -1
  187. package/dist/util/animation.js +3 -2
  188. package/dist/util/animation.js.map +1 -1
  189. package/dist/util/color.d.ts +10 -0
  190. package/dist/util/color.js +29 -9
  191. package/dist/util/color.js.map +1 -1
  192. package/dist/util/fetch.d.ts +5 -0
  193. package/dist/util/fetch.js +11 -0
  194. package/dist/util/fetch.js.map +1 -0
  195. package/dist/util/geo.d.ts +5 -0
  196. package/dist/util/geo.js +8 -2
  197. package/dist/util/geo.js.map +1 -1
  198. package/dist/util/math.d.ts +3 -0
  199. package/dist/util/math.js +4 -0
  200. package/dist/util/math.js.map +1 -0
  201. package/dist/util/requests.js.map +1 -0
  202. package/dist/util/roofs.d.ts +0 -2
  203. package/dist/util/roofs.js +0 -3
  204. package/dist/util/roofs.js.map +1 -1
  205. package/dist/wasm/isard.d.ts +18 -1
  206. package/dist/wasm/isard.js +28 -2
  207. package/dist/wasm/isard_core.d.ts +13 -1
  208. package/dist/wasm/isard_core.js +20 -2
  209. package/dist/workers/basemap/geometry.d.ts +9 -19
  210. package/dist/workers/{basemap.worker.d.ts → basemap/protocol.d.ts} +32 -23
  211. package/dist/workers/basemap/street.d.ts +4 -2
  212. package/dist/workers/basemap/tiles.d.ts +1 -3
  213. package/dist/workers/basemap/trees.d.ts +2 -2
  214. package/package.json +1 -1
  215. package/dist/basemap/furniture.d.ts +0 -26
  216. package/dist/basemap/furniture.js.map +0 -1
  217. package/dist/basemap/meshes.js.map +0 -1
  218. package/dist/basemap/trees.js.map +0 -1
  219. package/dist/engine/decoders.js.map +0 -1
  220. package/dist/engine/loader.js.map +0 -1
  221. package/dist/engine/protocol.js.map +0 -1
  222. package/dist/engine/requests.js.map +0 -1
  223. package/dist/workers/basemap/furniture.d.ts +0 -13
  224. package/dist/workers/basemap/labels.d.ts +0 -24
  225. package/dist/workers/basemap/lamps.d.ts +0 -10
  226. package/dist/workers/basemap/raster.d.ts +0 -10
  227. package/dist/workers/basemap.worker.js +0 -221
  228. package/dist/workers/basemap.worker.js.map +0 -1
  229. /package/dist/basemap/{meshes.d.ts → models/meshes.d.ts} +0 -0
  230. /package/dist/{engine → decoding}/decoders.d.ts +0 -0
  231. /package/dist/{engine → decoding}/decoders.js +0 -0
  232. /package/dist/{engine → decoding}/loader.d.ts +0 -0
  233. /package/dist/{engine → decoding}/protocol.js +0 -0
  234. /package/dist/{engine → util}/requests.d.ts +0 -0
  235. /package/dist/{engine → util}/requests.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/ui/search.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The search bar: places suggested as the user types (the Géoplateforme's geocoding by default, or yours), the map\n * flying to the one picked. A combobox for screen readers: arrows move in the list, Enter picks, Escape closes.\n */\n\nimport { type GeocodedPlace, geoplateformeGeocode } from '../geoplateforme.ts';\nimport type { GeoMap } from '../map.ts';\nimport type { Control } from './controls.ts';\n\nexport interface SearchOptions {\n /** The places of a text (default: the Géoplateforme's geocoding, France) */\n geocode?: (text: string, signal: AbortSignal) => Promise<GeocodedPlace[]>;\n /** What a pick does (default: a flight there, closer for an address than for a place) */\n onSelect?: (place: GeocodedPlace, map: GeoMap) => void;\n /** Default 'Search a place' */\n placeholder?: string;\n /** Suggestions shown at most (default 8) */\n maxResults?: number;\n}\n\n/** Milliseconds of typing before the text is looked up */\nconst DEBOUNCE_MS = 250;\n\n/** The default pick: a flight to the place, an address seen closer than a town */\nconst flyThere = (place: GeocodedPlace, map: GeoMap) =>\n map.flyTo({ center: place.lonLat, zoom: place.kind === 'address' ? 17 : 14 });\n\n/** A text box and the places it suggests, in a corner of the map */\nexport class SearchControl implements Control {\n private readonly options: SearchOptions;\n private stop: (() => void) | undefined;\n\n constructor(options: SearchOptions = {}) {\n this.options = options;\n }\n\n onAdd(map: GeoMap): HTMLElement {\n const { geocode, onSelect = flyThere, placeholder = 'Search a place', maxResults = 8 } = this.options;\n const lookUp = geocode ?? ((text: string, signal: AbortSignal) => geoplateformeGeocode(text, { signal }));\n const element = document.createElement('div');\n const input = document.createElement('input');\n const list = document.createElement('ul');\n const listId = `isard-search-${Math.random().toString(36).slice(2)}`;\n const state: {\n places: GeocodedPlace[];\n active: number;\n timer?: ReturnType<typeof setTimeout>;\n query?: AbortController;\n } = { places: [], active: -1 };\n\n element.className = 'isard-ctrl-search';\n input.type = 'search';\n input.placeholder = placeholder;\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-label', placeholder);\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-controls', listId);\n input.setAttribute('aria-expanded', 'false');\n list.id = listId;\n list.setAttribute('role', 'listbox');\n list.hidden = true;\n element.append(input, list);\n\n const show = () => {\n list.replaceChildren(\n ...state.places.map((place, i) => {\n const item = document.createElement('li');\n\n item.id = `${listId}-${i}`;\n item.setAttribute('role', 'option');\n item.setAttribute('aria-selected', String(i === state.active));\n item.textContent = place.label;\n // Before the input's blur\n item.addEventListener('pointerdown', (e) => {\n e.preventDefault();\n pick(i);\n });\n\n return item;\n }),\n );\n list.hidden = state.places.length === 0;\n input.setAttribute('aria-expanded', String(!list.hidden));\n if (state.active >= 0) input.setAttribute('aria-activedescendant', `${listId}-${state.active}`);\n else input.removeAttribute('aria-activedescendant');\n };\n const close = () => {\n state.places = [];\n state.active = -1;\n show();\n };\n const pick = (i: number) => {\n const place = state.places[i];\n\n if (!place) return;\n input.value = place.label;\n close();\n onSelect(place, map);\n };\n const search = () => {\n state.query?.abort();\n\n const query = new AbortController();\n\n state.query = query;\n lookUp(input.value, query.signal).then(\n (places) => {\n if (query.signal.aborted) return;\n state.places = places.slice(0, maxResults);\n state.active = -1;\n show();\n },\n (error: unknown) => {\n if (!query.signal.aborted) console.warn(error);\n },\n );\n };\n\n input.addEventListener('input', () => {\n clearTimeout(state.timer);\n state.timer = setTimeout(search, DEBOUNCE_MS);\n });\n input.addEventListener('keydown', (e) => {\n const count = state.places.length;\n\n if (e.key === 'ArrowDown' && count > 0) state.active = (state.active + 1) % count;\n else if (e.key === 'ArrowUp' && count > 0) state.active = (state.active - 1 + count) % count;\n else if (e.key === 'Enter') pick(Math.max(0, state.active));\n else if (e.key === 'Escape') close();\n else return;\n e.preventDefault();\n show();\n });\n input.addEventListener('blur', close);\n // The map's keys (arrows, +, -) are not the input's\n element.addEventListener('keydown', (e) => e.stopPropagation());\n\n this.stop = () => {\n clearTimeout(state.timer);\n state.query?.abort();\n };\n\n return element;\n }\n\n onRemove(): void {\n this.stop?.();\n this.stop = undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/ui/search.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The search bar: places suggested as the user types (the Géoplateforme's geocoding by default, or yours), the map\n * flying to the one picked. A combobox for screen readers: arrows move in the list, Enter picks, Escape closes.\n */\n\nimport { type GeocodedPlace, geoplateformeGeocode } from '../geoplateforme.ts';\nimport type { GeoMap } from '../map.ts';\nimport type { Control } from './controls.ts';\n\nexport interface SearchOptions {\n /** The places of a text (default: the Géoplateforme's geocoding, France) */\n geocode?: (text: string, signal: AbortSignal) => Promise<GeocodedPlace[]>;\n /** What a pick does (default: a flight there, closer for an address than for a place) */\n onSelect?: (place: GeocodedPlace, map: GeoMap) => void;\n /** Default 'Search a place' */\n placeholder?: string;\n /** Suggestions shown at most (default 8) */\n maxResults?: number;\n}\n\n/** Milliseconds of typing before the text is looked up */\nconst DEBOUNCE_MS = 250;\n\n/** The default pick: a flight to the place, an address seen closer than a town */\nconst flyThere = (place: GeocodedPlace, map: GeoMap) =>\n map.flyTo({ center: place.lonLat, zoom: place.kind === 'address' ? 17 : 14 });\n\n/** A text box and the places it suggests, in a corner of the map */\nexport class SearchControl implements Control {\n private readonly options: SearchOptions;\n private stop: (() => void) | undefined;\n\n constructor(options: SearchOptions = {}) {\n this.options = options;\n }\n\n onAdd(map: GeoMap): HTMLElement {\n const { geocode, onSelect = flyThere, placeholder = 'Search a place', maxResults = 8 } = this.options;\n const lookUp = geocode ?? ((text: string, signal: AbortSignal) => geoplateformeGeocode(text, { signal }));\n const element = document.createElement('div');\n const input = document.createElement('input');\n const list = document.createElement('ul');\n const listId = `isard-search-${Math.random().toString(36).slice(2)}`;\n const state: {\n places: GeocodedPlace[];\n active: number;\n timer?: ReturnType<typeof setTimeout>;\n query?: AbortController;\n } = { places: [], active: -1 };\n\n element.className = 'isard-ctrl-search';\n input.type = 'search';\n input.placeholder = placeholder;\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-label', placeholder);\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-controls', listId);\n input.setAttribute('aria-expanded', 'false');\n list.id = listId;\n list.setAttribute('role', 'listbox');\n list.hidden = true;\n element.append(input, list);\n\n const show = () => {\n list.replaceChildren(\n ...state.places.map((place, i) => {\n const item = document.createElement('li');\n\n item.id = `${listId}-${i}`;\n item.setAttribute('role', 'option');\n item.setAttribute('aria-selected', String(i === state.active));\n item.textContent = place.label;\n // Before the input's blur\n item.addEventListener('pointerdown', (e) => {\n e.preventDefault();\n pick(i);\n });\n\n return item;\n }),\n );\n list.hidden = state.places.length === 0;\n input.setAttribute('aria-expanded', String(!list.hidden));\n if (state.active >= 0) input.setAttribute('aria-activedescendant', `${listId}-${state.active}`);\n else input.removeAttribute('aria-activedescendant');\n };\n const close = () => {\n state.places = [];\n state.active = -1;\n show();\n };\n const pick = (i: number) => {\n const place = state.places[i];\n\n if (!place) return;\n input.value = place.label;\n close();\n onSelect(place, map);\n };\n const search = () => {\n state.query?.abort();\n\n const query = new AbortController();\n\n state.query = query;\n lookUp(input.value, query.signal).then(\n (places) => {\n if (query.signal.aborted) return;\n state.places = places.slice(0, maxResults);\n state.active = -1;\n show();\n },\n (error: unknown) => {\n if (!query.signal.aborted) console.warn('isard: search', error);\n },\n );\n };\n\n input.addEventListener('input', () => {\n clearTimeout(state.timer);\n state.timer = setTimeout(search, DEBOUNCE_MS);\n });\n input.addEventListener('keydown', (e) => {\n const count = state.places.length;\n\n if (e.key === 'ArrowDown' && count > 0) state.active = (state.active + 1) % count;\n else if (e.key === 'ArrowUp' && count > 0) state.active = (state.active - 1 + count) % count;\n else if (e.key === 'Enter') pick(Math.max(0, state.active));\n else if (e.key === 'Escape') close();\n else return;\n e.preventDefault();\n show();\n });\n input.addEventListener('blur', close);\n // The map's keys (arrows, +, -) are not the input's\n element.addEventListener('keydown', (e) => e.stopPropagation());\n\n this.stop = () => {\n clearTimeout(state.timer);\n state.query?.abort();\n };\n\n return element;\n }\n\n onRemove(): void {\n this.stop?.();\n this.stop = undefined;\n }\n}\n"]}
@@ -3,10 +3,11 @@
3
3
  * camera of the engine in use at that frame (it may be replaced during a flight).
4
4
  */
5
5
  import { fromMercator, toMercator } from "./geo.js";
6
+ import { clamp } from "./math.js";
6
7
  /** MapLibre's default easing: cubic Bézier (0.25, 0.1, 0.25, 1) */
7
8
  export const defaultEasing = (t) => {
8
9
  if (t <= 0 || t >= 1)
9
- return Math.max(0, Math.min(1, t));
10
+ return clamp(t, 0, 1);
10
11
  // Solve x(u) = t for the curve parameter, Newton then bisection
11
12
  const [x1, y1, x2, y2] = [0.25, 0.1, 0.25, 1];
12
13
  const bezier = (u, a, b) => 3 * a * u * (1 - u) ** 2 + 3 * b * u * u * (1 - u) + u ** 3;
@@ -16,7 +17,7 @@ export const defaultEasing = (t) => {
16
17
  const dx = 3 * x1 * (1 - u) ** 2 + 6 * (x2 - x1) * u * (1 - u) + 3 * (1 - x2) * u * u;
17
18
  if (Math.abs(x) < 1e-6 || dx === 0)
18
19
  break;
19
- u = Math.max(0, Math.min(1, u - x / dx));
20
+ u = clamp(u - x / dx, 0, 1);
20
21
  }
21
22
  return bezier(u, y1, y2);
22
23
  };
@@ -1 +1 @@
1
- {"version":3,"file":"animation.js","sourceRoot":"","sources":["../../src/util/animation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Camera animations: each is a step run every frame by the map (`GeoMap.animate`) until it returns false, setting the\n * camera of the engine in use at that frame (it may be replaced during a flight).\n */\n\nimport type { AnimationOptions, FlyToOptions } from '../types.ts';\nimport type { Camera, Engine } from '../wasm/isard.js';\nimport { fromMercator, toMercator } from './geo.ts';\n\n/** A step of an animation, at `now` (milliseconds, the frame's time): false once done */\nexport type Step = (now: number) => boolean;\n\n/** What a step needs of the engine, read at each frame */\ntype Target = () => Pick<Engine, 'setCamera' | 'clearPreload'>;\n\n/** MapLibre's default easing: cubic Bézier (0.25, 0.1, 0.25, 1) */\nexport const defaultEasing = (t: number): number => {\n if (t <= 0 || t >= 1) return Math.max(0, Math.min(1, t));\n\n // Solve x(u) = t for the curve parameter, Newton then bisection\n const [x1, y1, x2, y2] = [0.25, 0.1, 0.25, 1];\n const bezier = (u: number, a: number, b: number) => 3 * a * u * (1 - u) ** 2 + 3 * b * u * u * (1 - u) + u ** 3;\n let u = t;\n\n for (let i = 0; i < 8; i += 1) {\n const x = bezier(u, x1, x2) - t;\n const dx = 3 * x1 * (1 - u) ** 2 + 6 * (x2 - x1) * u * (1 - u) + 3 * (1 - x2) * u * u;\n\n if (Math.abs(x) < 1e-6 || dx === 0) break;\n u = Math.max(0, Math.min(1, u - x / dx));\n }\n\n return bezier(u, y1, y2);\n};\n\n/** The step of an animated move from `from` to `to`: over `duration` milliseconds (or the options), ease-out by\n * default, the bearing turning the shortest way round */\nexport const easeTo = (engine: Target, from: Camera, to: Camera, options: number | AnimationOptions = 600): Step => {\n const { duration = 600, easing = (t: number) => 1 - (1 - t) ** 3 } =\n typeof options === 'number' ? { duration: options } : options;\n // Shortest way round\n const turn = ((to.bearing - from.bearing + 540) % 360) - 180;\n const start = performance.now();\n\n return (now) => {\n if (now - start >= duration) engine().clearPreload();\n\n const t = duration > 0 ? Math.min(1, (now - start) / duration) : 1;\n const k = easing(t);\n const mix = (a: number, b: number) => a + (b - a) * k;\n\n engine().setCamera(\n mix(from.center[0], to.center[0]),\n mix(from.center[1], to.center[1]),\n mix(from.zoom, to.zoom),\n mix(from.pitch, to.pitch),\n from.bearing + turn * k,\n );\n\n return t < 1;\n };\n};\n\n/**\n * The step of a flight from `from` to `to` that zooms out on its way and back in (van Wijk and Nuij's optimal path, as\n * MapLibre's `flyTo`): long moves stay readable. Pitch and bearing follow the progress. `viewport`: the larger side of\n * the canvas, CSS pixels.\n */\nexport const flyTo = (engine: Target, from: Camera, to: Camera, viewport: number, options: FlyToOptions = {}): Step => {\n const { curve: rho = 1.42, speed = 1.2, easing = defaultEasing } = options;\n const [x0, y0] = toMercator(from.center);\n const [x1, y1] = toMercator(to.center);\n // Across the antimeridian, the short way\n const dx = x1 - x0 - Math.round(x1 - x0);\n const dy = y1 - y0;\n // In pixels at the start zoom (512 px world at zoom 0)\n const world = 512 * 2 ** from.zoom;\n const u1 = Math.hypot(dx, dy) * world;\n const w0 = Math.max(viewport, 1);\n const w1 = w0 / 2 ** (to.zoom - from.zoom);\n const rho2 = rho * rho;\n const r = (i: 0 | 1) => {\n const b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n\n return Math.log(Math.sqrt(b * b + 1) - b);\n };\n // No move on the ground (or nearly): a plain zoom\n const still = u1 < 1e-6 || !Number.isFinite(r(0)) || !Number.isFinite(r(1));\n const r0 = still ? 0 : r(0);\n const length = still ? Math.abs(Math.log(w1 / w0)) / rho : (r(1) - r0) / rho;\n const width = (s: number) =>\n still ? Math.exp((w1 < w0 ? -1 : 1) * rho * s) : Math.cosh(r0) / Math.cosh(r0 + rho * s);\n const along = (s: number) =>\n still ? 0 : (w0 * ((Math.cosh(r0) * Math.tanh(r0 + rho * s) - Math.sinh(r0)) / rho2)) / u1;\n const duration = options.duration ?? (1000 * length) / speed;\n const turn = ((to.bearing - from.bearing + 540) % 360) - 180;\n const start = performance.now();\n\n return (now) => {\n if (now - start >= duration) engine().clearPreload();\n\n const t = duration > 0 ? Math.min(1, (now - start) / duration) : 1;\n const k = easing(t);\n const s = k * length;\n const u = t >= 1 ? 1 : along(s);\n const zoom = t >= 1 ? to.zoom : from.zoom + Math.log2(1 / width(s));\n const [lon, lat] = fromMercator([x0 + dx * u, y0 + dy * u]);\n\n engine().setCamera(lon, lat, zoom, from.pitch + (to.pitch - from.pitch) * k, from.bearing + turn * k);\n\n return t < 1;\n };\n};\n"]}
1
+ {"version":3,"file":"animation.js","sourceRoot":"","sources":["../../src/util/animation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Camera animations: each is a step run every frame by the map (`GeoMap.animate`) until it returns false, setting the\n * camera of the engine in use at that frame (it may be replaced during a flight).\n */\n\nimport type { AnimationOptions, FlyToOptions } from '../types.ts';\nimport type { Camera, Engine } from '../wasm/isard.js';\nimport { fromMercator, toMercator } from './geo.ts';\nimport { clamp } from './math.ts';\n\n/** A step of an animation, at `now` (milliseconds, the frame's time): false once done */\nexport type Step = (now: number) => boolean;\n\n/** What a step needs of the engine, read at each frame */\ntype Target = () => Pick<Engine, 'setCamera' | 'clearPreload'>;\n\n/** MapLibre's default easing: cubic Bézier (0.25, 0.1, 0.25, 1) */\nexport const defaultEasing = (t: number): number => {\n if (t <= 0 || t >= 1) return clamp(t, 0, 1);\n\n // Solve x(u) = t for the curve parameter, Newton then bisection\n const [x1, y1, x2, y2] = [0.25, 0.1, 0.25, 1];\n const bezier = (u: number, a: number, b: number) => 3 * a * u * (1 - u) ** 2 + 3 * b * u * u * (1 - u) + u ** 3;\n let u = t;\n\n for (let i = 0; i < 8; i += 1) {\n const x = bezier(u, x1, x2) - t;\n const dx = 3 * x1 * (1 - u) ** 2 + 6 * (x2 - x1) * u * (1 - u) + 3 * (1 - x2) * u * u;\n\n if (Math.abs(x) < 1e-6 || dx === 0) break;\n u = clamp(u - x / dx, 0, 1);\n }\n\n return bezier(u, y1, y2);\n};\n\n/** The step of an animated move from `from` to `to`: over `duration` milliseconds (or the options), ease-out by\n * default, the bearing turning the shortest way round */\nexport const easeTo = (engine: Target, from: Camera, to: Camera, options: number | AnimationOptions = 600): Step => {\n const { duration = 600, easing = (t: number) => 1 - (1 - t) ** 3 } =\n typeof options === 'number' ? { duration: options } : options;\n // Shortest way round\n const turn = ((to.bearing - from.bearing + 540) % 360) - 180;\n const start = performance.now();\n\n return (now) => {\n if (now - start >= duration) engine().clearPreload();\n\n const t = duration > 0 ? Math.min(1, (now - start) / duration) : 1;\n const k = easing(t);\n const mix = (a: number, b: number) => a + (b - a) * k;\n\n engine().setCamera(\n mix(from.center[0], to.center[0]),\n mix(from.center[1], to.center[1]),\n mix(from.zoom, to.zoom),\n mix(from.pitch, to.pitch),\n from.bearing + turn * k,\n );\n\n return t < 1;\n };\n};\n\n/**\n * The step of a flight from `from` to `to` that zooms out on its way and back in (van Wijk and Nuij's optimal path, as\n * MapLibre's `flyTo`): long moves stay readable. Pitch and bearing follow the progress. `viewport`: the larger side of\n * the canvas, CSS pixels.\n */\nexport const flyTo = (engine: Target, from: Camera, to: Camera, viewport: number, options: FlyToOptions = {}): Step => {\n const { curve: rho = 1.42, speed = 1.2, easing = defaultEasing } = options;\n const [x0, y0] = toMercator(from.center);\n const [x1, y1] = toMercator(to.center);\n // Across the antimeridian, the short way\n const dx = x1 - x0 - Math.round(x1 - x0);\n const dy = y1 - y0;\n // In pixels at the start zoom (512 px world at zoom 0)\n const world = 512 * 2 ** from.zoom;\n const u1 = Math.hypot(dx, dy) * world;\n const w0 = Math.max(viewport, 1);\n const w1 = w0 / 2 ** (to.zoom - from.zoom);\n const rho2 = rho * rho;\n const r = (i: 0 | 1) => {\n const b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n\n return Math.log(Math.sqrt(b * b + 1) - b);\n };\n // No move on the ground (or nearly): a plain zoom\n const still = u1 < 1e-6 || !Number.isFinite(r(0)) || !Number.isFinite(r(1));\n const r0 = still ? 0 : r(0);\n const length = still ? Math.abs(Math.log(w1 / w0)) / rho : (r(1) - r0) / rho;\n const width = (s: number) =>\n still ? Math.exp((w1 < w0 ? -1 : 1) * rho * s) : Math.cosh(r0) / Math.cosh(r0 + rho * s);\n const along = (s: number) =>\n still ? 0 : (w0 * ((Math.cosh(r0) * Math.tanh(r0 + rho * s) - Math.sinh(r0)) / rho2)) / u1;\n const duration = options.duration ?? (1000 * length) / speed;\n const turn = ((to.bearing - from.bearing + 540) % 360) - 180;\n const start = performance.now();\n\n return (now) => {\n if (now - start >= duration) engine().clearPreload();\n\n const t = duration > 0 ? Math.min(1, (now - start) / duration) : 1;\n const k = easing(t);\n const s = k * length;\n const u = t >= 1 ? 1 : along(s);\n const zoom = t >= 1 ? to.zoom : from.zoom + Math.log2(1 / width(s));\n const [lon, lat] = fromMercator([x0 + dx * u, y0 + dy * u]);\n\n engine().setCamera(lon, lat, zoom, from.pitch + (to.pitch - from.pitch) * k, from.bearing + turn * k);\n\n return t < 1;\n };\n};\n"]}
@@ -6,3 +6,13 @@
6
6
  export type Rgba = [r: number, g: number, b: number, a: number];
7
7
  /** A CSS color to RGBA 0-1; undefined if it is not one */
8
8
  export declare const parseCssColor: (value: unknown) => Rgba | undefined;
9
+ /** Colors of values: `[[value, color], …]` in increasing values, linear in between */
10
+ export type Ramp = [value: number, color: string][];
11
+ /** A CSS color to RGBA 0-1 (see `parseCssColor`); black if unknown or missing */
12
+ export declare const parseColor: (color: string) => [r: number, g: number, b: number, a: number];
13
+ /** 256 RGBA texels of a ramp over its value range, and that range */
14
+ export declare const rampTexels: (ramp: Ramp) => {
15
+ rgba: Uint8Array;
16
+ min: number;
17
+ max: number;
18
+ };
@@ -1,8 +1,4 @@
1
- /**
2
- * CSS colors to RGBA 0-1: `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` and `rgba()`, `hsl()` and `hsla()` (comma
3
- * or space syntax, `/` before the alpha, percentages), the CSS named colors and `transparent`. No DOM: the workers use
4
- * it too.
5
- */
1
+ import { clamp } from "./math.js";
6
2
  /** The CSS named colors, as name and `rrggbb` pairs */
7
3
  const NAMES = 'aliceblue f0f8ff antiquewhite faebd7 aqua 00ffff aquamarine 7fffd4 azure f0ffff beige f5f5dc bisque ffe4c4 ' +
8
4
  'black 000000 blanchedalmond ffebcd blue 0000ff blueviolet 8a2be2 brown a52a2a burlywood deb887 cadetblue 5f9ea0 ' +
@@ -37,7 +33,8 @@ const namedHex = (name) => {
37
33
  }
38
34
  return named.get(name);
39
35
  };
40
- const clamp = (v) => (Number.isFinite(v) ? Math.max(0, Math.min(1, v)) : 0);
36
+ /** A channel in [0, 1], 0 if not a number */
37
+ const unit = (v) => (Number.isFinite(v) ? clamp(v, 0, 1) : 0);
41
38
  const hex = (digits) => {
42
39
  if (!/^[0-9a-f]+$/.test(digits) || ![3, 4, 6, 8].includes(digits.length))
43
40
  return undefined;
@@ -49,7 +46,7 @@ const hex = (digits) => {
49
46
  const alpha = (p) => {
50
47
  if (p === undefined)
51
48
  return 1;
52
- return clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p));
49
+ return unit(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p));
53
50
  };
54
51
  const hsl = (h, s, l) => {
55
52
  const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
@@ -86,11 +83,34 @@ export const parseCssColor = (value) => {
86
83
  return undefined;
87
84
  const a = alpha(parts[3]);
88
85
  if (match[1].startsWith('rgb')) {
89
- const channel = (p) => clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / 255);
86
+ const channel = (p) => unit(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / 255);
90
87
  return [channel(parts[0] ?? ''), channel(parts[1] ?? ''), channel(parts[2] ?? ''), a];
91
88
  }
92
89
  const h = Number.parseFloat(parts[0] ?? '') / 360;
93
- const [r, g, b] = hsl(h, clamp(Number.parseFloat(parts[1] ?? '') / 100), clamp(Number.parseFloat(parts[2] ?? '') / 100));
90
+ const [r, g, b] = hsl(h, unit(Number.parseFloat(parts[1] ?? '') / 100), unit(Number.parseFloat(parts[2] ?? '') / 100));
94
91
  return [r, g, b, a];
95
92
  };
93
+ /** A CSS color to RGBA 0-1 (see `parseCssColor`); black if unknown or missing */
94
+ export const parseColor = (color) => {
95
+ return parseCssColor(color) ?? [0, 0, 0, 1];
96
+ };
97
+ /** 256 RGBA texels of a ramp over its value range, and that range */
98
+ export const rampTexels = (ramp) => {
99
+ const stops = ramp.map(([v, c]) => [v, parseColor(c)]).sort((a, b) => a[0] - b[0]);
100
+ const min = stops[0]?.[0] ?? 0;
101
+ const max = stops.at(-1)?.[0] ?? 1;
102
+ const rgba = new Uint8Array(256 * 4);
103
+ for (let i = 0; i < 256; i += 1) {
104
+ const v = min + ((max - min) * i) / 255;
105
+ let k = 0;
106
+ while (k + 1 < stops.length && (stops[k + 1]?.[0] ?? 0) < v)
107
+ k += 1;
108
+ const [v0, c0] = stops[k] ?? [min, [0, 0, 0, 1]];
109
+ const [v1, c1] = stops[k + 1] ?? [v0, c0];
110
+ const t = v1 > v0 ? clamp((v - v0) / (v1 - v0), 0, 1) : 0;
111
+ for (let j = 0; j < 4; j += 1)
112
+ rgba[i * 4 + j] = Math.round(((c0[j] ?? 0) + ((c1[j] ?? 0) - (c0[j] ?? 0)) * t) * 255);
113
+ }
114
+ return { rgba, min, max };
115
+ };
96
116
  //# sourceMappingURL=color.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"color.js","sourceRoot":"","sources":["../../src/util/color.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CSS colors to RGBA 0-1: `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` and `rgba()`, `hsl()` and `hsla()` (comma\n * or space syntax, `/` before the alpha, percentages), the CSS named colors and `transparent`. No DOM: the workers use\n * it too.\n */\n\nexport type Rgba = [r: number, g: number, b: number, a: number];\n\n/** The CSS named colors, as name and `rrggbb` pairs */\nconst NAMES =\n 'aliceblue f0f8ff antiquewhite faebd7 aqua 00ffff aquamarine 7fffd4 azure f0ffff beige f5f5dc bisque ffe4c4 ' +\n 'black 000000 blanchedalmond ffebcd blue 0000ff blueviolet 8a2be2 brown a52a2a burlywood deb887 cadetblue 5f9ea0 ' +\n 'chartreuse 7fff00 chocolate d2691e coral ff7f50 cornflowerblue 6495ed cornsilk fff8dc crimson dc143c ' +\n 'cyan 00ffff darkblue 00008b darkcyan 008b8b darkgoldenrod b8860b darkgray a9a9a9 darkgreen 006400 ' +\n 'darkgrey a9a9a9 darkkhaki bdb76b darkmagenta 8b008b darkolivegreen 556b2f darkorange ff8c00 darkorchid 9932cc ' +\n 'darkred 8b0000 darksalmon e9967a darkseagreen 8fbc8f darkslateblue 483d8b darkslategray 2f4f4f ' +\n 'darkslategrey 2f4f4f darkturquoise 00ced1 darkviolet 9400d3 deeppink ff1493 deepskyblue 00bfff dimgray 696969 ' +\n 'dimgrey 696969 dodgerblue 1e90ff firebrick b22222 floralwhite fffaf0 forestgreen 228b22 fuchsia ff00ff ' +\n 'gainsboro dcdcdc ghostwhite f8f8ff gold ffd700 goldenrod daa520 gray 808080 green 008000 greenyellow adff2f ' +\n 'grey 808080 honeydew f0fff0 hotpink ff69b4 indianred cd5c5c indigo 4b0082 ivory fffff0 khaki f0e68c ' +\n 'lavender e6e6fa lavenderblush fff0f5 lawngreen 7cfc00 lemonchiffon fffacd lightblue add8e6 lightcoral f08080 ' +\n 'lightcyan e0ffff lightgoldenrodyellow fafad2 lightgray d3d3d3 lightgreen 90ee90 lightgrey d3d3d3 ' +\n 'lightpink ffb6c1 lightsalmon ffa07a lightseagreen 20b2aa lightskyblue 87cefa lightslategray 778899 ' +\n 'lightslategrey 778899 lightsteelblue b0c4de lightyellow ffffe0 lime 00ff00 limegreen 32cd32 linen faf0e6 ' +\n 'magenta ff00ff maroon 800000 mediumaquamarine 66cdaa mediumblue 0000cd mediumorchid ba55d3 ' +\n 'mediumpurple 9370db mediumseagreen 3cb371 mediumslateblue 7b68ee mediumspringgreen 00fa9a ' +\n 'mediumturquoise 48d1cc mediumvioletred c71585 midnightblue 191970 mintcream f5fffa mistyrose ffe4e1 ' +\n 'moccasin ffe4b5 navajowhite ffdead navy 000080 oldlace fdf5e6 olive 808000 olivedrab 6b8e23 orange ffa500 ' +\n 'orangered ff4500 orchid da70d6 palegoldenrod eee8aa palegreen 98fb98 paleturquoise afeeee ' +\n 'palevioletred db7093 papayawhip ffefd5 peachpuff ffdab9 peru cd853f pink ffc0cb plum dda0dd ' +\n 'powderblue b0e0e6 purple 800080 rebeccapurple 663399 red ff0000 rosybrown bc8f8f royalblue 4169e1 ' +\n 'saddlebrown 8b4513 salmon fa8072 sandybrown f4a460 seagreen 2e8b57 seashell fff5ee sienna a0522d ' +\n 'silver c0c0c0 skyblue 87ceeb slateblue 6a5acd slategray 708090 slategrey 708090 snow fffafa ' +\n 'springgreen 00ff7f steelblue 4682b4 tan d2b48c teal 008080 thistle d8bfd8 tomato ff6347 turquoise 40e0d0 ' +\n 'violet ee82ee wheat f5deb3 white ffffff whitesmoke f5f5f5 yellow ffff00 yellowgreen 9acd32';\n\nlet named: Map<string, string> | undefined;\n\nconst namedHex = (name: string): string | undefined => {\n if (!named) {\n const words = NAMES.split(' ');\n\n named = new Map(\n Array.from({ length: Math.floor(words.length / 2) }, (_, i) => [words[2 * i] ?? '', words[2 * i + 1] ?? '']),\n );\n }\n\n return named.get(name);\n};\n\nconst clamp = (v: number) => (Number.isFinite(v) ? Math.max(0, Math.min(1, v)) : 0);\n\nconst hex = (digits: string): Rgba | undefined => {\n if (!/^[0-9a-f]+$/.test(digits) || ![3, 4, 6, 8].includes(digits.length)) return undefined;\n\n const full = digits.length <= 4 ? [...digits].map((h) => h + h).join('') : digits;\n const v = (i: number) => Number.parseInt(full.slice(i, i + 2), 16) / 255;\n\n return [v(0), v(2), v(4), full.length === 8 ? v(6) : 1];\n};\n\n/** An alpha: a number from 0 to 1 or a percentage */\nconst alpha = (p: string | undefined): number => {\n if (p === undefined) return 1;\n\n return clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p));\n};\n\nconst hsl = (h: number, s: number, l: number): [number, number, number] => {\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n const hue = (t: number) => {\n const u = ((t % 1) + 1) % 1;\n\n if (u < 1 / 6) return p + (q - p) * 6 * u;\n if (u < 1 / 2) return q;\n if (u < 2 / 3) return p + (q - p) * (2 / 3 - u) * 6;\n\n return p;\n };\n\n return [hue(h + 1 / 3), hue(h), hue(h - 1 / 3)];\n};\n\n/** A CSS color to RGBA 0-1; undefined if it is not one */\nexport const parseCssColor = (value: unknown): Rgba | undefined => {\n if (typeof value !== 'string') return undefined;\n\n const c = value.trim().toLowerCase();\n\n if (c.startsWith('#')) return hex(c.slice(1));\n if (c === 'transparent') return [0, 0, 0, 0];\n\n const name = namedHex(c);\n\n if (name) return hex(name);\n\n const match = /^(rgba?|hsla?)\\(([^)]*)\\)$/.exec(c);\n\n if (!match?.[1] || match[2] === undefined) return undefined;\n\n const parts = match[2].split(/[\\s,/]+/).filter(Boolean);\n\n if (parts.length < 3 || parts.slice(0, 3).some((p) => Number.isNaN(Number.parseFloat(p)))) return undefined;\n\n const a = alpha(parts[3]);\n\n if (match[1].startsWith('rgb')) {\n const channel = (p: string) => clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / 255);\n\n return [channel(parts[0] ?? ''), channel(parts[1] ?? ''), channel(parts[2] ?? ''), a];\n }\n\n const h = Number.parseFloat(parts[0] ?? '') / 360;\n const [r, g, b] = hsl(\n h,\n clamp(Number.parseFloat(parts[1] ?? '') / 100),\n clamp(Number.parseFloat(parts[2] ?? '') / 100),\n );\n\n return [r, g, b, a];\n};\n"]}
1
+ {"version":3,"file":"color.js","sourceRoot":"","sources":["../../src/util/color.ts"],"names":[],"mappings":"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","sourcesContent":["import { clamp } from './math.ts';\n/**\n * CSS colors to RGBA 0-1: `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` and `rgba()`, `hsl()` and `hsla()` (comma\n * or space syntax, `/` before the alpha, percentages), the CSS named colors and `transparent`. No DOM: the workers use\n * it too.\n */\n\nexport type Rgba = [r: number, g: number, b: number, a: number];\n\n/** The CSS named colors, as name and `rrggbb` pairs */\nconst NAMES =\n 'aliceblue f0f8ff antiquewhite faebd7 aqua 00ffff aquamarine 7fffd4 azure f0ffff beige f5f5dc bisque ffe4c4 ' +\n 'black 000000 blanchedalmond ffebcd blue 0000ff blueviolet 8a2be2 brown a52a2a burlywood deb887 cadetblue 5f9ea0 ' +\n 'chartreuse 7fff00 chocolate d2691e coral ff7f50 cornflowerblue 6495ed cornsilk fff8dc crimson dc143c ' +\n 'cyan 00ffff darkblue 00008b darkcyan 008b8b darkgoldenrod b8860b darkgray a9a9a9 darkgreen 006400 ' +\n 'darkgrey a9a9a9 darkkhaki bdb76b darkmagenta 8b008b darkolivegreen 556b2f darkorange ff8c00 darkorchid 9932cc ' +\n 'darkred 8b0000 darksalmon e9967a darkseagreen 8fbc8f darkslateblue 483d8b darkslategray 2f4f4f ' +\n 'darkslategrey 2f4f4f darkturquoise 00ced1 darkviolet 9400d3 deeppink ff1493 deepskyblue 00bfff dimgray 696969 ' +\n 'dimgrey 696969 dodgerblue 1e90ff firebrick b22222 floralwhite fffaf0 forestgreen 228b22 fuchsia ff00ff ' +\n 'gainsboro dcdcdc ghostwhite f8f8ff gold ffd700 goldenrod daa520 gray 808080 green 008000 greenyellow adff2f ' +\n 'grey 808080 honeydew f0fff0 hotpink ff69b4 indianred cd5c5c indigo 4b0082 ivory fffff0 khaki f0e68c ' +\n 'lavender e6e6fa lavenderblush fff0f5 lawngreen 7cfc00 lemonchiffon fffacd lightblue add8e6 lightcoral f08080 ' +\n 'lightcyan e0ffff lightgoldenrodyellow fafad2 lightgray d3d3d3 lightgreen 90ee90 lightgrey d3d3d3 ' +\n 'lightpink ffb6c1 lightsalmon ffa07a lightseagreen 20b2aa lightskyblue 87cefa lightslategray 778899 ' +\n 'lightslategrey 778899 lightsteelblue b0c4de lightyellow ffffe0 lime 00ff00 limegreen 32cd32 linen faf0e6 ' +\n 'magenta ff00ff maroon 800000 mediumaquamarine 66cdaa mediumblue 0000cd mediumorchid ba55d3 ' +\n 'mediumpurple 9370db mediumseagreen 3cb371 mediumslateblue 7b68ee mediumspringgreen 00fa9a ' +\n 'mediumturquoise 48d1cc mediumvioletred c71585 midnightblue 191970 mintcream f5fffa mistyrose ffe4e1 ' +\n 'moccasin ffe4b5 navajowhite ffdead navy 000080 oldlace fdf5e6 olive 808000 olivedrab 6b8e23 orange ffa500 ' +\n 'orangered ff4500 orchid da70d6 palegoldenrod eee8aa palegreen 98fb98 paleturquoise afeeee ' +\n 'palevioletred db7093 papayawhip ffefd5 peachpuff ffdab9 peru cd853f pink ffc0cb plum dda0dd ' +\n 'powderblue b0e0e6 purple 800080 rebeccapurple 663399 red ff0000 rosybrown bc8f8f royalblue 4169e1 ' +\n 'saddlebrown 8b4513 salmon fa8072 sandybrown f4a460 seagreen 2e8b57 seashell fff5ee sienna a0522d ' +\n 'silver c0c0c0 skyblue 87ceeb slateblue 6a5acd slategray 708090 slategrey 708090 snow fffafa ' +\n 'springgreen 00ff7f steelblue 4682b4 tan d2b48c teal 008080 thistle d8bfd8 tomato ff6347 turquoise 40e0d0 ' +\n 'violet ee82ee wheat f5deb3 white ffffff whitesmoke f5f5f5 yellow ffff00 yellowgreen 9acd32';\n\nlet named: Map<string, string> | undefined;\n\nconst namedHex = (name: string): string | undefined => {\n if (!named) {\n const words = NAMES.split(' ');\n\n named = new Map(\n Array.from({ length: Math.floor(words.length / 2) }, (_, i) => [words[2 * i] ?? '', words[2 * i + 1] ?? '']),\n );\n }\n\n return named.get(name);\n};\n\n/** A channel in [0, 1], 0 if not a number */\nconst unit = (v: number) => (Number.isFinite(v) ? clamp(v, 0, 1) : 0);\n\nconst hex = (digits: string): Rgba | undefined => {\n if (!/^[0-9a-f]+$/.test(digits) || ![3, 4, 6, 8].includes(digits.length)) return undefined;\n\n const full = digits.length <= 4 ? [...digits].map((h) => h + h).join('') : digits;\n const v = (i: number) => Number.parseInt(full.slice(i, i + 2), 16) / 255;\n\n return [v(0), v(2), v(4), full.length === 8 ? v(6) : 1];\n};\n\n/** An alpha: a number from 0 to 1 or a percentage */\nconst alpha = (p: string | undefined): number => {\n if (p === undefined) return 1;\n\n return unit(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p));\n};\n\nconst hsl = (h: number, s: number, l: number): [number, number, number] => {\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n const hue = (t: number) => {\n const u = ((t % 1) + 1) % 1;\n\n if (u < 1 / 6) return p + (q - p) * 6 * u;\n if (u < 1 / 2) return q;\n if (u < 2 / 3) return p + (q - p) * (2 / 3 - u) * 6;\n\n return p;\n };\n\n return [hue(h + 1 / 3), hue(h), hue(h - 1 / 3)];\n};\n\n/** A CSS color to RGBA 0-1; undefined if it is not one */\nexport const parseCssColor = (value: unknown): Rgba | undefined => {\n if (typeof value !== 'string') return undefined;\n\n const c = value.trim().toLowerCase();\n\n if (c.startsWith('#')) return hex(c.slice(1));\n if (c === 'transparent') return [0, 0, 0, 0];\n\n const name = namedHex(c);\n\n if (name) return hex(name);\n\n const match = /^(rgba?|hsla?)\\(([^)]*)\\)$/.exec(c);\n\n if (!match?.[1] || match[2] === undefined) return undefined;\n\n const parts = match[2].split(/[\\s,/]+/).filter(Boolean);\n\n if (parts.length < 3 || parts.slice(0, 3).some((p) => Number.isNaN(Number.parseFloat(p)))) return undefined;\n\n const a = alpha(parts[3]);\n\n if (match[1].startsWith('rgb')) {\n const channel = (p: string) => unit(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / 255);\n\n return [channel(parts[0] ?? ''), channel(parts[1] ?? ''), channel(parts[2] ?? ''), a];\n }\n\n const h = Number.parseFloat(parts[0] ?? '') / 360;\n const [r, g, b] = hsl(\n h,\n unit(Number.parseFloat(parts[1] ?? '') / 100),\n unit(Number.parseFloat(parts[2] ?? '') / 100),\n );\n\n return [r, g, b, a];\n};\n\n/** Colors of values: `[[value, color], …]` in increasing values, linear in between */\nexport type Ramp = [value: number, color: string][];\n\n/** A CSS color to RGBA 0-1 (see `parseCssColor`); black if unknown or missing */\nexport const parseColor = (color: string): [r: number, g: number, b: number, a: number] => {\n return parseCssColor(color) ?? [0, 0, 0, 1];\n};\n\n/** 256 RGBA texels of a ramp over its value range, and that range */\nexport const rampTexels = (ramp: Ramp): { rgba: Uint8Array; min: number; max: number } => {\n const stops = ramp.map(([v, c]) => [v, parseColor(c)] as const).sort((a, b) => a[0] - b[0]);\n const min = stops[0]?.[0] ?? 0;\n const max = stops.at(-1)?.[0] ?? 1;\n const rgba = new Uint8Array(256 * 4);\n\n for (let i = 0; i < 256; i += 1) {\n const v = min + ((max - min) * i) / 255;\n let k = 0;\n\n while (k + 1 < stops.length && (stops[k + 1]?.[0] ?? 0) < v) k += 1;\n\n const [v0, c0] = stops[k] ?? [min, [0, 0, 0, 1]];\n const [v1, c1] = stops[k + 1] ?? [v0, c0];\n const t = v1 > v0 ? clamp((v - v0) / (v1 - v0), 0, 1) : 0;\n\n for (let j = 0; j < 4; j += 1)\n rgba[i * 4 + j] = Math.round(((c0[j] ?? 0) + ((c1[j] ?? 0) - (c0[j] ?? 0)) * t) * 255);\n }\n\n return { rgba, min, max };\n};\n"]}
@@ -0,0 +1,5 @@
1
+ /** Requests that fail as one: an error saying which URL answered which status */
2
+ /** A request's failure: `isard: <url>: HTTP <status>` */
3
+ export declare const httpError: (url: string | URL, status: number) => Error;
4
+ /** A response that is ok, else an `httpError` */
5
+ export declare const fetchOk: (url: string | URL, init?: RequestInit) => Promise<Response>;
@@ -0,0 +1,11 @@
1
+ /** Requests that fail as one: an error saying which URL answered which status */
2
+ /** A request's failure: `isard: <url>: HTTP <status>` */
3
+ export const httpError = (url, status) => new Error(`isard: ${String(url)}: HTTP ${status}`);
4
+ /** A response that is ok, else an `httpError` */
5
+ export const fetchOk = async (url, init) => {
6
+ const response = await fetch(url, init);
7
+ if (!response.ok)
8
+ throw httpError(url, response.status);
9
+ return response;
10
+ };
11
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/util/fetch.ts"],"names":[],"mappings":"AAAA,iFAAiF;AAEjF,yDAAyD;AACzD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAiB,EAAE,MAAc,EAAS,EAAE,CACpE,IAAI,KAAK,CAAC,UAAU,MAAM,CAAC,GAAG,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC;AAErD,iDAAiD;AACjD,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAAE,GAAiB,EAAE,IAAkB,EAAqB,EAAE;IACxF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAExC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,MAAM,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAExD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC","sourcesContent":["/** Requests that fail as one: an error saying which URL answered which status */\n\n/** A request's failure: `isard: <url>: HTTP <status>` */\nexport const httpError = (url: string | URL, status: number): Error =>\n new Error(`isard: ${String(url)}: HTTP ${status}`);\n\n/** A response that is ok, else an `httpError` */\nexport const fetchOk = async (url: string | URL, init?: RequestInit): Promise<Response> => {\n const response = await fetch(url, init);\n\n if (!response.ok) throw httpError(url, response.status);\n\n return response;\n};\n"]}
@@ -20,5 +20,10 @@ export declare const latitude: (y: number) => number;
20
20
  export declare const toMercator: ([lon, lat]: readonly [number, number, ...unknown[]]) => [x: number, y: number];
21
21
  /** Longitude and latitude of a Mercator x, y */
22
22
  export declare const fromMercator: ([x, y]: readonly [number, number]) => [lon: number, lat: number];
23
+ /** Metres per Mercator unit at a Mercator y (towards the south, [0, 1]): the circumference at its latitude (a roof's
24
+ * slopes, a tile's cells run in metres) */
25
+ export declare const metresAt: (y: number) => number;
23
26
  /** Metres across a tile of level `z` and row `y` at its middle */
24
27
  export declare const tileMetres: (z: number, y: number) => number;
28
+ /** A tile's URL from its source's template: every {z}, {x} and {y} replaced (`z` a level, or a WMTS matrix's id) */
29
+ export declare const tileUrl: (template: string, z: number | string, x: number, y: number) => string;
package/dist/util/geo.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { clamp } from "./math.js";
1
2
  /**
2
3
  * Web Mercator in [0, 1] across the world (y towards the south), for the page and the workers alike: the positions
3
4
  * sent to the engine, the tiles of a view, the flights, the label candidates of the vector tiles.
@@ -16,7 +17,7 @@ export const mercatorX = (lon) => {
16
17
  };
17
18
  /** Mercator y of a latitude (degrees), clamped to the edges of the map */
18
19
  export const mercatorY = (lat) => {
19
- const phi = (Math.max(-MAX_LAT, Math.min(MAX_LAT, lat)) * Math.PI) / 180;
20
+ const phi = clamp(lat, -MAX_LAT, MAX_LAT) * RAD;
20
21
  return 0.5 - Math.log(Math.tan(Math.PI / 4 + phi / 2)) / (2 * Math.PI);
21
22
  };
22
23
  /** Longitude (degrees) of a Mercator x */
@@ -35,6 +36,11 @@ export const toMercator = ([lon, lat]) => {
35
36
  export const fromMercator = ([x, y]) => {
36
37
  return [longitude(x), latitude(y)];
37
38
  };
39
+ /** Metres per Mercator unit at a Mercator y (towards the south, [0, 1]): the circumference at its latitude (a roof's
40
+ * slopes, a tile's cells run in metres) */
41
+ export const metresAt = (y) => EARTH_METRES * Math.cos(Math.atan(Math.sinh(Math.PI * (1 - 2 * y))));
38
42
  /** Metres across a tile of level `z` and row `y` at its middle */
39
- export const tileMetres = (z, y) => (EARTH_METRES * Math.cos((latitude((y + 0.5) / 2 ** z) * Math.PI) / 180)) / 2 ** z;
43
+ export const tileMetres = (z, y) => metresAt((y + 0.5) / 2 ** z) / 2 ** z;
44
+ /** A tile's URL from its source's template: every {z}, {x} and {y} replaced (`z` a level, or a WMTS matrix's id) */
45
+ export const tileUrl = (template, z, x, y) => template.replaceAll('{z}', String(z)).replaceAll('{x}', String(x)).replaceAll('{y}', String(y));
40
46
  //# sourceMappingURL=geo.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"geo.js","sourceRoot":"","sources":["../../src/util/geo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,0BAA0B;AAC1B,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC;AAEjC,oGAAoG;AACpG,MAAM,CAAC,MAAM,YAAY,GAAG,cAAc,CAAC;AAE3C,uFAAuF;AACvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,GAAG,GAAG,CAAC;AAEpD,sEAAsE;AACtE,MAAM,OAAO,GAAG,kBAAkB,CAAC;AAEnC,0CAA0C;AAC1C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAU,EAAE;IAC/C,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AAC3B,CAAC,CAAC;AAEF,0EAA0E;AAC1E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAU,EAAE;IAC/C,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;IAEzE,OAAO,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC,CAAC;AAEF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAS,EAAU,EAAE;IAC7C,OAAO,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AACvB,CAAC,CAAC;AAEF,yCAAyC;AACzC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAU,EAAE;IAC5C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;AACvE,CAAC,CAAC;AAEF,gDAAgD;AAChD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAA0C,EAA0B,EAAE;IACxG,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1C,CAAC,CAAC;AAEF,gDAAgD;AAChD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAA4B,EAA8B,EAAE;IAC5F,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF,kEAAkE;AAClE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CACzD,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC","sourcesContent":["/**\n * Web Mercator in [0, 1] across the world (y towards the south), for the page and the workers alike: the positions\n * sent to the engine, the tiles of a view, the flights, the label candidates of the vector tiles.\n */\n\n/** Radians in a degree */\nexport const RAD = Math.PI / 180;\n\n/** The Earth's circumference at the equator, metres (Web Mercator's sphere: WGS 84's major axis) */\nexport const EARTH_METRES = 40_075_016.686;\n\n/** Metres in a degree of latitude (and of longitude at the equator), on that sphere */\nexport const METRES_PER_DEGREE = EARTH_METRES / 360;\n\n/** The latitude where Web Mercator is square: the edges of the map */\nconst MAX_LAT = 85.051128779806589;\n\n/** Mercator x of a longitude (degrees) */\nexport const mercatorX = (lon: number): number => {\n return (lon + 180) / 360;\n};\n\n/** Mercator y of a latitude (degrees), clamped to the edges of the map */\nexport const mercatorY = (lat: number): number => {\n const phi = (Math.max(-MAX_LAT, Math.min(MAX_LAT, lat)) * Math.PI) / 180;\n\n return 0.5 - Math.log(Math.tan(Math.PI / 4 + phi / 2)) / (2 * Math.PI);\n};\n\n/** Longitude (degrees) of a Mercator x */\nexport const longitude = (x: number): number => {\n return x * 360 - 180;\n};\n\n/** Latitude (degrees) of a Mercator y */\nexport const latitude = (y: number): number => {\n return (Math.atan(Math.sinh(Math.PI * (1 - 2 * y))) * 180) / Math.PI;\n};\n\n/** Mercator x, y of a longitude and latitude */\nexport const toMercator = ([lon, lat]: readonly [number, number, ...unknown[]]): [x: number, y: number] => {\n return [mercatorX(lon), mercatorY(lat)];\n};\n\n/** Longitude and latitude of a Mercator x, y */\nexport const fromMercator = ([x, y]: readonly [number, number]): [lon: number, lat: number] => {\n return [longitude(x), latitude(y)];\n};\n\n/** Metres across a tile of level `z` and row `y` at its middle */\nexport const tileMetres = (z: number, y: number): number =>\n (EARTH_METRES * Math.cos((latitude((y + 0.5) / 2 ** z) * Math.PI) / 180)) / 2 ** z;\n"]}
1
+ {"version":3,"file":"geo.js","sourceRoot":"","sources":["../../src/util/geo.ts"],"names":[],"mappings":"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","sourcesContent":["import { clamp } from './math.ts';\n/**\n * Web Mercator in [0, 1] across the world (y towards the south), for the page and the workers alike: the positions\n * sent to the engine, the tiles of a view, the flights, the label candidates of the vector tiles.\n */\n\n/** Radians in a degree */\nexport const RAD = Math.PI / 180;\n\n/** The Earth's circumference at the equator, metres (Web Mercator's sphere: WGS 84's major axis) */\nexport const EARTH_METRES = 40_075_016.686;\n\n/** Metres in a degree of latitude (and of longitude at the equator), on that sphere */\nexport const METRES_PER_DEGREE = EARTH_METRES / 360;\n\n/** The latitude where Web Mercator is square: the edges of the map */\nconst MAX_LAT = 85.051128779806589;\n\n/** Mercator x of a longitude (degrees) */\nexport const mercatorX = (lon: number): number => {\n return (lon + 180) / 360;\n};\n\n/** Mercator y of a latitude (degrees), clamped to the edges of the map */\nexport const mercatorY = (lat: number): number => {\n const phi = clamp(lat, -MAX_LAT, MAX_LAT) * RAD;\n\n return 0.5 - Math.log(Math.tan(Math.PI / 4 + phi / 2)) / (2 * Math.PI);\n};\n\n/** Longitude (degrees) of a Mercator x */\nexport const longitude = (x: number): number => {\n return x * 360 - 180;\n};\n\n/** Latitude (degrees) of a Mercator y */\nexport const latitude = (y: number): number => {\n return (Math.atan(Math.sinh(Math.PI * (1 - 2 * y))) * 180) / Math.PI;\n};\n\n/** Mercator x, y of a longitude and latitude */\nexport const toMercator = ([lon, lat]: readonly [number, number, ...unknown[]]): [x: number, y: number] => {\n return [mercatorX(lon), mercatorY(lat)];\n};\n\n/** Longitude and latitude of a Mercator x, y */\nexport const fromMercator = ([x, y]: readonly [number, number]): [lon: number, lat: number] => {\n return [longitude(x), latitude(y)];\n};\n\n/** Metres per Mercator unit at a Mercator y (towards the south, [0, 1]): the circumference at its latitude (a roof's\n * slopes, a tile's cells run in metres) */\nexport const metresAt = (y: number): number => EARTH_METRES * Math.cos(Math.atan(Math.sinh(Math.PI * (1 - 2 * y))));\n\n/** Metres across a tile of level `z` and row `y` at its middle */\nexport const tileMetres = (z: number, y: number): number => metresAt((y + 0.5) / 2 ** z) / 2 ** z;\n\n/** A tile's URL from its source's template: every {z}, {x} and {y} replaced (`z` a level, or a WMTS matrix's id) */\nexport const tileUrl = (template: string, z: number | string, x: number, y: number): string =>\n template.replaceAll('{z}', String(z)).replaceAll('{x}', String(x)).replaceAll('{y}', String(y));\n"]}
@@ -0,0 +1,3 @@
1
+ /** Small numeric helpers shared by the page and the workers */
2
+ /** `value` kept within `min` and `max` */
3
+ export declare const clamp: (value: number, min: number, max: number) => number;
@@ -0,0 +1,4 @@
1
+ /** Small numeric helpers shared by the page and the workers */
2
+ /** `value` kept within `min` and `max` */
3
+ export const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
4
+ //# sourceMappingURL=math.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.js","sourceRoot":"","sources":["../../src/util/math.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAE/D,0CAA0C;AAC1C,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW,EAAU,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC","sourcesContent":["/** Small numeric helpers shared by the page and the workers */\n\n/** `value` kept within `min` and `max` */\nexport const clamp = (value: number, min: number, max: number): number => Math.max(min, Math.min(max, value));\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests.js","sourceRoot":"","sources":["../../src/util/requests.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,IAAI,KAAK,GAAgB,EAAE,CAAC;AAC5B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAgC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAE,OAAgC,EAAQ,EAAE;IAC1F,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;IAEjD,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,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;QAC7B,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,8BAA8B;AAC9B,MAAM,CAAC,MAAM,WAAW,GAAG,GAAgB,EAAE;IAC3C,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAiB,EAAQ,EAAE;IACxD,KAAK,GAAG,IAAI,CAAC;AACf,CAAC,CAAC;AAEF,sGAAsG;AACtG,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAsC,EAAgB,EAAE;IACpF,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAExB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1C,CAAC,CAAC;AAEF,+FAA+F;AAC/F,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAiB,EAAE,OAAoB,EAAE,EAAe,EAAE;IACpF,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;IAErE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE1C,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE;QAC3B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;YAC5C,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC,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 const setRequestHeaders = (prefix: string, headers?: Record<string, string>): void => {\n const kept = rules.filter(([p]) => p !== prefix);\n\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 listeners.forEach((listener) => {\n listener(rules);\n });\n};\n\n/** @internal The rules now */\nexport const headerRules = (): HeaderRules => {\n return rules;\n};\n\n/** @internal The rules, from the page (a worker's copy) */\nexport const 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 const onHeaderRules = (listener: (rules: HeaderRules) => void): (() => void) => {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n};\n\n/** @internal `init` with the headers of the rules matching `url` (unchanged when none does) */\nexport const withHeaders = (url: string | URL, init: RequestInit = {}): RequestInit => {\n const href = String(url);\n const matching = rules.filter(([prefix]) => href.startsWith(prefix));\n\n if (matching.length === 0) return init;\n\n const headers = new Headers(init.headers);\n\n matching.forEach(([, set]) => {\n Object.entries(set).forEach(([name, value]) => {\n headers.set(name, value);\n });\n });\n\n return { ...init, headers };\n};\n"]}
@@ -14,5 +14,3 @@ export type RoofMode = 'data' | 'generated' | 'flat';
14
14
  export declare const roofShapeOf: (properties: unknown, mode: RoofMode) => string | undefined;
15
15
  /** A building's roof height from its properties (`roof:height` or `roof_height`; not a number: as its slopes make it) */
16
16
  export declare const roofHeightOf: (properties: unknown) => number;
17
- /** Metres per Mercator unit at a Mercator y (towards the south, [0, 1]): a roof's slopes run in metres */
18
- export declare const metresAt: (y: number) => number;
@@ -2,7 +2,6 @@
2
2
  * The roofs of the buildings as the engine builds them (`RoofShape::number`): the shapes of OpenStreetMap's
3
3
  * `roof:shape`, those it does not draw as the nearest of them, or generated from a building's outline
4
4
  */
5
- import { EARTH_METRES } from "./geo.js";
6
5
  import { isRecord } from "./guards.js";
7
6
  /** OpenStreetMap's `roof:shape` as the engine's roofs (1 flat, 2 hipped, 3 gabled, 4 pyramidal, 5 mansard) */
8
7
  const ROOF_SHAPES = {
@@ -39,6 +38,4 @@ export const roofShapeOf = (properties, mode) => {
39
38
  };
40
39
  /** A building's roof height from its properties (`roof:height` or `roof_height`; not a number: as its slopes make it) */
41
40
  export const roofHeightOf = (properties) => Number(property(properties, ['roof:height', 'roof_height']) ?? Number.NaN);
42
- /** Metres per Mercator unit at a Mercator y (towards the south, [0, 1]): a roof's slopes run in metres */
43
- export const metresAt = (y) => EARTH_METRES * Math.cos(Math.atan(Math.sinh(Math.PI * (1 - 2 * y))));
44
41
  //# sourceMappingURL=roofs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"roofs.js","sourceRoot":"","sources":["../../src/util/roofs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,8GAA8G;AAC9G,MAAM,WAAW,GAAqC;IACpD,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;IACT,aAAa,EAAE,CAAC;IAChB,WAAW,EAAE,CAAC;IACd,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,CAAC;IACZ,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,CAAC;CACX,CAAC;AAEF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAElC,iHAAiH;AACjH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAsB,EAAE,CAC9D,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAM9D,yDAAyD;AACzD,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAE,KAAwB,EAAW,EAAE,CACjE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAEhF;8DAC8D;AAC9D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,UAAmB,EAAE,IAAc,EAAsB,EAAE;IACrF,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;IAEjE,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IACtC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,WAAW,CAAC,KAAK,CAAC,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAEhF,OAAO,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC,CAAC;AAEF,yHAAyH;AACzH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,UAAmB,EAAU,EAAE,CAC1D,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;AAE7E,0GAA0G;AAC1G,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["/**\n * The roofs of the buildings as the engine builds them (`RoofShape::number`): the shapes of OpenStreetMap's\n * `roof:shape`, those it does not draw as the nearest of them, or generated from a building's outline\n */\n\nimport { EARTH_METRES } from './geo.ts';\nimport { isRecord } from './guards.ts';\n\n/** OpenStreetMap's `roof:shape` as the engine's roofs (1 flat, 2 hipped, 3 gabled, 4 pyramidal, 5 mansard) */\nconst ROOF_SHAPES: Readonly<Record<string, number>> = {\n flat: 1,\n skillion: 1,\n hipped: 2,\n 'half-hipped': 2,\n side_hipped: 2,\n dome: 2,\n onion: 2,\n round: 2,\n gabled: 3,\n saltbox: 3,\n pyramidal: 4,\n cone: 4,\n mansard: 5,\n gambrel: 5,\n};\n\n/** A roof generated from its building's outline (`shapes::GENERATED_ROOF`) */\nexport const GENERATED_ROOF = 255;\n\n/** The engine's number of a roof shape (`roof:shape`, or `generated`); undefined for a shape it does not know */\nexport const roofNumber = (shape: string): number | undefined =>\n shape === 'generated' ? GENERATED_ROOF : ROOF_SHAPES[shape];\n\n/** How the buildings' roofs are made: from their data (`roof:shape`, `roof:height`; flat without), generated where\n * they have none, or all flat */\nexport type RoofMode = 'data' | 'generated' | 'flat';\n\n/** The first of a feature's properties `names` it has */\nconst property = (p: unknown, names: readonly string[]): unknown =>\n isRecord(p) ? names.map((n) => p[n]).find((v) => v !== undefined) : undefined;\n\n/** A building's roof shape by the `mode`, from its properties (`roof:shape` or `roof_shape`): one the engine knows,\n * else generated in `generated`; undefined for none (flat) */\nexport const roofShapeOf = (properties: unknown, mode: RoofMode): string | undefined => {\n const shape = property(properties, ['roof:shape', 'roof_shape']);\n\n if (mode === 'flat') return undefined;\n if (typeof shape === 'string' && ROOF_SHAPES[shape] !== undefined) return shape;\n\n return mode === 'generated' ? 'generated' : undefined;\n};\n\n/** A building's roof height from its properties (`roof:height` or `roof_height`; not a number: as its slopes make it) */\nexport const roofHeightOf = (properties: unknown): number =>\n Number(property(properties, ['roof:height', 'roof_height']) ?? Number.NaN);\n\n/** Metres per Mercator unit at a Mercator y (towards the south, [0, 1]): a roof's slopes run in metres */\nexport const metresAt = (y: number): number => EARTH_METRES * Math.cos(Math.atan(Math.sinh(Math.PI * (1 - 2 * y))));\n"]}
1
+ {"version":3,"file":"roofs.js","sourceRoot":"","sources":["../../src/util/roofs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,8GAA8G;AAC9G,MAAM,WAAW,GAAqC;IACpD,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;IACT,aAAa,EAAE,CAAC;IAChB,WAAW,EAAE,CAAC;IACd,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,CAAC;IACZ,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,CAAC;CACX,CAAC;AAEF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAElC,iHAAiH;AACjH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAsB,EAAE,CAC9D,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAM9D,yDAAyD;AACzD,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAE,KAAwB,EAAW,EAAE,CACjE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAEhF;8DAC8D;AAC9D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,UAAmB,EAAE,IAAc,EAAsB,EAAE;IACrF,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;IAEjE,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IACtC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,WAAW,CAAC,KAAK,CAAC,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAEhF,OAAO,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC,CAAC;AAEF,yHAAyH;AACzH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,UAAmB,EAAU,EAAE,CAC1D,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC","sourcesContent":["/**\n * The roofs of the buildings as the engine builds them (`RoofShape::number`): the shapes of OpenStreetMap's\n * `roof:shape`, those it does not draw as the nearest of them, or generated from a building's outline\n */\n\nimport { isRecord } from './guards.ts';\n\n/** OpenStreetMap's `roof:shape` as the engine's roofs (1 flat, 2 hipped, 3 gabled, 4 pyramidal, 5 mansard) */\nconst ROOF_SHAPES: Readonly<Record<string, number>> = {\n flat: 1,\n skillion: 1,\n hipped: 2,\n 'half-hipped': 2,\n side_hipped: 2,\n dome: 2,\n onion: 2,\n round: 2,\n gabled: 3,\n saltbox: 3,\n pyramidal: 4,\n cone: 4,\n mansard: 5,\n gambrel: 5,\n};\n\n/** A roof generated from its building's outline (`shapes::GENERATED_ROOF`) */\nexport const GENERATED_ROOF = 255;\n\n/** The engine's number of a roof shape (`roof:shape`, or `generated`); undefined for a shape it does not know */\nexport const roofNumber = (shape: string): number | undefined =>\n shape === 'generated' ? GENERATED_ROOF : ROOF_SHAPES[shape];\n\n/** How the buildings' roofs are made: from their data (`roof:shape`, `roof:height`; flat without), generated where\n * they have none, or all flat */\nexport type RoofMode = 'data' | 'generated' | 'flat';\n\n/** The first of a feature's properties `names` it has */\nconst property = (p: unknown, names: readonly string[]): unknown =>\n isRecord(p) ? names.map((n) => p[n]).find((v) => v !== undefined) : undefined;\n\n/** A building's roof shape by the `mode`, from its properties (`roof:shape` or `roof_shape`): one the engine knows,\n * else generated in `generated`; undefined for none (flat) */\nexport const roofShapeOf = (properties: unknown, mode: RoofMode): string | undefined => {\n const shape = property(properties, ['roof:shape', 'roof_shape']);\n\n if (mode === 'flat') return undefined;\n if (typeof shape === 'string' && ROOF_SHAPES[shape] !== undefined) return shape;\n\n return mode === 'generated' ? 'generated' : undefined;\n};\n\n/** A building's roof height from its properties (`roof:height` or `roof_height`; not a number: as its slopes make it) */\nexport const roofHeightOf = (properties: unknown): number =>\n Number(property(properties, ['roof:height', 'roof_height']) ?? Number.NaN);\n"]}
@@ -425,6 +425,10 @@ export class Engine {
425
425
  * Removes the panorama
426
426
  */
427
427
  clearPanorama(): void;
428
+ /**
429
+ * The turns go around the screen center again
430
+ */
431
+ clearPivot(): void;
428
432
  /**
429
433
  * Stops loading the tiles of the flight's destination (`preload`)
430
434
  */
@@ -554,7 +558,7 @@ export class Engine {
554
558
  */
555
559
  resize(width: number, height: number, pixel_ratio: number): void;
556
560
  /**
557
- * Turns and tilts around the screen center, in degrees
561
+ * Turns and tilts, in degrees: around the pivot if one is set (`setPivot`), else around the screen center
558
562
  */
559
563
  rotate(bearing: number, pitch: number): void;
560
564
  /**
@@ -816,6 +820,12 @@ export class Engine {
816
820
  * shader fails to compile (the error carries its info log)
817
821
  */
818
822
  setPanorama(lon: number, lat: number, height: number, rotation: Float64Array, cameras: Float64Array, radius: number, opacity: number): void;
823
+ /**
824
+ * Sets the point the next turns and tilts go around (`rotate`): what is drawn under a screen point (CSS
825
+ * pixels), a roof or a mesh as the relief. Read back from the last frame (a stall): once, where a drag starts.
826
+ * Returns whether something was drawn there; over nothing, the turns go around the center
827
+ */
828
+ setPivot(x: number, y: number): boolean;
819
829
  /**
820
830
  * The style of a point cloud: 14 numbers (see `Style::parse`), the colors of the 256 classes (RGBA,
821
831
  * alpha 0 hides a class) and the ramp of the altitudes (256 RGBA texels)
@@ -888,6 +898,10 @@ export class Engine {
888
898
  * it, tiles are decoded on the main thread. Set it before adding 3D Tiles layers.
889
899
  */
890
900
  setTileLoader(loader: TileLoaderLike | null): void;
901
+ /**
902
+ * Whether the walls of a 3D Tiles layer's untextured meshes show their windows: glass by day, some lit at night
903
+ */
904
+ setTiles3dFacades(id: number, facades: boolean): void;
891
905
  /**
892
906
  * Screen-space error threshold, opacity, size of the points (CSS pixels, 2 if not given) and color (RGB 0-1, empty
893
907
  * for none: it tints the textures and colors the untextured meshes) of a 3D Tiles layer
@@ -1078,6 +1092,7 @@ export interface InitOutput {
1078
1092
  readonly engine_bounds: (a: number) => [number, number];
1079
1093
  readonly engine_camera: (a: number) => any;
1080
1094
  readonly engine_clearPanorama: (a: number) => void;
1095
+ readonly engine_clearPivot: (a: number) => void;
1081
1096
  readonly engine_clearPreload: (a: number) => void;
1082
1097
  readonly engine_clearViewshed: (a: number) => void;
1083
1098
  readonly engine_customMatrix: (a: number, b: number, c: number) => [number, number];
@@ -1149,6 +1164,7 @@ export interface InitOutput {
1149
1164
  readonly engine_setNetworkValues: (a: number, b: number, c: number, d: number) => void;
1150
1165
  readonly engine_setPanorama: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => [number, number];
1151
1166
  readonly engine_setPanoramaImage: (a: number, b: number, c: any) => [number, number];
1167
+ readonly engine_setPivot: (a: number, b: number, c: number) => number;
1152
1168
  readonly engine_setPointCloudStyle: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
1153
1169
  readonly engine_setRasterStyle: (a: number, b: number, c: number, d: number) => void;
1154
1170
  readonly engine_setRequestHeaders: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
@@ -1159,6 +1175,7 @@ export interface InitOutput {
1159
1175
  readonly engine_setSymbols: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number) => [number, number];
1160
1176
  readonly engine_setTerrain: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
1161
1177
  readonly engine_setTileLoader: (a: number, b: any) => void;
1178
+ readonly engine_setTiles3dFacades: (a: number, b: number, c: number) => void;
1162
1179
  readonly engine_setTiles3dStyle: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
1163
1180
  readonly engine_setVectorSublayers: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number) => void;
1164
1181
  readonly engine_setVectorTile: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number) => [number, number];
@@ -361,6 +361,12 @@ export class Engine {
361
361
  clearPanorama() {
362
362
  wasm.engine_clearPanorama(this.__wbg_ptr);
363
363
  }
364
+ /**
365
+ * The turns go around the screen center again
366
+ */
367
+ clearPivot() {
368
+ wasm.engine_clearPivot(this.__wbg_ptr);
369
+ }
364
370
  /**
365
371
  * Stops loading the tiles of the flight's destination (`preload`)
366
372
  */
@@ -640,7 +646,7 @@ export class Engine {
640
646
  wasm.engine_resize(this.__wbg_ptr, width, height, pixel_ratio);
641
647
  }
642
648
  /**
643
- * Turns and tilts around the screen center, in degrees
649
+ * Turns and tilts, in degrees: around the pivot if one is set (`setPivot`), else around the screen center
644
650
  * @param {number} bearing
645
651
  * @param {number} pitch
646
652
  */
@@ -1268,6 +1274,18 @@ export class Engine {
1268
1274
  throw takeFromExternrefTable0(ret[0]);
1269
1275
  }
1270
1276
  }
1277
+ /**
1278
+ * Sets the point the next turns and tilts go around (`rotate`): what is drawn under a screen point (CSS
1279
+ * pixels), a roof or a mesh as the relief. Read back from the last frame (a stall): once, where a drag starts.
1280
+ * Returns whether something was drawn there; over nothing, the turns go around the center
1281
+ * @param {number} x
1282
+ * @param {number} y
1283
+ * @returns {boolean}
1284
+ */
1285
+ setPivot(x, y) {
1286
+ const ret = wasm.engine_setPivot(this.__wbg_ptr, x, y);
1287
+ return ret !== 0;
1288
+ }
1271
1289
  /**
1272
1290
  * The style of a point cloud: 14 numbers (see `Style::parse`), the colors of the 256 classes (RGBA,
1273
1291
  * alpha 0 hides a class) and the ramp of the altitudes (256 RGBA texels)
@@ -1439,6 +1457,14 @@ export class Engine {
1439
1457
  setTileLoader(loader) {
1440
1458
  wasm.engine_setTileLoader(this.__wbg_ptr, loader);
1441
1459
  }
1460
+ /**
1461
+ * Whether the walls of a 3D Tiles layer's untextured meshes show their windows: glass by day, some lit at night
1462
+ * @param {number} id
1463
+ * @param {boolean} facades
1464
+ */
1465
+ setTiles3dFacades(id, facades) {
1466
+ wasm.engine_setTiles3dFacades(this.__wbg_ptr, id, facades);
1467
+ }
1442
1468
  /**
1443
1469
  * Screen-space error threshold, opacity, size of the points (CSS pixels, 2 if not given) and color (RGB 0-1, empty
1444
1470
  * for none: it tints the textures and colors the untextured meshes) of a 3D Tiles layer
@@ -3129,7 +3155,7 @@ function __wbg_get_imports() {
3129
3155
  return ret;
3130
3156
  },
3131
3157
  __wbindgen_generic_0000000000000001: function(arg0, arg1) {
3132
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 225, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
3158
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 229, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
3133
3159
  const ret = makeMutClosure(arg0, arg1, wasm_bindgen_2e566c63402fe7fa___convert__closures_____invoke___wasm_bindgen_2e566c63402fe7fa___JsValue__core_37ee0ce0c4cd57d5___result__Result_____wasm_bindgen_2e566c63402fe7fa___JsError___true_);
3134
3160
  return ret;
3135
3161
  },