OpenStreetMap Близкий поиск с использованием MySQL - PullRequest
0 голосов
/ 06 июня 2010

Я просто играю с набором данных моего региона, сгенерированным JOSM. Я переместил его в базу данных mySQL со схемой 0.6 API, используя 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, и я не знаю, как я могу исправить эту функцию, чтобы она заработала.

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

Ответы [ 2 ]

0 голосов
/ 03 июля 2012

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

    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

в качестве условия ОТ для указания тегов узлов.(Конечно, это изменяет доступ lat / log к Station.lat/stations.log в приведенном выше коде.

0 голосов
/ 07 июля 2010

Может быть быстрее добавить дополнительные столбцы в вашу таблицу для широты и долготы, выраженной как тип данных 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;
...