GeographicLib
2.6
Toggle main menu visibility
Loading...
Searching...
No Matches
Geodesic3.hpp
Go to the documentation of this file.
1
/**
2
* \file Geodesic3.hpp
3
* \brief Header for GeographicLib::Triaxial::Geodesic3 class
4
*
5
* Copyright (c) Charles Karney (2024-2025) <karney@alum.mit.edu> and licensed
6
* under the MIT/X11 License. For more information, see
7
* https://geographiclib.sourceforge.io/
8
**********************************************************************/
9
10
#if !defined(GEOGRAPHICLIB_GEODESIC3_HPP)
11
#define GEOGRAPHICLIB_GEODESIC3_HPP 1
12
13
#include <functional>
14
#include <memory>
15
#include <
GeographicLib/Triaxial/Ellipsoid3.hpp
>
16
17
#if defined(_MSC_VER)
18
// Squelch warnings about dll vs shared_ptr
19
# pragma warning (push)
20
# pragma warning (disable: 4251)
21
#endif
22
23
namespace
GeographicLib
{
24
namespace
Triaxial
{
25
class
GeodesicLine3
;
26
27
/**
28
* \brief The solution of the geodesic problem for a triaxial ellipsoid
29
*
30
* This is an implementation of
31
* <a href="https://books.google.com/books?id=RbwGAAAAYAAJ&pg=PA309">
32
* Jacobi's method for finding geodesics on a triaxial ellipsoid</a>
33
* (1839). This class offers an interface to the solutions to the direct
34
* geodesic problem via the GeodesicLine3 class which contains the meat of
35
* Jacobi's direct solution. In addition it provides a solution to the
36
* inverse problem which closely parallels the solution for the biaxial
37
* problem given by GeodesicExact. For more details see \ref triaxial.
38
*
39
* Data for testing the geodesic routines is availble at
40
* <a href="https://doi.org/10.5281/zenodo.12510796"> Test set of geodesics
41
* on a triaxial ellipsoid (2024)</a>.
42
*
43
* \note There's a lot of new code here and testing is two orders of
44
* magnitude more difficult compared with the biaxial case (an extra
45
* parameter to fix the shape of the ellipsoid and geodesics now depend on
46
* the longitude of the two end points separately). I've limited by testing
47
* to ellipsoids with \e a/\e c ≤ 2. I don't expect any problems if \e
48
* a/\e c ≤ 10; but you might run into problems with more eccentric
49
* ellipsoids. The code treats oblate and prolate (biaxial) ellipsoids
50
* correctly; but, again, there may be problems with triaxial ellipsoids
51
* which are \e extremely close to oblate or prolate i.e., with either \e k
52
* or \e k' very small. (However the triaxial model of the Earth where the
53
* difference in the equatorial semiaxes is 70 m, \f$k' = 0.057\f$, is
54
* treated just fine.) While I have made every effort to ensure that the
55
* code is error free, it's likely that some bugs remain. Please use caution
56
* with the results and report any problems (via email or with a Github
57
* issue).
58
*
59
* Example of use:
60
* \include example-Geodesic3.cpp
61
*
62
* <a href="Geod3Solve.1.html">Geod3Solve</a> is a command-line utility
63
* providing access to the functionality of Geodesic3 and GeodesicLine3.
64
**********************************************************************/
65
class
GEOGRAPHICLIB_EXPORT
Geodesic3
{
66
private
:
67
/// \cond SKIP
68
// For access to BigValue, _ellipthresh, _biaxp
69
friend
class
GeodesicLine3
;
70
/// \endcond
71
using
real =
Math::real
;
72
using
ang =
Angle
;
73
static
constexpr
bool
debug_ =
false
;
// print out diagnostics
74
static
constexpr
bool
throw_ =
true
;
// exception on convergence failure
75
// special treatment for biaxial non-meridional
76
static
constexpr
bool
biaxp_ =
true
;
77
// favor hybrid solution in terms of omg
78
static
constexpr
bool
hybridalt_ =
true
;
79
// allow swapping of omega{1,2}
80
static
constexpr
bool
swapomg_ =
false
;
81
static
constexpr
int
maxit_ = 200;
82
Ellipsoid3
_t;
83
84
// Run geodesic from bet1, omg1, alp1, find its first intersection with bet
85
// = bet2a and return omg2a - omg2b
86
real HybridA(ang bet1, ang omg1, ang alp1,
87
ang bet2a, ang omg2b,
bool
betp)
const
;
88
static
ang findroot(
const
std::function<
real
(
const
ang&)>& f,
89
ang xa, ang xb,
90
real fa, real fb,
91
int
* countn =
nullptr
,
int
* countb =
nullptr
);
92
bool
_umbalt;
// how coordinates wrap with umbilical lines
93
// If k'^2 < ellipthresh transform phi -> F(phi, k^2)
94
real _ellipthresh;
95
mutable
std::shared_ptr<GeodesicLine3> _umbline;
96
static
real BigValue() {
97
using
std::log;
98
static
real bigval = -3*log(std::numeric_limits<real>::epsilon());
99
return
bigval;
100
}
101
class
gamblk {
102
public
:
103
bool
transpolar;
104
// gamma = (k * cbet * salp)^2 - (kp * somg * calp)^2
105
// = k2*cb2*sa2 - kp2*so2*ca2
106
// Need accurate expressions for
107
// k2 - gamma = k2*(sb2+ca2*cb2) + kp2*so2*ca2
108
// kp2 + gamma = k2*cb2*sa2 + kp2*(co2+sa2*so2)
109
// If gamma is given, eval new alp given new bet and new omg
110
// gamma < 0
111
// ca2 = (k2*cb2-gamma) / (k2*cb2+kp2*so2)
112
// sa2 = (kp2+gamma - kp2*co2) / (k2*cb2+kp2*so2)
113
// gamma > 0
114
// ca2 = (k2-gamma - k2*sb2) / (k2*cb2+kp2*so2)
115
// sa2 = (kp2*so2+gamma) / (k2*cb2+kp2*so2)
116
// gamma > 0
117
// k2*sb2 = spsi2 * (k2-gamma)
118
// (k2-gamma - k2*sb2) = (k2-gamma)*(1-spsi2) = (k2-gamma)*cpsi2
119
// spsi2 = k2*sb2/(k2-gamma)
120
// cpsi2 = (k2*cb2-gamma)/(k2-gamma)
121
real gamma,
122
// [nu, nup]
123
// = [sqrt(gam)/k, sqrt(1 - gam/k2)] for !signbit(gam)
124
// = [sqrt(-gam)/kp, sqrt(1 + gam/kp2)] for signbit(gam)
125
// unused for umbilics
126
nu, nup,
127
gammax, kx2, kxp2, kx, kxp;
128
// Default values for gamma = +/-0
129
gamblk() {}
130
gamblk(
const
Geodesic3
& tg,
bool
neg =
false
);
131
gamblk(
const
Geodesic3
& tg, ang bet, ang omg, ang alp);
132
// gamblk(real gammax, real nux, real nupx)
133
// : gamma(gammax), nu(nux), nup(nupx) {}
134
};
135
gamblk gamma(ang bet, ang omg, ang alp)
136
const
;
137
// real a() const { return t().a(); } // not needed
138
real b()
const
{
return
t
().b(); }
139
// real c() const { return t().c(); } // not needed
140
real e2()
const
{
return
t
().e2(); }
141
real k2()
const
{
return
t
().k2(); }
142
real kp2()
const
{
return
t
().kp2(); }
143
real k()
const
{
return
t
().k(); }
144
real kp()
const
{
return
t
().kp(); }
145
bool
oblate()
const
{
return
t
().oblate(); }
146
bool
prolate()
const
{
return
t
().prolate(); }
147
bool
biaxial()
const
{
return
t
().biaxial(); }
148
public
:
149
/**
150
* Constructor for a triaxial ellipsoid defined by Ellipsoid3 object.
151
*
152
* @param[in] t the Ellipsoid3 object.
153
**********************************************************************/
154
Geodesic3
(
const
Ellipsoid3
&
t
=
Ellipsoid3
{});
155
/**
156
* Constructor for a trixial ellipsoid with semi-axes.
157
*
158
* @param[in] a the largest semi-axis.
159
* @param[in] b the middle semi-axis.
160
* @param[in] c the smallest semi-axis.
161
* @exception GeographicErr if the required ordering is semiaxes is
162
* violated.
163
*
164
* The semi-axes must satisfy \e a ≥ \e b ≥ \e c > 0.
165
* If \e a = \e c (a sphere), then the oblate limit is taken.
166
**********************************************************************/
167
Geodesic3
(real a, real b, real c);
168
/**
169
* Alternate constructor for a triaxial ellipsoid.
170
*
171
* @param[in] b the middle semi-axis.
172
* @param[in] e2 the eccentricity squared \f$e^2 = (a^2 - c^2)/b^2\f$.
173
* @param[in] k2 the oblateness parameter squared \f$k^2 = (b^2 - c^2) /
174
* (a^2 - c^2)\f$.
175
* @param[in] kp2 the prolateness parameter squared \f$k'^2= (a^2 - b^2) /
176
* (a^2 - c^2)\f$.
177
* @exception GeographicErr if the required ordering is semiaxes is
178
* violated.
179
*
180
* \note The constructor normalizes \e k2 and \e kp2 to ensure then \e k2 +
181
* \e kp2 = 1.
182
**********************************************************************/
183
Geodesic3
(real b, real e2, real k2, real kp2);
184
/**
185
* @return the Ellipsoid3 object for this projection.
186
**********************************************************************/
187
const
Ellipsoid3
&
t
()
const
{
return
_t; }
188
/**
189
* Solve the inverse problem
190
*
191
* @param[in] bet1 the ellipsoidal latitude of point 1.
192
* @param[in] omg1 the ellipsoidal longitude of point 1.
193
* @param[in] bet2 the ellipsoidal latitude of point 2.
194
* @param[in] omg2 the ellipsoidal longitude of point 2.
195
* @param[out] s12 the shortest distance between the points.
196
* @param[out] alp1 the forward azimuth of the geodesic at point 1.
197
* @param[out] alp2 the forward azimuth of the geodesic at point 2.
198
* @return a GeodesicLine3 object defining the geodesic.
199
**********************************************************************/
200
GeodesicLine3
Inverse(
Angle
bet1,
Angle
omg1,
Angle
bet2,
Angle
omg2,
201
real
& s12,
Angle
& alp1,
Angle
& alp2)
const
;
202
/**
203
* Solve the inverse problem in degrees
204
*
205
* @param[in] bet1 the ellipsoidal latitude of point 1 (in degrees).
206
* @param[in] omg1 the ellipsoidal longitude of point 1 (in degrees).
207
* @param[in] bet2 the ellipsoidal latitude of point 2 (in degrees).
208
* @param[in] omg2 the ellipsoidal longitude of point 2 (in degrees).
209
* @param[out] s12 the shortest distance between the points.
210
* @param[out] alp1 the forward azimuth of the geodesic at point 1 (in
211
* degrees).
212
* @param[out] alp2 the forward azimuth of the geodesic at point 2 (in
213
* degrees).
214
* @return a GeodesicLine3 object defining the geodesic.
215
**********************************************************************/
216
GeodesicLine3
Inverse(
real
bet1,
real
omg1,
real
bet2,
real
omg2,
217
real
& s12,
real
& alp1,
real
& alp2)
const
;
218
/**
219
* Solve the direct problem
220
*
221
* @param[in] bet1 the ellipsoidal latitude of point 1.
222
* @param[in] omg1 the ellipsoidal longitude of point 1.
223
* @param[in] alp1 the forward azimuth of the geodesic at point 1.
224
* @param[in] s12 the distance from point 1 to point 2.
225
* @param[out] bet2 the ellipsoidal latitude of point 2.
226
* @param[out] omg2 the ellipsoidal longitude of point 2.
227
* @param[out] alp2 the forward azimuth of the geodesic at point 2.
228
* @return a GeodesicLine3 object defining the geodesic.
229
**********************************************************************/
230
GeodesicLine3
Direct(
Angle
bet1,
Angle
omg1,
Angle
alp1,
real
s12,
231
Angle
& bet2,
Angle
& omg2,
Angle
& alp2)
const
;
232
/**
233
* Solve the direct problem in degrees
234
*
235
* @param[in] bet1 the ellipsoidal latitude of point 1 (in degrees).
236
* @param[in] omg1 the ellipsoidal longitude of point 1 (in degrees).
237
* @param[in] alp1 the forward azimuth of the geodesic at point 1 (in
238
* degrees).
239
* @param[in] s12 the distance from point 1 to point 2.
240
* @param[out] bet2 the ellipsoidal latitude of point 2 (in degrees).
241
* @param[out] omg2 the ellipsoidal longitude of point 2 (in degrees).
242
* @param[out] alp2 the forward azimuth of the geodesic at point 2 (in
243
* degrees).
244
* @return a GeodesicLine3 object defining the geodesic.
245
**********************************************************************/
246
GeodesicLine3
Direct(
real
bet1,
real
omg1,
real
alp1,
real
s12,
247
real
& bet2,
real
& omg2,
real
& alp2)
const
;
248
/**
249
* A geodesic line defined at a starting point
250
*
251
* @param[in] bet1 the ellipsoidal latitude of point 1.
252
* @param[in] omg1 the ellipsoidal longitude of point 1.
253
* @param[in] alp1 the forward azimuth of the geodesic at point 1.
254
* @return a GeodesicLine3 object defining the geodesic.
255
**********************************************************************/
256
GeodesicLine3
Line(
Angle
bet1,
Angle
omg1,
Angle
alp1)
const
;
257
/**
258
* A geodesic line defined at a starting point specified in degrees
259
*
260
* @param[in] bet1 the ellipsoidal latitude of point 1 (in degrees).
261
* @param[in] omg1 the ellipsoidal longitude of point 1 (in degrees).
262
* @param[in] alp1 the forward azimuth of the geodesic at point 1 (in
263
* degrees).
264
* @return a GeodesicLine3 object defining the geodesic.
265
**********************************************************************/
266
GeodesicLine3
Line(
real
bet1,
real
omg1,
real
alp1)
const
;
267
/**
268
* Specify the behavior of umbilical geodesics
269
*
270
* @param[in] numbalt the new value of the \e umbalt flag.
271
*
272
* If \e umbalt is true (resp. false) then the latitude (resp. longitude)
273
* of an umbilical geodesic is the librating coordinate and the longitude
274
* (resp. latitude) is the rotating coordinate. This has no effect for
275
* biaxial ellipsoids. In this case the latitude (resp. longitude) is
276
* always the librating coordinate for oblate (resp. prolate) ellipsoids.
277
**********************************************************************/
278
void
umbalt
(
bool
numbalt) {
279
if
(_t.k2() > 0 && _t.kp2() > 0) _umbalt = numbalt;
280
}
281
/**
282
* @return the value of the \e umbalt flag; see umbalt(bool)).
283
**********************************************************************/
284
bool
umbalt
()
const
{
return
_umbalt; }
285
};
286
287
}
// namespace Triaxial
288
}
// namespace GeographicLib
289
290
#if defined(_MSC_VER)
291
# pragma warning (pop)
292
#endif
293
294
// Include this because all the Geodesic3 methods return a GeodesicLine3.
295
#include <
GeographicLib/Triaxial/GeodesicLine3.hpp
>
296
297
#endif
// GEOGRAPHICLIB_GEODESIC3_HPP
GEOGRAPHICLIB_EXPORT
#define GEOGRAPHICLIB_EXPORT
Definition
Constants.hpp:59
Ellipsoid3.hpp
Header for GeographicLib::Triaxial::Ellipsoid3 class.
real
GeographicLib::Math::real real
Definition
Geod3Solve.cpp:25
GeodesicLine3.hpp
Header for GeographicLib::Triaxial::GeodesicLine3 class.
GeographicLib::Math::real
double real
Definition
Math.hpp:115
GeographicLib::Triaxial::Ellipsoid3
A triaxial ellipsoid.
Definition
Ellipsoid3.hpp:82
GeographicLib::Triaxial::Geodesic3::Geodesic3
Geodesic3(const Ellipsoid3 &t=Ellipsoid3{})
Definition
Geodesic3.cpp:19
GeographicLib::Triaxial::Geodesic3::umbalt
void umbalt(bool numbalt)
Definition
Geodesic3.hpp:278
GeographicLib::Triaxial::Geodesic3::t
const Ellipsoid3 & t() const
Definition
Geodesic3.hpp:187
GeographicLib::Triaxial::Geodesic3::umbalt
bool umbalt() const
Definition
Geodesic3.hpp:284
GeographicLib::Triaxial::GeodesicLine3
The direct geodesic problem for a triaxial ellipsoid.
Definition
GeodesicLine3.hpp:54
GeographicLib::Triaxial
Namespace for operations on triaxial ellipsoids.
Definition
Cartesian3.cpp:13
GeographicLib
Namespace for GeographicLib.
Definition
Accumulator.cpp:12
GeographicLib::Angle
AngleT< Math::real > Angle
Definition
Angle.hpp:760
include
GeographicLib
Triaxial
Geodesic3.hpp
Generated by
1.17.0