- PVSM.RU - https://www.pvsm.ru -

*BSD / [Из песочницы] PostGIS + Mapnik + TileCache во FreeBSD

Привет! Появилась необходимость на одном из серверов в нашей сети сделать «что-то вроде openstreetmap.org», но так, чтобы все это продолжало работать и без подключения к Интернету.
К сожалению я не нашел хорошего мануала на «Великом и Могучем» о том, как это реализовать, потому, потратив на это два дня, решил рассказать о том как мне это удалось.

Что было дано:

  • FreeBSD 8.2
  • PostgreSQL 8.4.9
  • Apache 2.2
  • Python 2.7.2

Вообще существует достаточно много вариантов как реализовать требуемое, но я решил остановиться на таком наборе инструментов:

Установка

1. Ставим PostGIS
С этим никаких проблем не возникло, он есть в портах, а именно /usr/ports/databases/postgis
После установки нужно перейти в папку /usr/local/share/postgis/contrib/postgis-1.5 и выполнить там postgis.sql и spatial_ref_sys.sql при помощи утилиты psql
2. Ставим Mapnik
Сам он также есть в портах:/usr/ports/graphics/mapnik
После установки нужно скачать необходимые утилиты, вот тут:
svn.openstreetmap.org/applications/rendering/mapnik/ [3] (какие именно нам будут необходимы расскажу ниже).
3. Ставим TileCache
С TileCache все еще проще — качаем архив отсюда tilecache.org/tilecache-2.11.tar.gz. [4]

Настройка

Естественно настройка куда как увлекательнее установки!
Для начала на картинке поясню как оно все должно работать:
image

Итак. Сначала нужно получить osm файл. Для этого есть много вариантов, например экспортировать прямо из openstreetmap.org [5] (однако, там есть ограничения на размер области) или
скачать уже готовый экспорт, например отсюда: gis-lab.info/projects/osm_dump/ [6]
Этот файл нужно теперь загрузить в базу PostGIS, командой вроде
osm2pgsql -U user RU-SPE.osm
где user это логин к БД, а RU-SPE.osm это карта для загрузки. В моем случае это карта Санкт-Петербурга.
Вывод консоли должен быть примерно таким:

osm2pgsql SVN version 0.80.0 (32bit id space)

Using projection SRS 900913 (Spherical Mercator)
Setting up table: planet_osm_point
Setting up table: planet_osm_line
Setting up table: planet_osm_polygon
Setting up table: planet_osm_roads
Mid: Ram, scale=100

Reading in file: RU-SPE.osm
Processing: Node(1767k 176.7k/s) Way(264k 18.88k/s) Relation(7314 1828.50/s) parse time: 28s

Node stats: total(1767355), max(1633105798) in 10s
Way stats: total(264350), max(150391691) in 14s
Relation stats: total(7314), max(2024096) in 4s

Writing way (264k)

Writing relation (7314)
Committing transaction for planet_osm_point
Sorting data and creating indexes for planet_osm_point
Committing transaction for planet_osm_roads
Sorting data and creating indexes for planet_osm_roads
Committing transaction for planet_osm_line
Sorting data and creating indexes for planet_osm_line
Committing transaction for planet_osm_polygon
Sorting data and creating indexes for planet_osm_polygon
Indexes on planet_osm_roads created in 0s
Completed planet_osm_roads
Indexes on planet_osm_point created in 3s
Completed planet_osm_point
Indexes on planet_osm_line created in 4s
Completed planet_osm_line
Indexes on planet_osm_polygon created in 6s
Completed planet_osm_polygon

Osm2pgsql took 48s overall

Если никаких ошибок нет, то поехали дальше.

Теперь нам нужны границы и береговая линия всего мира — это будет подложкой для нашей карты. Если этого не делать, подложка будет просто одноцветной.
Чтобы держать все в одном месте и в порядке, создадим папку /mapnik/ в своем домашнем каталоге.
Теперь перемещаемся туда и загружаем туда эти границы, для этого воспользуемся командами:

wget tile.openstreetmap.org/world_boundaries-spherical.tgz [7]
tar xvzf world_boundaries-spherical.tgz
wget tile.openstreetmap.org/processed_p.tar.bz2 [8]
tar xvjf processed_p.tar.bz2 -C world_boundaries
wget tile.openstreetmap.org/shoreline_300.tar.bz2 [9]
tar xjf shoreline_300.tar.bz2 -C world_boundaries
wget www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/110m-admin-0-boundary-lines.zip [10]
unzip 110m-admin-0-boundary-lines.zip -d world_boundaries
wget www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/10m-populated-places.zip [11]
unzip 10m-populated-places.zip -d world_boundaries

Выше я обещал рассказать какие утилиты из svn.openstreetmap.org/applications/rendering/mapnik/ [3] нам будут нужны.
Так вот, нам будут нужны:
generate_xml.py (Скорее всего придется подредактировать файл, и заменить import mapnik на import mapnik2 as mapnik)
osm.xml
и папки
inc/
symbols/

Еще может понадобиться скрипт для обновления файла osm.xml, его можно взять тут: github.com/mapnik/mapnik/tree/master/utils/upgrade_map_xml [12]
А можно скачать osm.xml, который я уже поправил вот отсюда: pastebin.com/bMsXytcc [13]
Теперь сгенерируем map.xml, для этого запустим:

./generate_xml.py osm.xml --host localhost --user user --dbname gis --symbols symbols/ --world_boundaries world_boundaries/ --port 5432 --epsg='900913' --accept-none > map.xml
где --accept-none значит принимать непереданные параметры как пустые.

