add waypoint to map
This commit is contained in:
@ -73,6 +73,7 @@ class HikingAssistant:
|
||||
horizontal_speed=self._config['app']['estimated_time']['horizontal_speed'],
|
||||
vertical_speed=self._config['app']['estimated_time']['vertical_speed'],
|
||||
)
|
||||
waypoints = gpx_processor.waypoints
|
||||
|
||||
# Cache all processed data
|
||||
st.session_state.gpx_file_key = file_key
|
||||
@ -88,6 +89,7 @@ class HikingAssistant:
|
||||
st.session_state.elevations = elevations
|
||||
st.session_state.gradients = gradients
|
||||
st.session_state.estimated_time = estimated_time
|
||||
st.session_state.waypoints = waypoints
|
||||
|
||||
# Show altitude sickness warning for first gpx loading
|
||||
if max_elevation >= self._config['app']['altitude_sickness']['elevation_threshold']:
|
||||
@ -106,6 +108,7 @@ class HikingAssistant:
|
||||
elevations = st.session_state.elevations
|
||||
gradients = st.session_state.gradients
|
||||
estimated_time = st.session_state.estimated_time
|
||||
waypoints = st.session_state.waypoints
|
||||
|
||||
# Display statistics section
|
||||
st.header('📊 路線五四三')
|
||||
@ -136,7 +139,7 @@ class HikingAssistant:
|
||||
# Map section
|
||||
with st.spinner('正在渲染地圖...'):
|
||||
map_renderer = MapRenderer()
|
||||
route_map = map_renderer.create_route_map(all_points, start_point, end_point)
|
||||
route_map = map_renderer.create_route_map(all_points, start_point, end_point, waypoints)
|
||||
|
||||
if route_map:
|
||||
st_folium(route_map, width=None, height=500, key='route_map', returned_objects=[])
|
||||
@ -144,7 +147,7 @@ class HikingAssistant:
|
||||
st.error('無法渲染地圖')
|
||||
|
||||
# Create two columns: elevation profile on left, pie chart on right
|
||||
profile_col, pie_col = st.columns([2, 1])
|
||||
profile_col, pie_col = st.columns([3, 1])
|
||||
|
||||
with profile_col:
|
||||
with st.spinner('正在繪製海拔剖面圖...'):
|
||||
|
||||
@ -23,6 +23,7 @@ class GPXProcessor:
|
||||
self.points = []
|
||||
self.elevations = [] # unit: m
|
||||
self.distances = [] # unit: km
|
||||
self.waypoints = [] # list of (lat, lon, name, elevation)
|
||||
|
||||
def _get_sample_rate(self):
|
||||
"""Get the median time interval between points.
|
||||
@ -52,6 +53,17 @@ class GPXProcessor:
|
||||
|
||||
self.gpx = gpxpy.parse(gpx_data)
|
||||
|
||||
# Extract waypoints
|
||||
for waypoint in self.gpx.waypoints:
|
||||
self.waypoints.append(
|
||||
{
|
||||
'lat': round(waypoint.latitude, 6),
|
||||
'lon': round(waypoint.longitude, 6),
|
||||
'name': waypoint.name if waypoint.name else '航點',
|
||||
'elevation': round(waypoint.elevation, 1) if waypoint.elevation else None,
|
||||
}
|
||||
)
|
||||
|
||||
# Extract points from all tracks and segments
|
||||
for track in self.gpx.tracks:
|
||||
for segment in track.segments:
|
||||
@ -127,15 +139,15 @@ class GPXProcessor:
|
||||
return min(self.elevations), max(self.elevations)
|
||||
|
||||
def get_start_end_points(self):
|
||||
"""Get start and end point coordinates.
|
||||
"""Get start and end point coordinates with elevation.
|
||||
|
||||
Returns:
|
||||
tuple: ((start_lat, start_lon), (end_lat, end_lon))
|
||||
tuple: ((start_lat, start_lon, start_elevation), (end_lat, end_lon, end_elevation))
|
||||
"""
|
||||
if len(self.points) < 2:
|
||||
return None, None
|
||||
|
||||
return self.points[0], self.points[-1]
|
||||
return (self.points[0][0], self.points[0][1], self.elevations[0]), (self.points[-1][0], self.points[-1][1], self.elevations[-1])
|
||||
|
||||
def get_all_points(self):
|
||||
"""Get all route points.
|
||||
|
||||
@ -13,13 +13,14 @@ class MapRenderer:
|
||||
"""Initialize map renderer."""
|
||||
pass
|
||||
|
||||
def create_route_map(self, points, start_point, end_point, tile_layer='OpenStreetMap'):
|
||||
def create_route_map(self, points, start_point, end_point, waypoints=None, tile_layer='OpenStreetMap'):
|
||||
"""Create an interactive map with the hiking route.
|
||||
|
||||
Args:
|
||||
points: List of (latitude, longitude) tuples for the route
|
||||
start_point: (latitude, longitude) tuple for start
|
||||
end_point: (latitude, longitude) tuple for end
|
||||
waypoints: List of waypoint dictionaries with 'lat', 'lon', 'name', 'elevation'
|
||||
tile_layer: Map tile layer to use ('OpenStreetMap' or 'RudyMap')
|
||||
|
||||
Returns:
|
||||
@ -71,29 +72,43 @@ class MapRenderer:
|
||||
tooltip='登山路線',
|
||||
).add_to(route_map)
|
||||
|
||||
# Add waypoints if provided
|
||||
if waypoints:
|
||||
for waypoint in waypoints:
|
||||
popup_text = f'<b>{waypoint["name"]}</b>'
|
||||
if waypoint.get('elevation'):
|
||||
popup_text += f'<br>海拔: {waypoint["elevation"]} m'
|
||||
|
||||
folium.Marker(
|
||||
location=[waypoint['lat'], waypoint['lon']],
|
||||
popup=folium.Popup(popup_text, max_width=200),
|
||||
tooltip=waypoint['name'],
|
||||
icon=folium.Icon(color='orange', icon='info-sign'),
|
||||
).add_to(route_map)
|
||||
|
||||
# Add start point marker (blue circle)
|
||||
if start_point:
|
||||
folium.CircleMarker(
|
||||
location=start_point,
|
||||
location=(start_point[0], start_point[1]),
|
||||
radius=8,
|
||||
color='blue',
|
||||
fill=True,
|
||||
fill_color='blue',
|
||||
fill_opacity=0.7,
|
||||
popup=start_point,
|
||||
popup=f'<b>起點</b><br>海拔: {start_point[2]} m',
|
||||
tooltip='起點',
|
||||
).add_to(route_map)
|
||||
|
||||
# Add end point marker (blue circle)
|
||||
if end_point:
|
||||
folium.CircleMarker(
|
||||
location=end_point,
|
||||
location=(end_point[0], end_point[1]),
|
||||
radius=8,
|
||||
color='blue',
|
||||
fill=True,
|
||||
fill_color='blue',
|
||||
fill_opacity=0.7,
|
||||
popup=end_point,
|
||||
popup=f'<b>終點</b><br>海拔: {end_point[2]} m',
|
||||
tooltip='終點',
|
||||
).add_to(route_map)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user