Skip to content

Commit

Permalink
refactor: Update networks and GCC logic
Browse files Browse the repository at this point in the history
  • Loading branch information
annehaley committed Feb 14, 2025
1 parent 02a8f76 commit 5964fee
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 157 deletions.
11 changes: 5 additions & 6 deletions web/src/api/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,17 @@ export async function getDatasetLayers(datasetId: number): Promise<Layer[]> {
return (await apiClient.get(`datasets/${datasetId}/layers`)).data;
}

export async function getDatasetNetwork(datasetId: number): Promise<Network[]> {
return (await apiClient.get(`datasets/${datasetId}/network`)).data;
export async function getDatasetNetworks(datasetId: number): Promise<Network[]> {
return (await apiClient.get(`datasets/${datasetId}/networks`)).data;
}

export async function getNetworkGCC(
datasetId: number,
projectId: number,
networkId: number,
exclude_nodes: number[]
): Promise<NetworkNode[]> {
): Promise<number[]> {
return (
await apiClient.get(
`datasets/${datasetId}/gcc?project=${projectId}&exclude_nodes=${exclude_nodes.toString()}`
`networks/${networkId}/gcc?exclude_nodes=${exclude_nodes.toString()}`
)
).data;
}
Expand Down
5 changes: 3 additions & 2 deletions web/src/components/map/Map.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import {
tooltipOverlay,
openSidebars,
showMapBaseLayer,
clickedFeature,
} from "@/store";
import { clearClickedFeatureData, setMapCenter } from "@/storeFunctions";
import { setMapCenter } from "@/storeFunctions";
import "maplibre-gl/dist/maplibre-gl.css";

import MapTooltip from "./MapTooltip.vue";
Expand Down Expand Up @@ -125,7 +126,7 @@ function createMap() {
* this only has a real effect when the base map is clicked, as that means that no other
* feature layer can "catch" the event, and the tooltip stays hidden.
*/
newMap.on("click", clearClickedFeatureData);
newMap.on("click", () => {clickedFeature.value = undefined});

// Order is important as the following function relies on the ref being set
map.value = newMap;
Expand Down
12 changes: 7 additions & 5 deletions web/src/components/map/MapTooltip.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script setup lang="ts">
import { computed, watch } from "vue";
import {
deactivatedNodes,
clickedFeature,
selectedLayers,
rasterTooltipDataCache,
availableNetworks,
} from "@/store";
import { getMap, getTooltip } from "@/storeFunctions";
import type { SourceRegion } from "@/types";
Expand All @@ -13,7 +13,7 @@ import proj4 from "proj4";
import RecursiveTable from "../RecursiveTable.vue";
import { getDBObjectsForSourceID } from "@/layers";
import { toggleNodeActive } from "@/utils";
import { toggleNodeActive } from "@/networks";
const clickedFeatureProperties = computed(() => {
if (clickedFeature.value === undefined) {
Expand Down Expand Up @@ -124,9 +124,11 @@ watch(
const clickedFeatureIsDeactivatedNode = computed(
() =>
clickedFeature.value &&
deactivatedNodes.value.includes(
clickedFeature.value.feature.properties.node_id
)
availableNetworks.value.find((network) => {
return network.deactivated?.nodes.includes(
clickedFeature.value?.feature.properties.node_id
)
})
);
function toggleNodeHandler() {
Expand Down
88 changes: 84 additions & 4 deletions web/src/layerStyles.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { RasterTileSource } from "maplibre-gl";
import { getMap } from "./storeFunctions";
import { Style } from "./types";
import { Network, Style } from "./types";
import { THEMES } from "./themes";
import { mapSources, theme } from "./store";

// ------------------
// Exported functions
// ------------------

export const rasterColormaps = [
"terrain",
Expand Down Expand Up @@ -79,17 +82,94 @@ export function setMapLayerStyle(mapLayerId: string, style: Style) {
}
}

export function showGCC(network: Network) {
const vectorId = network.vector_data;
const map = getMap();
map.getLayersOrder().forEach((mapLayerId) => {
if (mapLayerId.includes(".vector." + vectorId)) {
if (mapLayerId.includes(".circle")) {
let defaultStrokeColor = map.getPaintProperty(mapLayerId, "circle-stroke-color");
if (Array.isArray(defaultStrokeColor)) {
defaultStrokeColor = defaultStrokeColor[defaultStrokeColor.length - 1]
}
if (network.deactivated?.nodes.length) {
["circle-opacity", "circle-stroke-opacity"].forEach((key) => {
map.setPaintProperty(
mapLayerId,
key,
[
"case",
["in", ["get", "node_id"], ["literal", network.deactivated?.nodes]],
0.4,
1,
]
)
})
map.setPaintProperty(
mapLayerId,
"circle-stroke-color",
[
"case",
// If node is part of GCC, set its stroke color to yellow
["in", ["get", "node_id"], ["literal", network.gcc]],
"yellow",
// else, set it to its normal color
defaultStrokeColor,
]
)
} else {
["circle-opacity", "circle-stroke-opacity"].forEach((key) => {
map.setPaintProperty(mapLayerId, key, 1)
})
map.setPaintProperty(
mapLayerId, "circle-stroke-color", defaultStrokeColor,
)
}
} else if (mapLayerId.includes(".line")) {
let defaultLineColor = map.getPaintProperty(mapLayerId, "line-color");
if (Array.isArray(defaultLineColor)) {
defaultLineColor = defaultLineColor[defaultLineColor.length - 1]
}
if (network.deactivated?.nodes.length) {
map.setPaintProperty(
mapLayerId,
"line-color",
[
"case",
[
"all",
// If node is part of GCC, set its stroke color to yellow
["in", ["get", "from_node_id"], ["literal", network.gcc]],
["in", ["get", "to_node_id"], ["literal", network.gcc]],
],
"yellow",
// else, set it to its normal color
defaultLineColor,
]
)
} else {
map.setPaintProperty(mapLayerId, "line-color", defaultLineColor)
}
}
}
});
}

// ------------------
// Internal functions
// ------------------

function getRasterTilesQuery(style: Style) {
const query: Record<string, string> = {
projection: "EPSG:3857",
}
if (style.colormap) {
query.palette = style.colormap;
query.band = "1";
}
if (Array.isArray(style.colormap_range) && style.colormap_range?.length === 2) {
}
if (Array.isArray(style.colormap_range) && style.colormap_range?.length === 2) {
query.min = style.colormap_range[0].toString();
query.max = style.colormap_range[1].toString();
}
}
return query;
}
17 changes: 13 additions & 4 deletions web/src/layers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
clickedFeature,
mapSources,
rasterTooltipDataCache,
selectedLayers,
selectedLayerStyles,
showMapBaseLayer
Expand All @@ -9,7 +10,7 @@ import { getMap } from "./storeFunctions";
import { Dataset, Layer, LayerFrame, RasterData, VectorData } from './types';
import { MapLayerMouseEvent, MapMouseEvent, Source } from "maplibre-gl";
import { baseURL } from "@/api/auth";
import { cacheRasterData } from "./utils";
import { getRasterDataValues } from "./api/rest";
import { getDefaultColor, setMapLayerStyle } from "./layerStyles";
import proj4 from "proj4";

Expand Down Expand Up @@ -133,7 +134,7 @@ export function handleMapClick(e: MapMouseEvent) {

function createVectorTileSource(vector: VectorData, sourceId: string): Source | undefined {
const map = getMap();
const vectorSourceId = sourceId + '.vector'
const vectorSourceId = sourceId + '.vector.' + vector.id
map.addSource(vectorSourceId, {
type: "vector",
tiles: [`${baseURL}vectors/${vector.id}/tiles/{z}/{x}/{y}/`],
Expand All @@ -151,15 +152,15 @@ function createRasterTileSource(raster: RasterData, sourceId: string): Source |
projection: 'EPSG:3857'
}
const tileParamString = new URLSearchParams(params).toString();
const tilesSourceId = sourceId + '.tiles';
const tilesSourceId = sourceId + '.tiles.' + raster.id;
map.addSource(tilesSourceId, {
type: "raster",
tiles: [`${baseURL}rasters/${raster.id}/tiles/{z}/{x}/{y}.png?${tileParamString}`],
});
const tileSource = map.getSource(tilesSourceId);

const bounds = raster.metadata.bounds;
const boundsSourceId = sourceId + '.bounds';
const boundsSourceId = sourceId + '.bounds.' + raster.id;
let {xmin, xmax, ymin, ymax, srs} = bounds;
[xmin, ymin] = proj4(srs, "EPSG:4326", [xmin, ymin]);
[xmax, ymax] = proj4(srs, "EPSG:4326", [xmax, ymax]);
Expand Down Expand Up @@ -290,6 +291,14 @@ function createRasterFeatureMapLayers(tileSource: Source, boundsSource: Source)
map.on("click", boundsSource.id + '.mask', handleLayerClick);
}

async function cacheRasterData(raster: RasterData) {
if (rasterTooltipDataCache.value[raster.id] !== undefined) {
return;
}
const data = await getRasterDataValues(raster.id);
rasterTooltipDataCache.value[raster.id] = data;
}

function handleLayerClick(e: MapLayerMouseEvent) {
if (!e.features?.length) {
return;
Expand Down
67 changes: 67 additions & 0 deletions web/src/networks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
getDatasetNetworks,
getNetworkGCC,
} from "@/api/rest";
import { Dataset, Network} from "./types";
import { availableNetworks } from './store';
import { showGCC } from "./layerStyles";


// ------------------
// Exported functions
// ------------------

export async function toggleNodeActive(
nodeId: number,
dataset: Dataset,
) {
const network = await getNetwork(nodeId, dataset);
if (network) {
if (network.deactivated === undefined) network.deactivated = {
nodes: [],
edges: [],
};
if (network.deactivated.nodes.includes(nodeId)) {
network.deactivated.nodes = network.deactivated.nodes.filter((n) => n !== nodeId)
} else {
network.deactivated.nodes = [
...network.deactivated.nodes,
nodeId,
]
}
if (network.deactivated.nodes.length) {
network.gcc = await getNetworkGCC(network.id, network.deactivated.nodes);
} else {
network.gcc = network.nodes.map((n) => n.id)
}
showGCC(network);
}
}

// ------------------
// Internal functions
// ------------------

async function getNetwork(
nodeId: number,
dataset: Dataset,
): Promise<Network | undefined> {
let network;
availableNetworks.value.forEach((net) => {
if (net.nodes.map((n) => n.id).includes(nodeId)) {
network = net;
}
})
if (!network) {
availableNetworks.value = [
...availableNetworks.value,
...await getDatasetNetworks(dataset.id),
]
}
availableNetworks.value.forEach((net) => {
if (net.nodes.map((n) => n.id).includes(nodeId)) {
network = net;
}
})
return network;
}
6 changes: 2 additions & 4 deletions web/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
RasterDataValues,
FloatingPanelConfig,
Style,
Network
} from "./types.js";
import { Map, Popup, Source } from "maplibre-gl";

Expand Down Expand Up @@ -57,10 +58,7 @@ export const currentSimulationType = ref<SimulationType>();
export const selectedSourceRegions = ref<SourceRegion[]>([]);

// Network
export const currentNetworkDataset = ref<Dataset>();
export const currentNetworkDatasetLayer = ref<Layer>();
export const deactivatedNodes = ref<number[]>([]);
export const currentNetworkGCC = ref();
export const availableNetworks = ref<Network[]>([]);

// ETC
export const currentUser = ref<User>();
Expand Down
Loading

0 comments on commit 5964fee

Please sign in to comment.