【问题标题】:OpenStreetMap Proximity search using mySQL使用 mySQL 的 OpenStreetMap 邻近搜索
【发布时间】:2011-02-28 08:04:38
【问题描述】:

我只是在玩由 JOSM 生成的我所在地区的数据集。我使用 Osmosis 将它移到了带有 0.6 API 方案的 mySQL DB 中,现在我正在拼命尝试以下方法:

我想获得一个城市的所有街道。 AFAIK OSM 数据中没有标签/关系来确定这一点,所以我尝试使用邻近搜索来获取代表市中心的节点周围半径内的所有节点。

大部分时间我都在看方法here

我得到的是以下 SQL 代码,它应该让我在 id 为 36187002 的节点周围和半径 10 公里内获得最近的 100 个节点。

set @nodeid = 36187002;
set @dist = 10;
select longitude, latitude into @mylon, @mylat from nodes where id=@nodeid limit 1;


SELECT id, ( 6371 * acos( cos( radians(@mylon) ) * cos( radians( latitude ) ) * 
cos( radians(  longitude ) - radians(@mylat) ) + sin( radians(@mylon) ) * sin( radians( latitude ) ) ) ) 
AS distance
FROM nodes HAVING distance < @dist ORDER BY distance LIMIT 0 , 100;

嗯..它不起作用。 :( 我想主要问题是 OSM 经纬度乘以 10.000.000,我不知道如何纠正此功能以使其正常工作。

对此有什么想法吗?非常欢迎所有解决方案/替代方案!

【问题讨论】:

    标签: mysql geo openstreetmap


    【解决方案1】:

    为以double 数据类型表示的纬度和经度添加额外的列可能会更快(因此三角函数有机会) - 您可能想要更进一步并预先计算 xaxis、yaxis 和zaxis 作为列(同样,存储为double

    因此,您的新列是松散的(您可能需要根据需要添加数据类型转换):

    XAxis   = cos(radians(Latitude / 10000000)) * cos(radians(Longitude / 10000000))
    YAxis   = cos(radians(Latitude / 10000000)) * sin(radians(Longitude / 10000000))
    ZAxis   = sin(radians(Latitude / 10000000))
    

    然后,您的邻近搜索变为:

    set @nodeid = 36187002;
    set @dist = 10;
    SELECT XAxis, YAxis, ZAxis
    INTO @CntXAxis, @CntYAxis, @CntZAxis
    FROM nodes
    WHERE id=@nodeid limit 1;
    
    SELECT id, ( 6371 * acos(
                 CASE
                    WHEN nodes.XAxis * @CntXAxis
                  + nodes.YAxis * @CntYAxis
                  + nodes.ZAxis * @CntZAxis > 1.0 THEN 1.0
                  ELSE  nodes.XAxis * @CntXAxis
                  + nodes.YAxis * @CntYAxis
                  + nodes.ZAxis * @CntZAxis 
                 END
               ) AS Distance
    FROM nodes 
    HAVING Distance < @dist 
    ORDER BY distance LIMIT 0 , 100;
    

    【讨论】:

      【解决方案2】:

      我稍微修改了查询,它可以工作。 这是我的代码:

          set @nodeid = 122317;
          set @dist = 10;
          select lon, lat into @mylon, @mylat from nodes where id=@nodeid limit 1;
      
          SELECT id, ( 6371 * acos(
          sin(radians(@mylat)) * sin(radians(lat)) +
          cos(radians(@mylat)) * cos( radians(lat)) * 
          cos(radians(lon) - radians(@mylon)) 
          )) 
          AS distance
          FROM nodes having distance <@dist
      

      我从德国维基百科得到了这个公式,它工作正常。我有一些 ruby​​ 代码拳头,但它也可以用作 sql 查询。

      为了选择一些特殊的节点,我添加了这个

      (select nodes.id,lat,lon,k,v from nodes join node_tags on nodes.id=node_tags.id where k='public_transport') as stations
      

      作为 FROM 条件来指定节点的标签。 (当然它改变了上面代码中对stations.lat/stations.log的lat/log访问。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-27
        相关资源
        最近更新 更多