Update pages/12_🌲_VertXtractor.py
Browse files- pages/12_🌲_VertXtractor.py +88 -30
pages/12_🌲_VertXtractor.py
CHANGED
@@ -6,17 +6,23 @@ from folium.plugins import Draw
|
|
6 |
import requests
|
7 |
from shapely.geometry import box
|
8 |
import json
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
# Liste des couches disponibles
|
11 |
LAYERS = {
|
12 |
-
"Swisstopo - SWISSIMAGE 10 cm": {"id": "ch.swisstopo.swissimage-dop10", "source": "swisstopo"},
|
13 |
-
"Swisstopo - Carte nationale 1:25'000": {"id": "ch.swisstopo.pixelkarte-farbe-pk25.noscale", "source": "swisstopo"},
|
14 |
-
"Swisstopo - Modèle numérique de terrain": {"id": "ch.swisstopo.swissalti3d", "source": "swisstopo"},
|
15 |
-
"ESRI - World Imagery": {"id": "
|
16 |
-
"ESRI - World Elevation": {"id": "
|
17 |
}
|
18 |
|
19 |
def draw_box_on_map():
|
|
|
20 |
m = folium.Map(location=[46.8, 8.2], zoom_start=8)
|
21 |
draw = Draw(
|
22 |
draw_options={
|
@@ -32,27 +38,89 @@ def draw_box_on_map():
|
|
32 |
return st_folium(m, width=700, height=500)
|
33 |
|
34 |
def create_geojson_from_box(bbox):
|
|
|
35 |
gdf = gpd.GeoDataFrame({'geometry': [bbox]}, crs="EPSG:4326")
|
36 |
gdf_swiss = gdf.to_crs("EPSG:2056")
|
37 |
return json.loads(gdf.to_json()), json.loads(gdf_swiss.to_json())
|
38 |
|
39 |
-
def extract_swisstopo_data(bbox, layer_id):
|
|
|
40 |
api_url = f"https://data.geo.admin.ch/api/stac/v0.9/collections/{layer_id}/items"
|
41 |
-
params = {"bbox": ",".join(map(str, bbox)), "limit":
|
42 |
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
return None
|
50 |
|
51 |
-
def extract_esri_data(bbox, layer_id):
|
52 |
-
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
return None
|
55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
def main():
|
57 |
st.title("Extracteur de données Swisstopo et ESRI")
|
58 |
|
@@ -94,22 +162,12 @@ def main():
|
|
94 |
|
95 |
if layer_info["source"] == "swisstopo":
|
96 |
bbox = gpd.GeoDataFrame.from_features(st.session_state['geojson_swiss']).total_bounds
|
97 |
-
data = extract_swisstopo_data(bbox, layer_info["id"])
|
98 |
else: # ESRI
|
99 |
bbox = gpd.GeoDataFrame.from_features(st.session_state['geojson_wgs84']).total_bounds
|
100 |
-
data = extract_esri_data(bbox, layer_info["id"])
|
101 |
-
|
102 |
-
|
103 |
-
st.write(f"Données extraites pour {layer_name}:")
|
104 |
-
st.write(data.head())
|
105 |
-
st.download_button(
|
106 |
-
label=f"Télécharger {layer_name} (GeoJSON)",
|
107 |
-
data=data.to_json(),
|
108 |
-
file_name=f"{layer_name.lower().replace(' ', '_')}.geojson",
|
109 |
-
mime="application/json"
|
110 |
-
)
|
111 |
-
else:
|
112 |
-
st.warning(f"Aucune donnée trouvée pour {layer_name}")
|
113 |
|
114 |
st.sidebar.markdown("## À propos")
|
115 |
st.sidebar.markdown("Cet outil permet d'extraire des données géospatiales de Swisstopo et ESRI.")
|
|
|
6 |
import requests
|
7 |
from shapely.geometry import box
|
8 |
import json
|
9 |
+
import io
|
10 |
+
import rasterio
|
11 |
+
from rasterio.io import MemoryFile
|
12 |
+
from PIL import Image
|
13 |
+
import numpy as np
|
14 |
|
15 |
# Liste des couches disponibles
|
16 |
LAYERS = {
|
17 |
+
"Swisstopo - SWISSIMAGE 10 cm": {"id": "ch.swisstopo.swissimage-dop10", "source": "swisstopo", "type": "image"},
|
18 |
+
"Swisstopo - Carte nationale 1:25'000": {"id": "ch.swisstopo.pixelkarte-farbe-pk25.noscale", "source": "swisstopo", "type": "image"},
|
19 |
+
"Swisstopo - Modèle numérique de terrain": {"id": "ch.swisstopo.swissalti3d", "source": "swisstopo", "type": "raster"},
|
20 |
+
"ESRI - World Imagery": {"id": "WorldImagery", "source": "esri", "type": "image"},
|
21 |
+
"ESRI - World Elevation": {"id": "WorldElevation", "source": "esri", "type": "raster"}
|
22 |
}
|
23 |
|
24 |
def draw_box_on_map():
|
25 |
+
"""Permet à l'utilisateur de dessiner une boîte sur une carte Folium."""
|
26 |
m = folium.Map(location=[46.8, 8.2], zoom_start=8)
|
27 |
draw = Draw(
|
28 |
draw_options={
|
|
|
38 |
return st_folium(m, width=700, height=500)
|
39 |
|
40 |
def create_geojson_from_box(bbox):
|
41 |
+
"""Crée des GeoJSON en WGS84 et LV95 à partir d'une boîte englobante."""
|
42 |
gdf = gpd.GeoDataFrame({'geometry': [bbox]}, crs="EPSG:4326")
|
43 |
gdf_swiss = gdf.to_crs("EPSG:2056")
|
44 |
return json.loads(gdf.to_json()), json.loads(gdf_swiss.to_json())
|
45 |
|
46 |
+
def extract_swisstopo_data(bbox, layer_id, layer_type):
|
47 |
+
"""Extrait les données Swisstopo en utilisant l'API STAC."""
|
48 |
api_url = f"https://data.geo.admin.ch/api/stac/v0.9/collections/{layer_id}/items"
|
49 |
+
params = {"bbox": ",".join(map(str, bbox)), "limit": 1}
|
50 |
|
51 |
+
try:
|
52 |
+
response = requests.get(api_url, params=params)
|
53 |
+
response.raise_for_status()
|
54 |
+
|
55 |
+
data = response.json()
|
56 |
+
if data['features']:
|
57 |
+
feature = data['features'][0]
|
58 |
+
if layer_type == "image":
|
59 |
+
return feature['assets']['rgb']['href']
|
60 |
+
elif layer_type == "raster":
|
61 |
+
raster_url = feature['assets']['data']['href']
|
62 |
+
raster_response = requests.get(raster_url)
|
63 |
+
raster_response.raise_for_status()
|
64 |
+
return raster_response.content
|
65 |
+
except requests.RequestException as e:
|
66 |
+
st.error(f"Erreur lors de l'extraction des données Swisstopo: {str(e)}")
|
67 |
return None
|
68 |
|
69 |
+
def extract_esri_data(bbox, layer_id, layer_type):
|
70 |
+
"""Extrait les données ESRI en utilisant les services ArcGIS REST."""
|
71 |
+
if layer_type == "image":
|
72 |
+
service_url = "https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/export"
|
73 |
+
elif layer_type == "raster":
|
74 |
+
service_url = "https://elevation.arcgis.com/arcgis/rest/services/WorldElevation/Terrain/ImageServer/exportImage"
|
75 |
+
|
76 |
+
params = {
|
77 |
+
"bbox": f"{bbox[0]},{bbox[1]},{bbox[2]},{bbox[3]}",
|
78 |
+
"bboxSR": 4326,
|
79 |
+
"size": "1000,1000",
|
80 |
+
"format": "tiff",
|
81 |
+
"f": "image"
|
82 |
+
}
|
83 |
+
|
84 |
+
try:
|
85 |
+
response = requests.get(service_url, params=params)
|
86 |
+
response.raise_for_status()
|
87 |
+
return response.content
|
88 |
+
except requests.RequestException as e:
|
89 |
+
st.error(f"Erreur lors de l'extraction des données ESRI: {str(e)}")
|
90 |
return None
|
91 |
|
92 |
+
def process_and_display_data(data, layer_name, layer_type):
|
93 |
+
"""Traite et affiche les données extraites."""
|
94 |
+
if data is None:
|
95 |
+
st.warning(f"Aucune donnée trouvée pour {layer_name}")
|
96 |
+
return
|
97 |
+
|
98 |
+
if layer_type == "image":
|
99 |
+
try:
|
100 |
+
with MemoryFile(data) as memfile:
|
101 |
+
with memfile.open() as dataset:
|
102 |
+
image_array = dataset.read()
|
103 |
+
image = Image.fromarray(np.transpose(image_array, (1, 2, 0)))
|
104 |
+
st.image(image, caption=layer_name, use_column_width=True)
|
105 |
+
except Exception as e:
|
106 |
+
st.error(f"Erreur lors du traitement de l'image pour {layer_name}: {str(e)}")
|
107 |
+
elif layer_type == "raster":
|
108 |
+
try:
|
109 |
+
with MemoryFile(data) as memfile:
|
110 |
+
with memfile.open() as dataset:
|
111 |
+
raster_array = dataset.read(1) # Lire le premier canal
|
112 |
+
st.image(raster_array, caption=f"{layer_name} (première bande)", use_column_width=True)
|
113 |
+
except Exception as e:
|
114 |
+
st.error(f"Erreur lors du traitement du raster pour {layer_name}: {str(e)}")
|
115 |
+
|
116 |
+
# Bouton de téléchargement
|
117 |
+
st.download_button(
|
118 |
+
label=f"Télécharger {layer_name}",
|
119 |
+
data=data,
|
120 |
+
file_name=f"{layer_name.lower().replace(' ', '_')}.tif",
|
121 |
+
mime="application/octet-stream"
|
122 |
+
)
|
123 |
+
|
124 |
def main():
|
125 |
st.title("Extracteur de données Swisstopo et ESRI")
|
126 |
|
|
|
162 |
|
163 |
if layer_info["source"] == "swisstopo":
|
164 |
bbox = gpd.GeoDataFrame.from_features(st.session_state['geojson_swiss']).total_bounds
|
165 |
+
data = extract_swisstopo_data(bbox, layer_info["id"], layer_info["type"])
|
166 |
else: # ESRI
|
167 |
bbox = gpd.GeoDataFrame.from_features(st.session_state['geojson_wgs84']).total_bounds
|
168 |
+
data = extract_esri_data(bbox, layer_info["id"], layer_info["type"])
|
169 |
+
|
170 |
+
process_and_display_data(data, layer_name, layer_info["type"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
|
172 |
st.sidebar.markdown("## À propos")
|
173 |
st.sidebar.markdown("Cet outil permet d'extraire des données géospatiales de Swisstopo et ESRI.")
|