Skip to content

Commit

Permalink
feat(map): rework layer enrichment
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Aschwanden committed Jan 28, 2024
1 parent 305dbb6 commit 1370647
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 108 deletions.
134 changes: 134 additions & 0 deletions src/components/map/EnrichedLayerFeatures.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import bearing from '@turf/bearing';
import { point } from '@turf/helpers';
import { BabsIcon, Schaeden, Others } from 'components/BabsIcons';
import { Feature, FeatureCollection, GeoJsonProperties, Geometry } from 'geojson';
import { Layer, Source } from "react-map-gl";

const enrichFeature = (f: Feature<Geometry, GeoJsonProperties>): Feature<Geometry, GeoJsonProperties>[] => {

if (f === undefined) {
return []
}

let features: Feature<Geometry, GeoJsonProperties>[] = [];

if (f.geometry.type === "LineString") {
let enrich: EnrichLineConfig | undefined = EnrichLineStringMap[f.properties?.lineType]
if (enrich !== undefined) {
if (enrich.iconStart) {
let startPoint = point(f.geometry.coordinates[0]);
startPoint.id = f.id + ":start";
startPoint.properties = {
parent: f.id,
icon: enrich.iconStart.name,
iconRotation: bearing(point(f.geometry.coordinates[0]), point(f.geometry.coordinates[1])) + enrich.iconRotation,
}
features.push(startPoint)
}

if (enrich.iconEnd) {
let endPoint = point(f.geometry.coordinates.slice(-1)[0]);
endPoint.id = f.id + ":end";
endPoint.properties = {
parent: f.id,
icon: enrich.iconEnd.name,
iconRotation: bearing(f.geometry.coordinates.slice(-1)[0], point(f.geometry.coordinates.slice(-2)[0])) + enrich.iconRotation,
};
features.push(endPoint);
}
}
}

return features
}

type EnrichLineConfig = {
iconStart?: BabsIcon;
iconEnd?: BabsIcon;
iconRotation: number;
}

const EnrichLineStringMap: { [key: string]: EnrichLineConfig } = {
"begehbar": {
iconStart: Schaeden.Beschaedigung,
iconEnd: Schaeden.Beschaedigung,
iconRotation: 90,
},
"schwerBegehbar": {
iconStart: Schaeden.Teilzerstoerung,
iconEnd: Schaeden.Teilzerstoerung,
iconRotation: 90,
},
"unpassierbar": {
iconStart: Schaeden.Totalzerstoerung,
iconEnd: Schaeden.Totalzerstoerung,
iconRotation: 90,
},
"beabsichtigteErkundung": {
iconStart: undefined,
iconEnd: Others.Verschiebung,
iconRotation: 90,
},
"durchgeführteErkundung": {
iconStart: undefined,
iconEnd: Others.Verschiebung,
iconRotation: 90,
},
"beabsichtigteVerschiebung": {
iconStart: undefined,
iconEnd: Others.Verschiebung,
iconRotation: 90,
},
"rettungsAchse": {
iconStart: undefined,
iconEnd: Others.Verschiebung,
iconRotation: 90,
},
"durchgeführteVerschiebung": {
iconStart: undefined,
iconEnd: Others.Verschiebung,
iconRotation: 90,
},
"beabsichtigterEinsatz": {
iconStart: undefined,
iconEnd: Others.Einsatz,
iconRotation: 90,
},
"durchgeführterEinsatz": {
iconStart: undefined,
iconEnd: Others.Einsatz,
iconRotation: 90,
},
}



const EnrichedSymbolSource = (props: EnrichedFeaturesProps) => {
let enrichedFC: FeatureCollection = { "type": "FeatureCollection", "features": [] };
enrichedFC.features = Object.assign([], props.featureCollection.features.filter(f => f.properties?.deletedAt === undefined).filter(f => f.id !== props.selectedFeature).flatMap(f => enrichFeature(f)))

return <Source id="enriched" type="geojson" data={enrichedFC} >
<Layer type="symbol" layout={{
'icon-image': ['coalesce', ["get", "icon"], 'default_marker'],
'icon-allow-overlap': true,
'icon-size': ['interpolate', ['linear'], ['zoom'], 12, 0.1, 17, 1],
'icon-rotation-alignment': 'map',
'icon-pitch-alignment': 'map',
'icon-rotate': ['coalesce', ["get", "iconRotation"], 0]
}} />
</Source>
}

export const EnrichedFeaturesSource = (props: EnrichedFeaturesProps) => {

return <>
<EnrichedSymbolSource {...props} />
</>
}

interface EnrichedFeaturesProps {
featureCollection: FeatureCollection;
selectedFeature: string | number | undefined
}

