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