Создание ГИС на Visual FoxPro средствами MapInfo Professional

Создание ГИС на Visual FoxPro средствами MapInfo Professional

Цель статьи: продемонстрировать основные приёмы работы при создании геоинформационной системы на VFP, с применением MapInfo Professional. Материал ориентирован на IT-специалистов, работающих в земельных комитетах, геодезических или землеустроительных организациях.
Введение
Запуск экземпляра MapInfo
Создание карт
Окно карты MapInfo в вашем приложении
«Знать ГДЕ – это только начало!»

1.Введение

Земля и объекты недвижимости – надёжный и, к тому же, стабильно растущий актив в большинстве государств. Как и всякий ресурс, земельные участки и другие объекты недвижимости необходимо учитывать. Инвентаризация земельных участков, расположенных на них объектов недвижимости, оценка, а в последующем, переоценка земли и строений осложняется интенсивно меняющимися окружающими условиями, общегосударственным и муниципальным законотворчеством. Расчётные операции, проводимые при оценке земли и объектов недвижимости, используют большое количество параметров имеющих географическую смысловую составляющую. Что, вызывает потребность в информационных системах, позволяющих аналитически обрабатывать географическую информацию.

Продукт MapInfo Professional американской компании MapInfo Corporation, предоставляет возможность включать в ваше приложение на VFP векторные карты совместно с инструментами анализа географической информации. MapInfo Professional позволяет выполнять программы MapBaisic – языке программирования, входящем в интегрированную среду разработки MapInfo. Разработчику предоставляется COM интерфейс MapInfo, позволяющий управлять отображением карт, а так же выполнять отдельные команды и программы MapBaisic.

2. Запуск экземпляра MapInfo

После установки MapInfo Professional в реестре OC Windows регистрируется класс «MapInfo.Application», если вы используете MapInfo Runtime, то класс «MapInfo.Runtime». Таким образом, запуск MapInfo:
Public poMI As Object
m.poMI=CreateObject([MapInfo.Application])

Так, как метода [.Quit] COM модель MapInfo не предусматривает, завершение работы экземпляра MapInfo реализуется следующим образом:
m.poMI=Null
Release poMI

3.Создание карт

Для включения векторной карты в ваше приложение, вы должны располагать такой картой. В некоторые дистрибутивы MapInfo Professional включены карты большинства стран и крупных городов Европы, Азии и Северной Америки. Но что делать, если вам нужна межевая карта садово-дачных участков в пригороде какого-нибудь Смоленска или Стамбула. Не знаю как в Турции, но качество материалов, которые вам по умеренной цене может предоставить земельный комитет администрации какого-нибудь Смоленска, вас не устроит. (Может быть, вы даже работаете в этом земельном комитете?) А карта нужна! Но, вы узнаёте, что некая землеустроительная контора проводила геодезическую съёмку и межевание той самой местности, карта которой вам так нужна! (А может, вы работаете в этой землеустроительной конторе?)

Итак, рассмотрим создание карты по координатным данным, полученным геодезической съёмкой. Не вдаваясь в подробности, можно считать что, карта в MapInfo это таблица, каждой строке которой может соответствовать графический объект. С помощью метода [.Do()] COM объекта MapInfo, выполним следующую последовательность команд MapBasic:
Local lcCommandMapBaisic As Character
Text To m.lcCommandMapBaisic TextMerge Noshow

Create Table «myMap» (c1 Integer,c2 Char(100))
File «c:\gis\myMap.TAB»
Type NATIVE
Charset «WindowsCyrillic»

Create Map For «myMap»
CoordSys NonEarth Units «m» Bounds (0,0) (10000,10000)

Browse * From «myMap»
Map From «myMap»

EndText

m.poMI.Do(m.lcCommandMapBaisic)
Release lcCommandMapBaisic

Здесь, первая команда [Create Table …] создаёт таблицу [myMap] с столбцами [c1] типа Integer и [c2] типа Char(100), файл таблицы размещается в каталоге [c:\gis\], тип таблицы – внутренний формат MapInfo, кодовая страница таблицы [WindowsCyrillic]. Следующая команда [Create Map …], создаёт в таблице [myMap] столбец [obj], имеющий специальный тип MapInfo, позволяющий создавать и хранить графические объекты, составляющие карту. Система координат карты задаётся фразой [CoordSys NonEarth], что соответствует декартовой системе координат и подходит для картографирования плана местности. Параметр [Units] задаёт единицу измерения 1 метр, а параметр [Bounds] границы карты. Оставшиеся две команды MapBasic [Browse …] и [Map From …] открывают окна таблицы и карты соответственно и имеют интуитивно понятный синтаксис.

