@npm9912/v-map 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (438) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/dist/cjs/_commonjsHelpers-B83fTs8d.js +36 -0
  4. package/dist/cjs/app-globals-V2Kpy_OQ.js +5 -0
  5. package/dist/cjs/cesium-provider-BiFFyAl9.js +2598 -0
  6. package/dist/cjs/deck-provider-Ctq3Q8a1.js +47824 -0
  7. package/dist/cjs/geotiff-CEwvF9cG.js +47 -0
  8. package/dist/cjs/geotiff-source-RaNzzWkC.js +1522 -0
  9. package/dist/cjs/index-B1oGO1g-.js +10658 -0
  10. package/dist/cjs/index-B8LHqjyg.js +1765 -0
  11. package/dist/cjs/index-BIL4VsgP.js +310 -0
  12. package/dist/cjs/index-Blku2QY8.js +167 -0
  13. package/dist/cjs/index-CJvvX4yx.js +21 -0
  14. package/dist/cjs/index-CbVT-Con.js +699 -0
  15. package/dist/cjs/index-ISOEpMC3.js +20478 -0
  16. package/dist/cjs/index-JSwBbvGA.js +1621 -0
  17. package/dist/cjs/index.browser-DQhD8Jwl.js +6873 -0
  18. package/dist/cjs/index.cjs.js +2 -0
  19. package/dist/cjs/layer-extension-B_olS0rc.js +65 -0
  20. package/dist/cjs/leaflet-provider-DOqfs7g5.js +1815 -0
  21. package/dist/cjs/loader.cjs.js +13 -0
  22. package/dist/cjs/main-dist-7TykwFci.js +2655 -0
  23. package/dist/cjs/messages-D7h4m8Tx.js +186 -0
  24. package/dist/cjs/openlayers-provider-Dfeg6L4n.js +1604 -0
  25. package/dist/cjs/polygon-layer-B9PrN7vr.js +1300 -0
  26. package/dist/cjs/scenegraph-layer-DwNoxQdi.js +2530 -0
  27. package/dist/cjs/styleconfig-CVRqArk-.js +23 -0
  28. package/dist/cjs/v-map-builder.cjs.entry.js +3786 -0
  29. package/dist/cjs/v-map-layer-geojson_12.cjs.entry.js +40894 -0
  30. package/dist/cjs/v-map-layer-helper-iAzxAg9I.js +285 -0
  31. package/dist/cjs/v-map-layer-terrain-geotiff.cjs.entry.js +258 -0
  32. package/dist/cjs/v-map-layercontrol.cjs.entry.js +247 -0
  33. package/dist/cjs/v-map.cjs.js +25 -0
  34. package/dist/cjs/v-map.v-map-layer-osm.v-map-layergroup-BsXp3BoL.js +582 -0
  35. package/dist/cjs/v-map_3.cjs.entry.js +12 -0
  36. package/dist/collection/collection-manifest.json +30 -0
  37. package/dist/collection/components/v-map/v-map.css +3 -0
  38. package/dist/collection/components/v-map/v-map.js +467 -0
  39. package/dist/collection/components/v-map/v-map.test.js +33 -0
  40. package/dist/collection/components/v-map-builder/v-map-builder.css +1 -0
  41. package/dist/collection/components/v-map-builder/v-map-builder.js +913 -0
  42. package/dist/collection/components/v-map-builder/v-map-builder.test.js +56 -0
  43. package/dist/collection/components/v-map-layer-geojson/v-map-layer-geojson.js +862 -0
  44. package/dist/collection/components/v-map-layer-geojson/v-map-layer-geojson.test.js +42 -0
  45. package/dist/collection/components/v-map-layer-geotiff/v-map-layer-geotiff.css +4 -0
  46. package/dist/collection/components/v-map-layer-geotiff/v-map-layer-geotiff.js +500 -0
  47. package/dist/collection/components/v-map-layer-geotiff/v-map-layer-geotiff.test.js +38 -0
  48. package/dist/collection/components/v-map-layer-google/v-map-layer-google.css +1 -0
  49. package/dist/collection/components/v-map-layer-google/v-map-layer-google.js +442 -0
  50. package/dist/collection/components/v-map-layer-osm/error-api.test.js +108 -0
  51. package/dist/collection/components/v-map-layer-osm/v-map-layer-osm.css +4 -0
  52. package/dist/collection/components/v-map-layer-osm/v-map-layer-osm.js +311 -0
  53. package/dist/collection/components/v-map-layer-osm/v-map-layer-osm.test.js +36 -0
  54. package/dist/collection/components/v-map-layer-scatterplot/v-map-layer-scatterplot.css +1 -0
  55. package/dist/collection/components/v-map-layer-scatterplot/v-map-layer-scatterplot.js +305 -0
  56. package/dist/collection/components/v-map-layer-terrain/v-map-layer-terrain.css +3 -0
  57. package/dist/collection/components/v-map-layer-terrain/v-map-layer-terrain.js +548 -0
  58. package/dist/collection/components/v-map-layer-terrain/v-map-layer-terrain.test.js +36 -0
  59. package/dist/collection/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.css +3 -0
  60. package/dist/collection/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.js +735 -0
  61. package/dist/collection/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.test.js +42 -0
  62. package/dist/collection/components/v-map-layer-tile3d/v-map-layer-tile3d.css +3 -0
  63. package/dist/collection/components/v-map-layer-tile3d/v-map-layer-tile3d.js +449 -0
  64. package/dist/collection/components/v-map-layer-tile3d/v-map-layer-tile3d.test.js +50 -0
  65. package/dist/collection/components/v-map-layer-wcs/v-map-layer-wcs.css +1 -0
  66. package/dist/collection/components/v-map-layer-wcs/v-map-layer-wcs.js +448 -0
  67. package/dist/collection/components/v-map-layer-wcs/v-map-layer-wcs.test.js +39 -0
  68. package/dist/collection/components/v-map-layer-wfs/v-map-layer-wfs.css +1 -0
  69. package/dist/collection/components/v-map-layer-wfs/v-map-layer-wfs.js +489 -0
  70. package/dist/collection/components/v-map-layer-wfs/v-map-layer-wfs.test.js +43 -0
  71. package/dist/collection/components/v-map-layer-wkt/v-map-layer-wkt.css +1 -0
  72. package/dist/collection/components/v-map-layer-wkt/v-map-layer-wkt.js +811 -0
  73. package/dist/collection/components/v-map-layer-wkt/v-map-layer-wkt.test.js +34 -0
  74. package/dist/collection/components/v-map-layer-wms/v-map-layer-wms.css +1 -0
  75. package/dist/collection/components/v-map-layer-wms/v-map-layer-wms.js +453 -0
  76. package/dist/collection/components/v-map-layer-wms/v-map-layer-wms.test.js +36 -0
  77. package/dist/collection/components/v-map-layer-xyz/v-map-layer-xyz.css +1 -0
  78. package/dist/collection/components/v-map-layer-xyz/v-map-layer-xyz.js +331 -0
  79. package/dist/collection/components/v-map-layer-xyz/v-map-layer-xyz.test.js +28 -0
  80. package/dist/collection/components/v-map-layercontrol/v-map-layercontrol.css +74 -0
  81. package/dist/collection/components/v-map-layercontrol/v-map-layercontrol.js +277 -0
  82. package/dist/collection/components/v-map-layercontrol/v-map-layercontrol.test.js +134 -0
  83. package/dist/collection/components/v-map-layergroup/v-map-layergroup.css +4 -0
  84. package/dist/collection/components/v-map-layergroup/v-map-layergroup.js +212 -0
  85. package/dist/collection/components/v-map-layergroup/v-map-layergroup.test.js +39 -0
  86. package/dist/collection/components/v-map-style/v-map-style.css +38 -0
  87. package/dist/collection/components/v-map-style/v-map-style.js +492 -0
  88. package/dist/collection/components/v-map-style/v-map-style.unit.js +62 -0
  89. package/dist/collection/index.js +1 -0
  90. package/dist/collection/layer/v-map-layer-helper.js +281 -0
  91. package/dist/collection/layer/v-map-layer-helper.unit.js +234 -0
  92. package/dist/collection/lib/cesium-loader.js +58 -0
  93. package/dist/collection/lib/ensure-importmap.js +12 -0
  94. package/dist/collection/lib/ensure-importmap.unit.js +57 -0
  95. package/dist/collection/lib/versions.gen.js +6 -0
  96. package/dist/collection/lib/vstyle.js +8 -0
  97. package/dist/collection/map-provider/cesium/CesiumGeoTIFFTerrainProvider.js +285 -0
  98. package/dist/collection/map-provider/cesium/CesiumLayerGroups.js +159 -0
  99. package/dist/collection/map-provider/cesium/GeoTIFFImageryProvider.js +192 -0
  100. package/dist/collection/map-provider/cesium/GeoTIFFImageryProvider.test.js +57 -0
  101. package/dist/collection/map-provider/cesium/cesium-provider.js +1408 -0
  102. package/dist/collection/map-provider/cesium/i-layer.js +1 -0
  103. package/dist/collection/map-provider/cesium/layer-manager.js +467 -0
  104. package/dist/collection/map-provider/deck/DeckGLGeoTIFFLayer.js +483 -0
  105. package/dist/collection/map-provider/deck/DeckGLGeoTIFFTerrainLayer.js +410 -0
  106. package/dist/collection/map-provider/deck/LayerGroupWithModel.js +169 -0
  107. package/dist/collection/map-provider/deck/LayerGroups.js +192 -0
  108. package/dist/collection/map-provider/deck/LayerModel.js +1 -0
  109. package/dist/collection/map-provider/deck/RenderableGroup.js +1 -0
  110. package/dist/collection/map-provider/deck/deck-provider.js +1563 -0
  111. package/dist/collection/map-provider/geotiff/geotiff-source.js +172 -0
  112. package/dist/collection/map-provider/geotiff/utils/AABB2D.js +24 -0
  113. package/dist/collection/map-provider/geotiff/utils/BVHNode2D.js +166 -0
  114. package/dist/collection/map-provider/geotiff/utils/GeoTIFFTileProcessor.js +484 -0
  115. package/dist/collection/map-provider/geotiff/utils/Triangle.js +1 -0
  116. package/dist/collection/map-provider/geotiff/utils/Triangulation.js +321 -0
  117. package/dist/collection/map-provider/geotiff/utils/colormap-utils.js +190 -0
  118. package/dist/collection/map-provider/geotiff/utils/normalization-utils.js +122 -0
  119. package/dist/collection/map-provider/geotiff/utils/sampling-utils.js +108 -0
  120. package/dist/collection/map-provider/leaflet/GeoTIFFGridLayer.js +147 -0
  121. package/dist/collection/map-provider/leaflet/WCSGridLayer.js +124 -0
  122. package/dist/collection/map-provider/leaflet/google-map-tiles-layer.js +352 -0
  123. package/dist/collection/map-provider/leaflet/leaflet-helpers.js +94 -0
  124. package/dist/collection/map-provider/leaflet/leaflet-provider.js +1095 -0
  125. package/dist/collection/map-provider/ol/CustomGeoTiff.js +145 -0
  126. package/dist/collection/map-provider/ol/openlayers-helper.js +26 -0
  127. package/dist/collection/map-provider/ol/openlayers-provider.js +1427 -0
  128. package/dist/collection/map-provider/provider-factory.js +44 -0
  129. package/dist/collection/map-provider/provider-factory.unit.js +66 -0
  130. package/dist/collection/testing/browser-test-utils.js +49 -0
  131. package/dist/collection/testing/e2e-testing.js +122 -0
  132. package/dist/collection/testing/e2e-utils.js +70 -0
  133. package/dist/collection/testing/geotiff-test-server.js +100 -0
  134. package/dist/collection/testing/mocks/geostyler-lyrx-parser.js +12 -0
  135. package/dist/collection/testing/mocks/geostyler-mapbox-parser.js +12 -0
  136. package/dist/collection/testing/mocks/geostyler-qgis-parser.js +12 -0
  137. package/dist/collection/testing/mocks/geostyler-sld-parser.js +13 -0
  138. package/dist/collection/testing/mocks/geostyler-style.js +5 -0
  139. package/dist/collection/testing/setupTests.browser.js +1 -0
  140. package/dist/collection/testing/setupTests.stencil.js +20 -0
  141. package/dist/collection/testing/setupTests.vitest.js +59 -0
  142. package/dist/collection/testing/stencil-testing-wrapper.js +43 -0
  143. package/dist/collection/testing/styleMock.js +1 -0
  144. package/dist/collection/types/color.js +1 -0
  145. package/dist/collection/types/cssmode.js +1 -0
  146. package/dist/collection/types/flavour.js +1 -0
  147. package/dist/collection/types/layerconfig.js +1 -0
  148. package/dist/collection/types/lonlat.js +1 -0
  149. package/dist/collection/types/mapinitoptions.js +1 -0
  150. package/dist/collection/types/mapprovider.js +1 -0
  151. package/dist/collection/types/provideroptions.js +1 -0
  152. package/dist/collection/types/styleconfig.js +19 -0
  153. package/dist/collection/types/styling.js +13 -0
  154. package/dist/collection/types/styling.unit.js +37 -0
  155. package/dist/collection/types/vmaplayer.js +1 -0
  156. package/dist/collection/utils/async-mutex.js +28 -0
  157. package/dist/collection/utils/diff.js +142 -0
  158. package/dist/collection/utils/diff.unit.js +59 -0
  159. package/dist/collection/utils/dom-env.js +43 -0
  160. package/dist/collection/utils/dom-env.unit.js +92 -0
  161. package/dist/collection/utils/events.js +8 -0
  162. package/dist/collection/utils/logger.js +183 -0
  163. package/dist/collection/utils/logger.unit.js +98 -0
  164. package/dist/collection/utils/messages.js +12 -0
  165. package/dist/collection/utils/spatial-utils.js +27 -0
  166. package/dist/collection/utils/spatial-utils.unit.js +24 -0
  167. package/dist/components/_commonjsHelpers.js +1 -0
  168. package/dist/components/cesium-provider.js +1 -0
  169. package/dist/components/deck-provider.js +1 -0
  170. package/dist/components/events.js +1 -0
  171. package/dist/components/geotiff-source.js +1 -0
  172. package/dist/components/geotiff.js +4 -0
  173. package/dist/components/index.browser.js +15 -0
  174. package/dist/components/index.d.ts +35 -0
  175. package/dist/components/index.js +1 -0
  176. package/dist/components/index2.js +1 -0
  177. package/dist/components/index3.js +1 -0
  178. package/dist/components/index4.js +1 -0
  179. package/dist/components/index5.js +1 -0
  180. package/dist/components/index6.js +1 -0
  181. package/dist/components/index7.js +1 -0
  182. package/dist/components/index8.js +7 -0
  183. package/dist/components/layer-extension.js +1 -0
  184. package/dist/components/leaflet-provider.js +1 -0
  185. package/dist/components/main-dist.js +1 -0
  186. package/dist/components/messages.js +1 -0
  187. package/dist/components/openlayers-provider.js +1 -0
  188. package/dist/components/polygon-layer.js +1 -0
  189. package/dist/components/scenegraph-layer.js +1 -0
  190. package/dist/components/styleconfig.js +1 -0
  191. package/dist/components/styling.js +1 -0
  192. package/dist/components/v-map-builder.d.ts +11 -0
  193. package/dist/components/v-map-builder.js +2 -0
  194. package/dist/components/v-map-layer-geojson.d.ts +11 -0
  195. package/dist/components/v-map-layer-geojson.js +1 -0
  196. package/dist/components/v-map-layer-geojson2.js +1 -0
  197. package/dist/components/v-map-layer-geotiff.d.ts +11 -0
  198. package/dist/components/v-map-layer-geotiff.js +1 -0
  199. package/dist/components/v-map-layer-geotiff2.js +1 -0
  200. package/dist/components/v-map-layer-google.d.ts +11 -0
  201. package/dist/components/v-map-layer-google.js +1 -0
  202. package/dist/components/v-map-layer-google2.js +1 -0
  203. package/dist/components/v-map-layer-helper.js +1 -0
  204. package/dist/components/v-map-layer-osm.d.ts +11 -0
  205. package/dist/components/v-map-layer-osm.js +1 -0
  206. package/dist/components/v-map-layer-osm2.js +1 -0
  207. package/dist/components/v-map-layer-scatterplot.d.ts +11 -0
  208. package/dist/components/v-map-layer-scatterplot.js +1 -0
  209. package/dist/components/v-map-layer-scatterplot2.js +1 -0
  210. package/dist/components/v-map-layer-terrain-geotiff.d.ts +11 -0
  211. package/dist/components/v-map-layer-terrain-geotiff.js +1 -0
  212. package/dist/components/v-map-layer-terrain.d.ts +11 -0
  213. package/dist/components/v-map-layer-terrain.js +1 -0
  214. package/dist/components/v-map-layer-terrain2.js +1 -0
  215. package/dist/components/v-map-layer-tile3d.d.ts +11 -0
  216. package/dist/components/v-map-layer-tile3d.js +1 -0
  217. package/dist/components/v-map-layer-tile3d2.js +1 -0
  218. package/dist/components/v-map-layer-wcs.d.ts +11 -0
  219. package/dist/components/v-map-layer-wcs.js +1 -0
  220. package/dist/components/v-map-layer-wcs2.js +1 -0
  221. package/dist/components/v-map-layer-wfs.d.ts +11 -0
  222. package/dist/components/v-map-layer-wfs.js +1 -0
  223. package/dist/components/v-map-layer-wfs2.js +1 -0
  224. package/dist/components/v-map-layer-wkt.d.ts +11 -0
  225. package/dist/components/v-map-layer-wkt.js +1 -0
  226. package/dist/components/v-map-layer-wkt2.js +1 -0
  227. package/dist/components/v-map-layer-wms.d.ts +11 -0
  228. package/dist/components/v-map-layer-wms.js +1 -0
  229. package/dist/components/v-map-layer-wms2.js +1 -0
  230. package/dist/components/v-map-layer-xyz.d.ts +11 -0
  231. package/dist/components/v-map-layer-xyz.js +1 -0
  232. package/dist/components/v-map-layer-xyz2.js +1 -0
  233. package/dist/components/v-map-layercontrol.d.ts +11 -0
  234. package/dist/components/v-map-layercontrol.js +1 -0
  235. package/dist/components/v-map-layergroup.d.ts +11 -0
  236. package/dist/components/v-map-layergroup.js +1 -0
  237. package/dist/components/v-map-layergroup2.js +1 -0
  238. package/dist/components/v-map-style.d.ts +11 -0
  239. package/dist/components/v-map-style.js +1 -0
  240. package/dist/components/v-map-style2.js +10 -0
  241. package/dist/components/v-map.d.ts +11 -0
  242. package/dist/components/v-map.js +1 -0
  243. package/dist/components/v-map2.js +1 -0
  244. package/dist/esm/_commonjsHelpers-E-ZsRS8r.js +32 -0
  245. package/dist/esm/app-globals-DQuL1Twl.js +3 -0
  246. package/dist/esm/cesium-provider-BJfAup3w.js +2596 -0
  247. package/dist/esm/deck-provider-C7U9VDEq.js +47709 -0
  248. package/dist/esm/geotiff-BEWxTIfH.js +45 -0
  249. package/dist/esm/geotiff-source-esnDnC-u.js +1516 -0
  250. package/dist/esm/index-B1zwA4IC.js +685 -0
  251. package/dist/esm/index-BBpiaTpT.js +165 -0
  252. package/dist/esm/index-BIEmlzCf.js +1697 -0
  253. package/dist/esm/index-BUHa4Jj0.js +307 -0
  254. package/dist/esm/index-DbSdn93t.js +20461 -0
  255. package/dist/esm/index-RpJarvr_.js +10656 -0
  256. package/dist/esm/index-jN06TXUp.js +14 -0
  257. package/dist/esm/index-jzneDarq.js +1613 -0
  258. package/dist/esm/index.browser-DhQAXuA7.js +6860 -0
  259. package/dist/esm/index.js +1 -0
  260. package/dist/esm/layer-extension-CZXK5goK.js +63 -0
  261. package/dist/esm/leaflet-provider-Q41TB6ku.js +1794 -0
  262. package/dist/esm/loader.js +11 -0
  263. package/dist/esm/main-dist-CwnA7_Xn.js +2652 -0
  264. package/dist/esm/messages-CMKJzsgL.js +180 -0
  265. package/dist/esm/openlayers-provider-CMsDsQTQ.js +1602 -0
  266. package/dist/esm/polygon-layer-ByhxGhWC.js +1295 -0
  267. package/dist/esm/scenegraph-layer-09K_B6DT.js +2526 -0
  268. package/dist/esm/styleconfig-B-bAcABs.js +21 -0
  269. package/dist/esm/v-map-builder.entry.js +3784 -0
  270. package/dist/esm/v-map-layer-geojson_12.entry.js +40881 -0
  271. package/dist/esm/v-map-layer-helper-Dys44Cgo.js +283 -0
  272. package/dist/esm/v-map-layer-terrain-geotiff.entry.js +256 -0
  273. package/dist/esm/v-map-layercontrol.entry.js +245 -0
  274. package/dist/esm/v-map.js +21 -0
  275. package/dist/esm/v-map.v-map-layer-osm.v-map-layergroup-B4pFHuSf.js +572 -0
  276. package/dist/esm/v-map_3.entry.js +4 -0
  277. package/dist/index.cjs.js +1 -0
  278. package/dist/index.js +1 -0
  279. package/dist/types/cesium-augment.d.ts +5 -0
  280. package/dist/types/components/v-map/v-map.d.ts +70 -0
  281. package/dist/types/components/v-map/v-map.test.d.ts +1 -0
  282. package/dist/types/components/v-map-builder/v-map-builder.d.ts +48 -0
  283. package/dist/types/components/v-map-builder/v-map-builder.test.d.ts +1 -0
  284. package/dist/types/components/v-map-layer-geojson/v-map-layer-geojson.d.ts +129 -0
  285. package/dist/types/components/v-map-layer-geojson/v-map-layer-geojson.test.d.ts +1 -0
  286. package/dist/types/components/v-map-layer-geotiff/v-map-layer-geotiff.d.ts +74 -0
  287. package/dist/types/components/v-map-layer-geotiff/v-map-layer-geotiff.test.d.ts +1 -0
  288. package/dist/types/components/v-map-layer-google/v-map-layer-google.d.ts +78 -0
  289. package/dist/types/components/v-map-layer-osm/error-api.test.d.ts +1 -0
  290. package/dist/types/components/v-map-layer-osm/v-map-layer-osm.d.ts +50 -0
  291. package/dist/types/components/v-map-layer-osm/v-map-layer-osm.test.d.ts +1 -0
  292. package/dist/types/components/v-map-layer-scatterplot/v-map-layer-scatterplot.d.ts +54 -0
  293. package/dist/types/components/v-map-layer-terrain/v-map-layer-terrain.d.ts +74 -0
  294. package/dist/types/components/v-map-layer-terrain/v-map-layer-terrain.test.d.ts +1 -0
  295. package/dist/types/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.d.ts +117 -0
  296. package/dist/types/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.test.d.ts +1 -0
  297. package/dist/types/components/v-map-layer-tile3d/v-map-layer-tile3d.d.ts +69 -0
  298. package/dist/types/components/v-map-layer-tile3d/v-map-layer-tile3d.test.d.ts +1 -0
  299. package/dist/types/components/v-map-layer-wcs/v-map-layer-wcs.d.ts +47 -0
  300. package/dist/types/components/v-map-layer-wcs/v-map-layer-wcs.test.d.ts +1 -0
  301. package/dist/types/components/v-map-layer-wfs/v-map-layer-wfs.d.ts +59 -0
  302. package/dist/types/components/v-map-layer-wfs/v-map-layer-wfs.test.d.ts +1 -0
  303. package/dist/types/components/v-map-layer-wkt/v-map-layer-wkt.d.ts +132 -0
  304. package/dist/types/components/v-map-layer-wkt/v-map-layer-wkt.test.d.ts +1 -0
  305. package/dist/types/components/v-map-layer-wms/v-map-layer-wms.d.ts +76 -0
  306. package/dist/types/components/v-map-layer-wms/v-map-layer-wms.test.d.ts +1 -0
  307. package/dist/types/components/v-map-layer-xyz/v-map-layer-xyz.d.ts +59 -0
  308. package/dist/types/components/v-map-layer-xyz/v-map-layer-xyz.test.d.ts +1 -0
  309. package/dist/types/components/v-map-layercontrol/v-map-layercontrol.d.ts +44 -0
  310. package/dist/types/components/v-map-layercontrol/v-map-layercontrol.test.d.ts +1 -0
  311. package/dist/types/components/v-map-layergroup/v-map-layergroup.d.ts +31 -0
  312. package/dist/types/components/v-map-layergroup/v-map-layergroup.test.d.ts +1 -0
  313. package/dist/types/components/v-map-style/v-map-style.d.ts +75 -0
  314. package/dist/types/components/v-map-style/v-map-style.unit.d.ts +1 -0
  315. package/dist/types/components.d.ts +2391 -0
  316. package/dist/types/globals.d.ts +16 -0
  317. package/dist/types/index.d.ts +10 -0
  318. package/dist/types/layer/v-map-layer-helper.d.ts +45 -0
  319. package/dist/types/layer/v-map-layer-helper.unit.d.ts +1 -0
  320. package/dist/types/leaflet-augment.d.ts +15 -0
  321. package/dist/types/lib/cesium-loader.d.ts +3 -0
  322. package/dist/types/lib/ensure-importmap.d.ts +3 -0
  323. package/dist/types/lib/ensure-importmap.unit.d.ts +1 -0
  324. package/dist/types/lib/versions.gen.d.ts +5 -0
  325. package/dist/types/lib/vstyle.d.ts +44 -0
  326. package/dist/types/map-provider/cesium/CesiumGeoTIFFTerrainProvider.d.ts +92 -0
  327. package/dist/types/map-provider/cesium/CesiumLayerGroups.d.ts +64 -0
  328. package/dist/types/map-provider/cesium/GeoTIFFImageryProvider.d.ts +75 -0
  329. package/dist/types/map-provider/cesium/GeoTIFFImageryProvider.test.d.ts +1 -0
  330. package/dist/types/map-provider/cesium/cesium-provider.d.ts +87 -0
  331. package/dist/types/map-provider/cesium/i-layer.d.ts +11 -0
  332. package/dist/types/map-provider/cesium/layer-manager.d.ts +31 -0
  333. package/dist/types/map-provider/deck/DeckGLGeoTIFFLayer.d.ts +91 -0
  334. package/dist/types/map-provider/deck/DeckGLGeoTIFFTerrainLayer.d.ts +82 -0
  335. package/dist/types/map-provider/deck/LayerGroupWithModel.d.ts +55 -0
  336. package/dist/types/map-provider/deck/LayerGroups.d.ts +63 -0
  337. package/dist/types/map-provider/deck/LayerModel.d.ts +8 -0
  338. package/dist/types/map-provider/deck/RenderableGroup.d.ts +20 -0
  339. package/dist/types/map-provider/deck/deck-provider.d.ts +92 -0
  340. package/dist/types/map-provider/geotiff/geotiff-source.d.ts +30 -0
  341. package/dist/types/map-provider/geotiff/utils/AABB2D.d.ts +28 -0
  342. package/dist/types/map-provider/geotiff/utils/BVHNode2D.d.ts +36 -0
  343. package/dist/types/map-provider/geotiff/utils/GeoTIFFTileProcessor.d.ts +116 -0
  344. package/dist/types/map-provider/geotiff/utils/Triangle.d.ts +5 -0
  345. package/dist/types/map-provider/geotiff/utils/Triangulation.d.ts +94 -0
  346. package/dist/types/map-provider/geotiff/utils/colormap-utils.d.ts +47 -0
  347. package/dist/types/map-provider/geotiff/utils/normalization-utils.d.ts +39 -0
  348. package/dist/types/map-provider/geotiff/utils/sampling-utils.d.ts +13 -0
  349. package/dist/types/map-provider/leaflet/GeoTIFFGridLayer.d.ts +34 -0
  350. package/dist/types/map-provider/leaflet/WCSGridLayer.d.ts +38 -0
  351. package/dist/types/map-provider/leaflet/google-map-tiles-layer.d.ts +73 -0
  352. package/dist/types/map-provider/leaflet/leaflet-helpers.d.ts +6 -0
  353. package/dist/types/map-provider/leaflet/leaflet-provider.d.ts +73 -0
  354. package/dist/types/map-provider/ol/CustomGeoTiff.d.ts +14 -0
  355. package/dist/types/map-provider/ol/openlayers-helper.d.ts +2 -0
  356. package/dist/types/map-provider/ol/openlayers-provider.d.ts +80 -0
  357. package/dist/types/map-provider/provider-factory.d.ts +12 -0
  358. package/dist/types/map-provider/provider-factory.unit.d.ts +1 -0
  359. package/dist/types/namespaces.d.ts +3 -0
  360. package/dist/types/ol-augment.d.ts +3 -0
  361. package/dist/types/ol-override.d.ts +7 -0
  362. package/dist/types/ol.d.ts +10 -0
  363. package/dist/types/stencil-public-runtime.d.ts +1860 -0
  364. package/dist/types/testing/browser-test-utils.d.ts +6 -0
  365. package/dist/types/testing/e2e-testing.d.ts +5 -0
  366. package/dist/types/testing/e2e-utils.d.ts +4 -0
  367. package/dist/types/testing/geotiff-test-server.d.ts +5 -0
  368. package/dist/types/testing/mocks/geostyler-lyrx-parser.d.ts +11 -0
  369. package/dist/types/testing/mocks/geostyler-mapbox-parser.d.ts +11 -0
  370. package/dist/types/testing/mocks/geostyler-qgis-parser.d.ts +11 -0
  371. package/dist/types/testing/mocks/geostyler-sld-parser.d.ts +11 -0
  372. package/dist/types/testing/mocks/geostyler-style.d.ts +5 -0
  373. package/dist/types/testing/setupTests.browser.d.ts +1 -0
  374. package/dist/types/testing/setupTests.stencil.d.ts +1 -0
  375. package/dist/types/testing/setupTests.vitest.d.ts +1 -0
  376. package/dist/types/testing/stencil-testing-wrapper.d.ts +3 -0
  377. package/dist/types/types/color.d.ts +1 -0
  378. package/dist/types/types/cssmode.d.ts +1 -0
  379. package/dist/types/types/flavour.d.ts +1 -0
  380. package/dist/types/types/layerconfig.d.ts +207 -0
  381. package/dist/types/types/lonlat.d.ts +1 -0
  382. package/dist/types/types/mapinitoptions.d.ts +4 -0
  383. package/dist/types/types/mapprovider.d.ts +46 -0
  384. package/dist/types/types/provideroptions.d.ts +8 -0
  385. package/dist/types/types/styleconfig.d.ts +27 -0
  386. package/dist/types/types/styling.d.ts +24 -0
  387. package/dist/types/types/styling.unit.d.ts +1 -0
  388. package/dist/types/types/vmaplayer.d.ts +10 -0
  389. package/dist/types/utils/async-mutex.d.ts +7 -0
  390. package/dist/types/utils/diff.d.ts +64 -0
  391. package/dist/types/utils/diff.unit.d.ts +1 -0
  392. package/dist/types/utils/dom-env.d.ts +5 -0
  393. package/dist/types/utils/dom-env.unit.d.ts +1 -0
  394. package/dist/types/utils/events.d.ts +29 -0
  395. package/dist/types/utils/logger.d.ts +47 -0
  396. package/dist/types/utils/logger.unit.d.ts +1 -0
  397. package/dist/types/utils/messages.d.ts +12 -0
  398. package/dist/types/utils/spatial-utils.d.ts +6 -0
  399. package/dist/types/utils/spatial-utils.unit.d.ts +1 -0
  400. package/dist/types/versions.d.ts +7 -0
  401. package/dist/v-map/index.esm.js +0 -0
  402. package/dist/v-map/p--vVleK-M.js +1 -0
  403. package/dist/v-map/p-09d10db0.entry.js +1 -0
  404. package/dist/v-map/p-5eba6058.entry.js +10 -0
  405. package/dist/v-map/p-6b102336.entry.js +1 -0
  406. package/dist/v-map/p-B-bAcABs.js +1 -0
  407. package/dist/v-map/p-BBpiaTpT.js +1 -0
  408. package/dist/v-map/p-BdijL4Av.js +1 -0
  409. package/dist/v-map/p-Be3r33VF.js +4 -0
  410. package/dist/v-map/p-BeFu0ap4.js +1 -0
  411. package/dist/v-map/p-BxFJezdK.js +1 -0
  412. package/dist/v-map/p-CMKJzsgL.js +1 -0
  413. package/dist/v-map/p-CXfA_q8m.js +1 -0
  414. package/dist/v-map/p-CZqY0yW4.js +1 -0
  415. package/dist/v-map/p-CafTHT9i.js +1 -0
  416. package/dist/v-map/p-DCTHyf58.js +1 -0
  417. package/dist/v-map/p-DQuL1Twl.js +1 -0
  418. package/dist/v-map/p-DR9McdNX.js +1 -0
  419. package/dist/v-map/p-Dckgonw8.js +1 -0
  420. package/dist/v-map/p-DhQAXuA7.js +15 -0
  421. package/dist/v-map/p-DmICdG34.js +7 -0
  422. package/dist/v-map/p-DrOQ9V4h.js +1 -0
  423. package/dist/v-map/p-DvHXtWUg.js +1 -0
  424. package/dist/v-map/p-E-ZsRS8r.js +1 -0
  425. package/dist/v-map/p-MyTSFnEk.js +1 -0
  426. package/dist/v-map/p-RpJarvr_.js +1 -0
  427. package/dist/v-map/p-WaMDUuAz.js +1 -0
  428. package/dist/v-map/p-aa410e64.entry.js +2 -0
  429. package/dist/v-map/p-c21c93fe.entry.js +1 -0
  430. package/dist/v-map/p-jzneDarq.js +2 -0
  431. package/dist/v-map/p-uiIP-taz.js +1 -0
  432. package/dist/v-map/v-map.esm.js +1 -0
  433. package/loader/cdn.js +1 -0
  434. package/loader/index.cjs.js +1 -0
  435. package/loader/index.d.ts +24 -0
  436. package/loader/index.es2017.js +1 -0
  437. package/loader/index.js +2 -0
  438. package/package.json +193 -0
