2010-06-06 3 views
0

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

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

Большую часть времени я смотрел на подходах here

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

set @nodeid = 36187002; 
set @dist = 10; 
select longitude, latitude into @mylon, @mylat from nodes where [email protected] 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 lats/lons умножаются на 10.000.000, и я не знаю, как я могу исправить эту функцию, чтобы она работала.

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

ответ

0

Возможно, вам потребуется добавить дополнительные столбцы в таблицу для широты и долготы, выраженные в виде типа данных 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 [email protected] 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; 
0

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

set @nodeid = 122317; 
    set @dist = 10; 
    select lon, lat into @mylon, @mylat from nodes where [email protected] 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 

i've получил формулу из немецкой Википедии и она отлично работает. У меня был кубик рубинового кода, но он также работает как 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 в приведенном выше коде.

Смежные вопросы