GeographicLib  1.30
Geodesic.hpp
Go to the documentation of this file.
1 /**
2  * \file Geodesic.hpp
3  * \brief Header for GeographicLib::Geodesic class
4  *
5  * Copyright (c) Charles Karney (2009-2012) <charles@karney.com> and licensed
6  * under the MIT/X11 License. For more information, see
7  * http://geographiclib.sourceforge.net/
8  **********************************************************************/
9 
10 #if !defined(GEOGRAPHICLIB_GEODESIC_HPP)
11 #define GEOGRAPHICLIB_GEODESIC_HPP 1
12 
14 
15 #if !defined(GEOGRAPHICLIB_GEODESIC_ORDER)
16 /**
17  * The order of the expansions used by Geodesic.
18  **********************************************************************/
19 # define GEOGRAPHICLIB_GEODESIC_ORDER \
20  (GEOGRAPHICLIB_PRECISION == 2 ? 6 : (GEOGRAPHICLIB_PRECISION == 1 ? 3 : 7))
21 #endif
22 
23 namespace GeographicLib {
24 
25  class GeodesicLine;
26 
27  /**
28  * \brief %Geodesic calculations
29  *
30  * The shortest path between two points on a ellipsoid at (\e lat1, \e lon1)
31  * and (\e lat2, \e lon2) is called the geodesic. Its length is \e s12 and
32  * the geodesic from point 1 to point 2 has azimuths \e azi1 and \e azi2 at
33  * the two end points. (The azimuth is the heading measured clockwise from
34  * north. \e azi2 is the "forward" azimuth, i.e., the heading that takes you
35  * beyond point 2 not back to point 1.)
36  *
37  * Given \e lat1, \e lon1, \e azi1, and \e s12, we can determine \e lat2, \e
38  * lon2, and \e azi2. This is the \e direct geodesic problem and its
39  * solution is given by the function Geodesic::Direct. (If \e s12 is
40  * sufficiently large that the geodesic wraps more than halfway around the
41  * earth, there will be another geodesic between the points with a smaller \e
42  * s12.)
43  *
44  * Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi1, \e
45  * azi2, and \e s12. This is the \e inverse geodesic problem, whose solution
46  * is given by Geodesic::Inverse. Usually, the solution to the inverse
47  * problem is unique. In cases where there are multiple solutions (all with
48  * the same \e s12, of course), all the solutions can be easily generated
49  * once a particular solution is provided.
50  *
51  * The standard way of specifying the direct problem is the specify the
52  * distance \e s12 to the second point. However it is sometimes useful
53  * instead to specify the arc length \e a12 (in degrees) on the auxiliary
54  * sphere. This is a mathematical construct used in solving the geodesic
55  * problems. The solution of the direct problem in this form is provide by
56  * Geodesic::ArcDirect. An arc length in excess of 180&deg; indicates
57  * that the geodesic is not a shortest path. In addition, the arc length
58  * between an equatorial crossing and the next extremum of latitude for a
59  * geodesic is 90&deg;.
60  *
61  * This class can also calculate several other quantities related to
62  * geodesics. These are:
63  * - <i>reduced length</i>. If we fix the first point and increase \e azi1
64  * by \e dazi1 (radians), the second point is displaced \e m12 \e dazi1 in
65  * the direction \e azi2 + 90&deg;. The quantity \e m12 is called
66  * the "reduced length" and is symmetric under interchange of the two
67  * points. On a curved surface the reduced length obeys a symmetry
68  * relation, \e m12 + \e m21 = 0. On a flat surface, we have \e m12 = \e
69  * s12. The ratio <i>s12</i>/\e m12 gives the azimuthal scale for an
70  * azimuthal equidistant projection.
71  * - <i>geodesic scale</i>. Consider a reference geodesic and a second
72  * geodesic parallel to this one at point 1 and separated by a small
73  * distance \e dt. The separation of the two geodesics at point 2 is \e
74  * M12 \e dt where \e M12 is called the "geodesic scale". \e M21 is
75  * defined similarly (with the geodesics being parallel at point 2). On a
76  * flat surface, we have \e M12 = \e M21 = 1. The quantity 1/\e M12 gives
77  * the scale of the Cassini-Soldner projection.
78  * - <i>area</i>. Consider the quadrilateral bounded by the following lines:
79  * the geodesic from point 1 to point 2, the meridian from point 2 to the
80  * equator, the equator from \e lon2 to \e lon1, the meridian from the
81  * equator to point 1. The area of this quadrilateral is represented by \e
82  * S12 with a clockwise traversal of the perimeter counting as a positive
83  * area and it can be used to compute the area of any simple geodesic
84  * polygon.
85  *
86  * Overloaded versions of Geodesic::Direct, Geodesic::ArcDirect, and
87  * Geodesic::Inverse allow these quantities to be returned. In addition
88  * there are general functions Geodesic::GenDirect, and Geodesic::GenInverse
89  * which allow an arbitrary set of results to be computed. The quantities \e
90  * m12, \e M12, \e M21 which all specify the behavior of nearby geodesics
91  * obey addition rules. If points 1, 2, and 3 all lie on a single geodesic,
92  * then the following rules hold:
93  * - \e s13 = \e s12 + \e s23
94  * - \e a13 = \e a12 + \e a23
95  * - \e S13 = \e S12 + \e S23
96  * - \e m13 = \e m12 \e M23 + \e m23 \e M21
97  * - \e M13 = \e M12 \e M23 &minus; (1 &minus; \e M12 \e M21) \e m23 / \e m12
98  * - \e M31 = \e M32 \e M21 &minus; (1 &minus; \e M23 \e M32) \e m12 / \e m23
99  *
100  * Additional functionality is provided by the GeodesicLine class, which
101  * allows a sequence of points along a geodesic to be computed.
102  *
103  * The shortest distance returned by the solution of the inverse problem is
104  * (obviously) uniquely defined. However, in a few special cases there are
105  * multiple azimuths which yield the same shortest distance. Here is a
106  * catalog of those cases:
107  * - \e lat1 = &minus;\e lat2 (with neither at a pole). If \e azi1 = \e
108  * azi2, the geodesic is unique. Otherwise there are two geodesics and the
109  * second one is obtained by setting [\e azi1, \e azi2] = [\e azi2, \e
110  * azi1], [\e M12, \e M21] = [\e M21, \e M12], \e S12 = &minus;\e S12.
111  * (This occurs when the longitude difference is near &plusmn;180&deg; for
112  * oblate ellipsoids.)
113  * - \e lon2 = \e lon1 &plusmn; 180&deg; (with neither at a pole). If \e
114  * azi1 = 0&deg; or &plusmn;180&deg;, the geodesic is unique. Otherwise
115  * there are two geodesics and the second one is obtained by setting [\e
116  * azi1, \e azi2] = [&minus;\e azi1, &minus;\e azi2], \e S12 = &minus;\e
117  * S12. (This occurs when the \e lat2 is near &minus;\e lat1 for prolate
118  * ellipsoids.)
119  * - Points 1 and 2 at opposite poles. There are infinitely many geodesics
120  * which can be generated by setting [\e azi1, \e azi2] = [\e azi1, \e
121  * azi2] + [\e d, &minus;\e d], for arbitrary \e d. (For spheres, this
122  * prescription applies when points 1 and 2 are antipodal.)
123  * - s12 = 0 (coincident points). There are infinitely many geodesics which
124  * can be generated by setting [\e azi1, \e azi2] = [\e azi1, \e azi2] +
125  * [\e d, \e d], for arbitrary \e d.
126  *
127  * The calculations are accurate to better than 15 nm (15 nanometers) for the
128  * WGS84 ellipsoid. See Sec. 9 of
129  * <a href="http://arxiv.org/abs/1102.1215v1">arXiv:1102.1215v1</a> for
130  * details. The algorithms used by this class are based on series expansions
131  * using the flattening \e f as a small parameter. These are only accurate
132  * for |<i>f</i>| &lt; 0.02; however reasonably accurate results will be
133  * obtained for |<i>f</i>| &lt; 0.2. Here is a table of the approximate
134  * maximum error (expressed as a distance) for an ellipsoid with the same
135  * major radius as the WGS84 ellipsoid and different values of the
136  * flattening.<pre>
137  * |f| error
138  * 0.01 25 nm
139  * 0.02 30 nm
140  * 0.05 10 um
141  * 0.1 1.5 mm
142  * 0.2 300 mm
143  * </pre>For very eccentric ellipsoids, use GeodesicExact instead.
144  *
145  * The algorithms are described in
146  * - C. F. F. Karney,
147  * <a href="http://dx.doi.org/10.1007/s00190-012-0578-z">
148  * Algorithms for geodesics</a>,
149  * J. Geodesy <b>87</b>, 43--55 (2013);
150  * DOI: <a href="http://dx.doi.org/10.1007/s00190-012-0578-z">
151  * 10.1007/s00190-012-0578-z</a>;
152  * addenda: <a href="http://geographiclib.sf.net/geod-addenda.html">
153  * geod-addenda.html</a>.
154  * .
155  * For more information on geodesics see \ref geodesic.
156  *
157  * Example of use:
158  * \include example-Geodesic.cpp
159  *
160  * <a href="Geod.1.html">Geod</a> is a command-line utility providing access
161  * to the functionality of Geodesic and GeodesicLine.
162  **********************************************************************/
163 
165  private:
166  typedef Math::real real;
167  friend class GeodesicLine;
168  static const int nA1_ = GEOGRAPHICLIB_GEODESIC_ORDER;
169  static const int nC1_ = GEOGRAPHICLIB_GEODESIC_ORDER;
170  static const int nC1p_ = GEOGRAPHICLIB_GEODESIC_ORDER;
171  static const int nA2_ = GEOGRAPHICLIB_GEODESIC_ORDER;
172  static const int nC2_ = GEOGRAPHICLIB_GEODESIC_ORDER;
173  static const int nA3_ = GEOGRAPHICLIB_GEODESIC_ORDER;
174  static const int nA3x_ = nA3_;
175  static const int nC3_ = GEOGRAPHICLIB_GEODESIC_ORDER;
176  static const int nC3x_ = (nC3_ * (nC3_ - 1)) / 2;
177  static const int nC4_ = GEOGRAPHICLIB_GEODESIC_ORDER;
178  static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2;
179  static const unsigned maxit1_ = 20;
180  static const unsigned maxit2_ = maxit1_ +
181  std::numeric_limits<real>::digits + 10;
182 
183  static const real tiny_;
184  static const real tol0_;
185  static const real tol1_;
186  static const real tol2_;
187  static const real tolb_;
188  static const real xthresh_;
189 
190  enum captype {
191  CAP_NONE = 0U,
192  CAP_C1 = 1U<<0,
193  CAP_C1p = 1U<<1,
194  CAP_C2 = 1U<<2,
195  CAP_C3 = 1U<<3,
196  CAP_C4 = 1U<<4,
197  CAP_ALL = 0x1FU,
198  OUT_ALL = 0x7F80U,
199  };
200 
201  static real SinCosSeries(bool sinp,
202  real sinx, real cosx, const real c[], int n)
203  throw();
204  static inline real AngRound(real x) throw() {
205  // The makes the smallest gap in x = 1/16 - nextafter(1/16, 0) = 1/2^57
206  // for reals = 0.7 pm on the earth if x is an angle in degrees. (This
207  // is about 1000 times more resolution than we get with angles around 90
208  // degrees.) We use this to avoid having to deal with near singular
209  // cases when x is non-zero but tiny (e.g., 1.0e-200).
210  const real z = 1/real(16);
211  volatile real y = std::abs(x);
212  // The compiler mustn't "simplify" z - (z - y) to y
213  y = y < z ? z - (z - y) : y;
214  return x < 0 ? -y : y;
215  }
216  static inline void SinCosNorm(real& sinx, real& cosx) throw() {
217  real r = Math::hypot(sinx, cosx);
218  sinx /= r;
219  cosx /= r;
220  }
221  static real Astroid(real x, real y) throw();
222 
223  real _a, _f, _f1, _e2, _ep2, _n, _b, _c2, _etol2;
224  real _A3x[nA3x_], _C3x[nC3x_], _C4x[nC4x_];
225 
226  void Lengths(real eps, real sig12,
227  real ssig1, real csig1, real dn1,
228  real ssig2, real csig2, real dn2,
229  real cbet1, real cbet2,
230  real& s12s, real& m12a, real& m0,
231  bool scalep, real& M12, real& M21,
232  real C1a[], real C2a[]) const throw();
233  real InverseStart(real sbet1, real cbet1, real dn1,
234  real sbet2, real cbet2, real dn2,
235  real lam12,
236  real& salp1, real& calp1,
237  real& salp2, real& calp2,
238  real C1a[], real C2a[]) const throw();
239  real Lambda12(real sbet1, real cbet1, real dn1,
240  real sbet2, real cbet2, real dn2,
241  real salp1, real calp1,
242  real& salp2, real& calp2, real& sig12,
243  real& ssig1, real& csig1, real& ssig2, real& csig2,
244  real& eps, real& domg12, bool diffp, real& dlam12,
245  real C1a[], real C2a[], real C3a[])
246  const throw();
247 
248  // These are Maxima generated functions to provide series approximations to
249  // the integrals for the ellipsoidal geodesic.
250  static real A1m1f(real eps) throw();
251  static void C1f(real eps, real c[]) throw();
252  static void C1pf(real eps, real c[]) throw();
253  static real A2m1f(real eps) throw();
254  static void C2f(real eps, real c[]) throw();
255 
256  void A3coeff() throw();
257  real A3f(real eps) const throw();
258  void C3coeff() throw();
259  void C3f(real eps, real c[]) const throw();
260  void C4coeff() throw();
261  void C4f(real k2, real c[]) const throw();
262 
263  public:
264 
265  /**
266  * Bit masks for what calculations to do. These masks do double duty.
267  * They signify to the GeodesicLine::GeodesicLine constructor and to
268  * Geodesic::Line what capabilities should be included in the GeodesicLine
269  * object. They also specify which results to return in the general
270  * routines Geodesic::GenDirect and Geodesic::GenInverse routines.
271  * GeodesicLine::mask is a duplication of this enum.
272  **********************************************************************/
273  enum mask {
274  /**
275  * No capabilities, no output.
276  * @hideinitializer
277  **********************************************************************/
278  NONE = 0U,
279  /**
280  * Calculate latitude \e lat2. (It's not necessary to include this as a
281  * capability to GeodesicLine because this is included by default.)
282  * @hideinitializer
283  **********************************************************************/
284  LATITUDE = 1U<<7 | CAP_NONE,
285  /**
286  * Calculate longitude \e lon2.
287  * @hideinitializer
288  **********************************************************************/
289  LONGITUDE = 1U<<8 | CAP_C3,
290  /**
291  * Calculate azimuths \e azi1 and \e azi2. (It's not necessary to
292  * include this as a capability to GeodesicLine because this is included
293  * by default.)
294  * @hideinitializer
295  **********************************************************************/
296  AZIMUTH = 1U<<9 | CAP_NONE,
297  /**
298  * Calculate distance \e s12.
299  * @hideinitializer
300  **********************************************************************/
301  DISTANCE = 1U<<10 | CAP_C1,
302  /**
303  * Allow distance \e s12 to be used as input in the direct geodesic
304  * problem.
305  * @hideinitializer
306  **********************************************************************/
307  DISTANCE_IN = 1U<<11 | CAP_C1 | CAP_C1p,
308  /**
309  * Calculate reduced length \e m12.
310  * @hideinitializer
311  **********************************************************************/
312  REDUCEDLENGTH = 1U<<12 | CAP_C1 | CAP_C2,
313  /**
314  * Calculate geodesic scales \e M12 and \e M21.
315  * @hideinitializer
316  **********************************************************************/
317  GEODESICSCALE = 1U<<13 | CAP_C1 | CAP_C2,
318  /**
319  * Calculate area \e S12.
320  * @hideinitializer
321  **********************************************************************/
322  AREA = 1U<<14 | CAP_C4,
323  /**
324  * All capabilities. Calculate everything.
325  * @hideinitializer
326  **********************************************************************/
327  ALL = OUT_ALL| CAP_ALL,
328  };
329 
330  /** \name Constructor
331  **********************************************************************/
332  ///@{
333  /**
334  * Constructor for a ellipsoid with
335  *
336  * @param[in] a equatorial radius (meters).
337  * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
338  * Negative \e f gives a prolate ellipsoid. If \e f > 1, set flattening
339  * to 1/\e f.
340  * @exception GeographicErr if \e a or (1 &minus; \e f ) \e a is not
341  * positive.
342  **********************************************************************/
343  Geodesic(real a, real f);
344  ///@}
345 
346  /** \name Direct geodesic problem specified in terms of distance.
347  **********************************************************************/
348  ///@{
349  /**
350  * Solve the direct geodesic problem where the length of the geodesic
351  * is specify in terms of distance.
352  *
353  * @param[in] lat1 latitude of point 1 (degrees).
354  * @param[in] lon1 longitude of point 1 (degrees).
355  * @param[in] azi1 azimuth at point 1 (degrees).
356  * @param[in] s12 distance between point 1 and point 2 (meters); it can be
357  * negative.
358  * @param[out] lat2 latitude of point 2 (degrees).
359  * @param[out] lon2 longitude of point 2 (degrees).
360  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
361  * @param[out] m12 reduced length of geodesic (meters).
362  * @param[out] M12 geodesic scale of point 2 relative to point 1
363  * (dimensionless).
364  * @param[out] M21 geodesic scale of point 1 relative to point 2
365  * (dimensionless).
366  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
367  * @return \e a12 arc length of between point 1 and point 2 (degrees).
368  *
369  * \e lat1 should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and \e
370  * azi1 should be in the range [&minus;540&deg;, 540&deg;). The values of
371  * \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
372  * 180&deg;).
373  *
374  * If either point is at a pole, the azimuth is defined by keeping the
375  * longitude fixed and writing \e lat = &plusmn;(90&deg; &minus; &epsilon;)
376  * and taking the limit &epsilon; &rarr; 0+. An arc length greater that
377  * 180&deg; signifies a geodesic which is not a shortest path. (For a
378  * prolate ellipsoid, an additional condition is necessary for a shortest
379  * path: the longitudinal extent must not exceed of 180&deg;.)
380  *
381  * The following functions are overloaded versions of Geodesic::Direct
382  * which omit some of the output parameters. Note, however, that the arc
383  * length is always computed and returned as the function value.
384  **********************************************************************/
385  Math::real Direct(real lat1, real lon1, real azi1, real s12,
386  real& lat2, real& lon2, real& azi2,
387  real& m12, real& M12, real& M21, real& S12)
388  const throw() {
389  real t;
390  return GenDirect(lat1, lon1, azi1, false, s12,
391  LATITUDE | LONGITUDE | AZIMUTH |
392  REDUCEDLENGTH | GEODESICSCALE | AREA,
393  lat2, lon2, azi2, t, m12, M12, M21, S12);
394  }
395 
396  /**
397  * See the documentation for Geodesic::Direct.
398  **********************************************************************/
399  Math::real Direct(real lat1, real lon1, real azi1, real s12,
400  real& lat2, real& lon2)
401  const throw() {
402  real t;
403  return GenDirect(lat1, lon1, azi1, false, s12,
404  LATITUDE | LONGITUDE,
405  lat2, lon2, t, t, t, t, t, t);
406  }
407 
408  /**
409  * See the documentation for Geodesic::Direct.
410  **********************************************************************/
411  Math::real Direct(real lat1, real lon1, real azi1, real s12,
412  real& lat2, real& lon2, real& azi2)
413  const throw() {
414  real t;
415  return GenDirect(lat1, lon1, azi1, false, s12,
416  LATITUDE | LONGITUDE | AZIMUTH,
417  lat2, lon2, azi2, t, t, t, t, t);
418  }
419 
420  /**
421  * See the documentation for Geodesic::Direct.
422  **********************************************************************/
423  Math::real Direct(real lat1, real lon1, real azi1, real s12,
424  real& lat2, real& lon2, real& azi2, real& m12)
425  const throw() {
426  real t;
427  return GenDirect(lat1, lon1, azi1, false, s12,
428  LATITUDE | LONGITUDE | AZIMUTH | REDUCEDLENGTH,
429  lat2, lon2, azi2, t, m12, t, t, t);
430  }
431 
432  /**
433  * See the documentation for Geodesic::Direct.
434  **********************************************************************/
435  Math::real Direct(real lat1, real lon1, real azi1, real s12,
436  real& lat2, real& lon2, real& azi2,
437  real& M12, real& M21)
438  const throw() {
439  real t;
440  return GenDirect(lat1, lon1, azi1, false, s12,
441  LATITUDE | LONGITUDE | AZIMUTH | GEODESICSCALE,
442  lat2, lon2, azi2, t, t, M12, M21, t);
443  }
444 
445  /**
446  * See the documentation for Geodesic::Direct.
447  **********************************************************************/
448  Math::real Direct(real lat1, real lon1, real azi1, real s12,
449  real& lat2, real& lon2, real& azi2,
450  real& m12, real& M12, real& M21)
451  const throw() {
452  real t;
453  return GenDirect(lat1, lon1, azi1, false, s12,
454  LATITUDE | LONGITUDE | AZIMUTH |
455  REDUCEDLENGTH | GEODESICSCALE,
456  lat2, lon2, azi2, t, m12, M12, M21, t);
457  }
458  ///@}
459 
460  /** \name Direct geodesic problem specified in terms of arc length.
461  **********************************************************************/
462  ///@{
463  /**
464  * Solve the direct geodesic problem where the length of the geodesic
465  * is specify in terms of arc length.
466  *
467  * @param[in] lat1 latitude of point 1 (degrees).
468  * @param[in] lon1 longitude of point 1 (degrees).
469  * @param[in] azi1 azimuth at point 1 (degrees).
470  * @param[in] a12 arc length between point 1 and point 2 (degrees); it can
471  * be negative.
472  * @param[out] lat2 latitude of point 2 (degrees).
473  * @param[out] lon2 longitude of point 2 (degrees).
474  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
475  * @param[out] s12 distance between point 1 and point 2 (meters).
476  * @param[out] m12 reduced length of geodesic (meters).
477  * @param[out] M12 geodesic scale of point 2 relative to point 1
478  * (dimensionless).
479  * @param[out] M21 geodesic scale of point 1 relative to point 2
480  * (dimensionless).
481  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
482  *
483  * \e lat1 should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and \e
484  * azi1 should be in the range [&minus;540&deg;, 540&deg;). The values of
485  * \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
486  * 180&deg;).
487  *
488  * If either point is at a pole, the azimuth is defined by keeping the
489  * longitude fixed and writing \e lat = &plusmn;(90&deg; &minus; &epsilon;)
490  * and taking the limit &epsilon; &rarr; 0+. An arc length greater that
491  * 180&deg; signifies a geodesic which is not a shortest path. (For a
492  * prolate ellipsoid, an additional condition is necessary for a shortest
493  * path: the longitudinal extent must not exceed of 180&deg;.)
494  *
495  * The following functions are overloaded versions of Geodesic::Direct
496  * which omit some of the output parameters.
497  **********************************************************************/
498  void ArcDirect(real lat1, real lon1, real azi1, real a12,
499  real& lat2, real& lon2, real& azi2, real& s12,
500  real& m12, real& M12, real& M21, real& S12)
501  const throw() {
502  GenDirect(lat1, lon1, azi1, true, a12,
503  LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
504  REDUCEDLENGTH | GEODESICSCALE | AREA,
505  lat2, lon2, azi2, s12, m12, M12, M21, S12);
506  }
507 
508  /**
509  * See the documentation for Geodesic::ArcDirect.
510  **********************************************************************/
511  void ArcDirect(real lat1, real lon1, real azi1, real a12,
512  real& lat2, real& lon2) const throw() {
513  real t;
514  GenDirect(lat1, lon1, azi1, true, a12,
515  LATITUDE | LONGITUDE,
516  lat2, lon2, t, t, t, t, t, t);
517  }
518 
519  /**
520  * See the documentation for Geodesic::ArcDirect.
521  **********************************************************************/
522  void ArcDirect(real lat1, real lon1, real azi1, real a12,
523  real& lat2, real& lon2, real& azi2) const throw() {
524  real t;
525  GenDirect(lat1, lon1, azi1, true, a12,
526  LATITUDE | LONGITUDE | AZIMUTH,
527  lat2, lon2, azi2, t, t, t, t, t);
528  }
529 
530  /**
531  * See the documentation for Geodesic::ArcDirect.
532  **********************************************************************/
533  void ArcDirect(real lat1, real lon1, real azi1, real a12,
534  real& lat2, real& lon2, real& azi2, real& s12)
535  const throw() {
536  real t;
537  GenDirect(lat1, lon1, azi1, true, a12,
538  LATITUDE | LONGITUDE | AZIMUTH | DISTANCE,
539  lat2, lon2, azi2, s12, t, t, t, t);
540  }
541 
542  /**
543  * See the documentation for Geodesic::ArcDirect.
544  **********************************************************************/
545  void ArcDirect(real lat1, real lon1, real azi1, real a12,
546  real& lat2, real& lon2, real& azi2,
547  real& s12, real& m12) const throw() {
548  real t;
549  GenDirect(lat1, lon1, azi1, true, a12,
550  LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
551  REDUCEDLENGTH,
552  lat2, lon2, azi2, s12, m12, t, t, t);
553  }
554 
555  /**
556  * See the documentation for Geodesic::ArcDirect.
557  **********************************************************************/
558  void ArcDirect(real lat1, real lon1, real azi1, real a12,
559  real& lat2, real& lon2, real& azi2, real& s12,
560  real& M12, real& M21) const throw() {
561  real t;
562  GenDirect(lat1, lon1, azi1, true, a12,
563  LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
564  GEODESICSCALE,
565  lat2, lon2, azi2, s12, t, M12, M21, t);
566  }
567 
568  /**
569  * See the documentation for Geodesic::ArcDirect.
570  **********************************************************************/
571  void ArcDirect(real lat1, real lon1, real azi1, real a12,
572  real& lat2, real& lon2, real& azi2, real& s12,
573  real& m12, real& M12, real& M21) const throw() {
574  real t;
575  GenDirect(lat1, lon1, azi1, true, a12,
576  LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
577  REDUCEDLENGTH | GEODESICSCALE,
578  lat2, lon2, azi2, s12, m12, M12, M21, t);
579  }
580  ///@}
581 
582  /** \name General version of the direct geodesic solution.
583  **********************************************************************/
584  ///@{
585 
586  /**
587  * The general direct geodesic problem. Geodesic::Direct and
588  * Geodesic::ArcDirect are defined in terms of this function.
589  *
590  * @param[in] lat1 latitude of point 1 (degrees).
591  * @param[in] lon1 longitude of point 1 (degrees).
592  * @param[in] azi1 azimuth at point 1 (degrees).
593  * @param[in] arcmode boolean flag determining the meaning of the \e
594  * s12_a12.
595  * @param[in] s12_a12 if \e arcmode is false, this is the distance between
596  * point 1 and point 2 (meters); otherwise it is the arc length between
597  * point 1 and point 2 (degrees); it can be negative.
598  * @param[in] outmask a bitor'ed combination of Geodesic::mask values
599  * specifying which of the following parameters should be set.
600  * @param[out] lat2 latitude of point 2 (degrees).
601  * @param[out] lon2 longitude of point 2 (degrees).
602  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
603  * @param[out] s12 distance between point 1 and point 2 (meters).
604  * @param[out] m12 reduced length of geodesic (meters).
605  * @param[out] M12 geodesic scale of point 2 relative to point 1
606  * (dimensionless).
607  * @param[out] M21 geodesic scale of point 1 relative to point 2
608  * (dimensionless).
609  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
610  * @return \e a12 arc length of between point 1 and point 2 (degrees).
611  *
612  * The Geodesic::mask values possible for \e outmask are
613  * - \e outmask |= Geodesic::LATITUDE for the latitude \e lat2.
614  * - \e outmask |= Geodesic::LONGITUDE for the latitude \e lon2.
615  * - \e outmask |= Geodesic::AZIMUTH for the latitude \e azi2.
616  * - \e outmask |= Geodesic::DISTANCE for the distance \e s12.
617  * - \e outmask |= Geodesic::REDUCEDLENGTH for the reduced length \e
618  * m12.
619  * - \e outmask |= Geodesic::GEODESICSCALE for the geodesic scales \e
620  * M12 and \e M21.
621  * - \e outmask |= Geodesic::AREA for the area \e S12.
622  * .
623  * The function value \e a12 is always computed and returned and this
624  * equals \e s12_a12 is \e arcmode is true. If \e outmask includes
625  * Geodesic::DISTANCE and \e arcmode is false, then \e s12 = \e s12_a12.
626  * It is not necessary to include Geodesic::DISTANCE_IN in \e outmask; this
627  * is automatically included is \e arcmode is false.
628  **********************************************************************/
629  Math::real GenDirect(real lat1, real lon1, real azi1,
630  bool arcmode, real s12_a12, unsigned outmask,
631  real& lat2, real& lon2, real& azi2,
632  real& s12, real& m12, real& M12, real& M21,
633  real& S12) const throw();
634  ///@}
635 
636  /** \name Inverse geodesic problem.
637  **********************************************************************/
638  ///@{
639  /**
640  * Solve the inverse geodesic problem.
641  *
642  * @param[in] lat1 latitude of point 1 (degrees).
643  * @param[in] lon1 longitude of point 1 (degrees).
644  * @param[in] lat2 latitude of point 2 (degrees).
645  * @param[in] lon2 longitude of point 2 (degrees).
646  * @param[out] s12 distance between point 1 and point 2 (meters).
647  * @param[out] azi1 azimuth at point 1 (degrees).
648  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
649  * @param[out] m12 reduced length of geodesic (meters).
650  * @param[out] M12 geodesic scale of point 2 relative to point 1
651  * (dimensionless).
652  * @param[out] M21 geodesic scale of point 1 relative to point 2
653  * (dimensionless).
654  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
655  * @return \e a12 arc length of between point 1 and point 2 (degrees).
656  *
657  * \e lat1 and \e lat2 should be in the range [&minus;90&deg;, 90&deg;]; \e
658  * lon1 and \e lon2 should be in the range [&minus;540&deg;, 540&deg;).
659  * The values of \e azi1 and \e azi2 returned are in the range
660  * [&minus;180&deg;, 180&deg;).
661  *
662  * If either point is at a pole, the azimuth is defined by keeping the
663  * longitude fixed and writing \e lat = &plusmn;(90&deg; &minus; &epsilon;)
664  * and taking the limit &epsilon; &rarr; 0+.
665  *
666  * The solution to the inverse problem is found using Newton's method. If
667  * this fails to converge (this is very unlikely in geodetic applications
668  * but does occur for very eccentric ellipsoids), then the bisection method
669  * is used to refine the solution.
670  *
671  * The following functions are overloaded versions of Geodesic::Inverse
672  * which omit some of the output parameters. Note, however, that the arc
673  * length is always computed and returned as the function value.
674  **********************************************************************/
675  Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
676  real& s12, real& azi1, real& azi2, real& m12,
677  real& M12, real& M21, real& S12) const throw() {
678  return GenInverse(lat1, lon1, lat2, lon2,
679  DISTANCE | AZIMUTH |
680  REDUCEDLENGTH | GEODESICSCALE | AREA,
681  s12, azi1, azi2, m12, M12, M21, S12);
682  }
683 
684  /**
685  * See the documentation for Geodesic::Inverse.
686  **********************************************************************/
687  Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
688  real& s12) const throw() {
689  real t;
690  return GenInverse(lat1, lon1, lat2, lon2,
691  DISTANCE,
692  s12, t, t, t, t, t, t);
693  }
694 
695  /**
696  * See the documentation for Geodesic::Inverse.
697  **********************************************************************/
698  Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
699  real& azi1, real& azi2) const throw() {
700  real t;
701  return GenInverse(lat1, lon1, lat2, lon2,
702  AZIMUTH,
703  t, azi1, azi2, t, t, t, t);
704  }
705 
706  /**
707  * See the documentation for Geodesic::Inverse.
708  **********************************************************************/
709  Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
710  real& s12, real& azi1, real& azi2)
711  const throw() {
712  real t;
713  return GenInverse(lat1, lon1, lat2, lon2,
714  DISTANCE | AZIMUTH,
715  s12, azi1, azi2, t, t, t, t);
716  }
717 
718  /**
719  * See the documentation for Geodesic::Inverse.
720  **********************************************************************/
721  Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
722  real& s12, real& azi1, real& azi2, real& m12)
723  const throw() {
724  real t;
725  return GenInverse(lat1, lon1, lat2, lon2,
726  DISTANCE | AZIMUTH | REDUCEDLENGTH,
727  s12, azi1, azi2, m12, t, t, t);
728  }
729 
730  /**
731  * See the documentation for Geodesic::Inverse.
732  **********************************************************************/
733  Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
734  real& s12, real& azi1, real& azi2,
735  real& M12, real& M21) const throw() {
736  real t;
737  return GenInverse(lat1, lon1, lat2, lon2,
738  DISTANCE | AZIMUTH | GEODESICSCALE,
739  s12, azi1, azi2, t, M12, M21, t);
740  }
741 
742  /**
743  * See the documentation for Geodesic::Inverse.
744  **********************************************************************/
745  Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
746  real& s12, real& azi1, real& azi2, real& m12,
747  real& M12, real& M21) const throw() {
748  real t;
749  return GenInverse(lat1, lon1, lat2, lon2,
750  DISTANCE | AZIMUTH |
751  REDUCEDLENGTH | GEODESICSCALE,
752  s12, azi1, azi2, m12, M12, M21, t);
753  }
754  ///@}
755 
756  /** \name General version of inverse geodesic solution.
757  **********************************************************************/
758  ///@{
759  /**
760  * The general inverse geodesic calculation. Geodesic::Inverse is defined
761  * in terms of this function.
762  *
763  * @param[in] lat1 latitude of point 1 (degrees).
764  * @param[in] lon1 longitude of point 1 (degrees).
765  * @param[in] lat2 latitude of point 2 (degrees).
766  * @param[in] lon2 longitude of point 2 (degrees).
767  * @param[in] outmask a bitor'ed combination of Geodesic::mask values
768  * specifying which of the following parameters should be set.
769  * @param[out] s12 distance between point 1 and point 2 (meters).
770  * @param[out] azi1 azimuth at point 1 (degrees).
771  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
772  * @param[out] m12 reduced length of geodesic (meters).
773  * @param[out] M12 geodesic scale of point 2 relative to point 1
774  * (dimensionless).
775  * @param[out] M21 geodesic scale of point 1 relative to point 2
776  * (dimensionless).
777  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
778  * @return \e a12 arc length of between point 1 and point 2 (degrees).
779  *
780  * The Geodesic::mask values possible for \e outmask are
781  * - \e outmask |= Geodesic::DISTANCE for the distance \e s12.
782  * - \e outmask |= Geodesic::AZIMUTH for the latitude \e azi2.
783  * - \e outmask |= Geodesic::REDUCEDLENGTH for the reduced length \e
784  * m12.
785  * - \e outmask |= Geodesic::GEODESICSCALE for the geodesic scales \e
786  * M12 and \e M21.
787  * - \e outmask |= Geodesic::AREA for the area \e S12.
788  * .
789  * The arc length is always computed and returned as the function value.
790  **********************************************************************/
791  Math::real GenInverse(real lat1, real lon1, real lat2, real lon2,
792  unsigned outmask,
793  real& s12, real& azi1, real& azi2,
794  real& m12, real& M12, real& M21, real& S12)
795  const throw();
796  ///@}
797 
798  /** \name Interface to GeodesicLine.
799  **********************************************************************/
800  ///@{
801 
802  /**
803  * Set up to compute several points on a singe geodesic.
804  *
805  * @param[in] lat1 latitude of point 1 (degrees).
806  * @param[in] lon1 longitude of point 1 (degrees).
807  * @param[in] azi1 azimuth at point 1 (degrees).
808  * @param[in] caps bitor'ed combination of Geodesic::mask values
809  * specifying the capabilities the GeodesicLine object should possess,
810  * i.e., which quantities can be returned in calls to
811  * GeodesicLib::Position.
812  *
813  * \e lat1 should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and \e
814  * azi1 should be in the range [&minus;540&deg;, 540&deg;).
815  *
816  * The Geodesic::mask values are
817  * - \e caps |= Geodesic::LATITUDE for the latitude \e lat2; this is
818  * added automatically
819  * - \e caps |= Geodesic::LONGITUDE for the latitude \e lon2
820  * - \e caps |= Geodesic::AZIMUTH for the azimuth \e azi2; this is
821  * added automatically
822  * - \e caps |= Geodesic::DISTANCE for the distance \e s12
823  * - \e caps |= Geodesic::REDUCEDLENGTH for the reduced length \e m12
824  * - \e caps |= Geodesic::GEODESICSCALE for the geodesic scales \e M12
825  * and \e M21
826  * - \e caps |= Geodesic::AREA for the area \e S12
827  * - \e caps |= Geodesic::DISTANCE_IN permits the length of the
828  * geodesic to be given in terms of \e s12; without this capability the
829  * length can only be specified in terms of arc length.
830  * .
831  * The default value of \e caps is Geodesic::ALL which turns on all the
832  * capabilities.
833  *
834  * If the point is at a pole, the azimuth is defined by keeping the \e lon1
835  * fixed and writing \e lat1 = &plusmn;&(90 &minus; &epsilon;) and taking
836  * the limit &epsilon; &rarr; 0+.
837  **********************************************************************/
838  GeodesicLine Line(real lat1, real lon1, real azi1, unsigned caps = ALL)
839  const throw();
840 
841  ///@}
842 
843  /** \name Inspector functions.
844  **********************************************************************/
845  ///@{
846 
847  /**
848  * @return \e a the equatorial radius of the ellipsoid (meters). This is
849  * the value used in the constructor.
850  **********************************************************************/
851  Math::real MajorRadius() const throw() { return _a; }
852 
853  /**
854  * @return \e f the flattening of the ellipsoid. This is the
855  * value used in the constructor.
856  **********************************************************************/
857  Math::real Flattening() const throw() { return _f; }
858 
859  /// \cond SKIP
860  /**
861  * <b>DEPRECATED</b>
862  * @return \e r the inverse flattening of the ellipsoid.
863  **********************************************************************/
864  Math::real InverseFlattening() const throw() { return 1/_f; }
865  /// \endcond
866 
867  /**
868  * @return total area of ellipsoid in meters<sup>2</sup>. The area of a
869  * polygon encircling a pole can be found by adding
870  * Geodesic::EllipsoidArea()/2 to the sum of \e S12 for each side of the
871  * polygon.
872  **********************************************************************/
873  Math::real EllipsoidArea() const throw()
874  { return 4 * Math::pi<real>() * _c2; }
875  ///@}
876 
877  /**
878  * A global instantiation of Geodesic with the parameters for the WGS84
879  * ellipsoid.
880  **********************************************************************/
881  static const Geodesic WGS84;
882 
883  };
884 
885 } // namespace GeographicLib
886 
887 #endif // GEOGRAPHICLIB_GEODESIC_HPP