Просмотр исходного кода

fix: Dont mess up HsConfig and viewport, don't add infinite layers, Work also in non-Krovak

raitis 2 лет назад
Родитель
Сommit
9e64f94719

+ 36 - 0
src/app/app.component.ts

@@ -1,5 +1,6 @@
 import {Component} from '@angular/core';
 
+import proj4 from 'proj4';
 import {
   HsConfig,
   HsEventBusService,
@@ -9,10 +10,25 @@ import {
   HsSidebarService,
   HsToastService,
 } from 'hslayers-ng';
+import {OSM} from 'ol/source';
+import {Tile} from 'ol/layer';
+import {View} from 'ol';
+import {get as getProjection, transform} from 'ol/proj';
+import {register} from 'ol/proj/proj4';
 
 import {AppService} from './app.service';
 import {FcCalculatorComponent} from './calculator/calculator-panel.component';
 
+proj4.defs(
+  'EPSG:3045',
+  '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'
+);
+proj4.defs(
+  'EPSG:5514',
+  '+proj=krovak +lat_0=49.5 +lon_0=24.83333333333333 +alpha=30.28813972222222 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=542.5,89.2,456.9,5.517,2.275,5.516,6.96 +units=m +no_defs'
+);
+register(proj4);
+
 @Component({
   selector: 'application-root',
   templateUrl: './app.component.html',
@@ -21,6 +37,7 @@ import {FcCalculatorComponent} from './calculator/calculator-panel.component';
 export class AppComponent {
   /* You can name your app as you like or not at all */
   title = 'hslayers-application';
+  sjtskProjection = getProjection('EPSG:5514');
   constructor(
     private appService: AppService,
     /* Inject here all modules from HSLayers-NG which you intend to use */
@@ -49,5 +66,24 @@ export class AppComponent {
       this.hsLanguageService.setLanguage('en');
       this.hsLayoutService.setDefaultPanel('calculator');
     });
+    this.hsConfig.update({
+      default_view: new View({
+        projection: this.sjtskProjection,
+        center: transform([16.964, 49.248], 'EPSG:4326', 'EPSG:5514'),
+        zoom: 14,
+      }),
+      default_layers: [
+        /* Baselayers */
+        new Tile({
+          source: new OSM(),
+          visible: true,
+          properties: {
+            title: 'OpenStreetMap',
+            base: true,
+            removable: false,
+          },
+        }),
+      ],
+    });
   }
 }

+ 152 - 85
src/app/app.service.ts

@@ -4,10 +4,10 @@ import proj4 from 'proj4';
 import {GeoJSON} from 'ol/format';
 import {OSM, TileWMS, Vector as VectorSource} from 'ol/source';
 import {Tile, Vector as VectorLayer} from 'ol/layer';
-import {View} from 'ol';
 import {bbox as bboxStrategy} from 'ol/loadingstrategy';
 import {get as getProjection, transform} from 'ol/proj';
 import {register} from 'ol/proj/proj4';
+import {transformExtent} from 'ol/proj';
 
 import {
   HsConfig,
@@ -15,11 +15,13 @@ import {
   HsLanguageService,
   HsLayerManagerService,
   HsLayoutService,
+  HsMapService,
   HsPanelContainerService,
+  HsQueryVectorService,
   HsSidebarService,
+  getTitle,
 } from 'hslayers-ng';
 
-import i18n from './translations.json';
 import {FcCalculatorService} from './calculator/calculator.service';
 import {imageWmsTLayer} from './calculator/image-wms-t-layer';
 
@@ -44,8 +46,12 @@ export class AppService {
     public hsLayerManagerService: HsLayerManagerService,
     public hsLayoutService: HsLayoutService,
     public hsPanelContainerService: HsPanelContainerService,
-    public hsSidebarService: HsSidebarService
-  ) {
+    public hsSidebarService: HsSidebarService,
+    private hsMapService: HsMapService,
+    private hsQueryVectorService: HsQueryVectorService
+  ) {}
+
+  init(): void {
     /* Define the polygon's style using SLD */
     const fieldSld = `<?xml version="1.0" encoding="ISO-8859-1"?>
       <StyledLayerDescriptor version="1.0.0" 
@@ -80,8 +86,14 @@ export class AppService {
     const lpisSource = new VectorSource({
       format: new GeoJSON({
         dataProjection: 'EPSG:5514',
+        featureProjection: this.hsMapService.getCurrentProj('default'),
       }),
       url: (extent) => {
+        if (extent == undefined) {
+          extent = this.hsMapService.getMapExtent('default');
+        }
+        const cur_proj = this.hsMapService.getCurrentProj('default');
+        extent = transformExtent(extent, cur_proj, 'EPSG:5514');
         const kulturaKod = 1; // Doesn't seem to work
         const proxyPath = window.location.hostname.includes('localhost')
           ? 'http://localhost:8085/'
@@ -203,6 +215,67 @@ export class AppService {
       }),
     ];*/
     /* Define and update the HsConfig configuration object */
+    const translationOverrides = this.hsConfig.get().translationOverrides ?? {};
+    const mergedTranslationOverrides = {
+      ...translationOverrides,
+      ...{
+        'cs': {
+          'CALCULATOR': {
+            'blurNone': 'žádné',
+            'getDates': 'VYBRAT DATUM',
+            'getZones': 'ZÍSKAT ZÓNY',
+            'errorLoading': 'Chyba při načítání dat',
+            'errorLoadingDates':
+              'Nebylo možné načíst seznam možných dat ze serveru. Zkuste to prosím později.',
+            'errorLoadingZones':
+              'Nebylo možné načíst zóny pole ze serveru. Pravděpodobně z důvodu přílišné oblačnosti snímku. Zkuste jiný datum.',
+            'loading': 'Načítám',
+            'panelHeader': 'Výpočet indexů pole',
+            'selectBlur': 'Vyhlazení hran zón',
+            'selectDate': 'Chci datum',
+            'selectField':
+              'Vyberte pole kliknutím do mapy. Více polí můžete vybrat podržením klávesy SHIFT.',
+            'selectMore': 'Více polí můžete vybrat podržením klávesy SHIFT',
+            'selectedField': 'Vybráno pole',
+            'selectedFields': 'Vybrána pole',
+            'selectFieldAndIndex': 'Nejprve vyberte index a pole v mapě',
+            'selectIndex': 'Vypočítat index',
+            'selectIndexHint': 'Vyberte z dostupných indexů',
+            'selectQuantiles': 'Počet kvantilů',
+            'zoomIn': 'Pro výběr pole je potřeba mapu přiblížit.',
+          },
+        },
+        'en': {
+          'CALCULATOR': {
+            'blurNone': 'none',
+            'getDates': 'GET DATES',
+            'getZones': 'GET ZONES',
+            'errorLoading': 'Error loading data',
+            'errorLoadingDates':
+              'It was not possible to load available dates from the server. Please, try again later.',
+            'errorLoadingZones':
+              'It was not possible to load field zones from the server. This is probably due to the high cloudiness of the source image. Try another date.',
+            'loading': 'Loading',
+            'panelHeader': 'Field calculation',
+            'selectBlur': 'Smoothing zone edges',
+            'selectDate': 'I want a date',
+            'selectField':
+              'Select a field by clicking in the map. You can select more fields by press and holding the SHIFT key.',
+            'selectMore':
+              'You can select more fields by press and holding the SHIFT key',
+            'selectedField': 'Selected field',
+            'selectedFields': 'Selected fields',
+            'selectFieldAndIndex':
+              'Select an index and a field in the map to continue',
+            'selectIndex': 'Calculate index',
+            'selectIndexHint': 'Select one of the available indices',
+            'selectQuantiles': 'Quantiles count',
+            'zoomIn': 'In order to select the field, you must zoom in the map.',
+          },
+          'PANEL_HEADER': {'CALCULATOR': 'Field calculation'},
+        },
+      },
+    };
     this.hsConfig.update(
       {
         datasources: [
@@ -221,11 +294,6 @@ export class AppService {
             type: 'micka',
           },
         ],
-        default_view: new View({
-          projection: this.sjtskProjection,
-          center: transform([16.964, 49.248], 'EPSG:4326', 'EPSG:5514'),
-          zoom: 14,
-        }),
         /* Use hslayers-server if you need to proxify your requests to other services. See https://www.npmjs.com/package/hslayers-server */
         proxyPrefix: window.location.hostname.includes('localhost')
           ? `${window.location.protocol}//${window.location.hostname}:8085/`
@@ -241,7 +309,7 @@ export class AppService {
         componentsEnabled: {
           basemapGallery: true,
         },
-        assetsPath: 'assets',
+        //assetsPath: 'assets',
         symbolizerIcons: [
           {name: 'beach', url: '/assets/icons/beach17.svg'},
           {name: 'bicycles', url: '/assets/icons/bicycles.svg'},
@@ -250,83 +318,82 @@ export class AppService {
           {name: 'warning', url: '/assets/icons/warning.svg'},
         ],
         popUpDisplay: 'hover',
-        default_layers: [
-          /* Baselayers */
-          new Tile({
-            source: new OSM(),
-            visible: true,
-            properties: {
-              title: 'OpenStreetMap',
-              base: true,
-              removable: false,
-            },
-          }),
-          new Tile({
-            properties: {
-              title: 'Ortofoto ČÚZK',
-              base: true,
-              removable: false,
-              thumbnail: 'https://www.agrihub.sk/hsl-ng/img/orto.jpg',
-            },
-            source: new TileWMS({
-              url: 'https://geoportal.cuzk.cz/WMS_ORTOFOTO_PUB/WMService.aspx',
-              params: {
-                LAYERS: 'GR_ORTFOTORGB',
-              },
-              attributions: [
-                '© <a href="geoportal.cuzk.cz" target="_blank">ČÚZK</a>',
-              ],
-            }),
-            visible: false,
-          }),
-          /* Thematic layers */
-          imageWmsTLayer,
-          new VectorLayer({
-            properties: {
-              title: 'LPIS (WFS)',
-              synchronize: false,
-              cluster: false,
-              inlineLegend: true,
-              editor: {
-                editable: false,
-              },
-              sld: fieldSld,
-              popUp: {
-                attributes: [
-                  'id_dpb',
-                  'id_uz',
-                  'nkod_dpb',
-                  'kultura',
-                  'svazitost',
-                  'vymeram',
-                ],
-              },
-              //path: 'User generated',
-            },
-            minZoom: this.calcService.MIN_LPIS_VISIBLE_ZOOM,
-            opacity: 0.7,
-            source: lpisSource,
-          }),
-          new Tile({
-            properties: {
-              title: 'LPIS (WMS)',
-              queryCapabilities: false,
-            },
-            maxZoom: this.calcService.MIN_LPIS_VISIBLE_ZOOM,
-            source: new TileWMS({
-              url: 'https://gis.lesprojekt.cz/cgi-bin/mapserv?map=/home/dima/maps/foodie/lpis.map',
-              params: {
-                LAYERS: 'lpis_borders', //'lpis_cultures'
-                INFO_FORMAT: undefined,
-                FORMAT: 'image/png; mode=8bit',
-              },
-              crossOrigin: 'anonymous',
-            }),
-          }),
-        ],
-        translationOverrides: i18n,
+        translationOverrides: mergedTranslationOverrides,
       },
       'default'
     );
+    this.hsLanguageService.setLanguage('en');
+    this.hsLayoutService.setDefaultPanel('calculator');
+    for (const layer of [
+      new Tile({
+        properties: {
+          title: 'Ortofoto ČÚZK',
+          base: true,
+          removable: false,
+          thumbnail: 'https://www.agrihub.sk/hsl-ng/img/orto.jpg',
+        },
+        source: new TileWMS({
+          url: 'https://geoportal.cuzk.cz/WMS_ORTOFOTO_PUB/WMService.aspx',
+          params: {
+            LAYERS: 'GR_ORTFOTORGB',
+          },
+          attributions: [
+            '© <a href="geoportal.cuzk.cz" target="_blank">ČÚZK</a>',
+          ],
+        }),
+        visible: false,
+      }),
+      /* Thematic layers */
+      imageWmsTLayer,
+      new VectorLayer({
+        properties: {
+          title: 'LPIS (WFS)',
+          synchronize: false,
+          cluster: false,
+          queryable: true,
+          inlineLegend: true,
+          editor: {
+            editable: false,
+          },
+          sld: fieldSld,
+          popUp: {
+            attributes: [
+              'id_dpb',
+              'id_uz',
+              'nkod_dpb',
+              'kultura',
+              'svazitost',
+              'vymeram',
+            ],
+          },
+          //path: 'User generated',
+        },
+        minZoom: this.calcService.MIN_LPIS_VISIBLE_ZOOM,
+        opacity: 0.7,
+        source: lpisSource,
+      }),
+      new Tile({
+        properties: {
+          title: 'LPIS (WMS)',
+          queryCapabilities: false,
+        },
+        maxZoom: this.calcService.MIN_LPIS_VISIBLE_ZOOM,
+        source: new TileWMS({
+          url: 'https://gis.lesprojekt.cz/cgi-bin/mapserv?map=/home/dima/maps/foodie/lpis.map',
+          params: {
+            LAYERS: 'lpis_borders', //'lpis_cultures'
+            INFO_FORMAT: undefined,
+            FORMAT: 'image/png; mode=8bit',
+          },
+          crossOrigin: 'anonymous',
+        }),
+      }),
+    ]) {
+      this.hsMapService
+        .getLayersArray()
+        .filter((l) => getTitle(l) == getTitle(layer))
+        .map((l) => this.hsMapService.getMap().removeLayer(l));
+      this.hsMapService.addLayer(layer, 'default');
+    }
   }
 }

+ 29 - 9
src/app/calculator/field.service.ts

@@ -1,25 +1,45 @@
 import {Injectable} from '@angular/core';
 import {Subject} from 'rxjs';
 
-import {Feature} from 'ol';
+import { FeatureLike } from "ol/Feature";
 import {Geometry, Polygon} from 'ol/geom';
 import {getCenter} from 'ol/extent';
 import {transform} from 'ol/proj';
 
-import {HsEventBusService, HsMapService} from 'hslayers-ng';
+import {
+  HsEventBusService,
+  HsMapService,
+  HsQueryBaseService,
+  HsQueryVectorService,
+} from 'hslayers-ng';
 
 @Injectable({providedIn: 'root'})
 export class FcFieldService {
   SELECTABLE_LAYERS = ['LPIS (WFS)'] as const;
-  fieldSelects: Subject<{features: Feature<Geometry>[]}> = new Subject();
+  fieldSelects: Subject<{features: FeatureLike[]}> = new Subject();
   selectedFields;
 
   constructor(
     private hsEventBus: HsEventBusService,
-    private hsMapService: HsMapService
+    private hsMapService: HsMapService,
+    private hsQueryBaseService: HsQueryBaseService,
+    private hsQueryVectorService: HsQueryVectorService
   ) {
-    this.hsEventBus.vectorQueryFeatureSelection.subscribe((data) => {
-      const features = data.selector.getFeatures().getArray();
+    this.hsMapService.getMap().on('singleclick', (e) => {
+      let tmpFeatures = this.hsQueryBaseService.getFeaturesUnderMouse(
+        e.map,
+        e.pixel,
+        'default'
+      );
+      tmpFeatures = [
+        ...this.hsQueryVectorService
+          .get('default')
+          .selector.getFeatures()
+          .getArray()
+          .filter((f) => !tmpFeatures.includes(f)),
+        ...tmpFeatures,
+      ];
+      const features = tmpFeatures;
       //  .filter((feature) => this.isValidGeometry(feature))
       //  .filter((feature) => this.isValidLayer(feature));
       if (features.length === 0) {
@@ -28,7 +48,7 @@ export class FcFieldService {
       this.selectedFields = features.map(
         (feature) => feature.getGeometry() as Polygon
       );
-      this.fieldSelects.next({features: features});
+      this.fieldSelects.next({features});
     });
   }
 
@@ -41,7 +61,7 @@ export class FcFieldService {
       type: 'Point',
       coordinates: transform(
         getCenter(field.getExtent()),
-        'EPSG:5514',
+        this.hsMapService.getCurrentProj(),
         'EPSG:4326'
       ),
     };
@@ -88,7 +108,7 @@ export class FcFieldService {
         type: 'Polygon',
         coordinates: feature
           .clone()
-          .transform('EPSG:5514', 'EPSG:4326')
+          .transform(this.hsMapService.getCurrentProj(), 'EPSG:4326')
           .getCoordinates(),
       },
     };

+ 5 - 3
src/app/calculator/zones.service.ts

@@ -12,6 +12,7 @@ import {
   HsAddDataService,
   HsLayerExt,
   HsLayerManagerService,
+  HsMapService,
   HsStylerService,
 } from 'hslayers-ng';
 
@@ -106,7 +107,8 @@ export class FcZonesService {
   constructor(
     private hsLayerManagerService: HsLayerManagerService,
     private hsAddDataService: HsAddDataService,
-    private hsStylerService: HsStylerService
+    private hsStylerService: HsStylerService,
+    private hsMapService: HsMapService
   ) {
     this.zonesStyle = (feature) =>
       new Style({
@@ -146,13 +148,13 @@ export class FcZonesService {
     const style: Style | Style[] | StyleFunction =
       await this.hsStylerService.geoStylerStyleToOlStyle(zonesStyleObj);
     this.zonesLayer.setStyle(style);
+    this.hsAddDataService.addLayer(this.zonesLayer, null);
     this.zonesSource.addFeatures(
       new GeoJSON().readFeatures(zones, {
         dataProjection: 'EPSG:4326',
-        featureProjection: 'EPSG:5514',
+        featureProjection: this.hsMapService.getCurrentProj(),
       })
     );
-    this.hsAddDataService.addLayer(this.zonesLayer, null);
   }
 
   private getSymbolizerRules(classes: number): Array<any> {