GeographicLib
2.5
AuxLatitude.hpp
Go to the documentation of this file.
1
/**
2
* \file AuxLatitude.hpp
3
* \brief Header for the GeographicLib::AuxLatitude 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 (2022-2023) <karney@alum.mit.edu> and licensed
14
* under the MIT/X11 License. For more information, see
15
* https://geographiclib.sourceforge.io/
16
**********************************************************************/
17
18
#if !defined(GEOGRAPHICLIB_AUXLATITUDE_HPP)
19
#define GEOGRAPHICLIB_AUXLATITUDE_HPP 1
20
21
#include <utility>
22
#include <
GeographicLib/Math.hpp
>
23
#include <
GeographicLib/AuxAngle.hpp
>
24
25
#if !defined(GEOGRAPHICLIB_AUXLATITUDE_ORDER)
26
/**
27
* The order of the series approximation used in AuxLatitude.
28
* GEOGRAPHICLIB_AUXLATITUDE_ORDER can be set to one of [4, 6, 8]. Use order
29
* appropriate for double precision, 6, also for GEOGRAPHICLIB_PRECISION == 5
30
* to enable truncation errors to be measured easily.
31
**********************************************************************/
32
# define GEOGRAPHICLIB_AUXLATITUDE_ORDER \
33
(GEOGRAPHICLIB_PRECISION == 2 || GEOGRAPHICLIB_PRECISION == 5 ? 6 : \
34
(GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8))
35
#endif
36
37
namespace
GeographicLib
{
38
39
/**
40
* \brief Conversions between auxiliary latitudes.
41
*
42
* This class is an implementation of the methods described in
43
* - C. F. F. Karney,
44
* <a href="https://doi.org/10.1080/00396265.2023.2217604">
45
* On auxiliary latitudes,</a>
46
* Survey Review 56(395), 165--180 (2024);
47
* preprint
48
* <a href="https://arxiv.org/abs/2212.05818">arXiv:2212.05818</a>.
49
*
50
* The provides accurate conversions between geographic (\e phi, φ),
51
* parametric (\e beta, β), geocentric (\e theta, θ), rectifying
52
* (\e mu, μ), conformal (\e chi, χ), and authalic (\e xi, ξ)
53
* latitudes for an ellipsoid of revolution. A latitude is represented by
54
* the class AuxAngle in order to maintain precision close to the poles.
55
*
56
* The class implements two methods for the conversion:
57
* - Direct evaluation of the defining equations, the \e exact method. These
58
* equations are formulated so as to preserve relative accuracy of the
59
* tangent of the latitude, ensuring high accuracy near the equator and the
60
* poles. Newton's method is used for those conversions that can't be
61
* expressed in closed form.
62
* - Expansions in powers of \e n, the third flattening, the \e series
63
* method. This delivers full accuracy for abs(\e f) ≤ 1/150. Here, \e
64
* f is the flattening of the ellipsoid.
65
*
66
* The series method is the preferred method of conversion for any conversion
67
* involving μ, χ, or ξ, with abs(\e f) ≤ 1/150. The equations
68
* for the conversions between φ, β, and θ are sufficiently
69
* simple that the exact method should be used for such conversions and also
70
* for conversions with with abs(\e f) > 1/150.
71
*
72
* Example of use:
73
* \include example-AuxLatitude.cpp
74
**********************************************************************/
75
class
GEOGRAPHICLIB_EXPORT
AuxLatitude
{
76
typedef
Math::real
real
;
77
AuxLatitude
(
const
std::pair<real, real>& axes);
78
public
:
79
/**
80
* The floating-point type for real numbers. This just connects to the
81
* template parameters for the class.
82
**********************************************************************/
83
/**
84
* The different auxiliary latitudes.
85
**********************************************************************/
86
enum
aux
{
87
/**
88
* Geographic latitude, \e phi, φ
89
* @hideinitializer
90
**********************************************************************/
91
GEOGRAPHIC = 0,
92
/**
93
* Parametric latitude, \e beta, β
94
* @hideinitializer
95
**********************************************************************/
96
PARAMETRIC = 1,
97
/**
98
* %Geocentric latitude, \e theta, θ
99
* @hideinitializer
100
**********************************************************************/
101
GEOCENTRIC = 2,
102
/**
103
* Rectifying latitude, \e mu, μ
104
* @hideinitializer
105
**********************************************************************/
106
RECTIFYING = 3,
107
/**
108
* Conformal latitude, \e chi, χ
109
* @hideinitializer
110
**********************************************************************/
111
CONFORMAL = 4,
112
/**
113
* Authalic latitude, \e xi, ξ
114
* @hideinitializer
115
**********************************************************************/
116
AUTHALIC = 5,
117
/**
118
* The total number of auxiliary latitudes
119
* @hideinitializer
120
**********************************************************************/
121
AUXNUMBER = 6,
122
/**
123
* An alias for GEOGRAPHIC
124
* @hideinitializer
125
**********************************************************************/
126
PHI = GEOGRAPHIC,
127
/**
128
* An alias for PARAMETRIC
129
* @hideinitializer
130
**********************************************************************/
131
BETA = PARAMETRIC,
132
/**
133
* An alias for GEOCENTRIC
134
* @hideinitializer
135
**********************************************************************/
136
THETA = GEOCENTRIC,
137
/**
138
* An alias for RECTIFYING
139
* @hideinitializer
140
**********************************************************************/
141
MU = RECTIFYING,
142
/**
143
* An alias for CONFORMAL
144
* @hideinitializer
145
**********************************************************************/
146
CHI = CONFORMAL,
147
/**
148
* An alias for AUTHALIC
149
* @hideinitializer
150
**********************************************************************/
151
XI = AUTHALIC,
152
/**
153
* An alias for GEOGRAPHIC
154
* @hideinitializer
155
**********************************************************************/
156
COMMON = GEOGRAPHIC,
157
/**
158
* An alias for GEOGRAPHIC
159
* @hideinitializer
160
**********************************************************************/
161
GEODETIC = GEOGRAPHIC,
162
/**
163
* An alias for PARAMETRIC
164
* @hideinitializer
165
**********************************************************************/
166
REDUCED = PARAMETRIC,
167
};
168
/**
169
* Constructor
170
*
171
* @param[in] a equatorial radius.
172
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
173
* Negative \e f gives a prolate ellipsoid.
174
* @exception GeographicErr if \e a or (1 − \e f) \e a is not
175
* positive.
176
*
177
* \note the constructor does not precompute the coefficients for the
178
* Fourier series for the series conversions. These are computed and saved
179
* when first needed.
180
**********************************************************************/
181
AuxLatitude
(
real
a,
real
f);
182
/**
183
* Construct and return an AuxLatitude object specified in terms of the
184
* semi-axes
185
*
186
* @param[in] a equatorial radius.
187
* @param[in] b polar semi-axis.
188
* @exception GeographicErr if \e a or \e b is not positive.
189
*
190
* This allows a new AuxAngle to be initialized as an angle in radians with
191
* @code
192
* AuxLatitude aux(AuxLatitude::axes(a, b));
193
* @endcode
194
**********************************************************************/
195
static
AuxLatitude
axes
(real a, real b) {
196
return
AuxLatitude
(std::pair<real, real>(a, b));
197
}
198
/**
199
* Convert between any two auxiliary latitudes specified as AuxAngle.
200
*
201
* @param[in] auxin an AuxLatitude::aux indicating the type of
202
* auxiliary latitude \e zeta.
203
* @param[in] auxout an AuxLatitude::aux indicating the type of
204
* auxiliary latitude \e eta.
205
* @param[in] zeta the input auxiliary latitude as an AuxAngle
206
* @param[in] exact if true use the exact equations instead of the Taylor
207
* series [default false].
208
* @return the output auxiliary latitude \e eta as an AuxAngle.
209
*
210
* With \e exact = false, the Fourier coefficients for a specific \e auxin
211
* and \e auxout are computed and saved on the first call; the saved
212
* coefficients are used on subsequent calls. The series method is
213
* accurate for abs(\e f) ≤ 1/150; for other \e f, the exact method
214
* should be used.
215
**********************************************************************/
216
AuxAngle
Convert(
int
auxin,
int
auxout,
const
AuxAngle
& zeta,
217
bool
exact =
false
)
const
;
218
/**
219
* Convert between any two auxiliary latitudes specified in degrees.
220
*
221
* @param[in] auxin an AuxLatitude::aux indicating the type of
222
* auxiliary latitude \e zeta.
223
* @param[in] auxout an AuxLatitude::aux indicating the type of
224
* auxiliary latitude \e eta.
225
* @param[in] zeta the input auxiliary latitude in degrees.
226
* @param[in] exact if true use the exact equations instead of the Taylor
227
* series [default false].
228
* @return the output auxiliary latitude \e eta in degrees.
229
*
230
* With \e exact = false, the Fourier coefficients for a specific \e auxin
231
* and \e auxout are computed and saved on the first call; the saved
232
* coefficients are used on subsequent calls. The series method is
233
* accurate for abs(\e f) ≤ 1/150; for other \e f, the exact method
234
* should be used.
235
**********************************************************************/
236
Math::real
Convert(
int
auxin,
int
auxout,
real
zeta,
bool
exact =
false
)
237
const
;
238
/**
239
* Convert geographic latitude to an auxiliary latitude \e eta.
240
*
241
* @param[in] auxout an AuxLatitude::aux indicating the auxiliary
242
* latitude returned.
243
* @param[in] phi the geographic latitude.
244
* @param[out] diff optional pointer to the derivative d tan(\e eta) / d
245
* tan(\e phi).
246
* @return the auxiliary latitude \e eta.
247
*
248
* This uses the exact equations.
249
**********************************************************************/
250
AuxAngle
ToAuxiliary(
int
auxout,
const
AuxAngle
& phi,
real
* diff =
nullptr
)
251
const
;
252
/**
253
* Convert an auxiliary latitude \e zeta to geographic latitude.
254
*
255
* @param[in] auxin an AuxLatitude::aux indicating the type of
256
* auxiliary latitude \e zeta.
257
* @param[in] zeta the input auxiliary latitude.
258
* @param[out] niter optional pointer to the number of iterations.
259
* @return the geographic latitude \e phi.
260
*
261
* This uses the exact equations.
262
**********************************************************************/
263
AuxAngle
FromAuxiliary(
int
auxin,
const
AuxAngle
& zeta,
264
int
* niter =
nullptr
)
const
;
265
/**
266
* Return the rectifying radius.
267
*
268
* @param[in] exact if true use the exact expression instead of the Taylor
269
* series [default false].
270
* @return the rectifying radius in the same units as \e a.
271
**********************************************************************/
272
Math::real
RectifyingRadius(
bool
exact =
false
)
const
;
273
/**
274
* Return the authalic radius squared.
275
*
276
* @param[in] exact if true use the exact expression instead of the Taylor
277
* series [default false].
278
* @return the authalic radius squared in the same units as \e a.
279
**********************************************************************/
280
Math::real
AuthalicRadiusSquared(
bool
exact =
false
)
const
;
281
/**
282
* @return \e a the equatorial radius of the ellipsoid (meters).
283
**********************************************************************/
284
Math::real
EquatorialRadius
()
const
{
return
_a; }
285
/**
286
* @return \e b the polar semi-axis of the ellipsoid (meters).
287
**********************************************************************/
288
Math::real
PolarSemiAxis
()
const
{
return
_b; }
289
/**
290
* @return \e f, the flattening of the ellipsoid.
291
**********************************************************************/
292
Math::real
Flattening
()
const
{
return
_f; }
293
/**
294
* Use Clenshaw to sum a Fouier series.
295
*
296
* @param[in] sinp if true sum the sine series, else sum the cosine series.
297
* @param[in] szeta sin(\e zeta).
298
* @param[in] czeta cos(\e zeta).
299
* @param[in] c the array of coefficients.
300
* @param[in] K the number of coefficients.
301
* @return the Clenshaw sum.
302
*
303
* The result returned is \f$ \sum_0^{K-1} c_k \sin (2k+2)\zeta \f$, if \e
304
* sinp is true; with \e sinp false, replace sin by cos.
305
**********************************************************************/
306
// Clenshaw applied to sum(c[k] * sin( (2*k+2) * zeta), i, 0, K-1);
307
// if !sinp then subst sine->cosine.
308
static
Math::real
Clenshaw
(
bool
sinp, real szeta, real czeta,
309
const
real c[],
int
K);
310
/**
311
* The order of the series expansions. This is set at compile time to
312
* either 4, 6, or 8, by the preprocessor macro
313
* GEOGRAPHICLIB_AUXLATITUDE_ORDER.
314
* @hideinitializer
315
**********************************************************************/
316
static
const
int
Lmax =
GEOGRAPHICLIB_AUXLATITUDE_ORDER
;
317
/**
318
* A global instantiation of Ellipsoid with the parameters for the WGS84
319
* ellipsoid.
320
**********************************************************************/
321
static
const
AuxLatitude
& WGS84();
322
private
:
323
// Maximum number of iterations for Newton's method
324
static
const
int
numit_ = 1000;
325
real tol_, bmin_, bmax_;
// Static consts for Newton's method
326
// the function atanh(e * sphi)/e + sphi / (1 - (e * sphi)^2);
327
protected
:
328
/**
329
* Convert geographic latitude to parametric latitude
330
*
331
* @param[in] phi geographic latitude.
332
* @param[out] diff optional pointer to the derivative d tan(\e beta) / d
333
* tan(\e phi).
334
* @return \e beta, the parametric latitude
335
**********************************************************************/
336
AuxAngle
Parametric(
const
AuxAngle
& phi, real* diff =
nullptr
)
const
;
337
/**
338
* Convert geographic latitude to geocentric latitude
339
*
340
* @param[in] phi geographic latitude.
341
* @param[out] diff optional pointer to the derivative d tan(\e theta) / d
342
* tan(\e phi).
343
* @return \e theta, the geocentric latitude.
344
**********************************************************************/
345
AuxAngle
Geocentric
(
const
AuxAngle
& phi, real* diff =
nullptr
)
const
;
346
/**
347
* Convert geographic latitude to rectifying latitude
348
*
349
* @param[in] phi geographic latitude.
350
* @param[out] diff optional pointer to the derivative d tan(\e mu) / d
351
* tan(\e phi).
352
* @return \e mu, the rectifying latitude.
353
**********************************************************************/
354
AuxAngle
Rectifying(
const
AuxAngle
& phi, real* diff =
nullptr
)
const
;
355
/**
356
* Convert geographic latitude to conformal latitude
357
*
358
* @param[in] phi geographic latitude.
359
* @param[out] diff optional pointer to the derivative d tan(\e chi) / d
360
* tan(\e phi).
361
* @return \e chi, the conformal latitude.
362
**********************************************************************/
363
AuxAngle
Conformal(
const
AuxAngle
& phi, real* diff =
nullptr
)
const
;
364
/**
365
* Convert geographic latitude to authalic latitude
366
*
367
* @param[in] phi geographic latitude.
368
* @param[out] diff optional pointer to the derivative d tan(\e xi) / d
369
* tan(\e phi).
370
* @return \e xi, the authalic latitude.
371
**********************************************************************/
372
AuxAngle
Authalic(
const
AuxAngle
& phi, real* diff =
nullptr
)
const
;
373
/// \cond SKIP
374
// Ellipsoid parameters
375
real _a, _b, _f, _fm1, _e2, _e2m1, _e12, _e12p1, _n, _e, _e1, _n2, _q;
376
// To hold computed Fourier coefficients
377
mutable
real _c[Lmax * AUXNUMBER * AUXNUMBER];
378
// 1d index into AUXNUMBER x AUXNUMBER data
379
static
int
ind(
int
auxout,
int
auxin) {
380
return
(auxout >= 0 && auxout < AUXNUMBER &&
381
auxin >= 0 && auxin < AUXNUMBER) ?
382
AUXNUMBER * auxout + auxin : -1;
383
}
384
// the function sqrt(1 + tphi^2), convert tan to sec
385
static
real
sc(
real
tphi)
386
{
using
std::hypot;
return
hypot(
real
(1), tphi); }
387
// the function tphi / sqrt(1 + tphi^2), convert tan to sin
388
static
real
sn(
real
tphi) {
389
using
std::isinf;
using
std::copysign;
390
return
isinf(tphi) ? copysign(
real
(1), tphi) : tphi / sc(tphi);
391
}
392
// Populate [_c[Lmax * k], _c[Lmax * (k + 1)])
393
void
fillcoeff(
int
auxin,
int
auxout,
int
k)
const
;
394
// the function atanh(e * sphi)/e; works for e^2 = 0 and e^2 < 0
395
real
atanhee(
real
tphi)
const
;
396
/// \endcond
397
private
:
398
// the function atanh(e * sphi)/e + sphi / (1 - (e * sphi)^2);
399
real
q(
real
tphi)
const
;
400
// The divided difference of (q(1) - q(sphi)) / (1 - sphi)
401
real
Dq(
real
tphi)
const
;
402
};
403
404
}
// namespace GeographicLib
405
406
#endif
// GEOGRAPHICLIB_AUXLATITUDE_HPP
AuxAngle.hpp
Header for the GeographicLib::AuxAngle class.
GEOGRAPHICLIB_AUXLATITUDE_ORDER
#define GEOGRAPHICLIB_AUXLATITUDE_ORDER
Definition
AuxLatitude.hpp:32
GEOGRAPHICLIB_EXPORT
#define GEOGRAPHICLIB_EXPORT
Definition
Constants.hpp:67
real
GeographicLib::Math::real real
Definition
GeodSolve.cpp:28
Math.hpp
Header for GeographicLib::Math class.
GeographicLib::AuxAngle
An accurate representation of angles.
Definition
AuxAngle.hpp:47
GeographicLib::AuxLatitude
Conversions between auxiliary latitudes.
Definition
AuxLatitude.hpp:75
GeographicLib::AuxLatitude::EquatorialRadius
Math::real EquatorialRadius() const
Definition
AuxLatitude.hpp:284
GeographicLib::AuxLatitude::Flattening
Math::real Flattening() const
Definition
AuxLatitude.hpp:292
GeographicLib::AuxLatitude::aux
aux
Definition
AuxLatitude.hpp:86
GeographicLib::AuxLatitude::PolarSemiAxis
Math::real PolarSemiAxis() const
Definition
AuxLatitude.hpp:288
GeographicLib::AuxLatitude::axes
static AuxLatitude axes(real a, real b)
Definition
AuxLatitude.hpp:195
GeographicLib::AuxLatitude::Clenshaw
static Math::real Clenshaw(bool sinp, real szeta, real czeta, const real c[], int K)
GeographicLib::Geocentric
Geocentric coordinates
Definition
Geocentric.hpp:67
GeographicLib::Math::real
double real
Definition
Math.hpp:110
GeographicLib
Namespace for GeographicLib.
Definition
Accumulator.cpp:12
include
GeographicLib
AuxLatitude.hpp
Generated by
1.9.8