File size: 6,457 Bytes
d0334cd 9e8e93e cb00c19 d0334cd 91c174c b6b6ea7 d0334cd 57fb324 5abcc84 d5eb90f 3cff2e0 c04a722 3f40f5f 57fb324 1f10f5c 18ee018 5abcc84 18ee018 5abcc84 1f10f5c 5abcc84 cb00c19 5abcc84 195f57b 5abcc84 b6b6ea7 16af22d 5abcc84 d5eb90f 5abcc84 1f10f5c 5abcc84 d043ba9 5abcc84 16af22d 5abcc84 3f40f5f 1f10f5c 3f40f5f 1f10f5c 3f40f5f 1f10f5c 1f63971 cb00c19 16af22d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
import streamlit as st
import geopandas as gpd
import folium
from streamlit_folium import folium_static, st_folium
from folium.plugins import Draw
import requests
from shapely.geometry import box
import json
st.set_page_config(layout="wide", page_title="Extracteur de données géospatiales")
SWISSTOPO_LAYERS = {
"SWISSIMAGE 10 cm": {"id": "ch.swisstopo.swissimage-dop10", "source": "swisstopo", "type": "image"},
"Carte nationale 1:25'000": {"id": "ch.swisstopo.pixelkarte-farbe-pk25.noscale", "source": "swisstopo", "type": "image"},
"MNT": {"id": "ch.swisstopo.swissalti3d", "source": "swisstopo", "type": "raster"},
"Carte géologique": {"id": "ch.swisstopo.geologie-geologische_karte", "source": "swisstopo", "type": "image"},
"Limites administratives": {"id": "ch.swisstopo.swissboundaries3d-gemeinde-flaeche.fill", "source": "swisstopo", "type": "vector"},
"RĂ©seau hydrographique": {"id": "ch.bafu.vec25-gewaessernetz", "source": "swisstopo", "type": "vector"},
"swissBUILDINGS3D 3.0 Beta": {"id": "ch.swisstopo.swissbuildings3d_3_0", "source": "swisstopo", "type": "3d"},
}
ESRI_LAYERS = {
"World Imagery": {"id": "World_Imagery", "source": "esri", "type": "image"},
"World Elevation": {"id": "Elevation/World_Elevation", "source": "esri", "type": "raster"},
"World Topographic": {"id": "World_Topo_Map", "source": "esri", "type": "image"},
"World Street Map": {"id": "World_Street_Map", "source": "esri", "type": "image"},
"World Terrain": {"id": "World_Terrain_Base", "source": "esri", "type": "image"},
}
def draw_box_on_map():
m = folium.Map(location=[46.8, 8.2], zoom_start=8)
Draw(draw_options={'polyline': False, 'polygon': False, 'circle': False, 'marker': False, 'circlemarker': False},
edit_options={'edit': False}).add_to(m)
return st_folium(m, width=700, height=500)
def create_geojson_from_box(bbox):
gdf = gpd.GeoDataFrame({'geometry': [bbox]}, crs="EPSG:4326")
return json.loads(gdf.to_json()), json.loads(gdf.to_crs("EPSG:2056").to_json())
@st.cache_data
def get_download_url(bbox, layer_info):
if layer_info["source"] == "swisstopo":
api_url = f"https://data.geo.admin.ch/api/stac/v0.9/collections/{layer_info['id']}/items"
params = {"bbox": ",".join(map(str, bbox)), "limit": 1}
response = requests.get(api_url, params=params)
data = response.json()
if data['features']:
feature = data['features'][0]
asset_keys = feature['assets'].keys()
data_key = 'rgb' if 'rgb' in asset_keys else 'data' if 'data' in asset_keys else next(iter(asset_keys))
return feature['assets'][data_key]['href']
else: # ESRI
service_url = f"https://services.arcgisonline.com/arcgis/rest/services/{layer_info['id']}/MapServer/export"
params = {
"bbox": f"{bbox[0]},{bbox[1]},{bbox[2]},{bbox[3]}",
"bboxSR": 4326,
"size": "1000,1000",
"format": "png",
"f": "html",
"imageSR": 4326,
"transparent": "true"
}
return f"{service_url}?{'&'.join([f'{k}={v}' for k, v in params.items()])}"
return None
def main():
st.title("Extracteur de données Swisstopo et ESRI")
col1, col2 = st.columns([1, 3])
with col1:
st.subheader("SĂ©lection des couches")
source = st.radio("Source des données", ["Swisstopo", "ESRI"])
layers = SWISSTOPO_LAYERS if source == "Swisstopo" else ESRI_LAYERS
selected_layers = st.multiselect("Couches Ă extraire", list(layers.keys()))
st.markdown("---")
st.markdown("## à propos\nExtracteur de données géospatiales Swisstopo et ESRI.\nDéveloppé par Vertdure")
with col2:
st.subheader("1. DĂ©finir la zone d'intĂ©rĂȘt")
method = st.radio("MĂ©thode", ["Dessiner", "GeoJSON"], horizontal=True)
if method == "Dessiner":
if 'bbox' not in st.session_state:
map_data = draw_box_on_map()
if map_data['last_active_drawing']:
coords = map_data['last_active_drawing']['geometry']['coordinates'][0]
bbox = box(min(c[0] for c in coords), min(c[1] for c in coords),
max(c[0] for c in coords), max(c[1] for c in coords))
st.session_state['bbox'] = bbox
st.session_state['geojson_wgs84'], st.session_state['geojson_swiss'] = create_geojson_from_box(bbox)
st.success("Zone sélectionnée!")
else:
st.success("Zone déjà sélectionnée. Cliquez sur 'Effacer la zone' pour redessiner.")
if st.button("Effacer la zone"):
del st.session_state['bbox']
del st.session_state['geojson_wgs84']
del st.session_state['geojson_swiss']
st.experimental_rerun()
else:
uploaded_file = st.file_uploader("GeoJSON", type="geojson")
if uploaded_file:
gdf = gpd.read_file(uploaded_file)
st.session_state['geojson_wgs84'] = json.loads(gdf.to_crs(4326).to_json())
st.session_state['geojson_swiss'] = json.loads(gdf.to_crs(2056).to_json())
st.success("GeoJSON chargé!")
if st.button("Obtenir les liens de téléchargement"):
if 'geojson_wgs84' not in st.session_state or 'geojson_swiss' not in st.session_state:
st.error("DĂ©finissez d'abord une zone d'intĂ©rĂȘt.")
elif not selected_layers:
st.error("SĂ©lectionnez au moins une couche Ă extraire.")
else:
for layer_name in selected_layers:
layer_info = layers[layer_name]
bbox = gpd.GeoDataFrame.from_features(st.session_state['geojson_swiss' if layer_info["source"] == "swisstopo" else 'geojson_wgs84']).total_bounds
st.write(f"Traitement de la couche : {layer_name}")
st.write(f"Bbox : {bbox}")
download_url = get_download_url(bbox, layer_info)
if download_url:
st.markdown(f"[Télécharger {layer_name}]({download_url})")
else:
st.error(f"Impossible d'obtenir le lien pour {layer_name}")
if __name__ == "__main__":
main() |