app.service.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //import hsv2rgb from 'hsv2rgb';
  2. import {Feature} from 'ol';
  3. import {Fill, Stroke, Style} from 'ol/style';
  4. import {Geometry} from 'ol/geom';
  5. import {Injectable} from '@angular/core';
  6. import {TopoJSON} from 'ol/format';
  7. import {Vector as VectorLayer} from 'ol/layer';
  8. import {Vector as VectorSource} from 'ol/source';
  9. import {HsConfig} from 'hslayers-ng';
  10. import {HsEventBusService} from 'hslayers-ng';
  11. import {HsLanguageService} from 'hslayers-ng';
  12. import {HsLayerManagerService} from 'hslayers-ng';
  13. import {HsLayoutService} from 'hslayers-ng';
  14. import {HsPanelContainerService} from 'hslayers-ng';
  15. import {HsSidebarService} from 'hslayers-ng';
  16. import {AdjusterComponent} from './adjuster/adjuster.component';
  17. import {AdjusterEventService} from './adjuster/adjuster-event.service';
  18. import {AdjusterLegendService} from './adjuster/adjuster-legend.service';
  19. import {AdjusterService} from './adjuster/adjuster.service';
  20. import {AppConfig, ugandaLayer, kenyaLayer, districtsIndexLayer} from './app.config';
  21. @Injectable({providedIn: 'root'})
  22. export class AppService {
  23. constructor(
  24. public adjusterService: AdjusterService,
  25. public adjusterEventService: AdjusterEventService,
  26. public adjusterLegendService: AdjusterLegendService,
  27. public hsConfig: HsConfig,
  28. public hsEventBus: HsEventBusService,
  29. public hsLanguageService: HsLanguageService,
  30. public hsLayerManagerService: HsLayerManagerService,
  31. public hsLayoutService: HsLayoutService,
  32. public hsPanelContainerService: HsPanelContainerService,
  33. public hsSidebarService: HsSidebarService
  34. ) {
  35. this.hsSidebarService.addButton({
  36. panel: 'adjuster',
  37. module: 'pra.adjuster',
  38. order: 0,
  39. title: () =>
  40. this.hsLanguageService.getTranslation('ADJUSTER.adjustFactors'),
  41. description: 'Adjust factors for computation',
  42. icon: 'icon-analytics-piechart',
  43. });
  44. this.hsPanelContainerService.create(AdjusterComponent, {});
  45. this.prepareLayers();
  46. this.adjusterEventService.loaded.subscribe(({success}) => {
  47. if (success) {
  48. this.adjusterLegendService.refreshColorPalette(
  49. this.adjusterService.numberOfClusters
  50. );
  51. }
  52. });
  53. this.hsEventBus.layoutLoads.subscribe(() => {
  54. this.init();
  55. });
  56. this.hsEventBus.olMapLoads.subscribe(() => {
  57. this.ensureLayerIsLoaded(districtsIndexLayer);
  58. for (const method of this.adjusterService.methods) {
  59. this.ensureLayerIsLoaded(method.layer);
  60. }
  61. });
  62. }
  63. init(): void {
  64. //this.hsLanguageService.setLanguage('en');
  65. this.hsLayoutService.setDefaultPanel('adjuster');
  66. }
  67. /**
  68. * Create separate layer fo each clustering method and add it to default_layers
  69. */
  70. prepareLayers(): void {
  71. for (const method of this.adjusterService.methods) {
  72. method.layer = new VectorLayer({
  73. properties: {
  74. editor: {editable: false},
  75. autoLegend: false,
  76. title: `Kenya & Uganda districts: ${method.name.replace(/\((.+?)\)/g, '')} clusters`,
  77. popUp: {
  78. attributes: [
  79. {
  80. attribute: method.codename,
  81. label: 'Cluster ID',
  82. },
  83. ],
  84. },
  85. },
  86. source: new VectorSource({
  87. format: new TopoJSON({dataProjection: 'EPSG:4326'}),
  88. url: require('./data/kenya+uganda_districts_10p_4326.topojson').default,
  89. attributions: ['HDX, IEBC, Uganda Bureau of Statistics with support from WHO'],
  90. overlaps: false,
  91. }),
  92. visible: true,
  93. style: this.generateStyle(method.codename),
  94. });
  95. method.layer
  96. .getSource()
  97. .on('featuresloadend', () =>
  98. this.adjusterEventService.layerReady.next({name: method.codename})
  99. );
  100. AppConfig.default_layers.push(method.layer as any);
  101. }
  102. // obceIndexLayer, okresyLayer and krajeLayer must be pushed in this order
  103. // so they will display in correct order
  104. AppConfig.default_layers.push(districtsIndexLayer as any);
  105. districtsIndexLayer
  106. .getSource()
  107. .on('featuresloadend', () =>
  108. this.adjusterEventService.layerReady.next({name: 'index'})
  109. );
  110. (districtsIndexLayer.getSource() as any).legend_categories = this.adjusterLegendService.createIndexLegend();
  111. AppConfig.default_layers.push(ugandaLayer as any);
  112. AppConfig.default_layers.push(kenyaLayer as any);
  113. this.hsConfig.update(AppConfig);
  114. }
  115. /**
  116. * Layer must be turned visible so it is loaded into the map.
  117. * This method ensures that layers critical for further computations
  118. * are for at least a moment turned visible and thus loaded properly.
  119. * @param {VectorLayer} layer One of layers used to calculate index or clusters
  120. */
  121. ensureLayerIsLoaded(layer: VectorLayer<VectorSource<Geometry>>): void {
  122. const layerVisible = layer.getVisible();
  123. if (!layerVisible) {
  124. layer.setVisible(true);
  125. setTimeout(() => layer.setVisible(false), 10);
  126. }
  127. }
  128. /**
  129. * @description Function factory for generating style functions based on different clustering methods
  130. * @param {string} method selected method
  131. * @returns {function} style function
  132. */
  133. private generateStyle(method: string) {
  134. return (feature: Feature<Geometry>): Style => {
  135. if (isNaN(feature.get(method))) {
  136. return new Style({
  137. fill: new Fill({
  138. color: '#FFF',
  139. }),
  140. stroke: new Stroke({
  141. color: '#3399CC',
  142. width: 0.25,
  143. }),
  144. });
  145. } else {
  146. return new Style({
  147. fill: new Fill({
  148. color: this.adjusterLegendService.colorPalette[
  149. feature.get(method) - 1
  150. ],
  151. }),
  152. stroke: new Stroke({
  153. color: '#FFF',
  154. width: 0.25,
  155. }),
  156. });
  157. }
  158. };
  159. }
  160. }