Skip to content

Commit

Permalink
Different colors for actual use polygons + code comments (#397)
Browse files Browse the repository at this point in the history
  • Loading branch information
Corgam authored Jul 13, 2024
2 parents 0ea60a5 + 75c00d0 commit 7bc3628
Show file tree
Hide file tree
Showing 32 changed files with 298 additions and 78 deletions.
22 changes: 21 additions & 1 deletion backend/lib/BieMetadata/MetadataObject.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
// ReSharper disable InconsistentNaming

namespace BieMetadata;

Expand Down Expand Up @@ -75,6 +74,12 @@ public class AdditionalData
/// Table data populated by the data pipeline. Contains the name and the size of the all .yaml files correlated to that specific dataset.
/// </summary>
public List<TableData> Tables { get; set; } = new List<TableData>();

/// <summary>
/// A polygon coloring rule for different values.
/// </summary>
[BsonIgnoreIfNull] // Add this attribute to ignore null values
public PolygonColoring? PolygonColoring { get; set; }
}

/// <summary>
Expand Down Expand Up @@ -113,4 +118,19 @@ public class DisplayProperty
// The value to show
public string value { get; set; } = string.Empty;
}

/// <summary>
/// Polygon coloring rules
/// </summary>
public class PolygonColoring
{
public string attributeName { get; set; } = string.Empty;
public List<PolygonColor> colors { get; set; } = new List<PolygonColor>();
}

