Дорожная сеть OpenStreetMap
Один из главных параметров карты — это информативность. Грубо говоря, это то, сколько информации можно считать с карты своими глазами. На самом подробном масштабе всё выглядит просто: места на экране много и нужно рисовать всё, что интересно пользователю (есть у нас в файле данных). Хотя тут остаётся важная задача — определить, что же всё-таки ему интересно. На обзорных масштабах всё сложнее: данных слишком много и надо выбрать те, которые повысят информативность и наглядность карты. Одновременно с этим карту нельзя перегружать. Если отобразить всё, то она станет нечитаемой. А пригодных для отображения на обзорном масштабе без предварительной обработки видов интересных пользователю объектов практически нет!
В этой статье я хочу коснуться одного из важных компонентов информативности обзорного масштаба — дорожной сети.
Суть в том, что нужно отобразить красивую дорожную сеть на обзорных масштабах карты. Это делается для того, чтобы карта не казалась пустой. На покупных данных эта задача успешно решается стилями. Когда все данные приходят от одного поставщика, они однородны и можно просто описать, какие дороги нужно рисовать на каких масштабах. Но OpenStreetMap не такой. Карта, которая заполняется пользователями со всего мира, таит в себе массу различий и региональных особенностей в методах картирования. На обзорных масштабах эти различия видны особенно явно. Из-за них не получается нарисовать связную и красивую сеть дорог поверх карты.
Раз на исходные данные положиться нельзя, то нужно придумать собственный механизм для определения дорожной сети, связывающей государства. О нём и пойдёт речь.
Для обозначения дорог в OpenStreetMap используется тег highway
. Он может принимать значения motorway
, trunk
, primary
, secondary
, residental
, service
и другие. Подробнее про тег можно почитать в Wiki проекта.
Тегом motorway обозначают магистрали. В Москве им отмечены платные трассы («Дон», М-11, новая Ленинградка) и некоторые вылетные магистрали (Симферопольское шоссе). Однако этим тегом не отмечен МКАД и большинство вылетных магистралей. В Польше всего пара трасс имеет тег motorway
. Причём одна из них — это объезд города. В Европе и США этот тег более распространён и образует связную дорожную сеть, но многие дороги из США заканчиваются на границе с Канадой. Всё это делает невозможным использование одного тега motorway
.
Дороги, отмеченные тегом motorway
Следующий по важности дорог — тег trunk
. Им отмечены «наиболее важные дороги, которые не являются motorway». При учёте этого тега в Москве появляются МКАД и Бетонка, также отмечены большинство вылетных магистралей. А в Польше отметились только несколько дополнительных объездов городов. Европейская дорожная сеть утратила целостность. Здесь много объездов обозначено как highway=trunk
. В США таких дорог немного, и они почти теряются в развитой сети дорог motorway.
В итоге на карте не получается единой дорожной сети. В разных городах одинаковыми тегами обозначают разные по качеству дороги. Зачастую более «весомые» теги обозначают крохотные участки объездов городов. Так как вся магистраль не отмечена этими тегами, дорога «повисает» в воздухе, что выглядит некрасиво. А сама проблема не нова. Осмеры сталкиваются с ней давно, только воз и ныне там.
Итак, задача — нарисовать дороги на обзорном масштабе. Причём все дороги нарисовать нельзя, так как карта сразу же станет нечитаемой. Получается, что надо поднимать только «главные». Главность дорог можно определять по-разному, я выбрал путь, при котором оцениваю важность дороги по тому, насколько она участвует в построении маршрута из пункта А в пункт B. Для этого я строю маршруты и проверяю, по каким дорогам эти маршруты прошли.
В качестве единицы адресации я выбрал OSM-идентификатор пути (way) того участка, по которому пролегает дорога. Строго говоря, маршрут может пройти только по части элемента OSM, но, так как на обзорных масштабах геометрия упрощается, а сами элементы относительно коротки, я учитываю их полностью.
Для того чтобы определить, какие дороги участвуют в прокладке маршрутов, я использовал OSRM. Правда, для этого его пришлось немного модифицировать. Основную роль играет специальный плагин для сервера, который вместо точек маршрута выводит последовательность wayID
, по которым проходит маршрут. Исходный код этого плагина можно найти в нашем репозитории.
В качестве первого эксперимента я взял все столицы на земле (точки городов с тегом capital=yes
) и построил дороги «каждый с каждым». На обзорный масштаб я поднял все дороги, которые хотя бы раз использовались при прокладке маршрутов. В результате у меня получилась единая сеть, которая хорошо покрыла Европу и даже западную часть России. Но здесь себя снова проявила региональная разница в обычаях картографирования OSM. В России тегом capital=yes
отмечаются все города, которые являются административными центрами областей, например Тула. А вот в США тегом capital
отмечен только город Вашингтон. В результате получившаяся дорожная сеть в США скудна и проходит вся вдоль восточного побережья. Непокрытой осталась и Сибирь.
Также со временем я заметил, что дорожная сеть между столицами получается уж больно плотной. Несмотря на довольно понятное описание тега в его предложении (proposal), которое определяет значения yes/no, самое популярное значение… capital=8
!!! На capital=yes/no
приходится меньше 3,7%! Вот и верь после этого документации OSM. Кроме того, capital=yes
массово используется на Филиппинах. Чтобы разделять местные столицы, нужно рассматривать значение admin_level
. Который тоже сильно различается по миру. В вики даже есть табличка, как читать этот тег.
Раз столиц мало, а после фильтрации их ещё меньше, то добавим в построение обычные города. Но их много, как и дорог между ними, поэтому нужно взять только те города, которые позволят построить дорожную сеть. Для выборки я пользовался двумя критериями: населением города и близостью к уже отобранным пунктам. Параметр близости позволяет отфильтровывать города, которые расположены рядом. Новые дороги между ними будут выглядеть плохо на обзорных масштабах. Учёт численности населения (где он есть) позволит рисовать дороги к наиболее значимым городам.
На примере России получилось, что в европейской части у нас много городов отмечены тегом capital
и все другие города отсеялись. А вот Якутия населена гораздо меньше. Чтобы нарисовать здесь хоть что-то, алгоритм поднимает на обзорную карту посёлок Депутатский с 2831 жителем и дорогу к нему. Но поскольку таких городов на карте заметно больше, то я провожу от них дороги только до нескольких ближайших городов. Это позволяет уменьшить количество обращений к роутеру и упростить сами запросы.
Вот что в результате у меня получилось:
После обновления приложения получившуюся картинку можно будет увидеть на собственном телефоне. Выполненные шаги позволили получить связную сеть дорог на обзорном масштабе карты. Из-за того что карта активно развивается, на ней отмечаются новые дороги и уточняются текущие, посчитанные данные быстро устаревают. По сути, для каждой генерации данных приходится считать дорожную сеть с нуля, а это увеличивает время, необходимое для подготовки данных. Но такая обработка позволяет повысить наглядность карты и преодолеть некоторые врождённые проблемы OpenStreetMap.