Vertdure commited on
Commit
c507920
‱
1 Parent(s): a862007

Update pages/5_📍_VertXtractor.py

Browse files
Files changed (1) hide show
  1. pages/5_📍_VertXtractor.py +149 -87
pages/5_📍_VertXtractor.py CHANGED
@@ -1,110 +1,172 @@
1
  import streamlit as st
2
- import requests
3
  import folium
4
  from streamlit_folium import folium_static
5
- import geopandas as gpd
 
6
  import rasterio
7
  from rasterio.merge import merge
8
- import os
9
  import tempfile
10
- import zipfile
11
  from io import BytesIO
 
 
 
12
 
13
- # Configurations et constantes
14
- STAC_API_URL = "https://data.geo.admin.ch/api/stac/v0.9/collections/"
15
- PRODUCTS = {
16
- 'Photo aérienne 10cm': 'ch.swisstopo.swissimage-dop10',
17
- 'Carte nationale 1:10 000': 'ch.swisstopo.landeskarte-farbe-10',
18
- 'Carte nationale 1:25 000': 'ch.swisstopo.pixelkarte-farbe-pk25.noscale',
19
- 'Carte nationale 1:50 000': 'ch.swisstopo.pixelkarte-farbe-pk50.noscale',
20
- 'Carte nationale 1:100 000': 'ch.swisstopo.pixelkarte-farbe-pk100.noscale',
21
- 'Carte nationale 1:200 000': 'ch.swisstopo.pixelkarte-farbe-pk200.noscale',
22
- 'ModÚle numérique de terrain': 'ch.swisstopo.swissalti3d',
23
- }
24
 
25
- @st.cache_data
26
- def get_items(product_name, bbox):
27
- """RĂ©cupĂšre les Ă©lĂ©ments pour une zone d'intĂ©rĂȘt (AOI)."""
28
- url = f"{STAC_API_URL}{product_name}/items?bbox={bbox}"
29
  response = requests.get(url)
30
  if response.status_code == 200:
31
- items = response.json().get('features', [])
32
- return [item['assets']['data']['href'] for item in items if 'data' in item['assets']]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  else:
34
- st.error(f"Erreur lors de la récupération des éléments: {response.status_code}")
35
  return []
36
 
37
- def download_and_merge(urls):
38
- """Télécharge et fusionne les tuiles raster."""
39
- with tempfile.TemporaryDirectory() as tmpdir:
40
- files = []
41
- for url in urls:
42
- response = requests.get(url)
43
- if response.status_code == 200:
44
- file_path = os.path.join(tmpdir, os.path.basename(url))
45
- with open(file_path, 'wb') as f:
46
- f.write(response.content)
47
- files.append(file_path)
48
-
49
- if files:
50
- src_files_to_mosaic = [rasterio.open(fp) for fp in files]
51
- mosaic, out_trans = merge(src_files_to_mosaic)
52
-
53
- out_meta = src_files_to_mosaic[0].meta.copy()
54
- out_meta.update({
55
- "driver": "GTiff",
56
- "height": mosaic.shape[1],
57
- "width": mosaic.shape[2],
58
- "transform": out_trans
59
- })
60
-
61
- merged_file = BytesIO()
62
- with rasterio.MemoryFile(merged_file) as memfile:
63
- with memfile.open(**out_meta) as dest:
64
- dest.write(mosaic)
65
-
66
- merged_file.seek(0)
67
- return merged_file
68
- return None
69
 
70
- def main():
71
- st.title("Téléchargeur de cartes SwissTopo")
 
 
 
 
 
 
 
 
 
 
 
72
 
73
- # SĂ©lection du produit
74
- product = st.selectbox("Choisissez un produit", list(PRODUCTS.keys()))
75
 
76
- # Carte pour sélectionner la bbox
77
- m = folium.Map(location=[46.8182, 8.2275], zoom_start=8)
78
- draw = folium.plugins.Draw(export=True)
79
- draw.add_to(m)
80
- folium_static(m)
 
81
 
