Как создать свою ГИС с помощью GIS ToolKit Active

Урок 10. Работа с внешними базами данных

Автор: Дарья Лунченко

Достаточно часто встречаются ситуации, когда при работе с картой нужно использовать данные из дополнительных источников, в частности баз данных различных типов. Это происходит, например, когда какая-то связанная с объектами карты информация может периодически обновляться и нужно хранить и текущее и все предыдущие значения. Например, у нас есть карта стран или административных единиц страны и по ним ведется статистика определенных экономических, демографических или социальных показателей. Другая ситуация, когда наше приложение должно работать вместе с какой-то системой и брать данные из ее базы. Или просто мы получаем данные для карты, оформленные в виде таблиц некоторой СУБД.

Давайте на практическом примере рассмотрим как организовать работу нашего приложения, чтобы получить данные из таблицы какой-то базы данных. Мы возьмем для примера таблицу из Microsoft Access и таблицу формата DBF.

На сегодняшний день еще достаточно много информации может передаваться с помощью формата *.dbf. К примеру, многие форматы данных, используют таблицы *.dbf, для хранения атрибутивной информации. Кроме того, некоторая справочная информация, полученная от внешних источников, может быть тоже оформлена в формате *.dbf.

В тоже время для работы с более сложными данными, представляющими собой наборы взаимосвязанной между собой информации, одной таблицей *.dbf не обойтись и для упорядочивания и анализа таких данных, используются реляционные базы данных. Одним из примеров таких баз данных, могут служить базы данных Microsoft Access.

Предположим, что перед нами поставлена задача формировать на основе данных из внешней таблицы тематические карты. В нашем уроке это будет карта распределения населения страны по административным единицам первого порядка. Наша исследуемая территория в этом уроке - Республика Гватемала. У нас есть карта Гватемала, на которой среди прочих объектов есть территории департаментов, а также данные о численности населения по результатам нескольких последних переписей. Нужно, чтобы программа создавала карту, где каждый департамент будет окрашен в соответствии с численностью населения. При этом пользователю должна быть предоставлена возможность указать, данные какой из переписей используются, как должна быть раскрашена карта и как происходит формирование тематической карты: путем окрашивания полигонов карты-основы или путем создания новой карты.

В конце урока наше приложение будет уметь:

  • считывать данные из таблицы формата *.dbf и *.mdb;
  • формировать на основе этих данных тематическую карту.

Внешний вид приложения и карты до и после выполнения обработки показан на рисунке 1.

а) исходный вид карты
 

б) вид карты после выполнения анализа таблицы с данными о населении

Рисунок 1 - Внешний вид приложения
 

Скачать рабочий образец программы, и ее исходный код можно на страничке "Дополнительные материалы к уроку 10". Если у вас не установлен GIS ToolKit Active, то для запуска приложения вам потребуется загрузить библиотеки GIS ToolKit, и выполнить их регистрацию. Все необходимые библиотеки и короткая инструкция размещены на этой же странице.

 

1. Построение тематической карты на основе таблицы данных DBF

Для того, чтобы создать тематическую карту распределения плотности населения по департаментам Республики Гватемала, была создана таблица формата DBF (табл. 1), в столбцах которой содержатся данные о численности населения каждого департамента согласно данным переписей.

Таблица 1 - Таблица количества населения по годам в Республике Гватемала
 

Существует несколько способов установления связи между объектами карты и таблицей с данными, одним из вариантов является наличие как в таблице, так и в семантике каждого анализируемого объекта одинакового поля. В нашем случае связь производится, посредством добавления в таблицу и в семантику объекта, стандартного геокода ISO 3166-1:GT для каждого департамента (в таблице это поле "Cydigo_ISO", на карте семантика "Код ISO 3166-1").

Для построения тематической карты пользователю необходимо:

  • с помощью стандартных инструментов, выбрать на карте объекты для анализа;
  • выбрать семантику карты, для связывания объектов на карте с данными в таблице;
  • выбрать поле таблицы для связывания с картой;
  • выбрать поле таблицы для построения тематической карты;
  • выбрать вид построения тематической карты: изменять основную карту или создавать новую;
  • выбрать количество диапазонов для разбиения значений легенды карты (рис. 2);
  • в окне легенды карты установить цвет, соответствующий каждому из диапазонов (рис.3).

Рисунок 2 - Диалог настройки работы с внешними данными
 

Рисунок 3 - Диалог настройки легенды карты
 

Реализация данной функции:

  • создадим новую форму DbfForm.cs для настройки работы с внешними данными, добавим на неё стандартные компоненты (рис. 4);

