import {Fill, Stroke, Style} from 'ol/style'; import {GeoJSON} from 'ol/format'; import {Geometry} from 'ol/geom'; import {Injectable} from '@angular/core'; import {Vector as VectorLayer} from 'ol/layer'; import {Vector as VectorSource} from 'ol/source'; import SLDParser from 'geostyler-sld-parser'; import { StyleFunction } from 'ol/style/Style'; import { HsAddDataService, HsLayerManagerService, HsStylerService, HsLayerExt } from 'hslayers-ng'; import { AppComponent } from '../app.component'; @Injectable({providedIn: 'root'}) export class ZonesService { zonesLayer: VectorLayer>; zonesSource: VectorSource; zonesStyle: (feature) => Style; /** Taken from https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=3 */ QUANTILE_COLORS_2 = ['#fc8d59', '#91cf60'] as const; /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=3 */ QUANTILE_COLORS_3 = ['#fc8d59', '#ffffbf', '#91cf60'] as const; /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=4 */ QUANTILE_COLORS_4 = ['#d7191c', '#fdae61', '#a6d96a', '#1a9641'] as const; /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=5 */ QUANTILE_COLORS_5 = [ '#d7191c', '#fdae61', '#ffffbf', '#a6d96a', '#1a9641', ] as const; /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=6 */ QUANTILE_COLORS_6 = [ '#d73027', '#fc8d59', '#fee08b', '#d9ef8b', '#91cf60', '#1a9850', ] as const; /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=7 */ QUANTILE_COLORS_7 = [ '#d73027', '#fc8d59', '#fee08b', '#ffffbf', '#d9ef8b', '#91cf60', '#1a9850', ] as const; /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=8 */ QUANTILE_COLORS_8 = [ '#d73027', '#f46d43', '#fdae61', '#fee08b', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', ] as const; /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=9 */ QUANTILE_COLORS_9 = [ '#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', ] as const; /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=10 */ QUANTILE_COLORS_10 = [ '#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837', ] as const; /** Pseudo-matrix of color ramps, first color in every row always represents the lowest value */ QUANTILE_COLORS_MATRIX = [ this.QUANTILE_COLORS_2, this.QUANTILE_COLORS_3, this.QUANTILE_COLORS_4, this.QUANTILE_COLORS_5, this.QUANTILE_COLORS_6, this.QUANTILE_COLORS_7, this.QUANTILE_COLORS_8, this.QUANTILE_COLORS_9, this.QUANTILE_COLORS_10, ] as const; sldParser: SLDParser; constructor( private hsLayerManagerService: HsLayerManagerService, private hsAddDataService: HsAddDataService, private hsStylerService: HsStylerService) { this.zonesStyle = (feature) => new Style({ fill: new Fill({ color: '#006666', }), stroke: new Stroke(), }); this.sldParser = new SLDParser(); } async updateZones(zones, {quantileCount}): Promise { if (this.zonesLayer) { this.hsLayerManagerService.get(null).map.removeLayer(this.zonesLayer); } this.zonesSource = new VectorSource(); this.zonesLayer = new VectorLayer({ properties: { title: 'Zones', path: 'Results', popUp: { attributes: ['quantile'], }, }, //style: this.zonesStyle, source: this.zonesSource, }); this.zonesSource.clear(); this.updateZonesStyle(quantileCount); let zonesStyleObj = { name: 'Zones', rules: [] }; zonesStyleObj.rules = this.getSymbolizerRules(quantileCount); const { output: sld } = await this.sldParser.writeStyle(zonesStyleObj); this.zonesLayer.set("sld", sld); let style: Style | Style[] | StyleFunction = await this.hsStylerService.geoStylerStyleToOlStyle(zonesStyleObj); this.zonesLayer.setStyle(style); this.zonesSource.addFeatures( new GeoJSON().readFeatures(zones, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:5514', }) ); this.hsAddDataService.addLayer(this.zonesLayer, null); } private getSymbolizerRules(classes: number): Array { const colorRamp = this.QUANTILE_COLORS_MATRIX[classes - 2]; let rules = []; for (let i = 0; i < colorRamp.length; i++) { let ruleIdx = (i + 1).toString(); rules[i] = { name: ruleIdx, filter: ["==", "quantile", ruleIdx], symbolizers: [ { kind: "Fill", color: colorRamp[i], // opacity: 0, // outlineColor: "#505050", // outlineWidth: 1 } ] }; } return rules; } private updateZonesStyle(classes: number) { const colorRamp = this.QUANTILE_COLORS_MATRIX[classes - 2]; this.zonesStyle = (feature) => new Style({ fill: new Fill({ color: colorRamp[feature.get('quantile') - 1], }), stroke: new Stroke(), }); } }