82
- # Récupération de la bbox dessinée
83
- bbox = None
84
- if 'last_active_drawing' in st.session_state:
85
- bbox_coords = st.session_state.last_active_drawing['geometry']['coordinates'][0]
86
- bbox = f"{bbox_coords[0][0]},{bbox_coords[0][1]},{bbox_coords[2][0]},{bbox_coords[2][1]}"
87
- st.write(f"Zone sélectionnée : {bbox}")
88
 
89
- if st.button("Télécharger") and bbox:
90
- with st.spinner("Téléchargement en cours..."):
91
- urls = get_items(PRODUCTS[product], bbox)
92
- if urls:
93
- merged_file = download_and_merge(urls)
94
- if merged_file:
95
- st.success("Fusion des fichiers réussie !")
96
- st.download_button(
97
- label="Télécharger la carte fusionnée",
98
- data=merged_file,
99
- file_name="carte_fusionnee.tif",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  mime="image/tiff"
101
  )
102
- else:
103
- st.error("Erreur lors de la fusion des fichiers.")
104
  else:
105
- st.warning("Aucune donnée trouvée pour cette zone.")
106
- elif not bbox:
107
- st.info("Veuillez dessiner une zone sur la carte avant de télécharger.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
- if __name__ == "__main__":
110
- main()
 
 
 
1
  import streamlit as st
 
2
  import folium
3
  from streamlit_folium import folium_static
4
+ from folium.plugins import Draw
5
+ import requests
6
  import rasterio
7
  from rasterio.merge import merge
 
8
  import tempfile
9
+ import os
10
  from io import BytesIO
11
+ import json
12
+ from shapely.geometry import box
13
+ import geopandas as gpd
14
 
15
+ # Configuration de la page Streamlit
16
+ st.set_page_config(layout="wide", page_title="SwissTopoBatchNMerge")
17
+ st.title("SwissTopoBatchNMerge Streamlit")
 
 
 
 
 
 
 
 
18
 
19
+ # Fonction pour télécharger les données depuis une URL
20
+ def download_data(url):
 
 
21
  response = requests.get(url)
22
  if response.status_code == 200:
23
+ return BytesIO(response.content)
24
+ else:
25
+ st.error(f"Erreur lors du téléchargement: {response.status_code}")
26
+ return None
27
+
28
+ # Fonction pour fusionner les tuiles raster
29
+ def merge_tiles(files):
30
+ src_files_to_mosaic = []
31
+ for file in files:
32
+ src = rasterio.open(file)
33
+ src_files_to_mosaic.append(src)
34
+ mosaic, out_trans = merge(src_files_to_mosaic)
35
+ return mosaic, out_trans
36
+
37
+ # Fonction pour obtenir les liens de téléchargement des tuiles de l'API swisstopo
38
+ def get_swisstopo_tiles(bbox, product):
39
+ # URL de l'API d'identification de swisstopo
40
+ api_url = "https://api3.geo.admin.ch/rest/services/api/MapServer/identify"
41
+
42
+ # ParamĂštres de la requĂȘte
43
+ params = {
44
+ 'geometry': f"{bbox[0]},{bbox[1]},{bbox[2]},{bbox[3]}",
45
+ 'geometryType': 'esriGeometryEnvelope',
46
+ 'imageDisplay': '1000,1000,96',
47
+ 'mapExtent': f"{bbox[0]},{bbox[1]},{bbox[2]},{bbox[3]}",
48
+ 'tolerance': '0',
49
+ 'layers': 'all:' + product,
50
+ 'sr': '4326'
51
+ }
52
+
53
+ # Envoi de la requĂȘte Ă  l'API
54
+ response = requests.get(api_url, params=params)
55
+
56
+ if response.status_code == 200:
57
+ data = response.json()
58
+ # Extraction des liens de téléchargement des résultats
59
+ return [result['attributes']['download'] for result in data['results'] if 'download' in result['attributes']]
60
  else:
61
+ st.error(f"Erreur lors de la requĂȘte Ă  l'API: {response.status_code}")
62
  return []
63
 
64
+ # Création de la carte Folium centrée sur la Suisse
65
+ m = folium.Map(location=[46.8182, 8.2275], zoom_start=8)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
+ # Ajout d'un contrĂŽle de dessin Ă  la carte
68
+ draw = Draw(
69
+ draw_options={
70
+ 'rectangle': True,
71
+ 'polygon': False,
72
+ 'polyline': False,
73
+ 'circle': False,
74
+ 'marker': False,
75
+ 'circlemarker': False,
76
+ },
77
+ edit_options={'edit': False}
78
+ )
79
+ m.add_child(draw)
80
 
81
+ # Affichage de la carte dans Streamlit
82
+ map_data = folium_static(m, width=700, height=500)
83
 
84
+ # SĂ©lection du produit swisstopo
85
+ product = st.selectbox(
86
+ "Choisissez un produit",
87
+ ["ch.swisstopo.swissimage-dop10", "ch.swisstopo.swissalti3d"],
88
+ help="Sélectionnez le type de données que vous souhaitez télécharger"
89
+ )
90
 
91
+ # Vérification si une boßte de sélection a été dessinée
92
+ if 'last_active_drawing' in st.session_state:
93
+ # Extraction des coordonnées de la boßte de sélection
94
+ bbox = st.session_state.last_active_drawing['geometry']['coordinates'][0]
95
+ bbox = [coord for sublist in bbox[:-1] for coord in sublist]
96
+ st.write(f"Boßte de sélection : {bbox}")
97
 
98
+ if st.button("Télécharger et fusionner"):
99
+ with st.spinner("Récupération des liens de téléchargement..."):
100
+ urls = get_swisstopo_tiles(bbox, product)
101
+
102
+ if urls:
103
+ with st.spinner("Téléchargement des tuiles..."):
104
+ temp_dir = tempfile.mkdtemp()
105
+ files = []
106
+ for i, url in enumerate(urls):
107
+ file = download_data(url)
108
+ if file:
109
+ file_path = os.path.join(temp_dir, f"tile_{i}.tif")
110
+ with open(file_path, "wb") as f:
111
+ f.write(file.getvalue())
112
+ files.append(file_path)
113
+
114
+ if files:
115
+ with st.spinner("Fusion des tuiles..."):
116
+ mosaic, out_trans = merge_tiles(files)
117
+
118
+ st.success("Traitement terminé !")
119
+
120
+ # Sauvegarde du résultat fusionné
121
+ output_path = os.path.join(temp_dir, "result.tif")
122
+ with rasterio.open(output_path, 'w', **mosaic.profile) as dst:
123
+ dst.write(mosaic)
124
+
125
+ # Proposition de téléchargement du résultat
126
+ with open(output_path, "rb") as file:
127
+ btn = st.download_button(
128
+ label="Télécharger le résultat",
129
+ data=file,
130
+ file_name="merged_result.tif",
131
  mime="image/tiff"
132
  )
 
 
133
  else:
134
+ st.error("Échec du tĂ©lĂ©chargement des tuiles.")
135
+ else:
136
+ st.error("Aucune tuile trouvée pour la zone sélectionnée.")
137
+ else:
138
+ st.write("Veuillez dessiner une boßte de sélection sur la carte.")
139
+
140
+ # JavaScript pour récupérer les coordonnées de la boßte dessinée
141
+ st.components.v1.html(
142
+ """
143
+ <script>
144
+ const map = document.getElementsByClassName('folium-map')[0];
145
+ map.addEventListener('draw:created', function(e) {
146
+ const type = e.layerType;
147
+ const layer = e.layer;
148
+ if (type === 'rectangle') {
149
+ const bounds = layer.getBounds();
150
+ const coordinates = [
151
+ bounds.getSouthWest().lng, bounds.getSouthWest().lat,
152
+ bounds.getNorthEast().lng, bounds.getNorthEast().lat
153
+ ];
154
+ window.parent.postMessage({
155
+ type: 'drawing',
156
+ coordinates: coordinates
157
+ }, '*');
158
+ }
159
+ });
160
+ </script>
161
+ """,
162
+ height=0,
163
+ )
164
+
165
+ # Gestion des événements de dessin
166
+ if 'last_active_drawing' not in st.session_state:
167
+ st.session_state.last_active_drawing = None
168
 
169
+ for event in st.session_state.get("events", []):
170
+ if event.type == 'drawing':
171
+ st.session_state.last_active_drawing = event.data
172
+ st.experimental_rerun()