Files
hiking_assistant/hiking_assistant/map.py

145 lines
4.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# map.py
#
# author: deng
# date: 20251127
import folium
class MapRenderer:
"""Render hiking routes on interactive maps."""
def __init__(self):
"""Initialize map renderer."""
pass
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:
folium.Map: Interactive map object
"""
if not points or len(points) < 2:
return None
# Calculate center of the route
center_lat = sum(p[0] for p in points) / len(points)
center_lon = sum(p[1] for p in points) / len(points)
# Create map obj
route_map = folium.Map(
location=[center_lat, center_lon],
zoom_start=13,
tiles=None,
)
# Add OpenStreetMap layer
folium.TileLayer(
tiles='OpenStreetMap',
name='平面OpenStreetMap',
overlay=False,
control=True,
show=tile_layer == 'OpenStreetMap',
).add_to(route_map)
# Add Rudy Map (魯地圖) layer
folium.TileLayer(
tiles='https://tile.happyman.idv.tw/map/moi_osm/{z}/{x}/{y}.png',
attr='&copy; <a href="https://rudy.basecamp.tw/">魯地圖</a>',
name='等高線(魯地圖)',
overlay=False,
control=True,
show=tile_layer == 'RudyMap',
max_zoom=18,
).add_to(route_map)
# Add layer control to switch between maps
folium.LayerControl(position='topright').add_to(route_map)
# Add the route as a red polyline
folium.PolyLine(
locations=points,
color='red',
weight=4,
opacity=0.8,
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[0], start_point[1]),
radius=8,
color='blue',
fill=True,
fill_color='blue',
fill_opacity=0.7,
popup=folium.Popup(f'<b>起點</b><br>海拔: {start_point[2]} m', max_width=200),
tooltip='起點',
).add_to(route_map)
# Add end point marker (blue circle)
if end_point:
folium.CircleMarker(
location=(end_point[0], end_point[1]),
radius=8,
color='blue',
fill=True,
fill_color='blue',
fill_opacity=0.7,
popup=folium.Popup(f'<b>終點</b><br>海拔: {end_point[2]} m', max_width=200),
tooltip='終點',
).add_to(route_map)
# Fit bounds to show entire route
route_map.fit_bounds(points)
return route_map
def add_hover_marker(self, route_map, position, label='當前位置'):
"""Add a hover position marker to the map.
Args:
route_map: Existing folium map
position: (latitude, longitude) tuple for the marker
label: Label for the marker
Returns:
folium.Map: Map with added marker
"""
if position and route_map:
folium.CircleMarker(
location=position,
radius=10,
color='orange',
fill=True,
fill_color='orange',
fill_opacity=0.9,
popup=label,
tooltip=label,
weight=3,
).add_to(route_map)
return route_map