Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
PROG2900
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Sara Savanovic Djordjevic
PROG2900
Commits
700b2e63
Commit
700b2e63
authored
10 months ago
by
Sara Savanovic Djordjevic
Browse files
Options
Downloads
Patches
Plain Diff
add: comments and docstrings to add_new_lake.py
parent
be979927
No related branches found
Branches containing commit
No related tags found
1 merge request
!14
Clhp map
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
app/lib/server_requests/init_state.dart
+0
-1
0 additions, 1 deletion
app/lib/server_requests/init_state.dart
server/map_handler/add_new_lake.py
+78
-15
78 additions, 15 deletions
server/map_handler/add_new_lake.py
with
78 additions
and
16 deletions
app/lib/server_requests/init_state.dart
+
0
−
1
View file @
700b2e63
...
...
@@ -14,7 +14,6 @@ import '../server_requests/fetch_relation.dart';
/// and the last requesting the list of all system lakes
Future
<
void
>
initialiseState
(
bool
fetchSearchOptions
)
async
{
bool
serverConnection
=
true
;
bool
internetConnection
=
false
;
late
Future
<
List
<
Measurement
>>
markerListFuture
;
late
Future
<
Uint8List
>
relationFuture
;
...
...
This diff is collapsed.
Click to expand it.
server/map_handler/add_new_lake.py
+
78
−
15
View file @
700b2e63
...
...
@@ -25,9 +25,18 @@ lng = (distance_in_km × 360)/(40075km × cos(lat))
# Read a json file with relation data and send to response object
def
cut_map
(
self
,
cursor
,
lake_name
:
str
,
dist_in_km
=
0.5
):
def
cut_map
(
self
,
cursor
,
lake_name
:
str
,
cell_size_in_km
=
0.5
):
"""
Cuts a map into a grid based on a selected cell size
Parameters:
self (BaseHTTPRequestHandler): A instance of a BaseHTTPRequestHandler
cursor (cursor): An Sqlite3 cursor object that points to the database
lake_name (str): The name of the lake to be cut
cell_size_in_km (float): The selected cell size in kilometers
"""
try
:
# Read relation from GeoJson file and extract all
p
olygon
s
# Read relation from GeoJson file and extract all
geometry of type P
olygon
geo_data
=
gpd
.
read_file
(
LAKE_RELATIONS_PATH
+
lake_name
+
"
.geojson
"
)
polygon_data
=
geo_data
[
geo_data
[
'
geometry
'
].
geom_type
==
'
Polygon
'
]
polygons
=
[
Polygon
(
polygon
.
exterior
)
for
polygon
in
polygon_data
[
'
geometry
'
]]
...
...
@@ -35,26 +44,35 @@ def cut_map(self, cursor, lake_name: str, dist_in_km=0.5):
if
len
(
polygons
)
<=
1
:
raise
Exception
(
"
Failed to convert JSON object to Shapely Polygons
"
)
# List to store all the map tiles
divided_map
=
[]
cell_size
=
dist_in_km
*
10
# Convert the cell size to degrees
cell_size
=
cell_size_in_km
*
10
cell_width
=
cell_size
/
111.32
# A slightly more complicated formula is required to calculate the height to ensure that
# the height in km is equal to the width in km regardless of the latitude.
cell_height
=
(
cell_size
*
360
)
/
(
40075
*
cos
(
cell_width
))
# Process all polygons
for
polygon
in
polygons
:
# Generate a grid based on the calculated cell size
lines
=
create_grid
(
polygon
,
cell_width
,
cell_height
)
lines
.
append
(
polygon
.
boundary
)
# Merge the grid lines into a single grid object
lines
=
unary_union
(
lines
)
lines
=
linemerge
(
lines
)
lines
=
list
(
polygonize
(
lines
))
# Divide the polygon into tiles based on the generated grid
divided_map
.
extend
(
combine_grid_with_poly
(
polygon
,
lines
))
# List to store new GeoJSON feature objects
features
=
[]
# Create subdivisions for each map tile
sub_div_id
=
0
for
tile
in
divided_map
:
# Calculate tile center based on bounds, and round down to two decimals
min_x
,
min_y
,
max_x
,
max_y
=
tile
.
bounds
center
=
round
(
max_y
-
(
max_y
-
min_y
),
6
),
round
(
max_x
-
(
max_x
-
min_x
),
6
)
...
...
@@ -66,6 +84,7 @@ def cut_map(self, cursor, lake_name: str, dist_in_km=0.5):
rounded_coordinates
.
append
(
rounded_coords
)
rounded_tile
=
Polygon
(
rounded_coordinates
)
# Create new feature object
tile_feature
=
{
'
type
'
:
'
Feature
'
,
'
properties
'
:
{
...
...
@@ -74,9 +93,11 @@ def cut_map(self, cursor, lake_name: str, dist_in_km=0.5):
},
'
geometry
'
:
rounded_tile
.
__geo_interface__
}
# Append new feature oject to list, and increment sub_div_id for next iteration
features
.
append
(
tile_feature
)
sub_div_id
+=
1
# Create new GeoJSON object containing all the new feature objects
feature_collection
=
{
'
type
'
:
'
FeatureCollection
'
,
'
features
'
:
features
,
...
...
@@ -95,10 +116,11 @@ def cut_map(self, cursor, lake_name: str, dist_in_km=0.5):
INSERT INTO BodyOfWater(Name) VALUES (?);
'''
,
(
lake_name
,))
# Plot the newly created map and save it to a new file
plot_map
(
divided_map
)
write_json_to_file
(
lake_name
,
feature_collection
)
# Return the map to the response object
self
.
send_response
(
200
)
self
.
send_header
(
"
Content-type
"
,
"
application/json
"
)
self
.
end_headers
()
...
...
@@ -113,21 +135,33 @@ def cut_map(self, cursor, lake_name: str, dist_in_km=0.5):
self
.
end_headers
()
def
create_grid
(
poly
:
Polygon
,
cell_width
,
cell_height
):
def
create_grid
(
poly
:
Polygon
,
cell_width
:
float
,
cell_height
:
float
):
"""
Returns a list of vertical and horizontal LineStrings that create a grid.
Parameters:
poly (Polygon): A Shapely Polygon representing a map or part of a map
cell_width (float): The width of the grid cells in degrees
cell_height (float): The height of the grid cells in degrees
Returns:
grid_lines (list): List of LineString objects defining the grid
"""
# Retrieve bounds of the entire polygon
bounds
=
poly
.
bounds
min_x
,
min_y
,
max_x
,
max_y
=
bounds
# List to store all created lines
grid_lines
=
[]
#
H
orizontal lines
#
Create new h
orizontal lines
while within bounds
y
=
min_y
while
y
<=
max_y
:
line
=
LineString
([(
min_x
,
y
),
(
max_x
,
y
)])
grid_lines
.
append
(
line
)
y
+=
cell_height
#
V
ertical lines
#
Create new v
ertical lines
while within bounds
x
=
min_x
while
x
<=
max_x
:
line
=
LineString
([(
x
,
min_y
),
(
x
,
max_y
)])
...
...
@@ -138,6 +172,17 @@ def create_grid(poly: Polygon, cell_width, cell_height):
def
combine_grid_with_poly
(
polygon
,
grid
):
"""
Returns a list of polygons that together make up map tiles.
Parameters:
polygon (Polygon): A polygon representing a map or part of a map
grid (list): List of LineString objects defining the grid
Returns:
intersecting_tiles (list): List of Polygons
"""
# List to contain all the tiles
intersecting_tiles
=
[]
for
line
in
grid
:
...
...
@@ -153,24 +198,32 @@ def combine_grid_with_poly(polygon, grid):
return
intersecting_tiles
def
write_json_to_file
(
lake_name
:
str
,
json_data
:
dict
):
def
write_json_to_file
(
lake_name
:
str
,
map_data
:
dict
):
"""
Writes a divided map to a JSON file and updates all_lake_names.json
Parameters:
lake_name (str): Name of the lake and file to write to
map_data (dict): List of map polygons converted to a JSON dictionary
"""
# Create and write divided map to new file
print
(
"
Writing to file...
"
)
if
not
os
.
path
.
exists
(
LAKE_RELATIONS_PATH
):
raise
Exception
(
"
Directory from path does not exist
"
)
with
open
(
LAKE_RELATIONS_PATH
+
'
/
'
+
lake_name
+
'
_div.json
'
,
'
w
'
)
as
f
:
json
.
dump
(
json
_data
,
f
)
json
.
dump
(
map
_data
,
f
)
#
Update
all_system_lakes
#
Read
all_system_lakes
.json
with
open
(
LAKE_RELATIONS_PATH
+
'
all_lake_names.json
'
,
'
r
'
)
as
file
:
data
=
json
.
load
(
file
)
# Check if the lake name exists in the list
if
lake_name
not
in
data
:
data
.
append
(
lake_name
)
data
.
append
(
lake_name
)
# Only append to list if it does not already exist
# Update all_lake_names.json with new lake name
with
open
(
LAKE_RELATIONS_PATH
+
'
all_lake_names.json
'
,
'
w
'
)
as
file
:
# json.dump(data, file, indent=2)
json
.
dump
(
data
,
file
,
ensure_ascii
=
False
,
indent
=
2
)
...
...
@@ -178,16 +231,26 @@ def write_json_to_file(lake_name: str, json_data: dict):
# subdivisions. Removing calls to plot_map will speed up the process, but it is recommended to plot the map
# after each division to ensure that the map was divided as intended.
def
plot_map
(
divided_map
):
tiles
=
[
gpd
.
GeoDataFrame
(
geometry
=
[
tile
])
for
tile
in
divided_map
]
"""
Plots a divided map using matplotlib.
Parameters:
divided_map (list): List of Shapely Polygons
"""
print
(
"
Plotting... This may take some time...
"
)
# Convert Polygon objects to GeoDataFrames
tiles
=
[
gpd
.
GeoDataFrame
(
geometry
=
[
tile
])
for
tile
in
divided_map
]
# Configure plot settings
fig
,
ax
=
plt
.
subplots
()
ax
.
set_aspect
(
1.5
)
# Plot each tile
for
tile
in
tiles
:
# Give each tile a random color to clearly visualize the grid
random_color
=
"
#{:06x}
"
.
format
(
random
.
randint
(
0
,
0xFFFFFF
))
gpd
.
GeoSeries
(
tile
.
geometry
).
plot
(
ax
=
ax
,
facecolor
=
random_color
,
edgecolor
=
'
none
'
)
# Display plot
plt
.
show
()
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment