@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.
- package/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/cjs/_commonjsHelpers-B83fTs8d.js +36 -0
- package/dist/cjs/app-globals-V2Kpy_OQ.js +5 -0
- package/dist/cjs/cesium-provider-BiFFyAl9.js +2598 -0
- package/dist/cjs/deck-provider-Ctq3Q8a1.js +47824 -0
- package/dist/cjs/geotiff-CEwvF9cG.js +47 -0
- package/dist/cjs/geotiff-source-RaNzzWkC.js +1522 -0
- package/dist/cjs/index-B1oGO1g-.js +10658 -0
- package/dist/cjs/index-B8LHqjyg.js +1765 -0
- package/dist/cjs/index-BIL4VsgP.js +310 -0
- package/dist/cjs/index-Blku2QY8.js +167 -0
- package/dist/cjs/index-CJvvX4yx.js +21 -0
- package/dist/cjs/index-CbVT-Con.js +699 -0
- package/dist/cjs/index-ISOEpMC3.js +20478 -0
- package/dist/cjs/index-JSwBbvGA.js +1621 -0
- package/dist/cjs/index.browser-DQhD8Jwl.js +6873 -0
- package/dist/cjs/index.cjs.js +2 -0
- package/dist/cjs/layer-extension-B_olS0rc.js +65 -0
- package/dist/cjs/leaflet-provider-DOqfs7g5.js +1815 -0
- package/dist/cjs/loader.cjs.js +13 -0
- package/dist/cjs/main-dist-7TykwFci.js +2655 -0
- package/dist/cjs/messages-D7h4m8Tx.js +186 -0
- package/dist/cjs/openlayers-provider-Dfeg6L4n.js +1604 -0
- package/dist/cjs/polygon-layer-B9PrN7vr.js +1300 -0
- package/dist/cjs/scenegraph-layer-DwNoxQdi.js +2530 -0
- package/dist/cjs/styleconfig-CVRqArk-.js +23 -0
- package/dist/cjs/v-map-builder.cjs.entry.js +3786 -0
- package/dist/cjs/v-map-layer-geojson_12.cjs.entry.js +40894 -0
- package/dist/cjs/v-map-layer-helper-iAzxAg9I.js +285 -0
- package/dist/cjs/v-map-layer-terrain-geotiff.cjs.entry.js +258 -0
- package/dist/cjs/v-map-layercontrol.cjs.entry.js +247 -0
- package/dist/cjs/v-map.cjs.js +25 -0
- package/dist/cjs/v-map.v-map-layer-osm.v-map-layergroup-BsXp3BoL.js +582 -0
- package/dist/cjs/v-map_3.cjs.entry.js +12 -0
- package/dist/collection/collection-manifest.json +30 -0
- package/dist/collection/components/v-map/v-map.css +3 -0
- package/dist/collection/components/v-map/v-map.js +467 -0
- package/dist/collection/components/v-map/v-map.test.js +33 -0
- package/dist/collection/components/v-map-builder/v-map-builder.css +1 -0
- package/dist/collection/components/v-map-builder/v-map-builder.js +913 -0
- package/dist/collection/components/v-map-builder/v-map-builder.test.js +56 -0
- package/dist/collection/components/v-map-layer-geojson/v-map-layer-geojson.js +862 -0
- package/dist/collection/components/v-map-layer-geojson/v-map-layer-geojson.test.js +42 -0
- package/dist/collection/components/v-map-layer-geotiff/v-map-layer-geotiff.css +4 -0
- package/dist/collection/components/v-map-layer-geotiff/v-map-layer-geotiff.js +500 -0
- package/dist/collection/components/v-map-layer-geotiff/v-map-layer-geotiff.test.js +38 -0
- package/dist/collection/components/v-map-layer-google/v-map-layer-google.css +1 -0
- package/dist/collection/components/v-map-layer-google/v-map-layer-google.js +442 -0
- package/dist/collection/components/v-map-layer-osm/error-api.test.js +108 -0
- package/dist/collection/components/v-map-layer-osm/v-map-layer-osm.css +4 -0
- package/dist/collection/components/v-map-layer-osm/v-map-layer-osm.js +311 -0
- package/dist/collection/components/v-map-layer-osm/v-map-layer-osm.test.js +36 -0
- package/dist/collection/components/v-map-layer-scatterplot/v-map-layer-scatterplot.css +1 -0
- package/dist/collection/components/v-map-layer-scatterplot/v-map-layer-scatterplot.js +305 -0
- package/dist/collection/components/v-map-layer-terrain/v-map-layer-terrain.css +3 -0
- package/dist/collection/components/v-map-layer-terrain/v-map-layer-terrain.js +548 -0
- package/dist/collection/components/v-map-layer-terrain/v-map-layer-terrain.test.js +36 -0
- package/dist/collection/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.css +3 -0
- package/dist/collection/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.js +735 -0
- package/dist/collection/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.test.js +42 -0
- package/dist/collection/components/v-map-layer-tile3d/v-map-layer-tile3d.css +3 -0
- package/dist/collection/components/v-map-layer-tile3d/v-map-layer-tile3d.js +449 -0
- package/dist/collection/components/v-map-layer-tile3d/v-map-layer-tile3d.test.js +50 -0
- package/dist/collection/components/v-map-layer-wcs/v-map-layer-wcs.css +1 -0
- package/dist/collection/components/v-map-layer-wcs/v-map-layer-wcs.js +448 -0
- package/dist/collection/components/v-map-layer-wcs/v-map-layer-wcs.test.js +39 -0
- package/dist/collection/components/v-map-layer-wfs/v-map-layer-wfs.css +1 -0
- package/dist/collection/components/v-map-layer-wfs/v-map-layer-wfs.js +489 -0
- package/dist/collection/components/v-map-layer-wfs/v-map-layer-wfs.test.js +43 -0
- package/dist/collection/components/v-map-layer-wkt/v-map-layer-wkt.css +1 -0
- package/dist/collection/components/v-map-layer-wkt/v-map-layer-wkt.js +811 -0
- package/dist/collection/components/v-map-layer-wkt/v-map-layer-wkt.test.js +34 -0
- package/dist/collection/components/v-map-layer-wms/v-map-layer-wms.css +1 -0
- package/dist/collection/components/v-map-layer-wms/v-map-layer-wms.js +453 -0
- package/dist/collection/components/v-map-layer-wms/v-map-layer-wms.test.js +36 -0
- package/dist/collection/components/v-map-layer-xyz/v-map-layer-xyz.css +1 -0
- package/dist/collection/components/v-map-layer-xyz/v-map-layer-xyz.js +331 -0
- package/dist/collection/components/v-map-layer-xyz/v-map-layer-xyz.test.js +28 -0
- package/dist/collection/components/v-map-layercontrol/v-map-layercontrol.css +74 -0
- package/dist/collection/components/v-map-layercontrol/v-map-layercontrol.js +277 -0
- package/dist/collection/components/v-map-layercontrol/v-map-layercontrol.test.js +134 -0
- package/dist/collection/components/v-map-layergroup/v-map-layergroup.css +4 -0
- package/dist/collection/components/v-map-layergroup/v-map-layergroup.js +212 -0
- package/dist/collection/components/v-map-layergroup/v-map-layergroup.test.js +39 -0
- package/dist/collection/components/v-map-style/v-map-style.css +38 -0
- package/dist/collection/components/v-map-style/v-map-style.js +492 -0
- package/dist/collection/components/v-map-style/v-map-style.unit.js +62 -0
- package/dist/collection/index.js +1 -0
- package/dist/collection/layer/v-map-layer-helper.js +281 -0
- package/dist/collection/layer/v-map-layer-helper.unit.js +234 -0
- package/dist/collection/lib/cesium-loader.js +58 -0
- package/dist/collection/lib/ensure-importmap.js +12 -0
- package/dist/collection/lib/ensure-importmap.unit.js +57 -0
- package/dist/collection/lib/versions.gen.js +6 -0
- package/dist/collection/lib/vstyle.js +8 -0
- package/dist/collection/map-provider/cesium/CesiumGeoTIFFTerrainProvider.js +285 -0
- package/dist/collection/map-provider/cesium/CesiumLayerGroups.js +159 -0
- package/dist/collection/map-provider/cesium/GeoTIFFImageryProvider.js +192 -0
- package/dist/collection/map-provider/cesium/GeoTIFFImageryProvider.test.js +57 -0
- package/dist/collection/map-provider/cesium/cesium-provider.js +1408 -0
- package/dist/collection/map-provider/cesium/i-layer.js +1 -0
- package/dist/collection/map-provider/cesium/layer-manager.js +467 -0
- package/dist/collection/map-provider/deck/DeckGLGeoTIFFLayer.js +483 -0
- package/dist/collection/map-provider/deck/DeckGLGeoTIFFTerrainLayer.js +410 -0
- package/dist/collection/map-provider/deck/LayerGroupWithModel.js +169 -0
- package/dist/collection/map-provider/deck/LayerGroups.js +192 -0
- package/dist/collection/map-provider/deck/LayerModel.js +1 -0
- package/dist/collection/map-provider/deck/RenderableGroup.js +1 -0
- package/dist/collection/map-provider/deck/deck-provider.js +1563 -0
- package/dist/collection/map-provider/geotiff/geotiff-source.js +172 -0
- package/dist/collection/map-provider/geotiff/utils/AABB2D.js +24 -0
- package/dist/collection/map-provider/geotiff/utils/BVHNode2D.js +166 -0
- package/dist/collection/map-provider/geotiff/utils/GeoTIFFTileProcessor.js +484 -0
- package/dist/collection/map-provider/geotiff/utils/Triangle.js +1 -0
- package/dist/collection/map-provider/geotiff/utils/Triangulation.js +321 -0
- package/dist/collection/map-provider/geotiff/utils/colormap-utils.js +190 -0
- package/dist/collection/map-provider/geotiff/utils/normalization-utils.js +122 -0
- package/dist/collection/map-provider/geotiff/utils/sampling-utils.js +108 -0
- package/dist/collection/map-provider/leaflet/GeoTIFFGridLayer.js +147 -0
- package/dist/collection/map-provider/leaflet/WCSGridLayer.js +124 -0
- package/dist/collection/map-provider/leaflet/google-map-tiles-layer.js +352 -0
- package/dist/collection/map-provider/leaflet/leaflet-helpers.js +94 -0
- package/dist/collection/map-provider/leaflet/leaflet-provider.js +1095 -0
- package/dist/collection/map-provider/ol/CustomGeoTiff.js +145 -0
- package/dist/collection/map-provider/ol/openlayers-helper.js +26 -0
- package/dist/collection/map-provider/ol/openlayers-provider.js +1427 -0
- package/dist/collection/map-provider/provider-factory.js +44 -0
- package/dist/collection/map-provider/provider-factory.unit.js +66 -0
- package/dist/collection/testing/browser-test-utils.js +49 -0
- package/dist/collection/testing/e2e-testing.js +122 -0
- package/dist/collection/testing/e2e-utils.js +70 -0
- package/dist/collection/testing/geotiff-test-server.js +100 -0
- package/dist/collection/testing/mocks/geostyler-lyrx-parser.js +12 -0
- package/dist/collection/testing/mocks/geostyler-mapbox-parser.js +12 -0
- package/dist/collection/testing/mocks/geostyler-qgis-parser.js +12 -0
- package/dist/collection/testing/mocks/geostyler-sld-parser.js +13 -0
- package/dist/collection/testing/mocks/geostyler-style.js +5 -0
- package/dist/collection/testing/setupTests.browser.js +1 -0
- package/dist/collection/testing/setupTests.stencil.js +20 -0
- package/dist/collection/testing/setupTests.vitest.js +59 -0
- package/dist/collection/testing/stencil-testing-wrapper.js +43 -0
- package/dist/collection/testing/styleMock.js +1 -0
- package/dist/collection/types/color.js +1 -0
- package/dist/collection/types/cssmode.js +1 -0
- package/dist/collection/types/flavour.js +1 -0
- package/dist/collection/types/layerconfig.js +1 -0
- package/dist/collection/types/lonlat.js +1 -0
- package/dist/collection/types/mapinitoptions.js +1 -0
- package/dist/collection/types/mapprovider.js +1 -0
- package/dist/collection/types/provideroptions.js +1 -0
- package/dist/collection/types/styleconfig.js +19 -0
- package/dist/collection/types/styling.js +13 -0
- package/dist/collection/types/styling.unit.js +37 -0
- package/dist/collection/types/vmaplayer.js +1 -0
- package/dist/collection/utils/async-mutex.js +28 -0
- package/dist/collection/utils/diff.js +142 -0
- package/dist/collection/utils/diff.unit.js +59 -0
- package/dist/collection/utils/dom-env.js +43 -0
- package/dist/collection/utils/dom-env.unit.js +92 -0
- package/dist/collection/utils/events.js +8 -0
- package/dist/collection/utils/logger.js +183 -0
- package/dist/collection/utils/logger.unit.js +98 -0
- package/dist/collection/utils/messages.js +12 -0
- package/dist/collection/utils/spatial-utils.js +27 -0
- package/dist/collection/utils/spatial-utils.unit.js +24 -0
- package/dist/components/_commonjsHelpers.js +1 -0
- package/dist/components/cesium-provider.js +1 -0
- package/dist/components/deck-provider.js +1 -0
- package/dist/components/events.js +1 -0
- package/dist/components/geotiff-source.js +1 -0
- package/dist/components/geotiff.js +4 -0
- package/dist/components/index.browser.js +15 -0
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +1 -0
- package/dist/components/index2.js +1 -0
- package/dist/components/index3.js +1 -0
- package/dist/components/index4.js +1 -0
- package/dist/components/index5.js +1 -0
- package/dist/components/index6.js +1 -0
- package/dist/components/index7.js +1 -0
- package/dist/components/index8.js +7 -0
- package/dist/components/layer-extension.js +1 -0
- package/dist/components/leaflet-provider.js +1 -0
- package/dist/components/main-dist.js +1 -0
- package/dist/components/messages.js +1 -0
- package/dist/components/openlayers-provider.js +1 -0
- package/dist/components/polygon-layer.js +1 -0
- package/dist/components/scenegraph-layer.js +1 -0
- package/dist/components/styleconfig.js +1 -0
- package/dist/components/styling.js +1 -0
- package/dist/components/v-map-builder.d.ts +11 -0
- package/dist/components/v-map-builder.js +2 -0
- package/dist/components/v-map-layer-geojson.d.ts +11 -0
- package/dist/components/v-map-layer-geojson.js +1 -0
- package/dist/components/v-map-layer-geojson2.js +1 -0
- package/dist/components/v-map-layer-geotiff.d.ts +11 -0
- package/dist/components/v-map-layer-geotiff.js +1 -0
- package/dist/components/v-map-layer-geotiff2.js +1 -0
- package/dist/components/v-map-layer-google.d.ts +11 -0
- package/dist/components/v-map-layer-google.js +1 -0
- package/dist/components/v-map-layer-google2.js +1 -0
- package/dist/components/v-map-layer-helper.js +1 -0
- package/dist/components/v-map-layer-osm.d.ts +11 -0
- package/dist/components/v-map-layer-osm.js +1 -0
- package/dist/components/v-map-layer-osm2.js +1 -0
- package/dist/components/v-map-layer-scatterplot.d.ts +11 -0
- package/dist/components/v-map-layer-scatterplot.js +1 -0
- package/dist/components/v-map-layer-scatterplot2.js +1 -0
- package/dist/components/v-map-layer-terrain-geotiff.d.ts +11 -0
- package/dist/components/v-map-layer-terrain-geotiff.js +1 -0
- package/dist/components/v-map-layer-terrain.d.ts +11 -0
- package/dist/components/v-map-layer-terrain.js +1 -0
- package/dist/components/v-map-layer-terrain2.js +1 -0
- package/dist/components/v-map-layer-tile3d.d.ts +11 -0
- package/dist/components/v-map-layer-tile3d.js +1 -0
- package/dist/components/v-map-layer-tile3d2.js +1 -0
- package/dist/components/v-map-layer-wcs.d.ts +11 -0
- package/dist/components/v-map-layer-wcs.js +1 -0
- package/dist/components/v-map-layer-wcs2.js +1 -0
- package/dist/components/v-map-layer-wfs.d.ts +11 -0
- package/dist/components/v-map-layer-wfs.js +1 -0
- package/dist/components/v-map-layer-wfs2.js +1 -0
- package/dist/components/v-map-layer-wkt.d.ts +11 -0
- package/dist/components/v-map-layer-wkt.js +1 -0
- package/dist/components/v-map-layer-wkt2.js +1 -0
- package/dist/components/v-map-layer-wms.d.ts +11 -0
- package/dist/components/v-map-layer-wms.js +1 -0
- package/dist/components/v-map-layer-wms2.js +1 -0
- package/dist/components/v-map-layer-xyz.d.ts +11 -0
- package/dist/components/v-map-layer-xyz.js +1 -0
- package/dist/components/v-map-layer-xyz2.js +1 -0
- package/dist/components/v-map-layercontrol.d.ts +11 -0
- package/dist/components/v-map-layercontrol.js +1 -0
- package/dist/components/v-map-layergroup.d.ts +11 -0
- package/dist/components/v-map-layergroup.js +1 -0
- package/dist/components/v-map-layergroup2.js +1 -0
- package/dist/components/v-map-style.d.ts +11 -0
- package/dist/components/v-map-style.js +1 -0
- package/dist/components/v-map-style2.js +10 -0
- package/dist/components/v-map.d.ts +11 -0
- package/dist/components/v-map.js +1 -0
- package/dist/components/v-map2.js +1 -0
- package/dist/esm/_commonjsHelpers-E-ZsRS8r.js +32 -0
- package/dist/esm/app-globals-DQuL1Twl.js +3 -0
- package/dist/esm/cesium-provider-BJfAup3w.js +2596 -0
- package/dist/esm/deck-provider-C7U9VDEq.js +47709 -0
- package/dist/esm/geotiff-BEWxTIfH.js +45 -0
- package/dist/esm/geotiff-source-esnDnC-u.js +1516 -0
- package/dist/esm/index-B1zwA4IC.js +685 -0
- package/dist/esm/index-BBpiaTpT.js +165 -0
- package/dist/esm/index-BIEmlzCf.js +1697 -0
- package/dist/esm/index-BUHa4Jj0.js +307 -0
- package/dist/esm/index-DbSdn93t.js +20461 -0
- package/dist/esm/index-RpJarvr_.js +10656 -0
- package/dist/esm/index-jN06TXUp.js +14 -0
- package/dist/esm/index-jzneDarq.js +1613 -0
- package/dist/esm/index.browser-DhQAXuA7.js +6860 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/layer-extension-CZXK5goK.js +63 -0
- package/dist/esm/leaflet-provider-Q41TB6ku.js +1794 -0
- package/dist/esm/loader.js +11 -0
- package/dist/esm/main-dist-CwnA7_Xn.js +2652 -0
- package/dist/esm/messages-CMKJzsgL.js +180 -0
- package/dist/esm/openlayers-provider-CMsDsQTQ.js +1602 -0
- package/dist/esm/polygon-layer-ByhxGhWC.js +1295 -0
- package/dist/esm/scenegraph-layer-09K_B6DT.js +2526 -0
- package/dist/esm/styleconfig-B-bAcABs.js +21 -0
- package/dist/esm/v-map-builder.entry.js +3784 -0
- package/dist/esm/v-map-layer-geojson_12.entry.js +40881 -0
- package/dist/esm/v-map-layer-helper-Dys44Cgo.js +283 -0
- package/dist/esm/v-map-layer-terrain-geotiff.entry.js +256 -0
- package/dist/esm/v-map-layercontrol.entry.js +245 -0
- package/dist/esm/v-map.js +21 -0
- package/dist/esm/v-map.v-map-layer-osm.v-map-layergroup-B4pFHuSf.js +572 -0
- package/dist/esm/v-map_3.entry.js +4 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/types/cesium-augment.d.ts +5 -0
- package/dist/types/components/v-map/v-map.d.ts +70 -0
- package/dist/types/components/v-map/v-map.test.d.ts +1 -0
- package/dist/types/components/v-map-builder/v-map-builder.d.ts +48 -0
- package/dist/types/components/v-map-builder/v-map-builder.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-geojson/v-map-layer-geojson.d.ts +129 -0
- package/dist/types/components/v-map-layer-geojson/v-map-layer-geojson.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-geotiff/v-map-layer-geotiff.d.ts +74 -0
- package/dist/types/components/v-map-layer-geotiff/v-map-layer-geotiff.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-google/v-map-layer-google.d.ts +78 -0
- package/dist/types/components/v-map-layer-osm/error-api.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-osm/v-map-layer-osm.d.ts +50 -0
- package/dist/types/components/v-map-layer-osm/v-map-layer-osm.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-scatterplot/v-map-layer-scatterplot.d.ts +54 -0
- package/dist/types/components/v-map-layer-terrain/v-map-layer-terrain.d.ts +74 -0
- package/dist/types/components/v-map-layer-terrain/v-map-layer-terrain.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.d.ts +117 -0
- package/dist/types/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-tile3d/v-map-layer-tile3d.d.ts +69 -0
- package/dist/types/components/v-map-layer-tile3d/v-map-layer-tile3d.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-wcs/v-map-layer-wcs.d.ts +47 -0
- package/dist/types/components/v-map-layer-wcs/v-map-layer-wcs.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-wfs/v-map-layer-wfs.d.ts +59 -0
- package/dist/types/components/v-map-layer-wfs/v-map-layer-wfs.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-wkt/v-map-layer-wkt.d.ts +132 -0
- package/dist/types/components/v-map-layer-wkt/v-map-layer-wkt.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-wms/v-map-layer-wms.d.ts +76 -0
- package/dist/types/components/v-map-layer-wms/v-map-layer-wms.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-xyz/v-map-layer-xyz.d.ts +59 -0
- package/dist/types/components/v-map-layer-xyz/v-map-layer-xyz.test.d.ts +1 -0
- package/dist/types/components/v-map-layercontrol/v-map-layercontrol.d.ts +44 -0
- package/dist/types/components/v-map-layercontrol/v-map-layercontrol.test.d.ts +1 -0
- package/dist/types/components/v-map-layergroup/v-map-layergroup.d.ts +31 -0
- package/dist/types/components/v-map-layergroup/v-map-layergroup.test.d.ts +1 -0
- package/dist/types/components/v-map-style/v-map-style.d.ts +75 -0
- package/dist/types/components/v-map-style/v-map-style.unit.d.ts +1 -0
- package/dist/types/components.d.ts +2391 -0
- package/dist/types/globals.d.ts +16 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/layer/v-map-layer-helper.d.ts +45 -0
- package/dist/types/layer/v-map-layer-helper.unit.d.ts +1 -0
- package/dist/types/leaflet-augment.d.ts +15 -0
- package/dist/types/lib/cesium-loader.d.ts +3 -0
- package/dist/types/lib/ensure-importmap.d.ts +3 -0
- package/dist/types/lib/ensure-importmap.unit.d.ts +1 -0
- package/dist/types/lib/versions.gen.d.ts +5 -0
- package/dist/types/lib/vstyle.d.ts +44 -0
- package/dist/types/map-provider/cesium/CesiumGeoTIFFTerrainProvider.d.ts +92 -0
- package/dist/types/map-provider/cesium/CesiumLayerGroups.d.ts +64 -0
- package/dist/types/map-provider/cesium/GeoTIFFImageryProvider.d.ts +75 -0
- package/dist/types/map-provider/cesium/GeoTIFFImageryProvider.test.d.ts +1 -0
- package/dist/types/map-provider/cesium/cesium-provider.d.ts +87 -0
- package/dist/types/map-provider/cesium/i-layer.d.ts +11 -0
- package/dist/types/map-provider/cesium/layer-manager.d.ts +31 -0
- package/dist/types/map-provider/deck/DeckGLGeoTIFFLayer.d.ts +91 -0
- package/dist/types/map-provider/deck/DeckGLGeoTIFFTerrainLayer.d.ts +82 -0
- package/dist/types/map-provider/deck/LayerGroupWithModel.d.ts +55 -0
- package/dist/types/map-provider/deck/LayerGroups.d.ts +63 -0
- package/dist/types/map-provider/deck/LayerModel.d.ts +8 -0
- package/dist/types/map-provider/deck/RenderableGroup.d.ts +20 -0
- package/dist/types/map-provider/deck/deck-provider.d.ts +92 -0
- package/dist/types/map-provider/geotiff/geotiff-source.d.ts +30 -0
- package/dist/types/map-provider/geotiff/utils/AABB2D.d.ts +28 -0
- package/dist/types/map-provider/geotiff/utils/BVHNode2D.d.ts +36 -0
- package/dist/types/map-provider/geotiff/utils/GeoTIFFTileProcessor.d.ts +116 -0
- package/dist/types/map-provider/geotiff/utils/Triangle.d.ts +5 -0
- package/dist/types/map-provider/geotiff/utils/Triangulation.d.ts +94 -0
- package/dist/types/map-provider/geotiff/utils/colormap-utils.d.ts +47 -0
- package/dist/types/map-provider/geotiff/utils/normalization-utils.d.ts +39 -0
- package/dist/types/map-provider/geotiff/utils/sampling-utils.d.ts +13 -0
- package/dist/types/map-provider/leaflet/GeoTIFFGridLayer.d.ts +34 -0
- package/dist/types/map-provider/leaflet/WCSGridLayer.d.ts +38 -0
- package/dist/types/map-provider/leaflet/google-map-tiles-layer.d.ts +73 -0
- package/dist/types/map-provider/leaflet/leaflet-helpers.d.ts +6 -0
- package/dist/types/map-provider/leaflet/leaflet-provider.d.ts +73 -0
- package/dist/types/map-provider/ol/CustomGeoTiff.d.ts +14 -0
- package/dist/types/map-provider/ol/openlayers-helper.d.ts +2 -0
- package/dist/types/map-provider/ol/openlayers-provider.d.ts +80 -0
- package/dist/types/map-provider/provider-factory.d.ts +12 -0
- package/dist/types/map-provider/provider-factory.unit.d.ts +1 -0
- package/dist/types/namespaces.d.ts +3 -0
- package/dist/types/ol-augment.d.ts +3 -0
- package/dist/types/ol-override.d.ts +7 -0
- package/dist/types/ol.d.ts +10 -0
- package/dist/types/stencil-public-runtime.d.ts +1860 -0
- package/dist/types/testing/browser-test-utils.d.ts +6 -0
- package/dist/types/testing/e2e-testing.d.ts +5 -0
- package/dist/types/testing/e2e-utils.d.ts +4 -0
- package/dist/types/testing/geotiff-test-server.d.ts +5 -0
- package/dist/types/testing/mocks/geostyler-lyrx-parser.d.ts +11 -0
- package/dist/types/testing/mocks/geostyler-mapbox-parser.d.ts +11 -0
- package/dist/types/testing/mocks/geostyler-qgis-parser.d.ts +11 -0
- package/dist/types/testing/mocks/geostyler-sld-parser.d.ts +11 -0
- package/dist/types/testing/mocks/geostyler-style.d.ts +5 -0
- package/dist/types/testing/setupTests.browser.d.ts +1 -0
- package/dist/types/testing/setupTests.stencil.d.ts +1 -0
- package/dist/types/testing/setupTests.vitest.d.ts +1 -0
- package/dist/types/testing/stencil-testing-wrapper.d.ts +3 -0
- package/dist/types/types/color.d.ts +1 -0
- package/dist/types/types/cssmode.d.ts +1 -0
- package/dist/types/types/flavour.d.ts +1 -0
- package/dist/types/types/layerconfig.d.ts +207 -0
- package/dist/types/types/lonlat.d.ts +1 -0
- package/dist/types/types/mapinitoptions.d.ts +4 -0
- package/dist/types/types/mapprovider.d.ts +46 -0
- package/dist/types/types/provideroptions.d.ts +8 -0
- package/dist/types/types/styleconfig.d.ts +27 -0
- package/dist/types/types/styling.d.ts +24 -0
- package/dist/types/types/styling.unit.d.ts +1 -0
- package/dist/types/types/vmaplayer.d.ts +10 -0
- package/dist/types/utils/async-mutex.d.ts +7 -0
- package/dist/types/utils/diff.d.ts +64 -0
- package/dist/types/utils/diff.unit.d.ts +1 -0
- package/dist/types/utils/dom-env.d.ts +5 -0
- package/dist/types/utils/dom-env.unit.d.ts +1 -0
- package/dist/types/utils/events.d.ts +29 -0
- package/dist/types/utils/logger.d.ts +47 -0
- package/dist/types/utils/logger.unit.d.ts +1 -0
- package/dist/types/utils/messages.d.ts +12 -0
- package/dist/types/utils/spatial-utils.d.ts +6 -0
- package/dist/types/utils/spatial-utils.unit.d.ts +1 -0
- package/dist/types/versions.d.ts +7 -0
- package/dist/v-map/index.esm.js +0 -0
- package/dist/v-map/p--vVleK-M.js +1 -0
- package/dist/v-map/p-09d10db0.entry.js +1 -0
- package/dist/v-map/p-5eba6058.entry.js +10 -0
- package/dist/v-map/p-6b102336.entry.js +1 -0
- package/dist/v-map/p-B-bAcABs.js +1 -0
- package/dist/v-map/p-BBpiaTpT.js +1 -0
- package/dist/v-map/p-BdijL4Av.js +1 -0
- package/dist/v-map/p-Be3r33VF.js +4 -0
- package/dist/v-map/p-BeFu0ap4.js +1 -0
- package/dist/v-map/p-BxFJezdK.js +1 -0
- package/dist/v-map/p-CMKJzsgL.js +1 -0
- package/dist/v-map/p-CXfA_q8m.js +1 -0
- package/dist/v-map/p-CZqY0yW4.js +1 -0
- package/dist/v-map/p-CafTHT9i.js +1 -0
- package/dist/v-map/p-DCTHyf58.js +1 -0
- package/dist/v-map/p-DQuL1Twl.js +1 -0
- package/dist/v-map/p-DR9McdNX.js +1 -0
- package/dist/v-map/p-Dckgonw8.js +1 -0
- package/dist/v-map/p-DhQAXuA7.js +15 -0
- package/dist/v-map/p-DmICdG34.js +7 -0
- package/dist/v-map/p-DrOQ9V4h.js +1 -0
- package/dist/v-map/p-DvHXtWUg.js +1 -0
- package/dist/v-map/p-E-ZsRS8r.js +1 -0
- package/dist/v-map/p-MyTSFnEk.js +1 -0
- package/dist/v-map/p-RpJarvr_.js +1 -0
- package/dist/v-map/p-WaMDUuAz.js +1 -0
- package/dist/v-map/p-aa410e64.entry.js +2 -0
- package/dist/v-map/p-c21c93fe.entry.js +1 -0
- package/dist/v-map/p-jzneDarq.js +2 -0
- package/dist/v-map/p-uiIP-taz.js +1 -0
- package/dist/v-map/v-map.esm.js +1 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +193 -0
|
@@ -0,0 +1,1815 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var vMap_vMapLayerOsm_vMapLayergroup_entry = require('./v-map.v-map-layer-osm.v-map-layergroup-BsXp3BoL.js');
|
|
4
|
+
var L = require('leaflet');
|
|
5
|
+
var messages = require('./messages-D7h4m8Tx.js');
|
|
6
|
+
var styleconfig = require('./styleconfig-CVRqArk-.js');
|
|
7
|
+
var geotiffSource = require('./geotiff-source-RaNzzWkC.js');
|
|
8
|
+
var index = require('./index-BIL4VsgP.js');
|
|
9
|
+
var index_browser = require('./index.browser-DQhD8Jwl.js');
|
|
10
|
+
require('./index-JSwBbvGA.js');
|
|
11
|
+
require('./v-map-layer-helper-iAzxAg9I.js');
|
|
12
|
+
require('./_commonjsHelpers-B83fTs8d.js');
|
|
13
|
+
|
|
14
|
+
function _interopNamespaceDefault(e) {
|
|
15
|
+
var n = Object.create(null);
|
|
16
|
+
if (e) {
|
|
17
|
+
Object.keys(e).forEach(function (k) {
|
|
18
|
+
if (k !== 'default') {
|
|
19
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
20
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return e[k]; }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
n.default = e;
|
|
28
|
+
return Object.freeze(n);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var L__namespace = /*#__PURE__*/_interopNamespaceDefault(L);
|
|
32
|
+
|
|
33
|
+
function injectInlineMin(root) {
|
|
34
|
+
if (!vMap_vMapLayerOsm_vMapLayergroup_entry.isBrowser())
|
|
35
|
+
return;
|
|
36
|
+
const css = `
|
|
37
|
+
:host { display:block; }
|
|
38
|
+
#map { width:100%; height:100%; display:block; }
|
|
39
|
+
`;
|
|
40
|
+
if (vMap_vMapLayerOsm_vMapLayergroup_entry.supportsAdoptedStyleSheets()) {
|
|
41
|
+
const sheet = new CSSStyleSheet();
|
|
42
|
+
sheet.replaceSync(css);
|
|
43
|
+
const target = (root ?? document);
|
|
44
|
+
const current = target.adoptedStyleSheets ?? [];
|
|
45
|
+
target.adoptedStyleSheets = [...current, sheet];
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const style = document.createElement('style');
|
|
50
|
+
style.textContent = css;
|
|
51
|
+
(root ?? document.head).appendChild(style);
|
|
52
|
+
return style;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function addLeafletCssFromCdn(root, version = vMap_vMapLayerOsm_vMapLayergroup_entry.LEAFLET_VERSION, cdn = 'jsdelivr') {
|
|
56
|
+
if (!vMap_vMapLayerOsm_vMapLayergroup_entry.isBrowser())
|
|
57
|
+
return;
|
|
58
|
+
const href = cdn === 'unpkg'
|
|
59
|
+
? `https://unpkg.com/leaflet@${version}/dist/leaflet.css`
|
|
60
|
+
: `https://cdn.jsdelivr.net/npm/leaflet@${version}/dist/leaflet.css`;
|
|
61
|
+
if (cdn === 'unpkg')
|
|
62
|
+
L__namespace.Icon.Default.imagePath = `https://unpkg.com/npm/leaflet@${version}/dist/images/`;
|
|
63
|
+
else
|
|
64
|
+
L__namespace.Icon.Default.imagePath = `https://cdn.jsdelivr.net/npm/leaflet@${version}/dist/images/`;
|
|
65
|
+
// doppelte Injektion vermeiden (prüfe ShadowRoot **und** globales head)
|
|
66
|
+
const scope = root ?? document;
|
|
67
|
+
const already = scope.querySelector?.(`link[rel="stylesheet"][href="${href}"]`) ||
|
|
68
|
+
document.head.querySelector(`link[rel="stylesheet"][href="${href}"]`);
|
|
69
|
+
if (already)
|
|
70
|
+
return null;
|
|
71
|
+
const link = document.createElement('link');
|
|
72
|
+
link.rel = 'stylesheet';
|
|
73
|
+
link.href = href;
|
|
74
|
+
// Optional: link.integrity = '<SRI-Hash>'; link.crossOrigin = '';
|
|
75
|
+
(root ?? document.head).appendChild(link);
|
|
76
|
+
return link;
|
|
77
|
+
}
|
|
78
|
+
function removeInjectedCss(shadowRoot, injectedStyle) {
|
|
79
|
+
if (!shadowRoot || !injectedStyle)
|
|
80
|
+
return;
|
|
81
|
+
// Das <style>-Element aus dem Shadow‑DOM entfernen
|
|
82
|
+
injectedStyle.remove(); // moderne API
|
|
83
|
+
}
|
|
84
|
+
function ensureLeafletCss(mode, root) {
|
|
85
|
+
if (!vMap_vMapLayerOsm_vMapLayergroup_entry.isBrowser())
|
|
86
|
+
return; // Tests/SSR: no-op
|
|
87
|
+
switch (mode) {
|
|
88
|
+
case 'cdn':
|
|
89
|
+
return addLeafletCssFromCdn(root);
|
|
90
|
+
case 'inline-min':
|
|
91
|
+
return injectInlineMin(root);
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
// Die Google Maps JS API wird seit der Umstellung auf Map Tiles nicht mehr geladen.
|
|
96
|
+
/** Fügt ein kleines Google-Logo als Leaflet-Control hinzu (Branding-Sicherheit) */
|
|
97
|
+
function ensureGoogleLogo(map, markAdded) {
|
|
98
|
+
if (map._googleLogoAdded)
|
|
99
|
+
return;
|
|
100
|
+
const Logo = L__namespace.Control.extend({
|
|
101
|
+
onAdd() {
|
|
102
|
+
const img = L__namespace.DomUtil.create('img');
|
|
103
|
+
img.src =
|
|
104
|
+
'https://developers.google.com/static/maps/documentation/images/google_on_white.png';
|
|
105
|
+
img.alt = 'Google';
|
|
106
|
+
img.style.pointerEvents = 'none';
|
|
107
|
+
img.style.height = '18px';
|
|
108
|
+
img.style.margin = '0 0 6px 6px';
|
|
109
|
+
return img;
|
|
110
|
+
},
|
|
111
|
+
onRemove() { },
|
|
112
|
+
});
|
|
113
|
+
new Logo({ position: 'bottomleft' }).addTo(map);
|
|
114
|
+
map._googleLogoAdded = true;
|
|
115
|
+
markAdded();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const CREATE_SESSION_URL = 'https://tile.googleapis.com/v1/createSession';
|
|
119
|
+
const TILE_URL_BASE = 'https://tile.googleapis.com/v1/2dtiles';
|
|
120
|
+
const ATTRIBUTION_URL = 'https://tile.googleapis.com/tile/v1/viewport';
|
|
121
|
+
const DEFAULT_MAX_ZOOM = 22;
|
|
122
|
+
const SESSION_REFRESH_BUFFER_MS = 60 * 1000;
|
|
123
|
+
const FALLBACK_TILE_SIZE = 256;
|
|
124
|
+
class GoogleMapTilesLayer extends L__namespace.GridLayer {
|
|
125
|
+
apiKey;
|
|
126
|
+
highDpi;
|
|
127
|
+
sessionRequest;
|
|
128
|
+
scaleFactor;
|
|
129
|
+
sessionToken;
|
|
130
|
+
sessionPromise;
|
|
131
|
+
sessionRefreshId;
|
|
132
|
+
previousViewport;
|
|
133
|
+
currentAttribution;
|
|
134
|
+
mapInstance;
|
|
135
|
+
onMoveEnd;
|
|
136
|
+
constructor(options) {
|
|
137
|
+
super();
|
|
138
|
+
this.applyInitialGridOptions(options);
|
|
139
|
+
const { apiKey, mapType, language, region, imageFormat, scale, highDpi, layerTypes, overlay, styles, apiOptions, } = options;
|
|
140
|
+
if (!apiKey) {
|
|
141
|
+
throw new Error('Google Map Tiles layer requires an apiKey');
|
|
142
|
+
}
|
|
143
|
+
this.apiKey = apiKey;
|
|
144
|
+
this.highDpi =
|
|
145
|
+
highDpi ?? (scale === undefined ? true : scale !== 'scaleFactor1x');
|
|
146
|
+
this.scaleFactor = this.mapScaleToFactor(scale, this.highDpi);
|
|
147
|
+
const request = {
|
|
148
|
+
mapType: mapType ?? 'roadmap',
|
|
149
|
+
language: language ?? 'en-US',
|
|
150
|
+
region: region ?? 'US',
|
|
151
|
+
};
|
|
152
|
+
if (imageFormat) {
|
|
153
|
+
request.imageFormat = imageFormat;
|
|
154
|
+
}
|
|
155
|
+
if (layerTypes?.length) {
|
|
156
|
+
request.layerTypes = layerTypes;
|
|
157
|
+
}
|
|
158
|
+
if (apiOptions?.length) {
|
|
159
|
+
request.apiOptions = apiOptions;
|
|
160
|
+
}
|
|
161
|
+
if (Array.isArray(styles) && styles.length > 0) {
|
|
162
|
+
request.styles = styles;
|
|
163
|
+
}
|
|
164
|
+
if (overlay === true) {
|
|
165
|
+
request.overlay = true;
|
|
166
|
+
}
|
|
167
|
+
const resolvedScale = scale ?? (this.scaleFactor > 1 ? this.factorToScale(this.scaleFactor) : undefined);
|
|
168
|
+
if (resolvedScale) {
|
|
169
|
+
request.scale = resolvedScale;
|
|
170
|
+
}
|
|
171
|
+
if (this.highDpi) {
|
|
172
|
+
request.highDpi = true;
|
|
173
|
+
}
|
|
174
|
+
this.sessionRequest = request;
|
|
175
|
+
this.onMoveEnd = () => {
|
|
176
|
+
void this.updateAttribution();
|
|
177
|
+
};
|
|
178
|
+
this.sessionPromise = this.startSessionFetch();
|
|
179
|
+
}
|
|
180
|
+
onAdd(map) {
|
|
181
|
+
this.mapInstance = map;
|
|
182
|
+
map.on('moveend', this.onMoveEnd);
|
|
183
|
+
map.on('zoomend', this.onMoveEnd);
|
|
184
|
+
void this.ensureSession().then(() => this.updateAttribution());
|
|
185
|
+
return super.onAdd(map);
|
|
186
|
+
}
|
|
187
|
+
onRemove(map) {
|
|
188
|
+
map.off('moveend', this.onMoveEnd);
|
|
189
|
+
map.off('zoomend', this.onMoveEnd);
|
|
190
|
+
this.clearSessionRefresh();
|
|
191
|
+
this.removeCurrentAttribution();
|
|
192
|
+
this.mapInstance = undefined;
|
|
193
|
+
return super.onRemove(map);
|
|
194
|
+
}
|
|
195
|
+
createTile(coords, done) {
|
|
196
|
+
const tile = document.createElement('img');
|
|
197
|
+
tile.decoding = 'async';
|
|
198
|
+
tile.alt = '';
|
|
199
|
+
tile.crossOrigin = 'anonymous';
|
|
200
|
+
const size = this.resolveTileSize();
|
|
201
|
+
tile.width = size.x;
|
|
202
|
+
tile.height = size.y;
|
|
203
|
+
const handleError = (err) => {
|
|
204
|
+
const message = err instanceof Error ? err.message : 'Google tile load error';
|
|
205
|
+
done(new Error(message), tile);
|
|
206
|
+
};
|
|
207
|
+
tile.onload = () => done(null, tile);
|
|
208
|
+
tile.onerror = (event) => {
|
|
209
|
+
const err = event instanceof ErrorEvent
|
|
210
|
+
? event.error ?? new Error(event.message)
|
|
211
|
+
: new Error('Google tile failed to load');
|
|
212
|
+
handleError(err);
|
|
213
|
+
};
|
|
214
|
+
void this.ensureSession()
|
|
215
|
+
.then(() => {
|
|
216
|
+
if (!this.sessionToken) {
|
|
217
|
+
handleError(new Error('Google Maps session unavailable'));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
tile.src = this.buildTileUrl(coords);
|
|
221
|
+
})
|
|
222
|
+
.catch((err) => {
|
|
223
|
+
handleError(err);
|
|
224
|
+
});
|
|
225
|
+
return tile;
|
|
226
|
+
}
|
|
227
|
+
ensureSession() {
|
|
228
|
+
if (this.sessionToken) {
|
|
229
|
+
return Promise.resolve();
|
|
230
|
+
}
|
|
231
|
+
if (!this.sessionPromise) {
|
|
232
|
+
this.sessionPromise = this.startSessionFetch();
|
|
233
|
+
}
|
|
234
|
+
return this.sessionPromise;
|
|
235
|
+
}
|
|
236
|
+
startSessionFetch(force = false) {
|
|
237
|
+
if (this.sessionPromise && !force) {
|
|
238
|
+
return this.sessionPromise;
|
|
239
|
+
}
|
|
240
|
+
const promise = this.fetchAndApplySession()
|
|
241
|
+
.catch((err) => {
|
|
242
|
+
const wrapped = err instanceof Error
|
|
243
|
+
? err
|
|
244
|
+
: new Error('Failed to create Google Maps session');
|
|
245
|
+
messages.error('Google Map Tiles session error', wrapped);
|
|
246
|
+
this.sessionToken = undefined;
|
|
247
|
+
throw wrapped;
|
|
248
|
+
})
|
|
249
|
+
.finally(() => {
|
|
250
|
+
if (this.sessionPromise === promise) {
|
|
251
|
+
this.sessionPromise = undefined;
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
this.sessionPromise = promise;
|
|
255
|
+
return promise;
|
|
256
|
+
}
|
|
257
|
+
async fetchAndApplySession() {
|
|
258
|
+
const url = `${CREATE_SESSION_URL}?key=${this.apiKey}`;
|
|
259
|
+
const response = await fetch(url, {
|
|
260
|
+
method: 'POST',
|
|
261
|
+
headers: {
|
|
262
|
+
'Content-Type': 'application/json',
|
|
263
|
+
},
|
|
264
|
+
body: JSON.stringify(this.sessionRequest),
|
|
265
|
+
});
|
|
266
|
+
if (!response.ok) {
|
|
267
|
+
let details;
|
|
268
|
+
try {
|
|
269
|
+
const body = await response.json();
|
|
270
|
+
details = body?.error?.message;
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
// ignore JSON parse errors
|
|
274
|
+
}
|
|
275
|
+
throw new Error(details ?? `Google Maps session request failed (${response.status})`);
|
|
276
|
+
}
|
|
277
|
+
const data = (await response.json());
|
|
278
|
+
this.sessionToken = data.session;
|
|
279
|
+
this.applyTileSize(data);
|
|
280
|
+
this.scheduleSessionRefresh(this.parseExpiry(data.expiry));
|
|
281
|
+
if (this.mapInstance) {
|
|
282
|
+
void this.updateAttribution();
|
|
283
|
+
this.redrawLayer();
|
|
284
|
+
}
|
|
285
|
+
messages.log('Google Map Tiles session established');
|
|
286
|
+
}
|
|
287
|
+
scheduleSessionRefresh(expiryMs) {
|
|
288
|
+
if (!isFinite(expiryMs))
|
|
289
|
+
return;
|
|
290
|
+
const refreshInMs = Math.max(expiryMs - Date.now() - SESSION_REFRESH_BUFFER_MS, 1000);
|
|
291
|
+
this.clearSessionRefresh();
|
|
292
|
+
this.sessionRefreshId = setTimeout(() => {
|
|
293
|
+
void this.startSessionFetch(true).then(() => {
|
|
294
|
+
if (this.mapInstance) {
|
|
295
|
+
void this.updateAttribution();
|
|
296
|
+
this.redrawLayer();
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}, refreshInMs);
|
|
300
|
+
}
|
|
301
|
+
clearSessionRefresh() {
|
|
302
|
+
if (this.sessionRefreshId !== undefined) {
|
|
303
|
+
clearTimeout(this.sessionRefreshId);
|
|
304
|
+
this.sessionRefreshId = undefined;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
async updateAttribution() {
|
|
308
|
+
if (!this.mapInstance || !this.sessionToken)
|
|
309
|
+
return;
|
|
310
|
+
const bounds = this.mapInstance.getBounds();
|
|
311
|
+
if (!bounds?.isValid())
|
|
312
|
+
return;
|
|
313
|
+
const zoom = this.mapInstance.getZoom();
|
|
314
|
+
const viewport = `zoom=${zoom}&north=${bounds.getNorth()}&south=${bounds.getSouth()}&east=${bounds.getEast()}&west=${bounds.getWest()}`;
|
|
315
|
+
if (this.previousViewport === viewport) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
this.previousViewport = viewport;
|
|
319
|
+
try {
|
|
320
|
+
const response = await fetch(`${ATTRIBUTION_URL}?session=${this.sessionToken}&key=${this.apiKey}&${viewport}`);
|
|
321
|
+
if (!response.ok) {
|
|
322
|
+
throw new Error(`Attribution request failed (${response.status})`);
|
|
323
|
+
}
|
|
324
|
+
const json = await response.json();
|
|
325
|
+
const copyright = json?.copyright;
|
|
326
|
+
if (typeof copyright === 'string' && copyright.length > 0) {
|
|
327
|
+
this.applyAttribution(copyright);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
messages.error('Failed to fetch Google attribution', err);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
applyAttribution(value) {
|
|
335
|
+
const map = this.mapInstance;
|
|
336
|
+
if (!map?.attributionControl)
|
|
337
|
+
return;
|
|
338
|
+
if (this.currentAttribution && this.currentAttribution !== value) {
|
|
339
|
+
map.attributionControl.removeAttribution(this.currentAttribution);
|
|
340
|
+
}
|
|
341
|
+
if (!this.currentAttribution || this.currentAttribution !== value) {
|
|
342
|
+
map.attributionControl.addAttribution(value);
|
|
343
|
+
this.currentAttribution = value;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
removeCurrentAttribution() {
|
|
347
|
+
const map = this.mapInstance;
|
|
348
|
+
if (!map?.attributionControl || !this.currentAttribution)
|
|
349
|
+
return;
|
|
350
|
+
map.attributionControl.removeAttribution(this.currentAttribution);
|
|
351
|
+
this.currentAttribution = undefined;
|
|
352
|
+
}
|
|
353
|
+
applyTileSize(data) {
|
|
354
|
+
const width = Math.max(1, Math.round(data.tileWidth / this.scaleFactor));
|
|
355
|
+
const height = Math.max(1, Math.round(data.tileHeight / this.scaleFactor));
|
|
356
|
+
const tileSize = L__namespace.point(width, height);
|
|
357
|
+
this.setGridOptions({ tileSize });
|
|
358
|
+
}
|
|
359
|
+
parseExpiry(expiry) {
|
|
360
|
+
const asInt = parseInt(expiry, 10);
|
|
361
|
+
return Number.isFinite(asInt) ? asInt * 1000 : Number.NaN;
|
|
362
|
+
}
|
|
363
|
+
buildTileUrl(coords) {
|
|
364
|
+
if (!this.sessionToken) {
|
|
365
|
+
throw new Error('Google Maps session missing');
|
|
366
|
+
}
|
|
367
|
+
const z = coords.z;
|
|
368
|
+
const x = coords.x;
|
|
369
|
+
const y = coords.y;
|
|
370
|
+
return `${TILE_URL_BASE}/${z}/${x}/${y}?session=${this.sessionToken}&key=${this.apiKey}`;
|
|
371
|
+
}
|
|
372
|
+
mapScaleToFactor(scale, highDpi) {
|
|
373
|
+
switch (scale) {
|
|
374
|
+
case 'scaleFactor4x':
|
|
375
|
+
return 4;
|
|
376
|
+
case 'scaleFactor2x':
|
|
377
|
+
return 2;
|
|
378
|
+
case 'scaleFactor1x':
|
|
379
|
+
return 1;
|
|
380
|
+
default:
|
|
381
|
+
return highDpi ? 2 : 1;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
factorToScale(factor) {
|
|
385
|
+
switch (factor) {
|
|
386
|
+
case 4:
|
|
387
|
+
return 'scaleFactor4x';
|
|
388
|
+
case 2:
|
|
389
|
+
return 'scaleFactor2x';
|
|
390
|
+
case 1:
|
|
391
|
+
return 'scaleFactor1x';
|
|
392
|
+
default:
|
|
393
|
+
return undefined;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
applyInitialGridOptions(options) {
|
|
397
|
+
const payload = {};
|
|
398
|
+
const keys = [
|
|
399
|
+
'attribution',
|
|
400
|
+
'bounds',
|
|
401
|
+
'className',
|
|
402
|
+
'detectRetina',
|
|
403
|
+
'errorTileUrl',
|
|
404
|
+
'keepBuffer',
|
|
405
|
+
'maxNativeZoom',
|
|
406
|
+
'maxZoom',
|
|
407
|
+
'minNativeZoom',
|
|
408
|
+
'minZoom',
|
|
409
|
+
'noWrap',
|
|
410
|
+
'opacity',
|
|
411
|
+
'pane',
|
|
412
|
+
'reuseTiles',
|
|
413
|
+
'subdomains',
|
|
414
|
+
'tileSize',
|
|
415
|
+
'tms',
|
|
416
|
+
'updateInterval',
|
|
417
|
+
'updateWhenIdle',
|
|
418
|
+
'updateWhenZooming',
|
|
419
|
+
'zIndex',
|
|
420
|
+
'zoomOffset',
|
|
421
|
+
];
|
|
422
|
+
for (const key of keys) {
|
|
423
|
+
const value = options[key];
|
|
424
|
+
if (value !== undefined) {
|
|
425
|
+
payload[key] = value;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (payload.maxZoom === undefined) {
|
|
429
|
+
payload.maxZoom = DEFAULT_MAX_ZOOM;
|
|
430
|
+
}
|
|
431
|
+
this.setGridOptions(payload);
|
|
432
|
+
}
|
|
433
|
+
setGridOptions(options) {
|
|
434
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- L.Util.setOptions is typed as (obj: any, options: any) => any in Leaflet
|
|
435
|
+
const setOptionsFn = L__namespace.Util?.setOptions;
|
|
436
|
+
if (typeof setOptionsFn === 'function') {
|
|
437
|
+
setOptionsFn(this, options);
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
const self = this;
|
|
441
|
+
self.options = {
|
|
442
|
+
...self.options,
|
|
443
|
+
...options,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
resolveTileSize() {
|
|
448
|
+
const raw = this.options?.tileSize;
|
|
449
|
+
if (raw && typeof raw === 'object') {
|
|
450
|
+
if (Array.isArray(raw) && raw.length === 2) {
|
|
451
|
+
const [x, y] = raw;
|
|
452
|
+
return L__namespace.point(Number(x) || FALLBACK_TILE_SIZE, Number(y) || FALLBACK_TILE_SIZE);
|
|
453
|
+
}
|
|
454
|
+
if ('x' in raw && 'y' in raw) {
|
|
455
|
+
const point = raw;
|
|
456
|
+
return L__namespace.point(Number(point.x) || FALLBACK_TILE_SIZE, Number(point.y) || FALLBACK_TILE_SIZE);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
if (typeof raw === 'number' && Number.isFinite(raw)) {
|
|
460
|
+
return L__namespace.point(raw, raw);
|
|
461
|
+
}
|
|
462
|
+
return L__namespace.point(FALLBACK_TILE_SIZE, FALLBACK_TILE_SIZE);
|
|
463
|
+
}
|
|
464
|
+
redrawLayer() {
|
|
465
|
+
this.redraw();
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
class GeoTIFFGridLayer extends L__namespace.GridLayer {
|
|
470
|
+
geotiffOptions;
|
|
471
|
+
tileProcessor = null;
|
|
472
|
+
colorStops;
|
|
473
|
+
loadingPromise;
|
|
474
|
+
defaultResolution = 1;
|
|
475
|
+
defaultResample = 'bilinear';
|
|
476
|
+
constructor(options) {
|
|
477
|
+
super(options);
|
|
478
|
+
this.geotiffOptions = { ...options };
|
|
479
|
+
}
|
|
480
|
+
onAdd(map) {
|
|
481
|
+
super.onAdd(map);
|
|
482
|
+
void this.ensureReady().then(() => this.redraw());
|
|
483
|
+
return this;
|
|
484
|
+
}
|
|
485
|
+
createTile(coords, done) {
|
|
486
|
+
const size = this.getTileSize();
|
|
487
|
+
const canvas = L__namespace.DomUtil.create('canvas', 'leaflet-tile');
|
|
488
|
+
canvas.width = size.x;
|
|
489
|
+
canvas.height = size.y;
|
|
490
|
+
this.ensureReady()
|
|
491
|
+
.then(async () => {
|
|
492
|
+
if (!this.tileProcessor) {
|
|
493
|
+
done(null, canvas);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
const rgba = await this.tileProcessor.getTileData({
|
|
498
|
+
x: coords.x,
|
|
499
|
+
y: coords.y,
|
|
500
|
+
z: coords.z,
|
|
501
|
+
tileSize: size.x,
|
|
502
|
+
resolution: this.geotiffOptions.resolution ?? this.defaultResolution,
|
|
503
|
+
resampleMethod: this.geotiffOptions.resampleMethod ?? this.defaultResample,
|
|
504
|
+
colorStops: this.colorStops,
|
|
505
|
+
});
|
|
506
|
+
if (!rgba) {
|
|
507
|
+
done(null, canvas);
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
const ctx = canvas.getContext('2d');
|
|
511
|
+
if (ctx) {
|
|
512
|
+
const imageData = ctx.createImageData(size.x, size.y);
|
|
513
|
+
imageData.data.set(rgba);
|
|
514
|
+
ctx.putImageData(imageData, 0, 0);
|
|
515
|
+
}
|
|
516
|
+
done(null, canvas);
|
|
517
|
+
}
|
|
518
|
+
catch (err) {
|
|
519
|
+
done(err, canvas);
|
|
520
|
+
}
|
|
521
|
+
})
|
|
522
|
+
.catch(err => {
|
|
523
|
+
done(err, canvas);
|
|
524
|
+
});
|
|
525
|
+
return canvas;
|
|
526
|
+
}
|
|
527
|
+
async ensureReady() {
|
|
528
|
+
if (!this.loadingPromise) {
|
|
529
|
+
this.loadingPromise = this.initializeProcessor();
|
|
530
|
+
}
|
|
531
|
+
return this.loadingPromise;
|
|
532
|
+
}
|
|
533
|
+
async updateSource(options) {
|
|
534
|
+
Object.assign(this.geotiffOptions, options);
|
|
535
|
+
this.tileProcessor = null;
|
|
536
|
+
this.colorStops = undefined;
|
|
537
|
+
this.loadingPromise = undefined;
|
|
538
|
+
await this.ensureReady();
|
|
539
|
+
this.redraw();
|
|
540
|
+
}
|
|
541
|
+
async initializeProcessor() {
|
|
542
|
+
if (this.tileProcessor)
|
|
543
|
+
return;
|
|
544
|
+
const [geotiffModule, { default: proj4 }, geokeysModule] = await Promise.all([
|
|
545
|
+
Promise.resolve().then(function () { return require('./geotiff-CEwvF9cG.js'); }).then(function (n) { return n.geotiff; }),
|
|
546
|
+
Promise.resolve().then(function () { return require('./index-B1oGO1g-.js'); }),
|
|
547
|
+
Promise.resolve().then(function () { return require('./main-dist-7TykwFci.js'); }).then(function (n) { return n.mainDist; }),
|
|
548
|
+
]);
|
|
549
|
+
const source = await geotiffSource.loadGeoTIFFSource(this.geotiffOptions.url, {
|
|
550
|
+
projection: undefined,
|
|
551
|
+
forceProjection: false,
|
|
552
|
+
nodata: this.geotiffOptions.nodata,
|
|
553
|
+
}, {
|
|
554
|
+
geotiff: geotiffModule,
|
|
555
|
+
proj4,
|
|
556
|
+
geokeysToProj4: geokeysModule,
|
|
557
|
+
});
|
|
558
|
+
const transformViewToSourceMapFn = (coord) => {
|
|
559
|
+
const result = source.proj4(this.geotiffOptions.viewProjection, //source.toProjection,
|
|
560
|
+
source.fromProjection, coord);
|
|
561
|
+
return [Number(result[0]), Number(result[1])];
|
|
562
|
+
};
|
|
563
|
+
const transformSourceMapToViewFn = (coord) => {
|
|
564
|
+
const result = source.proj4(source.fromProjection, this.geotiffOptions.viewProjection, //source.toProjection,
|
|
565
|
+
coord);
|
|
566
|
+
return [Number(result[0]), Number(result[1])];
|
|
567
|
+
};
|
|
568
|
+
this.tileProcessor = new geotiffSource.GeoTIFFTileProcessor({
|
|
569
|
+
transformViewToSourceMapFn,
|
|
570
|
+
transformSourceMapToViewFn,
|
|
571
|
+
sourceBounds: source.sourceBounds,
|
|
572
|
+
sourceRef: source.sourceRef,
|
|
573
|
+
resolution: source.resolution,
|
|
574
|
+
imageWidth: source.width,
|
|
575
|
+
imageHeight: source.height,
|
|
576
|
+
fromProjection: source.fromProjection,
|
|
577
|
+
toProjection: this.geotiffOptions.viewProjection, //source.toProjection,
|
|
578
|
+
baseImage: source.baseImage,
|
|
579
|
+
overviewImages: source.overviewImages ?? [],
|
|
580
|
+
});
|
|
581
|
+
this.tileProcessor.createGlobalTriangulation();
|
|
582
|
+
// Set bounds to restrict tile loading to GeoTIFF coverage area
|
|
583
|
+
this.setViewBounds(source.sourceBounds, transformSourceMapToViewFn);
|
|
584
|
+
if (this.geotiffOptions.colorMap) {
|
|
585
|
+
const { stops } = geotiffSource.getColorStops(this.geotiffOptions.colorMap, this.geotiffOptions.valueRange);
|
|
586
|
+
this.colorStops = stops;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Set Leaflet bounds from GeoTIFF source bounds
|
|
591
|
+
* Restricts tile loading to the GeoTIFF coverage area
|
|
592
|
+
*/
|
|
593
|
+
setViewBounds(sourceBounds, transformSourceToView) {
|
|
594
|
+
const [srcWest, srcSouth, srcEast, srcNorth] = sourceBounds;
|
|
595
|
+
// Transform corners from Source to View (Web Mercator for Leaflet)
|
|
596
|
+
const sw = transformSourceToView([srcWest, srcSouth]);
|
|
597
|
+
const se = transformSourceToView([srcEast, srcSouth]);
|
|
598
|
+
const nw = transformSourceToView([srcWest, srcNorth]);
|
|
599
|
+
const ne = transformSourceToView([srcEast, srcNorth]);
|
|
600
|
+
// Calculate bounds in View coordinates
|
|
601
|
+
const minX = Math.min(sw[0], se[0], nw[0], ne[0]);
|
|
602
|
+
const maxX = Math.max(sw[0], se[0], nw[0], ne[0]);
|
|
603
|
+
const minY = Math.min(sw[1], se[1], nw[1], ne[1]);
|
|
604
|
+
const maxY = Math.max(sw[1], se[1], nw[1], ne[1]);
|
|
605
|
+
// Convert to Leaflet LatLngBounds (Web Mercator meters to lat/lng)
|
|
606
|
+
const southWest = L__namespace.CRS.EPSG3857.unproject(L__namespace.point(minX, maxY));
|
|
607
|
+
const northEast = L__namespace.CRS.EPSG3857.unproject(L__namespace.point(maxX, minY));
|
|
608
|
+
// Set bounds option - Leaflet will use this to restrict tile loading
|
|
609
|
+
this.options.bounds = L__namespace.latLngBounds(southWest, northEast);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
const LOG_PREFIX = 'v-map - leaflet - wcs - tile - ';
|
|
614
|
+
/**
|
|
615
|
+
* Custom Leaflet GridLayer for WCS (Web Coverage Service) support
|
|
616
|
+
*
|
|
617
|
+
* Supports:
|
|
618
|
+
* - WCS 2.0.1 with subset parameters
|
|
619
|
+
* - WCS 1.x.x with BBOX parameters (backward compatibility)
|
|
620
|
+
* - GeoTIFF FLOAT32 format
|
|
621
|
+
* - Dynamic BBOX-based requests
|
|
622
|
+
*/
|
|
623
|
+
class WCSGridLayer extends L__namespace.GridLayer {
|
|
624
|
+
wcsOptions;
|
|
625
|
+
constructor(options) {
|
|
626
|
+
super(options);
|
|
627
|
+
this.wcsOptions = {
|
|
628
|
+
...options,
|
|
629
|
+
version: options.version ?? '2.0.1',
|
|
630
|
+
format: options.format ?? 'image/tiff',
|
|
631
|
+
projection: options.projection ?? 'EPSG:4326',
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Build WCS GetCoverage URL for a given tile
|
|
636
|
+
*/
|
|
637
|
+
buildWCSUrl(coords) {
|
|
638
|
+
const { url, coverageName, version, format, projection, params } = this.wcsOptions;
|
|
639
|
+
// Calculate tile bounds in lat/lng
|
|
640
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Leaflet private method not exposed in type definitions
|
|
641
|
+
const tileBounds = this._tileCoordsToBounds(coords);
|
|
642
|
+
const southwest = tileBounds.getSouthWest();
|
|
643
|
+
const northeast = tileBounds.getNorthEast();
|
|
644
|
+
const minx = southwest.lng;
|
|
645
|
+
const miny = southwest.lat;
|
|
646
|
+
const maxx = northeast.lng;
|
|
647
|
+
const maxy = northeast.lat;
|
|
648
|
+
const baseParams = {
|
|
649
|
+
SERVICE: 'WCS',
|
|
650
|
+
REQUEST: 'GetCoverage',
|
|
651
|
+
VERSION: version,
|
|
652
|
+
FORMAT: format,
|
|
653
|
+
};
|
|
654
|
+
// WCS 2.0.1 uses subset parameters
|
|
655
|
+
if (version.startsWith('2.0')) {
|
|
656
|
+
baseParams.coverageId = coverageName;
|
|
657
|
+
// Build URL with subset parameters
|
|
658
|
+
// Note: We can't use the same param name twice in URLSearchParams,
|
|
659
|
+
// so we'll manually construct the query string
|
|
660
|
+
const extraParams = params ? { ...params } : {};
|
|
661
|
+
const allParams = { ...baseParams, ...extraParams };
|
|
662
|
+
// Add GeoTIFF compression if format is tiff
|
|
663
|
+
if (format.includes('tiff') || format.includes('geotiff')) {
|
|
664
|
+
allParams['geotiff:compression'] = 'LZW';
|
|
665
|
+
}
|
|
666
|
+
const query = new URLSearchParams();
|
|
667
|
+
Object.entries(allParams).forEach(([key, value]) => {
|
|
668
|
+
if (value !== undefined && value !== null) {
|
|
669
|
+
query.set(key, String(value));
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
// Manually add subset parameters (can't use URLSearchParams for duplicate keys)
|
|
673
|
+
const queryString = query.toString();
|
|
674
|
+
const subsetX = `subset=X(${minx},${maxx})`;
|
|
675
|
+
const subsetY = `subset=Y(${miny},${maxy})`;
|
|
676
|
+
return `${url}${url.includes('?') ? '&' : '?'}${queryString}&${subsetX}&${subsetY}`;
|
|
677
|
+
}
|
|
678
|
+
// WCS 1.x.x uses BBOX parameter
|
|
679
|
+
else {
|
|
680
|
+
baseParams.COVERAGE = coverageName;
|
|
681
|
+
baseParams.BBOX = `${minx},${miny},${maxx},${maxy}`;
|
|
682
|
+
baseParams.CRS = projection;
|
|
683
|
+
// Calculate width and height for the tile
|
|
684
|
+
const tileSize = this.getTileSize();
|
|
685
|
+
baseParams.WIDTH = typeof tileSize === 'number' ? tileSize : tileSize.x;
|
|
686
|
+
baseParams.HEIGHT = typeof tileSize === 'number' ? tileSize : tileSize.y;
|
|
687
|
+
const extraParams = params ? { ...params } : {};
|
|
688
|
+
const allParams = { ...baseParams, ...extraParams };
|
|
689
|
+
const query = new URLSearchParams();
|
|
690
|
+
Object.entries(allParams).forEach(([key, value]) => {
|
|
691
|
+
if (value !== undefined && value !== null) {
|
|
692
|
+
query.set(key, String(value));
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
return `${url}${url.includes('?') ? '&' : '?'}${query.toString()}`;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Create tile element (required by GridLayer)
|
|
700
|
+
*/
|
|
701
|
+
createTile(coords, done) {
|
|
702
|
+
const tile = document.createElement('img');
|
|
703
|
+
const wcsUrl = this.buildWCSUrl(coords);
|
|
704
|
+
messages.log(`${LOG_PREFIX}load: coords=(${coords.x},${coords.y},${coords.z})`);
|
|
705
|
+
messages.log(`${LOG_PREFIX}url: ${wcsUrl}`);
|
|
706
|
+
tile.onload = () => {
|
|
707
|
+
done(null, tile);
|
|
708
|
+
};
|
|
709
|
+
tile.onerror = (err) => {
|
|
710
|
+
messages.error(`${LOG_PREFIX}failed to load tile:`, err);
|
|
711
|
+
done(err instanceof Error ? err : new Error(String(err)), tile);
|
|
712
|
+
};
|
|
713
|
+
// Set crossOrigin for CORS support
|
|
714
|
+
tile.crossOrigin = 'anonymous';
|
|
715
|
+
tile.src = wcsUrl;
|
|
716
|
+
return tile;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Update WCS options and redraw
|
|
720
|
+
*/
|
|
721
|
+
updateOptions(newOptions) {
|
|
722
|
+
this.wcsOptions = {
|
|
723
|
+
...this.wcsOptions,
|
|
724
|
+
...newOptions,
|
|
725
|
+
};
|
|
726
|
+
this.redraw();
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
class LeafletProvider {
|
|
731
|
+
map;
|
|
732
|
+
layers = [];
|
|
733
|
+
baseLayers = [];
|
|
734
|
+
hiddenLayerGroups = [];
|
|
735
|
+
googleLogoAdded = false;
|
|
736
|
+
unsubscribeResize;
|
|
737
|
+
shadowRoot;
|
|
738
|
+
injectedStyle;
|
|
739
|
+
layerErrorCallbacks = new Map();
|
|
740
|
+
layerErrorCleanups = new Map();
|
|
741
|
+
async init(options) {
|
|
742
|
+
if (!vMap_vMapLayerOsm_vMapLayergroup_entry.isBrowser())
|
|
743
|
+
return;
|
|
744
|
+
this.shadowRoot = options.shadowRoot;
|
|
745
|
+
this.injectedStyle = ensureLeafletCss(options.cssMode, this.shadowRoot);
|
|
746
|
+
const [lon, lat] = (options?.mapInitOptions?.center ?? [0, 0]);
|
|
747
|
+
this.map = L__namespace.map(options.target, {
|
|
748
|
+
zoomControl: true,
|
|
749
|
+
attributionControl: true,
|
|
750
|
+
}).setView([lat, lon], options?.mapInitOptions?.zoom ?? 2);
|
|
751
|
+
this.unsubscribeResize = vMap_vMapLayerOsm_vMapLayergroup_entry.watchElementResize(options.target, () => {
|
|
752
|
+
this.map?.invalidateSize();
|
|
753
|
+
}, {
|
|
754
|
+
attributes: true,
|
|
755
|
+
attributeFilter: ['style', 'class'],
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
async updateLayer(layerId, update) {
|
|
759
|
+
const layer = await this._getLayerById(layerId);
|
|
760
|
+
switch (update.type) {
|
|
761
|
+
case 'geojson':
|
|
762
|
+
await this.updateGeoJSONLayer(layer, update.data);
|
|
763
|
+
break;
|
|
764
|
+
case 'osm':
|
|
765
|
+
await this.updateOSMLayer(layer, update.data);
|
|
766
|
+
break;
|
|
767
|
+
case 'arcgis':
|
|
768
|
+
await this.updateArcGISLayer(layer, update.data);
|
|
769
|
+
break;
|
|
770
|
+
case 'wkt':
|
|
771
|
+
await this.updateWKTLayer(layer, update.data);
|
|
772
|
+
break;
|
|
773
|
+
case 'geotiff':
|
|
774
|
+
await this.updateGeoTIFFLayer(layer, update.data);
|
|
775
|
+
break;
|
|
776
|
+
case 'wcs':
|
|
777
|
+
await this.updateWCSLayer(layer, update.data);
|
|
778
|
+
break;
|
|
779
|
+
case 'wfs':
|
|
780
|
+
if (layer instanceof L__namespace.GeoJSON) {
|
|
781
|
+
await this.updateWFSLayer(layer, update.data);
|
|
782
|
+
}
|
|
783
|
+
break;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
// private async addStandaloneLayer(layerConfig: LayerConfig): Promise<L.Layer> {
|
|
787
|
+
// const layer = await this.createLayer(layerConfig);
|
|
788
|
+
// layer.addTo(this.map!);
|
|
789
|
+
// this.layers.push(layer);
|
|
790
|
+
// }
|
|
791
|
+
async addLayerToGroup(layerConfig) {
|
|
792
|
+
const group = await this._ensureGroup(layerConfig.groupId, layerConfig.groupVisible);
|
|
793
|
+
const layer = await this.createLayer(layerConfig);
|
|
794
|
+
if (layer == null) {
|
|
795
|
+
return null;
|
|
796
|
+
}
|
|
797
|
+
group.addLayer(layer);
|
|
798
|
+
const layerId = this.getLayerId(layer);
|
|
799
|
+
layer.vmapVisible = true;
|
|
800
|
+
layer.vmapOpacity = 1.0;
|
|
801
|
+
if (layerConfig.opacity !== undefined) {
|
|
802
|
+
this.setOpacityByLayer(layer, layerConfig.opacity);
|
|
803
|
+
}
|
|
804
|
+
if (layerConfig.zIndex !== undefined) {
|
|
805
|
+
layer.setZIndex?.(layerConfig.zIndex);
|
|
806
|
+
}
|
|
807
|
+
if (layerConfig.visible) {
|
|
808
|
+
this.setVisibleByLayer(layer, true);
|
|
809
|
+
}
|
|
810
|
+
else if (layerConfig.visible === false) {
|
|
811
|
+
this.setVisibleByLayer(layer, false);
|
|
812
|
+
}
|
|
813
|
+
return layerId;
|
|
814
|
+
}
|
|
815
|
+
// async addLayer(config: LayerConfig): Promise<string> {
|
|
816
|
+
// if (!this.map) return;
|
|
817
|
+
// let layer: L.Layer = null;
|
|
818
|
+
// if ('groupId' in config && config.groupId) {
|
|
819
|
+
// try {
|
|
820
|
+
// layer = await this.addLayerToGroup(
|
|
821
|
+
// config as LayerConfig & { groupId: string },
|
|
822
|
+
// );
|
|
823
|
+
// } catch (ex) {
|
|
824
|
+
// error('addLayer - Unerwarteter Fehler:', ex);
|
|
825
|
+
// return null;
|
|
826
|
+
// }
|
|
827
|
+
// } else {
|
|
828
|
+
// try {
|
|
829
|
+
// layer = await this.addStandaloneLayer(config);
|
|
830
|
+
// } catch (ex) {
|
|
831
|
+
// error('addLayer - Unerwarteter Fehler:', ex);
|
|
832
|
+
// return null;
|
|
833
|
+
// }
|
|
834
|
+
// }
|
|
835
|
+
// if (layer == null) {
|
|
836
|
+
// return null;
|
|
837
|
+
// }
|
|
838
|
+
// const layerId = L.Util.stamp(layer); //layer._leaflet_id;
|
|
839
|
+
// layer.vmapVisible = true;
|
|
840
|
+
// layer.vmapOpacity = 1.0;
|
|
841
|
+
// if (config.opacity !== undefined) {
|
|
842
|
+
// this.setOpacityByLayer(layer, config.opacity);
|
|
843
|
+
// }
|
|
844
|
+
// if (config.zIndex !== undefined) {
|
|
845
|
+
// layer.setZIndex(config.zIndex);
|
|
846
|
+
// }
|
|
847
|
+
// if (config.visible) {
|
|
848
|
+
// this.setVisibleByLayer(layer, true);
|
|
849
|
+
// } else if (config.visible === false) {
|
|
850
|
+
// this.setVisibleByLayer(layer, false);
|
|
851
|
+
// }
|
|
852
|
+
// return layerId;
|
|
853
|
+
// }
|
|
854
|
+
async addBaseLayer(layerConfig, basemapid, layerElementId) {
|
|
855
|
+
if (layerElementId === undefined || layerElementId === null) {
|
|
856
|
+
messages.log('leaflet - addBaseLayer - layerElementId not set.');
|
|
857
|
+
return null;
|
|
858
|
+
}
|
|
859
|
+
if (basemapid === undefined || basemapid === null) {
|
|
860
|
+
messages.log('leaflet - addBaseLayer - basemapid not set.');
|
|
861
|
+
}
|
|
862
|
+
const group = await this._ensureGroup(layerConfig.groupId, layerConfig.groupVisible);
|
|
863
|
+
group.basemap = true;
|
|
864
|
+
const layer = await this.createLayer(layerConfig);
|
|
865
|
+
// layer.group = group;
|
|
866
|
+
this.baseLayers.push(layer);
|
|
867
|
+
if (layer == null) {
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
layer.layerElementId = layerElementId;
|
|
871
|
+
const layerId = this.getLayerId(layer);
|
|
872
|
+
layer.vmapVisible = true;
|
|
873
|
+
layer.vmapOpacity = 1.0;
|
|
874
|
+
if (layerConfig.opacity !== undefined) {
|
|
875
|
+
this.setOpacityByLayer(layer, layerConfig.opacity);
|
|
876
|
+
}
|
|
877
|
+
if (layerConfig.zIndex !== undefined) {
|
|
878
|
+
layer.setZIndex?.(layerConfig.zIndex);
|
|
879
|
+
}
|
|
880
|
+
if (layerConfig.visible) {
|
|
881
|
+
this.setVisibleByLayer(layer, true);
|
|
882
|
+
}
|
|
883
|
+
else if (layerConfig.visible === false) {
|
|
884
|
+
this.setVisibleByLayer(layer, false);
|
|
885
|
+
}
|
|
886
|
+
if (basemapid === layerElementId) {
|
|
887
|
+
const prev_layer = group.getLayers()[0];
|
|
888
|
+
if (prev_layer) {
|
|
889
|
+
this.map.removeLayer(prev_layer);
|
|
890
|
+
group.clearLayers();
|
|
891
|
+
}
|
|
892
|
+
group.addLayer(layer);
|
|
893
|
+
if (group.visible) {
|
|
894
|
+
layer.addTo(this.map);
|
|
895
|
+
}
|
|
896
|
+
//group.layerId = layerId;
|
|
897
|
+
}
|
|
898
|
+
return layerId;
|
|
899
|
+
}
|
|
900
|
+
async setBaseLayer(groupId, layerElementId) {
|
|
901
|
+
if (layerElementId === null) {
|
|
902
|
+
messages.log('leaflet - setBaseLayer - layerElementId is null.');
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
const group = this.layers.find(l => l._groupId === groupId);
|
|
906
|
+
const layer = this.baseLayers.find(l => l.layerElementId === layerElementId);
|
|
907
|
+
if (layer === undefined) {
|
|
908
|
+
messages.log('leaflet - setBaseLayer - layer not found. layerElementId: ' +
|
|
909
|
+
layerElementId);
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
if (!group) {
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
const prev_layer = group.getLayers()[0];
|
|
916
|
+
if (prev_layer) {
|
|
917
|
+
this.map.removeLayer(prev_layer);
|
|
918
|
+
group.clearLayers();
|
|
919
|
+
}
|
|
920
|
+
group.addLayer(layer);
|
|
921
|
+
////layer.addTo(this.map!);
|
|
922
|
+
//group.layerId = layerId;
|
|
923
|
+
//group.set('layerId', layerId, false);
|
|
924
|
+
}
|
|
925
|
+
getLayerId(layer) {
|
|
926
|
+
return String(L__namespace.Util.stamp(layer));
|
|
927
|
+
}
|
|
928
|
+
normalizeAttribution(attribution) {
|
|
929
|
+
if (Array.isArray(attribution)) {
|
|
930
|
+
return attribution.join(', ');
|
|
931
|
+
}
|
|
932
|
+
return attribution;
|
|
933
|
+
}
|
|
934
|
+
async _getLayerById(layerId) {
|
|
935
|
+
let layerFound = null;
|
|
936
|
+
this.map?.eachLayer(layer => {
|
|
937
|
+
if (this.getLayerId(layer) === layerId) {
|
|
938
|
+
layerFound = layer;
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
if (layerFound)
|
|
942
|
+
return layerFound;
|
|
943
|
+
layerFound =
|
|
944
|
+
this.baseLayers.find(l => this.getLayerId(l) === layerId) ?? null;
|
|
945
|
+
if (layerFound === undefined)
|
|
946
|
+
return null;
|
|
947
|
+
return layerFound;
|
|
948
|
+
}
|
|
949
|
+
async createLayer(layerConfig) {
|
|
950
|
+
switch (layerConfig.type) {
|
|
951
|
+
case 'geojson':
|
|
952
|
+
return this.createGeoJSONLayer(layerConfig);
|
|
953
|
+
case 'xyz':
|
|
954
|
+
return this.createXYZLayer(layerConfig);
|
|
955
|
+
case 'osm':
|
|
956
|
+
return this.createOSMLayer(layerConfig);
|
|
957
|
+
case 'wms':
|
|
958
|
+
return this.createWMSLayer(layerConfig);
|
|
959
|
+
case 'wcs':
|
|
960
|
+
return this.createWCSLayer(layerConfig);
|
|
961
|
+
case 'wfs':
|
|
962
|
+
return this.createWFSLayer(layerConfig);
|
|
963
|
+
case 'arcgis':
|
|
964
|
+
return this.createArcGISLayer(layerConfig);
|
|
965
|
+
case 'google':
|
|
966
|
+
return this.createGoogleLayer(layerConfig);
|
|
967
|
+
case 'wkt':
|
|
968
|
+
return this.createWKTLayer(layerConfig);
|
|
969
|
+
case 'geotiff':
|
|
970
|
+
return this.createGeoTIFFLayer(layerConfig);
|
|
971
|
+
default:
|
|
972
|
+
throw new Error(`Unsupported layer type: ${layerConfig.type}`);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
async updateGeoJSONLayer(layer, data) {
|
|
976
|
+
if (!(layer instanceof L__namespace.GeoJSON))
|
|
977
|
+
return;
|
|
978
|
+
let geoJsonData = null;
|
|
979
|
+
if (data.geojson) {
|
|
980
|
+
geoJsonData = JSON.parse(data.geojson);
|
|
981
|
+
}
|
|
982
|
+
else if (data.url) {
|
|
983
|
+
const res = await fetch(data.url);
|
|
984
|
+
if (!res.ok)
|
|
985
|
+
throw new Error(`GeoJSON fetch failed: ${res.status} ${res.statusText}`);
|
|
986
|
+
geoJsonData = await res.json();
|
|
987
|
+
}
|
|
988
|
+
layer.clearLayers();
|
|
989
|
+
layer.addData(geoJsonData);
|
|
990
|
+
}
|
|
991
|
+
async createGeoJSONLayer(config) {
|
|
992
|
+
let data = null;
|
|
993
|
+
if (config.geojson) {
|
|
994
|
+
data = JSON.parse(config.geojson);
|
|
995
|
+
}
|
|
996
|
+
else if (config.url) {
|
|
997
|
+
const res = await fetch(config.url);
|
|
998
|
+
if (!res.ok)
|
|
999
|
+
throw new Error(`GeoJSON fetch failed: ${res.status} ${res.statusText}`);
|
|
1000
|
+
data = await res.json();
|
|
1001
|
+
}
|
|
1002
|
+
if (data) {
|
|
1003
|
+
// Use geostyler style if available, otherwise use provided style or default style
|
|
1004
|
+
let layerOptions = {};
|
|
1005
|
+
if (config.geostylerStyle) {
|
|
1006
|
+
layerOptions = await this.createGeostylerLeafletOptions(config.geostylerStyle);
|
|
1007
|
+
}
|
|
1008
|
+
else {
|
|
1009
|
+
const style = config.style
|
|
1010
|
+
? { ...styleconfig.DEFAULT_STYLE, ...config.style }
|
|
1011
|
+
: styleconfig.DEFAULT_STYLE;
|
|
1012
|
+
layerOptions = {
|
|
1013
|
+
style: this.createLeafletStyle(style),
|
|
1014
|
+
pointToLayer: (feature, latlng) => this.createLeafletPoint(feature, latlng, style),
|
|
1015
|
+
onEachFeature: (feature, layer) => this.bindLeafletPopup(feature, layer, style),
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
const layer = L__namespace.geoJSON(data, layerOptions);
|
|
1019
|
+
return layer;
|
|
1020
|
+
}
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
1023
|
+
async createXYZLayer(config) {
|
|
1024
|
+
const layer = L__namespace.tileLayer(config.url, {
|
|
1025
|
+
attribution: this.normalizeAttribution(config.attributions),
|
|
1026
|
+
maxZoom: config.maxZoom ?? 19,
|
|
1027
|
+
...(config.options ?? {}),
|
|
1028
|
+
});
|
|
1029
|
+
return layer;
|
|
1030
|
+
}
|
|
1031
|
+
async updateOSMLayer(layer, data) {
|
|
1032
|
+
if (!('setUrl' in layer) || typeof layer.setUrl !== 'function')
|
|
1033
|
+
return;
|
|
1034
|
+
let url = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
|
|
1035
|
+
if (data.url) {
|
|
1036
|
+
url = data.url + '/{z}/{x}/{y}.png';
|
|
1037
|
+
}
|
|
1038
|
+
layer.setUrl(url);
|
|
1039
|
+
}
|
|
1040
|
+
async createOSMLayer(cfg) {
|
|
1041
|
+
let url = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
|
|
1042
|
+
if (cfg.url) {
|
|
1043
|
+
url = cfg.url + '/{z}/{x}/{y}.png';
|
|
1044
|
+
}
|
|
1045
|
+
return L__namespace.tileLayer(url, {
|
|
1046
|
+
attribution: '© OpenStreetMap contributors',
|
|
1047
|
+
maxZoom: 19,
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
async createWMSLayer(config) {
|
|
1051
|
+
return L__namespace.tileLayer.wms(config.url, {
|
|
1052
|
+
layers: config.layers,
|
|
1053
|
+
format: config.format ?? 'image/png',
|
|
1054
|
+
transparent: config.transparent ?? true,
|
|
1055
|
+
...(config.extraParams ?? {}),
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
buildArcGISUrl(url, params) {
|
|
1059
|
+
if (!params || Object.keys(params).length === 0)
|
|
1060
|
+
return url;
|
|
1061
|
+
const query = new URLSearchParams();
|
|
1062
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
1063
|
+
if (value !== undefined && value !== null) {
|
|
1064
|
+
query.set(key, String(value));
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
if (query.toString().length === 0)
|
|
1068
|
+
return url;
|
|
1069
|
+
return `${url}${url.includes('?') ? '&' : '?'}${query.toString()}`;
|
|
1070
|
+
}
|
|
1071
|
+
async createArcGISLayer(config) {
|
|
1072
|
+
const params = {
|
|
1073
|
+
...(config.params ?? {}),
|
|
1074
|
+
};
|
|
1075
|
+
if (config.token) {
|
|
1076
|
+
params.token = config.token;
|
|
1077
|
+
}
|
|
1078
|
+
const arcgisUrl = this.buildArcGISUrl(config.url, params);
|
|
1079
|
+
const options = {
|
|
1080
|
+
attribution: this.normalizeAttribution(config.attributions),
|
|
1081
|
+
minZoom: config.minZoom,
|
|
1082
|
+
maxZoom: config.maxZoom,
|
|
1083
|
+
...(config.options ?? {}),
|
|
1084
|
+
};
|
|
1085
|
+
return L__namespace.tileLayer(arcgisUrl, options);
|
|
1086
|
+
}
|
|
1087
|
+
async updateArcGISLayer(layer, data) {
|
|
1088
|
+
const params = {
|
|
1089
|
+
...(data?.params ?? {}),
|
|
1090
|
+
};
|
|
1091
|
+
if (data?.token) {
|
|
1092
|
+
params.token = data.token;
|
|
1093
|
+
}
|
|
1094
|
+
const tileLayer = layer;
|
|
1095
|
+
const targetUrl = data?.url ?? tileLayer.options?.url ?? '';
|
|
1096
|
+
const nextUrl = this.buildArcGISUrl(targetUrl, params);
|
|
1097
|
+
if ('setUrl' in tileLayer && typeof tileLayer.setUrl === 'function') {
|
|
1098
|
+
tileLayer.setUrl(nextUrl);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
async createGoogleLayer(config) {
|
|
1102
|
+
if (!this.map)
|
|
1103
|
+
throw new Error('Map not initialized');
|
|
1104
|
+
if (!config.apiKey)
|
|
1105
|
+
throw new Error("Google-Layer benötigt 'apiKey' (Google Maps Platform).");
|
|
1106
|
+
const parsedStyles = typeof config.styles === 'string'
|
|
1107
|
+
? this.tryParseStyles(config.styles)
|
|
1108
|
+
: config.styles;
|
|
1109
|
+
const googleLayer = new GoogleMapTilesLayer({
|
|
1110
|
+
apiKey: config.apiKey,
|
|
1111
|
+
mapType: config.mapType ?? 'roadmap',
|
|
1112
|
+
language: config.language,
|
|
1113
|
+
region: config.region,
|
|
1114
|
+
scale: config.scale,
|
|
1115
|
+
highDpi: config.highDpi,
|
|
1116
|
+
layerTypes: config.layerTypes,
|
|
1117
|
+
overlay: config.overlay,
|
|
1118
|
+
styles: Array.isArray(parsedStyles) ? parsedStyles : undefined,
|
|
1119
|
+
imageFormat: config.imageFormat,
|
|
1120
|
+
apiOptions: config.apiOptions,
|
|
1121
|
+
maxZoom: config.maxZoom ?? 22,
|
|
1122
|
+
});
|
|
1123
|
+
ensureGoogleLogo(this.map, () => {
|
|
1124
|
+
this.googleLogoAdded = true;
|
|
1125
|
+
messages.log('v-map - provider - leaflet - googleLogoAdded: ', this.googleLogoAdded);
|
|
1126
|
+
});
|
|
1127
|
+
return googleLayer;
|
|
1128
|
+
}
|
|
1129
|
+
tryParseStyles(value) {
|
|
1130
|
+
try {
|
|
1131
|
+
const parsed = JSON.parse(value);
|
|
1132
|
+
return Array.isArray(parsed) ? parsed : undefined;
|
|
1133
|
+
}
|
|
1134
|
+
catch {
|
|
1135
|
+
messages.error('Failed to parse Google styles JSON');
|
|
1136
|
+
return undefined;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
async destroy() {
|
|
1140
|
+
this.unsubscribeResize?.();
|
|
1141
|
+
removeInjectedCss(this.shadowRoot, this.injectedStyle);
|
|
1142
|
+
for (const l of this.layers) {
|
|
1143
|
+
this.map?.removeLayer(l);
|
|
1144
|
+
}
|
|
1145
|
+
this.layers = [];
|
|
1146
|
+
this.map?.remove();
|
|
1147
|
+
this.map = undefined;
|
|
1148
|
+
}
|
|
1149
|
+
async setView([lon, lat], zoom) {
|
|
1150
|
+
this.map?.setView([lat, lon], zoom, { animate: false });
|
|
1151
|
+
}
|
|
1152
|
+
onLayerError(layerId, callback) {
|
|
1153
|
+
this.layerErrorCallbacks.set(layerId, callback);
|
|
1154
|
+
this._getLayerById(layerId).then(layer => {
|
|
1155
|
+
if (!layer)
|
|
1156
|
+
return;
|
|
1157
|
+
const handler = () => { callback({ type: 'network', message: 'Tile load error' }); };
|
|
1158
|
+
layer.on('tileerror', handler);
|
|
1159
|
+
this.layerErrorCleanups.set(layerId, () => layer.off('tileerror', handler));
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
offLayerError(layerId) {
|
|
1163
|
+
this.layerErrorCleanups.get(layerId)?.();
|
|
1164
|
+
this.layerErrorCleanups.delete(layerId);
|
|
1165
|
+
this.layerErrorCallbacks.delete(layerId);
|
|
1166
|
+
}
|
|
1167
|
+
async removeLayer(layerId) {
|
|
1168
|
+
if (!layerId) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
this.offLayerError(layerId);
|
|
1172
|
+
const layer = await this._getLayerById(layerId);
|
|
1173
|
+
if (layer) {
|
|
1174
|
+
this.map.removeLayer(layer);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
async setZIndex(layerId, zIndex) {
|
|
1178
|
+
if (!layerId) {
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
const layer = await this._getLayerById(layerId);
|
|
1182
|
+
if (layer) {
|
|
1183
|
+
if (typeof layer.setZIndex === 'function') {
|
|
1184
|
+
layer.setZIndex(zIndex);
|
|
1185
|
+
} //todo
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
async setOpacity(layerId, opacity) {
|
|
1189
|
+
if (!layerId)
|
|
1190
|
+
return;
|
|
1191
|
+
const layer = await this._getLayerById(layerId);
|
|
1192
|
+
this.setOpacityByLayer(layer, opacity);
|
|
1193
|
+
}
|
|
1194
|
+
setOpacityByLayer(layer, opacity) {
|
|
1195
|
+
if (!layer)
|
|
1196
|
+
return;
|
|
1197
|
+
// 1. Speichere die Ziel-Opazität (auch wenn Layer unsichtbar)
|
|
1198
|
+
layer.vmapOpacity = opacity;
|
|
1199
|
+
if (layer.vmapVisible === undefined) {
|
|
1200
|
+
layer.vmapVisible = true;
|
|
1201
|
+
}
|
|
1202
|
+
// 2. Wende sie nur an, wenn der Layer sichtbar IST ODER GEMACHT WIRD
|
|
1203
|
+
// (vermeidet unnötige setOpacity-Aufrufe, wenn vmapVisible=false)
|
|
1204
|
+
if (layer.vmapVisible !== false) {
|
|
1205
|
+
this.setLayerOpacity(layer, opacity);
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
async setVisible(layerId, visible) {
|
|
1209
|
+
if (!layerId)
|
|
1210
|
+
return;
|
|
1211
|
+
const layer = await this._getLayerById(layerId);
|
|
1212
|
+
this.setVisibleByLayer(layer, visible);
|
|
1213
|
+
}
|
|
1214
|
+
setVisibleByLayer(layer, visible) {
|
|
1215
|
+
if (!layer)
|
|
1216
|
+
return;
|
|
1217
|
+
// 1. Aktualisiere den Sichtbarkeitszustand
|
|
1218
|
+
layer.vmapVisible = visible;
|
|
1219
|
+
if (layer.vmapOpacity === undefined) {
|
|
1220
|
+
layer.vmapOpacity = 1.0;
|
|
1221
|
+
}
|
|
1222
|
+
// 2. Setze die Opazität basierend auf dem neuen Zustand:
|
|
1223
|
+
const targetOpacity = visible ? layer.vmapOpacity : 0.0;
|
|
1224
|
+
this.setLayerOpacity(layer, targetOpacity);
|
|
1225
|
+
}
|
|
1226
|
+
setLayerOpacity(layer, options) {
|
|
1227
|
+
if (!layer)
|
|
1228
|
+
return;
|
|
1229
|
+
const opacity = typeof options === 'number' ? options : options.opacity ?? 1;
|
|
1230
|
+
const fillOpacity = typeof options === 'number' ? options : options.fillOpacity ?? opacity;
|
|
1231
|
+
const hasLeafletClass = (candidate, className) => {
|
|
1232
|
+
if (!(className in L__namespace))
|
|
1233
|
+
return false;
|
|
1234
|
+
const ctor = L__namespace[className];
|
|
1235
|
+
return (typeof ctor === 'function' &&
|
|
1236
|
+
candidate instanceof ctor);
|
|
1237
|
+
};
|
|
1238
|
+
const isLayerCollection = (candidate) => hasLeafletClass(candidate, 'GeoJSON') ||
|
|
1239
|
+
hasLeafletClass(candidate, 'LayerGroup');
|
|
1240
|
+
const isPathLayer = (candidate) => hasLeafletClass(candidate, 'Path');
|
|
1241
|
+
const isMarkerLayer = (candidate) => hasLeafletClass(candidate, 'Marker');
|
|
1242
|
+
if (isLayerCollection(layer)) {
|
|
1243
|
+
layer.eachLayer(subLayer => this.setLayerOpacity(subLayer, options));
|
|
1244
|
+
}
|
|
1245
|
+
else if (isPathLayer(layer)) {
|
|
1246
|
+
layer.setStyle({ opacity, fillOpacity });
|
|
1247
|
+
}
|
|
1248
|
+
else if (isMarkerLayer(layer)) {
|
|
1249
|
+
layer.setOpacity(opacity);
|
|
1250
|
+
}
|
|
1251
|
+
else if ('setOpacity' in layer) {
|
|
1252
|
+
layer.setOpacity(opacity);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
async ensureGroup(groupId, visible, _opts) {
|
|
1256
|
+
await this._ensureGroup(groupId, visible);
|
|
1257
|
+
}
|
|
1258
|
+
async _ensureGroup(groupId, visible) {
|
|
1259
|
+
let group = await this._getLayerGroupById(groupId);
|
|
1260
|
+
if (!group) {
|
|
1261
|
+
group = L__namespace.layerGroup();
|
|
1262
|
+
group._groupId = groupId;
|
|
1263
|
+
group.visible = true;
|
|
1264
|
+
group.addTo(this.map);
|
|
1265
|
+
this.layers.push(group);
|
|
1266
|
+
}
|
|
1267
|
+
this.setGroupVisible(groupId, visible !== undefined ? visible : true);
|
|
1268
|
+
return group;
|
|
1269
|
+
}
|
|
1270
|
+
async _getLayerGroupById(groupId) {
|
|
1271
|
+
if (!this.map) {
|
|
1272
|
+
return null;
|
|
1273
|
+
}
|
|
1274
|
+
let group = this.layers.find(l => l instanceof L__namespace.LayerGroup && l._groupId === groupId);
|
|
1275
|
+
if (!group) {
|
|
1276
|
+
group = this.hiddenLayerGroups.find(lg => lg._groupId === groupId);
|
|
1277
|
+
if (!group)
|
|
1278
|
+
return null;
|
|
1279
|
+
}
|
|
1280
|
+
return group;
|
|
1281
|
+
}
|
|
1282
|
+
async setGroupVisible(groupId, visible) {
|
|
1283
|
+
const layerGroup = await this._getLayerGroupById(groupId);
|
|
1284
|
+
if (layerGroup) {
|
|
1285
|
+
if (layerGroup.visible === visible)
|
|
1286
|
+
return;
|
|
1287
|
+
if (layerGroup.visible === false) {
|
|
1288
|
+
layerGroup.addTo(this.map);
|
|
1289
|
+
// remove layergroup from hidden list
|
|
1290
|
+
this.hiddenLayerGroups = this.hiddenLayerGroups.filter(lg => lg._groupId !== groupId);
|
|
1291
|
+
layerGroup.visible = visible;
|
|
1292
|
+
}
|
|
1293
|
+
else if (layerGroup.visible === true) {
|
|
1294
|
+
this.map.removeLayer(layerGroup);
|
|
1295
|
+
// add layergroup to hidden list
|
|
1296
|
+
layerGroup.visible = visible;
|
|
1297
|
+
this.hiddenLayerGroups.push(layerGroup);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
async updateWKTLayer(layer, data) {
|
|
1302
|
+
if (!(layer instanceof L__namespace.GeoJSON))
|
|
1303
|
+
return;
|
|
1304
|
+
let geoJsonData = null;
|
|
1305
|
+
if (data.wkt) {
|
|
1306
|
+
geoJsonData = await this.wktToGeoJSON(data.wkt);
|
|
1307
|
+
}
|
|
1308
|
+
else if (data.url) {
|
|
1309
|
+
try {
|
|
1310
|
+
const response = await fetch(data.url);
|
|
1311
|
+
if (!response.ok)
|
|
1312
|
+
throw new Error(`Failed to fetch WKT: ${response.status}`);
|
|
1313
|
+
const wktText = await response.text();
|
|
1314
|
+
geoJsonData = await this.wktToGeoJSON(wktText);
|
|
1315
|
+
}
|
|
1316
|
+
catch (e) {
|
|
1317
|
+
messages.error('Failed to load WKT from URL:', e);
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
if (geoJsonData) {
|
|
1322
|
+
layer.clearLayers();
|
|
1323
|
+
// Update layer options to use enhanced styling
|
|
1324
|
+
const geoJsonLayer = layer;
|
|
1325
|
+
geoJsonLayer.options.style = this.createLeafletStyle(data.style);
|
|
1326
|
+
geoJsonLayer.options.pointToLayer = (feature, latlng) => this.createLeafletPoint(feature, latlng, data.style);
|
|
1327
|
+
geoJsonLayer.options.onEachFeature = (feature, layer) => this.bindLeafletPopup(feature, layer, data.style);
|
|
1328
|
+
geoJsonLayer.addData(geoJsonData);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
async createWKTLayer(config) {
|
|
1332
|
+
let geoJsonData = null;
|
|
1333
|
+
const emptyCollection = { type: 'FeatureCollection', features: [] };
|
|
1334
|
+
if (config.wkt) {
|
|
1335
|
+
geoJsonData = await this.wktToGeoJSON(config.wkt);
|
|
1336
|
+
}
|
|
1337
|
+
else if (config.url) {
|
|
1338
|
+
try {
|
|
1339
|
+
const response = await fetch(config.url);
|
|
1340
|
+
if (!response.ok)
|
|
1341
|
+
throw new Error(`Failed to fetch WKT: ${response.status}`);
|
|
1342
|
+
const wktText = await response.text();
|
|
1343
|
+
geoJsonData = await this.wktToGeoJSON(wktText);
|
|
1344
|
+
}
|
|
1345
|
+
catch (e) {
|
|
1346
|
+
messages.error('Failed to load WKT from URL:', e);
|
|
1347
|
+
geoJsonData = emptyCollection;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
else {
|
|
1351
|
+
geoJsonData = emptyCollection;
|
|
1352
|
+
}
|
|
1353
|
+
messages.log('[Leaflet WKT] Creating layer with GeoJSON data:', geoJsonData);
|
|
1354
|
+
messages.log('[Leaflet WKT] Config:', config);
|
|
1355
|
+
// Use geostyler style if available, otherwise use config style or default
|
|
1356
|
+
let layerOptions = {};
|
|
1357
|
+
if (config.geostylerStyle) {
|
|
1358
|
+
layerOptions = await this.createGeostylerLeafletOptions(config.geostylerStyle);
|
|
1359
|
+
}
|
|
1360
|
+
else {
|
|
1361
|
+
const style = config.style
|
|
1362
|
+
? { ...styleconfig.DEFAULT_STYLE, ...config.style }
|
|
1363
|
+
: styleconfig.DEFAULT_STYLE;
|
|
1364
|
+
layerOptions = {
|
|
1365
|
+
style: this.createLeafletStyle(style),
|
|
1366
|
+
pointToLayer: (feature, latlng) => this.createLeafletPoint(feature, latlng, style),
|
|
1367
|
+
onEachFeature: (feature, layer) => this.bindLeafletPopup(feature, layer, style),
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
messages.log('[Leaflet WKT] Layer options:', layerOptions);
|
|
1371
|
+
const layer = L__namespace.geoJSON(geoJsonData, layerOptions);
|
|
1372
|
+
messages.log('[Leaflet WKT] Created layer:', layer);
|
|
1373
|
+
if (typeof layer.getBounds === 'function') {
|
|
1374
|
+
messages.log('[Leaflet WKT] Layer bounds:', layer.getBounds());
|
|
1375
|
+
}
|
|
1376
|
+
return layer;
|
|
1377
|
+
}
|
|
1378
|
+
async wktToGeoJSON(wkt) {
|
|
1379
|
+
try {
|
|
1380
|
+
// Use wellknown library to parse WKT into GeoJSON (browser-compatible)
|
|
1381
|
+
const geoJSON = index.wellknownExports.wellknown.parse(wkt);
|
|
1382
|
+
if (!geoJSON) {
|
|
1383
|
+
throw new Error('Failed to parse WKT - returned null');
|
|
1384
|
+
}
|
|
1385
|
+
// Return as a Feature
|
|
1386
|
+
const feature = {
|
|
1387
|
+
type: 'Feature',
|
|
1388
|
+
geometry: geoJSON,
|
|
1389
|
+
properties: {},
|
|
1390
|
+
};
|
|
1391
|
+
// Debug output to browser console
|
|
1392
|
+
messages.log('[Leaflet WKT] Input WKT:', wkt);
|
|
1393
|
+
messages.log('[Leaflet WKT] Generated GeoJSON:', JSON.stringify(feature, null, 2));
|
|
1394
|
+
const fc = {
|
|
1395
|
+
type: 'FeatureCollection',
|
|
1396
|
+
features: [feature],
|
|
1397
|
+
};
|
|
1398
|
+
return fc;
|
|
1399
|
+
}
|
|
1400
|
+
catch (e) {
|
|
1401
|
+
messages.error('[Leaflet WKT] Failed to parse WKT:', wkt, e);
|
|
1402
|
+
// If parsing fails, return empty FeatureCollection
|
|
1403
|
+
const empty = { type: 'FeatureCollection', features: [] };
|
|
1404
|
+
return empty;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
async createGeoTIFFLayer(config) {
|
|
1408
|
+
if (!config.url) {
|
|
1409
|
+
throw new Error('GeoTIFF layer requires a URL');
|
|
1410
|
+
}
|
|
1411
|
+
try {
|
|
1412
|
+
const layer = new GeoTIFFGridLayer({
|
|
1413
|
+
url: config.url,
|
|
1414
|
+
tileSize: 256,
|
|
1415
|
+
colorMap: config.colorMap,
|
|
1416
|
+
valueRange: config.valueRange,
|
|
1417
|
+
nodata: config.nodata,
|
|
1418
|
+
resolution: config.resolution,
|
|
1419
|
+
resampleMethod: config.resampleMethod,
|
|
1420
|
+
viewProjection: this.map.options.crs.code,
|
|
1421
|
+
});
|
|
1422
|
+
if (config.opacity !== undefined) {
|
|
1423
|
+
layer.setOpacity?.(config.opacity);
|
|
1424
|
+
}
|
|
1425
|
+
if (config.zIndex !== undefined) {
|
|
1426
|
+
layer.setZIndex?.(config.zIndex);
|
|
1427
|
+
}
|
|
1428
|
+
return layer;
|
|
1429
|
+
}
|
|
1430
|
+
catch (err) {
|
|
1431
|
+
messages.error('Failed to create GeoTIFF layer:', err);
|
|
1432
|
+
// Return a placeholder layer in case of error
|
|
1433
|
+
return L__namespace.layerGroup([]);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
async updateGeoTIFFLayer(layer, data) {
|
|
1437
|
+
if (!data.url) {
|
|
1438
|
+
throw new Error('GeoTIFF update requires a URL');
|
|
1439
|
+
}
|
|
1440
|
+
if (!layer)
|
|
1441
|
+
return;
|
|
1442
|
+
if (!(layer instanceof GeoTIFFGridLayer))
|
|
1443
|
+
return;
|
|
1444
|
+
const extData = data;
|
|
1445
|
+
await layer.updateSource({
|
|
1446
|
+
url: data.url,
|
|
1447
|
+
colorMap: data.colorMap,
|
|
1448
|
+
valueRange: data.valueRange,
|
|
1449
|
+
nodata: data.nodata,
|
|
1450
|
+
resolution: extData.resolution,
|
|
1451
|
+
resampleMethod: extData.resampleMethod,
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
async createWCSLayer(config) {
|
|
1455
|
+
if (!config.url) {
|
|
1456
|
+
throw new Error('WCS layer requires a URL');
|
|
1457
|
+
}
|
|
1458
|
+
if (!config.coverageName) {
|
|
1459
|
+
throw new Error('WCS layer requires a coverageName');
|
|
1460
|
+
}
|
|
1461
|
+
try {
|
|
1462
|
+
const wcsOptions = {
|
|
1463
|
+
url: config.url,
|
|
1464
|
+
coverageName: config.coverageName,
|
|
1465
|
+
version: config.version ?? '2.0.1',
|
|
1466
|
+
format: config.format ?? 'image/tiff',
|
|
1467
|
+
projection: config.projection ?? 'EPSG:4326',
|
|
1468
|
+
params: config.params,
|
|
1469
|
+
};
|
|
1470
|
+
// Add GridLayer options
|
|
1471
|
+
if (config.tileSize)
|
|
1472
|
+
wcsOptions.tileSize = config.tileSize;
|
|
1473
|
+
if (config.minZoom !== undefined)
|
|
1474
|
+
wcsOptions.minZoom = config.minZoom;
|
|
1475
|
+
if (config.maxZoom !== undefined)
|
|
1476
|
+
wcsOptions.maxZoom = config.maxZoom;
|
|
1477
|
+
const layer = new WCSGridLayer(wcsOptions);
|
|
1478
|
+
if (config.opacity !== undefined) {
|
|
1479
|
+
layer.setOpacity?.(config.opacity);
|
|
1480
|
+
}
|
|
1481
|
+
if (config.zIndex !== undefined) {
|
|
1482
|
+
layer.setZIndex?.(config.zIndex);
|
|
1483
|
+
}
|
|
1484
|
+
return layer;
|
|
1485
|
+
}
|
|
1486
|
+
catch (err) {
|
|
1487
|
+
messages.error('[Leaflet WCS] Failed to create WCS layer:', err);
|
|
1488
|
+
// Return a placeholder layer in case of error
|
|
1489
|
+
return L__namespace.layerGroup([]);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
async updateWCSLayer(layer, data) {
|
|
1493
|
+
if (!layer)
|
|
1494
|
+
return;
|
|
1495
|
+
if (layer instanceof WCSGridLayer) {
|
|
1496
|
+
const updateOptions = {};
|
|
1497
|
+
if (data.url)
|
|
1498
|
+
updateOptions.url = data.url;
|
|
1499
|
+
if (data.coverageName)
|
|
1500
|
+
updateOptions.coverageName = data.coverageName;
|
|
1501
|
+
if (data.version)
|
|
1502
|
+
updateOptions.version = data.version;
|
|
1503
|
+
if (data.format)
|
|
1504
|
+
updateOptions.format = data.format;
|
|
1505
|
+
if (data.projection)
|
|
1506
|
+
updateOptions.projection = data.projection;
|
|
1507
|
+
if (data.params)
|
|
1508
|
+
updateOptions.params = data.params;
|
|
1509
|
+
layer.updateOptions(updateOptions);
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
// ========== Enhanced Styling Methods ==========
|
|
1513
|
+
/**
|
|
1514
|
+
* Convert a Geostyler style to Leaflet GeoJSON options
|
|
1515
|
+
*/
|
|
1516
|
+
async createGeostylerLeafletOptions(geostylerStyle) {
|
|
1517
|
+
// Helper to extract static value from GeoStyler property
|
|
1518
|
+
const getValue = (prop, defaultValue = undefined) => {
|
|
1519
|
+
if (prop === undefined || prop === null)
|
|
1520
|
+
return defaultValue;
|
|
1521
|
+
// If it's a GeoStyler function object, we can't evaluate it here - return default
|
|
1522
|
+
if (typeof prop === 'object' && prop.name)
|
|
1523
|
+
return defaultValue;
|
|
1524
|
+
return prop;
|
|
1525
|
+
};
|
|
1526
|
+
const options = {
|
|
1527
|
+
style: (feature) => {
|
|
1528
|
+
const geometryType = feature?.geometry?.type;
|
|
1529
|
+
let leafletStyle = {};
|
|
1530
|
+
if (geostylerStyle.rules) {
|
|
1531
|
+
for (const rule of geostylerStyle.rules) {
|
|
1532
|
+
if (rule.symbolizers) {
|
|
1533
|
+
for (const symbolizer of rule.symbolizers) {
|
|
1534
|
+
switch (symbolizer.kind) {
|
|
1535
|
+
case 'Fill':
|
|
1536
|
+
if (geometryType === 'Polygon' ||
|
|
1537
|
+
geometryType === 'MultiPolygon') {
|
|
1538
|
+
const fillColor = getValue(symbolizer.color, 'rgba(0,100,255,0.3)');
|
|
1539
|
+
const fillOpacity = getValue(symbolizer.opacity, 0.3);
|
|
1540
|
+
const outlineColor = getValue(symbolizer.outlineColor, 'rgba(0,100,255,1)');
|
|
1541
|
+
const outlineWidth = getValue(symbolizer.outlineWidth, 1);
|
|
1542
|
+
leafletStyle = {
|
|
1543
|
+
...leafletStyle,
|
|
1544
|
+
fillColor: fillColor,
|
|
1545
|
+
fillOpacity: fillOpacity,
|
|
1546
|
+
color: outlineColor,
|
|
1547
|
+
weight: outlineWidth,
|
|
1548
|
+
};
|
|
1549
|
+
}
|
|
1550
|
+
break;
|
|
1551
|
+
case 'Line':
|
|
1552
|
+
const lineColor = getValue(symbolizer.color, 'rgba(0,100,255,1)');
|
|
1553
|
+
const lineWidth = getValue(symbolizer.width, 2);
|
|
1554
|
+
const dashArray = symbolizer.dasharray
|
|
1555
|
+
? Array.isArray(symbolizer.dasharray)
|
|
1556
|
+
? symbolizer.dasharray
|
|
1557
|
+
.map((v) => getValue(v, 0))
|
|
1558
|
+
.join(',')
|
|
1559
|
+
: undefined
|
|
1560
|
+
: undefined;
|
|
1561
|
+
leafletStyle = {
|
|
1562
|
+
...leafletStyle,
|
|
1563
|
+
color: lineColor,
|
|
1564
|
+
weight: lineWidth,
|
|
1565
|
+
dashArray: dashArray,
|
|
1566
|
+
};
|
|
1567
|
+
break;
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
return leafletStyle;
|
|
1574
|
+
},
|
|
1575
|
+
pointToLayer: (_feature, latlng) => {
|
|
1576
|
+
if (geostylerStyle.rules) {
|
|
1577
|
+
for (const rule of geostylerStyle.rules) {
|
|
1578
|
+
if (rule.symbolizers) {
|
|
1579
|
+
for (const symbolizer of rule.symbolizers) {
|
|
1580
|
+
switch (symbolizer.kind) {
|
|
1581
|
+
case 'Mark':
|
|
1582
|
+
const markColor = getValue(symbolizer.color, 'rgba(0,100,255,1)');
|
|
1583
|
+
const markRadius = getValue(symbolizer.radius, 6);
|
|
1584
|
+
const strokeColor = getValue(symbolizer.strokeColor, 'rgba(0,100,255,1)');
|
|
1585
|
+
const strokeWidth = getValue(symbolizer.strokeWidth, 2);
|
|
1586
|
+
return L__namespace.circleMarker(latlng, {
|
|
1587
|
+
radius: markRadius,
|
|
1588
|
+
fillColor: markColor,
|
|
1589
|
+
fillOpacity: 1,
|
|
1590
|
+
color: strokeColor,
|
|
1591
|
+
weight: strokeWidth,
|
|
1592
|
+
});
|
|
1593
|
+
case 'Icon':
|
|
1594
|
+
const iconSrc = getValue(symbolizer.image);
|
|
1595
|
+
const iconSize = getValue(symbolizer.size, 32);
|
|
1596
|
+
if (iconSrc && typeof iconSrc === 'string') {
|
|
1597
|
+
const icon = L__namespace.icon({
|
|
1598
|
+
iconUrl: iconSrc,
|
|
1599
|
+
iconSize: [iconSize, iconSize],
|
|
1600
|
+
iconAnchor: [iconSize / 2, iconSize],
|
|
1601
|
+
});
|
|
1602
|
+
return L__namespace.marker(latlng, { icon });
|
|
1603
|
+
}
|
|
1604
|
+
break;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
// Default point style
|
|
1611
|
+
return L__namespace.circleMarker(latlng, {
|
|
1612
|
+
radius: 6,
|
|
1613
|
+
fillColor: 'rgba(0,100,255,1)',
|
|
1614
|
+
fillOpacity: 1,
|
|
1615
|
+
color: 'rgba(0,100,255,1)',
|
|
1616
|
+
weight: 2,
|
|
1617
|
+
});
|
|
1618
|
+
},
|
|
1619
|
+
onEachFeature: (feature, layer) => {
|
|
1620
|
+
if (geostylerStyle.rules) {
|
|
1621
|
+
for (const rule of geostylerStyle.rules) {
|
|
1622
|
+
if (rule.symbolizers) {
|
|
1623
|
+
for (const symbolizer of rule.symbolizers) {
|
|
1624
|
+
if (symbolizer.kind === 'Text') {
|
|
1625
|
+
const labelProp = symbolizer.label;
|
|
1626
|
+
if (labelProp &&
|
|
1627
|
+
typeof labelProp === 'string' &&
|
|
1628
|
+
feature.properties &&
|
|
1629
|
+
feature.properties[labelProp]) {
|
|
1630
|
+
const textContent = String(feature.properties[labelProp]);
|
|
1631
|
+
const textColor = getValue(symbolizer.color, '#000000');
|
|
1632
|
+
const textSize = getValue(symbolizer.size, 12);
|
|
1633
|
+
const styledText = `<div style="color: ${textColor}; font-size: ${textSize}px; font-family: Arial, sans-serif;">${textContent}</div>`;
|
|
1634
|
+
layer.bindTooltip(styledText, {
|
|
1635
|
+
permanent: true,
|
|
1636
|
+
direction: 'center',
|
|
1637
|
+
className: 'leaflet-tooltip-custom',
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
},
|
|
1646
|
+
};
|
|
1647
|
+
return options;
|
|
1648
|
+
}
|
|
1649
|
+
createLeafletStyle(style) {
|
|
1650
|
+
return (feature) => {
|
|
1651
|
+
const geometryType = feature?.geometry?.type;
|
|
1652
|
+
const fillColor = style?.fillColor ?? 'rgba(0,100,255,0.3)';
|
|
1653
|
+
const fillOpacity = style?.fillOpacity ?? 0.3;
|
|
1654
|
+
const strokeColor = style?.strokeColor ?? 'rgba(0,100,255,1)';
|
|
1655
|
+
const strokeOpacity = style?.strokeOpacity ?? 1;
|
|
1656
|
+
const strokeWidth = style?.strokeWidth ?? 2;
|
|
1657
|
+
if (geometryType === 'Polygon' || geometryType === 'MultiPolygon') {
|
|
1658
|
+
return {
|
|
1659
|
+
fillColor,
|
|
1660
|
+
fillOpacity,
|
|
1661
|
+
color: strokeColor,
|
|
1662
|
+
opacity: strokeOpacity,
|
|
1663
|
+
weight: strokeWidth,
|
|
1664
|
+
dashArray: style?.strokeDashArray
|
|
1665
|
+
? style.strokeDashArray.join(',')
|
|
1666
|
+
: undefined,
|
|
1667
|
+
};
|
|
1668
|
+
}
|
|
1669
|
+
if (geometryType === 'LineString' || geometryType === 'MultiLineString') {
|
|
1670
|
+
return {
|
|
1671
|
+
color: strokeColor,
|
|
1672
|
+
opacity: strokeOpacity,
|
|
1673
|
+
weight: strokeWidth,
|
|
1674
|
+
dashArray: style?.strokeDashArray
|
|
1675
|
+
? style.strokeDashArray.join(',')
|
|
1676
|
+
: undefined,
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
return {};
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1682
|
+
createLeafletPoint(feature, latlng, style) {
|
|
1683
|
+
let finalStyle = { ...(style ?? {}) };
|
|
1684
|
+
if (style?.styleFunction) {
|
|
1685
|
+
const conditionalStyle = style.styleFunction(feature);
|
|
1686
|
+
if (conditionalStyle) {
|
|
1687
|
+
finalStyle = {
|
|
1688
|
+
...style,
|
|
1689
|
+
...conditionalStyle,
|
|
1690
|
+
};
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
if (finalStyle?.iconUrl) {
|
|
1694
|
+
// Create icon marker
|
|
1695
|
+
const iconSize = finalStyle.iconSize || [32, 32];
|
|
1696
|
+
const iconAnchor = finalStyle.iconAnchor || [
|
|
1697
|
+
iconSize[0] / 2,
|
|
1698
|
+
iconSize[1],
|
|
1699
|
+
];
|
|
1700
|
+
const icon = L__namespace.icon({
|
|
1701
|
+
iconUrl: finalStyle.iconUrl,
|
|
1702
|
+
iconSize: iconSize,
|
|
1703
|
+
iconAnchor: iconAnchor,
|
|
1704
|
+
});
|
|
1705
|
+
return L__namespace.marker(latlng, { icon });
|
|
1706
|
+
}
|
|
1707
|
+
else {
|
|
1708
|
+
// Create circle marker
|
|
1709
|
+
const pointColor = finalStyle?.pointColor ?? 'rgba(0,100,255,1)';
|
|
1710
|
+
const pointOpacity = finalStyle?.pointOpacity ?? 1;
|
|
1711
|
+
const pointRadius = finalStyle?.pointRadius ?? 6;
|
|
1712
|
+
const strokeColor = finalStyle?.strokeColor ?? 'rgba(0,100,255,1)';
|
|
1713
|
+
const strokeOpacity = finalStyle?.strokeOpacity ?? 1;
|
|
1714
|
+
const strokeWidth = finalStyle?.strokeWidth ?? 2;
|
|
1715
|
+
return L__namespace.circleMarker(latlng, {
|
|
1716
|
+
radius: pointRadius,
|
|
1717
|
+
fillColor: pointColor,
|
|
1718
|
+
fillOpacity: pointOpacity,
|
|
1719
|
+
color: strokeColor,
|
|
1720
|
+
opacity: strokeOpacity,
|
|
1721
|
+
weight: strokeWidth,
|
|
1722
|
+
});
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
bindLeafletPopup(feature, layer, style) {
|
|
1726
|
+
// Text labeling via popup or tooltip - handle undefined style
|
|
1727
|
+
if (style?.textProperty &&
|
|
1728
|
+
feature.properties &&
|
|
1729
|
+
feature.properties[style.textProperty]) {
|
|
1730
|
+
const textContent = String(feature.properties[style.textProperty]);
|
|
1731
|
+
const textColor = style?.textColor ?? '#000000';
|
|
1732
|
+
const textSize = style?.textSize ?? 12;
|
|
1733
|
+
// Create styled text content
|
|
1734
|
+
const styledText = `<div style="color: ${textColor}; font-size: ${textSize}px; font-family: Arial, sans-serif;">${textContent}</div>`;
|
|
1735
|
+
// Bind as permanent tooltip for labels or popup for clickable info
|
|
1736
|
+
layer.bindTooltip(styledText, {
|
|
1737
|
+
permanent: true,
|
|
1738
|
+
direction: 'center',
|
|
1739
|
+
className: 'leaflet-tooltip-custom',
|
|
1740
|
+
});
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
async createWFSLayer(config) {
|
|
1744
|
+
const geojson = await this.fetchWFSFromUrl(config);
|
|
1745
|
+
// Use geostyler style if available, otherwise use provided style or default style
|
|
1746
|
+
let layerOptions = {};
|
|
1747
|
+
if (config.geostylerStyle) {
|
|
1748
|
+
layerOptions = await this.createGeostylerLeafletOptions(config.geostylerStyle);
|
|
1749
|
+
}
|
|
1750
|
+
else {
|
|
1751
|
+
const style = config.style
|
|
1752
|
+
? { ...styleconfig.DEFAULT_STYLE, ...config.style }
|
|
1753
|
+
: styleconfig.DEFAULT_STYLE;
|
|
1754
|
+
layerOptions = {
|
|
1755
|
+
style: this.createLeafletStyle(style),
|
|
1756
|
+
pointToLayer: (feature, latlng) => this.createLeafletPoint(feature, latlng, style),
|
|
1757
|
+
onEachFeature: (feature, layer) => this.bindLeafletPopup(feature, layer, style),
|
|
1758
|
+
};
|
|
1759
|
+
}
|
|
1760
|
+
const layer = L__namespace.geoJSON(geojson, layerOptions);
|
|
1761
|
+
return layer;
|
|
1762
|
+
}
|
|
1763
|
+
async updateWFSLayer(layer, data) {
|
|
1764
|
+
const geojson = await this.fetchWFSFromUrl(data);
|
|
1765
|
+
layer.clearLayers();
|
|
1766
|
+
layer.addData(geojson);
|
|
1767
|
+
}
|
|
1768
|
+
async fetchWFSFromUrl(config) {
|
|
1769
|
+
const baseParams = {
|
|
1770
|
+
service: 'WFS',
|
|
1771
|
+
request: 'GetFeature',
|
|
1772
|
+
version: config.version ?? '1.1.0',
|
|
1773
|
+
typeName: config.typeName,
|
|
1774
|
+
outputFormat: config.outputFormat ?? 'application/json',
|
|
1775
|
+
srsName: config.srsName ?? 'EPSG:4326',
|
|
1776
|
+
};
|
|
1777
|
+
const params = { ...baseParams, ...(config.params ?? {}) };
|
|
1778
|
+
const requestUrl = this.appendParams(config.url, params);
|
|
1779
|
+
const response = await fetch(requestUrl);
|
|
1780
|
+
if (!response.ok) {
|
|
1781
|
+
throw new Error(`WFS request failed (${response.status} ${response.statusText})`);
|
|
1782
|
+
}
|
|
1783
|
+
const outputFormat = (config.outputFormat ?? 'application/json').toLowerCase();
|
|
1784
|
+
// Handle JSON formats
|
|
1785
|
+
if (outputFormat.includes('json') ||
|
|
1786
|
+
outputFormat.includes('geojson') ||
|
|
1787
|
+
outputFormat === 'application/json') {
|
|
1788
|
+
return (await response.json());
|
|
1789
|
+
}
|
|
1790
|
+
// Handle GML formats - parse XML to GeoJSON using gml2geojson
|
|
1791
|
+
if (outputFormat.includes('gml') || outputFormat.includes('xml')) {
|
|
1792
|
+
const xml = await response.text();
|
|
1793
|
+
const parser = new index_browser.GmlParser();
|
|
1794
|
+
return (await parser.parse(xml));
|
|
1795
|
+
}
|
|
1796
|
+
// Default: try to parse as JSON
|
|
1797
|
+
return (await response.json());
|
|
1798
|
+
}
|
|
1799
|
+
appendParams(baseUrl, params) {
|
|
1800
|
+
const query = new URLSearchParams();
|
|
1801
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
1802
|
+
if (value !== undefined && value !== null) {
|
|
1803
|
+
query.set(key, String(value));
|
|
1804
|
+
}
|
|
1805
|
+
});
|
|
1806
|
+
if (!query.toString())
|
|
1807
|
+
return baseUrl;
|
|
1808
|
+
return `${baseUrl}${baseUrl.includes('?') ? '&' : '?'}${query.toString()}`;
|
|
1809
|
+
}
|
|
1810
|
+
getMap() {
|
|
1811
|
+
return this.map;
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
exports.LeafletProvider = LeafletProvider;
|