JS8Call-Improved master
Loading...
Searching...
No Matches
Geodesic.h
1#include <QString>
2#include <QStringView>
3
4#include <cmath>
5#include <utility>
6
7namespace Geodesic {
8// Azimuth class, describes an azimuth in degrees. Created via
9// interpolation of Maidenhead grid coordinates, and as such
10// will be invalid if interpolation failed, typically due to
11// bad coordinates.
12
13class Azimuth {
14 // Data members
15
16 float m_value = NAN;
17
18 // Constructors
19
20 Azimuth() = default;
21 Azimuth(float const value) : m_value{value} {}
22
23 // Allow construction only by Vector.
24
25 friend class Vector;
26
27 public:
28 // Allow copying, moving, and assignment by anyone.
29
30 Azimuth(Azimuth const &) = default;
31 Azimuth &operator=(Azimuth const &) = default;
32 Azimuth(Azimuth &&) noexcept = default;
33 Azimuth &operator=(Azimuth &&) noexcept = default;
34
35 // Inline Accessors
36
37 auto isValid() const { return !std::isnan(m_value); }
38
39 // Conversion operators; return validity and value. These
40 // are all we need to implement an ordering relation, but
41 // we do so elsewhere.
42
43 explicit operator bool() const noexcept { return isValid(); }
44 operator float() const noexcept { return m_value; }
45
46 // Return as a directional arrow and cardinal direction, if
47 // valid, an empty string if invalid.
48
49 QStringView compass() const;
50
51 // String conversion, to the nearest whole degree; always
52 // succeeds, returning an empty string if invalid. Caller
53 // must specify if they want units or just a bare value.
54
55 QString toString(bool units) const;
56};
57
58// Distance class, describes a distance in kilometers. Created via
59// interpolation of Maidenhead grid coordinates, and as such will
60// be invalid if interpolation failed, typically due to bad coordinates.
61//
62// May additionally be defined as 'close', meaning that either of the
63// grids provided was only 4 characters and the computed distance was
64// short, so we know it's close, but not just how close. In this case,
65// the value will be a non-zero minimum constant, and string conversion
66// will prepend a '<'.
67//
68// While distances are stored internally only in kilometers, caller may
69// request string conversion in terms of statute miles.
70
71class Distance {
72 // Value, in kilometers, that we consider to be the close limit, so
73 // if we're informed that we should consider the value for closeness,
74 // i.e., one of the grids that gave rise to use is of at best square
75 // magnitude, we'd consider any value at or under the limit to be of
76 // only the limit in terms of precision.
77
78 static constexpr float CLOSE = 120.0f;
79
80 // Data members
81
82 float m_value = NAN;
83
84 // Constructors
85
86 Distance() = default;
87 Distance(float const value, bool const close)
88 : m_value{close && CLOSE > value ? INFINITY : value} {}
89
90 // Allow construction only by Vector.
91
92 friend class Vector;
93
94 public:
95 // Allow copying, moving, and assignment by anyone.
96
97 Distance(Distance const &) = default;
98 Distance &operator=(Distance const &) = default;
99 Distance(Distance &&) noexcept = default;
100 Distance &operator=(Distance &&) noexcept = default;
101
102 // Inline Accessors
103
104 auto isValid() const { return !std::isnan(m_value); }
105 auto isClose() const { return std::isinf(m_value); }
106
107 // Conversion operators; return validity and value. These
108 // are all we need to implement an ordering relation, but
109 // we do so elsewhere.
110
111 explicit operator bool() const noexcept { return isValid(); }
112 operator float() const noexcept { return isClose() ? CLOSE : m_value; }
113
114 // String conversion, to the nearest whole kilometer or mile,
115 // always succeeds, returning an empty string if invalid. Caller
116 // must specify if they want units or just the bare value.
117
118 QString toString(bool miles, bool units) const;
119};
120
121// Vector class, aggregate of azimuth and distance from an
122// origin grid to a remote grid.
123
124class Vector {
125 // Data members
126
127 Azimuth m_azimuth;
128 Distance m_distance;
129
130 // Constructors; disallow creation without going through
131 // the vector() function.
132
133 Vector() = default;
134 Vector(std::pair<float, float> const &azdist, bool const square)
135 : m_azimuth{azdist.first}, m_distance{azdist.second, square} {}
136
137 friend Vector vector(QStringView, QStringView);
138
139 public:
140 // Allow copying, moving, and assignment by anyone.
141
142 Vector(Vector const &) = default;
143 Vector &operator=(Vector const &) = default;
144 Vector(Vector &&) noexcept = default;
145 Vector &operator=(Vector &&) noexcept = default;
146
147 // Inline accessors
148
149 Azimuth const &azimuth() const { return m_azimuth; }
150 Distance const &distance() const { return m_distance; }
151};
152
153// Creation method; manages a cache, returning cached data
154// if possible. This gets called just a lot; performing the
155// calculations needed to make a vector are not cheap, so
156// we want to reuse results as much as possible.
157
158Vector vector(QStringView origin, QStringView remote);
159} // namespace Geodesic
Definition Geodesic.h:13
Definition Geodesic.h:71
Definition Geodesic.h:124