Дисклеймер


Недавно по работе возникла задача генерации тайлов на основе OSM данных. Поискал, прочитал несколько статей, но везде фигурировали *nix-системы, а у меня был в наличии сервер под управлением Windows. В конце-концов, более-менее внятный туториал нашёлся, но он слегка устарел и не везде подробен, посему пришлось повозиться. После удачного завершения подумал, что мой опыт будет полезен.

Кого заинтересовал, прошу под кат.

Вводные


Установка производилась на чистые Windows 7 и 8.1, безо всякого софта. Понадобится следующее:
  • PostgreSQL (использовал 9.4.4) — БД для хранения геоинформации из дампа OSM.
  • PostGIS (использовал 2.1) — расширение БД для работы с геоинформацией.
  • Osm2pgsql — утилита для импорта дамп OSM данных в БД.
  • Mapnik (использовал 2.2.0) — утилита для генерации тайлов.

Также понадобятся дополнительные инструменты, без которых, однако, ничего не выйдет:
  • Патч для GiST-индексов в PostGIS
  • Python 2.х (использовал 2.7.10) — на нём написаны скрипты генерации тайлов.
  • PROJ.4 — библиотека картографических проекций.
  • SVN-клиент (использовал TortoiseSVN) — для выкачивания скриптов генерации тайлов от OSM, см. ниже.
  • Скрипты генерации от OSM (использовал ревизию 31519)
  • OSM информация: линии побережья и всё такое.

1. Установка и настройка PostgreSQL


Дистрибутив можно взять с офсайта. Установка достаточно тривиальна, однако, есть пара моментов.

Во-первых, возможно, следует изменить директорию, где хранится БД (может потребоваться до терабайта, в случае использования OSM данных для всей планеты). По умолчанию (для версии 9.4) это C:\Program Files\PostgreSQL\9.4\data

Во-вторых, возможно, следует изменить локаль кластера. В моём случае на Russian, Russia. При установке у вас также спросят пароль для сервера PostgreSQL, он ещё понадобится, запомните его.

После установки самого PostgreSQL, запустится StackBuilder, мастер установки расширений для БД. Нужно выбрать два расширения: Spatial Extensions -> PostGIS и Database Drivers -> JDBC. Все настройки при установке по-умолчанию. В процессе установки PostGIS будет запрос на создание системной переменной и ещё пара вопросов, соглашайтесь. После этого нужно перезапустить службу PostgreSQL.

Далее добавьте bin директорию PostgreSQL в PATH. После добавления нужно выйти из системы и войти заново (logoff-login), чтобы настройки применились.

Проверяем корректность установки, понадобится вспомнить пароль, который вы вводили на этапе установки. Находим в программах pgAdmin III и запускаем. В списке серверов будет единственный localhost:5432, подключаемся. Если не удаётся, скорее всего, служба не запущена.

Создаём шаблон для базы геоданных:
CREATE DATABASE template_postgis_20
  WITH ENCODING='UTF8'
       OWNER=postgres
       CONNECTION LIMIT=-1
       LC_COLLATE = 'Russian_Russia.1251'
       LC_CTYPE = 'Russian_Russia.1251'
       TABLESPACE=pg_default;

Добавляем два расширения в шаблон: postgis и postgis_topology. Отключаемся от этой базы.

Создаём базу данных gis на основе шаблона template_postgis_20:
CREATE DATABASE gis
  WITH OWNER = postgres
       ENCODING = 'UTF8'
       TEMPLATE = template_postgis_20
       TABLESPACE = pg_default
       LC_COLLATE = 'Russian_Russia.1251'
       LC_CTYPE = 'Russian_Russia.1251'
       CONNECTION LIMIT = -1;

Берём патч для PostGIS GiST отсюда. Патчим из командной строки:
C:\Users\red>psql -U postgres -d gis -f legacy-postgis-gist.sql
CREATE OPERATOR CLASS

База данных готова.

2. Установка и настройка Osm2pgsql


Можно взять последний релиз с гитхаба и собрать самому, а можно взять готовый артефакт отсюда.

Скачиваем, распаковываем, переименовываем для удобства в osm2pgsql. Добавляем эту директорию в переменную PATH. Logoff-login. Проверяем, что всё работает:
C:\Users\red>osm2pgsql -h

Должна вывестись справка. Берём последний default.style из репозитория на гитхабе.

Всё готово для импорта OSM данных.

Карта планеты в сжатом виде весит ~40 Гб. Для примера можно взять карту Москвы, например, отсюда. Скачиваем.

Для импорта выполняем в командной строке:
C:\Users\red>osm2pgsql -d gis -U postgres -W -H localhost -P 5432 -s -S C:\osm2pgsql\default.style RU-MOW.osm.pbf

