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