Поле карты создано. Следующий шаг – добавление графических примитивов на карту. Пример:
Local lcCommandMapBaisic As Character
Text To m.lcCommandMapBaisic TextMerge Noshow

Set CoordSys NonEarth Units «m» Bounds (0,0)(10000,10000)

Dim loRegion As Object
Create Region Into Variable loRegion 3
6 (10,100)(100,100)(100,90)(20,90)(20,70)(10,70)
6 (110,100)(120,100)(120,50)(80,50)(80,60)(110,60)
4 (10,50)(70,50)(70,60)(10,60)

Insert Into «myMap» (c1,obj) Values (1,loRegion)
UnDim loRegion

Set Map Zoom Entire

EndText

m.poMI.Do(m.lcCommandMapBaisic)
Release lcCommandMapBaisic

Обратите внимание – первой командой MapBasic [Set CoordSys …] мы устанавливаем соответствие координат создаваемых графических объектов координатному полю карты. Затем, объявляем переменную [loRegion] типа [Object]. Командой [Create Region …] создаём графический объект, сохраняя результат в ранее объявленную переменную. После чего, командой [Insert Into …] вставляем в таблицу [myMap] новую строку, используя 1, как значение для поля [c1] и переменную [loRegion], как значение для поля [obj]. Команда [UnDim …] удаляет переменную [loRegion]. Последняя команда MapBasic [Set Map Zoom Entire] – масштабирует изображение в рабочей области окна карты.

Вот вид окна MapInfo Professional, демонстрирующий результат нашей работы:

Таким образом, располагая координатными данными геодезических работ, не составляет труда программно формировать команды создания графических объектов, подставляя координатные данные геодезических замеров и тем самым, создавать векторные карты и планы местности.

Одно важное замечание. Вы, конечно, обратили внимание, на то обстоятельство, что создавая карту, мы не использовали масштаб. Ничего странного – в векторном картографировании очень удобно создавать карты именно в масштабе 1:1, как мы и сделали, для просмотра карты на экране можно выбрать произвольный масштаб. При печати твёрдых копий карт или планов, принято придерживаться стандартных масштабов 1:200, 1:500, 1:1000, 1:2000 и т.д.

4.Окно карты MapInfo в вашем приложении

Код класса VFP, демонстрирующий приёмы работы с картой MapInfo:
* пример использования
*Public poFM As Form
*m.poFM=Createobject([form4map],[c:\gis\myMap.tab])
*m.poFM.Show()
*————————————————————————
Define Class form4map As Form
map_hwnd=0 && указатель окна карты

Procedure Init
Lparameters lcFileMap
This.AddProperty([Map],Createobject([Mapinfo.Application]))
* окно следующего документа MapInfo
* будет дочерним окном этой формы
This.Map.Do([Set Next Document Parent ]+;
Transform(This.HWnd)+[ Style 1])
* открытие карты
This.Map.Do([Open Table «]+m.lcFileMap+[» ]+;
[Map From «]+Juststem(m.lcFileMap)+[«])
* определение указателя окна карты
This.map_hwnd=Val(This.Map.Eval([WindowInfo(FrontWindow(),12)]))
* объявление функции для управления размером окна карты
Declare Integer MoveWindow In user32 ;
Integer HWnd,;
Integer x,;
Integer y,;
Integer nWidth,;
Integer nHeight,;
Integer bRepaint
Endproc

Procedure Resize
* изменение размеров окна карты до размеров, включающей её формы
MoveWindow(This.map_hwnd,0,0,This.Width,This.Height,0)
Endproc

Procedure Destroy
* завершение работы COM объекта MapInfo
This.Map=Null
Clear Dlls MoveWindow
Endproc

Enddefine

В результате, форма VFP содержит план (карту), см. рис.

Благодаря применению api-функции [MoveWindow] в методе [Resize] формы, при изменении размеров формы карта, находящаяся в окне MapInfo, автоматически масштабируется к размерам родительской формы.

5.«Знать ГДЕ – это только начало!»

Пусть, мы располагаем планом (картой) некоторого населённого пункта, см. рис.:

