Последнее время наблюдаю тенденцию, что всё больше и больше людей сталкиваются с проблемами в отсутствии геоданных. Вернее даже не так, в их закрытости. Если ещё вчера всех устраивали возможности картографических сервисов по расстановке маркеров, то теперь пользователь хочет большего: подсветить улицу, показать дома на ней, посчитать протяжённости рек и т.д. И тут их ожидает сюрприз, казалось бы на карте они всё это видят, но сделать ни чего не могут — это просто картинки. Развитие, что Google.Maps, что Яндекс.Карт остановилось на показе картинок, геокодинге, да навигации.


Шаг вправо, шаг влево и ты в тупике. Единственный путь — воссоздать необходимую геометрию самому. И если нарисовать дорогу и десяток домиков по улице вполне быстро и легко, то скажем сотня другая километров водного пути отбивает всё желание.


Именно в такие трудные моменты за спинами разрекламированных Google и Яндекс становится виден проект OpenStreetMap, и заявляет он: — Данные у меня есть, хочешь которые ты.


Да, возможно не такие полные местами, но именно геоданные, а не весёлые картинки. А это открывает большие возможности по их обработки и анализу. К тому же данные доступны по открытой лицензии ODbL и имеют два главных условия использования: обязательная ссылка на источник данных (участники OpenStreetMap) и в случае публичных производных данных они должны быть также опубликованы по лицензии ODbL.


Поехали


А теперь собственно окунёмся в эти данные. Сегодня наша цель извлечь из них адреса и получить их координаты. Причём будем делать это не поштучно, как это делают геокодеры — вводя адрес и получая координаты, а сразу все имеющиеся. Сохранять результат будем в CSV.


Особенность простого способа в том, что нам не нужны ни какие базы данных, знай себе копируй и вставляй. Но чтобы это было возможно, придётся идти на жертвы. А именно, наше упрощение в том, что адреса мы будем извлекать для заранее оговоренного одного населённого пункта. Мы просто первоначально ограничим наши поиски заданной территорией — нужный населённый пункт вырежем из общего набора данных.


Исходный материал


Итак, отправная точка — это данные OSM о всей планете. Но они очень большие, поэтому если нам не нужно покрытие всей планеты, то берут более локальные территории например на Geofabric разбито по континентам. Для российского сегмента наилучший вариант Gis-Lab, где удобно нарезаны файлы по регионам. Забираем необходимый файл региона в формате pbf.


Инструменты


Для дальнейшей работа нам понадобятся инструменты osmconvert и osmfilter. C помощью первого можно конвертировать данные из разных форматов и обрезать, оставляя только интересующие области, уменьшая тем самым объём и как следствие скорость обработки. Второй предназначен для фильтрации объектов по их свойствам.


Обрезание, хм… Вырезание области


Как и договаривались, нам необходимо локализовать данные только для нашего населённого пункта. С помощью osmconvert, это можно сделать топорно, задав ограничивающий прямоугольник двумя точками. За это отвечает параметр -b=<x1>,<y1>,<x2>,<y2> задаются южно-западная точка и северо-восточная. Если же у населённого пункта сложная форма и прямоугольная вырез не подходит можно создать полигон обрезки из ломанных линий. Параметр для задания такого файл будет -B=file.poly. Формат у него довольно прост: первая строка — название; затем «1» номер контура; далее перечисляем координаты точек, которые бы целиком охватывали наш НП и где последняя точка замыкается на первую; конец контура; конец файла. Больше информации о формате и как его можно получить.


А вот пример файла:


kursk
1
   36.035249   51.838105
   35.991534   51.562810
   36.125976   51.563141
   36.317305   51.681037
   36.333813   51.780274
   36.159021   51.837612
   36.035249   51.838105
END
END

Главное чтобы дома из соседних НП не попали к нам в вырезаемую область. Так же для упрощения превратим все дома в точки, для этого используем ключ --all-to-nodes. Выходной файл попросим сделать в формате o5m (достаточно указать расширение у файла), так как другая утилита умеет работать только с ним.


В итоге первая команда будет у нас такая:


osmconvert.exe -B=city.poly --all-to-nodes RU-Region.pbf -o=1_to-node.o5m

Теперь у нас есть точечные данные только из заданной области. Но там много того, что нам в итоге не нужно, например дороги, парки, заборы и т.д.


Фильтрация


Поэтому следующим шагом мы отфильтруем из всего многообразия только дома содержащие адреса. Дома в OSM обозначаются тегом building, а адресная информация в тегах начинающихся на addr. Так же отбросим информацию об авторе и версии объекта, она нам просто не нужна.


