ЭКСПОРТ КАРТЫ В ТАБЛИЦУ БАЗЫ ДАННЫХ POSTGRESQL
Автор: Дарья Лунченко
Примечание:
PostgreSQL — это объектно-реляционная система управления базами данных, с открытым исходным кодом. Она поддерживает большую часть стандарта SQL и предлагает множество современных функций: сложные запросы, внешние ключи, триггер, изменяемые представления, транзакционная целостность, многоверсионность.
PostGIS — расширение объектно-реляционной СУБД PostgreSQL, предназначенное для хранения в базе географических данных.
Создание и наполнение БД PostgreSQL проводилось в программе pgAdmin 4.
В примере демонстрируется создание прикладной потоковой задачи ГИС "Карта" (12-я версия) для экспорта объектов карты в таблицу базы данных PostgreSQL. В качестве исходных данных используется карта Харьковской области, полученная на основе данных OSM и таблица базы данных площадных объектов PostgreSQL, содержащая поля: code (bigint) - уникальный идентификатор, keyname(character(80))- ключ объекта, ownname(character(80)) - собственное название, the_geom(geometry) - метрика объекта (рис.1).
Рисунок 1- Вид таблицы базы данных в pgAdmin4
На карте были выбраны площадные объекты слоя землепользование - новые районы под строительство и экспортированы в таблицу БД polygon_objects (рис.2).
Рисунок 2 - Результат экспорта объектов в таблицу БД
Рассмотрим некоторые аспекты работы с БД PostgreSQL:
1) спецификация OpenGIS определяет два стандартных формата хранения метрики объектов Well-Known Text (WKT) и Well-Known Binary (WKB). В нашей БД поля для хранения метрики имеют тип данных geometry, и представляют собой формат WKB.
Примеры текстового представления (WKT) пространственных объектов приведены ниже:
POINT(0 0)
LINESTRING(0 0,1 1,1 2)
POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
MULTIPOINT(0 0,1 2)
MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4))
MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)),((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))
GEOMETRYCOLLECTION(POINT(2 3),LINESTRING((2 3,3 4)))
Спецификация OpenGIS требует, чтобы внутренний формат хранения пространственных объектов включал идентификатор системы координат (spatial referencing system identifier - SRID). SRID необходим для добавления объекта в базу данных.
Ввод/вывод в этих форматах доступен с использованием следующих интерфейсов:
text WKT = ST_AsText(geometry);
geometry = GeomFromWKB(bytea WKB, SRID);
geometry = GeometryFromText(text WKT, SRID);
2) так как пример является демонстрационным, пользователь может экспортировать только точечные(POINT), линейные(LINESTRING) и площадные(POLYGON) объекты карты. Также при экспорте не учитываются подобъекты;
3) для экспорта данных в существующую БД, используются SQL запросы вида:
- получить имена полей таблицы:
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'
AND table_name NOT IN('spatial_ref_sys') AND table_type = 'BASE TABLE'
- получить тип данных поля таблицы:
SELECT data_type FROM information_schema.columns WHERE table_name = ‘polygon_objects’
AND column_name = ‘ownname’
- получить тип поля геометрии:
SELECT type FROM geometry_columns WHERE f_table_schema = ‘public’
AND f_table_name = ‘polygon_objects’ AND f_geometry_column = ‘the_geom’
SELECT Find_SRID(‘public’, ‘polygon_objects’ ,‘the_geom’ )
- получить поле первичного ключа:
SELECT a.attname, format_type(a.atttypid,a.atttypmod) AS data_type
FROM pg_index I JOIN pg_attribute a
ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
WHERE i.indrelid = ‘polygon_objects’::regclass AND i.indisprimary
- вставить новую запись в таблицу площадных объектов:
INSERT INTO polygon_objects(code, the_geom, keyname, ownname) VALUES(1,
ST_GeomFromText(‘POLYGON((6458421.406 4030936.914,
6458753.732 4031153.353,6458620.269 4031344.155,
6458303.089 4031112.154, 6458421.406 4030936.914))’, ‘S000000009715’, ‘16’)
- вставить новую запись в таблицу линейных объектов:
INSERT INTO line_objects (the_geom, keyname, ownname) VALUES(
ST_GeomFromText(‘LINESTRING(6458393.951 4030525.990,
6458406.265 4030682.104, 6458315.247 4030818.983)’,3395), ‘L00600000001’, ‘3’)
- вставить новую запись в таблицу точечных объектов:
INSERT INTO point_ojects (the_geom, key , ownname) VALUES
(ST_GeomFromText(‘POINT(6458130.369 4030841.558)’, 3395), ‘kiosk’, ‘Кулиничи’)
3. Реализация программы экспорта данных
Проект создан, как библиотека DLL MFC, в среде разработки Microsoft Visual Studio Community, которая может использоваться бесплатно в учебных целях.
Как создать в Microsoft Visual Studio новый проект DLL, и настроить внешние зависимости, вы можете посмотреть здесь.
Структуру проекта вы можете видеть на рис. 3.
Рисунок 3 - Структура проекта DLL экспорта объектов
Работа с БД PostgreSQL осуществляется с помощью набора специальных dll-библиотек (архив libpqdll), которые нужно добавить в папку с утановленной ГИС "Карта". Для доступа к функциям dll-библиотек PostgreSQL необходимо добавить во внешние зависимости указание на папку libpq с h-файлами PostgreSQL.
Также необходимо добавить во внешние зависимости также указание на папку include, содержащую объявление функций интерфейса "MAPAPI". Ссылки на архивы со всеми необходимыми библиотеками приведены в конце страницы.
Функции работы с PostgreSQL:
1) подключение к базе данных, PGconnection - структура подключения к БД:
//выполняем подключение к PostgreSQL
PGconnection = PQconnectdb(conn);
//проверяем статус подключения
if (PQstatus(PGconnection) == CONNECTION_BAD) {
AfxMessageBox(TEXT("Не удается подключиться к базе данных!"));
return;
2) отправка запроса на сервер и ожидание результата PGresult:
//формируем запрос для получения имён таблиц базы данных
PGresultMain = PQexec(PGconnection, "SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public' AND table_name NOT IN('spatial_ref_sys')
AND table_type = 'BASE TABLE'");
if (PQresultStatus(PGresultMain) != PGRES_TUPLES_OK) {
AfxMessageBox(TEXT("Данные о таблицах базы данных не были получены!"));
return;
}
3) определение количества строк и столбцов, получение значения результата запроса:
//определяем количество строк в результате запроса
row_count = PQntuples(PGresultMain);
//определяем количество столбцов в результате запроса
col_count = PQnfields(PGresultMain);
for (int i = 0; i < row_count; i++) {
for (int j = 0; j < col_count; j++)
{//получем значение,соответствующее i-ой строке, j-му столбцу результата запроса
CString tName(PQgetvalue(PGresultMain, i, j));
cbTableName.AddString(tName);
}
}
4) установка пользовательской кодировки:
PQsetClientEncoding(PGconnection, "WIN1251");
Функции MAPAPI используемые в программе:
// Запрос и установка кода EPSG системы координат
mapGetEPSGCode
// Запросить количество семантик в классификаторе
mapGetRscSemanticCount
// Запросить код семантики по порядковому номеру
mapGetRscSemanticCodeByNumber
// Запросить название семантики по порядковому номеру в кодировке UNICODE
mapGetRscSemanticNameByNumberUn
// Запросить тип семантики по её внешнему коду
mapGetRscSemanticTypeByCode
// Подсчитать сколько объектов удовлетворяет условиям
// обобщенного поиска
mapTotalSeekObjectCount
// Запросить признак выделения объектов по обобщённым
// условиям поиска
mapGetTotalSelectFlag
// Cоздать пустой объект векторной карты
mapCreateObject
// Обобщенный поиск объектов по заданным условиям
mapTotalSeekObject
// Запросить характер локализации объекта
mapObjectLocal
// Запрос числа точек метрики объекта/подобъекта
mapPointCount
// Запросить число семантических характеристик у объекта
mapSemanticAmount
// Запросить код семантической характеристики объекта
mapSemanticCode
// Запросить значение семантической характеристики объекта
mapSemanticValue
4. Алгоритм работы пользователя
1) выбрать на карте объекты для экспорта, с одинаковым типом локализации;
2) выбрать меню «Задачи»-> «Запуск приложений»-> «Экспорт объектов карты в таблицу БД PostgreSQL»;
3) ввести параметры подключения к базе данных, и нажать кнопку «Подключиться» ;
4) выбрать таблицу базы данных для экспорта;
5) если таблица содержит поле первичного ключа, то оно автоматически отобразится в «Поле идентификатора», в другом случае поле будет не заполнено;
6) установить поле метрики;
7) при выборе условия «Экспортировать ключ объекта», выбрать поле в которое будет записываться ключ объекта(поле может иметь только тип character);
8) если это необходимо, то установить в соответствие оставшимся полям таблицы семантики: выбрать поле из первого списка, и сделать двойной щелчок мыши на семантике из второго списка. Если объект, который экспортируется, не содержит соответствующую семантику, то в таблицу записывается пустая строка;
9) нажать кнопку «Выполнить», в таблицу экспортируются только те объекты, число точек которых не превышает 100 000.