Рисунок 4 - Добавление на форму компонентов
 

  • выделим объекты на карте и сформируем их список, как описано в уроке №3 (п.1, п. 3.2, 3.3);
  • создадим новый класс WorkWithDBF.cs, в котором при нажатии на основной форме на кнопку "Работа с внешними данными", с помощью свойства MapSites.SiteCount, определяем количество открытых пользовательских карт и добавляем их имена, используя функцию ChooseMapBox.Items.Insert, в список для выбора ComboBox;

  • в форме настройки работы с внешними данными DbfForm.cs, при нажатии на кнопку выбора файла DBF, устанавливаем имя файла в соответствующий textBox, а также получаем все семантики выделенных объектов, более подробно о получении характеристик выделенных объектов в уроке 4, п.3;

  • определяем уникальные семантики выделенных объектов, а также получаем значения кодов семантики и ее типов;

  • определяем функцию GetFieldsFromTable для получения названий полей, содержащихся в таблице.dbf;
  • в классе FMapAPI.cs импортируем функции dbOpenTable - для открытия таблицы, dbGetFieldCount - для получения количества полей в записи, dbGetNameAndTypeByNumber - для получения названия и типа поля;

  • с помощью импортируемых функций, открываем таблицу, проходим по каждой записи в ней и получаем ее значение и тип, после чего заполняем соответствующие списки FieldType, TableField, а также выпадающие списки ComboBox, чтобы выбрать поля таблицы для связывания и построения тематической карты;

  • в классе FMapAPI.cs импортируем функции dbGotoFirst - для перехода на первую запись в таблице, dbGetRecordCount - для получения количества записей, dbGetValueAsChar - для считывания данных из таблицы в виде символьной строки; dbGotoNext - для перехода к следующей записи в таблице;

  • при выборе из списка ComboBox значения поля таблицы для связывания с картой, проверяем значение типа поля, которое было получено нами ранее и может иметь значения в виде кодированных символов в соответствии с стандартом ANSI:

    1) 'C' = 67 - Char (1 - 254);

    2) 'D' = 68 - Date (10 символов );

    3) 'F' = 70 - Float (1-20);

    4) 'N' = 78 - Numeric (1-20);

    5) 'L' = 76 - Logical (Yy, Tt, Nn, Ff);

    6) 'M' = 77 - Memo (10 цифр);

    7) 'V' = 86 - Variable (4+4+1+1);

    8) 'P' = 80 - Picture (10 цифр);

    9) 'B' = 66 - Binary (10 цифр);

    10) 'G' = 71 - OLE-объекты (10 цифр);

    11) 'O' = 79 - Double;

  • далее проверяем тип выбранной семантики выделенных объектов, который может быть:

    1) 0 - символьная строка;

    2) 1 - числовое значение;

    3) 10 - имя файла BMP;

    4) 11 - имя файла, обрабатываемого OLE сервером;

    5) 12 - ссылка на произвольный объект карты;

    6) 13 - имя файла паспорта карты;

    7) 14 - имя текстового файла;

    8) 15 - имя файла PCX;

    9) 16 - значение в виде числового кода из классификатора значений для данной семантики;

  • при условии, что выбранное поле таблицы для связывания и выбранная семантика имеют одинаковый тип, с помощью импортированных функций, переходим на первую запись таблицы и, пока не достигнем конца записей, считываем значение поля в виде символьной строки;

  • аналогично считываем значения полей при условии, что оба поля имеют числовое значение;
  • при выборе из списка ComboBox поля таблицы для построения легенды тематической карты, проверяем является ли поле числовым, и с помощью функции MAPAPI dbGetValueAsDouble, получаем значения выбранного поля и записываем их в список RecordValue;

  • при выборе количества диапазонов для разбиения легенды, определяем шаг значений в соответствии с выбранным диапазоном, а также количество интервалов для построения секторов тематической карты;
  • создаем новую форму DbfLegendForm.cs для установления легенды карты, помещаем на ней стандартные элементы TextBox и Button (рис.5);

Рисунок 5 - Добавление на форму элементов
 

  • при нажатии на кнопку "Выполнить" на форме DbfForm.cs, заполняем TextBox полученными значениями диапазонов, определяем шаг для автоматического задания цвета и переводим его в формат COLORREF;

  • динамически создаем на форме легенды кнопки Button, определяем их размер, положение и цвет фона, создаем событие нажатия на кнопку LegendForm.LegendButtonClick;

  • на форме DbfLegendForm.cs помещаем диалог выбора цвета colorDialog, а также создаем функцию LegendButtonClick, с помощью которой пользователь сможет самостоятельно задавать цвет диапазонов;
  • в функции LegendButtonClick, при выборе пользователем цвета, устанавливаем соответствующий цвет фону кнопки, определяем порядковый номер кнопки по ее имени и изменяем список цветов диапазонов;

  • при нажатии на кнопку "Выполнить" на форме DbfLegendForm.cs, определяем две функции: GetThematicMapOnAnotherMap - для построения тематической карты в новой карте; GetThematicMapOnMainMap - для изменения основной карты;

