YashMK89's picture
Update app.py
840b26e verified
# import streamlit as st
# import geopandas as gpd
# from shapely.geometry import Point
# import folium
# from streamlit_folium import st_folium
# from geopy.geocoders import Nominatim
# import tempfile
# import os
# import zipfile
# # Configure page
# st.set_page_config(page_title="City Shapefile Generator", layout="wide")
# st.title("🌍 City Location Exporter")
# # Initialize geocoder
# geolocator = Nominatim(user_agent="city_shape_app")
# def get_city_location(city_name):
# """Get coordinates for a city name"""
# location = geolocator.geocode(city_name)
# if location:
# return location.latitude, location.longitude
# return None
# def create_geodataframe(lat, lon, city_name):
# """Create a GeoDataFrame from coordinates"""
# geometry = Point(lon, lat)
# return gpd.GeoDataFrame(
# [[city_name, lat, lon, geometry]],
# columns=["city", "latitude", "longitude", "geometry"],
# crs="EPSG:4326"
# )
# def create_map(lat, lon, city_name):
# """Create Folium map with marker"""
# m = folium.Map(location=[lat, lon], zoom_start=12)
# folium.Marker(
# [lat, lon],
# popup=city_name,
# tooltip=city_name,
# icon=folium.Icon(color="red", icon="info-sign")
# ).add_to(m)
# folium.CircleMarker(
# [lat, lon],
# radius=100,
# color='blue',
# fill=True,
# fill_color='blue'
# ).add_to(m)
# return m
# def save_to_format(gdf, format_type, temp_dir, city_name):
# """Save to specific format and return file path"""
# base_path = os.path.join(temp_dir, f"{city_name}_location")
# if format_type == "SHP":
# full_path = f"{base_path}.shp"
# gdf.to_file(full_path)
# return [f"{base_path}.{ext}" for ext in ["shp", "shx", "dbf", "prj", "cpg"]]
# elif format_type == "GeoJSON":
# full_path = f"{base_path}.geojson"
# gdf.to_file(full_path, driver='GeoJSON')
# return [full_path]
# elif format_type == "KML":
# full_path = f"{base_path}.kml"
# gdf.to_file(full_path, driver='KML')
# return [full_path]
# def create_download_button(file_paths, format_type, city_name):
# """Create a download button for the files"""
# if format_type == "SHP":
# zip_path = f"{city_name}_shapefile.zip"
# with zipfile.ZipFile(zip_path, 'w') as zipf:
# for file in file_paths:
# if os.path.exists(file):
# zipf.write(file, os.path.basename(file))
# with open(zip_path, 'rb') as f:
# return st.download_button(
# label=f"Download {format_type}",
# data=f,
# file_name=zip_path,
# mime="application/zip",
# key=f"{city_name}_shp" # Unique key for each button
# )
# else:
# with open(file_paths[0], 'rb') as f:
# return st.download_button(
# label=f"Download {format_type}",
# data=f,
# file_name=os.path.basename(file_paths[0]),
# mime="application/octet-stream",
# key=f"{city_name}_{format_type.lower()}"
# )
# # Main app
# city_name = st.text_input("Enter city name:", "Paris")
# if 'coords' not in st.session_state:
# st.session_state.coords = None
# if 'city_found' not in st.session_state:
# st.session_state.city_found = None
# if st.button("Locate City"):
# with st.spinner("Searching location..."):
# coords = get_city_location(city_name)
# st.session_state.coords = coords
# st.session_state.city_found = city_name
# if st.session_state.coords:
# lat, lon = st.session_state.coords
# st.success(f"Found {st.session_state.city_found} at coordinates: {lat:.4f}, {lon:.4f}")
# # Display persistent map
# m = create_map(lat, lon, st.session_state.city_found)
# st_folium(m, width=800, height=500)
# # Create GeoDataFrame
# gdf = create_geodataframe(lat, lon, st.session_state.city_found)
# # Persistent download buttons
# st.header("Download Options")
# col1, col2, col3 = st.columns(3)
# with tempfile.TemporaryDirectory() as temp_dir:
# # Shapefile
# with col1:
# shp_files = save_to_format(gdf, "SHP", temp_dir, st.session_state.city_found)
# create_download_button(shp_files, "SHP", st.session_state.city_found)
# # GeoJSON
# with col2:
# geojson_file = save_to_format(gdf, "GeoJSON", temp_dir, st.session_state.city_found)
# create_download_button(geojson_file, "GeoJSON", st.session_state.city_found)
# # KML
# with col3:
# kml_file = save_to_format(gdf, "KML", temp_dir, st.session_state.city_found)
# create_download_button(kml_file, "KML", st.session_state.city_found)
# elif st.session_state.city_found and not st.session_state.coords:
# st.error("City not found. Please try a different name.")
import streamlit as st
import geopandas as gpd
import folium
from streamlit_folium import st_folium
import tempfile
import os
import zipfile
import osmnx as ox
from shapely.geometry import Polygon
# Configure page
st.set_page_config(page_title="City Boundary Exporter", layout="wide")
st.title("πŸŒ† City Boundary Exporter")
def get_city_boundary(city_name):
"""Get city boundary polygon from OpenStreetMap"""
try:
# Get the boundary geometry
gdf = ox.geocode_to_gdf(city_name)
# Simplify geometry if too complex
if gdf.shape[0] > 0:
gdf['geometry'] = gdf['geometry'].simplify(0.001)
return gdf
return None
except Exception as e:
st.error(f"Error fetching boundary: {str(e)}")
return None
def create_map(gdf):
"""Create Folium map with the boundary"""
centroid = gdf.geometry.centroid.iloc[0]
m = folium.Map(location=[centroid.y, centroid.x], zoom_start=11)
folium.GeoJson(
gdf.__geo_interface__,
style_function=lambda x: {
'fillColor': '#1f77b4',
'color': '#1f77b4',
'weight': 2,
'fillOpacity': 0.4
}
).add_to(m)
# Add centroid marker
folium.Marker(
[centroid.y, centroid.x],
popup="Centroid",
icon=folium.Icon(color="red")
).add_to(m)
return m
def save_to_format(gdf, format_type, temp_dir, city_name):
"""Save to specific format and return file path"""
base_path = os.path.join(temp_dir, f"{city_name}_boundary")
if format_type == "SHP":
full_path = f"{base_path}.shp"
gdf.to_file(full_path)
return [f"{base_path}.{ext}" for ext in ["shp", "shx", "dbf", "prj", "cpg"]]
elif format_type == "GeoJSON":
full_path = f"{base_path}.geojson"
gdf.to_file(full_path, driver='GeoJSON')
return [full_path]
elif format_type == "KML":
full_path = f"{base_path}.kml"
gdf.to_file(full_path, driver='KML')
return [full_path]
def create_download_button(file_paths, format_type, city_name):
"""Create a download button for the files"""
if format_type == "SHP":
zip_path = f"{city_name}_boundary.zip"
with zipfile.ZipFile(zip_path, 'w') as zipf:
for file in file_paths:
if os.path.exists(file):
zipf.write(file, os.path.basename(file))
with open(zip_path, 'rb') as f:
st.download_button(
label=f"Download {format_type}",
data=f,
file_name=zip_path,
mime="application/zip",
key=f"{city_name}_shp"
)
else:
with open(file_paths[0], 'rb') as f:
st.download_button(
label=f"Download {format_type}",
data=f,
file_name=os.path.basename(file_paths[0]),
mime="application/octet-stream",
key=f"{city_name}_{format_type.lower()}"
)
# Main app
city_name = st.text_input("Enter city name (include country if needed):", "Berlin, Germany")
if st.button("Get City Boundary"):
with st.spinner("Fetching boundary from OpenStreetMap..."):
boundary_gdf = get_city_boundary(city_name)
if boundary_gdf is not None:
st.session_state.boundary_gdf = boundary_gdf
st.session_state.city_found = city_name
if 'boundary_gdf' in st.session_state:
st.success(f"Found boundary for {st.session_state.city_found}")
# Display map
m = create_map(st.session_state.boundary_gdf)
st_folium(m, width=800, height=500)
# Download options
st.header("Download Options")
col1, col2, col3 = st.columns(3)
with tempfile.TemporaryDirectory() as temp_dir:
# Shapefile
with col1:
shp_files = save_to_format(st.session_state.boundary_gdf, "SHP", temp_dir, st.session_state.city_found)
create_download_button(shp_files, "SHP", st.session_state.city_found)
# GeoJSON
with col2:
geojson_file = save_to_format(st.session_state.boundary_gdf, "GeoJSON", temp_dir, st.session_state.city_found)
create_download_button(geojson_file, "GeoJSON", st.session_state.city_found)
# KML
with col3:
kml_file = save_to_format(st.session_state.boundary_gdf, "KML", temp_dir, st.session_state.city_found)
create_download_button(kml_file, "KML", st.session_state.city_found)