Параметр -s, т.е. slim — режим, при котором временные данные хранятся в БД. Это замедляет процесс, увеличивает использование диска, но уменьшает использование оперативной памяти.

Если всё правильно, будет запрос пароля и начнётся импорт дампа в БД. В первых строчках будут всякие предупреждения, не пугайтесь, всё в порядке. После завершения импорта будет выведено что-то вроде:
Osm2pgsql took 160s overall

Геоданные в базе.

3. Установка Python'а 2.x


Скачиваем дистрибутив x86 (потому что бинарники Mapnik для Windows есть только x86) отсюда. Ставим, настройки по-умолчанию, кроме одного: стоит отметить «Добавить python.exe в PATH», или сделать это ручками после установки. Logoff-login.

Проверяем правильность установки:
C:\Users\red>python
Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Питон готов.

4. Установка и настройка Mapnik'а


Опять-таки есть два варианта: или собирать самому из исходников с гитхаба, или взять готовые бинарники здесь. Ищем Windows 32 bit Package, скачиваем, распаковываем в C:\mapnik-v2.2.0.

У них есть довольно подробный мануал по установке в вики. Вкратце: добавить lib и bin директории мапника в PATH, это раз. Создать новую системную переменную PYTHONPATH и присвоить ей путь до C:\mapnik-v2.2.0\python\2.7\site-packages, это два. Поставить этот vcredist, это три. Logoff-login.

Проверяем правильность установки:
C:\Users\red>python
Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>import mapnik
>>>
Возможные ошибки разобраны в вики. Но помимио этого стоит попробовать перенести пути до lib и bin в начало PATH.

И генерим тестовые тайлы:
C:\Users\red>cd C:\mapnik-v2.2.0\demo\python
C:\mapnik-v2.2.0\demo\python>python rundemo.py

Pycairo not available...  will render Cairo formats using alternative method

12 maps have been rendered in the current directory:
- demo.png
- demo256.png
- demo64_binary_transparency.png
- demo128_colors_hextree_no_alpha.png
- demo_high.jpg
- demo_low.jpg
- demo.tif
- demo.pdf
- demo.ps
- demo.svg
- demo_cairo_rgb.png
- demo_cairo_argb.png

Have a look!

Почти всё.

Идём на гитхаб, находим библиотеку PROJ.4, находим бинарники: Prebuilt Win32 executables, DLL including NAD27 grid shift files. Скачиваем, распаковываем (c:\proj). В PATH добавляем путь до bin, в новую переменную PROJ_LIB путь до nad. Logoff-login.

Ещё немного.

Скачиваем скрипты для генерации тайлов из официального svn-репозитория, кладём в c:\mapnik.

Далее, для работы скрипта нужны береговые линии и всякое такое. Для этого есть скрипт get-coastlines.sh, однако он написан на баше и под Windows работать не будет. Но он довольно простой и короткий, поэтому просто повторим все действия ручками.

Скачиваем:
Распаковываем все архивы в директорию в c:\mapnik\world_boundaries.

Последние приготовления. Идём в mapnik\inc, файл settings.xml.inc.template переименовываем в settings.xml.inc.

Файл fontset-settings.xml.inc.template в fontset-settings.xml.inc.

Файл datasource-settings.xml.inc.template в datasource-settings.xml.inc и правим его:
<Parameter name="type">postgis</Parameter>
<Parameter name="password">password</Parameter>
<Parameter name="host">localhost</Parameter>
<Parameter name="port">5432</Parameter>
<Parameter name="user">postgres</Parameter>
<Parameter name="dbname">gis</Parameter>
<Parameter name="estimate_extent">false</Parameter>

Немного поправим скрипт generate_tiles.py:
Блок на строке 193:
if __name__ == "__main__":
    home = os.environ['HOME']
    try:
        mapfile = os.environ['MAPNIK_MAP_FILE']
    except KeyError:
        mapfile = home + "/svn.openstreetmap.org/applications/rendering/mapnik/osm-local.xml"
    try:
        tile_dir = os.environ['MAPNIK_TILE_DIR']
    except KeyError:
        tile_dir = home + "/osm/tiles/"

    if not tile_dir.endswith('/'):
        tile_dir = tile_dir + '/'
заменяем на
if __name__ == "__main__":
    try:
        mapfile = os.environ['MAPNIK_MAP_FILE']
    except KeyError:
        print('MAPNIK_MAP_FILE env var not found! Use default.')
        mapfile = 'C:/mapnik/osm.xml' #Путь по-умолчанию
    try:
        tile_dir = os.environ['MAPNIK_TILE_DIR']
    except KeyError:
        print('MAPNIK_TILE_DIR env var not found! Use default.')
        tile_dir = 'C:/tiles/' #Путь по-умолчанию

    if not tile_dir.endswith('/'):
        tile_dir = tile_dir + '/'