Примечание: для построения тематической карты, мы воспользуемся семантикой объекта с кодом 31002 (OBJCOLOR) - цвет отображения знака RGB, которая позволяет заменить фон объекта на заданный цвет. При построении тематической карты с созданием новой карты на ней будут отображаться только те объекты, которые участвуют в построении тематической карты, при изменении основной карты, к анализируемым объектам будет добавлена соответствующая семантика 31002.

  • в классе FMapAPI.cs импортируем функции: mapCreateAndAppendSiteForMap - для создания пользовательской карты по уже открытой карте; mapSetObjectMap - для перенесения объекта на другую карту;

  • в функции GetThematicMapOnAnotherMap определяем путь к новой карте и ее классификатору и с помощью импортируемой функции, создаем пользовательскую карту по открытой карте;

  • проверяем в какой диапазон легенды попадает считанное из таблицы значение, определяем порядковый номер семантики, выбранной пользователем в качестве семантики для связывания, получаем ее значение, если оно совпадает с значением полученным из таблицы, то с помощью метода Semantic.AddWithValueAsInteger, добавляем в объект семантическую характеристику с кодом 31002 и значением цвета из списка цветов диапазонов, далее копируем объект на новую карту, используя функцию mapSetObjectMap;

  • после данной операции объекты основной карты также содержат семантику для изменения цвета 31002, поэтому далее мы удаляем ее с помощью функции Semantic.Delete;

  • в функции GetThematicMapOnMainMap аналогично с функцией создания тематической карты в новой карте, анализируемым объектам добавляем семантику изменения цвета фона объекта OBJCOLOR 31002;

 

2. Построение тематической карты на основе базы данных Microsoft Access.mdb

Для построения тематической карты на основе базы данных, воспользуемся технологией ADO.NET, представляющей собой ряд пространств имен для взаимодействия с локальными и удаленными базами данных.

Наша база данных формата.mdb будет состоять из одной таблицы, содержащей те же данные, что и таблица в формате DBF в предыдущем пункте.

В ADO.NET используется многоуровневая архитектура, которая оперирует такими ключевыми объектами как: Connection, Command и DataSet.

Одним из основных объектов является поставщик данных (data provider), представляющий собой набор классов ADO.NET, которые позволяют получать доступ к определенной базе данных, выполнять команды SQL и извлекать данные.

В таблице 2 представлены некоторые основные источники данных.

Таблица 2 - Некоторые основные объекты поставщиков данных ADO.NET
 

В нашем случае при работе с базой данных источником данных будет объект DataAdapter, с помощью которого заполняется данными объект DataTable, используемый для представления одной из таблиц базы данных. DataTable содержит в себе DataColumn - представляет один столбец, DataRow - набор строк (записей) заданной таблицы.

При создании тематической карты на основе базы данных у пользователя возникает такой же диалог, как и при использовании таблицы DBF. Отличительной особенностью является, появляющееся дополнительное поле, для выбора из базы данных таблицы для анализа (рис.6).

Рисунок 6 - Диалог настройки работы с базой данных
 

После выполнения операции построения тематической карты, аналогично с п.1, пользователь получит новую тематическую карту или же измененную основную карту.

Перейдем к реализации данной функции:

  • подключаем в форме DbfForm.cs пространство имен System.Data.OleDb для работы с базой данных MS Access;
  • определяем функцию GetFieldsFromBD, в которой создаем строку соединения с базой данных, где параметр Provider применяется для установки имени поставщика для соединения, Data Source - имя файла базы данных Microsoft Access далее, используя объект Connection и его метод Open, устанавливаем соединение с базой данных;

  • для отображения таблиц, которые содержит база данных, динамически создаем на форме Label и ComboBox;

  • с помощью метода класса Connection.GetSchema, получаем схему базы данных и названия содержащихся в ней таблиц, после чего выводим полученные значения в созданный ранее список ComboBox и создаем для него событие изменения его значения;

  • инициализируем класс OleDbDataAdapter, задав инструкцию SQL: "SELECT * FROM "+TableNameBox.Item для выбора всех полей из таблицы, далее с помощью метода OleDbDataAdapter.Fill, заполняем таблицу выбранными данными и, используя свойство DataTable.Columns, получаем значения полей таблицы, вставляя их в выпадающие списки для выбора;

  • при выборе из выпадающего списка поля таблицы для связывания, с помощью свойства DataTable.Columns.DataType, определяем тип выбранного поля и сравниваем его с типом выбранной семантики, если типы полей совпадают, то проходим по всем строкам таблицы DataTable.Rows и заполняем список значениями, соответствующими выбранному столбцу данных;

  • аналогично поступаем при условии, что оба поля имеют числовое значение;
  • при выборе из выпадающего списка поля таблицы для построения легенды определяем, является ли поле числовое, если да, то заполняем список RecordValue, соответствующими значениями;

  • далее используем те же функции, что и при работе с таблицей DBF в п.1.

Мы познакомились с основами работы с данными из таблиц БД посредством функций MAPAPI и стандартных инструментов, основанных на технологии ADO.NET. Опираясь на приведенные примеры, вы теперь можете встроить в свое приложение разные инструменты анализа и тематического картографирования, используя не только данные самой карты, но также данные из различных баз данных.

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

Смотреть: Дополнительные материалы к уроку 10