GeographicLib  2.6
Ellipsoid.hpp
Go to the documentation of this file.
1 /**
2  * \file Ellipsoid.hpp
3  * \brief Header for GeographicLib::Ellipsoid class
4  *
5  * Copyright (c) Charles Karney (2012-2023) <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_ELLIPSOID_HPP)
11 #define GEOGRAPHICLIB_ELLIPSOID_HPP 1
12 
15 
16 namespace GeographicLib {
17 
18  /**
19  * \brief Properties of an ellipsoid
20  *
21  * This class returns various properties of the ellipsoid and converts
22  * between various types of latitudes. This is for the most part a thin
23  * wrapper on top of the AuxLatitude class which is called with \e exact =
24  * true so that the results are valid for arbitrary flattenings &minus;100 <
25  * \e f < 99/100 (i.e., 1/100 < b/a < 100).
26  *
27  * Example of use:
28  * \include example-Ellipsoid.cpp
29  **********************************************************************/
30 
32  private:
33  typedef Math::real real;
34  static const int numit_ = 10;
35  real stol_;
36  real _a, _f,_b, _e2, _e12, _n;
37  AuxLatitude _aux;
38  real _rm, _c2;
39 
40  public:
41  /** \name Constructor
42  **********************************************************************/
43  ///@{
44 
45  /**
46  * Constructor for an ellipsoid with
47  *
48  * @param[in] a equatorial radius (meters).
49  * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
50  * Negative \e f gives a prolate ellipsoid.
51  * @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
52  * positive.
53  **********************************************************************/
54  Ellipsoid(real a, real f);
55  ///@}
56 
57  /** \name %Ellipsoid dimensions.
58  **********************************************************************/
59  ///@{
60 
61  /**
62  * @return \e a the equatorial radius of the ellipsoid (meters). This is
63  * the value used in the constructor.
64  **********************************************************************/
65  Math::real EquatorialRadius() const { return _a; }
66 
67  /**
68  * @return \e b the polar semi-axis (meters).
69  **********************************************************************/
70  Math::real PolarRadius() const { return _b; }
71 
72  /**
73  * @return \e L the distance between the equator and a pole along a
74  * meridian (meters). For a sphere \e L = (&pi;/2) \e a. The radius
75  * of a sphere with the same meridian length is \e L / (&pi;/2).
76  **********************************************************************/
77  Math::real QuarterMeridian() const;
78 
79  /**
80  * @return \e A the total area of the ellipsoid (meters<sup>2</sup>). For
81  * a sphere \e A = 4&pi; <i>a</i><sup>2</sup>. The radius of a sphere
82  * with the same area is sqrt(\e A / (4&pi;)).
83  **********************************************************************/
84  Math::real Area() const;
85 
86  /**
87  * @return \e V the total volume of the ellipsoid (meters<sup>3</sup>).
88  * For a sphere \e V = (4&pi; / 3) <i>a</i><sup>3</sup>. The radius of
89  * a sphere with the same volume is cbrt(\e V / (4&pi;/3)).
90  **********************************************************************/
92  { return (4 * Math::pi()) * Math::sq(_a) * _b / 3; }
93  ///@}
94 
95  /** \name %Ellipsoid shape
96  **********************************************************************/
97  ///@{
98 
99  /**
100  * @return \e f = (\e a &minus; \e b) / \e a, the flattening of the
101  * ellipsoid. This is the value used in the constructor. This is zero,
102  * positive, or negative for a sphere, oblate ellipsoid, or prolate
103  * ellipsoid.
104  **********************************************************************/
105  Math::real Flattening() const { return _f; }
106 
107  /**
108  * @return \e f ' = (\e a &minus; \e b) / \e b, the second flattening of
109  * the ellipsoid. This is zero, positive, or negative for a sphere,
110  * oblate ellipsoid, or prolate ellipsoid.
111  **********************************************************************/
112  Math::real SecondFlattening() const { return _f / (1 - _f); }
113 
114  /**
115  * @return \e n = (\e a &minus; \e b) / (\e a + \e b), the third flattening
116  * of the ellipsoid. This is zero, positive, or negative for a sphere,
117  * oblate ellipsoid, or prolate ellipsoid.
118  **********************************************************************/
119  Math::real ThirdFlattening() const { return _n; }
120 
121  /**
122  * @return <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
123  * <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity squared
124  * of the ellipsoid. This is zero, positive, or negative for a sphere,
125  * oblate ellipsoid, or prolate ellipsoid.
126  **********************************************************************/
127  Math::real EccentricitySq() const { return _e2; }
128 
129  /**
130  * @return <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
131  * <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentricity
132  * squared of the ellipsoid. This is zero, positive, or negative for a
133  * sphere, oblate ellipsoid, or prolate ellipsoid.
134  **********************************************************************/
135  Math::real SecondEccentricitySq() const { return _e12; }
136 
137  /**
138  * @return <i>e''</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
139  * <i>b</i><sup>2</sup>) / (<i>a</i><sup>2</sup> + <i>b</i><sup>2</sup>),
140  * the third eccentricity squared of the ellipsoid. This is zero,
141  * positive, or negative for a sphere, oblate ellipsoid, or prolate
142  * ellipsoid.
143  **********************************************************************/
144  Math::real ThirdEccentricitySq() const { return _e2 / (2 - _e2); }
145  ///@}
146 
147  /** \name Latitude conversion.
148  **********************************************************************/
149  ///@{
150 
151  /**
152  * @param[in] phi the geographic latitude (degrees).
153  * @return &beta; the parametric latitude (degrees).
154  *
155  * The geographic latitude, &phi;, is the angle between the equatorial
156  * plane and a vector normal to the surface of the ellipsoid.
157  *
158  * The parametric latitude (also called the reduced latitude), &beta;,
159  * allows the cartesian coordinated of a meridian to be expressed
160  * conveniently in parametric form as
161  * - \e R = \e a cos &beta;
162  * - \e Z = \e b sin &beta;
163  * .
164  * where \e a and \e b are the equatorial radius and the polar semi-axis.
165  * For a sphere &beta; = &phi;.
166  *
167  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
168  * result is undefined if this condition does not hold. The returned value
169  * &beta; lies in [&minus;90&deg;, 90&deg;].
170  **********************************************************************/
171  Math::real ParametricLatitude(real phi) const;
172 
173  /**
174  * @param[in] beta the parametric latitude (degrees).
175  * @return &phi; the geographic latitude (degrees).
176  *
177  * &beta; must lie in the range [&minus;90&deg;, 90&deg;]; the
178  * result is undefined if this condition does not hold. The returned value
179  * &phi; lies in [&minus;90&deg;, 90&deg;].
180  **********************************************************************/
181  Math::real InverseParametricLatitude(real beta) const;
182 
183  /**
184  * @param[in] phi the geographic latitude (degrees).
185  * @return &theta; the geocentric latitude (degrees).
186  *
187  * The geocentric latitude, &theta;, is the angle between the equatorial
188  * plane and a line between the center of the ellipsoid and a point on the
189  * ellipsoid. For a sphere &theta; = &phi;.
190  *
191  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
192  * result is undefined if this condition does not hold. The returned value
193  * &theta; lies in [&minus;90&deg;, 90&deg;].
194  **********************************************************************/
195  Math::real GeocentricLatitude(real phi) const;
196 
197  /**
198  * @param[in] theta the geocentric latitude (degrees).
199  * @return &phi; the geographic latitude (degrees).
200  *
201  * &theta; must lie in the range [&minus;90&deg;, 90&deg;]; the
202  * result is undefined if this condition does not hold. The returned value
203  * &phi; lies in [&minus;90&deg;, 90&deg;].
204  **********************************************************************/
205  Math::real InverseGeocentricLatitude(real theta) const;
206 
207  /**
208  * @param[in] phi the geographic latitude (degrees).
209  * @return &mu; the rectifying latitude (degrees).
210  *
211  * The rectifying latitude, &mu;, has the property that the distance along
212  * a meridian of the ellipsoid between two points with rectifying latitudes
213  * &mu;<sub>1</sub> and &mu;<sub>2</sub> is equal to
214  * (&mu;<sub>2</sub> - &mu;<sub>1</sub>) \e L / 90&deg;,
215  * where \e L = QuarterMeridian(). For a sphere &mu; = &phi;.
216  *
217  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
218  * result is undefined if this condition does not hold. The returned value
219  * &mu; lies in [&minus;90&deg;, 90&deg;].
220  **********************************************************************/
221  Math::real RectifyingLatitude(real phi) const;
222 
223  /**
224  * @param[in] mu the rectifying latitude (degrees).
225  * @return &phi; the geographic latitude (degrees).
226  *
227  * &mu; must lie in the range [&minus;90&deg;, 90&deg;]; the
228  * result is undefined if this condition does not hold. The returned value
229  * &phi; lies in [&minus;90&deg;, 90&deg;].
230  **********************************************************************/
231  Math::real InverseRectifyingLatitude(real mu) const;
232 
233  /**
234  * @param[in] phi the geographic latitude (degrees).
235  * @return &xi; the authalic latitude (degrees).
236  *
237  * The authalic latitude, &xi;, has the property that the area of the
238  * ellipsoid between two circles with authalic latitudes
239  * &xi;<sub>1</sub> and &xi;<sub>2</sub> is equal to (sin
240  * &xi;<sub>2</sub> - sin &xi;<sub>1</sub>) \e A / 2, where \e A
241  * = Area(). For a sphere &xi; = &phi;.
242  *
243  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
244  * result is undefined if this condition does not hold. The returned value
245  * &xi; lies in [&minus;90&deg;, 90&deg;].
246  **********************************************************************/
247  Math::real AuthalicLatitude(real phi) const;
248 
249  /**
250  * @param[in] xi the authalic latitude (degrees).
251  * @return &phi; the geographic latitude (degrees).
252  *
253  * &xi; must lie in the range [&minus;90&deg;, 90&deg;]; the
254  * result is undefined if this condition does not hold. The returned value
255  * &phi; lies in [&minus;90&deg;, 90&deg;].
256  **********************************************************************/
257  Math::real InverseAuthalicLatitude(real xi) const;
258 
259  /**
260  * @param[in] phi the geographic latitude (degrees).
261  * @return &chi; the conformal latitude (degrees).
262  *
263  * The conformal latitude, &chi;, gives the mapping of the ellipsoid to a
264  * sphere which which is conformal (angles are preserved) and in which the
265  * equator of the ellipsoid maps to the equator of the sphere. For a
266  * sphere &chi; = &phi;.
267  *
268  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
269  * result is undefined if this condition does not hold. The returned value
270  * &chi; lies in [&minus;90&deg;, 90&deg;].
271  **********************************************************************/
272  Math::real ConformalLatitude(real phi) const;
273 
274  /**
275  * @param[in] chi the conformal latitude (degrees).
276  * @return &phi; the geographic latitude (degrees).
277  *
278  * &chi; must lie in the range [&minus;90&deg;, 90&deg;]; the
279  * result is undefined if this condition does not hold. The returned value
280  * &phi; lies in [&minus;90&deg;, 90&deg;].
281  **********************************************************************/
282  Math::real InverseConformalLatitude(real chi) const;
283 
284  /**
285  * @param[in] phi the geographic latitude (degrees).
286  * @return &psi; the isometric latitude (degrees).
287  *
288  * The isometric latitude gives the mapping of the ellipsoid to a plane
289  * which which is conformal (angles are preserved) and in which the equator
290  * of the ellipsoid maps to a straight line of constant scale; this mapping
291  * defines the Mercator projection. For a sphere &psi; =
292  * sinh<sup>&minus;1</sup> tan &phi;.
293  *
294  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the result is
295  * undefined if this condition does not hold. The value returned for &phi;
296  * = &plusmn;90&deg; is some (positive or negative) large but finite value,
297  * such that InverseIsometricLatitude returns the original value of &phi;.
298  **********************************************************************/
299  Math::real IsometricLatitude(real phi) const;
300 
301  /**
302  * @param[in] psi the isometric latitude (degrees).
303  * @return &phi; the geographic latitude (degrees).
304  *
305  * The returned value &phi; lies in [&minus;90&deg;, 90&deg;]. For a
306  * sphere &phi; = tan<sup>&minus;1</sup> sinh &psi;.
307  **********************************************************************/
308  Math::real InverseIsometricLatitude(real psi) const;
309  ///@}
310 
311  /** \name Other quantities.
312  **********************************************************************/
313  ///@{
314 
315  /**
316  * @param[in] phi the geographic latitude (degrees).
317  * @return \e R = \e a cos &beta; the radius of a circle of latitude
318  * &phi; (meters). \e R (&pi;/180&deg;) gives meters per degree
319  * longitude measured along a circle of latitude.
320  *
321  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
322  * result is undefined if this condition does not hold.
323  **********************************************************************/
324  Math::real CircleRadius(real phi) const;
325 
326  /**
327  * @param[in] phi the geographic latitude (degrees).
328  * @return \e Z = \e b sin &beta; the distance of a circle of latitude
329  * &phi; from the equator measured parallel to the ellipsoid axis
330  * (meters).
331  *
332  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
333  * result is undefined if this condition does not hold.
334  **********************************************************************/
335  Math::real CircleHeight(real phi) const;
336 
337  /**
338  * @param[in] phi the geographic latitude (degrees).
339  * @return \e s the distance along a meridian
340  * between the equator and a point of latitude &phi; (meters). \e s is
341  * given by \e s = &mu; \e L / 90&deg;, where \e L =
342  * QuarterMeridian()).
343  *
344  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
345  * result is undefined if this condition does not hold.
346  **********************************************************************/
347  Math::real MeridianDistance(real phi) const;
348 
349  /**
350  * @param[in] phi the geographic latitude (degrees).
351  * @return &rho; the meridional radius of curvature of the ellipsoid at
352  * latitude &phi; (meters); this is the curvature of the meridian. \e
353  * rho is given by &rho; = (180&deg;/&pi;) d\e s / d&phi;,
354  * where \e s = MeridianDistance(); thus &rho; (&pi;/180&deg;)
355  * gives meters per degree latitude measured along a meridian.
356  *
357  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
358  * result is undefined if this condition does not hold.
359  **********************************************************************/
360  Math::real MeridionalCurvatureRadius(real phi) const;
361 
362  /**
363  * @param[in] phi the geographic latitude (degrees).
364  * @return &nu; the transverse radius of curvature of the ellipsoid at
365  * latitude &phi; (meters); this is the curvature of a curve on the
366  * ellipsoid which also lies in a plane perpendicular to the ellipsoid
367  * and to the meridian. &nu; is related to \e R = CircleRadius() by \e
368  * R = &nu; cos &phi;.
369  *
370  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
371  * result is undefined if this condition does not hold.
372  **********************************************************************/
373  Math::real TransverseCurvatureRadius(real phi) const;
374 
375  /**
376  * @param[in] phi the geographic latitude (degrees).
377  * @param[in] azi the angle between the meridian and the normal section
378  * (degrees).
379  * @return the radius of curvature of the ellipsoid in the normal
380  * section at latitude &phi; inclined at an angle \e azi to the
381  * meridian (meters).
382  *
383  * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the result is
384  * undefined this condition does not hold.
385  **********************************************************************/
386  Math::real NormalCurvatureRadius(real phi, real azi) const;
387  ///@}
388 
389  /** \name Eccentricity conversions.
390  **********************************************************************/
391  ///@{
392 
393  /**
394  * @param[in] fp = \e f ' = (\e a &minus; \e b) / \e b, the second
395  * flattening.
396  * @return \e f = (\e a &minus; \e b) / \e a, the flattening.
397  *
398  * \e f ' should lie in (&minus;1, &infin;).
399  * The returned value \e f lies in (&minus;&infin;, 1).
400  **********************************************************************/
402  { return fp / (1 + fp); }
403 
404  /**
405  * @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
406  * @return \e f ' = (\e a &minus; \e b) / \e b, the second flattening.
407  *
408  * \e f should lie in (&minus;&infin;, 1).
409  * The returned value \e f ' lies in (&minus;1, &infin;).
410  **********************************************************************/
412  { return f / (1 - f); }
413 
414  /**
415  * @param[in] n = (\e a &minus; \e b) / (\e a + \e b), the third
416  * flattening.
417  * @return \e f = (\e a &minus; \e b) / \e a, the flattening.
418  *
419  * \e n should lie in (&minus;1, 1).
420  * The returned value \e f lies in (&minus;&infin;, 1).
421  **********************************************************************/
423  { return 2 * n / (1 + n); }
424 
425  /**
426  * @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
427  * @return \e n = (\e a &minus; \e b) / (\e a + \e b), the third
428  * flattening.
429  *
430  * \e f should lie in (&minus;&infin;, 1).
431  * The returned value \e n lies in (&minus;1, 1).
432  **********************************************************************/
434  { return f / (2 - f); }
435 
436  /**
437  * @param[in] e2 = <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
438  * <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity
439  * squared.
440  * @return \e f = (\e a &minus; \e b) / \e a, the flattening.
441  *
442  * <i>e</i><sup>2</sup> should lie in (&minus;&infin;, 1).
443  * The returned value \e f lies in (&minus;&infin;, 1).
444  **********************************************************************/
446  { using std::sqrt; return e2 / (sqrt(1 - e2) + 1); }
447 
448  /**
449  * @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
450  * @return <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
451  * <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity
452  * squared.
453  *
454  * \e f should lie in (&minus;&infin;, 1).
455  * The returned value <i>e</i><sup>2</sup> lies in (&minus;&infin;, 1).
456  **********************************************************************/
458  { return f * (2 - f); }
459 
460  /**
461  * @param[in] ep2 = <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
462  * <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentricity
463  * squared.
464  * @return \e f = (\e a &minus; \e b) / \e a, the flattening.
465  *
466  * <i>e'</i> <sup>2</sup> should lie in (&minus;1, &infin;).
467  * The returned value \e f lies in (&minus;&infin;, 1).
468  **********************************************************************/
470  { using std::sqrt; return ep2 / (sqrt(1 + ep2) + 1 + ep2); }
471 
472  /**
473  * @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
474  * @return <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
475  * <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentricity
476  * squared.
477  *
478  * \e f should lie in (&minus;&infin;, 1).
479  * The returned value <i>e'</i> <sup>2</sup> lies in (&minus;1, &infin;).
480  **********************************************************************/
482  { return f * (2 - f) / Math::sq(1 - f); }
483 
484  /**
485  * @param[in] epp2 = <i>e''</i> <sup>2</sup> = (<i>a</i><sup>2</sup>
486  * &minus; <i>b</i><sup>2</sup>) / (<i>a</i><sup>2</sup> +
487  * <i>b</i><sup>2</sup>), the third eccentricity squared.
488  * @return \e f = (\e a &minus; \e b) / \e a, the flattening.
489  *
490  * <i>e''</i> <sup>2</sup> should lie in (&minus;1, 1).
491  * The returned value \e f lies in (&minus;&infin;, 1).
492  **********************************************************************/
494  using std::sqrt;
495  return 2 * epp2 / (sqrt((1 - epp2) * (1 + epp2)) + 1 + epp2);
496  }
497 
498  /**
499  * @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
500  * @return <i>e''</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
501  * <i>b</i><sup>2</sup>) / (<i>a</i><sup>2</sup> + <i>b</i><sup>2</sup>),
502  * the third eccentricity squared.
503  *
504  * \e f should lie in (&minus;&infin;, 1).
505  * The returned value <i>e''</i> <sup>2</sup> lies in (&minus;1, 1).
506  **********************************************************************/
508  { return f * (2 - f) / (1 + Math::sq(1 - f)); }
509 
510  ///@}
511 
512  /**
513  * A global instantiation of Ellipsoid with the parameters for the WGS84
514  * ellipsoid.
515  **********************************************************************/
516  static const Ellipsoid& WGS84();
517  };
518 
519 } // namespace GeographicLib
520 
521 #endif // GEOGRAPHICLIB_ELLIPSOID_HPP
static T pi()
Definition: Math.hpp:187
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:59
Math::real EccentricitySq() const
Definition: Ellipsoid.hpp:127
static Math::real SecondFlatteningToFlattening(real fp)
Definition: Ellipsoid.hpp:401
Math::real Volume() const
Definition: Ellipsoid.hpp:91
Math::real SecondEccentricitySq() const
Definition: Ellipsoid.hpp:135
static Math::real FlatteningToEccentricitySq(real f)
Definition: Ellipsoid.hpp:457
Math::real Flattening() const
Definition: Ellipsoid.hpp:105
static Math::real ThirdEccentricitySqToFlattening(real epp2)
Definition: Ellipsoid.hpp:493
Math::real EquatorialRadius() const
Definition: Ellipsoid.hpp:65
static Math::real ThirdFlatteningToFlattening(real n)
Definition: Ellipsoid.hpp:422
Math::real PolarRadius() const
Definition: Ellipsoid.hpp:70
static T sq(T x)
Definition: Math.hpp:209
Math::real SecondFlattening() const
Definition: Ellipsoid.hpp:112
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
static Math::real FlatteningToThirdEccentricitySq(real f)
Definition: Ellipsoid.hpp:507
static Math::real SecondEccentricitySqToFlattening(real ep2)
Definition: Ellipsoid.hpp:469
GeographicLib::Math::real real
Definition: Geod3Solve.cpp:25
Properties of an ellipsoid.
Definition: Ellipsoid.hpp:31
static Math::real FlatteningToThirdFlattening(real f)
Definition: Ellipsoid.hpp:433
Math::real ThirdFlattening() const
Definition: Ellipsoid.hpp:119
Header for GeographicLib::Constants class.
static Math::real EccentricitySqToFlattening(real e2)
Definition: Ellipsoid.hpp:445
Conversions between auxiliary latitudes.
Definition: AuxLatitude.hpp:75
static Math::real FlatteningToSecondFlattening(real f)
Definition: Ellipsoid.hpp:411
static Math::real FlatteningToSecondEccentricitySq(real f)
Definition: Ellipsoid.hpp:481
Math::real ThirdEccentricitySq() const
Definition: Ellipsoid.hpp:144
Header for the GeographicLib::AuxLatitude class.