GeographicLib  2.6
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)
51  else if (ib == DMS::NONE)
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>
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
105 #if GEOGRAPHICLIB_HAVE_LONG_DOUBLE
106  // Instantiate if long double is distinct from double
108 #endif
109 #if GEOGRAPHICLIB_PRECISION > 3
110  // Instantiate with the high precision type
112 #endif
113 
114 } // namespace GeographicLib
static void DecodeLatLon(const std::string &stra, const std::string &strb, AngleT &lat, AngleT &lon, bool longfirst=false)
Definition: Angle.cpp:39
An accurate representation of angles.
Definition: Angle.hpp:50
#define GEOGRAPHICLIB_VOLATILE
Definition: Math.hpp:64
static AngleT DecodeAzimuth(const std::string &azistr)
Definition: Angle.cpp:62
static std::string Encode(real angle, component trailing, unsigned prec, flag ind=NONE, char dmssep=char(0))
Definition: DMS.cpp:422
static Math::real Decode(const std::string &dms, flag &ind)
Definition: DMS.cpp:40
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
static std::string AzimuthString(AngleT azi, int prec, bool dms=false, char dmssep='\0')
Definition: Angle.cpp:86
#define GEOGRAPHICLIB_ANGLE_INSTANTIATE(T)
Definition: Angle.cpp:91
Exception handling for GeographicLib.
Definition: Constants.hpp:344
static std::string LatLonString(AngleT lat, AngleT lon, int prec, bool dms=false, char dmssep='\0', bool longfirst=false)
Definition: Angle.cpp:72
Header for the GeographicLib::AngleT class.
Header for GeographicLib::DMS class.