From edb119ae8f8139f76a36803e56274eafce0e4ce4 Mon Sep 17 00:00:00 2001 From: Muhammad Ahsan Khan Date: Fri, 28 Jun 2024 20:38:25 +0200 Subject: [PATCH 01/10] Updated LoadLocationData API Signed-off-by: Muhammad Ahsan Khan --- .../Controllers/DatasetController.cs | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs index 29f5368b..bd883b2c 100644 --- a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs +++ b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs @@ -195,11 +195,9 @@ FROM dbo.Hausumringe_mittelfranken_small [ProducesResponseType(500)] public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest request) { - _logger.LogInformation("Received request to load location data: {request}", request); if (!ModelState.IsValid) { - _logger.LogWarning("Invalid model state: {ModelState}", ModelState); return BadRequest(ModelState); } @@ -208,60 +206,32 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r var coordinate = request.Location.FirstOrDefault(); if (coordinate == null) { - _logger.LogWarning("Location coordinates are required."); return BadRequest("Location coordinates are required."); } var latitude = coordinate.Latitude; var longitude = coordinate.Longitude; var radius = 10000000; // Define the radius as needed + var buffer = 1000; // Define the buffer as needed - DbHelper.CreateDbConnection(); - - string command = @" - SELECT TOP 5 - Id, - Location.STArea() AS Area, - Location.STAsText() AS Location, - geography::Point({0}, {1}, 4326).STDistance(Location) AS Distance - FROM - dbo.Hausumringe_mittelfranken_small - WHERE - geography::Point({0}, {1}, 4326).STBuffer({2}).STIntersects(Location) = 1 - ORDER BY - geography::Point({0}, {1}, 4326).STDistance(Location);"; + var houseFootprints = QueryParameters.GetHouseFootprints(latitude, longitude, radius); + var evChargingStations = QueryParameters.GetEVChargingStations(latitude, longitude, buffer); - string formattedQuery = string.Format(command, latitude, longitude, radius); - var response = new LocationDataResponse + var response = new { - CurrentDatasetData = new List() + HouseFootprints = houseFootprints, + EVChargingStations = evChargingStations }; - foreach (var row in DbHelper.GetData(formattedQuery, 600)) - { - var area = row["Area"]; - var distance = row["Distance"]; - var location = row["Location"]; - - response.CurrentDatasetData.Add(new DatasetItem - { - Id = row["Id"].ToString(), - Key = location, - Value = $"{distance}m, {area}m^2", - MapId = "house_footprints" - }); - } - - _logger.LogInformation("Location data loaded successfully."); return Ok(response); } catch (Exception ex) { - _logger.LogError(ex, "Exception occurred while loading location data."); return StatusCode(500, $"Internal server error: {ex.Message}"); } } + /// /// WIP: DO NOT USE, Get a record /// @@ -464,6 +434,44 @@ public static double[] CalculateCentroid(List coordinates) return new double[] { centroidX / pointCount, centroidY / pointCount }; } + + public static List> GetEVChargingStations(double latitude, double longitude, int buffer) + { + string command = @" + SELECT TOP 5 + Id, + Location.STAsText() AS Location, + geometry::Point({0}, {1}, 4326).STDistance(Location) AS Distance + FROM + dbo.EV_charging_stations + WHERE + geometry::Point({0}, {1}, 4326).STBuffer({2}).STIntersects(Location) = 1 + ORDER BY + geometry::Point({0}, {1}, 4326).STDistance(Location);"; + + string formattedQuery = string.Format(command, latitude, longitude, buffer); + return DbHelper.GetData(formattedQuery).ToList(); + } + + public static List> GetHouseFootprints(double latitude, double longitude, int radius) + { + string command = @" + SELECT TOP 5 + Id, + Location.STArea() AS Area, + Location.STAsText() AS Location, + geometry::Point({0}, {1}, 4326).STDistance(Location) AS Distance + FROM + dbo.Hausumringe_mittelfranken_small + WHERE + geometry::Point({0}, {1}, 4326).STBuffer({2}).STIntersects(Location) = 1 + ORDER BY + geometry::Point({0}, {1}, 4326).STDistance(Location);"; + + string formattedQuery = string.Format(command, latitude, longitude, radius); + return DbHelper.GetData(formattedQuery).ToList(); + } + public static List> ClusterData(List data, int numberOfClusters) { var centroids = data.Select(d => CalculateCentroid(d.Coordinates)).ToArray(); From eb5aa59ab721b6b1335cb6300fadf382086c9f18 Mon Sep 17 00:00:00 2001 From: Muhammad Ahsan Khan Date: Tue, 2 Jul 2024 09:06:37 +0200 Subject: [PATCH 02/10] Update Loadlocationdata API to return data as Key value pair in json Signed-off-by: Muhammad Ahsan Khan --- .../Controllers/DatasetController.cs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs index bd883b2c..a212b41e 100644 --- a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs +++ b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs @@ -195,7 +195,6 @@ FROM dbo.Hausumringe_mittelfranken_small [ProducesResponseType(500)] public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest request) { - if (!ModelState.IsValid) { return BadRequest(ModelState); @@ -214,8 +213,28 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r var radius = 10000000; // Define the radius as needed var buffer = 1000; // Define the buffer as needed - var houseFootprints = QueryParameters.GetHouseFootprints(latitude, longitude, radius); - var evChargingStations = QueryParameters.GetEVChargingStations(latitude, longitude, buffer); + var houseFootprintsData = QueryParameters.GetHouseFootprints(latitude, longitude, radius); + var evChargingStationsData = QueryParameters.GetEVChargingStations(latitude, longitude, buffer); + + var houseFootprints = houseFootprintsData.SelectMany(h => + h.Select(kv => new DatasetItem + { + Id = h.ContainsKey("Id") ? h["Id"] : null, + Key = kv.Key, + Value = kv.Value, + MapId = h.ContainsKey("MapId") ? h["MapId"] : null // Optional + }) + ).ToList(); + + var evChargingStations = evChargingStationsData.SelectMany(e => + e.Select(kv => new DatasetItem + { + Id = e.ContainsKey("Id") ? e["Id"] : null, + Key = kv.Key, + Value = kv.Value, + MapId = e.ContainsKey("MapId") ? e["MapId"] : null // Optional + }) + ).ToList(); var response = new { From 21ce27299f659d42ba1028134a1bf9f74d6acdd4 Mon Sep 17 00:00:00 2001 From: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:56:03 +0200 Subject: [PATCH 03/10] refactored and fixed basic loadLocationData. still WIP Signed-off-by: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> --- .../Controllers/DatasetController.cs | 105 +++++++++++++----- frontend/src/components/DataView/DataView.tsx | 26 +++-- 2 files changed, 94 insertions(+), 37 deletions(-) diff --git a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs index a212b41e..5cd9d064 100644 --- a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs +++ b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs @@ -211,35 +211,21 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r var latitude = coordinate.Latitude; var longitude = coordinate.Longitude; var radius = 10000000; // Define the radius as needed - var buffer = 1000; // Define the buffer as needed - var houseFootprintsData = QueryParameters.GetHouseFootprints(latitude, longitude, radius); - var evChargingStationsData = QueryParameters.GetEVChargingStations(latitude, longitude, buffer); + var houseFootprintsData = getNclosestObjects("EV_charging_stations", longitude, latitude, radius, 5); - var houseFootprints = houseFootprintsData.SelectMany(h => - h.Select(kv => new DatasetItem - { - Id = h.ContainsKey("Id") ? h["Id"] : null, - Key = kv.Key, - Value = kv.Value, - MapId = h.ContainsKey("MapId") ? h["MapId"] : null // Optional - }) - ).ToList(); - - var evChargingStations = evChargingStationsData.SelectMany(e => - e.Select(kv => new DatasetItem - { - Id = e.ContainsKey("Id") ? e["Id"] : null, - Key = kv.Key, - Value = kv.Value, - MapId = e.ContainsKey("MapId") ? e["MapId"] : null // Optional - }) - ).ToList(); - - var response = new + var houseFootprints = houseFootprintsData.Select(h => new DatasetItem + { + Id = h.ContainsKey("Id") ? h["Id"] : null, + Key = "Charging station: " + (h.ContainsKey("operator") ? h["operator"] : "No operator defined"), + Value = h.ContainsKey("Distance") ? h["Distance"] : "-1", + MapId = "EV_charging_stations", + }).ToList(); + + LocationDataResponse response = new LocationDataResponse { - HouseFootprints = houseFootprints, - EVChargingStations = evChargingStations + CurrentDatasetData = houseFootprints, + GeneralData = new List() // Initialize GeneralData with an empty list }; return Ok(response); @@ -250,6 +236,73 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r } } + private IEnumerable> getNclosestObjects(string datasetId, double longitude, double lattitude, double radius, int n) + { + // number of closest objects with input of dataset name to be queried and maybe column for name + string command = @" + SELECT TOP {4} + operator, Id, + Location.STArea() AS Area, + Location.STAsText() AS Location, + geometry::Point({0}, {1}, 4326).STDistance(Location) AS Distance + FROM + dbo.{3} + WHERE + geometry::Point({0}, {1}, 4326).STBuffer({2}).STIntersects(Location) = 1 + ORDER BY + geometry::Point({0}, {1}, 4326).STDistance(Location);"; + + string formattedQuery = string.Format(command, lattitude, longitude, radius, datasetId, n); + _logger.LogInformation(formattedQuery); + + return DbHelper.GetData(formattedQuery); + } + + public static List> GetHouseFootprints(double latitude, double longitude, int radius) + { + string command = @" + SELECT TOP 5 + Id, + Location.STArea() AS Area, + Location.STAsText() AS Location, + geometry::Point({0}, {1}, 4326).STDistance(Location) AS Distance + FROM + dbo.Hausumringe_mittelfranken_small + WHERE + geometry::Point({0}, {1}, 4326).STBuffer({2}).STIntersects(Location) = 1 + ORDER BY + geometry::Point({0}, {1}, 4326).STDistance(Location);"; + + string formattedQuery = string.Format(command, latitude, longitude, radius); + return DbHelper.GetData(formattedQuery).ToList(); + } + + public static List> ClusterData(List data, int numberOfClusters) + { + var centroids = data.Select(d => QueryParameters.CalculateCentroid(d.Coordinates)).ToArray(); + var kmeans = new KMeans(numberOfClusters); + var clusters = kmeans.Learn(centroids); + int[] labels = clusters.Decide(centroids); + + for (int i = 0; i < labels.Length; i++) + { + data[i].ClusterId = labels[i]; + } + + var clusteredData = new List>(); + for (int i = 0; i < numberOfClusters; i++) + { + clusteredData.Add(new List()); + } + + for (int i = 0; i < labels.Length; i++) + { + clusteredData[labels[i]].Add(data[i]); + } + + return clusteredData; + } + /// /// WIP: DO NOT USE, Get a record diff --git a/frontend/src/components/DataView/DataView.tsx b/frontend/src/components/DataView/DataView.tsx index a285ccd8..076ea3c1 100644 --- a/frontend/src/components/DataView/DataView.tsx +++ b/frontend/src/components/DataView/DataView.tsx @@ -9,13 +9,14 @@ import LoadDataButton from "./LoadDataButton"; import axios from "axios"; import { getAPIGatewayURL } from "../../utils"; -const loadLocationData = async (): Promise< - LocationDataResponse | undefined -> => { +const loadLocationData = async ( + latitude: number, + longitude: number +): Promise => { const requestBody = { datasetId: "example_dataset", location: [ - { latitude: 51.509865, longitude: -0.118092 }, // Example coordinate + { latitude, longitude }, // Example coordinate ], }; @@ -74,13 +75,16 @@ function DataView() { }, [currentMapCache, ifNeedsReloading]); const reloadData = async () => { - setIfNeedsReloading(false); - setCurrentMapCache({ - ...currentMapCache, - loadedCoordinates: currentMapCache.selectedCoordinates, - }); - const responseData = await loadLocationData(); - setData(responseData); + if (currentMapCache.selectedCoordinates) { + const { lat, lng } = currentMapCache.selectedCoordinates; + setIfNeedsReloading(false); + setCurrentMapCache({ + ...currentMapCache, + loadedCoordinates: currentMapCache.selectedCoordinates, + }); + const responseData = await loadLocationData(lat, lng); + setData(responseData); + } }; return ( From 8cf116265010347b4cfc161994f830d8f6afe48e Mon Sep 17 00:00:00 2001 From: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:09:15 +0200 Subject: [PATCH 04/10] added area for current housefootprint in general data Signed-off-by: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> --- .../Controllers/DatasetController.cs | 83 ++++++++++++++----- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs index 5cd9d064..87427d1a 100644 --- a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs +++ b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs @@ -212,9 +212,10 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r var longitude = coordinate.Longitude; var radius = 10000000; // Define the radius as needed - var houseFootprintsData = getNclosestObjects("EV_charging_stations", longitude, latitude, radius, 5); + var columns = new HashSet { "operator", "Id" }; + var chargingStations = getNclosestObjects("EV_charging_stations", longitude, latitude, radius, 5, columns); - var houseFootprints = houseFootprintsData.Select(h => new DatasetItem + var chargingStationsData = chargingStations.Select(h => new DatasetItem { Id = h.ContainsKey("Id") ? h["Id"] : null, Key = "Charging station: " + (h.ContainsKey("operator") ? h["operator"] : "No operator defined"), @@ -222,10 +223,21 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r MapId = "EV_charging_stations", }).ToList(); + columns = new HashSet { "Id" }; + var houseFootprintsInArea = getMatchingObjects("Hausumringe_mittelfranken_small", longitude, latitude, columns); + + var houseFootprintsInAreaData = houseFootprintsInArea.Select(h => new DatasetItem + { + Id = h.ContainsKey("Id") ? h["Id"] : null, + Key = "Building footprint: ", + Value = h.ContainsKey("Area") ? h["Area"] : "-1", + MapId = "house_footprints", + }).ToList(); + LocationDataResponse response = new LocationDataResponse { - CurrentDatasetData = houseFootprints, - GeneralData = new List() // Initialize GeneralData with an empty list + CurrentDatasetData = chargingStationsData, + GeneralData = houseFootprintsInAreaData }; return Ok(response); @@ -236,26 +248,55 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r } } - private IEnumerable> getNclosestObjects(string datasetId, double longitude, double lattitude, double radius, int n) + private IEnumerable> getNclosestObjects(string datasetId, double longitude, double latitude, double radius, int n, IEnumerable columns) { // number of closest objects with input of dataset name to be queried and maybe column for name - string command = @" - SELECT TOP {4} - operator, Id, - Location.STArea() AS Area, - Location.STAsText() AS Location, - geometry::Point({0}, {1}, 4326).STDistance(Location) AS Distance - FROM - dbo.{3} - WHERE - geometry::Point({0}, {1}, 4326).STBuffer({2}).STIntersects(Location) = 1 - ORDER BY - geometry::Point({0}, {1}, 4326).STDistance(Location);"; - - string formattedQuery = string.Format(command, lattitude, longitude, radius, datasetId, n); - _logger.LogInformation(formattedQuery); + string columnsString = string.Join(", ", columns); + + // Define the SQL command with the columns string + string command = $@" + SELECT TOP {n} + {columnsString}, + Location.STArea() AS Area, + Location.STAsText() AS Location, + geometry::Point({latitude}, {longitude}, 4326).STDistance(Location) AS Distance + FROM + dbo.{datasetId} + WHERE + geometry::Point({latitude}, {longitude}, 4326).STBuffer({radius}).STIntersects(Location) = 1 + ORDER BY + geometry::Point({latitude}, {longitude}, 4326).STDistance(Location);"; + + _logger.LogInformation(command); + + return DbHelper.GetData(command); + } - return DbHelper.GetData(formattedQuery); + private IEnumerable> getMatchingObjects( + string datasetId, + double longitude, + double latitude, + IEnumerable columns) + { + // Convert the columns set to a comma-separated string + string columnsString = string.Join(", ", columns); + + // Define the SQL command with the columns string + string command = $@" + SELECT TOP 1000 + {columnsString}, + Location.STArea() AS Area, + Location.STAsText() AS Location + FROM + dbo.{datasetId} + WHERE + Location.STIntersects(geometry::Point({latitude}, {longitude}, 4326)) = 1 + ORDER BY + geometry::Point({latitude}, {longitude}, 4326).STDistance(Location);"; + + _logger.LogInformation(command); + + return DbHelper.GetData(command); } public static List> GetHouseFootprints(double latitude, double longitude, int radius) From 0c32fad9827890ebec098b4458b7310d158557bb Mon Sep 17 00:00:00 2001 From: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> Date: Tue, 2 Jul 2024 18:51:07 +0200 Subject: [PATCH 05/10] added correct sending of id, added temp workaround for wrong coord order, added meter calculation for area Signed-off-by: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> --- .../Controllers/DatasetController.cs | 21 +------------------ frontend/src/components/DataView/DataView.tsx | 15 +++++++------ 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs index 87427d1a..f9f42979 100644 --- a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs +++ b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs @@ -285,7 +285,7 @@ private IEnumerable> getMatchingObjects( string command = $@" SELECT TOP 1000 {columnsString}, - Location.STArea() AS Area, + geography::STGeomFromText(Location.STAsText(),4326).STArea() AS Area, Location.STAsText() AS Location FROM dbo.{datasetId} @@ -299,25 +299,6 @@ ORDER BY return DbHelper.GetData(command); } - public static List> GetHouseFootprints(double latitude, double longitude, int radius) - { - string command = @" - SELECT TOP 5 - Id, - Location.STArea() AS Area, - Location.STAsText() AS Location, - geometry::Point({0}, {1}, 4326).STDistance(Location) AS Distance - FROM - dbo.Hausumringe_mittelfranken_small - WHERE - geometry::Point({0}, {1}, 4326).STBuffer({2}).STIntersects(Location) = 1 - ORDER BY - geometry::Point({0}, {1}, 4326).STDistance(Location);"; - - string formattedQuery = string.Format(command, latitude, longitude, radius); - return DbHelper.GetData(formattedQuery).ToList(); - } - public static List> ClusterData(List data, int numberOfClusters) { var centroids = data.Select(d => QueryParameters.CalculateCentroid(d.Coordinates)).ToArray(); diff --git a/frontend/src/components/DataView/DataView.tsx b/frontend/src/components/DataView/DataView.tsx index 076ea3c1..4e679937 100644 --- a/frontend/src/components/DataView/DataView.tsx +++ b/frontend/src/components/DataView/DataView.tsx @@ -11,13 +11,12 @@ import { getAPIGatewayURL } from "../../utils"; const loadLocationData = async ( latitude: number, - longitude: number + longitude: number, + datasetId: string ): Promise => { const requestBody = { - datasetId: "example_dataset", - location: [ - { latitude, longitude }, // Example coordinate - ], + datasetId: datasetId, + location: [{ latitude, longitude }], }; try { @@ -82,7 +81,11 @@ function DataView() { ...currentMapCache, loadedCoordinates: currentMapCache.selectedCoordinates, }); - const responseData = await loadLocationData(lat, lng); + const responseData = await loadLocationData( + lat, + lng, + getCurrentTabTitle() + ); setData(responseData); } }; From 1b59d538c10f6d50db93cd31b9d554efb37fd685 Mon Sep 17 00:00:00 2001 From: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:34:19 +0200 Subject: [PATCH 06/10] added wkt parsing for areas and distance. wip Signed-off-by: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> --- backend/api-gateway/Models/LocationData.cs | 10 +- .../BIE.Core/BIE.Core.API/BIE.Core.API.csproj | 1 + .../Controllers/DatasetController.cs | 341 ++++++++++-------- .../Properties/launchSettings.json | 17 + frontend/src/services/locationDataService.ts | 3 +- 5 files changed, 209 insertions(+), 163 deletions(-) create mode 100644 backend/src/BIE.Core/BIE.Core.API/Properties/launchSettings.json diff --git a/backend/api-gateway/Models/LocationData.cs b/backend/api-gateway/Models/LocationData.cs index 61bbfd27..6043658a 100644 --- a/backend/api-gateway/Models/LocationData.cs +++ b/backend/api-gateway/Models/LocationData.cs @@ -1,9 +1,13 @@ -namespace APIGateway.Models +using System.Text.Json.Serialization; + +namespace APIGateway.Models { public class LocationDataRequest { - public string DatasetId { get; set; } = string.Empty; - public List Location { get; set; } = new List(); + [JsonPropertyName("datasetId")] + public string DatasetId { get; set; } + [JsonPropertyName("location")] + public List>> Location { get; set; } } public class Coordinate diff --git a/backend/src/BIE.Core/BIE.Core.API/BIE.Core.API.csproj b/backend/src/BIE.Core/BIE.Core.API/BIE.Core.API.csproj index 37fa139c..b919ac21 100644 --- a/backend/src/BIE.Core/BIE.Core.API/BIE.Core.API.csproj +++ b/backend/src/BIE.Core/BIE.Core.API/BIE.Core.API.csproj @@ -16,6 +16,7 @@ + diff --git a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs index 1a69ee3a..ed8546de 100644 --- a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs +++ b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs @@ -15,6 +15,11 @@ using BIE.Core.API.DatasetHandlers; using BieMetadata; using Microsoft.Extensions.Logging; +using System.Text.Json.Serialization; +using NetTopologySuite.IO; +using NetTopologySuite.Geometries; +using Microsoft.AspNetCore.Http; +using NetTopologySuite; namespace BIE.Core.API.Controllers { @@ -29,6 +34,7 @@ public class DatasetController : Controller private readonly ILogger _logger; private MetadataDbHelper mMetadataDbHelper; + private static readonly WKTReader GeoReader = new(new NtsGeometryServices(new PrecisionModel(), 4326)); private MetadataDbHelper MetadataDbHelper { @@ -103,117 +109,7 @@ public ActionResult GetDatasetViewportData([FromQuery] QueryParameters parameter return Ok(handler.GetDataInsideArea(boundingBox)); } - private ActionResult GetChargingStations(QueryParameters parameters) - { - _logger.LogInformation("Fetching charging stations with parameters: {parameters}", parameters); - try - { - // Create polygon WKT from bounding box - var polygonWkt = ApiHelper.GetPolygonFromQueryParameters(parameters); - - - // SQL Query to find intersecting points - var sqlQuery = $@" - SELECT top 1000 operator, Location.AsTextZM() AS Location - FROM dbo.EV_charging_stations - WHERE Location.STIntersects(geometry::STGeomFromText('{polygonWkt}', 4326)) = 1; - "; - - Console.WriteLine(sqlQuery); - // Get data from database - var data = DbHelper.GetData(sqlQuery); - - // Construct GeoJSON response - var response = new StringBuilder(); - response.Append("{\"type\": \"FeatureCollection\",\n\"features\": ["); - foreach (var row in data) - { - var location = row["Location"].ToString(); - // Extract the coordinates from the POINT string - var coordinates = location.Replace("POINT (", "").Replace(")", "").Split(' '); - var longitude = coordinates[0]; - var latitude = coordinates[1]; - - response.Append($@" - {{ - ""type"": ""Feature"", - ""geometry"": {{ - ""type"": ""Point"", - ""coordinates"": [{longitude}, {latitude}] - }}, - ""properties"": {{ - ""name"": ""{row["operator"]}"" - }} - }},"); - } - - if (response[response.Length - 1] == ',') - { - response.Length--; // Remove the trailing comma - } - - response.Append("]}"); - - return Ok(response.ToString()); - } - catch (Exception ex) - { - return BadRequest(ex.Message); - } - } - - - private ActionResult GetHouseFootprintsData([FromQuery] QueryParameters parameters) - { - _logger.LogInformation("Fetching house footprints with parameters: {parameters}", parameters); - try - { - DbHelper.CreateDbConnection(); - - // Create polygon WKT from bounding box - var polygonWkt = ApiHelper.GetPolygonFromQueryParameters(parameters); - - // SQL Query to find intersecting points - var sqlQuery = $@" -SELECT top 1000 Location.AsTextZM() AS Location, Location.STGeometryType() AS Type -FROM dbo.Hausumringe_mittelfranken_small -WHERE Location.STIntersects(geometry::STGeomFromText('{polygonWkt}', 4326)) = 1; -"; - Console.WriteLine(sqlQuery); - // Console.WriteLine(command); - var response = "{\"type\": \"FeatureCollection\",\n\"features\": ["; - foreach (var row in DbHelper.GetData(sqlQuery)) - { - response += $@" -{{ - ""type"": ""Feature"", - ""geometry"": {{ - ""type"": ""{row["Type"]}"", - ""coordinates"": [{QueryParameters.GetPolygonCordinates(row["Location"])}] - }}, - ""properties"": {{ - ""text"": ""{row["Type"]}"" -}} -}},"; - } - - if (response.Last() == ',') - { - response = response[..^1]; - } - - response += "]}"; - - _logger.LogInformation("House footprints data fetched successfully."); - return Ok(response); - } - catch (ServiceException se) - { - _logger.LogError(se, "ServiceException occurred while fetching house footprints data."); - return BadRequest(se.Message); - } - } /// /// Loads the location data for the given point or polygon. @@ -234,45 +130,84 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r try { - var coordinate = request.Location.FirstOrDefault(); - if (coordinate == null) + + // 2 parts: general data summarized for areas, indiviualized data for single parts + // in case of point we have a single entry inside the first polygon + if (request.Location.Count <= 0) { - return BadRequest("Location coordinates are required."); + return BadRequest("at least a single point has to be given"); } + else if (request.Location.Count == 1) + { + var coordinate = request.Location.FirstOrDefault().FirstOrDefault(); + if (coordinate == null) + { + return BadRequest("Location coordinates are required."); + } - var latitude = coordinate.Latitude; - var longitude = coordinate.Longitude; - var radius = 10000000; // Define the radius as needed + var latitude = coordinate.ElementAt(0); + var longitude = coordinate.ElementAt(1); - var columns = new HashSet { "operator", "Id" }; - var chargingStations = getNclosestObjects("EV_charging_stations", longitude, latitude, radius, 5, columns); + ////// all entries are saved to the result dataitem list. + var results = new List(); - var chargingStationsData = chargingStations.Select(h => new DatasetItem - { - Id = h.ContainsKey("Id") ? h["Id"] : null, - Key = "Charging station: " + (h.ContainsKey("operator") ? h["operator"] : "No operator defined"), - Value = h.ContainsKey("Distance") ? h["Distance"] : "-1", - MapId = "EV_charging_stations", - }).ToList(); + var reader = new WKTReader(); + var geoFactory = new GeometryFactory(new PrecisionModel(), 4326); - columns = new HashSet { "Id" }; - var houseFootprintsInArea = getMatchingObjects("Hausumringe_mittelfranken_small", longitude, latitude, columns); + //////////// load charging stations data + var radius = 10000000; // Define the radius as needed + var columns = new HashSet { "operator", "Id" }; + var metadata = MetadataDbHelper.GetMetadata("EV_charging_stations"); + if (metadata != null) + { + var tables = metadata.additionalData.Tables; + if (tables.Count == 1) + { - var houseFootprintsInAreaData = houseFootprintsInArea.Select(h => new DatasetItem - { - Id = h.ContainsKey("Id") ? h["Id"] : null, - Key = "Building footprint: ", - Value = h.ContainsKey("Area") ? h["Area"] : "-1", - MapId = "house_footprints", - }).ToList(); + var chargingStations = getNclosestObjects(tables[0].Name, longitude, latitude, radius, 3, columns); + + var chargingStationsData = chargingStations.Select(h => new DatasetItem + { + Id = h.ContainsKey("Id") ? h["Id"] : null, + Key = "Charging station: " + (h.ContainsKey("operator") ? h["operator"] : "No operator defined"), + Value = h.ContainsKey("Distance") ? h["Distance"] : "-1", + MapId = "EV_charging_stations", + }).ToList(); + + results.AddRange(chargingStationsData); + } + } - LocationDataResponse response = new LocationDataResponse - { - CurrentDatasetData = chargingStationsData, - GeneralData = houseFootprintsInAreaData - }; - return Ok(response); + //////////// house footprints charging stations data + columns = new HashSet { "Id" }; + metadata = MetadataDbHelper.GetMetadata("house_footprints"); + if (metadata != null) + { + var tables = metadata.additionalData.Tables; + foreach (var table in tables) + { + var houseFootprintsInArea = getMatchingObjects(table.Name, longitude, latitude, columns); + + var currentData = houseFootprintsInArea.Select(h => new DatasetItem + { + Id = h.ContainsKey("Id") ? h["Id"] : null, + Key = "Building footprint: ", + Value = h.ContainsKey("Area") ? h["Area"] : "-1", + MapId = "house_footprints", + }).ToList(); + results.AddRange(currentData); + } + } + + LocationDataResponse locationDataResponse = new() + { + CurrentDatasetData = results + }; + + return Ok(locationDataResponse); + } + return StatusCode(500, $"Currently unsupported operatin"); } catch (Exception ex) { @@ -288,10 +223,8 @@ private IEnumerable> getNclosestObjects(string datase // Define the SQL command with the columns string string command = $@" SELECT TOP {n} - {columnsString}, - Location.STArea() AS Area, - Location.STAsText() AS Location, - geometry::Point({latitude}, {longitude}, 4326).STDistance(Location) AS Distance + {columnsString} + Location.STAsText() AS Location FROM dbo.{datasetId} WHERE @@ -301,23 +234,52 @@ ORDER BY _logger.LogInformation(command); - return DbHelper.GetData(command); + // Get data from the database + var results = DbHelper.GetData(command); + + var geometryFactory = new GeometryFactory(new PrecisionModel(), 4326); + var point1 = geometryFactory.CreatePoint(new Coordinate(longitude, latitude)); + + foreach (var result in results) + { + if (result.ContainsKey("Location")) + { + var wkt = result["Location"]; + var point2 = GeoReader.Read(wkt) as Point; + if (point2 != null) + { + var distance = point1.Distance(point2); + result["Distance"] = distance.ToString(); + } + else + { + result["Distance"] = "-1"; + } + } + else + { + result["Distance"] = "-1"; + } + } + + return results; } + //private long getObjectCount(string datasetId, ) + private IEnumerable> getMatchingObjects( string datasetId, double longitude, double latitude, IEnumerable columns) - { - // Convert the columns set to a comma-separated string - string columnsString = string.Join(", ", columns); + { + // Convert the columns set to a comma-separated string + string columnsString = string.Join(", ", columns); - // Define the SQL command with the columns string - string command = $@" + // Define the SQL command with the columns string + string command = $@" SELECT TOP 1000 {columnsString}, - geography::STGeomFromText(Location.STAsText(),4326).STArea() AS Area, Location.STAsText() AS Location FROM dbo.{datasetId} @@ -328,8 +290,36 @@ ORDER BY _logger.LogInformation(command); - return DbHelper.GetData(command); + // Get data from the database + var results = DbHelper.GetData(command); + + var geometryFactory = new GeometryFactory(new PrecisionModel(), 4326); + var point1 = geometryFactory.CreatePoint(new Coordinate(longitude, latitude)); + + foreach (var result in results) + { + if (result.ContainsKey("Location")) + { + var wkt = result["Location"]; + var polygon = GeoReader.Read(wkt) as Polygon; + if (polygon != null) + { + result["Area"] = polygon.Area.ToString(); + } + else + { + result["Area"] = "-1"; + } + } + else + { + result["Area"] = "-1"; + } + } + + return results; } + public static List> ClusterData(List data, int numberOfClusters) { @@ -564,6 +554,43 @@ public static double[] CalculateCentroid(List coordinates) return new double[] { centroidX / pointCount, centroidY / pointCount }; } + public static List> GetEVChargingStations(double latitude, double longitude, int buffer) + { + string command = @" + SELECT TOP 5 + Id, + Location.STAsText() AS Location, + geometry::Point({0}, {1}, 4326).STDistance(Location) AS Distance + FROM + dbo.EV_charging_stations + WHERE + geometry::Point({0}, {1}, 4326).STBuffer({2}).STIntersects(Location) = 1 + ORDER BY + geometry::Point({0}, {1}, 4326).STDistance(Location);"; + + string formattedQuery = string.Format(command, latitude, longitude, buffer); + return DbHelper.GetData(formattedQuery).ToList(); + } + + public static List> GetHouseFootprints(double latitude, double longitude, int radius) + { + string command = @" + SELECT TOP 5 + Id, + Location.STArea() AS Area, + Location.STAsText() AS Location, + geometry::Point({0}, {1}, 4326).STDistance(Location) AS Distance + FROM + dbo.Hausumringe_mittelfranken_small + WHERE + geometry::Point({0}, {1}, 4326).STBuffer({2}).STIntersects(Location) = 1 + ORDER BY + geometry::Point({0}, {1}, 4326).STDistance(Location);"; + + string formattedQuery = string.Format(command, latitude, longitude, radius); + return DbHelper.GetData(formattedQuery).ToList(); + } + public static List> ClusterData(List data, int numberOfClusters) { var centroids = data.Select(d => CalculateCentroid(d.Coordinates)).ToArray(); @@ -630,14 +657,10 @@ public static GeoJsonFeatureCollection ConvertToGeoJson(List> public class LocationDataRequest { + [JsonPropertyName("datasetId")] public string DatasetId { get; set; } - public List Location { get; set; } - } - - public class Coordinate - { - public double Latitude { get; set; } - public double Longitude { get; set; } + [JsonPropertyName("location")] + public List>> Location { get; set; } } public class LocationDataResponse diff --git a/backend/src/BIE.Core/BIE.Core.API/Properties/launchSettings.json b/backend/src/BIE.Core/BIE.Core.API/Properties/launchSettings.json new file mode 100644 index 00000000..c80fa219 --- /dev/null +++ b/backend/src/BIE.Core/BIE.Core.API/Properties/launchSettings.json @@ -0,0 +1,17 @@ +{ + "profiles": { + "BIE.Core.API": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "DB_SERVER": "localhost", + "DB_NAME": "BIEDB", + "DB_PASSWORD": "MyPass@1234", + "DB_TYPE": "SQL", + "TRUSTED": "False", + "DB_USERNAME": "db_user1" + }, + "applicationUrl": "https://localhost:63103;http://localhost:63104" + } + } +} \ No newline at end of file diff --git a/frontend/src/services/locationDataService.ts b/frontend/src/services/locationDataService.ts index 0a9a9028..f4438ac4 100644 --- a/frontend/src/services/locationDataService.ts +++ b/frontend/src/services/locationDataService.ts @@ -11,7 +11,7 @@ import { Position } from "geojson"; */ export const fetchLocationData = async ( datasetId: string, - location: Position[][][] | Position[][] + location: Position[][] ): Promise => { // Build the request body const requestBody = { @@ -19,6 +19,7 @@ export const fetchLocationData = async ( location: location, }; try { + console.log(requestBody); const response = await axios.put( getAPIGatewayURL() + "/api/loadLocationData", requestBody From 3ab2d39ec835f79f77a8e46a0a40ccb967e312c6 Mon Sep 17 00:00:00 2001 From: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:48:23 +0200 Subject: [PATCH 07/10] fixed correct distance calculation Signed-off-by: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> --- .../BIE.Core/BIE.Core.API/BIE.Core.API.csproj | 1 + .../Controllers/DatasetController.cs | 147 +++++++++++------- 2 files changed, 93 insertions(+), 55 deletions(-) diff --git a/backend/src/BIE.Core/BIE.Core.API/BIE.Core.API.csproj b/backend/src/BIE.Core/BIE.Core.API/BIE.Core.API.csproj index b919ac21..fdd411a2 100644 --- a/backend/src/BIE.Core/BIE.Core.API/BIE.Core.API.csproj +++ b/backend/src/BIE.Core/BIE.Core.API/BIE.Core.API.csproj @@ -18,6 +18,7 @@ + diff --git a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs index ed8546de..3940906f 100644 --- a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs +++ b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs @@ -20,6 +20,11 @@ using NetTopologySuite.Geometries; using Microsoft.AspNetCore.Http; using NetTopologySuite; +using ProjNet.CoordinateSystems.Transformations; +using ProjNet.CoordinateSystems; +using ProjNet.IO.CoordinateSystems; +using static System.Collections.Specialized.BitVector32; +using NetTopologySuite.Algorithm; namespace BIE.Core.API.Controllers { @@ -35,6 +40,8 @@ public class DatasetController : Controller private MetadataDbHelper mMetadataDbHelper; private static readonly WKTReader GeoReader = new(new NtsGeometryServices(new PrecisionModel(), 4326)); + private static readonly GeometryFactory GeometryFactory = new(new PrecisionModel(), 4326); + private MetadataDbHelper MetadataDbHelper { @@ -130,9 +137,6 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r try { - - // 2 parts: general data summarized for areas, indiviualized data for single parts - // in case of point we have a single entry inside the first polygon if (request.Location.Count <= 0) { return BadRequest("at least a single point has to be given"); @@ -147,14 +151,8 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r var latitude = coordinate.ElementAt(0); var longitude = coordinate.ElementAt(1); - - ////// all entries are saved to the result dataitem list. var results = new List(); - var reader = new WKTReader(); - var geoFactory = new GeometryFactory(new PrecisionModel(), 4326); - - //////////// load charging stations data var radius = 10000000; // Define the radius as needed var columns = new HashSet { "operator", "Id" }; var metadata = MetadataDbHelper.GetMetadata("EV_charging_stations"); @@ -163,14 +161,19 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r var tables = metadata.additionalData.Tables; if (tables.Count == 1) { - var chargingStations = getNclosestObjects(tables[0].Name, longitude, latitude, radius, 3, columns); + // Log chargingStations to inspect the content + foreach (var station in chargingStations) + { + _logger.LogInformation($"Station data: {string.Join(", ", station.Select(kv => $"{kv.Key}: {kv.Value}"))}"); + } + var chargingStationsData = chargingStations.Select(h => new DatasetItem { Id = h.ContainsKey("Id") ? h["Id"] : null, Key = "Charging station: " + (h.ContainsKey("operator") ? h["operator"] : "No operator defined"), - Value = h.ContainsKey("Distance") ? h["Distance"] : "-1", + Value = h.ContainsKey("Distance") ? h["Distance"] : "-1 no dist", MapId = "EV_charging_stations", }).ToList(); @@ -178,27 +181,7 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r } } - - //////////// house footprints charging stations data - columns = new HashSet { "Id" }; - metadata = MetadataDbHelper.GetMetadata("house_footprints"); - if (metadata != null) - { - var tables = metadata.additionalData.Tables; - foreach (var table in tables) - { - var houseFootprintsInArea = getMatchingObjects(table.Name, longitude, latitude, columns); - - var currentData = houseFootprintsInArea.Select(h => new DatasetItem - { - Id = h.ContainsKey("Id") ? h["Id"] : null, - Key = "Building footprint: ", - Value = h.ContainsKey("Area") ? h["Area"] : "-1", - MapId = "house_footprints", - }).ToList(); - results.AddRange(currentData); - } - } + // Additional section for house footprints omitted for brevity LocationDataResponse locationDataResponse = new() { @@ -207,7 +190,7 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r return Ok(locationDataResponse); } - return StatusCode(500, $"Currently unsupported operatin"); + return StatusCode(500, $"Currently unsupported operation"); } catch (Exception ex) { @@ -217,38 +200,91 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r private IEnumerable> getNclosestObjects(string datasetId, double longitude, double latitude, double radius, int n, IEnumerable columns) { - // number of closest objects with input of dataset name to be queried and maybe column for name string columnsString = string.Join(", ", columns); - // Define the SQL command with the columns string string command = $@" - SELECT TOP {n} - {columnsString} - Location.STAsText() AS Location - FROM - dbo.{datasetId} - WHERE - geometry::Point({latitude}, {longitude}, 4326).STBuffer({radius}).STIntersects(Location) = 1 - ORDER BY - geometry::Point({latitude}, {longitude}, 4326).STDistance(Location);"; - - _logger.LogInformation(command); - - // Get data from the database - var results = DbHelper.GetData(command); - - var geometryFactory = new GeometryFactory(new PrecisionModel(), 4326); - var point1 = geometryFactory.CreatePoint(new Coordinate(longitude, latitude)); + SELECT TOP {n} + {columnsString}, + Location.STAsText() AS Location + FROM + dbo.{datasetId} + WHERE + geometry::Point({latitude}, {longitude}, 4326).STBuffer({radius}).STIntersects(Location) = 1 + ORDER BY + geometry::Point({latitude}, {longitude}, 4326).STDistance(Location);"; + + var results = DbHelper.GetData(command).ToList(); + + const string epsg27700 = @"PROJCS[""North_America_Albers_Equal_Area_Conic"", + GEOGCS[""NAD83"", + DATUM[""North_American_Datum_1983"", + SPHEROID[""GRS 1980"",6378137,298.257222101, + AUTHORITY[""EPSG"",""7019""]], + AUTHORITY[""EPSG"",""6269""]], + PRIMEM[""Greenwich"",0, + AUTHORITY[""EPSG"",""8901""]], + UNIT[""degree"",0.0174532925199433, + AUTHORITY[""EPSG"",""9122""]], + AUTHORITY[""EPSG"",""4269""]], + PROJECTION[""Albers_Conic_Equal_Area""], + PARAMETER[""latitude_of_center"",40], + PARAMETER[""longitude_of_center"",-96], + PARAMETER[""standard_parallel_1"",20], + PARAMETER[""standard_parallel_2"",60], + PARAMETER[""false_easting"",0], + PARAMETER[""false_northing"",0], + UNIT[""metre"",1, + AUTHORITY[""EPSG"",""9001""]], + AXIS[""Easting"",EAST], + AXIS[""Northing"",NORTH], + AUTHORITY[""ESRI"",""102008""] + "; // see http://epsg.io/27700 + + var epsg27700_crs = CoordinateSystemWktReader + .Parse(epsg27700); + var wgs84 = GeographicCoordinateSystem.WGS84; + // Create coordinate transformation + var mTransformation = + new CoordinateTransformationFactory().CreateFromCoordinateSystems(wgs84, (CoordinateSystem)epsg27700_crs); + + var windsorCastle = new Coordinate(51.483884, -0.604455); + var buckinghamPalace = new Coordinate(51.501576, -0.141208); + double[] basic = { -0.604455, 51.483884 }; + double[] epsg27700Point = mTransformation.MathTransform.Transform(basic); + + double[] basic2 = { -0.141208, 51.501576 }; + double[] epsg27700Point2 = mTransformation.MathTransform.Transform(basic2); + + // Extract latitude and longitude + double latitude1 = epsg27700Point[1]; + double longitude1 = epsg27700Point[0]; + + double latitude2 = epsg27700Point2[1]; + double longitude2 = epsg27700Point2[0]; + + var distance = new Coordinate(longitude1, latitude1).Distance(new Coordinate(longitude2, latitude2)); + _logger.LogInformation($"windsor castle: {mTransformation.MathTransform.Transform(basic)}"); + _logger.LogInformation($"distance: {distance}"); + + double[] sourceInWGS84_arr = {longitude,latitude }; + double[] sourceInEPSG27700_arr = mTransformation.MathTransform.Transform(sourceInWGS84_arr); + Coordinate sourceInEPSG27700 = new Coordinate(sourceInEPSG27700_arr[0], sourceInEPSG27700_arr[1]); + _logger.LogInformation($"sourceInWGS84_arr: [{string.Join(", ", sourceInWGS84_arr)}] and sourceInEPSG27700_arr: [{string.Join(", ", sourceInEPSG27700_arr)}] and sourceInEPSG27700: {sourceInEPSG27700}"); foreach (var result in results) { if (result.ContainsKey("Location")) { var wkt = result["Location"]; - var point2 = GeoReader.Read(wkt) as Point; - if (point2 != null) + var point2_wrong = GeoReader.Read(wkt) as Point; + if (point2_wrong != null) { - var distance = point1.Distance(point2); + double[] targetPointInWGS84 = { point2_wrong.Y, point2_wrong.X }; + double[] targetPointInEpsg27700 = mTransformation.MathTransform.Transform(targetPointInWGS84); + Coordinate targetInEPSG27700 = new Coordinate(targetPointInEpsg27700[0], targetPointInEpsg27700[1]); + distance = sourceInEPSG27700.Distance(targetInEPSG27700); + _logger.LogInformation($"targetPointInWGS84: [{string.Join(", ", targetPointInWGS84)}] and targetPointInEpsg27700: [{string.Join(", ", targetPointInEpsg27700)}] and targetInEPSG27700: {targetInEPSG27700}"); + result["Distance"] = distance.ToString(); } else @@ -265,6 +301,7 @@ ORDER BY return results; } + //private long getObjectCount(string datasetId, ) private IEnumerable> getMatchingObjects( From 3f913375ecafb60a43f1deb9ac2c1a7806c53db2 Mon Sep 17 00:00:00 2001 From: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> Date: Mon, 8 Jul 2024 17:00:26 +0200 Subject: [PATCH 08/10] fixed correct area calculation | refactorings Signed-off-by: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> --- .../src/BIE.Core/BIE.Core.API/ApiHelper.cs | 71 ++++++++++++ .../Controllers/DatasetController.cs | 105 +++++------------- 2 files changed, 101 insertions(+), 75 deletions(-) diff --git a/backend/src/BIE.Core/BIE.Core.API/ApiHelper.cs b/backend/src/BIE.Core/BIE.Core.API/ApiHelper.cs index f1a362ea..a979c3b0 100644 --- a/backend/src/BIE.Core/BIE.Core.API/ApiHelper.cs +++ b/backend/src/BIE.Core/BIE.Core.API/ApiHelper.cs @@ -5,12 +5,83 @@ using Accord.Math; using BIE.Core.API.Controllers; using BieMetadata; +using NetTopologySuite.Geometries; +using ProjNet.CoordinateSystems; +using ProjNet.CoordinateSystems.Transformations; +using ProjNet.IO.CoordinateSystems; namespace BIE.Core.API; public static class ApiHelper { private static CultureInfo sCultureInfo = new CultureInfo("en-US"); + private static string epsg27700 = @"PROJCS[""North_America_Albers_Equal_Area_Conic"", + GEOGCS[""NAD83"", + DATUM[""North_American_Datum_1983"", + SPHEROID[""GRS 1980"",6378137,298.257222101, + AUTHORITY[""EPSG"",""7019""]], + AUTHORITY[""EPSG"",""6269""]], + PRIMEM[""Greenwich"",0, + AUTHORITY[""EPSG"",""8901""]], + UNIT[""degree"",0.0174532925199433, + AUTHORITY[""EPSG"",""9122""]], + AUTHORITY[""EPSG"",""4269""]], + PROJECTION[""Albers_Conic_Equal_Area""], + PARAMETER[""latitude_of_center"",40], + PARAMETER[""longitude_of_center"",-96], + PARAMETER[""standard_parallel_1"",20], + PARAMETER[""standard_parallel_2"",60], + PARAMETER[""false_easting"",0], + PARAMETER[""false_northing"",0], + UNIT[""metre"",1, + AUTHORITY[""EPSG"",""9001""]], + AXIS[""Easting"",EAST], + AXIS[""Northing"",NORTH], + AUTHORITY[""ESRI"",""102008""] + "; // see http://epsg.io/27700 + private static ICoordinateTransformation mTransformation = new CoordinateTransformationFactory(). + CreateFromCoordinateSystems(GeographicCoordinateSystem.WGS84, + (CoordinateSystem)CoordinateSystemWktReader.Parse(epsg27700)); + + public static double getDistance(double longitude, double latitude, Point p) + { + double[] sourceInWGS84_arr = { longitude, latitude }; + double[] sourceInEPSG27700_arr = mTransformation.MathTransform.Transform(sourceInWGS84_arr); + Coordinate sourceInEPSG27700 = new Coordinate(sourceInEPSG27700_arr[0], sourceInEPSG27700_arr[1]); + + double[] targetPointInWGS84 = { p.Y, p.X }; + double[] targetPointInEpsg27700 = mTransformation.MathTransform.Transform(targetPointInWGS84); + Coordinate targetInEPSG27700 = new Coordinate(targetPointInEpsg27700[0], targetPointInEpsg27700[1]); + var distance = sourceInEPSG27700.Distance(targetInEPSG27700); + return distance; + } + + public static double getArea(Polygon p) + { + // convert each point of the polygon into a new coordinate (revert x and y + // convert it into EPSG27700 + // return area + var coordinates = p.Coordinates; + Console.WriteLine($"coordinates {coordinates}"); + var transformedCoordinates = new Coordinate[coordinates.Length]; + // Transform each coordinate + for (int i = 0; i < coordinates.Length; i++) + { + double[] pointWGS84 = { coordinates[i].Y, coordinates[i].X }; // Switch X and Y + double[] pointEPSG27700 = mTransformation.MathTransform.Transform(pointWGS84); + transformedCoordinates[i] = new Coordinate(pointEPSG27700[0], pointEPSG27700[1]); + Console.WriteLine($"transformedCoordinates[i] {transformedCoordinates[i]}"); + } + var geometryFactory = new GeometryFactory(new PrecisionModel(), 27700); + var transformedPolygon = new Polygon(new LinearRing(transformedCoordinates), geometryFactory); + Console.WriteLine($"area {transformedPolygon.Area}"); + Console.WriteLine($"transformed coords {transformedPolygon.Coordinates}"); + + + + // Return the area of the transformed polygon + return transformedPolygon.Area; + } /// /// Get the Bounding Box from the query parameters. diff --git a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs index 3940906f..fb69f562 100644 --- a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs +++ b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs @@ -173,15 +173,34 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r { Id = h.ContainsKey("Id") ? h["Id"] : null, Key = "Charging station: " + (h.ContainsKey("operator") ? h["operator"] : "No operator defined"), - Value = h.ContainsKey("Distance") ? h["Distance"] : "-1 no dist", + Value = h.ContainsKey("Distance") ? h["Distance"] + "m" : "-1", MapId = "EV_charging_stations", - }).ToList(); + }); results.AddRange(chargingStationsData); } } - // Additional section for house footprints omitted for brevity + // Additional section for house footprints + columns = new HashSet { "Id" }; + metadata = MetadataDbHelper.GetMetadata("house_footprints"); + if (metadata != null) + { + foreach(var table in metadata.additionalData.Tables) + { + var housefootprints = getMatchingObjects(table.Name, longitude, latitude, columns); + var housefootprintsData = housefootprints.Select(h => new DatasetItem + { + Id = h.ContainsKey("Id") ? h["Id"] : null, + Key = "House footprints" , + Value = h.ContainsKey("Area") ? h["Area"] + "m²" : "-1", + MapId = table.Name, + }); + results.AddRange(housefootprintsData); + + } + } + LocationDataResponse locationDataResponse = new() { @@ -215,62 +234,7 @@ ORDER BY var results = DbHelper.GetData(command).ToList(); - const string epsg27700 = @"PROJCS[""North_America_Albers_Equal_Area_Conic"", - GEOGCS[""NAD83"", - DATUM[""North_American_Datum_1983"", - SPHEROID[""GRS 1980"",6378137,298.257222101, - AUTHORITY[""EPSG"",""7019""]], - AUTHORITY[""EPSG"",""6269""]], - PRIMEM[""Greenwich"",0, - AUTHORITY[""EPSG"",""8901""]], - UNIT[""degree"",0.0174532925199433, - AUTHORITY[""EPSG"",""9122""]], - AUTHORITY[""EPSG"",""4269""]], - PROJECTION[""Albers_Conic_Equal_Area""], - PARAMETER[""latitude_of_center"",40], - PARAMETER[""longitude_of_center"",-96], - PARAMETER[""standard_parallel_1"",20], - PARAMETER[""standard_parallel_2"",60], - PARAMETER[""false_easting"",0], - PARAMETER[""false_northing"",0], - UNIT[""metre"",1, - AUTHORITY[""EPSG"",""9001""]], - AXIS[""Easting"",EAST], - AXIS[""Northing"",NORTH], - AUTHORITY[""ESRI"",""102008""] - "; // see http://epsg.io/27700 - - var epsg27700_crs = CoordinateSystemWktReader - .Parse(epsg27700); - var wgs84 = GeographicCoordinateSystem.WGS84; - // Create coordinate transformation - var mTransformation = - new CoordinateTransformationFactory().CreateFromCoordinateSystems(wgs84, (CoordinateSystem)epsg27700_crs); - - var windsorCastle = new Coordinate(51.483884, -0.604455); - var buckinghamPalace = new Coordinate(51.501576, -0.141208); - double[] basic = { -0.604455, 51.483884 }; - double[] epsg27700Point = mTransformation.MathTransform.Transform(basic); - - double[] basic2 = { -0.141208, 51.501576 }; - double[] epsg27700Point2 = mTransformation.MathTransform.Transform(basic2); - - // Extract latitude and longitude - double latitude1 = epsg27700Point[1]; - double longitude1 = epsg27700Point[0]; - - double latitude2 = epsg27700Point2[1]; - double longitude2 = epsg27700Point2[0]; - - var distance = new Coordinate(longitude1, latitude1).Distance(new Coordinate(longitude2, latitude2)); - _logger.LogInformation($"windsor castle: {mTransformation.MathTransform.Transform(basic)}"); - _logger.LogInformation($"distance: {distance}"); - - double[] sourceInWGS84_arr = {longitude,latitude }; - double[] sourceInEPSG27700_arr = mTransformation.MathTransform.Transform(sourceInWGS84_arr); - Coordinate sourceInEPSG27700 = new Coordinate(sourceInEPSG27700_arr[0], sourceInEPSG27700_arr[1]); - _logger.LogInformation($"sourceInWGS84_arr: [{string.Join(", ", sourceInWGS84_arr)}] and sourceInEPSG27700_arr: [{string.Join(", ", sourceInEPSG27700_arr)}] and sourceInEPSG27700: {sourceInEPSG27700}"); - + foreach (var result in results) { if (result.ContainsKey("Location")) @@ -279,13 +243,9 @@ ORDER BY var point2_wrong = GeoReader.Read(wkt) as Point; if (point2_wrong != null) { - double[] targetPointInWGS84 = { point2_wrong.Y, point2_wrong.X }; - double[] targetPointInEpsg27700 = mTransformation.MathTransform.Transform(targetPointInWGS84); - Coordinate targetInEPSG27700 = new Coordinate(targetPointInEpsg27700[0], targetPointInEpsg27700[1]); - distance = sourceInEPSG27700.Distance(targetInEPSG27700); - _logger.LogInformation($"targetPointInWGS84: [{string.Join(", ", targetPointInWGS84)}] and targetPointInEpsg27700: [{string.Join(", ", targetPointInEpsg27700)}] and targetInEPSG27700: {targetInEPSG27700}"); - result["Distance"] = distance.ToString(); + var distance = ApiHelper.getDistance(longitude, latitude, point2_wrong); + result["Distance"] = distance.ToString("0.##"); } else { @@ -328,10 +288,7 @@ ORDER BY _logger.LogInformation(command); // Get data from the database - var results = DbHelper.GetData(command); - - var geometryFactory = new GeometryFactory(new PrecisionModel(), 4326); - var point1 = geometryFactory.CreatePoint(new Coordinate(longitude, latitude)); + var results = DbHelper.GetData(command).ToList(); foreach (var result in results) { @@ -341,17 +298,15 @@ ORDER BY var polygon = GeoReader.Read(wkt) as Polygon; if (polygon != null) { - result["Area"] = polygon.Area.ToString(); + result["Area"] = ApiHelper.getArea(polygon).ToString("0.##"); } else - { result["Area"] = "-1"; - } + } else - { - result["Area"] = "-1"; - } + result["Area"] = "-1 no location"; + } return results; From 76e3a6ca36cc8182a9c99016e32caad9aa90748a Mon Sep 17 00:00:00 2001 From: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:14:11 +0200 Subject: [PATCH 09/10] added loading icon in fe for dataview Signed-off-by: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> --- frontend/src/components/DataView/DataView.css | 12 +++++++++ frontend/src/components/DataView/DataView.tsx | 26 +++++++++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/DataView/DataView.css b/frontend/src/components/DataView/DataView.css index de24cdd0..e75e3dd8 100644 --- a/frontend/src/components/DataView/DataView.css +++ b/frontend/src/components/DataView/DataView.css @@ -91,3 +91,15 @@ color: gray; font-size: 0.6rem; } + +.spinner-container { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + width: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 10; /* Ensure the spinner is on top */ +} diff --git a/frontend/src/components/DataView/DataView.tsx b/frontend/src/components/DataView/DataView.tsx index 188cd5d2..cae16beb 100644 --- a/frontend/src/components/DataView/DataView.tsx +++ b/frontend/src/components/DataView/DataView.tsx @@ -13,6 +13,7 @@ import { PolygonSelection, } from "../../types/MapSelectionTypes"; import { MultiPolygon, Position } from "geojson"; +import { CircularProgress } from "@mui/material"; // Function to filter and return an array of outer polygons function getOuterPolygons(multiPolygon: MultiPolygon): Position[][] { @@ -21,6 +22,7 @@ function getOuterPolygons(multiPolygon: MultiPolygon): Position[][] { } function DataView() { + const [isLoading, setIsLoading] = useState(false); const { currentTabsCache, getCurrentTab } = useContext(TabsContext); const { currentMapCache, setCurrentMapCache } = useContext(MapContext); const [filterValue, setFilterValue] = useState(""); @@ -70,7 +72,7 @@ function DataView() { * Reloads the location data. */ const reloadData = async () => { - // Get all parameters + setIsLoading(true); // Set loading to true before starting the fetch request setIfNeedsReloading(false); const currentID = currentTabsCache.currentTabID; const currentCoords = currentMapCache.selectedCoordinates; @@ -111,6 +113,8 @@ function DataView() { } else { console.log("Currently selected coordinates are null."); } + + setIsLoading(false); // Set loading to false after the fetch request completes }; return ( @@ -159,13 +163,19 @@ function DataView() { /> - + {isLoading ? ( +
+ +
+ ) : ( + + )} {ifNeedsReloading ? (
From de84f5828e28c65b68fef5e41671f1c7fd847e15 Mon Sep 17 00:00:00 2001 From: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:41:24 +0200 Subject: [PATCH 10/10] many extra data entries Signed-off-by: Lucas-Nan <166795065+Lucas-Nan@users.noreply.github.com> --- backend/api-gateway/Models/LocationData.cs | 4 +- .../src/BIE.Core/BIE.Core.API/ApiHelper.cs | 34 ++- .../Controllers/DatasetController.cs | 207 ++++++++++++++---- .../src/components/DataView/DataPanel.tsx | 72 +----- frontend/src/components/DataView/DataView.tsx | 20 +- frontend/src/types/LocationDataTypes.tsx | 3 +- 6 files changed, 200 insertions(+), 140 deletions(-) diff --git a/backend/api-gateway/Models/LocationData.cs b/backend/api-gateway/Models/LocationData.cs index 6043658a..2351ffb2 100644 --- a/backend/api-gateway/Models/LocationData.cs +++ b/backend/api-gateway/Models/LocationData.cs @@ -7,7 +7,7 @@ public class LocationDataRequest [JsonPropertyName("datasetId")] public string DatasetId { get; set; } [JsonPropertyName("location")] - public List>> Location { get; set; } + public List>> Location { get; set; } } public class Coordinate @@ -18,7 +18,7 @@ public class Coordinate public class LocationDataResponse { - public List CurrentDatasetData { get; set; } = new List(); + public List IndividualData { get; set; } = new List(); public List GeneralData { get; set; } = new List(); } diff --git a/backend/src/BIE.Core/BIE.Core.API/ApiHelper.cs b/backend/src/BIE.Core/BIE.Core.API/ApiHelper.cs index a979c3b0..ce132dbe 100644 --- a/backend/src/BIE.Core/BIE.Core.API/ApiHelper.cs +++ b/backend/src/BIE.Core/BIE.Core.API/ApiHelper.cs @@ -124,6 +124,38 @@ public static string GetPolygonFromBoundingBox(BoundingBox boundingBox) $" {bottomLong} {bottomLat}))"; } + public static List ConvertToWktPolygons(List>> locations) + { + var culture = new CultureInfo("en-US"); + var wktPolygons = new List(); + + foreach (var polygon in locations) + { + var wktString = "POLYGON(("; + foreach (var point in polygon) + { + if (point.Count != 2) + { + throw new ArgumentException("Each point should have exactly two coordinates."); + } + + var longitude = point[0].ToString(culture); + var latitude = point[1].ToString(culture); + wktString += $"{longitude} {latitude}, "; + } + + // Close the polygon by repeating the first point + var firstPoint = polygon[0]; + var firstLongitude = firstPoint[0].ToString(culture); + var firstLatitude = firstPoint[1].ToString(culture); + wktString += $"{firstLongitude} {firstLatitude}))"; + + wktPolygons.Add(wktString); + } + + return wktPolygons; + } + /// /// Get the polygon of the bounding box given in the queryparameters /// @@ -155,7 +187,7 @@ public static bool BoxIntersection(BoundingBox box1, BoundingBox box2) var right2 = box2.maxX; var top2 = box2.maxY; - Console.WriteLine($"left1: {left1}, left2: {left2}"); + //Console.WriteLine($"left1: {left1}, left2: {left2}"); return !(right1 < left2 || right2 < left1 || top1 < bottom2 || top2 < bottom1); } diff --git a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs index fb69f562..c720bfe0 100644 --- a/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs +++ b/backend/src/BIE.Core/BIE.Core.API/Controllers/DatasetController.cs @@ -25,6 +25,11 @@ using ProjNet.IO.CoordinateSystems; using static System.Collections.Specialized.BitVector32; using NetTopologySuite.Algorithm; +using MySqlX.XDevAPI.Relational; +using Org.BouncyCastle.Asn1.Cms; +using MySqlX.XDevAPI.Common; +using static MongoDB.Bson.Serialization.Serializers.SerializerHelper; +using Accord.Math; namespace BIE.Core.API.Controllers { @@ -137,79 +142,177 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r try { + var generalData = new List(); + var individualData = new List(); + + // can still be called even if we have a single point + var polygons = ApiHelper.ConvertToWktPolygons(request.Location); + + if (request.Location.Count <= 0) { return BadRequest("at least a single point has to be given"); } - else if (request.Location.Count == 1) + + bool onlySinglePoint = request.Location.Count == 1 && request.Location.ElementAt(0).Count == 1; + + Point pointForCalculations = new Point(new Coordinate()); + if (onlySinglePoint) { - var coordinate = request.Location.FirstOrDefault().FirstOrDefault(); - if (coordinate == null) - { - return BadRequest("Location coordinates are required."); - } + var p = request.Location.First().First(); + pointForCalculations = new Point(p.ElementAt(0), p.ElementAt(1)); + } + else + { + // Create a WKTReader instance + WKTReader reader = new WKTReader(); + Geometry geometry = reader.Read(polygons.First()); + if (geometry is Polygon polygon) + pointForCalculations = polygon.Centroid; - var latitude = coordinate.ElementAt(0); - var longitude = coordinate.ElementAt(1); - var results = new List(); + } - var radius = 10000000; // Define the radius as needed - var columns = new HashSet { "operator", "Id" }; - var metadata = MetadataDbHelper.GetMetadata("EV_charging_stations"); - if (metadata != null) + // closest charging stations and number of charging stations + var radius = 10000000; // Define the radius as needed + var columns = new HashSet { "operator", "Id", "rated_power_kw" }; + var metadata = MetadataDbHelper.GetMetadata("EV_charging_stations"); + if (metadata != null) + { + var tables = metadata.additionalData.Tables; + if (tables.Count == 1) { - var tables = metadata.additionalData.Tables; - if (tables.Count == 1) - { - var chargingStations = getNclosestObjects(tables[0].Name, longitude, latitude, radius, 3, columns); + var chargingStations = getNclosestObjects(tables[0].Name, pointForCalculations.Y, pointForCalculations.X, radius, 3, columns); - // Log chargingStations to inspect the content - foreach (var station in chargingStations) - { - _logger.LogInformation($"Station data: {string.Join(", ", station.Select(kv => $"{kv.Key}: {kv.Value}"))}"); - } + // Log chargingStations to inspect the content + foreach (var station in chargingStations) + { + _logger.LogInformation($"Station data: {string.Join(", ", station.Select(kv => $"{kv.Key}: {kv.Value}"))}"); + } - var chargingStationsData = chargingStations.Select(h => new DatasetItem - { - Id = h.ContainsKey("Id") ? h["Id"] : null, - Key = "Charging station: " + (h.ContainsKey("operator") ? h["operator"] : "No operator defined"), - Value = h.ContainsKey("Distance") ? h["Distance"] + "m" : "-1", - MapId = "EV_charging_stations", - }); + var chargingStationsData = chargingStations.Select(h => new DatasetItem + { + Id = h.ContainsKey("Id") ? h["Id"] : null, + Key = "Charging station: " + (h.ContainsKey("operator") ? h["operator"] : "No operator defined"), + Value = (h.ContainsKey("Distance") ? h["Distance"] + "m" : "-1") + " | " + (h.ContainsKey("rated_power_kw") ? h["rated_power_kw"] + "kw" : "-1"), + MapId = "EV_charging_stations", + }); - results.AddRange(chargingStationsData); - } + individualData.AddRange(chargingStationsData); } + } + + var housefootprints = new List>(); + if(onlySinglePoint) + { // Additional section for house footprints columns = new HashSet { "Id" }; metadata = MetadataDbHelper.GetMetadata("house_footprints"); if (metadata != null) { - foreach(var table in metadata.additionalData.Tables) + var p = request.Location.First().First(); + foreach (var table in metadata.additionalData.Tables) + housefootprints.AddRange(getMatchingObjects(table.Name, p.ElementAt(1), p.ElementAt(0), columns)); + + } + } + else + { + _logger.LogInformation("Do housefootprints for area"); + + foreach (var polygonWkt in polygons) + { + // then go through house footprints + metadata = MetadataDbHelper.GetMetadata("house_footprints"); + if (metadata != null) { - var housefootprints = getMatchingObjects(table.Name, longitude, latitude, columns); - var housefootprintsData = housefootprints.Select(h => new DatasetItem + _logger.LogInformation("metadata from housefootprints retrieved"); + foreach (var table in metadata.additionalData.Tables) { - Id = h.ContainsKey("Id") ? h["Id"] : null, - Key = "House footprints" , - Value = h.ContainsKey("Area") ? h["Area"] + "m²" : "-1", - MapId = table.Name, - }); - results.AddRange(housefootprintsData); + var sqlQuery = $"SELECT Id, Location.STAsText() AS Location" + + ApiHelper.FromTableIntersectsPolygon(table.Name, polygonWkt); + _logger.LogInformation(sqlQuery); + housefootprints.AddRange(DbHelper.GetData(sqlQuery)); + } } + + } + } + double totalBuildingArea = 0.0; + if (housefootprints.Any()) + { + var housefootprintsData = housefootprints.Select(h => new DatasetItem + { + Id = h.ContainsKey("Id") ? h["Id"] : null, + Key = "House footprints", + Value = h.ContainsKey("Location") ? ApiHelper.getArea(GeoReader.Read(h["Location"]) as Polygon).ToString("0.##") + "m²" : "-1", + MapId = "House footprints", + }); + individualData.AddRange(housefootprintsData); + + long totalCountHouseFootprints = housefootprints.Count(); + long totalCountChargingStations = 0l; + foreach (var hdata in housefootprints) + { + + totalBuildingArea += hdata.ContainsKey("Location") ? ApiHelper.getArea(GeoReader.Read(hdata["Location"]) as Polygon) : 0; + } + if (!onlySinglePoint) + { + generalData.Add(new DatasetItem + { + Id = "Total number of buildings in area", + Key = "Total number of buildings in area", + Value = totalCountHouseFootprints.ToString(), + MapId = "" + }); + } + generalData.Add(new DatasetItem + { + Id = "Total building", + Key = "Total building area", + Value = totalBuildingArea.ToString("0.##") + "m²", + MapId = "" + }); + } - LocationDataResponse locationDataResponse = new() + ////////////// + if (!onlySinglePoint) + { + WKTReader reader = new WKTReader(); + double totalAreaSearchPolygon = 0.0; + foreach(var polygonWkt in polygons) { - CurrentDatasetData = results - }; - - return Ok(locationDataResponse); + Geometry geometry = reader.Read(polygonWkt); + if (geometry is Polygon polygon) + totalAreaSearchPolygon += ApiHelper.getArea(polygon); + } + generalData.Insert(0, new DatasetItem + { + Id = "Searched area", + Key = "Searched area", + Value = totalAreaSearchPolygon.ToString("0.##") + "m²", + MapId = "" + }); + generalData.Add(new DatasetItem + { + Id = "Potential Area for geothermal use", + Key = "Potential Area for geothermal use", + Value = Math.Max(totalAreaSearchPolygon - totalBuildingArea, 0).ToString("0.##") + "m²", + MapId = "" + }); } - return StatusCode(500, $"Currently unsupported operation"); + + LocationDataResponse locationDataResponse = new() + { + IndividualData = individualData, + GeneralData = generalData + }; + + return Ok(locationDataResponse); } catch (Exception ex) { @@ -263,6 +366,14 @@ ORDER BY //private long getObjectCount(string datasetId, ) + private IEnumerable> getMatchingObjects( + string datasetId, + double[] longitude, + double[] latitude, + IEnumerable columns) + { + return new List>(); + } private IEnumerable> getMatchingObjects( string datasetId, @@ -652,12 +763,12 @@ public class LocationDataRequest [JsonPropertyName("datasetId")] public string DatasetId { get; set; } [JsonPropertyName("location")] - public List>> Location { get; set; } + public List>> Location { get; set; } } public class LocationDataResponse { - public List CurrentDatasetData { get; set; } + public List IndividualData { get; set; } public List GeneralData { get; set; } } diff --git a/frontend/src/components/DataView/DataPanel.tsx b/frontend/src/components/DataView/DataPanel.tsx index 7d653725..560037fc 100644 --- a/frontend/src/components/DataView/DataPanel.tsx +++ b/frontend/src/components/DataView/DataPanel.tsx @@ -24,7 +24,6 @@ interface DataPanelProps { filterValue: string; mapRows: DatasetItem[]; genericRows: DatasetItem[]; - extraRows: DatasetItem[]; } /* @@ -36,14 +35,12 @@ const DataPanel: React.FC = ({ filterValue, mapRows, genericRows, - extraRows, }) => { // Keep track of if tabs are hidden const [ifMapDataTabHidden, toggleMapDataHidden] = useState(false); const [ifGeneralDataTabHidden, toggleGeneralDataHidden] = useState(false); - const [ifExtraDataTabHidden, toggleExtraDataHidden] = - useState(false); + useState(false); const { currentAlertCache, setCurrentAlertCache } = useContext(AlertContext); const { openNewTab } = useContext(TabsContext); @@ -206,7 +203,7 @@ const DataPanel: React.FC = ({ ifGeneralDataTabHidden ? "data-panel-toggle-icon-hidden" : "" }`} /> - General Data + Individual Data
= ({ />
-
-
{ - toggleExtraDataHidden(!ifExtraDataTabHidden); - }} - > - - Extra Capabilities -
- - { - return row.key + row.value; - }} - hideFooter={true} - disableColumnMenu - columnHeaderHeight={0} - rows={extraRows} - columns={columns} - slots={{ - toolbar: MyCustomToolbar, - }} - slotProps={{ - toolbar: { - printOptions: { disableToolbarButton: true }, - csvOptions: { disableToolbarButton: true }, - }, - }} - disableDensitySelector - disableColumnFilter - disableColumnSelector - disableColumnSorting - initialState={{ - filter: { - filterModel: { - items: [], - quickFilterValues: [filterValue], - quickFilterExcludeHiddenColumns: true, - }, - }, - }} - filterModel={{ - items: [ - { field: "key", operator: "contains", value: filterValue }, - ], - }} - density="compact" - disableRowSelectionOnClick - autoHeight - /> - -
); }; diff --git a/frontend/src/components/DataView/DataView.tsx b/frontend/src/components/DataView/DataView.tsx index cae16beb..f1f8029f 100644 --- a/frontend/src/components/DataView/DataView.tsx +++ b/frontend/src/components/DataView/DataView.tsx @@ -33,19 +33,6 @@ function DataView() { setFilterValue(event.target.value); }; - /** - * Returns the title of the currently selected tab - * @returns current tab title - */ - const getCurrentTabTitle = (): string => { - const currentTabID = currentTabsCache.currentTabID.toString(); - const currentTab = currentTabsCache.openedTabs.find( - (tab) => tab.id === currentTabID - ); - - return currentTab ? currentTab.dataset.displayName : "No map loaded"; - }; - /** * Check if the "Reload data" button should be visible. * Should be run on selecting different coordinates or changing the current map ID. @@ -169,11 +156,10 @@ function DataView() { ) : ( )} {ifNeedsReloading ? ( diff --git a/frontend/src/types/LocationDataTypes.tsx b/frontend/src/types/LocationDataTypes.tsx index ec9471da..5163856e 100644 --- a/frontend/src/types/LocationDataTypes.tsx +++ b/frontend/src/types/LocationDataTypes.tsx @@ -1,7 +1,6 @@ export interface LocationDataResponse { - currentDatasetData: DatasetItem[]; + individualData: DatasetItem[]; generalData: DatasetItem[]; - extraRows: DatasetItem[]; } export interface DatasetItem {