Skip to content
Snippets Groups Projects
Commit 4df57f00 authored by Sara Savanovic Djordjevic's avatar Sara Savanovic Djordjevic
Browse files

add: new lake, file_name implementation

parent 1edf35f0
No related branches found
No related tags found
1 merge request!12Clhp map
This commit is part of merge request !12. Comments created here will be created in the context of that merge request.
Showing
with 172 additions and 133 deletions
...@@ -13,7 +13,7 @@ Precompiled binaries can be found on https://www.sqlite.org/download.html. Extra ...@@ -13,7 +13,7 @@ Precompiled binaries can be found on https://www.sqlite.org/download.html. Extra
binary in a folder and note its path. Add the path to your system environment variables. Now you can binary in a folder and note its path. Add the path to your system environment variables. Now you can
manage the SQLite database. manage the SQLite database.
## Adding new maps ## Adding new lakes
The current server only contains the data for a single lake, Mjøsa. To add more lakes The current server only contains the data for a single lake, Mjøsa. To add more lakes
go to https://overpass-turbo.eu/. Once you have navigated to Overpass API, enter go to https://overpass-turbo.eu/. Once you have navigated to Overpass API, enter
the Overpass query below in the left field, but swap 'lakeName' out the Overpass query below in the left field, but swap 'lakeName' out
...@@ -29,12 +29,24 @@ press the 'Run' button. ...@@ -29,12 +29,24 @@ press the 'Run' button.
(._;>;); (._;>;);
out body; out body;
``` ```
![img.png](images/overpass-query.png)
![img.png](images/geojson-export.png)
If a text box saying "This query returned quite a lot of data (approx. x MB). Your browser may have a hard time trying to render this. Do you really want to continue? If a text box saying "This query returned quite a lot of data (approx. x MB). Your browser may have a hard time trying to render this. Do you really want to continue?
" appears, press 'continue anyway'. Double check that you have " appears, press 'continue anyway'. Double check that you have
the correct lake, then press 'Export'. In the 'Export' menu, download the shape data as the correct lake, then press 'Export'. In the 'Export' menu, download the shape data as
GeoJson. Once downloaded, name the file the *lakeName.json, and move the file into GeoJson. Once downloaded, name the file the *lakeName.json, and move the file into
IceMap/server/lake_relations. Once you have added the file, run map division... IceMap/server/lake_relations. Once you have added the file, run map division...
![img.png](images/geojson-file.png)
The result will be two new files named lakeName_centers.txt and lakeName_div.json. The original
lakeName.geojson file should also remain in the system. Additionally, the file named all_lake_names.json
should be updated to contain the newly added lake name.
![img.png](images/resulting-files.png)
## Endpoints ## Endpoints
## Bugs ## Bugs
......
...@@ -162,6 +162,16 @@ class _BarDataState extends State<BarData> { ...@@ -162,6 +162,16 @@ class _BarDataState extends State<BarData> {
reservedSize: 30, reservedSize: 30,
interval: 2, interval: 2,
), ),
topTitles: SideTitles(
showTitles: true,
getTextStyles: (value) => const TextStyle(color: Colors.white60),
margin: 0,
reservedSize: 10,
getTitles: (value) {
// Return "cm" for a specific value (e.g., 0) and empty string for others
return value == 0 ? 'cm' : '';
},
),
), ),
groupsSpace: 14, groupsSpace: 14,
gridData: FlGridData( gridData: FlGridData(
......
...@@ -258,51 +258,11 @@ class _MapContainerWidgetState extends State<MapContainerWidget> { ...@@ -258,51 +258,11 @@ class _MapContainerWidgetState extends State<MapContainerWidget> {
), ),
), ),
const SizedBox(height: contPadding*2.5), const SizedBox(height: contPadding*2.5),
SizedBox(
width: screenWidth * boxWidth * 1.2,
child: Center(
child: Text(
'Ice layers',
style: regTextStyleBig,
),
),
),
SizedBox( SizedBox(
width: screenWidth * boxWidth * 1.2, width: screenWidth * boxWidth * 1.2,
child: const StatCharts(), child: const StatCharts(),
), ),
const SizedBox(height: contPadding*2), const SizedBox(height: contPadding*4),
SizedBox(
width: screenWidth * boxWidth * 1.2,
child: Padding(
padding: const EdgeInsets.only(top: 20, left: 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
const Icon(
Icons.info,
color: Colors.white54,
),
const SizedBox(width: 10),
Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 15),
child: Text(
'There may be multiple layers of black ice and slush ice stacked'
' between the snow and the steel ice.',
style: regTextStyle,
),
),
),
],
),
],
),
),
),
const SizedBox(height: contPadding*2),
], ],
), ),
], ],
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'bar_graph/bar_data.dart'; import 'graph_data/bar_data.dart';
import '../../consts.dart';
class StatCharts extends StatelessWidget { class StatCharts extends StatelessWidget {
const StatCharts({Key? key}) : super(key: key); const StatCharts({Key? key}) : super(key: key);
...@@ -68,16 +69,34 @@ class StatCharts extends StatelessWidget { ...@@ -68,16 +69,34 @@ class StatCharts extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(
children: [ children: [
/*SizedBox( SizedBox(
width: MediaQuery.of(context).size.width * 0.8, // Set the width of the LineChart child: Center(
height: 200, child: Text(
child: buildLineChart(context), 'Ice layers',
),*/ style: regTextStyleBig,
const SizedBox(height: 20), ),
),
),
SizedBox( SizedBox(
width: MediaQuery.of(context).size.width-30, width: MediaQuery.of(context).size.width-30,
child: const BarData(), child: const BarData(),
), ),
/*
const SizedBox(height: 60),
SizedBox(
child: Center(
child: Text(
'Total ice thickness',
style: regTextStyleBig,
),
),
),
const SizedBox(height: 10),
SizedBox(
width: MediaQuery.of(context).size.width * 0.8, // Set the width of the LineChart
height: 200,
child: buildLineChart(context),
),*/
], ],
); );
} }
......
images/geojson-export.png

