Skip to content

Commit 7edf7fb

Browse files
committed
initial time config synching
1 parent 715a0cb commit 7edf7fb

File tree

6 files changed

+93
-47
lines changed

6 files changed

+93
-47
lines changed

client/src/MapStore.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ import {
1010
DisplayConfiguration,
1111
LayerCollection,
1212
NetCDFData,
13+
NetCDFImageWorking,
1314
NetCDFLayer,
1415
RasterMapLayer,
1516
SearchableVectorData,
1617
VectorFeatureTableGraph,
1718
VectorMapLayer,
1819
} from './types';
1920
import UVdatApi from './api/UVDATApi';
20-
import { visibleNetCDFLayers } from './map/mapNetCDFLayer';
2121

2222
export const VECTOR_PMTILES_URL = '/public/vectortiles/us.pmtiles';
2323

@@ -72,6 +72,10 @@ export default class MapStore {
7272

7373
public static visibleMapLayers: Ref<Set<string>> = ref(new Set());
7474

75+
// Net CDF Layers
76+
77+
public static visibleNetCDFLayers: Ref<NetCDFImageWorking[]> = ref([]);
78+
7579
public static selectedVectorMapLayers: Ref<VectorMapLayer[]> = computed(
7680
() => MapStore.selectedMapLayers.value.filter((layer) => layer.type === 'vector'),
7781
);
@@ -361,33 +365,34 @@ export default class MapStore {
361365
public static graphChartsMinMax = ref({
362366
min: 0,
363367
max: 0,
368+
stepSize: 0,
364369
});
365370

366-
public static updateChartsMinMax = (min: number, max: number) => {
367-
MapStore.graphChartsMinMax.value.min = min;
368-
MapStore.graphChartsMinMax.value.max = max;
371+
public static timeLinked = ref(true);
372+
373+
public static updateChartsMinMax = (min: number, max: number, stepSize: number) => {
374+
MapStore.graphChartsMinMax.value = { min, max, stepSize };
369375
};
370376

371377
// Computes in Unix Time
372-
public static globalTimeRange = computed(() => {
378+
public static globalTimeRange: Ref<{ min: number; max: number, stepSize: number }> = computed(() => {
373379
let globalMin = Infinity;
374380
let globalMax = -Infinity;
375-
MapStore.visibleMapLayers.value.forEach((visibleMapLayer) => {
376-
const [type, layerId] = visibleMapLayer.split('_');
377-
const foundLayer = MapStore.selectedMapLayers.value.find((layer) => layer.id === parseInt(layerId, 10) && layer.type === type);
378-
if (type === 'netcdf' && foundLayer !== undefined) {
379-
const netCDFLayer = visibleNetCDFLayers.value.find((item) => item.netCDFLayer === foundLayer.id);
380-
if (netCDFLayer && netCDFLayer.sliding) {
381-
const { min, max } = netCDFLayer.sliding;
382-
globalMin = Math.min(globalMin, min);
383-
globalMax = Math.max(globalMax, max);
384-
}
381+
let stepSize = Infinity;
382+
MapStore.visibleNetCDFLayers.value.forEach((layer) => {
383+
if (layer.sliding) {
384+
const { min, max } = layer.sliding;
385+
const stepsize = layer.images.length;
386+
stepSize = Math.min(stepSize, (max - min) / stepsize);
387+
globalMin = Math.min(globalMin, min);
388+
globalMax = Math.max(globalMax, max);
385389
}
386390
});
387391
if (MapStore.mapLayerFeatureGraphsVisible.value && MapStore.mapLayerFeatureGraphs.value.length) {
388392
globalMin = Math.min(globalMin, MapStore.graphChartsMinMax.value.min);
389393
globalMax = Math.max(globalMax, MapStore.graphChartsMinMax.value.max);
394+
stepSize = Math.min(stepSize, MapStore.graphChartsMinMax.value.stepSize);
390395
}
391-
return { min: globalMin, max: globalMax };
396+
return { min: globalMin, max: globalMax, stepSize };
392397
});
393398
}

client/src/components/MapLegends/ControlsKey.vue

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
<script lang="ts">
33
import {
44
computed, defineComponent,
5+
watch,
56
} from 'vue';
67
import { throttle } from 'lodash';
8+
import GlobalTime from './GlobalTime.vue';
79
import {
810
AnnotationTypes,
911
NetCDFLayer,
@@ -13,12 +15,15 @@ import {
1315
VectorMapLayer,
1416
} from '../../types'; // Import your defined types
1517
import MapStore from '../../MapStore';
16-
import { updateNetCDFLayer, visibleNetCDFLayers } from '../../map/mapNetCDFLayer';
18+
import { updateNetCDFLayer } from '../../map/mapNetCDFLayer';
1719
import { getRasterLayerDisplayConfig, getVectorLayerDisplayConfig } from '../../utils';
1820
import { updateLayer } from '../../map/mapLayers';
1921
2022
export default defineComponent({
2123
name: 'ControlsKey',
24+
components: {
25+
GlobalTime,
26+
},
2227
props: {
2328
vectorLayers: {
2429
type: Array as () => VectorMapLayer[],
@@ -73,7 +78,7 @@ export default defineComponent({
7378
// Compute NetCDF Layer Keys
7479
const stepIndexMap: Record<string, { length: number, currentIndex: number }> = {};
7580
const resamplingMap: Record<string, 'linear' | 'nearest'> = {};
76-
visibleNetCDFLayers.value.forEach((item) => {
81+
MapStore.visibleNetCDFLayers.value.forEach((item) => {
7782
const found = props.netcdfLayers.find((layer) => layer.id === item.netCDFLayer);
7883
if (found) {
7984
const { opacity } = item;
@@ -123,7 +128,7 @@ export default defineComponent({
123128
124129
const stepMapping = computed(() => {
125130
const mappedStepMapping: Record<string, Record<number, string | number>> = {};
126-
visibleNetCDFLayers.value.forEach((item) => {
131+
MapStore.visibleNetCDFLayers.value.forEach((item) => {
127132
const foundLayer = props.netcdfLayers.find((layer) => layer.id === item.netCDFLayer);
128133
mappedStepMapping[`netcdf_${foundLayer?.id}`] = {};
129134
const mapSlicer: Record<number, string | number> = {};
@@ -174,7 +179,7 @@ export default defineComponent({
174179
});
175180
}
176181
if (item.type === 'netcdf') {
177-
const found = visibleNetCDFLayers.value.find((layer) => item.id === layer.netCDFLayer);
182+
const found = MapStore.visibleNetCDFLayers.value.find((layer) => item.id === layer.netCDFLayer);
178183
if (found) {
179184
found.opacity = val;
180185
updateNetCDFLayer(item.id, { opacity: val });
@@ -194,13 +199,32 @@ export default defineComponent({
194199
};
195200
196201
const toggleResampling = (id: number) => {
197-
const found = visibleNetCDFLayers.value.find((layer) => id === layer.netCDFLayer);
202+
const found = MapStore.visibleNetCDFLayers.value.find((layer) => id === layer.netCDFLayer);
198203
if (found) {
199204
const val = found.resampling === 'linear' ? 'nearest' : 'linear';
200205
found.resampling = val;
201206
updateNetCDFLayer(id, { resampling: val });
202207
}
203208
};
209+
210+
watch(MapStore.globalTime, (newVal) => {
211+
if (!MapStore.timeLinked.value) {
212+
return;
213+
}
214+
props.netcdfLayers.forEach((netcdfLayer) => {
215+
const found = MapStore.visibleNetCDFLayers.value.find((layer) => layer.netCDFLayer === netcdfLayer.id);
216+
if (found) {
217+
// now we need to find the closest index to the current time
218+
const { min } = found.sliding;
219+
const stepSize = found.sliding.step;
220+
const currentIndex = Math.round((newVal - min) / stepSize);
221+
if (currentIndex >= 0 && currentIndex < found.images.length) {
222+
found.currentIndex = currentIndex;
223+
throttledUpdateNetCDFLayer(netcdfLayer.id, currentIndex);
224+
}
225+
}
226+
});
227+
});
204228
return {
205229
processedLayers,
206230
iconMapper,
@@ -214,6 +238,11 @@ export default defineComponent({
214238
</script>
215239

216240
<template>
241+
<v-card class="pa-0 ma-0 mb-2">
242+
<v-card-text class="pa-0 ma-0">
243+
<global-time />
244+
</v-card-text>
245+
</v-card>
217246
<v-card
218247
v-for="(item, index) in processedLayers"
219248
:key="`opacity_${index}`"

client/src/components/MapLegends/GlobalTime.vue

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts">
22
import { computed, defineComponent } from 'vue';
33
import MapStore from '../../MapStore';
4+
import { min } from 'd3';
45
56
export default defineComponent({
67
name: 'GlobalTime',
@@ -9,14 +10,13 @@ export default defineComponent({
910
props: {
1011
},
1112
setup() {
12-
const minMax = computed(() => MapStore.graphChartsMinMax.value);
13-
13+
const minMaxSteps = computed(() => MapStore.globalTimeRange.value);
1414
const updateGlobalTime = (time: number) => {
1515
let updateTime = time;
16-
if (time > minMax.value.max) {
17-
updateTime = minMax.value.max;
18-
} else if (time < minMax.value.min) {
19-
updateTime = minMax.value.min;
16+
if (time > minMaxSteps.value.max) {
17+
updateTime = minMaxSteps.value.max;
18+
} else if (time < minMaxSteps.value.min) {
19+
updateTime = minMaxSteps.value.min;
2020
}
2121
MapStore.globalTime.value = updateTime;
2222
};
@@ -25,37 +25,46 @@ export default defineComponent({
2525
return date.toISOString().split('T')[0];
2626
});
2727
28+
const toggleLink = () => {
29+
MapStore.timeLinked.value = !MapStore.timeLinked.value;
30+
};
31+
2832
return {
29-
minMax,
33+
minMaxSteps,
3034
globalTime: MapStore.globalTime,
35+
timeLinked: MapStore.timeLinked,
3136
updateGlobalTime,
3237
dateString,
38+
toggleLink,
3339
};
3440
},
3541
});
3642
</script>
3743

3844
<template>
39-
<v-row>
45+
<v-row align="center" justify="center" dense>
4046
<v-col cols="1">
4147
<v-tooltip text="Global Time">
4248
<template #activator="{ props }">
4349
<v-icon
4450
class="pl-3"
4551
v-bind="props"
4652
color="primary"
53+
@click="toggleLink()"
4754
>
48-
mdi-timer-outline
55+
mdi-timer-lock-outline
4956
</v-icon>
5057
</template>
58+
<span>Global Time Slider</span>
5159
</v-tooltip>
5260
</v-col>
5361
<v-col cols="6">
5462
<v-slider
5563
:model-value="globalTime"
56-
:min="minMax.min"
57-
:max="minMax.max"
58-
step="1"
64+
:min="minMaxSteps.min"
65+
:max="minMaxSteps.max"
66+
:step="minMaxSteps.stepSize"
67+
:disabled="!timeLinked"
5968
hide-details
6069
thumb-size="12"
6170
track-size="4"

client/src/components/NetCDFLayerConfig.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
} from 'vue';
66
import { throttle } from 'lodash';
77
import { NetCDFLayer } from '../types';
8-
import { updateNetCDFLayer, visibleNetCDFLayers } from '../map/mapNetCDFLayer';
8+
import MapStore from '../MapStore';
9+
import { updateNetCDFLayer } from '../map/mapNetCDFLayer';
910
1011
export default defineComponent({
1112
props: {
@@ -19,16 +20,16 @@ export default defineComponent({
1920
const layerOpacity = ref(0);
2021
const currentIndex = ref(0);
2122
onMounted(() => {
22-
const found = visibleNetCDFLayers.value.find((item) => item.netCDFLayer === props.layer.id);
23+
const found = MapStore.visibleNetCDFLayers.value.find((item) => item.netCDFLayer === props.layer.id);
2324
layerOpacity.value = found?.opacity || 0.75;
2425
currentIndex.value = found?.currentIndex || 0;
2526
});
2627
const totalIndex = computed(() => {
27-
const found = visibleNetCDFLayers.value.find((item) => item.netCDFLayer === props.layer.id);
28+
const found = MapStore.visibleNetCDFLayers.value.find((item) => item.netCDFLayer === props.layer.id);
2829
return found?.images.length ? found.images.length - 1 : 0;
2930
});
3031
const stepMapping = computed(() => {
31-
const found = visibleNetCDFLayers.value.find((item) => item.netCDFLayer === props.layer.id);
32+
const found = MapStore.visibleNetCDFLayers.value.find((item) => item.netCDFLayer === props.layer.id);
3233
const mapSlicer: Record<number, string | number> = {};
3334
let unixTimeStamp = true;
3435
if (found) {

client/src/components/TabularData/MapLayerTableGraph.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,16 @@ export default defineComponent({
116116
graphData.value = data;
117117
let minGraph = Infinity;
118118
let maxGraph = -Infinity;
119+
let steps = Infinity;
119120
Object.keys(data.graphs).forEach((key) => {
120121
const index = parseInt(key, 10);
121122
const [min, max] = data.graphs[index].xAxisRange;
122123
minGraph = Math.min(minGraph, min);
123124
maxGraph = Math.max(maxGraph, max);
125+
const stepChartSize = (max - min) / data.graphs[index].data.length;
126+
steps = Math.min(steps, stepChartSize);
124127
});
125-
MapStore.updateChartsMinMax(minGraph, maxGraph);
128+
MapStore.updateChartsMinMax(minGraph, maxGraph, steps);
126129
if (graphContainer.value) {
127130
const colorMapping = renderVectorFeatureGraph(
128131
data,

client/src/map/mapNetCDFLayer.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import UVdatApi from '../api/UVDATApi';
44
import MapStore from '../MapStore';
55
import { MapLibreCoordinates, NetCDFImageWorking, NetCDFLayer } from '../types';
66

7-
const visibleNetCDFLayers: Ref<NetCDFImageWorking[]> = ref([]);
87
const internalMap: Ref<maplibregl.Map | null> = ref(null);
98

109
const setNetCDFInternalMap = (map: Ref<maplibregl.Map>) => {
@@ -20,14 +19,14 @@ const toggleNetCDFMapLayers = async (map: maplibregl.Map) => {
2019
});
2120
for (let i = 0; i < addLayers.length; i += 1) {
2221
const addLayer = addLayers[i];
23-
const index = visibleNetCDFLayers.value.findIndex((item) => item.netCDFLayer === addLayer.id);
22+
const index = MapStore.visibleNetCDFLayers.value.findIndex((item) => item.netCDFLayer === addLayer.id);
2423
if (index === -1) {
2524
// eslint-disable-next-line no-await-in-loop
2625
const newData = await UVdatApi.getNetCDFLayerImages(addLayer.id);
2726
const modifiedData: NetCDFImageWorking = {
2827
...newData, currentIndex: 0, opacity: 0.75, name: addLayer.name, resampling: 'linear',
2928
};
30-
visibleNetCDFLayers.value.push(modifiedData);
29+
MapStore.visibleNetCDFLayers.value.push(modifiedData);
3130
// Coordinates need to be top-left then clockwise
3231
const baseCoordinates = modifiedData.parent_bounds[0].slice(0, 4);
3332
const coordinates = [baseCoordinates[3], baseCoordinates[2], baseCoordinates[1], baseCoordinates[0]] as MapLibreCoordinates;
@@ -48,11 +47,11 @@ const toggleNetCDFMapLayers = async (map: maplibregl.Map) => {
4847
}
4948
}
5049
// Remove any extra items that are no longer visible
51-
for (let i = 0; i < visibleNetCDFLayers.value.length; i += 1) {
52-
const visibleLayer = visibleNetCDFLayers.value[i];
50+
for (let i = 0; i < MapStore.visibleNetCDFLayers.value.length; i += 1) {
51+
const visibleLayer = MapStore.visibleNetCDFLayers.value[i];
5352
const index = addLayers.findIndex((item) => visibleLayer.netCDFLayer === item.id);
5453
if (index === -1) {
55-
visibleNetCDFLayers.value.splice(i, 1);
54+
MapStore.visibleNetCDFLayers.value.splice(i, 1);
5655
map.removeLayer(`NetCDFLayer_${visibleLayer.netCDFLayer}`);
5756
map.removeSource(`NetCDFSource_${visibleLayer.netCDFLayer}`);
5857
}
@@ -61,7 +60,7 @@ const toggleNetCDFMapLayers = async (map: maplibregl.Map) => {
6160

6261
const updateNetCDFLayer = (layer: number, data: { index?: number, opacity?: number, resampling?: 'nearest' | 'linear' }) => {
6362
const { index, opacity, resampling } = data;
64-
const foundLayer = visibleNetCDFLayers.value.find((item) => item.netCDFLayer === layer);
63+
const foundLayer = MapStore.visibleNetCDFLayers.value.find((item) => item.netCDFLayer === layer);
6564
if (foundLayer && internalMap.value) {
6665
if (index !== undefined) {
6766
const source = internalMap.value.getSource(`NetCDFSource_${layer}`);
@@ -83,9 +82,9 @@ const updateNetCDFLayer = (layer: number, data: { index?: number, opacity?: numb
8382
internalMap.value.setPaintProperty(`NetCDFLayer_${layer}`, 'raster-resampling', resampling);
8483
}
8584
}
86-
visibleNetCDFLayers.value = visibleNetCDFLayers.value.map((item) => item);
85+
MapStore.visibleNetCDFLayers.value = MapStore.visibleNetCDFLayers.value.map((item) => item);
8786
};
8887

8988
export {
90-
toggleNetCDFMapLayers, updateNetCDFLayer, setNetCDFInternalMap, visibleNetCDFLayers,
89+
toggleNetCDFMapLayers, updateNetCDFLayer, setNetCDFInternalMap,
9190
};

0 commit comments

Comments
 (0)