Spaces:
Runtime error
Runtime error
updated area estimates
Browse files- pag/add_field.py +56 -28
pag/add_field.py
CHANGED
|
@@ -8,9 +8,13 @@ from folium.plugins import Draw
|
|
| 8 |
from shapely.geometry import Polygon
|
| 9 |
from streamlit_folium import st_folium
|
| 10 |
from authentication import greeting, check_password
|
| 11 |
-
import shapely.ops as ops
|
| 12 |
from functools import partial
|
| 13 |
-
import pyproj
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
def check_authentication():
|
| 16 |
if not check_password():
|
|
@@ -18,7 +22,18 @@ def check_authentication():
|
|
| 18 |
|
| 19 |
|
| 20 |
|
|
|
|
|
|
|
|
|
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
def display_existing_fields(current_user):
|
| 24 |
with st.expander("Existing Fields", expanded=False):
|
|
@@ -30,17 +45,28 @@ def display_existing_fields(current_user):
|
|
| 30 |
else:
|
| 31 |
st.info("No Fields Added Yet!")
|
| 32 |
|
| 33 |
-
def add_existing_fields_to_map(
|
| 34 |
if os.path.exists(f"fields_{current_user}.parquet"):
|
| 35 |
-
fg = folium.FeatureGroup(name="Existing Fields", control=True).add_to(
|
| 36 |
gdf = gpd.read_parquet(f"fields_{current_user}.parquet")
|
| 37 |
for i, row in gdf.iterrows():
|
| 38 |
edges = row['geometry'].exterior.coords.xy
|
| 39 |
edges = [[i[1], i[0]] for i in zip(*edges)]
|
| 40 |
folium.Polygon(edges, color='blue', fill=True, fill_color='blue', fill_opacity=0.6).add_to(fg)
|
| 41 |
-
return
|
| 42 |
|
| 43 |
def get_center_of_existing_fields(current_user):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
if os.path.exists(f"fields_{current_user}.parquet"):
|
| 45 |
gdf = gpd.read_parquet(f"fields_{current_user}.parquet")
|
| 46 |
edges = gdf['geometry'][0].exterior.coords.xy
|
|
@@ -50,14 +76,14 @@ def get_center_of_existing_fields(current_user):
|
|
| 50 |
return edges_center
|
| 51 |
return [15.572363674301132, 32.69167103104079]
|
| 52 |
|
| 53 |
-
def display_map_and_drawing_controls(
|
| 54 |
zoom_start = 13
|
| 55 |
if st.session_state['active_drawing'] is None:
|
| 56 |
st.info("IMPORTANT: Click on the drawing to confirm the drawn field", icon="🚨")
|
| 57 |
sat_basemap = utils.basemaps['Google Satellite Hybrid'] # Change this line to use 'Google Satellite Hybrid'
|
| 58 |
-
sat_basemap.add_to(
|
| 59 |
-
folium.LayerControl().add_to(
|
| 60 |
-
output = st_folium(
|
| 61 |
active_drawing = output['last_active_drawing']
|
| 62 |
st.session_state['active_drawing'] = active_drawing
|
| 63 |
return False
|
|
@@ -136,9 +162,9 @@ def check_intersection_with_existing_fields(active_drawing, current_user):
|
|
| 136 |
if geom1.overlaps(geom2).any():
|
| 137 |
st.warning("Field intersects with existing fields. Please draw again!")
|
| 138 |
with st.expander("Intersecting Fields", expanded=False):
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
st_folium(
|
| 142 |
return True
|
| 143 |
return False
|
| 144 |
|
|
@@ -147,21 +173,23 @@ def check_intersection_with_existing_fields(active_drawing, current_user):
|
|
| 147 |
def check_polygon_area_within_range(active_drawing, min_area_km2=1, max_area_km2=10):
|
| 148 |
if active_drawing is None:
|
| 149 |
return
|
|
|
|
|
|
|
| 150 |
edges = [[i[0], i[1]] for i in active_drawing['geometry']['coordinates'][0]]
|
| 151 |
geom = Polygon(edges)
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
if geom_area < min_area_km2:
|
| 160 |
-
st.warning(f"Field area is less than {min_area_km2} km2. Please draw again!")
|
| 161 |
return False
|
| 162 |
-
if
|
| 163 |
-
st.warning(f"Field area is more than {max_area_km2} km2. Please draw again!")
|
| 164 |
return False
|
|
|
|
|
|
|
| 165 |
return True
|
| 166 |
|
| 167 |
|
|
@@ -170,18 +198,18 @@ def add_drawing():
|
|
| 170 |
current_user = greeting("Drag and Zoom and draw your fields on the map, make sure to name them uniquely")
|
| 171 |
current_user = st.session_state['current_user']
|
| 172 |
display_existing_fields(current_user)
|
| 173 |
-
|
| 174 |
center_start = get_center_of_existing_fields(current_user)
|
| 175 |
zoom_start = 13
|
| 176 |
-
|
|
|
|
| 177 |
|
| 178 |
draw_options = {'polyline': False, 'polygon': True, 'rectangle': True, 'circle': False, 'marker': False, 'circlemarker': False}
|
| 179 |
-
Draw(export=True, draw_options=draw_options).add_to(
|
| 180 |
-
|
| 181 |
|
| 182 |
|
| 183 |
|
| 184 |
-
captured = display_map_and_drawing_controls(
|
| 185 |
if captured:
|
| 186 |
intersects = check_intersection_with_existing_fields(st.session_state['active_drawing'], current_user)
|
| 187 |
within_area = check_polygon_area_within_range(st.session_state['active_drawing'])
|
|
|
|
| 8 |
from shapely.geometry import Polygon
|
| 9 |
from streamlit_folium import st_folium
|
| 10 |
from authentication import greeting, check_password
|
| 11 |
+
# import shapely.ops as ops
|
| 12 |
from functools import partial
|
| 13 |
+
# import pyproj
|
| 14 |
+
from pyproj import Transformer
|
| 15 |
+
from shapely.ops import transform
|
| 16 |
+
from geopy.geocoders import Nominatim
|
| 17 |
+
from streamlit_folium import folium_static
|
| 18 |
|
| 19 |
def check_authentication():
|
| 20 |
if not check_password():
|
|
|
|
| 22 |
|
| 23 |
|
| 24 |
|
| 25 |
+
# Function to get coordinates from a location name
|
| 26 |
+
def get_location_coordinates(location_name):
|
| 27 |
+
geolocator = Nominatim(user_agent="geoapiExercises")
|
| 28 |
|
| 29 |
+
try:
|
| 30 |
+
location = geolocator.geocode(location_name)
|
| 31 |
+
if location:
|
| 32 |
+
return location.latitude, location.longitude
|
| 33 |
+
else:
|
| 34 |
+
return None, None
|
| 35 |
+
except:
|
| 36 |
+
return None, None
|
| 37 |
|
| 38 |
def display_existing_fields(current_user):
|
| 39 |
with st.expander("Existing Fields", expanded=False):
|
|
|
|
| 45 |
else:
|
| 46 |
st.info("No Fields Added Yet!")
|
| 47 |
|
| 48 |
+
def add_existing_fields_to_map(field_map, current_user):
|
| 49 |
if os.path.exists(f"fields_{current_user}.parquet"):
|
| 50 |
+
fg = folium.FeatureGroup(name="Existing Fields", control=True).add_to(field_map)
|
| 51 |
gdf = gpd.read_parquet(f"fields_{current_user}.parquet")
|
| 52 |
for i, row in gdf.iterrows():
|
| 53 |
edges = row['geometry'].exterior.coords.xy
|
| 54 |
edges = [[i[1], i[0]] for i in zip(*edges)]
|
| 55 |
folium.Polygon(edges, color='blue', fill=True, fill_color='blue', fill_opacity=0.6).add_to(fg)
|
| 56 |
+
return field_map
|
| 57 |
|
| 58 |
def get_center_of_existing_fields(current_user):
|
| 59 |
+
location_name = st.text_input('Enter a location to search:')
|
| 60 |
+
if location_name:
|
| 61 |
+
lat, lon = get_location_coordinates(location_name)
|
| 62 |
+
if lat is not None and lon is not None:
|
| 63 |
+
# Update your map to center on the search result and adjust zoom as desired
|
| 64 |
+
m = folium.Map(location=[lat, lon], zoom_start=13)
|
| 65 |
+
# Add the map to the Streamlit app
|
| 66 |
+
# st_data = folium_static(m)
|
| 67 |
+
return [lat, lon]
|
| 68 |
+
else:
|
| 69 |
+
st.error('Location not found. Please try again.')
|
| 70 |
if os.path.exists(f"fields_{current_user}.parquet"):
|
| 71 |
gdf = gpd.read_parquet(f"fields_{current_user}.parquet")
|
| 72 |
edges = gdf['geometry'][0].exterior.coords.xy
|
|
|
|
| 76 |
return edges_center
|
| 77 |
return [15.572363674301132, 32.69167103104079]
|
| 78 |
|
| 79 |
+
def display_map_and_drawing_controls(field_map, center_start):
|
| 80 |
zoom_start = 13
|
| 81 |
if st.session_state['active_drawing'] is None:
|
| 82 |
st.info("IMPORTANT: Click on the drawing to confirm the drawn field", icon="🚨")
|
| 83 |
sat_basemap = utils.basemaps['Google Satellite Hybrid'] # Change this line to use 'Google Satellite Hybrid'
|
| 84 |
+
sat_basemap.add_to(field_map)
|
| 85 |
+
folium.LayerControl().add_to(field_map)
|
| 86 |
+
output = st_folium(field_map, center=center_start, zoom=zoom_start, key="new", width=800)
|
| 87 |
active_drawing = output['last_active_drawing']
|
| 88 |
st.session_state['active_drawing'] = active_drawing
|
| 89 |
return False
|
|
|
|
| 162 |
if geom1.overlaps(geom2).any():
|
| 163 |
st.warning("Field intersects with existing fields. Please draw again!")
|
| 164 |
with st.expander("Intersecting Fields", expanded=False):
|
| 165 |
+
field_map = geom1.explore(name= "New Field", color="red")
|
| 166 |
+
field_map = gdf.explore(m=field_map, name="Existing Fields", color="blue")
|
| 167 |
+
st_folium(field_map)
|
| 168 |
return True
|
| 169 |
return False
|
| 170 |
|
|
|
|
| 173 |
def check_polygon_area_within_range(active_drawing, min_area_km2=1, max_area_km2=10):
|
| 174 |
if active_drawing is None:
|
| 175 |
return
|
| 176 |
+
transformer = Transformer.from_crs("EPSG:4326", "EPSG:6933", always_xy=True)
|
| 177 |
+
|
| 178 |
edges = [[i[0], i[1]] for i in active_drawing['geometry']['coordinates'][0]]
|
| 179 |
geom = Polygon(edges)
|
| 180 |
+
transformed_geom = transform(transformer.transform, geom)
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
area_km2 = transformed_geom.area / 10**6
|
| 184 |
+
|
| 185 |
+
if area_km2 < min_area_km2:
|
| 186 |
+
st.warning(f"Field area {area_km2} is less than {min_area_km2} km2. Please draw again!")
|
|
|
|
|
|
|
| 187 |
return False
|
| 188 |
+
if area_km2 > max_area_km2:
|
| 189 |
+
st.warning(f"Field area {TRUNC(area_km2,3)} is more than {max_area_km2} km2. Please draw again!")
|
| 190 |
return False
|
| 191 |
+
st.success(f"Field area is {TRUNC(area_km2,3} km2, now give it a unique name {st.session_state['current_user']} !")
|
| 192 |
+
|
| 193 |
return True
|
| 194 |
|
| 195 |
|
|
|
|
| 198 |
current_user = greeting("Drag and Zoom and draw your fields on the map, make sure to name them uniquely")
|
| 199 |
current_user = st.session_state['current_user']
|
| 200 |
display_existing_fields(current_user)
|
|
|
|
| 201 |
center_start = get_center_of_existing_fields(current_user)
|
| 202 |
zoom_start = 13
|
| 203 |
+
field_map = folium.Map(location=center_start, zoom_start=zoom_start)
|
| 204 |
+
|
| 205 |
|
| 206 |
draw_options = {'polyline': False, 'polygon': True, 'rectangle': True, 'circle': False, 'marker': False, 'circlemarker': False}
|
| 207 |
+
Draw(export=True, draw_options=draw_options).add_to(field_map)
|
| 208 |
+
field_map = add_existing_fields_to_map(field_map, current_user)
|
| 209 |
|
| 210 |
|
| 211 |
|
| 212 |
+
captured = display_map_and_drawing_controls(field_map, center_start)
|
| 213 |
if captured:
|
| 214 |
intersects = check_intersection_with_existing_fields(st.session_state['active_drawing'], current_user)
|
| 215 |
within_area = check_polygon_area_within_range(st.session_state['active_drawing'])
|