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()