Рассматривается учебная программа для студентов картографов и геодезистов, изучающих основы программирования на языке С++. В настоящее время имеется много хороших книг по программированию на языке С++, например классический, многостраничный справочник Стивена Прата, небольшой по объему самоучитель Джесси Либерти или учебник, иллюстрированный комиксами, Стефана Дениса [1-3]. Однако отсутствуют учебники, ориентированные на подготовку профильных инженеров, например, картографов и геодезистов. Нашей целью является разработка набора типовых учебных геодезических программ [4-6], которые могут использовать как преподаватели, так и студенты, обучающиеся по специальностям картографии и геодезии. Задачей данной работы является разработка программы, демонстрирующей использование стандартных функций округления, на примере вычисления Гауссова сближения меридианов.
Рассмотрим содержательную постановку задачи. Пусть задана географическая широта и долгота некоторого пункта на местности М(?, ?). Требуется вычислить зональное (Гауссово) сближение меридианов для этого пункта. Как известно, сближение меридианов определяется по формуле: ? = ??•sin(?), где ?? разность долгот меридиана, проходящего через данный пункт и осевого меридиана зоны, ? – широта данного пункта. Долгота осевого меридиана зоны Восточного полушария вычисляется по формуле (1), а долгота осевого меридиана зоны Западного полушария вычисляется по формуле (2):
?ос = 6 °•N – 3, (1)
?ос = 180 ° – (6 °•(N – 30) –3), (2)
где N – номер зоны, в которой находится данный пункт.
Разработанная программа вычисляет зональное сближение меридианов, используя стандартные математические функции округления ceil и floor, а также функцию modf для извлечения из действительного числа дробной и целой части. Функции округления ceil, floor и modf находятся в математической библиотеке стандартных функций компилятора. Прототипы этих функции находятся в заголовочном файле <cmath>. Функция ceil округляет исходное действительное число с избытком (т.е. в большую сторону), а функция floor округляет действительное число с недостатком (т.е. в меньшую сторону). При этом функции ceil и floor возвращают результат в формате действительного числа с точкой. Например, если действительное число равно 1.23, функция ceil возвратит 2.0, а функция floor число 1.0. Если действительное число равно -1.23, функция ceil возвратит -1.0, а функция floor число -2.0. С помощью функции ceil также сконструирована функция реализующая округление чисел до ближайшего целого. Для этого используется выражение ceil(secondsWithFractionalPart – 0.5), в котором аргумент вначале уменьшается на 0.5, а затем передается функции ceil. В результате округление выполняется в соответствии с правилами арифметики. Функции modf извлекает из действительного числа целую и дробную части. Дробная части возвращается функцией, а целая часть сохраняется в переменной, которая передается в функцию по адресу. Использование стандартных функций упрощает процесс программирования и уменьшает время разработки программы.
01: #include <iostream>
02: #include <cmath>
03: using namespace std;
04:
05: int main(void)
06: {
07: double degreesWithFractionalPart, minutesWithFractionalPart;
08: double secondsWithFractionalPart, degrees, minutes, seconds;
09: double latitude, longitude;
10: int numberOfZone,axialZoneMeridian;
11: char hemisphere, sign;
12:
13: cout <<"Введите \"+\" или \"-\",в зависимости от долготы точки М,"
13: <<" восточной или западной: ";
14: cin >> hemisphere;
15: cout <<"Введите географическую широту точки в градусах, минутах "
15: <<"и секундах: "<< endl;
16: cin >> degrees >> minutes >> seconds;
17:
18: latitude = degrees + minutes/60 + seconds/3600;
19:
20: cout <<"Введите географическую долготу точки в градусах, минутах "
20: <<»и секундах: "<< endl;
21: cin >> degrees >> minutes >> seconds;
22:
23: longitude = degrees + minutes/60 + seconds/3600;
24:
25: //Вычисление осевого меридиана для искомой точки
26:
27: if(hemisphere == '+')
28: {
29: numberOfZone = int(longitude/6) + 1;
30: axialZoneMeridian = numberOfZone * 6 - 3;
31: }
32: else
33: {
34: numberOfZone = 60 - floor(longitude/6);
35: axialZoneMeridian = 180 - ((numberOfZone - 30) * 6 - 3);
36: }
37:
38: cout <<"Номер зоны: " << numberOfZone << endl;
39: cout <<"Осевой меридиан зоны: " << axialZoneMeridian << endl;
40:
41: double deltaLongitude = longitude - axialZoneMeridian;
42: double radian = latitude * M_PI/180;
43: double GaussianConvergence = deltaLongitude * sin(radian);
44:
45: sign = (GaussianConvergence < 0) ? '-' : '+';
46:
47: degreesWithFractionalPart = fabs(GaussianConvergence);
48:
49: minutesWithFractionalPart = modf(degreesWithFractionalPart,
49: °rees) * 60;
50: secondsWithFractionalPart = modf(minutesWithFractionalPart,
50: &minutes) * 60;
51: seconds = ceil(secondsWithFractionalPart - 0.5);
52:
53: cout <<"Гауссово сближение меридианов для точки М: " << sign;
54: cout <<degrees <<" ° «<<minutes <<"\' «<<seconds <<"\" "<<endl;
55: return 0;
56: }
Рассмотрим код программы. В строках 07-08 объявляются переменные с плавающей точкой двойной точности: degreesWithFractionalPart, minutesWithFractionalPart, secondsWithFractionalPart для хранения значений градусов, минут и секунд с дробной частью. Эти переменные используются в строках 47, 49, 50 и 51 для преобразования значения угла сближения меридианов из градусов с дробной частью отдельно в градусы, минуты и секунды. Переменные degrees, minutes и seconds предназначены для географических координат пункта М – они сначала содержат значения широты, а затем долготы в градусах, минутах и секундах. Переменные latitude и longitude хранят значения широты и долготы пункта М в формате градусов с дробной частью. Объявление переменных в начале программы – строгое правило в языке программирования С, в настоящее время в С++ это не является обязательным и переменные могут объявляться по ходу программы, важно лишь, чтобы до использования, переменная была бы объявлена. Это иллюстрирует строка 41, в которой объявляется и затем используется переменная deltaLongitude для хранения разности долгот меридиана, проходящего через данный пункт и осевого меридиана зоны. В строке 43 также объявляется и используется переменная GaussianConvergence для хранения зонального сближения меридианов. В строке 10 объявляются целочисленные переменные: numberOfZone для номера зоны, в которой находится пункт и axialZoneMeridian для значения осевого меридиана зоны. Затем объявляется переменная hemisphere типа char. Эта переменная предназначена для хранения знака «+» или «-», в зависимости от долготы пункта М, восточной или западной соответственно. Пользователь сначала вводит географическую широту пункта М в градусах, минутах и секундах. В строке 18 значение угла преобразуется в градусную меру, в виде целой и дробной частей градуса. Далее используется условная конструкция if-else, позволяющая выбрать соответствующие формулы для расчета номера зоны и осевого меридиана зоны. Если пункт М находится в Восточном полушарии, то номер зоны вычисляется как результат деления долготы пункта М на 6, отбрасывания дробной части и прибавления 1. Здесь не используется функции ceil, поскольку в случае долготы строго равной 0 °0?0? функция давала бы результатом номер зоны равный 0, а нумерация зон начинается с единицы. Если пункт М находится в Западном полушарии, то номер зоны вычисляется в результате деления долготы пункта М на 6, округления полученного значения до меньшего целого с помощи функции floor и вычитания полученного значения из 60. Затем вычисляется осевой меридиан зоны в зависимости от полушария по формулам (1) или (2). В строке 41 вычисляется разность долгот меридианов, проходящего через пункт М и осевого меридиана зоны. В строке 42 широта пункта М в градусах с дробной частью преобразуется в значения радиан. Полученное значение хранится в переменной radian с плавающей точкой двойной точности. Для преобразования угла в радианную меру применяется именованная константа M_PI – число «пи». Последнее необходимо, поскольку в тригонометрических функциях математической библиотеки значения углов задаются в радианах. В строке 43 вычисляется Гауссово сближение меридианов. Как известно, для точек, лежащих к востоку от осевого меридиана, склонение меридианов считается положительным, для точек, лежащих к западу от осевого меридиана – отрицательным. Чтобы сохранить знак склонения меридианов в строке 45 используется условный или тернарный оператор « ? : ». Переменная sign получает знак плюс либо минус в зависимости от знака сближения меридианов. Если условное выражение (GaussianConvergence < 0) в тернарном операторе будет истинным, т. е. сближение меридианов восточное, то переменной sign присваивается символ «+», иначе, если сближение меридианов западное, sign присваивается символ «-». Функция fabs в строке 47 применяется для нахождения модуля числа или абсолютного значения переменной GaussianConvergence. Далее в строках 53-55 на экран выводится результат расчета сближения меридианов вместе со своим знаком.
Предположим, что пользователем были введены следующие данные, широта и долгота пункта М соответственно равны: ? = 43 °07?10?с.ш., ? = 35 °12?37?в.д. В результате программа напечатает на экране следующее: «Номер зоны: 6. Осевой меридиан зоны: 33 °. Гауссово сближение меридианов для пункта М: +1 °30?39?».
Выводы. Разработана учебная программа для студентов картографов и геодезистов, изучающих основы программирования на языке С++ в геодезическом вузе. Программа демонстрирует использование функций округления ceil, floor стандартной математической библиотеки, а также функции modf в задаче вычисления Гауссова сближения меридианов для пункта местности с заданными географическими координатами. Функция modf позволяет извлечь дробную и целую части действительного числа для представления значения сближения меридианов отдельно в градусах, минутах и секундах. Данная программа иллюстрирует решение задачи вычисления зонального сближения меридианов на основе использования технологии процедурного программирования.