Streamlit / pages /12_🌲_VertXtractor.py
Vertdure's picture
Update pages/12_🌲_VertXtractor.py
0dd9e26 verified
raw
history blame
No virus
5.15 kB
import streamlit as st
import geopandas as gpd
import folium
from streamlit_folium import folium_static
from shapely.geometry import box
import requests
import json
from io import BytesIO
import zipfile
from PIL import Image
import numpy as np
# Liste des couches de données Swisstopo
LAYERS = {
"Bâtiments": "ch.swisstopo.vec25-gebaeude",
"Bâtiments 3D": "ch.swisstopo.swissbuildings3d_2",
"RĂ©seau hydrographique": "ch.swisstopo.vec25-gewaessernetz",
"RĂ©seau routier": "ch.swisstopo.vec25-strassen",
"Couverture du sol": "ch.swisstopo.vec25-landesbedeckung",
"Limites administratives": "ch.swisstopo.swissboundaries3d",
"Modèle numérique de terrain": "ch.swisstopo.swissalti3d",
"Carte nationale 1:25'000": "ch.swisstopo.pixelkarte-farbe-pk25.noscale",
"Carte nationale 1:50'000": "ch.swisstopo.pixelkarte-farbe-pk50.noscale",
"Carte nationale 1:100'000": "ch.swisstopo.pixelkarte-farbe-pk100.noscale",
"Orthophoto SWISSIMAGE": "ch.swisstopo.swissimage-product",
"Noms géographiques": "ch.swisstopo.swissnames3d",
}
def extract_swisstopo_data(min_x, min_y, max_x, max_y, layer):
bbox = box(min_x, min_y, max_x, max_y)
api_url = "https://api3.geo.admin.ch/rest/services/api/MapServer/identify"
params = {
"geometry": f"{bbox.bounds[0]},{bbox.bounds[1]},{bbox.bounds[2]},{bbox.bounds[3]}",
"geometryType": "esriGeometryEnvelope",
"layers": f"all:{layer}",
"mapExtent": f"{bbox.bounds[0]},{bbox.bounds[1]},{bbox.bounds[2]},{bbox.bounds[3]}",
"imageDisplay": "1000,1000,96",
"tolerance": "0",
"lang": "fr",
"sr": "2056"
}
response = requests.get(api_url, params=params)
response.raise_for_status()
data = response.json()
features = [feature["geometry"] for feature in data["results"]]
gdf = gpd.GeoDataFrame.from_features(features, crs="EPSG:2056")
return gdf
def download_swissimage(min_x, min_y, max_x, max_y):
api_url = "https://data.geo.admin.ch/api/stac/v0.9/collections/ch.swisstopo.swissimage-dop10/items"
params = {
"bbox": f"{min_x},{min_y},{max_x},{max_y}",
"datetime": "2022-01-01T00:00:00Z/..",
"limit": 1
}
response = requests.get(api_url, params=params)
response.raise_for_status()
data = response.json()
if data['features']:
asset_url = data['features'][0]['assets']['rgb']['href']
image_response = requests.get(asset_url)
image_response.raise_for_status()
with zipfile.ZipFile(BytesIO(image_response.content)) as zf:
image_file = [f for f in zf.namelist() if f.endswith('.tif')][0]
with zf.open(image_file) as file:
image = Image.open(file)
return np.array(image)
return None
# Interface utilisateur Streamlit
st.title("Extracteur de données Swisstopo")
# SĂ©lection de la couche
selected_layer_name = st.selectbox(
"Sélectionnez la couche de données",
list(LAYERS.keys())
)
layer = LAYERS[selected_layer_name]
# Entrée des coordonnées
col1, col2 = st.columns(2)
with col1:
min_x = st.number_input("Coordonnée X minimale", value=2600000)
min_y = st.number_input("Coordonnée Y minimale", value=1200000)
with col2:
max_x = st.number_input("Coordonnée X maximale", value=2601000)
max_y = st.number_input("Coordonnée Y maximale", value=1201000)
if st.button("Extraire les données"):
try:
# Extraction des données Swisstopo
gdf = extract_swisstopo_data(min_x, min_y, max_x, max_y, layer)
# Affichage des données
st.subheader("Aperçu des données")
st.write(gdf.head())
# Visualisation sur une carte
st.subheader("Visualisation des données")
m = folium.Map(location=[gdf.geometry.centroid.y.mean(), gdf.geometry.centroid.x.mean()], zoom_start=14)
folium.GeoJson(gdf).add_to(m)
folium_static(m)
# Téléchargement des données
st.download_button(
label="Télécharger les données (GeoJSON)",
data=gdf.to_json(),
file_name=f"{selected_layer_name.lower().replace(' ', '_')}.geojson",
mime="application/json"
)
# Téléchargement et affichage de l'image SWISSIMAGE
if layer == "ch.swisstopo.swissimage-product":
st.subheader("Image SWISSIMAGE")
image = download_swissimage(min_x, min_y, max_x, max_y)
if image is not None:
st.image(image, caption="Image SWISSIMAGE", use_column_width=True)
else:
st.warning("Aucune image SWISSIMAGE disponible pour cette zone.")
except Exception as e:
st.error(f"Une erreur s'est produite : {str(e)}")
# Informations supplémentaires
st.sidebar.markdown("## À propos")
st.sidebar.markdown("Cet outil permet d'extraire des données géospatiales de Swisstopo.")
st.sidebar.markdown("Développé par Vertdure")
st.sidebar.markdown("[Code source](https://huggingface.co/spaces/Vertdure/Streamlit/tree/main)")