骑行相关
1. 线路规划(路书) 1.1. 需求 可以生成 GPX 文件导入码表 可以根据起点和终点自动规划路线,且能添加途径点 规划路线时可以方便查看海拔和坡度 1.2. 现有 APP 码表类 APP: Garmin Connect 没用过。 iGPSPORT 支持高德规划算法,地图更新及时、规划路线好 可以方便查看海拔和坡度 不支持 GPX 导出,只能配合 iGPSPORT 码表使用。 运动、骑行类 APP: Strava 收费 线路规划比较蠢 Komoot 部分功能收费 行者(推荐) 支持高德规划算法 可以导出 GPX 可以方便查看海拔和坡度 途径点调整不太方便 地图类 APP 百度地图 有路书功能,不支持导出 GPX 高德地图 仅支持导航,不支持导出 GPX 网页类 APP brouter(推荐) BRouter web client bikerouter.de (m11n.de) 采用 OpenStreetMap GIS 数据,大陆路线更新不及时 支持起点到终点线路规划算法 方便添加途径点 方便查看海拔和坡度 可以导出 GPX 大陆访问较慢 gpx.studio(推荐) gpx.studio — the online GPX file editor 采用 OpenStreetMap GIS 数据,大陆路线更新不及时 支持起点到终点线路规划算法(和 brouter 一样) 支持起点到终点线路规划算法 方便添加途径点 方便查看海拔和坡度 可以导出 GPX 大陆访问较慢 支持私有化部署 1.3. gpx.studio 私有化部署 1.3.1. Install gpx.studio Readme: gpx.studio/README.md at main · gpxstudio/gpx.studio · GitHub Run: cd website npm run preview -- --host 1.3.2. Install brouter Readme: brouter/README.md at master · abrensch/brouter · GitHub Download profiles2 Into the misc/profiles2 directory GitHub - poutnikl/Brouter-profiles: My profiles for Brouter offline routing on Android platform Download segments4 Into the misc/segments4 directory Auto download script. (Python) import requests from bs4 import BeautifulSoup import os from urllib.parse import urljoin from concurrent.futures import ThreadPoolExecutor import time failed_files = [] def download_file(file_url, dir_name): attempt = 0 while attempt < 3: try: response = requests.get(file_url, timeout=10) response.raise_for_status() file_name = os.path.basename(file_url) with open(os.path.join(dir_name, file_name), 'wb') as file: file.write(response.content) print(f"Download: {file_name}") return except Exception as e: attempt += 1 print(f"Success: {file_url} Fail: {e},Retry: {attempt}/{3}") if attempt < 3: time.sleep(5) print(f"Download {file_url} fail,max retry has reached") failed_files.append(file_url) base_url = "https://brouter.de/brouter/segments4/" dir_name = "segments4" response = requests.get(base_url) if response.status_code == 200: soup = BeautifulSoup(response.text, 'lxml') rd5_files = soup.select('a[href*="rd5"]') file_urls = [] for rd5_file in rd5_files: file_urls.append(urljoin(base_url, rd5_file.get_text())) if not os.path.exists(dir_name): os.makedirs(dir_name) with ThreadPoolExecutor(max_workers=10) as executor: executor.map(lambda file_url: download_file(file_url, dir_name), file_urls) print(f"Fail Num: {len(failed_files)}") if failed_files: print("\nFiled List:") for file_url in failed_files: print(file_url) else: print(f"Error,status code:{response.status_code}") Run: ./misc/scripts/standalone/server.sh 1.3.3. Modify gpx.studio Routing Service Address File: ./website/src/lib/components/toolbar/tools/routing/Routing.ts async function getRoute( ... ) { let url = `[YOUR BROUTER SERVICE URL]?lonlats=...`; ... }