diff --git a/src/app/components/map/map.component.ts b/src/app/components/map/map.component.ts index fabbc789c..dc60c3fe3 100644 --- a/src/app/components/map/map.component.ts +++ b/src/app/components/map/map.component.ts @@ -249,7 +249,7 @@ export class MapComponent implements OnInit, OnDestroy { let wktRepresenation = format.writeGeometry(point); let pointIndex = this.pointHistoryService.getHistory().findIndex((thing) => { - if(thing === point) { + if(thing.point === point) { return true } }) diff --git a/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts b/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts index b0d9e4d9c..49ec9512c 100644 --- a/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts +++ b/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit, Input, OnDestroy, ViewChild, ElementRef, computed, signal} from '@angular/core'; +import { Component, OnInit, Input, OnDestroy, ViewChild, ElementRef, computed, signal } from '@angular/core'; import { first, Observable, Subject, withLatestFrom } from 'rxjs'; import { ResizeEvent } from 'angular-resizable-element'; @@ -9,10 +9,11 @@ import * as searchStore from '@store/search'; import * as mapStore from '@store/map'; import * as chartStore from '@store/charts'; -import { DrawService, MapService, NetcdfService, PointHistoryService, ScreenSizeService, +import { + DrawService, MapService, NetcdfService, PointHistoryService, ScreenSizeService, WktService } from '@services'; -import { Breakpoints, SearchType, MapInteractionModeType, MapDrawModeType } from '@models'; +import { Breakpoints, SearchType, MapInteractionModeType, MapDrawModeType } from '@models'; import { SubSink } from 'subsink'; @@ -132,21 +133,27 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { ) ); - this.subs.add(this.pointHistoryService.history$.subscribe(history => { - this.mapService.setDisplacementLayer(history); + this.subs.add(this.store$.select(getTimeseriesChartStates).pipe( + withLatestFrom(this.pointHistoryService.history$) + ).subscribe(([chartStates, history]) => { + let data = [] + for (const p of history) { + data.push({ point: p.point, seriesNumber: chartStates[p.wkt].seriesNumber, color: chartStates[p.wkt].color }) + } + this.mapService.setDisplacementLayer(data); })); let thing: string = localStorage.getItem('timeseries-points') - if(thing && thing.length > 0) { + if (thing && thing.length > 0) { let previous_points: any[] = thing?.split(';'); - if(previous_points.length > 0) { - console.log(previous_points) + if (previous_points.length > 0) { + // console.log(previous_points) previous_points = previous_points?.map(value => { return this.wktService.wktToFeature(value, 'EPSG:4326'); }) previous_points?.forEach((point, idx) => { - this.pointHistoryService.addPoint(point.getGeometry(), idx); + this.pointHistoryService.addPoint(point.getGeometry(), idx + 1); this.netcdfService.getTimeSeries(point.getGeometry()).pipe(first()).subscribe() }); } diff --git a/src/app/components/timeseries-chart/timeseries-chart.component.ts b/src/app/components/timeseries-chart/timeseries-chart.component.ts index 84c1b3e56..35e76f488 100644 --- a/src/app/components/timeseries-chart/timeseries-chart.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart.component.ts @@ -181,31 +181,33 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { aoi = ''; // pre-process data, remove test v_2 files from results // won't be necessary in production - for (let key of Object.keys(result.point)) { - if (key.startsWith('v_2_')) { - delete result.point[key]; + if (!!result.point) { + for (let key of Object.keys(result.point)) { + if (key.startsWith('v_2_')) { + delete result.point[key]; + } + if (key.startsWith('aoi')) { + aoi = result.point[key]; + } } - if (key.startsWith('aoi')) { - aoi = result.point[key]; + + this.timeSeriesData = []; + for (let key of Object.keys(result.point).filter(x => x !== 'mean' && x !== 'aoi')) { + this.dataSource.push({ + 'aoi': aoi, + 'short_wavelength_displacement': result.point[key].short_wavelength_displacement, + 'interferometric_correlation': result.point[key].interferometric_correlation, + 'temporal_coherence': result.point[key].temporal_coherence, + 'date': result.point[key].secondary_datetime, + 'file_name': key, + 'id': key, + 'temporal_baseline': result.point[key].temporal_baseline, + }) + this.timeSeriesData.push({ + 'short_wavelength_displacement': result.point[key].short_wavelength_displacement, + 'date': result.point[key].secondary_datetime, + }); } - } - this.timeSeriesData = []; - for (let key of Object.keys(result.point).filter(x => x !== 'mean' && x !== 'aoi')) { - this.dataSource.push({ - 'aoi': aoi, - 'short_wavelength_displacement': result.point[key].short_wavelength_displacement, - 'interferometric_correlation': result.point[key].interferometric_correlation, - 'temporal_coherence': result.point[key].temporal_coherence, - 'date': result.point[key].secondary_datetime, - 'file_name': key, - 'id': key, - 'temporal_baseline': result.point[key].temporal_baseline, - }) - this.timeSeriesData.push({ - 'short_wavelength_displacement': result.point[key].short_wavelength_displacement, - 'date': result.point[key].secondary_datetime, - }); - } this.timeSeriesData.sort((a, b) => { if(a.date < b.date) { return -1 @@ -218,6 +220,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { // ...data.mean // }) } + } } else { this.dataSource = []; this.averageData = {}; diff --git a/src/app/services/map/map.service.ts b/src/app/services/map/map.service.ts index 1d20fa294..47ccb8730 100644 --- a/src/app/services/map/map.service.ts +++ b/src/app/services/map/map.service.ts @@ -27,7 +27,7 @@ import { SarviewsEvent } from '@models'; import { EventEmitter } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState } from '@store'; -import {Circle as CircleStyle, Fill, Icon, Stroke, Style} from 'ol/style'; +import { Circle as CircleStyle, Fill, Icon, Stroke, Style, Text as olText } from 'ol/style'; import Geometry from 'ol/geom/Geometry'; import LayerGroup from 'ol/layer/Group'; import { PinnedProduct } from '@services/browse-map.service'; @@ -509,14 +509,14 @@ export class MapService { this.selectClick.on('select', e => { // netcdf-layer // if (this.drawService.in) - this.timeseriesPixelSelected$.emit(null) + this.timeseriesPixelSelected$.emit(null) e.target.getFeatures().forEach( feature => this.newSelectedScene$.next(feature.get('filename')) ); }); this.timeseriesClick.on('select', e => { e.target.getFeatures().forEach( - feature => {this.pointHistoryService.passDraw = true; this.newSelectedDisplacement$.next(feature.get('point'))} + feature => { this.pointHistoryService.passDraw = true; this.newSelectedDisplacement$.next(feature.get('point')) } ); }); @@ -695,7 +695,7 @@ export class MapService { this.map.removeLayer(this.browseImageLayer); } if (!url.endsWith('.tif')) { - if(url.includes('OPERA')) { + if (url.includes('OPERA')) { this.trimImage(url).then((imageBlob: Blob) => { let url = URL.createObjectURL(imageBlob); URL.revokeObjectURL(this.localBrowseImageURL) @@ -752,14 +752,15 @@ export class MapService { const overview_source = new XYZ({ 'url': `${base_url}/{z}/{x}/{y}.png`, wrapX: models.mapOptions.wrapX, - tileSize: [256,256] + tileSize: [256, 256] }); - this.displacementOverview = new TileLayer({ 'source': overview_source, + this.displacementOverview = new TileLayer({ + 'source': overview_source, 'extent': response['extent'] - }); + }); - this.map.addLayer(this.displacementOverview); + this.map.addLayer(this.displacementOverview); }) } @@ -768,25 +769,34 @@ export class MapService { this.displacementOverview = null; } - public setDisplacementLayer(points: Point[]) { + public setDisplacementLayer(points: { point: Point, seriesNumber: number, color: string }[]) { if (!!this.displacmentLayer) { this.map.removeLayer(this.displacmentLayer); this.displacmentLayer = null; } let source = new VectorSource(); - let pointFeatures = points.map((point: Point) => { - let temp = point.clone() as Point; - temp.transform( 'EPSG:4326', 'EPSG:3857') + let pointFeatures = points.map(dataPoint => { + let temp = dataPoint.point.clone() as Point; + temp.transform('EPSG:4326', 'EPSG:3857') let temp_feature = new Feature(temp) - temp_feature.set('point', point) + temp_feature.set('point', dataPoint.point) + temp_feature.set('seriesNumber', dataPoint.seriesNumber) + temp_feature.set('seriesColor', dataPoint.color); return temp_feature; }); source.addFeatures(pointFeatures); - this.displacmentLayer = new VectorLayer({ - source: source, - style: new Style({ + const stylize = function StyleFunction(feature: Feature) { + const textFunction = function (f: Feature) { + let labelContent = f.get('seriesNumber'); + return labelContent.toString(); + } + const textColorFunction = function (f: Feature) { + return f.get('seriesColor') ?? "#000000"; + } + let layerStyle = new Style({ + // image: symbol, image: new CircleStyle({ stroke: new Stroke({ // color: '#000000', @@ -800,8 +810,29 @@ export class MapService { color: '#236192', // color: '#ffcc33', }), + }), + text: new olText({ + overflow: true, + offsetY: 15, + offsetX: -15, + font: '25px sans-serif', + stroke: new Stroke({ + color: '#000000', + width: 3 + }), + fill: new Fill({ + color: textColorFunction(feature), + }), + text: textFunction(feature) }) }) + + return layerStyle + } + + this.displacmentLayer = new VectorLayer({ + source: source, + style: stylize }); this.displacmentLayer.set('displacement-layer', 'true'); @@ -833,15 +864,15 @@ export class MapService { ] this.priorityOverview = new VectorLayer({ source: source, - style: function(feature, _resolution) { + style: function (feature, _resolution) { const test = feature.getProperties(); - const priority= +test['priority']; + const priority = +test['priority']; let color = '#FF0000'; - if(priority === 1) { + if (priority === 1) { color = colorTable[1]; - } else if(priority === 2) { + } else if (priority === 2) { color = colorTable[2]; - } else if(priority === 3) { + } else if (priority === 3) { color = colorTable[3]; } else { color = colorTable[0] diff --git a/src/app/services/point-history.service.ts b/src/app/services/point-history.service.ts index 7db0aa74c..29982e064 100644 --- a/src/app/services/point-history.service.ts +++ b/src/app/services/point-history.service.ts @@ -13,8 +13,8 @@ import { Subject } from 'rxjs'; providedIn: 'root' }) export class PointHistoryService { - private history : Point[] = []; - public history$ = new Subject(); + private history : {point: Point, wkt: string}[] = []; + public history$ = new Subject<{point: Point, wkt: string}[]>(); public passDraw: boolean = false; public selectedPoint: number = 0; @@ -25,7 +25,7 @@ export class PointHistoryService { } - public getHistory(): Point[] { + public getHistory(): {point: Point, wkt: string}[] { return this.history; } @@ -37,14 +37,14 @@ export class PointHistoryService { } const format = new WKT() const wkt = format.writeGeometry(point) - this.history.push(point); + this.history.push({point, wkt}); this.store$.dispatch(addTimeseriesState({item: {geoemetry: point, checked: true, seriesNumber, wkt: wkt, color: '#FFFFFF', name: `Series ${this.history.length}`}})) this.history$.next(this.history); this.savePoints(); } public removePoint(index) { - const format = new WKT() - const wkt = format.writeGeometry(this.history[index]) + // const format = new WKT() + const wkt = this.history[index].wkt this.history.splice(index,1); this.history$.next(this.history) this.store$.dispatch(removeTimeseriesState({wkt})) @@ -58,9 +58,8 @@ export class PointHistoryService { } private savePoints() { - let format = new WKT(); let converted = this.history.map((value) => { - return format.writeGeometry(value) + return value.wkt }) localStorage.setItem('timeseries-points', converted.join(';')) }