5. Импорт демонстрационной базы данных PostgreSQL в pgAdmin 4
Для импорта базы данных необходимо:
1) запустить pgAdmin4, перейти в меню «File»->«Preferences»-> «Binary Paths», и установить в соответствующие поля путь к папке bin, расположенной в каталоге установки PostgreSQL;
2) создать новую базу данных, выбрав «Databases»-> «Create»-> «Database»;
3) выбрать базу данных и нажать правой кнопкой мыши, в открывшемся меню, выбрать «Restore», в диалоге указать формат и путь к файлу импорта, нажать кнопку «Restore».

Данные для загрузки:
1) Задача экспорта данных в PostgreSQL (только для ГИС "Карта" 12-й версии): PostgreSqlExportDll.zip
2) dll-библиотеки PostgreSQL (должны быть скопированы в папку установки ГИС "Карта"): libpqdll.zip
3) Исходные файлы примера: codex001.zip
4) h-файлы интерфейса Mapapi для VC++: include.zip
5) h-файлы PostgreSQL: libpq.zip
6) Пример карты для импорта/экспорта: map001.zip
7) Пример базы данных PostgreSQL: db001.zip
Задача экспорта данных в PostgreSQL позволяет использовать любые карты и базы. Добавленные выше архивы с картой и базой приведены только для примера, если у вас нет собственных подходящих данных.