Указываем границы в которых будет производиться генерация тайлов (географические координаты прямоугольника):

На строке 213 перед
    bbox = (-180.0,-90.0, 180.0,90.0)
    render_tiles(bbox, mapfile, tile_dir, 0, 5, "World")
пишем (в нашем случае Москвы)
    bbox = (37.32, 55.57, 37.88, 55.92)
    render_tiles(bbox, mapfile, tile_dir, 17, 17, "Moscow")
    exit() #Для того, чтобы он не пошёл генерить карту мира

Tips&Tricks
Координаты границы берём из файла osm, из которого взяты данные (они будут в самом начале). Из-за того, что файл данных может быть очень большим, обычным текстовым редактором его не откроешь, советую использовать редакторы типа EmEditor (платный) или поставить себе grep.

Указываем пути и запускаем генерацию тайлов:
C:\mapnik>generate_tiles.py

Процесс должен пойти.
Займёт от нескольких минут до недель (в случае всего мира и не самой мощной машины).

Ссылки


0. softwaresimian.com/2012/12/02/openstreetmap-osm-install-on-windows-part-i-the-database
1. switch2osm.org/serving-tiles/manually-building-a-tile-server
2. wiki.openstreetmap.org/wiki/PostGIS/Installation
3. wiki.openstreetmap.org/wiki/Osm2pgsql
4. wiki.openstreetmap.org/wiki/Creating_your_own_tiles
5. habrahabr.ru/post/144675
6. habrahabr.ru/post/203212
7. Русификация данных: habrahabr.ru/post/259141

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


  1. Zverik
    24.08.2015 14:30
    +1

    Рад, что для вашей задачи этот способ сработал.
    Но инструкции, которыми вы пользовались, немного устарели.

    Добавлю две ссылки:
    Инструкция по поднятию PostGIS
    Osm2pgsql лучше собирать из исходников, но вот более свежая сборка 0.85
    Актуальный картостиль osm.org (понадобятся nodejs и npm для установки carto)
    Скрипт для рендеринга тайлов, лучше generate_tiles.


    1. redmanmale
      24.08.2015 15:49

      Спасибо!
      Попробую на досуге, если всё выйдет, напишу обновлённый вариант.

      Насчёт Carto, некоторые рекомендуют OSM Bright, не пользовали его?


      1. shoorick
        24.08.2015 21:02

        Я пробовал OSM Bright. Точнее, не просто пробовал, а успешно нагенерил тайлы в разных стилях (примеры: серый русский, серый недопереведённый английский, бежевый, зелёный) и применяю их на сайтах.

        Но под линуксом, а не под виндой. И список программ отличается: вместо osm2pgsql — imposm, вместо голого мапника — TileMill. Пробовал для начала по инструкции, а потом, разобравшись в питоноподобных конфигах импосма и в синтаксисе CartoCSS, смог кое-какие изменения в стили внести — кое-что я описал в блоге. Тайлмилл может экспортировать, помимо привычных растровых и векторных картинок, в MBTiles — это база SQLite, из которой тайлы легко можно извлечь.


  1. vovochkin
    24.08.2015 15:36

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


    1. freeExec
      24.08.2015 17:31

      Очевидно, что то же самое, ведь он взял готовый стиль.


  1. FSA
    25.08.2015 07:12
    +2

    ИМХО, создание своего тайлового сервера тянет за собой установку нового сервера специально под эти цели. Задача очень ресурсоёмкая. А раз уж всё равно отдельный сервер ставить, то зачем использовать на нём Windows.
    С другой стороны вы показали гибкость открытого исходного кода. Спасибо за труд.


    1. redmanmale
      28.08.2015 19:48

      В моём случае не тянет. Карта нужна для десктопного приложения.
      Для работы с картой использовал библиотеку GMap.NET. Она опенсорсная, есть несколько готовых провайдеров данных, можно свой написать, если нужно будет. Как вариант, в тот же Postgres положить сгенерённые тайлы и пользовать.


      1. FSA
        28.08.2015 19:52

        Я наверно не понял. Вроде речь шла о генерации тайлов., а не о клиенте?


        1. redmanmale
          28.08.2015 21:14

          Да, тайлы нужны для клиентского приложения.
          БД с тайлами ставится вместе с самим приложением на компьютер пользователя, т.е. отдельная машина под тайловый сервер не нужна.


          1. FSA
            28.08.2015 21:16

            Ну что могу сказать… бедный пользователь. Сейчас антивирусы то дико тормозят систему… а тут ещё и тайловый сервер.


            1. redmanmale
              28.08.2015 21:18

              Проверял ведь. Лагов вообще не чувствуется.
              Клиентская машина мощная, БД на SSD, антивируса нет :)