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