基于OSRM/TypeScript获取最近警局、消防站距离的技术求助
解决方案:获取当前位置到最近警局的驾驶距离
一、修复Nominatim API调用问题
你当前的Nominatim请求未限定搜索范围,导致返回热门地点而非指定坐标附近的警局。需添加radius(搜索半径,单位米)和bounded=1参数强制限定坐标周边搜索,同时优化查询词提升准确性。
修正后的TypeScript代码:
import axios from "axios"; async function getNearestPoliceStation(lat: number, lon: number): Promise<[number, number] | null> { try { // 限定10公里范围内搜索警局,使用精准查询词 const url = `https://nominatim.openstreetmap.org/search?format=json&q=police station&limit=1&lat=${lat}&lon=${lon}&radius=10000&bounded=1&addressdetails=1`; const response = await axios.get(url); if (!response.data || response.data.length === 0) { return null; } const station = response.data[0]; return [parseFloat(station.lat), parseFloat(station.lon)]; } catch (error) { console.error("获取警局位置失败:", error); return null; } }
二、正确使用OSRM API计算驾驶距离
OSRM的nearest/v1/driving仅用于查找最近道路节点,无法直接获取POI(警局);route/v1/driving用于计算两点间路线距离。完整流程:
- 用Nominatim获取最近警局坐标
- 将当前位置与警局坐标传入OSRM route接口,获取驾驶距离
TypeScript完整实现:
import axios from "axios"; async function getDrivingDistance(startLat: number, startLon: number, endLat: number, endLon: number): Promise<number | null> { try { // OSRM route接口格式:起点lon,lat;终点lon,lat const url = `https://router.project-osrm.org/route/v1/driving/${startLon},${startLat};${endLon},${endLat}?annotations=distance&exclude=motorway,toll`; const response = await axios.get(url); if (!response.data.routes || response.data.routes.length === 0) { return null; } // 返回总距离(单位公里) return response.data.routes[0].distance / 1000; } catch (error) { console.error("计算驾驶距离失败:", error); return null; } } // 整合调用 async function getNearestPoliceStationDistance(lat: number, lon: number): Promise<number | null> { const stationCoords = await getNearestPoliceStation(lat, lon); if (!stationCoords) { return null; } const distance = await getDrivingDistance(lat, lon, stationCoords[0], stationCoords[1]); return distance; } // 测试德国坐标 getNearestPoliceStationDistance(49.85349, 8.65859).then(dist => { console.log("到最近警局的驾驶距离(公里):", dist); });
三、Python实现方案
使用requests调用Nominatim和OSRM API,逻辑与TypeScript一致:
import requests def get_nearest_police_station(lat: float, lon: float): try: url = f"https://nominatim.openstreetmap.org/search?format=json&q=police station&limit=1&lat={lat}&lon={lon}&radius=10000&bounded=1&addressdetails=1" response = requests.get(url) response.raise_for_status() data = response.json() if not data: return None station = data[0] return (float(station["lat"]), float(station["lon"])) except Exception as e: print(f"获取警局位置失败: {e}") return None def get_driving_distance(start_lat: float, start_lon: float, end_lat: float, end_lon: float): try: url = f"https://router.project-osrm.org/route/v1/driving/{start_lon},{start_lat};{end_lon},{end_lat}?annotations=distance&exclude=motorway,toll" response = requests.get(url) response.raise_for_status() data = response.json() if not data.get("routes"): return None # 返回公里数 return data["routes"][0]["distance"] / 1000 except Exception as e: print(f"计算驾驶距离失败: {e}") return None def get_nearest_police_station_distance(lat: float, lon: float): station_coords = get_nearest_police_station(lat, lon) if not station_coords: return None distance = get_driving_distance(lat, lon, station_coords[0], station_coords[1]) return distance # 测试德国坐标 distance = get_nearest_police_station_distance(49.85349, 8.65859) print("到最近警局的驾驶距离(公里):", distance)
关键说明
- Nominatim添加
radius和bounded=1是确保返回指定区域结果的核心,可按需调整radius值(单位米) - OSRM route接口参数顺序为经度在前,纬度在后,请勿混淆
- 扩展到消防站时,只需将Nominatim的
q=police station改为q=fire station即可
内容的提问来源于stack exchange,提问作者ArieAI
相关产品推荐
相关产品推荐