osmfilter.exe 1_to-node.o5m --keep="building AND addr*" --drop-author --drop-version -o=2.building-addr.o5m

Ну вот файл ещё раз уменьшился в размерах и теперь настал момент посмотреть что же там внутри осталось. Самое время превратить его во что-то человеко-читаемое. Как и обещал это будет CSV.


Результат


Воспользуемся всё тем же osmconvert, в котором предусмотрен вывод в CSV. Из параметров стоит заострить внимание на колонки и из каких тегов вставляется в них информация.


osmconvert.exe 2.building-addr.o5m -o=3.addr.csv --csv-headline --csv-separator=; --csv="@id addr:street addr:housenumber @lat @lon"

@id addr:street addr:housenumber @lat @lon
1000000147959515 улица Масалова 25А 51.6522509 36.0337820
1000000147960436 Школьная улица 71 51.6546536 36.0139438
1000000147965426 улица Котова Гора 1 51.7337383 36.1837660

Ну вот, это уже какие-то да геоданные и их можно вставить в ГИС и как-то проанализировать, что и видно на представленной в начале картинке.


Но тема не ограничивается только адресами. На втором шаге можно оставить например остановки общественного транспорта и визуализировать транспортную доступность. Впрочем это уже совершенно из другой статьи...

Поделиться с друзьями
-->

