zones.service.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import {Fill, Stroke, Style} from 'ol/style';
  2. import {GeoJSON} from 'ol/format';
  3. import {Geometry} from 'ol/geom';
  4. import {Injectable} from '@angular/core';
  5. import {Vector as VectorLayer} from 'ol/layer';
  6. import {Vector as VectorSource} from 'ol/source';
  7. import SLDParser from 'geostyler-sld-parser';
  8. import { StyleFunction } from 'ol/style/Style';
  9. import { HsAddDataService, HsLayerManagerService, HsStylerService, HsLayerExt } from 'hslayers-ng';
  10. import { AppComponent } from '../app.component';
  11. @Injectable({providedIn: 'root'})
  12. export class ZonesService {
  13. zonesLayer: VectorLayer<VectorSource<Geometry>>;
  14. zonesSource: VectorSource<Geometry>;
  15. zonesStyle: (feature) => Style;
  16. /** Taken from https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=3 */
  17. QUANTILE_COLORS_2 = ['#fc8d59', '#91cf60'] as const;
  18. /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=3 */
  19. QUANTILE_COLORS_3 = ['#fc8d59', '#ffffbf', '#91cf60'] as const;
  20. /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=4 */
  21. QUANTILE_COLORS_4 = ['#d7191c', '#fdae61', '#a6d96a', '#1a9641'] as const;
  22. /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=5 */
  23. QUANTILE_COLORS_5 = [
  24. '#d7191c',
  25. '#fdae61',
  26. '#ffffbf',
  27. '#a6d96a',
  28. '#1a9641',
  29. ] as const;
  30. /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=6 */
  31. QUANTILE_COLORS_6 = [
  32. '#d73027',
  33. '#fc8d59',
  34. '#fee08b',
  35. '#d9ef8b',
  36. '#91cf60',
  37. '#1a9850',
  38. ] as const;
  39. /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=7 */
  40. QUANTILE_COLORS_7 = [
  41. '#d73027',
  42. '#fc8d59',
  43. '#fee08b',
  44. '#ffffbf',
  45. '#d9ef8b',
  46. '#91cf60',
  47. '#1a9850',
  48. ] as const;
  49. /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=8 */
  50. QUANTILE_COLORS_8 = [
  51. '#d73027',
  52. '#f46d43',
  53. '#fdae61',
  54. '#fee08b',
  55. '#d9ef8b',
  56. '#a6d96a',
  57. '#66bd63',
  58. '#1a9850',
  59. ] as const;
  60. /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=9 */
  61. QUANTILE_COLORS_9 = [
  62. '#d73027',
  63. '#f46d43',
  64. '#fdae61',
  65. '#fee08b',
  66. '#ffffbf',
  67. '#d9ef8b',
  68. '#a6d96a',
  69. '#66bd63',
  70. '#1a9850',
  71. ] as const;
  72. /** https://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=10 */
  73. QUANTILE_COLORS_10 = [
  74. '#a50026',
  75. '#d73027',
  76. '#f46d43',
  77. '#fdae61',
  78. '#fee08b',
  79. '#d9ef8b',
  80. '#a6d96a',
  81. '#66bd63',
  82. '#1a9850',
  83. '#006837',
  84. ] as const;
  85. /** Pseudo-matrix of color ramps, first color in every row always represents the lowest value */
  86. QUANTILE_COLORS_MATRIX = [
  87. this.QUANTILE_COLORS_2,
  88. this.QUANTILE_COLORS_3,
  89. this.QUANTILE_COLORS_4,
  90. this.QUANTILE_COLORS_5,
  91. this.QUANTILE_COLORS_6,
  92. this.QUANTILE_COLORS_7,
  93. this.QUANTILE_COLORS_8,
  94. this.QUANTILE_COLORS_9,
  95. this.QUANTILE_COLORS_10,
  96. ] as const;
  97. sldParser: SLDParser;
  98. constructor(
  99. private hsLayerManagerService: HsLayerManagerService,
  100. private hsAddDataService: HsAddDataService,
  101. private hsStylerService: HsStylerService) {
  102. this.zonesStyle = (feature) =>
  103. new Style({
  104. fill: new Fill({
  105. color: '#006666',
  106. }),
  107. stroke: new Stroke(),
  108. });
  109. this.sldParser = new SLDParser();
  110. }
  111. async updateZones(zones, {quantileCount}): Promise<void> {
  112. if (this.zonesLayer) {
  113. this.hsLayerManagerService.get(null).map.removeLayer(this.zonesLayer);
  114. }
  115. this.zonesSource = new VectorSource();
  116. this.zonesLayer = new VectorLayer({
  117. properties: {
  118. title: 'Zones',
  119. path: 'Results',
  120. popUp: {
  121. attributes: ['quantile'],
  122. },
  123. },
  124. //style: this.zonesStyle,
  125. source: this.zonesSource,
  126. });
  127. this.zonesSource.clear();
  128. this.updateZonesStyle(quantileCount);
  129. let zonesStyleObj = { name: 'Zones', rules: [] };
  130. zonesStyleObj.rules = this.getSymbolizerRules(quantileCount);
  131. const { output: sld } = await this.sldParser.writeStyle(zonesStyleObj);
  132. this.zonesLayer.set("sld", sld);
  133. let style: Style | Style[] | StyleFunction = await this.hsStylerService.geoStylerStyleToOlStyle(zonesStyleObj);
  134. this.zonesLayer.setStyle(style);
  135. this.zonesSource.addFeatures(
  136. new GeoJSON().readFeatures(zones, {
  137. dataProjection: 'EPSG:4326',
  138. featureProjection: 'EPSG:5514',
  139. })
  140. );
  141. this.hsAddDataService.addLayer(this.zonesLayer, null);
  142. }
  143. private getSymbolizerRules(classes: number): Array<any> {
  144. const colorRamp = this.QUANTILE_COLORS_MATRIX[classes - 2];
  145. let rules = [];
  146. for (let i = 0; i < colorRamp.length; i++) {
  147. let ruleIdx = (i + 1).toString();
  148. rules[i] = {
  149. name: ruleIdx,
  150. filter: ["==", "quantile", ruleIdx],
  151. symbolizers: [
  152. {
  153. kind: "Fill",
  154. color: colorRamp[i],
  155. // opacity: 0,
  156. // outlineColor: "#505050",
  157. // outlineWidth: 1
  158. }
  159. ]
  160. };
  161. }
  162. return rules;
  163. }
  164. private updateZonesStyle(classes: number) {
  165. const colorRamp = this.QUANTILE_COLORS_MATRIX[classes - 2];
  166. this.zonesStyle = (feature) =>
  167. new Style({
  168. fill: new Fill({
  169. color: colorRamp[feature.get('quantile') - 1],
  170. }),
  171. stroke: new Stroke(),
  172. });
  173. }
  174. }