public class PolygonColor
{
public string color { get; set; } = string.Empty;
public List<string> values { get; set; } = new List<string>();
}
}
59 changes: 55 additions & 4 deletions backend/metadata-database/init-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const datasets = [
MinZoomLevel: -1,
MarkersThreshold: -1,
DisplayProperty: [],
PolygonColoring: null,
Tables: [],
},
},
Expand All @@ -46,7 +47,8 @@ const datasets = [
LongDescription: `A map of EV charging stations displays the locations of electric vehicle charging points located in Germany, helping drivers plan routes and manage charging needs. It is essential for supporting the adoption and convenience of electric vehicles.`,
MinZoomLevel: 11,
MarkersThreshold: -1,
DisplayProperty: [{ displayName: "Operator", value: "text" }],
DisplayProperty: [{ displayName: "Operator", value: "operator" }],
PolygonColoring: null,
Tables: [],
},
},
Expand All @@ -65,6 +67,7 @@ const datasets = [
MinZoomLevel: 11,
MarkersThreshold: 17,
DisplayProperty: [],
PolygonColoring: null,
Tables: [],
},
},
Expand All @@ -81,8 +84,55 @@ const datasets = [
DataType: "SHAPE",
LongDescription: `The Actual Use map describes the use of the earth's surface in four main groups (settlement, traffic, vegetation and water bodies). The division of these main groups into almost 140 different types of use, such as residential areas, road traffic, agriculture or flowing water, enables detailed evaluations and analyses of the use of the earth's surface.`,
MinZoomLevel: 11,
MarkersThreshold: 17,
MarkersThreshold: 15,
DisplayProperty: [],
PolygonColoring: {
attributeName: "nutzart",
colors: [
{
color: "DarkOrchid",
values: [
"Wohnbaufläche",
"Industrie- und Gewerbefläche",
"Halde",
"Bergbaubetrieb",
"Tagebau, Grube Steinbruch",
"Fläche gemischter Nutzung",
"Fläche besonderer funktionaler Prägung",
"Sport-, Freizeit- und Erholungsfläche",
"Friedhof",
],
},
{
color: "green",
values: ["Wald", "Gehölz", "Sumpf"],
},
{
color: "yellow",
values: [
"Landwirtschaft",
"Heide",
"Moor",
"Unland/Vegetationslose Fläche",
],
},
{
color: "RosyBrown",
values: [
"Straßenverkehr",
"Weg",
"Platz",
"Bahnverkehr",
"Flugverkehr",
"Schiffsverkehr",
],
},
{
color: "Cyan",
values: ["Fließgewässer", "Hafenbecken", "Stehendes Gewässer"],
},
],
},
Tables: [],
},
},
Expand All @@ -91,15 +141,16 @@ const datasets = [
DatasetId: "building_models",
Name: "Building Models",
ShortDescription: `Simplified 3D building models.`,
Icon: '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M136.83,220.43a8,8,0,0,1-11.09,2.23A183.15,183.15,0,0,0,24,192a8,8,0,0,1,0-16,199.11,199.11,0,0,1,110.6,33.34A8,8,0,0,1,136.83,220.43ZM24,144a8,8,0,0,0,0,16,214.81,214.81,0,0,1,151.17,61.71,8,8,0,1,0,11.2-11.42A230.69,230.69,0,0,0,24,144Zm208,16a216.51,216.51,0,0,0-48.59,5.49q8.24,6.25,16,13.16A201.53,201.53,0,0,1,232,176a8,8,0,0,1,0,16c-6,0-11.93.29-17.85.86q8.32,8.67,15.94,18.14a8,8,0,1,1-12.48,10A247,247,0,0,0,24,128a8,8,0,0,1,0-16,266.33,266.33,0,0,1,48,4.37V80a8,8,0,0,1,3.2-6.4l64-48a8,8,0,0,1,9.6,0l64,48A8,8,0,0,1,216,80v32.49c5.31-.31,10.64-.49,16-.49a8,8,0,0,1,0,16,246.3,246.3,0,0,0-84.26,14.69q9.44,5,18.46,10.78A232.2,232.2,0,0,1,232,144a8,8,0,0,1,0,16ZM120,88h48a8,8,0,0,1,8,8v21.94q11.88-2.56,24-4V84L144,42,88,84v35.81q12.19,3,24,7.18V96A8,8,0,0,1,120,88Zm8.07,45.27A262.48,262.48,0,0,1,160,121.94V104H128v29.24Z"></path></svg>',
Icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M104,216V152h48v64h64V120a8,8,0,0,0-2.34-5.66l-80-80a8,8,0,0,0-11.32,0l-80,80A8,8,0,0,0,40,120v96Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>',
},
additionalData: {
Icon: '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M136.83,220.43a8,8,0,0,1-11.09,2.23A183.15,183.15,0,0,0,24,192a8,8,0,0,1,0-16,199.11,199.11,0,0,1,110.6,33.34A8,8,0,0,1,136.83,220.43ZM24,144a8,8,0,0,0,0,16,214.81,214.81,0,0,1,151.17,61.71,8,8,0,1,0,11.2-11.42A230.69,230.69,0,0,0,24,144Zm208,16a216.51,216.51,0,0,0-48.59,5.49q8.24,6.25,16,13.16A201.53,201.53,0,0,1,232,176a8,8,0,0,1,0,16c-6,0-11.93.29-17.85.86q8.32,8.67,15.94,18.14a8,8,0,1,1-12.48,10A247,247,0,0,0,24,128a8,8,0,0,1,0-16,266.33,266.33,0,0,1,48,4.37V80a8,8,0,0,1,3.2-6.4l64-48a8,8,0,0,1,9.6,0l64,48A8,8,0,0,1,216,80v32.49c5.31-.31,10.64-.49,16-.49a8,8,0,0,1,0,16,246.3,246.3,0,0,0-84.26,14.69q9.44,5,18.46,10.78A232.2,232.2,0,0,1,232,144a8,8,0,0,1,0,16ZM120,88h48a8,8,0,0,1,8,8v21.94q11.88-2.56,24-4V84L144,42,88,84v35.81q12.19,3,24,7.18V96A8,8,0,0,1,120,88Zm8.07,45.27A262.48,262.48,0,0,1,160,121.94V104H128v29.24Z"></path></svg>',
Icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M104,216V152h48v64h64V120a8,8,0,0,0-2.34-5.66l-80-80a8,8,0,0,0-11.32,0l-80,80A8,8,0,0,0,40,120v96Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>',
Type: "areas",
LongDescription: `The building models have a 3D object of each building plus additional information on its dimentions.`,
MinZoomLevel: 11,
MarkersThreshold: 17,
DisplayProperty: [],
PolygonColoring: null,
Tables: [],
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public string GetDataInsideArea(BoundingBox boundingBox)
{
"properties", new Dictionary<string, object>
{
{ "text", $"{row["operator"]}" }
{ "operator", $"{row["operator"]}" }
}
}
};
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/components/Alerts/ErrorAlert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ import "./Alerts.css";
import { useContext, useEffect } from "react";
import { AlertContext } from "../../contexts/AlertContext";

