Смекни!
smekni.com

Программа информационной поддержки создания плана местности (стр. 2 из 5)

Затем вычисляется расстояние между точками, находящимися на Земном шаре, проекции которых мы только что изобразили на нашей карте. Расстояния вычисляются в километрах, радиус Земли берется равным 6371км. Вычисление расстояния производится в том случае, если i не равно 0, те не первое прохождение по циклу. Это условие необходимо, так как мы используем координаты предыдущей точки, чтобы найти расстояние до текущей.

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

Рассматриваются три случая:

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

2)если точки находятся на одинаковой широте, то тут его определение тоже не представляет сложности – он равен разности между большим и меньшим значением долготы, умноженной на поправку cos(f), где f – текущая широта.

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

Сначала находим разность долгот точек, как если бы они находились на одной широте, помножаем на поправку cos(f), и вычисляем линейное расстояние между ними по теореме косинусов (другие две стороны треугольника – радиусы Земли). Таким же образом рассчитываем расстояние между точками, как если бы они находились на одной долготе. Эти расстояния обозначим l1 и l2.

Теперь у нас есть прямоугольный треугольник с катетами l1, l2, гипотенузой которого является расстояние l3. Вычисляем ее по теореме Пифагора. Нашей целью является найти угол a. С помощью теоремы косинусов находим косинус этого угла. Вычислив по нему арккосинус, мы получаем угол! Ниже приводится поясняющий рисунок.


Рис. 4.1. Пояснение к расчету расстояния на различных широте и долготе.

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

Замечание: так как функции косинуса и арккосинуса оперируют с углами, заданными в радианах, в программе производится пересчет радианов в градусы и наоборот. Все эти вычисления приводят к накоплению погрешности.

Все упомянутые формулы даны в Приложении Д.

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

Также на карте отображаются тип объекта для данной точки, если флажок "показывать тип объекта" установлен.

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

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

4.2 Блок-схема алгоритма

Рис. 4.2. Блок-схема алгоритма рисования плана.

5. ПРОГРАММНАЯ РЕАЛИЗАЦИЯ

5.1 Выбор среды разработки программы

Как уже говорилось в "Постановке задачи", для создания этой программы была выбрана среда разработки BorlandC++Builder 5. Это решение обуславливается тем, что в ней процесс создания интерфейса не представляет труда даже для программиста, столкнувшегося с Builder’ом впервые, и там хорошо поставлена работа с базами данных и графикой, что как раз и нужно для разработки нашей программы.

Недостатком на мой взгляд является большой исполняемый код программы – чтобы она работала на машине, где Builder не установлен, необходимо включить в него все используемые библиотеки, из-за чего размер программы становиться в несколько раз больше.

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

5.2 Работа с таблицами

В качестве драйвера базы данных используем Paradox. Этот тип базы данных был выбран, во-первых, потому, что Builder имеет встроенные средства для работы с таблицами Paradox, такие как Borland Database Engine, а также с ним поставляется программа DatabaseDesktop. Во-вторых, преимущество Paradox состоит еще и в том, что в качестве имени базы данных можно указывать путь к каталогу, где находится файл таблицы, причем все таблицы хранятся в отдельных файлах. В третьих, они занимают мало места и являются наиболее простыми из локальных таблиц. В-четвертых, именно таблицы Paradox позволяют создавать ключевые поля.

Чтобы обеспечить работу с таблицей мы установили на форме следующие компоненты:

- сетка DBGrid, с помощью которой мы можем вставлять, удалять, или редактировать данные в таблице, или просто отображать их.

- список DBComboBox, с помощью которого мы можем вставлять данные из таблицы объектов в текущую запись главной таблицы. Перед использованием этого списка его нужно заполнить значениями из таблицы объектов. Для этого при запуске программы проходим по всем ее записям и заносим их содержимое в поле Items этого списка.

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

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

1)Active – показывает, активна ли таблица. Если попытаться обратиться к ней, если это свойство отключено, то программа выдаст ошибку "Cannotperformthisoperationoncloseddataset". При тестировании все возможные ситуации, которые могли привести к этой ошибке, были отслежены и обработаны.

2)DatabaseName – имя базы данных, в качестве него берется путь к каталогу, из которого открыта или создана таблица.

3)TableName – имя таблицы - файл с расширением .db, в котором храниться таблица.

Все эти свойства меняются в процессе выполнения программы.

Компонент Table нужен нам для того, чтобы избавиться от конкретизации. Те мы можем под видом Table открыть любую конкретную таблицу, и изменить при этом только свойства Table, не затрагивая других компонентов. Например, при открытии таблицы мы закрываем и дезактивируем предыдущую, при этом имя базы данных и имя таблицы в свойствах компонента Table удаляются, и открываем и активируем новую, при открытии записав в DatabaseName и TableName новые имена каталога и файла. (См. методы TBOpenFileClick и TBCloseFileClick в Приложении А).

Компоненты DataSourse и Table располагаются на форме, но они видны только при работе с программой в Builder’е.

5.3 Работа с графикой

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

1)Picture – представляет собой объект класса TPicture, который является контейнером для графики любого вида. Т.е. этот компонент может хранить bitmap-графику, иконку или другой вид графики, определенный пользователем. В Picture как раз и находится наш рисунок. С его помощью мы сохраняем в файл полученный рисунок. (См Приложение А, метод TBSaveFileClick). Также следует учесть, что размер Picture и Image могут не совпадать. Об этой проблеме более подробно будет рассказано ниже.

2)Canvas – канва. Весь процесс рисования осуществляется именно на канве компонента Image. Canvas позволяет устанавливать параметры пера, кисти, шрифта, выполнять рисование таких объектов, как линии, прямоугольники, эллипсы, а также выводить текст.

В нашей программе мы используем рисование линий с помощью методов канвы MoveTo и LineTo, рисование точек с помощью Ellipse, а также вывод текста методом TextOut. (см. Приложение А, plandraw).

Т.е. канва позволяет нам работать с функциями WindowsGDI, не обращаясь к ним непосредственно, что значительно упрощает работу с графикой.

5.4 Разработка интерфейса

Разработке интерфейса также следует уделить особое внимание, так как необходимо сделать его удобным для пользователя. Средства Builder'а позволяют легко реализовать интерфейс в стандартах Windows.

Основные элементы стандартного интерфейса Windows-программ:

1) Меню - обеспечивают простой путь для выполнения пользователями логически сгруппированных команд.

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

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

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

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

В соответствие со стандартом Windows, я создала на панели кнопки, соответствующие пунктам меню "Новый", "Открыть", "Сохранить", "Печать".

3) Кнопки – с их помощью пользователь запускает выполнение действия, приписанного этой кнопке.

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

Но так как наша программа выполняет не очень большое количество действий, можно использовать и кнопки. Это удобно хотя бы тем, что, в отличии от меню, они располагаются рядом с тем элементом, по отношению к которому осуществляется вызываемое ими действие (например, кнопки добавления и удаления объектов, находятся рядом со списком объектов, а кнопки масштабирования – рядом с рисунком), что конечно же будет удобно для пользователя.