You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

问题排查与修复建议

  1. 空交叉路口处理:调试日志显示存在空的交叉路口输入,需在sanitizeIntersection函数开头增加空值校验,避免无效请求:
    if (empty(trim($intersection))) {
        addToDebugLog("交叉路口输入为空");
        return null;
    }
    
  2. 地理编码格式优化:调整交叉路口的查询格式,将逗号分隔改为&分隔,更符合地理编码接口的识别逻辑:
    $intersection = str_replace(" and ", " & ", $intersection);
    
  3. 偏移量与街道走向适配:当前偏移逻辑未区分街道走向(东西/南北向),可能导致反向编码返回原街道。可将偏移量调整为0.0005(约50米),同时在获取街道后过滤掉原交叉路口的街道名称。
  4. 反向编码精度提升:将reverseGeocode中的zoom参数调整为18,提升地址解析精度,确保返回最近的街道信息。

内容的提问来源于stack exchange,提问作者user1759356

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 15:52:01