/**
* A component handling error alert on the bottom edge of the screen.
*/
const ErrorAlert: React.FC = () => {
const { currentAlertCache, setCurrentAlertCache } = useContext(AlertContext);

// Auto-hide
/**
* Auto-hiding of the component after some time.
*/
useEffect(() => {
const timeId = setTimeout(() => {
// After 3 seconds set the show value to false
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/DataView/DataRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ interface RowProps {
currentDatasets: DatasetBasicData[];
}

/**
* A single data row for the data view.
*/
const DataRow: React.FC<RowProps> = ({ row, currentDatasets }) => {
const [open, setOpen] = useState(false);
const [shouldFlyTo, setShouldFlyTo] = useState<LatLng | null>(null);
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/DataView/DataView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ function getOuterPolygons(multiPolygon: MultiPolygon): Position[][] {
return multiPolygon.coordinates.map((polygon) => polygon[0]);
}

/**
* Data view component for the right side of the main page.
*/
const DataView = () => {
const [isLoading, setIsLoading] = useState(false);
const { currentTabsCache, getCurrentTab } = useContext(TabsContext);
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/DataView/LoadDataButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ interface LoadDataButtonProps {
disabled: boolean;
}

/**
* A reload button for fetching the newest location data.
*/
const LoadDataButton: React.FC<LoadDataButtonProps> = ({
ifNeedsReloading,
disabled,
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/DatasetsList/CustomSvgIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ interface CustomSvgIconProps extends SvgIconProps {
size?: number;
}

/**
* Custom svg icon for the map markers.
*/
const CustomSvgIcon: React.FC<CustomSvgIconProps> = ({
svgString,
size = 32,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/DatasetsList/DatasetsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ interface DatasetsListProps {
closeDialog: () => void;
}

/**
* Component for listing all available datasets.
* @returns
*/
const DatasetsList: React.FC<DatasetsListProps> = ({ closeDialog }) => {
const [datasets, setDatasets] = useState<Dataset[]>([]);
const { openNewTab } = useContext(TabsContext);
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/MainMenu/MainMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import DatasetsList from "../DatasetsList/DatasetsList";

import "./MainMenu.css";

/**
* The main menu of the website.
*/
const MainMenu = () => {
return (
<Fragment>
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/MapView/LeafletMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ interface LeafletMapProps {
if3D: boolean;
}

/**
* Leaflet map visible in the map view on the left side of the page.
*/
const LeafletMap: React.FC<LeafletMapProps> = ({ datasetId, if3D }) => {
const { currentTabsCache, getCurrentTab, getOrFetchMetadata } =
useContext(TabsContext);
Expand Down
42 changes: 41 additions & 1 deletion frontend/src/components/MapView/MapDatasetVisualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ const MapDatasetVisualizer: React.FC<MapDatasetVisualizerProps> = ({
new LatLng(51.505, -0.09)
);

/**
* Updates the data for a specific dataset.
*/
const updateDatasetData = useCallback(
(newData: FeatureCollection, bounds: LatLngBounds) => {
setCurrentTabsCache((prevCache) => {
Expand Down Expand Up @@ -87,6 +90,27 @@ const MapDatasetVisualizer: React.FC<MapDatasetVisualizerProps> = ({
updateDatasetData
);

/**
* Function to determine the color based on usageType using PolygonColoring from metadata
* @param usageType the usage type string
* @returns the color to use
*/
const getColor = (usageType: string) => {
console.log(usageType);
if (dataset.metaData && dataset.metaData.polygonColoring) {
const coloring = dataset.metaData.polygonColoring;
for (const colorRule of coloring.colors) {
if (colorRule.values.includes(usageType)) {
return colorRule.color;
}
}
}
return "#3388ff";
};

/**
* Fetches the data for current viewport.
*/
useEffect(() => {
// Check if data has been fetched
if (!geoData || !dataset.metaData) return;
Expand All @@ -101,7 +125,23 @@ const MapDatasetVisualizer: React.FC<MapDatasetVisualizerProps> = ({
if (currentMapCache.zoom > dataset.metaData.markersThreshold) {
// Add the polygons to the map
try {
const geojsonLayer = L.geoJson(geoData);
const geojsonLayer = L.geoJson(geoData, {
style: (feature) => {
return {
color:
feature &&
dataset.metaData &&
dataset.metaData.polygonColoring
? getColor(
feature.properties[
dataset.metaData.polygonColoring.attributeName
]
)
: "#3388ff",
fillOpacity: 0.2,
};
},
});
geojsonLayer.addTo(map);
return () => {
map.removeLayer(geojsonLayer);
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/components/MapView/MapEventsHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import { flushSync } from "react-dom";
import { MarkerSelection } from "../../types/MapSelectionTypes";
import "./MapEventsHandler.css";

// Utility function to render a React component to HTML string
/**
* Utility function to render a React component to HTML string
*/
const renderToHtml = (Component: React.FC) => {
const div = document.createElement("div");
const root = createRoot(div);
Expand All @@ -19,6 +21,9 @@ const renderToHtml = (Component: React.FC) => {
return div.innerHTML;
};

/**
* Returns a MapPin div for one map marker.
*/
const divIconMarker: DivIcon = L.divIcon({
html: renderToHtml(() => (
<MapPin size={36} color="#ff0000" weight="fill" style={{ zIndex: "-10" }} />
Expand All @@ -28,6 +33,9 @@ const divIconMarker: DivIcon = L.divIcon({
iconAnchor: [18, 36], // Adjust the anchor point as needed
});

/**
* Takes care of the leaflet map events and renders a single selection marker
*/
const MapEventsHandler: React.FC = () => {
const { currentMapCache, setCurrentMapCache } = useContext(MapContext);

Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/MapView/MapOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ interface MapOptionsProps {
toggle3D: () => void;
}

/**
* Additional options buttons visible in the top right corner of the map.
*/
const MapOptions: React.FC<MapOptionsProps> = ({
onMapTypeChange,
if3D,
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/MapView/MapView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ interface MapViewProps {
datasetId: string;
}

/**
* One of the main components on the website. Displays the map on the left side of the page.
*/
const MapView: React.FC<MapViewProps> = ({ datasetId }) => {
const [if3D, setIf3D] = useState<boolean>(false);
const { currentMapCache, setCurrentMapCache } = useContext(MapContext);
Expand Down
12 changes: 10 additions & 2 deletions frontend/src/components/MultiMap/MultiMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ import { TabProps, TabsContext } from "../../contexts/TabsContext";
import NewTabButton from "./NewTabButton";
import TabOptions from "./TabOptions";

/**
* Main tabs component allowing for opening and saving of new map tabs.
*/
const MultiMap = () => {
// Access the tabs context
const { currentTabsCache, setCurrentTabsCache } = useContext(TabsContext);

// Dropdown menu for the tab options
/**
* Dropdown menu for the tab options
*/
const [anchorElementTabOptions, setAnchorElementTabOptions] =
useState<null | HTMLElement>(null);

Expand All @@ -35,7 +40,10 @@ const MultiMap = () => {

const [selectedTabId, setSelectedTabId] = useState<string | null>(null);

// Handles the change of the current tab id
/**
* Handles the change of the current tab id
* @param newTabID new current tab
*/
const handleChange = (newTabID: string) => {
setCurrentTabsCache({ ...currentTabsCache, currentTabID: newTabID });
};
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/components/MultiMap/NewTabButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ import { useState } from "react";
import DatasetsPopUp from "../PopUp/DatasetsPopUp";
import "./NewTabButton.css";

/**
* The new tab button for adding a new tab.
*/
const NewTabButton = () => {
// Stores the state of if the datasets popup is open
const [ifOpenedDialog, setIfOpenedDialog] = useState(false);

/**
* Toggles the new tab dialog.
*/
const toggleIfOpenedDialog = () => {
setIfOpenedDialog(!ifOpenedDialog);
};
Expand Down
Loading

0 comments on commit 7bc3628

Please sign in to comment.