GeographicLib
2.7
Toggle main menu visibility
Loading...
Searching...
No Matches
Ellipsoid3.hpp
Go to the documentation of this file.
1
/**
2
* \file Ellipsoid3.hpp
3
* \brief Header for GeographicLib::Triaxial::Ellipsoid3 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_ELLIPSOID3_HPP)
11
#define GEOGRAPHICLIB_ELLIPSOID3_HPP 1
12
13
#include <iostream>
14
#include <array>
15
#include <
GeographicLib/Constants.hpp
>
16
#include <
GeographicLib/Angle.hpp
>
17
18
namespace
GeographicLib
{
19
/**
20
* \brief Namespace for operations on triaxial ellipsoids
21
*
22
* The algorithms on triaxial ellipsoids are, for the most part, distinct
23
* from those in the rest of %GeographicLib, which deal with biaxial
24
* ellipsoids; it is therefore convenient to put them in a distinct
25
* namespace. In order to minimize the change of name clashes, the classes
26
* in the namespace include "3" in their names. The header files are
27
* included via GeographicLib/Triaxial/Class.hpp.
28
**********************************************************************/
29
namespace
Triaxial
{
30
/**
31
* \brief A triaxial ellipsoid.
32
*
33
* The class holds the basic information about a triaxial ellipsoid
34
* given by
35
* \f[ S(\mathbf R) =
36
* \frac{X^2}{a^2} + \frac{Y^2}{b^2} + \frac{Z^2}{c^2} - 1 = 0, \f]
37
* where the semiaxes satisfy \f$ a \ge b \ge c > 0\f$.
38
* It is useful to characterize the shape of the ellipsoid by
39
* \f[
40
* \begin{align}
41
* e &= \frac{\sqrt{a^2-c^2}}b,\\
42
* k &= \frac{\sqrt{b^2-c^2}}{\sqrt{a^2-c^2}},\\
43
* k' &= \frac{\sqrt{a^2-b^2}}{\sqrt{a^2-c^2}};
44
* \end{align}
45
* \f]
46
* note that \f$k^2 + k'^2 = 1\f$. The spherical limit \f$ e\rightarrow 0
47
* \f$ is nonuniform since the values of \f$k\f$ and \f$k'\f$ depend on how
48
* the limit is taken. In this cases, it's convenient to specify the
49
* ellipsoid in terms of these parameters. The semiaxes are related to these
50
* parameters by
51
* \f[
52
* [a,b,c] = b \bigl[ \sqrt{1 + e^2k'^2}, 1, \sqrt{1 - e^2k^2} \bigr].
53
* \f]
54
*
55
* Positions on the ellipsoid are given in term so the ellipsoidal
56
* coordinates given in Section 2 of
57
* - C. F. F. Karney,<br>
58
* <a href="https://arxiv.org/abs/2511.01621">
59
* Jacobi's solution for geodesics on a triaxial ellipsoid</a>,<br>
60
* Technical Report, SRI International, Nov. 2025.<br>
61
* <a href="https://arxiv.org/abs/2511.01621">arxiv:2511.01621</a>
62
* .
63
* Ellipsoidal latitude * \f$\beta\f$ and the ellipsoidal longitude
64
* \f$\omega\f$ which are defined * by
65
* \f[
66
* \mathbf R = \begin{bmatrix}
67
* a \cos\omega \sqrt{k^2\cos^2\beta + k'^2} \\
68
* b \cos\beta \sin\omega \\
69
* c \sin\beta \sqrt{k^2 + k'^2\sin^2\omega}
70
* \end{bmatrix}.
71
* \f]
72
* Headings are given by the direction \f$ \alpha \f$ measured clockwise from
73
* a line of constant \f$ \omega \f$. Conversions between cartesian and
74
* ellipsoidal coordinates is provided by cart2toellip() and elliptocart2().
75
*
76
* The ellipsoid coordinates "cover" the ellipsoid twice; the replacement
77
* \f[
78
* \begin{align}
79
* \omega & \rightarrow -\omega,\\
80
* \beta & \rightarrow \pi-\beta,\\
81
* \alpha & \rightarrow \pi+\alpha,
82
* \end{align}
83
* \f]
84
* leaves the position and direction unchanged; see AngNorm(),
85
*
86
* Example of use:
87
* \include example-Ellipsoid3.cpp
88
**********************************************************************/
89
class
GEOGRAPHICLIB_EXPORT
Ellipsoid3
{
90
public
:
91
/**
92
* A type to hold three-dimensional positions and directions in cartesian
93
* coordinates.
94
**********************************************************************/
95
using
vec3
= std::array<Math::real, 3>;
96
private
:
97
/// \cond SKIP
98
friend
class
Cartesian3
;
// For access to cart2toellipint normvec
99
friend
class
Geodesic3
;
// For Flip
100
/// \endcond
101
using
real =
Math::real
;
102
using
ang =
Angle
;
103
static
void
normvec(
vec3
& R) {
104
real h =
Math::hypot3
(R[0], R[1], R[2]);
105
// No checking for h = 0. Result will be NaNs (we rely on this in
106
// Cartesian3::cart2rand).
107
R[0] /= h; R[1] /= h; R[2] /= h;
108
}
109
static
void
Flip(
ang
& bet,
ang
& omg,
ang
& alp) {
110
bet.
reflect
(
false
,
true
);
111
omg.
reflect
(
true
);
112
alp.
reflect
(
true
,
true
);
113
}
114
real
_a, _b, _c;
// semiaxes
115
real
_e2, _k2, _kp2, _k, _kp;
116
bool
_oblate, _prolate, _biaxial;
117
void
cart2toellipint(vec3 R,
ang
& bet,
ang
& omg, vec3 axes)
const
;
118
/**
119
* @return \e k the oblateness parameter.
120
**********************************************************************/
121
real
k()
const
{
return
_k; }
122
/**
123
* @return \e kp the prolateness parameter.
124
**********************************************************************/
125
real
kp()
const
{
return
_kp; }
126
/**
127
* @return whether the ellipsoid is oblate.
128
*
129
* This is determined by the condition kp2() == 0.
130
**********************************************************************/
131
bool
oblate()
const
{
return
_oblate; }
132
/**
133
* @return whether the ellipsoid is prolate.
134
*
135
* This is determined by the condition k2() == 0.
136
**********************************************************************/
137
bool
prolate()
const
{
return
_prolate; }
138
/**
139
* @return whether the ellipsoid is oblate or prolate.
140
**********************************************************************/
141
bool
biaxial()
const
{
return
_biaxial; }
142
public
:
143
/**
144
* The default constructor for a unit sphere in the oblate limit.
145
**********************************************************************/
146
Ellipsoid3();
147
/**
148
* An ellipsoid specified by its semiaxes.
149
*
150
* @param[in] a the major semiaxis.
151
* @param[in] b the median semiaxis.
152
* @param[in] c the minor semiaxis.
153
* @exception GeographicErr if the required ordering is semiaxes is
154
* violated.
155
*
156
* The semiaxes must satisfy \e a ≥ \e b ≥ \e c > 0.
157
* If \e a = \e c (a sphere), then the oblate limit is taken.
158
**********************************************************************/
159
Ellipsoid3(
real
a,
real
b,
real
c);
160
/**
161
* An ellipsoid specified by its median semiaxis and shape.
162
*
163
* @param[in] b the middle semiaxis.
164
* @param[in] e2 the eccentricity squared \f$e^2 = (a^2 - c^2)/b^2\f$.
165
* @param[in] k2 the oblateness parameter squared \f$k^2 = (b^2 - c^2) /
166
* (a^2 - c^2)\f$.
167
* @param[in] kp2 the prolateness parameter squared \f$k'^2= (a^2 - b^2) /
168
* (a^2 - c^2)\f$.
169
* @exception GeographicErr if the required ordering is semiaxes is
170
* violated.
171
*
172
* This form of the constructor is important when the eccentricity is small
173
* and giving \e e2 allows for more precision.
174
*
175
* In the case of a sphere with \e e2 = 0, this constructor distinguishes
176
* between and "oblate sphere" (\e k2 = 1), a "prolate sphere" (\e k2 = 0),
177
* and a "triaxial sphere" (\e k2 &isin (0,1)). These distinctions matter
178
* when ellipsoidal coordinates are used.
179
*
180
* \note The constructor normalizes \e k2 and \e kp2 so that \e k2 + \e kp2
181
* = 1.
182
**********************************************************************/
183
Ellipsoid3(
real
b,
real
e2,
real
k2,
real
kp2);
184
/** \name Inspector functions
185
**********************************************************************/
186
///@{
187
/**
188
* @return \e a the major semiaxis.
189
**********************************************************************/
190
real
a
()
const
{
return
_a; }
191
/**
192
* @return \e b the median semiaxis.
193
**********************************************************************/
194
real
b
()
const
{
return
_b; }
195
/**
196
* @return \e c the minor semiaxis.
197
**********************************************************************/
198
real
c
()
const
{
return
_c; }
199
/**
200
* @return \e e2 the eccentricity squared.
201
**********************************************************************/
202
real
e2
()
const
{
return
_e2; }
203
/**
204
* @return \e k2 the oblateness parameter squared.
205
**********************************************************************/
206
real
k2
()
const
{
return
_k2; }
207
/**
208
* @return \e kp2 the prolateness parameter squared.
209
**********************************************************************/
210
real
kp2
()
const
{
return
_kp2; }
211
///@}
212
/** \name Normalizing functions
213
**********************************************************************/
214
///@{
215
/**
216
* Scale a position to ensure it lies on the ellipsoid
217
*
218
* @param[inout] R the position.
219
*
220
* The components of \e R are scaled so that it lies on the ellipsoid. The
221
* resulting position is not in general the closest point on the ellipsoid.
222
* Use Cartesian3::carttocart2() for that.
223
**********************************************************************/
224
void
Norm(vec3& R)
const
;
225
/**
226
* Scale a position and direction to the ellipsoid
227
*
228
* @param[inout] R the position.
229
* @param[inout] V the position.
230
*
231
* The components of \e R are scaled so that it lies on the ellipsoid. Then
232
* \e V is projected to be tangent to the surface and is normalized to a
233
* unit vector.
234
**********************************************************************/
235
void
Norm(vec3& R, vec3& V)
const
;
236
/**
237
* Set the sheet for coordinates.
238
*
239
* @param[inout] bet the ellipsoidal latitude.
240
* @param[inout] omg the ellipsoidal longitude.
241
* @param[inout] alp the heading.
242
* @param[in] alt if true switch to the alternate sheet.
243
* @return whether the coordinates were changed.
244
*
245
* If alt = false (the default), the conventional sheet is used switching
246
* the values of \e bet, \e omg, and \e alp, so that \e bet ∈
247
* [-π/2, &pi/2].
248
*
249
* If alt = true, the alternate sheet is used switching the values of \e
250
* bet, \e omg, and \e alp, so that \e omg ∈ [0, π].
251
*
252
* This routine does not change \e n (the number of turns) for the
253
* coordinates.
254
**********************************************************************/
255
static
bool
AngNorm
(
Angle
& bet,
Angle
& omg,
Angle
& alp,
bool
alt =
false
) {
256
using
std::signbit;
257
// If !alt, put bet in [-pi/2,pi/2]
258
// If alt, put omg in [0, pi]
259
bool
flip = alt ? signbit(omg.
s
()) : signbit(bet.
c
());
260
if
(flip)
261
Flip(bet, omg, alp);
262
return
flip;
263
}
264
/**
265
* Set the sheet for coordinates.
266
*
267
* @param[inout] bet the ellipsoidal latitude.
268
* @param[inout] omg the ellipsoidal longitude.
269
* @param[in] alt if true switch to the alternate sheet.
270
* @return whether the coordinated were changed.
271
*
272
* This acts precisely the same and AngNorm(Angle&, Angle&, Angle&, bool)
273
* except that \e alp is omitted.
274
**********************************************************************/
275
static
bool
AngNorm
(
Angle
& bet,
Angle
& omg,
bool
alt =
false
) {
276
using
std::signbit;
277
// If !alt, put bet in [-pi/2,pi/2]
278
// If alt, put omg in [0, pi]
279
bool
flip = alt ? signbit(omg.
s
()) : signbit(bet.
c
());
280
if
(flip) {
281
ang alp;
282
Flip(bet, omg, alp);
283
}
284
return
flip;
285
}
286
///@}
287
/** \name Coordinate conversions.
288
**********************************************************************/
289
///@{
290
/**
291
* Convert a cartesian position to ellipsoidal coordinates.
292
*
293
* @param[in] R the cartesian position.
294
* @param[out] bet the ellipsoidal latitude.
295
* @param[out] omg the ellipsoidal longitude.
296
*
297
* \note \e R must lie on the surface of the ellipsoid. The "2" in "cart2"
298
* is used to emphasize this.
299
**********************************************************************/
300
void
cart2toellip(vec3 R,
Angle
& bet,
Angle
& omg)
const
;
301
/**
302
* Convert a cartesian position and direction to ellipsoidal coordinates.
303
*
304
* @param[in] R the cartesian position.
305
* @param[in] V the cartesian direction.
306
* @param[out] bet the ellipsoidal latitude.
307
* @param[out] omg the ellipsoidal longitude.
308
* @param[out] alp the azimuth.
309
*
310
* \note \e R must lie on the surface of the ellipsoid and \e V must be
311
* tangent to the surface at that point. The "2" in "cart2" is used to
312
* emphasize this.
313
**********************************************************************/
314
void
cart2toellip(vec3 R, vec3 V,
315
Angle
& bet,
Angle
& omg,
Angle
& alp)
const
;
316
/**
317
* Convert an ellipsoid position and cartesian direction to a heading.
318
*
319
* @param[in] bet the ellipsoidal latitude.
320
* @param[in] omg the ellipsoidal longitude.
321
* @param[in] V the cartesian direction.
322
* @param[out] alp the azimuth.
323
*
324
* This is a variant of cart2toellip(vec3, vec3, Angle&, Angle&, Angle&)
325
* where \e bet and \e omg are used to ensure that the correct sheet is
326
* used in determining \e alp.
327
*
328
* \note \e V must be tangent to the surface of the ellipsoid. The "2" in
329
* "cart2" is used to emphasize this.
330
**********************************************************************/
331
void
cart2toellip(
Angle
bet,
Angle
omg,
332
vec3 V,
Angle
& alp)
const
;
333
/**
334
* Convert ellipsoidal coordinates to a cartesian position.
335
*
336
* @param[in] bet the ellipsoidal latitude.
337
* @param[in] omg the ellipsoidal longitude.
338
* @param[out] R the cartesian position.
339
**********************************************************************/
340
void
elliptocart2(
Angle
bet,
Angle
omg, vec3& R)
const
;
341
/**
342
* Convert coordinates and heading to a cartesian position and direction.
343
*
344
* @param[in] bet the ellipsoidal latitude.
345
* @param[in] omg the ellipsoidal longitude.
346
* @param[in] alp the azimuth.
347
* @param[out] R the cartesian position.
348
* @param[out] V the cartesian direction.
349
**********************************************************************/
350
void
elliptocart2(
Angle
bet,
Angle
omg,
Angle
alp,
351
vec3& R, vec3& V)
const
;
352
///@}
353
/**
354
* A global instantiation of Ellipsoid3 with the parameters for the
355
* Earth.
356
**********************************************************************/
357
static
const
Ellipsoid3
& Earth();
358
359
};
360
361
}
// namespace Triaxial
362
}
// namespace GeographicLib
363
364
#endif
// GEOGRAPHICLIB_TRIAXIAL_HPP
Angle.hpp
Header for the GeographicLib::AngleT class.
Constants.hpp
Header for GeographicLib::Constants class.
GEOGRAPHICLIB_EXPORT
#define GEOGRAPHICLIB_EXPORT
Definition
Constants.hpp:59
ang
GeographicLib::Angle ang
Definition
Geod3Solve.cpp:26
real
GeographicLib::Math::real real
Definition
Geod3Solve.cpp:25
GeographicLib::AngleT::c
T c() const
Definition
Angle.hpp:153
GeographicLib::AngleT::s
T s() const
Definition
Angle.hpp:149
GeographicLib::AngleT::reflect
AngleT & reflect(bool flips, bool flipc=false, bool swapp=false)
Definition
Angle.hpp:696
GeographicLib::Math::hypot3
static T hypot3(T x, T y, T z)
Definition
Math.cpp:285
GeographicLib::Math::real
double real
Definition
Math.hpp:115
GeographicLib::Triaxial::Cartesian3
Transformations between cartesian and triaxial coordinates.
Definition
Cartesian3.hpp:101
GeographicLib::Triaxial::Ellipsoid3
A triaxial ellipsoid.
Definition
Ellipsoid3.hpp:89
GeographicLib::Triaxial::Ellipsoid3::k2
real k2() const
Definition
Ellipsoid3.hpp:206
GeographicLib::Triaxial::Ellipsoid3::b
real b() const
Definition
Ellipsoid3.hpp:194
GeographicLib::Triaxial::Ellipsoid3::AngNorm
static bool AngNorm(Angle &bet, Angle &omg, Angle &alp, bool alt=false)
Definition
Ellipsoid3.hpp:255
GeographicLib::Triaxial::Ellipsoid3::Ellipsoid3
Ellipsoid3()
Definition
Ellipsoid3.cpp:17
GeographicLib::Triaxial::Ellipsoid3::AngNorm
static bool AngNorm(Angle &bet, Angle &omg, bool alt=false)
Definition
Ellipsoid3.hpp:275
GeographicLib::Triaxial::Ellipsoid3::kp2
real kp2() const
Definition
Ellipsoid3.hpp:210
GeographicLib::Triaxial::Ellipsoid3::c
real c() const
Definition
Ellipsoid3.hpp:198
GeographicLib::Triaxial::Ellipsoid3::vec3
std::array< Math::real, 3 > vec3
Definition
Ellipsoid3.hpp:95
GeographicLib::Triaxial::Ellipsoid3::e2
real e2() const
Definition
Ellipsoid3.hpp:202
GeographicLib::Triaxial::Ellipsoid3::a
real a() const
Definition
Ellipsoid3.hpp:190
GeographicLib::Triaxial::Geodesic3
The solution of the geodesic problem for a triaxial ellipsoid.
Definition
Geodesic3.hpp:71
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
Ellipsoid3.hpp
Generated by
1.17.0