//import hsv2rgb from 'hsv2rgb'; import {Feature} from 'ol'; import {Fill, Stroke, Style} from 'ol/style'; import {Geometry} from 'ol/geom'; import {Injectable} from '@angular/core'; import {TopoJSON} from 'ol/format'; import {Vector as VectorLayer} from 'ol/layer'; import {Vector as VectorSource} from 'ol/source'; import {HsConfig} from 'hslayers-ng'; import {HsEventBusService} from 'hslayers-ng'; import {HsLanguageService} from 'hslayers-ng'; import {HsLayerManagerService} from 'hslayers-ng'; import {HsLayoutService} from 'hslayers-ng'; import {HsPanelContainerService} from 'hslayers-ng'; import {HsSidebarService} from 'hslayers-ng'; import {AdjusterComponent} from './adjuster/adjuster.component'; import {AdjusterEventService} from './adjuster/adjuster-event.service'; import {AdjusterLegendService} from './adjuster/adjuster-legend.service'; import {AdjusterService} from './adjuster/adjuster.service'; import {AppConfig, ugandaLayer, kenyaLayer, districtsIndexLayer} from './app.config'; @Injectable({providedIn: 'root'}) export class AppService { constructor( public adjusterService: AdjusterService, public adjusterEventService: AdjusterEventService, public adjusterLegendService: AdjusterLegendService, public hsConfig: HsConfig, public hsEventBus: HsEventBusService, public hsLanguageService: HsLanguageService, public hsLayerManagerService: HsLayerManagerService, public hsLayoutService: HsLayoutService, public hsPanelContainerService: HsPanelContainerService, public hsSidebarService: HsSidebarService ) { this.hsSidebarService.addButton({ panel: 'adjuster', module: 'pra.adjuster', order: 0, title: () => this.hsLanguageService.getTranslation('ADJUSTER.adjustFactors'), description: 'Adjust factors for computation', icon: 'icon-analytics-piechart', }); this.hsPanelContainerService.create(AdjusterComponent, {}); this.prepareLayers(); this.adjusterEventService.loaded.subscribe(({success}) => { if (success) { this.adjusterLegendService.refreshColorPalette( this.adjusterService.numberOfClusters ); } }); this.hsEventBus.layoutLoads.subscribe(() => { this.init(); }); this.hsEventBus.olMapLoads.subscribe(() => { this.ensureLayerIsLoaded(districtsIndexLayer); for (const method of this.adjusterService.methods) { this.ensureLayerIsLoaded(method.layer); } }); } init(): void { //this.hsLanguageService.setLanguage('en'); this.hsLayoutService.setDefaultPanel('adjuster'); } /** * Create separate layer fo each clustering method and add it to default_layers */ prepareLayers(): void { for (const method of this.adjusterService.methods) { method.layer = new VectorLayer({ properties: { editor: {editable: false}, autoLegend: false, title: `Kenya & Uganda districts: ${method.name.replace(/\((.+?)\)/g, '')} clusters`, popUp: { attributes: [ { attribute: method.codename, label: 'Cluster ID', }, ], }, }, source: new VectorSource({ format: new TopoJSON({dataProjection: 'EPSG:4326'}), url: require('./data/kenya+uganda_districts_10p_4326.topojson').default, attributions: ['HDX, IEBC, Uganda Bureau of Statistics with support from WHO'], overlaps: false, }), visible: true, style: this.generateStyle(method.codename), }); method.layer .getSource() .on('featuresloadend', () => this.adjusterEventService.layerReady.next({name: method.codename}) ); AppConfig.default_layers.push(method.layer as any); } // obceIndexLayer, okresyLayer and krajeLayer must be pushed in this order // so they will display in correct order AppConfig.default_layers.push(districtsIndexLayer as any); districtsIndexLayer .getSource() .on('featuresloadend', () => this.adjusterEventService.layerReady.next({name: 'index'}) ); (districtsIndexLayer.getSource() as any).legend_categories = this.adjusterLegendService.createIndexLegend(); AppConfig.default_layers.push(ugandaLayer as any); AppConfig.default_layers.push(kenyaLayer as any); this.hsConfig.update(AppConfig); } /** * Layer must be turned visible so it is loaded into the map. * This method ensures that layers critical for further computations * are for at least a moment turned visible and thus loaded properly. * @param {VectorLayer} layer One of layers used to calculate index or clusters */ ensureLayerIsLoaded(layer: VectorLayer>): void { const layerVisible = layer.getVisible(); if (!layerVisible) { layer.setVisible(true); setTimeout(() => layer.setVisible(false), 10); } } /** * @description Function factory for generating style functions based on different clustering methods * @param {string} method selected method * @returns {function} style function */ private generateStyle(method: string) { return (feature: Feature): Style => { if (isNaN(feature.get(method))) { return new Style({ fill: new Fill({ color: '#FFF', }), stroke: new Stroke({ color: '#3399CC', width: 0.25, }), }); } else { return new Style({ fill: new Fill({ color: this.adjusterLegendService.colorPalette[ feature.get(method) - 1 ], }), stroke: new Stroke({ color: '#FFF', width: 0.25, }), }); } }; } }