Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import geopandas as gpd | |
| import folium | |
| import zipfile | |
| import tempfile | |
| import os | |
| from streamlit_folium import st_folium | |
| from shapely.geometry import LineString | |
| st.set_page_config(page_title="GIS Viewer", layout="wide") | |
| st.title("πΊοΈ GIS Viewer with Connected Points") | |
| st.markdown("Upload a GeoJSON, KMZ, or zipped Shapefile. This app will connect every 2 consecutive points with a solid line.") | |
| uploaded_file = st.file_uploader("Upload GeoJSON, KMZ or zipped Shapefile", type=["geojson", "zip", "kmz"]) | |
| def load_geodata(file): | |
| ext = file.name.lower() | |
| with tempfile.TemporaryDirectory() as tmpdir: | |
| if ext.endswith(".geojson"): | |
| gdf = gpd.read_file(file) | |
| elif ext.endswith(".zip"): | |
| with zipfile.ZipFile(file, "r") as z: | |
| z.extractall(tmpdir) | |
| shp_files = [f for f in os.listdir(tmpdir) if f.endswith(".shp")] | |
| if not shp_files: | |
| raise Exception("No .shp file found in ZIP.") | |
| gdf = gpd.read_file(os.path.join(tmpdir, shp_files[0])) | |
| elif ext.endswith(".kmz"): | |
| with zipfile.ZipFile(file, "r") as z: | |
| z.extractall(tmpdir) | |
| kml_files = [f for f in os.listdir(tmpdir) if f.endswith(".kml")] | |
| if not kml_files: | |
| raise Exception("No .kml file found inside KMZ.") | |
| gdf = gpd.read_file(os.path.join(tmpdir, kml_files[0])) | |
| else: | |
| raise Exception("Unsupported file format.") | |
| if gdf.crs and gdf.crs.to_epsg() != 4326: | |
| gdf = gdf.to_crs(epsg=4326) | |
| return gdf | |
| def create_lines_from_points(points_gdf): | |
| lines = [] | |
| for i in range(0, len(points_gdf) - 1, 2): | |
| p1 = points_gdf.iloc[i].geometry | |
| p2 = points_gdf.iloc[i+1].geometry | |
| if p1.geom_type == "Point" and p2.geom_type == "Point": | |
| line = LineString([p1, p2]) | |
| lines.append({"geometry": line}) | |
| return gpd.GeoDataFrame(lines, geometry="geometry", crs="EPSG:4326") | |
| if uploaded_file: | |
| try: | |
| with st.spinner("Processing file..."): | |
| gdf = load_geodata(uploaded_file) | |
| st.success("File loaded successfully!") | |
| # Filter only points | |
| point_gdf = gdf[gdf.geometry.type == "Point"].reset_index(drop=True) | |
| line_gdf = create_lines_from_points(point_gdf) | |
| # Map setup | |
| center = gdf.geometry.unary_union.centroid | |
| m = folium.Map(location=[center.y, center.x], zoom_start=10) | |
| folium.GeoJson(gdf, name="Features", | |
| tooltip=folium.GeoJsonTooltip(fields=gdf.columns[:3].tolist())).add_to(m) | |
| # Add lines between points | |
| folium.GeoJson(line_gdf, name="Lines Between Points", | |
| style_function=lambda x: {"color": "red", "weight": 3}).add_to(m) | |
| # Add point markers | |
| for idx, row in point_gdf.iterrows(): | |
| coords = row.geometry.coords[0] | |
| folium.Marker( | |
| location=[coords[1], coords[0]], | |
| popup=f"Point {idx+1} - ({coords[1]}, {coords[0]})", | |
| icon=folium.Icon(color="blue", icon="info-sign") | |
| ).add_to(m) | |
| folium.LayerControl().add_to(m) | |
| st.subheader("π Map Viewer") | |
| st_folium(m, width=1100, height=600) | |
| st.subheader("π Points Table") | |
| st.dataframe(point_gdf) | |
| st.subheader("π Full Attribute Table") | |
| st.dataframe(gdf) | |
| except Exception as e: | |
| st.error(f"Error: {e}") | |
| else: | |
| st.info("Please upload a geospatial file to get started.") |