Комментарии (24)


  1. trir
    26.01.2017 23:22
    +3

    те же данные можно получить через Overpass API:
    way(poly:"51.838105 36.035249 51.562810 35.991534 51.563141 36.125976 51.681037 36.317305 51.780274 36.333813 51.837612 36.159021 51.838105 36.035249")[building][~"addr:."~"."];
    out;


    1. za90
      27.01.2017 07:45

      А ссылку на оверпасс-турбо стесняемся давать или хабраэффекта опасаемся?;-)


      1. trir
        27.01.2017 10:07

        там ответ >20мегов, у меня браузер заметно подвисает.
        Лучше использовать https://github.com/mvexel/overpass-api-python-wrapper или типа того…


        1. freeExec
          27.01.2017 10:32

          Да, оверпасс мощный инструмент и при простых задачах очень удобный. Но с ним плохо работать когда сложные запросы или объёмные результаты. Особенно со сложными запросами, когда у тебя нет инструмента для оценки производительности и приходится гадать на кофейной гуще почему так медленно. В отличии от локальной базы где можно посмотреть почему затык и в случае чего создать дополнительные индексы. Поэтому я привык по старинке делать локально и не от кого не зависеть.


          1. trir
            27.01.2017 11:03
            +3

            Тогда лучше сразу загрузить pbf в СУБД и дальше SQL-запросами


  1. Systraner
    27.01.2017 10:22

    Да сама реализация вывода OpenStreet лишает всяких ее возможностей. У меня центр города Россия, Красноярск выводится порядка 8 секунд. Это еще без домов.

    Яндекс 3 сек, гугл около 5 сек до дома.


    1. freeExec
      27.01.2017 10:34

      Не совсем понял, вывода чего и каких возможностей нет?


    1. trir
      27.01.2017 12:47

      сделай свой сервер


    1. Moskus
      27.01.2017 20:04

      Выводится куда?
      Если речь о показе картинок с картой — эта статья вообще не об этом.


  1. 8bitjoey
    27.01.2017 11:04
    -1

    это просто картинки

    В основе OSM тоже «просто картинки». Это просто набор точек, линий и полигонов. Осмысленность они приобретают только с добавлением тегов. Есть у этой area тег «дом»? Значит это дом.

    Что меня смущало в OSM в свое время – так это несогласованность тегов. Если мне надо найти какую-то entity, которая может быть обозначена разными тегами, мне надо выполнять поиск, который бы все вариации учитывал? Или правило по написанию номеров домов. Да, я видел голосование, но все ли здания следуют выбранному варианту, или мне придется еще писать свой универсальный парсер номеров, чтобы потом в UI моего приложения показывать человекочитабельный номер дома. Получается, что я не могу просто взять и использовать данные OSM, надо писать какие-то обертки. Или я не прав и есть какое-то решение?


    1. freeExec
      27.01.2017 11:27
      +2

      В основе OSM тоже «просто картинки». Это просто набор точек, линий и полигонов.

      Нет, в просто картинках нет ни точек, ни линий, ни тем более тегов, есть только пиксели разных цветов. И в этом проблема.
      Что же до несогласованности тегов, то проблема слишком преувеличена. Да, существуют несколько схем обозначения схожих свойств. И тут я не вижу большой проблемы учитывать два варианта для полноты покрытия.
      С номерами домов конечно интересно, но почему вы думаете, что дизайн вывода их в вашем UI идеален и никому не захочется видеть их в другом виде? Поэтому визуальная составляющая всё равно потребует каких-то преобразований.


      1. 8bitjoey
        27.01.2017 13:34

        С номерами домов конечно интересно, но почему вы думаете, что дизайн вывода их в вашем UI идеален и никому не захочется видеть их в другом виде?

        Она и не должна быть идеальной. Я вот о чем: хочу, например, составить какой-то справочник организаций со списком адресов. Понятно, что я использую какой-то свой формат вывода, например пишу полностью «дом 13 корпус 2 строение 4». И вот из голосования я вижу, что в OSM были предложены такие варианты: «48АК2С1», «48Ак2с1», «48А к2с1», «48А к2 с1» и «48а к2 с1». Выбран был предпоследний. Соответственно, я могу написать код, который такой формат преобразует к моему. Проблема в том, что в реальности я могу встретить и другие форматы, а так же те, которые вообще не перечислены выше. И получается, что для того, чтобы корректно работать с этим значением, мне надо прикладывать больше усилий, чем думалось. И ладно еще справочник, его можно отредактировать после генерации, если что-то не распозналось. Сложнее, если надо реализовать поиск по адресу, например.

        Я далеко не OSM гуру и, возможно, преувеличиваю проблему. Но наличие некого стандарта все же было бы большим плюсом.


        1. trir
          27.01.2017 13:42

          Хочешь стандартов — используй ФИАС (КЛАДР)


          1. redmanmale
            27.01.2017 14:40

            Который сам устарел, неполон и местами противоречив?
            У самого была схожая задача, в итоге купили API яндекса.


        1. freeExec
          27.01.2017 14:55
          +2

          Тут какое дело — это не то чтобы проблема конкретно ОСМ, ей подвержены все внешние источники по отношению к процессу. Тут как бы на одной чаше весов полнота данных, на другой код коррекции. Или вы думаете в ФИАС, как предлагают ниже, всё идеально. Да там от региона к региону, кто в лес, кто по дрова. Уже не говорю о фейках когда у них идёт сплошная нумерация от 1 до 999.
          А представьте какой будет головняк, если надо объединить не только Россию, а весь мир :) Поэтому вариант — данные идеальны я бы рассматривал в живой ситуации.


        1. za90
          28.01.2017 14:42

          Добавлю свои три копейки. Только в ОСМ можно играться с форматом вывода так или эдак, у других поставщиков геоданных (а они наверняка существуют, и это не яндекс с гуглом) — только за деньги. Так что просто берёшь и используешь данные ОСМ. И обёртку конечно пишешь, не без этого.


  1. NikiN
    27.01.2017 13:25

    Может кто напишет статью про Overpass


    1. trir
      27.01.2017 13:43
      +2

      А чего там писать? В OSM wiki всё расписано


      1. Zverik
        27.01.2017 16:23

        В вики чёрт ногу сломит. Документация длинная, а учебник всем лень писать.


        1. trir
          27.01.2017 16:26
          +3

          мне хватило http://wiki.openstreetmap.org/wiki/RU:Overpass_API/Overpass_QL


  1. Jenyay
    27.01.2017 15:07

    А есть ли возможность получить, например, все улицы определенного города или все улицы определенного района города?


    1. trir
      27.01.2017 15:10
      +2

    1. freeExec
      27.01.2017 15:13
      +2

      Можно, если обрезать по границе этого определенного хххх и фильтровать по highway. Тут другая проблема, что вывести так же в CSV не выйдет. Но ogr2ogr умеет читать форматы OSM и может выдать shape или geojson.


    1. tbicr
      28.01.2017 11:36
      +2

      Возможность то есть, но нужно уточнить:

      1. какие улицы (нужны ли пешеходные, грунтовки, сервисные и внутредворовые проезды)
      2. нужно понимать, что улица может быть разбита на несколько кусков, которые прийдётся склеивать (схемы осм не во всём бывают хорошы)
      3. есть всякого рода двойные улицы, бульвары, развязки дорог и нужно ли как-то это обрабатывать

      Я как-то пытался связать викиданные данные с осм касательно улиц и сталкивался с этими вопросами, решение получилось страшнованым: https://github.com/opendataby/osm-streets/blob/gh-pages/main.py#L732, а так на скорую руку можно и так http://overpass-turbo.eu/s/lz9.