Vertdure commited on
Commit
d10f6f3
•
1 Parent(s): 7f066e2

Update pages/12_🌲_VertXtractor.py

Browse files
Files changed (1) hide show
  1. 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 tempfile
9
 
10
- st.set_page_config(layout="wide", page_title="GeoJSON Orthophoto Downloader")
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- st.title("GeoJSON Orthophoto Downloader")
13
-
14
- @st.cache_data
15
- def get_swisstopo_layers():
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
- # Create a map centered on the GeoJSON data
36
- m = folium.Map(location=[(miny+maxy)/2, (minx+maxx)/2], zoom_start=10)
 
 
 
 
 
 
 
 
37
 
38
- # Add GeoJSON to the map
39
- folium.GeoJson(gdf).add_to(m)
40
 
41
- # Fit the map to the GeoJSON bounds
42
- m.fit_bounds([[miny, minx], [maxy, maxx]])
43
 
44
- # Display the map
45
- folium_static(m)
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
- st.write("Note: This is a demo application. For production use, please ensure you comply with the usage terms of the chosen map provider.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
- else:
100
- st.write("Please upload a GeoJSON file to start.")
 
 
 
 
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)")