[Из песочницы] Postgis тип данных Geometry на примере импортированных OpenStreetMap карт
Для моего проекта понадобилось построить пешеходные маршруты и считать их длину.Я решил эту задачу с помощью 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 достаточно, чтобы хранить карту.