GeographicLib 2.7

Loading...
Searching...
No Matches
Angle.cpp
Go to the documentation of this file.
1/**
2 * \file Angle.cpp
3 * \brief Implementation for the GeographicLib::Angle class.
4 *
5 * This file is an implementation of the methods described in
6 * - C. F. F. Karney,
7 * <a href="https://doi.org/10.1080/00396265.2023.2217604">
8 * On auxiliary latitudes,</a>
9 * Survey Review 56(395), 165--180 (2024);
10 * preprint
11 * <a href="https://arxiv.org/abs/2212.05818">arXiv:2212.05818</a>.
12 * .
13 * Copyright (c) Charles Karney (2024-2025) <karney@alum.mit.edu> and licensed
14 * under the MIT/X11 License. For more information, see
15 * https://geographiclib.sourceforge.io/
16 **********************************************************************/
17
18#include <GeographicLib/Angle.hpp>
19#include <GeographicLib/DMS.hpp>
20#include <iostream>
21
22 namespace GeographicLib {
23
24 using namespace std;
25
26 template<typename T>
27 T AngleT<T>::rnd(T x) {
28 // This value of z more-or-less matches the value z = 1/16 in
29 // Math::AngRound (where the argument is in degrees).
30 static const T z = 1/T(1024);
31 GEOGRAPHICLIB_VOLATILE T y = fabs(x);
32 GEOGRAPHICLIB_VOLATILE T w = z - y;
33 // The compiler mustn't "simplify" z - (z - y) to y
34 y = w > 0 ? z - w : y;
35 return copysign(y, x);
36 }
37
38 template<typename T>
39 void AngleT<T>::DecodeLatLon(const string& stra, const string& strb,
40 AngleT<T>& lat, AngleT<T>& lon, bool longfirst) {
41 T a, b;
42 DMS::flag ia, ib;
43 a = T(DMS::Decode(stra, ia));
44 b = T(DMS::Decode(strb, ib));
45 if (ia == DMS::NONE && ib == DMS::NONE) {
46 // Default to lat, long unless longfirst
47 ia = longfirst ? DMS::LONGITUDE : DMS::LATITUDE;
48 ib = longfirst ? DMS::LATITUDE : DMS::LONGITUDE;
49 } else if (ia == DMS::NONE)
50 ia = DMS::flag(DMS::LATITUDE + DMS::LONGITUDE - ib);
51 else if (ib == DMS::NONE)
52 ib = DMS::flag(DMS::LATITUDE + DMS::LONGITUDE - ia);
53 if (ia == ib)
54 throw GeographicErr("Both " + stra + " and "
55 + strb + " interpreted as "
56 + (ia == DMS::LATITUDE ? "latitudes" : "longitudes"));
57 lat = AngleT<T>(ia == DMS::LATITUDE ? a : b);
58 lon = AngleT<T>(ia == DMS::LATITUDE ? b : a);
59 }
60
61 template<typename T>
62 AngleT<T> AngleT<T>::DecodeAzimuth(const string& azistr) {
63 DMS::flag ind;
64 T azi = T(DMS::Decode(azistr, ind));
65 if (ind == DMS::LATITUDE)
66 throw GeographicErr("Azimuth " + azistr
67 + " has a latitude hemisphere, N/S");
68 return AngleT<T>(azi);
69 }
70
71 template<typename T>
72 string AngleT<T>::LatLonString(AngleT<T> lat, AngleT<T> lon,
73 int prec, bool dms, char dmssep, bool longfirst) {
74 string
75 latstr = dms ? DMS::Encode(Math::real(T(lat)),
76 prec, DMS::LATITUDE, dmssep) :
77 DMS::Encode(Math::real(T(lat)), prec, DMS::NUMBER),
78 lonstr = dms ? DMS::Encode(Math::real(T(lon)),
79 prec, DMS::LONGITUDE, dmssep) :
80 DMS::Encode(Math::real(T(lon)), prec, DMS::NUMBER);
81 return
82 (longfirst ? lonstr : latstr) + " " + (longfirst ? latstr : lonstr);
83 }
84
85 template<typename T>
86 string AngleT<T>::AzimuthString(AngleT<T> azi, int prec, bool dms, char dmssep) {
87 return dms ? DMS::Encode(Math::real(T(azi)), prec, DMS::AZIMUTH, dmssep) :
88 DMS::Encode(Math::real(T(azi)), prec, DMS::NUMBER);
89 }
90
91#define GEOGRAPHICLIB_ANGLE_INSTANTIATE(T) \
92 template T GEOGRAPHICLIB_EXPORT AngleT<T>::rnd(T); \
93 template void GEOGRAPHICLIB_EXPORT AngleT<T>::DecodeLatLon \
94 (const string& , const string&,AngleT<T>&, AngleT<T>&, bool); \
95 template AngleT<T> GEOGRAPHICLIB_EXPORT AngleT<T>::DecodeAzimuth \
96 (const string&); \
97 template string GEOGRAPHICLIB_EXPORT AngleT<T>::LatLonString \
98 (AngleT<T>, AngleT<T>, int, bool, char, bool); \
99 template string GEOGRAPHICLIB_EXPORT AngleT<T>::AzimuthString \
100 (AngleT<T>, int, bool, char);
101
102 // Instantiate with the standard floating type
103 GEOGRAPHICLIB_ANGLE_INSTANTIATE(float)
104 GEOGRAPHICLIB_ANGLE_INSTANTIATE(double)
105#if GEOGRAPHICLIB_HAVE_LONG_DOUBLE
106 // Instantiate if long double is distinct from double
107 GEOGRAPHICLIB_ANGLE_INSTANTIATE(long double)
108#endif
109#if GEOGRAPHICLIB_PRECISION > 3
110 // Instantiate with the high precision type
111 GEOGRAPHICLIB_ANGLE_INSTANTIATE(Math::real)
112#endif
113
114} // namespace GeographicLib
GEOGRAPHICLIB_ANGLE_INSTANTIATE
#define GEOGRAPHICLIB_ANGLE_INSTANTIATE(T)
Definition Angle.cpp:91
Angle.hpp
Header for the GeographicLib::AngleT class.
DMS.hpp
Header for GeographicLib::DMS class.
GEOGRAPHICLIB_VOLATILE
#define GEOGRAPHICLIB_VOLATILE
Definition Math.hpp:64
GeographicLib::AngleT::DecodeLatLon
static void DecodeLatLon(const std::string &stra, const std::string &strb, AngleT &lat, AngleT &lon, bool longfirst=false)
Definition Angle.cpp:39
GeographicLib::AngleT::LatLonString
static std::string LatLonString(AngleT lat, AngleT lon, int prec, bool dms=false, char dmssep='\0', bool longfirst=false)
Definition Angle.cpp:72
GeographicLib::AngleT::AngleT
AngleT()
Definition Angle.hpp:65
GeographicLib::AngleT::DecodeAzimuth
static AngleT DecodeAzimuth(const std::string &azistr)
Definition Angle.cpp:62
GeographicLib::AngleT::AzimuthString
static std::string AzimuthString(AngleT azi, int prec, bool dms=false, char dmssep='\0')
Definition Angle.cpp:86
GeographicLib::DMS::flag
flag
Definition DMS.hpp:41
GeographicLib::DMS::LONGITUDE
@ LONGITUDE
Definition DMS.hpp:56
GeographicLib::DMS::NUMBER
@ NUMBER
Definition DMS.hpp:67
GeographicLib::DMS::LATITUDE
@ LATITUDE
Definition DMS.hpp:51
GeographicLib::DMS::AZIMUTH
@ AZIMUTH
Definition DMS.hpp:62
GeographicLib::DMS::NONE
@ NONE
Definition DMS.hpp:46
GeographicLib::DMS::Encode
static std::string Encode(real angle, component trailing, unsigned prec, flag ind=NONE, char dmssep=char(0))
Definition DMS.cpp:422
GeographicLib::DMS::Decode
static Math::real Decode(const std::string &dms, flag &ind)
Definition DMS.cpp:40
GeographicLib::GeographicErr
Exception handling for GeographicLib.
Definition Constants.hpp:344
GeographicLib::Math::real
double real
Definition Math.hpp:115
GeographicLib
Namespace for GeographicLib.
Definition Accumulator.cpp:12