/
Введение
Изучение особенностей рельефа морского дна является одной из важнейших задач морской геологии и геофизики, картографии и навигации. Батиметрия - изучение рельефа морского дна, получение данных о глубинах в зоне исследования. Также данный термин может использоваться как совокупность данных о глубинах водного объекта, результат батиметрической съёмки. Подстроение батиметрии применяется для решения множества задач:
Создание подробной карты глубин прибрежной зоны позволяет упростить и обезопасить навигацию морских судов.
Многократные батиметрические съемки позволяют производить исследования динамики рельефа морского дна. Если для обследуемой акватории дополнительно проводить регистрацию параметров волнения и течений, то появляется возможность проследить литодинамику и причины размытия прибрежных участков, а также предсказать тенденцию изменений в будущем. Это может существенно сказаться на экономике региона, если разрушению подвергаются стратегически важные объекты, такие как прибрежные авто и железные дороги или пристани.
В совокупности с данными о форме береговой линии, батиметрия позволяет производить исследования динамики устьев рек и сточных озёр.
Батиметрическая сетка необходима для расчёта периодов Сейш и тягуна: длинноволновых колебаний в бухтах и заливах. Данная работа производится обеспечения безопасности судохождения в портах.
Глобальное исследование глубин океанского дна позволяет сформировать полное представление о рельефе земли.
Целью данной работы является проектирование и разработка программного комплекса, направленного на решение задач автоматизации чтения и подготовки исходных батиметрических и вспомогательных данных, построения батиметрических карт, исследования динамики рельефа, экспорта данных для дальнейшей обработки в различные форматы. Основными пользователями системы являются техники и научные сотрудники лабораторий, занимающихся исследованием цунами, волновой динамики и прибрежных течений, также программа может использоваться работниками портов.
Система, предназначенная для решения задачи автоматизации обработки батиметрических данных, должна обеспечивать автоматизацию за счёт реализации программных модулей, предназначенных для решения следующих задач:
Импорт батиметрическиз данных из исходных треков, получаемых с картплоттера-эхолота, береговых линий из GPS-навигатора а также загрузка сторонних искусственно созданных данных.
Совмещение, компоновка и редактирование данных, исправление ошибок.
Подготовка данных к отображению и обработке: вычитание высоты прилива и сезонных колебаний уровня моря.
Построение и импорт батиметрических карт.
Построение карт сравнения динамики рельефа.
Экспорт данных в различные форматы.
Создаваемое программное обеспечение опирается на анализ предметной области по методике объектно-ориентированного подхода с использованием рационального унифицированного процесса, предложенного авторами языка UML - американской фирмой Rational [6]. На основе результатов анализа должен быть разработан проект программного обеспечения для компьютеризации перечисленных выше функций обработки батиметрических данных.
Итоговый требуемый результат выполнения работы программный косплекс для автоматизации обработки и визуализации батиметрических данных. Спецификация разделов работы дана в таблице 1.
Таблица 1 - Спецификация разделов работы
Обозначение |
Наименование |
Приме-чание |
|
4217.02067988.09 - 2599 12 |
Текст программы |
||
4217.02067988.09 - 2599 13 |
Описание программы |
||
4217.02067988.09 - 2599 33 |
Руководство программиста |
||
4217.02067988.09 - 2599 34 |
Руководство оператора |
||
4217.02067988.09 - 2599 51 |
Программа и методика испытаний |
||
4217.02067988.09 - 2599 90 |
Техническое задание |
||
4217.02067988.09 - 2599 92 |
Организационно - экономическая часть |
1. ТЕХНИЧЕСКОЕ ЗАДАНИЕ
1.1. Общие сведения
1.1.1 Полное наименование программного обеспечения и его условное обозначение
Полное наименование - Разработка программного косплекса обработки, визуализации и анализа батиметрических данных.
Условное обозначение - ПО «СОКО».
1.1.2 Шифр темы
Шифр темы - код 4217.02067988.09 - 2599, «Дипломная работа».
1.1.3 Сведения о разработчике и заказчике
Разработчик - студент группы ВТ-51 ГОУВПО «КнАГТУ» Филипп Андреевич Плеханов.
Заказчик - ИМГИГ ДВО РАН, лаборатория Волновой динамики и прибрежных течений, в лице заведующего лабораторией Петра Дмитриевича Ковалёва.
программа модуль сообщение эксплуатация
1.1.4 Перечень документов, на основании которых создается программное обеспечение
Перечень документов, на основании которых создается программное обеспечение:
задание на дипломное проектирование;
техническое задание;
календарный план-график выполнения этапов работы (см. п. 1.5 данного технического задания).
1.1.5 Плановые сроки начала и окончания работы по созданию программного обеспечения
Плановый срок начала работ: 20 февраля 2012 г.
Плановый срок окончания работ: 10 июня 2012 г.
1.1.6 Сведения об источниках и порядке финансирования работ
Данная работа выполняется в рамках дипломного проектирования, финансирование не производится.
1.1.7 Порядок оформления и предъявления заказчику результатов работы по созданию программного обеспечения
При оформлении и предъявлении заказчику результата работы следует придерживаться следующего порядка действий:
После подписания технического задания создается рабочий вариант программного обеспечения.
Работа осуществляется в соответствии с графиком (см. п. 1.5 данного технического задания). По окончании работ программное обеспечение тестируется и передается заказчику для эксплуатации.
Также заказчику передается комплект технической документации, оформленный в соответствии с ГОСТ 34.201 и ЕСПД.
1.2. Назначение и цели создания программного обеспечения
1.2.1 Назначение программного обеспечения
Разрабатываемая система предназначена для автоматизации обработки, визуализации и анализа батиметрических данных.
1.2.2 Цели создания программного обеспечения
Целями разрабатываемой системы являются:
Ускорение, упрощение и автоматизация чтения и подготовки исходных данных из различных форматов.
Построение двумерных и трёхмерных батиметрических карт для анализа и обработки в научных лабораториях и для навигационных служб портов.
Быстрое построение батиметрической карты в процессе её съемки на основе имеющихся данных
Экспорт данных в различные графические, текстовые и двоичные форматы.
1.3. Характеристики предметной области
1.3.1 Краткие сведения о предметной области
Объектом автоматизации является процесс подготовки, визуализации и анализа батиметрических данных.
Проектируемое программное обеспечение используется для автоматизации следующих объектов:
процесс подготовки батиметрических данных, выбора необходимых треков, исправления ошибок, сведения в единое целое;
процесс построения батиметрических карт в различных вариантах;
процесс получения результатов в графическом, анимированном, текстовом или бинарном формате;
Форматы выходных данных определяются стандартами фирм-производителей оборудования, такими как Garmin и Lowrance, а форматы исходных определяются стандартами на батиметрические карты, принятыми в РАН, а также форматами входных данных других программных комплексов, предназначенных для обработки батиметрических данных, таких как ANI. К основным данным предметной области относятся батиметрические треки, треки-пути, полученные с помощью GPS-навигатора, коэффициенты приливных гармоники и гармоник сезонных изменений уровня моря исследуемых областей.
Структура деятельности процессов обработки батиметрических данных изображена на диаграммах объектно-ориентированной модели данной предметной области, выполненных в нотации языка UML (см. приложение 1, рисунки 1.1-1.5) [2,6,9].
1.3.2 Сведения об условиях эксплуатации объекта автоматизации характеристик окружающей среды
Разрабатываемая система предназначена для использования на персональных IBM-совместимых компьютерах с центральным Intel-совместимом процессором с частотой работы не менее 1ГГц, оперативным запоминающим устройством объёмом не менее 512 Мб, свободным дисковым пространством не менее 25 Мб для хранения программного обеспечения и произвольным, но желательно не менее 500 мб объёмом для хранения промежуточных результатов работы. Обязательным условием является наличие манипулятора типа «мышь», SVGA-адаптера, совместимого со стандартом OpenGL, и монитора с разрешением не менее 1024х768 [7].
1.4. Требования к программному обеспечению
1.4.1 Требования к программному обеспечению в целом
Требования к структуре и функционированию программного обеспечения
Разрабатываемая система должна быть предназначена для автоматизации обработки, визуализации и анализа батиметрических данных, к которым относятся процессы, связанные чтением и исправлением данных, построением триангуляционной сетки, настройкой параметров сцены, экспортом данных.
Разрабатываемая система должна быть представлена в виде единого приложения, входные данные для которого могут располагаться как на том же носителе, так и в локальной сети научного института. Разрабатываемая система должна отображать специфику предметной области и представлять собой единое целое.
К основным входным данным создаваемой системы можно отнести следующие:
батиметрические треки, получаемые посредством съёмки с помощью картплоттера-эхолота;
береговые треки, получаемые с помощью GPS-навигатора;
название региона и его координаты для определения уровня прилива и сезонных изменений уровня моря;
информация о размере обрабатываемого участка, качестве обработки, пределах глубины, позициях камеры, режимах отображения, количестве изолиний и прочие настройки состояния системы.
Выходными данными разрабатываемой системы являются:
батиметрические карты и карты разницы для выбранных участков в чёрно-белом и цветом варианте;
изображения трёхмерных срезов батиметрических данных, показанные с определённого ракурса;
видео-файлы, представляющие собой съёмку трёхмерной батиметрической карты с различных ракурсов;
батиметрические треки и сетки, готовые для отображения в программе Google Earth;
батиметрические сетки в формате.inf для обработки в программном комплексе ANI.
Требования к численности и квалификации персонала
С программным обеспечением может работать техник или научный сотрудник, в должностные обязанности которого входит обработка батиметрических данных, а также любой человек, имеющий необходимость получить батиметрическую карту региона при наличии исходных данных. Для работы с программой необходимы навыкаи оператора ПЭВМ. Система предлагается для использования следующими категориями пользователей: техники научных лабораторий, научные сотрудники; практиканты, аспиранты, кандидаты и доктора наук, занимающиеся опасными морскими явлениями; сотрудники портов и лица, занимающиеся рыболовством. Данные группы пользователей условны, в программе не предусматривается распределение прав доступа с разным уровнем полномочий на управление данными.
Требования к надежности
В случае ошибок, вызванных некорректными действиями пользователя при работе, программа должна выдавать соответствующее сообщение и продолжать нормальную работу.
Должно быть предусмотрено динамическое сохранение последних изменяемых данных для предотвращения потерь информации в случаях сбоя в работе технических средств и различных аварийных ситуациях.
Требования к эргономике и технической эстетике
Создаваемое программное обеспечение должно обеспечить дружественный интерфейс пользователя - стандартное расположение компонентов управления (рекомендованное для данной операционной системы), дублирование команд, наличие всплывающих подсказок. При организации интерфейса необходимо использовать цвета в соответствии с правилами технической этики и текущей системной пользовательской палитры. Интерфейс пользователя должен обеспечивать эффективное взаимодействие пользователя с системой с минимальной необходимостью обращения к дополнительным справочным материалам.
Требования к эксплуатации и техническому обслуживанию
Условия и режим эксплуатации ПО определяются условиями эксплуатации использующихся технических средств. Техническое обслуживание ПО не требуется.
Требования к допустимым площадям для размещения персонала и технических средств ПО, к параметрам сети энергоснабжения определяются требованиями использующегося аппаратного обеспечения.
Требования к защите информации от несанкционированного доступа
Защита информации от несанкционированного доступа не предусмотрена.
Требования по сохранности информации при авариях
Сохранность данных при авариях не гарантируется в случае непредвиденного прерывания работы программы.
Программное обеспечение должно оставаться работоспособным при восстановлении системы после аварий (за исключением случаев, не зависящих от программного обеспечения: повреждение дисковой подсистемы, повреждение файловой структуры).
Требования к защите от влияния внешних воздействий
ПО должно быть устойчивой к наличию и параллельной с ней работе на той же ЭВМ другого программного обеспечения. Разрабатываемая программа должна позволять работать с системой любой рабочей станции, которая подключена к локальной сети предприятия и является частью домена.
Требования к защите от физических внешних воздействий определяются аналогичными требованиями, предъявляемыми к используемому аппаратному обеспечению.
Требования к стандартизации и унификации
ПО должно предоставлять пользователю стандартный графический интерфейс операционной системы Microsoft Windows. Сопутствующая программная документация, поставляемая с программным обеспечением, должна быть оформлена в соответствии со стандартом ЕСПД.
1.4.2 Требования к функциям, выполняемым системой
Разрабатываемое приложение должно обеспечивать выполнение следующих основных функций:
Импорт батиметрическиз данных из исходных треков, получаемых с картплоттера-эхолота, береговых линий из GPS-навигатора а также загрузка сторонних искусственно созданных данных.
Совмещение, компоновка и редактирование данных, исправление ошибок.
Подготовка данных к отображению и обработке: вычитание высоты прилива и сезонных колебаний уровня моря.
Построение и импорт батиметрических карт.
Построение карт сравнения динамики рельефа.
Экспорт данных в различные форматы.
1.4.3 Требования к видам обеспечения
Требования к математическому обеспечению
В основе разрабатываемого программного обеспечения должна находиться корректная математическая модель обработки данных: алгоритмы триангуляции, размытия, вычисления приливов и сезонных изменений уровня должны корректно преобразовывать данные. В случае наличия аппроксимации данных диапазон отклонения должен быть не выше уровня, допустимого стандартами Российской Академии Наук.
Требования к информационному обеспечению
Создаваемая система должна использовать файловую базу данных. В структуру базы данных должны входить: файлы, содержащие данные о приливах на определённый период времени для определённых участков местности; файлы, содержащие информацию о годовых, третьгодовых и четвертьгодовых гармониках колебаний уровня моря для определённых участков; вспомогательные файлы, содержащие растровые изображения цифровых подписей к изолиниям.
Требования к лингвистическому обеспечению
Программное обеспечение и интерфейс пользователя в среде разработки приложений Borland C++ Builder 6 [11, 12]. В своей работе программное обеспечение не требует установки никаких сторонних библиотек, отсутствующих в стандарте Microsoft Windows.
Языком ввода-вывода данных, манипулирования данными, способа организации диалога с пользователем является русский язык.
Требования к программному обеспечению
Перечень программных средств, необходимых для проектирования и функционирования системы:
операционная система Microsoft Windows версии не ниже 98;
редактор диаграмм и блок-схем Microsoft Visio;
среда разработки приложений Borland C++ Builder 6;
Raize Components - набор визуальных компонентов для Delphi / C++Builder версии не ниже 4.3.2;
приложение для предвычисления приливов wxtide версии не ниже 4.7;
Требования к техническому обеспечению
Для создания данного программного обеспечения необходимы:
персональный компьютер совместимый с IBM PC с тактовой частотой процессора не ниже 1000 МГц, оперативная память 1024 Мб и более;
накопитель данных со свободным объёмом не менее 3 Гб;
видеокарта и монитор, поддерживающие разрешение 1024*768 точек и выше, с частотой обновления не менее 60 Гц, а также поддерживающие стандарт OpenGL;
устройства ввода клавиатура и манипулятор «мышь» (стандартные);
1.5 Состав и содержание работ по созданию программного обеспечения
Этапы выполнения работ по созданию «Регистрация компьютерной техники» приведены в таблице 1.1.
Таблица 1.1 - Этапы выполнения работ
Этап |
Дата начала |
Срок окончания |
||
Минимальный |
Максимальный |
|||
Разработка и утверждение технического задания |
09.02.12 |
18.02.12 |
23.02.12 |
|
Проектирование системы |
21.02.12 |
11.03.12 |
14.03.12 |
|
Программная реализация |
14.03.12 |
21.04.12 |
25.04.12 |
|
Оформление технической документации (Техническое задание) |
25.04.12 |
02.05.12 |
03.05.12 |
|
Оформление технической документации (Описание программы) |
03.05.12 |
07.05.12 |
08.05.12 |
|
Оформление технической документации (Теоретическое описание) |
08.05.12 |
10.05.12 |
11.05.12 |
|
Оформление технической документации (Текст программы) |
11.05.12 |
13.05.12 |
14.05.12 |
|
Оформление технической документации (Руководство программиста) |
14.05.12 |
16.05.12 |
17.05.12 |
|
Оформление технической документации (Руководство пользователя) |
17.05.12 |
21.05.12 |
22.05.12 |
|
Оформление технической документации (Программа и методика испытаний) |
22.05.12 |
24.05.12 |
25.05.12 |
|
Оформление технической документации (Организационно-экономическая часть) |
27.05.12 |
28.05.12 |
10.06.12 |
1.6 Порядок контроля и приемки программного обеспечения
При приёмке системы проводится её тестирование. Порядок и методики тестирования определяются в соответствии с ГОСТ 34.301-89. После завершения тестов и исправления недоработок система сдаётся в опытную эксплуатацию программы.
1.7 Требования к документации
Пояснительная записка оформляется в соответствии с ГОСТ 19.106-78 от 01.01.80 «Требования к программным документам, выполненным печатным способом», ГОСТ 19.101-77 от 01.01.80 «Виды программ и программных документов», ГОСТ 2.301-68 от 01.01.71 «Форматы ЕСКД», ЕСПД ГОСТ 19.001-77 от 1.01.80.
2. ОПИСАНИЕ ПРОГРАММЫ
2.1 Описание программы в целом
2.1.1 Общие сведения
Модель предметной области, использованная для разработки программного обеспечения в нотации UML дана в приложении (см. приложение 1, рисунок 1.1 - 1.5). Схемы выполнения основных функций программы приведены в приложении 1 на рисунках 1.6 - 1.9.
Разработанный программный продукт называется «СОКО». Система функционирует в операционных системах Microsoft Windows любых версий, начиная с Windows 98.
Для хранения информации в указанной системе используется файловая база данных. Необходимая для работы часть информации хранится в одном каталоге с исполняемым файлом, а исходные, промежуточные и выходные данные могут храниться на любых носителях, в том числе сетевых.
Программное обеспечение создано в среде разработки приложений Borland C++ Builder 6 на языке программирования C++. Для исполнения двоичных модулей программного обеспечения не требуется установки дополнительных библиотек.
Главный исполняемый двоичный файл называется Soko.exe.
2.1.2 Функциональное назначение
Созданная система реализует следующие основные функции:
Импорт батиметрическиз данных из исходных треков, получаемых с картплоттера-эхолота;
Импорт береговых линий из GPS-навигатора;
Импорт данных, искусственно созданных с помощью приложения Google Maps;
Наглядное совмещение, компоновка и редактирование данных, исправление ошибок;
Подготовка данных к отображению и обработке: вычитание высоты прилива и сезонных колебаний уровня моря;
Выбор необходимого участка для расчёта посредством введения географических координат прямоугольника, либо в графическом режиме;
Настройка параметров отображения будущей карты: коэффициента пропорциональности высоты, частоты изолиний и других;
Построение и батиметрических карт;
Построение карт сравнения динамики рельефа;
Сохранение готовых карт в виде изображений любого размера;
Создание видеоролика, отображающего карту с различных ракурсов путём последовательной установки камеры с различных позиций;
Экспорт данных в различные форматы;
Сохранение текущего состояния системы для дальнейшей обработки.
2.1.3 Описание логической структуры
Программа включает в себя 74 файла кода на языке программирования C++ (модулей) и 35 форм рабочих окон и вспомогательных диалоговых окон.
Перечень модулей и их назначение указаны далее в таблице 2.1.
Таблица 2.1 - Перечень модулей проекта
Название модуля |
Назначение модуля |
|
soko.cpp |
Входная точка программного приложения, содержит функцию main и запускает главный исполняемый поток. |
|
soko_code.cpp soko_code.h soko_code.dfm |
Основной модуль класса окна, сожержит основные методы, управляющие интерфейсом приложения и связывающие его с другими объектами. Также ссылки на остальные модули. |
|
cursor.cpp cursor.h |
Класс курсора. Сожержит методы получения координат курсора на экране, преобразования их в проекцию OpenGL и обратно. |
|
camera.cpp camera.h |
Класс камеры. Содержит методы упрощённого управления камерой в проекции OpenGL. |
|
3dcontrol.cpp 3dcontrol.h |
Класс управления сценой, наследник классов камеры и курсора, управлять просмотром трёхмерного изображения с помощью мыши: вращать, перемещать, масштабировать. |
|
camerasequence.cpp camerasequence.h |
Класс-массив камер, является наследником класса камеры, применяется для создания видеороликов. |
|
chizu.cpp chizu.h |
Основной класс для расчёта батиметрии. Содержит все функции обработки и анализа данных. |
|
averagelevel.cpp averagelevel.h |
Класс, применяемый для расчёта сезонных изменений уровня моря. |
|
dinmas.cpp dinmas.h |
Модуль, сожержащий различные варианты динамических массивов: одномерный, двумерный, трёхмерный, одномерный с двойной адресацией и древовидную структуру. Применяется как контейнер для большинства массивов проекта. |
|
doubletable.cpp doubletable |
Класс, позволяющий читать ascii-файл, представляющий собой таблицу из чисел, разделённых табуляцией и создающий на выходе двумерный массив. Применяется для чтения исходных данных. |
|
geometry.cpp geometry.h |
Модуль, содержащий функции, решающий некоторые геометрические задачи, связанные с триангуляцией. |
|
glWindow.cpp glWindow.h |
Класс API-окна, реализующего вывод OpenGL-графики. |
|
lamp.cpp lamp.h |
Класс, упрощяющий работу с освещением в OpenGL. |
|
lotexture.cpp lotexture.h |
Класс, предназначенный для чтения и записи файлов в формате TGA. Применяется как в качестве контейнера текстуры батиметрической карты, так и для сохранения изображений и видео. |
|
material.cpp material.h |
Класс, упрощающий работу с материалами в OpelGL. |
|
mathadv.cpp mathadv.h |
Модуль, содержащий некоторые дополнительные математические функции. |
|
merkator.cpp merkator.h |
Модуль, содержащий фунцции преобразования географических координат в координаты Меркатора и обратно. |
|
point3d.cpp point3d.h |
Класс, представляющий собой трёхмерную точку. Сожержит некоторые методы обработки. |
|
rastrfont.cpp rastrfont.h |
Класс, упрощающий работу с выводом текста в среде OpenGL. |
Коды перечисленных выше модулей приведены в пункте 3 настоящей пояснительной записки. Программное обеспечение опирается файловую на базу данных.
2.1.4 Используемые технические средства
Техническое обеспечение для разработчика:
Персональный компьютер совместимый с IBM PC, тактовой частотой процессора не ниже 1000 МГц с объёмом оперативной памяти 1024 Мб и более, свободным дисковое пространством не менее 50 Мб, видеокартой и монитором, поддерживающие разрешение 1024х768 точек (или выше) и частотой обновления не менее 60 Гц, оборудованный стандартными устройствами ввода и вывода (клавиатура, мышь).
2.1.5 Используемые программные средства
Программное обеспечение для разработчика программной системы:
операционная система - Microsoft Windows 98 или более поздняя;
редактор диаграмм и блок-схем Microsoft Visio;
интегрированная среда разработки программных приложений Borland C++ Builder 6;
приложение для предрасчёта приливов wxtide версии 4,7 или выше;
консольное приложение для расчёта триангуляции qdelaunay из группы библиотек Qhull;
консольное приложение Slg2Txt для преобразования бинарных файлов формата slg в текстовый формат, предоставленной фирмой-производителем картплоттеров-эхолотов Lowrance;
консольное приложение tga2avi для преобразования последовательности изображений tga в видеоряд avi.
2.1.6 Вызов и загрузка
Вызов и загрузка программного обеспечения осуществляется запуском исполняемого файла soko.exe. Исполняемый файл должен находится в одной папке с представленными выше консольными приложениями.
2.1.7 Входные данные
Входными данными приложения являются:
1) батиметрические треки, получаемые посредством съёмки с помощью картплоттера-эхолота;
2) береговые треки, получаемые с помощью GPS-навигатора;
3) название региона и его координаты для определения уровня прилива и сезонных изменений уровня моря;
4) информация о размере обрабатываемого участка, качестве обработки, пределах глубины, позициях камеры, режимах отображения, количестве изолиний и прочие настройки состояния системы.
2.1.8 Выходные данные
Выходными приложения являются:
1) батиметрические карты и карты разницы для выбранных участков в чёрно-белом и цветом варианте;
2) изображения трёхмерных срезов батиметрических данных, показанные с определённого ракурса;
3) видео-файлы, представляющие собой съёмку трёхмерной батимет-рической карты с различных ракурсов;
4) батиметрические треки и сетки, готовые для отображения в про-грамме Google Earth;
5) батиметрические сетки в формате.inf для обработки в программном комплексе ANI.
3. ТЕКСТ ПРОГРАММЫ
3.1 Модуль soko.cpp
/******************************************************
Автор: Плеханов Ф. А.
Назначение: Входная точка программного приложения, содержит функцию WinMain
и запускает главный исполняемый поток.
*******************************************************/
#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM('soko_code.cpp', BathWin);
//---------------------------------------------------------------------------
using namespace std;
//Аргументы командной строки
extern AnsiString args;
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR Args, int)
{
args=Args;
try
{
Application->Initialize();
Application->CreateForm(__classid(TBathWin), &BathWin);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception('');
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
//---------------------------------------------------------------------------
3.2 Модуль dinmas.cpp (выборочно)
/******************************************************
Автор: Плеханов Ф.А.
Назначение: Модуль контейнерных классов
Входные данные: размер контейнера
Выходные данные: готовый к использванию динамический массив
*******************************************************/
#ifndef DINMAS_CPP
#define DINMAS_CPP
#include <vcl>
#include <fstream>
#include <ComCtrls.hpp>
#define SIZETYPE long
//Обычный одномерный динамический массив
export template<typename type>
class dinmas
{
protected: public:
type* data;
public:
SIZETYPE siz;
dinmas();
dinmas(SIZETYPE);
~dinmas();
bool make(SIZETYPE);
void clear();
type& operator[](SIZETYPE);
int bytes();
void insert(type &, int);
void erase(int);
push(type &);
pop();
type& top();
bool SaveToFile(AnsiString);
bool LoadFromFile(AnsiString);
SIZETYPE& size();
#ifndef NOCOPY
operator=(dinmas<type> &);
#endif
};
//Обычный двумерный динамический массив
template<typename type>
class dinmas2d
{
public:
type** data;
SIZETYPE n,m;
bool exists;
dinmas2d();
dinmas2d(SIZETYPE, SIZETYPE);
~dinmas2d();
bool make(SIZETYPE, SIZETYPE);
void clear();
type* operator[](SIZETYPE);
int bytes();
#ifndef NOCOPY
operator=(dinmas2d<type> &);
#endif
};
//Одномерный динамический массив с двойной адресацией, может содержать в себе
//другие динамические массивы
template<typename type>
class smartcont
{
private:
type** graphs;
int _size;
int selected;
public:
smartcont(int);
smartcont();
make(int n);
int &size();
void clear();
type& operator[](int);
type& operator()();
~smartcont();
insert(type &value);
insert();
void copy();
void erase(int);
void erase();
bool select(int);
int SelectedItem();
void MoveUp();
void MoveDown();
};
using namespace std;
template<typename type>dinmas<type>::dinmas()
{
siz=0;
}
template<typename type>dinmas<type>::dinmas(SIZETYPE Size)
{
Beep(2500,100);
siz=0;
make(Size);
}
template<typename type>dinmas<type>::~dinmas()
{
clear();
}
template<typename type> bool dinmas<type>::make(SIZETYPE Size)
{
if(siz>0) clear();
siz=Size;
data=new type[siz];
return 1;
}
template<typename type> void dinmas<type>::clear()
{
if(siz<=0) return;
delete[] data;
siz=0;
}
template<typename type> type& dinmas<type>::operator[](SIZETYPE i)
{
return data[i];
}
template<typename type> int dinmas<type>::bytes()
{
return siz*sizeof(type);
}
template<typename type> void dinmas<type>::insert(type &variable, int position)
{
if(siz==0)
{
make(1);
data[0]=variable;
return;
}
if(position<0) position=0;
if(position>siz) position=siz;
type *buff1, *buff2;
buff1=new type[position];
for(int i=0;i<position;i++)
{
buff1[i]=data[i];
}
buff2=new type[siz-position];
for(int i=0;i<siz-position;i++)
{
buff2[i]=data[position+i];
}
siz++;
make(siz);
for(int i=0;i<position;i++)
{
data[i]=buff1[i];
}
data[position]=variable;
for(int i=0;i<siz-1-position;i++)
{
data[position+1+i]=buff2[i];
}
delete[] buff1;
delete[] buff2;
}
template<typename type> void dinmas<type>::erase(int position)
{
if(position<0) position=0;
if(position>siz-1) position=siz-1;
if(siz==0) return;
type *buff1, *buff2;
buff1=new type[position];
for(int i=0;i<position;i++)
{
buff1[i]=data[i];
}
buff2=new type[siz-position-1];
for(int i=0;i<siz-position-1;i++)
{
buff2[i]=data[position+1+i];
}
siz--;
make(siz);
for(int i=0;i<position;i++)
{
data[i]=buff1[i];
}
for(int i=0;i<siz-position;i++)
{
data[position+i]=buff2[i];
}
delete[] buff1;
delete[] buff2;
}
template<typename type> dinmas<type>::push(type &variable)
{
insert(variable, 0);
}
template<typename type> dinmas<type>::pop()
{
erase(0);
}
template<typename type> type& dinmas<type>::top()
{
return data[0];
}
template<typename type> bool dinmas<type>::SaveToFile(AnsiString FileName)
{
ofstream file(FileName.c_str(), ios::binary);
file.write((char*)&siz,sizeof(siz));
for(int i=0;i<siz;i++)
{
file.write((char*)&data[i],sizeof(type));
}
file.close();
return 1;
}
template<typename type> bool dinmas<type>::LoadFromFile(AnsiString FileName)
{
ifstream file(FileName.c_str(), ios::binary);
file.read((char*)&siz,sizeof(siz));
make(siz);
for(int i=0;i<siz;i++)
{
file.read((char*)&data[i],sizeof(type));
}
file.close();
return 1;
}
template<typename type> SIZETYPE& dinmas<type>::size()
{
return siz;
}
#ifndef NOCOPY
template<typename type> dinmas<type>::operator=(dinmas<type> &object)
{
if(object.size()>0)
{
make(object.size());
for(int i=0;i<size();i++)
{
data[i]=object.data[i];
}
}
}
#endif
template<typename type> dinmas2d<type>::dinmas2d()
{
exists=0;
n=m=0;
}
template<typename type> dinmas2d<type>::dinmas2d(SIZETYPE N, SIZETYPE M)
{
exists=0;
n=m=0;
make(N,M);
}
template<typename type> dinmas2d<type>::~dinmas2d()
{
clear();
}
template<typename type> bool dinmas2d<type>::make(SIZETYPE N, SIZETYPE M)
{
if(N==0 || M==0) return 0;
clear();
n=N; m=M;
data=new type*[n];
for(int i=0;i<n;i++)
{
data[i]=new type[m];
}
exists=1;
return 1;
}
template<typename type> void dinmas2d<type>::clear()
{
if(!exists) return;
for(int i=0;i<n;i++)
{
delete data[i];
}
delete[] data;
exists=0;
}
template<typename type> type* dinmas2d<type>::operator[](SIZETYPE i)
{
return data[i];
}
template<typename type> int bytes()
{
return n*m*sizeof(type);
}
#ifndef NOCOPY
template<typename type> dinmas2d<type>::operator=(dinmas2d<type> &object)
{
if(object.exists)
{
make(object.n,object.m);
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
data[i][j]=object.data[i][j];
}
}
exists=1;
}
}
#endif
template<typename type> smartcont<type>::smartcont(int n)
{
_size=selected=0;
make(n);
}
template<typename type> smartcont<type>::smartcont()
{
_size=selected=0;
make(0);
}
template<typename type> smartcont<type>::make(int n)
{
if(_size>0) clear();
_size=n;
if(_size!=0)
{
graphs = new type*[n];
for(int i=0;i<n;i++)
{
graphs[i] = new type[1];
}
}
}
template<typename type> int & smartcont<type>::size()
{
return _size;
}
template<typename type> void smartcont<type>::clear()
{
if(_size<=0) return;
for(int i=0;i<_size;i++)
{
delete[] graphs[i];
}
delete[] graphs;
_size=0;
}
template<typename type> type& smartcont<type>::operator[](int n)
{
if(_size>0 && n<_size)
return *graphs[n];
else
{
MessageBox(NULL,'Ошибка массива','Ошибка',MB_OK|MB_ICONERROR);
}
}
template<typename type> type& smartcont<type>::operator()()
{
if(_size>0 && selected<_size)
return *graphs[selected];
else
{
MessageBox(NULL,'Ошибка массива','Ошибка',MB_OK|MB_ICONERROR);
}
}
template<typename type> smartcont<type>::~smartcont()
{
clear();
}
template<typename type> smartcont<type>::insert(type &value)
{
insert();
graphs[selected]=value;
}
template<typename type> smartcont<type>::insert()
{
if(_size!=0)
{
selected++;
type** buff;
buff = new type*[_size];
for(int i=0;i<_size;i++)
{
buff[i]=graphs[i];
}
_size++;
graphs = new type*[_size];
for(int i=0;i<selected;i++)
{
graphs[i]=buff[i];
}
graphs[selected] = new type[1];
for(int i=selected+1;i<_size;i++)
{
graphs[i]=buff[i-1];
}
delete[] buff;
select(selected);
}
else
{
make(1);
selected=0;
select(selected);
}
}
template<typename type> void smartcont<type>::copy()
{
insert();
*graphs[selected]=*graphs[selected-1];
select(selected);
}
template<typename type> void smartcont<type>::erase(int n)
{
int buff=selected;
select(n);
erase();
select(selected);
}
template<typename type> void smartcont<type>::erase()
{
if(_size==0) return;
delete[] graphs[selected];
type** buff;
buff = new type*[_size];
for(int i=0;i<_size;i++)
{
buff[i]=graphs[i];
}
_size--;
graphs = new type*[_size];
for(int i=0;i<selected;i++)
{
graphs[i]=buff[i];
}
for(int i=selected;i<_size;i++)
{
graphs[i]=buff[i+1];
}
delete[] buff;
if(selected>0)
select(selected-1);
}
template<typename type> bool smartcont<type>::select(int item)
{
if(_size==0) return 0;
selected=item;
return 1;
}
template<typename type> int smartcont<type>::SelectedItem()
{
return selected;
}
template<typename type> void smartcont<type>::MoveUp()
{
if(selected<1) return;
type* buff;
buff=graphs[selected-1];
graphs[selected-1]=graphs[selected];
graphs[selected]=buff;
selected--;
}
template<typename type> void smartcont<type>::MoveDown()
{
if(selected>_size-1) return;
type* buff;
buff=graphs[selected+1];
graphs[selected+1]=graphs[selected];
graphs[selected]=buff;
selected++;
}
#endif
3.3 Модуль lotexture
/******************************************************
Автор: Плеханов Ф.А.
Назначение: Класс для чтения файлов изображений в формате TGA и преобразования
в готовые для использования в среде OpenGL текстуры, также позволяет сохранять
изображения в формате TGA.
Входные данные: файл TGA, настройки чтения
Выходные данные: ID текстуры в OpenGL
*******************************************************/
3.3.1 Заголовочный файл lotexture.h
#ifndef LOTEXTURE_H
#define LOTEXTURE_H
#include <vcl.h>
#include <windowsx.h>
#include <winuser.h>
#include <gl>
#include <glu>
#include 'mathadv.h'
#include 'dinmas.cpp'
#define LT_IGNORE_ERROR 1
using namespace std;
#pragma pack (push, 1)
//Заголовок TGA-файла
struct TgaHeader
{
byte idLength;
byte colormapType;
byte imageType;
unsigned __int16 colormapIndex;
unsigned __int16 colormapLength;
byte colormapEntrySize;
unsigned __int16 xOrigin;
unsigned __int16 yOrigin;
unsigned __int16 width;
unsigned __int16 height;
byte pixelSize;
byte imageDesc;
};
#pragma pack (pop)
//Структуры точнек в формате TGA
struct RGBApixel
{
GLubyte r,g,b,a;
RGBApixel(GLubyte, GLubyte, GLubyte, GLubyte);
RGBApixel();
void GetPixel(GLubyte &, GLubyte &, GLubyte &, GLubyte &);
RGBApixel ToBGRA();
};
struct RGBpixel
{
GLubyte r,g,b;
RGBpixel(GLubyte, GLubyte, GLubyte);
GBpixel();
void GetPixel(GLubyte &, GLubyte &, GLubyte &);
RGBpixel ToBGR();
RGBApixel ToBGRA();
};
//Основной класс текстуры
class texture
{
protected:
bool exsist; //суествует
bool binded; //уже применяется
int width; //ширина
int height; //высота
int RealWidth; //ширина, приближённая к степени двойки
int RealHeight; //высота, приближённая к степени двойки
int PixelsQnt; //количество точек
int ID; //идентификационный номер текстуры в OpelGL
float hcoeff; //отношение height к RealHeight
float wcoeff; //отношение width к RealWidth
public:
//поля
dinmas<RGBApixel> imageData; //массив точек
//методы
//исправление целочисленного цвета,
//если он выходит из диапазона 0-255
GLubyte correct(float);
//копировать текстуру
void operator=(texture &);
//задать одну точку целыми числами
void SetPixel(int, int, GLubyte, GLubyte, GLubyte, GLubyte);
//задать одну точку числами с плавающей точкой
void SetPixelf(int, int, float, float, float, float);
//получить одну точку
void GetPixel(int, int, GLubyte &, GLubyte &, GLubyte &, GLubyte &);
texture(); //конструктор
//выделение памяти c проверкой на степень двойки
bool MakeArray(int, int);
//выделение памяти в обход проверки на степень двойки
bool MakeArraySimple(unsigned int, unsigned int);
//применение текстуры
bool BindTexture(unsigned int, bool, bool);
//сохранение в TGA
bool SaveToTGA(AnsiString);
//чтение из TGA
bool LoadFromTGA(AnsiString, unsigned int, bool, bool);
~texture(); //деструктор
void DeleteArray(); //очистить массив
void UnBind(); //отменить текстуру
//Методы получения величин
unsigned int GetWidth();
unsigned int GetHeight();
unsigned int GetRealWidth();
unsigned int GetRealHeight();
unsigned int GetPixelsQnt();
unsigned int GetID();
bool GetExsist();
bool GetBinded();
float GetWCoeff();
float GetHCoeff();
float GetWCoeffF();
float GetHCoeffF();
//Методы установки величин
void PutWidth(unsigned int);
void PutHeight(unsigned int);
void PutRealWidth(unsigned int);
void PutRealHeight(unsigned int);
void PutPixelsQnt(unsigned int);
void PutID(unsigned int);
void PutExsist(bool);
void PutBinded(bool);
void PutWCoeff(float);
void PutHCoeff(float);
};
#endif
3.3.2 Реализация lotexture.cpp
#ifndef LOTEXTURE_CPP
#define LOTEXTURE_CPP
#include 'lotexture.h'
using namespace std;
RGBApixel::RGBApixel(GLubyte R, GLubyte G, GLubyte B, GLubyte A)
{
r=R; g=G; b=B; a=A;
}
RGBApixel::RGBApixel()
{
r=0; g=0; b=0; a=255;
}
void RGBApixel::GetPixel(GLubyte &R, GLubyte &G, GLubyte &B, GLubyte &A)
{
R=r; G=g; B=b; A=a;
}
RGBApixel RGBApixel::ToBGRA()
{
return RGBApixel(b,g,r,a);
}
RGBpixel::RGBpixel(GLubyte R, GLubyte G, GLubyte B)
{
r=R; g=G; b=B;
}
RGBpixel::RGBpixel()
{
r=0; g=0; b=0;
}
void RGBpixel::GetPixel(GLubyte &R, GLubyte &G, GLubyte &B)
{
R=r; G=g; B=b;
}
RGBpixel RGBpixel::ToBGR()
{
return RGBpixel(b,g,r);
}
RGBApixel RGBpixel::ToBGRA()
{
return RGBApixel(b,g,r,255);
}
GLubyte texture::correct(float x)
{
if(x<=0) return 0;
if(x>=1) return 255;
return floor(255*x);
}
void texture::operator=(texture &object)
{
exsist=object.exsist;
}
void texture::SetPixel(int Col, int Row, GLubyte r, GLubyte g, GLubyte b, GLubyte a)
{
int i=Row*RealWidth+Col;
if(i<PixelsQnt) imageData[i]=RGBApixel(r,g,b,a);
}
void texture::SetPixelf(int Col, int Row, float r, float g, float b, float a)
{
int i=Row*RealWidth+Col;
if(i<PixelsQnt) imageData[i]=RGBApixel(correct(r),correct(g),correct(b),correct(a));
}
void texture::GetPixel(int Col, int Row, GLubyte &r, GLubyte &g, GLubyte &b, GLubyte &a)
{
int i=Row*RealWidth+Col;
if(i<PixelsQnt)
{
imageData[i].GetPixel(r,g,b,a);
}
}
texture::texture()
{
exsist=0; binded=0;
}
bool texture::MakeArray(int w, int h)
{
if(w==0 || h==0) return 0;
width=w; height=h;
#ifdef LT_IGNORE_ERROR
{
RealWidth =NearestPow2(w);
RealHeight=NearestPow2(h);
wcoeff=1-1.*(RealWidth -width )/RealWidth ;
hcoeff=1-1.*(RealHeight-height)/RealHeight;
}
#else
{
RealWidth=width;
RealHeight=height;
hcoeff=wcoeff=1;
}
#endif
PixelsQnt=RealWidth*RealHeight;
if(imageData.make(PixelsQnt))
{
exsist=1;
return 1;
}
else
{
ShowMessage('Ошибка');
return 0;
}
}
bool texture::MakeArraySimple(unsigned int w, unsigned int h)
{
if(w==0 || h==0) return 0;
width=w; height=h;
RealWidth=width;
RealHeight=height;
hcoeff=wcoeff=1;
PixelsQnt=RealWidth*RealHeight;
if(imageData.make(PixelsQnt))
{
exsist=1;
return 1;
}
else
{
ShowMessage('Ошибка');
return 0;
}
}
bool texture::BindTexture(unsigned int TexID, bool Interpolation, bool Multiply)
{
if(!exsist) return 0;
ID=TexID;
glBindTexture(GL_TEXTURE_2D, TexID);
if (Interpolation)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
if (Multiply)
{
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
}
else
{
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RealWidth, RealHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData.data);
binded=1;
return 1;
}
bool texture::SaveToTGA(AnsiString fileName)
{
if(!exsist) return 0;
TgaHeader hdr;
memset ( &hdr, ' ', sizeof ( hdr ) );
hdr.imageType = 2; // unencoded image
hdr.width = width;
hdr.height = height;
hdr.pixelSize = 32;
FILE *pFile;
pFile=fopen(fileName.c_str(), 'wb');
fwrite(&hdr, sizeof(hdr),1,pFile);
int WritedPxlQnt=width*height;
RGBApixel *temp = new RGBApixel[WritedPxlQnt];
int i=0;
for(int row=0;row<height;row++)
{
for(int col=0;col<width;col++)
{
temp[i]=imageData[row*RealWidth+col].ToBGRA();
i++;
}
}
fwrite(temp, WritedPxlQnt*4, 1, pFile);
fclose(pFile);
free ( temp );
return 1;
}
bool texture::LoadFromTGA(AnsiString fileName, unsigned int TexID, bool Interpolation, bool Multiply)
{
TgaHeader hdr;
FILE *pFile;
pFile=fopen(fileName.c_str(), 'rb');
if(pFile==NULL) return 0;
fread(&hdr, sizeof(hdr),1,pFile);
if(!(hdr.pixelSize==32 || hdr.pixelSize==24) || hdr.imageType!=2) return 0;
MakeArray(hdr.width,hdr.height);
int ReadPxlQnt=hdr.width*hdr.height;
if(hdr.pixelSize==32)
{
RGBApixel *temp = new RGBApixel[ReadPxlQnt];
fread(temp, ReadPxlQnt*4, 1, pFile);
int i=0;
for(int row=0;row<height;row++)
{
for(int col=0;col<width;col++)
{
imageData[row*RealWidth+col]=temp[i].ToBGRA();
i++;
}
}
free(temp);
}
if(hdr.pixelSize==24)
{
RGBpixel *temp = new RGBpixel[ReadPxlQnt];
fread(temp, ReadPxlQnt*3, 1, pFile);
int i=0;
for(int row=0;row<height;row++)
{
for(int col=0;col<width;col++)
{
imageData[row*RealWidth+col]=temp[i].ToBGRA();
i++;
}
}
free(temp);
}
fclose(pFile);
BindTexture(TexID,Interpolation,Multiply);
return 1;
}
texture::~texture()
{
DeleteArray();
}
void texture::DeleteArray()
{
if(!exsist) return;
imageData.clear();
exsist=0;
}
void texture::UnBind()
{
if(!binded) return;
glBindTexture(GL_TEXTURE_2D, ID);
char data[4]='1111';
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
binded=0;
}
unsigned int texture::GetWidth()
{
return width;
}
unsigned int texture::GetHeight()
{
return height;
}
unsigned int texture::GetRealWidth()
{
return RealWidth;
}
unsigned int texture::GetRealHeight()
{
return RealHeight;
}
unsigned int texture::GetPixelsQnt()
{
return PixelsQnt;
}
unsigned int texture::GetID()
{
return ID;
}
bool texture::GetExsist()
{
return exsist;
}
bool texture::GetBinded()
{
return binded;
}
float texture::GetWCoeff()
{
return wcoeff;
}
float texture::GetHCoeff()
{
return hcoeff;
}
float texture::GetWCoeffF()
{
return 1-1.*(RealWidth-width-2)/RealWidth;
}
float texture::GetHCoeffF()
{
return 1-1.*(RealHeight-height-2)/RealHeight;
}
void texture::PutWidth(unsigned int w)
{
width=w;
}
void texture::PutHeight(unsigned int h)
{
height=h;
}
void texture::PutRealWidth(unsigned int rw)
{
RealWidth=rw;
}
void texture::PutRealHeight(unsigned int rh)
{
RealHeight=rh;
}
void texture::PutPixelsQnt(unsigned int pq)
{
PixelsQnt=pq;
}
void texture::PutID(unsigned int id)
{
ID=id;
}
void texture::PutExsist(bool ex)
{
exsist=ex;
}
void texture::PutBinded(bool bd)
{
binded=bd;
}
void texture::PutWCoeff(float wc)
{
wcoeff=wc;
}
void texture::PutHCoeff(float hc)
{
hcoeff=hc;
}
#endif
3.4 Модуль chizu
/******************************************************
Автор: Плеханов Ф.А.
Назначение: Класс батиметрии. Производит всю обработку батиметрических данных
и построение батиметрической сетки.
Входные данные: исходные треки, множество настроек, таких как частота изолиний
Выходные данные: трёхмерная батиметрическая карта с изолиниями и подписями
*******************************************************/
3.4.1 Заголовочный файл chizu.h
#ifndef CHIZU_H
#define CHIZU_H
#include <vector>
#include <map>
#include <list>
//Пользовательские модули
#include 'merkator.h'
#include 'doubletable.h'
#include 'spline.h'
#include 'lotexture.h'
#include 'material.h'
#include 'geometry.h'
#include 'mathadv.h'
using namespace std;
//Константы максимума и минимума
#define MAX 9999999999
#define MIN -9999999999
//Цветовые константы
#define COLOR_RED 0
#define COLOR_GREEN 1
#define COLOR_BLUE 2
//Стандартизация исходных
AnsiString ReplaceComma(AnsiString);
//Получение строки из числа
AnsiString PointDouble(double);
//Получние строки с градусами и минутами из градусов с нецелой частью
AnsiString DegToDegMin(double);
//Получение строки с градусами,
//минутами и секундами из градусов с нецелой частью
AnsiString DegToCoord(double);
//Получение строки из градусов с нецелой частью, добавляет букву E или N
AnsiString DegToDegMinI(double, bool);
//Получние строки с градусами и минутами из градусов с нецелой частью,
//добавляет букву E или N
AnsiString DegToDegMinSecI(double, bool);
//Получение градусов с нецелой частью из градусов, минут и секунд
double DegMinSecToDouble(double, double, double);
//Установка заголовка окна, виртуальная функция, реализуемая
//в модуле, где расположено окно
void SetTitle(AnsiString msg);
//Функуция для тестирования
void Debag(AnsiString msg);
//Структура 'трёхмерная точка'
struct point3D
{
double x,y,z; //координаты
bool ataru(point3D &); //проверка на совпадение с другой
};
//Структура 'узел батиметрии', основанная на трёхмерной точке
struct vertex:point3D
{
double nx,ny,nz; //нормали
double b; //буфер для размытия
bool e; //существует ли
};
//Попадает ли трёхмерная точка в треугольник
bool InTriangle(point3D &, point3D &, point3D &, point3D &);
//Существует ли такой треугольник
bool CorrectTria(point3D &, point3D &, point3D &, double);
//Универсальная функция расчёта цвета по глубине
double countColor(double, double, double, unsigned __int8, bool, bool);
//Точка батиметрического трека
struct BathPoint
{
point3D r,m; //Точка в географических и нормализованных к 1 координатах
unsigned int t; //Сколько миллисекунд прошло с начала трека
double tide; //Высота прилива в данной точке
BathPoint(); //Конструктор
};
//Изолиния
struct isoline
{
point3D a,b; //начало и конец
bool zero; //не показывать
isoline(); //конструктор
void put(double &, double &, double &, //задать
double &, double &, double &, bool &);
void view(int &); //показать
};
//цифра-подпись
struct figure:public point3D
{
bool exists; //показывать
double length; //размер
isoline *line; //к какой изолинии привязана
char str[8]; //что отображать
int strl; //длина строки
double angle; //угол разворота
void activate(double, double); //'прилепить' к изолинии
void view(int); //показать
};
//Структура треугольника для триангуляции
struct OneTri
{
//порядковые номера точек в качестве вершин
unsigned int a,b,c;
};
//основной класс батиметрии
class bath:public texture
{
private:
//поля
double f; //уровень для расчёта изолиний
bool zero; //являетмя ли уровень текущей изолинии нулевым
float material_color[4]; //массив цвета материала
dinmas<OneTri> tri; //набор треугольников для триангуляции
//буферная изолиния для работы функции расчёта изолиний
isoline line;
//методы
bool triangulation();
public:
//поля
dinmas<BathPoint> q; //батиметрический трек
dinmas2d<vertex> p; //батиметрическая сетка
dinmas2d<double> blurBuff; //буфферный массив для размытия
TDateTime startDate; //дата начала съёмки
TDateTime endDate; //дата конца съёмки
vector<isoline> iso; //вектор изолиний
dinmas2d<figure> figures; //массив цифр
dinmas<double> *isolist; //список уровней изолиний
double d; //шаг сетки
double sclxy; //коэффициент нормализации долготы и широты
double sclz; //коэффициент нормализации высоты
double cfx; //коэффициент нормализации долготы
double cfy; //коэффициент нормализации широты
//суммарное математическое отклонение данных от исходных в
//результате сглаживания и расчёта равномерной сетки
double dev;
double tmpz; //нормализованная высота для расчёта цвета
double isoHaba; //частота изолиний
double isolineSize; //толщина изолинии
point3D min; //минимум, нормализованный к 1
point3D max; //максимум, нормализованный к 1
point3D rmn; //минимум в географических координатах
point3D rmx; //максимум в географических координатах
//число строк в текстуре для доступа к ячейке одномерной
//текстуры по двум координатам
int k;
int blurCount; //количество проходов размытия
int texNum; //ID текстуры в среде OpenGL
int fighaba; //Расстояние между подписями
int diffBlur; //количество проходов размытия для сравнения батиметрий
int step; //пропуск кратных узлов сетки для ускорения отображения
AnsiString Filename; //имя файла
bool tex; //отображение текстуры средставми OpenGL
bool varIso; //переменный список изолиний
bool lighting; //освещение включено
bool rt; //режим отображения без пропусков
bool viewPoints; //отображать треки
bool net; //отображать сетку
bool counted; //сетка уже расчитана
bool isolines; //отображать изолинии
bool viewRelief; //отображать рельеф
bool visible; //отображать сетку
bool hideFar; //скрыть удалённые участки
//скрыть участки, выходящие за границу минимума и максимума
bool hideUpLimit;
bool needRecount; //требуется перерасчёт
bool difference; //является разницей между двумя батиметриями
bool blackAndWhite; //отображать в чёрнобелых тонах
bool slg; //является прочитанным slg-файлом
bool hasTide; //прилив вычтен
//методы
//Конструктор
bath();
//Чтение точек из ASCII-файла
bool LoadPoints(AnsiString, bool, bool);
//Чтение трека из slg-файла
bool LoadSlg(DoubleTable &, AnsiString);
//Очистить батиметрию
bool MakeEmpty(int);
//Расчёт прилива
void CountTide(cubic_spline &);
//Вычисление минимума и максимума
void ReCountMinMax();
//Вычисление только минимума
double ReCountMin();
//Расчёт батиметрической сетки
bool CountNet(int, point3D, point3D, double, double, double, double,
double, int, double, double, int, int, int, dinmas<double> *, bool);
//размытие
void blur(int);
//расчёт отклонения
void deviation();
//Расчёт цвета для выбранного узла сетки
inline __fastcall void CountColor(int &, int &);
//Перерасчёт цвета
void ReCountColor();
//Вычисление нормалей
inline __fastcall void CountNorm(int &, int &);
//Конструктор (в виде вызываемой функции)
void DefConstr();
//Вывод одного узла сетки на экран
void OneVertex(int &, int &);
//Вывод всей батиметрии
void view();
//Вывот треков
void ViewPoints();
//Линейная интерполяция
double cf(double &, double &, double &, bool);
//Создание одной изолинии
void makeLine(int &, int &);
//Отображение цифр-подписей
void ViewFigures(int);
//Расчёт одного слоя изолиний
void countOneIso(double);
//Расчёт всех изолиний
void countIso(double, dinmas<double> *, bool);
//Расчёт цифр-подписей
void CountFigures(int);
//Отображение изолиний
void viewIso();
//Удаление расчитанной батиметрической сетки
void EraseNet();
//Вычисление разницы между двумя батиметриями
bool GetDiffer(bath &, bath &, int, double, int);
//Вычисление
bool GetDifferPoints(bath &, double);
//Наложение текстуры
bool ReBindTexture();
//Сохранение сетки в ASCII-формате
bool SaveNet(AnsiString);
//Сохранение данных в формате.inf и.dat для программы ANI
bool SaveANI(AnsiString, double);
//Сохранение набора точек для отображения в прорамме Google Chrome
bool SavePointsGoogle(AnsiString);
//Сохранение трека для отображения в прорамме Google Chrome
bool SaveTrack(AnsiString);
//Сохранение набора точек в ASCII-формате в географических коордиантах
bool SavePoints(AnsiString);
//Сохранение набора точек в ASCII-формате в координатах меркатора
bool SavePointsMer(AnsiString);
//Сохранение батиметрической карты для отображения в прорамме Google Chrome
bool SaveNetGoogle(AnsiString, int);
//Получение всех статических переменных батиметрии из другой
void setConstantPreset(bath &);
//Полное копирование батиметрии из другой
operator=(bath &);
};
//Точка данных нивелирования
struct LevelPoint
{
double l; //расстояние от берега
double h; //высота над уровнем моря
//Координаты начальной точки
double x;
double y;
double z;
};
//Класс для работы с нивелированием
struct Levelling
{
dinmas<LevelPoint> levelPoint; //массив точек местности
};
#endif
3.4.2 Реализация chizu.cpp
#ifndef CHIZU_CPP
#define CHIZU_CPP
#include 'chizu.h'
using namespace std;
//Константы малентких чисел
#define SM 0.00000001
#define SM2 0.1
//Смещение изолинии вверх
#define UE 0.001
//Коэффициенты для раскрашивания шкалы
#define RC 4.3
#define GC 1.8
#define BC 1.2
#define RD 0.0
#define GD 0.0
#define BD 0.0
//Эпсилон отклонения
#define EPS 0.0001
AnsiString ReplaceComma(AnsiString str)
{
for(int i=1;i<=str.Length();i++)
{
if(str[i]==',')
str[i]='.';
}
return str;
}
AnsiString PointDouble(double x)
{
return AnsiString(x);
}
AnsiString DegToDegMin(double x)
{
int deg=floor(x);
double min=(x-deg)*60;
return AnsiString(deg)+'° '+PointDouble(min)+''';
}
AnsiString DegToCoord(double x)
{
int deg=floor(x);
int min=floor(fabs(x-deg)*60);
nt sec=floor(fabs((fabs(x-deg)*60)-min)*60);
int ms=floor(100*((fabs(fabs(fabs(x-deg)*60)-min)*60)-sec));
if(ms==99)
{
ms=0;
sec++;
if(sec==59 || sec==60)
{
sec=0;
min++;
if(min==59 || min==60)
{
min=0;
deg++;
}
}
}
if(min==0 && sec==0 && ms==0)
{
return AnsiString(deg)+':';
}
if(min!=0 && sec==0 && ms==0)
{
return AnsiString(deg)+':'+AnsiString(min)+''';
}
if(min!=0 && sec!=0 && ms==0)
{
return AnsiString(deg)+':'+
AnsiString(min)+'''+AnsiString(sec)+''';
}
return AnsiString(deg)+':'+AnsiString(min)+
'''+AnsiString(sec)+'''+AnsiString(ms);
}
AnsiString DegToDegMinI(double x, bool E)
{
int deg=floor(x);
int min=round((x-deg)*60);
return AnsiString(deg)+'° '+AnsiString(min)+'' '+((E)?'E':'N');
}
AnsiString DegToDegMinSecI(double x, bool E)
{
int deg=floor(x);
int min=floor((x-deg)*60);
int sec=floor((((x-deg)*60)-min)*60);
AnsiString secs=AnsiString(sec)+'' ';
return AnsiString(deg)+'° '+AnsiString(min)+
'' '+((sec!=0)?(secs):AnsiString(''))+((E)?'E':'N');
}
double DegMinSecToDouble(double deg, double min, double sec)
{
return deg+(min/60.)+(sec/3600.);
}
bool point3D::ataru(point3D &p)
{
return (fabs(p.x-x)<EPS) && (fabs(p.y-y)<EPS) && (fabs(p.z-z)<EPS);
}
bool InTriangle(point3D &a, point3D &b, point3D &c, point3D &p)
{
double pl1, pl2, pl3;
pl1 = (a.x - p.x)*(b.y - a.y)-(b.x - a.x)*(a.y - p.y);
pl2 = (b.x - p.x)*(c.y - b.y)-(c.x - b.x)*(b.y - p.y);
pl3 = (c.x - p.x)*(a.y - c.y)-(a.x - c.x)*(c.y - p.y);
if ((pl1 >= 0 && pl2 >= 0 && pl3 >= 0) ||
(pl1 <= 0 && pl2 <= 0 && pl3 <= 0))
{
return true;
}
return false;
}
bool CorrectTria(point3D &a, point3D &b, point3D &c, double max)
{
if (sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))>max)
{
return 0;
}
else
{
if (sqrt(sqr(a.x-c.x)+sqr(a.y-c.y))>max)
{
return 0;
}
else
{
if (sqrt(sqr(b.x-c.x)+sqr(b.y-c.y))>max)
{
return 0;
}
else
{
return 1;
}
}
}
}
double countColor(double z, double A, double B,
unsigned __int8 color, bool difference, bool blackAndWhite)
{
if(!difference)
{
if(!blackAndWhite)
if(B<=A) return 0;
switch(color)
{
case COLOR_RED:
if(z<0)
return exp(-sqr((z)*(4.3/(-A))));
else
return exp(-sqr((z+B*(-1))*(2/(((1.6)*(B))))));
break;
case COLOR_GREEN:
if(z<0)
return exp(-sqr((z)*(1.8/(-A))));
else
return exp(-sqr((z+B*(-0.42))*(2/(((0.85)*(B))))));
break;
case COLOR_BLUE:
if(z<0)
return exp(-sqr((z)*(1.2/(-A))));
else
return exp(-sqr((z+B*(1.2))*(2/(((1.9)*(B))))));
break;
}
}
else
{
double ret=1-(z-A)/(B-A);
if(ret<0) return 0;
if(ret>1) return 1;
return ret;
}
}
else
{
if(!blackAndWhite)
{
switch(color)
{
case COLOR_RED:
return exp(-pow((z-A-(B-A)*2)*(2./(((3.3)*(B-A)))),10));
break;
case COLOR_GREEN:
return exp(-pow((z-A-(B-A)*0)*(2./(((5)*(B-A)))),4));
break;
case COLOR_BLUE:
return exp(-pow((z-A-(B-A)*(-2))*(2./(((3.5)*(B-A)))),8));
break;
}
}
else
{
double ret=z/((B-A)/8)+B;
if(ret<0) return 0;
if(ret>1) return 1;
return ret;
}
}
}
BathPoint::BathPoint()
{
t=0;
tide=0;
}
isoline::isoline(){};
void isoline::put(double &x1, double &y1, double &z1,
double &x2, double &y2, double &z2, bool &Zero)
{
a.x=x1;
a.y=y1;
a.z=z1;
b.x=x2;
b.y=y2;
b.z=z2;
zero=Zero;
}
void isoline::view(int &isolineSize)
{
if(zero)
{
glLineWidth(2*isolineSize);
glColor4d(0,0,0,1);
}
else
{
glLineWidth(1*isolineSize);
glColor4d(0,0,0,0.5);
}
glBegin(GL_LINES);
glVertex3d(a.x,a.y,a.z+UE);
glVertex3d(b.x,b.y,b.z+UE);
glEnd();
}
void figure::activate(double figh, double h)
{
if(length<figh)
{
x=line->a.x;
y=line->a.y;
z=line->a.z;
double r;
polar(line->b.x-line->a.x, line->b.y-line->a.y, r, angle);
angle=deg(angle);
exists=1;
AnsiString s=FormatFloat('0.00',h);
if(s[s.Length()]=='0')s=s.SubString(1,s.Length()-1);
if(s[s.Length()]=='0')s=s.SubString(1,s.Length()-2);
int i;
for(i=0;i<s.Length()&&i<8;i++)
{
str[i]=s[i+1];
}
strl=i;
}
else
{
exists=0;
}
}
void figure::view(int size)
{
glEnd();
if(!exists) return;
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D,0);
PutMaterial(1,1,1,0,0,0,0,0,0,0,120);
glColor3f(1,1,1);
double figsize=size*0.001875;
#define FIGCF 1.0
#define FIGDS 0.5
#define FIGSM 0.0005
double k=0;
glPushMatrix();
glTranslatef(x,y,z);
glRotatef(angle,0,0,1);
for(int i=0;i<strl;i++)
{
if(str[i]>='0' && str[i]<='9') k=str[i]-'0';
if(str[i]=='.' || str[i]==',') k=10;
if(str[i]=='-') k=11;
glBegin(GL_QUADS);
glTexCoord2f(k/16.0,0);
glVertex3d(-figsize*0.5+figsize*FIGDS*i,-figsize*0.5*FIGCF,i*FIGSM);
glTexCoord2f(k/16.0,1);
glVertex3d(-figsize*0.5+figsize*FIGDS*i,figsize*0.5*FIGCF,i*FIGSM);
glTexCoord2f((k+1)/16.0,1);
glVertex3d(figsize*0.5+figsize*FIGDS*i,figsize*0.5*FIGCF,i*FIGSM);
glTexCoord2f((k+1)/16.0,0);
glVertex3d(figsize*0.5+figsize*FIGDS*i,-figsize*0.5*FIGCF,i*FIGSM);
glEnd();
}
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glPopMatrix();
}
bool bath::triangulation()
{
ofstream file('input.txt');
if(!file.is_open()) return 0;
file<<'2 RBOX s 4 W0 c D2n';
file<<q.size()<<'n';
char buffer [50];
SetTitle('СОКО - сохранение точек');
for(int i=0;i<q.size();i++)
{
sprintf(buffer, '%.19f %.19fn', q[i].m.x, q[i].m.y);
file<<buffer;
}
file.close();
SetTitle('СОКО - расчёт триангуляции');
system(AnsiString('qdelaunay TI input.txt s i Qt TO output.txt').c_str());
//ShowMessage('');
SetTitle('СОКО - чтение треугольников');
ifstream file2('output.txt');
//if(!file2.is_open()) return 0;
unsigned int n=0,x;
file2>>n;
tri.make(n);
for(int i=0;i<n;i++)
{
file2>>x;
tri[i].a=x;
file2>>x;
tri[i].b=x;
file2>>x;
tri[i].c=x;
}
SetTitle('СОКО - треугольники прочитаны');
file2.close();
remove('input.txt');
remove('output.txt');
SetTitle('СОКО - временные файлы удалены');
return 1;
}
bath::bath()
{
DefConstr();
}
bool bath::LoadPoints(AnsiString FileName, bool merkator, bool minus)
{
DefConstr();
fstream file0(AnsiString(FileName+'.dat').c_str());
file0.close();
ifstream file(FileName.c_str());
char tmp[30];
double val;
int size=0;
if(!file.is_open()) return 0;
char name[32];
_splitpath(FileName.c_str(),NULL,NULL,name,NULL);
Filename=name;
SetTitle('СОКО - Чтение ASCII');
vector<double> buff;
while (!file.eof())
{
file>>val;
buff.push_back(val);
size++;
}
q.make(size/3);
file.close();
int i=0, coord=0;
for (int j=0;j<size-1;j++)
{
switch(coord)
{
case 0:
q[i].r.x=buff[j];
coord=1;
break;
case 1:
q[i].r.y=buff[j];
coord=2;
if(merkator) MerToGeo(q[i].r.x,q[i].r.y);
break;
case 2:
q[i].r.z=(-minus*2+1)*buff[j];
coord=0;
if(q[i].r.x<min.x) min.x=q[i].r.x;
if(q[i].r.x>max.x) max.x=q[i].r.x;
if(q[i].r.y<min.y) min.y=q[i].r.y;
if(q[i].r.y>max.y) max.y=q[i].r.y;
if(q[i].r.z<min.z) min.z=q[i].r.z;
if(q[i].r.z>max.z) max.z=q[i].r.z;
i++;
break;
}
}
SetTitle('СОКО');
return 1;
}
bool bath::LoadSlg(DoubleTable &table, AnsiString name)
{
#define FEET_TO_M 0.3048
int c=0,n=1,num;
double depth=0;
SetTitle('СОКО - Чтение slg');
for(int i=1;i<table.d.m;i++)
{
if(table.d[13][i]!=0) c++;
}
if(c>=table.d.m) return 0;
q.make(c);
c=0;
int i;
for(i=1;i<table.d.m;i++)
{
if(table.d[13][i]!=0)
{
if(c>0)
{
q[c-1].r.z=-(depth/n)*FEET_TO_M;
if(q[c-1].r.x<min.x) min.x=q[c-1].r.x;
if(q[c-1].r.x>max.x) max.x=q[c-1].r.x;
if(q[c-1].r.y<min.y) min.y=q[c-1].r.y;
if(q[c-1].r.y>max.y) max.y=q[c-1].r.y;
if(q[c-1].r.z<min.z) min.z=q[c-1].r.z;
if(q[c-1].r.z>max.z) max.z=q[c-1].r.z;
}
q[c].r.x=table.d[13][i];
q[c].r.y=table.d[14][i];
q[c].t=table.d[21][i];
MerToGeo(q[c].r.x,q[c].r.y);
depth=table.d[3][i];
n=1;
c++;
}
else
{
n++;
depth+=table.d[3][i];
}
}
q[c-1].r.z=-(depth/n)*FEET_TO_M;
if(q[c-1].r.x<min.x) min.x=q[c-1].r.x;
if(q[c-1].r.x>max.x) max.x=q[c-1].r.x;
if(q[c-1].r.y<min.y) min.y=q[c-1].r.y;
if(q[c-1].r.y>max.y) max.y=q[c-1].r.y;
if(q[c-1].r.z<min.z) min.z=q[c-1].r.z;
if(q[c-1].r.z>max.z) max.z=q[c-1].r.z;
Filename=name;
SetTitle('СОКО');
slg=1;
return 1;
}
bool bath::MakeEmpty(int length)
{
q.make(length);
return 1;
}
void bath::CountTide(cubic_spline &spl)
{
if(slg)
{
if((double)startDate==0.0) return;
for(int i=0;i<q.size();i++)
{
if(hasTide)
q[i].tide=spl.f(startDate+q[i].t/86400000.0);
else
q[i].tide=0;
}
}
else
{
if((double)startDate==0.0 || (double)endDate==0.0) return;
TDateTime current;
for(int i=0;i<q.size();i++)
{
if(hasTide)
q[i].tide=spl.f((double)startDate+((double)endDate-
(double)startDate)*(i/(double)q.size()));
else
q[i].tide=0;
}
}
}
void bath::ReCountMinMax()
{
min.x=MAX;
max.x=MIN;
min.y=MAX;
max.y=MIN;
min.z=MAX;
max.z=MIN;
for(int i=0;i<q.size();i++)
{
if(q[i].r.x<min.x) min.x=q[i].r.x;
if(q[i].r.x>max.x) max.x=q[i].r.x;
if(q[i].r.y<min.y) min.y=q[i].r.y;
if(q[i].r.y>max.y) max.y=q[i].r.y;
if(q[i].r.z<min.z) min.z=q[i].r.z;
if(q[i].r.z>max.z) max.z=q[i].r.z;
}
needRecount=0;
}
double bath::ReCountMin()
{
double min=MAX;
for(int i=0;i<q.size();i++)
{
if(q[i].r.z<min) min=q[i].r.z;
}
return min;
}
bool bath::CountNet(int TexNum, point3D Min, point3D Max, double Sclxy,
double Sclz, double Cfx, double Cfy, double D, int N, double rad,
double isoHABA, int maskBlurCount, int FigHaba, int IsolineSize,
dinmas<double> *Isolist, bool VarIso)
{
fighaba=FigHaba;
sclxy=Sclxy;
sclz=Sclz;
min=Min;
max=Max;
d=D;
texNum=TexNum;
isoHaba=isoHABA;
isolineSize=IsolineSize;
isolist=Isolist;
varIso=VarIso;
height=cfy*N;
width=cfx*N;
for(int i=0;i<q.size();i++)
{
q[i].m.x=sclxy*(q[i].r.x-min.x-(max.x-min.x)/2);
q[i].m.y=sclxy*(q[i].r.y-min.y-(max.y-min.y)/2);
q[i].m.z=sclz*(q[i].r.z+q[i].tide*(hasTide)-min.z-(max.z-min.z)/2);
}
rmn.z=sclz*(min.z-min.z-(max.z-min.z)/2);
rmx.z=sclz*(max.z-min.z-(max.z-min.z)/2);
SetTitle('СОКО - триангуляция');
triangulation();
SetTitle('СОКО - триангуляция завершена');
counted=0;
if(!p.make(width,height)) return 0;
SetTitle('СОКО - создана сетка');
if(!blurBuff.make(width,height))
{
SetTitle('СОКО - не создана буферная сетка');
return 0;
}
else
{
SetTitle('СОКО - создана буферная сетка');
}
if(!MakeArray(height,width)) return 0;
SetTitle('СОКО - создана текстура');
double ls,hs,ls2,l,mn,lm;
if(max.y-min.y>max.x-min.x)
lm=SphereLenght(min.x, min.y, min.x, max.y);
else
lm=SphereLenght(min.x, min.y, max.x, min.y);
int km=0;
SetTitle('СОКО - обнуление сетки');
for(int j=0;j<width;j++)
{
for(int i=0;i<height;i++)
{
p[i][j].x=-cfx/2+d*i;
p[i][j].y=-cfy/2+d*j;
p[i][j].z=0;
p[i][j].b=p[i][j].z;
blurBuff[i][j]=p[i][j].z;
p[i][j].e=0;
}
}
int ia,ib,ja,jb;
double ta=0,tb=0,tc=1,td=0;
SetTitle('СОКО - расчёт треугольников');
for(int k=0;k<tri.size();k++)
{
ia=floor((MinFrom3(q[tri[k].a].m.x,
q[tri[k].b].m.x,q[tri[k].c].m.x)+cfx/2)/d);
ib=ceil((MaxFrom3(q[tri[k].a].m.x,
q[tri[k].b].m.x,q[tri[k].c].m.x)+cfx/2)/d);
ja=floor((MinFrom3(q[tri[k].a].m.y,
q[tri[k].b].m.y,q[tri[k].c].m.y)+cfy/2)/d);
jb=ceil((MaxFrom3(q[tri[k].a].m.y,
q[tri[k].b].m.y,q[tri[k].c].m.y)+cfy/2)/d);
if(ia<0 || ja<0 || ib>height || jb>width) continue;
if(!CorrectTria(q[tri[k].a].m,
q[tri[k].b].m,q[tri[k].c].m,rad/lm)) continue;
planeSet(
q[tri[k].a].m.x,q[tri[k].b].m.x,q[tri[k].c].m.x,
q[tri[k].a].m.y,q[tri[k].b].m.y,q[tri[k].c].m.y,
q[tri[k].a].m.z,q[tri[k].b].m.z,q[tri[k].c].m.z,
ta,tb,tc,td);
for(int j=ja;j<jb;j++)
{
for(int i=ia;i<ib;i++)
{
if(InTriangle(q[tri[k].a].m,
q[tri[k].b].m,q[tri[k].c].m,p[i][j])
&& tri[k].a>=0 && tri[k].a<q.size()
&& tri[k].b>=0 && tri[k].b<q.size()
&& tri[k].b>=0 && tri[k].c<q.size()
)
{
p[i][j].z=(-ta*p[i][j].x-tb*p[i][j].y-td)/tc;
p[i][j].b=p[i][j].z;
blurBuff[i][j]=p[i][j].z;
p[i][j].e=1;
}
}
}
}
if(maskBlurCount==0)
{
SetTitle('СОКО - расчёт цвета и нормалей');
for(int j=0;j<width;j++)
{
for(int i=0;i<height;i++)
{
if(p[i][j].e)
{
CountColor(i,j);
CountNorm(i,j);
}
}
}
}
else
{
blur(maskBlurCount);
}
exsist=1;
counted=1;
SetTitle('СОКО - наложение текстуры');
BindTexture(texNum,1,0);
if(maskBlurCount==0)
{
countIso(isoHaba,isolist,varIso);
deviation();
}
SetTitle('СОКО');
return 1;
}
void bath::blur(int times)
{
for(int k=0;k<times;k++)
{
for(int j=1;j<width-1;j++)
{
for(int i=1;i<height-1;i++)
{
if(
p[i-1][j+1].e && p[i ][j+1].e && p[i+1][j+1].e &&
p[i-1][j ].e && p[i ][j ].e && p[i+1][j ].e &&
p[i-1][j-1].e && p[i ][j-1].e && p[i+1][j-1].e
)
{
blurBuff[i][j]=(
(0.0625)*p[i-1][j+1].z+(0.125)*
p[i ][j+1].z+(0.0625)*p[i+1][j+1].z+
(0.125 )*p[i-1][j ].z+(0.25 )*
p[i ][j ].z+(0.125 )*p[i+1][j ].z+
(0.0625)*p[i-1][j-1].z+(0.125)*
p[i ][j-1].z+(0.0625)*p[i+1][j-1].z
);
}
else
{
blurBuff[i][j]=p[i][j].z;
}
}
}
for(int j=1;j<width-1;j++)
{
for(int i=1;i<height-1;i++)
{
if(
p[i-1][j+1].e && p[i ][j+1].e && p[i+1][j+1].e &&
p[i-1][j ].e && p[i ][j ].e && p[i+1][j ].e &&
p[i-1][j-1].e && p[i ][j-1].e && p[i+1][j-1].e
)
{
p[i][j].z=blurBuff[i][j];
(
(0.0625)*blurBuff[i-1][j+1]+(0.125 )*
blurBuff[i ][j+1]+(0.0625)*blurBuff[i+1][j+1]+
(0.125 )*blurBuff[i-1][j ]+(0.25 )*
blurBuff[i ][j ]+(0.125 )*blurBuff[i+1][j ]+
(0.0625)*blurBuff[i-1][j-1]+(0.125 )*
blurBuff[i ][j-1]+(0.0625)*blurBuff[i+1][j-1]
);
}
else
{
p[i][j].z=blurBuff[i][j];
}
if(k==times-1)
{
CountColor(i,j);
CountNorm(i,j);
}
}
SetTitle('СОКО - размытие '+
AnsiString(FormatFloat(100*(double(k+1)/double(times)),2))+'%');
}
SetTitle('СОКО');
}
exsist=1;
BindTexture(texNum,1,0);
blurCount+=times;
countIso(isoHaba,isolist,varIso);
deviation();
SetTitle('СОКО');
}
void bath::deviation()
{
return;
SetTitle('СОКО - расчёт ошибки');
double sz=0, srz=0, z;
int nx,ny;
for(int i=0;i<q.size();i++)
{
nx=floor((q[i].m.x+cfx/2)/d);
ny=floor((q[i].m.y+cfy/2)/d);
if(nx>=height-2 || ny>=width-2) continue;
if(!p[nx][ny].e || !p[nx][ny+1].e ||
!p[nx+1][ny+1].e || !p[nx+1][ny].e) continue;
z=bilinear(p[nx][ny].z,p[nx][ny+1].z,
p[nx+1][ny].z,p[nx+1][ny+1].z,p[nx][ny].x,
p[nx+1][ny].x,p[nx][ny].y,p[nx][ny+1].y,
q[i].m.x,q[i].m.y);
sz+=fabs(q[i].m.z);
srz+=fabs(z);
}
dev=100*fabs(sz-srz)/srz;
}
inline __fastcall void bath::CountColor(int &i, int &j)
{
tmpz=p[i][j].z/sclz+min.z+(max.z-min.z)/2;
if(difference)
{
imageData[i*RealWidth+j].r=
255*countColor(tmpz,-2,2,0,1,blackAndWhite);
imageData[i*RealWidth+j].g=
255*countColor(tmpz,-2,2,1,1,blackAndWhite);
imageData[i*RealWidth+j].b=
255*countColor(tmpz,-2,2,2,1,blackAndWhite);
}
else
{
imageData[i*RealWidth+j].r=
255*countColor(tmpz,min.z,max.z,0,0,blackAndWhite);
imageData[i*RealWidth+j].g=
255*countColor(tmpz,min.z,max.z,1,0,blackAndWhite);
imageData[i*RealWidth+j].b=
255*countColor(tmpz,min.z,max.z,2,0,blackAndWhite);
}
}
void bath::ReCountColor()
{
SetTitle('СОКО - расчёт цвета');
for(int j=1;j<width-1;j++)
{
for(int i=1;i<height-1;i++)
{
if(p[i][j].e) CountColor(i,j);
}
}
exsist=1;
SetTitle('СОКО - наложение текстуры');
BindTexture(texNum,1,0);
SetTitle('СОКО');
}
inline __fastcall void bath::CountNorm(int &i, int &j)
{
if(i>0 && j>0)
{
VecNormD(
p[i][j].x, p[i][j].y, p[i][j].z,
p[i][j-1].x, p[i][j-1].y, p[i][j-1].z,
p[i-1][j-1].x, p[i-1][j-1].y, p[i-1][j-1].z,
p[i][j].nx, p[i][j].ny, p[i][j].nz, 0) ;
}
}
void bath::DefConstr()
{
//rt=1;
width=1;
height=1;
counted=0;
tex=1;
viewPoints=1;
net=0;
//fb=0;
step=1;
PixelsQnt=0;
isolines=1;
dev=0;
//dif=0;
viewRelief=1;
min.x=MAX; max.x=MIN; min.y=MAX; max.y=MIN; min.z=MAX; max.z=MIN;
visible=1;
hideFar=1;
hideUpLimit=0;
needRecount=0;
difference=0;
blackAndWhite=0;
slg=0;
hasTide=1;
startDate=0;
endDate=0;
lighting=1;
}
void bath::OneVertex(int &i, int &j)
{
//glColor3d(1,1,1);
//material1.view(1,1,1,0,1,1,1,0,0,0,60);
if(tex)
{
glTexCoord2f(((1.*j/width))*wcoeff,((1.*i/height))*hcoeff);
}
else
{
k=i*RealWidth+j;
material_color[0]=imageData[k].r/255.0;
material_color[1]=imageData[k].g/255.0;
material_color[2]=imageData[k].b/255.0;
glColor3fv(material_color);
glMaterialfv(GL_FRONT_AND_BACK,
GL_AMBIENT_AND_DIFFUSE, material_color);
}
glNormal3d(p[i][j].nx,p[i][j].ny,p[i][j].nz);
glVertex3d(p[i][j].x,p[i][j].y,p[i][j].z);
}
void bath::view()
{
if(!counted) return;
if(viewRelief)
{
exsist=0;
if(tex)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,texNum);
PutMaterial(1,1,1,0,0,0,0,0,0,0,120);
}
int tc=0;
int stepBuff;
if(!rt)
{
stepBuff=step;
step=1;
}
glColor3d(1,1,1);
PutMaterial(1,1,1,0,0.5,0.5,0.5,0,0,0,60);
if(lighting) glEnable(GL_LIGHTING);
if(step<height && step<width)
{
for(int i=1;i<height-step;i+=step)
{
for(int j=1;j<width-step;j+=step)
{
if(
((hideFar && p[i][j].e && p[i][j+step].e &&
p[i+step][j+step].e && p[i+step][j].e) || !hideFar )
&&
((hideUpLimit && p[i][j].z<rmx.z && p[i][j].z>rmn.z) ||
!hideUpLimit || difference )
)
{
if(!net) glBegin(GL_QUADS); else glBegin(GL_LINE_LOOP);
OneVertex(i,j);
OneVertex(i,j+step);
OneVertex(i+step,j+step);
OneVertex(i+step,j);
glEnd();
}
}
}
}
if(lighting) glDisable(GL_LIGHTING);
glColor3d(0,0,0);
if(!rt)
{
step=stepBuff;
}
if(tex)
{
glDisable(GL_TEXTURE_2D);
}
}
if(isolines) viewIso();
}
void bath::ViewPoints()
{
if(viewPoints)
{
glPointSize(1);
glBegin(GL_POINTS);
for(int i=0;i<q.size();i++)
{
glVertex3d(q[i].r.x,q[i].r.y,q[i].r.z+q[i].tide*(hasTide));
}
glEnd();
}
}
double bath::cf(double &s, double &e, double &f, bool revert)
{
return fabs((revert)-((f-s)/(e-s)));
}
void bath::makeLine(int &i, int &j)
{
if(
(p[i][j].z< f && p[i][j+1].z>=f && p[i+1][j+1].z>=f && p[i+1][j].z>=f)||
(p[i][j].z>=f && p[i][j+1].z< f && p[i+1][j+1].z< f && p[i+1][j].z< f))
{
line.put(p[i][j].x,p[i][j].y+d*cf(p[i][j].z,p[i][j+1].z,f,0),f
,p[i][j].x+d*cf(p[i][j].z,p[i+1][j].z,f,0),p[i][j].y,f,zero);
iso.push_back(line);
//isom.insert(pair<pair<int,int>,isoline>(pair<int,int>(i,j),line));
return;
}
if(
(p[i][j].z>=f && p[i][j+1].z< f && p[i+1][j+1].z>=f && p[i+1][j].z>=f)||
(p[i][j].z< f && p[i][j+1].z>=f && p[i+1][j+1].z< f && p[i+1][j].z< f))
{
line.put(p[i][j].x,p[i][j].y+d*cf(p[i][j].z,p[i][j+1].z,f,0),f
,p[i][j].x+d*cf(p[i][j+1].z,p[i+1][j+1].z,f,0),p[i][j].y+d,f,zero);
iso.push_back(line);
//isom.insert(pair<pair<int,int>,isoline>(pair<int,int>(i,j),line));
return;
}
if(
(p[i][j].z>=f && p[i][j+1].z>=f && p[i+1][j+1].z< f && p[i+1][j].z>=f)||
(p[i][j].z< f && p[i][j+1].z< f && p[i+1][j+1].z>=f && p[i+1][j].z< f))
{
line.put(p[i][j].x+d*cf(p[i+1][j+1].z,p[i][j+1].z,f,1),p[i][j].y+d,f
,p[i][j].x+d,p[i][j].y+d*cf(p[i+1][j+1].z,p[i+1][j].z,f,1),f,zero);
iso.push_back(line);
//isom.insert(pair<pair<int,int>,isoline>(pair<int,int>(i,j),line));
return;
}
if(
(p[i][j].z>=f && p[i][j+1].z>=f && p[i+1][j+1].z>=f && p[i+1][j].z< f)||
(p[i][j].z< f && p[i][j+1].z< f && p[i+1][j+1].z< f && p[i+1][j].z>=f))
{
line.put(p[i][j].x+d*cf(p[i][j].z,p[i+1][j].z,f,0),p[i][j].y,f
,p[i][j].x+d,p[i][j].y+d*cf(p[i+1][j].z,p[i+1][j+1].z,f,0),f,zero);
iso.push_back(line);
//isom.insert(pair<pair<int,int>,isoline>(pair<int,int>(i,j),line));
return;
}
if(
(p[i][j].z< f && p[i][j+1].z< f && p[i+1][j+1].z>=f && p[i+1][j].z>=f)||
(p[i][j].z>=f && p[i][j+1].z>=f && p[i+1][j+1].z< f && p[i+1][j].z< f))
{
line.put(p[i][j].x+d*cf(p[i][j].z,p[i+1][j].z,f,0),p[i][j].y,f
,p[i][j].x+d*cf(p[i][j+1].z,p[i+1][j+1].z,f,0),p[i][j].y+d,f,zero);
iso.push_back(line);
//isom.insert(pair<pair<int,int>,isoline>(pair<int,int>(i,j),line));
return;
}
if(
(p[i][j].z< f && p[i][j+1].z>=f && p[i+1][j+1].z>=f && p[i+1][j].z< f)||
(p[i][j].z>=f && p[i][j+1].z< f && p[i+1][j+1].z< f && p[i+1][j].z>=f))
{
line.put(p[i][j].x,p[i][j].y+d*cf(p[i][j].z,p[i][j+1].z,f,0),f
,p[i][j].x+d,p[i][j].y+d*cf(p[i+1][j].z,p[i+1][j+1].z,f,0),f,zero);
iso.push_back(line);
//isom.insert(pair<pair<int,int>,isoline>(pair<int,int>(i,j),line));
return;
}
if(
(p[i][j].z>=f && p[i][j+1].z< f && p[i+1][j+1].z>=f && p[i+1][j].z< f)||
(p[i][j].z< f && p[i][j+1].z>=f && p[i+1][j+1].z< f && p[i+1][j].z>=f))
{
line.put(p[i][j].x,p[i][j].y+d*cf(p[i][j].z,p[i][j+1].z,f,0),f
,p[i][j].x+d*cf(p[i][j].z,p[i+1][j].z,f,0),p[i][j].y,f,zero);
iso.push_back(line);
//isom.insert(pair<pair<int,int>,isoline>(pair<int,int>(i,j),line));
line.put(p[i][j].x+d*cf(p[i+1][j+1].z,p[i][j+1].z,f,1),p[i][j].y+d,f
,p[i][j].x+d,p[i][j].y+d*cf(p[i+1][j+1].z,p[i+1][j].z,f,1),f,zero);
iso.push_back(line);
//isom.insert(pair<pair<int,int>,isoline>(pair<int,int>(i,j),line));
return;
}
}
void bath::ViewFigures(int size)
{
//ViewValue('-125.4',0,0,0.05,270);
if(!figures.exists) return;
glBegin(GL_LINES);
for(int i=0;i<fighaba;i++)
{
for(int j=0;j<fighaba;j++)
{
figures[i][j].view(size);
}
}
glEnd();
}
void bath::countOneIso(double k)
f=sclz*(k-min.z-(max.z-min.z)/2);
for(int i=1;i<height-1;i++)
{
for(int j=1;j<width-1;j++)
{
if(
(p[i][j].e && p[i][j+1].e && p[i+1][j+1].e && p[i+1][j].e)
&&
((hideUpLimit && p[i][j].z<rmx.z && p[i][j].z>rmn.z)
|| !hideUpLimit)
)
makeLine(i,j);
}
}
}
void bath::countIso(double IsoHaba, dinmas<double> *Isolist, bool VarIso)
{
isoHaba=IsoHaba;
varIso=VarIso;
isolist=Isolist;
if(p.n==0) return;
double k;
iso.clear();
SetTitle('СОКО - расчёт изолиний');
zero=1;
if(!difference)
{
double min=ReCountMin();
if(varIso)
{
for(k=0;k>min;k-=isoHaba)
{
countOneIso(k);
zero=0;
}
for(k=isoHaba;k<max.z;k+=isoHaba)
{
countOneIso(k);
}
}
else
{
for(int i=0;i<isolist->size();i++)
{
zero=(isolist->operator [](i)==0);
countOneIso(isolist->operator [](i));
}
}
}
else
{
for(k=0;k>-4;k-=isoHaba)
{
countOneIso(k);
zero=0;
}
for(k=isoHaba;k<4;k+=isoHaba)
{
countOneIso(k);
}
}
CountFigures(fighaba);
}
void bath::CountFigures(int figh)
{
//return;
if(p.n==0 || iso.size()==0) return;
SetTitle('СОКО - расчёт цифр');
fighaba=figh;
figures.make(fighaba,fighaba);
double l;
for(int i=0;i<fighaba;i++)
{ //0.86602540378443864676372317075294
for(int j=0;j<fighaba;j++)
{
if(cfx<cfy)
{
figures[i][j].x=-cfx/2+(cfx*i/fighaba);
if(i%2!=0)
figures[i][j].y=-cfy/2+(cfy*j/fighaba);
else
figures[i][j].y=-cfy/2+0.5*cfy/fighaba+(cfy*j/fighaba);
}
else
{
figures[i][j].y=-cfy/2+(cfy*j/fighaba);
if(j%2!=0)
figures[i][j].x=-cfx/2+(cfx*i/fighaba);
else
figures[i][j].x=-cfx/2+0.5*cfx/fighaba+(cfx*i/fighaba);
}
figures[i][j].length=MAX;
for(int k=0;k<iso.size();k++)
{
l=sqrt(sqr(iso[k].a.x-figures[i][j].x)+
sqr(iso[k].a.y-figures[i][j].y));
if(l<figures[i][j].length)
{
figures[i][j].length=l;
figures[i][j].line=&iso[k];
}
}
figures[i][j].activate(
((cfx>cfy)?(cfy/fighaba):(cfx/fighaba))/2,-
(figures[i][j].line->a.z/sclz+min.z+
(max.z-min.z)/2)*(difference?-1:1));
}
}
SetTitle('СОКО');
}
void bath::viewIso()
{
//glEnable(GL_BLEND);
for(int i=0;i<iso.size();i++)
{
iso[i].view(isolineSize);
}
//glDisable(GL_BLEND);
}
void bath::EraseNet()
{
if(!counted) return;
counted=0;
}
bool bath::GetDiffer(bath &src, bath &dst,
int TexNum, double isoHABA, int DiffBlur)
{
SetTitle('СОКО - расчёт разницы');
//DefConstr();
setConstantPreset(src);
difference=1;
Filename=src.Filename+'-'+dst.Filename;
//dif=1;
sclxy=src.sclxy;
sclz=src.sclz;
cfx=src.cfx;
cfy=src.cfy;
min=src.min;
max=src.max;
rmn=src.rmn;
rmx=src.rmx;
diffBlur=DiffBlur;
d=src.d;
texNum=TexNum;
height=src.width;
width=src.height;
isoHaba=isoHABA;
counted=0;
p.make(width,height);
blurBuff.make(width,height);
MakeArray(height,width);
for(int j=0;j<width;j++)
{
for(int i=0;i<height;i++)
{
p[i][j].x=src.p[i][j].x;
p[i][j].y=src.p[i][j].y;
p[i][j].z=
sclz*(
((src.p[i][j].z/src.sclz+src.min.z+(src.max.z-src.min.z)/2)-
(dst.p[i][j].z/dst.sclz+dst.min.z+(dst.max.z-dst.min.z)/2))
-src.min.z-(src.max.z-src.min.z)/2);
p[i][j].b=p[i][j].z;
blurBuff[i][j]=p[i][j].z;
//p[i][j].s=(src.p[i][j].s+dst.p[i][j].s)/2.;
p[i][j].e=src.p[i][j].e&&dst.p[i][j].e;
if(diffBlur==0)
{
CountColor(i,j);
CountNorm(i,j);
}
}
}
exsist=1;
counted=1;
blur(diffBlur);
BindTexture(texNum,1,0);
countIso(isoHaba,isolist,varIso);
return 1;
bool bath::GetDifferPoints(bath &dst, double Range)
{
SetTitle('СОКО - расчёт разницы');
double rx=Range*(max.x-min.x)/SphereLenght(min.x, min.y, max.x, min.y);
double ry=Range*(max.y-min.y)/SphereLenght(min.x, min.y, min.x, max.y);
vector<BathPoint> q1;
for(int i=0;i<q.size();i++)
{
for(int j=0;j<dst.q.size();j++)
{
if((fabs(q[i].r.x-dst.q[j].r.x)<=rx) &&
(fabs(q[i].r.y-dst.q[j].r.y)<=ry))
{
q1.push_back(q[i]);
goto kk;
}
}
kk:
if(i%1000==0)
SetTitle('СОКО - расчёт разницы для ''+Filename+'' '+
AnsiString(FormatFloat(100*(double(i+1)/double(q.size())),2))+'%');
}
q.make(q1.size());
for(int i=0;i<q1.size();i++)
{
q[i]=q1[i];
}
SetTitle('СОКО');
return 1;
}
bool bath::ReBindTexture()
{
if(counted) exsist=1;
return BindTexture(texNum,1,0);
}
bool bath::SaveNet(AnsiString FileName)
{
ofstream file(FileName.c_str());
if(!file.is_open()) return 0;
SetTitle('СОКО - сохранение сетки');
char buffer [10];
int n;
file<<'0 ';
for(int i=0;i<height;i++)
{
sprintf(buffer, '%.13f', p[i][0].x/sclxy+min.x+(max.x-min.x)/2);
file<<buffer<<' ';
}
file<<'n';
for(int j=0;j<width;j++)
{
sprintf(buffer, '%.13f', p[0][j].y/sclxy+min.y+(max.y-min.y)/2);
file<<buffer<<' ';
for(int i=0;i<height;i++)
{
sprintf(buffer, '%.13f', p[i][j].z/sclz+min.z+(max.z-min.z)/2);
file<<buffer<<' ';
}
file<<'n';
}
file.close();
return 1;
}
bool bath::SaveANI(AnsiString FileName, double minutesStep)
{
SetTitle('СОКО - сохранение сетки');
FILE *pFile;
pFile=fopen(AnsiString(FileName.SubString(
1,FileName.Length()-4)+'.dat').c_str(), 'wb');
if(pFile==0) return 0;
float value;
for(int j=0;j<width;j++)
{
for(int i=0;i<height;i++)
{
if(p[i][j].e)
{
value=-p[i][j].z/sclz+min.z+(max.z-min.z)/2;
}
else
{
value=10001;
}
fwrite(&value, sizeof(float), 1, pFile);
}
}
fclose(pFile);
char buff[256];
char drive[3],direc[256],name[128],ext[8];
_splitpath(FileName.c_str(),drive,direc,name,ext);
ofstream file(FileName.c_str());
CharToOem(Filename.c_str(),buff);
file<<buff<<'n';
file<<'Created by SOKOn';
CharToOem(name,buff);
file<<buff<<'.datn4n2n';
file<<width<<' '<<height<<'n';
file<<'0 0 0 0n';
file<<ReplaceComma(FormatFloat('0.000000',min.z)).c_str()<<
' '<<ReplaceComma(FormatFloat('0.000000',max.z)).c_str()<<' mn';
file<<ReplaceComma(minutesStep).c_str()<<' '<<
ReplaceComma(minutesStep).c_str()<<' ' 0n';
file<<'0 '<<DegToCoord(min.y).c_str()<<' '<<DegToCoord(min.x).c_str();
file<<'n0n';
file.close();
return 1;
}
bool bath::SavePointsGoogle(AnsiString FileName)
{
ofstream file(FileName.c_str());
if(!file.is_open()) return 0;
SetTitle('СОКО - сохранение точек');
char buffer [20];
file<< AnsiString(
'<?xml version='1.0' encoding='UTF-8'?><kml xmlns='http://www.opengis.net/kml/2.2' xmlns:gx='http://www.google.com/kml/ext/2.2' xmlns:kml='http://www.opengis.net/kml/2.2' xmlns:atom='http://www.w3.org/2005/Atom'><Document><name>'+
Filename+'.kml</name>n'+
'<StyleMap id='msn_shaded_dot'><Pair><key>normal</key><styleUrl>#sn_shaded_dot</styleUrl></Pair><Pair><key>highlight</key><styleUrl>#sh_shaded_dot</styleUrl></Pair></StyleMap><Style id='sn_shaded_dot'><IconStyle><scale>0.2</scale><Icon><href>http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png</href></Icon></IconStyle><ListStyle></ListStyle></Style><Style id='sh_shaded_dot'><IconStyle><scale>0.236364</scale><Icon><href>http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png</href></Icon></IconStyle><ListStyle></ListStyle></Style>'+
'<Folder><name>'+Filename+'</name><open>1</open>n').c_str();
for(int i=0;i<q.size();i++)
{
file<<'<Placemark><styleUrl>#msn_shaded_dot</styleUrl><Point><altitudeMode>relativeToGround</altitudeMode><coordinates>';
sprintf(buffer, '%.13f', q[i].r.x);
file<<buffer<<',';
sprintf(buffer, '%.13f', q[i].r.y);
file<<buffer<<',';
sprintf(buffer, '%.13f', q[i].r.z+q[i].tide*(hasTide));
file<<buffer<<'n';
file<<'n</coordinates></Point></Placemark>';
}
file<<'</Folder></Document></kml>';
file.close();
return 1;
}
bool bath::SaveTrack(AnsiString FileName)
{
ofstream file(FileName.c_str());
if(!file.is_open()) return 0;
SetTitle('СОКО - сохранение трека');
char buffer [20];
file<<'<?xml version='1.0' encoding='UTF-8'?>n<kml xmlns='http://www.opengis.net/kml/2.2' xmlns:gx='http://www.google.com/kml/ext/2.2' xmlns:kml='http://www.opengis.net/kml/2.2' xmlns:atom='http://www.w3.org/2005/Atom'>n<Document>n<name>';
file<<'track';
file<<'</name>n<Style id='sn_ylw-pushpin'>n<IconStyle>n<scale>n1.1</scale>n<Icon>n<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>n</Icon>n<hotSpot x='20' y='2' xunits='pixels' yunits='pixels'/>n</IconStyle>n</Style>n<StyleMap id='msn_ylw-pushpin'>n<Pair>n<key>normal</key>n<styleUrl>#sn_ylw-pushpin</styleUrl>n</Pair>n<Pair>n<key>highlight</key>n<styleUrl>#sh_ylw-pushpin</styleUrl>n</Pair>n</StyleMap>n<Style id='sh_ylw-pushpin'>n<IconStyle>n<scale>n1.3</scale>n<Icon>n<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>n</Icon>n<hotSpot x='20' y='2' xunits='pixels' yunits='pixels'/>n</IconStyle>n</Style>n<Placemark>n<name>';
file<<'track';
file<<'</name>n<styleUrl>#msn_ylw-pushpin</styleUrl>n<LineString>n<tessellate>1</tessellate>n<coordinates>n';
for(int i=0;i<q.size();i++)
{
sprintf(buffer, '%.13f', q[i].r.x);
file<<buffer<<',';
sprintf(buffer, '%.13f', q[i].r.y);
file<<buffer<<',0 ';
}
file<<'</coordinates>n</LineString>n</Placemark>n</Document>n</kml>n';
file.close();
return 1;
}
bool bath::SavePoints(AnsiString FileName)
{
ofstream file(FileName.c_str());
if(!file.is_open()) return 0;
SetTitle('СОКО - сохранение точек');
char buffer [20];
for(int i=0;i<q.size();i++)
{
sprintf(buffer, '%.13f', q[i].r.x);
file<<buffer<<' ';
sprintf(buffer, '%.13f', q[i].r.y);
file<<buffer<<' ';
sprintf(buffer, '%.13f', -q[i].r.z-q[i].tide*(hasTide));
file<<buffer<<'n';
}
file.close();
return 1;
}
bool bath::SavePointsMer(AnsiString FileName)
{
ofstream file(FileName.c_str());
if(!file.is_open()) return 0;
SetTitle('СОКО - сохранение точек');
char buffer [20];
double x,y;
for(int i=0;i<q.size();i++)
{
x=q[i].r.x;
y=q[i].r.y;
GeoToMer(x,y);
sprintf(buffer, '%i', (int)x);
file<<buffer<<' ';
sprintf(buffer, '%i', (int)y);
file<<buffer<<' ';
sprintf(buffer, '%.13f', -q[i].r.z-q[i].tide*(hasTide));
file<<buffer<<'n';
}
file.close();
return 1;
}
bool bath::SaveNetGoogle(AnsiString FileName, int ScaleZ)
{
ofstream file(FileName.c_str());
if(!file.is_open()) return 0;
SetTitle('СОКО - сохранение сетки');
char buffer [20];
int k;
file<< AnsiString(
<?xml version='1.0' encoding='UTF-8'?><kml xmlns='http://www.opengis.net/kml/2.2'><Document><name>'+
Filename+'</name>n<Style id='line'><LineStyle><color>'+((viewRelief)?'4d000000':'ffffffff')+'</color><width>1</width></LineStyle><PolyStyle><color>'+((viewRelief)?'4d000000':'ffffffff')+'</color></PolyStyle></Style>n').c_str();
if(viewRelief)
{
for(int i=1;i<height-step;i+=step)
{
for(int j=1;j<width-step;j+=step)
{
if(
((hideFar && p[i][j].e && p[i][j+step].e &&
p[i+step][j+step].e && p[i+step][j].e) || !hideFar )
&&
((hideUpLimit && p[i][j].z<rmx.z && p[i][j].z>rmn.z &&
p[i+step][j+step].e && p[i+step][j].e) ||
!hideUpLimit || difference )
)
{
file<<'<Placemark><visibility>1</visibility><Style id='transBluePoly'><LineStyle><width>0</width></LineStyle><PolyStyle><color>n';
k=i*RealWidth+j;;
sprintf(buffer, 'ff%0*x%0*x%0*x',2,imageData[k].b,2,imageData[k].g,2,imageData[k].r);
file<<buffer<<'n';
file<<'</color></PolyStyle></Style><Polygon><altitudeMode>absolute</altitudeMode><outerBoundaryIs><LinearRing><coordinates>n';
sprintf(buffer, '%.13f',p[i][j].x/sclxy+
min.x+(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',p[i][j].y/sclxy+
min.y+(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*(p[i][j].z/sclz+min.z+
(max.z-min.z)/2-min.z));
file<<buffer<<'n';
sprintf(buffer, '%.13f',p[i+step][j].x/sclxy+min.x+
(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',p[i+step][j].y/sclxy+min.y+
(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*(p[i+step][j].z/sclz+min.z+
(max.z-min.z)/2-min.z));
file<<buffer<<'n';
sprintf(buffer, '%.13f',p[i+step][j+step].x/sclxy+min.x+
(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',p[i+step][j+step].y/sclxy+min.y+
(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*
(p[i+step][j+step].z/sclz+min.z+(max.z-min.z)/2-min.z));
file<<buffer<<'n';
sprintf(buffer, '%.13f',p[i][j].x/sclxy+min.x+
(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',p[i][j].y/sclxy+min.y+
(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*(p[i][j].z/sclz+min.z+
(max.z-min.z)/2-min.z));
file<<buffer<<'n';
file<<'</coordinates></LinearRing></outerBoundaryIs></Polygon></Placemark>n';
file<<'<Placemark><visibility>1</visibility><Style id='transBluePoly'><LineStyle><width>0</width></LineStyle><PolyStyle><color>n';
k=i*RealWidth+j;;
sprintf(buffer, 'ff%0*x%0*x%0*x',2,imageData[k].b,2,
imageData[k].g,2,imageData[k].r);
file<<buffer<<'n';
file<<'</color></PolyStyle></Style><Polygon><altitudeMode>absolute</altitudeMode><outerBoundaryIs><LinearRing><coordinates>n';
sprintf(buffer, '%.13f',p[i+step][j+step].x/
sclxy+min.x+(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',p[i+step][j+step].y/
sclxy+min.y+(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*(p[i+step][j+step].z/
sclz+min.z+(max.z-min.z)/2-min.z));
file<<buffer<<'n';
sprintf(buffer, '%.13f',p[i][j+step].x/
sclxy+min.x+(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',p[i][j+step].y/
sclxy+min.y+(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*(p[i][j+step].z/
sclz+min.z+(max.z-min.z)/2-min.z));
file<<buffer<<'n';
sprintf(buffer, '%.13f',p[i][j].x/
sclxy+min.x+(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',p[i][j].y/
sclxy+min.y+(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*(p[i][j].z/
sclz+min.z+(max.z-min.z)/2-min.z));
file<<buffer<<'n';
sprintf(buffer, '%.13f',p[i+step][j+step].x/
sclxy+min.x+(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',p[i+step][j+step].y/
sclxy+min.y+(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*(p[i+step][j+step].z/
sclz+min.z+(max.z-min.z)/2-min.z));
file<<buffer<<'n';
file<<'</coordinates></LinearRing></outerBoundaryIs></Polygon></Placemark>n';
}
}
}
}
if(isolines)
{
for(int i=0;i<iso.size();i++)
{
file<<'<Placemark><name>Absolute</name><visibility>1</visibility><styleUrl>#line</styleUrl><LineString><tessellate>1</tessellate><altitudeMode>absolute</altitudeMode><coordinates>n';
sprintf(buffer, '%.13f',iso[i].a.x/sclxy+min.x+(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',iso[i].a.y/sclxy+min.y+(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*(iso[i].a.z/sclz+min.z+
(max.z-min.z)/2-min.z));
file<<buffer<<'n';
sprintf(buffer, '%.13f',iso[i].b.x/sclxy+min.x+(max.x-min.x)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',iso[i].b.y/sclxy+min.y+(max.y-min.y)/2);
file<<buffer<<',';
sprintf(buffer, '%.13f',ScaleZ*(iso[i].b.z/sclz+min.z+
(max.z-min.z)/2-min.z));
file<<buffer<<'n';
file<<'</coordinates></LineString></Placemark>n';
}
}
file<<'</Document></kml>';
file.close();
return 1;
}
void bath::setConstantPreset(bath &src)
{
f=src.f;
zero=src.zero;
startDate=src.startDate;
endDate=src.startDate;
d=src.d;
sclxy=src.sclxy;
sclz=src.sclz;
cfx=src.cfx;
cfy=src.cfy;
dev=src.dev;
tmpz=src.tmpz;
isoHaba=src.isoHaba;
min=src.min;
max=src.max;
rmn=src.rmn;
rmx=src.rmx;
k=src.k;
blurCount=src.blurCount;
texNum=src.texNum+1;
Filename=src.Filename;
tex=src.tex;
step=src.step;
rt=src.rt;
viewPoints=src.viewPoints;
net=src.net;
counted=src.counted;
isolines=src.isolines;
viewRelief=src.viewRelief;
visible=src.visible;
hideFar=src.hideFar;
hideUpLimit=src.hideUpLimit;
needRecount=src.needRecount;
difference=src.difference;
blackAndWhite=src.blackAndWhite;
slg=src.slg;
hasTide=src.hasTide;
exsist=src.exsist;
binded=src.binded;
width=src.width;
height=src.height;
RealWidth=src.RealWidth;
RealHeight=src.RealHeight;
PixelsQnt=src.PixelsQnt,
hcoeff=src.hcoeff;
wcoeff=src.wcoeff;
ID=src.ID;
fighaba=src.fighaba;
isolineSize=src.isolineSize;
}
bath::operator=(bath &src)
{
setConstantPreset(src);
if(src.q.size()>0)
{
q.make(src.q.size());
for(int i=0;i<src.q.size();i++)
{
q[i]=src.q[i];
}
}
if(src.iso.size()>0)
{
for(int i=0;i<src.iso.size();i++)
{
iso.push_back(src.iso[i]);
}
}
if(src.imageData.size()>0)
{
imageData.make(src.imageData.size());
for(int i=0;i<src.imageData.size();i++)
{
imageData[i]=src.imageData[i];
}
}
if(src.p.n>0)
{
p.make(src.p.n,src.p.m);
blurBuff.make(src.p.n,src.p.m);
for(int i=0;i<src.p.n;i++)
{
for(int j=0;j<src.p.m;j++)
{
p[i][j]=src.p[i][j];
blurBuff[i][j]=src.blurBuff[i][j];
}
}
exsist=1;
BindTexture(texNum,1,0);
}
}
#endif
4. РУКОВОДСТВО ПРОГРАММИСТА
4.1 Руководство программиста для программы в целом
4.1.1 Назначение и условия применения программного обеспечения
SOKO обеспечивает выполнение следующих основных функций:
Импорт батиметрическиз данных из исходных треков, получаемых с картплоттера-эхолота;
Импорт береговых линий из GPS-навигатора;
Импорт данных, искусственно созданных с помощью приложения Google Maps;
Наглядное совмещение, компоновка и редактирование данных, исправление ошибок;
Подготовка данных к отображению и обработке: вычитание высоты прилива и сезонных колебаний уровня моря;
Выбор необходимого участка для расчёта посредством введения географических координат прямоугольника, либо в графическом режиме;
Настройка параметров отображения будущей карты: коэффициента пропорциональности высоты, частоты изолиний и других;
Построение и батиметрических карт;
Построение карт сравнения динамики рельефа;
Сохранение готовых карт в виде изображений любого размера;
Создание видеоролика, отображающего карту с различных ракурсов путём последовательной установки камеры с различных позиций;
Экспорт данных в различные форматы;
Сохранение текущего состояния системы для дальнейшей обработки.
Для работы с данным программным обеспечением необходимо перечисленное далее аппаратное и программное обеспечение.
Техническое обеспечение:
персональный компьютер совместимый с IBM PC с тактовой частотой процессора не ниже 1000 МГц;
оперативная память 1024 Мб и более;
накопитель данных со свободным объёмом не менее 3 Гб;
видеокарта и монитор, поддерживающие разрешение 1024*768 точек и выше, с частотой обновления не менее 60 Гц;
устройства ввода клавиатура и манипулятор «мышь» (стандартные);
Программное обеспечение:
операционная система - Microsoft Windows 98 или более поздняя;
интегрированная среда разработки приложений Borland C+ Builder 6
Raize Components - набор визуальных компонентов для Delphi / C++Builder версии не ниже 4.3.2;
приложение для предвычисления приливов wxtide версии не ниже 4.7;
Microsoft Office Excel 2003 или выше;
распространяемый дистрибутив приложения с пакетом дополнительных консольных программ и исполняемым файлом программы «Soko.exe» (схема зависимостей компонентов приложения показана на рисунке 1.10 в приложении №1).
4.1.2 Характеристика программного обеспечения
Программа включает в себя 74 заголовочных файла языке программирования C++, 10 файлов реализации функций, и один файл формы soko_code.dfm, где дана спецификация графического интерфейса.
Графический интерфейс приложения создан в среде разработки приложений Borland C++ Builder на основе компонентов библиотек классов VCL и библиотеки Raize.
Приложение опирается на стандартную библиотеку классов C++, библиотеку VCL, предоставляемую фирмой Borland, библиотеку OpenGL, а также на несколько консольных приложений, необходимых для преобразования данных.
При разработке программного обеспечения в проекте используются модули стандартной библиотеки C++, библиотек VCL, Raize и OpenGL, перечисленные далее в таблицах 4.1-4.3.
Таблица 4.1 - Использованные в программе заголовочные файлы стандартной библиотеки
Заголовочный файл |
Назначение в проекте программы |
|
windows.h |
Реализует доступ к API-функциям операционной системы Microsoft Windows |
|
iostream.h |
Работа с потоками и консолью операционной системы, используется для связи с консольными модулями. |
|
fstream.h |
Чтение и запись файлов |
|
stdio.h |
Стандартный ввод и вывод |
|
map |
Реализует шаблоны классов контейнеров std::map и std::multimap - Ассоциативный массив и мультиотображение. |
|
vector |
Реализует шаблон класса контейнеров std::vector - динамический массив. |
|
math |
Основные математческие операции, такие как косинус или возведение в степень |
|
stdarg.h |
Средства для перебора аргументов функции, количество и типы которых заранее не известны. |
|
ctime |
Типы и функции для работы с датой и временем. |
|
cstdlib |
Функции, занимающиеся выделением памяти, контроль процесса выполнения программы, преобразования типов и другие. |
|
limits |
Определения характеристик общих типов переменных. |
Таблица 4.2 - Использованные в программе классы стандартной библиотеки (выборочно)
Название класса |
Назначение в проекте программы |
|
vector |
Универсальный контейнер, используется редко: для хранения изолиний и уровней изолиний. В остальных случаях заменяется пользовательскими контейнерами семейства dinmas. |
|
map |
Отображение, используется во время вычисления приливов для подготовки данных к кубической интерполяции. |
|
ifstream |
Чтение файлов |
|
ofstream |
Запись файлов |
Таблица 4.3 - Использованные в программе заголовочные файлы VCL
Заголовочный файл |
Назначение в проекте программы |
|
Classes.hpp |
Стандартные классы VCL |
|
StdCtrls.hpp |
Стандартные элементы управления |
|
Forms.hpp |
Форма - окно настроек в программе |
|
Menus.hpp |
Главное меню |
|
Dialogs.hpp |
Диалоговые окна |
|
msxmldom.hpp XMLDoc.hpp xmldom.hpp XMLIntf.hpp |
Классы для работы с XMLёиспользуются для чтения файлов в формате kml (Google Earth), а также xml-файлы треков GPS-навигатора Garmin. |
Таблица 4.4 - Использованные в программе классы VCL
Название класса |
Назначение в проекте программы |
|
AnsiString |
Основной строковый класс программы, используется повсеместно. |
|
TDateTime |
Класс для работы с датой и временем. |
|
FileInfo |
Операции управления файловой структурой. |
|
DirectoryInfo |
Получение сведений о файлах и каталогах. |
|
TMainMenu |
Главное меню |
|
TTimer |
Таймер |
|
TOpenDialog |
Диалог открытия файлов |
|
TSaveDialog |
Диалог сохранения файлов |
|
TPopupMenu |
Контекстное меню |
|
TMenuItem |
Класс элемента главного меню |
|
TXMLDocument |
Класс для работы с XML |
|
TForm |
Рабочее окно программы |
Таблица 4.5 - Использованные в программе программе заголовочные файлы Raize
Заголовочный файл |
Назначение в проекте программы |
|
RzEdit.hpp |
Поля ввода |
|
RzSpnEdt.hpp |
Поля числового ввода, позволяющие изменять значение с помощью колёсика мыши |
|
RzPanel.hpp |
Панели, объединяющие несколько элементов |
|
RzTabs.hpp |
Панели управления страницами |
|
RzButton.hpp |
Кнопки |
|
RzChkLst.hpp |
Списки с выбором элеметов |
|
RzLstBox.hpp |
Списки |
|
RzCmboBx.hpp |
Выпадающие списки |
|
RzRadGrp.hpp |
Группы, позволяющие выбрать один параметр |
|
RzRadChk.hpp |
Группы, позволяющие выбрать несколько параметров |
|
RzLabel.hpp |
Текстовая строка |
|
RzTrkBar.hpp |
Информационная панель внизу |
|
RzGroupBar.hpp |
Вертикальные панели, содержащие сворачиваемые группы элементов управления |
Таблица 4.6 - Использованные в программе программе заголовочные файлы Raize
Название компонента |
Описание |
|
TRzToolbar |
Панель инструментов |
|
TRzToolbarButton |
Кнопка на панели инструментов |
|
TRzPanel |
Панель, объединяющая другие компоненты |
|
TRzSplitter |
Бегунок, разделяющий две панели |
|
TRzListBox |
Список |
|
TRzGroupBar |
Вертикальная панель со сворачиваемыми группами |
|
TRzLabel |
Текстовая подпись |
|
TRzSpinEdit |
Элемент числового ввода, позволяющий изменять значение с помощью колёсика мыи |
|
TRzStatusBar |
Строка состояния |
|
TRzSpacer |
Разделитель на панели инструментов |
|
TRzBitBtn |
Кнопка с изображением |
|
TRzComboBox |
Всплывающий список |
|
TRzCheckBox |
Группа с выбором нескольких элементов |
|
TRzRadioGroup |
Группа с выбором одного элемента |
|
TRzColorEdit |
Элемент управления цветом |
|
TRzCheckList |
Список в выбором элементов |
|
TRzEdit |
Компонент текстового ввода |
|
TRzDateTimeEdit |
Элемент отображения и задания времени и даты |
Кроме перечисленных классов в программе используются классы собственной разработки, предназначенные для чтения, хранения и обработки различных данных: как промежуточных, так и непоредственно батиметрических.
Далее в таблице 4.4 представлены названия основных таких классов, а в таблицах 4.5 и 4.6 дано описание их структуры.
Также следует отметить, что каждый модуль реализован в виде одного или нескольких классов, реализующих функциональность, возложенную на данный модуль.
Таблица 4.7 - Главные структуры данных пользователя, использованные в программе
Название класса |
Назначение в проекте программы |
|
point2d |
Структура «двумерная точка», используется как предок класса «трёхмерная точка» |
|
point3d |
Структура «трёхмерная точка», используется как предок классов Vertex и BathPoint, и поле в классах Camera, Cursor, Isoline, Figure, Lamp. |
|
camera |
Класс камеры. Содержит методы упрощённого управления камерой в проекции OpenGL. Является предком класса control3d. |
|
cursor |
Класс курсора. Сожержит методы получения координат курсора на экране, преобразования их в проекцию OpenGL и обратно. Является предком класса control3d |
|
coltrol3d |
Класс управления сценой, наследник классов камеры и курсора, управлять просмотром трёхмерного изображения с помощью мыши: вращать, перемещать, масштабировать. |
|
AverageLevel |
Класс, применяемый для расчёта сезонных изменений уровня моря. |
|
CamItem |
Элемент последовательности камер, входит в качестве поля в класс CameraSequence. |
|
CameraSequence |
Класс-массив камер, является наследником класса Camera, применяется для создания видеороликов. |
|
dinmas |
Одномерный простой динамический массив. Используется в качестве массива для большинства типов данных. |
|
dinmas2d |
Двумерный простой динамический массив. Используется в качестве массива для батиметрической карты и её текстуры. |
|
smartcont |
Одномерный динамический массив с двойной адресацией. Используется для хранения объектов, содержащих поля типа dinmas и dinmas2d, в частности для списка батиметрических треков и списка камер. |
|
TgaHeader |
Заголовок TGA-файла. |
|
RGBApixel |
Структура точки в формате TGA |
|
texture |
Класс, предназначенный для чтения и записи файлов в формате TGA. Применяется как в качестве контейнера текстуры батиметрической карты, так и для сохранения изображений и видео. Является предком класса bath. |
|
DoubleTable |
Класс, позволяющий читать ascii-файл, представляющий собой таблицу из чисел, разделённых табуляцией и создающий на выходе двумерный массив. Применяется для чтения исходных данных. |
|
vertex |
Структура 'узел батиметрии', основанная на трёхмерной точке. |
|
BathPoint |
Точка батиметрического трека. |
|
isoline |
Класс одного отрезка изолинии. |
|
figure |
Класс цифры-подписи. |
|
OneTri |
Структура треугольника для триангуляции. |
|
bath |
Основной класс для расчёта батиметрии. Содержит все функции обработки и анализа данных. |
|
glWindow |
Класс API-окна, реализующего вывод OpenGL-графики. |
|
lamp |
Класс, упрощяющий работу с освещением в OpenGL. |
|
RastrFont |
Класс, упрощающий работу с выводом текста в среде OpenGL. |
|
WorkArea |
Класс, предназначенный для чтения параметров текущего экрана. |
Таблица 4.8 - Структура point2d
Вид члена |
Описание |
Назначение |
|
поле |
double x |
Абсцисса |
|
поле |
double y |
Ордината |
|
метод |
point2d() |
Пустой конструктор |
|
метод |
point2d(double, double) |
Конструктор |
|
метод |
bool equal(point2d&) |
Проверка на равенство |
|
метод |
void mix(point2d&) |
Вычислить среднюю точку |
|
метод |
double angto(point2d&) |
Получить ориентацию точки |
|
Вид члена |
Описание |
Назначение |
|
поле |
double z |
Аппликата |
|
метод |
point3d() |
Пустой конструктор |
|
метод |
point3d(double, double, double) |
Конструктор |
|
метод |
bool equal(point3d&) |
Проверка на равенство |
|
метод |
void mix(point3d&) |
Вычислить среднюю точку |
|
метод |
bool ataru(point3d&) |
Попадает ли в точку с радиусом EPS |
|
метод |
double z |
Аппликата |
|
Вид члена |
Описание |
Назначение |
|
поле |
point3d pos |
Позиция |
|
метод |
point3d startpos |
Начальная позиция |
|
метод |
point3d ang |
Вектор угла поворота |
|
метод |
point3d startang |
Начальный вектор угла поворота |
|
метод |
camera() |
Пустой конструктор |
|
метод |
camera(float, float, float, float, float, float) |
Конструктор |
|
метод |
void view() |
Применить камеру |
|
Вид члена |
Описание |
Назначение |
|
поле |
float x |
Абсцисса в среде OpenGL |
|
поле |
float y |
Ордината в среде OpenGL |
|
поле |
float dx |
Текущая скорость по оси абсцисс в среде OpenGL |
|
поле |
float dy |
Текущая скорость по оси ординат в среде OpenGL |
|
поле |
float size |
Размер курсора |
|
поле |
float oldX |
Предыдущая абсцисса в среде OpenGL |
|
поле |
float oldY |
Предыдущая ордината в среде OpenGL |
|
поле |
int WinX |
Абсцисса в оконных координатах |
|
поле |
int WinY |
Ордината в оконных координатах |
|
поле |
int OldWinX |
Предыдущая абсцисса в среде OpenGL |
|
поле |
int OldWinY |
Предыдущая абсцисса в среде OpenGL |
|
поле |
bool RMB |
Нажата правая кнопка |
|
поле |
bool LMB |
Нажата левая кнопка |
|
поле |
bool MMB |
Нажата средняя кнопка |
|
метод |
cursor() |
Пустой конструктор |
|
метод |
void check(int &, int &, int, int) |
Получить координаты курсора |
|
метод |
void putold() |
Запомнить предыдущие значения |
|
метод |
void view() |
Отобразить курсор |
|
метод |
void PutState(bool, bool, bool) |
Установить состояние кнопок мыши |
|
метод |
void PutState(bool, bool, bool, bool) |
Установить состояние кнопок мыши с проверкой |
Таблица 4.9 - Структура класса coltrol3d, потомок классов camera и cursor
Вид члена |
Описание |
Назначение |
|
метод |
coltrol3d() |
Пустой конструктор |
|
метод |
coltrol3d(float, float, float, float, float, float) |
Конструктор |
|
метод |
void view(bool) |
Установить камеру на текущую позицию в соответствии с курсором |
|
метод |
void gets(int, int, int, int, bool) |
Получить координаты курсора |
|
метод |
wheel(bool, float) |
Получить сообщение прокрутки мыши, отдалив камеру |
|
метод |
coltrol3d middle(coltrol3d, double) |
Установить позицию камеры посередине между двумя позициями |
Таблица 4.10 - Структура класса AverageLevel
Вид члена |
Описание |
Назначение |
|
поле |
TDateTime date |
Текущая дата |
|
поле |
double ya |
Годовая амплитуда |
|
поле |
double yf |
Годовая частота |
|
поле |
double hya |
Полугодовая амплитуда |
|
поле |
double hyf |
Полугодовая частота |
|
поле |
double tya |
Третьгодовая амплитуда |
|
поле |
double tyf |
Третьгодовая частота |
|
поле |
unsigned short y |
Текущий год |
|
поле |
unsigned short m |
Текущий месяц |
|
поле |
unsigned short d |
Текущий день |
|
метод |
void put(AnsiString) |
Задать данные из файла |
|
метод |
double get(TDateTime) |
Получить уровень для выбранной даты |
Таблица 4.11 - Структура класса dinmas
Вид члена |
Описание |
Назначение |
|
поле |
type* data |
Указатель на массив данных |
|
поле |
long siz |
Размер массива |
|
метод |
dinmas() |
Пустой конструктор |
|
метод |
dinmas(long) |
Конструктор |
|
метод |
~dinmas() |
Десруктор |
|
метод |
bool make(long) |
Управляемый конструктор (выделить память) |
|
метод |
void clear() |
Управляемый декструктор (очистить память) |
|
метод |
type& operator[](long) |
Доступ к элементу массива |
|
метод |
int bytes() |
Вывести занимаемую память |
|
метод |
void insert(type &, int) |
Вставить элемент |
|
метод |
void erase(int) |
Вырезать элемент |
|
метод |
push(type &) |
Вставить элемент в конец |
|
метод |
pop() |
Удалить последний элемент |
|
метод |
type& top() |
Получить последний элемент |
|
метод |
bool SaveToFile(AnsiString) |
Сохранить содержимое в файл |
|
метод |
bool LoadFromFile(AnsiString) |
Загрузить содержимое из файла |
|
метод |
long& size() |
Получить размер массива |
|
метод |
operator=(dinmas<type> &) |
Скопировать массив |
Таблица 4.12 - Структура класса dinmas2d
Вид члена |
Описание |
Назначение |
|
поле |
type** data |
Указатель на массив данных |
|
поле |
long n |
Размер по первому измерению |
|
поле |
long m |
Размер по второму измерению |
|
поле |
bool exists |
Массив создан |
|
метод |
dinmas2d() |
Пустой конструктор |
|
метод |
dinmas2d(long, long) |
Конструктор |
|
метод |
~dinmas2d() |
Деструктор |
|
метод |
bool make(long, long) |
Управляемый конструктор (выделить память) |
|
метод |
void clear() |
Управляемый декструктор (очистить память) |
|
метод |
type* operator[](long) |
Доступ к элементу массива |
|
метод |
int bytes() |
Вывести занимаемую память |
|
метод |
operator=(dinmas2d<type> &) |
Скопировать массив |
Таблица 4.13 - Структура класса smartcont
Вид члена |
Описание |
Назначение |
|
поле |
type** graphs |
Указатель на массив данных |
|
поле |
int _size |
Размер массива |
|
поле |
int selected |
Индекс выбранного элемента |
|
метод |
smartcont(int) |
Конструктор |
|
метод |
smartcont() |
Пустой конструктор |
|
метод |
make(int n) |
Управляемый конструктор (выделить память) |
|
метод |
int &size() |
Получить размер массива |
|
метод |
void clear() |
Управляемый деструктор (очистить память) |
|
метод |
type& operator[](int) |
Получить элемент по индексу |
|
метод |
type& operator()() |
Получить выбранный элемент |
|
метод |
~smartcont() |
Деструктор |
|
метод |
insert(type &value) |
Вставить элемент по индексу |
|
метод |
insert() |
Вставить элемент в выбранное место |
|
метод |
void copy() |
Создать дубликат рядом с выбранным элементом |
|
метод |
void erase(int) |
Удалить элемент по индексу |
|
метод |
void erase() |
Удалить выбранный элемент |
|
метод |
bool select(int) |
Выбрать элемент |
|
метод |
int SelectedItem() |
Получить индекс выбранного элемента |
|
метод |
void MoveUp() |
Переместить элемент вверх |
|
метод |
void MoveDown() |
Переместить элемент вниз |
Таблица 4.14 - Структура класса CamItem
Вид члена |
Описание |
Назначение |
|
поле |
coltrol3d ctrl |
Позиция камеры |
|
поле |
int secs |
Занимает секунд |
|
метод |
CamItem(coltrol3d, int) |
Конструктор |
|
метод |
CamItem() |
Пустой конструктор |
Таблица 4.15 - Структура класса CameraSequence
Вид члена |
Описание |
Назначение |
|
поле |
coltrol3d ctrl |
Позиция камеры |
|
поле |
int secs |
Занимает секунд |
|
метод |
CamItem(coltrol3d, int) |
Конструктор |
|
метод |
CamItem() |
Пустой конструктор |
|
Вид члена |
Описание |
Назначение |
|
поле |
int selected |
Выбранный элемент |
|
поле |
int secs |
Всего секунд |
|
поле |
int shots |
Всего кадров |
|
метод |
dinmas<CamItem> ctrl |
Массив позиций камеры |
|
метод |
dinmas<double> x |
Дискретный массив отрезков времени |
|
метод |
dinmas<double> y[6] |
Дискретный массив позиций и углов поворота камеры |
|
метод |
cubic_spline spl[6] |
Непрервыный массив (кубический сплайн) позиций и углов поворота камеры |
|
метод |
CameraSequence() |
Пустой конструктор |
|
метод |
void insert(coltrol3d, int) |
Вставить новую камеру |
|
метод |
void update(coltrol3d, int) |
Заменить выбранную камеру |
|
метод |
void remove() |
Удалить выбранную камеру |
|
метод |
coltrol3d selectedCtrl() |
Получить выбранную камеру |
|
метод |
void countSpline() |
Расчитать кубическую интерполяцию |
Таблица 4.16 - Структура класса RGBpixel
Вид члена |
Описание |
Назначение |
|
поле |
GLubyte r |
Красный канал |
|
поле |
GLubyte g |
Зелёный канал |
|
поле |
GLubyte b |
Синий канал |
|
метод |
RGBpixel(GLubyte, GLubyte, GLubyte) |
Конструктор |
|
метод |
RGBpixel() |
Пустой конструктор |
|
метод |
void GetPixel(GLubyte &, GLubyte &, GLubyte &) |
Получить пиксель |
|
метод |
RGBpixel ToBGR() |
Преобразовать в формат для записи в TGA на 24 бита |
|
метод |
RGBApixel ToBGRA() |
Преобразовать в формат для записи в TGA на 32 бита |
|
Вид члена |
Описание |
Назначение |
|
поле |
GLubyte a |
Альфаканал |
|
метод |
RGBApixel(GLubyte, GLubyte, GLubyte, GLubyte) |
Конструктор |
|
метод |
RGBApixel() |
Пустой конструктор |
|
метод |
void GetPixel(GLubyte &, GLubyte &, GLubyte &, GLubyte &) |
Получить пиксель |
|
метод |
RGBApixel ToBGRA() |
Преобразовать в формат для записи в TGA на 32 бита |
Таблица 4.17 - Структура класса texture
Вид члена |
Описание |
Назначение |
|
поле |
bool exsist |
суествует |
|
поле |
bool binded |
уже применяется |
|
поле |
int width |
ширина |
|
поле |
int height |
высота |
|
поле |
int RealWidth |
ширина, приближённая к степени двойки |
|
поле |
int RealHeight |
высота, приближённая к степени двойки |
|
поле |
int PixelsQnt |
количество точек |
|
поле |
int ID |
идентификационный номер текстуры в OpelGL |
|
поле |
float hcoeff |
отношение height к RealHeight |
|
поле |
float wcoeff |
отношение width к RealWidth |
|
поле |
dinmas<RGBApixel> imageData |
массив точек |
|
метод |
GLubyte correct(float) |
исправление целочисленного цвета, если он выходит из диапазона 0-255 |
|
метод |
void operator=(texture &) |
копировать текстуру |
|
метод |
void SetPixel(int, int, GLubyte, GLubyte, GLubyte, GLubyte) |
задать одну точку целыми числами |
|
метод |
void SetPixelf(int, int, float, float, float, float) |
задать одну точку числами с плавающей точкой |
|
метод |
void GetPixel(int, int, GLubyte &, GLubyte &, GLubyte &, GLubyte &) |
получить одну точку |
|
метод |
texture() |
конструктор |
|
метод |
bool MakeArray(int, int) |
выделение памяти c проверкой на степень двойки |
|
метод |
bool MakeArraySimple(unsigned int, unsigned int) |
выделение памяти в обход проверки на степень двойки |
|
метод |
bool BindTexture(unsigned int, bool, bool) |
применение текстуры |
|
метод |
bool SaveToTGA(AnsiString) |
сохранение в TGA |
|
метод |
bool LoadFromTGA(AnsiString, unsigned int, bool, bool) |
чтение из TGA |
|
метод |
~texture() |
деструктор |
|
метод |
void DeleteArray() |
очистить массив |
|
метод |
void UnBind() |
отменить текстуру |
|
метод |
unsigned int GetWidth() |
Получить ширину |
|
метод |
unsigned int GetHeight() |
Получить высоту |
|
метод |
unsigned int GetRealWidth() |
Получить ширину, ближайшую к степени двойки |
|
метод |
unsigned int GetRealHeight() |
Получить высоту, ближайшую к степени двойки |
|
метод |
unsigned int GetPixelsQnt() |
Получить число пикселей |
|
метод |
unsigned int GetID() |
Получить ID текстуры |
|
метод |
bool GetExsist() |
Узнать, существует ли текстура |
|
метод |
bool GetBinded() |
Узнать, наложена ли текстура |
|
метод |
float GetWCoeff() |
Получить отношение height к RealHeight |
|
метод |
float GetHCoeff() |
Получить отношение width к RealWidth |
|
метод |
void PutWidth(unsigned int) |
Задать ширину |
|
метод |
void PutHeight(unsigned int) |
Получить высоту |
|
метод |
void PutRealWidth(unsigned int) |
Получить ширину, ближайшую к степени двойки |
|
метод |
void PutRealHeight(unsigned int) |
Получить высоту, ближайшую к степени двойки |
|
метод |
void PutPixelsQnt(unsigned int) |
Получить число пикселей |
|
метод |
void PutID(unsigned int) |
Получить ID текстуры |
|
метод |
void PutExsist(bool) |
Узнать, существует ли текстура |
|
метод |
void PutBinded(bool) |
Узнать, наложена ли текстура |
|
метод |
void PutWCoeff(float) |
Получить отношение height к RealHeight |
|
метод |
void PutHCoeff(float) |
Получить отношение width к RealWidth |
Таблица 4.18 - Структура класса DoubleTable
Вид члена |
Описание |
Назначение |
|
поле |
dinmas2d<double> d |
Выходной массив данных |
|
метод |
DoubleTable(AnsiString) |
Конструктор |
|
метод |
DoubleTable() |
Пустой конструктор |
|
метод |
bool Load(AnsiString, char) |
Прочитать файл, узнав разделитель |
|
метод |
double* operator[](unsigned int) |
Доступ к элементу |
Таблица 4.19 - Структура класса lamp
Вид члена |
Описание |
Назначение |
|
поле |
int light |
ID источника света в OpenGL |
|
поле |
GLUquadricObj* sun |
Указатель на объект-солнце |
|
поле |
GLfloat position[4] |
Позиция |
|
поле |
GLfloat ambient[4] |
Внешний свет |
|
поле |
GLfloat diffuse[4] |
Рассеянный светт |
|
поле |
GLfloat specular[4] |
Отражащий свет |
|
поле |
GLfloat attenuation |
Размер блика |
|
поле |
bool active |
Активен |
|
поле |
bool focused |
Выбран |
|
метод |
lamp() |
Пустой конструктор |
|
метод |
lamp(int, float, float, float) |
Конструктор |
|
метод |
make(int, float, float, float) |
Задать цвет на позиции |
|
метод |
make(int, float, float, float, float, float, float, float, float, float, float, float, float, bool, bool, float); |
Задать свет по всем параметрам |
|
метод |
void setlight(int) |
Установить свет |
|
метод |
void put(bool) |
Включить свет |
|
метод |
void view(bool,bool) |
Показать источник света |
|
метод |
color(float, float, float, int) |
Задать цвет |
|
метод |
pos(float, float, float) |
Задать позицию |
|
метод |
SetInfinity(bool) |
Установить, бесконечный ли свет |
|
метод |
SetAttenuation(float) |
Установить размер бликов |
|
метод |
void border() |
Показывать рамку на источнике |
|
метод |
SetActive(bool) |
Активировать |
Таблица 4.20 - Структура класса BathPoint
Вид члена |
Описание |
Назначение |
|
поле |
point3d r,m |
Точка в географических и нормализованных к 1 координатах |
|
поле |
unsigned int t |
Сколько миллисекунд прошло с начала трека |
|
поле |
double tide |
Высота прилива в данной точке |
|
метод |
BathPoint() |
Конструктор |
|
Вид члена |
Описание |
Назначение |
|
поле |
point3d a |
начало |
|
поле |
point3d b |
конец |
|
поле |
bool zero |
не показывать |
|
метод |
isoline() |
конструктор |
|
метод |
void put(double &, double &, double &, double &, double &, double &, bool &) |
задать |
|
метод |
void view(int &) |
показать |
Таблица 4.21 - Структура класса figure, потомок класса point3d
Вид члена |
Описание |
Назначение |
|
поле |
bool exists |
показывать |
|
поле |
double length |
размер |
|
поле |
isoline *line |
к какой изолинии привязана |
|
поле |
char str[8] |
что отображать |
|
поле |
int strl |
длина строки |
|
поле |
double angle |
угол разворота |
|
метод |
void activate(double, double) |
'прилепить' к изолинии |
|
метод |
void view(int) |
показать |
|
поле |
double f |
уровень для расчёта изолиний |
|
поле |
bool zero |
являетмя ли уровень текущей изолинии нулевым |
|
поле |
float material_color[4] |
массив цвета материала |
|
поле |
dinmas<OneTri> tri |
набор треугольников для триангуляции |
|
поле |
isoline line |
буферная изолиния для работы функции расчёта изолиний |
|
поле |
bool triangulation() |
произвести триангуляцию |
|
поле |
dinmas<BathPoint> q |
батиметрический трек |
|
поле |
dinmas2d<vertex> p |
батиметрическая сетка |
|
поле |
TDateTime startDate |
дата начала съёмки |
|
поле |
TDateTime endDate |
дата конца съёмки |
|
поле |
vector<isoline> iso |
вектор изолиний |
|
поле |
dinmas2d<figure> figures |
массив цифр |
|
поле |
dinmas<double> *isolist |
список уровней изолиний |
|
поле |
double d |
шаг сетки |
|
поле |
double sclxy |
коэффициент нормализации долготы и широты |
|
поле |
double sclz |
коэффициент нормализации высоты |
|
поле |
double cfx |
коэффициент нормализации долготы |
|
поле |
double cfy |
коэффициент нормализации широты |
|
поле |
double dev |
суммарное математическое отклонение данных от исходных в результате сглаживания и расчёта равномерной сетки |
|
поле |
double tmpz |
нормализованная высота для расчёта цвета |
|
поле |
double isoHaba |
частота изолиний |
|
поле |
double isolineSize |
толщина изолинии |
|
поле |
point3d min |
минимум, нормализованный к 1 |
|
поле |
point3d max |
максимум, нормализованный к 1 |
|
поле |
point3d rmn |
минимум в географических координатах |
|
поле |
point3d rmx |
максимум в географических координатах |
|
поле |
int k |
число строк в текстуре для доступа к ячейке одномерной текстуры по двум координатам |
|
поле |
int blurCount |
количество проходов размытия |
|
поле |
int texNum |
ID текстуры в среде OpenGL |
|
поле |
int fighaba |
Расстояние между подписями |
|
поле |
int diffBlur |
количество проходов размытия для сравнения батиметрий |
|
поле |
int step |
пропуск кратных узлов сетки для ускорения отображения |
|
поле |
AnsiString Filename |
имя файла |
|
поле |
bool tex |
отображение текстуры средставми OpenGL |
|
поле |
bool varIso |
переменный список изолиний |
|
поле |
bool lighting |
освещение включено |
|
поле |
bool rt |
режим отображения без пропусков |
|
поле |
bool viewPoints |
отображать треки |
|
поле |
bool net |
отображать сетку |
|
поле |
bool counted |
сетка уже расчитана |
|
поле |
bool isolines |
отображать изолинии |
|
поле |
bool viewRelief |
отображать рельеф |
|
поле |
bool visible |
отображать сетку |
|
поле |
bool hideFar |
скрыть удалённые участки |
|
поле |
bool hideUpLimit |
скрыть участки, выходящие за границу минимума и максимума |
|
поле |
bool needRecount |
требуется перерасчёт |
|
поле |
bool difference |
является разницей между двумя батиметриями |
|
поле |
bool blackAndWhite |
отображать в чёрнобелых тонах |
|
поле |
bool slg |
является прочитанным slg-файлом |
|
поле |
bool hasTide |
прилив вычтен |
|
метод |
bath() |
Конструктор |
|
метод |
bool LoadPoints(AnsiString, bool, bool) |
Чтение точек из ASCII-файла |
|
метод |
bool LoadSlg(DoubleTable &, AnsiString) |
Чтение трека из slg-файла |
|
метод |
bool MakeEmpty(int) |
Очистить батиметрию |
|
метод |
void CountTide(cubic_spline &) |
Расчёт прилива |
|
метод |
void ReCountMinMax() |
Вычисление минимума и максимума |
|
метод |
double ReCountMin() |
Вычисление только минимума |
|
метод |
bool CountNet(int, point3d, point3d, double, double, double, double, double, int, double, double, int, int, int, dinmas<double> *, bool) |
Расчёт батиметрической сетки |
|
метод |
void blur(int) |
размытие |
|
метод |
void deviation() |
расчёт отклонения |
|
метод |
inline __fastcall void CountColor(int &, int &) |
Расчёт цвета для выбранного узла сетки |
|
метод |
void ReCountColor() |
Перерасчёт цвета |
|
метод |
inline __fastcall void CountNorm(int &, int &) |
Вычисление нормалей |
|
метод |
void DefConstr() |
Конструктор (в виде вызываемой функции) |
|
метод |
void OneVertex(int &, int &) |
Вывод одного узла сетки на экран |
|
метод |
void view() |
Вывод всей батиметрии |
|
метод |
void ViewPoints() |
Вывот треков |
|
метод |
double cf(double &, double &, double &, bool) |
Линейная интерполяция |
|
метод |
void makeLine(int &, int &) |
Создание одной изолинии |
|
метод |
void ViewFigures(int) |
Отображение цифр-подписей |
|
метод |
void countOneIso(double) |
Расчёт одного слоя изолиний |
|
метод |
void countIso(double, dinmas<double> *, bool) |
Расчёт всех изолиний |
|
метод |
void CountFigures(int) |
Расчёт цифр-подписей |
|
метод |
void viewIso() |
Отображение изолиний |
|
метод |
void EraseNet() |
Удаление расчитанной батиметрической сетки |
|
метод |
bool GetDiffer(bath &, bath &, int, double, int) |
Вычисление разницы между двумя батиметриями |
|
метод |
bool GetDifferPoints(bath &, double) |
Вычисление |
|
метод |
bool ReBindTexture() |
Наложение текстуры |
|
метод |
bool SaveNet(AnsiString) |
Сохранение сетки в ASCII-формате |
|
метод |
bool SaveANI(AnsiString, double) |
Сохранение данных в формате.inf и.dat для программы ANI |
|
метод |
bool SavePointsGoogle(AnsiString) |
Сохранение набора точек для отображения в прорамме Google Chrome |
|
метод |
bool SaveTrack(AnsiString) |
Сохранение трека для отображения в прорамме Google Chrome |
|
метод |
bool SavePoints(AnsiString) |
Сохранение набора точек в ASCII-формате в географических коордиантах |
|
метод |
bool SavePointsMer(AnsiString) |
Сохранение набора точек в ASCII-формате в координатах меркатора |
|
метод |
bool SaveNetGoogle(AnsiString, int) |
Сохранение батиметрической карты для отображения в прорамме Google Chrome |
|
метод |
void setConstantPreset(bath &) |
Получение всех статических переменных батиметрии из другой |
|
метод |
operator=(bath &) |
Полное копирование батиметрии из другой |
Таблица 4.22 - Структура класса glWindow
Вид члена |
Описание |
Назначение |
|
метод |
LRESULT CALLBACK (*WindProc)(HWND,UINT,WPARAM,LPARAM) |
Функция обработки сообщений окна |
|
поле |
AnsiString title |
Заголовок окна |
|
поле |
HINSTANCE hInstance |
Содержит экземпляр приложения |
|
поле |
GLuint |
||
метод |
GLvoid KillGLWindow(GLvoid) |
Закрыть окно |
|
метод |
BOOL CreateGLWindow(char*, int, int, int, bool) |
Создать окно |
|
поле |
HDC hDC |
Приватный контекст устройства GDI |
|
поле |
HWND hWnd |
Содержит handle окна типа hWnd |
|
поле |
HGLRC hRC |
Текущий контекст воспроизведения |
|
поле |
HANDLE H |
Содержит handle окна типа HANDLE |
|
поле |
int winW |
Ширина окна |
|
поле |
int winH |
Высота окна |
|
поле |
int winL |
Смещение окна слева |
|
поле |
int winT |
Смещение окна сверху |
|
поле |
bool killed |
Закрыто ли окно |
|
метод |
glWindow() |
Пустой конструктор |
|
метод |
glWindow(int, int, AnsiString, LRESULT CALLBACK (*wp)(HWND,UINT,WPARAM,LPARAM)) |
Конструктор |
|
метод |
void make(int, int, AnsiString, LRESULT CALLBACK (*wp)(HWND,UINT,WPARAM,LPARAM)) |
Управляемый конструктор |
|
метод |
void __fastcall Execute() |
Запуск окна |
|
метод |
bool ConnectGlToWindow() |
Подключить к окну параметры OpenGL |
4.2 Характеристика и структура интерфейса проекта
Интерфейс приложения состоит из двух окон, не считая стандартных всплывающих диалоговых окон и окон сообщений. Окно настроек (по-умолчанию слева) содержит все средства управления программой, кроме настроек положения, угла поворота и масштаба камеры. Данное окно реализовано средствами VCL в среде C++ Builder при помощи стандартных компонентов VCL и (в большей степени) компонетов библиотеки Raize. Окно отображения выводит результаты работы на экран и представляет собой окно, реализованное средствами Windows API, связанной контекстом воспроизведения с OpenGL. Данное окно позволяет вращать и масштабировать сцену.
Модуль «soko_code.cpp» проекта приложения имеет принципиальное значение и реализует базисный функционал системы. В графическом интерфейсе системы данный модуль реализует главное окно настроек приложения.
4.2.1 Главное окно
Главная форма приложения MainForm принадлежит к типу TForm и содержит в себе остальные элементы интерфейса. При закрытии формы, если в программе были произведены изменения, возникнет диалоговое окно с вопросом, сохранить ли изменения в редактируемом файле. Главное окно содержит строку меню, панель инструментов и две сворачиваемые панели - панель сцены и панель батиметрии. Панель сцены состоит из двух частей: верхняя часть содержит элементы управления камерами, нижняя - группы настроек текущей сцены. Панель батиметрии также состоит из двух частей: верхняя часть содержит список батиметрических треков и панель управления ими, нижняя - группы настроек выбранного трека.
Таблица 4.23 - Состав основных компонентов главного окна
Название компоненты |
Тип компоненты |
Назначение |
|
TMainMenu |
MainMenu |
Главное меню. Содержит пункты управления открытием, сохранением, испортом и экспортом данных. |
|
TRzToolbar |
MainToolBar |
Главная панель инструментов. Повторяет функции главного меню. |
|
TRzSizePanel |
ViewPanel |
Содержит элементы управления всей сценой. |
|
TRzSizePanel |
BathsPanel |
Содержит элементы управления списком треков и выбранной батиметрией |
|
TRzListBox |
CameraList |
Список камер для рендеринга видео |
|
TRzToolbar |
CameraListEditToolBar |
Панель управления камерами, позволяет добавлять, удалять, заменять камеры |
|
TRzGroupbar |
CameraGroupBar |
Группа управления камерами |
|
TRzGroupbar |
SceneGroupBar |
Группа управления сценой |
|
TRzCheckList |
PointsList |
Список треков |
|
TRzToolbar |
TrackListEditToolBar |
Панель управления списком треков, позволяет импортировать и экспортировать данные, объединять и разделять треки. |
|
TRzGroupbar |
BathsGroupBar |
Группа управления выбранной батиметрией |
4.2.2 Главное меню
Главное меню содержит пункты управления файлами: окрытия, сохранения, импорта и экспорта. Также имеется возможность выйти из приложения, предварительно сохранив изменения с помощью всплывающего окна.
Таблица 4.24 - Состав компонентов главного меню
Название компоненты |
Тип компоненты |
Назначение |
|
MainMenu |
TMainMenu |
Основной объект главного меню |
|
MenuFile |
TMenuItem |
Пукт «файл», сохранение и открытие батиметрических сцен. |
|
MenuNew |
TMenuItem |
Создать новую сцену / сбросить все настройки |
|
MenuOpen |
TMenuItem |
Открыть сцену |
|
MenuSave |
TMenuItem |
Сохранить текущую сцену |
|
MenuSaveAs |
TMenuItem |
Сохранить новую сцену |
|
MenuSpacer |
TMenuItem |
Разделитель |
|
MenuExit |
TMenuItem |
Выйти из программы |
|
MenuData |
TMenuItem |
Пункт «дата», управление импортом и экспортом данных. |
|
MenuImport |
TMenuItem |
Импортировать данные |
|
MenuExport |
TMenuItem |
Экспортировать данные |
4.2.3 Группа «границы»
Данная группа является первой среди групп настроек текущей сцены (левая колонка). Данная группа предназначена для установки границ четырёхугольника, в котором будет производиться расчёт батиметрической сетки. Она содержит настройки переменных, общих для всех рассчитываемых батиметрий, и особенностью её работы является тот факт, что при расчёте хотя бы одной батиметрической сетки доступ к данной группе ограничивается. Это необходимо для того, чтобы вся совокупность батиметрических сеток существовала в единых координатах для удобства их совместной обработки.
Таблица 4.25 - Состав компонентов группы «границы» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
BordersGroup |
TRzGroup |
Объект данной группы |
|
Borders |
TRzPanel |
Панель, ограничивающая редактирование группы в случае наличия хотя бы одной расчитанной батиметрической сетки. |
|
GetFromPoints |
TRzBitBtn |
Кнопка, позволяющая автоматически получить границы из текущего набора батиметрических треков |
|
PlMinY |
TRzSpinEdit |
Минимальная широта |
|
PlMaxY |
TRzSpinEdit |
Максимальная широта |
|
PlMinX |
TRzSpinEdit |
Минимальная долгота |
|
PlMaxX |
TRzSpinEdit |
Максимальная долгота |
|
PlMinZ |
TRzSpinEdit |
Минимальная глубина |
|
PlMaxZ |
TRzSpinEdit |
Максимальная глубина |
|
PlSclZ |
TRzSpinEdit |
Масштабирование глубины |
|
PlaceBox |
TRzComboBox |
Список доступных районов для вычисления прилива и сезонных гармонических колебаний |
|
SeparationType |
TRzRadioGroup |
Группа, позволяющая выбрать тип задания сетки: с помощью деления выбранного прямоугольника на определённое число узлов сетки, либо задание шага вручную |
|
PlN |
TRzSpinEdit |
Число узлов сетки по максимальному измерению |
|
Step |
TRzSpinEdit |
Шаг |
|
StepType |
TRzComboBox |
Тип задания узлов сетки |
|
BorderLines |
TCheckBox |
Показывать границы |
|
Lines |
TRzCheckBox |
Показывать линейки |
|
Measurment |
TRzRadioGroup |
Отбражать градусную или километровую сетку |
С использованием группы «границы» могут быть выполнены следующие основные действия:
Автоматическое задание границ равномерной сетки
Корректировка границ на местности
Установка диапазона глубин
Корректировка масштабирования по высоте
Установка размера и шага батиметрической сетки
Установка названия участка местности для вычисления прилива
Управление внешним видом градусной или киломентровой сетки
4.2.4 Группа «рельеф»
Следующая группа на панели сцены отвечает за внешний вид батиметрической сетки. Она позволяет оптимизировать просмотр, опционально выбирая только необходимые элементы сетки.
Таблица 4.26 - Состав компонентов группы «рельеф» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
SurfceGroup |
TRzGroup |
Объект данной группы |
|
HideUpLimit |
TCheckBox |
Опция, позволяющая скрывать участки рельефа, не вошедшие в диапазон глубин |
|
Net |
TCheckBox |
Показывать рельеф в виде сетки |
|
PreviewSpin |
TRzSpinEdit |
Кратный пропуск узлов сетки, используется для ускорения просмотра |
|
Relief |
TCheckBox |
Опция, позволяющая отображать и скрывать рельеф |
|
ViewPoints |
TCheckBox |
Опция, позволяющая отображать и скрывать батиметрические треки |
4.2.5 Группа «свет и цвет»
Следующая группа на панели сцены отвечает за настройку освещения сцены. Имеется возможность включать и отключать объёмное освещение, изменять режим на чёрно-белый и цветной, изменять угол наклона источника света.
Таблица 4.27 - Состав компонентов группы «свет и цвет» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
ColorAndLightGroup |
TRzGroup |
Объект данной группы |
|
BackColor |
TRzColorEdit |
Объект редактирования цвета фона |
|
Lighting |
TCheckBox |
Включить или отключить динамическое освещение |
|
Hotspots |
TCheckBox |
Включить или отключить блики (режим с бликами требует повышенных ресурсов графической системы) |
|
BlackAndWhite |
TCheckBox |
Чёрно-белый или цветной режим |
|
LightUV |
TRzSpinEdit |
Угол поворота источника света |
|
LightW |
TRzSpinEdit |
Угол наклона источника света |
4.2.6 Группа «изолинии»
Следующая группа на панели сцены отвечает за настройку изолиний. Имеется возможность задать изолинии с регулярной частотой или на произвольных уровнях, регулировать толщину изолиний
Таблица 4.28 - Состав компонентов группы «изолинии» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
IsolinesGroup |
TRzGroup |
Объект данной группы |
|
VarIso |
TRzRadioGroup |
Опция, задающая режим постоянной или переменной частоты изолиний |
|
Isolines |
TCheckBox |
Отображать или скрывать изолинии |
|
IsolineSize |
TRzSpinEdit |
Толщина изолиний |
|
IsolineListOpen |
TRzToolbarButton |
Кнопка, позвляющая загрузить список уровней изолиний из файла при режиме переменной частоты |
|
IsoHaba |
TRzSpinEdit |
Частота изолиний при режиме постоянной частоты |
|
IsolineList |
TRzComboBox |
Список переменных уровней изолиний, получаемый после загрузки из файла |
4.2.7 Группа «цифры»
Следующая группа на панели сцены отвечает за настройку цифр-подписей. Имеется возможность задать размер и частоту подписей.
Таблица 4.29 - Состав компонентов группы «цифры» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
FiguresGroup |
TRzGroup |
Объект данной группы |
|
FiguresSize |
TRzSpinEdit |
Видимый размер цифр-подписей |
|
FiguresFreq |
TRzSpinEdit |
Частота расположения цифр-подписей на батиметрической сетке |
|
FiguresCheck |
TRzCheckBox |
Отображать или скрывать цифры-подписи |
4.2.8 Группа «общие настройки»
Следующая группа на панели сцены отвечает за общую настройку сцены. Имеется опция отключения привязки окна отображения к окну настроек, и управление размером цифр шкалы глубин.
Таблица 4.30 - Состав компонентов группы «общие настройки» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
MainOptionsGroup |
TRzGroup |
Объект данной группы |
|
PlaceWindow |
TRzCheckBox |
Опция, позволяющая выбрать, привязывать ли окно отображения к окну настроек |
|
ScaleFigureSize |
TRzSpinEdit |
Размер цифр шкалы глубин справа в пикселах |
4.2.9 Группа «правка трека»
Первая группа на панели батиметрий отвечает за исправление выбранного трека. Имеется возможность вручную просматривать каждую точку, изменять её глубину и географические координаты в абсолютных и относительных координатах. Выбранная точка будет выделяться на окне отображения. Также имеется возможность смещения всего трека в любом направлении.
Таблица 4.31 - Состав компонентов группы «правка трека» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
TrackEditGoup |
TRzGroup |
Объект данной группы |
|
PointInd |
TRzSpinEdit |
Номер выбранной точки |
|
ViewOnePoint |
TCheckBox |
Выделять на экране выбранную точку |
|
PointsCount |
TRzEdit |
Поле, отображающее общее число точек |
|
PointX |
TRzSpinEdit |
Поле для изменения текущей широты точки |
|
PointY |
TRzSpinEdit |
Поле для изменения текущей долготы точки |
|
PointDepth |
TRzSpinEdit |
Поле для изменения текущей глубины точки |
|
PointDepthFin |
TRzSpinEdit |
Поле для задания глубины с помощью градиента. При режиме абсолютных координат предыдущее поле выступает в качестве начального значения, а данное в качестве конечного. Смещение глубин рассчитывается с помощью линейной интерполяции |
|
Absolute |
TRzCheckBox |
Режим смещения в абсолютных или относительных координатах |
|
Replace |
TRzBitBtn |
Произвести смещение всего трека |
4.2.10 Группа «прилив»
Вторая группа на панели батиметрий отвечает за расчёт прилива. Прилив расчитывается по-умолчанию без задействования данной группы, путём выбора местности в группе «границы», однако данная группа позволяет просматривать и изменять дату начала и конца трека, отключать вычет прилива и производить его перерасчёт при изменении местности.
Таблица 4.32 - Состав компонентов группы «прилив» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
TideGroup |
TRzGroup |
Объект данной группы |
|
HasTide |
TRzCheckBox |
Опция, включающая режим вычитания прилива |
|
TideCount |
TRzBitBtn |
Произвести перерасчёт прилива |
|
StartDate |
TRzDateTimeEdit |
Управление датой начала съёмки |
|
StartTime |
TRzDateTimeEdit |
Управление временем начала съёмки |
|
EndDate |
TRzDateTimeEdit |
Управление датой конца съёмки |
|
EndTime |
TRzDateTimeEdit |
Управление временем конца съёмки |
4.2.11 Группа «расчёт»
Третья группа на панели батиметрий отвечает за расчёт батиметрической сетки. Имеется возможность установить максимальный радиус для смежных областей, что должно соответствовать частоте галсов во время батиметрической съёмки. Участки, расстояние между которыми превышает данный радиус, показаны не будут, так как полагается, что данных недостаточно. Также имеется возможность настроить число проходов размытия готовой сетки.
Таблица 4.33 - Состав компонентов группы «расчёт» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
CountGroup |
TRzGroup |
Объект данной группы |
|
CountBtn |
TRzBitBtn |
Кнопка расчёта батиметрической сетки |
|
DeleteNet |
TRzBitBtn |
Кнопка удаления сетки из объекта трека |
|
MaxRad |
TRzSpinEdit |
Максимальный радиус, при котором между смежными данными будет построена сетка |
|
MaskBlurCount |
TRzSpinEdit |
Число проходов размытия сетки |
4.2.12 Группа «разность»
Четвёртая группа на панели батиметрий отвечает за расчёт разностей между батиметрическими сетками. Позволяет выбрать вторую батиметрию для сравнения и построить карту разности. Также, для случая, когда исходные треки сравниваемых батиметрий сильно не совпадают, имеется возможность произвести усечение, оставив только точки, где данные пересекаются в заданном радиусе.
Таблица 4.34 - Состав компонентов группы «разность» (выборочно)
Название компоненты |
Тип компоненты |
Назначение |
|
DifferenceGroup |
TRzGroup |
Объект данной группы |
|
DiffList |
TRzComboBox |
Список батиметрий для сравнения |
|
DiffBtn |
TRzBitBtn |
Кнопка расчёта разности |
|
DiffRange |
TRzSpinEdit |
Поле задания радиуса обрезания участков, находящихся вне пересечений треков двух выбранных батиметрий |
|
Nokosu |
TRzBitBtn |
Кнопка, выполняющая обрезание вышеназванных участков |
|
DiffBlur |
TRzSpinEdit |
Число проходов размытия сетки |
4.2.13 Список треков
В верхней части панели батиметрий расположен список треков и панель управления треками. Расположенные на панели кнопки позволяют производить все основные операции с треками: импорт, экспорт, удаление, перемещение, копирование, переименование, объединение и разделение треков.
Таблица 4.35 - Состав компонентов списка треков и кнопки управления им
Название компоненты |
Тип компоненты |
Назначение |
|
PointsList |
TRzCheckList |
Список треков. Позволяет отметить опцией любой трек, что отображает либо скрывает его. |
|
TrackListEditToolBar |
TRzToolbar |
Список батиметрий для сравнения |
|
PointsOpen |
TRzToolbarButton |
Импорт треков |
|
PointsDelete |
TRzToolbarButton |
Удаление выбранного трека |
|
CopyButton |
TRzToolbarButton |
Копирование трека |
|
Export |
TRzToolbarButton |
Экспорт выбранного трека |
|
ConnectVisible |
TRzToolbarButton |
Объединить отмеченные треки в один |
|
Separate |
TRzToolbarButton |
Разделить треки на точке, отмеченной как «текущая» в группе «правка трека» |
|
RenameButton |
TRzToolbarButton |
Переименовать трек |
|
BathUp |
TRzToolbarButton |
Переместить трек вверх |
|
BathDown |
TRzToolbarButton |
Переместить трек вниз |
4.2.14 Камеры
В верхней части панели сцены расположен список камер и панель управления треками. Расположенные на панели кнопки позволяют производить все основные операции с камерами: добавление, обновление, удаление, перемещение, копирование, предваритеьный просмотр видеоролика. Находящаяся под панелью группа камер позволяет задавать свойства видеоряда: продолжительность нахождения на экране в милисекундах, частоту кадров, разрешение видео. Также имеется возможность выбирать между плавным и резким перемещением видео, а также между режимами перспективной и ортогональной проекиций.
Таблица 4.36 - Состав компонентов списка треков и кнопки управления им
Название компоненты |
Тип компоненты |
Назначение |
|
CameraList |
TRzListBox |
Список камер |
|
CameraAdd |
TRzToolbarButton |
Добавить камеру |
|
CameraDelete |
TRzToolbarButton |
Удалить выбранную камеру |
|
CameraUpdate |
TRzToolbarButton |
Обновить выбранную камеру на текущую |
|
CameraReload |
TRzToolbarButton |
Установить текущую камеру как выбранную |
|
CameraPlay |
TRzToolbarButton |
Предварительный просмотр видео |
|
ResetCamera |
TRzToolbarButton |
Обнулить текущую камеру |
|
ShotButton |
TRzToolbarButton |
Сохранить изображение |
|
SaveVideo |
TRzToolbarButton |
Сохранить видео |
|
CameraGroupBar |
TRzGroupBar |
Панель групп для камеры |
|
CameraGroup |
TRzGroup |
Группа камер |
|
Perspective |
TCheckBox |
Установить перспективную или ортогональную проекцию |
|
CameraSmooth |
TCheckBox |
Сглаживание движения камеры |
|
ShotWidth |
TRzSpinEdit |
Ширина экрана для сохранения |
|
ShotHeight |
TRzSpinEdit |
Высота экрана для сохранения |
|
CameraFrameRate |
TRzSpinEdit |
Частота кадров в секунду |
|
CameraSecs |
TRzSpinEdit |
Количество миллисекунд, за которые будет показана выбранная позиция камеры в видео |
|
CameraStat |
TRzStatusBar |
Панель для вывода сообщений о размере видео и общем количестве кадров |
4.2.15 Обращение к программе
Вызов и загрузка программы осуществляется запуском исполняемого файла Soko.exe. Исполняемый файл должен находится в одной папке с набором дополнительных консольных приложений и директорий, содержащих файловую базу данных к ней (в соответствии со схемой программы, приведённой в приложении 1 на рисунке 1.10).
Входные данные
Входными данными приложения являются:
1) батиметрические треки, получаемые посредством съёмки с помощью картплоттера-эхолота;
2) береговые треки, получаемые с помощью GPS-навигатора;
3) название региона и его координаты для определения уровня прилива и сезонных изменений уровня моря;
4) информация о размере обрабатываемого участка, качестве обработки, пределах глубины, позициях камеры, режимах отображения, количестве изолиний и прочие настройки состояния системы.
Выходные данные
Выходными приложения являются:
1) батиметрические карты и карты разницы для выбранных участков в чёрно-белом и цветом варианте;
2) изображения трёхмерных срезов батиметрических данных, показанные с определённого ракурса;
3) видео-файлы, представляющие собой съёмку трёхмерной батимет-рической карты с различных ракурсов;
4) батиметрические треки и сетки, готовые для отображения в про-грамме Google Earth;
5) батиметрические сетки в формате.inf для обработки в программном комплексе ANI.
4.3 Сообщения, выдаваемые программисту
В процессе работы приложения отслеживаются ошибки пользователя и ошибки, возникающие вследствие не зависящих от самого приложения причин (такие как отказы файловой структуры или файловой системы). В данных сатурациях на экран выводятся информационные сообщения об ошибках. Также программа выводит предупреждающее сообщения в случае закрытия приложения без сохранения изменений и предлагает произвести сохранение. Перечень выдаваемых сообщений приводится далее в списке.
'Сохранить изменения в файле <имя файла> перед закрытием?';
'Ошибка чтения файла';
'Ошибка чтения таблицы';
'Файл не может быть открыт';
'Файл не содержит корректных данных';
'Сетка не рассчитана';
'Ошибка записи';
'Ошибка чтения';
'Ошибка массива';
'Невозмоно создать контекст устройства OpenGL';
'Не найден подходящий формат пиксела';
'Невозможно установить формат пиксела';
'Невозможно создать контекст воспроизведения OpenGL';
'Контекст воспроизведения OpenGL не может быть активирован';
'Ошибка создания текстуры'.
'Ошибка выделения памяти'
'Дата начала больше даты конца'
5. РУКОВОДСТВО ОПЕРАТОРА
5.1 Назначение
Система обеспечивает выполнение следующих основных функций:
Импорт батиметрическиз данных из исходных треков, получаемых с картплоттера-эхолота, береговых линий из GPS-навигатора а также загрузка сторонних искусственно созданных данных.
Совмещение, компоновка и редактирование данных, исправление ошибок.
Подготовка данных к отображению и обработке: вычитание высоты прилива и сезонных колебаний уровня моря.
Построение и импорт батиметрических карт.
Построение карт сравнения динамики рельефа.
Экспорт данных в различные форматы.
Процесс обработки батиметрических данных изображён на диаграммах объектно-ориентированной модели данной предметной области, выполненных в нотации языка UML.
5.2 Условия эксплуатации
Разрабатываемая система предназначена для использования на персональных IBM-совместимых компьютерах с центральным Intel-совместимом процессором с частотой работы не менее 1ГГц, оперативным запоминающим устройством объёмом не менее 512 Мб, свободным дисковым пространством не менее 25 Мб для хранения программного обеспечения и 500 Мб для хранения промежуточных данных. Обязательным условием является наличие манипулятора типа «мышь», SVGA-адаптера, совместимого с библиотекой OpenGL и монитора с разрешением не менее 1024х768.
5.3 Выполнение программы
Схема компонентов программы приведена на рисунке 1.10 в приложении 1. Для запуска программы необходимо наличие в каталоге указанных на данной схеме консольных приложений.
После запуска программы открывается два окна - окно настроек слева и окно отображения справа (см. приложение 1, рисунок 3.1).
Окно насроек предоставляет интерфейс ко всем функциональным возможностям программы, кроме управления текущей камерой, которое осуществляется в окне отображения. Окно разделено на несколько логических блоков. Любой элемент интерфейса окна настроек можно масштабировать и сворачивать. Имеется строка меню, панель инструментов и две сворачиваемые панели - панель сцены и панель батиметрии. Панель сцены состоит из двух частей: верхняя часть содержит элементы управления камерами, нижняя - группы настроек текущей сцены. Панель батиметрии также состоит из двух частей: верхняя часть содержит список батиметрических треков и панель управления ими, нижняя - группы настроек выбранного трека. Особенностью интерфейся приложения являются группы - сворачиваемые наборы настроек, объединённые общим назначением. Список доступных групп перечислен в таблице 99.
Таблица 5.1 - Группы интерфейса
Название |
Назначение |
Расположение |
|
Границы |
Постоянные настройки батиме трической сетки, границы, частота сетки, местность |
Левая панель |
|
Рельеф |
Внешний вид рельефа батиметрической карты |
Левая панель |
|
Свет и цвет |
Настройка освещения и цветов в программе |
Левая панель |
|
Изолинии |
Настройка изолиний: расположения, частоты, толщин |
Левая панель |
|
Цифры |
Настройка цифр-подписей на карте: размера, частоты |
Левая панель |
|
Общие настройки |
Общие настройки приложения |
Левая панель |
|
Правка трека |
Правка отдельных точек, смещение всего трека |
Правая панель |
|
Прилив |
Вычисление и исправление приливов |
Правая панель |
|
Расчёт |
Расчёт батиметрической сетки |
Правая панель |
|
Разность |
Вычисление разностей батиметрий |
Правая панель |
|
Камера |
Создание одиночных изображений и динамических |
Левая панель (сверху) |
После запуска программы следует нажать первую кнопку с изображением папки в самом верху панели «батиметрии». Это откроет диалоговое окно импорта исходных данных.
В списке возможных форматов находятся описанные ранее варианты загрузки данных. ASCII-координаты могут быть с глубиной, записанной отрицательными либо положительными числами, а координаты могут быть географическими или Меркатора. Также имеется возможность открывать треки необработанных исходных данных, или преобразованных в текст.
При запуске программы осуществляется аргументов командной строки: если в них содержится путь к доступному для открытия файлу, производится автоматическое чтение файла. Согласно концепции, принятой для системы, на одном компьютере может быть запущено сколько угодно экземпляров данного приложения.
После запуска программы следует выбрать локацию, чтобы приливы и сезонные колебания уровня расчитались автоматически при загрузке данных. Для этого следует в группе «границы» открыть список «район» и выбрать доступный район.
Если исходные данные не были загружены в момент запуска, следует импортировать батиметрические данные. Для этого можно выбрать пункт меню Файл>Импорт, либо нажать на изображение папки в правой панели под пустым списком треков - откроется диалоговое окно импорта исходных данных.
В списке возможных форматов находятся описанные ранее варианты загрузки данных. ASCII-координаты могут быть с глубиной, записанной отрицательными либо положительными числами, а координаты могут быть географическими или Меркатора. Также имеется возможность открывать треки необработанных исходных данных, или преобразованных в текст. Полный список форматов импорта показан в таблице 99.
Таблица 5.2 - Форматы импорта
Название формата |
Расширения |
|
ASCII координаты эхолота, глубина положительная |
*.txt;*.dat |
|
ASCII координаты эхолота, глубина отрицательная |
*.txt;*.dat |
|
ASCII координаты в градусах, глубина положительная |
*.txt;*.dat |
|
ASCII координаты в градусах, глубина отрицательная |
*.txt;*.dat |
|
Lowrance SLG |
*.slg |
|
Lowrance SLG преобразованный |
*.txt |
|
GPS eXchange |
*.gpx |
|
Трек пути из Google |
*.kml |
|
Промеры пляжа |
*.csv |
Предположим, импортируются исходные треки в формате slg. После их загрузки на экране появится изображение. Иногда приборы могут выдать ошибочные данные, что можно легко заметить по резкому перепаду высот. Чтобы устранить ошибки, в группе «правка трека» следует установить флажок «показать», тогда будет выделена выбранная точка (см. рисунок 12). Следует изменить высоту всех ошибочных точек, если таковые имеются.
Далее следует отметить флажком в списке, которые из треков следует включать в батиметрию, и нажать кнопку «объединить видимые» а панели под списком треков (обозначена пиктограммой прямоугольника). Оставшиеся ненужные треки следует удалить, выделив каждый в списке, и нажав кнопку с крестом, справа от кнопки импорта. При загрузке обработанных данных, этот этап пропускается.
В программе уже хранятся настройки по-умолчанию, обеспечивающие корректный расчёт равномерной сетки. При необходимости, воспользовавшись группой «границы», можно сделать дополнительные настройки: установить частоту будущей сетки, задать пользовательские границы с помощью полей ввода, изменить масштабирование по глубине (по-умолчанию 50 раз), изменить диапазон глубин. В группе «расчёт» имеется возможность установить пользовательское число проходов размытия перед расчётом. В группе «изолинии» имеется возможность установить пользовательскую частоту изолиний. В группе «цифры» - пользовательские настройки цифр-подписей.
После нажатия кнопки «расчёт» следует подождать некоторое время. Отключится часть группы «границы», а к видимым трекам добавится рассчитанная сетка.
При наличии нескольких рассчитанных батиметрий имеется позможность получить карту их разностей. Для возвращения в режим исходных данных следует выбрать каждую батиметрию с рассчитанной равномерной сеткой и нажать кнопку «удалить сетку». Только в этом случае станет доступным изменение границ.
Экспорт производится аналогично импорту нажатием кнопки экспорта, которая находится справа от кнопок импорта и удаления. Полный список форматов экспорта показан в таблице 99.
Таблица 5.3 - Форматы импорта
Название формата |
Расширения |
|
Матрица высот для MathCad |
*.grd |
|
Матрица высот для Google |
*.kml |
|
Набор точек в географических координатах с положительной глубиной |
*.txt |
|
Набор точек для Google |
*.kml |
|
Набор точек в координатах меркатора с отрицательной глубиной |
*.txt |
|
Трек пути для Google |
*.kml |
|
Матрица для ANI |
*.inf |
Следует обратить особое внимание на внешний вид сцены: при экспорте равномерной сетки в формат kml изображение будет соответствовать текущему изображению на экране, включая скрываемые области, наличие изолиний и остальные настройки.
Для сохранения и загрузки всего состояния системы, сдедует использовать пункты меню «открыть» и «сохранить как…». Данные сохраняются в формате.soko, разработанном специально для данного приложения.
Для сохранения результатов в графическом виде, следует воспользоваться группой «камеры». Установив требуемую ширину и высоту изображения следует нажать на кнопку «сохранить изображение».
Для создания видеоролика следует последовательно установить камеры - ракурсы, по которым будет перемещаться объектив. Для этого следует установить камеру в начальном положении, задать количество миллисекунд, которые камера будет находиться на этом месте, и нажать кнопку «добавить камеру» с изображением плюса. Далее следует изменить положение на новое и повторить операцию. В конце, задав частоту кадров, следует также указать разрешение видео и нажать на кнопку «сохранить видео». Рендеринг может занять продолжительное время. В конце будет предложено диалоговое окно с выбором кодека, кодирующего будущий видеофайл.
5.4 Сообщения, выдаваемые оператору
Программа информирует пользователя обо всех важных процессах с помощью изменения заголовка окна. При одидании действий от пользователя заголовок окна принимает вид «СОКО», остальные варианты заголовка перечислены ниже:
'СОКО - сохранение точек';
'СОКО - расчёт триангуляции';
'СОКО - чтение треугольников';
'СОКО - треугольники прочитаны';
'СОКО - временные файлы удалены';
'СОКО - Чтение ASCII';
'СОКО - Чтение slg';
'СОКО - триангуляция';
'СОКО - триангуляция завершена';
'СОКО - создана сетка';
'СОКО - не создана буферная сетка';
'СОКО - создана буферная сетка';
'СОКО - создана текстура';
'СОКО - обнуление сетки';
'СОКО - расчёт треугольников';
'СОКО - расчёт цвета и нормалей';
'СОКО - наложение текстуры';
'СОКО - размытие <номер трека>';
'СОКО - расчёт ошибки';
'СОКО - расчёт цвета';
6. ПРОГРАММА И МЕТОДИКА ИСПЫТАНИЙ
6.1. Объект испытаний
6.1.1 Наименование системы
Наименование системы - Приложение «SOKO».
6.1.2 Назначение системы
Система обеспечивает выполнение следующих основных функций:
Ускорение, упрощение и автоматизация чтения и подготовки исходных данных из различных форматов.
Построение двумерных и трёхмерных батиметрических карт для анализа и обработки в научных лабораториях и для навигационных служб портов.
Быстрое построение батиметрической карты в процессе её съемки на основе имеющихся данных
Экспорт данных в различные графические, текстовые и двоичные форматы.
6.2 Цель испытаний
Целью данных испытаний являются проверка работоспособности программного обеспечения и соответствие программы и результатов её работы требованиям корректности, надежности и правильности, предъявленными в техническом задании.
6.3 Требования к программе
Разрабатываемая система должна быть предназначена для автоматизации обработки, визуализации и анализа батиметрических данных, к которым относятся процессы, связанные чтением и исправлением данных, построением триангуляционной сетки, настройкой параметров сцены, экспортом данных.
Разрабатываемая система должна быть представлена в виде единого приложения, входные данные для которого могут располагаться как на том же носителе, так и в локальной сети научного института. Разрабатываемая система должна отображать специфику предметной области и представлять собой единое целое.
Программное обеспечение должно надежно функционировать и не приводить к зависаниям или авариям работы операционной системы при любых ошибочных действиях пользователя.
6.4 Требования к программной документации
При испытании системы использовались следующие документы:
техническое задание;
руководство оператора;
руководство программиста.
6.5 Состав и порядок испытаний
6.5.1 Технические средства, используемые во время испытаний
Тестирование проводилось на рабочих станциях локальной компьютерной сети предприятия. Компьютеры, используемые для тестирования, соответствуют следующей спецификации: IBM PC совместимый персональный компьютер, оснащённый процессором с тактовой частотой не менее 2,7 ГГц, оперативной памятью не менее 8 Гб, графической подсистемой с памятью не менее 2 Гб, устройствами ввода (клавиатура и манипулятор мышь).
6.5.2 Программные средства, используемые во время испытаний
Во время испытаний использовалось программное обеспечение:
операционная система Microsoft Windows XP (32-битная), Windows 7 (32-битная), Windows 7 (64-битная);
среда разработки Borland C++ Builder.
6.5.3 Порядок испытаний
Испытания программы проводились в следующем порядке:
испытание на корректность (адекватно ли программа реагирует на ввод-вывод информации);
испытание на правильность (соответствуют ли полученные результаты ожидаемым);
испытание на надежность (процент отказов и сбоев системы).
6.6 Методы испытаний
6.6.1 Проверка на корректность
После запуска исполняемого файла Soko.exe на экране появляются окно отображения и настройки (рисунок 3.1). В окне настроек предлагается произвести импорт исходных данных. В случае открытия неподходящего файла, пользователь получает соответственное сообщение (рисунок 3.2) и может продолжить работу с программой.
В случае удачной загрузки данных программа автоматически вычисляет прилив и границы по долготе, широте и глубине. В окне отображения появляются батиметрические треки, а список треков заполняется.
Пользователь имеет возможность задать любой размер рассчитываемой сетки. Если память, необходимая для выделения в программе превысит ресурсы системы, пользователь получает соответственное сообщение (рисунок 3.3) и может продолжить работу с программой.
Проверки на корректность входных данных и результата осуществляются в ходе работы пользователя на всех этапах его деятельности с использованием данной системы.
Возможные ошибочные ситуации во время работы программы и реакция на них системы приведены в таблице 5.1.
Следует отметить, что в целом интерфейс пользователя и порядок реализации функций программы спроектированы таким образом, чтобы избежать ошибочных ситуаций из-за неграмотных действий оператора. Тем не менее, иногда такие случаи возможны, ввиду того, что программа полагается при выполнении вычислений на пользовательские настройки.
Таблица 6.1 - Проверка на корректность
Проверка |
Рабочая операция |
Причина ошибочной ситуации |
Способ устранения |
|
Корректность обработки заданного размера сетки (рис. 3.6, рис. 3.7) |
Расчёт батиметрической сетки |
введено слишком большое число |
Ввести меньшее число, такое, чтобы программа смогла ввыделить соответствующий участок памяти |
|
Корректность вычисления прилива |
Вычисление прилива |
Дата начала больше даты конца трека |
Установить дату начала меньше даты конца трека |
|
Корректность октрытия файла |
Открытие импорт файлов |
Файл повреждён или имеет неверные данные |
Открыть другой файл |
6.6.2 Проверка на правильность
При работе программы, где возможно ограничиваются элементы интерфейса, доступ к которым в данный момент не имеет смысла или приведёт к неисправимым ошибкам. Например, при расчёте хотя бы одной батиметрической сетки блокируется группа «границы», а при попытке произвести сравнение батиметрии с самой собой, блокируется кнопка «сравнение».
С любыми корректными входными данными программа позволяет пользователю просмотр и редактирование батиметрических треков, расчёт и настройку батиметрических сеток и разностей, сохранение и экспорт данных в двоичные, текстовые, графические и видеоформаты.
При проверке на правильность результат построяния батиметрических карт не отличается от ожидаемого, поэтому можно утверждать, что программа работает правильно.
6.6.3 Проверка на надежность
Программа тестировалась в течение года. В процессе тестирования глобальных сбоев системы обнаружено не было. Все замечания пользователей были рассмотрены и исправлены в процессе тестирования.
Поскольку в процессе работы программы не было зафиксировано сбоев, приводящих к нарушению функционирования и краху системы, можно сделать вывод, что созданная система работает надежно.
7. ОРГАНИЗАЦИОННО-ЭКОНОМИЧЕСКАЯ ЧАСТЬ
7.1 Расчет трудоемкости разработки программного обеспечения
В качестве объекта расчета взят вариант создания программного обеспечения, разработанного с использованием среды программирования Borland C++ Builder 6.
Проведем расчёт затрат времени на выполнение работ по созданию программного обеспечения, в котором выделим два этапа:
составление необходимого перечня работ и их кодирование;
установление оценок времени продолжительности работ.
В данном случае была использована система с оптимистической и пессимистической оценками времени. Исходя из оценок, определяется ожидаемое время продолжительности каждой работы по формуле (7.1).
, (7.1)
где tmin - оптимистическая оценка, при наиболее благоприятных условиях, tmax - пессимистическая оценка, при неблагоприятных условиях.
Рассчитаем трудоемкость разработки программного обеспечения.
Расчёт трудоемкости приведен в таблице 7.1. В результате предполагаемая продолжительность работы составляет 101 человеко-день.
Таблица 7.1 - Расчет трудоемкости программного обеспечения и оптимизация на основе экспертных оценок
Формулировка работы |
Вероятностные оценки |
|||
tmin |
tmax |
tож |
||
Постановка задачи |
2 |
4 |
3 |
|
Сбор данных о предметной области |
20 |
30 |
25 |
|
Оформление ТЗ |
2 |
4 |
2,8 |
|
Разработка метода реализации задачи |
30 |
40 |
35 |
|
Формирование структуры программного обеспечения |
5 |
7 |
5,8 |
|
Разработка структуры файловой базы данных |
1 |
2 |
1,2 |
|
Разработка графических модулей для работы с OpenGL (освещение, камера, текстуры и прочие) |
12 |
15 |
13,5 |
|
Разработка контейнерных типов данных |
4 |
8 |
6 |
|
Разработка ядра системы - модуля работы с батиметрией |
15 |
20 |
13,5 |
|
Разработка интерфейса пользователя |
10 |
15 |
12 |
|
Комплексное тестирование и отладка системы |
6 |
10 |
7 |
|
Документирование системы |
5 |
10 |
7 |
|
Итого |
88 |
127 |
101 |
7.2 Определение себестоимости разработки программы
Стоимость разработки программы состоит в общем виде из затрат на разработку модулей информационной системы. Себестоимость разработки включает в себя следующие статьи расходов:
материальные затраты;
затраты на оплату труда разработчику;
отчисления во внебюджетные фонды;
налог на имущество;
затраты на электроэнергию;
расходы по эксплуатации оборудования;
общехозяйственные расходы;
прочие расходы.
К материальным затратам отнесём затраты на оргтехнику и расходные материалы: картриджи для принтера, бумагу и так далее, необходимые при разработке моделей, алгоритмов и программ. В стоимость материальных затрат включаются расходы на прикладное и системное программное обеспечение, необходимое для проектирования, разработки и эксплуатации создаваемой системы.
Затраты на оплату труда разработчиков программы рассчитываются на основе данных о тарифных ставках, трудоемкости подготовки программного обеспечения и совокупности доплат и надбавок работникам. Трудоемкость разработки программного обеспечения рассчитывается в человеко-часах и определяется на базе скорректированных отчётных данных по аналогичным работам.
Норматив отчислений на страхование для бюджетных организаций производится в размере 34% от общего фонда заработной платы.
Расходы по эксплуатации оборудования включают в себя амортизационные отчисления от стоимости основных фондов, используемых разработчиками при подготовке программного обеспечения, затраты на потребляемую электроэнергию, расходы по обслуживанию и наладке программного и аппаратного обеспечения.
Общехозяйственные расходы составляют 75% от затрат на оплату труда разработчиков, прочие расходы - 10%.
7.2.1 Расчёт материальных затрат
В таблице 7.2. представлены данные о материалах, используемых для решения поставленной задачи.
Таблица 7.2 - Материальные затраты
Наименование материала |
Количество комплектов, шт. |
Цена комплекта, р. |
Сумма затрат, р. |
|
Картридж для принтера |
1 |
1 200 |
1 200 |
|
Бумага для принтера |
1 |
180 |
180 |
|
Итого |
1 380 |
7.2.2 Затраты на оплату труда разработчика и налоговые отчисления
Месячная зарплата программиста - 21000 р.
Дневная зарплата программиста (21 рабочий день в месяце) - 1 000 р.
Тогда при трудоемкости 101 человеко-день оплата труда программиста по разработке системы составляет 101 000 р.
Отчисления во внебюджетные фонды при трудоемкости 104 ч/дн составляют 34% от зарплаты программиста (в рублях): 0,34?101000 = 34340.
7.2.3 Расходы на эксплуатации оборудования
Затраты на электроэнергию
Основным оборудованием, используемым при разработке системы, являются персональный компьютер (потребляемая мощность данного устройства составляет около 0,5 кВт), печатающее устройство (принтер), потребляемая мощность которого составляет 0,02 кВт.
Средняя стоимость 1 кВт/час для предприятий составляет 3,72 р.
При трудоемкости 101 ч/дн компьютеры использовались 808 часа, принтер эксплуатировался около 19 часов.
В итоге затраты на оплату электропитания составили:
для компьютера: 0,5?808?3,72 = 1502,88,
принтера: 0,02*19*3,72 = 1,41.
Амортизационные отчисления
При годовой амортизации в 12,5%, дневная амортизация оборудования равна 12,5/365 = 0,034%.
Стоимость компьютера с установленным системным программным обеспечением составляет 40 000 р. При указанной выше дневной амортизации и при условии использования серверного компьютера в течение 101 ч/дня, суммарная амортизация за период разработки системы составила 101?40000?0,00034 = 1373,6.
Стоимость принтера Hewlett Packard HP LaserJet 1010 составляет 3000 рублей. При указанной выше дневной амортизации и при условии использования этого устройства в течение 19 ч. (0,79 дня), суммарная амортизация за период разработки системы составила 0,79*3000*0,00034 = 0,80.
Обобщение расходов на эксплуатацию оборудования дано в таблице 7.3.
Таблица 7.3 - Расходы по эксплуатации оборудования при трудоёмкости 104 человека-дня
Вид оборудования |
Время использования, дн. |
Электроэнергия, р. |
Амортизационные отчисления, р. |
Суммарные затраты, р. |
|
Клиентский IBM PC |
101 |
1502,9 |
1373,6 |
2977,5 |
|
Лазерный принтер HP LaserJet 1010 |
0,79 |
1,41 |
0,8 |
3 |
|
Итого |
1504,3 |
1374,4 |
2980,5 |
7.2.4 Общехозяйственные и прочие расходы
Общехозяйственные расходы составляют 75% от затрат на оплату труда разработчика. Таким образом, при трудоемкости разработки в 104 ч/дня данная статья расходов будет равна 101000 ? 0,75 = 75 750.
Прочие расходы составляют 10% от затрат на оплату труда разработчика, и равны 101000*0,10 = 10 100.
7.2.5 Расчет общей себестоимости разработки
Общие затраты на разработку комплекса сведены в таблицу 7.4.
Таблица 7.4 - Общие затраты на разработку комплекса
Наименование статьи расхода |
Сумма, р. |
|
Материальные затраты |
1 380,00 |
|
Затраты на оплату труда разработчика |
101 000,00 |
|
Единый социальный налог |
34340,00 |
|
Расходы по эксплуатации оборудования |
2 980,5 |
|
Общехозяйственные расходы |
75 750,00 |
|
Прочие расходы |
10 100,00 |
|
Итого |
225 550,50 |
7.3 Капитальные вложения по внедрению системы
Для внедрения системы необходимо закупить более мощный компьютер, чем до него. Стоимость аппаратного обеспечения вместе с установленной на каждый из компьютеров операционной системой Microsoft Windows XP составляет 57 000 р.
Ремонт и обслуживание составляют 2% от стоимости оборудования и оцениваются в 57000 ? 0,02 = 1140.
Рассчитаем затраты на электроэнергию при внедрении системы.
Мощность компьютера составляет 0,5 кВт. Стоимость 1 кВт/час - 3,72 р. Представим, что обработка батиметрических данных необходима лаборатории каждый день. Тогда для создания одной батиметрической карты в день потребуется не более 30 минут = 0,5 часа в день.
3,72 ? 0,5 ? 0,5 ? 500 = 465 в год на один компьютер.
Рассчитаем зарплату персонала. Работой с системой занимается 1 техник. Годовая заработная плата техника составляет 12 ? 18 000 = 216000. Согласно должностной инструкции время, потраченное на работу с системой, составляет 5% от общего фонда времени. Значит, стоимость обслуживания системы за год составляет 216000 ? 0,05 = = 10800. Подведем итог в таблице 7.5.
Таблица 7.5 - Суммарные затраты на эксплуатацию системы
Наименование |
Стоимость, р. |
|
Расходы на электроэнергию |
465 |
|
Ремонт и обслуживание |
1 140 |
|
Оплата персонала |
10 800,00 |
|
Итого |
12 405 |
7.4 Расчет годовой экономии от эксплуатации
7.4.1 Расчет годовых расходов при неавтоматизированном создании батиметрических карт
Рассчитаем стоимость материальных ресурсов на основании имеющихся данных о материалах, использующихся при неавтоматизированной работе.
Оценим затраты на оплату труда. Средняя месячная заработная плата техника лаборатории с требуемой квалификацией составляет 18 000 р. Оплата за 1 год составляет 18 000 ? 12 = 216000.
Оценим затраты на оплату труда. Средняя месячная заработная плата лаборанта кафедры с требуемой квалификацией составляет 18 000 р., младшего научного сотрудника- 25 000 р.
Оплата за 1 год на двух работников составляет 43 000?12 = 516 000.
Отчисления во внебюджетный фонд (34%) составляют 516 000? 0,34 = = 175 440.
Общехозяйственные расходы от затрат на оплату труда (75%) составят 516 000? 0,75 = 387 000.
Прочие расходы от затрат на оплату труда (10%): 516 000 ? 0,1 = = 51 600.
При необходимости печатать одну батиметрическую карту в день при 250 рабочих днях в году, в год требуется 0,5 упаковки бумаги для принтеров в 500 листов стоимостью 180 руб. При стоимости картриджа для цветного принтера в 3290 руб., его ресурс 2200 страниц, тоесть 250/2200=11% запаса картриджа в год.
Таблица 7.6 - Затраченные материальные ресурсы при неавтоматизированном способе управления
Наименование материала |
Количество, шт. |
Цена комплекта, руб. |
Годовые затраты, руб. |
|
Картридж для принтера |
0,11 |
3290 |
361,9 |
|
Бумага для принтера |
0,5 |
180 |
90 |
|
Итого |
451,9 |
7.4.2 Расчет годовых расходов при автоматизированном создании батиметрических карт
Оценим затраты на оплату труда. Средняя месячная заработная плата техника лаборатории с требуемой квалификацией составляет 18 000 р.
Оплата за составляет 18 000 ?12 = 216 000.
Отчисления во внебюджетный фонд (34%) составляют: 216 000?0,34 = =73440.
Общехозяйственные расходы (75%) составят 216 000 ? 0,75 = 162 000. Прочие расходы (10%) составят 216 000 ? 0,1 = 21 600.
При необходимости печатать одну батиметрическую карту в день при 250 рабочих днях в году, в год требуется 0,5 упаковки бумаги для принтеров в 500 листов стоимостью 180 руб. При стоимости картриджа для цветного принтера в 3290 руб., его ресурс 2200 страниц, тоесть 250/2200=11% запаса картриджа в год.
Наименование материала |
Количество, шт. |
Цена комплекта, руб. |
Годовые затраты, руб. |
|
Картридж для принтера |
0,11 |
3290 |
361,9 |
|
Бумага для принтера |
0,5 |
180 |
90 |
|
Итого |
451,9 |
Сделаем сравнение автоматизированного и неавтоматизированного способа управления.
Таблица 7.8 - Расчёт расходов при ручном и автоматизированном способах работы с учетом годовой загрузки
Наименование статьи расходов |
Неавтоматизированный способ, руб. |
Автоматизированный способ, руб. |
|
Материальные затраты |
451,9 |
451,9 |
|
Затраты на оплату труда |
516 000 |
216 000 |
|
Отчисления во внебюджетные фонды |
175 440 |
73440 |
|
Общехозяйственные расходы |
387 000 |
162 000 |
|
Прочие расходы |
51 600 |
21 600 |
|
Итого |
614 491,9 |
257 491,9 |
Приведённый выше расчет годовых эксплуатационных расходов при неавтоматизированном и автоматизированном способах работы показывает, что расходы для первого способа составляют 614 491,9 р., а для второго - 257 491,9 р. Таким образом, годовая экономия для автоматизированного способа работы составляет 357 000р. в год.
7.5 Определение экономической эффективности
К показателям экономической эффективности внедрения новой технологии обработки информации относятся следующие показатели:
годовой экономический коэффициент от внедрения технологии;
коэффициент эффективности капитальных вложений;
срок окупаемости капитальных вложений.
Годовой экономический эффект
Э = ( ЭГ - ЕН · КД ) · КТ, (7.2)где ЭГ - годовая экономия текущих затрат, ЕН - нормативный коэффициент эффективности капвложений - 0,15, КД - дополнительные капитальные вложения; КТ - коэффициент, учитывающий преимущество ускорения обработки информации, равный 1,25;
Э = (357 000- 0,15 · (225 550,50 + 12 405)) · 1,25 = 321306,68.
Расчетный коэффициент экономической эффективности капитальных затрат ЕР представляет собой отношение годовой экономии к капитальным затратам на разработку и внедрение программного обеспечения:
Ер = ЭГ / КД, (7.3)
где ЭГ - годовая экономия текущих затрат, Кд - дополнительные капитальные вложения, Ер = 357 000 / (225 550,50 + 12405) = 1,5.
Срок окупаемости (Т) представляет собой отношение капитальных затрат на разработку и внедрение ИС к годовой экономии составит следующее количество лет:
Т = КД / ЭГ = 1 / Ер, (7.4)
Т = 1 / 1,5 = 0,(6).
Получаем, что затраты на покупку данной программы окупаются за период, равный примерно 8 месяцам.
Заключение
Целью дипломной работы была разработка программного комплекса, предназначенного для чтения, обработки и анализа батиметрических данных. В процессе дипломного проектирования был проведен анализ предметной области. Изучены структуры основных входных данных, разработаны их объектно-ориентированнае модели и модель программного обеспечения. Для создания моделей использована нотация UML.
Реализация программного комплекса проведена с использованием среды разработки приложений Borland C++ Builder 6 на языке программирования C++.
Конечным результатом работы является автоматизированный программный комплекс, соответствующий требованиям технического задания и удовлетворяющая требованиям заказчика. Проведенное тестирование показало, что разработанная система корректно выполняет все свои функции.
Также был проведена оценка экономической эффективности разработки данного комплекса.
Таким образом, все задачи дипломного проектирования полностью решены.
Список использованных источников
1. Вендров А.М. CASE-технологии. Современные методы и средства проектирования информационных систем. / А.М. Вендров. - М.: Финансы и статистика, 1998. - 176 с.
2. Буч Г. Объектно-ориентированное проектирование с примерами применения / Г. Буч - Киев: Диалектика, 1992. - 800 c.
3. Гуннерсон Э. Введение в C#. Библиотека программиста. / Э. Гуннерсон -СПб.: Питер, 2001. -304 с.
4. Дейт К. Введение в системы баз данных. / К. Дейт М., -СПб., Киев: Издательский дом «Вильямс». 2000. -950 с.: ил.
5. Конноли Т. Базы данных: проектирование, реализация, сопровождение / Т. Конноли, К. Бегг, А. Страчан. - М.: издательский дом «Вильямс», 2000. -1120 с.
6. Кратчен Ф. Введение в Rational Unified Process. / Ф. Кратчен - М.: Вильямс. 2002. - 456 с.
7. Лупин С.А. Архитектура электронных вычислительных машин. / С.А. Лунин - М.: Инфра-М, 2009. -458 с.
8. Мамаев Е. Microsoft SQL Server 2000. / Е. Мамаев -СПб.: БХВ-Петербург, 2002. -1200 с.
9. Мюллер Р. Базы данных и UML проектирование. / Р. Мюллер -М.: Лори, 2002. - 420 с.
10. Нейбург Э. Проектирование баз данных с помощью UML. / Э. Нейбург, Роберт Максимчук -М.: Вильямс, 2002. -288 с.
11. Робинсон С. Язык программирования C# для профессионалов. Том 1. / С. Робинсон - М.: Лори, 2003. - 478 с.
12. Робинсон С. Язык программирования C# для профессионалов. Том 2. / С. Робинсон- М.: Лори, 2003. - 523 с.
13. Троелсен Э. Язык программирования C# / Э. Троелсен -СПб.: Питер, 2002. - 800 с.
14. Хомоненко А.Д. Базы данных. / А.Д. Хомоненко, М.Г. Мальцев, В.М. Цыганков - СПб: КОРОНА принт, 2000. - 345 с.
15. Шилдт Г. C#: учебный курс. / Г. Шилдт - СПб.: Питер, 2002. - 512 с.
ПРИЛОЖЕНИЕ 1
СТРУКТУРНЫЕ СХЕМЫ
Рис. 1.1
Рис. 1.2
Рис. 1.3
Рис. 1.4
Рис. 1.5
Рис. 1.6
Рис. 1.7
Рис. 1.8
Рис. 1.9
Рис. 1.10
ПРИЛОЖЕНИЕ 2
Окна программы
Рис. 2.1
Рис. 2.2
Рис. 2.3
Рис. 2.4
Рис. 2.5
Рис. 2.6
Рис. 2.7
Рис. 2.8
Рис. 2.9
Рис. 2.10
Рис. 2.11
Рис. 2.12
Рис. 2.13
Рис. 2.14
Рис. 2.15
Рис. 2.16
Рис. 2.17
Рис. 2.18
Рис. 2.19
Рис. 2.20
Рис. 2.21
Рис. 2.22
Рис. 2.23
Рис. 2.24
Рис. 2.25
Рис. 2.26
Рис. 2.27
Рис. 2.28
Рис. 2.29
Рис. 2.30
Рис. 2.31
Рис. 2.32
Рис. 2.33
Рис. 2.34
Рис. 2.35
Рис. 2.36
Рис. 2.37