@@ -0,0 +1,1516 @@
1
+ import { w as warn, l as log } from './messages-CMKJzsgL.js';
2
+
3
+ /**
4
+ * ColorMap utilities for GeoTIFF visualization
5
+ * Extracted for testability
6
+ */
7
+ /**
8
+ * Predefined color maps
9
+ */
10
+ const PREDEFINED_COLORMAPS = {
11
+ grayscale: [
12
+ { value: 0.0, color: [0, 0, 0] },
13
+ { value: 1.0, color: [255, 255, 255] },
14
+ ],
15
+ viridis: [
16
+ { value: 0.0, color: [68, 1, 84] },
17
+ { value: 0.25, color: [59, 82, 139] },
18
+ { value: 0.5, color: [33, 145, 140] },
19
+ { value: 0.75, color: [94, 201, 98] },
20
+ { value: 1.0, color: [253, 231, 37] },
21
+ ],
22
+ terrain: [
23
+ { value: 0.0, color: [0, 128, 0] }, // dark green (low)
24
+ { value: 0.25, color: [139, 195, 74] }, // light green
25
+ { value: 0.5, color: [255, 235, 59] }, // yellow
26
+ { value: 0.75, color: [255, 152, 0] }, // orange
27
+ { value: 1.0, color: [255, 255, 255] }, // white (high)
28
+ ],
29
+ turbo: [
30
+ { value: 0.0, color: [48, 18, 59] },
31
+ { value: 0.2, color: [33, 102, 172] },
32
+ { value: 0.4, color: [68, 190, 112] },
33
+ { value: 0.6, color: [253, 231, 37] },
34
+ { value: 0.8, color: [234, 51, 35] },
35
+ { value: 1.0, color: [122, 4, 3] },
36
+ ],
37
+ rainbow: [
38
+ { value: 0.0, color: [148, 0, 211] }, // violet
39
+ { value: 0.2, color: [0, 0, 255] }, // blue
40
+ { value: 0.4, color: [0, 255, 0] }, // green
41
+ { value: 0.6, color: [255, 255, 0] }, // yellow
42
+ { value: 0.8, color: [255, 127, 0] }, // orange
43
+ { value: 1.0, color: [255, 0, 0] }, // red
44
+ ],
45
+ };
46
+ /**
47
+ * Parse a hex color string to RGB array
48
+ * @param hexColor - Hex color string (e.g., "#FF0000" or "#F00")
49
+ * @returns RGB array [r, g, b] with values 0-255
50
+ */
51
+ function parseHexColor(hexColor) {
52
+ let hex = hexColor.trim();
53
+ if (hex.startsWith('#')) {
54
+ hex = hex.slice(1);
55
+ }
56
+ // Handle shorthand hex (#RGB -> #RRGGBB)
57
+ if (hex.length === 3) {
58
+ hex = hex
59
+ .split('')
60
+ .map(c => c + c)
61
+ .join('');
62
+ }
63
+ if (hex.length !== 6) {
64
+ warn(`Invalid hex color: ${hexColor}, using black`);
65
+ return [0, 0, 0];
66
+ }
67
+ const r = parseInt(hex.slice(0, 2), 16);
68
+ const g = parseInt(hex.slice(2, 4), 16);
69
+ const b = parseInt(hex.slice(4, 6), 16);
70
+ if (isNaN(r) || isNaN(g) || isNaN(b)) {
71
+ warn(`Invalid hex color: ${hexColor}, using black`);
72
+ return [0, 0, 0];
73
+ }
74
+ return [r, g, b];
75
+ }
76
+ /**
77
+ * Convert GeoStyler ColorMap to internal ColorStop array
78
+ * @param geoStylerColorMap - GeoStyler ColorMap object
79
+ * @param valueRange - Optional value range [min, max] for normalization
80
+ * @returns Object with ColorStop array and computed range
81
+ */
82
+ function convertGeoStylerColorMap(geoStylerColorMap, valueRange) {
83
+ const entries = geoStylerColorMap.colorMapEntries || [];
84
+ if (entries.length === 0) {
85
+ warn('GeoStyler ColorMap has no entries, using grayscale');
86
+ return { stops: PREDEFINED_COLORMAPS.grayscale };
87
+ }
88
+ // Extract quantity values for normalization
89
+ const quantities = entries
90
+ .map(e => e.quantity)
91
+ .filter((q) => typeof q === 'number');
92
+ let minVal;
93
+ let maxVal;
94
+ if (valueRange) {
95
+ [minVal, maxVal] = valueRange;
96
+ }
97
+ else if (quantities.length > 0) {
98
+ minVal = Math.min(...quantities);
99
+ maxVal = Math.max(...quantities);
100
+ }
101
+ else {
102
+ // No quantities and no valueRange - assume normalized 0-1
103
+ minVal = 0;
104
+ maxVal = 1;
105
+ }
106
+ // Avoid division by zero
107
+ if (maxVal === minVal) {
108
+ maxVal = minVal + 1;
109
+ }
110
+ const stops = entries.map(entry => {
111
+ const quantity = typeof entry.quantity === 'number' ? entry.quantity : 0;
112
+ const normalizedValue = (quantity - minVal) / (maxVal - minVal);
113
+ // Parse color (handle both string and Expression<string>)
114
+ const colorStr = typeof entry.color === 'string' ? entry.color : String(entry.color);
115
+ const color = parseHexColor(colorStr);
116
+ return {
117
+ value: Math.max(0, Math.min(1, normalizedValue)), // Clamp to [0, 1]
118
+ color,
119
+ };
120
+ });
121
+ // Sort by value for binary search
122
+ stops.sort((a, b) => a.value - b.value);
123
+ return {
124
+ stops,
125
+ computedRange: valueRange ? undefined : [minVal, maxVal],
126
+ };
127
+ }
128
+ /**
129
+ * Apply colormap to a normalized value using interpolation
130
+ * @param normalizedValue - Value between 0 and 1
131
+ * @param colorStops - Array of color stops (must be sorted by value)
132
+ * @returns RGB color [r, g, b]
133
+ */
134
+ function applyColorMap(normalizedValue, colorStops) {
135
+ const v = Math.max(0, Math.min(1, normalizedValue));
136
+ if (colorStops.length === 0) {
137
+ return [0, 0, 0]; // Black fallback
138
+ }
139
+ if (colorStops.length === 1) {
140
+ return colorStops[0].color;
141
+ }
142
+ // Binary search for surrounding color stops
143
+ let left = 0;
144
+ let right = colorStops.length - 1;
145
+ // Handle edge cases
146
+ if (v <= colorStops[left].value) {
147
+ return colorStops[left].color;
148
+ }
149
+ if (v >= colorStops[right].value) {
150
+ return colorStops[right].color;
151
+ }
152
+ // Binary search
153
+ while (right - left > 1) {
154
+ const mid = Math.floor((left + right) / 2);
155
+ if (colorStops[mid].value <= v) {
156
+ left = mid;
157
+ }
158
+ else {
159
+ right = mid;
160
+ }
161
+ }
162
+ // Interpolate between left and right
163
+ const lower = colorStops[left];
164
+ const upper = colorStops[right];
165
+ const ratio = (v - lower.value) / (upper.value - lower.value);
166
+ const r = Math.round(lower.color[0] + ratio * (upper.color[0] - lower.color[0]));
167
+ const g = Math.round(lower.color[1] + ratio * (upper.color[1] - lower.color[1]));
168
+ const b = Math.round(lower.color[2] + ratio * (upper.color[2] - lower.color[2]));
169
+ return [r, g, b];
170
+ }
171
+ /**
172
+ * Get ColorStop array from ColorMapName or GeoStyler ColorMap
173
+ * @param colorMap - Predefined name or GeoStyler ColorMap
174
+ * @param valueRange - Optional value range for GeoStyler ColorMap
175
+ * @returns ColorStop array and computed range (if applicable)
176
+ */
177
+ function getColorStops(colorMap, valueRange) {
178
+ if (typeof colorMap === 'string') {
179
+ // Predefined colormap name
180
+ const stops = PREDEFINED_COLORMAPS[colorMap];
181
+ if (!stops) {
182
+ warn(`Unknown colormap: ${colorMap}, using grayscale`);
183
+ return { stops: PREDEFINED_COLORMAPS.grayscale };
184
+ }
185
+ return { stops };
186
+ }
187
+ else {
188
+ // GeoStyler ColorMap
189
+ return convertGeoStylerColorMap(colorMap, valueRange);
190
+ }
191
+ }
192
+
193
+ class AABB2D {
194
+ min;
195
+ max;
196
+ constructor(min, max) {
197
+ this.min = min;
198
+ this.max = max;
199
+ }
200
+ contains(point) {
201
+ return (point.x >= this.min.x &&
202
+ point.x <= this.max.x &&
203
+ point.y >= this.min.y &&
204
+ point.y <= this.max.y);
205
+ }
206
+ static fromTriangle(triangle) {
207
+ const minX = Math.min(triangle.a.x, triangle.b.x, triangle.c.x);
208
+ const minY = Math.min(triangle.a.y, triangle.b.y, triangle.c.y);
209
+ const maxX = Math.max(triangle.a.x, triangle.b.x, triangle.c.x);
210
+ const maxY = Math.max(triangle.a.y, triangle.b.y, triangle.c.y);
211
+ return new AABB2D({ x: minX, y: minY }, { x: maxX, y: maxY });
212
+ }
213
+ static union(a, b) {
214
+ return new AABB2D({ x: Math.min(a.min.x, b.min.x), y: Math.min(a.min.y, b.min.y) }, { x: Math.max(a.max.x, b.max.x), y: Math.max(a.max.y, b.max.y) });
215
+ }
216
+ }
217
+
218
+ class BVHNode2D {
219
+ bbox;
220
+ triangles;
221
+ left;
222
+ right;
223
+ constructor(bbox, triangles = [], left = null, right = null) {
224
+ this.bbox = bbox;
225
+ this.triangles = triangles;
226
+ this.left = left;
227
+ this.right = right;
228
+ }
229
+ static build(triangles, depth = 0, maxDepth = 10) {
230
+ if (triangles.length <= 2 || depth >= maxDepth) {
231
+ let bbox = AABB2D.fromTriangle(triangles[0]);
232
+ for (let i = 1; i < triangles.length; i++) {
233
+ bbox = AABB2D.union(bbox, AABB2D.fromTriangle(triangles[i]));
234
+ }
235
+ return new BVHNode2D(bbox, triangles);
236
+ }
237
+ const centroids = triangles.map(t => ({
238
+ x: (t.a.x + t.b.x + t.c.x) / 3,
239
+ y: (t.a.y + t.b.y + t.c.y) / 3,
240
+ }));
241
+ const { min, max } = centroids.reduce((acc, c) => ({
242
+ min: { x: Math.min(acc.min.x, c.x), y: Math.min(acc.min.y, c.y) },
243
+ max: { x: Math.max(acc.max.x, c.x), y: Math.max(acc.max.y, c.y) },
244
+ }), { min: centroids[0], max: centroids[0] });
245
+ const axis = max.x - min.x > max.y - min.y ? 'x' : 'y';
246
+ centroids.sort((a, b) => a[axis] - b[axis]);
247
+ const mid = Math.floor(centroids.length / 2);
248
+ const leftTriangles = [];
249
+ const rightTriangles = [];
250
+ for (let i = 0; i < triangles.length; i++) {
251
+ (i < mid ? leftTriangles : rightTriangles).push(triangles[i]);
252
+ }
253
+ const left = BVHNode2D.build(leftTriangles, depth + 1, maxDepth);
254
+ const right = BVHNode2D.build(rightTriangles, depth + 1, maxDepth);
255
+ const bbox = AABB2D.union(left.bbox, right.bbox);
256
+ return new BVHNode2D(bbox, [], left, right);
257
+ }
258
+ /**
259
+ * Finds the triangle containing the given point.
260
+ * @param point The point to test.
261
+ * @returns The containing triangle or `null`.
262
+ */
263
+ findContainingTriangle(point) {
264
+ if (!this.bbox.contains(point)) {
265
+ return null;
266
+ }
267
+ if (this.triangles.length > 0) {
268
+ for (const triangle of this.triangles) {
269
+ if (BVHNode2D.punktInDreieck2D(point, triangle)) {
270
+ return triangle;
271
+ }
272
+ }
273
+ return null;
274
+ }
275
+ return (this.left?.findContainingTriangle(point) ||
276
+ this.right?.findContainingTriangle(point) ||
277
+ null);
278
+ }
279
+ static punktInDreieck2D(p, triangle) {
280
+ const { a, b, c } = triangle;
281
+ const v0 = { x: c.x - a.x, y: c.y - a.y };
282
+ const v1 = { x: b.x - a.x, y: b.y - a.y };
283
+ const v2 = { x: p.x - a.x, y: p.y - a.y };
284
+ const dot00 = v0.x * v0.x + v0.y * v0.y;
285
+ const dot01 = v0.x * v1.x + v0.y * v1.y;
286
+ const dot02 = v0.x * v2.x + v0.y * v2.y;
287
+ const dot11 = v1.x * v1.x + v1.y * v1.y;
288
+ const dot12 = v1.x * v2.x + v1.y * v2.y;
289
+ const invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
290
+ const u = (dot11 * dot02 - dot01 * dot12) * invDenom;
291
+ const v = (dot00 * dot12 - dot01 * dot02) * invDenom;
292
+ return u >= 0 && v >= 0 && u + v <= 1;
293
+ //return u >= 0 && v >= 0 && u + v < 1;
294
+ }
295
+ static toTriangle2D(triangle) {
296
+ return {
297
+ a: { x: triangle.target[0][0], y: triangle.target[0][1] },
298
+ b: { x: triangle.target[1][0], y: triangle.target[1][1] },
299
+ c: { x: triangle.target[2][0], y: triangle.target[2][1] },
300
+ triangle: triangle,
301
+ transform: null,
302
+ };
303
+ }
304
+ /**
305
+ * Returns a string representation of the BVH tree structure
306
+ * @param indent - Internal parameter for recursive formatting
307
+ * @returns Formatted string showing tree structure
308
+ */
309
+ toString(indent = '') {
310
+ const isLeaf = this.triangles.length > 0;
311
+ const nodeType = isLeaf ? 'LEAF' : 'NODE';
312
+ const bboxStr = `[${this.bbox.min.x.toFixed(2)}, ${this.bbox.min.y.toFixed(2)}, ${this.bbox.max.x.toFixed(2)}, ${this.bbox.max.y.toFixed(2)}]`;
313
+ let result = `${indent}${nodeType} bbox=${bboxStr}`;
314
+ if (isLeaf) {
315
+ const triArray = this.triangles.map(t2D => t2D.a.x.toFixed(2) +
316
+ ',' +
317
+ t2D.a.y.toFixed(2) +
318
+ ' ' +
319
+ t2D.b.x.toFixed(2) +
320
+ ',' +
321
+ t2D.b.y.toFixed(2) +
322
+ ' ' +
323
+ t2D.c.x.toFixed(2) +
324
+ ',' +
325
+ t2D.c.y.toFixed(2));
326
+ const triArrayStr = triArray.toString();
327
+ result += ` triangles=${this.triangles.length} - ${triArrayStr}`;
328
+ }
329
+ else {
330
+ result += '\n';
331
+ if (this.left) {
332
+ result += `${indent}├─ left:\n${this.left.toString(indent + '│ ')}`;
333
+ }
334
+ if (this.right) {
335
+ result += `${indent}└─ right:\n${this.right.toString(indent + ' ')}`;
336
+ }
337
+ }
338
+ return result;
339
+ }
340
+ /**
341
+ * Get statistics about the BVH tree
342
+ * @returns Object with tree statistics
343
+ */
344
+ getStats() {
345
+ const stats = {
346
+ depth: 1,
347
+ nodeCount: 1,
348
+ leafCount: 0,
349
+ triangleCount: this.triangles.length,
350
+ minTrianglesPerLeaf: Infinity,
351
+ maxTrianglesPerLeaf: 0,
352
+ };
353
+ if (this.triangles.length > 0) {
354
+ // This is a leaf
355
+ stats.leafCount = 1;
356
+ stats.minTrianglesPerLeaf = this.triangles.length;
357
+ stats.maxTrianglesPerLeaf = this.triangles.length;
358
+ }
359
+ else {
360
+ // This is an internal node
361
+ if (this.left) {
362
+ const leftStats = this.left.getStats();
363
+ stats.depth = Math.max(stats.depth, leftStats.depth + 1);
364
+ stats.nodeCount += leftStats.nodeCount;
365
+ stats.leafCount += leftStats.leafCount;
366
+ stats.triangleCount += leftStats.triangleCount;
367
+ stats.minTrianglesPerLeaf = Math.min(stats.minTrianglesPerLeaf, leftStats.minTrianglesPerLeaf);
368
+ stats.maxTrianglesPerLeaf = Math.max(stats.maxTrianglesPerLeaf, leftStats.maxTrianglesPerLeaf);
369
+ }
370
+ if (this.right) {
371
+ const rightStats = this.right.getStats();
372
+ stats.depth = Math.max(stats.depth, rightStats.depth + 1);
373
+ stats.nodeCount += rightStats.nodeCount;
374
+ stats.leafCount += rightStats.leafCount;
375
+ stats.triangleCount += rightStats.triangleCount;
376
+ stats.minTrianglesPerLeaf = Math.min(stats.minTrianglesPerLeaf, rightStats.minTrianglesPerLeaf);
377
+ stats.maxTrianglesPerLeaf = Math.max(stats.maxTrianglesPerLeaf, rightStats.maxTrianglesPerLeaf);
378
+ }
379
+ }
380
+ return stats;
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Triangulation for raster reprojection
386
+ *
387
+ * Based on OpenLayers' triangulation approach for efficient raster reprojection.
388
+ * Instead of transforming every pixel, we:
389
+ * 1. Divide the target extent into triangles
390
+ * 2. Transform only triangle vertices with proj4
391
+ * 3. Use affine transformation to map pixels within each triangle
392
+ *
393
+ * This reduces proj4 calls from ~65,536 per tile to ~50-200 per tile.
394
+ */
395
+ function calculateBounds(sourceRef, resolution, targetExtent, transformFn, step = 10) {
396
+ const [west, south, east, north] = targetExtent;
397
+ let minX = Infinity;
398
+ let minY = Infinity;
399
+ let maxX = -Infinity;
400
+ let maxY = -Infinity;
401
+ let minXTarget = [0, 0];
402
+ let minYTarget = [0, 0];
403
+ let maxXTarget = [0, 0];
404
+ let maxYTarget = [0, 0];
405
+ // Funktion zum Abtasten einer Kante
406
+ const sampleEdge = (start, end, steps) => {
407
+ for (let i = 0; i <= steps; i++) {
408
+ const t = i / steps;
409
+ const x = start[0] + (end[0] - start[0]) * t;
410
+ const y = start[1] + (end[1] - start[1]) * t;
411
+ const target = [x, y];
412
+ const [xSrc, ySrc] = transformFn(target);
413
+ if (xSrc < minX) {
414
+ minX = xSrc;
415
+ minXTarget = target;
416
+ }
417
+ if (ySrc < minY) {
418
+ minY = ySrc;
419
+ minYTarget = target;
420
+ }
421
+ if (xSrc > maxX) {
422
+ maxX = xSrc;
423
+ maxXTarget = target;
424
+ }
425
+ if (ySrc > maxY) {
426
+ maxY = ySrc;
427
+ maxYTarget = target;
428
+ }
429
+ }
430
+ };
431
+ // Abtasten aller vier Kanten
432
+ sampleEdge([west, north], [east, north], step); // Top edge
433
+ sampleEdge([east, north], [east, south], step); // Right edge
434
+ sampleEdge([east, south], [west, south], step); // Bottom edge
435
+ sampleEdge([west, south], [west, north], step); // Left edge
436
+ if (sourceRef != null && resolution != null) {
437
+ const minXPix = Math.floor((minX - sourceRef[0]) / resolution);
438
+ minX = sourceRef[0] + minXPix * resolution;
439
+ const minYPix = Math.floor((minY - sourceRef[1]) / resolution);
440
+ minY = sourceRef[1] + minYPix * resolution;
441
+ const maxXPix = Math.ceil((maxX - sourceRef[0]) / resolution);
442
+ maxX = sourceRef[0] + maxXPix * resolution;
443
+ const maxYPix = Math.ceil((maxY - sourceRef[1]) / resolution);
444
+ maxY = sourceRef[1] + maxYPix * resolution;
445
+ }
446
+ return {
447
+ source: {
448
+ minX,
449
+ minY,
450
+ maxX,
451
+ maxY,
452
+ },
453
+ target: {
454
+ minX: minXTarget[0],
455
+ minY: minYTarget[1],
456
+ maxX: maxXTarget[0],
457
+ maxY: maxYTarget[1],
458
+ },
459
+ };
460
+ }
461
+ const MAX_SUBDIVISION = 10;
462
+ /**
463
+ * Class for triangulation of the given target extent
464
+ * Used for determining source data and the reprojection itself
465
+ */
466
+ class Triangulation {
467
+ triangles_ = [];
468
+ transformFn_;
469
+ errorThresholdSquared_;
470
+ bvh_ = null;
471
+ bounds;
472
+ /**
473
+ * @param transformFn - Function that transforms [x, y] from target to source projection
474
+ * @param targetExtent - [west, south, east, north] in target projection
475
+ * @param errorThreshold - Maximum allowed error in pixels (default: 0.5)
476
+ */
477
+ constructor(transformFn, targetExtent, errorThreshold = 0.5, sourceRef = null, resolution = null, step = 10) {
478
+ this.transformFn_ = transformFn;
479
+ this.errorThresholdSquared_ = errorThreshold * errorThreshold;
480
+ const [west, south, east, north] = targetExtent;
481
+ // Transform the four corners
482
+ const a = [west, north]; // top-left
483
+ const b = [east, north]; // top-right
484
+ const c = [east, south]; // bottom-right
485
+ const d = [west, south]; // bottom-left
486
+ const extBounds = calculateBounds(sourceRef, resolution, targetExtent, this.transformFn_, step);
487
+ // const aSrc = this.transformFn_(a);
488
+ // const bSrc = this.transformFn_(b);
489
+ // const cSrc = this.transformFn_(c);
490
+ // const dSrc = this.transformFn_(d);
491
+ const aSrc = [
492
+ extBounds.source.minX,
493
+ extBounds.source.maxY,
494
+ ]; // top-left
495
+ const bSrc = [
496
+ extBounds.source.maxX,
497
+ extBounds.source.maxY,
498
+ ]; // top-right
499
+ const cSrc = [
500
+ extBounds.source.maxX,
501
+ extBounds.source.minY,
502
+ ]; // bottom-right
503
+ const dSrc = [
504
+ extBounds.source.minX,
505
+ extBounds.source.minY,
506
+ ]; // bottom-left
507
+ this.bounds = extBounds.source;
508
+ this.addQuad_(a, b, c, d, aSrc, bSrc, cSrc, dSrc, MAX_SUBDIVISION);
509
+ }
510
+ getBounds() {
511
+ return this.bounds;
512
+ }
513
+ /**
514
+ * Recursively subdivide a quadrilateral if needed
515
+ */
516
+ addQuad_(a, b, c, d, aSrc, bSrc, cSrc, dSrc, maxSubdivision) {
517
+ let needsSubdivision = false;
518
+ // Check if we need to subdivide based on error threshold
519
+ if (maxSubdivision > 0) {
520
+ // Calculate midpoints of all edges (linear interpolation in target space)
521
+ const abTarget = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];
522
+ const bcTarget = [(b[0] + c[0]) / 2, (b[1] + c[1]) / 2];
523
+ const cdTarget = [(c[0] + d[0]) / 2, (c[1] + d[1]) / 2];
524
+ const daTarget = [(d[0] + a[0]) / 2, (d[1] + a[1]) / 2];
525
+ // Transform midpoints to source space
526
+ const abSrc = this.transformFn_(abTarget);
527
+ const bcSrc = this.transformFn_(bcTarget);
528
+ const cdSrc = this.transformFn_(cdTarget);
529
+ const daSrc = this.transformFn_(daTarget);
530
+ // Calculate expected midpoints (linear interpolation in source space)
531
+ const abExpected = [
532
+ (aSrc[0] + bSrc[0]) / 2,
533
+ (aSrc[1] + bSrc[1]) / 2,
534
+ ];
535
+ const bcExpected = [
536
+ (bSrc[0] + cSrc[0]) / 2,
537
+ (bSrc[1] + cSrc[1]) / 2,
538
+ ];
539
+ const cdExpected = [
540
+ (cSrc[0] + dSrc[0]) / 2,
541
+ (cSrc[1] + dSrc[1]) / 2,
542
+ ];
543
+ const daExpected = [
544
+ (dSrc[0] + aSrc[0]) / 2,
545
+ (dSrc[1] + aSrc[1]) / 2,
546
+ ];
547
+ // Calculate squared errors
548
+ const abError = this.getSquaredError_(abSrc, abExpected);
549
+ const bcError = this.getSquaredError_(bcSrc, bcExpected);
550
+ const cdError = this.getSquaredError_(cdSrc, cdExpected);
551
+ const daError = this.getSquaredError_(daSrc, daExpected);
552
+ // Check if any edge exceeds error threshold
553
+ if (abError > this.errorThresholdSquared_ ||
554
+ bcError > this.errorThresholdSquared_ ||
555
+ cdError > this.errorThresholdSquared_ ||
556
+ daError > this.errorThresholdSquared_) {
557
+ needsSubdivision = true;
558
+ }
559
+ }
560
+ if (needsSubdivision) {
561
+ // Subdivide into 4 smaller quads
562
+ // Calculate center point
563
+ const eTarget = [
564
+ (a[0] + b[0] + c[0] + d[0]) / 4,
565
+ (a[1] + b[1] + c[1] + d[1]) / 4,
566
+ ];
567
+ const eSrc = this.transformFn_(eTarget);
568
+ // Calculate edge midpoints
569
+ const abTarget = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];
570
+ const bcTarget = [(b[0] + c[0]) / 2, (b[1] + c[1]) / 2];
571
+ const cdTarget = [(c[0] + d[0]) / 2, (c[1] + d[1]) / 2];
572
+ const daTarget = [(d[0] + a[0]) / 2, (d[1] + a[1]) / 2];
573
+ const abSrc = this.transformFn_(abTarget);
574
+ const bcSrc = this.transformFn_(bcTarget);
575
+ const cdSrc = this.transformFn_(cdTarget);
576
+ const daSrc = this.transformFn_(daTarget);
577
+ const newMaxSubdivision = maxSubdivision - 1;
578
+ // Recursively add 4 sub-quads
579
+ this.addQuad_(a, abTarget, eTarget, daTarget, aSrc, abSrc, eSrc, daSrc, newMaxSubdivision);
580
+ this.addQuad_(abTarget, b, bcTarget, eTarget, abSrc, bSrc, bcSrc, eSrc, newMaxSubdivision);
581
+ this.addQuad_(eTarget, bcTarget, c, cdTarget, eSrc, bcSrc, cSrc, cdSrc, newMaxSubdivision);
582
+ this.addQuad_(daTarget, eTarget, cdTarget, d, daSrc, eSrc, cdSrc, dSrc, newMaxSubdivision);
583
+ }
584
+ else {
585
+ // No subdivision needed - add two triangles for this quad
586
+ // Triangle 1: a-b-d
587
+ this.addTriangle_(a, b, d, aSrc, bSrc, dSrc);
588
+ // Triangle 2: b-c-d
589
+ this.addTriangle_(b, c, d, bSrc, cSrc, dSrc);
590
+ }
591
+ }
592
+ /**
593
+ * Add a single triangle
594
+ */
595
+ addTriangle_(a, b, c, aSrc, bSrc, cSrc) {
596
+ // Check for non-finite coordinates
597
+ if (!isFinite(aSrc[0]) ||
598
+ !isFinite(aSrc[1]) ||
599
+ !isFinite(bSrc[0]) ||
600
+ !isFinite(bSrc[1]) ||
601
+ !isFinite(cSrc[0]) ||
602
+ !isFinite(cSrc[1])) {
603
+ return; // Skip invalid triangles
604
+ }
605
+ this.triangles_.push({
606
+ source: [aSrc, bSrc, cSrc],
607
+ target: [a, b, c],
608
+ });
609
+ }
610
+ /**
611
+ * Calculate squared error between two points
612
+ */
613
+ getSquaredError_(actual, expected) {
614
+ const dx = actual[0] - expected[0];
615
+ const dy = actual[1] - expected[1];
616
+ return dx * dx + dy * dy;
617
+ }
618
+ /**
619
+ * Get all triangles
620
+ */
621
+ getTriangles() {
622
+ return this.triangles_;
623
+ }
624
+ /**
625
+ * Calculate the bounding extent of all source coordinates
626
+ */
627
+ calculateSourceExtent() {
628
+ if (this.triangles_.length === 0) {
629
+ return null;
630
+ }
631
+ let minX = Infinity;
632
+ let minY = Infinity;
633
+ let maxX = -Infinity;
634
+ let maxY = -Infinity;
635
+ for (const triangle of this.triangles_) {
636
+ for (const [x, y] of triangle.source) {
637
+ if (x < minX)
638
+ minX = x;
639
+ if (x > maxX)
640
+ maxX = x;
641
+ if (y < minY)
642
+ minY = y;
643
+ if (y > maxY)
644
+ maxY = y;
645
+ }
646
+ }
647
+ return [minX, minY, maxX, maxY];
648
+ }
649
+ buildBVH() {
650
+ const triangles2D = this.triangles_.map(BVHNode2D.toTriangle2D);
651
+ this.bvh_ = BVHNode2D.build(triangles2D);
652
+ }
653
+ findSourceTriangleForTargetPoint(point, extraTri = null) {
654
+ if (!this.bvh_)
655
+ this.buildBVH();
656
+ const point2D = { x: point[0], y: point[1] };
657
+ if (extraTri?.tri &&
658
+ BVHNode2D.punktInDreieck2D(point2D, BVHNode2D.toTriangle2D(extraTri.tri))) {
659
+ return extraTri;
660
+ }
661
+ const result = this.bvh_.findContainingTriangle(point2D);
662
+ if (result && !result.transform) {
663
+ result.transform = this.calculateAffineTransform(result.triangle);
664
+ }
665
+ return result
666
+ ? { tri: result.triangle, transform: result.transform }
667
+ : null;
668
+ }
669
+ /**
670
+ * Calculate affine transformation matrix for a triangle
671
+ * Maps from target triangle to source triangle
672
+ */
673
+ calculateAffineTransform(triangle) {
674
+ const [[x0t, y0t], [x1t, y1t], [x2t, y2t]] = triangle.target;
675
+ const [[x0s, y0s], [x1s, y1s], [x2s, y2s]] = triangle.source;
676
+ // Solve for affine transformation: [xs, ys] = [a*xt + b*yt + c, d*xt + e*yt + f]
677
+ // Using the three triangle vertices
678
+ const det = (x1t - x0t) * (y2t - y0t) - (x2t - x0t) * (y1t - y0t);
679
+ if (Math.abs(det) < 1e-10) {
680
+ // Degenerate triangle - return identity-like transform
681
+ return { a: 1, b: 0, c: x0s, d: 0, e: 1, f: y0s };
682
+ }
683
+ const a = ((x1s - x0s) * (y2t - y0t) - (x2s - x0s) * (y1t - y0t)) / det;
684
+ const b = ((x2s - x0s) * (x1t - x0t) - (x1s - x0s) * (x2t - x0t)) / det;
685
+ const c = x0s - a * x0t - b * y0t;
686
+ const d = ((y1s - y0s) * (y2t - y0t) - (y2s - y0s) * (y1t - y0t)) / det;
687
+ const e = ((y2s - y0s) * (x1t - x0t) - (y1s - y0s) * (x2t - x0t)) / det;
688
+ const f = y0s - d * x0t - e * y0t;
689
+ return { a, b, c, d, e, f };
690
+ }
691
+ // ============================================================================
692
+ // REPROJECTION METHODS
693
+ // ============================================================================
694
+ /**
695
+ * Apply affine transformation to a point
696
+ */
697
+ applyAffineTransform(x, y, transform) {
698
+ return [
699
+ transform.a * x + transform.b * y + transform.c,
700
+ transform.d * x + transform.e * y + transform.f,
701
+ ];
702
+ }
703
+ }
704
+
705
+ /**
706
+ * Normalization utilities for raster data
707
+ * Handles conversion of different TypedArray types to normalized 0-255 range
708
+ */
709
+ /**
710
+ * Normalize a raw value to 0-255 range based on array type
711
+ * @param rawValue - The raw value from the raster
712
+ * @param arrayType - The TypedArray type name
713
+ * @returns Normalized value 0-255
714
+ */
715
+ function normalizeValue(rawValue, arrayType) {
716
+ switch (arrayType) {
717
+ case 'Uint8Array':
718
+ return rawValue; // Already 0-255
719
+ case 'Uint16Array':
720
+ // 0-65535 → 0-255
721
+ return Math.round((rawValue / 65535) * 255);
722
+ case 'Int16Array':
723
+ // -32768-32767 → 0-255
724
+ return Math.round(((rawValue + 32768) / 65535) * 255);
725
+ case 'Uint32Array':
726
+ // 0-4294967295 → 0-255
727
+ return Math.round((rawValue / 4294967295) * 255);
728
+ case 'Int32Array':
729
+ // -2147483648-2147483647 → 0-255
730
+ return Math.round(((rawValue + 2147483648) / 4294967295) * 255);
731
+ case 'Float32Array':
732
+ case 'Float64Array':
733
+ // Assume 0.0-1.0 range for Float arrays (common for normalized data)
734
+ // Clamp to [0, 1] first
735
+ const clamped = Math.max(0, Math.min(1, rawValue));
736
+ return Math.round(clamped * 255);
737
+ default:
738
+ warn(`Unknown array type: ${arrayType}, treating as Uint8`);
739
+ return rawValue;
740
+ }
741
+ }
742
+ /**
743
+ * Normalize a raw value to 0-1 range for colormap application
744
+ * @param rawValue - The raw value from the raster
745
+ * @param valueRange - Optional [min, max] range. If not provided, assumes normalized data.
746
+ * @returns Normalized value 0-1
747
+ */
748
+ function normalizeToColorMapRange(rawValue, valueRange) {
749
+ {
750
+ // Assume already normalized or single-value range
751
+ return Math.max(0, Math.min(1, rawValue));
752
+ }
753
+ }
754
+
755
+ /**
756
+ * Nearest-Neighbor Sampling with window-based reading and multi-band support
757
+ * Returns [R, G, B, A] values (0-255)
758
+ */
759
+ function sampleNearest(x, y, rasterBands, arrayType, width, height, offsetX, offsetY, colorStops) {
760
+ const px = Math.round(x) - offsetX;
761
+ const py = Math.round(y) - offsetY;
762
+ if (px < 0 || px >= width || py < 0 || py >= height) {
763
+ return null;
764
+ }
765
+ const idx = py * width + px;
766
+ const bandCount = rasterBands.length;
767
+ if (bandCount === 1) {
768
+ // Grayscale - apply colormap if specified
769
+ const rawValue = rasterBands[0][idx];
770
+ if (colorStops) {
771
+ // Apply colormap (only for Float types or when colorStops provided)
772
+ const normalizedValue = normalizeToColorMapRange(rawValue);
773
+ const [r, g, b] = applyColorMap(normalizedValue, colorStops);
774
+ return [r, g, b, 255];
775
+ }
776
+ else {
777
+ // Regular grayscale normalization
778
+ const gray = normalizeValue(rawValue, arrayType);
779
+ return [gray, gray, gray, 255];
780
+ }
781
+ }
782
+ else if (bandCount === 3) {
783
+ // RGB
784
+ const r = normalizeValue(rasterBands[0][idx], arrayType);
785
+ const g = normalizeValue(rasterBands[1][idx], arrayType);
786
+ const b = normalizeValue(rasterBands[2][idx], arrayType);
787
+ return [r, g, b, 255];
788
+ }
789
+ else if (bandCount >= 4) {
790
+ // RGBA
791
+ const r = normalizeValue(rasterBands[0][idx], arrayType);
792
+ const g = normalizeValue(rasterBands[1][idx], arrayType);
793
+ const b = normalizeValue(rasterBands[2][idx], arrayType);
794
+ const a = normalizeValue(rasterBands[3][idx], arrayType);
795
+ return [r, g, b, a];
796
+ }
797
+ return null;
798
+ }
799
+ /**
800
+ * Bilinear Interpolation with window-based reading and multi-band support
801
+ * Returns [R, G, B, A] values (0-255)
802
+ */
803
+ function sampleBilinear(x, y, rasterBands, arrayType, width, height, offsetX, offsetY, colorStops) {
804
+ const localX = x - offsetX;
805
+ const localY = y - offsetY;
806
+ // Bounds-Check
807
+ if (localX < 0 ||
808
+ localX >= width - 1 ||
809
+ localY < 0 ||
810
+ localY >= height - 1) {
811
+ return null;
812
+ }
813
+ // Bilineare Interpolation
814
+ const x0 = Math.floor(localX);
815
+ const x1 = Math.ceil(localX);
816
+ const y0 = Math.floor(localY);
817
+ const y1 = Math.ceil(localY);
818
+ const fx = localX - x0;
819
+ const fy = localY - y0;
820
+ const bandCount = rasterBands.length;
821
+ const result = [0, 0, 0, 255];
822
+ if (bandCount === 1) {
823
+ // Grayscale - interpolate first, then apply colormap
824
+ const band = rasterBands[0];
825
+ const v00 = band[y0 * width + x0];
826
+ const v10 = band[y0 * width + x1];
827
+ const v01 = band[y1 * width + x0];
828
+ const v11 = band[y1 * width + x1];
829
+ const v0 = v00 * (1 - fx) + v10 * fx;
830
+ const v1 = v01 * (1 - fx) + v11 * fx;
831
+ const interpolated = v0 * (1 - fy) + v1 * fy;
832
+ if (colorStops) {
833
+ // Apply colormap (only for Float types or when colorStops provided)
834
+ const normalizedValue = normalizeToColorMapRange(interpolated);
835
+ const [r, g, b] = applyColorMap(normalizedValue, colorStops);
836
+ return [r, g, b, 255];
837
+ }
838
+ else {
839
+ // Regular grayscale normalization
840
+ const gray = normalizeValue(interpolated, arrayType);
841
+ return [gray, gray, gray, 255];
842
+ }
843
+ }
844
+ else {
845
+ // RGB/RGBA - interpolate each band
846
+ const bandsToProcess = Math.min(bandCount, 4);
847
+ for (let b = 0; b < bandsToProcess; b++) {
848
+ const band = rasterBands[b];
849
+ const v00 = band[y0 * width + x0];
850
+ const v10 = band[y0 * width + x1];
851
+ const v01 = band[y1 * width + x0];
852
+ const v11 = band[y1 * width + x1];
853
+ const v0 = v00 * (1 - fx) + v10 * fx;
854
+ const v1 = v01 * (1 - fx) + v11 * fx;
855
+ const interpolated = v0 * (1 - fy) + v1 * fy;
856
+ result[b] = normalizeValue(interpolated, arrayType);
857
+ }
858
+ }
859
+ return result;
860
+ }
861
+
862
+ /**
863
+ * Processes GeoTIFF tiles with triangulation-based reprojection
864
+ *
865
+ * This class encapsulates the tile rendering logic using triangulation
866
+ * for efficient reprojection from arbitrary source projections to Web Mercator.
867
+ */
868
+ class GeoTIFFTileProcessor {
869
+ // Configuration
870
+ config;
871
+ worldSize = 40075016.686; // Earth circumference in meters (Web Mercator)
872
+ // Global triangulation for the entire image (created once)
873
+ globalTriangulation;
874
+ constructor(config) {
875
+ this.config = config;
876
+ if (config.worldSize) {
877
+ this.worldSize = config.worldSize;
878
+ }
879
+ }
880
+ /**
881
+ * Create global triangulation for the entire GeoTIFF image
882
+ * This is called once to avoid recreating triangulation for every tile
883
+ */
884
+ createGlobalTriangulation() {
885
+ const startTime = performance.now();
886
+ const [srcWest, srcSouth, srcEast, srcNorth] = this.config.sourceBounds;
887
+ // Transform source corners to target projection (Mercator)
888
+ const transformFnToProj = (coord) => {
889
+ return this.config.transformSourceMapToViewFn(coord);
890
+ };
891
+ const { source: bounds } = calculateBounds(null, null, [srcWest, srcSouth, srcEast, srcNorth], transformFnToProj);
892
+ const mercatorBounds = [
893
+ bounds.minX,
894
+ bounds.minY,
895
+ bounds.maxX,
896
+ bounds.maxY,
897
+ ];
898
+ log('Creating global triangulation for bounds:', {
899
+ source: this.config.sourceBounds,
900
+ mercator: mercatorBounds,
901
+ });
902
+ // Inverse transformation: from target (Mercator) back to source
903
+ const inverseTransformFn = (coord) => {
904
+ return this.config.transformViewToSourceMapFn(coord);
905
+ };
906
+ // Use adaptive error threshold based on pixel resolution
907
+ const errorThreshold = this.config.resolution / 2.0;
908
+ const step = Math.min(10, Math.max(this.config.imageWidth, this.config.imageHeight) / 256);
909
+ this.globalTriangulation = new Triangulation(inverseTransformFn, mercatorBounds, errorThreshold, this.config.sourceRef, this.config.resolution, step);
910
+ // Force indexing
911
+ this.globalTriangulation.findSourceTriangleForTargetPoint([0, 0]);
912
+ const triangles = this.globalTriangulation.getTriangles();
913
+ log(`Global triangulation created: ${triangles.length} triangles in ${(performance.now() - startTime).toFixed(2)}ms`);
914
+ }
915
+ /**
916
+ * Get the global triangulation (may be undefined if not created yet)
917
+ */
918
+ getGlobalTriangulation() {
919
+ return this.globalTriangulation;
920
+ }
921
+ /**
922
+ * Normalize terrain samples so mesh generation does not create spikes
923
+ * for nodata or otherwise invalid height values.
924
+ */
925
+ sanitizeElevationValue(value) {
926
+ if (!Number.isFinite(value)) {
927
+ return 0;
928
+ }
929
+ if (this.config.noDataValue !== undefined &&
930
+ value === this.config.noDataValue) {
931
+ return 0;
932
+ }
933
+ return value;
934
+ }
935
+ /**
936
+ * Calculate tile size in meters for a given zoom level
937
+ */
938
+ getTileSizeInMeter(z) {
939
+ return this.worldSize / Math.pow(2, z);
940
+ }
941
+ /**
942
+ * Convert tile coordinates to View projection bounds
943
+ * For Web Mercator (deck.gl/Leaflet/Cesium): returns bounds in meters
944
+ * Note: This assumes Web Mercator tiling scheme. Override for other projections.
945
+ */
946
+ getTileBounds(x, y, z) {
947
+ const tileSize = this.getTileSizeInMeter(z);
948
+ const west = -this.worldSize / 2 + x * tileSize;
949
+ const north = this.worldSize / 2 - y * tileSize;
950
+ const east = west + tileSize;
951
+ const south = north - tileSize;
952
+ return [west, south, east, north];
953
+ }
954
+ /**
955
+ * Select best overview image based on zoom level
956
+ */
957
+ selectOverviewImage(z, tileSize) {
958
+ const baseResolution = this.config.baseImage.getResolution()[0];
959
+ if (!this.config.overviewImages ||
960
+ this.config.overviewImages.length === 0) {
961
+ return {
962
+ bestImage: this.config.baseImage,
963
+ bestResolution: baseResolution,
964
+ imageLevel: 0,
965
+ };
966
+ }
967
+ const tileSizeInMeter = this.getTileSizeInMeter(z);
968
+ const tileResolution = tileSizeInMeter / tileSize;
969
+ // Check base image and all overviews
970
+ const allImages = [this.config.baseImage, ...this.config.overviewImages];
971
+ const maxResImage = allImages[this.config.overviewImages.length];
972
+ const maxResolution = baseResolution * Math.pow(2, this.config.overviewImages.length);
973
+ let imageLevel = this.config.overviewImages.length;
974
+ let bestResolution = maxResolution;
975
+ let bestImage = maxResImage;
976
+ let levelCounter = 0;
977
+ let resolution = baseResolution;
978
+ for (const img of allImages) {
979
+ const ratio = tileResolution / (resolution * 2.0);
980
+ if (ratio <= 1.0) {
981
+ bestImage = img;
982
+ bestResolution = resolution;
983
+ imageLevel = levelCounter;
984
+ break;
985
+ }
986
+ levelCounter++;
987
+ resolution = resolution * 2;
988
+ }
989
+ return { bestImage, bestResolution, imageLevel };
990
+ }
991
+ /**
992
+ * Calculate source bounds for a tile after transformation
993
+ * @param viewBounds - Tile bounds in View projection
994
+ */
995
+ calculateTileSourceBounds(viewBounds) {
996
+ const [viewWest, viewSouth, viewEast, viewNorth] = viewBounds;
997
+ const { source: bounds } = calculateBounds(this.config.sourceRef, this.config.resolution, [viewWest, viewSouth, viewEast, viewNorth], this.config.transformViewToSourceMapFn);
998
+ // Transform tile corners from View to Source projection
999
+ const sw = this.config.transformViewToSourceMapFn([viewWest, viewSouth]);
1000
+ const ne = this.config.transformViewToSourceMapFn([viewEast, viewNorth]);
1001
+ const nw = this.config.transformViewToSourceMapFn([viewWest, viewNorth]);
1002
+ const se = this.config.transformViewToSourceMapFn([viewEast, viewSouth]);
1003
+ // Calculate bounding box from transformed corners
1004
+ const tileSrcWest = Math.min(bounds.minX, sw[0], ne[0], nw[0], se[0]);
1005
+ const tileSrcEast = Math.max(bounds.maxX, sw[0], ne[0], nw[0], se[0]);
1006
+ const tileSrcSouth = Math.min(bounds.minY, sw[1], ne[1], nw[1], se[1]);
1007
+ const tileSrcNorth = Math.max(bounds.maxY, sw[1], ne[1], nw[1], se[1]);
1008
+ return { tileSrcWest, tileSrcEast, tileSrcSouth, tileSrcNorth };
1009
+ }
1010
+ /**
1011
+ * Calculate pixel window for reading from GeoTIFF
1012
+ */
1013
+ calculateReadWindow(tileSrcBounds, ovWidth, ovHeight) {
1014
+ const [srcWest, srcSouth, srcEast, srcNorth] = this.config.sourceBounds;
1015
+ const srcWidth = srcEast - srcWest;
1016
+ const srcHeight = srcNorth - srcSouth;
1017
+ const { tileSrcWest, tileSrcEast, tileSrcSouth, tileSrcNorth } = tileSrcBounds;
1018
+ // Calculate pixel window for this tile area
1019
+ const pixelXMin = Math.floor(((tileSrcWest - srcWest) / srcWidth) * ovWidth);
1020
+ const pixelXMax = Math.ceil(((tileSrcEast - srcWest) / srcWidth) * ovWidth);
1021
+ const pixelYMin = Math.floor(((srcNorth - tileSrcNorth) / srcHeight) * ovHeight);
1022
+ const pixelYMax = Math.ceil(((srcNorth - tileSrcSouth) / srcHeight) * ovHeight);
1023
+ // Bounds check with 2-pixel padding
1024
+ const readXMin = Math.min(ovWidth, Math.max(0, pixelXMin - 2));
1025
+ const readXMax = Math.max(0, Math.min(ovWidth, pixelXMax + 2));
1026
+ const readYMin = Math.min(ovHeight, Math.max(0, pixelYMin - 2));
1027
+ const readYMax = Math.max(0, Math.min(ovHeight, pixelYMax + 2));
1028
+ const readWidth = readXMax - readXMin;
1029
+ const readHeight = readYMax - readYMin;
1030
+ if (readWidth <= 0 || readHeight <= 0) {
1031
+ warn('Invalid read window for tile', {
1032
+ readXMin,
1033
+ readXMax,
1034
+ readYMin,
1035
+ readYMax,
1036
+ ovWidth,
1037
+ ovHeight,
1038
+ });
1039
+ return null;
1040
+ }
1041
+ return {
1042
+ readXMin,
1043
+ readXMax,
1044
+ readYMin,
1045
+ readYMax,
1046
+ readWidth,
1047
+ readHeight,
1048
+ };
1049
+ }
1050
+ /**
1051
+ * Load and convert raster data from GeoTIFF image
1052
+ */
1053
+ async loadAndConvertRasterData(image, readWindow) {
1054
+ const { readXMin, readYMin, readXMax, readYMax } = readWindow;
1055
+ let rasters = null;
1056
+ let lasterr = null;
1057
+ for (let i = 0; i <= 2; i++) {
1058
+ try {
1059
+ // Read only the needed area from GeoTIFF (COG-optimized!)
1060
+ rasters = await image.readRasters({
1061
+ window: [readXMin, readYMin, readXMax, readYMax],
1062
+ });
1063
+ }
1064
+ catch (err) {
1065
+ // warn('Error - readRasters - read window: ', readWindow);
1066
+ lasterr = err;
1067
+ }
1068
+ if (rasters != null) {
1069
+ lasterr = null;
1070
+ break;
1071
+ }
1072
+ }
1073
+ if (lasterr != null) {
1074
+ log(lasterr);
1075
+ warn('Error - readRasters - read window: ', readWindow);
1076
+ throw lasterr;
1077
+ }
1078
+ // Convert to TypedArray array and detect type
1079
+ const rasterBands = [];
1080
+ let arrayType = '';
1081
+ for (let i = 0; i < rasters.length; i++) {
1082
+ const raster = rasters[i];
1083
+ if (typeof raster === 'number') {
1084
+ warn('Unexpected number in rasters array');
1085
+ continue;
1086
+ }
1087
+ rasterBands.push(raster);
1088
+ if (i === 0) {
1089
+ arrayType = raster.constructor.name;
1090
+ }
1091
+ }
1092
+ return { rasterBands, arrayType };
1093
+ }
1094
+ /**
1095
+ * Render tile pixels using triangulation-based reprojection
1096
+ */
1097
+ renderTilePixels(params) {
1098
+ const { sampleSize, mercatorBounds, triangulation, rasterBands, arrayType, readWindow, ovWidth, ovHeight, resampleMethod, colorStops, } = params;
1099
+ const [mercWest, mercSouth, mercEast, mercNorth] = mercatorBounds;
1100
+ const [srcWest, srcSouth, srcEast, srcNorth] = this.config.sourceBounds;
1101
+ const srcWidth = srcEast - srcWest;
1102
+ const srcHeight = srcNorth - srcSouth;
1103
+ const outputData = new Uint8ClampedArray(sampleSize * sampleSize * 4); // RGBA
1104
+ let tri = null;
1105
+ for (let py = 0; py < sampleSize; py++) {
1106
+ for (let px = 0; px < sampleSize; px++) {
1107
+ const idx = (py * sampleSize + px) * 4; // RGBA index
1108
+ // Pixel position in Mercator
1109
+ const mercX = mercWest + (px / sampleSize) * (mercEast - mercWest);
1110
+ const mercY = mercNorth - (py / sampleSize) * (mercNorth - mercSouth);
1111
+ // Find triangle containing this pixel
1112
+ const targetPoint = [mercX, mercY];
1113
+ tri = triangulation.findSourceTriangleForTargetPoint(targetPoint, tri);
1114
+ if (tri) {
1115
+ // Transform using affine transformation
1116
+ const [srcX, srcY] = triangulation.applyAffineTransform(mercX, mercY, tri.transform);
1117
+ // Check if point is within source bounds
1118
+ if (srcX < srcWest ||
1119
+ srcX > srcEast ||
1120
+ srcY < srcSouth ||
1121
+ srcY > srcNorth) {
1122
+ // Outside bounds - transparent
1123
+ outputData[idx] = 0;
1124
+ outputData[idx + 1] = 0;
1125
+ outputData[idx + 2] = 0;
1126
+ outputData[idx + 3] = 0;
1127
+ }
1128
+ else {
1129
+ // Convert source coordinates to pixel coordinates (in overview image)
1130
+ const imgX = ((srcX - srcWest) / srcWidth) * ovWidth;
1131
+ const imgY = ((srcNorth - srcY) / srcHeight) * ovHeight;
1132
+ // Sample pixel from source raster
1133
+ const rgba = resampleMethod === 'near'
1134
+ ? sampleNearest(imgX, imgY, rasterBands, arrayType, readWindow.readWidth, readWindow.readHeight, readWindow.readXMin, readWindow.readYMin, colorStops)
1135
+ : sampleBilinear(imgX, imgY, rasterBands, arrayType, readWindow.readWidth, readWindow.readHeight, readWindow.readXMin, readWindow.readYMin, colorStops);
1136
+ if (rgba) {
1137
+ outputData[idx] = rgba[0];
1138
+ outputData[idx + 1] = rgba[1];
1139
+ outputData[idx + 2] = rgba[2];
1140
+ outputData[idx + 3] = rgba[3];
1141
+ }
1142
+ else {
1143
+ // No data
1144
+ outputData[idx] = 0;
1145
+ outputData[idx + 1] = 0;
1146
+ outputData[idx + 2] = 0;
1147
+ outputData[idx + 3] = 0;
1148
+ }
1149
+ }
1150
+ }
1151
+ else {
1152
+ // Pixel not in any triangle (should not happen)
1153
+ outputData[idx] = 0;
1154
+ outputData[idx + 1] = 0;
1155
+ outputData[idx + 2] = 0;
1156
+ outputData[idx + 3] = 0;
1157
+ }
1158
+ }
1159
+ }
1160
+ return outputData;
1161
+ }
1162
+ /**
1163
+ * Check if tile intersects with GeoTIFF source bounds
1164
+ * @param viewBounds - Tile bounds in View projection (e.g., Web Mercator for deck.gl/Leaflet/Cesium)
1165
+ */
1166
+ tileIntersectsSource(viewBounds) {
1167
+ const [viewWest, viewSouth, viewEast, viewNorth] = viewBounds;
1168
+ const [srcWest, srcSouth, srcEast, srcNorth] = this.config.sourceBounds;
1169
+ // Transform tile corners from View to Source projection
1170
+ const sw = this.config.transformViewToSourceMapFn([viewWest, viewSouth]);
1171
+ const ne = this.config.transformViewToSourceMapFn([viewEast, viewNorth]);
1172
+ const nw = this.config.transformViewToSourceMapFn([viewWest, viewNorth]);
1173
+ const se = this.config.transformViewToSourceMapFn([viewEast, viewSouth]);
1174
+ // Calculate bounding box of transformed tile in source projection
1175
+ const tileMinX = Math.min(sw[0], ne[0], nw[0], se[0]);
1176
+ const tileMaxX = Math.max(sw[0], ne[0], nw[0], se[0]);
1177
+ const tileMinY = Math.min(sw[1], ne[1], nw[1], se[1]);
1178
+ const tileMaxY = Math.max(sw[1], ne[1], nw[1], se[1]);
1179
+ // Check for intersection
1180
+ const intersects = tileMaxX >= srcWest &&
1181
+ tileMinX <= srcEast &&
1182
+ tileMaxY >= srcSouth &&
1183
+ tileMinY <= srcNorth;
1184
+ return intersects;
1185
+ }
1186
+ /**
1187
+ * Generate tile data with triangulation-based reprojection
1188
+ *
1189
+ * This is the main method that orchestrates the entire tile rendering process.
1190
+ */
1191
+ async getTileData(params) {
1192
+ const { x, y, z, tileSize, resolution, resampleMethod, colorStops } = params;
1193
+ // 1. Calculate View projection bounds for the tile
1194
+ const viewBounds = this.getTileBounds(x, y, z);
1195
+ log(`v-map - geotiff - getTileData(${x},${y},${z}): viewBounds=[${viewBounds.map(v => v.toFixed(0)).join(',')}], sourceBounds=[${this.config.sourceBounds.map(v => v.toFixed(0)).join(',')}], toProjection=${this.config.toProjection}`);
1196
+ // 2. Early exit: Check if tile intersects with source bounds
1197
+ if (!this.tileIntersectsSource(viewBounds)) {
1198
+ // Tile is completely outside source bounds - return transparent tile
1199
+ log(`v-map - geotiff - getTileData(${x},${y},${z}): no intersection, returning transparent`);
1200
+ const sampleSize = Math.ceil(tileSize * resolution);
1201
+ return new Uint8ClampedArray(sampleSize * sampleSize * 4);
1202
+ }
1203
+ // 3. Calculate sampling resolution
1204
+ const sampleSize = Math.ceil(tileSize * resolution);
1205
+ // 4. Get or create triangulation
1206
+ let triangulation;
1207
+ if (!this.globalTriangulation) {
1208
+ warn('Global triangulation not available, creating fallback for tile');
1209
+ triangulation = new Triangulation(this.config.transformViewToSourceMapFn, viewBounds, 0.5);
1210
+ }
1211
+ else {
1212
+ triangulation = this.globalTriangulation;
1213
+ }
1214
+ // 5. Calculate source bounds for this tile
1215
+ const tileSrcBounds = this.calculateTileSourceBounds(viewBounds);
1216
+ // 6. Select best overview image based on zoom
1217
+ const { bestImage, bestResolution, imageLevel } = this.selectOverviewImage(z, tileSize);
1218
+ const ovWidth = bestImage.getWidth();
1219
+ const ovHeight = bestImage.getHeight();
1220
+ // 7. Calculate pixel window for reading
1221
+ const readWindow = this.calculateReadWindow(tileSrcBounds, ovWidth, ovHeight);
1222
+ if (!readWindow) {
1223
+ return new Uint8ClampedArray(sampleSize * sampleSize * 4);
1224
+ }
1225
+ // 8. Load and convert raster data
1226
+ const { rasterBands, arrayType } = await this.loadAndConvertRasterData(bestImage, readWindow);
1227
+ const bandCount = rasterBands.length;
1228
+ log(`Read window: [${readWindow.readXMin}, ${readWindow.readYMin}, ${readWindow.readXMax}, ${readWindow.readYMax}] (${readWindow.readWidth}x${readWindow.readHeight} pixels), ${bandCount} bands, type: ${arrayType}, imageLevel: ${imageLevel}, resolution: ${bestResolution}`);
1229
+ // 9. Render tile pixels
1230
+ const outputData = this.renderTilePixels({
1231
+ sampleSize,
1232
+ mercatorBounds: viewBounds, // Pass View bounds (kept name for backward compat)
1233
+ triangulation,
1234
+ rasterBands,
1235
+ arrayType,
1236
+ readWindow,
1237
+ ovWidth,
1238
+ ovHeight,
1239
+ resampleMethod,
1240
+ colorStops,
1241
+ });
1242
+ return outputData;
1243
+ }
1244
+ /**
1245
+ * Get raw elevation values for a tile as Float32Array.
1246
+ *
1247
+ * Returns a (tileSize+1) × (tileSize+1) float array suitable for Martini
1248
+ * terrain mesh generation. Border pixels are backfilled for Martini compatibility.
1249
+ * Band 0 of the GeoTIFF is used as the elevation source.
1250
+ */
1251
+ async getElevationData(params) {
1252
+ const { x, y, z, tileSize } = params;
1253
+ const gridSize = tileSize + 1; // Martini requires (2^n + 1)^2 grid
1254
+ const viewBounds = this.getTileBounds(x, y, z);
1255
+ if (!this.tileIntersectsSource(viewBounds)) {
1256
+ return new Float32Array(gridSize * gridSize);
1257
+ }
1258
+ let triangulation;
1259
+ if (!this.globalTriangulation) {
1260
+ warn('Global triangulation not available, creating fallback for elevation tile');
1261
+ triangulation = new Triangulation(this.config.transformViewToSourceMapFn, viewBounds, 0.5);
1262
+ }
1263
+ else {
1264
+ triangulation = this.globalTriangulation;
1265
+ }
1266
+ const tileSrcBounds = this.calculateTileSourceBounds(viewBounds);
1267
+ const { bestImage } = this.selectOverviewImage(z, tileSize);
1268
+ const ovWidth = bestImage.getWidth();
1269
+ const ovHeight = bestImage.getHeight();
1270
+ const readWindow = this.calculateReadWindow(tileSrcBounds, ovWidth, ovHeight);
1271
+ if (!readWindow) {
1272
+ return new Float32Array(gridSize * gridSize);
1273
+ }
1274
+ const { rasterBands } = await this.loadAndConvertRasterData(bestImage, readWindow);
1275
+ const [mercWest, mercSouth, mercEast, mercNorth] = viewBounds;
1276
+ const [srcWest, srcSouth, srcEast, srcNorth] = this.config.sourceBounds;
1277
+ const srcWidth = srcEast - srcWest;
1278
+ const srcHeight = srcNorth - srcSouth;
1279
+ const output = new Float32Array(gridSize * gridSize);
1280
+ let tri = null;
1281
+ for (let py = 0; py < tileSize; py++) {
1282
+ for (let px = 0; px < tileSize; px++) {
1283
+ const mercX = mercWest + (px / tileSize) * (mercEast - mercWest);
1284
+ const mercY = mercNorth - (py / tileSize) * (mercNorth - mercSouth);
1285
+ const targetPoint = [mercX, mercY];
1286
+ tri = triangulation.findSourceTriangleForTargetPoint(targetPoint, tri);
1287
+ if (tri) {
1288
+ const [srcX, srcY] = triangulation.applyAffineTransform(mercX, mercY, tri.transform);
1289
+ if (srcX >= srcWest && srcX <= srcEast && srcY >= srcSouth && srcY <= srcNorth) {
1290
+ const imgX = ((srcX - srcWest) / srcWidth) * ovWidth;
1291
+ const imgY = ((srcNorth - srcY) / srcHeight) * ovHeight;
1292
+ const sampleX = Math.round(imgX) - readWindow.readXMin;
1293
+ const sampleY = Math.round(imgY) - readWindow.readYMin;
1294
+ if (sampleX >= 0 && sampleX < readWindow.readWidth &&
1295
+ sampleY >= 0 && sampleY < readWindow.readHeight) {
1296
+ const sampleValue = Number(rasterBands[0][sampleY * readWindow.readWidth + sampleX]);
1297
+ output[py * gridSize + px] =
1298
+ this.sanitizeElevationValue(sampleValue);
1299
+ }
1300
+ }
1301
+ }
1302
+ }
1303
+ }
1304
+ // Backfill right border column (Martini requirement)
1305
+ for (let row = 0; row < tileSize; row++) {
1306
+ output[row * gridSize + tileSize] = output[row * gridSize + tileSize - 1];
1307
+ }
1308
+ // Backfill bottom border row (Martini requirement)
1309
+ for (let col = 0; col <= tileSize; col++) {
1310
+ output[tileSize * gridSize + col] = output[(tileSize - 1) * gridSize + col];
1311
+ }
1312
+ return output;
1313
+ }
1314
+ }
1315
+ async function getTileProcessorConfig(tiffSource, viewProjection) {
1316
+ const { default: proj4 } = await import('./index-RpJarvr_.js');
1317
+ // Transform from View projection to Source projection
1318
+ const transformViewToSourceMapFn = (coord) => {
1319
+ const result = proj4(viewProjection, tiffSource.fromProjection, coord);
1320
+ return [Number(result[0]), Number(result[1])];
1321
+ };
1322
+ // Inverse: Transform from Source projection to View projection
1323
+ const transformSourceMapToViewFn = (coord) => {
1324
+ const result = proj4(tiffSource.fromProjection, viewProjection, coord);
1325
+ return [Number(result[0]), Number(result[1])];
1326
+ };
1327
+ const config = {
1328
+ transformViewToSourceMapFn,
1329
+ transformSourceMapToViewFn,
1330
+ sourceBounds: tiffSource.sourceBounds,
1331
+ sourceRef: tiffSource.sourceRef,
1332
+ resolution: tiffSource.resolution,
1333
+ imageWidth: tiffSource.width,
1334
+ imageHeight: tiffSource.height,
1335
+ fromProjection: tiffSource.fromProjection,
1336
+ toProjection: viewProjection,
1337
+ baseImage: tiffSource.baseImage,
1338
+ overviewImages: tiffSource.overviewImages ?? [],
1339
+ noDataValue: tiffSource.noDataValue,
1340
+ };
1341
+ return config;
1342
+ }
1343
+
1344
+ //const DEFAULT_TO_PROJECTION = 'EPSG:3857';
1345
+ async function loadGeoTIFFSource(url, options, deps) {
1346
+ const { geotiff, proj4, geokeysToProj4 } = deps;
1347
+ const { fromUrl } = geotiff;
1348
+ const { toProj4 } = geokeysToProj4;
1349
+ let tiff = null;
1350
+ let lasterr = null;
1351
+ for (let i = 0; i <= 2; i++) {
1352
+ try {
1353
+ tiff = await fromUrl(url, {
1354
+ allowFullFile: true,
1355
+ blockSize: 1024 * 1024, // 1MB blocks to reduce HTTP range-request count for non-COG files
1356
+ cacheSize: 100,
1357
+ });
1358
+ }
1359
+ catch (err) {
1360
+ lasterr = err;
1361
+ }
1362
+ if (tiff != null) {
1363
+ lasterr = null;
1364
+ break;
1365
+ }
1366
+ }
1367
+ if (lasterr != null) {
1368
+ log(lasterr);
1369
+ warn('Error - loadGeoTIFFSource - fromUrl: ', url);
1370
+ throw lasterr;
1371
+ }
1372
+ const baseImage = await tiff.getImage(0);
1373
+ const imageCount = await tiff.getImageCount();
1374
+ const overviewImages = [];
1375
+ for (let i = 1; i < imageCount; i++) {
1376
+ overviewImages.push(await tiff.getImage(i));
1377
+ }
1378
+ const width = baseImage.getWidth();
1379
+ const height = baseImage.getHeight();
1380
+ const samplesPerPixel = Math.max(1, baseImage.getSamplesPerPixel?.() ?? 1);
1381
+ let fromProjection = options.forceProjection && options.projection
1382
+ ? options.projection
1383
+ : options.projection ?? 'EPSG:4326';
1384
+ let proj4String = null;
1385
+ if (!options.forceProjection) {
1386
+ const geoKeys = typeof baseImage.getGeoKeys === 'function'
1387
+ ? baseImage.getGeoKeys() ?? null
1388
+ : null;
1389
+ if (geoKeys) {
1390
+ try {
1391
+ const projParams = toProj4(geoKeys);
1392
+ const epsg = geoKeys.ProjectedCSTypeGeoKey ?? geoKeys.GeographicTypeGeoKey;
1393
+ if (epsg) {
1394
+ fromProjection = `EPSG:${epsg}`;
1395
+ }
1396
+ if (projParams?.proj4) {
1397
+ proj4String = projParams.proj4;
1398
+ const numericCode = String(epsg);
1399
+ if (epsg && !proj4.defs(fromProjection)) {
1400
+ proj4.defs(fromProjection, projParams.proj4);
1401
+ }
1402
+ if (epsg && !proj4.defs(numericCode)) {
1403
+ proj4.defs(numericCode, projParams.proj4);
1404
+ }
1405
+ }
1406
+ }
1407
+ catch (err) {
1408
+ warn('v-map - geotiff - failed to parse GeoKeys', err);
1409
+ }
1410
+ }
1411
+ }
1412
+ if (!proj4String) {
1413
+ switch (fromProjection) {
1414
+ case 'EPSG:4326':
1415
+ proj4String = '+proj=longlat +datum=WGS84 +no_defs';
1416
+ break;
1417
+ case 'EPSG:3857':
1418
+ proj4String =
1419
+ '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs';
1420
+ break;
1421
+ case 'EPSG:32632':
1422
+ proj4String = '+proj=utm +zone=32 +datum=WGS84 +units=m +no_defs';
1423
+ break;
1424
+ }
1425
+ }
1426
+ if (!fromProjection || fromProjection.trim() === '') {
1427
+ fromProjection = 'EPSG:4326';
1428
+ }
1429
+ if (proj4String && !proj4.defs(fromProjection)) {
1430
+ proj4.defs(fromProjection, proj4String);
1431
+ }
1432
+ const sourceBounds = baseImage.getBoundingBox();
1433
+ const sourceRef = [sourceBounds[0], sourceBounds[1]];
1434
+ const resolution = baseImage.getResolution()[0];
1435
+ const rawNoData = options.nodata !== undefined && options.nodata !== null
1436
+ ? Number(options.nodata)
1437
+ : typeof baseImage.getGDALNoData === 'function'
1438
+ ? baseImage.getGDALNoData()
1439
+ : undefined;
1440
+ const noDataValue = rawNoData !== undefined && rawNoData !== null
1441
+ ? Number(rawNoData)
1442
+ : undefined;
1443
+ const clampLon = (lon) => Math.max(-180, Math.min(180, Number.isFinite(lon) ? lon : 0));
1444
+ const clampLat = (lat) => Math.max(-90, Math.min(90, Number.isFinite(lat) ? lat : 0));
1445
+ let transformToWgs84;
1446
+ if (!fromProjection || fromProjection === 'EPSG:4326') {
1447
+ transformToWgs84 = coord => coord;
1448
+ }
1449
+ else {
1450
+ transformToWgs84 = (coord) => {
1451
+ try {
1452
+ const result = proj4(fromProjection, 'EPSG:4326', coord);
1453
+ return [Number(result[0]), Number(result[1])];
1454
+ }
1455
+ catch (err) {
1456
+ warn('v-map - geotiff - transform to WGS84 failed, falling back', err);
1457
+ return coord;
1458
+ }
1459
+ };
1460
+ }
1461
+ const [minX, minY, maxX, maxY] = sourceBounds;
1462
+ const corners = [
1463
+ transformToWgs84([minX, minY]),
1464
+ transformToWgs84([maxX, minY]),
1465
+ transformToWgs84([maxX, maxY]),
1466
+ transformToWgs84([minX, maxY]),
1467
+ ];
1468
+ const west = clampLon(Math.min(...corners.map(c => c[0])));
1469
+ const east = clampLon(Math.max(...corners.map(c => c[0])));
1470
+ const south = clampLat(Math.min(...corners.map(c => c[1])));
1471
+ const north = clampLat(Math.max(...corners.map(c => c[1])));
1472
+ log('v-map - geotiff - loaded source', {
1473
+ url,
1474
+ width,
1475
+ height,
1476
+ samplesPerPixel,
1477
+ fromProjection,
1478
+ bounds: sourceBounds,
1479
+ });
1480
+ return {
1481
+ tiff,
1482
+ baseImage,
1483
+ overviewImages,
1484
+ width,
1485
+ height,
1486
+ samplesPerPixel,
1487
+ fromProjection,
1488
+ //toProjection: DEFAULT_TO_PROJECTION,
1489
+ sourceBounds,
1490
+ sourceRef,
1491
+ resolution,
1492
+ proj4,
1493
+ noDataValue,
1494
+ wgs84Bounds: [west, south, east, north],
1495
+ transformToWgs84,
1496
+ };
1497
+ }
1498
+ async function getGeoTIFFSource(url, projection, forceProjection, nodata) {
1499
+ const [geotiffModule, { default: proj4 }, geokeysModule] = await Promise.all([
1500
+ import('./geotiff-BEWxTIfH.js').then(function (n) { return n.g; }),
1501
+ import('./index-RpJarvr_.js'),
1502
+ import('./main-dist-CwnA7_Xn.js').then(function (n) { return n.m; }),
1503
+ ]);
1504
+ const source = await loadGeoTIFFSource(url, {
1505
+ projection: projection,
1506
+ forceProjection: forceProjection,
1507
+ nodata: nodata,
1508
+ }, {
1509
+ geotiff: geotiffModule,
1510
+ proj4,
1511
+ geokeysToProj4: geokeysModule,
1512
+ });
1513
+ return source;
1514
+ }
1515
+
1516
+ export { GeoTIFFTileProcessor as G, getGeoTIFFSource as a, getTileProcessorConfig as b, getColorStops as g, loadGeoTIFFSource as l };