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