Update pages/12_🌲_VertXtractor.py
Browse files- pages/12_🌲_VertXtractor.py +100 -85
pages/12_🌲_VertXtractor.py
CHANGED
@@ -2,99 +2,114 @@ import streamlit as st
|
|
2 |
import geopandas as gpd
|
3 |
import folium
|
4 |
from streamlit_folium import folium_static
|
|
|
5 |
import requests
|
|
|
6 |
from io import BytesIO
|
|
|
7 |
from PIL import Image
|
8 |
-
import
|
9 |
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
url = "https://api3.geo.admin.ch/rest/services/api/MapServer"
|
17 |
-
response = requests.get(url)
|
18 |
-
if response.status_code == 200:
|
19 |
-
layers = response.json()
|
20 |
-
return {layer['layerBodId']: layer['layerName'] for layer in layers['layers']}
|
21 |
-
return {}
|
22 |
-
|
23 |
-
swisstopo_layers = get_swisstopo_layers()
|
24 |
-
|
25 |
-
# File uploader for GeoJSON
|
26 |
-
uploaded_file = st.file_uploader("Choose a GeoJSON file", type="geojson")
|
27 |
-
|
28 |
-
if uploaded_file is not None:
|
29 |
-
# Read the GeoJSON file
|
30 |
-
gdf = gpd.read_file(uploaded_file)
|
31 |
-
|
32 |
-
# Get the bounding box
|
33 |
-
minx, miny, maxx, maxy = gdf.total_bounds
|
34 |
|
35 |
-
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
-
|
39 |
-
|
40 |
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
# Choose the map provider
|
48 |
-
provider = st.selectbox("Choose map provider", ["ESRI World Imagery", "Swisstopo"])
|
49 |
-
|
50 |
-
if provider == "Swisstopo":
|
51 |
-
selected_layer = st.selectbox("Choose Swisstopo layer", list(swisstopo_layers.keys()), format_func=lambda x: swisstopo_layers[x])
|
52 |
-
|
53 |
-
if st.button("Download Orthophoto"):
|
54 |
-
if provider == "ESRI World Imagery":
|
55 |
-
# ESRI World Imagery WMS URL
|
56 |
-
wms_url = "https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/export"
|
57 |
-
|
58 |
-
# Parameters for the WMS request
|
59 |
-
params = {
|
60 |
-
'bbox': f"{minx},{miny},{maxx},{maxy}",
|
61 |
-
'bboxSR': 4326,
|
62 |
-
'imageSR': 4326,
|
63 |
-
'size': '1000,1000',
|
64 |
-
'format': 'png',
|
65 |
-
'f': 'image'
|
66 |
-
}
|
67 |
-
|
68 |
-
# Make the request
|
69 |
-
response = requests.get(wms_url, params=params)
|
70 |
-
|
71 |
-
elif provider == "Swisstopo":
|
72 |
-
# Swisstopo MapServer URL
|
73 |
-
mapserver_url = f"https://api3.geo.admin.ch/rest/services/api/MapServer/{selected_layer}/image"
|
74 |
-
|
75 |
-
# Parameters for the MapServer request
|
76 |
-
params = {
|
77 |
-
'bbox': f"{minx},{miny},{maxx},{maxy}",
|
78 |
-
'imageSize': '1000,1000',
|
79 |
-
'format': 'png'
|
80 |
-
}
|
81 |
-
|
82 |
-
# Make the request
|
83 |
-
response = requests.get(mapserver_url, params=params)
|
84 |
-
|
85 |
-
if response.status_code == 200:
|
86 |
-
# Save the image
|
87 |
-
image = Image.open(BytesIO(response.content))
|
88 |
-
with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp_file:
|
89 |
-
image.save(tmp_file.name)
|
90 |
-
st.success(f"Image saved as {tmp_file.name}")
|
91 |
-
|
92 |
-
# Display the downloaded image
|
93 |
-
st.image(image, caption=f"Downloaded {provider} Orthophoto", use_column_width=True)
|
94 |
-
else:
|
95 |
-
st.error(f"Failed to download the image. Status code: {response.status_code}")
|
96 |
|
97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
|
99 |
-
|
100 |
-
|
|
|
|
|
|
|
|
2 |
import geopandas as gpd
|
3 |
import folium
|
4 |
from streamlit_folium import folium_static
|
5 |
+
from shapely.geometry import box
|
6 |
import requests
|
7 |
+
import json
|
8 |
from io import BytesIO
|
9 |
+
import zipfile
|
10 |
from PIL import Image
|
11 |
+
import numpy as np
|
12 |
|
13 |
+
# Liste des couches de données Swisstopo
|
14 |
+
LAYERS = {
|
15 |
+
"Bâtiments": "ch.swisstopo.vec25-gebaeude",
|
16 |
+
"RĂ©seau hydrographique": "ch.swisstopo.vec25-gewaessernetz",
|
17 |
+
"RĂ©seau routier": "ch.swisstopo.vec25-strassen",
|
18 |
+
"Couverture du sol": "ch.swisstopo.vec25-landesbedeckung",
|
19 |
+
"Limites administratives": "ch.swisstopo.swissboundaries3d",
|
20 |
+
"Modèle numérique de terrain": "ch.swisstopo.swissalti3d",
|
21 |
+
"Carte nationale 1:25'000": "ch.swisstopo.pixelkarte-farbe-pk25.noscale",
|
22 |
+
"Carte nationale 1:50'000": "ch.swisstopo.pixelkarte-farbe-pk50.noscale",
|
23 |
+
"Carte nationale 1:100'000": "ch.swisstopo.pixelkarte-farbe-pk100.noscale",
|
24 |
+
"Orthophoto SWISSIMAGE": "ch.swisstopo.swissimage-product",
|
25 |
+
"Noms géographiques": "ch.swisstopo.swissnames3d",
|
26 |
+
}
|
27 |
|
28 |
+
# Fonction pour extraire les données Swisstopo
|
29 |
+
def extract_swisstopo_data(min_x, min_y, max_x, max_y, layer):
|
30 |
+
bbox = box(min_x, min_y, max_x, max_y)
|
31 |
+
api_url = "https://api3.geo.admin.ch/rest/services/api/MapServer/identify"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
+
params = {
|
34 |
+
"geometry": f"{bbox.bounds[0]},{bbox.bounds[1]},{bbox.bounds[2]},{bbox.bounds[3]}",
|
35 |
+
"geometryType": "esriGeometryEnvelope",
|
36 |
+
"layers": f"all:{layer}",
|
37 |
+
"mapExtent": f"{bbox.bounds[0]},{bbox.bounds[1]},{bbox.bounds[2]},{bbox.bounds[3]}",
|
38 |
+
"imageDisplay": "1000,1000,96",
|
39 |
+
"tolerance": "0",
|
40 |
+
"lang": "fr",
|
41 |
+
"sr": "2056"
|
42 |
+
}
|
43 |
|
44 |
+
response = requests.get(api_url, params=params)
|
45 |
+
response.raise_for_status()
|
46 |
|
47 |
+
data = response.json()
|
48 |
+
features = [feature["geometry"] for feature in data["results"]]
|
49 |
|
50 |
+
gdf = gpd.GeoDataFrame.from_features(features, crs="EPSG:2056")
|
51 |
+
return gdf
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
+
# Fonction pour télécharger l'image SWISSIMAGE (inchangée)
|
54 |
+
def download_swissimage(min_x, min_y, max_x, max_y):
|
55 |
+
# ... (le code reste le mĂŞme)
|
56 |
+
|
57 |
+
# Interface utilisateur Streamlit
|
58 |
+
st.title("Extracteur de données Swisstopo")
|
59 |
+
|
60 |
+
# SĂ©lection de la couche
|
61 |
+
selected_layer_name = st.selectbox(
|
62 |
+
"Sélectionnez la couche de données",
|
63 |
+
list(LAYERS.keys())
|
64 |
+
)
|
65 |
+
layer = LAYERS[selected_layer_name]
|
66 |
+
|
67 |
+
# Entrée des coordonnées
|
68 |
+
col1, col2 = st.columns(2)
|
69 |
+
with col1:
|
70 |
+
min_x = st.number_input("Coordonnée X minimale", value=2600000)
|
71 |
+
min_y = st.number_input("Coordonnée Y minimale", value=1200000)
|
72 |
+
with col2:
|
73 |
+
max_x = st.number_input("Coordonnée X maximale", value=2601000)
|
74 |
+
max_y = st.number_input("Coordonnée Y maximale", value=1201000)
|
75 |
+
|
76 |
+
if st.button("Extraire les données"):
|
77 |
+
try:
|
78 |
+
# Extraction des données Swisstopo
|
79 |
+
gdf = extract_swisstopo_data(min_x, min_y, max_x, max_y, layer)
|
80 |
+
|
81 |
+
# Affichage des données
|
82 |
+
st.subheader("Aperçu des données")
|
83 |
+
st.write(gdf.head())
|
84 |
+
|
85 |
+
# Visualisation sur une carte
|
86 |
+
st.subheader("Visualisation des données")
|
87 |
+
m = folium.Map(location=[gdf.geometry.centroid.y.mean(), gdf.geometry.centroid.x.mean()], zoom_start=14)
|
88 |
+
folium.GeoJson(gdf).add_to(m)
|
89 |
+
folium_static(m)
|
90 |
+
|
91 |
+
# Téléchargement des données
|
92 |
+
st.download_button(
|
93 |
+
label="Télécharger les données (GeoJSON)",
|
94 |
+
data=gdf.to_json(),
|
95 |
+
file_name=f"{selected_layer_name.lower().replace(' ', '_')}.geojson",
|
96 |
+
mime="application/json"
|
97 |
+
)
|
98 |
+
|
99 |
+
# Téléchargement et affichage de l'image SWISSIMAGE
|
100 |
+
if layer == "ch.swisstopo.swissimage-product":
|
101 |
+
st.subheader("Image SWISSIMAGE")
|
102 |
+
image = download_swissimage(min_x, min_y, max_x, max_y)
|
103 |
+
if image is not None:
|
104 |
+
st.image(image, caption="Image SWISSIMAGE", use_column_width=True)
|
105 |
+
else:
|
106 |
+
st.warning("Aucune image SWISSIMAGE disponible pour cette zone.")
|
107 |
+
|
108 |
+
except Exception as e:
|
109 |
+
st.error(f"Une erreur s'est produite : {str(e)}")
|
110 |
|
111 |
+
# Informations supplémentaires
|
112 |
+
st.sidebar.markdown("## À propos")
|
113 |
+
st.sidebar.markdown("Cet outil permet d'extraire des données géospatiales de Swisstopo.")
|
114 |
+
st.sidebar.markdown("Développé par Vertdure")
|
115 |
+
st.sidebar.markdown("[Code source](https://huggingface.co/spaces/Vertdure/Streamlit/tree/main)")
|