GeographicLib 2.5
GeodesicExact.hpp
Go to the documentation of this file.
1/**
2 * \file GeodesicExact.hpp
3 * \brief Header for GeographicLib::GeodesicExact class
4 *
5 * Copyright (c) Charles Karney (2012-2024) <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_GEODESICEXACT_HPP)
11#define GEOGRAPHICLIB_GEODESICEXACT_HPP 1
12
15#include <GeographicLib/DST.hpp>
16
17namespace GeographicLib {
18
19 class GeodesicLineExact;
20 // Visual Studio needs this forward declaration...
21 class GEOGRAPHICLIB_EXPORT DST;
22
23 /**
24 * \brief Exact geodesic calculations
25 *
26 * The equations for geodesics on an ellipsoid can be expressed in terms of
27 * incomplete elliptic integrals. The Geodesic class expands these integrals
28 * in a series in the flattening \e f and this provides an accurate solution
29 * for \e f &isin; [-0.01, 0.01]. The GeodesicExact class computes the
30 * ellitpic integrals directly and so provides a solution which is valid for
31 * all \e f. However, in practice, its use should be limited to about
32 * <i>b</i>/\e a &isin; [0.01, 100] or \e f &isin; [&minus;99, 0.99].
33 *
34 * For the WGS84 ellipsoid, these classes are 2--3 times \e slower than the
35 * series solution and 2--3 times \e less \e accurate (because it's less easy
36 * to control round-off errors with the elliptic integral formulation); i.e.,
37 * the error is about 40 nm (40 nanometers) instead of 15 nm. However the
38 * error in the series solution scales as <i>f</i><sup>7</sup> while the
39 * error in the elliptic integral solution depends weakly on \e f. If the
40 * quarter meridian distance is 10000 km and the ratio <i>b</i>/\e a = 1
41 * &minus; \e f is varied then the approximate maximum error (expressed as a
42 * distance) is <pre>
43 * 1 - f error (nm)
44 * 1/128 387
45 * 1/64 345
46 * 1/32 269
47 * 1/16 210
48 * 1/8 115
49 * 1/4 69
50 * 1/2 36
51 * 1 15
52 * 2 25
53 * 4 96
54 * 8 318
55 * 16 985
56 * 32 2352
57 * 64 6008
58 * 128 19024
59 * </pre>
60 *
61 * The area in this classes is computing by finding an accurate approximation
62 * to the area integrand using a discrete sine transform fitting \e N equally
63 * spaced points in &sigma;. \e N chosen to ensure full accuracy for
64 * <i>b</i>/\e a &isin; [0.01, 100] or \e f &isin; [&minus;99, 0.99].
65 *
66 * The algorithms are described in
67 * - C. F. F. Karney,
68 * <a href="https://doi.org/10.1007/s00190-023-01813-2">
69 * Geodesics on an arbitrary ellipsoid of revolution</a>,
70 * J. Geodesy <b>98</b>, 4:1--14 (2024);
71 * DOI: <a href="https://doi.org/10.1007/s00190-023-01813-2">
72 * 10.1007/s00190-023-01813-2</a>.
73 * .
74 * See \ref geodellip for the formulation. See the documentation on the
75 * Geodesic class for additional information on the geodesic problems.
76 *
77 * Example of use:
78 * \include example-GeodesicExact.cpp
79 *
80 * <a href="GeodSolve.1.html">GeodSolve</a> is a command-line utility
81 * providing access to the functionality of GeodesicExact and
82 * GeodesicLineExact (via the -E option).
83 **********************************************************************/
84
86 private:
87 typedef Math::real real;
88 friend class GeodesicLineExact;
89 friend class Geodesic; // Allow Geodesic to call the default constructor
90 // Private default constructor to support Geodesic(a, f, exact)
91 GeodesicExact() {}; // Do nothing; used with exact = false.
92
93 static const unsigned maxit1_ = 20;
94 unsigned maxit2_;
95 real tiny_, tol0_, tol1_, tol2_, tolb_, xthresh_;
96
97 static constexpr unsigned CAP_NONE = 0U;
98 static constexpr unsigned CAP_E = 1U<<0;
99 // Skip 1U<<1 for compatibility with Geodesic (not required)
100 static constexpr unsigned CAP_D = 1U<<2;
101 static constexpr unsigned CAP_H = 1U<<3;
102 static constexpr unsigned CAP_C4 = 1U<<4;
103 static constexpr unsigned CAP_ALL = 0x1FU;
104 static constexpr unsigned CAP_MASK = CAP_ALL;
105 static constexpr unsigned OUT_ALL = 0x7F80U;
106 static constexpr unsigned OUT_MASK = 0xFF80U; // Includes LONG_UNROLL
107
108 static real Astroid(real x, real y);
109
110 real _a, _f, _f1, _e2, _ep2, _n, _b, _c2, _etol2;
111 int _nC4;
112 DST _fft;
113
114 void Lengths(const EllipticFunction& E,
115 real sig12,
116 real ssig1, real csig1, real dn1,
117 real ssig2, real csig2, real dn2,
118 real cbet1, real cbet2, unsigned outmask,
119 real& s12s, real& m12a, real& m0,
120 real& M12, real& M21) const;
121 real InverseStart(EllipticFunction& E,
122 real sbet1, real cbet1, real dn1,
123 real sbet2, real cbet2, real dn2,
124 real lam12, real slam12, real clam12,
125 real& salp1, real& calp1,
126 real& salp2, real& calp2, real& dnm) const;
127 real Lambda12(real sbet1, real cbet1, real dn1,
128 real sbet2, real cbet2, real dn2,
129 real salp1, real calp1, real slam120, real clam120,
130 real& salp2, real& calp2, real& sig12,
131 real& ssig1, real& csig1, real& ssig2, real& csig2,
133 real& domg12, bool diffp, real& dlam12) const;
134 real GenInverse(real lat1, real lon1, real lat2, real lon2,
135 unsigned outmask, real& s12,
136 real& salp1, real& calp1, real& salp2, real& calp2,
137 real& m12, real& M12, real& M21, real& S12) const;
138
139 class I4Integrand {
140 private:
141 real X, tX, tdX, sX, sX1, sXX1, asinhsX, _k2;
142 static real asinhsqrt(real x);
143 static real t(real x);
144 static real td(real x);
145 // static real Dt(real x, real y);
146 real DtX(real y) const;
147 public:
148 I4Integrand(real ep2, real k2);
149 real operator()(real sig) const;
150 };
151
152 public:
153
154 /**
155 * Bit masks for what calculations to do. These masks do double duty.
156 * They signify to the GeodesicLineExact::GeodesicLineExact constructor and
157 * to GeodesicExact::Line what capabilities should be included in the
158 * GeodesicLineExact object. They also specify which results to return in
159 * the general routines GeodesicExact::GenDirect and
160 * GeodesicExact::GenInverse routines. GeodesicLineExact::mask is a
161 * duplication of this enum.
162 **********************************************************************/
163 enum mask {
164 /**
165 * No capabilities, no output.
166 * @hideinitializer
167 **********************************************************************/
168 NONE = 0U,
169 /**
170 * Calculate latitude \e lat2. (It's not necessary to include this as a
171 * capability to GeodesicLineExact because this is included by default.)
172 * @hideinitializer
173 **********************************************************************/
174 LATITUDE = 1U<<7 | CAP_NONE,
175 /**
176 * Calculate longitude \e lon2.
177 * @hideinitializer
178 **********************************************************************/
179 LONGITUDE = 1U<<8 | CAP_H,
180 /**
181 * Calculate azimuths \e azi1 and \e azi2. (It's not necessary to
182 * include this as a capability to GeodesicLineExact because this is
183 * included by default.)
184 * @hideinitializer
185 **********************************************************************/
186 AZIMUTH = 1U<<9 | CAP_NONE,
187 /**
188 * Calculate distance \e s12.
189 * @hideinitializer
190 **********************************************************************/
191 DISTANCE = 1U<<10 | CAP_E,
192 /**
193 * A combination of the common capabilities: GeodesicExact::LATITUDE,
194 * GeodesicExact::LONGITUDE, GeodesicExact::AZIMUTH,
195 * GeodesicExact::DISTANCE.
196 * @hideinitializer
197 **********************************************************************/
198 STANDARD = LATITUDE | LONGITUDE | AZIMUTH | DISTANCE,
199 /**
200 * Allow distance \e s12 to be used as input in the direct geodesic
201 * problem.
202 * @hideinitializer
203 **********************************************************************/
204 DISTANCE_IN = 1U<<11 | CAP_E,
205 /**
206 * Calculate reduced length \e m12.
207 * @hideinitializer
208 **********************************************************************/
209 REDUCEDLENGTH = 1U<<12 | CAP_D,
210 /**
211 * Calculate geodesic scales \e M12 and \e M21.
212 * @hideinitializer
213 **********************************************************************/
214 GEODESICSCALE = 1U<<13 | CAP_D,
215 /**
216 * Calculate area \e S12.
217 * @hideinitializer
218 **********************************************************************/
219 AREA = 1U<<14 | CAP_C4,
220 /**
221 * Unroll \e lon2 in the direct calculation.
222 * @hideinitializer
223 **********************************************************************/
224 LONG_UNROLL = 1U<<15,
225 /**
226 * All capabilities, calculate everything. (GeodesicExact::LONG_UNROLL
227 * is not included in this mask.)
228 * @hideinitializer
229 **********************************************************************/
230 ALL = OUT_ALL| CAP_ALL,
231 };
232
233 /** \name Constructor
234 **********************************************************************/
235 ///@{
236 /**
237 * Constructor for an ellipsoid with
238 *
239 * @param[in] a equatorial radius (meters).
240 * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
241 * Negative \e f gives a prolate ellipsoid.
242 * @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
243 * positive.
244 **********************************************************************/
245 GeodesicExact(real a, real f);
246 ///@}
247
248 /** \name Direct geodesic problem specified in terms of distance.
249 **********************************************************************/
250 ///@{
251 /**
252 * Perform the direct geodesic calculation where the length of the geodesic
253 * is specified in terms of distance.
254 *
255 * @param[in] lat1 latitude of point 1 (degrees).
256 * @param[in] lon1 longitude of point 1 (degrees).
257 * @param[in] azi1 azimuth at point 1 (degrees).
258 * @param[in] s12 distance between point 1 and point 2 (meters); it can be
259 * signed.
260 * @param[out] lat2 latitude of point 2 (degrees).
261 * @param[out] lon2 longitude of point 2 (degrees).
262 * @param[out] azi2 (forward) azimuth at point 2 (degrees).
263 * @param[out] m12 reduced length of geodesic (meters).
264 * @param[out] M12 geodesic scale of point 2 relative to point 1
265 * (dimensionless).
266 * @param[out] M21 geodesic scale of point 1 relative to point 2
267 * (dimensionless).
268 * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
269 * @return \e a12 arc length of between point 1 and point 2 (degrees).
270 *
271 * \e lat1 should be in the range [&minus;90&deg;, 90&deg;]. The values of
272 * \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
273 * 180&deg;].
274 *
275 * If either point is at a pole, the azimuth is defined by keeping the
276 * longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
277 * and taking the limit &epsilon; &rarr; 0+. An arc length greater that
278 * 180&deg; signifies a geodesic which is not a shortest path. (For a
279 * prolate ellipsoid, an additional condition is necessary for a shortest
280 * path: the longitudinal extent must not exceed of 180&deg;.)
281 *
282 * The following functions are overloaded versions of GeodesicExact::Direct
283 * which omit some of the output parameters. Note, however, that the arc
284 * length is always computed and returned as the function value.
285 **********************************************************************/
286 Math::real Direct(real lat1, real lon1, real azi1, real s12,
287 real& lat2, real& lon2, real& azi2,
288 real& m12, real& M12, real& M21, real& S12)
289 const {
290 real t;
291 return GenDirect(lat1, lon1, azi1, false, s12,
292 LATITUDE | LONGITUDE | AZIMUTH |
293 REDUCEDLENGTH | GEODESICSCALE | AREA,
294 lat2, lon2, azi2, t, m12, M12, M21, S12);
295 }
296
297 /**
298 * See the documentation for GeodesicExact::Direct.
299 **********************************************************************/
300 Math::real Direct(real lat1, real lon1, real azi1, real s12,
301 real& lat2, real& lon2)
302 const {
303 real t;
304 return GenDirect(lat1, lon1, azi1, false, s12,
305 LATITUDE | LONGITUDE,
306 lat2, lon2, t, t, t, t, t, t);
307 }
308
309 /**
310 * See the documentation for GeodesicExact::Direct.
311 **********************************************************************/
312 Math::real Direct(real lat1, real lon1, real azi1, real s12,
313 real& lat2, real& lon2, real& azi2)
314 const {
315 real t;
316 return GenDirect(lat1, lon1, azi1, false, s12,
317 LATITUDE | LONGITUDE | AZIMUTH,
318 lat2, lon2, azi2, t, t, t, t, t);
319 }
320
321 /**
322 * See the documentation for GeodesicExact::Direct.
323 **********************************************************************/
324 Math::real Direct(real lat1, real lon1, real azi1, real s12,
325 real& lat2, real& lon2, real& azi2, real& m12)
326 const {
327 real t;
328 return GenDirect(lat1, lon1, azi1, false, s12,
329 LATITUDE | LONGITUDE | AZIMUTH | REDUCEDLENGTH,
330 lat2, lon2, azi2, t, m12, t, t, t);
331 }
332
333 /**
334 * See the documentation for GeodesicExact::Direct.
335 **********************************************************************/
336 Math::real Direct(real lat1, real lon1, real azi1, real s12,
337 real& lat2, real& lon2, real& azi2,
338 real& M12, real& M21)
339 const {
340 real t;
341 return GenDirect(lat1, lon1, azi1, false, s12,
342 LATITUDE | LONGITUDE | AZIMUTH | GEODESICSCALE,
343 lat2, lon2, azi2, t, t, M12, M21, t);
344 }
345
346 /**
347 * See the documentation for GeodesicExact::Direct.
348 **********************************************************************/
349 Math::real Direct(real lat1, real lon1, real azi1, real s12,
350 real& lat2, real& lon2, real& azi2,
351 real& m12, real& M12, real& M21)
352 const {
353 real t;
354 return GenDirect(lat1, lon1, azi1, false, s12,
355 LATITUDE | LONGITUDE | AZIMUTH |
356 REDUCEDLENGTH | GEODESICSCALE,
357 lat2, lon2, azi2, t, m12, M12, M21, t);
358 }
359 ///@}
360
361 /** \name Direct geodesic problem specified in terms of arc length.
362 **********************************************************************/
363 ///@{
364 /**
365 * Perform the direct geodesic calculation where the length of the geodesic
366 * is specified in terms of arc length.
367 *
368 * @param[in] lat1 latitude of point 1 (degrees).
369 * @param[in] lon1 longitude of point 1 (degrees).
370 * @param[in] azi1 azimuth at point 1 (degrees).
371 * @param[in] a12 arc length between point 1 and point 2 (degrees); it can
372 * be signed.
373 * @param[out] lat2 latitude of point 2 (degrees).
374 * @param[out] lon2 longitude of point 2 (degrees).
375 * @param[out] azi2 (forward) azimuth at point 2 (degrees).
376 * @param[out] s12 distance between point 1 and point 2 (meters).
377 * @param[out] m12 reduced length of geodesic (meters).
378 * @param[out] M12 geodesic scale of point 2 relative to point 1
379 * (dimensionless).
380 * @param[out] M21 geodesic scale of point 1 relative to point 2
381 * (dimensionless).
382 * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
383 *
384 * \e lat1 should be in the range [&minus;90&deg;, 90&deg;]. The values of
385 * \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
386 * 180&deg;].
387 *
388 * If either point is at a pole, the azimuth is defined by keeping the
389 * longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
390 * and taking the limit &epsilon; &rarr; 0+. An arc length greater that
391 * 180&deg; signifies a geodesic which is not a shortest path. (For a
392 * prolate ellipsoid, an additional condition is necessary for a shortest
393 * path: the longitudinal extent must not exceed of 180&deg;.)
394 *
395 * The following functions are overloaded versions of GeodesicExact::Direct
396 * which omit some of the output parameters.
397 **********************************************************************/
398 void ArcDirect(real lat1, real lon1, real azi1, real a12,
399 real& lat2, real& lon2, real& azi2, real& s12,
400 real& m12, real& M12, real& M21, real& S12)
401 const {
402 GenDirect(lat1, lon1, azi1, true, a12,
403 LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
404 REDUCEDLENGTH | GEODESICSCALE | AREA,
405 lat2, lon2, azi2, s12, m12, M12, M21, S12);
406 }
407
408 /**
409 * See the documentation for GeodesicExact::ArcDirect.
410 **********************************************************************/
411 void ArcDirect(real lat1, real lon1, real azi1, real a12,
412 real& lat2, real& lon2) const {
413 real t;
414 GenDirect(lat1, lon1, azi1, true, a12,
415 LATITUDE | LONGITUDE,
416 lat2, lon2, t, t, t, t, t, t);
417 }
418
419 /**
420 * See the documentation for GeodesicExact::ArcDirect.
421 **********************************************************************/
422 void ArcDirect(real lat1, real lon1, real azi1, real a12,
423 real& lat2, real& lon2, real& azi2) const {
424 real t;
425 GenDirect(lat1, lon1, azi1, true, a12,
426 LATITUDE | LONGITUDE | AZIMUTH,
427 lat2, lon2, azi2, t, t, t, t, t);
428 }
429
430 /**
431 * See the documentation for GeodesicExact::ArcDirect.
432 **********************************************************************/
433 void ArcDirect(real lat1, real lon1, real azi1, real a12,
434 real& lat2, real& lon2, real& azi2, real& s12)
435 const {
436 real t;
437 GenDirect(lat1, lon1, azi1, true, a12,
438 LATITUDE | LONGITUDE | AZIMUTH | DISTANCE,
439 lat2, lon2, azi2, s12, t, t, t, t);
440 }
441
442 /**
443 * See the documentation for GeodesicExact::ArcDirect.
444 **********************************************************************/
445 void ArcDirect(real lat1, real lon1, real azi1, real a12,
446 real& lat2, real& lon2, real& azi2,
447 real& s12, real& m12) const {
448 real t;
449 GenDirect(lat1, lon1, azi1, true, a12,
450 LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
451 REDUCEDLENGTH,
452 lat2, lon2, azi2, s12, m12, t, t, t);
453 }
454
455 /**
456 * See the documentation for GeodesicExact::ArcDirect.
457 **********************************************************************/
458 void ArcDirect(real lat1, real lon1, real azi1, real a12,
459 real& lat2, real& lon2, real& azi2, real& s12,
460 real& M12, real& M21) const {
461 real t;
462 GenDirect(lat1, lon1, azi1, true, a12,
463 LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
464 GEODESICSCALE,
465 lat2, lon2, azi2, s12, t, M12, M21, t);
466 }
467
468 /**
469 * See the documentation for GeodesicExact::ArcDirect.
470 **********************************************************************/
471 void ArcDirect(real lat1, real lon1, real azi1, real a12,
472 real& lat2, real& lon2, real& azi2, real& s12,
473 real& m12, real& M12, real& M21) const {
474 real t;
475 GenDirect(lat1, lon1, azi1, true, a12,
476 LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
477 REDUCEDLENGTH | GEODESICSCALE,
478 lat2, lon2, azi2, s12, m12, M12, M21, t);
479 }
480 ///@}
481
482 /** \name General version of the direct geodesic solution.
483 **********************************************************************/
484 ///@{
485
486 /**
487 * The general direct geodesic calculation. GeodesicExact::Direct and
488 * GeodesicExact::ArcDirect are defined in terms of this function.
489 *
490 * @param[in] lat1 latitude of point 1 (degrees).
491 * @param[in] lon1 longitude of point 1 (degrees).
492 * @param[in] azi1 azimuth at point 1 (degrees).
493 * @param[in] arcmode boolean flag determining the meaning of the second
494 * parameter.
495 * @param[in] s12_a12 if \e arcmode is false, this is the distance between
496 * point 1 and point 2 (meters); otherwise it is the arc length between
497 * point 1 and point 2 (degrees); it can be signed.
498 * @param[in] outmask a bitor'ed combination of GeodesicExact::mask values
499 * specifying which of the following parameters should be set.
500 * @param[out] lat2 latitude of point 2 (degrees).
501 * @param[out] lon2 longitude of point 2 (degrees).
502 * @param[out] azi2 (forward) azimuth at point 2 (degrees).
503 * @param[out] s12 distance between point 1 and point 2 (meters).
504 * @param[out] m12 reduced length of geodesic (meters).
505 * @param[out] M12 geodesic scale of point 2 relative to point 1
506 * (dimensionless).
507 * @param[out] M21 geodesic scale of point 1 relative to point 2
508 * (dimensionless).
509 * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
510 * @return \e a12 arc length of between point 1 and point 2 (degrees).
511 *
512 * The GeodesicExact::mask values possible for \e outmask are
513 * - \e outmask |= GeodesicExact::LATITUDE for the latitude \e lat2;
514 * - \e outmask |= GeodesicExact::LONGITUDE for the latitude \e lon2;
515 * - \e outmask |= GeodesicExact::AZIMUTH for the latitude \e azi2;
516 * - \e outmask |= GeodesicExact::DISTANCE for the distance \e s12;
517 * - \e outmask |= GeodesicExact::REDUCEDLENGTH for the reduced length \e
518 * m12;
519 * - \e outmask |= GeodesicExact::GEODESICSCALE for the geodesic scales \e
520 * M12 and \e M21;
521 * - \e outmask |= GeodesicExact::AREA for the area \e S12;
522 * - \e outmask |= GeodesicExact::ALL for all of the above;
523 * - \e outmask |= GeodesicExact::LONG_UNROLL to unroll \e lon2 instead of
524 * wrapping it into the range [&minus;180&deg;, 180&deg;].
525 * .
526 * The function value \e a12 is always computed and returned and this
527 * equals \e s12_a12 is \e arcmode is true. If \e outmask includes
528 * GeodesicExact::DISTANCE and \e arcmode is false, then \e s12 = \e
529 * s12_a12. It is not necessary to include GeodesicExact::DISTANCE_IN in
530 * \e outmask; this is automatically included is \e arcmode is false.
531 *
532 * With the GeodesicExact::LONG_UNROLL bit set, the quantity \e lon2
533 * &minus; \e lon1 indicates how many times and in what sense the geodesic
534 * encircles the ellipsoid.
535 **********************************************************************/
536 Math::real GenDirect(real lat1, real lon1, real azi1,
537 bool arcmode, real s12_a12, unsigned outmask,
538 real& lat2, real& lon2, real& azi2,
539 real& s12, real& m12, real& M12, real& M21,
540 real& S12) const;
541 ///@}
542
543 /** \name Inverse geodesic problem.
544 **********************************************************************/
545 ///@{
546 /**
547 * Perform the inverse geodesic calculation.
548 *
549 * @param[in] lat1 latitude of point 1 (degrees).
550 * @param[in] lon1 longitude of point 1 (degrees).
551 * @param[in] lat2 latitude of point 2 (degrees).
552 * @param[in] lon2 longitude of point 2 (degrees).
553 * @param[out] s12 distance between point 1 and point 2 (meters).
554 * @param[out] azi1 azimuth at point 1 (degrees).
555 * @param[out] azi2 (forward) azimuth at point 2 (degrees).
556 * @param[out] m12 reduced length of geodesic (meters).
557 * @param[out] M12 geodesic scale of point 2 relative to point 1
558 * (dimensionless).
559 * @param[out] M21 geodesic scale of point 1 relative to point 2
560 * (dimensionless).
561 * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
562 * @return \e a12 arc length of between point 1 and point 2 (degrees).
563 *
564 * \e lat1 and \e lat2 should be in the range [&minus;90&deg;, 90&deg;].
565 * The values of \e azi1 and \e azi2 returned are in the range
566 * [&minus;180&deg;, 180&deg;].
567 *
568 * If either point is at a pole, the azimuth is defined by keeping the
569 * longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
570 * and taking the limit &epsilon; &rarr; 0+.
571 *
572 * The following functions are overloaded versions of
573 * GeodesicExact::Inverse which omit some of the output parameters. Note,
574 * however, that the arc length is always computed and returned as the
575 * function value.
576 **********************************************************************/
577 Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
578 real& s12, real& azi1, real& azi2, real& m12,
579 real& M12, real& M21, real& S12) const {
580 return GenInverse(lat1, lon1, lat2, lon2,
581 DISTANCE | AZIMUTH |
582 REDUCEDLENGTH | GEODESICSCALE | AREA,
583 s12, azi1, azi2, m12, M12, M21, S12);
584 }
585
586 /**
587 * See the documentation for GeodesicExact::Inverse.
588 **********************************************************************/
589 Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
590 real& s12) const {
591 real t;
592 return GenInverse(lat1, lon1, lat2, lon2,
593 DISTANCE,
594 s12, t, t, t, t, t, t);
595 }
596
597 /**
598 * See the documentation for GeodesicExact::Inverse.
599 **********************************************************************/
600 Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
601 real& azi1, real& azi2) const {
602 real t;
603 return GenInverse(lat1, lon1, lat2, lon2,
604 AZIMUTH,
605 t, azi1, azi2, t, t, t, t);
606 }
607
608 /**
609 * See the documentation for GeodesicExact::Inverse.
610 **********************************************************************/
611 Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
612 real& s12, real& azi1, real& azi2)
613 const {
614 real t;
615 return GenInverse(lat1, lon1, lat2, lon2,
616 DISTANCE | AZIMUTH,
617 s12, azi1, azi2, t, t, t, t);
618 }
619
620 /**
621 * See the documentation for GeodesicExact::Inverse.
622 **********************************************************************/
623 Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
624 real& s12, real& azi1, real& azi2, real& m12)
625 const {
626 real t;
627 return GenInverse(lat1, lon1, lat2, lon2,
628 DISTANCE | AZIMUTH | REDUCEDLENGTH,
629 s12, azi1, azi2, m12, t, t, t);
630 }
631
632 /**
633 * See the documentation for GeodesicExact::Inverse.
634 **********************************************************************/
635 Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
636 real& s12, real& azi1, real& azi2,
637 real& M12, real& M21) const {
638 real t;
639 return GenInverse(lat1, lon1, lat2, lon2,
640 DISTANCE | AZIMUTH | GEODESICSCALE,
641 s12, azi1, azi2, t, M12, M21, t);
642 }
643
644 /**
645 * See the documentation for GeodesicExact::Inverse.
646 **********************************************************************/
647 Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
648 real& s12, real& azi1, real& azi2, real& m12,
649 real& M12, real& M21) const {
650 real t;
651 return GenInverse(lat1, lon1, lat2, lon2,
652 DISTANCE | AZIMUTH |
653 REDUCEDLENGTH | GEODESICSCALE,
654 s12, azi1, azi2, m12, M12, M21, t);
655 }
656 ///@}
657
658 /** \name General version of inverse geodesic solution.
659 **********************************************************************/
660 ///@{
661 /**
662 * The general inverse geodesic calculation. GeodesicExact::Inverse is
663 * defined in terms of this function.
664 *
665 * @param[in] lat1 latitude of point 1 (degrees).
666 * @param[in] lon1 longitude of point 1 (degrees).
667 * @param[in] lat2 latitude of point 2 (degrees).
668 * @param[in] lon2 longitude of point 2 (degrees).
669 * @param[in] outmask a bitor'ed combination of GeodesicExact::mask values
670 * specifying which of the following parameters should be set.
671 * @param[out] s12 distance between point 1 and point 2 (meters).
672 * @param[out] azi1 azimuth at point 1 (degrees).
673 * @param[out] azi2 (forward) azimuth at point 2 (degrees).
674 * @param[out] m12 reduced length of geodesic (meters).
675 * @param[out] M12 geodesic scale of point 2 relative to point 1
676 * (dimensionless).
677 * @param[out] M21 geodesic scale of point 1 relative to point 2
678 * (dimensionless).
679 * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
680 * @return \e a12 arc length of between point 1 and point 2 (degrees).
681 *
682 * The GeodesicExact::mask values possible for \e outmask are
683 * - \e outmask |= GeodesicExact::DISTANCE for the distance \e s12;
684 * - \e outmask |= GeodesicExact::AZIMUTH for the latitude \e azi2;
685 * - \e outmask |= GeodesicExact::REDUCEDLENGTH for the reduced length \e
686 * m12;
687 * - \e outmask |= GeodesicExact::GEODESICSCALE for the geodesic scales \e
688 * M12 and \e M21;
689 * - \e outmask |= GeodesicExact::AREA for the area \e S12;
690 * - \e outmask |= GeodesicExact::ALL for all of the above.
691 * .
692 * The arc length is always computed and returned as the function value.
693 **********************************************************************/
694 Math::real GenInverse(real lat1, real lon1, real lat2, real lon2,
695 unsigned outmask,
696 real& s12, real& azi1, real& azi2,
697 real& m12, real& M12, real& M21, real& S12) const;
698 ///@}
699
700 /** \name Interface to GeodesicLineExact.
701 **********************************************************************/
702 ///@{
703
704 /**
705 * Typedef for the class for computing multiple points on a geodesic.
706 **********************************************************************/
708
709 /**
710 * Set up to compute several points on a single geodesic.
711 *
712 * @param[in] lat1 latitude of point 1 (degrees).
713 * @param[in] lon1 longitude of point 1 (degrees).
714 * @param[in] azi1 azimuth at point 1 (degrees).
715 * @param[in] caps bitor'ed combination of GeodesicExact::mask values
716 * specifying the capabilities the GeodesicLineExact object should
717 * possess, i.e., which quantities can be returned in calls to
718 * GeodesicLineExact::Position.
719 * @return a GeodesicLineExact object.
720 *
721 * \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
722 *
723 * The GeodesicExact::mask values are
724 * - \e caps |= GeodesicExact::LATITUDE for the latitude \e lat2; this is
725 * added automatically;
726 * - \e caps |= GeodesicExact::LONGITUDE for the latitude \e lon2;
727 * - \e caps |= GeodesicExact::AZIMUTH for the azimuth \e azi2; this is
728 * added automatically;
729 * - \e caps |= GeodesicExact::DISTANCE for the distance \e s12;
730 * - \e caps |= GeodesicExact::REDUCEDLENGTH for the reduced length \e m12;
731 * - \e caps |= GeodesicExact::GEODESICSCALE for the geodesic scales \e M12
732 * and \e M21;
733 * - \e caps |= GeodesicExact::AREA for the area \e S12;
734 * - \e caps |= GeodesicExact::DISTANCE_IN permits the length of the
735 * geodesic to be given in terms of \e s12; without this capability the
736 * length can only be specified in terms of arc length;
737 * - \e caps |= GeodesicExact::ALL for all of the above.
738 * .
739 * The default value of \e caps is GeodesicExact::ALL which turns on all
740 * the capabilities.
741 *
742 * If the point is at a pole, the azimuth is defined by keeping \e lon1
743 * fixed, writing \e lat1 = &plusmn;(90 &minus; &epsilon;), and taking the
744 * limit &epsilon; &rarr; 0+.
745 **********************************************************************/
746 GeodesicLineExact Line(real lat1, real lon1, real azi1,
747 unsigned caps = ALL) const;
748
749 /**
750 * Define a GeodesicLineExact in terms of the inverse geodesic problem.
751 *
752 * @param[in] lat1 latitude of point 1 (degrees).
753 * @param[in] lon1 longitude of point 1 (degrees).
754 * @param[in] lat2 latitude of point 2 (degrees).
755 * @param[in] lon2 longitude of point 2 (degrees).
756 * @param[in] caps bitor'ed combination of GeodesicExact::mask values
757 * specifying the capabilities the GeodesicLineExact object should
758 * possess, i.e., which quantities can be returned in calls to
759 * GeodesicLineExact::Position.
760 * @return a GeodesicLineExact object.
761 *
762 * This function sets point 3 of the GeodesicLineExact to correspond to
763 * point 2 of the inverse geodesic problem.
764 *
765 * \e lat1 and \e lat2 should be in the range [&minus;90&deg;, 90&deg;].
766 **********************************************************************/
767 GeodesicLineExact InverseLine(real lat1, real lon1, real lat2, real lon2,
768 unsigned caps = ALL) const;
769
770 /**
771 * Define a GeodesicLineExact in terms of the direct geodesic problem
772 * specified in terms of distance.
773 *
774 * @param[in] lat1 latitude of point 1 (degrees).
775 * @param[in] lon1 longitude of point 1 (degrees).
776 * @param[in] azi1 azimuth at point 1 (degrees).
777 * @param[in] s12 distance between point 1 and point 2 (meters); it can be
778 * negative.
779 * @param[in] caps bitor'ed combination of GeodesicExact::mask values
780 * specifying the capabilities the GeodesicLineExact object should
781 * possess, i.e., which quantities can be returned in calls to
782 * GeodesicLineExact::Position.
783 * @return a GeodesicLineExact object.
784 *
785 * This function sets point 3 of the GeodesicLineExact to correspond to
786 * point 2 of the direct geodesic problem.
787 *
788 * \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
789 **********************************************************************/
790 GeodesicLineExact DirectLine(real lat1, real lon1, real azi1, real s12,
791 unsigned caps = ALL) const;
792
793 /**
794 * Define a GeodesicLineExact in terms of the direct geodesic problem
795 * specified in terms of arc length.
796 *
797 * @param[in] lat1 latitude of point 1 (degrees).
798 * @param[in] lon1 longitude of point 1 (degrees).
799 * @param[in] azi1 azimuth at point 1 (degrees).
800 * @param[in] a12 arc length between point 1 and point 2 (degrees); it can
801 * be negative.
802 * @param[in] caps bitor'ed combination of GeodesicExact::mask values
803 * specifying the capabilities the GeodesicLineExact object should
804 * possess, i.e., which quantities can be returned in calls to
805 * GeodesicLineExact::Position.
806 * @return a GeodesicLineExact object.
807 *
808 * This function sets point 3 of the GeodesicLineExact to correspond to
809 * point 2 of the direct geodesic problem.
810 *
811 * \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
812 **********************************************************************/
813 GeodesicLineExact ArcDirectLine(real lat1, real lon1, real azi1, real a12,
814 unsigned caps = ALL) const;
815
816 /**
817 * Define a GeodesicLineExact in terms of the direct geodesic problem
818 * specified in terms of either distance or arc length.
819 *
820 * @param[in] lat1 latitude of point 1 (degrees).
821 * @param[in] lon1 longitude of point 1 (degrees).
822 * @param[in] azi1 azimuth at point 1 (degrees).
823 * @param[in] arcmode boolean flag determining the meaning of the \e
824 * s12_a12.
825 * @param[in] s12_a12 if \e arcmode is false, this is the distance between
826 * point 1 and point 2 (meters); otherwise it is the arc length between
827 * point 1 and point 2 (degrees); it can be negative.
828 * @param[in] caps bitor'ed combination of GeodesicExact::mask values
829 * specifying the capabilities the GeodesicLineExact object should
830 * possess, i.e., which quantities can be returned in calls to
831 * GeodesicLineExact::Position.
832 * @return a GeodesicLineExact object.
833 *
834 * This function sets point 3 of the GeodesicLineExact to correspond to
835 * point 2 of the direct geodesic problem.
836 *
837 * \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
838 **********************************************************************/
839 GeodesicLineExact GenDirectLine(real lat1, real lon1, real azi1,
840 bool arcmode, real s12_a12,
841 unsigned caps = ALL) const;
842 ///@}
843
844 /** \name Inspector functions.
845 **********************************************************************/
846 ///@{
847
848 /**
849 * @return \e a the equatorial radius of the ellipsoid (meters). This is
850 * the value used in the constructor.
851 **********************************************************************/
852 Math::real EquatorialRadius() const { return _a; }
853
854 /**
855 * @return \e f the flattening of the ellipsoid. This is the
856 * value used in the constructor.
857 **********************************************************************/
858 Math::real Flattening() const { return _f; }
859
860 /**
861 * @return total area of ellipsoid in meters<sup>2</sup>. The area of a
862 * polygon encircling a pole can be found by adding
863 * GeodesicExact::EllipsoidArea()/2 to the sum of \e S12 for each side of
864 * the polygon.
865 **********************************************************************/
867 { return 4 * Math::pi() * _c2; }
868 ///@}
869
870 /**
871 * A global instantiation of GeodesicExact with the parameters for the
872 * WGS84 ellipsoid.
873 **********************************************************************/
874 static const GeodesicExact& WGS84();
875
876 };
877
878} // namespace GeographicLib
879
880#endif // GEOGRAPHICLIB_GEODESICEXACT_HPP
Header for GeographicLib::Constants class.
#define GEOGRAPHICLIB_EXPORT
Definition Constants.hpp:67
Header for GeographicLib::DST class.
Header for GeographicLib::EllipticFunction class.
GeographicLib::Math::real real
Definition GeodSolve.cpp:28
Discrete sine transforms.
Definition DST.hpp:63
Elliptic integrals and functions.
Exact geodesic calculations.
Math::real Direct(real lat1, real lon1, real azi1, real s12, real &lat2, real &lon2, real &azi2, real &m12, real &M12, real &M21) const
void ArcDirect(real lat1, real lon1, real azi1, real a12, real &lat2, real &lon2, real &azi2, real &s12, real &M12, real &M21) const
Math::real Direct(real lat1, real lon1, real azi1, real s12, real &lat2, real &lon2, real &azi2, real &m12) const
Math::real EllipsoidArea() const
Math::real Inverse(real lat1, real lon1, real lat2, real lon2, real &s12, real &azi1, real &azi2, real &m12, real &M12, real &M21, real &S12) const
void ArcDirect(real lat1, real lon1, real azi1, real a12, real &lat2, real &lon2, real &azi2, real &s12) const
void ArcDirect(real lat1, real lon1, real azi1, real a12, real &lat2, real &lon2, real &azi2, real &s12, real &m12, real &M12, real &M21) const
void ArcDirect(real lat1, real lon1, real azi1, real a12, real &lat2, real &lon2, real &azi2, real &s12, real &m12, real &M12, real &M21, real &S12) const
Math::real Inverse(real lat1, real lon1, real lat2, real lon2, real &s12) const
Math::real Inverse(real lat1, real lon1, real lat2, real lon2, real &s12, real &azi1, real &azi2, real &m12) const
Math::real Inverse(real lat1, real lon1, real lat2, real lon2, real &s12, real &azi1, real &azi2, real &m12, real &M12, real &M21) const
Math::real Direct(real lat1, real lon1, real azi1, real s12, real &lat2, real &lon2, real &azi2, real &M12, real &M21) const
Math::real Direct(real lat1, real lon1, real azi1, real s12, real &lat2, real &lon2, real &azi2) const
Math::real Inverse(real lat1, real lon1, real lat2, real lon2, real &azi1, real &azi2) const
void ArcDirect(real lat1, real lon1, real azi1, real a12, real &lat2, real &lon2, real &azi2) const
void ArcDirect(real lat1, real lon1, real azi1, real a12, real &lat2, real &lon2) const
Math::real Direct(real lat1, real lon1, real azi1, real s12, real &lat2, real &lon2, real &azi2, real &m12, real &M12, real &M21, real &S12) const
Math::real EquatorialRadius() const
Math::real Direct(real lat1, real lon1, real azi1, real s12, real &lat2, real &lon2) const
void ArcDirect(real lat1, real lon1, real azi1, real a12, real &lat2, real &lon2, real &azi2, real &s12, real &m12) const
Math::real Inverse(real lat1, real lon1, real lat2, real lon2, real &s12, real &azi1, real &azi2) const
Math::real Inverse(real lat1, real lon1, real lat2, real lon2, real &s12, real &azi1, real &azi2, real &M12, real &M21) const
Geodesic calculations
Definition Geodesic.hpp:175
Namespace for GeographicLib.