2014-11-23

Об OSM

OSM — это OpenStreetMap. Это уникальный в своем роде проект, где, подобно Википедии, подробнейшая карта мира создается энтузиастами. Аж с 2004 года. Когда еще никаких народных карт да мапмейкеров даже не существовало. Ну и, в отличие от упомянутых конкурентов, данные OSM открыты под свободной лицензией, что приводит к тому, что встретить эти данные можно где угодно, где нужна карта.
OSM logo
А сами эти данные изложены в весьма интересной и не очень реляционной модели.
Есть узлы (nodes), с айдишником и парой географических координат (широтой и долготой в WGS 84). Узлы — это, собственно, единственные объекты, имеющие эти самые координаты.
Есть пути (ways), которые объединяют от двух до двух тысяч узлов в некоторую ломаную линию. Путь может представлять какую-нибудь дорогу, например. Путь может быть замкнутым, если первая и последняя точка у него совпадает. Замкнутый путь может представлять, например, здание, или ограничивать определенную площадь.
Есть отношения (relations), которые объединяют узлы, пути и другие отношения в более сложные структуры. Узлы, пути и отношения, входящие в данное отношение являются его членами (members), и как правило обозначены конкретными ролями (roles) в рамках данного отношения. Отношениями может быть выражено все что угодно.
Есть теги (tags), которые придают смысл всем другим объектам. Это наборы пар ключ-значение, навешанные на все эти узлы, пути и отношения. Какие ключи, и что означают их значение, собственно, и является основой OSM, и решается путем длительных споров и переговоров. Но это уже никак не затрагивает саму модель данных. Такой вот конвенционализм.
OSM data model
Есть еще юзеры, ченджсеты, версии и даты изменения. Но это уже контроль версионности основной модели. Это ж по сути вики. Нужно знать, кто, когда и что поменял, чтобы, если что, дать по шапке и откатить обратно.
Чаще всего эту модель представляют в виде XML файла с расширением OSM.
<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="CGImap 0.0.2">
    <bounds minlat="54.0889580" minlon="12.2487570" maxlat="54.0913900" maxlon="12.2524800"/>
        <node id="298884269" lat="54.0901746" lon="12.2482632" user="SvenHRO" uid="46882" visible="true" version="1" changeset="676636" timestamp="2008-09-21T21:37:45Z"/>
        <node id="261728686" lat="54.0906309" lon="12.2441924" user="PikoWinter" uid="36744" visible="true" version="1" changeset="323878" timestamp="2008-05-03T13:39:23Z"/>
        <node id="1831881213" version="1" changeset="12370172" lat="54.0900666" lon="12.2539381" user="lafkor" uid="75625" visible="true" timestamp="2012-07-20T09:43:19Z">
            <tag k="name" v="Neu Broderstorf"/>
            <tag k="traffic_sign" v="city_limit"/>
        </node>
        ...
        <way id="26659127" user="Masch" uid="55988" visible="true" version="5" changeset="4142606" timestamp="2010-03-16T11:47:08Z">
            <nd ref="292403538"/>
            <nd ref="298884289"/>
            ...
            <tag k="highway" v="unclassified"/>
            <tag k="name" v="Pastower Straße"/>
        </way>
        ...
        <relation id="56688" user="kmvar" uid="56190" visible="true" version="28" changeset="6947637" timestamp="2011-01-12T14:23:49Z">
            <member type="node" ref="294942404" role=""/>
            <member type="way" ref="4579143" role=""/>
            ...
            <tag k="name" v="Küstenbus Linie 123"/>
            <tag k="route" v="bus"/>
            <tag k="type" v="route"/>
            ...
        </relation>
        ...
</osm>
XML этот содержит перечисление узлов, путей и отношений с их тегами. Чаще всего этот XML содержит объекты, ограниченные некоторым обрамляющим прямоугольником интересующей нас местности. Но есть и файл с данными по всей планете Земля, так и называется, planet.osm. В несжатом виде он весит сотни гигабайт, что, очевидно, обработать почти невозможно.
Поэтому сейчас переходят на гораздо более компактный формат PBF. Это те же узлы, пути и отношения, но упакованные в бинарном виде с помощью Google Protobuf.
Конвенционализм выражается и в том, что не по всем моментам применения тегов достигнуто окончательное соглашение. И большая часть вики посвящена описанию правил использования тегов.
Помнится, на заре OSM долго спорили, на каком языке должно даваться имя по-умолчанию: на местном наречии или на международном (сиречь, английском). В результате родилась целая куча тегов для имен. И это не считая локализации, которая делается тегами с суффиксами :en:ru и т.п.


