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