Для моего проекта понадобилось построить пешеходные маршруты и считать их длину.
Я решил эту задачу с помощью pgrouting, который в свою очередь опирается на postgis.
Postgis — это расширение к Postgresql, реализующее стандарт OpenGis.
В данном расширение содержится обширный функционал для работы с пространственными данными.
Это позволяет писать интересные приложения.
В частности, OpenStreetMap использует postgis для отображения своих карт.
Постараюсь рассказать о том, как выглядят в postgis, импортированные osm карты.
Я пропущу описание того, как устанавливать postgres и postgis.
Начну с создания базы для хранения пространственных данных.
Создадим базу данных:
create database openstreetmap;
Инициализируем postgis:
create extension postgis;
У нас в базе данных появится таблица spatial_ref_sys, в которой сразу будет почти 4 тысячи записей.
Каждая запись соответствует некоторой пространственной системе координат, которая определяет проекцию долготы и широты на плоскость.
С помощью этой таблицы postgis может конвертировать данные из одной проекции в другую.
Создадим таблицу в нашими пространственными данными:
create table my_map(
id bigserial primary key,
name text,
shape geometry
);
В этой таблице поле shape имеет тип geometry.
В postgis этот тип данных является основным для представления объектов в евклидовой системе координат.
Добавим во вновь созданную таблицу точку, соответствующую центру Санкт-Петербурга:
insert into my_map(name, shape) values ('Центр СПб', ST_Point(30.3250575, 59.9174455));
Функция ST_Point создает объект точку типа geometry.
Также есть ST_MakeLine, ST_MakeEnvelope, ST_MakePolygon и другие полезные конструкторы.
Теперь можно перейти к загрузке osm карты.
Для этого нам понадобится сама карта и osm2pgsql.
Я не буду рассказывать, как устанавливать osm2pgsql.
Это зависит от системы и на windows кажется нетривиальным.
Скачав файл russia-european-part-latest.osm.pbf запускаем импорт:
osm2pgsql -d openstreetmap -U iakov -C 2000 russia-european-part-latest.osm.pbf
Неочевидным мне кажется только параметр -С он определяет размер в мегабайтах кэша, используемого при загрузке.
По умолчанию, он равен 800 и для конкретного файла не хватило, поэтому я его увеличил до 2000.
Сразу после запуска появляется надпись:
NOTICE: table "planet_osm_point" does not exist, skipping
Это не ошибка. Postgis пытается удалить нужные ему таблицы. Так база пустая их еще не существует.
Значительное время занимает обработка данных:
Processing: Node(83577k 1816.9k/s) Way(8382k 37.42k/s) Relation(245290 939.81/s) parse time: 531s
Это обрабатываются объекты osm. Node — это узлы, которые соответствуют точкам на карте. Way — это путь, упорядоченный список узлов.
Relation — отношение, в которые можно объединять другие элементы(узлы, пути, отношения).
Подробнее об этом можно прочитать на openstreetmap wiki.
По окончанию работы в базе появилось 4 таблицы: planet_osm_line, planet_osm_point, planet_osm_polygon, planet_osm_roads.
В planet_osm_point хранятся обработанные узлы, в planet_osm_line хранятся незамкнутые пути, в planet_osm_polygon хранятся замкнутые пути, в planet_osm_roads хранятся пути, которые соответствуют дорогам.
В каждой таблице есть поле way типа geometry.
Можно посмотреть тип геометрии с помощью GeometryType:
openstreetmap=# select GeometryType(way) from planet_osm_point group by GeometryType(way);
geometrytype
--------------
POINT
(1 row)
openstreetmap=# select GeometryType(way) from planet_osm_line group by GeometryType(way);
geometrytype
--------------
LINESTRING
(1 row)
openstreetmap=# select GeometryType(way) from planet_osm_polygon group by GeometryType(way);
geometrytype
--------------
MULTIPOLYGON
POLYGON
(2 rows)
openstreetmap=# select GeometryType(way) from planet_osm_roads group by GeometryType(way);
geometrytype
--------------
LINESTRING
(1 row)
Четырех типов POINT, LINESTRING, POLYGON, MULTIPOLYGON достаточно, чтобы хранить карту.
Автор: corvette