使用mySQL进行OpenStreetMap Proximity搜索

时间:2010-06-06 07:49:43

标签: mysql geo openstreetmap

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

我希望得到一座城市的所有街道。 AFAIK在OSM数据中没有标记/关系来确定这一点,所以我尝试使用邻近搜索来获得围绕代表市中心的节点的半径内的所有节点。

我大部分时间都在研究方法here

我得到的是以下SQL代码,它应该让我在节点周围最近的100个节点,ID为36187002,半径为10km。

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拉特/ lons乘以10.000.000并且我不知道如何纠正这个功能以使其工作。

有关于此的任何想法?所有解决方案/替代品都非常受欢迎!

2 个答案:

答案 0 :(得分:0)

对于表示为double数据类型的纬度和经度,为表添加额外列可能会更快(因此三角函数有机会) - 您可能希望更进一步预先计算x轴, 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;

答案 1 :(得分:0)

我稍微修改了一下这个查询,但它确实有效。 这是我的代码:

    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访问。

相关问题