OpenStreetMap Proximity поиск с использованием mySQL

Я просто играю с набором данных моего региона, созданным JOSM. Я переместил его в базу данных mySQL со схемой API 0.6 с помощью Osmosis, и теперь я отчаянно пытаюсь сделать следующее:

Я хочу заполучить все улицы города. AFAIK нет тега / отношения в данных OSM для определения этого, поэтому я попробовал использовать поиск по близости, чтобы получить все узлы в радиусе вокруг узла, представляющего центр города.

В большинстве случаев я рассматривал подходы здесь

Я получил следующий код SQL, который должен предоставить мне ближайшие 100 узлов вокруг узла с идентификатором 36187002 в радиусе 10 км.

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, и я не знаю, как исправить эту функцию, чтобы она работала.

Есть идеи по этому поводу? Все решения / альтернативы приветствуются!


person Chris    schedule 06.06.2010    source источник


Ответы (2)


Возможно, будет быстрее добавить в таблицу дополнительные столбцы для широты и долготы, выраженных как тип данных 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;
person Rowland Shaw    schedule 07.07.2010

Я немного изменил запрос, и он работает. Вот мой код:

    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

У меня есть формула из немецкой Википедии, и она отлично работает. У меня был какой-то кулак с рубиновым кодом, но он также работает как 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 для указания тегов узлов. (Конечно, в приведенном выше коде изменяется доступ lat / log к station.lat/stations.log.

person nailen    schedule 03.07.2012