|
|
@@ -4,52 +4,27 @@ import {Injectable} from '@angular/core';
|
|
|
import {Feature} from 'ol';
|
|
|
import {Fill, Stroke, Style} from 'ol/style';
|
|
|
import {GeoJSON} from 'ol/format';
|
|
|
+import {Geometry} from 'ol/geom';
|
|
|
import {Vector as VectorLayer} from 'ol/layer';
|
|
|
import {Vector as VectorSource} from 'ol/source';
|
|
|
|
|
|
-import {HsConfig} from 'hslayers-ng/config.service';
|
|
|
-import {HsEventBusService} from 'hslayers-ng/components/core/event-bus.service';
|
|
|
-import {HsLanguageService} from 'hslayers-ng/components/language/language.service';
|
|
|
-import {HsLayoutService} from 'hslayers-ng/components/layout/layout.service';
|
|
|
+import {HsConfig} from 'hslayers-ng';
|
|
|
+import {HsEventBusService} from 'hslayers-ng';
|
|
|
+import {HsLanguageService} from 'hslayers-ng';
|
|
|
+import {HsLayoutService} from 'hslayers-ng';
|
|
|
//import {HsMapService} from 'hslayers-ng/components/map/map.service';
|
|
|
-import {HsPanelContainerService} from 'hslayers-ng/components/layout/panels/panel-container.service';
|
|
|
-import {HsSidebarService} from 'hslayers-ng/components/sidebar/sidebar.service';
|
|
|
+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, nuts2Layer, nuts3IndexLayer} from './app.config';
|
|
|
import {nuts} from './nuts';
|
|
|
|
|
|
@Injectable({providedIn: 'root'})
|
|
|
export class AppService {
|
|
|
- nuts2style = new Style({
|
|
|
- stroke: new Stroke({
|
|
|
- color: '#000000',
|
|
|
- width: 0.5,
|
|
|
- }),
|
|
|
- });
|
|
|
- nuts2Layer = new VectorLayer({
|
|
|
- source: nuts.nuts2Source,
|
|
|
- editor: {editable: false},
|
|
|
- visible: false,
|
|
|
- style: this.nuts2style,
|
|
|
- title: 'NUTS2 regions',
|
|
|
- });
|
|
|
- nuts3IndexLayer = new VectorLayer({
|
|
|
- source: nuts.nuts3IndexSource,
|
|
|
- editor: {editable: false},
|
|
|
- visible: true,
|
|
|
- style: (f) => this.indexStyle(f),
|
|
|
- title: 'NUTS3 regions: Rural attractiveness index',
|
|
|
- });
|
|
|
- nuts3ClustersLayer = new VectorLayer({
|
|
|
- source: nuts.nuts3ClustersSource,
|
|
|
- editor: {editable: false},
|
|
|
- visible: true,
|
|
|
- style: this.generateStyle(this.adjusterService.method),
|
|
|
- title: 'NUTS3 regions: Clusters',
|
|
|
- });
|
|
|
pilotsColor = 'rgba(29, 148, 29, 0.2)';
|
|
|
pilotsStyle = new Style({
|
|
|
stroke: new Stroke({
|
|
|
@@ -61,16 +36,17 @@ export class AppService {
|
|
|
}),
|
|
|
});
|
|
|
pilotRegions = new VectorLayer({
|
|
|
+ properties: {
|
|
|
+ title: 'Polirural Pilot Regions',
|
|
|
+ editor: {editable: false},
|
|
|
+ },
|
|
|
source: new VectorSource({
|
|
|
format: new GeoJSON(),
|
|
|
url: require('./data/pilot_regions.geojson').default,
|
|
|
}),
|
|
|
- editor: {editable: false},
|
|
|
visible: true,
|
|
|
style: this.pilotsStyle,
|
|
|
- title: 'Polirural Pilot Regions',
|
|
|
});
|
|
|
- serviceUrl: string;
|
|
|
constructor(
|
|
|
public adjusterService: AdjusterService,
|
|
|
public adjusterEventService: AdjusterEventService,
|
|
|
@@ -83,50 +59,116 @@ export class AppService {
|
|
|
public hsPanelContainerService: HsPanelContainerService,
|
|
|
public hsSidebarService: HsSidebarService
|
|
|
) {
|
|
|
- this.serviceUrl = this.adjusterService.serviceBaseUrl + 'georeport/';
|
|
|
- this.nuts3IndexLayer.set('popUp', {
|
|
|
- attributes: [
|
|
|
- {attribute: 'CNTR_CODE', label: 'Country'},
|
|
|
- {attribute: 'NUTS_NAME', label: 'Name'},
|
|
|
- {
|
|
|
- attribute: 'aggregate',
|
|
|
- label: 'aggregated index',
|
|
|
- displayFunction: (x) => {
|
|
|
- return `${(x * 100).toFixed(2)} %`;
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- attribute: 'NUTS_ID',
|
|
|
- label: 'Detailed report',
|
|
|
- displayFunction: (x) => {
|
|
|
- return `<a href="${this.serviceUrl}${x}" target="_blank">in a new page</a>.`;
|
|
|
- },
|
|
|
- },
|
|
|
- ],
|
|
|
+ this.hsSidebarService.buttons.push({
|
|
|
+ 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(() => {
|
|
|
+ console.log('olMap loaded');
|
|
|
+ this.ensureLayerIsLoaded(nuts3IndexLayer);
|
|
|
+ for (const method of this.adjusterService.methods) {
|
|
|
+ this.ensureLayerIsLoaded(method.layer);
|
|
|
+ }
|
|
|
});
|
|
|
/* For debugging only */
|
|
|
/*this.hsEventBus.olMapLoads.subscribe((map) => {
|
|
|
map.on('click', this.debugMe);
|
|
|
});*/
|
|
|
- this.nuts3IndexLayer.set('editable', false);
|
|
|
- this.nuts3IndexLayer.set('queryable', false);
|
|
|
- this.nuts3IndexLayer.getSource().legend_categories = this.adjusterLegendService.createIndexLegend();
|
|
|
- this.nuts3ClustersLayer.set('popUp', {
|
|
|
- attributes: [
|
|
|
- {attribute: 'CNTR_CODE', label: 'Country'},
|
|
|
- {attribute: 'NUTS_NAME', label: 'Name'},
|
|
|
- {attribute: this.adjusterService.method, label: 'Cluster ID'},
|
|
|
- {
|
|
|
- attribute: 'NUTS_ID',
|
|
|
- label: 'Detailed report',
|
|
|
- displayFunction: (x) => {
|
|
|
- return `<a href="${this.serviceUrl}${x}" target="_blank">in a new page</a>.`;
|
|
|
- },
|
|
|
- },
|
|
|
- ],
|
|
|
+ this.adjusterEventService.loaded.subscribe(({success}) => {
|
|
|
+ if (success) {
|
|
|
+ this.adjusterLegendService.refreshColorPalette(
|
|
|
+ this.adjusterService.numberOfClusters
|
|
|
+ );
|
|
|
+ /*this.colorPalette = this.generateRandomColorPalette(
|
|
|
+ adjusterService.clusters.length
|
|
|
+ );*/
|
|
|
+ }
|
|
|
});
|
|
|
- this.nuts3ClustersLayer.set('editable', false);
|
|
|
- this.nuts3ClustersLayer.set('queryable', false);
|
|
|
+ /*this.adjusterEventService.methodChanged.subscribe((method) => {
|
|
|
+ //TODO: prettify this
|
|
|
+ this.nuts3ClustersLayer.set(
|
|
|
+ 'title',
|
|
|
+ `NUTS3 regions: ${method.replaceAll(/\((.+?)\)/g, '')} Clusters`
|
|
|
+ );
|
|
|
+ this.nuts3ClustersLayer.get('popUp').attributes[2].attribute = method;
|
|
|
+ this.nuts3ClustersLayer.setStyle(
|
|
|
+ this.generateStyle(this.adjusterService.method)
|
|
|
+ );
|
|
|
+ });*/
|
|
|
+ }
|
|
|
+
|
|
|
+ init(): void {
|
|
|
+ this.hsLayoutService.setDefaultPanel('adjuster');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create separate layer fo each clustering method and add it to default_layers
|
|
|
+ */
|
|
|
+ prepareLayers(): void {
|
|
|
+ console.log('loading layers...');
|
|
|
+ for (const method of this.adjusterService.methods) {
|
|
|
+ method.layer = new VectorLayer({
|
|
|
+ properties: {
|
|
|
+ editor: {editable: false},
|
|
|
+ queryable: false,
|
|
|
+ autoLegend: false,
|
|
|
+ title: `NUTS3 regions: ${method.name.replace(
|
|
|
+ /\((.+?)\)/g,
|
|
|
+ ''
|
|
|
+ )} clusters`,
|
|
|
+ },
|
|
|
+ source: new VectorSource({
|
|
|
+ //features: new GeoJSON().readFeatures(nuts3).map((f) => f.clone()),
|
|
|
+ format: new GeoJSON(),
|
|
|
+ url: require('./data/NUTS_RG_20M_2016_3857_LEVL_3.geojson').default,
|
|
|
+ overlaps: false,
|
|
|
+ }),
|
|
|
+ visible: true,
|
|
|
+ style: this.generateStyle(method.codename),
|
|
|
+ });
|
|
|
+ method.layer.getSource().on('featuresloadend', () => {
|
|
|
+ console.log(`featuresloadend of ${method.codename}`);
|
|
|
+ this.adjusterEventService.layerReady.next({name: method.codename});
|
|
|
+ });
|
|
|
+ method.layer.getSource().on('featuresloadstart', () => {
|
|
|
+ console.log(`loadstart of ${method.codename}`);
|
|
|
+ });
|
|
|
+ method.layer.getSource().on('featuresloaderror', () => {
|
|
|
+ console.log('evil shit');
|
|
|
+ });
|
|
|
+ AppConfig.default_layers.push(method.layer as any);
|
|
|
+ console.log(
|
|
|
+ `layer for method ${method.codename} (${method.name}) created`
|
|
|
+ );
|
|
|
+ }
|
|
|
+ /* The order of pushes matter! */
|
|
|
+ AppConfig.default_layers.push(nuts3IndexLayer as any);
|
|
|
+ nuts3IndexLayer
|
|
|
+ .getSource()
|
|
|
+ .on('featuresloadend', () =>
|
|
|
+ this.adjusterEventService.layerReady.next({name: 'index'})
|
|
|
+ );
|
|
|
+ (nuts3IndexLayer.getSource() as any).legend_categories =
|
|
|
+ this.adjusterLegendService.createIndexLegend();
|
|
|
+ AppConfig.default_layers.push(nuts2Layer as any);
|
|
|
+ AppConfig.default_layers.push(this.pilotRegions as any);
|
|
|
this.pilotRegions.set('popUp', {
|
|
|
attributes: [
|
|
|
{attribute: 'NUTS_NAME', label: 'Region name'},
|
|
|
@@ -140,59 +182,29 @@ export class AppService {
|
|
|
},*/
|
|
|
],
|
|
|
});
|
|
|
- this.pilotRegions.getSource().legend_categories = [
|
|
|
+ (this.pilotRegions.getSource() as any).legend_categories = [
|
|
|
{
|
|
|
color: this.pilotsColor,
|
|
|
name: 'Polirural pilot region',
|
|
|
},
|
|
|
];
|
|
|
this.pilotRegions.set('queryable', false);
|
|
|
- this.adjusterEventService.loaded.subscribe(({success}) => {
|
|
|
- if (success) {
|
|
|
- this.adjusterLegendService.refreshColorPalette(
|
|
|
- this.adjusterService.numberOfClusters
|
|
|
- );
|
|
|
- /*this.colorPalette = this.generateRandomColorPalette(
|
|
|
- adjusterService.clusters.length
|
|
|
- );*/
|
|
|
- }
|
|
|
- });
|
|
|
- this.adjusterEventService.methodChanged.subscribe((method) => {
|
|
|
- /*TODO: prettify this
|
|
|
- this.nuts3ClustersLayer.set(
|
|
|
- 'title',
|
|
|
- `NUTS3 regions: ${method.replaceAll(/\((.+?)\)/g, '')} Clusters`
|
|
|
- );*/
|
|
|
- this.nuts3ClustersLayer.get('popUp').attributes[2].attribute = method;
|
|
|
- this.nuts3ClustersLayer.setStyle(
|
|
|
- this.generateStyle(this.adjusterService.method)
|
|
|
- );
|
|
|
- });
|
|
|
- /* The order of pushes matter! */
|
|
|
- this.hsConfig.default_layers.push(this.nuts3ClustersLayer);
|
|
|
- this.hsConfig.default_layers.push(this.nuts3IndexLayer);
|
|
|
- this.hsConfig.default_layers.push(this.nuts2Layer);
|
|
|
- this.hsConfig.default_layers.push(this.pilotRegions);
|
|
|
- /*this.hsMapService
|
|
|
- .loaded()
|
|
|
- .then((map) => this.hsMapService.repopulateLayers([]));*/
|
|
|
- this.hsEventBus.layoutLoads.subscribe(() => {
|
|
|
- this.init();
|
|
|
- });
|
|
|
+ this.hsConfig.update(AppConfig);
|
|
|
+ console.log('layers preapared');
|
|
|
}
|
|
|
|
|
|
- init(): void {
|
|
|
- this.hsSidebarService.buttons.push({
|
|
|
- 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.hsLayoutService.setDefaultPanel('adjuster');
|
|
|
+ /**
|
|
|
+ * 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<VectorSource<Geometry>>): void {
|
|
|
+ const layerVisible = layer.getVisible();
|
|
|
+ if (!layerVisible) {
|
|
|
+ layer.setVisible(true);
|
|
|
+ setTimeout(() => layer.setVisible(false), 10);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -201,7 +213,7 @@ export class AppService {
|
|
|
* @returns {function} style function
|
|
|
*/
|
|
|
private generateStyle(method: string) {
|
|
|
- return (feature: Feature): Style => {
|
|
|
+ return (feature: Feature<Geometry>): Style => {
|
|
|
if (isNaN(feature.get(method))) {
|
|
|
return new Style({
|
|
|
fill: new Fill({
|
|
|
@@ -215,9 +227,8 @@ export class AppService {
|
|
|
} else {
|
|
|
return new Style({
|
|
|
fill: new Fill({
|
|
|
- color: this.adjusterLegendService.colorPalette[
|
|
|
- feature.get(method) - 1
|
|
|
- ],
|
|
|
+ color:
|
|
|
+ this.adjusterLegendService.colorPalette[feature.get(method) - 1],
|
|
|
}),
|
|
|
stroke: new Stroke({
|
|
|
color: '#FFF',
|
|
|
@@ -228,36 +239,6 @@ export class AppService {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- private indexStyle = (feature) => {
|
|
|
- if (isNaN(feature.get('aggregate'))) {
|
|
|
- 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.perc2color(
|
|
|
- feature.get('aggregate')
|
|
|
- ),
|
|
|
- }),
|
|
|
- stroke: new Stroke({
|
|
|
- color: '#FFFFFF',
|
|
|
- width: 0.15,
|
|
|
- }),
|
|
|
- }),
|
|
|
- ];
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
private debugMe(e) {
|
|
|
console.log(e);
|
|
|
const feats = e.map.getFeaturesAtPixel(e.pixel);
|