export default EnrichedFeaturesSource;
37 changes: 14 additions & 23 deletions src/views/map/FeatureDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import bearing from "@turf/bearing";
import { LineString, point } from "@turf/helpers";
import { BabsIcon, IconGroups, Others, Schaeden } from "components/BabsIcons";
import { BabsIcon, IconGroups, } from "components/BabsIcons";
import { Feature, GeoJsonProperties } from "geojson";
import { isEmpty, isUndefined, omitBy } from "lodash";
import { SetStateAction, memo, useCallback, useEffect, useState } from "react";
Expand All @@ -22,7 +22,6 @@ function FeatureDetail(props: { onUpdate: (e: any) => void, feature: Feature | u
const [iconRotation, setIconRotation] = useState<number | undefined>(feature && feature.properties && (feature.properties.iconRotation));
const [name, setName] = useState<string>((feature && feature.properties && feature.properties.name));
const [icon, setIcon] = useState<string>((feature && feature.properties && feature.properties.icon));
const [iconEnd, setIconEnd] = useState<string | undefined>((feature && feature.properties && feature.properties.iconEnd));
const [color, setColor] = useState<string>((feature && feature.properties && feature.properties.color));
const [kind, setKind] = useState<string>((feature && feature.properties && ((feature.geometry.type === "LineString" || feature.geometry.type === "MultiLineString") ? feature.properties.lineType : feature.properties.zoneType)));

Expand All @@ -45,7 +44,6 @@ function FeatureDetail(props: { onUpdate: (e: any) => void, feature: Feature | u
if (feature !== undefined) {
let properties: GeoJsonProperties = Object.assign({}, feature.properties, {
"icon": icon,
"iconEnd": iconEnd,
"color": color,
"name": name,
"lineType": feature.geometry.type === "LineString" || feature.geometry.type === "MultiLineString" ? kind : undefined,
Expand All @@ -57,7 +55,7 @@ function FeatureDetail(props: { onUpdate: (e: any) => void, feature: Feature | u
onUpdate({ features: [feature], action: "featureDetail" });
}
return () => onUpdate({ features: [feature] });
}, [onUpdate, feature, name, iconRotation, iconEnd, color, icon, kind]);
}, [onUpdate, feature, name, iconRotation, color, icon, kind]);

let selectableTypes: typeof LineTypes | typeof ZoneTypes | undefined = undefined;

Expand All @@ -77,12 +75,6 @@ function FeatureDetail(props: { onUpdate: (e: any) => void, feature: Feature | u
else {
setIcon("");
}
if (t && t.iconEnd) {
setIconEnd(t.iconEnd.name);
}
else {
setIconEnd(undefined);
}
}, [setIcon, selectableTypes])

return (
Expand Down Expand Up @@ -171,7 +163,6 @@ interface TypesType {
description: string;
color?: string;
icon?: BabsIcon;
iconEnd?: BabsIcon;
}

interface SelectableTypes { [key: string]: TypesType }
Expand All @@ -193,40 +184,40 @@ const ZoneTypes: SelectableTypes = {

const LineTypes: SelectableTypes = {
"Rutschgebiet": {
name: "Rutschgebiet", description: "Rutschgebiet", color: Colors.Red, icon: undefined,
name: "Rutschgebiet", description: "Rutschgebiet", color: Colors.Red,
},
"RutschgebietGespiegelt": {
name: "RutschgebietGespiegelt", description: "Rutschgebiet (umgekehrt)", color: Colors.Red, icon: undefined,
name: "RutschgebietGespiegelt", description: "Rutschgebiet (umgekehrt)", color: Colors.Red,
},
"begehbar": {
name: "begehbar", description: "Strasse erschwert befahrbar / begehbar", color: Colors.Red, icon: Schaeden.Beschaedigung, iconEnd: Schaeden.Beschaedigung,
name: "begehbar", description: "Strasse erschwert befahrbar / begehbar", color: Colors.Red,
},
"schwerBegehbar": {
name: "schwerBegehbar", description: "Strasse nicht befahrbar / schwer Begehbar", color: Colors.Red, icon: Schaeden.Teilzerstoerung, iconEnd: Schaeden.Teilzerstoerung,
name: "schwerBegehbar", description: "Strasse nicht befahrbar / schwer Begehbar", color: Colors.Red,
},
"unpassierbar": {
name: "unpassierbar", description: "Strasse unpassierbar / gesperrt", color: Colors.Red, icon: Schaeden.Totalzerstoerung, iconEnd: Schaeden.Totalzerstoerung,
name: "unpassierbar", description: "Strasse unpassierbar / gesperrt", color: Colors.Red,
},
"beabsichtigteErkundung": {
name: "beabsichtigteErkundung", description: "Beabsichtigte Erkundung", color: Colors.Blue, icon: Others.Verschiebung,
name: "beabsichtigteErkundung", description: "Beabsichtigte Erkundung", color: Colors.Blue,
},
"durchgeführteErkundung": {
name: "durchgeführteErkundung", description: "Durchgeführte Erkundung", color: Colors.Blue, icon: Others.Verschiebung,
name: "durchgeführteErkundung", description: "Durchgeführte Erkundung", color: Colors.Blue,
},
"beabsichtigteVerschiebung": {
name: "beabsichtigteVerschiebung", description: "Beabsichtigte Verschiebung", color: Colors.Blue, icon: Others.Verschiebung,
name: "beabsichtigteVerschiebung", description: "Beabsichtigte Verschiebung", color: Colors.Blue,
},
"rettungsAchse": {
name: "rettungsAchse", description: "Rettungs Achse", color: Colors.Blue, icon: Others.Verschiebung,
name: "rettungsAchse", description: "Rettungs Achse", color: Colors.Blue,
},
"durchgeführteVerschiebung": {
name: "durchgeführteVerschiebung", description: "Durchgeführte Verschiebung", color: Colors.Blue, icon: Others.Verschiebung,
name: "durchgeführteVerschiebung", description: "Durchgeführte Verschiebung", color: Colors.Blue,
},
"beabsichtigterEinsatz": {
name: "beabsichtigterEinsatz", description: "Beabsichtigter Einsatz", color: Colors.Blue, icon: Others.Einsatz,
name: "beabsichtigterEinsatz", description: "Beabsichtigter Einsatz", color: Colors.Blue,
},
"durchgeführterEinsatz": {
name: "durchgeführterEinsatz", description: "Durchgeführter Einsatz", color: Colors.Blue, icon: Others.Einsatz,
name: "durchgeführterEinsatz", description: "Durchgeführter Einsatz", color: Colors.Blue,
},
};

Expand Down
Loading

0 comments on commit 1370647

Please sign in to comment.