Update pages/5_đ_VertXtractor.py
Browse files- pages/5_đ_VertXtractor.py +118 -185
pages/5_đ_VertXtractor.py
CHANGED
@@ -2,167 +2,143 @@ import streamlit as st
|
|
2 |
import folium
|
3 |
from streamlit_folium import folium_static
|
4 |
from folium.plugins import Draw
|
5 |
-
import branca
|
6 |
import requests
|
7 |
import json
|
8 |
import os
|
9 |
import urllib.request
|
10 |
import csv
|
11 |
-
import gdal_merge as gm
|
12 |
-
import nested_lookup
|
13 |
from osgeo import gdal
|
14 |
-
|
15 |
import math
|
16 |
import shutil
|
17 |
import sys
|
|
|
18 |
|
19 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
def osm_to_decimal(tile_x, tile_y, zoom):
|
|
|
21 |
n = 2.0 ** zoom
|
22 |
lon_deg = tile_x / n * 360.0 - 180.0
|
23 |
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * tile_y / n)))
|
24 |
lat_deg = math.degrees(lat_rad)
|
25 |
return lat_deg, lon_deg
|
26 |
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
itemsrequest = requests.get(nextpage)
|
40 |
-
itemsresult = json.loads(itemsrequest.content)
|
41 |
-
assets = assets + nested_lookup.nested_lookup('assets', itemsresult)
|
42 |
-
|
43 |
-
if len(itemsresult['links']) >= 6 and itemsresult['links'][5]['rel'] == 'next':
|
44 |
-
pagination = 1
|
45 |
-
else:
|
46 |
-
pagination = 0
|
47 |
-
|
48 |
-
itemsfiles = nested_lookup.nested_lookup('href', assets)
|
49 |
|
50 |
# Filtrage des fichiers selon les cas spécifiques
|
51 |
-
|
52 |
-
|
53 |
-
itemsfiles = krel
|
54 |
|
55 |
-
|
56 |
-
|
57 |
-
itemsfiles = highres
|
58 |
|
59 |
if productname == 'ch.swisstopo.swissalti3d':
|
60 |
-
|
61 |
-
if
|
62 |
-
|
63 |
-
|
64 |
-
if len(highres) != 0:
|
65 |
-
itemsfiles = highres
|
66 |
-
|
67 |
-
return itemsfiles, morethan100
|
68 |
|
69 |
-
|
70 |
-
|
71 |
coords = f"{LLlon}_{LLlat}_{URlon}_{URlat}"
|
72 |
-
|
73 |
|
74 |
-
|
75 |
|
76 |
-
with open(
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
def mergeRaster(iteration, merged, temp_merged, filename, name, ordername, filename_ext, homedir):
|
83 |
-
if iteration == 0:
|
84 |
-
if os.path.exists(temp_merged):
|
85 |
-
os.remove(temp_merged)
|
86 |
-
else:
|
87 |
-
os.rename(filename, temp_merged)
|
88 |
-
else:
|
89 |
-
st.text(f"Fusion du fichier : {name}")
|
90 |
-
|
91 |
-
if "nonImageLayers" in name: # Remplacez par la condition appropriée
|
92 |
-
gm.main(['', '-o', f"{ordername}_merged{filename_ext[1]}", f"{ordername}_temp_merged{filename_ext[1]}", name, '-co', 'COMPRESS=LZW'])
|
93 |
-
else:
|
94 |
-
gm.main(['', '-o', f"{ordername}_merged{filename_ext[1]}", f"{ordername}_temp_merged{filename_ext[1]}", name, '-co', 'COMPRESS=JPEG', '-co', 'PREDICTOR=2', '-co', 'TILED=YES', '-co', 'BLOCKXSIZE=512', '-co', 'BLOCKYSIZE=512', '-co', 'PHOTOMETRIC=YCBCR', '-ot', 'Byte'])
|
95 |
-
|
96 |
-
os.remove(temp_merged)
|
97 |
-
os.remove(filename)
|
98 |
-
os.rename(merged, temp_merged)
|
99 |
-
|
100 |
-
# Fonction pour découper le raster
|
101 |
-
def cropRaster(inputRaster, outputRaster, bbox):
|
102 |
-
transformer = Transformer.from_crs("epsg:4326", "epsg:2056")
|
103 |
-
bbox95 = transformer.transform(bbox[3], bbox[0]) + transformer.transform(bbox[1], bbox[2])
|
104 |
-
gdal.Translate(outputRaster, inputRaster, projWin=bbox95)
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
filename = os.path.join(downloaddir, name)
|
131 |
-
filename_ext = os.path.splitext(name)
|
132 |
-
temp_merged = os.path.join(downloaddir, f'{ordername}_temp_merged{filename_ext[1]}')
|
133 |
-
merged = os.path.join(downloaddir, f'{ordername}_merged{filename_ext[1]}')
|
134 |
-
result = os.path.join(downloaddir, f'{ordername}{filename_ext[1]}')
|
135 |
|
136 |
if not os.path.isfile(filename):
|
137 |
-
st.text(f"Téléchargement du fichier : {
|
138 |
-
urllib.request.urlretrieve(url
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
st.text("DĂ©coupage...")
|
148 |
-
cropRaster(temp_merged, merged, geom)
|
149 |
-
os.remove(temp_merged)
|
150 |
-
|
151 |
-
if st.session_state.noMERGE:
|
152 |
-
st.text(f"RĂ©sultat dans {downloaddir}")
|
153 |
else:
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
if os.path.exists(temp_merged):
|
158 |
-
os.rename(temp_merged, result)
|
159 |
-
if os.path.exists(merged):
|
160 |
-
os.rename(merged, result)
|
161 |
-
st.text(f"RĂ©sultat dans {result}")
|
162 |
-
os.chdir(os.getcwd())
|
163 |
|
164 |
-
#
|
165 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
m = folium.Map(location=[46.8182, 8.2275], zoom_start=8)
|
167 |
draw = Draw(
|
168 |
draw_options={
|
@@ -176,69 +152,26 @@ def draw_map():
|
|
176 |
edit_options={'edit': False}
|
177 |
)
|
178 |
draw.add_to(m)
|
179 |
-
|
180 |
-
output = folium_static(m)
|
181 |
-
return output
|
182 |
-
|
183 |
-
# Fonction pour obtenir les coordonnées de la bbox
|
184 |
-
def get_bbox_coordinates(draw_data):
|
185 |
-
if draw_data:
|
186 |
-
bbox = draw_data['features'][0]['geometry']['coordinates'][0]
|
187 |
-
lons = [coord[0] for coord in bbox]
|
188 |
-
lats = [coord[1] for coord in bbox]
|
189 |
-
return min(lons), min(lats), max(lons), max(lats)
|
190 |
-
return None
|
191 |
-
|
192 |
-
# Fonction principale
|
193 |
-
def main():
|
194 |
-
st.title("SwissTopo Downloader")
|
195 |
|
196 |
-
|
197 |
-
if 'noCROP' not in st.session_state:
|
198 |
-
st.session_state.noCROP = False
|
199 |
-
if 'noMERGE' not in st.session_state:
|
200 |
-
st.session_state.noMERGE = False
|
201 |
-
if 'draw_data' not in st.session_state:
|
202 |
-
st.session_state.draw_data = None
|
203 |
-
|
204 |
-
# SĂ©lection du produit
|
205 |
-
products = {
|
206 |
-
'Luftbild 10cm': 'ch.swisstopo.swissimage-dop10',
|
207 |
-
'Landeskarte 1:10': 'ch.swisstopo.landeskarte-farbe-10',
|
208 |
-
'Landeskarte 1:25': 'ch.swisstopo.pixelkarte-farbe-pk25.noscale',
|
209 |
-
'Landeskarte 1:50': 'ch.swisstopo.pixelkarte-farbe-pk50.noscale',
|
210 |
-
'Landeskarte 1:100': 'ch.swisstopo.pixelkarte-farbe-pk100.noscale',
|
211 |
-
'Landeskarte 1:200': 'ch.swisstopo.pixelkarte-farbe-pk200.noscale',
|
212 |
-
'Höhenmodell': 'ch.swisstopo.swissalti3d',
|
213 |
-
}
|
214 |
-
selected_product = st.selectbox("SĂ©lectionnez un produit", list(products.keys()))
|
215 |
-
|
216 |
-
# Carte interactive pour dessiner la bbox
|
217 |
-
st.subheader("Dessinez une boĂźte englobante sur la carte")
|
218 |
-
map_data = draw_map()
|
219 |
|
220 |
# Récupération des coordonnées de la bbox
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
st.write(f"Coordonnées de la bbox : {LLlon:.4f}, {LLlat:.4f}, {URlon:.4f}, {URlat:.4f}")
|
229 |
-
else:
|
230 |
-
st.write("Aucune bbox dessinée. Veuillez dessiner une boßte sur la carte.")
|
231 |
|
232 |
# Options
|
233 |
-
|
234 |
-
st.session_state.noMERGE = st.checkbox("Ne pas fusionner", value=st.session_state.noMERGE)
|
235 |
|
236 |
if st.button("Télécharger") and bbox_coords:
|
237 |
-
product =
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
st.success("Téléchargement terminé!")
|
242 |
elif st.button("Télécharger") and not bbox_coords:
|
243 |
st.error("Veuillez dessiner une boßte englobante sur la carte avant de télécharger.")
|
244 |
|
|
|
2 |
import folium
|
3 |
from streamlit_folium import folium_static
|
4 |
from folium.plugins import Draw
|
|
|
5 |
import requests
|
6 |
import json
|
7 |
import os
|
8 |
import urllib.request
|
9 |
import csv
|
|
|
|
|
10 |
from osgeo import gdal
|
11 |
+
import numpy as np
|
12 |
import math
|
13 |
import shutil
|
14 |
import sys
|
15 |
+
import glob
|
16 |
|
17 |
+
# Configuration de la page Streamlit
|
18 |
+
st.set_page_config(page_title="SwissTopo Downloader", layout="wide")
|
19 |
+
|
20 |
+
# Constantes
|
21 |
+
PRODUCTS = {
|
22 |
+
'Luftbild 10cm': 'ch.swisstopo.swissimage-dop10',
|
23 |
+
'Landeskarte 1:10': 'ch.swisstopo.landeskarte-farbe-10',
|
24 |
+
'Landeskarte 1:25': 'ch.swisstopo.pixelkarte-farbe-pk25.noscale',
|
25 |
+
'Landeskarte 1:50': 'ch.swisstopo.pixelkarte-farbe-pk50.noscale',
|
26 |
+
'Landeskarte 1:100': 'ch.swisstopo.pixelkarte-farbe-pk100.noscale',
|
27 |
+
'Landeskarte 1:200': 'ch.swisstopo.pixelkarte-farbe-pk200.noscale',
|
28 |
+
'Höhenmodell': 'ch.swisstopo.swissalti3d',
|
29 |
+
}
|
30 |
+
|
31 |
+
# Fonctions utilitaires
|
32 |
def osm_to_decimal(tile_x, tile_y, zoom):
|
33 |
+
"""Convertit les coordonnées OSM en coordonnées décimales."""
|
34 |
n = 2.0 ** zoom
|
35 |
lon_deg = tile_x / n * 360.0 - 180.0
|
36 |
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * tile_y / n)))
|
37 |
lat_deg = math.degrees(lat_rad)
|
38 |
return lat_deg, lon_deg
|
39 |
|
40 |
+
def get_items(productname, LLlon, LLlat, URlon, URlat, first100=False):
|
41 |
+
"""RĂ©cupĂšre les Ă©lĂ©ments pour une zone d'intĂ©rĂȘt donnĂ©e."""
|
42 |
+
url = f"https://data.geo.admin.ch/api/stac/v0.9/collections/{productname}/items?bbox={LLlon},{LLlat},{URlon},{URlat}"
|
43 |
+
response = requests.get(url)
|
44 |
+
items_result = json.loads(response.content)
|
45 |
+
assets = items_result.get('features', [])
|
46 |
+
|
47 |
+
items_files = []
|
48 |
+
for asset in assets:
|
49 |
+
asset_url = asset.get('assets', {}).get('data', {}).get('href')
|
50 |
+
if asset_url:
|
51 |
+
items_files.append(asset_url)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
# Filtrage des fichiers selon les cas spécifiques
|
54 |
+
if "_krel_" in productname:
|
55 |
+
items_files = [i for i in items_files if "_krel_" in i]
|
|
|
56 |
|
57 |
+
if "0.1" in productname:
|
58 |
+
items_files = [i for i in items_files if "_0.1_" in i]
|
|
|
59 |
|
60 |
if productname == 'ch.swisstopo.swissalti3d':
|
61 |
+
items_files = [i for i in items_files if i.endswith(".tif")]
|
62 |
+
items_files = [i for i in items_files if "_0.5_" in i]
|
63 |
+
|
64 |
+
return items_files
|
|
|
|
|
|
|
|
|
65 |
|
66 |
+
def create_csv(productname, LLlon, LLlat, URlon, URlat):
|
67 |
+
"""Crée un fichier CSV contenant les URLs des données à télécharger."""
|
68 |
coords = f"{LLlon}_{LLlat}_{URlon}_{URlat}"
|
69 |
+
csv_filepath = os.path.join(os.getcwd(), f"{productname}{coords}.csv")
|
70 |
|
71 |
+
items_files = get_items(productname, LLlon, LLlat, URlon, URlat)
|
72 |
|
73 |
+
with open(csv_filepath, 'w', newline='') as f:
|
74 |
+
writer = csv.writer(f)
|
75 |
+
for item in items_files:
|
76 |
+
writer.writerow([item])
|
77 |
+
|
78 |
+
return csv_filepath
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
+
def merge_rasters(input_files, output_file, compress_method='JPEG'):
|
81 |
+
"""Fusionne plusieurs rasters en un seul."""
|
82 |
+
gdal.UseExceptions()
|
83 |
+
|
84 |
+
# Ouvrir le premier fichier pour obtenir les métadonnées
|
85 |
+
src_ds = gdal.Open(input_files[0])
|
86 |
+
driver = gdal.GetDriverByName("GTiff")
|
87 |
+
|
88 |
+
# Créer le fichier de sortie
|
89 |
+
dst_ds = driver.CreateCopy(output_file, src_ds, 0,
|
90 |
+
options=[f"COMPRESS={compress_method}",
|
91 |
+
"TILED=YES",
|
92 |
+
"BIGTIFF=YES"])
|
93 |
+
|
94 |
+
# Fermer le premier fichier
|
95 |
+
src_ds = None
|
96 |
+
|
97 |
+
# Fusionner les autres fichiers
|
98 |
+
for file in input_files[1:]:
|
99 |
+
gdal.Warp(output_file, file, format="GTiff", options=[f"COMPRESS={compress_method}"])
|
100 |
+
|
101 |
+
# Fermer le fichier de sortie
|
102 |
+
dst_ds = None
|
103 |
|
104 |
+
def process_csv(csv_filepath, no_merge=False):
|
105 |
+
"""Traite le fichier CSV pour télécharger et fusionner les données."""
|
106 |
+
download_dir = os.path.dirname(csv_filepath)
|
107 |
+
order_name = os.path.basename(csv_filepath).split('.')[0]
|
108 |
+
|
109 |
+
with open(csv_filepath, 'r') as file:
|
110 |
+
urls = file.readlines()
|
111 |
+
|
112 |
+
downloaded_files = []
|
113 |
+
for i, url in enumerate(urls):
|
114 |
+
url = url.strip()
|
115 |
+
filename = os.path.join(download_dir, url.split('/')[-1])
|
|
|
|
|
|
|
|
|
|
|
116 |
|
117 |
if not os.path.isfile(filename):
|
118 |
+
st.text(f"Téléchargement du fichier : {i+1} sur {len(urls)}")
|
119 |
+
urllib.request.urlretrieve(url, filename)
|
120 |
+
|
121 |
+
downloaded_files.append(filename)
|
122 |
+
|
123 |
+
if not no_merge:
|
124 |
+
output_file = os.path.join(download_dir, f"{order_name}_merged.tif")
|
125 |
+
st.text("Fusion des fichiers téléchargés...")
|
126 |
+
merge_rasters(downloaded_files, output_file)
|
127 |
+
st.text(f"Résultat fusionné dans : {output_file}")
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
else:
|
129 |
+
st.text(f"Fichiers téléchargés dans : {download_dir}")
|
130 |
+
|
131 |
+
return output_file if not no_merge else download_dir
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
|
133 |
+
# Interface utilisateur Streamlit
|
134 |
+
def main():
|
135 |
+
st.title("SwissTopo Downloader")
|
136 |
+
|
137 |
+
# SĂ©lection du produit
|
138 |
+
selected_product = st.selectbox("SĂ©lectionnez un produit", list(PRODUCTS.keys()))
|
139 |
+
|
140 |
+
# Carte interactive pour dessiner la bbox
|
141 |
+
st.subheader("Dessinez une boĂźte englobante sur la carte")
|
142 |
m = folium.Map(location=[46.8182, 8.2275], zoom_start=8)
|
143 |
draw = Draw(
|
144 |
draw_options={
|
|
|
152 |
edit_options={'edit': False}
|
153 |
)
|
154 |
draw.add_to(m)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
|
156 |
+
output = folium_static(m)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
|
158 |
# Récupération des coordonnées de la bbox
|
159 |
+
bbox_coords = None
|
160 |
+
if 'last_active_drawing' in st.session_state:
|
161 |
+
bbox = st.session_state.last_active_drawing['geometry']['coordinates'][0]
|
162 |
+
lons = [coord[0] for coord in bbox]
|
163 |
+
lats = [coord[1] for coord in bbox]
|
164 |
+
bbox_coords = [min(lons), min(lats), max(lons), max(lats)]
|
165 |
+
st.write(f"Coordonnées de la bbox : {bbox_coords}")
|
|
|
|
|
|
|
166 |
|
167 |
# Options
|
168 |
+
no_merge = st.checkbox("Ne pas fusionner les fichiers téléchargés")
|
|
|
169 |
|
170 |
if st.button("Télécharger") and bbox_coords:
|
171 |
+
product = PRODUCTS[selected_product]
|
172 |
+
csv_filepath = create_csv(product, *bbox_coords)
|
173 |
+
result = process_csv(csv_filepath, no_merge)
|
174 |
+
st.success(f"Téléchargement terminé ! Résultat : {result}")
|
|
|
175 |
elif st.button("Télécharger") and not bbox_coords:
|
176 |
st.error("Veuillez dessiner une boßte englobante sur la carte avant de télécharger.")
|
177 |
|