UNPKG

@dlr-eoc/map-cesium

Version:

This is a angular module that exports a cesium component that can handle UKIS layers. See @dlr-eoc/services-layers for supported types.

1,102 lines (1,101 loc) 75.3 kB
import * as i0 from '@angular/core'; import { Injectable, Input, ViewChild, ViewEncapsulation, Component } from '@angular/core'; import { TmsLayertype, RasterLayer, VectorLayer, WmtsLayertype, WmsLayertype, XyzLayertype } from '@dlr-eoc/services-layers'; import { JulianDate, TimeIntervalCollection, Color, Cartesian3, Rectangle, Math as Math$1, CesiumTerrainProvider, EllipsoidTerrainProvider, Cesium3DTileset, I3SDataProvider, ImageryLayer, UrlTemplateImageryProvider, WebMercatorTilingScheme, WebMapServiceImageryProvider, WebMapTileServiceImageryProvider, Credit, TileMapServiceImageryProvider, GeoJsonDataSource, BillboardGraphics, KmlDataSource, Cesium3DTileStyle, Ion, ScreenSpaceEventHandler, ScreenSpaceEventType } from '@cesium/engine'; import { Viewer } from '@cesium/widgets'; import { MapState } from '@dlr-eoc/services-map-state'; import { Subject } from 'rxjs'; import { skip } from 'rxjs/operators'; const WebMercator = 'EPSG:3857'; const WGS84 = 'EPSG:4326'; class MapCesiumService { constructor() { //map objects for ImageryLayers this.baseLayerImageryGroup = new Map(); this.standardLayerImageryGroup = new Map(); this.overlayLayerImageryGroup = new Map(); //map objects for vector DataSources this.baseLayerDataSourceGroup = new Map(); this.standardLayerDataSourceGroup = new Map(); this.overlayLayerDataSourceGroup = new Map(); //additional object for vector DataSource opacity this.dataSourceOpacity = new Map(); //map objects for 3D data this.terrainLayerGroup = new Map(); //Map for terrain containing layerID and visibility this.tilesetLayerGroup = new Map(); //Map for 3D tilesets containing layerID and viewer handler //Time objects this.cesiumCurrentTime = JulianDate.now(); this.cesiumTimeInterval = new TimeIntervalCollection(); //Default viewer options this.viewerOptions = { timeline: false, animation: false, sceneModePicker: false, homeButton: false, baseLayerPicker: false, geocoder: false, //the geocoder requires an cesium ion access token to work navigationHelpButton: false, navigationInstructionsInitiallyVisible: false, fullscreenButton: false, scene3DOnly: true, skyAtmosphere: false, infoBox: false, selectionIndicator: false, baseLayer: false }; this.defaultGlobeColor = Color.WHITE; this.EPSG = WebMercator; } //When the controlls are specified, change the default values of the viewer options setControls(newControls) { //If an ion access token is given, set it as default. Some cesium widgets are requiring an working token. if (typeof newControls.ionAccessToken !== 'undefined') { this.addIonAccessToken(newControls.ionAccessToken); } if (typeof newControls.GoogleMapsApiKey !== 'undefined') { this.addGoogleMapsApiKey(newControls.GoogleMapsApiKey); } if (typeof newControls.timeline !== 'undefined') { this.viewerOptions.timeline = newControls.timeline; } if (typeof newControls.animation !== 'undefined') { this.viewerOptions.animation = newControls.animation; } if (typeof newControls.sceneModePicker !== 'undefined') { this.viewerOptions.sceneModePicker = newControls.sceneModePicker; } if (typeof newControls.homeButton !== 'undefined') { this.viewerOptions.homeButton = newControls.homeButton; } if (typeof newControls.baseLayerPicker !== 'undefined') { this.viewerOptions.baseLayerPicker = newControls.baseLayerPicker; } if (typeof newControls.navigationHelpButton !== 'undefined') { this.viewerOptions.navigationHelpButton = newControls.navigationHelpButton; } if (typeof newControls.navigationInstructionsInitiallyVisible !== 'undefined') { this.viewerOptions.navigationInstructionsInitiallyVisible = newControls.navigationInstructionsInitiallyVisible; } if (typeof newControls.fullscreenButton !== 'undefined') { this.viewerOptions.fullscreenButton = newControls.fullscreenButton; } if (typeof newControls.scene3DOnly !== 'undefined') { this.viewerOptions.scene3DOnly = newControls.scene3DOnly; } if (typeof newControls.infoBox !== 'undefined') { this.viewerOptions.infoBox = newControls.infoBox; } if (typeof newControls.selectionIndicator !== 'undefined') { this.viewerOptions.selectionIndicator = newControls.selectionIndicator; } if (typeof newControls.globeColor !== 'undefined') { this.defaultGlobeColor = Color.fromCssColorString(newControls.globeColor); } } //Create Cesium Viewer createMap(target) { this.viewer = new Viewer(target, this.viewerOptions); //remove all default baselayers this.viewer.imageryLayers.removeAll(); //remove fog and ground atmosphere const scene = this.viewer.scene; scene.fog.enabled = false; scene.globe.showGroundAtmosphere = false; scene.sun.show = false; scene.moon.show = false; //reduce light effect on tilesets scene.globe.enableLighting = false; scene.highDynamicRange = false; //set default color to white for transparent backgrounds scene.globe.baseColor = this.defaultGlobeColor; //set start time this.viewer.clock.currentTime = this.cesiumCurrentTime; //change default infoBox if (this.viewerOptions.infoBox) { this.viewer.infoBox.container.getElementsByTagName('iframe')[0].remove(); const newDiv = document.createElement("div"); newDiv.className = 'cesium-infoBox-content'; newDiv.id = 'cesiumInfoBoxContent'; this.viewer.infoBox.container.children[0].append(newDiv); } //Change primitive collection settings this.viewer.scene.primitives.destroyPrimitives = false; return { viewer: this.viewer }; } // Map State functions // Partially not transferable to 3D globe, see: https://stackoverflow.com/questions/33237064/get-current-zoom-in-cesium // The following implementation is therefore not perfect but an approximation // Connection between zoom and map scale (WGS84/ EPSG: 4326): https://docs.geoserver.org/latest/en/user/styling/ysld/reference/scalezoom.html // map_scale = (2^zoom_level) / 559082264 // Connection between map scale and view height (very rough approximation): // map_scale = 0.1/height // height = 55908226 / (2^zoom_level) // zoom_level = log (55908226 / height) / log (2) // log (2) = 0.3 // There is also a constant offset between the zoom levels of the 2D and 3D map. To make the transition between the two maps more smooth, the cesium zoom level needs to be adjusted by this constant. setZoom(zoom, notifier) { //set screen size dependent scale constant const screenSizeConst = this.viewer.canvas.width / 1000; zoom = zoom - screenSizeConst; // calculate new height and get current camera position const height = 55908226 / Math.pow(2, zoom); const currentPosition = this.viewer.camera.positionCartographic; // set camera to new position this.viewer.camera.setView({ destination: Cartesian3.fromRadians(currentPosition.longitude, currentPosition.latitude, height) }); //console.log('SetZoom: ' + height + ', ' + currentPosition.longitude + ', ' + currentPosition.latitude); } getZoom() { let zoom; // get current height from viewer and calculate zoom value if (this.viewer) { const height = this.viewer.camera.positionCartographic.height; zoom = Math.round(Math.log10(55908226 / height) / 0.3); if (zoom < 0) { zoom = 0; } } else { // Cesium default zoom zoom = 2; } //console.log('GetZoom: ' + zoom); const screenSizeConst = this.viewer.canvas.width / 1000; zoom = zoom + screenSizeConst; return zoom; } setCenter(center) { // to avoid confusion about the lat, lon ordering, the IMapCenter interfaced is used here // get current height from viewer const height = this.viewer.camera.positionCartographic.height; // set camera to new position this.viewer.camera.setView({ destination: Cartesian3.fromDegrees(center.lon, center.lat, height) }); //console.log('SetCenter: ' + center.lat + ', ' + center.lon + ', ' + height); } getCenter() { const currentPosition = this.viewer.camera.positionCartographic; const lat = currentPosition.latitude * (180 / Math.PI); const lon = currentPosition.longitude * (180 / Math.PI); //console.log('GetCenter: ' + lat + ', ' + lon); return { lat: lat, lon: lon }; } setExtent(extent, geographic, fitOptions) { const destination = Rectangle.fromDegrees(extent[0], extent[1], extent[2], extent[3]); this.viewer.camera.setView({ destination }); //console.log('SetExtent: ' + extent[0] + ', ' + extent[1] + ', ' + extent[3] + ', ' + extent[4]); } getCurrentExtent(geographic) { let extent; // https://cesium.com/learn/cesiumjs/ref-doc/Rectangle.html const currentRectangle = this.viewer.camera.computeViewRectangle(); if (currentRectangle) { const minX = currentRectangle.west * (180 / Math.PI); const minY = currentRectangle.south * (180 / Math.PI); const maxX = currentRectangle.east * (180 / Math.PI); const maxY = currentRectangle.north * (180 / Math.PI); extent = [minX, minY, maxX, maxY]; //console.log('GetCurrentExtent: ' + minX + ', ' + minY + ', ' + maxX + ', ' + maxY); } return extent; } /** * Set initial oblique view, see https://cesium.com/learn/cesiumjs/ref-doc/Camera.html * subtract 90°, to get the same behavior as in openlayers * options of viewer.camera.flyTo` * * https://github.com/CesiumGS/cesium/blob/99d6fffe20d9cf19f2d70de97777dc00a435bc5e/packages/engine/Source/Scene/Camera.js#L1457 * https://github.com/CesiumGS/cesium/blob/99d6fffe20d9cf19f2d70de97777dc00a435bc5e/packages/engine/Source/Scene/Camera.js#L3540-L3541 */ setViewAngle(viewAngle, options) { const flyToOptions = Object.assign({ destination: this.viewer.camera.position, orientation: { heading: this.viewer.camera.heading, pitch: Math$1.toRadians(viewAngle - 90), roll: this.viewer.camera.roll, }, }, options || {}); this.viewer.camera.flyTo(flyToOptions); } /** * @param options of viewer.camera.flyTo */ setNadirViewAngle(options) { if (this.getViewAngle() !== 0) { if (options) { this.setViewAngle(0, options); } else { this.setViewAngle(0); } } else { // If view angle is 0, setViewAngle(0) (flyTo) is not necessary console.log(typeof options.complete); if (options.complete && typeof options.complete === 'function') { options.complete(); } } } //add 90°, to get the same behavior as in openlayers getViewAngle() { return Math$1.toDegrees(this.viewer.camera.pitch) + 90; } /** * subtract rotation degree from 360° to get the same behavior as in openlayers * options of viewer.camera.flyTo` * * https://github.com/CesiumGS/cesium/blob/99d6fffe20d9cf19f2d70de97777dc00a435bc5e/packages/engine/Source/Scene/Camera.js#L3424 * https://github.com/CesiumGS/cesium/blob/99d6fffe20d9cf19f2d70de97777dc00a435bc5e/packages/engine/Source/Scene/Camera.js#L1456 */ setRotation(rotation, options) { const flyToOptions = Object.assign({ destination: this.viewer.camera.position, orientation: { heading: Math$1.toRadians(360 - rotation), pitch: this.viewer.camera.pitch, roll: this.viewer.camera.roll, }, }, options || {}); this.viewer.camera.flyTo(flyToOptions); } // subtract rotation degree from 360° to get the same behavior as in openlayers getRotation() { return 360 - Math$1.toDegrees(this.viewer.camera.heading); } // https://sandcastle.cesium.com/index.html?src=Imagery%2520Layers.html // https://sandcastle.cesium.com/index.html?src=Imagery%2520Layers%2520Manipulation.html getAll2DLayersSize(filtertype) { const lowerType = filtertype.toLowerCase(); let length = 0; if (lowerType === 'baselayers') { length = this.baseLayerImageryGroup.size + this.baseLayerDataSourceGroup.size; } else if (lowerType === 'layers') { length = this.standardLayerImageryGroup.size + this.standardLayerDataSourceGroup.size; } else if (lowerType === 'overlays') { length = this.overlayLayerImageryGroup.size + this.overlayLayerDataSourceGroup.size; } return length; } get2DImageryLayersSize(filtertype) { const lowerType = filtertype.toLowerCase(); let length = 0; if (lowerType === 'baselayers') { length = this.baseLayerImageryGroup.size; } else if (lowerType === 'layers') { length = this.standardLayerImageryGroup.size; } else if (lowerType === 'overlays') { length = this.overlayLayerImageryGroup.size; } return length; } getDataSourceLayersSize(filtertype) { const lowerType = filtertype.toLowerCase(); let length = 0; if (lowerType === 'baselayers') { length = this.baseLayerDataSourceGroup.size; } else if (lowerType === 'layers') { length = this.standardLayerDataSourceGroup.size; } else if (lowerType === 'overlays') { length = this.overlayLayerDataSourceGroup.size; } return length; } getVisible2DLayersSize(filtertype) { const lowerType = filtertype.toLowerCase(); let length = 0; if (lowerType === 'baselayers') { this.baseLayerImageryGroup.forEach(value => { if (value.show) { length++; } }); this.baseLayerDataSourceGroup.forEach(value => { if (value.show) { length++; } }); } else if (lowerType === 'layers') { this.standardLayerImageryGroup.forEach(value => { if (value.show) { length++; } }); this.standardLayerDataSourceGroup.forEach(value => { if (value.show) { length++; } }); } else if (lowerType === 'overlays') { this.overlayLayerImageryGroup.forEach(value => { if (value.show) { length++; } }); this.overlayLayerDataSourceGroup.forEach(value => { if (value.show) { length++; } }); } return length; } get3DLayersSize(filtertype) { const lowerType = filtertype.toLowerCase(); let length = 0; if (lowerType === 'baselayers') { length = this.terrainLayerGroup.size; } else if (lowerType === 'layers') { length = this.tilesetLayerGroup.size; } return length; } getVisible3DLayersSize(filtertype) { const lowerType = filtertype.toLowerCase(); let length = 0; if (lowerType === 'baselayers') { this.terrainLayerGroup.forEach(value => { if (value) { length++; } }); } else if (lowerType === 'layers') { this.tilesetLayerGroup.forEach(value => { if (value.show) { length++; } }); } return length; } set2DUkisLayers(layers, filtertype) { const lowerType = filtertype.toLowerCase(); const tempLayers = []; this.remove2DLayers(lowerType); layers.forEach((newLayer) => { const layerType = newLayer.type; if (layerType === 'geojson' || layerType === 'kml') { const dataSourceLayer = this.create_dataSource_layer(newLayer); if (typeof dataSourceLayer !== 'undefined') { if (lowerType === 'baselayers') { this.baseLayerDataSourceGroup.set(newLayer.id, dataSourceLayer); } else if (lowerType === 'layers') { this.standardLayerDataSourceGroup.set(newLayer.id, dataSourceLayer); } else if (lowerType === 'overlays') { this.overlayLayerDataSourceGroup.set(newLayer.id, dataSourceLayer); } this.viewer.dataSources.add(dataSourceLayer); } } else { const layer = this.create_2D_layer(newLayer); // check if layer not undefined if (typeof layer !== 'undefined') { tempLayers.push(layer); let layerIndex = layers.indexOf(newLayer); // index must be greater than or equal to zero and less than or equal to the number of the layers. if (layerIndex > this.viewer.imageryLayers.length) { layerIndex = this.viewer.imageryLayers.length; } if (lowerType === 'baselayers') { this.baseLayerImageryGroup.set(newLayer.id, layer); } else if (lowerType === 'layers') { layerIndex += this.get2DImageryLayersSize('baselayers'); this.standardLayerImageryGroup.set(newLayer.id, layer); } else if (lowerType === 'overlays') { layerIndex += (this.get2DImageryLayersSize('baselayers') + this.get2DImageryLayersSize('layers')); this.overlayLayerImageryGroup.set(newLayer.id, layer); } this.viewer.imageryLayers.add(layer, layerIndex); } } }); } set3DUkisLayers(layers, filtertype) { const lowerType = filtertype.toLowerCase(); this.remove3DLayers(lowerType); layers.forEach((newLayer) => { this.create_3D_layer(newLayer); }); } create_2D_layer(newLayer) { let newImageryLayer; switch (newLayer.type) { case XyzLayertype: newImageryLayer = this.create_xyz_layer(newLayer); break; case WmsLayertype: newImageryLayer = this.create_wms_layer(newLayer); break; case WmtsLayertype: newImageryLayer = this.create_wmts_layer(newLayer); break; case TmsLayertype: if (newLayer instanceof RasterLayer) { newImageryLayer = this.create_xyz_layer(newLayer); break; } else if (newLayer instanceof VectorLayer) { newImageryLayer = this.create_tms_layer(newLayer); break; } else { console.log('Not supportet layer type: ' + newLayer.type + ' layer: ' + newLayer.name); break; } /* case WfsLayertype: // WFS is currently (01/2023) not supported by Cesium break; */ default: console.log('Not supportet layer type: ' + newLayer.type + ' layer: ' + newLayer.name); break; } return newImageryLayer; } create_3D_layer(newLayer) { if (newLayer.custom_layer instanceof CesiumTerrainProvider) { this.setTerrain(newLayer); } else if (newLayer.custom_layer instanceof EllipsoidTerrainProvider) { this.setTerrain(newLayer); } else if (newLayer.custom_layer instanceof Cesium3DTileset || newLayer.custom_layer instanceof I3SDataProvider) { this.create_3Dtileset_layer(newLayer); } else { console.log('Not supportet layer type: ' + newLayer.name); } } create_xyz_layer(l) { let maxLevel = 20; let enablePopups = false; if (l.maxZoom) { maxLevel = l.maxZoom; } if (l.popup) { enablePopups = true; } const newImageryLayer = new ImageryLayer(new UrlTemplateImageryProvider({ url: l.url, subdomains: l.subdomains, credit: l.attribution, maximumLevel: maxLevel, enablePickFeatures: enablePopups }), { show: l.visible, alpha: l.opacity }); return newImageryLayer; } create_wms_layer(l) { let defaultFormat = 'image/png'; let maxLevel = 20; if (l.maxZoom) { maxLevel = l.maxZoom; } if (l.params.FORMAT) { defaultFormat = l.params.FORMAT; } let wmsOptions = {}; if (l.bbox) { wmsOptions.rectangle = Rectangle.fromDegrees(l.bbox[0], l.bbox[1], l.bbox[2], l.bbox[3]); } wmsOptions = { url: l.url, credit: l.attribution, layers: l.params.LAYERS, parameters: { transparent: l.params.TRANSPARENT, format: defaultFormat, tiled: l.params.TILED }, maximumLevel: maxLevel, srs: this.EPSG, tilingScheme: new WebMercatorTilingScheme() }; if (l.params.TIME) { wmsOptions.clock = this.viewer.clock; wmsOptions.times = this.cesiumTimeInterval; } if (l.popup) { wmsOptions.enablePickFeatures = true; } else { wmsOptions.enablePickFeatures = false; } const newImageryLayer = new ImageryLayer(new WebMapServiceImageryProvider(wmsOptions), { show: l.visible, alpha: l.opacity }); return newImageryLayer; } create_wmts_layer(l) { let maxLevel = 16; if (l.maxZoom) { let maxLevel = l.maxZoom; } const matrixOptions = l.params.matrixSetOptions; let wmtsOptions = {}; if (matrixOptions.matrixIds) { wmtsOptions = { url: l.url, credit: l.attribution, layer: l.params.layer, style: l.params.style, format: l.params.format, tileMatrixSetID: matrixOptions.matrixSet, tileMatrixLabels: matrixOptions.matrixIds, maximumLevel: matrixOptions.matrixIds.length - 1 }; } else { wmtsOptions = { url: l.url, credit: l.attribution, layer: l.params.layer, style: l.params.style, format: l.params.format, tileMatrixSetID: this.EPSG, tileMatrixLabels: Array(maxLevel + 1).fill(null).map((e, i) => this.EPSG + ':' + i), maximumLevel: maxLevel }; } if (l.bbox) { wmtsOptions.rectangle = Rectangle.fromDegrees(l.bbox[0], l.bbox[1], l.bbox[2], l.bbox[3]); } if (l.popup) { //Not supported by cesium as 07/2024, https://cesium.com/learn/cesiumjs/ref-doc/WebMapTileServiceImageryProvider.html#pickFeatures } const newImageryLayer = new ImageryLayer(new WebMapTileServiceImageryProvider(wmtsOptions), { show: l.visible, alpha: l.opacity }); return newImageryLayer; } create_tms_layer(l) { const constructorOptions = { url: l.url, fileExtension: 'png', maximumLevel: l.maxZoom, minimumLevel: l.minZoom }; if (l.attribution) { constructorOptions.credit = new Credit(l.attribution); } const tmsImageryProvider = new TileMapServiceImageryProvider(constructorOptions); const imageryOptions = { show: l.visible, alpha: l.opacity }; return new ImageryLayer(tmsImageryProvider, imageryOptions); } create_dataSource_layer(l) { let newDataSource; if (l.type === 'geojson') { newDataSource = this.create_geojson_layer(l); } else if (l.type === 'kml') { newDataSource = this.create_kml_layer(l); } return newDataSource; } create_geojson_layer(l) { const newGeoJsonDataSource = new GeoJsonDataSource(); // default UKIS values let fillColor = Color.fromCssColorString('#FFFFFF99'); let strokeColor = Color.fromCssColorString('#3399CC'); let strokeWidth = 1; let clamp = false; if (l.options && l.options.style) { const styleProperties = l.options.style(l.data)[0]; if (styleProperties) { fillColor = Color.fromCssColorString(styleProperties.fill_.color_) || fillColor; strokeColor = Color.fromCssColorString(styleProperties.stroke_.color_) || strokeColor; strokeWidth = styleProperties.stroke_.width_ || strokeWidth; } if (l.options['clampToGround']) { clamp = l.options['clampToGround']; } } const dataSourceOptions = { // as Cesium cannot handle an opacity for the whole datasource, we need to modify the layer opacity, // in case the cesium color already has an opacity value fill: fillColor.withAlpha(l.opacity * fillColor.alpha), stroke: strokeColor.withAlpha(l.opacity * strokeColor.alpha), strokeWidth: strokeWidth, clampToGround: clamp }; if (l.attribution) { dataSourceOptions.credit = new Credit(l.attribution); } newGeoJsonDataSource.load(l.data, dataSourceOptions).then(function () { let i = 0; const entityArray = newGeoJsonDataSource.entities.values; //check if vector data has icon features and set the icon graphic accordingly entityArray.forEach(entity => { if (l.data['features'] && l.data['features'][i]['properties'] && l.data['features'][i]['properties']['iconUrl']) { entity.billboard = new BillboardGraphics({ image: l.data['features'][i]['properties']['iconUrl'], width: 20, height: 20 }); entity.description = l.data['features'][i]['properties']['id']; } i++; }); }); newGeoJsonDataSource.show = l.visible; newGeoJsonDataSource.name = l.name; this.dataSourceOpacity.set(l.id, l.opacity); return newGeoJsonDataSource; } create_kml_layer(l) { const newKmlDataSource = new KmlDataSource(); const dataSourceOptions = {}; if (l.attribution) { dataSourceOptions.credit = new Credit(l.attribution); } newKmlDataSource.load(l.data, dataSourceOptions); newKmlDataSource.show = l.visible; newKmlDataSource.name = l.id; return newKmlDataSource; } getLayerById(id, filtertype) { const lowerType = filtertype.toLowerCase(); let wantedLayer; if (lowerType === 'baselayers') { if (this.baseLayerImageryGroup.has(id)) { wantedLayer = this.baseLayerImageryGroup.get(id); } else if (this.baseLayerDataSourceGroup.has(id)) { wantedLayer = this.baseLayerDataSourceGroup.get(id); } } else if (lowerType === 'layers') { if (this.standardLayerImageryGroup.has(id)) { wantedLayer = this.standardLayerImageryGroup.get(id); } else if (this.standardLayerDataSourceGroup.has(id)) { wantedLayer = this.standardLayerDataSourceGroup.get(id); } } else if (lowerType === 'overlays') { if (this.overlayLayerImageryGroup.has(id)) { wantedLayer = this.overlayLayerImageryGroup.get(id); } else if (this.overlayLayerDataSourceGroup.has(id)) { wantedLayer = this.overlayLayerDataSourceGroup.get(id); } } return wantedLayer; } removeAll2DLayers() { let IDs = Array.from(this.baseLayerImageryGroup.keys()); this.remove2DLayer(IDs, 'baselayers'); IDs = Array.from(this.standardLayerImageryGroup.keys()); this.remove2DLayer(IDs, 'layers'); IDs = Array.from(this.overlayLayerImageryGroup.keys()); this.remove2DLayer(IDs, 'overlays'); IDs = Array.from(this.baseLayerDataSourceGroup.keys()); this.remove2DLayer(IDs, 'baselayers'); IDs = Array.from(this.standardLayerDataSourceGroup.keys()); this.remove2DLayer(IDs, 'layers'); IDs = Array.from(this.overlayLayerDataSourceGroup.keys()); this.remove2DLayer(IDs, 'overlays'); } remove2DLayers(filtertype) { const lowerType = filtertype.toLowerCase(); if (lowerType === 'baselayers') { let IDs = Array.from(this.baseLayerImageryGroup.keys()); this.remove2DLayer(IDs, 'baselayers'); IDs = Array.from(this.baseLayerDataSourceGroup.keys()); this.remove2DLayer(IDs, 'baselayers'); } else if (lowerType === 'layers') { let IDs = Array.from(this.standardLayerImageryGroup.keys()); this.remove2DLayer(IDs, 'layers'); IDs = Array.from(this.standardLayerDataSourceGroup.keys()); this.remove2DLayer(IDs, 'layers'); } else if (lowerType === 'overlays') { let IDs = Array.from(this.overlayLayerImageryGroup.keys()); this.remove2DLayer(IDs, 'overlays'); IDs = Array.from(this.overlayLayerDataSourceGroup.keys()); this.remove2DLayer(IDs, 'overlays'); } } remove2DLayer(layerId, filtertype) { const lowerType = filtertype.toLowerCase(); if (lowerType === 'baselayers') { layerId.forEach(id => { if (this.baseLayerImageryGroup.has(id)) { this.viewer.imageryLayers.remove(this.baseLayerImageryGroup.get(id)); this.baseLayerImageryGroup.delete(id); } else if (this.baseLayerDataSourceGroup.has(id)) { this.viewer.dataSources.remove(this.baseLayerDataSourceGroup.get(id)); this.baseLayerDataSourceGroup.delete(id); if (this.dataSourceOpacity.has(id)) { this.dataSourceOpacity.delete(id); } } }); } else if (lowerType === 'layers') { layerId.forEach(id => { if (this.standardLayerImageryGroup.has(id)) { this.viewer.imageryLayers.remove(this.standardLayerImageryGroup.get(id)); this.standardLayerImageryGroup.delete(id); } else if (this.standardLayerDataSourceGroup.has(id)) { this.viewer.dataSources.remove(this.standardLayerDataSourceGroup.get(id)); this.standardLayerDataSourceGroup.delete(id); if (this.dataSourceOpacity.has(id)) { this.dataSourceOpacity.delete(id); } } }); } else if (lowerType === 'overlays') { layerId.forEach(id => { if (this.overlayLayerImageryGroup.has(id)) { this.viewer.imageryLayers.remove(this.overlayLayerImageryGroup.get(id)); this.overlayLayerImageryGroup.delete(id); } else if (this.overlayLayerDataSourceGroup.has(id)) { this.viewer.dataSources.remove(this.overlayLayerDataSourceGroup.get(id)); this.overlayLayerDataSourceGroup.delete(id); if (this.dataSourceOpacity.has(id)) { this.dataSourceOpacity.delete(id); } } }); } } removeAll3DLayers() { let IDs = Array.from(this.terrainLayerGroup.keys()); this.remove3DLayer(IDs, 'baselayers'); IDs = Array.from(this.tilesetLayerGroup.keys()); this.remove3DLayer(IDs, 'layers'); } remove3DLayers(filtertype) { const lowerType = filtertype.toLowerCase(); if (lowerType === 'baselayers') { const IDs = Array.from(this.terrainLayerGroup.keys()); this.remove3DLayer(IDs, 'baselayers'); } else if (lowerType === 'layers') { const IDs = Array.from(this.tilesetLayerGroup.keys()); this.remove3DLayer(IDs, 'layers'); this.tilesetLayerGroup.clear(); } } remove3DLayer(layerId, filtertype) { const lowerType = filtertype.toLowerCase(); if (lowerType === 'baselayers') { layerId.forEach(id => { if (this.terrainLayerGroup.has(id)) { this.removeTerrain(); this.terrainLayerGroup.delete(id); } }); } else if (lowerType === 'layers') { layerId.forEach(id => { if (this.tilesetLayerGroup.has(id)) { const temp = this.viewer.scene.primitives.remove(this.tilesetLayerGroup.get(id)); this.tilesetLayerGroup.delete(id); } }); } } update2DLayerOpacity(layers, filtertype) { const lowerType = filtertype.toLowerCase(); if (lowerType === 'baselayers') { for (const layer of layers) { if (this.baseLayerImageryGroup.has(layer.id)) { const viewerLayer = this.baseLayerImageryGroup.get(layer.id); if (viewerLayer && viewerLayer.alpha !== layer.opacity) { viewerLayer.alpha = layer.opacity; } } else if (this.baseLayerDataSourceGroup.has(layer.id)) { //only set new datasource, if opacity has changed if (this.dataSourceOpacity.get(layer.id) != layer.opacity) { const oldDataSourceLayer = this.baseLayerDataSourceGroup.get(layer.id); this.viewer.dataSources.remove(oldDataSourceLayer); const newDataSourceLayer = this.create_dataSource_layer(layer); this.viewer.dataSources.add(newDataSourceLayer); this.baseLayerDataSourceGroup.set(layer.id, newDataSourceLayer); this.dataSourceOpacity.set(layer.id, layer.opacity); } } } } else if (lowerType === 'layers') { for (const layer of layers) { if (this.standardLayerImageryGroup.has(layer.id)) { const viewerLayer = this.standardLayerImageryGroup.get(layer.id); if (viewerLayer && viewerLayer.alpha !== layer.opacity) { viewerLayer.alpha = layer.opacity; } } else if (this.standardLayerDataSourceGroup.has(layer.id)) { //only set new datasource, if opacity has changed if (this.dataSourceOpacity.get(layer.id) != layer.opacity) { const oldDataSourceLayer = this.standardLayerDataSourceGroup.get(layer.id); this.viewer.dataSources.remove(oldDataSourceLayer); const newDataSourceLayer = this.create_dataSource_layer(layer); this.viewer.dataSources.add(newDataSourceLayer); this.standardLayerDataSourceGroup.set(layer.id, newDataSourceLayer); this.dataSourceOpacity.set(layer.id, layer.opacity); } } } } else if (lowerType === 'overlays') { for (const layer of layers) { if (this.overlayLayerImageryGroup.has(layer.id)) { const viewerLayer = this.overlayLayerImageryGroup.get(layer.id); if (viewerLayer && viewerLayer.alpha !== layer.opacity) { viewerLayer.alpha = layer.opacity; } } else if (this.overlayLayerDataSourceGroup.has(layer.id)) { //only set new datasource, if opacity has changed if (this.dataSourceOpacity.get(layer.id) != layer.opacity) { const oldDataSourceLayer = this.overlayLayerDataSourceGroup.get(layer.id); this.viewer.dataSources.remove(oldDataSourceLayer); const newDataSourceLayer = this.create_dataSource_layer(layer); this.viewer.dataSources.add(newDataSourceLayer); this.overlayLayerDataSourceGroup.set(layer.id, newDataSourceLayer); this.dataSourceOpacity.set(layer.id, layer.opacity); } } } } } update2DLayerVisibility(layers, filtertype) { const lowerType = filtertype.toLowerCase(); for (const layer of layers) { if (layer.type === 'geojson' || layer.type === 'kml') { if (lowerType === 'baselayers') { const dataSourceLayer = this.baseLayerDataSourceGroup.get(layer.id); if (dataSourceLayer && dataSourceLayer.show !== layer.visible) { dataSourceLayer.show = layer.visible; } } else if (lowerType === 'layers') { const dataSourceLayer = this.standardLayerDataSourceGroup.get(layer.id); if (dataSourceLayer && dataSourceLayer.show !== layer.visible) { dataSourceLayer.show = layer.visible; } } else if (lowerType === 'overlays') { const dataSourceLayer = this.overlayLayerDataSourceGroup.get(layer.id); if (dataSourceLayer && dataSourceLayer.show !== layer.visible) { dataSourceLayer.show = layer.visible; } } } else { if (lowerType === 'baselayers') { if (this.baseLayerImageryGroup.has(layer.id)) { const viewerLayer = this.baseLayerImageryGroup.get(layer.id); if (viewerLayer && viewerLayer.show !== layer.visible) { viewerLayer.show = layer.visible; } } } else if (lowerType === 'layers') { if (this.standardLayerImageryGroup.has(layer.id)) { const viewerLayer = this.standardLayerImageryGroup.get(layer.id); if (viewerLayer && viewerLayer.show !== layer.visible) { viewerLayer.show = layer.visible; } } } else if (lowerType === 'overlays') { if (this.overlayLayerImageryGroup.has(layer.id)) { const viewerLayer = this.overlayLayerImageryGroup.get(layer.id); if (viewerLayer && viewerLayer.show !== layer.visible) { viewerLayer.show = layer.visible; } } } } } } update2DLayerZIndex(layers, filtertype) { const lowerType = filtertype.toLowerCase(); const layerCollection = this.viewer.imageryLayers; if (lowerType === 'baselayers') { for (const layer of layers) { if (this.baseLayerImageryGroup.has(layer.id)) { const viewerLayer = this.baseLayerImageryGroup.get(layer.id); if (viewerLayer) { const cesiumIndex = layerCollection.indexOf(viewerLayer); const layerIndex = layers.indexOf(layer); if (cesiumIndex !== layerIndex) { const diffIndex = cesiumIndex - layerIndex; if (diffIndex < 0) { // Move layer up in collection for (let i = 0; i < Math.abs(diffIndex); i++) { layerCollection.raise(viewerLayer); } } else if (diffIndex > 0) { // Move layer down in collection for (let i = 0; i < Math.abs(diffIndex); i++) { layerCollection.lower(viewerLayer); } } } } } } } else if (lowerType === 'layers') { for (const layer of layers) { if (this.standardLayerImageryGroup.has(layer.id)) { const viewerLayer = this.standardLayerImageryGroup.get(layer.id); if (viewerLayer) { const cesiumIndex = layerCollection.indexOf(viewerLayer); const layerIndex = layers.indexOf(layer) + this.get2DImageryLayersSize('baselayers'); //console.log('CesiumIndex: '+ cesiumIndex); //console.log('LayerIndex: '+ layerIndex); if (cesiumIndex !== layerIndex) { const diffIndex = cesiumIndex - layerIndex; if (diffIndex < 0) { // Move layer up in collection for (let i = 0; i < Math.abs(diffIndex); i++) { layerCollection.raise(viewerLayer); } } else if (diffIndex > 0) { // Move layer down in collection for (let i = 0; i < Math.abs(diffIndex); i++) { layerCollection.lower(viewerLayer); } } } } } } } else if (lowerType === 'overlays') { for (const layer of layers) { if (this.overlayLayerImageryGroup.has(layer.id)) { const viewerLayer = this.overlayLayerImageryGroup.get(layer.id); if (viewerLayer) { const cesiumIndex = layerCollection.indexOf(viewerLayer); const layerIndex = layers.indexOf(layer) + this.get2DImageryLayersSize('baselayers') + this.get2DImageryLayersSize('layers'); if (cesiumIndex !== layerIndex) { const diffIndex = cesiumIndex - layerIndex; if (diffIndex < 0) { // Move layer up in collection for (let i = 0; i < Math.abs(diffIndex); i++) { layerCollection.raise(viewerLayer); } } else if (diffIndex > 0) { // Move layer down in collection for (let i = 0; i < Math.abs(diffIndex); i++) { layerCollection.lower(viewerLayer); } } } } } } } } updateDataSourceZIndex(layers, filtertype) { const dataSourceCollection = this.viewer.dataSources; if (dataSourceCollection.length > 1) { const lowerType = filtertype.toLowerCase(); if (lowerType === 'baselayers') { for (const layer of layers) { if (this.baseLayerDataSourceGroup.has(layer.id)) { const viewerLayer = this.baseLayerDataSourceGroup.get(layer.id); if (viewerLayer) { const cesiumIndex = dataSourceCollection.indexOf(viewerLayer); const layerIndex = layers.indexOf(layer); if (cesiumIndex !== layerIndex && cesiumIndex >= 0) { const diffIndex = cesiumIndex - layerIndex; if (diffIndex < 0) { // Move layer up in collection for (let i = 0; i < Math.abs(diffIndex); i++) { dataSourceCollection.raise(viewerLayer); } } else if (diffIndex > 0) { // Move layer down in collection for (let i = 0; i < Math.abs(diffIndex); i++) { dataSourceCollection.lower(viewerLayer); } } } } } } } else if (lowerType === 'layers') { for (const layer of layers) { if (this.standardLayerDataSourceGroup.has(layer.id)) { const viewerLayer = this.standardLayerDataSourceGroup.get(layer.id); if (viewerLayer) { const cesiumIndex = dataSourceCollection.indexOf(viewerLayer); const layerIndex = layers.indexOf(layer) + this.getDataSourceLayersSize('baselayers'); if (cesiumIndex !== layerIndex && cesiumIndex >= 0) { const diffIndex = cesiumIndex - layerIndex; if (diffIndex < 0) { // Move layer up in collection for (let i = 0; i < Math.abs(diffIndex); i++) { dataSourceCollection.raise(viewerLayer); } } else if (diffIndex > 0) { // Move layer down in collection for (let i = 0; i < Math.abs(diffIndex); i++) { dataSourceCollection.lower(viewerLayer); } } } } } } } else if (lowerType === 'overlays') { for (const layer of layers) { if (this.overlayLayerDataSourceGroup.has(layer.id)) { const viewerLayer = this.overlayLayerDataSourceGroup.get(layer.id); if (viewerLayer) { const cesiumIndex = dataSourceCollection.indexOf(viewerLayer); const layerIndex = layers.indexOf(layer) + this.getDataSourceLayersSize('baselayers') + this.getDataSourceLayersSize('layers'); if (cesiumIndex !== layerIndex && cesiumIndex >= 0) { const diffIndex = cesiumIndex - layerIndex; if (diffIndex < 0) { // Move layer up in collection for (let i = 0; i < Math.abs(diffIndex); i++) { dataSourceCollection.raise(viewerLayer); } } else if (diffIn