Skip to content

Commit

Permalink
Backend - Dataview Rework and bug fixes (#393)
Browse files Browse the repository at this point in the history
  • Loading branch information
Corgam authored Jul 13, 2024
2 parents 7bc3628 + df9d608 commit d6517b7
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 44 deletions.
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.##") + "",
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.##") + "",
Coordinate = new double[] { p.X, p.Y },
Subdata = new List<SubdataItem>
{
new() { Key = "Ground area", Value = area.ToString("0.##") + "" },
new() { Key = "Living area", Value = livingArea.ToString("0.##") + "" },
new() { Key = "Roof surface", Value = roofArea.ToString("0.##") + "" },
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.##") + "",
});
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.##") + "",
Subdata = new List<SubdataItem>
{
new() { Key = "Average", Value = listOfDataValues.Average().ToString() + "" },
new() { Key = "Median", Value = listOfDataValues.Median().ToString() + ""},
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

0 comments on commit d6517b7

Please sign in to comment.