У нас должен получиться достаточно большой файл map.xml

Уже почти все, осталось сконфигурировать только TileCache.

Скачанный архив распакуем в /usr/local/www/data/tilecache. Тут нужно настроить всего два файла: tilecache.cfg и index.html.
В первом нужно объяснить TileCache откуда брать данные (а брать их надо из map.xml, который мы только что сделали).
Для этого добавим туда таки строки:
[osm-map]
type=MapnikLayer
mapfile=/usr/home/user/mapnik/map.xml
spherical_mercator=true
bbox=-20037508.34,-20037508.34,20037508.34,20037508.34
resolutions=2445.984375,1222.9921875,611.49609375,305.748046875,152.8740234375,76.43701171875,38.218505859375,19.1092529296875,9.55462646484375,4.777314,2.388657,1.1943285,0.59716427,0.298582
metaTile=true
metaSize=8,8
metaBuffer=40
levels=12
extent_type=loose

Важные параметры тут:
mapfile=/usr/home/user/mapnik/map.xml путь к файлу с данными
bbox=-20037508.34,-20037508.34,20037508.34,20037508.34 границы области. Это границы для всего мира, подробнее можно прочитать тут: docs.openlayers.org/library/spherical_mercator.html [14]
resolutions=… вот это самое интересное. Эти числа — разрешения разных уровней приближения (zoom level), которые должны быть такими, что при делении на них число 20037508.34*2/256 будет давать степень двойки. Это число — сторона «квадрата» мира деленная на сторону одного тайла (маленького квадратика), которая по-умолчанию равна 256 пикселей.

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

Теперь перейдем к index.html.
В нем нужно настроить функцию init(), например так:

function init(){

map = new OpenLayers.Map("map", {
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
numZoomLevels:14,
maxResolution:156543.03125/64,
units:'m',
projection: "EPSG:900913",
displayProjection: new OpenLayers.Projection("EPSG:4326")
});

layer = new OpenLayers.Layer.WMS( "OSM",
"tilecache.cgi?", {layers: 'osm-map', format: 'image/png'} );
map.addLayer(layer);
map.addControl(new OpenLayers.Control.Permalink());
map.addControl(new OpenLayers.Control.PanZoomBar());
map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false}));
map.addControl(new OpenLayers.Control.Permalink());
map.addControl(new OpenLayers.Control.Permalink('permalink'));
map.addControl(new OpenLayers.Control.MousePosition());
map.addControl(new OpenLayers.Control.OverviewMap());
map.addControl(new OpenLayers.Control.KeyboardDefaults());

if (!map.getCenter()) {
var proj = new OpenLayers.Projection("EPSG:4326");
var point = new OpenLayers.LonLat(30, 60);
map.setCenter(point.transform(proj, map.getProjectionObject()),4);
}
}

Нужно обратить внимание на следующие параметры:
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34) границы должны быть точно такими же, как и в tilecache.cfg.
maxResolution:156543.03125/64 это 2445.984375, т.е. максимальное разрешение.
map.setCenter(point.transform(proj, map.getProjectionObject()),4); установка центра карты и начального зума так, чтобы был виден общий план Санкт-Петербурга.
Мелкий штрих: разрешить апачу выполнять tilecache.cgi:
<Directory "/usr/local/www/apache22/cgi-bin">
AllowOverride None
Options None
Order allow,deny
Allow from all

И chmod 755 tilecache.cgi

Проверяем

Для проверки нужно просто открыть браузером папку tilecache и если все прошло хорошо, увидеть вот такую карту (правда тут еще загружена Ленинградская область):
image

Итого

В итоге должен получиться сервер, умеющий читать данные из базы данных PostGIS и превращать их в тайлы без подключения к Интернету.
Постараюсь ответить на вопросы, если что-то пойдет не так.

Автор: k102


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/freebsd/2394

Ссылки в тексте:

[1] PostGIS: http://postgis.refractions.net/

[2] TileCache: http://tilecache.org/

[3] svn.openstreetmap.org/applications/rendering/mapnik/: http://svn.openstreetmap.org/applications/rendering/mapnik/

[4] tilecache.org/tilecache-2.11.tar.gz.: http://tilecache.org/tilecache-2.11.tar.gz.

[5] openstreetmap.org: http://openstreetmap.org

[6] gis-lab.info/projects/osm_dump/: http://gis-lab.info/projects/osm_dump/

[7] tile.openstreetmap.org/world_boundaries-spherical.tgz: http://tile.openstreetmap.org/world_boundaries-spherical.tgz

[8] tile.openstreetmap.org/processed_p.tar.bz2: http://tile.openstreetmap.org/processed_p.tar.bz2

[9] tile.openstreetmap.org/shoreline_300.tar.bz2: http://tile.openstreetmap.org/shoreline_300.tar.bz2

[10] www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/110m-admin-0-boundary-lines.zip: http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/110m-admin-0-boundary-lines.zip

[11] www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/10m-populated-places.zip: http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/10m-populated-places.zip

[12] github.com/mapnik/mapnik/tree/master/utils/upgrade_map_xml: https://github.com/mapnik/mapnik/tree/master/utils/upgrade_map_xml

[13] pastebin.com/bMsXytcc: http://pastebin.com/bMsXytcc

[14] docs.openlayers.org/library/spherical_mercator.html: http://docs.openlayers.org/library/spherical_mercator.html