@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,2596 @@
1
+ import { w as warn, l as log, e as error } from './messages-CMKJzsgL.js';
2
+ import { C as CESIUM_VERSION } from './v-map.v-map-layer-osm.v-map-layergroup-B4pFHuSf.js';
3
+ import { l as loadGeoTIFFSource, a as getGeoTIFFSource, b as getTileProcessorConfig, G as GeoTIFFTileProcessor, g as getColorStops } from './geotiff-source-esnDnC-u.js';
4
+ import './index-jzneDarq.js';
5
+ import './v-map-layer-helper-Dys44Cgo.js';
6
+
7
+ /**
8
+ * Eine Gruppe verwaltet Sichtbarkeit & Basemap-Filter ihrer Cesium-Layer.
9
+ * - group.visible = false => Alle Layer der Gruppe unsichtbar.
10
+ * - group.basemap = "X" => Nur Layer mit elementId==="X" in der Gruppe sichtbar.
11
+ * - Der ursprüngliche Sichtbarkeitszustand jedes Layers wird gemerkt und bei
12
+ * Re-Aktivierung wiederhergestellt.
13
+ */
14
+ class CesiumLayerGroup {
15
+ id;
16
+ _visible = true;
17
+ _basemap = null;
18
+ _layers = new Map();
19
+ _originalVisible = new Map();
20
+ _dirty = true;
21
+ constructor(id, visible = true) {
22
+ this.id = id;
23
+ this._visible = visible;
24
+ }
25
+ get visible() {
26
+ return this._visible;
27
+ }
28
+ set visible(v) {
29
+ if (this._visible === v)
30
+ return;
31
+ this._visible = v;
32
+ this._dirty = true;
33
+ }
34
+ get basemap() {
35
+ return this._basemap;
36
+ }
37
+ set basemap(b) {
38
+ if (this._basemap === b)
39
+ return;
40
+ this._basemap = b;
41
+ this._dirty = true;
42
+ }
43
+ isDirty() {
44
+ return this._dirty;
45
+ }
46
+ addLayer(ref) {
47
+ if (this._layers.has(ref.id))
48
+ return;
49
+ this._layers.set(ref.id, ref);
50
+ this._originalVisible.set(ref.id, ref.layer.getVisible());
51
+ this._dirty = true;
52
+ }
53
+ /** optional zum Nachziehen von elementId (z. B. wenn erst später bekannt) */
54
+ setLayerElementId(layerId, elementId) {
55
+ const r = this._layers.get(layerId);
56
+ if (!r)
57
+ return;
58
+ if (r.elementId === elementId)
59
+ return;
60
+ r.elementId = elementId ?? null;
61
+ this._dirty = true;
62
+ }
63
+ removeLayer(layerId) {
64
+ const had = this._layers.delete(layerId);
65
+ this._originalVisible.delete(layerId);
66
+ if (had)
67
+ this._dirty = true;
68
+ return had;
69
+ }
70
+ clear() {
71
+ this._layers.clear();
72
+ this._originalVisible.clear();
73
+ this._dirty = true;
74
+ }
75
+ /** zentrale Logik: Basemap/Visibility anwenden */
76
+ apply() {
77
+ if (!this._dirty)
78
+ return;
79
+ for (const [id, ref] of this._layers) {
80
+ const original = this._originalVisible.get(id) ?? true;
81
+ // effektive Sichtbarkeit nach Gruppenregeln
82
+ let effective = this._visible && original;
83
+ if (effective && this._basemap) {
84
+ // innerhalb der Gruppe nur Layer mit passender elementId anzeigen
85
+ effective = ref.elementId === this._basemap;
86
+ }
87
+ // Nur dann setzen, wenn sich etwas ändert
88
+ if (ref.layer.getVisible() !== effective) {
89
+ ref.layer.setVisible(effective);
90
+ }
91
+ }
92
+ this._dirty = false;
93
+ }
94
+ }
95
+ /**
96
+ * Root-Store für mehrere Cesium-Gruppen.
97
+ * - Ordnung/Z-Index übernimmst du weiterhin im LayerManager pro Layer.
98
+ * - Diese Klasse kümmert sich um Gruppensichtbarkeit & Basemap-Filter.
99
+ */
100
+ class CesiumLayerGroups {
101
+ _groups = [];
102
+ _dirty = true;
103
+ get groups() {
104
+ return [...this._groups];
105
+ }
106
+ getGroup(id) {
107
+ return this._groups.find(g => g.id === id);
108
+ }
109
+ hasGroup(id) {
110
+ return this._groups.some(g => g.id === id);
111
+ }
112
+ ensureGroup(id, visible = true) {
113
+ let g = this.getGroup(id);
114
+ if (g)
115
+ return g;
116
+ g = new CesiumLayerGroup(id, visible);
117
+ this._groups.push(g);
118
+ this._dirty = true;
119
+ return g;
120
+ }
121
+ addLayerToGroup(groupId, visible, ref) {
122
+ const g = this.ensureGroup(groupId, visible);
123
+ g.addLayer(ref);
124
+ this._dirty = true;
125
+ }
126
+ removeLayer(layerId, removeFromAll = true) {
127
+ let removed = false;
128
+ for (const g of this._groups) {
129
+ if (g.removeLayer(layerId)) {
130
+ removed = true;
131
+ if (!removeFromAll)
132
+ break;
133
+ }
134
+ }
135
+ if (removed)
136
+ this._dirty = true;
137
+ return removed;
138
+ }
139
+ setGroupVisible(groupId, visible) {
140
+ const g = this.getGroup(groupId);
141
+ if (!g)
142
+ throw new Error(`CesiumLayerGroup "${groupId}" nicht gefunden`);
143
+ g.visible = visible;
144
+ this._dirty = true;
145
+ }
146
+ setBasemap(groupId, basemap) {
147
+ const g = this.getGroup(groupId);
148
+ if (!g)
149
+ throw new Error(`CesiumLayerGroup "${groupId}" nicht gefunden`);
150
+ g.basemap = basemap;
151
+ this._dirty = true;
152
+ }
153
+ /** Wendet alle Gruppenregeln an (sichtbar/basemap). */
154
+ apply() {
155
+ if (!this._dirty && !this._groups.some(g => g.isDirty()))
156
+ return;
157
+ for (const g of this._groups)
158
+ g.apply();
159
+ this._dirty = false;
160
+ }
161
+ clear() {
162
+ this._groups = [];
163
+ this._dirty = true;
164
+ }
165
+ }
166
+
167
+ class LayerManager {
168
+ Cesium;
169
+ layers = new Map();
170
+ viewer;
171
+ //private imageryZMutex = new AsyncMutex();
172
+ constructor(Cesium, viewer) {
173
+ this.viewer = viewer;
174
+ this.Cesium = Cesium;
175
+ }
176
+ replaceLayer(id, oldlayer, layer) {
177
+ if (!this.Cesium) {
178
+ throw new Error('Cesium must be initialized first. Call init() method.');
179
+ }
180
+ const zIndex = oldlayer.getZIndex();
181
+ const visible = oldlayer.getVisible();
182
+ const opacity = oldlayer.getOpacity();
183
+ this.removeLayer(id);
184
+ const wrappedLayer = this.addLayer(id, layer);
185
+ wrappedLayer.setZIndex(zIndex);
186
+ wrappedLayer.setVisible(visible);
187
+ wrappedLayer.setOpacity(opacity);
188
+ return wrappedLayer;
189
+ }
190
+ addLayer(id, layer) {
191
+ if (!this.Cesium) {
192
+ throw new Error('Cesium must be initialized first. Call init() method.');
193
+ }
194
+ //add layer
195
+ if (layer instanceof this.Cesium.GeoJsonDataSource) {
196
+ this.viewer.dataSources.add(layer);
197
+ }
198
+ else if (layer instanceof this.Cesium.DataSource) {
199
+ this.viewer.dataSources.add(layer);
200
+ }
201
+ else if (layer instanceof this.Cesium.Cesium3DTileset) {
202
+ this.viewer.scene.primitives.add(layer);
203
+ if (!layer.style) {
204
+ layer.style = new this.Cesium.Cesium3DTileStyle();
205
+ }
206
+ }
207
+ else if (layer instanceof this.Cesium.ImageryLayer) {
208
+ this.viewer.imageryLayers.add(layer);
209
+ }
210
+ layer.id = id;
211
+ const wrapped = this.wrapLayer(layer);
212
+ this.layers.set(id, wrapped);
213
+ return wrapped;
214
+ }
215
+ addCustomLayer(id, layer) {
216
+ this.layers.set(id, layer);
217
+ return layer;
218
+ }
219
+ getLayer(layerId) {
220
+ const layer = this.layers.get(layerId);
221
+ if (!layer)
222
+ throw new Error(`Layer mit ID "${layerId}" nicht gefunden.`);
223
+ return layer;
224
+ }
225
+ getLayerById(layerId) {
226
+ return this.getLayer(layerId);
227
+ }
228
+ removeLayer(layerId) {
229
+ const layer = this.getLayer(layerId);
230
+ layer.remove();
231
+ this.layers.delete(layerId);
232
+ }
233
+ setVisible(layerId, visible) {
234
+ const layer = this.getLayer(layerId);
235
+ layer.setVisible(visible);
236
+ }
237
+ setOpacity(layerId, opacity) {
238
+ const layer = this.getLayer(layerId);
239
+ layer.setOpacity(opacity);
240
+ }
241
+ async setZIndex(layerId, zindex) {
242
+ const layer = this.getLayer(layerId);
243
+ await layer.setZIndex(zindex);
244
+ }
245
+ wrapLayer(layer) {
246
+ if (layer instanceof this.Cesium.ImageryLayer) {
247
+ return this.wrapImageryLayer(layer);
248
+ }
249
+ else if (layer instanceof this.Cesium.Cesium3DTileset) {
250
+ return this.wrapTilesetLayer(layer);
251
+ }
252
+ else {
253
+ return this.wrapDataSourceLayer(layer);
254
+ }
255
+ }
256
+ async sortImageryLayers(collection, layer, targetZ) {
257
+ const tempCollection = this.sort(collection, layer, targetZ);
258
+ // Collection leeren und neu befüllen
259
+ collection.removeAll(false);
260
+ tempCollection.forEach(ds => collection.add(ds));
261
+ }
262
+ async sort3DTileSets(collection, tileset, targetZ) {
263
+ const tempCollection = this.sort(collection, tileset, targetZ);
264
+ // Collection leeren und neu befüllen
265
+ collection.removeAll();
266
+ tempCollection.forEach(ds => collection.add(ds));
267
+ }
268
+ async sortDataSources(collection, dataSource, zIndex) {
269
+ const tempCollection = this.sort(collection, dataSource, zIndex);
270
+ // Collection leeren und neu befüllen
271
+ collection.removeAll(false);
272
+ tempCollection.forEach(async (ds) => await collection.add(ds));
273
+ }
274
+ sort(collection, dataSource, zIndex) {
275
+ // 1. Layer entfernen
276
+ collection.remove(dataSource, false);
277
+ // 2. Layer an der richtigen Position wieder hinzufügen
278
+ // Cesium hat keine direkte "setZIndex"-Methode für DataSources,
279
+ // also müssen wir die Reihenfolge manuell steuern.
280
+ // Da DataSourceCollection keine Z-Index-Unterstützung hat,
281
+ // müssen wir alle Layer neu sortieren.
282
+ // const dataSources: DataSource[] = [];
283
+ const tempDataSources = [];
284
+ // Alle Layer sammeln
285
+ for (let i = 0; i < collection.length; i++) {
286
+ tempDataSources.push(collection.get(i));
287
+ }
288
+ // Sortieren nach zIndex (falls vorhanden) oder Reihenfolge
289
+ tempDataSources.sort((a, b) => {
290
+ const aZIndex = a.zIndex || 0;
291
+ const bZIndex = b.zIndex || 0;
292
+ return aZIndex - bZIndex;
293
+ });
294
+ // Den Layer mit dem neuen zIndex einfügen
295
+ dataSource.zIndex = zIndex;
296
+ tempDataSources.push(dataSource);
297
+ // Neu sortieren
298
+ tempDataSources.sort((a, b) => {
299
+ const aZIndex = a.zIndex || 0;
300
+ const bZIndex = b.zIndex || 0;
301
+ return aZIndex - bZIndex;
302
+ });
303
+ return tempDataSources;
304
+ }
305
+ // /**
306
+ // * Verschiebt ein bereits vorhandenes ImageryLayer innerhalb seiner Collection
307
+ // * zu einem gewünschten zIndex und hält die Collection nach zIndex sortiert.
308
+ // *
309
+ // * @param collection Die Sammlung, in der sich das Layer befindet.
310
+ // * @param layer Das zu verschiebende Layer (ist bereits Teil der Collection).
311
+ // * @param targetZ Der gewünschte neue zIndex.
312
+ // */
313
+ // private moveImageryLayerToZIndex(
314
+ // collection: ImageryLayerCollection,
315
+ // layer: ImageryLayer,
316
+ // targetZ: number,
317
+ // ): void {
318
+ // // fire-and-forget; Thread-Sicherheit via Mutex
319
+ // void this.imageryZMutex.runExclusive(async () => {
320
+ // // -------------------------------------------------
321
+ // // 1️⃣ Neues zIndex setzen (überschreibt das alte)
322
+ // // -------------------------------------------------
323
+ // (layer as any).zIndex = targetZ;
324
+ // // -------------------------------------------------
325
+ // // 2️⃣ Aktuelle Position bestimmen
326
+ // // -------------------------------------------------
327
+ // const curIdx = collection.indexOf(layer);
328
+ // if (curIdx === -1) {
329
+ // throw new Error('Der übergebene Layer ist nicht Teil der Collection.');
330
+ // }
331
+ // // -------------------------------------------------
332
+ // // 3️⃣ Nach oben schieben, solange Vorgänger einen
333
+ // // größeren zIndex hat (stabile Sortierung)
334
+ // // -------------------------------------------------
335
+ // let idx = curIdx;
336
+ // while (
337
+ // idx > 0 && // nicht am Anfang
338
+ // collection[idx - 1].zIndex > targetZ // Vorgänger hat höheren zIndex
339
+ // ) {
340
+ // // `raise` vertauscht das aktuelle Element mit seinem Vorgänger
341
+ // collection.raise(collection[idx]);
342
+ // idx--;
343
+ // }
344
+ // // -------------------------------------------------
345
+ // // 4️⃣ Nach unten schieben, falls das neue zIndex
346
+ // // größer ist als das der nachfolgenden Elemente
347
+ // // -------------------------------------------------
348
+ // while (
349
+ // idx < collection.length - 1 && // nicht am Ende
350
+ // collection[idx + 1].zIndex < targetZ // Nachfolger hat kleineren zIndex
351
+ // ) {
352
+ // // `lower` vertauscht das aktuelle Element mit seinem Nachfolger
353
+ // collection.lower(collection[idx]);
354
+ // idx++;
355
+ // }
356
+ // });
357
+ // // -------------------------------------------------
358
+ // // 5️⃣ Optional: Guard‑Clause für extreme Werte
359
+ // // -------------------------------------------------
360
+ // // (Falls du Min/Max‑Grenzen definieren willst)
361
+ // // if (targetZ < MIN_Z) (layer as any).zIndex = MIN_Z;
362
+ // // if (targetZ > MAX_Z) (layer as any).zIndex = MAX_Z;
363
+ // }
364
+ // private moveTilesetToIndex(tileset: Cesium3DTileset, index: number): void {
365
+ // const primitives = this.viewer.scene.primitives;
366
+ // primitives.remove(tileset);
367
+ // if (index >= primitives.length) {
368
+ // primitives.add(tileset);
369
+ // } else {
370
+ // const tilesets = [];
371
+ // for (let i = 0; i < primitives.length; i++) {
372
+ // const current = primitives.get(i);
373
+ // if (i === index) tilesets.push(tileset);
374
+ // if (current !== tileset) tilesets.push(current);
375
+ // }
376
+ // primitives.removeAll();
377
+ // tilesets.forEach(t => primitives.add(t));
378
+ // }
379
+ // }
380
+ // private moveDataSourceToIndex(
381
+ // collection: DataSourceCollection,
382
+ // dataSource: DataSource,
383
+ // zIndex: number,
384
+ // ): void {
385
+ // // 1. Layer entfernen
386
+ // collection.remove(dataSource);
387
+ // // 2. Layer an der richtigen Position wieder hinzufügen
388
+ // // Cesium hat keine direkte "setZIndex"-Methode für DataSources,
389
+ // // also müssen wir die Reihenfolge manuell steuern.
390
+ // // Da DataSourceCollection keine Z-Index-Unterstützung hat,
391
+ // // müssen wir alle Layer neu sortieren.
392
+ // // const dataSources: DataSource[] = [];
393
+ // const tempDataSources: DataSource[] = [];
394
+ // // Alle Layer sammeln
395
+ // for (let i = 0; i < collection.length; i++) {
396
+ // tempDataSources.push(collection.get(i));
397
+ // }
398
+ // // Sortieren nach zIndex (falls vorhanden) oder Reihenfolge
399
+ // tempDataSources.sort((a, b) => {
400
+ // const aZIndex = (a as any).zIndex || 0;
401
+ // const bZIndex = (b as any).zIndex || 0;
402
+ // return aZIndex - bZIndex;
403
+ // });
404
+ // // Den Layer mit dem neuen zIndex einfügen
405
+ // (dataSource as any).zIndex = zIndex;
406
+ // tempDataSources.push(dataSource);
407
+ // // Neu sortieren
408
+ // tempDataSources.sort((a, b) => {
409
+ // const aZIndex = (a as any).zIndex || 0;
410
+ // const bZIndex = (b as any).zIndex || 0;
411
+ // return aZIndex - bZIndex;
412
+ // });
413
+ // // Collection leeren und neu befüllen
414
+ // collection.removeAll();
415
+ // tempDataSources.forEach(ds => collection.add(ds));
416
+ // }
417
+ wrapImageryLayer(layer) {
418
+ const collection = this.viewer.imageryLayers;
419
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches ILayer interface contract
420
+ let iLOptions = {};
421
+ return {
422
+ getOptions: () => {
423
+ return iLOptions;
424
+ },
425
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches ILayer interface contract
426
+ setOptions(options) {
427
+ iLOptions = options;
428
+ },
429
+ getVisible: () => {
430
+ return layer.show;
431
+ },
432
+ setVisible: (value) => {
433
+ layer.show = value;
434
+ },
435
+ getOpacity: () => layer.alpha,
436
+ setOpacity: (value) => {
437
+ layer.alpha = value;
438
+ },
439
+ getZIndex: () => {
440
+ for (let i = 0; i < collection.length; i++) {
441
+ if (collection.get(i) === layer)
442
+ return i;
443
+ }
444
+ return -1;
445
+ },
446
+ setZIndex: async (zIndex) => {
447
+ if (zIndex !== undefined) {
448
+ await this.sortImageryLayers(collection, layer, zIndex);
449
+ }
450
+ },
451
+ remove: () => collection.remove(layer),
452
+ };
453
+ }
454
+ wrapTilesetLayer(layer) {
455
+ const collection = this.viewer.scene.primitives;
456
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches ILayer interface contract
457
+ let c3dTSOptions = {};
458
+ return {
459
+ getOptions: () => {
460
+ return c3dTSOptions;
461
+ },
462
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches ILayer interface contract
463
+ setOptions(options) {
464
+ c3dTSOptions = options;
465
+ },
466
+ getVisible: () => {
467
+ return layer.show;
468
+ },
469
+ setVisible: (value) => {
470
+ layer.show = value;
471
+ },
472
+ getOpacity: () => {
473
+ const style = layer.style;
474
+ if (style.color && typeof style.color === 'string') {
475
+ const colorStr = style.color;
476
+ const match = colorStr.match(/color\(.*?,([\d.]+)\)/);
477
+ return match ? parseFloat(match[1]) : 1.0;
478
+ }
479
+ return 1.0;
480
+ },
481
+ setOpacity: (value) => {
482
+ const currentColor = layer.style.color;
483
+ let colorExpr;
484
+ if (typeof currentColor === 'string') {
485
+ const colorStr = currentColor;
486
+ const colorPart = colorStr.replace(/color\((.*?),[\d.]+\)/, `color($1, ${value})`);
487
+ colorExpr = colorPart.includes('color')
488
+ ? colorPart
489
+ : `color('white', ${value})`;
490
+ }
491
+ else {
492
+ colorExpr = `color('white', ${value})`;
493
+ }
494
+ layer.style = new this.Cesium.Cesium3DTileStyle({
495
+ color: colorExpr,
496
+ colorBlendMode: this.Cesium.ColorBlendMode.MIX,
497
+ });
498
+ },
499
+ getZIndex: () => {
500
+ const primitives = this.viewer.scene.primitives;
501
+ for (let i = 0; i < primitives.length; i++) {
502
+ if (primitives.get(i) === layer)
503
+ return i;
504
+ }
505
+ return -1;
506
+ },
507
+ setZIndex: async (zIndex) => {
508
+ if (zIndex !== undefined) {
509
+ this.sort3DTileSets(collection, layer, zIndex);
510
+ //this.moveTilesetToIndex(layer, zIndex);
511
+ }
512
+ },
513
+ setColor: (color, opacity = 1.0) => {
514
+ const cssColor = color instanceof this.Cesium.Color
515
+ ? color.toCssHexString()
516
+ : color.replace(/[#\s]/g, '');
517
+ layer.style = new this.Cesium.Cesium3DTileStyle({
518
+ color: `color('${cssColor}', ${opacity})`,
519
+ colorBlendMode: this.Cesium.ColorBlendMode.MIX,
520
+ });
521
+ },
522
+ setStyle: (style) => {
523
+ layer.style =
524
+ style instanceof this.Cesium.Cesium3DTileStyle
525
+ ? style
526
+ : new this.Cesium.Cesium3DTileStyle(style);
527
+ },
528
+ remove: () => this.viewer.scene.primitives.remove(layer),
529
+ };
530
+ }
531
+ wrapDataSourceLayer(layer) {
532
+ const collection = this.viewer.dataSources;
533
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches ILayer interface contract
534
+ let dsOptions = {};
535
+ return {
536
+ getOptions: () => {
537
+ return dsOptions;
538
+ },
539
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches ILayer interface contract
540
+ setOptions(options) {
541
+ dsOptions = options;
542
+ },
543
+ getVisible: () => {
544
+ return layer.show;
545
+ },
546
+ setVisible: (value) => {
547
+ layer.show = value;
548
+ },
549
+ getOpacity: () => 1.0, //todo
550
+ setOpacity: (value) => {
551
+ if (layer.__vmapLockOpacity)
552
+ return;
553
+ layer.entities.values.forEach((entity) => {
554
+ // Helper-Funktion zum Setzen der Opacity
555
+ const setColorOpacity = (colorProperty, defaultColor) => {
556
+ const { Color: CesiumColor, JulianDate } = this.Cesium;
557
+ const applyAlpha = (color) => CesiumColor.fromAlpha(color ?? defaultColor, value, new CesiumColor());
558
+ if (!colorProperty) {
559
+ return new this.Cesium.ConstantProperty(applyAlpha(defaultColor));
560
+ }
561
+ const maybeProperty = colorProperty;
562
+ if (maybeProperty && typeof maybeProperty.getValue === 'function') {
563
+ const currentColor = maybeProperty.getValue(this.viewer?.clock?.currentTime ?? new JulianDate(), new CesiumColor());
564
+ const nextColor = applyAlpha(currentColor);
565
+ if (typeof maybeProperty.setValue === 'function') {
566
+ maybeProperty.setValue(nextColor);
567
+ return maybeProperty;
568
+ }
569
+ return new this.Cesium.ConstantProperty(nextColor);
570
+ }
571
+ if (colorProperty instanceof this.Cesium.Color) {
572
+ return new this.Cesium.ConstantProperty(applyAlpha(colorProperty));
573
+ }
574
+ return new this.Cesium.ConstantProperty(applyAlpha(defaultColor));
575
+ };
576
+ // Polygone
577
+ if (entity.polygon) {
578
+ const material = entity.polygon.material;
579
+ if (material instanceof Cesium.ColorMaterialProperty) {
580
+ const color = material.color;
581
+ material.color = setColorOpacity(color, Cesium.Color.WHITE);
582
+ }
583
+ else if (material instanceof Cesium.ImageMaterialProperty) {
584
+ material.color = setColorOpacity(material.color, Cesium.Color.WHITE);
585
+ }
586
+ }
587
+ // Polylinien
588
+ if (entity.polyline) {
589
+ const material = entity.polyline.material;
590
+ if (material instanceof Cesium.ColorMaterialProperty) {
591
+ material.color = setColorOpacity(material.color, Cesium.Color.WHITE);
592
+ }
593
+ else if (material instanceof Cesium.PolylineOutlineMaterialProperty) {
594
+ material.color = setColorOpacity(material.color, Cesium.Color.WHITE);
595
+ }
596
+ }
597
+ // Punkte
598
+ if (entity.point) {
599
+ entity.point.color = setColorOpacity(entity.point.color, Cesium.Color.WHITE);
600
+ }
601
+ // Billboards
602
+ if (entity.billboard) {
603
+ entity.billboard.color = setColorOpacity(entity.billboard.color, Cesium.Color.WHITE);
604
+ }
605
+ // Labels
606
+ if (entity.label) {
607
+ entity.label.fillColor = setColorOpacity(entity.label.fillColor, Cesium.Color.BLACK);
608
+ if (entity.label.outlineColor) {
609
+ entity.label.outlineColor = setColorOpacity(entity.label.outlineColor, Cesium.Color.BLACK);
610
+ }
611
+ }
612
+ // 3D-Modelle (falls vorhanden)
613
+ if (entity.model) {
614
+ entity.model.color = setColorOpacity(entity.model.color, Cesium.Color.WHITE);
615
+ }
616
+ });
617
+ },
618
+ getZIndex: () => {
619
+ for (let i = 0; i < collection.length; i++) {
620
+ if (collection.get(i) === layer)
621
+ return i;
622
+ }
623
+ return -1;
624
+ },
625
+ setZIndex: async (zIndex) => {
626
+ if (zIndex !== undefined) {
627
+ await this.sortDataSources(collection, layer, zIndex);
628
+ }
629
+ },
630
+ remove: () => collection.remove(layer),
631
+ };
632
+ }
633
+ }
634
+
635
+ // utils/async-mutex.ts
636
+ class AsyncMutex {
637
+ locked = false;
638
+ queue = [];
639
+ async runExclusive(fn) {
640
+ await this.acquire();
641
+ try {
642
+ return await fn();
643
+ }
644
+ finally {
645
+ this.release();
646
+ }
647
+ }
648
+ acquire() {
649
+ if (!this.locked) {
650
+ this.locked = true;
651
+ return Promise.resolve();
652
+ }
653
+ return new Promise(resolve => this.queue.push(resolve));
654
+ }
655
+ release() {
656
+ const next = this.queue.shift();
657
+ if (next)
658
+ next();
659
+ else
660
+ this.locked = false;
661
+ }
662
+ }
663
+
664
+ function assert(cond, msg) {
665
+ if (!cond)
666
+ throw new Error(msg);
667
+ }
668
+ const sameMM = (exp, act) => exp.match(/^\d+\.\d+/)?.[0] === act.match(/^\d+\.\d+/)?.[0];
669
+ const loadCesiumMutex = new AsyncMutex();
670
+ async function loadCesium(version = CESIUM_VERSION) {
671
+ const v = version.replace(/^[^\d]*/, '');
672
+ const base = `https://cdn.jsdelivr.net/npm/cesium@${v}/Build/Cesium`;
673
+ const url = `${base}/Cesium.js`;
674
+ await loadCesiumMutex.runExclusive(async () => {
675
+ if (!globalThis.Cesium) {
676
+ await new Promise((resolve, reject) => {
677
+ const id = 'cesium-cdn-script';
678
+ if (document.getElementById(id))
679
+ return resolve();
680
+ const s = document.createElement('script');
681
+ s.id = id;
682
+ s.async = true;
683
+ s.src = url;
684
+ s.addEventListener('load', () => resolve(), { once: true });
685
+ s.addEventListener('error', () => reject(new Error(`Laden fehlgeschlagen: ${url}`)), { once: true });
686
+ document.head.appendChild(s);
687
+ });
688
+ }
689
+ });
690
+ const Cesium = globalThis.Cesium;
691
+ assert(Cesium, 'globalThis.Cesium nicht verfügbar.');
692
+ const actual = Cesium.VERSION; // z.B. "1.133"
693
+ assert(sameMM(String(version), actual), // Major.Minor muss passen
694
+ `Cesium-Version abweichend: erwartet ~${version}, geladen ${actual}`);
695
+ globalThis.CESIUM_BASE_URL = base;
696
+ return Cesium;
697
+ }
698
+ async function injectWidgetsCss(shadowRoot) {
699
+ const v = CESIUM_VERSION.replace(/^[^\d]*/, '');
700
+ const base = `https://cdn.jsdelivr.net/npm/cesium@${v}/Build/Cesium`;
701
+ const cssUrl = `${base}/Widgets/widgets.css`;
702
+ const cssText = await (await fetch(cssUrl)).text();
703
+ const absolutized = cssText.replace(/url\((?!['"]?data:)(['"]?)([^'")]+)\1\)/g, (_m, _q, rel) => `url(${base}/Widgets/${rel.replace(/^\.?\//, '')})`);
704
+ if (!shadowRoot)
705
+ return;
706
+ if ('adoptedStyleSheets' in Document.prototype) {
707
+ const sheet = new CSSStyleSheet();
708
+ await sheet.replace(absolutized);
709
+ shadowRoot.adoptedStyleSheets = [
710
+ ...(shadowRoot.adoptedStyleSheets ?? []),
711
+ sheet,
712
+ ];
713
+ }
714
+ else {
715
+ const style = document.createElement('style');
716
+ style.textContent = absolutized;
717
+ shadowRoot.appendChild(style);
718
+ }
719
+ }
720
+
721
+ /**
722
+ * Custom ImageryProvider that renders GeoTIFF tiles on demand using
723
+ * the shared GeoTIFFTileProcessor (triangulation-based reprojection).
724
+ */
725
+ class GeoTIFFImageryProvider {
726
+ tileWidth;
727
+ tileHeight;
728
+ tilingScheme;
729
+ rectangle;
730
+ errorEvent;
731
+ credit = undefined;
732
+ tileDiscardPolicy = undefined;
733
+ proxy = undefined;
734
+ hasAlphaChannel = true;
735
+ minimumLevel;
736
+ maximumLevel;
737
+ Cesium;
738
+ tileProcessor;
739
+ resolution;
740
+ resampleMethod;
741
+ colorStops;
742
+ readyPromiseInternal;
743
+ ready = false;
744
+ constructor(options) {
745
+ const { Cesium, rectangleDegrees, tileProcessor, tileSize, resolution, resampleMethod, colorStops, minimumLevel, maximumLevel, } = options;
746
+ this.Cesium = Cesium;
747
+ this.tileProcessor = tileProcessor;
748
+ this.tileWidth = tileSize;
749
+ this.tileHeight = tileSize;
750
+ this.resolution = resolution;
751
+ this.resampleMethod = resampleMethod;
752
+ this.colorStops = colorStops;
753
+ this.minimumLevel = minimumLevel ?? 0;
754
+ this.maximumLevel = maximumLevel;
755
+ this.rectangle = Cesium.Rectangle.fromDegrees(rectangleDegrees[0], rectangleDegrees[1], rectangleDegrees[2], rectangleDegrees[3]);
756
+ // Always use WebMercatorTilingScheme because the GeoTIFFTileProcessor
757
+ // interprets (x,y,z) as Web Mercator tile coordinates.
758
+ this.tilingScheme = new Cesium.WebMercatorTilingScheme();
759
+ this.errorEvent = new Cesium.Event();
760
+ this.ready = true;
761
+ this.readyPromiseInternal = Promise.resolve(true);
762
+ }
763
+ get tilingSchemeName() {
764
+ // Expose helper for debugging if needed.
765
+ return this.tilingScheme instanceof this.Cesium.WebMercatorTilingScheme
766
+ ? 'WebMercator'
767
+ : undefined;
768
+ }
769
+ get readyPromise() {
770
+ return this.readyPromiseInternal;
771
+ }
772
+ get tileCredits() {
773
+ return undefined;
774
+ }
775
+ getTileCredits(_x, _y, _level) {
776
+ return undefined;
777
+ }
778
+ get url() {
779
+ return undefined;
780
+ }
781
+ /**
782
+ * Flips a canvas vertically (Y-axis inversion) for Cesium.
783
+ * Creates a new canvas with the flipped content.
784
+ *
785
+ * @param sourceCanvas - The canvas to flip
786
+ * @param width - Width of the canvas
787
+ * @param height - Height of the canvas
788
+ * @returns A new canvas with vertically flipped content, or the source canvas if flipping fails
789
+ */
790
+ flipCanvasVertically(sourceCanvas, width, height) {
791
+ const flippedCanvas = document.createElement('canvas');
792
+ flippedCanvas.width = width;
793
+ flippedCanvas.height = height;
794
+ const flippedCtx = flippedCanvas.getContext('2d');
795
+ if (!flippedCtx) {
796
+ warn('v-map - cesium - failed to get 2d context for flip');
797
+ return sourceCanvas; // Fallback to source canvas
798
+ }
799
+ flippedCtx.translate(0, height);
800
+ flippedCtx.scale(1, -1);
801
+ flippedCtx.drawImage(sourceCanvas, 0, 0);
802
+ return flippedCanvas;
803
+ }
804
+ /**
805
+ * Creates a flipped ImageBitmap from RGBA data.
806
+ * Uses ImageBitmap for better performance when available.
807
+ *
808
+ * @param rgbaData - The RGBA pixel data
809
+ * @param sampleSize - Size of the tile (width and height)
810
+ * @returns A flipped ImageBitmap, or undefined if creation fails
811
+ */
812
+ async createFlippedImageBitmap(rgbaData, sampleSize) {
813
+ if (typeof createImageBitmap !== 'function') {
814
+ return undefined;
815
+ }
816
+ try {
817
+ // Create temporary canvas for Y-axis flip
818
+ const tempCanvas = document.createElement('canvas');
819
+ tempCanvas.width = sampleSize;
820
+ tempCanvas.height = sampleSize;
821
+ const tempCtx = tempCanvas.getContext('2d');
822
+ if (!tempCtx) {
823
+ throw new Error('Failed to get 2d context');
824
+ }
825
+ const imageData = tempCtx.createImageData(sampleSize, sampleSize);
826
+ imageData.data.set(rgbaData);
827
+ tempCtx.putImageData(imageData, 0, 0);
828
+ // Flip vertically for Cesium
829
+ const flippedCanvas = this.flipCanvasVertically(tempCanvas, sampleSize, sampleSize);
830
+ return await createImageBitmap(flippedCanvas);
831
+ }
832
+ catch (err) {
833
+ warn('v-map - cesium - createImageBitmap failed, falling back', err);
834
+ return undefined;
835
+ }
836
+ }
837
+ /**
838
+ * Creates a flipped image (ImageBitmap or Canvas) from RGBA data.
839
+ * Prefers ImageBitmap for better performance, falls back to Canvas.
840
+ *
841
+ * @param rgbaData - The RGBA pixel data
842
+ * @returns A flipped ImageBitmap or Canvas, or undefined if creation fails
843
+ */
844
+ async createFlippedImageFromRGBA(rgbaData) {
845
+ // Calculate actual sample size (may differ from tileWidth due to resolution)
846
+ const sampleSize = Math.ceil(this.tileWidth * this.resolution);
847
+ // Prefer ImageBitmap when available for better performance
848
+ const imageBitmap = await this.createFlippedImageBitmap(rgbaData, sampleSize);
849
+ if (imageBitmap) {
850
+ return imageBitmap;
851
+ }
852
+ // Fallback to Canvas
853
+ const canvas = document.createElement('canvas');
854
+ canvas.width = sampleSize;
855
+ canvas.height = sampleSize;
856
+ const ctx = canvas.getContext('2d');
857
+ if (!ctx) {
858
+ warn('v-map - cesium - unable to acquire canvas 2d context');
859
+ return undefined;
860
+ }
861
+ const imageData = ctx.createImageData(sampleSize, sampleSize);
862
+ imageData.data.set(rgbaData);
863
+ ctx.putImageData(imageData, 0, 0);
864
+ // Flip the canvas vertically for Cesium (Y-axis inversion)
865
+ return this.flipCanvasVertically(canvas, sampleSize, sampleSize);
866
+ }
867
+ async requestImage(x, y, level) {
868
+ if (!this.ready)
869
+ return undefined;
870
+ if (level < this.minimumLevel ||
871
+ (this.maximumLevel !== undefined && level > this.maximumLevel)) {
872
+ return undefined;
873
+ }
874
+ const params = {
875
+ x,
876
+ y,
877
+ z: level,
878
+ tileSize: this.tileWidth,
879
+ resolution: this.resolution,
880
+ resampleMethod: this.resampleMethod,
881
+ colorStops: this.colorStops,
882
+ };
883
+ let rgbaData = null;
884
+ try {
885
+ rgbaData = await this.tileProcessor.getTileData(params);
886
+ if (!rgbaData) {
887
+ log(`v-map - cesium - geotiff - requestImage(${x},${y},${level}): no data returned`);
888
+ return undefined;
889
+ }
890
+ log(`v-map - cesium - geotiff - requestImage(${x},${y},${level}): rgba ${rgbaData.length} bytes, sampleSize=${Math.ceil(this.tileWidth * this.resolution)}`);
891
+ }
892
+ catch (err) {
893
+ this.errorEvent.raiseEvent(err);
894
+ warn('v-map - cesium - getTileData - GeoTIFF tile request failed', err);
895
+ return undefined;
896
+ }
897
+ try {
898
+ const result = await this.createFlippedImageFromRGBA(rgbaData);
899
+ log(`v-map - cesium - geotiff - requestImage(${x},${y},${level}): result=${result?.constructor?.name ?? 'undefined'}, size=${result instanceof HTMLCanvasElement ? `${result.width}x${result.height}` : result instanceof ImageBitmap ? `${result.width}x${result.height}` : 'n/a'}`);
900
+ return result;
901
+ }
902
+ catch (err) {
903
+ this.errorEvent.raiseEvent(err);
904
+ warn('v-map - cesium - createFlippedImageFromRGBA - GeoTIFF tile request failed', err);
905
+ return undefined;
906
+ }
907
+ }
908
+ pickFeatures() {
909
+ return undefined;
910
+ }
911
+ }
912
+
913
+ const LOG_PREFIX = 'v-map - cesium - terrain-geotiff - ';
914
+ /**
915
+ * Custom Cesium Terrain Provider for GeoTIFF elevation data
916
+ *
917
+ * This provider loads a GeoTIFF file containing elevation data and provides
918
+ * it to Cesium's terrain system as a heightmap.
919
+ */
920
+ class CesiumGeoTIFFTerrainProvider {
921
+ Cesium;
922
+ image;
923
+ fromProjection = 'EPSG:4326';
924
+ sourceBounds = [0, 0, 0, 0];
925
+ wgs84Bounds = [0, 0, 0, 0];
926
+ width = 0;
927
+ height = 0;
928
+ noDataValue = 0;
929
+ ready = false;
930
+ _readyPromise;
931
+ heightmapWidth = 65;
932
+ heightmapHeight = 65;
933
+ proj4;
934
+ tilingScheme;
935
+ constructor(options) {
936
+ this.Cesium = options.Cesium;
937
+ // Initialize with GeographicTilingScheme (WGS84)
938
+ this.tilingScheme = new this.Cesium.GeographicTilingScheme();
939
+ // Start loading the GeoTIFF
940
+ this._readyPromise = this.initialize(options);
941
+ }
942
+ async initialize(options) {
943
+ try {
944
+ log(`${LOG_PREFIX}loadGeoTIFF: url=${options.url}`);
945
+ const [geotiffModule, { default: proj4 }, geokeysModule] = await Promise.all([
946
+ import('./geotiff-BEWxTIfH.js').then(function (n) { return n.g; }),
947
+ import('./index-RpJarvr_.js'),
948
+ import('./main-dist-CwnA7_Xn.js').then(function (n) { return n.m; }),
949
+ ]);
950
+ const source = await loadGeoTIFFSource(options.url, {
951
+ projection: options.projection,
952
+ forceProjection: options.forceProjection ?? false,
953
+ nodata: options.nodata,
954
+ }, {
955
+ geotiff: geotiffModule,
956
+ proj4,
957
+ geokeysToProj4: geokeysModule,
958
+ });
959
+ this.image = source.baseImage;
960
+ this.fromProjection = source.fromProjection;
961
+ this.sourceBounds = source.sourceBounds;
962
+ this.wgs84Bounds = source.wgs84Bounds;
963
+ this.width = source.width;
964
+ this.height = source.height;
965
+ this.noDataValue = source.noDataValue ?? 0;
966
+ this.proj4 = source.proj4; // Store proj4 instance with registered projections
967
+ log(`${LOG_PREFIX}loaded: projection=${this.fromProjection}, bounds=[${this.sourceBounds.map(v => v.toFixed(0)).join(',')}], wgs84=[${this.wgs84Bounds.map(v => v.toFixed(4)).join(',')}], size=${this.width}x${this.height}`);
968
+ this.ready = true;
969
+ return true;
970
+ }
971
+ catch (err) {
972
+ error(`${LOG_PREFIX}failed to load GeoTIFF:`, err);
973
+ this.ready = false;
974
+ return false;
975
+ }
976
+ }
977
+ /**
978
+ * Get the coverage rectangle in WGS84 coordinates
979
+ */
980
+ get rectangle() {
981
+ if (!this.ready || !this.wgs84Bounds) {
982
+ return this.Cesium.Rectangle.MAX_VALUE;
983
+ }
984
+ const [west, south, east, north] = this.wgs84Bounds;
985
+ return this.Cesium.Rectangle.fromDegrees(west, south, east, north);
986
+ }
987
+ /**
988
+ * Request tile geometry for a specific tile
989
+ */
990
+ async requestTileGeometry(x, y, level) {
991
+ if (!this.ready || !this.image) {
992
+ return undefined;
993
+ }
994
+ try {
995
+ // Get tile bounds in WGS84
996
+ const rectangle = this.tilingScheme.tileXYToRectangle(x, y, level);
997
+ let west = this.Cesium.Math.toDegrees(rectangle.west);
998
+ let south = this.Cesium.Math.toDegrees(rectangle.south);
999
+ let east = this.Cesium.Math.toDegrees(rectangle.east);
1000
+ let north = this.Cesium.Math.toDegrees(rectangle.north);
1001
+ // Get GeoTIFF bounds in WGS84
1002
+ const [geoWest, geoSouth, geoEast, geoNorth] = this.wgs84Bounds;
1003
+ // Check if tile intersects with GeoTIFF bounds
1004
+ if (east < geoWest ||
1005
+ west > geoEast ||
1006
+ north < geoSouth ||
1007
+ south > geoNorth) {
1008
+ // Tile is completely outside GeoTIFF bounds, return flat heightmap
1009
+ return this.createFlatHeightmap();
1010
+ }
1011
+ // Clamp tile bounds to GeoTIFF coverage area
1012
+ // This prevents transformation errors when the GeoTIFF projection
1013
+ // doesn't support the full WGS84 range (e.g., Mercator and poles)
1014
+ west = Math.max(geoWest, Math.min(geoEast, west));
1015
+ east = Math.max(geoWest, Math.min(geoEast, east));
1016
+ south = Math.max(geoSouth, Math.min(geoNorth, south));
1017
+ north = Math.max(geoSouth, Math.min(geoNorth, north));
1018
+ // Transform tile bounds to source projection
1019
+ // Use the stored proj4 instance that has the projection definitions
1020
+ const transformToSource = (coord) => {
1021
+ try {
1022
+ return this.proj4('EPSG:4326', this.fromProjection, coord);
1023
+ }
1024
+ catch (err) {
1025
+ warn(`${LOG_PREFIX}transform failed:`, err);
1026
+ return coord;
1027
+ }
1028
+ };
1029
+ const swSource = transformToSource([west, south]);
1030
+ const neSource = transformToSource([east, north]);
1031
+ // Calculate pixel coordinates in GeoTIFF
1032
+ const [srcWest, srcSouth, srcEast, srcNorth] = this.sourceBounds;
1033
+ const srcWidth = this.width;
1034
+ const srcHeight = this.height;
1035
+ const pixelWidth = srcEast - srcWest;
1036
+ const pixelHeight = srcNorth - srcSouth;
1037
+ const x0 = Math.floor(((swSource[0] - srcWest) / pixelWidth) * srcWidth);
1038
+ const y0 = Math.floor(((srcNorth - neSource[1]) / pixelHeight) * srcHeight);
1039
+ const x1 = Math.ceil(((neSource[0] - srcWest) / pixelWidth) * srcWidth);
1040
+ const y1 = Math.ceil(((srcNorth - swSource[1]) / pixelHeight) * srcHeight);
1041
+ // Clamp to image bounds
1042
+ const windowX = Math.max(0, Math.min(x0, srcWidth));
1043
+ const windowY = Math.max(0, Math.min(y0, srcHeight));
1044
+ const windowWidth = Math.max(1, Math.min(x1 - x0, srcWidth - windowX));
1045
+ const windowHeight = Math.max(1, Math.min(y1 - y0, srcHeight - windowY));
1046
+ // Read elevation data from GeoTIFF
1047
+ const rasterData = await this.image.readRasters({
1048
+ window: [
1049
+ windowX,
1050
+ windowY,
1051
+ windowX + windowWidth,
1052
+ windowY + windowHeight,
1053
+ ],
1054
+ width: this.heightmapWidth,
1055
+ height: this.heightmapHeight,
1056
+ resampleMethod: 'bilinear',
1057
+ });
1058
+ // Convert to heightmap array (first band contains elevation)
1059
+ const elevationData = rasterData[0];
1060
+ const buffer = new Float32Array(this.heightmapWidth * this.heightmapHeight);
1061
+ for (let i = 0; i < buffer.length; i++) {
1062
+ let value = elevationData[i];
1063
+ // Replace nodata values with 0
1064
+ if (value === this.noDataValue || !isFinite(value)) {
1065
+ value = 0;
1066
+ }
1067
+ buffer[i] = value;
1068
+ }
1069
+ // Create Cesium HeightmapTerrainData
1070
+ return new this.Cesium.HeightmapTerrainData({
1071
+ buffer,
1072
+ width: this.heightmapWidth,
1073
+ height: this.heightmapHeight,
1074
+ childTileMask: 0,
1075
+ structure: {
1076
+ heightScale: 1.0,
1077
+ heightOffset: 0.0,
1078
+ elementsPerHeight: 1,
1079
+ stride: 1,
1080
+ elementMultiplier: 1.0,
1081
+ },
1082
+ });
1083
+ }
1084
+ catch (err) {
1085
+ warn(`${LOG_PREFIX}failed to load tile geometry:`, err);
1086
+ return this.createFlatHeightmap();
1087
+ }
1088
+ }
1089
+ /**
1090
+ * Create a flat heightmap for tiles outside the GeoTIFF bounds
1091
+ */
1092
+ createFlatHeightmap() {
1093
+ const buffer = new Float32Array(this.heightmapWidth * this.heightmapHeight);
1094
+ buffer.fill(0);
1095
+ return new this.Cesium.HeightmapTerrainData({
1096
+ buffer,
1097
+ width: this.heightmapWidth,
1098
+ height: this.heightmapHeight,
1099
+ childTileMask: 0,
1100
+ });
1101
+ }
1102
+ /**
1103
+ * Get the availability of tiles
1104
+ */
1105
+ get availability() {
1106
+ // For now, we say all tiles are available
1107
+ // In a more sophisticated implementation, we'd track which tiles
1108
+ // intersect with the GeoTIFF bounds
1109
+ return undefined;
1110
+ }
1111
+ /**
1112
+ * Get the tiling scheme
1113
+ */
1114
+ getTilingScheme() {
1115
+ return this.tilingScheme;
1116
+ }
1117
+ /**
1118
+ * Get the maximum geometric error allowed at a specific level
1119
+ * Required by Cesium's TerrainProvider interface
1120
+ *
1121
+ * The geometric error is the difference (in meters) between the actual terrain
1122
+ * and the terrain approximation at this level. Higher levels have lower error.
1123
+ */
1124
+ getLevelMaximumGeometricError(level) {
1125
+ // Standard geometric error calculation for terrain providers
1126
+ // Based on Cesium's approach: error decreases exponentially with level
1127
+ // Formula: maximumRadius / (tileWidth * (2^level))
1128
+ const ellipsoid = this.tilingScheme.ellipsoid;
1129
+ const maximumRadius = ellipsoid.maximumRadius;
1130
+ const tileWidth = 65; // Standard heightmap width
1131
+ return maximumRadius / (tileWidth * Math.pow(2, level));
1132
+ }
1133
+ loadTileDataAvailability(_x, _y, _level) {
1134
+ return undefined;
1135
+ }
1136
+ /**
1137
+ * Check if tile data is available for a specific tile
1138
+ * Required by Cesium's TerrainProvider interface
1139
+ */
1140
+ getTileDataAvailable(x, y, level) {
1141
+ if (!this.ready) {
1142
+ return false;
1143
+ }
1144
+ // Check if tile intersects with GeoTIFF bounds
1145
+ const rectangle = this.tilingScheme.tileXYToRectangle(x, y, level);
1146
+ const west = this.Cesium.Math.toDegrees(rectangle.west);
1147
+ const south = this.Cesium.Math.toDegrees(rectangle.south);
1148
+ const east = this.Cesium.Math.toDegrees(rectangle.east);
1149
+ const north = this.Cesium.Math.toDegrees(rectangle.north);
1150
+ const [geoWest, geoSouth, geoEast, geoNorth] = this.wgs84Bounds;
1151
+ // Return true if tile intersects with GeoTIFF bounds
1152
+ return !(east < geoWest ||
1153
+ west > geoEast ||
1154
+ north < geoSouth ||
1155
+ south > geoNorth);
1156
+ }
1157
+ /**
1158
+ * Check if the provider is ready
1159
+ */
1160
+ get readyPromise() {
1161
+ return this._readyPromise;
1162
+ }
1163
+ /**
1164
+ * Get the credit to display
1165
+ */
1166
+ get credit() {
1167
+ return new this.Cesium.Credit('GeoTIFF Terrain');
1168
+ }
1169
+ /**
1170
+ * Check if the provider has water mask
1171
+ */
1172
+ get hasWaterMask() {
1173
+ return false;
1174
+ }
1175
+ /**
1176
+ * Check if the provider has vertex normals
1177
+ */
1178
+ get hasVertexNormals() {
1179
+ return false;
1180
+ }
1181
+ /**
1182
+ * Get the error event
1183
+ */
1184
+ get errorEvent() {
1185
+ return new this.Cesium.Event();
1186
+ }
1187
+ }
1188
+ /**
1189
+ * Factory function to create a CesiumGeoTIFFTerrainProvider
1190
+ */
1191
+ async function createCesiumGeoTIFFTerrainProvider(options) {
1192
+ const provider = new CesiumGeoTIFFTerrainProvider(options);
1193
+ await provider.readyPromise;
1194
+ return provider;
1195
+ }
1196
+
1197
+ // CesiumProvider.ts – relevante Ergänzungen
1198
+ const TERRAIN_GEOTIFF_LOG_PREFIX = 'v-map - cesium - terrain-geotiff - ';
1199
+ /**
1200
+ * Entfernt das von Cesium injectWidgetsCss() eingefügte CSS.
1201
+ * Funktioniert sowohl, wenn das Element eine ID hat,
1202
+ * als auch wenn es keine ID besitzt (neue Cesium‑Versionen).
1203
+ */
1204
+ function removeCesiumWidgetsCss(shadowRoot) {
1205
+ if (!shadowRoot)
1206
+ return;
1207
+ // NodeList → echtes Array konvertieren
1208
+ const styles = Array.from(shadowRoot.querySelectorAll('style'));
1209
+ for (const style of styles) {
1210
+ if (style.textContent?.includes('.cesium-credit-lightbox-overlay')) {
1211
+ style.remove(); // modernes DOM‑API
1212
+ // oder für sehr alte Browser:
1213
+ // style.parentNode?.removeChild(style);
1214
+ log('v-map - provider - cesium - Cesium‑Widget‑CSS entfernt');
1215
+ break; // wir haben das gesuchte Style‑Tag gefunden
1216
+ }
1217
+ }
1218
+ }
1219
+ class CesiumTerrainLayer {
1220
+ Cesium;
1221
+ viewer;
1222
+ provider;
1223
+ options;
1224
+ opacity = 1;
1225
+ previousProvider;
1226
+ constructor(Cesium, viewer, provider, options) {
1227
+ this.Cesium = Cesium;
1228
+ this.viewer = viewer;
1229
+ this.provider = provider;
1230
+ this.options = options ?? {};
1231
+ this.previousProvider = viewer.terrainProvider;
1232
+ this.viewer.terrainProvider = this.provider;
1233
+ }
1234
+ getOptions() {
1235
+ return this.options;
1236
+ }
1237
+ setOptions(options) {
1238
+ this.options = options;
1239
+ }
1240
+ getVisible() {
1241
+ return this.viewer.scene.globe.show;
1242
+ }
1243
+ setVisible(value) {
1244
+ this.viewer.scene.globe.show = value;
1245
+ }
1246
+ getOpacity() {
1247
+ return this.opacity;
1248
+ }
1249
+ setOpacity(value) {
1250
+ this.opacity = value;
1251
+ const globe = this.viewer.scene.globe;
1252
+ if (!globe.translucency) {
1253
+ try {
1254
+ globe.translucency = new this.Cesium.GlobeTranslucency();
1255
+ globe.translucency.enabled = true;
1256
+ }
1257
+ catch (e) {
1258
+ warn('Cesium terrain opacity not supported', e);
1259
+ return;
1260
+ }
1261
+ }
1262
+ globe.translucency.enabled = value < 1;
1263
+ globe.translucency.frontFaceAlpha = value;
1264
+ }
1265
+ getZIndex() {
1266
+ return 0;
1267
+ }
1268
+ async setZIndex(_zIndex) {
1269
+ return;
1270
+ }
1271
+ remove() {
1272
+ try {
1273
+ this.viewer.terrainProvider = this.previousProvider
1274
+ ? this.previousProvider
1275
+ : new this.Cesium.EllipsoidTerrainProvider();
1276
+ this.viewer.scene.globe.show = true;
1277
+ }
1278
+ catch (error) {
1279
+ warn('Cesium terrain reset failed', error);
1280
+ }
1281
+ }
1282
+ }
1283
+ class CesiumProvider {
1284
+ viewer;
1285
+ Cesium;
1286
+ layerManager;
1287
+ shadowRoot;
1288
+ layerGroups = new CesiumLayerGroups();
1289
+ layerManagerMutex = new AsyncMutex();
1290
+ layerErrorCallbacks = new Map();
1291
+ layerErrorCleanups = new Map();
1292
+ async init(options) {
1293
+ this.shadowRoot = options.shadowRoot;
1294
+ const sr = options.target.getRootNode() instanceof ShadowRoot
1295
+ ? options.target.getRootNode()
1296
+ : undefined;
1297
+ await injectWidgetsCss(sr);
1298
+ this.Cesium = await loadCesium();
1299
+ /*
1300
+ this.viewer = new this.Cesium.Viewer(container, {
1301
+ terrainProvider: await this.Cesium.createWorldTerrainAsync(),
1302
+ ...options,
1303
+ });
1304
+ */
1305
+ Cesium.Ion.defaultAccessToken = null;
1306
+ this.viewer = new this.Cesium.Viewer(options.target, {
1307
+ baseLayer: false,
1308
+ baseLayerPicker: false, // Remove the base layer picker if you don’t need to switch layers
1309
+ terrainProvider: new Cesium.EllipsoidTerrainProvider(), // Use a simple ellipsoid terrain
1310
+ });
1311
+ //this.viewer.scene.terrainProvider..removeAll();
1312
+ this.viewer.scene.primitives.removeAll();
1313
+ this.viewer.scene.backgroundColor = this.Cesium.Color.WHITE;
1314
+ this.viewer.scene.globe.baseColor = this.Cesium.Color.WHITE;
1315
+ this.viewer.scene.globe.depthTestAgainstTerrain = false;
1316
+ // this.viewer.terrainProvider = null;
1317
+ /*
1318
+ if (options.center) {
1319
+ await this.viewer.camera.flyTo({
1320
+ destination: this.Cesium.Cartesian3.fromDegrees(
1321
+ options.center.longitude,
1322
+ options.center.latitude,
1323
+ 1000,
1324
+ ),
1325
+ });
1326
+ }
1327
+ */
1328
+ this.layerManager = new LayerManager(this.Cesium, this.viewer);
1329
+ }
1330
+ async destroy() {
1331
+ removeCesiumWidgetsCss(this.shadowRoot);
1332
+ this.viewer?.destroy();
1333
+ this.viewer = undefined;
1334
+ }
1335
+ async createLayer(layerConfig, layerId) {
1336
+ let wrapper = null;
1337
+ switch (layerConfig.type) {
1338
+ case 'geojson': {
1339
+ const options = {
1340
+ // clampToGround: true,
1341
+ //fill: Cesium.Color.RED,
1342
+ };
1343
+ const geojsonConfig = layerConfig;
1344
+ const ds = await this.createGeoJSONLayer(geojsonConfig, options);
1345
+ wrapper = this.layerManager.addLayer(layerId, ds);
1346
+ wrapper.setOptions(options);
1347
+ break;
1348
+ }
1349
+ case 'osm': {
1350
+ const iLayer = await this.createOSMLayer(layerConfig);
1351
+ wrapper = this.layerManager.addLayer(layerId, iLayer);
1352
+ break;
1353
+ }
1354
+ case 'google': {
1355
+ const iLayer = await this.createGoogleLayer(layerConfig);
1356
+ wrapper = this.layerManager.addLayer(layerId, iLayer);
1357
+ break;
1358
+ }
1359
+ case 'terrain': {
1360
+ const terrainLayer = await this.createTerrainLayer(layerConfig);
1361
+ wrapper = this.layerManager.addCustomLayer(layerId, terrainLayer);
1362
+ break;
1363
+ }
1364
+ case 'xyz': {
1365
+ const iLayer = await this.createXYZLayer(layerConfig);
1366
+ wrapper = this.layerManager.addLayer(layerId, iLayer);
1367
+ break;
1368
+ }
1369
+ case 'wms': {
1370
+ const iLayer = await this.addWMSLayer(layerConfig);
1371
+ wrapper = this.layerManager.addLayer(layerId, iLayer);
1372
+ break;
1373
+ }
1374
+ case 'wcs': {
1375
+ const iLayer = await this.createWCSLayer(layerConfig);
1376
+ wrapper = this.layerManager.addLayer(layerId, iLayer);
1377
+ break;
1378
+ }
1379
+ case 'arcgis': {
1380
+ await this.addArcGISLayer(layerConfig);
1381
+ //todo wrapper = this.layerManager.addLayer(layerId, iLayer);
1382
+ break;
1383
+ }
1384
+ case 'wfs': {
1385
+ const options = { clampToGround: true };
1386
+ const wfsConfig = layerConfig;
1387
+ const ds = await this.createWFSLayer(wfsConfig, options);
1388
+ wrapper = this.layerManager.addLayer(layerId, ds);
1389
+ wrapper.setOptions(options);
1390
+ break;
1391
+ }
1392
+ case 'wkt': {
1393
+ const options = { clampToGround: true };
1394
+ const wktConfig = layerConfig;
1395
+ const ds = await this.createWKTLayer(wktConfig, options);
1396
+ wrapper = this.layerManager.addLayer(layerId, ds);
1397
+ wrapper.setOptions(options);
1398
+ break;
1399
+ }
1400
+ case 'geotiff': {
1401
+ const iLayer = await this.createGeoTIFFLayer(layerConfig);
1402
+ wrapper = this.layerManager.addLayer(layerId, iLayer);
1403
+ break;
1404
+ }
1405
+ case 'tile3d': {
1406
+ const tileset = await this.createTile3DLayer(layerConfig);
1407
+ wrapper = this.layerManager.addLayer(layerId, tileset);
1408
+ const tile3dConfig = layerConfig;
1409
+ wrapper.setOptions(tile3dConfig.tilesetOptions ?? {});
1410
+ if (tile3dConfig.cesiumStyle && 'setStyle' in wrapper) {
1411
+ wrapper.setStyle(tile3dConfig.cesiumStyle);
1412
+ }
1413
+ break;
1414
+ }
1415
+ case 'terrain-geotiff': {
1416
+ const terrainLayer = await this.createGeoTIFFTerrainLayer(layerConfig);
1417
+ wrapper = this.layerManager.addCustomLayer(layerId, terrainLayer);
1418
+ break;
1419
+ }
1420
+ default:
1421
+ throw new Error(`Unsupported layer type: ${layerConfig.type}`);
1422
+ }
1423
+ if (!wrapper)
1424
+ return null;
1425
+ // zIndex/Opacity/Visible zuerst auf dem Layer anwenden (bleiben „Originalzustand“ der Gruppe)
1426
+ const commonProps = layerConfig;
1427
+ if (commonProps.zIndex !== undefined)
1428
+ await wrapper.setZIndex(commonProps.zIndex);
1429
+ if (commonProps.opacity !== undefined)
1430
+ wrapper.setOpacity(commonProps.opacity);
1431
+ if (commonProps.visible !== undefined)
1432
+ wrapper.setVisible(commonProps.visible);
1433
+ return wrapper;
1434
+ }
1435
+ // ---------- Layer anlegen (mit Group & Basemap-Key) ----------
1436
+ async addLayerToGroup(layerConfig) {
1437
+ return await this.layerManagerMutex.runExclusive(async () => {
1438
+ const layerId = crypto.randomUUID();
1439
+ const wrapper = await this.createLayer(layerConfig, layerId);
1440
+ // >>> In Gruppenverwaltung registrieren (inkl. Basemap-Key)
1441
+ const elementId = layerConfig.layerElementId ??
1442
+ layerConfig.elementId ??
1443
+ null;
1444
+ this.layerGroups.addLayerToGroup(layerConfig.groupId, typeof layerConfig.groupVisible !== undefined
1445
+ ? layerConfig.groupVisible
1446
+ : true, {
1447
+ id: layerId,
1448
+ elementId,
1449
+ layer: wrapper,
1450
+ });
1451
+ // Regeln anwenden (sichtbar/basemap)
1452
+ this.layerGroups.apply();
1453
+ return layerId;
1454
+ });
1455
+ }
1456
+ // ---------- Basemap-API analog deck ----------
1457
+ async setBaseLayer(groupId, layerElementId) {
1458
+ await this.layerManagerMutex.runExclusive(async () => {
1459
+ this.layerGroups.setBasemap(groupId, layerElementId ?? null);
1460
+ this.layerGroups.apply();
1461
+ });
1462
+ }
1463
+ // Optional: Helper wie in deck.addBaseLayer(...)
1464
+ async addBaseLayer(layerConfig, basemapid, layerElementId) {
1465
+ if (!layerElementId || !basemapid)
1466
+ return null;
1467
+ return await this.layerManagerMutex.runExclusive(async () => {
1468
+ const layerId = crypto.randomUUID();
1469
+ const wrapper = await this.createLayer(layerConfig, layerId);
1470
+ this.layerGroups.addLayerToGroup(layerConfig.groupId, typeof layerConfig.groupVisible !== undefined
1471
+ ? layerConfig.groupVisible
1472
+ : true, {
1473
+ id: layerId,
1474
+ elementId: layerElementId,
1475
+ layer: wrapper,
1476
+ });
1477
+ this.layerGroups.setBasemap(layerConfig.groupId ?? 'basemap', basemapid);
1478
+ this.layerGroups.apply();
1479
+ return layerId;
1480
+ });
1481
+ }
1482
+ async ensureGroup(groupId, visible, _opts) {
1483
+ this.layerGroups.ensureGroup(groupId, visible);
1484
+ }
1485
+ // ---------- Sichtbarkeit/Z-Index/Opacity bleiben wie gehabt ----------
1486
+ async setGroupVisible(groupId, visible) {
1487
+ this.layerGroups.setGroupVisible(groupId, visible);
1488
+ this.layerGroups.apply();
1489
+ }
1490
+ // ── Runtime error listeners ──────────────────────────────────────
1491
+ onLayerError(layerId, callback) {
1492
+ this.layerErrorCallbacks.set(layerId, callback);
1493
+ this.attachCesiumErrorListeners(layerId);
1494
+ }
1495
+ offLayerError(layerId) {
1496
+ this.layerErrorCleanups.get(layerId)?.();
1497
+ this.layerErrorCleanups.delete(layerId);
1498
+ this.layerErrorCallbacks.delete(layerId);
1499
+ }
1500
+ attachCesiumErrorListeners(layerId) {
1501
+ this.layerErrorCleanups.get(layerId)?.();
1502
+ const cb = this.layerErrorCallbacks.get(layerId);
1503
+ if (!cb)
1504
+ return;
1505
+ const iLayer = this.layerManager.getLayer(layerId);
1506
+ if (!iLayer)
1507
+ return;
1508
+ const cleanups = [];
1509
+ const handler = () => { cb({ type: 'network', message: 'Tile load error' }); };
1510
+ // ImageryLayer: access provider.errorEvent
1511
+ const nativeLayer = iLayer._imageryLayer;
1512
+ if (nativeLayer?.imageryProvider?.errorEvent) {
1513
+ const unsub = nativeLayer.imageryProvider.errorEvent.addEventListener(handler);
1514
+ cleanups.push(unsub);
1515
+ }
1516
+ // Cesium3DTileset: tileFailed event
1517
+ const tileset = iLayer._tileset;
1518
+ if (tileset?.tileFailed) {
1519
+ const unsub = tileset.tileFailed.addEventListener(handler);
1520
+ cleanups.push(unsub);
1521
+ }
1522
+ if (cleanups.length > 0) {
1523
+ this.layerErrorCleanups.set(layerId, () => cleanups.forEach(fn => fn()));
1524
+ }
1525
+ }
1526
+ async removeLayer(layerId) {
1527
+ if (!layerId)
1528
+ return;
1529
+ this.offLayerError(layerId);
1530
+ await this.layerManagerMutex.runExclusive(async () => {
1531
+ this.layerManager.removeLayer(layerId);
1532
+ this.layerGroups.removeLayer(layerId, true);
1533
+ this.layerGroups.apply();
1534
+ });
1535
+ }
1536
+ // updateLayer, setOpacity, setZIndex, setVisible bleiben – du änderst damit den
1537
+ // „Originalzustand“ der Layer. Danach LayerGroups.apply() aufrufen, damit
1538
+ // Gruppen-/Basemap-Regeln sofort wieder durchgesetzt werden:
1539
+ async setOpacity(layerId, opacity) {
1540
+ this.layerManager.setOpacity(layerId, opacity);
1541
+ this.layerGroups.apply();
1542
+ }
1543
+ async setVisible(layerId, visible) {
1544
+ this.layerManager.setVisible(layerId, visible);
1545
+ this.layerGroups.apply();
1546
+ }
1547
+ async setZIndex(layerId, zIndex) {
1548
+ // Note: layerManager.setZIndex calls layer.setZIndex which is async (returns Promise<void>)
1549
+ // even though the manager method itself is not marked as async. The await is kept here
1550
+ // for future compatibility when the manager method becomes properly async.
1551
+ await this.layerManager.setZIndex(layerId, zIndex);
1552
+ // Z-Order ist unabhängig von Basemap/Group-Visible, aber apply() schadet nicht
1553
+ this.layerGroups.apply();
1554
+ }
1555
+ // ========== Enhanced Styling Helper Methods ==========
1556
+ /**
1557
+ * Apply Geostyler styling to a GeoJsonDataSource
1558
+ */
1559
+ applyGeostylerStyling(dataSource, geostylerStyle) {
1560
+ dataSource.__vmapLockOpacity = true;
1561
+ // Helper to extract static value from GeoStyler property
1562
+ const getValue = (prop, defaultValue) => {
1563
+ if (prop === undefined || prop === null)
1564
+ return defaultValue;
1565
+ // If it's a GeoStyler function object, we can't evaluate it here - return default
1566
+ if (typeof prop === 'object' && prop !== null && 'name' in prop)
1567
+ return defaultValue;
1568
+ return prop;
1569
+ };
1570
+ const toNumber = (value, fallback) => {
1571
+ if (value == null)
1572
+ return fallback;
1573
+ if (typeof value === 'number')
1574
+ return value;
1575
+ const n = Number(value);
1576
+ return Number.isFinite(n) ? n : fallback;
1577
+ };
1578
+ const entities = dataSource.entities.values;
1579
+ if (geostylerStyle.rules) {
1580
+ for (const rule of geostylerStyle.rules) {
1581
+ if (rule.symbolizers) {
1582
+ for (const symbolizer of rule.symbolizers) {
1583
+ for (let i = 0; i < entities.length; i++) {
1584
+ const entity = entities[i];
1585
+ switch (symbolizer.kind) {
1586
+ case 'Fill':
1587
+ if (entity.polygon) {
1588
+ const fillColor = getValue(symbolizer.color, 'rgba(0,100,255,0.3)');
1589
+ const fillOpacity = toNumber(getValue(symbolizer.opacity, 0.3), 0.3);
1590
+ const outlineColor = getValue(symbolizer.outlineColor, 'rgba(0,100,255,1)');
1591
+ const outlineWidth = getValue(symbolizer.outlineWidth, 1);
1592
+ let polygonColor = this.parseCesiumColor(fillColor, this.Cesium.Color.BLUE.withAlpha(0.3));
1593
+ if (fillOpacity !== undefined && fillOpacity !== null) {
1594
+ polygonColor = this.applyCesiumOpacity(polygonColor, fillOpacity);
1595
+ }
1596
+ //outline color
1597
+ const outlineCesiumColor = this.parseCesiumColor(outlineColor, this.Cesium.Color.BLUE);
1598
+ log('v-map - provider - cesium - applyGeostylerStyling: Fill', {
1599
+ fillColor,
1600
+ fillOpacity,
1601
+ computedFill: polygonColor?.toString?.(),
1602
+ outlineColor,
1603
+ outlineWidth,
1604
+ });
1605
+ //fill
1606
+ entity.polygon.fill = new this.Cesium.ConstantProperty(true);
1607
+ //fill color
1608
+ entity.polygon.material =
1609
+ new this.Cesium.ColorMaterialProperty(polygonColor);
1610
+ //outline
1611
+ entity.polygon.outline = new this.Cesium.ConstantProperty(true);
1612
+ entity.polygon.outlineColor =
1613
+ new this.Cesium.ConstantProperty(outlineCesiumColor);
1614
+ entity.polygon.outlineWidth =
1615
+ new this.Cesium.ConstantProperty(outlineWidth);
1616
+ //entity.polygon.height = new this.Cesium.ConstantProperty(0);
1617
+ //
1618
+ entity.polygon.extrudedHeight = undefined;
1619
+ entity.polygon.heightReference =
1620
+ new this.Cesium.ConstantProperty(this.Cesium.HeightReference.CLAMP_TO_GROUND);
1621
+ entity.polygon.perPositionHeight =
1622
+ new this.Cesium.ConstantProperty(false);
1623
+ entity.polygon.classificationType =
1624
+ new this.Cesium.ConstantProperty(this.Cesium.ClassificationType.BOTH);
1625
+ }
1626
+ break;
1627
+ case 'Line':
1628
+ if (entity.polyline) {
1629
+ const lineColor = getValue(symbolizer.color, 'rgba(0,100,255,1)');
1630
+ const lineWidth = toNumber(getValue(symbolizer.width, 2), 2);
1631
+ const lineOpacity = toNumber(getValue(symbolizer.opacity, 1), 1);
1632
+ let materialColor = this.parseCesiumColor(lineColor, this.Cesium.Color.BLUE);
1633
+ if (lineOpacity !== undefined && lineOpacity !== null) {
1634
+ materialColor = this.applyCesiumOpacity(materialColor, lineOpacity);
1635
+ }
1636
+ log('v-map - provider - cesium - applyGeostylerStyling: Line', {
1637
+ lineColor,
1638
+ lineOpacity,
1639
+ computedColor: materialColor?.toString?.(),
1640
+ lineWidth,
1641
+ });
1642
+ entity.polyline.material =
1643
+ new this.Cesium.ColorMaterialProperty(materialColor);
1644
+ entity.polyline.width = new this.Cesium.ConstantProperty(lineWidth);
1645
+ }
1646
+ break;
1647
+ case 'Mark':
1648
+ if (entity.point) {
1649
+ const pointColor = getValue(symbolizer.color, 'rgba(0,100,255,1)');
1650
+ const pointRadius = toNumber(getValue(symbolizer.radius, 6), 6);
1651
+ const pointOpacity = toNumber(getValue(symbolizer.opacity, 1), 1);
1652
+ let materialColor = this.parseCesiumColor(pointColor, this.Cesium.Color.BLUE);
1653
+ if (pointOpacity !== undefined && pointOpacity !== null) {
1654
+ materialColor = this.applyCesiumOpacity(materialColor, pointOpacity);
1655
+ }
1656
+ log('v-map - provider - cesium - applyGeostylerStyling: Mark', {
1657
+ pointColor,
1658
+ pointOpacity,
1659
+ computedColor: materialColor?.toString?.(),
1660
+ pointRadius,
1661
+ });
1662
+ entity.point.color = new this.Cesium.ConstantProperty(materialColor);
1663
+ entity.point.pixelSize = new this.Cesium.ConstantProperty(pointRadius);
1664
+ }
1665
+ break;
1666
+ case 'Icon':
1667
+ if (entity.point) {
1668
+ const iconSrc = getValue(symbolizer.image);
1669
+ const iconSize = toNumber(getValue(symbolizer.size, 32), 32);
1670
+ const iconOpacity = toNumber(getValue(symbolizer.opacity, 1), 1);
1671
+ if (iconSrc && typeof iconSrc === 'string') {
1672
+ entity.billboard = new this.Cesium.BillboardGraphics({
1673
+ image: new this.Cesium.ConstantProperty(iconSrc),
1674
+ width: new this.Cesium.ConstantProperty(iconSize),
1675
+ height: new this.Cesium.ConstantProperty(iconSize),
1676
+ verticalOrigin: new this.Cesium.ConstantProperty(this.Cesium.VerticalOrigin.BOTTOM),
1677
+ color: iconOpacity !== undefined && iconOpacity !== null
1678
+ ? new this.Cesium.ConstantProperty(this.Cesium.Color.WHITE.withAlpha(iconOpacity))
1679
+ : undefined,
1680
+ });
1681
+ entity.point.show = new this.Cesium.ConstantProperty(false);
1682
+ log('v-map - provider - cesium - applyGeostylerStyling: Icon', {
1683
+ iconSrc,
1684
+ iconSize,
1685
+ iconOpacity,
1686
+ });
1687
+ }
1688
+ }
1689
+ break;
1690
+ case 'Text':
1691
+ const labelExpr = symbolizer.label;
1692
+ const labelProp = typeof labelExpr === 'string' ? labelExpr : undefined;
1693
+ if (labelProp &&
1694
+ entity.properties &&
1695
+ entity.properties[labelProp]) {
1696
+ const textColor = getValue(symbolizer.color, '#000000');
1697
+ const textSize = toNumber(getValue(symbolizer.size, 12), 12);
1698
+ const textOpacity = toNumber(getValue(symbolizer.opacity, 1), 1);
1699
+ let labelColor = this.parseCesiumColor(textColor, this.Cesium.Color.WHITE);
1700
+ if (textOpacity !== undefined && textOpacity !== null) {
1701
+ labelColor = this.applyCesiumOpacity(labelColor, textOpacity);
1702
+ }
1703
+ log('v-map - provider - cesium - applyGeostylerStyling: Text', {
1704
+ labelProp,
1705
+ textColor,
1706
+ textOpacity,
1707
+ computedColor: labelColor?.toString?.(),
1708
+ textSize,
1709
+ });
1710
+ const textValue = entity.properties[labelProp]?.getValue?.(this.viewer.clock.currentTime) ??
1711
+ entity.properties[labelProp]?._value ??
1712
+ '';
1713
+ entity.label = new this.Cesium.LabelGraphics({
1714
+ text: new this.Cesium.ConstantProperty(String(textValue)),
1715
+ font: new this.Cesium.ConstantProperty(`${textSize}px Arial`),
1716
+ fillColor: new this.Cesium.ConstantProperty(labelColor),
1717
+ verticalOrigin: new this.Cesium.ConstantProperty(this.Cesium.VerticalOrigin.BOTTOM),
1718
+ });
1719
+ }
1720
+ break;
1721
+ }
1722
+ }
1723
+ }
1724
+ }
1725
+ }
1726
+ }
1727
+ }
1728
+ /**
1729
+ * Convert CSS color to Cesium Color
1730
+ */
1731
+ parseCesiumColor(color, defaultColor) {
1732
+ if (!color)
1733
+ return defaultColor;
1734
+ // Handle hex colors
1735
+ if (color.startsWith('#')) {
1736
+ return this.Cesium.Color.fromCssColorString(color);
1737
+ }
1738
+ // Handle rgba/rgb colors
1739
+ if (color.includes('rgb')) {
1740
+ return this.Cesium.Color.fromCssColorString(color);
1741
+ }
1742
+ // Try to parse as CSS color string
1743
+ try {
1744
+ return this.Cesium.Color.fromCssColorString(color);
1745
+ }
1746
+ catch {
1747
+ return defaultColor;
1748
+ }
1749
+ }
1750
+ /**
1751
+ * Apply opacity to Cesium color
1752
+ */
1753
+ applyCesiumOpacity(color, opacity) {
1754
+ if (!color)
1755
+ return color;
1756
+ return color.withAlpha(opacity);
1757
+ }
1758
+ /**
1759
+ * Create Cesium styling options from StyleConfig
1760
+ */
1761
+ createCesiumStyle(style = {}) {
1762
+ // Default colors
1763
+ const defaultFillColor = this.Cesium.Color.BLUE.withAlpha(0.3);
1764
+ const defaultStrokeColor = this.Cesium.Color.BLUE;
1765
+ const defaultPointColor = this.Cesium.Color.BLUE;
1766
+ // Parse colors
1767
+ const fillColor = this.parseCesiumColor(style.fillColor, defaultFillColor);
1768
+ const strokeColor = this.parseCesiumColor(style.strokeColor, defaultStrokeColor);
1769
+ const pointColor = this.parseCesiumColor(style.pointColor, defaultPointColor);
1770
+ // Apply opacity
1771
+ const finalFillColor = style.fillOpacity !== undefined
1772
+ ? this.applyCesiumOpacity(fillColor, style.fillOpacity)
1773
+ : fillColor;
1774
+ const finalStrokeColor = style.strokeOpacity !== undefined
1775
+ ? this.applyCesiumOpacity(strokeColor, style.strokeOpacity)
1776
+ : strokeColor;
1777
+ const finalPointColor = style.pointOpacity !== undefined
1778
+ ? this.applyCesiumOpacity(pointColor, style.pointOpacity)
1779
+ : pointColor;
1780
+ return {
1781
+ // Polygon styling
1782
+ fill: true,
1783
+ fillColor: finalFillColor,
1784
+ outline: true,
1785
+ outlineColor: finalStrokeColor,
1786
+ outlineWidth: style.strokeWidth ?? 2,
1787
+ extrudedHeight: style.extrudeHeight,
1788
+ heightReference: style.zOffset
1789
+ ? this.Cesium.HeightReference.RELATIVE_TO_GROUND
1790
+ : this.Cesium.HeightReference.CLAMP_TO_GROUND,
1791
+ // Point styling
1792
+ pixelSize: style.pointRadius ?? 8,
1793
+ color: finalPointColor,
1794
+ scaleByDistance: style.pointRadius
1795
+ ? new this.Cesium.NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5)
1796
+ : undefined,
1797
+ // Line styling
1798
+ width: style.strokeWidth ?? 2,
1799
+ clampToGround: !style.zOffset,
1800
+ // Text/Label styling
1801
+ labelText: style.textProperty,
1802
+ labelFont: style.textSize
1803
+ ? `${style.textSize}pt monospace`
1804
+ : '12pt monospace',
1805
+ labelFillColor: style.textColor
1806
+ ? this.parseCesiumColor(style.textColor, this.Cesium.Color.WHITE)
1807
+ : this.Cesium.Color.WHITE,
1808
+ labelOutlineColor: style.textHaloColor
1809
+ ? this.parseCesiumColor(style.textHaloColor, this.Cesium.Color.BLACK)
1810
+ : this.Cesium.Color.BLACK,
1811
+ labelOutlineWidth: style.textHaloWidth ?? 1,
1812
+ labelPixelOffset: style.textOffset
1813
+ ? new this.Cesium.Cartesian2(style.textOffset[0], style.textOffset[1])
1814
+ : this.Cesium.Cartesian2.ZERO,
1815
+ // 3D specific
1816
+ height: style.zOffset ?? 0,
1817
+ };
1818
+ }
1819
+ /**
1820
+ * Apply enhanced styling to a GeoJsonDataSource
1821
+ */
1822
+ applyEnhancedStyling(dataSource, style = {}) {
1823
+ const cesiumStyle = this.createCesiumStyle(style);
1824
+ const entities = dataSource.entities.values;
1825
+ for (let i = 0; i < entities.length; i++) {
1826
+ const entity = entities[i];
1827
+ let finalStyle = cesiumStyle;
1828
+ if (style.styleFunction && entity.properties) {
1829
+ const feature = {
1830
+ properties: entity.properties._propertyNames.reduce((props, name) => {
1831
+ props[name] = entity.properties[name]?._value;
1832
+ return props;
1833
+ }, {}),
1834
+ geometry: entity,
1835
+ };
1836
+ const conditionalStyle = style.styleFunction(feature);
1837
+ if (conditionalStyle) {
1838
+ finalStyle = {
1839
+ ...cesiumStyle,
1840
+ ...this.createCesiumStyle(conditionalStyle),
1841
+ };
1842
+ }
1843
+ }
1844
+ if (entity.polygon) {
1845
+ entity.polygon.fill = new this.Cesium.ConstantProperty(finalStyle.fill);
1846
+ entity.polygon.material = new this.Cesium.ColorMaterialProperty(finalStyle.fillColor);
1847
+ entity.polygon.outline = new this.Cesium.ConstantProperty(finalStyle.outline);
1848
+ entity.polygon.outlineColor = new this.Cesium.ConstantProperty(finalStyle.outlineColor);
1849
+ entity.polygon.outlineWidth = new this.Cesium.ConstantProperty(finalStyle.outlineWidth);
1850
+ entity.polygon.height =
1851
+ finalStyle.height !== undefined
1852
+ ? new this.Cesium.ConstantProperty(finalStyle.height)
1853
+ : undefined;
1854
+ entity.polygon.extrudedHeight =
1855
+ finalStyle.extrudedHeight !== undefined
1856
+ ? new this.Cesium.ConstantProperty(finalStyle.extrudedHeight)
1857
+ : undefined;
1858
+ entity.polygon.heightReference =
1859
+ finalStyle.heightReference !== undefined
1860
+ ? new this.Cesium.ConstantProperty(finalStyle.heightReference)
1861
+ : undefined;
1862
+ }
1863
+ if (entity.polyline) {
1864
+ entity.polyline.material = new this.Cesium.ColorMaterialProperty(finalStyle.outlineColor);
1865
+ entity.polyline.width = new this.Cesium.ConstantProperty(finalStyle.width);
1866
+ entity.polyline.clampToGround = new this.Cesium.ConstantProperty(finalStyle.clampToGround);
1867
+ }
1868
+ if (entity.point) {
1869
+ entity.point.pixelSize = new this.Cesium.ConstantProperty(finalStyle.pixelSize);
1870
+ entity.point.color = new this.Cesium.ConstantProperty(finalStyle.color);
1871
+ const scaleByDistance = finalStyle.scaleByDistance;
1872
+ entity.point.scaleByDistance = scaleByDistance
1873
+ ? new this.Cesium.ConstantProperty(scaleByDistance)
1874
+ : undefined;
1875
+ if (style.iconUrl) {
1876
+ entity.billboard = new this.Cesium.BillboardGraphics({
1877
+ image: new this.Cesium.ConstantProperty(style.iconUrl),
1878
+ width: new this.Cesium.ConstantProperty(style.iconSize ? style.iconSize[0] : 32),
1879
+ height: new this.Cesium.ConstantProperty(style.iconSize ? style.iconSize[1] : 32),
1880
+ verticalOrigin: new this.Cesium.ConstantProperty(this.Cesium.VerticalOrigin.BOTTOM),
1881
+ scaleByDistance: scaleByDistance
1882
+ ? new this.Cesium.ConstantProperty(scaleByDistance)
1883
+ : undefined,
1884
+ });
1885
+ entity.point.show = new this.Cesium.ConstantProperty(false);
1886
+ }
1887
+ }
1888
+ if (style.textProperty &&
1889
+ entity.properties &&
1890
+ entity.properties[style.textProperty]) {
1891
+ const textValue = entity.properties[style.textProperty]?.getValue?.(this.viewer.clock.currentTime) ??
1892
+ entity.properties[style.textProperty]?._value ??
1893
+ '';
1894
+ entity.label = new this.Cesium.LabelGraphics({
1895
+ text: new this.Cesium.ConstantProperty(String(textValue)),
1896
+ font: new this.Cesium.ConstantProperty(finalStyle.labelFont),
1897
+ fillColor: new this.Cesium.ConstantProperty(finalStyle.labelFillColor),
1898
+ outlineColor: new this.Cesium.ConstantProperty(finalStyle.labelOutlineColor),
1899
+ outlineWidth: new this.Cesium.ConstantProperty(finalStyle.labelOutlineWidth),
1900
+ pixelOffset: new this.Cesium.ConstantProperty(finalStyle.labelPixelOffset),
1901
+ verticalOrigin: new this.Cesium.ConstantProperty(this.Cesium.VerticalOrigin.BOTTOM),
1902
+ });
1903
+ }
1904
+ }
1905
+ }
1906
+ async createWKTLayer(config, options) {
1907
+ const geoJsonData = await this.wktToGeoJSON(config);
1908
+ const dataSource = await this.Cesium.GeoJsonDataSource.load(geoJsonData, options);
1909
+ // Apply geostyler style if provided, otherwise use enhanced styling
1910
+ if (config.geostylerStyle) {
1911
+ this.applyGeostylerStyling(dataSource, config.geostylerStyle);
1912
+ }
1913
+ else if (config.style) {
1914
+ this.applyEnhancedStyling(dataSource, config.style);
1915
+ }
1916
+ return dataSource;
1917
+ }
1918
+ async wktToGeoJSON(config) {
1919
+ const wktText = await this.resolveWktText(config);
1920
+ const wellknownModule = await import('./index-BUHa4Jj0.js').then(function (n) { return n.i; });
1921
+ const parseFn = typeof wellknownModule.default === 'function'
1922
+ ? wellknownModule.default
1923
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- wellknown has inconsistent module exports across bundlers
1924
+ : wellknownModule.parse;
1925
+ if (typeof parseFn !== 'function') {
1926
+ throw new Error('wellknown parser not available');
1927
+ }
1928
+ const geometry = parseFn(wktText);
1929
+ if (!geometry) {
1930
+ throw new Error('Failed to parse WKT');
1931
+ }
1932
+ return {
1933
+ type: 'FeatureCollection',
1934
+ features: [
1935
+ {
1936
+ type: 'Feature',
1937
+ properties: {},
1938
+ geometry,
1939
+ },
1940
+ ],
1941
+ };
1942
+ }
1943
+ async resolveWktText(config) {
1944
+ if (config.wkt)
1945
+ return config.wkt;
1946
+ if (config.url) {
1947
+ const response = await fetch(config.url);
1948
+ if (!response.ok)
1949
+ throw new Error(`Failed to fetch WKT: ${response.status}`);
1950
+ return await response.text();
1951
+ }
1952
+ throw new Error('Either wkt or url must be provided');
1953
+ }
1954
+ async createGeoJSONLayer(config, options) {
1955
+ let geojson_or_url = null;
1956
+ if (config.geojson) {
1957
+ geojson_or_url = JSON.parse(config.geojson);
1958
+ }
1959
+ else {
1960
+ geojson_or_url = config.url;
1961
+ }
1962
+ //https://cesium.com/learn/ion-sdk/ref-doc/GeoJsonDataSource.html
1963
+ const dataSource = await this.Cesium.GeoJsonDataSource.load(geojson_or_url, options);
1964
+ // Apply geostyler style if provided, otherwise use enhanced styling
1965
+ if (config.geostylerStyle) {
1966
+ this.applyGeostylerStyling(dataSource, config.geostylerStyle);
1967
+ }
1968
+ else if (config.style) {
1969
+ this.applyEnhancedStyling(dataSource, config.style);
1970
+ }
1971
+ return dataSource;
1972
+ }
1973
+ async createWFSLayer(config, options) {
1974
+ // Fetch GeoJSON from WFS server
1975
+ const geojson = await this.fetchWFSFromUrl(config);
1976
+ // Load GeoJSON into Cesium DataSource
1977
+ const dataSource = await this.Cesium.GeoJsonDataSource.load(geojson, options);
1978
+ // Apply geostyler style if provided, otherwise use enhanced styling
1979
+ if (config.geostylerStyle) {
1980
+ this.applyGeostylerStyling(dataSource, config.geostylerStyle);
1981
+ }
1982
+ else if (config.style) {
1983
+ this.applyEnhancedStyling(dataSource, config.style);
1984
+ }
1985
+ return dataSource;
1986
+ }
1987
+ async createOSMLayer(cfg) {
1988
+ return new this.Cesium.ImageryLayer(new this.Cesium.OpenStreetMapImageryProvider({
1989
+ url: cfg.url || 'https://a.tile.openstreetmap.org',
1990
+ }));
1991
+ }
1992
+ async createGoogleLayer(config) {
1993
+ if (!config.apiKey) {
1994
+ throw new Error("Google-Layer benötigt 'apiKey' (Google Maps Platform).");
1995
+ }
1996
+ // Load Google Maps JavaScript API
1997
+ await this.loadGoogleMapsApi(config.apiKey, {
1998
+ language: config.language,
1999
+ region: config.region,
2000
+ libraries: config.libraries,
2001
+ });
2002
+ const mapType = config.mapType || 'roadmap';
2003
+ const googleMapTypeId = this.getGoogleMapTypeId(mapType);
2004
+ // Use a simpler approach with UrlTemplateImageryProvider and custom URL generator
2005
+ const Cesium = this.Cesium;
2006
+ // Create a custom URL template that we'll handle in the urlSchemeZeroPadding function
2007
+ const customUrlTemplate = 'https://maps.googleapis.com/maps/api/staticmap?template';
2008
+ const googleImageryProvider = new Cesium.UrlTemplateImageryProvider({
2009
+ url: customUrlTemplate,
2010
+ maximumLevel: config.maxZoom || 19,
2011
+ minimumLevel: 0,
2012
+ tilingScheme: new Cesium.WebMercatorTilingScheme(),
2013
+ credit: 'Google Maps',
2014
+ // Override URL generation using urlSchemeZeroPadding as a custom URL builder
2015
+ urlSchemeZeroPadding: {
2016
+ '{x}': '',
2017
+ '{y}': '',
2018
+ '{z}': '',
2019
+ },
2020
+ });
2021
+ // Override the buildImageResource method to use Google Static Maps API
2022
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- monkey-patching internal Cesium method not exposed in typings
2023
+ googleImageryProvider.buildImageResource = function (x, y, level) {
2024
+ const tilingScheme = new Cesium.WebMercatorTilingScheme();
2025
+ const rectangle = tilingScheme.tileXYToRectangle(x, y, level);
2026
+ const west = Cesium.Math.toDegrees(rectangle.west);
2027
+ const south = Cesium.Math.toDegrees(rectangle.south);
2028
+ const east = Cesium.Math.toDegrees(rectangle.east);
2029
+ const north = Cesium.Math.toDegrees(rectangle.north);
2030
+ // Center point of the tile
2031
+ const centerLat = (south + north) / 2;
2032
+ const centerLng = (west + east) / 2;
2033
+ // Build Google Static Maps API URL
2034
+ const params = new URLSearchParams({
2035
+ center: `${centerLat},${centerLng}`,
2036
+ zoom: level.toString(),
2037
+ size: '256x256',
2038
+ scale: config.scale === 'scaleFactor1x' ? '1' : '2',
2039
+ maptype: googleMapTypeId,
2040
+ key: config.apiKey,
2041
+ format: 'png',
2042
+ });
2043
+ if (config.language) {
2044
+ params.set('language', config.language);
2045
+ }
2046
+ if (config.region) {
2047
+ params.set('region', config.region);
2048
+ }
2049
+ const url = `https://maps.googleapis.com/maps/api/staticmap?${params.toString()}`;
2050
+ return new Cesium.Resource({ url });
2051
+ };
2052
+ // Add Google logo for compliance
2053
+ this.ensureGoogleLogo();
2054
+ return new this.Cesium.ImageryLayer(googleImageryProvider, {
2055
+ alpha: config.opacity ?? 1,
2056
+ show: config.visible ?? true,
2057
+ });
2058
+ }
2059
+ getGoogleMapTypeId(mapType) {
2060
+ switch (mapType) {
2061
+ case 'roadmap':
2062
+ return 'roadmap';
2063
+ case 'satellite':
2064
+ return 'satellite';
2065
+ case 'terrain':
2066
+ return 'terrain';
2067
+ case 'hybrid':
2068
+ return 'hybrid';
2069
+ default:
2070
+ return 'roadmap';
2071
+ }
2072
+ }
2073
+ /**
2074
+ * Load Google Maps JavaScript API
2075
+ */
2076
+ async loadGoogleMapsApi(apiKey, opts) {
2077
+ const w = window;
2078
+ const mockLoader = w.__mockGoogleMapsApi;
2079
+ if (typeof mockLoader === 'function') {
2080
+ await mockLoader(apiKey, opts);
2081
+ return;
2082
+ }
2083
+ if (w.google?.maps)
2084
+ return;
2085
+ await new Promise((resolve, reject) => {
2086
+ const cbName = '___cesiumGoogleInit___' + Math.random().toString(36).slice(2);
2087
+ w[cbName] = () => resolve();
2088
+ const script = document.createElement('script');
2089
+ const params = new URLSearchParams({
2090
+ key: apiKey,
2091
+ callback: cbName,
2092
+ v: 'weekly',
2093
+ });
2094
+ if (opts?.language)
2095
+ params.set('language', opts.language);
2096
+ if (opts?.region)
2097
+ params.set('region', opts.region);
2098
+ if (opts?.libraries?.length)
2099
+ params.set('libraries', opts.libraries.join(','));
2100
+ script.src = `https://maps.googleapis.com/maps/api/js?${params.toString()}`;
2101
+ script.async = true;
2102
+ script.onerror = () => reject(new Error('Google Maps JS API failed to load'));
2103
+ document.head.appendChild(script);
2104
+ });
2105
+ }
2106
+ /**
2107
+ * Add Google logo for compliance
2108
+ */
2109
+ ensureGoogleLogo() {
2110
+ if (!this.viewer?.container ||
2111
+ this.viewer.container._googleLogoAdded)
2112
+ return;
2113
+ const logo = document.createElement('img');
2114
+ logo.src =
2115
+ 'https://developers.google.com/static/maps/documentation/images/google_on_white.png';
2116
+ logo.alt = 'Google';
2117
+ logo.style.position = 'absolute';
2118
+ logo.style.bottom = '6px';
2119
+ logo.style.left = '6px';
2120
+ logo.style.height = '18px';
2121
+ logo.style.pointerEvents = 'none';
2122
+ logo.style.zIndex = '1000';
2123
+ this.viewer.container.appendChild(logo);
2124
+ this.viewer.container._googleLogoAdded = true;
2125
+ }
2126
+ async createXYZLayer(config) {
2127
+ if (!config.url) {
2128
+ throw new Error('XYZ layer requires a url');
2129
+ }
2130
+ const credit = Array.isArray(config.attributions)
2131
+ ? config.attributions.join(', ')
2132
+ : config.attributions;
2133
+ const providerOptions = {
2134
+ url: config.url,
2135
+ credit,
2136
+ maximumLevel: config.maxZoom,
2137
+ ...(config.options || {}),
2138
+ };
2139
+ const provider = new this.Cesium.UrlTemplateImageryProvider(providerOptions);
2140
+ const layerOptions = {
2141
+ alpha: config.opacity ?? 1,
2142
+ show: config.visible ?? true,
2143
+ };
2144
+ return new this.Cesium.ImageryLayer(provider, layerOptions);
2145
+ }
2146
+ async createTerrainLayer(config) {
2147
+ let provider;
2148
+ if (config.elevationData) {
2149
+ provider = await this.Cesium.CesiumTerrainProvider.fromUrl(config.elevationData);
2150
+ }
2151
+ else {
2152
+ provider = await this.Cesium.createWorldTerrainAsync();
2153
+ }
2154
+ const layer = new CesiumTerrainLayer(this.Cesium, this.viewer, provider, config);
2155
+ if (config.visible !== undefined) {
2156
+ layer.setVisible(config.visible);
2157
+ }
2158
+ if (config.opacity !== undefined) {
2159
+ layer.setOpacity(config.opacity);
2160
+ }
2161
+ return layer;
2162
+ }
2163
+ /**
2164
+ * Create GeoTIFF Terrain Layer
2165
+ * Loads GeoTIFF elevation data and provides it as terrain
2166
+ */
2167
+ async createGeoTIFFTerrainLayer(config) {
2168
+ // If no URL is set, return a fallback layer with EllipsoidTerrainProvider
2169
+ if (!config.url) {
2170
+ log(`${TERRAIN_GEOTIFF_LOG_PREFIX}layer created without URL, waiting for URL to load`);
2171
+ const fallbackProvider = new this.Cesium.EllipsoidTerrainProvider();
2172
+ const layer = new CesiumTerrainLayer(this.Cesium, this.viewer, fallbackProvider, config);
2173
+ // Set to invisible since there's no terrain data
2174
+ layer.setVisible(false);
2175
+ return layer;
2176
+ }
2177
+ try {
2178
+ log(`${TERRAIN_GEOTIFF_LOG_PREFIX}create layer: url=${config.url}`);
2179
+ // Create the custom GeoTIFF terrain provider
2180
+ const provider = await createCesiumGeoTIFFTerrainProvider({
2181
+ url: config.url,
2182
+ projection: config.projection,
2183
+ forceProjection: config.forceProjection,
2184
+ nodata: config.nodata,
2185
+ Cesium: this.Cesium,
2186
+ });
2187
+ // Wrap it in a CesiumTerrainLayer
2188
+ // Cast config to terrain type since CesiumTerrainLayer expects it
2189
+ const layer = new CesiumTerrainLayer(this.Cesium, this.viewer, provider, config);
2190
+ if (config.visible !== undefined) {
2191
+ layer.setVisible(config.visible);
2192
+ }
2193
+ if (config.opacity !== undefined) {
2194
+ layer.setOpacity(config.opacity);
2195
+ }
2196
+ log(`${TERRAIN_GEOTIFF_LOG_PREFIX}layer created successfully`);
2197
+ return layer;
2198
+ }
2199
+ catch (err) {
2200
+ error(`${TERRAIN_GEOTIFF_LOG_PREFIX}failed to create terrain layer:`, err);
2201
+ // Return a fallback with EllipsoidTerrainProvider
2202
+ const fallbackProvider = new this.Cesium.EllipsoidTerrainProvider();
2203
+ return new CesiumTerrainLayer(this.Cesium, this.viewer, fallbackProvider, config);
2204
+ }
2205
+ }
2206
+ async addWMSLayer(config) {
2207
+ return new this.Cesium.ImageryLayer(new this.Cesium.WebMapServiceImageryProvider({
2208
+ url: config.url,
2209
+ layers: config.layers,
2210
+ parameters: config.extraParams,
2211
+ }));
2212
+ }
2213
+ /**
2214
+ * Create WCS (Web Coverage Service) ImageryLayer
2215
+ * Supports WCS 2.0.1 (subset) and 1.x.x (BBOX) versions
2216
+ */
2217
+ async createWCSLayer(config) {
2218
+ if (!config.url || !config.coverageName) {
2219
+ throw new Error('WCS layer requires url and coverageName');
2220
+ }
2221
+ const version = config.version ?? '2.0.1';
2222
+ const format = config.format ?? 'image/tiff';
2223
+ const projection = config.projection ?? 'EPSG:4326';
2224
+ const tileSize = config.tileSize ?? 256;
2225
+ const Cesium = this.Cesium;
2226
+ // Create a custom URL template - will be overridden by buildImageResource
2227
+ const customUrlTemplate = `${config.url}?wcs_placeholder`;
2228
+ const wcsImageryProvider = new Cesium.UrlTemplateImageryProvider({
2229
+ url: customUrlTemplate,
2230
+ maximumLevel: config.maxZoom ?? 18,
2231
+ minimumLevel: config.minZoom ?? 0,
2232
+ tileWidth: tileSize,
2233
+ tileHeight: tileSize,
2234
+ tilingScheme: new Cesium.GeographicTilingScheme(),
2235
+ credit: 'WCS',
2236
+ });
2237
+ // Override the buildImageResource method to generate WCS GetCoverage URLs
2238
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- monkey-patching internal Cesium method not exposed in typings
2239
+ wcsImageryProvider.buildImageResource = function (x, y, level) {
2240
+ const tilingScheme = new Cesium.GeographicTilingScheme();
2241
+ const rectangle = tilingScheme.tileXYToRectangle(x, y, level);
2242
+ // Convert to degrees
2243
+ const west = Cesium.Math.toDegrees(rectangle.west);
2244
+ const south = Cesium.Math.toDegrees(rectangle.south);
2245
+ const east = Cesium.Math.toDegrees(rectangle.east);
2246
+ const north = Cesium.Math.toDegrees(rectangle.north);
2247
+ const baseParams = {
2248
+ SERVICE: 'WCS',
2249
+ REQUEST: 'GetCoverage',
2250
+ VERSION: version,
2251
+ FORMAT: format,
2252
+ };
2253
+ let url;
2254
+ // WCS 2.0.1 uses subset parameters
2255
+ if (version.startsWith('2.0')) {
2256
+ const params = {
2257
+ ...baseParams,
2258
+ coverageId: config.coverageName,
2259
+ ...(config.params || {}),
2260
+ };
2261
+ // Add GeoTIFF compression if format is tiff
2262
+ if (format.includes('tiff') || format.includes('geotiff')) {
2263
+ params['geotiff:compression'] = 'LZW';
2264
+ }
2265
+ // Build query string
2266
+ const query = new URLSearchParams();
2267
+ Object.entries(params).forEach(([key, value]) => {
2268
+ if (value !== undefined && value !== null) {
2269
+ query.set(key, String(value));
2270
+ }
2271
+ });
2272
+ const queryString = query.toString();
2273
+ const subsetX = `subset=X(${west},${east})`;
2274
+ const subsetY = `subset=Y(${south},${north})`;
2275
+ url = `${config.url}${config.url.includes('?') ? '&' : '?'}${queryString}&${subsetX}&${subsetY}`;
2276
+ }
2277
+ // WCS 1.x.x uses BBOX parameter
2278
+ else {
2279
+ const params = {
2280
+ ...baseParams,
2281
+ COVERAGE: config.coverageName,
2282
+ BBOX: `${west},${south},${east},${north}`,
2283
+ CRS: projection,
2284
+ WIDTH: String(tileSize),
2285
+ HEIGHT: String(tileSize),
2286
+ ...(config.params || {}),
2287
+ };
2288
+ const query = new URLSearchParams();
2289
+ Object.entries(params).forEach(([key, value]) => {
2290
+ if (value !== undefined && value !== null) {
2291
+ query.set(key, String(value));
2292
+ }
2293
+ });
2294
+ url = `${config.url}${config.url.includes('?') ? '&' : '?'}${query.toString()}`;
2295
+ }
2296
+ return new Cesium.Resource({ url });
2297
+ };
2298
+ return new this.Cesium.ImageryLayer(wcsImageryProvider, {
2299
+ alpha: config.opacity ?? 1,
2300
+ show: config.visible ?? true,
2301
+ });
2302
+ }
2303
+ async addArcGISLayer(config) {
2304
+ //"https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
2305
+ const provider = await this.Cesium.ArcGisMapServerImageryProvider.fromUrl(config.url);
2306
+ this.viewer.imageryLayers.addImageryProvider(provider);
2307
+ }
2308
+ async createGeoTIFFLayer(config) {
2309
+ if (!config.url) {
2310
+ throw new Error('GeoTIFF layer requires a URL');
2311
+ }
2312
+ // The GeoTIFFImageryProvider always uses WebMercatorTilingScheme,
2313
+ // so the tile processor must reproject into EPSG:3857 to match
2314
+ // the tile coordinate math (x,y,z → bounds).
2315
+ const viewProjection = 'EPSG:3857';
2316
+ try {
2317
+ const geotiffExtra = config;
2318
+ const source = await getGeoTIFFSource(config.url, geotiffExtra.projection, geotiffExtra.forceProjection, config.nodata);
2319
+ const tileProcessorConfig = await getTileProcessorConfig(source, viewProjection);
2320
+ const tileProcessor = new GeoTIFFTileProcessor(tileProcessorConfig);
2321
+ tileProcessor.createGlobalTriangulation();
2322
+ let colorStops;
2323
+ if (config.colorMap) {
2324
+ const { stops } = getColorStops(config.colorMap, config.valueRange);
2325
+ colorStops = stops;
2326
+ }
2327
+ const geotiffRenderExtra = config;
2328
+ const tileSize = geotiffRenderExtra.tileSize ?? 256;
2329
+ const resolution = geotiffRenderExtra.resolution ?? 1.0;
2330
+ const resampleMethod = geotiffRenderExtra.resampleMethod ?? 'bilinear';
2331
+ const imageryProvider = new GeoTIFFImageryProvider({
2332
+ Cesium: this.Cesium,
2333
+ rectangleDegrees: source.wgs84Bounds,
2334
+ tileProcessor,
2335
+ tileSize,
2336
+ resolution,
2337
+ resampleMethod,
2338
+ colorStops,
2339
+ });
2340
+ const layer = new this.Cesium.ImageryLayer(imageryProvider, {
2341
+ alpha: config.opacity ?? 1.0,
2342
+ show: config.visible ?? true,
2343
+ });
2344
+ layer.__vmapGeoTIFFMeta = {
2345
+ url: config.url,
2346
+ width: source.width,
2347
+ height: source.height,
2348
+ samplesPerPixel: source.samplesPerPixel,
2349
+ noData: source.noDataValue,
2350
+ };
2351
+ return layer;
2352
+ }
2353
+ catch (err) {
2354
+ error('v-map - provider - cesium - Failed to create GeoTIFF layer', err);
2355
+ // Return a placeholder layer in case of error
2356
+ const provider = new this.Cesium.SingleTileImageryProvider({
2357
+ url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
2358
+ rectangle: this.Cesium.Rectangle.fromDegrees(-180, -90, 180, 90),
2359
+ });
2360
+ return new this.Cesium.ImageryLayer(provider, {
2361
+ alpha: 0,
2362
+ show: false,
2363
+ });
2364
+ }
2365
+ }
2366
+ async createTile3DLayer(config) {
2367
+ if (!config.url) {
2368
+ throw new Error('Tile3D layer requires a URL');
2369
+ }
2370
+ const tileset = await this.Cesium.Cesium3DTileset.fromUrl(config.url, config.tilesetOptions ?? {});
2371
+ if (config.cesiumStyle) {
2372
+ tileset.style = new this.Cesium.Cesium3DTileStyle(config.cesiumStyle);
2373
+ }
2374
+ return tileset;
2375
+ }
2376
+ async updateLayer(layerId, update) {
2377
+ return await this.layerManagerMutex.runExclusive(async () => {
2378
+ const hadErrorListener = this.layerErrorCallbacks.has(layerId);
2379
+ if (hadErrorListener)
2380
+ this.offLayerError(layerId);
2381
+ const oldLayer = this.layerManager.getLayer(layerId);
2382
+ switch (update.type) {
2383
+ case 'geojson':
2384
+ {
2385
+ const data = update.data;
2386
+ const options = oldLayer.getOptions();
2387
+ const dataSource = await this.createGeoJSONLayer({
2388
+ geojson: data.geojson,
2389
+ url: data.url,
2390
+ style: data.style,
2391
+ geostylerStyle: data.geostylerStyle,
2392
+ }, options);
2393
+ const layer = this.layerManager.replaceLayer(layerId, oldLayer, dataSource);
2394
+ layer.setOptions(options);
2395
+ }
2396
+ break;
2397
+ case 'wfs':
2398
+ {
2399
+ const data = update.data;
2400
+ const options = oldLayer.getOptions();
2401
+ const dataSource = await this.createWFSLayer(data, options);
2402
+ const layer = this.layerManager.replaceLayer(layerId, oldLayer, dataSource);
2403
+ layer.setOptions(options);
2404
+ }
2405
+ break;
2406
+ case 'osm':
2407
+ {
2408
+ const osmOptions = oldLayer.getOptions();
2409
+ const osmLayer = new this.Cesium.ImageryLayer(new this.Cesium.OpenStreetMapImageryProvider({
2410
+ url: update.data.url || 'https://a.tile.openstreetmap.org',
2411
+ }));
2412
+ const updatedOsmlayer = this.layerManager.replaceLayer(layerId, oldLayer, osmLayer);
2413
+ updatedOsmlayer.setOptions(osmOptions);
2414
+ }
2415
+ break;
2416
+ case 'google':
2417
+ {
2418
+ const googleOptions = oldLayer.getOptions();
2419
+ const googleLayer = await this.createGoogleLayer(update.data);
2420
+ const updatedGoogleLayer = this.layerManager.replaceLayer(layerId, oldLayer, googleLayer);
2421
+ updatedGoogleLayer.setOptions(googleOptions);
2422
+ }
2423
+ break;
2424
+ case 'xyz':
2425
+ {
2426
+ const xyzOptions = oldLayer.getOptions();
2427
+ const xyzLayer = await this.createXYZLayer(update.data);
2428
+ const updatedXyzLayer = this.layerManager.replaceLayer(layerId, oldLayer, xyzLayer);
2429
+ updatedXyzLayer.setOptions(xyzOptions);
2430
+ }
2431
+ break;
2432
+ case 'wcs':
2433
+ {
2434
+ const wcsOptions = oldLayer.getOptions();
2435
+ const wcsLayer = await this.createWCSLayer(update.data);
2436
+ const updatedWcsLayer = this.layerManager.replaceLayer(layerId, oldLayer, wcsLayer);
2437
+ updatedWcsLayer.setOptions(wcsOptions);
2438
+ }
2439
+ break;
2440
+ case 'wkt':
2441
+ {
2442
+ const data = update.data;
2443
+ const options = oldLayer.getOptions();
2444
+ const dataSource = await this.createWKTLayer({
2445
+ wkt: data.wkt,
2446
+ url: data.url,
2447
+ style: data.style,
2448
+ geostylerStyle: data.geostylerStyle,
2449
+ }, options);
2450
+ const layer = this.layerManager.replaceLayer(layerId, oldLayer, dataSource);
2451
+ layer.setOptions(options);
2452
+ }
2453
+ break;
2454
+ case 'geotiff':
2455
+ {
2456
+ const data = update.data;
2457
+ const iLayer = await this.createGeoTIFFLayer({
2458
+ url: data.url,
2459
+ });
2460
+ this.layerManager.replaceLayer(layerId, oldLayer, iLayer);
2461
+ }
2462
+ break;
2463
+ case 'tile3d':
2464
+ {
2465
+ const data = update.data ?? {};
2466
+ if (!data.url) {
2467
+ throw new Error('tile3d update requires a url');
2468
+ }
2469
+ const layer = await this.createTile3DLayer({
2470
+ type: 'tile3d',
2471
+ url: data.url,
2472
+ tilesetOptions: data.tilesetOptions,
2473
+ cesiumStyle: data.cesiumStyle,
2474
+ });
2475
+ const updatedLayer = this.layerManager.replaceLayer(layerId, oldLayer, layer);
2476
+ updatedLayer.setOptions(data.tilesetOptions ?? {});
2477
+ if (data.cesiumStyle && 'setStyle' in updatedLayer) {
2478
+ updatedLayer.setStyle(data.cesiumStyle);
2479
+ }
2480
+ }
2481
+ break;
2482
+ case 'tile3d-style':
2483
+ {
2484
+ const data = update.data ?? {};
2485
+ if ('setStyle' in oldLayer) {
2486
+ const stylePayload = data.style ?? {};
2487
+ oldLayer.setStyle(stylePayload);
2488
+ }
2489
+ }
2490
+ break;
2491
+ case 'terrain':
2492
+ {
2493
+ const previousOptions = oldLayer.getOptions();
2494
+ const visible = oldLayer.getVisible();
2495
+ const opacity = oldLayer.getOpacity();
2496
+ oldLayer.remove();
2497
+ const terrainLayer = await this.createTerrainLayer({
2498
+ type: 'terrain',
2499
+ ...previousOptions,
2500
+ ...(update.data ?? {}),
2501
+ });
2502
+ const wrapped = this.layerManager.addCustomLayer(layerId, terrainLayer);
2503
+ wrapped.setVisible(visible);
2504
+ wrapped.setOpacity(opacity);
2505
+ }
2506
+ break;
2507
+ case 'terrain-geotiff':
2508
+ {
2509
+ //const previousOptions = oldLayer.getOptions();
2510
+ //const visible = oldLayer.getVisible();
2511
+ //const opacity = oldLayer.getOpacity();
2512
+ oldLayer.remove();
2513
+ const terrainLayer = await this.createGeoTIFFTerrainLayer({
2514
+ type: 'terrain-geotiff',
2515
+ ...(update.data ?? {}),
2516
+ });
2517
+ this.layerManager.addCustomLayer(layerId, terrainLayer);
2518
+ //wrapped.setVisible(visible);
2519
+ //wrapped.setOpacity(opacity);
2520
+ }
2521
+ break;
2522
+ }
2523
+ // Re-attach error listeners after layer replacement
2524
+ if (hadErrorListener)
2525
+ this.attachCesiumErrorListeners(layerId);
2526
+ });
2527
+ }
2528
+ async setView(center, zoom) {
2529
+ if (!this.viewer)
2530
+ return;
2531
+ const [lon, lat] = center;
2532
+ this.viewer.camera.flyTo({
2533
+ destination: this.Cesium.Cartesian3.fromDegrees(lon, lat, 1000000 / zoom),
2534
+ duration: 2.0, // Sekunden, anpassbar
2535
+ orientation: {
2536
+ heading: this.Cesium.Math.toRadians(0.0), // Blickrichtung nach Norden
2537
+ pitch: this.Cesium.Math.toRadians(-30), // leicht nach unten schauen
2538
+ roll: 0.0,
2539
+ },
2540
+ // optional: onComplete / onCancel callbacks
2541
+ complete: () => log('v-map - provider - cesium - Fly‑to finished'),
2542
+ cancel: () => warn('v-map - provider - cesium - Fly‑to cancelled'),
2543
+ });
2544
+ }
2545
+ async fetchWFSFromUrl(config) {
2546
+ const baseParams = {
2547
+ service: 'WFS',
2548
+ request: 'GetFeature',
2549
+ version: config.version ?? '1.1.0',
2550
+ typeName: config.typeName,
2551
+ outputFormat: config.outputFormat ?? 'application/json',
2552
+ srsName: config.srsName ?? 'EPSG:4326',
2553
+ };
2554
+ const params = { ...baseParams, ...(config.params ?? {}) };
2555
+ const requestUrl = this.appendParams(config.url, params);
2556
+ const response = await fetch(requestUrl);
2557
+ if (!response.ok) {
2558
+ throw new Error(`WFS request failed (${response.status} ${response.statusText})`);
2559
+ }
2560
+ const outputFormat = (config.outputFormat ?? 'application/json').toLowerCase();
2561
+ // Handle JSON formats
2562
+ if (outputFormat.includes('json') ||
2563
+ outputFormat.includes('geojson') ||
2564
+ outputFormat === 'application/json') {
2565
+ const contentType = response.headers.get('content-type');
2566
+ if (contentType?.includes('application/json')) {
2567
+ return await response.json();
2568
+ }
2569
+ // Try to parse as JSON anyway
2570
+ const text = await response.text();
2571
+ return JSON.parse(text);
2572
+ }
2573
+ // Handle GML formats - parse XML to GeoJSON using @npm9912/s-gml
2574
+ if (outputFormat.includes('gml') || outputFormat.includes('xml')) {
2575
+ const xml = await response.text();
2576
+ const { GmlParser } = await import('./index.browser-DhQAXuA7.js');
2577
+ const parser = new GmlParser();
2578
+ return await parser.parse(xml);
2579
+ }
2580
+ // Default: try to parse as JSON
2581
+ return await response.json();
2582
+ }
2583
+ appendParams(baseUrl, params) {
2584
+ const query = new URLSearchParams();
2585
+ Object.entries(params).forEach(([key, value]) => {
2586
+ if (value !== undefined && value !== null) {
2587
+ query.set(key, String(value));
2588
+ }
2589
+ });
2590
+ if (!query.toString())
2591
+ return baseUrl;
2592
+ return `${baseUrl}${baseUrl.includes('?') ? '&' : '?'}${query.toString()}`;
2593
+ }
2594
+ }
2595
+
2596
+ export { CesiumProvider };