Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend - Dataview Rework and bug fixes #393

Merged
merged 9 commits into from
Jul 13, 2024
1 change: 1 addition & 0 deletions backend/metadata-database/init-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ const datasets = [
additionalData: {
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",
DataType: "CITYGML",
LongDescription: `The building models have a 3D object of each building plus additional information on its dimentions.`,
MinZoomLevel: 11,
MarkersThreshold: 17,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,12 @@ public ActionResult GetDatasetViewportData([FromQuery] QueryParameters parameter
switch (metadata.additionalData.DataType)
{
case "CITYGML":
handler = new ShapeDatasetHandler(metadata);
break;
case "SHAPE":
handler = new ShapeDatasetHandler(metadata);
break;
case "CSV":
// TODO
handler = new CsvDatasetHandler(metadata);
break;
default:
Expand Down Expand Up @@ -151,7 +152,7 @@ public IActionResult LoadLocationData([FromBody, Required] LocationDataRequest r
return Ok(data);
} catch (Exception ex)
{
return BadRequest(ex);
return BadRequest(ex.ToString());
}
}

Expand Down
145 changes: 115 additions & 30 deletions backend/src/BIE.Core/BIE.Core.API/LoadLocationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,23 +63,34 @@ public static LocationDataResponse loadLocationDataforPolygons(LocationDataReque
});

var housefootprints = new List<Dictionary<String, String>>();
var columns = new HashSet<string> { "Id" };
var datasetId = "house_footprints";
foreach (var polygonWkt in polygons)
getDataInPolygon(housefootprints, columns, datasetId, polygonWkt);

AggregateDataForHousefootprints(generalData, individualData, totalAreaSearchPolygon, housefootprints);

var lod2buildings = new List<Dictionary<String, String>>();
foreach (var polygonWkt in polygons)
getDataInPolygon(lod2buildings, new() { "Id", "GroundArea", "BuildingWallHeight", "LivingArea", "RoofArea" }, "building_models", polygonWkt);

AggregateDataForLod2Citygml(generalData, individualData, totalAreaSearchPolygon, lod2buildings);

LocationDataResponse locationDataResponse = new()
{
// then go through house footprints
var metadata = MetadataDbHelper.GetMetadata("house_footprints");
if (metadata != null)
{
foreach (var table in metadata.additionalData.Tables)
{
var sqlQuery = $"SELECT Id, Location.STAsText() AS Location" +
ApiHelper.FromTableWhereIntersectsPolygon(table.Name, polygonWkt);
housefootprints.AddRange(DbHelper.GetData(sqlQuery));
}
}
SelectionData = generalData,
IndividualData = individualData.Take(500).ToList()

}
};

return locationDataResponse;
}

private static void AggregateDataForHousefootprints(List<DatasetItem> generalData, List<DatasetItem> individualData, double totalAreaSearchPolygon, List<Dictionary<string, string>> housefootprints)
{
long totalCountHouseFootprints = housefootprints.Count();
if (totalCountHouseFootprints == 0)
return;
double totalBuildingArea = 0.0;
List<double> totalBuildingAreas = new List<double>();
foreach (var h in housefootprints)
Expand Down Expand Up @@ -108,29 +119,103 @@ public static LocationDataResponse loadLocationDataforPolygons(LocationDataReque
});
generalData.Add(new DatasetItem
{
DisplayName = "Total number of buildings in area",
DisplayName = "Total number of buildings",
Value = totalCountHouseFootprints.ToString()
});
generalData.Add(new DatasetItem
if(totalBuildingAreas.Count > 0)
generalData.Add(GenerateDatalistStatisticsEntry(totalBuildingAreas, "Total building area"));

}

private static void AggregateDataForLod2Citygml(List<DatasetItem> generalData, List<DatasetItem> individualData, double totalAreaSearchPolygon, List<Dictionary<string, string>> citygmldata)
{
long totalCountLod2Buildings = citygmldata.Count();
if (totalCountLod2Buildings == 0)
return;

// GroundHeight, DistrictKey, CheckDate, GroundArea, BuildingWallHeight, LivingArea, RoofArea
List<double> totalBuildingAreas = new();
List<double> totalBuildingLivingAreas = new();
List<double> totalBuildingRoofAreas = new();
foreach (var h in citygmldata)
{
DisplayName = "Total building area",
Value = totalBuildingArea.ToString("0.##") + "m²",
Subdata = new List<SubdataItem>
double area = double.Parse(h["GroundArea"]);
totalBuildingAreas.Add(area);

double livingArea = double.Parse(h["LivingArea"]);
totalBuildingLivingAreas.Add(livingArea);

double roofArea = double.Parse(h["RoofArea"]);
totalBuildingRoofAreas.Add(roofArea);

double wallHeight = double.Parse(h["BuildingWallHeight"]);
totalBuildingRoofAreas.Add(roofArea);

Point p = (GeoReader.Read(h["Location"]) as Polygon).Centroid;
var item = new DatasetItem
{
new() { Key = "Average", Value = totalBuildingAreas.Average().ToString() },
new() { Key = "Median", Value = totalBuildingAreas.Median().ToString() },
new() { Key = "Variance", Value = totalBuildingAreas.Variance().ToString() }
}
});
DisplayName = "Building model: " + (h.ContainsKey("Id") ? h["Id"] : ""),
DatasetId = "building_models",
Value = area.ToString("0.##") + "m²",
Coordinate = new double[] { p.X, p.Y },
Subdata = new List<SubdataItem>
{
new() { Key = "Ground area", Value = area.ToString("0.##") + "m²" },
new() { Key = "Living area", Value = livingArea.ToString("0.##") + "m²" },
new() { Key = "Roof surface", Value = roofArea.ToString("0.##") + "m²" },
new() { Key = "Building wall height", Value = wallHeight.ToString("0.##") + "m" }
}
};
individualData.Add(item);
}

