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