Посмотреть теги можно либо на самой карте, либо (что более интересно) перейдя в режим редактирования. Для редактирования вам понадобится какой-нибудь, например, гугловый, аккаунт, и тыкнуть кнопку Edit в браузере (главное, не жмите Save :). Раньше редактирование в основном производилось через десктопные редакторы (вроде JOSM или Merkaator). Теперь же онлайн редакторы (по дефолту запускается Potlatch) предоставляют несколько удобный интерфейс, для работы с типичным набором тегов и отношениями, чтобы создавать уже правильные объекты, соответствующие принятым соглашениям.
Гибкость модели с отношениями и тегами приводит иногда к тому, что некоторые обычные вещи выражаются в OSM как-то не очень. Например, в OSM отсутствует адресный каталог. По идее, дома должны быть связаны с улицами, улицы входить в районы города, города объединяться в области, области входить в страну и т.п. Но в OSM здание связано с улицей лишь косвенно: значение тега addr:street может совпадать с тегом name улицы где-то поблизости. А может и не совпадать. А может, такой улицы (в виде отдельного пути) и нет нигде. А то, что улица находится в таком-то городе можно узнать только по географическим координатам (путь улицы проходит где-то внутри контуров города) и больше никак. Даже совпадения тегов нет. Впрочем, для выражения связи улиц и домов уже придумали несколько "стандартов" отношений. Что, пожалуй, только добавляет путаницы.


С другой стороны, в OSM есть потрясающие своей детальностью данные об административном делении континентов, стран и т.д. и т.п. У тега admin_level, который применяется к многоугольникам, представляющим административные границы есть аж десять значений, которые определены для всех стран и обозначают границы государства, округов, субъектов федерации, районов, городов и т.п.
А вот построить маршрут по дорогам в OSM, как они есть, не получится. Ибо пути в OSM не обязаны объединяться в связный направленный граф. Направление движения и тип дороги — это теги. А перекресток — это отношение со своими тегами. Две дороги на перекрестке не обязаны иметь общий узел в месте перекрестка. А разрешенные направления поворотов задаются еще дополнительными ограничивающими отношениями. Эти навески отношений да гроздья тегов сильно сложнее просто графа. Поэтому все средства для прокладки маршрутов по OSM преобразуют исходную модель в граф, а потом осуществляют поиск уже по графу.


У OSM есть свой рендер, и даже не один. Вы наверняка видели результат его работы где-нибудь в вебе, где рисуется карта. Ибо, опять-таки, OSM — самый свободный вариант.
Все эти OSM данные доступны через API, с большой буквы A, ибо это главное API. Правда, в последнее время API сильно ограничивает как объем данных, выдаваемых по одному запросу, так и количество запросов в секунду. Теперь API позиционируется как место для внесения изменений в OSM. И это единственное место. Все редакторы коммитят сюда. Так достигается целостность данных и истории изменений. А вот для больших или сложных запросов существуют зеркала и даже другие API: например, XAPI или Overpass API.
За главным API скрывается обычный реляционный PostgreSQL, вроде даже без PostGIS. Ну разве что для тегов используется колонка со специальным типом key-value хранилища hstore. Можно запросто заполучить копию подобной базы (без полной истории изменений, только последний слепок). Нужно взять PostgreSQL и Osmosis. Создать схему данных по скриптам из Osmosis. Раздобыть osm (или лучше pbf) нужного вам города или страны (всю планету даже не пытайтесь, только если вам это действительно нужно и есть большой и быстрый сервер). Залить файлик в PostgreSQL с помощью Osmosis. Теперь можно делать запросы к базе и даже сделать своё API :) Только тут всплывают пространственные данные, рассмотренные в прошлый раз. Osmosis позволяет в таблицы с узлами или путями добавить колонки с точками или полигонами. Эту локальную базу можно держать актуальной, если брать файлы обновлений (OSC) и накатывать их.