В статьях посвящённых работе с GPS в Android (ссылки в конце статьи) было упомянуто о необходимости пересчёта получаемых значений географических координат и пояснены причины, вследствие которых это необходимо.
Рассмотрим алгоритмы пересчёта угловых размеров на примере Delphi и Java.
Пересчёт угловых размеров на Delphi
Допустим есть некоторое угловое значение 25,756897°. Приведём его к привычному представлению «градусы-минуты-секунды».
Для этого воспользуемся универсальным способом конвертации, который вытекает из самого определения данных единиц измерения.
Создадим три переменные для хранения градусов (Integer), минут (Integer) и секунд (double), а также одну вспомогательную переменную для удобства.
Сам пересчёт легко реализуется посредством стандартных функций Delphi.
1 2 3 4 5 6 7 8 9 10 11 |
var floatMinutes: double; begin // Градусы fDegres := Trunc(source); floatMinutes := Frac(source) * 60; // Минуты fMinutes := Trunc(floatMinutes); // Секунды fSeconds := Frac(floatMinutes) * 60; end; |
Обратное преобразование выполняется ещё проще:
1 |
fSourceValue := fDegres + (fMinutes + fSeconds / 60) / 60; |
Работу с угловыми величинами лучше всего оформить в виде класса. Ниже приведён пример его возможной реализации.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
unit Degres; interface uses System.SysUtils; type TDegres = class private fSourceValue: double; fDegres: Integer; fMinutes: Integer; fSeconds: double; procedure SetSourceValue; procedure ChangeOfDegres(Degres: Integer); procedure CangeOfMinutes(minutes: Integer); procedure ChangeOfSeconds(seconds: double); procedure ChangeOfSource(source: double); public constructor Create(value: double); // Градусы property Degres: Integer read fDegres write ChangeOfDegres; // Минуты property Minutes: Integer read fMinutes write CangeOfMinutes; // Секунды property Seconds: double read fSeconds write ChangeOfSeconds; // Значение в десятичном формате property DecimalValue: double read fSourceValue write ChangeOfSource; end; implementation { TDegres } procedure TDegres.ChangeOfDegres(Degres: Integer); begin fDegres := Degres; SetSourceValue(); end; procedure TDegres.ChangeOfMinutes(minutes: Integer); begin try Validate(minutes); fMinutes := minutes; SetSourceValue(); except on E: Exception do WriteLn(E.Message); end; end; procedure TDegres.ChangeOfSeconds(seconds: double); begin try Validate(seconds); fSeconds := seconds; SetSourceValue(); except on E: Exception do WriteLn(E.Message); end; end; procedure TDegres.ChangeOfSource(source: double); var floatMinutes: double; begin fSourceValue := source; fDegres := Trunc(source); floatMinutes := Frac(source) * 60; fMinutes := Trunc(floatMinutes); fSeconds := Frac(floatMinutes) * 60; end; constructor TDegres.Create(value: double); begin ChangeOfSource(value); end; procedure TDegres.SetSourceValue; begin fSourceValue := fDegres + (fMinutes + fSeconds / 60) / 60; end; procedure TDegres.Validate(value: double); begin if (value 60) then raise Exception.Create('Неверный угловой размер в минутах или секундах'); end; end. |
В данном примере при изменении исходного десятичного значения или одной из составляющих представления «градусы-минуты-секунды» производится автоматический пересчёт всех связанных величин.
Далее приведена программа, которая наглядно демонстрирует работу данного класса.
1 2 3 4 5 6 7 8 9 |
var degresValue:TDegres; begin degresValue:=TDegres.Create(25.756897); WriteLn('Градусы: '+degresValue.Degres.ToString+' Минуты: '+degresValue.Minutes.ToString+' Секунды: '+degresValue.Seconds.ToString); degresValue.seconds:=15.29; WriteLn('Градусы: '+degresValue.Degres.ToString+' Минуты: '+degresValue.Minutes.ToString+' Секунды: '+degresValue.Seconds.ToString); WriteLn('Десятичное значение: '+degresValue.DecimalValue.ToString); end. |
И её скриншот:
Пересчёт угловых размеров на Java
В случае Java конкретный алгоритм зависит от используемой платформы.
Android SDK
При использовании Android SDK совершать никаких особых действий не требуется.
Пересчёт уже реализован в виде метода convert класса Location.
1 2 |
String latitude=Location.convert(location.getLatitude(),Location.FORMAT_SECONDS); String longitude =Location.convert(location.getLongitude(),Location.FORMAT_SECONDS); |
Его первый параметр – значение широты или долготы, а второй параметр – формат представления данных. Значение FORMAT_SECONDS соответствует представлению «градусы-минуты-секунды».
Этот метод имеет также перегрузку, которая принимает только один параметр в виде строки. Он выполняет обратное преобразование.
Если данный способ по каким-либо причинам не подходит можно воспользоваться способом, приведённым для Delphi транслированным на Java (см. ниже).
Java SE
В Java также можно использовать и универсальный способ пересчёта. Если программа пишется не для Android или возможности класса Location не обеспечивают нужный функционал.
В качестве примера возможной реализации перепишем на Java тот класс для работы с угловыми величинами, который был ранее приведён для Delphi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
public class Degres { private double sourceValue; private int degres; private int minutes; private double seconds; private void ChangeOfSource(double source) { sourceValue = source; degres = (int) source; double floatMinutes = (source - degres) * 60; minutes = (int) floatMinutes; seconds = (floatMinutes - minutes) * 60; } private void SetSourceValue() { sourceValue = degres + (minutes + seconds / 60) / 60; } private void Validate(double value) throws Exception { if ((value 60)) { throw new Exception("Неверный угловой размер в минутах или секундах"); } } public Degres(double value) { ChangeOfSource(value); } public double getDecimalValue() { return sourceValue; } public int getDegres() { return degres; } public int getMinutes() { return minutes; } public double getSeconds() { return seconds; } public void setDecimalValue(double value) { sourceValue = value; ChangeOfSource(value); } public void setDegres(int newdegres) { degres = newdegres; SetSourceValue(); } public void setMinutes(int newminutes) { try { Validate(newminutes); minutes = newminutes; SetSourceValue(); } catch (Exception ex){ System.out.println(ex.getMessage()); } } public void setSeconds(double newseconds) { try { Validate(newseconds); seconds = newseconds; SetSourceValue(); } catch (Exception ex) { System.out.println(ex.getMessage()); } } } |
Данный класс реализует тот же самый функционал, но на языке программирования Java. Ниже приведён пример его использования.
1 2 3 4 5 |
Degres degresValue = new Degres(25.756897); System.out.println("Градусы: " + degresValue.getDegres() + " Минуты: " + degresValue.getMinutes() + " Секунды: " + degresValue.getSeconds()); degresValue.setMinutes(18); System.out.println("Градусы: " + degresValue.getDegres() + " Минуты: " + degresValue.getMinutes() + " Секунды: " + degresValue.getSeconds()); System.out.println("Десятичное представление: " + degresValue.getDecimalValue()); |
Величины углов
Как известно из курса геометрии длина полной окружности составляет 360°. И, как известно из курса географии значение широты не может превышать 90°, а долготы 180°.
Аналогично градус состоит из 60 минут, а минута из 60 секунд
Из этого следует, что в классе, описывающем угловую величину необходимо ввести обязательные ограничения на размер и в градусах. Однако это решение на самом деле ничем не оправдано.
Например, в технике часто встречаются угловые значения больше 360°. В частности 720° цикл двигателя внутреннего сгорания.
Поэтому наиболее разумно включить подобные проверки на правильность вводимых данных в бизнес-логику приложения или класс наследник, адаптированный для конкретной предметной области. А, исходный класс, описывающий угловое значение использовать просто для хранения информации или в качестве базового для реализации основных структур данных и алгоритмов по работе с ними.
Ссылки:
Добавить комментарий