28.4 KiB

images/geojson-file.png

25.6 KiB

images/overpass-query.png

46 KiB

images/resulting-files.png

19.4 KiB

...@@ -63,8 +63,18 @@ class IceHTTP(BaseHTTPRequestHandler): ...@@ -63,8 +63,18 @@ class IceHTTP(BaseHTTPRequestHandler):
parsed_path = urlparse(self.path) parsed_path = urlparse(self.path)
query_params = parse_qs(parsed_path.query) query_params = parse_qs(parsed_path.query)
get_divided_map(self, 'Mjosa') # NB temp hardcoded value get_divided_map(self, 'Mjosa') # NB temp hardcoded value
elif self.path == '/divide_new_relation': elif self.path.startswith('/add_new_lake'):
cut_map(self, 'Mjosa') parsed_path = urlparse(self.path)
query_params = parse_qs(parsed_path.query)
lake_name = query_params.get('lake', [None])[0]
if lake_name is not None:
cut_map(self, lake_name)
else:
self.send_response(400)
self.send_header('Content-type', 'application/json')
self.end_headers()
def do_POST(self): def do_POST(self):
if self.path == '/new_lidar_data': if self.path == '/new_lidar_data':
input_new_Lidar_data(self, self.cursor, 1, 'Mjosa') # hardcoded body of water must change later input_new_Lidar_data(self, self.cursor, 1, 'Mjosa') # hardcoded body of water must change later
......
No preview for this file type
No preview for this file type
...@@ -10,9 +10,11 @@ from server.consts import LAKE_RELATIONS_PATH ...@@ -10,9 +10,11 @@ from server.consts import LAKE_RELATIONS_PATH
# Read a json file with relation data and send to response object # Read a json file with relation data and send to response object
def cut_map(self, body_of_water: str): # NB: implement body_of_water def cut_map(self, lake_name: str):
try:
# Read relation from GeoJson file and extract all polygons # Read relation from GeoJson file and extract all polygons
geo_data = gpd.read_file(LAKE_RELATIONS_PATH + "mjosa.geojson") geo_data = gpd.read_file(LAKE_RELATIONS_PATH + lake_name + ".geojson")
polygon_data = geo_data[geo_data['geometry'].geom_type == 'Polygon'] polygon_data = geo_data[geo_data['geometry'].geom_type == 'Polygon']
polygons = [Polygon(polygon.exterior) for polygon in polygon_data['geometry']] polygons = [Polygon(polygon.exterior) for polygon in polygon_data['geometry']]
...@@ -73,19 +75,27 @@ def cut_map(self, body_of_water: str): # NB: implement body_of_water ...@@ -73,19 +75,27 @@ def cut_map(self, body_of_water: str): # NB: implement body_of_water
'tile_count': sub_div_id, # Add the last subdivision ID as number of tiles 'tile_count': sub_div_id, # Add the last subdivision ID as number of tiles
} }
# NB currently hardcoded file path # Create a text file containing all subdivision ids and center coordinates
# Create the txt file specified by the path with open(LAKE_RELATIONS_PATH + lake_name + "_centers.txt", 'w') as file:
with open(LAKE_RELATIONS_PATH + "mjosa_centers.txt", 'w') as file:
# Iterate over the list and write each element to the file
for sub_div_id, x, y in sub_div_center_list: for sub_div_id, x, y in sub_div_center_list:
file.write(f"{sub_div_id}, {x}, {y}\n") # Write each list entry on a new line file.write(f"{sub_div_id}, {x}, {y}\n") # Write each list entry on a new line
write_json_to_file(lake_name, feature_collection)
self.send_response(200) self.send_response(200)
self.send_header("Content-type", "application/json") self.send_header("Content-type", "application/json")
self.end_headers() self.end_headers()
self.wfile.write(json.dumps(feature_collection).encode('utf-8')) self.wfile.write(json.dumps(feature_collection).encode('utf-8'))
except Exception as e:
print(f"Error in adding new map: {e}")
self.send_response(500)
self.send_header("Content-type", "application/json")
self.end_headers()
def create_grid(poly: Polygon, cell_width, cell_height): def create_grid(poly: Polygon, cell_width, cell_height):
# Retrieve bounds of the entire polygon # Retrieve bounds of the entire polygon
...@@ -127,27 +137,36 @@ def combine_grid_with_poly(polygon, grid): ...@@ -127,27 +137,36 @@ def combine_grid_with_poly(polygon, grid):
return intersecting_tiles return intersecting_tiles
def write_json_to_file(path: str, file_name: str, json_data: dict): def write_json_to_file(lake_name: str, json_data: dict):
# NB add lake name to 'added_lakes.txt' # Create and write divided map to new file
print("Writing to file...") print("Writing to file...")
if not os.path.exists(path): if not os.path.exists(LAKE_RELATIONS_PATH):
raise Exception("Directory from path does not exist") raise Exception("Directory from path does not exist")
with open(path + '/' + file_name + '_div.json', 'w') as f: with open(LAKE_RELATIONS_PATH + '/' + lake_name + '_div.json', 'w') as f:
json.dump(json_data, f) json.dump(json_data, f)
# Update all_system_lakes
with open(LAKE_RELATIONS_PATH + 'all_lake_names.json', 'r') as file:
data = json.load(file)
data.append(lake_name)
with open(LAKE_RELATIONS_PATH + 'all_lake_names.json', 'w') as file:
json.dump(data, file, indent=2)
def plot_map(divided_map): def plot_map(divided_map):
tiles = [gpd.GeoDataFrame(geometry=[tile]) for tile in divided_map] tiles = [gpd.GeoDataFrame(geometry=[tile]) for tile in divided_map]
print("Plotting... This may take some time...") print("Plotting... This may take some time...")
# NB test plot
fig, ax = plt.subplots() fig, ax = plt.subplots()
ax.set_aspect(1.5) ax.set_aspect(1.5)
# Plot each tile # Plot each tile
for tile in tiles: # NB temporarily limited to 5 tiles for tile in tiles:
random_color = "#{:06x}".format(random.randint(0, 0xFFFFFF)) random_color = "#{:06x}".format(random.randint(0, 0xFFFFFF))
gpd.GeoSeries(tile.geometry).plot(ax=ax, facecolor=random_color, edgecolor='none') gpd.GeoSeries(tile.geometry).plot(ax=ax, facecolor=random_color, edgecolor='none')
plt.show() plt.show()
...@@ -5,7 +5,7 @@ from datetime import datetime ...@@ -5,7 +5,7 @@ from datetime import datetime
# get_markers requests all marker data or valid markers, converts the data to json, and writes # get_markers requests all marker data or valid markers, converts the data to json, and writes
# the data to the response object # the data to the response object
def get_all_markers(self, cursor, waterBodyName): def get_all_markers(self, cursor, lake_name):
try: try:
sql_query = ''' sql_query = '''
SELECT m.MeasurementID, m.SensorID, m.TimeMeasured, m.CenterLat, m.CenterLon, SELECT m.MeasurementID, m.SensorID, m.TimeMeasured, m.CenterLat, m.CenterLon,
......
[ [
"Mjøsa", "Mj\u00c3\u00b8sa",
"Bogstadsvannet", "Bogstadsvannet",
"Einavatnet", "Einavatnet",
"Femsjøen", "Femsj\u00c3\u00b8en",
"Femunden", "Femunden",
"Fjellsjøen", "Fjellsj\u00c3\u00b8en",
"Gjende", "Gjende",
"Gjersjøen" "Gjersj\u00c3\u00b8en",
"skumsj\u00f8en"
] ]
\ No newline at end of file
This diff is collapsed.
0, 0.0217, 0.0112
1, 0.017, 0.02
2, 0.0008, 0.001
3, 0.0005, 0.0003
4, 0.0002, 0.0001
5, 0.0004, 0.0002
6, 0.0004, 0.0004
7, 0.0003, 0.0002
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment