dasf-web
Version:
Web frontend components for the data analytics software framework (DASF)
163 lines (140 loc) • 6.94 kB
text/typescript
import GeometryType from 'ol/geom/GeometryType';
import Layer from 'ol/layer/Layer';
import Source from 'ol/source/Source';
import VectorSource from 'ol/source/Vector';
import Geometry from 'ol/geom/Geometry';
import Feature from 'ol/Feature';
import { ProjectionLike } from 'ol/proj';
import LayerGroup from 'ol/layer/Group';
import LayerColorScale from '../model/LayerColorScale';
import NumericalParameter from '../model/Parameter';
import TemporalImageLayer from '../model/TemporalImageLayer';
import VectorLayer from 'ol/layer/Vector';
import GeoJSON from 'ol/format/GeoJSON';
import NetcdfRasterSource from '../model/NetcdfRasterSource';
import getBackendModule from '../../dataAcquisition/RasterBackendModule';
import FileUtils from '../../util/FileUtils';
import Demap from '../Demap.vue';
export default class LayerUtils {
/**
* Extracts the first 'valid' geometry from the given layer and returns it in the given targetCRS.
*
* @param layer
* @param targetCRS
* @param allowedGeometryTypes
*/
public static extractGeometryFromLayer(layer: Layer, targetCRS: string = 'EPSG:4326', allowedGeometryTypes: string[] = [GeometryType.POLYGON, GeometryType.MULTI_POLYGON, GeometryType.LINEAR_RING]): Geometry | undefined {
let source: Source = layer.getSource();
if (source && (typeof source['getFeatures'] === "function") || source instanceof VectorSource) {
// get features from source
let features: Feature[] = source['getFeatures']();
if (features && features.length) {
for (let feature of features) {
// get the features geometry
let geom: Geometry = feature.getGeometry();
// assert geometry type and return geometry
if (allowedGeometryTypes.includes(geom.getType())) {
let geomTarget = geom.clone();
if (targetCRS && targetCRS.length > 0) {
// target projection given
let srcProj: ProjectionLike = source.getProjection();
// if (!srcProj) {
// // check layer
// srcProj = layer.getProjection();
// }
if (!srcProj) {
// assume web mercator
srcProj = 'EPSG:3857';
}
if (srcProj != targetCRS) {
// transform the geometry from map-view projection to wgs84
geomTarget.transform(srcProj, targetCRS);
}
}
// return the geometry
return geomTarget;
}
}
}
}
// either not a vector source or an empty source or not containing a polygon
return undefined;
}
public static containsGeometry(layer: Layer, allowedGeometryTypes: string[] = [GeometryType.POLYGON, GeometryType.MULTI_POLYGON, GeometryType.LINEAR_RING]): boolean {
return this.extractGeometryFromLayer(layer) != undefined;
}
public static downloadAsGeojson(layer: VectorLayer): void {
let features: Feature<Geometry>[] = [];
(layer.getSource() as VectorSource).forEachFeature((f: Feature<Geometry>) => {
features.push(new Feature(f.getGeometry().clone().transform('EPSG:3857', 'EPSG:4326')));
});
FileUtils.forceFileDownload(layer.get('title') + '.geojson', new GeoJSON().writeFeatures(features, { decimals: 6 }));
}
public static downloadAsNetcdf(layer: TemporalImageLayer | ArrayBuffer, filename?: string): void {
if(layer instanceof TemporalImageLayer) {
let src = layer.getSource();
if (src instanceof NetcdfRasterSource) {
getBackendModule().requestNetcdfBytes((status: string, netcdf: ArrayBuffer | string) => {
if (status == 'success') {
// we received the netcdf bytestream - force file download
if(!filename) {
// use layer title
filename = layer.get('title') + '.nc';
}
FileUtils.forceFileDownload(filename, netcdf);
} else {
throw new Error(netcdf as string);
}
}, src);
}
} else if(layer instanceof ArrayBuffer) {
// we already have an array buffer given - force download directly
if(!filename) {
filename = 'raster.nc';
}
FileUtils.forceFileDownload(filename, layer);
} else {
throw new Error('unsupported argument type for netcdf download');
}
}
public static downloadLayer(layer: Layer): void {
if (layer instanceof VectorLayer) {
LayerUtils.downloadAsGeojson(layer as VectorLayer);
} else if (layer instanceof TemporalImageLayer) {
LayerUtils.downloadAsNetcdf(layer as TemporalImageLayer);
}
else {
throw Error('download of this layer type is not yet implemented');
}
}
public static splitIntoPropertyLayers(layer: Layer, group: LayerGroup): void {
// console.log('splitting layer ', layer);
let colorScale: LayerColorScale = layer.get(LayerColorScale.KEY);
if (colorScale === undefined) {
console.warn('cannot split layers without existing colorscale');
return;
}
let layerTitle: string = layer.get('title');
let parameters: NumericalParameter[] = colorScale.getAvailableParameters();
let demap: Demap = layer.get('demap') as Demap;
for (let param of parameters) {
if (layer instanceof TemporalImageLayer) {
// split temporal image layer
let source = layer.getSource();
if (source instanceof NetcdfRasterSource) {
let splitSource: NetcdfRasterSource = source.cloneParameterSource(param);
let splitLayer: TemporalImageLayer = new TemporalImageLayer({
title: param.getName() + "::" + layerTitle,
source: splitSource
});
demap.addLayer(splitLayer);
} else {
console.warn('splitting not yet supported for given source type', source);
return;
}
} else if (layer instanceof VectorLayer) {
console.warn('splitting of vector layers is not yet supported');
}
}
}
}