LocationDataResponse locationDataResponse = new()
double totalBuildingArea = totalBuildingAreas.Sum();
generalData.Add(new DatasetItem
{
SelectionData = generalData,
IndividualData = individualData.Take(500).ToList()
DisplayName = "Potential Area for geothermal use",
Value = Math.Max(totalAreaSearchPolygon - totalBuildingArea, 0).ToString("0.##") + "m²",
});
generalData.Add(new DatasetItem
{
DisplayName = "Total number of LOD2 buildings",
Value = totalCountLod2Buildings.ToString()
});
if (totalBuildingAreas.Count > 0)
generalData.Add(GenerateDatalistStatisticsEntry(totalBuildingAreas, "Total ground area"));
if (totalBuildingLivingAreas.Count > 0)
generalData.Add(GenerateDatalistStatisticsEntry(totalBuildingLivingAreas, "Total living area"));
if (totalBuildingRoofAreas.Count > 0)
generalData.Add(GenerateDatalistStatisticsEntry(totalBuildingRoofAreas, "Total roof surface"));
}

private static DatasetItem GenerateDatalistStatisticsEntry(List<double> listOfDataValues, string displayText)
{
return new DatasetItem
{
DisplayName = displayText,
Value = listOfDataValues.Sum().ToString("0.##") + "m²",
Subdata = new List<SubdataItem>
{
new() { Key = "Average", Value = listOfDataValues.Average().ToString() + "m²" },
new() { Key = "Median", Value = listOfDataValues.Median().ToString() + "m²"},
new() { Key = "Variance", Value = listOfDataValues.Variance().ToString()}
}
};
}

return locationDataResponse;
private static void getDataInPolygon(List<Dictionary<string, string>> housefootprints, HashSet<string> columns, string datasetId, string polygonWkt)
{
var metadata = MetadataDbHelper.GetMetadata(datasetId);
if (metadata != null)
{
foreach (var table in metadata.additionalData.Tables)
{
var sqlQuery = $"SELECT {string.Join(", ", columns)}, Location.STAsText() AS Location" +
ApiHelper.FromTableWhereIntersectsPolygon(table.Name, polygonWkt);
Console.WriteLine(sqlQuery);
housefootprints.AddRange(DbHelper.GetData(sqlQuery));
}
}
}

public static LocationDataResponse loadLocationDataForSinglePoint(LocationDataRequest request)
Expand Down Expand Up @@ -193,10 +278,10 @@ public static LocationDataResponse loadLocationDataForSinglePoint(LocationDataRe
}

private static IEnumerable<Dictionary<string, string>> getMatchingObjects(
string datasetId,
double longitude,
double latitude,
IEnumerable<string> columns)
string datasetId,
double longitude,
double latitude,
IEnumerable<string> columns)
{
// Convert the columns set to a comma-separated string
string columnsString = string.Join(", ", columns);
Expand Down
2 changes: 2 additions & 0 deletions backend/src/BIE.DataPipeline/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@

case "SHAPE":
importer = new ShapeImporter(description);

dbHelper.SetInfo(description.table_name, importer.GetInsertHeader() + ",Area");

break;

case "CITYGML":
Expand Down
24 changes: 15 additions & 9 deletions frontend/src/components/DataView/DataRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const DataRow: React.FC<RowProps> = ({ row, currentDatasets }) => {
return (
<Fragment>
<TableRow className="data-row">
{row.subdata.length > 0 ? (
{row.subdata && row.subdata.length > 0 ? (
<TableCell className="toggle-column" size="small">
<IconButton
aria-label="expand row"
Expand Down Expand Up @@ -155,14 +155,20 @@ const DataRow: React.FC<RowProps> = ({ row, currentDatasets }) => {
<Collapse in={open} timeout="auto" unmountOnExit>
<Table size="small" aria-label="subdata">
<TableBody className="subdata-rows-container">
{row.subdata.map((subItem) => (
<TableRow key={subItem.key}>
<TableCell component="th" scope="row" size="small">
{subItem.key}
</TableCell>
<TableCell size="small">{subItem.value}</TableCell>
</TableRow>
))}
{row.subdata ? (
<div>
{row.subdata.map((subItem) => (
<TableRow key={subItem.key}>
<TableCell component="th" scope="row" size="small">
{subItem.key}
</TableCell>
<TableCell size="small">{subItem.value}</TableCell>
</TableRow>
))}
</div>
) : (
<div></div>
)}
</TableBody>
</Table>
</Collapse>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/DataView/DataView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ const DataView = () => {
<TableBody>
{filterData(data?.selectionData ?? []).map((row) => (
<DataRow
key={row.datasetID}
key={row.displayName + row.value + row.coordinate}
row={row}
currentDatasets={currentDatasets}
/>
Expand All @@ -241,7 +241,7 @@ const DataView = () => {
<TableBody>
{filterData(data?.individualData ?? []).map((row) => (
<DataRow
key={row.datasetID}
key={row.displayName + row.value + row.coordinate}
row={row}
currentDatasets={currentDatasets}
/>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/types/LocationDataTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface DatasetItem {
value: string | null;
datasetID: string | null;
coordinate: number[] | null;
subdata: SubdataItem[];
subdata: SubdataItem[] | null;
}

/**
Expand Down
Loading