使用PHP调用Nominatim获取交叉路口各方向相邻街道问题
交叉路口相邻街道获取故障排查
问题描述
无法从交叉路口获取四个方向各两条相邻街道的结果,期望输出格式示例:
交叉路口:6th Ave和12th St
所需输出:
North 1: 11th St
North 2: 10th St
South 1: 12th St
South 2: 13th St
East 1: 7th Ave
East 2: 8th Ave
West 1: 5th Ave
West 2: 4th Ave
实现代码
// 清理交叉路口名称的函数 function sanitizeIntersection($intersection) { $intersection = str_replace(" and ", ", ", $intersection); // 把"and"替换成逗号 $intersection = trim($intersection); // 添加城市和州信息以优化地理编码 $city = "Sioux Falls"; $state = "SD"; return "$intersection, $city, $state"; } // 使用cURL获取地理编码数据的函数 function geocodeIntersection($intersection) { $url = "https://nominatim.openstreetmap.org/search?q=" . urlencode($intersection) . "&format=json&limit=1"; global $debugLog; // 记录使用的URL addToDebugLog("Geocoding URL: $url"); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "User-Agent: RedObsidianSecurity/1.0 (admin@redobsidiansecurity.com)" ]); $response = curl_exec($ch); if (curl_errno($ch)) { addToDebugLog("cURL错误: " . curl_error($ch)); return null; } $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($httpCode !== 200) { addToDebugLog("HTTP错误: $httpCode for $intersection"); return null; } curl_close($ch); $data = json_decode($response, true); if (isset($data[0])) { return [ "lat" => $data[0]["lat"], "lon" => $data[0]["lon"] ]; } else { addToDebugLog("未找到$intersection的地理编码结果"); } return null; } // 获取指定方向两条相邻街道的函数 function getNearbyStreets($lat, $lon, $direction) { $offset = 0.001; // 约100米偏移量 $streets = []; // 第一条街道 $lat1 = $lat; $lon1 = $lon; switch ($direction) { case 'N': $lat1 += $offset; break; case 'S': $lat1 -= $offset; break; case 'E': $lon1 += $offset; break; case 'W': $lon1 -= $offset; break; } $streets[] = reverseGeocode($lat1, $lon1); // 第二条街道 $lat2 = $lat1; $lon2 = $lon1; switch ($direction) { case 'N': $lat2 += $offset; break; case 'S': $lat2 -= $offset; break; case 'E': $lon2 += $offset; break; case 'W': $lon2 -= $offset; break; } $streets[] = reverseGeocode($lat2, $lon2); return $streets; } // 执行反向地理编码的函数 function reverseGeocode($lat, $lon) { $url = "https://nominatim.openstreetmap.org/reverse?format=json&lat=$lat&lon=$lon&zoom=17"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "User-Agent: RedObsidianSecurity/1.0 (admin@redobsidiansecurity.com)" ]); $response = curl_exec($ch); if (curl_errno($ch)) { addToDebugLog("cURL错误: " . curl_error($ch)); return "Unknown"; } $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($httpCode !== 200) { addToDebugLog("HTTP错误: $httpCode for lat: $lat, lon: $lon"); return "Unknown"; } curl_close($ch); $data = json_decode($response, true); return $data['address']['road'] ?? "Unknown"; }
调试日志
运行查询: SELECT id, ClosestIntersection, IncidentNumber FROM Incident WHERE id NOT IN (SELECT pkid FROM nearbystreets) LIMIT 10 处理交叉路口: , Sioux Falls, SD (事件ID: XXXXXXX) 地理编码URL: https://nominatim.openstreetmap.org/search?q=%2C+Sioux+Falls%2C+SD&format=json&limit=1 坐标: 纬度 43.5476008, 经度 -96.7293629 成功插入记录,pkid: 1, 事件ID: XXXXXXX. 处理交叉路口: S MARION RD, W ST JAMES DR, Sioux Falls, SD (事件ID: XXXXXXX) 地理编码URL: https://nominatim.openstreetmap.org/search?q=S+MARION+RD%2C+W+ST+JAMES+DR%2C+Sioux+Falls%2C+SD&format=json&limit=1 未找到S MARION RD, W ST JAMES DR, Sioux Falls, SD的地理编码结果 地理编码交叉路口失败: S MARION RD, W ST JAMES DR, Sioux Falls, SD 处理交叉路口: W RUSSELL ST, N WEST AVE, Sioux Falls, SD (事件ID: CFS25-017102) 地理编码URL: https://nominatim.openstreetmap.org/search?q=W+RUSSELL+ST%2C+N+WEST+AVE%2C+Sioux+Falls%2C+SD&format=json&limit=1
问题排查与修复建议
- 空交叉路口处理:调试日志显示存在空的交叉路口输入,需在
sanitizeIntersection函数开头增加空值校验,避免无效请求:if (empty(trim($intersection))) { addToDebugLog("交叉路口输入为空"); return null; } - 地理编码格式优化:调整交叉路口的查询格式,将逗号分隔改为
&分隔,更符合地理编码接口的识别逻辑:$intersection = str_replace(" and ", " & ", $intersection); - 偏移量与街道走向适配:当前偏移逻辑未区分街道走向(东西/南北向),可能导致反向编码返回原街道。可将偏移量调整为0.0005(约50米),同时在获取街道后过滤掉原交叉路口的街道名称。
- 反向编码精度提升:将
reverseGeocode中的zoom参数调整为18,提升地址解析精度,确保返回最近的街道信息。
内容的提问来源于stack exchange,提问作者user1759356
相关产品推荐
相关产品推荐

