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

в 10:07, , рубрики: freebsd, gis, mapnik, postgis, карты, метки: , , , ,

Привет! Появилась необходимость на одном из серверов в нашей сети сделать «что-то вроде 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. Ставим TileCache
С TileCache все еще проще — качаем архив отсюда tilecache.org/tilecache-2.11.tar.gz.

Настройка

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

Итак. Сначала нужно получить osm файл. Для этого есть много вариантов, например экспортировать прямо из openstreetmap.org (однако, там есть ограничения на размер области) или
скачать уже готовый экспорт, например отсюда: gis-lab.info/projects/osm_dump/
Этот файл нужно теперь загрузить в базу 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
tar xvzf world_boundaries-spherical.tgz
wget tile.openstreetmap.org/processed_p.tar.bz2
tar xvjf processed_p.tar.bz2 -C world_boundaries
wget tile.openstreetmap.org/shoreline_300.tar.bz2
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
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
unzip 10m-populated-places.zip -d world_boundaries

Выше я обещал рассказать какие утилиты из svn.openstreetmap.org/applications/rendering/mapnik/ нам будут нужны.
Так вот, нам будут нужны:
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
А можно скачать osm.xml, который я уже поправил вот отсюда: pastebin.com/bMsXytcc
Теперь сгенерируем 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
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


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js