Предположим, что требуется смоделировать чрезвычайную ситуацию: в результате прорыва плотины на реке Хауки, произойдёт затопление территории до 700 метров от береговой линии. Требуется определить, сколько всего, и какие именно городские строения могут попасть в зону затопления.

Построим 700 метровую буферную зону от правого берега реки Хауки:
Local lcCommandMapBaisic As Character
Text To m.lcCommandMapBaisic TextMerge Noshow

Dim loFlooding_zone as Object

Create Object As Buffer From Selection
Into Variable loFlooding_zone
Width 700 Units «m»

Select c1,c2 From «myMap»
Where myMap.obj WithIn loFlooding_zone
Group By c1,c2
Order by c1

UnDim loFlooding_zone

EndText

* SelectionInfo() – функция MapBasic,
* в зависимости от передаваемого параметра возвращает информацию
* о выделенной области на текущей карте, в данном случае
* количество выделенных объектов
If Val(m.poMI.Eval([SelectionInfo(3)]))>0
m.poMI.Do(m.lcCommandMapBaisic)
Else
Messagebox([Для построения буферной зоны ;
необходимо выбрать объект на карте.],48,[Внимание],10000)
Endif
Release lcCommandMapBaisic

Рассмотрим приведённый код. Команда [Create Object As Buffer …] – создаёт требуемую буферную зону, сохраняя результат в переменной [loFlooding_zone]. Следующая команда – SQL-запрос, где фразу [Where …] следует понимать так: объекты карты [myMap] внутри (WithIn) буферной зоны [loFlooding_zone]. Если на момент выполнения этого скрипта на карте нет выделенных объектов, MapInfo сгенерирует ошибку, по этому, перед отправкой на выполнение, с помощью метода [.Eval(…)] COM модели MapInfo, мы выполняем функцию SelectionInfo() для проверки наличия на карте выделенных объектов.

В результате MapInfo формирует специальный объект [Selection], в котором содержатся все графические объекты карты, попадающие в 700 метровую буферную зону от береговой линии реки Хауки. На рисунке эти объекты помечены красными насечками.

MapInfo поддерживает следующие пространственные операторы над географическими объектами:
Contains
«Содержит»
Объект A содержит объект Б, если центроид Б лежит в границах A.

Contains Entire
«Полностью содержит».
Объект A полностью содержит объект Б, если граница Б полностью лежит внутри границ A.

WithIn
«Внутри».
Объект A лежит внутри объекта Б, если его центроид лежит в границах Б.

Entirely WithIn
«Полностью внутри».
Объект A лежит полностью внутри объекта Б, если его граница полностью лежит внутри границ Б.

Intersects
«Пересекает».
Объект A пересекается с объектом Б, если они имеют хотя бы одну общую точку.

Различие между [Contains] и [WithIn], с одной стороны, и [Contains Entire] и [Entirely WithIn], с другой, состоит в том, что [Contains] и [WithIn] основаны на анализе центроида объекта, а [Contains Entirely] и [Entirely WithIn] — на анализе всего объекта.

Географические функции:
Area(…)
Возвращает площадь объекта

Distance(…)
Возвращает расстояние между двумя точками

ObjectLen(…)
Возвращает длину объекта

Perimeter(…)
Возвращает периметр объекта

Применение в пространственных SQL-запросах MapInfo таких инструментов позволяет проводить географический анализ карты. Девиз разработчиков MapInfo: «Знать ГДЕ – это только начало!»

В завершение, код позволяющий получить данные о выделенных объектах, составляющих буферную зону.
Create Cursor Flooding_obj (id_obj Integer, name_obj Character(70))

Local lnNRows As Integer
m.lnNRows=Val(m.poMI.Eval([SelectionInfo(3)]))

If m.lnNRows>0
For m.i=1 To m.lnNRows
m.poMI.Do([Fetch Rec ]+Transform(m.i)+[ From «Selection»])
Insert Into Flooding_obj (id_obj, name_obj) ;
Values (Val(m.poMI.Eval([Selection.c1])),;
m.poMI.Eval([Selection.c2]))

Endfor
Endif

В данном примере организован перебор всех строк специальной таблицы MapInfo: [Selection], в которую MapInfo помещает все выделенные объекты карты.

На этом всё. Спасибо за внимание.
Замечания принимаются.

 

Комментарии

Комментариев пока нет. Почему бы ’Вам не начать обсуждение?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *