Разработка прикладных задач для ГИС "Панорама"

Урок 2. Особенности работы с интерактивными режимами прикладной задачи на примере задачи обработки мультиполигонов

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

Задача обработки мультиполигонов представляет собой набор режимов, которые позволяют обрабатывать мультиполигоны, создавать новые и получать информацию об уже существующих на карте. Мультиполигоны - это объекты, состоящие из двух и более не пересекающихся внешних контуров, которые в свою очередь могут иметь внутренние контура - подобъекты (рис. 1).

Рисунок 1. Объект - мультиполигон

Созданная нами библиотека для работы с мультиполигонами содержит следующие режимы: проверка объектов и мультиполигонов, поиск и выделение мультиполигонов, разбиение мультиполигона, создание мультиполигона, добавление нового контура в мультиполигон, удаление контура из мультиполигона, исключение объекта из мультиполигона, установка нового главного контура, получение справки о метрике мультиполигонов.

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

Для работы в интерактивном режиме необходимо создать класс - обработчик команд, который является производным от TPanAction, и переопределить в нем набор функций, позволяющих реагировать библиотеке на стандартные действия выбора, производимые пользователем в ГИС "Панорама".

1. Создание обработчика команды

В первом уроке были описаны основные методы класса прикладной задачи TPanTask (MulpiPoligonTask.cpp), один из них GetAction - является методом для подключения обработчика.

Таким образом, экземпляр объекта "обработчик команды" автоматически создаётся объектом "прикладная задача" в методе GetAction.

Для соотнесения идентификатора задачи и обработчика заполняется список обработчиков.

При вызове команды с идентификатором MP_CHECK_TASK, т.е. по нажатию на кнопку панели задач, автоматически вызывается конструктор класса CCheckMultipoligon.

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

Данный режим позволяет, выбрав на карте мультиполигон, разделить его на отдельные простые объекты в соответствии с внешними контурами мультиполигона.

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

Исходный код режима представлен в файле DivideMultipolygon.cpp.

Один из основных методов обработчика является метод Setup, в него мы попадаем сразу после запуска режима, и задаём реакцию на выделенные объекты на карте (т.е. реализуем первый вариант работы):

Реализация второго варианта работы происходит при выборе на карте объекта по двойному щелчку мыши, после этого он выделяется красным пунктиром и генерируется событие SelectObject:

Существует ещё несколько основных событий, для корректной работы обработчика задачи:

1) управлять запретом на выбор объекта по их характеристикам или любым другим условиям можно с помощью функций CanSelectObject (выбор объектов на карте) и CanSelectThisObject (выбор конкретного объекта на карте);

2) для завершения работы обработчика используется метод CanClose при этом запрашивается разрешение на завершение или Quit - безусловное завершение задачи, для того чтобы не завершать, а перезапустить обработчик можно использовать метод Restart.

2. Методы для реализации интерактивной работы пользователя с картой

В некоторых режимах бывает необходимо реагировать не только на выделения объектов на карте, но и на работу левой или правой кнопки мыши. Для этого, рассмотрим режим исключения объекта из мультиполигона.

В данном режиме пользователь должен запустить режим, нажав кнопку на панели задач, затем двойным щелчком левой кнопкой мыши выбрать интересующий мультиполигон, после чего последовательно выбрать одним щелчком левой кнопки мыши внешние контура для исключения.

Исходный код режима представлен в файле ExcludeFromMultipolygon.cpp.

Для перехвата события "отжата левой кнопки мыши", переопределим функцию PANAPI LeftUp, которая работает только при условии, что в функции CanSelectObject запрещён выбор объектов, т.е. возвращаемое ею значение равно 0:

В данной функции:

1) с помощью метода GetPlanePoint, получаем координаты точки нажатия левой кнопки мыши;

2) используя метод ovlGetLocationPoint и текущие координаты, проверяем в какой из внешних контуров мультиполигона попадает точка;

3) если пользователь повторно выбрал контур, то снимаем с него выделение, или же выделяем для исключения (подробнее о функции отрисовки см. далее).

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

1) создать экземпляр структуры PAINTPARM, которая позволяет настроить вид отображения графического объекта;

2) создать экземпляр структуры IMGLINE, для выделения объекта линейным контуром;

Для того чтобы при масштабировании карты или перемещении, выделение контуров мультиполигона не стёрлось, переопределим метод PANAPI Paint, который позволяет рисовать обработчику "на карте".

Чтобы по нажатию на правую кнопку мыши вызвать меню ГИС "Панорама", переопределим методы PANAPI RightUp, RightDown, а для реакции на пункты правого меню "Отменить операцию" и "Выполнить операцию", добавим методы Revert и Commit соответственно.

Возможно и другое использование методов, например, в режиме добавления объекта в мультиполигон, по отжатию правой кнопки мыши RightUp, осуществляется завершение операции, посредством вызова функции Commit . Исходный код данного режима находится в файле InsertInMultipolygon.cpp.

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

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