Vertdure commited on
Commit
d42475b
·
verified ·
1 Parent(s): be912e9

Update pages/Ter.py

Browse files
Files changed (1) hide show
  1. pages/Ter.py +40 -131
pages/Ter.py CHANGED
@@ -1,140 +1,49 @@
1
- import streamlit as st
2
- import geopandas as gpd
3
- import folium
4
- from folium import plugins
5
- import requests
6
  import numpy as np
7
- import plotly.graph_objects as go
8
- from streamlit_folium import folium_static
9
- import tempfile
10
- import os
11
- import uuid
12
- from concurrent.futures import ThreadPoolExecutor
13
- import time
14
 
15
- st.set_page_config(layout="wide")
16
-
17
- def uploaded_file_to_gdf(data):
18
- _, file_extension = os.path.splitext(data.name)
19
- file_id = str(uuid.uuid4())
20
- file_path = os.path.join(tempfile.gettempdir(), f"{file_id}{file_extension}")
21
- with open(file_path, "wb") as file:
22
- file.write(data.getbuffer())
23
- if file_path.lower().endswith(".kml"):
24
- gdf = gpd.read_file(file_path, driver="KML")
25
- else:
26
- gdf = gpd.read_file(file_path)
27
- return gdf
28
-
29
- def get_elevation(x, y):
30
- url = "https://api3.geo.admin.ch/rest/services/height"
31
- params = {
32
- "easting": x,
33
- "northing": y,
34
- "sr": "2056"
35
  }
36
- response = requests.get(url, params=params)
37
- if response.status_code == 200:
38
- data = response.json()
39
- return data['height']
40
- else:
41
  return None
42
 
43
- def get_elevation_data(bbox, resolution=0.5):
44
- x_min, y_min, x_max, y_max = bbox
45
- width = int((x_max - x_min) / resolution)
46
- height = int((y_max - y_min) / resolution)
47
- x_coords = np.linspace(x_min, x_max, width)
48
- y_coords = np.linspace(y_min, y_max, height)
49
-
50
- elevation_data = np.zeros((height, width))
51
-
52
- total_points = width * height
53
- points_processed = 0
54
-
55
- progress_bar = st.progress(0)
56
- status_text = st.empty()
57
-
58
- with ThreadPoolExecutor(max_workers=20) as executor:
59
- futures = []
60
- for i, y in enumerate(y_coords):
61
- for j, x in enumerate(x_coords):
62
- futures.append(executor.submit(get_elevation, x, y))
63
-
64
- start_time = time.time()
65
- for i, future in enumerate(futures):
66
- row = i // width
67
- col = i % width
68
- elevation_data[row, col] = future.result() if future.result() is not None else 0
69
-
70
- points_processed += 1
71
- if points_processed % 100 == 0:
72
- progress = points_processed / total_points
73
- progress_bar.progress(progress)
74
- elapsed_time = time.time() - start_time
75
- estimated_total_time = elapsed_time / progress
76
- remaining_time = estimated_total_time - elapsed_time
77
- status_text.text(f"Traitement : {points_processed}/{total_points} points. Temps restant estimé : {remaining_time:.2f} secondes")
78
 
79
- return elevation_data
 
80
 
81
- def create_3d_terrain(elevation_data, bbox):
82
- x_min, y_min, x_max, y_max = bbox
83
- x = np.linspace(x_min, x_max, elevation_data.shape[1])
84
- y = np.linspace(y_max, y_min, elevation_data.shape[0])
85
- x, y = np.meshgrid(x, y)
86
- fig = go.Figure(data=[go.Surface(z=elevation_data, x=x, y=y)])
87
- fig.update_layout(title='Visualisation 3D du Terrain', autosize=True,
88
- scene=dict(
89
- aspectmode='manual',
90
- aspectratio=dict(x=1, y=1, z=0.1)
91
- ))
92
- return fig
93
 
94
- def app():
95
- st.title("Visualisation 3D du Terrain Suisse (Échelle 1:1)")
96
- st.markdown(
97
- """
98
- Une application web interactive pour visualiser le terrain suisse en 3D à l'échelle 1:1.
99
- """
100
- )
101
- col1, col2 = st.columns([2, 1])
102
- with col1:
103
- m = folium.Map(location=[46.8182, 8.2275], zoom_start=8)
104
- folium.TileLayer(
105
- tiles="https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/3857/{z}/{x}/{y}.jpeg",
106
- attr="© swisstopo",
107
- name="swisstopo",
108
- overlay=False,
109
- control=True
110
- ).add_to(m)
111
- draw = plugins.Draw(export=True)
112
- draw.add_to(m)
113
- folium.LayerControl().add_to(m)
114
- folium_static(m, height=400)
115
- with col2:
116
- data = st.file_uploader(
117
- "Téléchargez un fichier GeoJSON à utiliser comme ROI.",
118
- type=["geojson", "kml", "zip"],
119
- )
120
- resolution = st.slider("Résolution (en mètres)", min_value=0.1, max_value=5.0, value=0.5, step=0.1)
121
- if st.button("Générer la visualisation 3D"):
122
- if data is None:
123
- st.warning("Veuillez télécharger un fichier GeoJSON.")
124
- else:
125
- gdf = uploaded_file_to_gdf(data)
126
- gdf_2056 = gdf.to_crs(epsg=2056)
127
- bbox = gdf_2056.total_bounds
128
- st.subheader("Visualisation 3D du terrain")
129
- with st.spinner('Génération de la visualisation 3D en cours... Cela peut prendre plusieurs minutes.'):
130
- elevation_data = get_elevation_data(bbox, resolution)
131
- if elevation_data is not None:
132
- fig = create_3d_terrain(elevation_data, bbox)
133
- st.plotly_chart(fig, use_container_width=True)
134
-
135
- # Sauvegarde des données pour l'impression 3D
136
- np.savetxt("elevation_data.csv", elevation_data, delimiter=",")
137
- st.success("Les données d'élévation ont été sauvegardées dans 'elevation_data.csv' pour l'impression 3D.")
138
 
139
- if __name__ == "__main__":
140
- app()
 
1
+ import leafmap
 
 
 
 
2
  import numpy as np
 
 
 
 
 
 
 
3
 
4
+ # Fonction pour calculer les coordonnées de la bbox
5
+ def calculate_bbox(center_lat, center_lon, format, scale):
6
+ paper_sizes = {
7
+ 'A4': (210, 297),
8
+ 'A3': (297, 420),
9
+ 'A2': (420, 594),
10
+ 'A1': (594, 841),
11
+ 'A0': (841, 1189)
 
 
 
 
 
 
 
 
 
 
 
 
12
  }
13
+
14
+ size = paper_sizes.get(format)
15
+ if not size:
 
 
16
  return None
17
 
18
+ width_mm, height_mm = size
19
+ width_m = (width_mm / 1000) * scale
20
+ height_m = (height_mm / 1000) * scale
21
+
22
+ bounds = [
23
+ [center_lat - (height_m / 2) / 111320, center_lon - (width_m / 2) / (111320 * np.cos(center_lat * np.pi / 180))],
24
+ [center_lat + (height_m / 2) / 111320, center_lon + (width_m / 2) / (111320 * np.cos(center_lat * np.pi / 180))]
25
+ ]
26
+
27
+ return bounds
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ # Créer une carte centrée sur la Suisse
30
+ m = leafmap.Map(center=[46.8182, 8.2275], zoom=8)
31
 
32
+ # Ajouter un outil pour dessiner des formes
33
+ m.add_draw_control()
34
+
35
+ # Fonction pour ajuster la carte à la bbox calculée
36
+ def draw_bbox():
37
+ center_lat, center_lon = m.center
38
+ format = 'A4' # Exemple de format
39
+ scale = 1000 # Exemple d'échelle
40
+ bbox = calculate_bbox(center_lat, center_lon, format, scale)
41
+
42
+ if bbox:
43
+ m.fit_bounds(bbox)
44
 
45
+ # Ajouter un bouton pour dessiner la bbox
46
+ m.add_button(label="Dessiner BBox", on_click=draw_bbox)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ # Afficher la carte dans Streamlit
49
+ m.to_streamlit()