diff --git a/app/lib/pages/widgets/cloropleth_map.dart b/app/lib/pages/widgets/cloropleth_map.dart index ac235158ef6e648da752817143bad965ee07297b..3e4fb6bc46c5d3968e7a8104f6bf802c18cae86f 100644 --- a/app/lib/pages/widgets/cloropleth_map.dart +++ b/app/lib/pages/widgets/cloropleth_map.dart @@ -1,5 +1,7 @@ import 'dart:typed_data'; -import 'package:app/pages/consts.dart'; +import 'package:latlong2/latlong.dart'; + +import '../marker_handler/marker_data.dart'; import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_maps/maps.dart'; import '../consts.dart'; @@ -17,9 +19,13 @@ class IceThicknessModel { /// The map data is fetched from the server, and the map is rendered /// using the Syncfusion Flutter Maps library. class ChoroplethMap extends StatefulWidget { - const ChoroplethMap({Key? key, required this.relation}) : super(key: key); + const ChoroplethMap({Key? key, + required this.relation, + required this.measurements + }) : super(key: key); final Uint8List relation; + final List<Measurement> measurements; @override _ChoroplethMapState createState() => _ChoroplethMapState(); diff --git a/app/lib/pages/widgets/map_widget.dart b/app/lib/pages/widgets/map_widget.dart index 1dee6355584483b55f33a8057e1ad21af18bdbb0..f0ca2186963df44cdaa70ed7e2850d6439035a0c 100644 --- a/app/lib/pages/widgets/map_widget.dart +++ b/app/lib/pages/widgets/map_widget.dart @@ -118,7 +118,7 @@ class _MapContainerWidgetState extends State<MapContainerWidget> { height: screenWidth * boxHeight, child: Padding( padding: const EdgeInsets.all(15.0), // Padding around map - child: ChoroplethMap(relation: widget.relation), + child: ChoroplethMap(relation: widget.relation, measurements: widget.markerList,), ), ), Positioned( // Quick view box layered over map diff --git a/server/data_processing/__pycache__/process_lidar_data.cpython-311.pyc b/server/data_processing/__pycache__/process_lidar_data.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bcaab3c96c44cab902c18d3bd614a974fbd0561c Binary files /dev/null and b/server/data_processing/__pycache__/process_lidar_data.cpython-311.pyc differ diff --git a/server/main.py b/server/main.py index 90c4048f8c59ea441269c4301db6572ff0f6d90d..989e1c30ef336b29029bfefdd10ba3e6cc0c95f3 100644 --- a/server/main.py +++ b/server/main.py @@ -2,6 +2,7 @@ from flask import Flask from http.server import HTTPServer, BaseHTTPRequestHandler from consts import SSL_CERT_PATH, SSL_KEY_PATH, HOST, PORT from map.get_markers import get_all_markers +from map.get_relation import get_relation from APIs.get_weather import get_weather import ssl import keyboard diff --git a/server/map/__pycache__/get_markers.cpython-311.pyc b/server/map/__pycache__/get_markers.cpython-311.pyc index 465b8e596d1a8109ff12180b38c80096d6b4e58d..e0b4752477d0eafd895b1d8937cd74c85045d82a 100644 Binary files a/server/map/__pycache__/get_markers.cpython-311.pyc and b/server/map/__pycache__/get_markers.cpython-311.pyc differ diff --git a/server/map/__pycache__/get_relation.cpython-311.pyc b/server/map/__pycache__/get_relation.cpython-311.pyc index 664196b347f107025d30408fd41a62052110dbee..12b87d51b16f83f1ef4d1dc694a1692b02674d0f 100644 Binary files a/server/map/__pycache__/get_relation.cpython-311.pyc and b/server/map/__pycache__/get_relation.cpython-311.pyc differ diff --git a/server/map/__pycache__/input_new_data.cpython-311.pyc b/server/map/__pycache__/input_new_data.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd6d9570fddc887d26dcac27986f9c6d168eb713 Binary files /dev/null and b/server/map/__pycache__/input_new_data.cpython-311.pyc differ diff --git a/server/map/get_markers.py b/server/map/get_markers.py index deef58340d4e2f8c31243fc9a790b8d527bea8c2..6b777a4f3ae8af3df23e741504bdf1fdb839e34a 100644 --- a/server/map/get_markers.py +++ b/server/map/get_markers.py @@ -1,9 +1,10 @@ import json from math import pi, cos + # get_markers requests all marker data or valid markers, converts the data to json, and writes # the data to the response object -def get_all_markers(self, cursor, valid: bool, waterBodyName): +def get_all_markers(cursor, valid: bool, waterBodyName): try: sql_query = ''' SELECT m.MeasurementID, m.SensorID, m.TimeMeasured, m.CenterLat, m.CenterLon, @@ -63,7 +64,8 @@ def get_all_markers(self, cursor, valid: bool, waterBodyName): 'Active': bool(row[6]) }, 'Subdivisions': [sub_division], # Array of sub_division objects - 'Corners': calculate_corners(row[3], row[4]), # Return list of corners calculated based on center coordinates + 'Corners': calculate_corners(row[3], row[4]), + # Returns list of corners calculated based on center coordinates } # Convert dictionary values to list of measurements @@ -71,25 +73,16 @@ def get_all_markers(self, cursor, valid: bool, waterBodyName): if len(rows) == 0 or len(data) == 0: # Return 500 and empty list if no data is found print(f"Error in querying database") - resp_code = 500 marker_data = '[]' else: - resp_code = 200 # Convert list of dictionaries to JSON marker_data = json.dumps(data, indent=4) except Exception as e: print(f"Error in querying database: {e}") - resp_code = 500 marker_data = '[]' - # Set headers - self.send_response(resp_code) - self.send_header("Content-type", "application/json") - self.end_headers() - - # Write marker data to response object - self.wfile.write(marker_data.encode('utf-8')) + return marker_data EARTH = 6378.137 # Radius of the earth in kilometer diff --git a/server/map/get_relation.py b/server/map/get_relation.py index b96120ec9dc8234faa3c6467e23f664b8337eef9..4ffd04094bc1f0378e88bfb1be01e823b02f68cd 100644 --- a/server/map/get_relation.py +++ b/server/map/get_relation.py @@ -1,7 +1,8 @@ import string import json import geopandas as gpd -import matplotlib.pyplot as plt +from server.map.get_markers import get_all_markers +from shapely.geometry import Polygon, LineString, Point # get_relation returns the geojson data for a selected body of water @@ -16,7 +17,7 @@ def get_relation(self, body_of_water: string): geojson_dict = json.loads(polygon_data.to_json()) # Convert response data to JSON string - response_json = json.dumps(geojson_dict) + response_json = json.dumps(divide_relation(self, polygon_data)) # Set headers self.send_response(200) @@ -25,3 +26,56 @@ def get_relation(self, body_of_water: string): # Write coordinates to response object self.wfile.write(response_json.encode('utf-8')) + + +def divide_relation(self, polygon): + # Fetch measurements from database + measurements = get_all_markers(self.cursor, False, 'Mjosa') + + # Temporary hardcoded point at which relation is split, should be + splitting_points = [(60.6853, 10.9571), (60.7018, 11.1058)] + + # Lists to hold new polygons + divided_relation = [] + temp_seg_1 = [] + temp_seg_2 = [] + + # Loop through polygon coordinates and split at defined coordinates + for i in range(len(polygon)): + + closest_point = [] + + # Find the closest point on the polygon to the splitting point + for point in splitting_points: + closest_point = polygon.exterior.interpolate(polygon.exterior.project(Point(point)),normalized=True) + + # Check if the closest point is already in the polygon coordinates + if closest_point.coords[0] not in polygon: + # If not, add it to the polygon coordinates + polygon.append(closest_point.coords[0]) + # Add the splitting point (either the original or the closest) to the splitting points list + splitting_points.append(closest_point.coords[0]) + + current_point = polygon[i] + next_point = polygon[(i + 1) % len(polygon)] # Circular index + + # Check if the current segment crosses any splitting point + for splitting_point in splitting_points: + if (current_point != splitting_point and + next_point != splitting_point and + LineString([current_point, next_point]).intersects(Point(splitting_point))): + # Split the segment at the splitting point + temp_seg_1.append(current_point) + temp_seg_2.append(splitting_point) + temp_seg_1.append(splitting_point) + temp_seg_2.append(next_point) + break + else: + # If the segment doesn't cross any splitting point, add it to both lists + temp_seg_1.append(current_point) + temp_seg_2.append(current_point) + + # Return a list containing all the created polygons + divided_relation = [Polygon(temp_seg_1), Polygon(temp_seg_2)] + + return divided_relation