From 09e29afe7bd5ab6eca68ae39dd379de97b9749eb Mon Sep 17 00:00:00 2001 From: Sven Czarnian Date: Mon, 22 Nov 2021 16:16:36 +0100 Subject: [PATCH] add GeographicLib --- cmake/3rdPartyTargets.cmake | 12 + .../include/GeographicLib/Accumulator.hpp | 198 ++++ .../include/GeographicLib/AlbersEqualArea.hpp | 321 ++++++ .../GeographicLib/AzimuthalEquidistant.hpp | 145 +++ .../include/GeographicLib/CassiniSoldner.hpp | 210 ++++ .../include/GeographicLib/CircularEngine.hpp | 195 ++++ external/include/GeographicLib/Config.h | 25 + external/include/GeographicLib/Constants.hpp | 329 ++++++ external/include/GeographicLib/DMS.hpp | 405 ++++++++ external/include/GeographicLib/Ellipsoid.hpp | 542 ++++++++++ .../GeographicLib/EllipticFunction.hpp | 702 +++++++++++++ external/include/GeographicLib/GARS.hpp | 143 +++ external/include/GeographicLib/GeoCoords.hpp | 553 ++++++++++ external/include/GeographicLib/Geocentric.hpp | 274 +++++ external/include/GeographicLib/Geodesic.hpp | 977 ++++++++++++++++++ .../include/GeographicLib/GeodesicExact.hpp | 869 ++++++++++++++++ .../include/GeographicLib/GeodesicLine.hpp | 708 +++++++++++++ .../GeographicLib/GeodesicLineExact.hpp | 673 ++++++++++++ external/include/GeographicLib/Geohash.hpp | 180 ++++ external/include/GeographicLib/Geoid.hpp | 478 +++++++++ external/include/GeographicLib/Georef.hpp | 161 +++ external/include/GeographicLib/Gnomonic.hpp | 221 ++++ .../include/GeographicLib/GravityCircle.hpp | 287 +++++ .../include/GeographicLib/GravityModel.hpp | 549 ++++++++++ .../GeographicLib/LambertConformalConic.hpp | 330 ++++++ .../include/GeographicLib/LocalCartesian.hpp | 244 +++++ external/include/GeographicLib/MGRS.hpp | 361 +++++++ .../include/GeographicLib/MagneticCircle.hpp | 204 ++++ .../include/GeographicLib/MagneticModel.hpp | 406 ++++++++ external/include/GeographicLib/Math.hpp | 684 ++++++++++++ .../include/GeographicLib/NearestNeighbor.hpp | 837 +++++++++++++++ .../include/GeographicLib/NormalGravity.hpp | 400 +++++++ external/include/GeographicLib/OSGB.hpp | 255 +++++ .../GeographicLib/PolarStereographic.hpp | 160 +++ .../include/GeographicLib/PolygonArea.hpp | 325 ++++++ external/include/GeographicLib/Rhumb.hpp | 621 +++++++++++ .../include/GeographicLib/SphericalEngine.hpp | 384 +++++++ .../GeographicLib/SphericalHarmonic.hpp | 356 +++++++ .../GeographicLib/SphericalHarmonic1.hpp | 283 +++++ .../GeographicLib/SphericalHarmonic2.hpp | 320 ++++++ .../GeographicLib/TransverseMercator.hpp | 206 ++++ .../GeographicLib/TransverseMercatorExact.hpp | 264 +++++ external/include/GeographicLib/UTMUPS.hpp | 428 ++++++++ external/include/GeographicLib/Utility.hpp | 733 +++++++++++++ external/lib/Geographic.lib | Bin 0 -> 6131358 bytes external/lib/Geographic_d.lib | Bin 0 -> 8765328 bytes 46 files changed, 16958 insertions(+) create mode 100644 external/include/GeographicLib/Accumulator.hpp create mode 100644 external/include/GeographicLib/AlbersEqualArea.hpp create mode 100644 external/include/GeographicLib/AzimuthalEquidistant.hpp create mode 100644 external/include/GeographicLib/CassiniSoldner.hpp create mode 100644 external/include/GeographicLib/CircularEngine.hpp create mode 100644 external/include/GeographicLib/Config.h create mode 100644 external/include/GeographicLib/Constants.hpp create mode 100644 external/include/GeographicLib/DMS.hpp create mode 100644 external/include/GeographicLib/Ellipsoid.hpp create mode 100644 external/include/GeographicLib/EllipticFunction.hpp create mode 100644 external/include/GeographicLib/GARS.hpp create mode 100644 external/include/GeographicLib/GeoCoords.hpp create mode 100644 external/include/GeographicLib/Geocentric.hpp create mode 100644 external/include/GeographicLib/Geodesic.hpp create mode 100644 external/include/GeographicLib/GeodesicExact.hpp create mode 100644 external/include/GeographicLib/GeodesicLine.hpp create mode 100644 external/include/GeographicLib/GeodesicLineExact.hpp create mode 100644 external/include/GeographicLib/Geohash.hpp create mode 100644 external/include/GeographicLib/Geoid.hpp create mode 100644 external/include/GeographicLib/Georef.hpp create mode 100644 external/include/GeographicLib/Gnomonic.hpp create mode 100644 external/include/GeographicLib/GravityCircle.hpp create mode 100644 external/include/GeographicLib/GravityModel.hpp create mode 100644 external/include/GeographicLib/LambertConformalConic.hpp create mode 100644 external/include/GeographicLib/LocalCartesian.hpp create mode 100644 external/include/GeographicLib/MGRS.hpp create mode 100644 external/include/GeographicLib/MagneticCircle.hpp create mode 100644 external/include/GeographicLib/MagneticModel.hpp create mode 100644 external/include/GeographicLib/Math.hpp create mode 100644 external/include/GeographicLib/NearestNeighbor.hpp create mode 100644 external/include/GeographicLib/NormalGravity.hpp create mode 100644 external/include/GeographicLib/OSGB.hpp create mode 100644 external/include/GeographicLib/PolarStereographic.hpp create mode 100644 external/include/GeographicLib/PolygonArea.hpp create mode 100644 external/include/GeographicLib/Rhumb.hpp create mode 100644 external/include/GeographicLib/SphericalEngine.hpp create mode 100644 external/include/GeographicLib/SphericalHarmonic.hpp create mode 100644 external/include/GeographicLib/SphericalHarmonic1.hpp create mode 100644 external/include/GeographicLib/SphericalHarmonic2.hpp create mode 100644 external/include/GeographicLib/TransverseMercator.hpp create mode 100644 external/include/GeographicLib/TransverseMercatorExact.hpp create mode 100644 external/include/GeographicLib/UTMUPS.hpp create mode 100644 external/include/GeographicLib/Utility.hpp create mode 100644 external/lib/Geographic.lib create mode 100644 external/lib/Geographic_d.lib diff --git a/cmake/3rdPartyTargets.cmake b/cmake/3rdPartyTargets.cmake index 37ebfa8..92bbb5d 100644 --- a/cmake/3rdPartyTargets.cmake +++ b/cmake/3rdPartyTargets.cmake @@ -21,6 +21,18 @@ ELSE () MESSAGE(FATAL_ERROR "Unsupported compiler") ENDIF () +# define the import target of GeographicLib +ADD_LIBRARY(GeographicLib STATIC IMPORTED) +IF (MSVC) + SET_TARGET_PROPERTIES(GeographicLib PROPERTIES + IMPORTED_LOCATION_DEBUG "${CMAKE_SOURCE_DIR}/external/lib/Geographic_d.lib" + IMPORTED_LOCATION_RELEASE "${CMAKE_SOURCE_DIR}/external/lib/Geographic.lib" + ) + TARGET_INCLUDE_DIRECTORIES(GeographicLib INTERFACE "${CMAKE_SOURCE_DIR}/external/include") +ELSE () + MESSAGE(FATAL_ERROR "Unsupported compiler") +ENDIF () + # define the import target of libsodium ADD_LIBRARY(libsodium STATIC IMPORTED) IF (MSVC) diff --git a/external/include/GeographicLib/Accumulator.hpp b/external/include/GeographicLib/Accumulator.hpp new file mode 100644 index 0000000..577b556 --- /dev/null +++ b/external/include/GeographicLib/Accumulator.hpp @@ -0,0 +1,198 @@ +/** + * \file Accumulator.hpp + * \brief Header for GeographicLib::Accumulator class + * + * Copyright (c) Charles Karney (2010-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_ACCUMULATOR_HPP) +#define GEOGRAPHICLIB_ACCUMULATOR_HPP 1 + +#include + +namespace GeographicLib { + + /** + * \brief An accumulator for sums + * + * This allows many numbers of floating point type \e T to be added together + * with twice the normal precision. Thus if \e T is double, the effective + * precision of the sum is 106 bits or about 32 decimal places. + * + * The implementation follows J. R. Shewchuk, + * Adaptive Precision + * Floating-Point Arithmetic and Fast Robust Geometric Predicates, + * Discrete & Computational Geometry 18(3) 305--363 (1997). + * + * Approximate timings (summing a vector) + * - double: 2ns + * - Accumulator: 23ns + * + * In the documentation of the member functions, \e sum stands for the value + * currently held in the accumulator. + * + * Example of use: + * \include example-Accumulator.cpp + **********************************************************************/ + template + class GEOGRAPHICLIB_EXPORT Accumulator { + private: + // _s + _t accumulators for the sum. + T _s, _t; + // Same as Math::sum, but requires abs(u) >= abs(v). This isn't currently + // used. + static T fastsum(T u, T v, T& t) { + GEOGRAPHICLIB_VOLATILE T s = u + v; + GEOGRAPHICLIB_VOLATILE T vp = s - u; + t = v - vp; + return s; + } + void Add(T y) { + // Here's Shewchuk's solution... + T u; // hold exact sum as [s, t, u] + // Accumulate starting at least significant end + y = Math::sum(y, _t, u); + _s = Math::sum(y, _s, _t); + // Start is _s, _t decreasing and non-adjacent. Sum is now (s + t + u) + // exactly with s, t, u non-adjacent and in decreasing order (except for + // possible zeros). The following code tries to normalize the result. + // Ideally, we want _s = round(s+t+u) and _u = round(s+t+u - _s). The + // following does an approximate job (and maintains the decreasing + // non-adjacent property). Here are two "failures" using 3-bit floats: + // + // Case 1: _s is not equal to round(s+t+u) -- off by 1 ulp + // [12, -1] - 8 -> [4, 0, -1] -> [4, -1] = 3 should be [3, 0] = 3 + // + // Case 2: _s+_t is not as close to s+t+u as it shold be + // [64, 5] + 4 -> [64, 8, 1] -> [64, 8] = 72 (off by 1) + // should be [80, -7] = 73 (exact) + // + // "Fixing" these problems is probably not worth the expense. The + // representation inevitably leads to small errors in the accumulated + // values. The additional errors illustrated here amount to 1 ulp of the + // less significant word during each addition to the Accumulator and an + // additional possible error of 1 ulp in the reported sum. + // + // Incidentally, the "ideal" representation described above is not + // canonical, because _s = round(_s + _t) may not be true. For example, + // with 3-bit floats: + // + // [128, 16] + 1 -> [160, -16] -- 160 = round(145). + // But [160, 0] - 16 -> [128, 16] -- 128 = round(144). + // + if (_s == 0) // This implies t == 0, + _s = u; // so result is u + else + _t += u; // otherwise just accumulate u to t. + } + T Sum(T y) const { + Accumulator a(*this); + a.Add(y); + return a._s; + } + public: + /** + * Construct from a \e T. This is not declared explicit, so that you can + * write Accumulator a = 5;. + * + * @param[in] y set \e sum = \e y. + **********************************************************************/ + Accumulator(T y = T(0)) : _s(y), _t(0) { + static_assert(!std::numeric_limits::is_integer, + "Accumulator type is not floating point"); + } + /** + * Set the accumulator to a number. + * + * @param[in] y set \e sum = \e y. + **********************************************************************/ + Accumulator& operator=(T y) { _s = y; _t = 0; return *this; } + /** + * Return the value held in the accumulator. + * + * @return \e sum. + **********************************************************************/ + T operator()() const { return _s; } + /** + * Return the result of adding a number to \e sum (but don't change \e + * sum). + * + * @param[in] y the number to be added to the sum. + * @return \e sum + \e y. + **********************************************************************/ + T operator()(T y) const { return Sum(y); } + /** + * Add a number to the accumulator. + * + * @param[in] y set \e sum += \e y. + **********************************************************************/ + Accumulator& operator+=(T y) { Add(y); return *this; } + /** + * Subtract a number from the accumulator. + * + * @param[in] y set \e sum -= \e y. + **********************************************************************/ + Accumulator& operator-=(T y) { Add(-y); return *this; } + /** + * Multiply accumulator by an integer. To avoid loss of accuracy, use only + * integers such that \e n × \e T is exactly representable as a \e T + * (i.e., ± powers of two). Use \e n = −1 to negate \e sum. + * + * @param[in] n set \e sum *= \e n. + **********************************************************************/ + Accumulator& operator*=(int n) { _s *= n; _t *= n; return *this; } + /** + * Multiply accumulator by a number. The fma (fused multiply and add) + * instruction is used (if available) in order to maintain accuracy. + * + * @param[in] y set \e sum *= \e y. + **********************************************************************/ + Accumulator& operator*=(T y) { + using std::fma; + T d = _s; _s *= y; + d = fma(y, d, -_s); // the error in the first multiplication + _t = fma(y, _t, d); // add error to the second term + return *this; + } + /** + * Reduce accumulator to the range [-y/2, y/2]. + * + * @param[in] y the modulus. + **********************************************************************/ + Accumulator& remainder(T y) { + using std::remainder; + _s = remainder(_s, y); + Add(0); // This renormalizes the result. + return *this; + } + /** + * Test equality of an Accumulator with a number. + **********************************************************************/ + bool operator==(T y) const { return _s == y; } + /** + * Test inequality of an Accumulator with a number. + **********************************************************************/ + bool operator!=(T y) const { return _s != y; } + /** + * Less operator on an Accumulator and a number. + **********************************************************************/ + bool operator<(T y) const { return _s < y; } + /** + * Less or equal operator on an Accumulator and a number. + **********************************************************************/ + bool operator<=(T y) const { return _s <= y; } + /** + * Greater operator on an Accumulator and a number. + **********************************************************************/ + bool operator>(T y) const { return _s > y; } + /** + * Greater or equal operator on an Accumulator and a number. + **********************************************************************/ + bool operator>=(T y) const { return _s >= y; } + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_ACCUMULATOR_HPP diff --git a/external/include/GeographicLib/AlbersEqualArea.hpp b/external/include/GeographicLib/AlbersEqualArea.hpp new file mode 100644 index 0000000..a759d01 --- /dev/null +++ b/external/include/GeographicLib/AlbersEqualArea.hpp @@ -0,0 +1,321 @@ +/** + * \file AlbersEqualArea.hpp + * \brief Header for GeographicLib::AlbersEqualArea class + * + * Copyright (c) Charles Karney (2010-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_ALBERSEQUALAREA_HPP) +#define GEOGRAPHICLIB_ALBERSEQUALAREA_HPP 1 + +#include + +namespace GeographicLib { + + /** + * \brief Albers equal area conic projection + * + * Implementation taken from the report, + * - J. P. Snyder, + * Map Projections: A + * Working Manual, USGS Professional Paper 1395 (1987), + * pp. 101--102. + * + * This is a implementation of the equations in Snyder except that divided + * differences will be [have been] used to transform the expressions into + * ones which may be evaluated accurately. [In this implementation, the + * projection correctly becomes the cylindrical equal area or the azimuthal + * equal area projection when the standard latitude is the equator or a + * pole.] + * + * The ellipsoid parameters, the standard parallels, and the scale on the + * standard parallels are set in the constructor. Internally, the case with + * two standard parallels is converted into a single standard parallel, the + * latitude of minimum azimuthal scale, with an azimuthal scale specified on + * this parallel. This latitude is also used as the latitude of origin which + * is returned by AlbersEqualArea::OriginLatitude. The azimuthal scale on + * the latitude of origin is given by AlbersEqualArea::CentralScale. The + * case with two standard parallels at opposite poles is singular and is + * disallowed. The central meridian (which is a trivial shift of the + * longitude) is specified as the \e lon0 argument of the + * AlbersEqualArea::Forward and AlbersEqualArea::Reverse functions. + * AlbersEqualArea::Forward and AlbersEqualArea::Reverse also return the + * meridian convergence, γ, and azimuthal scale, \e k. A small square + * aligned with the cardinal directions is projected to a rectangle with + * dimensions \e k (in the E-W direction) and 1/\e k (in the N-S direction). + * The E-W sides of the rectangle are oriented γ degrees + * counter-clockwise from the \e x axis. There is no provision in this class + * for specifying a false easting or false northing or a different latitude + * of origin. + * + * Example of use: + * \include example-AlbersEqualArea.cpp + * + * ConicProj is a command-line utility + * providing access to the functionality of LambertConformalConic and + * AlbersEqualArea. + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT AlbersEqualArea { + private: + typedef Math::real real; + real eps_, epsx_, epsx2_, tol_, tol0_; + real _a, _f, _fm, _e2, _e, _e2m, _qZ, _qx; + real _sign, _lat0, _k0; + real _n0, _m02, _nrho0, _k2, _txi0, _scxi0, _sxi0; + static const int numit_ = 5; // Newton iterations in Reverse + static const int numit0_ = 20; // Newton iterations in Init + static real hyp(real x) { + using std::hypot; + return hypot(real(1), x); + } + // atanh( e * x)/ e if f > 0 + // atan (sqrt(-e2) * x)/sqrt(-e2) if f < 0 + // x if f = 0 + real atanhee(real x) const { + using std::atan; using std::abs; using std::atanh; + return _f > 0 ? atanh(_e * x)/_e : (_f < 0 ? (atan(_e * x)/_e) : x); + } + // return atanh(sqrt(x))/sqrt(x) - 1, accurate for small x + static real atanhxm1(real x); + + // Divided differences + // Definition: Df(x,y) = (f(x)-f(y))/(x-y) + // See: + // W. M. Kahan and R. J. Fateman, + // Symbolic computation of divided differences, + // SIGSAM Bull. 33(3), 7-28 (1999) + // https://doi.org/10.1145/334714.334716 + // http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf + // + // General rules + // h(x) = f(g(x)): Dh(x,y) = Df(g(x),g(y))*Dg(x,y) + // h(x) = f(x)*g(x): + // Dh(x,y) = Df(x,y)*g(x) + Dg(x,y)*f(y) + // = Df(x,y)*g(y) + Dg(x,y)*f(x) + // = Df(x,y)*(g(x)+g(y))/2 + Dg(x,y)*(f(x)+f(y))/2 + // + // sn(x) = x/sqrt(1+x^2): Dsn(x,y) = (x+y)/((sn(x)+sn(y))*(1+x^2)*(1+y^2)) + static real Dsn(real x, real y, real sx, real sy) { + // sx = x/hyp(x) + real t = x * y; + return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) : + (x - y != 0 ? (sx - sy) / (x - y) : 1); + } + // Datanhee(x,y) = (atanee(x)-atanee(y))/(x-y) + // = atanhee((x-y)/(1-e^2*x*y))/(x-y) + real Datanhee(real x, real y) const { + real t = x - y, d = 1 - _e2 * x * y; + return t == 0 ? 1 / d : + (x*y < 0 ? atanhee(x) - atanhee(y) : atanhee(t / d)) / t; + } + // DDatanhee(x,y) = (Datanhee(1,y) - Datanhee(1,x))/(y-x) + real DDatanhee(real x, real y) const; + real DDatanhee0(real x, real y) const; + real DDatanhee1(real x, real y) const; + real DDatanhee2(real x, real y) const; + void Init(real sphi1, real cphi1, real sphi2, real cphi2, real k1); + real txif(real tphi) const; + real tphif(real txi) const; + + friend class Ellipsoid; // For access to txif, tphif, etc. + public: + + /** + * Constructor with a single standard parallel. + * + * @param[in] a equatorial radius of ellipsoid (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @param[in] stdlat standard parallel (degrees), the circle of tangency. + * @param[in] k0 azimuthal scale on the standard parallel. + * @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k0 is + * not positive. + * @exception GeographicErr if \e stdlat is not in [−90°, + * 90°]. + **********************************************************************/ + AlbersEqualArea(real a, real f, real stdlat, real k0); + + /** + * Constructor with two standard parallels. + * + * @param[in] a equatorial radius of ellipsoid (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @param[in] stdlat1 first standard parallel (degrees). + * @param[in] stdlat2 second standard parallel (degrees). + * @param[in] k1 azimuthal scale on the standard parallels. + * @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k1 is + * not positive. + * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in + * [−90°, 90°], or if \e stdlat1 and \e stdlat2 are + * opposite poles. + **********************************************************************/ + AlbersEqualArea(real a, real f, real stdlat1, real stdlat2, real k1); + + /** + * Constructor with two standard parallels specified by sines and cosines. + * + * @param[in] a equatorial radius of ellipsoid (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @param[in] sinlat1 sine of first standard parallel. + * @param[in] coslat1 cosine of first standard parallel. + * @param[in] sinlat2 sine of second standard parallel. + * @param[in] coslat2 cosine of second standard parallel. + * @param[in] k1 azimuthal scale on the standard parallels. + * @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k1 is + * not positive. + * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in + * [−90°, 90°], or if \e stdlat1 and \e stdlat2 are + * opposite poles. + * + * This allows parallels close to the poles to be specified accurately. + * This routine computes the latitude of origin and the azimuthal scale at + * this latitude. If \e dlat = abs(\e lat2 − \e lat1) ≤ 160°, + * then the error in the latitude of origin is less than 4.5 × + * 10−14d;. + **********************************************************************/ + AlbersEqualArea(real a, real f, + real sinlat1, real coslat1, + real sinlat2, real coslat2, + real k1); + + /** + * Set the azimuthal scale for the projection. + * + * @param[in] lat (degrees). + * @param[in] k azimuthal scale at latitude \e lat (default 1). + * @exception GeographicErr \e k is not positive. + * @exception GeographicErr if \e lat is not in (−90°, + * 90°). + * + * This allows a "latitude of conformality" to be specified. + **********************************************************************/ + void SetScale(real lat, real k = real(1)); + + /** + * Forward projection, from geographic to Lambert conformal conic. + * + * @param[in] lon0 central meridian longitude (degrees). + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k azimuthal scale of projection at point; the radial + * scale is the 1/\e k. + * + * The latitude origin is given by AlbersEqualArea::LatitudeOrigin(). No + * false easting or northing is added and \e lat should be in the range + * [−90°, 90°]. The values of \e x and \e y returned for + * points which project to infinity (i.e., one or both of the poles) will + * be large but finite. + **********************************************************************/ + void Forward(real lon0, real lat, real lon, + real& x, real& y, real& gamma, real& k) const; + + /** + * Reverse projection, from Lambert conformal conic to geographic. + * + * @param[in] lon0 central meridian longitude (degrees). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k azimuthal scale of projection at point; the radial + * scale is the 1/\e k. + * + * The latitude origin is given by AlbersEqualArea::LatitudeOrigin(). No + * false easting or northing is added. The value of \e lon returned is in + * the range [−180°, 180°]. The value of \e lat returned is + * in the range [−90°, 90°]. If the input point is outside + * the legal projected space the nearest pole is returned. + **********************************************************************/ + void Reverse(real lon0, real x, real y, + real& lat, real& lon, real& gamma, real& k) const; + + /** + * AlbersEqualArea::Forward without returning the convergence and + * scale. + **********************************************************************/ + void Forward(real lon0, real lat, real lon, + real& x, real& y) const { + real gamma, k; + Forward(lon0, lat, lon, x, y, gamma, k); + } + + /** + * AlbersEqualArea::Reverse without returning the convergence and + * scale. + **********************************************************************/ + void Reverse(real lon0, real x, real y, + real& lat, real& lon) const { + real gamma, k; + Reverse(lon0, x, y, lat, lon, gamma, k); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _a; } + + /** + * @return \e f the flattening of the ellipsoid. This is the value used in + * the constructor. + **********************************************************************/ + Math::real Flattening() const { return _f; } + + /** + * @return latitude of the origin for the projection (degrees). + * + * This is the latitude of minimum azimuthal scale and equals the \e stdlat + * in the 1-parallel constructor and lies between \e stdlat1 and \e stdlat2 + * in the 2-parallel constructors. + **********************************************************************/ + Math::real OriginLatitude() const { return _lat0; } + + /** + * @return central scale for the projection. This is the azimuthal scale + * on the latitude of origin. + **********************************************************************/ + Math::real CentralScale() const { return _k0; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e + * stdlat = 0, and \e k0 = 1. This degenerates to the cylindrical equal + * area projection. + **********************************************************************/ + static const AlbersEqualArea& CylindricalEqualArea(); + + /** + * A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e + * stdlat = 90°, and \e k0 = 1. This degenerates to the + * Lambert azimuthal equal area projection. + **********************************************************************/ + static const AlbersEqualArea& AzimuthalEqualAreaNorth(); + + /** + * A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e + * stdlat = −90°, and \e k0 = 1. This degenerates to the + * Lambert azimuthal equal area projection. + **********************************************************************/ + static const AlbersEqualArea& AzimuthalEqualAreaSouth(); + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_ALBERSEQUALAREA_HPP diff --git a/external/include/GeographicLib/AzimuthalEquidistant.hpp b/external/include/GeographicLib/AzimuthalEquidistant.hpp new file mode 100644 index 0000000..05a6c41 --- /dev/null +++ b/external/include/GeographicLib/AzimuthalEquidistant.hpp @@ -0,0 +1,145 @@ +/** + * \file AzimuthalEquidistant.hpp + * \brief Header for GeographicLib::AzimuthalEquidistant class + * + * Copyright (c) Charles Karney (2009-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_AZIMUTHALEQUIDISTANT_HPP) +#define GEOGRAPHICLIB_AZIMUTHALEQUIDISTANT_HPP 1 + +#include +#include + +namespace GeographicLib { + + /** + * \brief Azimuthal equidistant projection + * + * Azimuthal equidistant projection centered at an arbitrary position on the + * ellipsoid. For a point in projected space (\e x, \e y), the geodesic + * distance from the center position is hypot(\e x, \e y) and the azimuth of + * the geodesic from the center point is atan2(\e x, \e y). The Forward and + * Reverse methods also return the azimuth \e azi of the geodesic at (\e x, + * \e y) and reciprocal scale \e rk in the azimuthal direction which, + * together with the basic properties of the projection, serve to specify + * completely the local affine transformation between geographic and + * projected coordinates. + * + * The conversions all take place using a Geodesic object (by default + * Geodesic::WGS84()). For more information on geodesics see \ref geodesic. + * + * Example of use: + * \include example-AzimuthalEquidistant.cpp + * + * GeodesicProj is a command-line utility + * providing access to the functionality of AzimuthalEquidistant, Gnomonic, + * and CassiniSoldner. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT AzimuthalEquidistant { + private: + typedef Math::real real; + real eps_; + Geodesic _earth; + public: + + /** + * Constructor for AzimuthalEquidistant. + * + * @param[in] earth the Geodesic object to use for geodesic calculations. + * By default this uses the WGS84 ellipsoid. + **********************************************************************/ + explicit AzimuthalEquidistant(const Geodesic& earth = Geodesic::WGS84()); + + /** + * Forward projection, from geographic to azimuthal equidistant. + * + * @param[in] lat0 latitude of center point of projection (degrees). + * @param[in] lon0 longitude of center point of projection (degrees). + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] azi azimuth of geodesic at point (degrees). + * @param[out] rk reciprocal of azimuthal scale at point. + * + * \e lat0 and \e lat should be in the range [−90°, 90°]. + * The scale of the projection is 1 in the "radial" direction, \e azi + * clockwise from true north, and is 1/\e rk in the direction perpendicular + * to this. A call to Forward followed by a call to Reverse will return + * the original (\e lat, \e lon) (to within roundoff). + **********************************************************************/ + void Forward(real lat0, real lon0, real lat, real lon, + real& x, real& y, real& azi, real& rk) const; + + /** + * Reverse projection, from azimuthal equidistant to geographic. + * + * @param[in] lat0 latitude of center point of projection (degrees). + * @param[in] lon0 longitude of center point of projection (degrees). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] azi azimuth of geodesic at point (degrees). + * @param[out] rk reciprocal of azimuthal scale at point. + * + * \e lat0 should be in the range [−90°, 90°]. \e lat will + * be in the range [−90°, 90°] and \e lon will be in the + * range [−180°, 180°]. The scale of the projection is 1 in + * the "radial" direction, \e azi clockwise from true north, and is 1/\e rk + * in the direction perpendicular to this. A call to Reverse followed by a + * call to Forward will return the original (\e x, \e y) (to roundoff) only + * if the geodesic to (\e x, \e y) is a shortest path. + **********************************************************************/ + void Reverse(real lat0, real lon0, real x, real y, + real& lat, real& lon, real& azi, real& rk) const; + + /** + * AzimuthalEquidistant::Forward without returning the azimuth and scale. + **********************************************************************/ + void Forward(real lat0, real lon0, real lat, real lon, + real& x, real& y) const { + real azi, rk; + Forward(lat0, lon0, lat, lon, x, y, azi, rk); + } + + /** + * AzimuthalEquidistant::Reverse without returning the azimuth and scale. + **********************************************************************/ + void Reverse(real lat0, real lon0, real x, real y, + real& lat, real& lon) const { + real azi, rk; + Reverse(lat0, lon0, x, y, lat, lon, azi, rk); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value inherited from the Geodesic object used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the Geodesic object used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _earth.Flattening(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_AZIMUTHALEQUIDISTANT_HPP diff --git a/external/include/GeographicLib/CassiniSoldner.hpp b/external/include/GeographicLib/CassiniSoldner.hpp new file mode 100644 index 0000000..fdc0957 --- /dev/null +++ b/external/include/GeographicLib/CassiniSoldner.hpp @@ -0,0 +1,210 @@ +/** + * \file CassiniSoldner.hpp + * \brief Header for GeographicLib::CassiniSoldner class + * + * Copyright (c) Charles Karney (2009-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_CASSINISOLDNER_HPP) +#define GEOGRAPHICLIB_CASSINISOLDNER_HPP 1 + +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief Cassini-Soldner projection + * + * Cassini-Soldner projection centered at an arbitrary position, \e lat0, \e + * lon0, on the ellipsoid. This projection is a transverse cylindrical + * equidistant projection. The projection from (\e lat, \e lon) to easting + * and northing (\e x, \e y) is defined by geodesics as follows. Go north + * along a geodesic a distance \e y from the central point; then turn + * clockwise 90° and go a distance \e x along a geodesic. + * (Although the initial heading is north, this changes to south if the pole + * is crossed.) This procedure uniquely defines the reverse projection. The + * forward projection is constructed as follows. Find the point (\e lat1, \e + * lon1) on the meridian closest to (\e lat, \e lon). Here we consider the + * full meridian so that \e lon1 may be either \e lon0 or \e lon0 + + * 180°. \e x is the geodesic distance from (\e lat1, \e lon1) to + * (\e lat, \e lon), appropriately signed according to which side of the + * central meridian (\e lat, \e lon) lies. \e y is the shortest distance + * along the meridian from (\e lat0, \e lon0) to (\e lat1, \e lon1), again, + * appropriately signed according to the initial heading. [Note that, in the + * case of prolate ellipsoids, the shortest meridional path from (\e lat0, \e + * lon0) to (\e lat1, \e lon1) may not be the shortest path.] This procedure + * uniquely defines the forward projection except for a small class of points + * for which there may be two equally short routes for either leg of the + * path. + * + * Because of the properties of geodesics, the (\e x, \e y) grid is + * orthogonal. The scale in the easting direction is unity. The scale, \e + * k, in the northing direction is unity on the central meridian and + * increases away from the central meridian. The projection routines return + * \e azi, the true bearing of the easting direction, and \e rk = 1/\e k, the + * reciprocal of the scale in the northing direction. + * + * The conversions all take place using a Geodesic object (by default + * Geodesic::WGS84()). For more information on geodesics see \ref geodesic. + * The determination of (\e lat1, \e lon1) in the forward projection is by + * solving the inverse geodesic problem for (\e lat, \e lon) and its twin + * obtained by reflection in the meridional plane. The scale is found by + * determining where two neighboring geodesics intersecting the central + * meridian at \e lat1 and \e lat1 + \e dlat1 intersect and taking the ratio + * of the reduced lengths for the two geodesics between that point and, + * respectively, (\e lat1, \e lon1) and (\e lat, \e lon). + * + * Example of use: + * \include example-CassiniSoldner.cpp + * + * GeodesicProj is a command-line utility + * providing access to the functionality of AzimuthalEquidistant, Gnomonic, + * and CassiniSoldner. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT CassiniSoldner { + private: + typedef Math::real real; + Geodesic _earth; + GeodesicLine _meridian; + real _sbet0, _cbet0; + static const unsigned maxit_ = 10; + + public: + + /** + * Constructor for CassiniSoldner. + * + * @param[in] earth the Geodesic object to use for geodesic calculations. + * By default this uses the WGS84 ellipsoid. + * + * This constructor makes an "uninitialized" object. Call Reset to set the + * central latitude and longitude, prior to calling Forward and Reverse. + **********************************************************************/ + explicit CassiniSoldner(const Geodesic& earth = Geodesic::WGS84()); + + /** + * Constructor for CassiniSoldner specifying a center point. + * + * @param[in] lat0 latitude of center point of projection (degrees). + * @param[in] lon0 longitude of center point of projection (degrees). + * @param[in] earth the Geodesic object to use for geodesic calculations. + * By default this uses the WGS84 ellipsoid. + * + * \e lat0 should be in the range [−90°, 90°]. + **********************************************************************/ + CassiniSoldner(real lat0, real lon0, + const Geodesic& earth = Geodesic::WGS84()); + + /** + * Set the central point of the projection + * + * @param[in] lat0 latitude of center point of projection (degrees). + * @param[in] lon0 longitude of center point of projection (degrees). + * + * \e lat0 should be in the range [−90°, 90°]. + **********************************************************************/ + void Reset(real lat0, real lon0); + + /** + * Forward projection, from geographic to Cassini-Soldner. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] azi azimuth of easting direction at point (degrees). + * @param[out] rk reciprocal of azimuthal northing scale at point. + * + * \e lat should be in the range [−90°, 90°]. A call to + * Forward followed by a call to Reverse will return the original (\e lat, + * \e lon) (to within roundoff). The routine does nothing if the origin + * has not been set. + **********************************************************************/ + void Forward(real lat, real lon, + real& x, real& y, real& azi, real& rk) const; + + /** + * Reverse projection, from Cassini-Soldner to geographic. + * + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] azi azimuth of easting direction at point (degrees). + * @param[out] rk reciprocal of azimuthal northing scale at point. + * + * A call to Reverse followed by a call to Forward will return the original + * (\e x, \e y) (to within roundoff), provided that \e x and \e y are + * sufficiently small not to "wrap around" the earth. The routine does + * nothing if the origin has not been set. + **********************************************************************/ + void Reverse(real x, real y, + real& lat, real& lon, real& azi, real& rk) const; + + /** + * CassiniSoldner::Forward without returning the azimuth and scale. + **********************************************************************/ + void Forward(real lat, real lon, + real& x, real& y) const { + real azi, rk; + Forward(lat, lon, x, y, azi, rk); + } + + /** + * CassiniSoldner::Reverse without returning the azimuth and scale. + **********************************************************************/ + void Reverse(real x, real y, + real& lat, real& lon) const { + real azi, rk; + Reverse(x, y, lat, lon, azi, rk); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return true if the object has been initialized. + **********************************************************************/ + bool Init() const { return _meridian.Init(); } + + /** + * @return \e lat0 the latitude of origin (degrees). + **********************************************************************/ + Math::real LatitudeOrigin() const + { return _meridian.Latitude(); } + + /** + * @return \e lon0 the longitude of origin (degrees). + **********************************************************************/ + Math::real LongitudeOrigin() const + { return _meridian.Longitude(); } + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value inherited from the Geodesic object used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the Geodesic object used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _earth.Flattening(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_CASSINISOLDNER_HPP diff --git a/external/include/GeographicLib/CircularEngine.hpp b/external/include/GeographicLib/CircularEngine.hpp new file mode 100644 index 0000000..ef43a21 --- /dev/null +++ b/external/include/GeographicLib/CircularEngine.hpp @@ -0,0 +1,195 @@ +/** + * \file CircularEngine.hpp + * \brief Header for GeographicLib::CircularEngine class + * + * Copyright (c) Charles Karney (2011-2015) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_CIRCULARENGINE_HPP) +#define GEOGRAPHICLIB_CIRCULARENGINE_HPP 1 + +#include +#include +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs vector +# pragma warning (push) +# pragma warning (disable: 4251) +#endif + +namespace GeographicLib { + + /** + * \brief Spherical harmonic sums for a circle + * + * The class is a companion to SphericalEngine. If the results of a + * spherical harmonic sum are needed for several points on a circle of + * constant latitude \e lat and height \e h, then SphericalEngine::Circle can + * compute the inner sum, which is independent of longitude \e lon, and + * produce a CircularEngine object. CircularEngine::operator()() can + * then be used to perform the outer sum for particular vales of \e lon. + * This can lead to substantial improvements in computational speed for high + * degree sum (approximately by a factor of \e N / 2 where \e N is the + * maximum degree). + * + * CircularEngine is tightly linked to the internals of SphericalEngine. For + * that reason, the constructor for this class is private. Use + * SphericalHarmonic::Circle, SphericalHarmonic1::Circle, and + * SphericalHarmonic2::Circle to create instances of this class. + * + * CircularEngine stores the coefficients needed to allow the summation over + * order to be performed in 2 or 6 vectors of length \e M + 1 (depending on + * whether gradients are to be calculated). For this reason the constructor + * may throw a std::bad_alloc exception. + * + * Example of use: + * \include example-CircularEngine.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT CircularEngine { + private: + typedef Math::real real; + enum normalization { + FULL = SphericalEngine::FULL, + SCHMIDT = SphericalEngine::SCHMIDT, + }; + int _M; + bool _gradp; + unsigned _norm; + real _a, _r, _u, _t; + std::vector _wc, _ws, _wrc, _wrs, _wtc, _wts; + real _q, _uq, _uq2; + + Math::real Value(bool gradp, real sl, real cl, + real& gradx, real& grady, real& gradz) const; + + friend class SphericalEngine; + CircularEngine(int M, bool gradp, unsigned norm, + real a, real r, real u, real t) + : _M(M) + , _gradp(gradp) + , _norm(norm) + , _a(a) + , _r(r) + , _u(u) + , _t(t) + , _wc(std::vector(_M + 1, 0)) + , _ws(std::vector(_M + 1, 0)) + , _wrc(std::vector(_gradp ? _M + 1 : 0, 0)) + , _wrs(std::vector(_gradp ? _M + 1 : 0, 0)) + , _wtc(std::vector(_gradp ? _M + 1 : 0, 0)) + , _wts(std::vector(_gradp ? _M + 1 : 0, 0)) + { + _q = _a / _r; + _uq = _u * _q; + _uq2 = Math::sq(_uq); + } + + void SetCoeff(int m, real wc, real ws) + { _wc[m] = wc; _ws[m] = ws; } + + void SetCoeff(int m, real wc, real ws, + real wrc, real wrs, real wtc, real wts) { + _wc[m] = wc; _ws[m] = ws; + if (_gradp) { + _wrc[m] = wrc; _wrs[m] = wrs; + _wtc[m] = wtc; _wts[m] = wts; + } + } + + public: + + /** + * A default constructor. CircularEngine::operator()() on the resulting + * object returns zero. The resulting object can be assigned to the result + * of SphericalHarmonic::Circle. + **********************************************************************/ + CircularEngine() + : _M(-1) + , _gradp(true) + , _u(0) + , _t(1) + {} + + /** + * Evaluate the sum for a particular longitude given in terms of its + * sine and cosine. + * + * @param[in] sinlon the sine of the longitude. + * @param[in] coslon the cosine of the longitude. + * @return \e V the value of the sum. + * + * The arguments must satisfy sinlon2 + + * coslon2 = 1. + **********************************************************************/ + Math::real operator()(real sinlon, real coslon) const { + real dummy; + return Value(false, sinlon, coslon, dummy, dummy, dummy); + } + + /** + * Evaluate the sum for a particular longitude. + * + * @param[in] lon the longitude (degrees). + * @return \e V the value of the sum. + **********************************************************************/ + Math::real operator()(real lon) const { + real sinlon, coslon; + Math::sincosd(lon, sinlon, coslon); + return (*this)(sinlon, coslon); + } + + /** + * Evaluate the sum and its gradient for a particular longitude given in + * terms of its sine and cosine. + * + * @param[in] sinlon the sine of the longitude. + * @param[in] coslon the cosine of the longitude. + * @param[out] gradx \e x component of the gradient. + * @param[out] grady \e y component of the gradient. + * @param[out] gradz \e z component of the gradient. + * @return \e V the value of the sum. + * + * The gradients will only be computed if the CircularEngine object was + * created with this capability (e.g., via \e gradp = true in + * SphericalHarmonic::Circle). If not, \e gradx, etc., will not be + * touched. The arguments must satisfy sinlon2 + + * coslon2 = 1. + **********************************************************************/ + Math::real operator()(real sinlon, real coslon, + real& gradx, real& grady, real& gradz) const { + return Value(true, sinlon, coslon, gradx, grady, gradz); + } + + /** + * Evaluate the sum and its gradient for a particular longitude. + * + * @param[in] lon the longitude (degrees). + * @param[out] gradx \e x component of the gradient. + * @param[out] grady \e y component of the gradient. + * @param[out] gradz \e z component of the gradient. + * @return \e V the value of the sum. + * + * The gradients will only be computed if the CircularEngine object was + * created with this capability (e.g., via \e gradp = true in + * SphericalHarmonic::Circle). If not, \e gradx, etc., will not be + * touched. + **********************************************************************/ + Math::real operator()(real lon, + real& gradx, real& grady, real& gradz) const { + real sinlon, coslon; + Math::sincosd(lon, sinlon, coslon); + return (*this)(sinlon, coslon, gradx, grady, gradz); + } + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_CIRCULARENGINE_HPP diff --git a/external/include/GeographicLib/Config.h b/external/include/GeographicLib/Config.h new file mode 100644 index 0000000..74fcd0e --- /dev/null +++ b/external/include/GeographicLib/Config.h @@ -0,0 +1,25 @@ +#define GEOGRAPHICLIB_VERSION_STRING "1.52" +#define GEOGRAPHICLIB_VERSION_MAJOR 1 +#define GEOGRAPHICLIB_VERSION_MINOR 52 +#define GEOGRAPHICLIB_VERSION_PATCH 0 +#define GEOGRAPHICLIB_DATA "C:/Users/sven/Documents/Visual Studio 2019/Projects/TST/install" + +// These are macros which affect the building of the library +#define GEOGRAPHICLIB_HAVE_LONG_DOUBLE 0 +#define GEOGRAPHICLIB_WORDS_BIGENDIAN 0 +#define GEOGRAPHICLIB_PRECISION 1 + +// Specify whether GeographicLib is a shared or static library. When compiling +// under Visual Studio it is necessary to specify whether GeographicLib is a +// shared library. This is done with the macro GEOGRAPHICLIB_SHARED_LIB, which +// cmake will correctly define as 0 or 1 when only one type of library is in +// the package. If both shared and static libraries are available, +// GEOGRAPHICLIB_SHARED_LIB is set to 2 which triggers a preprocessor error in +// Constants.hpp. In this case, the appropriate value (0 or 1) for +// GEOGRAPHICLIB_SHARED_LIB must be specified when compiling any program that +// includes GeographicLib headers. This is done automatically if GeographicLib +// and the user's code were built with cmake version 2.8.11 (which introduced +// the command target_compile_definitions) or later. +#if !defined(GEOGRAPHICLIB_SHARED_LIB) +#define GEOGRAPHICLIB_SHARED_LIB 0 +#endif diff --git a/external/include/GeographicLib/Constants.hpp b/external/include/GeographicLib/Constants.hpp new file mode 100644 index 0000000..e184f9b --- /dev/null +++ b/external/include/GeographicLib/Constants.hpp @@ -0,0 +1,329 @@ +/** + * \file Constants.hpp + * \brief Header for GeographicLib::Constants class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_CONSTANTS_HPP) +#define GEOGRAPHICLIB_CONSTANTS_HPP 1 + +#include + +/** + * @relates GeographicLib::Constants + * Pack the version components into a single integer. Users should not rely on + * this particular packing of the components of the version number; see the + * documentation for GEOGRAPHICLIB_VERSION, below. + **********************************************************************/ +#define GEOGRAPHICLIB_VERSION_NUM(a,b,c) ((((a) * 10000 + (b)) * 100) + (c)) + +/** + * @relates GeographicLib::Constants + * The version of GeographicLib as a single integer, packed as MMmmmmpp where + * MM is the major version, mmmm is the minor version, and pp is the patch + * level. Users should not rely on this particular packing of the components + * of the version number. Instead they should use a test such as \code + #if GEOGRAPHICLIB_VERSION >= GEOGRAPHICLIB_VERSION_NUM(1,37,0) + ... + #endif + * \endcode + **********************************************************************/ +#define GEOGRAPHICLIB_VERSION \ + GEOGRAPHICLIB_VERSION_NUM(GEOGRAPHICLIB_VERSION_MAJOR, \ + GEOGRAPHICLIB_VERSION_MINOR, \ + GEOGRAPHICLIB_VERSION_PATCH) + +// For reference, here is a table of Visual Studio and _MSC_VER +// correspondences: +// +// _MSC_VER Visual Studio +// 1100 vc5 +// 1200 vc6 +// 1300 vc7 +// 1310 vc7.1 (2003) +// 1400 vc8 (2005) +// 1500 vc9 (2008) +// 1600 vc10 (2010) +// 1700 vc11 (2012) +// 1800 vc12 (2013) +// 1900 vc14 (2015) First version of VS to include enough C++11 support +// 191[0-9] vc15 (2017) +// 192[0-9] vc16 (2019) + +#if defined(_MSC_VER) && defined(GEOGRAPHICLIB_SHARED_LIB) && \ + GEOGRAPHICLIB_SHARED_LIB +# if GEOGRAPHICLIB_SHARED_LIB > 1 +# error GEOGRAPHICLIB_SHARED_LIB must be 0 or 1 +# elif defined(GeographicLib_SHARED_EXPORTS) +# define GEOGRAPHICLIB_EXPORT __declspec(dllexport) +# else +# define GEOGRAPHICLIB_EXPORT __declspec(dllimport) +# endif +#else +# define GEOGRAPHICLIB_EXPORT +#endif + +// Use GEOGRAPHICLIB_DEPRECATED to mark functions, types or variables as +// deprecated. Code inspired by Apache Subversion's svn_types.h file (via +// MPFR). +#if defined(__GNUC__) +# if __GNUC__ > 4 +# define GEOGRAPHICLIB_DEPRECATED(msg) __attribute__((deprecated(msg))) +# else +# define GEOGRAPHICLIB_DEPRECATED(msg) __attribute__((deprecated)) +# endif +#elif defined(_MSC_VER) && _MSC_VER >= 1300 +# define GEOGRAPHICLIB_DEPRECATED(msg) __declspec(deprecated(msg)) +#else +# define GEOGRAPHICLIB_DEPRECATED(msg) +#endif + +#include +#include +#include + +/** + * \brief Namespace for %GeographicLib + * + * All of %GeographicLib is defined within the GeographicLib namespace. In + * addition all the header files are included via %GeographicLib/Class.hpp. + * This minimizes the likelihood of conflicts with other packages. + **********************************************************************/ +namespace GeographicLib { + + /** + * \brief %Constants needed by %GeographicLib + * + * Define constants specifying the WGS84 ellipsoid, the UTM and UPS + * projections, and various unit conversions. + * + * Example of use: + * \include example-Constants.cpp + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT Constants { + private: + typedef Math::real real; + Constants(); // Disable constructor + + public: + /** + * A synonym for Math::degree(). + **********************************************************************/ + static Math::real degree() { return Math::degree(); } + /** + * @return the number of radians in an arcminute. + **********************************************************************/ + static Math::real arcminute() + { return Math::degree() / 60; } + /** + * @return the number of radians in an arcsecond. + **********************************************************************/ + static Math::real arcsecond() + { return Math::degree() / 3600; } + + /** \name Ellipsoid parameters + **********************************************************************/ + ///@{ + /** + * @tparam T the type of the returned value. + * @return the equatorial radius of WGS84 ellipsoid (6378137 m). + **********************************************************************/ + template static T WGS84_a() + { return 6378137 * meter(); } + /** + * @tparam T the type of the returned value. + * @return the flattening of WGS84 ellipsoid (1/298.257223563). + **********************************************************************/ + template static T WGS84_f() { + // Evaluating this as 1000000000 / T(298257223563LL) reduces the + // round-off error by about 10%. However, expressing the flattening as + // 1/298.257223563 is well ingrained. + return 1 / ( T(298257223563LL) / 1000000000 ); + } + /** + * @tparam T the type of the returned value. + * @return the gravitational constant of the WGS84 ellipsoid, \e GM, in + * m3 s−2. + **********************************************************************/ + template static T WGS84_GM() + { return T(3986004) * 100000000 + 41800000; } + /** + * @tparam T the type of the returned value. + * @return the angular velocity of the WGS84 ellipsoid, ω, in rad + * s−1. + **********************************************************************/ + template static T WGS84_omega() + { return 7292115 / (T(1000000) * 100000); } + /** + * @tparam T the type of the returned value. + * @return the equatorial radius of GRS80 ellipsoid, \e a, in m. + **********************************************************************/ + template static T GRS80_a() + { return 6378137 * meter(); } + /** + * @tparam T the type of the returned value. + * @return the gravitational constant of the GRS80 ellipsoid, \e GM, in + * m3 s−2. + **********************************************************************/ + template static T GRS80_GM() + { return T(3986005) * 100000000; } + /** + * @tparam T the type of the returned value. + * @return the angular velocity of the GRS80 ellipsoid, ω, in rad + * s−1. + * + * This is about 2 π 366.25 / (365.25 × 24 × 3600) rad + * s−1. 365.25 is the number of days in a Julian year and + * 365.35/366.25 converts from solar days to sidereal days. Using the + * number of days in a Gregorian year (365.2425) results in a worse + * approximation (because the Gregorian year includes the precession of the + * earth's axis). + **********************************************************************/ + template static T GRS80_omega() + { return 7292115 / (T(1000000) * 100000); } + /** + * @tparam T the type of the returned value. + * @return the dynamical form factor of the GRS80 ellipsoid, + * J2. + **********************************************************************/ + template static T GRS80_J2() + { return T(108263) / 100000000; } + /** + * @tparam T the type of the returned value. + * @return the central scale factor for UTM (0.9996). + **********************************************************************/ + template static T UTM_k0() + {return T(9996) / 10000; } + /** + * @tparam T the type of the returned value. + * @return the central scale factor for UPS (0.994). + **********************************************************************/ + template static T UPS_k0() + { return T(994) / 1000; } + ///@} + + /** \name SI units + **********************************************************************/ + ///@{ + /** + * @tparam T the type of the returned value. + * @return the number of meters in a meter. + * + * This is unity, but this lets the internal system of units be changed if + * necessary. + **********************************************************************/ + template static T meter() { return T(1); } + /** + * @return the number of meters in a kilometer. + **********************************************************************/ + static Math::real kilometer() + { return 1000 * meter(); } + /** + * @return the number of meters in a nautical mile (approximately 1 arc + * minute) + **********************************************************************/ + static Math::real nauticalmile() + { return 1852 * meter(); } + + /** + * @tparam T the type of the returned value. + * @return the number of square meters in a square meter. + * + * This is unity, but this lets the internal system of units be changed if + * necessary. + **********************************************************************/ + template static T square_meter() + { return meter() * meter(); } + /** + * @return the number of square meters in a hectare. + **********************************************************************/ + static Math::real hectare() + { return 10000 * square_meter(); } + /** + * @return the number of square meters in a square kilometer. + **********************************************************************/ + static Math::real square_kilometer() + { return kilometer() * kilometer(); } + /** + * @return the number of square meters in a square nautical mile. + **********************************************************************/ + static Math::real square_nauticalmile() + { return nauticalmile() * nauticalmile(); } + ///@} + + /** \name Anachronistic British units + **********************************************************************/ + ///@{ + /** + * @return the number of meters in an international foot. + **********************************************************************/ + static Math::real foot() + { return real(254 * 12) / 10000 * meter(); } + /** + * @return the number of meters in a yard. + **********************************************************************/ + static Math::real yard() { return 3 * foot(); } + /** + * @return the number of meters in a fathom. + **********************************************************************/ + static Math::real fathom() { return 2 * yard(); } + /** + * @return the number of meters in a chain. + **********************************************************************/ + static Math::real chain() { return 22 * yard(); } + /** + * @return the number of meters in a furlong. + **********************************************************************/ + static Math::real furlong() { return 10 * chain(); } + /** + * @return the number of meters in a statute mile. + **********************************************************************/ + static Math::real mile() { return 8 * furlong(); } + /** + * @return the number of square meters in an acre. + **********************************************************************/ + static Math::real acre() { return chain() * furlong(); } + /** + * @return the number of square meters in a square statute mile. + **********************************************************************/ + static Math::real square_mile() { return mile() * mile(); } + ///@} + + /** \name Anachronistic US units + **********************************************************************/ + ///@{ + /** + * @return the number of meters in a US survey foot. + **********************************************************************/ + static Math::real surveyfoot() + { return real(1200) / 3937 * meter(); } + ///@} + }; + + /** + * \brief Exception handling for %GeographicLib + * + * A class to handle exceptions. It's derived from std::runtime_error so it + * can be caught by the usual catch clauses. + * + * Example of use: + * \include example-GeographicErr.cpp + **********************************************************************/ + class GeographicErr : public std::runtime_error { + public: + + /** + * Constructor + * + * @param[in] msg a string message, which is accessible in the catch + * clause via what(). + **********************************************************************/ + GeographicErr(const std::string& msg) : std::runtime_error(msg) {} + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_CONSTANTS_HPP diff --git a/external/include/GeographicLib/DMS.hpp b/external/include/GeographicLib/DMS.hpp new file mode 100644 index 0000000..23f4654 --- /dev/null +++ b/external/include/GeographicLib/DMS.hpp @@ -0,0 +1,405 @@ +/** + * \file DMS.hpp + * \brief Header for GeographicLib::DMS class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_DMS_HPP) +#define GEOGRAPHICLIB_DMS_HPP 1 + +#include +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs vector and constant conditional expressions +# pragma warning (push) +# pragma warning (disable: 4251 4127) +#endif + +namespace GeographicLib { + + /** + * \brief Convert between degrees and the %DMS representation + * + * Parse a string representing degree, minutes, and seconds and return the + * angle in degrees and format an angle in degrees as degree, minutes, and + * seconds. In addition, handle NANs and infinities on input and output. + * + * Example of use: + * \include example-DMS.cpp + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT DMS { + public: + + /** + * Indicator for presence of hemisphere indicator (N/S/E/W) on latitudes + * and longitudes. + **********************************************************************/ + enum flag { + /** + * No indicator present. + * @hideinitializer + **********************************************************************/ + NONE = 0, + /** + * Latitude indicator (N/S) present. + * @hideinitializer + **********************************************************************/ + LATITUDE = 1, + /** + * Longitude indicator (E/W) present. + * @hideinitializer + **********************************************************************/ + LONGITUDE = 2, + /** + * Used in Encode to indicate output of an azimuth in [000, 360) with no + * letter indicator. + * @hideinitializer + **********************************************************************/ + AZIMUTH = 3, + /** + * Used in Encode to indicate output of a plain number. + * @hideinitializer + **********************************************************************/ + NUMBER = 4, + }; + + /** + * Indicator for trailing units on an angle. + **********************************************************************/ + enum component { + /** + * Trailing unit is degrees. + * @hideinitializer + **********************************************************************/ + DEGREE = 0, + /** + * Trailing unit is arc minutes. + * @hideinitializer + **********************************************************************/ + MINUTE = 1, + /** + * Trailing unit is arc seconds. + * @hideinitializer + **********************************************************************/ + SECOND = 2, + }; + + private: + typedef Math::real real; + // Replace all occurrences of pat by c. If c is NULL remove pat. + static void replace(std::string& s, const std::string& pat, char c) { + std::string::size_type p = 0; + int count = c ? 1 : 0; + while (true) { + p = s.find(pat, p); + if (p == std::string::npos) + break; + s.replace(p, pat.length(), count, c); + } + } + static const char* const hemispheres_; + static const char* const signs_; + static const char* const digits_; + static const char* const dmsindicators_; + static const char* const components_[3]; + static Math::real NumMatch(const std::string& s); + static Math::real InternalDecode(const std::string& dmsa, flag& ind); + DMS(); // Disable constructor + + public: + + /** + * Convert a string in DMS to an angle. + * + * @param[in] dms string input. + * @param[out] ind a DMS::flag value signaling the presence of a + * hemisphere indicator. + * @exception GeographicErr if \e dms is malformed (see below). + * @return angle (degrees). + * + * Degrees, minutes, and seconds are indicated by the characters d, ' + * (single quote), " (double quote), and these components may only be + * given in this order. Any (but not all) components may be omitted and + * other symbols (e.g., the ° symbol for degrees and the unicode prime + * and double prime symbols for minutes and seconds) may be substituted; + * two single quotes can be used instead of ". The last component + * indicator may be omitted and is assumed to be the next smallest unit + * (thus 33d10 is interpreted as 33d10'). The final component may be a + * decimal fraction but the non-final components must be integers. Instead + * of using d, ', and " to indicate degrees, minutes, and seconds, : + * (colon) may be used to separate these components (numbers must + * appear before and after each colon); thus 50d30'10.3" may be + * written as 50:30:10.3, 5.5' may be written 0:5.5, and so on. The + * integer parts of the minutes and seconds components must be less + * than 60. A single leading sign is permitted. A hemisphere designator + * (N, E, W, S) may be added to the beginning or end of the string. The + * result is multiplied by the implied sign of the hemisphere designator + * (negative for S and W). In addition \e ind is set to DMS::LATITUDE if N + * or S is present, to DMS::LONGITUDE if E or W is present, and to + * DMS::NONE otherwise. Throws an error on a malformed string. No check + * is performed on the range of the result. Examples of legal and illegal + * strings are + * - LEGAL (all the entries on each line are equivalent) + * - -20.51125, 20d30'40.5"S, -20°30'40.5, -20d30.675, + * N-20d30'40.5", -20:30:40.5 + * - 4d0'9, 4d9", 4d9'', 4:0:9, 004:00:09, 4.0025, 4.0025d, 4d0.15, + * 04:.15 + * - 4:59.99999999999999, 4:60.0, 4:59:59.9999999999999, 4:59:60.0, 5 + * - ILLEGAL (the exception thrown explains the problem) + * - 4d5"4', 4::5, 4:5:, :4:5, 4d4.5'4", -N20.5, 1.8e2d, 4:60, + * 4:59:60 + * + * The decoding operation can also perform addition and subtraction + * operations. If the string includes internal signs (i.e., not at + * the beginning nor immediately after an initial hemisphere designator), + * then the string is split immediately before such signs and each piece is + * decoded according to the above rules and the results added; thus + * S3-2.5+4.1N is parsed as the sum of S3, + * -2.5, +4.1N. Any piece can include a + * hemisphere designator; however, if multiple designators are given, they + * must compatible; e.g., you cannot mix N and E. In addition, the + * designator can appear at the beginning or end of the first piece, but + * must be at the end of all subsequent pieces (a hemisphere designator is + * not allowed after the initial sign). Examples of legal and illegal + * combinations are + * - LEGAL (these are all equivalent) + * - 070:00:45, 70:01:15W+0:0.5, 70:01:15W-0:0:30W, W70:01:15+0:0:30E + * - ILLEGAL (the exception thrown explains the problem) + * - 70:01:15W+0:0:15N, W70:01:15+W0:0:15 + * + * \warning The "exponential" notation is not recognized. Thus + * 7.0E1 is illegal, while 7.0E+1 is parsed as + * (7.0E) + (+1), yielding the same result as + * 8.0E. + * + * \note At present, all the string handling in the C++ implementation of + * %GeographicLib is with 8-bit characters. The support for unicode + * symbols for degrees, minutes, and seconds is therefore via the + * UTF-8 encoding. (The + * JavaScript implementation of this class uses unicode natively, of + * course.) + * + * Here is the list of Unicode symbols supported for degrees, minutes, + * seconds, and the plus and minus signs; various symbols denoting variants + * of a space, which may separate the components of a DMS string, are + * removed: + * - degrees: + * - d, D lower and upper case letters + * - U+00b0 degree symbol (°) + * - U+00ba masculine ordinal indicator (º) + * - U+2070 superscript zero (⁰) + * - U+02da ring above (˚) + * - U+2218 compose function (∘) + * - * the GRiD symbol for degrees + * - minutes: + * - ' apostrophe + * - ` grave accent + * - U+2032 prime (′) + * - U+2035 back prime (‵) + * - U+00b4 acute accent (´) + * - U+2018 left single quote (‘) + * - U+2019 right single quote (’) + * - U+201b reversed-9 single quote (‛) + * - U+02b9 modifier letter prime (ʹ) + * - U+02ca modifier letter acute accent (ˊ) + * - U+02cb modifier letter grave accent (ˋ) + * - seconds: + * - " quotation mark + * - U+2033 double prime (″) + * - U+2036 reversed double prime (‶) + * + U+02dd double acute accent (˝) + * - U+201c left double quote (“) + * - U+201d right double quote (”) + * - U+201f reversed-9 double quote (‟) + * - U+02ba modifier letter double prime (ʺ) + * - ' ' any two consecutive symbols for minutes + * - plus sign: + * - + plus + * - U+2795 heavy plus (➕) + * - U+2064 invisible plus (|⁤|) + * - minus sign: + * - - hyphen + * - U+2010 dash (‐) + * - U+2011 non-breaking hyphen (‑) + * - U+2013 en dash (–) + * - U+2014 em dash (—) + * - U+2212 minus sign (−) + * - U+2796 heavy minus (➖) + * - ignored spaces: + * - U+00a0 non-breaking space + * - U+2007 figure space (| |) + * - U+2009 thin space (| |) + * - U+200a hair space ( | |) + * - U+200b invisible space (|​|) + * - U+202f narrow space ( | |) + * - U+2063 invisible separator (|⁣|) + * . + * The codes with a leading zero byte, e.g., U+00b0, are accepted in their + * UTF-8 coded form 0xc2 0xb0 and as a single byte 0xb0. + **********************************************************************/ + static Math::real Decode(const std::string& dms, flag& ind); + + /** + * Convert DMS to an angle. + * + * @param[in] d degrees. + * @param[in] m arc minutes. + * @param[in] s arc seconds. + * @return angle (degrees) + * + * This does not propagate the sign on \e d to the other components, + * so -3d20' would need to be represented as - DMS::Decode(3.0, 20.0) or + * DMS::Decode(-3.0, -20.0). + **********************************************************************/ + static Math::real Decode(real d, real m = 0, real s = 0) + { return d + (m + s / 60) / 60; } + + /** + * Convert a pair of strings to latitude and longitude. + * + * @param[in] dmsa first string. + * @param[in] dmsb second string. + * @param[out] lat latitude (degrees). + * @param[out] lon longitude (degrees). + * @param[in] longfirst if true assume longitude is given before latitude + * in the absence of hemisphere designators (default false). + * @exception GeographicErr if \e dmsa or \e dmsb is malformed. + * @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as + * latitudes. + * @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as + * longitudes. + * @exception GeographicErr if decoded latitude is not in [−90°, + * 90°]. + * + * By default, the \e lat (resp., \e lon) is assigned to the results of + * decoding \e dmsa (resp., \e dmsb). However this is overridden if either + * \e dmsa or \e dmsb contain a latitude or longitude hemisphere designator + * (N, S, E, W). If an exception is thrown, \e lat and \e lon are + * unchanged. + **********************************************************************/ + static void DecodeLatLon(const std::string& dmsa, const std::string& dmsb, + real& lat, real& lon, + bool longfirst = false); + + /** + * Convert a string to an angle in degrees. + * + * @param[in] angstr input string. + * @exception GeographicErr if \e angstr is malformed. + * @exception GeographicErr if \e angstr includes a hemisphere designator. + * @return angle (degrees) + * + * No hemisphere designator is allowed and no check is done on the range of + * the result. + **********************************************************************/ + static Math::real DecodeAngle(const std::string& angstr); + + /** + * Convert a string to an azimuth in degrees. + * + * @param[in] azistr input string. + * @exception GeographicErr if \e azistr is malformed. + * @exception GeographicErr if \e azistr includes a N/S designator. + * @return azimuth (degrees) reduced to the range [−180°, + * 180°]. + * + * A hemisphere designator E/W can be used; the result is multiplied by + * −1 if W is present. + **********************************************************************/ + static Math::real DecodeAzimuth(const std::string& azistr); + + /** + * Convert angle (in degrees) into a DMS string (using d, ', and "). + * + * @param[in] angle input angle (degrees) + * @param[in] trailing DMS::component value indicating the trailing units + * of the string (this component is given as a decimal number if + * necessary). + * @param[in] prec the number of digits after the decimal point for the + * trailing component. + * @param[in] ind DMS::flag value indicating additional formatting. + * @param[in] dmssep if non-null, use as the DMS separator character + * (instead of d, ', " delimiters). + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return formatted string + * + * The interpretation of \e ind is as follows: + * - ind == DMS::NONE, signed result no leading zeros on degrees except in + * the units place, e.g., -8d03'. + * - ind == DMS::LATITUDE, trailing N or S hemisphere designator, no sign, + * pad degrees to 2 digits, e.g., 08d03'S. + * - ind == DMS::LONGITUDE, trailing E or W hemisphere designator, no + * sign, pad degrees to 3 digits, e.g., 008d03'W. + * - ind == DMS::AZIMUTH, convert to the range [0, 360°), no + * sign, pad degrees to 3 digits, e.g., 351d57'. + * . + * The integer parts of the minutes and seconds components are always given + * with 2 digits. + **********************************************************************/ + static std::string Encode(real angle, component trailing, unsigned prec, + flag ind = NONE, char dmssep = char(0)); + + /** + * Convert angle into a DMS string (using d, ', and ") selecting the + * trailing component based on the precision. + * + * @param[in] angle input angle (degrees) + * @param[in] prec the precision relative to 1 degree. + * @param[in] ind DMS::flag value indicated additional formatting. + * @param[in] dmssep if non-null, use as the DMS separator character + * (instead of d, ', " delimiters). + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return formatted string + * + * \e prec indicates the precision relative to 1 degree, e.g., \e prec = 3 + * gives a result accurate to 0.1' and \e prec = 4 gives a result accurate + * to 1". \e ind is interpreted as in DMS::Encode with the additional + * facility that DMS::NUMBER represents \e angle as a number in fixed + * format with precision \e prec. + **********************************************************************/ + static std::string Encode(real angle, unsigned prec, flag ind = NONE, + char dmssep = char(0)) { + return ind == NUMBER ? Utility::str(angle, int(prec)) : + Encode(angle, + prec < 2 ? DEGREE : (prec < 4 ? MINUTE : SECOND), + prec < 2 ? prec : (prec < 4 ? prec - 2 : prec - 4), + ind, dmssep); + } + + /** + * Split angle into degrees and minutes + * + * @param[in] ang angle (degrees) + * @param[out] d degrees (an integer returned as a real) + * @param[out] m arc minutes. + **********************************************************************/ + static void Encode(real ang, real& d, real& m) { + d = int(ang); m = 60 * (ang - d); + } + + /** + * Split angle into degrees and minutes and seconds. + * + * @param[in] ang angle (degrees) + * @param[out] d degrees (an integer returned as a real) + * @param[out] m arc minutes (an integer returned as a real) + * @param[out] s arc seconds. + **********************************************************************/ + static void Encode(real ang, real& d, real& m, real& s) { + d = int(ang); ang = 60 * (ang - d); + m = int(ang); s = 60 * (ang - m); + } + + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_DMS_HPP diff --git a/external/include/GeographicLib/Ellipsoid.hpp b/external/include/GeographicLib/Ellipsoid.hpp new file mode 100644 index 0000000..6a821ce --- /dev/null +++ b/external/include/GeographicLib/Ellipsoid.hpp @@ -0,0 +1,542 @@ +/** + * \file Ellipsoid.hpp + * \brief Header for GeographicLib::Ellipsoid class + * + * Copyright (c) Charles Karney (2012-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_ELLIPSOID_HPP) +#define GEOGRAPHICLIB_ELLIPSOID_HPP 1 + +#include +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief Properties of an ellipsoid + * + * This class returns various properties of the ellipsoid and converts + * between various types of latitudes. The latitude conversions are also + * possible using the various projections supported by %GeographicLib; but + * Ellipsoid provides more direct access (sometimes using private functions + * of the projection classes). Ellipsoid::RectifyingLatitude, + * Ellipsoid::InverseRectifyingLatitude, and Ellipsoid::MeridianDistance + * provide functionality which can be provided by the Geodesic class. + * However Geodesic uses a series approximation (valid for abs \e f < 1/150), + * whereas Ellipsoid computes these quantities using EllipticFunction which + * provides accurate results even when \e f is large. Use of this class + * should be limited to −3 < \e f < 3/4 (i.e., 1/4 < b/a < 4). + * + * Example of use: + * \include example-Ellipsoid.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT Ellipsoid { + private: + typedef Math::real real; + static const int numit_ = 10; + real stol_; + real _a, _f, _f1, _f12, _e2, _es, _e12, _n, _b; + TransverseMercator _tm; + EllipticFunction _ell; + AlbersEqualArea _au; + + // These are the alpha and beta coefficients in the Krueger series from + // TransverseMercator. Thy are used by RhumbSolve to compute + // (psi2-psi1)/(mu2-mu1). + const Math::real* ConformalToRectifyingCoeffs() const { return _tm._alp; } + const Math::real* RectifyingToConformalCoeffs() const { return _tm._bet; } + friend class Rhumb; friend class RhumbLine; + public: + /** \name Constructor + **********************************************************************/ + ///@{ + + /** + * Constructor for a ellipsoid with + * + * @param[in] a equatorial radius (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @exception GeographicErr if \e a or (1 − \e f) \e a is not + * positive. + **********************************************************************/ + Ellipsoid(real a, real f); + ///@} + + /** \name %Ellipsoid dimensions. + **********************************************************************/ + ///@{ + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _a; } + + /** + * @return \e b the polar semi-axis (meters). + **********************************************************************/ + Math::real MinorRadius() const { return _b; } + + /** + * @return \e L the distance between the equator and a pole along a + * meridian (meters). For a sphere \e L = (π/2) \e a. The radius + * of a sphere with the same meridian length is \e L / (π/2). + **********************************************************************/ + Math::real QuarterMeridian() const; + + /** + * @return \e A the total area of the ellipsoid (meters2). For + * a sphere \e A = 4π a2. The radius of a sphere + * with the same area is sqrt(\e A / (4π)). + **********************************************************************/ + Math::real Area() const; + + /** + * @return \e V the total volume of the ellipsoid (meters3). + * For a sphere \e V = (4π / 3) a3. The radius of + * a sphere with the same volume is cbrt(\e V / (4π/3)). + **********************************************************************/ + Math::real Volume() const + { return (4 * Math::pi()) * Math::sq(_a) * _b / 3; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** \name %Ellipsoid shape + **********************************************************************/ + ///@{ + + /** + * @return \e f = (\e a − \e b) / \e a, the flattening of the + * ellipsoid. This is the value used in the constructor. This is zero, + * positive, or negative for a sphere, oblate ellipsoid, or prolate + * ellipsoid. + **********************************************************************/ + Math::real Flattening() const { return _f; } + + /** + * @return \e f ' = (\e a − \e b) / \e b, the second flattening of + * the ellipsoid. This is zero, positive, or negative for a sphere, + * oblate ellipsoid, or prolate ellipsoid. + **********************************************************************/ + Math::real SecondFlattening() const { return _f / (1 - _f); } + + /** + * @return \e n = (\e a − \e b) / (\e a + \e b), the third flattening + * of the ellipsoid. This is zero, positive, or negative for a sphere, + * oblate ellipsoid, or prolate ellipsoid. + **********************************************************************/ + Math::real ThirdFlattening() const { return _n; } + + /** + * @return e2 = (a2 − + * b2) / a2, the eccentricity squared + * of the ellipsoid. This is zero, positive, or negative for a sphere, + * oblate ellipsoid, or prolate ellipsoid. + **********************************************************************/ + Math::real EccentricitySq() const { return _e2; } + + /** + * @return e' 2 = (a2 − + * b2) / b2, the second eccentricity + * squared of the ellipsoid. This is zero, positive, or negative for a + * sphere, oblate ellipsoid, or prolate ellipsoid. + **********************************************************************/ + Math::real SecondEccentricitySq() const { return _e12; } + + /** + * @return e'' 2 = (a2 − + * b2) / (a2 + b2), + * the third eccentricity squared of the ellipsoid. This is zero, + * positive, or negative for a sphere, oblate ellipsoid, or prolate + * ellipsoid. + **********************************************************************/ + Math::real ThirdEccentricitySq() const { return _e2 / (2 - _e2); } + ///@} + + /** \name Latitude conversion. + **********************************************************************/ + ///@{ + + /** + * @param[in] phi the geographic latitude (degrees). + * @return β the parametric latitude (degrees). + * + * The geographic latitude, φ, is the angle between the equatorial + * plane and a vector normal to the surface of the ellipsoid. + * + * The parametric latitude (also called the reduced latitude), β, + * allows the cartesian coordinated of a meridian to be expressed + * conveniently in parametric form as + * - \e R = \e a cos β + * - \e Z = \e b sin β + * . + * where \e a and \e b are the equatorial radius and the polar semi-axis. + * For a sphere β = φ. + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * β lies in [−90°, 90°]. + **********************************************************************/ + Math::real ParametricLatitude(real phi) const; + + /** + * @param[in] beta the parametric latitude (degrees). + * @return φ the geographic latitude (degrees). + * + * β must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * φ lies in [−90°, 90°]. + **********************************************************************/ + Math::real InverseParametricLatitude(real beta) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @return θ the geocentric latitude (degrees). + * + * The geocentric latitude, θ, is the angle between the equatorial + * plane and a line between the center of the ellipsoid and a point on the + * ellipsoid. For a sphere θ = φ. + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * θ lies in [−90°, 90°]. + **********************************************************************/ + Math::real GeocentricLatitude(real phi) const; + + /** + * @param[in] theta the geocentric latitude (degrees). + * @return φ the geographic latitude (degrees). + * + * θ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * φ lies in [−90°, 90°]. + **********************************************************************/ + Math::real InverseGeocentricLatitude(real theta) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @return μ the rectifying latitude (degrees). + * + * The rectifying latitude, μ, has the property that the distance along + * a meridian of the ellipsoid between two points with rectifying latitudes + * μ1 and μ2 is equal to + * (μ2 - μ1) \e L / 90°, + * where \e L = QuarterMeridian(). For a sphere μ = φ. + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * μ lies in [−90°, 90°]. + **********************************************************************/ + Math::real RectifyingLatitude(real phi) const; + + /** + * @param[in] mu the rectifying latitude (degrees). + * @return φ the geographic latitude (degrees). + * + * μ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * φ lies in [−90°, 90°]. + **********************************************************************/ + Math::real InverseRectifyingLatitude(real mu) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @return ξ the authalic latitude (degrees). + * + * The authalic latitude, ξ, has the property that the area of the + * ellipsoid between two circles with authalic latitudes + * ξ1 and ξ2 is equal to (sin + * ξ2 - sin ξ1) \e A / 2, where \e A + * = Area(). For a sphere ξ = φ. + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * ξ lies in [−90°, 90°]. + **********************************************************************/ + Math::real AuthalicLatitude(real phi) const; + + /** + * @param[in] xi the authalic latitude (degrees). + * @return φ the geographic latitude (degrees). + * + * ξ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * φ lies in [−90°, 90°]. + **********************************************************************/ + Math::real InverseAuthalicLatitude(real xi) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @return χ the conformal latitude (degrees). + * + * The conformal latitude, χ, gives the mapping of the ellipsoid to a + * sphere which which is conformal (angles are preserved) and in which the + * equator of the ellipsoid maps to the equator of the sphere. For a + * sphere χ = φ. + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * χ lies in [−90°, 90°]. + **********************************************************************/ + Math::real ConformalLatitude(real phi) const; + + /** + * @param[in] chi the conformal latitude (degrees). + * @return φ the geographic latitude (degrees). + * + * χ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. The returned value + * φ lies in [−90°, 90°]. + **********************************************************************/ + Math::real InverseConformalLatitude(real chi) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @return ψ the isometric latitude (degrees). + * + * The isometric latitude gives the mapping of the ellipsoid to a plane + * which which is conformal (angles are preserved) and in which the equator + * of the ellipsoid maps to a straight line of constant scale; this mapping + * defines the Mercator projection. For a sphere ψ = + * sinh−1 tan φ. + * + * φ must lie in the range [−90°, 90°]; the result is + * undefined if this condition does not hold. The value returned for φ + * = ±90° is some (positive or negative) large but finite value, + * such that InverseIsometricLatitude returns the original value of φ. + **********************************************************************/ + Math::real IsometricLatitude(real phi) const; + + /** + * @param[in] psi the isometric latitude (degrees). + * @return φ the geographic latitude (degrees). + * + * The returned value φ lies in [−90°, 90°]. For a + * sphere φ = tan−1 sinh ψ. + **********************************************************************/ + Math::real InverseIsometricLatitude(real psi) const; + ///@} + + /** \name Other quantities. + **********************************************************************/ + ///@{ + + /** + * @param[in] phi the geographic latitude (degrees). + * @return \e R = \e a cos β the radius of a circle of latitude + * φ (meters). \e R (π/180°) gives meters per degree + * longitude measured along a circle of latitude. + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. + **********************************************************************/ + Math::real CircleRadius(real phi) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @return \e Z = \e b sin β the distance of a circle of latitude + * φ from the equator measured parallel to the ellipsoid axis + * (meters). + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. + **********************************************************************/ + Math::real CircleHeight(real phi) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @return \e s the distance along a meridian + * between the equator and a point of latitude φ (meters). \e s is + * given by \e s = μ \e L / 90°, where \e L = + * QuarterMeridian()). + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. + **********************************************************************/ + Math::real MeridianDistance(real phi) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @return ρ the meridional radius of curvature of the ellipsoid at + * latitude φ (meters); this is the curvature of the meridian. \e + * rho is given by ρ = (180°/π) d\e s / dφ, + * where \e s = MeridianDistance(); thus ρ (π/180°) + * gives meters per degree latitude measured along a meridian. + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. + **********************************************************************/ + Math::real MeridionalCurvatureRadius(real phi) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @return ν the transverse radius of curvature of the ellipsoid at + * latitude φ (meters); this is the curvature of a curve on the + * ellipsoid which also lies in a plane perpendicular to the ellipsoid + * and to the meridian. ν is related to \e R = CircleRadius() by \e + * R = ν cos φ. + * + * φ must lie in the range [−90°, 90°]; the + * result is undefined if this condition does not hold. + **********************************************************************/ + Math::real TransverseCurvatureRadius(real phi) const; + + /** + * @param[in] phi the geographic latitude (degrees). + * @param[in] azi the angle between the meridian and the normal section + * (degrees). + * @return the radius of curvature of the ellipsoid in the normal + * section at latitude φ inclined at an angle \e azi to the + * meridian (meters). + * + * φ must lie in the range [−90°, 90°]; the result is + * undefined this condition does not hold. + **********************************************************************/ + Math::real NormalCurvatureRadius(real phi, real azi) const; + ///@} + + /** \name Eccentricity conversions. + **********************************************************************/ + ///@{ + + /** + * @param[in] fp = \e f ' = (\e a − \e b) / \e b, the second + * flattening. + * @return \e f = (\e a − \e b) / \e a, the flattening. + * + * \e f ' should lie in (−1, ∞). + * The returned value \e f lies in (−∞, 1). + **********************************************************************/ + static Math::real SecondFlatteningToFlattening(real fp) + { return fp / (1 + fp); } + + /** + * @param[in] f = (\e a − \e b) / \e a, the flattening. + * @return \e f ' = (\e a − \e b) / \e b, the second flattening. + * + * \e f should lie in (−∞, 1). + * The returned value \e f ' lies in (−1, ∞). + **********************************************************************/ + static Math::real FlatteningToSecondFlattening(real f) + { return f / (1 - f); } + + /** + * @param[in] n = (\e a − \e b) / (\e a + \e b), the third + * flattening. + * @return \e f = (\e a − \e b) / \e a, the flattening. + * + * \e n should lie in (−1, 1). + * The returned value \e f lies in (−∞, 1). + **********************************************************************/ + static Math::real ThirdFlatteningToFlattening(real n) + { return 2 * n / (1 + n); } + + /** + * @param[in] f = (\e a − \e b) / \e a, the flattening. + * @return \e n = (\e a − \e b) / (\e a + \e b), the third + * flattening. + * + * \e f should lie in (−∞, 1). + * The returned value \e n lies in (−1, 1). + **********************************************************************/ + static Math::real FlatteningToThirdFlattening(real f) + { return f / (2 - f); } + + /** + * @param[in] e2 = e2 = (a2 − + * b2) / a2, the eccentricity + * squared. + * @return \e f = (\e a − \e b) / \e a, the flattening. + * + * e2 should lie in (−∞, 1). + * The returned value \e f lies in (−∞, 1). + **********************************************************************/ + static Math::real EccentricitySqToFlattening(real e2) + { using std::sqrt; return e2 / (sqrt(1 - e2) + 1); } + + /** + * @param[in] f = (\e a − \e b) / \e a, the flattening. + * @return e2 = (a2 − + * b2) / a2, the eccentricity + * squared. + * + * \e f should lie in (−∞, 1). + * The returned value e2 lies in (−∞, 1). + **********************************************************************/ + static Math::real FlatteningToEccentricitySq(real f) + { return f * (2 - f); } + + /** + * @param[in] ep2 = e' 2 = (a2 − + * b2) / b2, the second eccentricity + * squared. + * @return \e f = (\e a − \e b) / \e a, the flattening. + * + * e' 2 should lie in (−1, ∞). + * The returned value \e f lies in (−∞, 1). + **********************************************************************/ + static Math::real SecondEccentricitySqToFlattening(real ep2) + { using std::sqrt; return ep2 / (sqrt(1 + ep2) + 1 + ep2); } + + /** + * @param[in] f = (\e a − \e b) / \e a, the flattening. + * @return e' 2 = (a2 − + * b2) / b2, the second eccentricity + * squared. + * + * \e f should lie in (−∞, 1). + * The returned value e' 2 lies in (−1, ∞). + **********************************************************************/ + static Math::real FlatteningToSecondEccentricitySq(real f) + { return f * (2 - f) / Math::sq(1 - f); } + + /** + * @param[in] epp2 = e'' 2 = (a2 + * − b2) / (a2 + + * b2), the third eccentricity squared. + * @return \e f = (\e a − \e b) / \e a, the flattening. + * + * e'' 2 should lie in (−1, 1). + * The returned value \e f lies in (−∞, 1). + **********************************************************************/ + static Math::real ThirdEccentricitySqToFlattening(real epp2) { + using std::sqrt; + return 2 * epp2 / (sqrt((1 - epp2) * (1 + epp2)) + 1 + epp2); + } + + /** + * @param[in] f = (\e a − \e b) / \e a, the flattening. + * @return e'' 2 = (a2 − + * b2) / (a2 + b2), + * the third eccentricity squared. + * + * \e f should lie in (−∞, 1). + * The returned value e'' 2 lies in (−1, 1). + **********************************************************************/ + static Math::real FlatteningToThirdEccentricitySq(real f) + { return f * (2 - f) / (1 + Math::sq(1 - f)); } + + ///@} + + /** + * A global instantiation of Ellipsoid with the parameters for the WGS84 + * ellipsoid. + **********************************************************************/ + static const Ellipsoid& WGS84(); + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_ELLIPSOID_HPP diff --git a/external/include/GeographicLib/EllipticFunction.hpp b/external/include/GeographicLib/EllipticFunction.hpp new file mode 100644 index 0000000..0a353a9 --- /dev/null +++ b/external/include/GeographicLib/EllipticFunction.hpp @@ -0,0 +1,702 @@ +/** + * \file EllipticFunction.hpp + * \brief Header for GeographicLib::EllipticFunction class + * + * Copyright (c) Charles Karney (2008-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_ELLIPTICFUNCTION_HPP) +#define GEOGRAPHICLIB_ELLIPTICFUNCTION_HPP 1 + +#include + +namespace GeographicLib { + + /** + * \brief Elliptic integrals and functions + * + * This provides the elliptic functions and integrals needed for Ellipsoid, + * GeodesicExact, and TransverseMercatorExact. Two categories of function + * are provided: + * - \e static functions to compute symmetric elliptic integrals + * (https://dlmf.nist.gov/19.16.i) + * - \e member functions to compute Legrendre's elliptic + * integrals (https://dlmf.nist.gov/19.2.ii) and the + * Jacobi elliptic functions (https://dlmf.nist.gov/22.2). + * . + * In the latter case, an object is constructed giving the modulus \e k (and + * optionally the parameter α2). The modulus is always + * passed as its square k2 which allows \e k to be pure + * imaginary (k2 < 0). (Confusingly, Abramowitz and + * Stegun call \e m = k2 the "parameter" and \e n = + * α2 the "characteristic".) + * + * In geodesic applications, it is convenient to separate the incomplete + * integrals into secular and periodic components, e.g., + * \f[ + * E(\phi, k) = (2 E(k) / \pi) [ \phi + \delta E(\phi, k) ] + * \f] + * where δ\e E(φ, \e k) is an odd periodic function with period + * π. + * + * The computation of the elliptic integrals uses the algorithms given in + * - B. C. Carlson, + * Computation of real or + * complex elliptic integrals, Numerical Algorithms 10, 13--26 (1995) + * . + * with the additional optimizations given in https://dlmf.nist.gov/19.36.i. + * The computation of the Jacobi elliptic functions uses the algorithm given + * in + * - R. Bulirsch, + * Numerical Calculation of + * Elliptic Integrals and Elliptic Functions, Numericshe Mathematik 7, + * 78--90 (1965). + * . + * The notation follows https://dlmf.nist.gov/19 and https://dlmf.nist.gov/22 + * + * Example of use: + * \include example-EllipticFunction.cpp + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT EllipticFunction { + private: + typedef Math::real real; + + enum { num_ = 13 }; // Max depth required for sncndn; probably 5 is enough. + real _k2, _kp2, _alpha2, _alphap2, _eps; + real _Kc, _Ec, _Dc, _Pic, _Gc, _Hc; + public: + /** \name Constructor + **********************************************************************/ + ///@{ + /** + * Constructor specifying the modulus and parameter. + * + * @param[in] k2 the square of the modulus k2. + * k2 must lie in (−∞, 1]. + * @param[in] alpha2 the parameter α2. + * α2 must lie in (−∞, 1]. + * @exception GeographicErr if \e k2 or \e alpha2 is out of its legal + * range. + * + * If only elliptic integrals of the first and second kinds are needed, + * then set α2 = 0 (the default value); in this case, we + * have Π(φ, 0, \e k) = \e F(φ, \e k), \e G(φ, 0, \e k) = \e + * E(φ, \e k), and \e H(φ, 0, \e k) = \e F(φ, \e k) - \e + * D(φ, \e k). + **********************************************************************/ + EllipticFunction(real k2 = 0, real alpha2 = 0) + { Reset(k2, alpha2); } + + /** + * Constructor specifying the modulus and parameter and their complements. + * + * @param[in] k2 the square of the modulus k2. + * k2 must lie in (−∞, 1]. + * @param[in] alpha2 the parameter α2. + * α2 must lie in (−∞, 1]. + * @param[in] kp2 the complementary modulus squared k'2 = + * 1 − k2. This must lie in [0, ∞). + * @param[in] alphap2 the complementary parameter α'2 = 1 + * − α2. This must lie in [0, ∞). + * @exception GeographicErr if \e k2, \e alpha2, \e kp2, or \e alphap2 is + * out of its legal range. + * + * The arguments must satisfy \e k2 + \e kp2 = 1 and \e alpha2 + \e alphap2 + * = 1. (No checking is done that these conditions are met.) This + * constructor is provided to enable accuracy to be maintained, e.g., when + * \e k is very close to unity. + **********************************************************************/ + EllipticFunction(real k2, real alpha2, real kp2, real alphap2) + { Reset(k2, alpha2, kp2, alphap2); } + + /** + * Reset the modulus and parameter. + * + * @param[in] k2 the new value of square of the modulus + * k2 which must lie in (−∞, ]. + * done.) + * @param[in] alpha2 the new value of parameter α2. + * α2 must lie in (−∞, 1]. + * @exception GeographicErr if \e k2 or \e alpha2 is out of its legal + * range. + **********************************************************************/ + void Reset(real k2 = 0, real alpha2 = 0) + { Reset(k2, alpha2, 1 - k2, 1 - alpha2); } + + /** + * Reset the modulus and parameter supplying also their complements. + * + * @param[in] k2 the square of the modulus k2. + * k2 must lie in (−∞, 1]. + * @param[in] alpha2 the parameter α2. + * α2 must lie in (−∞, 1]. + * @param[in] kp2 the complementary modulus squared k'2 = + * 1 − k2. This must lie in [0, ∞). + * @param[in] alphap2 the complementary parameter α'2 = 1 + * − α2. This must lie in [0, ∞). + * @exception GeographicErr if \e k2, \e alpha2, \e kp2, or \e alphap2 is + * out of its legal range. + * + * The arguments must satisfy \e k2 + \e kp2 = 1 and \e alpha2 + \e alphap2 + * = 1. (No checking is done that these conditions are met.) This + * constructor is provided to enable accuracy to be maintained, e.g., when + * is very small. + **********************************************************************/ + void Reset(real k2, real alpha2, real kp2, real alphap2); + + ///@} + + /** \name Inspector functions. + **********************************************************************/ + ///@{ + /** + * @return the square of the modulus k2. + **********************************************************************/ + Math::real k2() const { return _k2; } + + /** + * @return the square of the complementary modulus k'2 = + * 1 − k2. + **********************************************************************/ + Math::real kp2() const { return _kp2; } + + /** + * @return the parameter α2. + **********************************************************************/ + Math::real alpha2() const { return _alpha2; } + + /** + * @return the complementary parameter α'2 = 1 − + * α2. + **********************************************************************/ + Math::real alphap2() const { return _alphap2; } + ///@} + + /** \name Complete elliptic integrals. + **********************************************************************/ + ///@{ + /** + * The complete integral of the first kind. + * + * @return \e K(\e k). + * + * \e K(\e k) is defined in https://dlmf.nist.gov/19.2.E4 + * \f[ + * K(k) = \int_0^{\pi/2} \frac1{\sqrt{1-k^2\sin^2\phi}}\,d\phi. + * \f] + **********************************************************************/ + Math::real K() const { return _Kc; } + + /** + * The complete integral of the second kind. + * + * @return \e E(\e k). + * + * \e E(\e k) is defined in https://dlmf.nist.gov/19.2.E5 + * \f[ + * E(k) = \int_0^{\pi/2} \sqrt{1-k^2\sin^2\phi}\,d\phi. + * \f] + **********************************************************************/ + Math::real E() const { return _Ec; } + + /** + * Jahnke's complete integral. + * + * @return \e D(\e k). + * + * \e D(\e k) is defined in https://dlmf.nist.gov/19.2.E6 + * \f[ + * D(k) = + * \int_0^{\pi/2} \frac{\sin^2\phi}{\sqrt{1-k^2\sin^2\phi}}\,d\phi. + * \f] + **********************************************************************/ + Math::real D() const { return _Dc; } + + /** + * The difference between the complete integrals of the first and second + * kinds. + * + * @return \e K(\e k) − \e E(\e k). + **********************************************************************/ + Math::real KE() const { return _k2 * _Dc; } + + /** + * The complete integral of the third kind. + * + * @return Π(α2, \e k). + * + * Π(α2, \e k) is defined in + * https://dlmf.nist.gov/19.2.E7 + * \f[ + * \Pi(\alpha^2, k) = \int_0^{\pi/2} + * \frac1{\sqrt{1-k^2\sin^2\phi}(1 - \alpha^2\sin^2\phi)}\,d\phi. + * \f] + **********************************************************************/ + Math::real Pi() const { return _Pic; } + + /** + * Legendre's complete geodesic longitude integral. + * + * @return \e G(α2, \e k). + * + * \e G(α2, \e k) is given by + * \f[ + * G(\alpha^2, k) = \int_0^{\pi/2} + * \frac{\sqrt{1-k^2\sin^2\phi}}{1 - \alpha^2\sin^2\phi}\,d\phi. + * \f] + **********************************************************************/ + Math::real G() const { return _Gc; } + + /** + * Cayley's complete geodesic longitude difference integral. + * + * @return \e H(α2, \e k). + * + * \e H(α2, \e k) is given by + * \f[ + * H(\alpha^2, k) = \int_0^{\pi/2} + * \frac{\cos^2\phi}{(1-\alpha^2\sin^2\phi)\sqrt{1-k^2\sin^2\phi}} + * \,d\phi. + * \f] + **********************************************************************/ + Math::real H() const { return _Hc; } + ///@} + + /** \name Incomplete elliptic integrals. + **********************************************************************/ + ///@{ + /** + * The incomplete integral of the first kind. + * + * @param[in] phi + * @return \e F(φ, \e k). + * + * \e F(φ, \e k) is defined in https://dlmf.nist.gov/19.2.E4 + * \f[ + * F(\phi, k) = \int_0^\phi \frac1{\sqrt{1-k^2\sin^2\theta}}\,d\theta. + * \f] + **********************************************************************/ + Math::real F(real phi) const; + + /** + * The incomplete integral of the second kind. + * + * @param[in] phi + * @return \e E(φ, \e k). + * + * \e E(φ, \e k) is defined in https://dlmf.nist.gov/19.2.E5 + * \f[ + * E(\phi, k) = \int_0^\phi \sqrt{1-k^2\sin^2\theta}\,d\theta. + * \f] + **********************************************************************/ + Math::real E(real phi) const; + + /** + * The incomplete integral of the second kind with the argument given in + * degrees. + * + * @param[in] ang in degrees. + * @return \e E(π ang/180, \e k). + **********************************************************************/ + Math::real Ed(real ang) const; + + /** + * The inverse of the incomplete integral of the second kind. + * + * @param[in] x + * @return φ = E−1(\e x, \e k); i.e., the + * solution of such that \e E(φ, \e k) = \e x. + **********************************************************************/ + Math::real Einv(real x) const; + + /** + * The incomplete integral of the third kind. + * + * @param[in] phi + * @return Π(φ, α2, \e k). + * + * Π(φ, α2, \e k) is defined in + * https://dlmf.nist.gov/19.2.E7 + * \f[ + * \Pi(\phi, \alpha^2, k) = \int_0^\phi + * \frac1{\sqrt{1-k^2\sin^2\theta}(1 - \alpha^2\sin^2\theta)}\,d\theta. + * \f] + **********************************************************************/ + Math::real Pi(real phi) const; + + /** + * Jahnke's incomplete elliptic integral. + * + * @param[in] phi + * @return \e D(φ, \e k). + * + * \e D(φ, \e k) is defined in https://dlmf.nist.gov/19.2.E4 + * \f[ + * D(\phi, k) = \int_0^\phi + * \frac{\sin^2\theta}{\sqrt{1-k^2\sin^2\theta}}\,d\theta. + * \f] + **********************************************************************/ + Math::real D(real phi) const; + + /** + * Legendre's geodesic longitude integral. + * + * @param[in] phi + * @return \e G(φ, α2, \e k). + * + * \e G(φ, α2, \e k) is defined by + * \f[ + * \begin{align} + * G(\phi, \alpha^2, k) &= + * \frac{k^2}{\alpha^2} F(\phi, k) + + * \biggl(1 - \frac{k^2}{\alpha^2}\biggr) \Pi(\phi, \alpha^2, k) \\ + * &= \int_0^\phi + * \frac{\sqrt{1-k^2\sin^2\theta}}{1 - \alpha^2\sin^2\theta}\,d\theta. + * \end{align} + * \f] + * + * Legendre expresses the longitude of a point on the geodesic in terms of + * this combination of elliptic integrals in Exercices de Calcul + * Intégral, Vol. 1 (1811), p. 181, + * https://books.google.com/books?id=riIOAAAAQAAJ&pg=PA181. + * + * See \ref geodellip for the expression for the longitude in terms of this + * function. + **********************************************************************/ + Math::real G(real phi) const; + + /** + * Cayley's geodesic longitude difference integral. + * + * @param[in] phi + * @return \e H(φ, α2, \e k). + * + * \e H(φ, α2, \e k) is defined by + * \f[ + * \begin{align} + * H(\phi, \alpha^2, k) &= + * \frac1{\alpha^2} F(\phi, k) + + * \biggl(1 - \frac1{\alpha^2}\biggr) \Pi(\phi, \alpha^2, k) \\ + * &= \int_0^\phi + * \frac{\cos^2\theta} + * {(1-\alpha^2\sin^2\theta)\sqrt{1-k^2\sin^2\theta}} + * \,d\theta. + * \end{align} + * \f] + * + * Cayley expresses the longitude difference of a point on the geodesic in + * terms of this combination of elliptic integrals in Phil. Mag. 40 + * (1870), p. 333, https://books.google.com/books?id=Zk0wAAAAIAAJ&pg=PA333. + * + * See \ref geodellip for the expression for the longitude in terms of this + * function. + **********************************************************************/ + Math::real H(real phi) const; + ///@} + + /** \name Incomplete integrals in terms of Jacobi elliptic functions. + **********************************************************************/ + ///@{ + /** + * The incomplete integral of the first kind in terms of Jacobi elliptic + * functions. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return \e F(φ, \e k) as though φ ∈ (−π, π]. + **********************************************************************/ + Math::real F(real sn, real cn, real dn) const; + + /** + * The incomplete integral of the second kind in terms of Jacobi elliptic + * functions. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return \e E(φ, \e k) as though φ ∈ (−π, π]. + **********************************************************************/ + Math::real E(real sn, real cn, real dn) const; + + /** + * The incomplete integral of the third kind in terms of Jacobi elliptic + * functions. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return Π(φ, α2, \e k) as though φ ∈ + * (−π, π]. + **********************************************************************/ + Math::real Pi(real sn, real cn, real dn) const; + + /** + * Jahnke's incomplete elliptic integral in terms of Jacobi elliptic + * functions. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return \e D(φ, \e k) as though φ ∈ (−π, π]. + **********************************************************************/ + Math::real D(real sn, real cn, real dn) const; + + /** + * Legendre's geodesic longitude integral in terms of Jacobi elliptic + * functions. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return \e G(φ, α2, \e k) as though φ ∈ + * (−π, π]. + **********************************************************************/ + Math::real G(real sn, real cn, real dn) const; + + /** + * Cayley's geodesic longitude difference integral in terms of Jacobi + * elliptic functions. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return \e H(φ, α2, \e k) as though φ ∈ + * (−π, π]. + **********************************************************************/ + Math::real H(real sn, real cn, real dn) const; + ///@} + + /** \name Periodic versions of incomplete elliptic integrals. + **********************************************************************/ + ///@{ + /** + * The periodic incomplete integral of the first kind. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return the periodic function π \e F(φ, \e k) / (2 \e K(\e k)) - + * φ. + **********************************************************************/ + Math::real deltaF(real sn, real cn, real dn) const; + + /** + * The periodic incomplete integral of the second kind. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return the periodic function π \e E(φ, \e k) / (2 \e E(\e k)) - + * φ. + **********************************************************************/ + Math::real deltaE(real sn, real cn, real dn) const; + + /** + * The periodic inverse of the incomplete integral of the second kind. + * + * @param[in] stau = sinτ. + * @param[in] ctau = sinτ. + * @return the periodic function E−1(τ (2 \e + * E(\e k)/π), \e k) - τ. + **********************************************************************/ + Math::real deltaEinv(real stau, real ctau) const; + + /** + * The periodic incomplete integral of the third kind. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return the periodic function π Π(φ, α2, + * \e k) / (2 Π(α2, \e k)) - φ. + **********************************************************************/ + Math::real deltaPi(real sn, real cn, real dn) const; + + /** + * The periodic Jahnke's incomplete elliptic integral. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return the periodic function π \e D(φ, \e k) / (2 \e D(\e k)) - + * φ. + **********************************************************************/ + Math::real deltaD(real sn, real cn, real dn) const; + + /** + * Legendre's periodic geodesic longitude integral. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return the periodic function π \e G(φ, \e k) / (2 \e G(\e k)) - + * φ. + **********************************************************************/ + Math::real deltaG(real sn, real cn, real dn) const; + + /** + * Cayley's periodic geodesic longitude difference integral. + * + * @param[in] sn = sinφ. + * @param[in] cn = cosφ. + * @param[in] dn = sqrt(1 − k2 + * sin2φ). + * @return the periodic function π \e H(φ, \e k) / (2 \e H(\e k)) - + * φ. + **********************************************************************/ + Math::real deltaH(real sn, real cn, real dn) const; + ///@} + + /** \name Elliptic functions. + **********************************************************************/ + ///@{ + /** + * The Jacobi elliptic functions. + * + * @param[in] x the argument. + * @param[out] sn sn(\e x, \e k). + * @param[out] cn cn(\e x, \e k). + * @param[out] dn dn(\e x, \e k). + **********************************************************************/ + void sncndn(real x, real& sn, real& cn, real& dn) const; + + /** + * The Δ amplitude function. + * + * @param[in] sn sinφ. + * @param[in] cn cosφ. + * @return Δ = sqrt(1 − k2 + * sin2φ). + **********************************************************************/ + Math::real Delta(real sn, real cn) const { + using std::sqrt; + return sqrt(_k2 < 0 ? 1 - _k2 * sn*sn : _kp2 + _k2 * cn*cn); + } + ///@} + + /** \name Symmetric elliptic integrals. + **********************************************************************/ + ///@{ + /** + * Symmetric integral of the first kind RF. + * + * @param[in] x + * @param[in] y + * @param[in] z + * @return RF(\e x, \e y, \e z). + * + * RF is defined in https://dlmf.nist.gov/19.16.E1 + * \f[ R_F(x, y, z) = \frac12 + * \int_0^\infty\frac1{\sqrt{(t + x) (t + y) (t + z)}}\, dt \f] + * If one of the arguments is zero, it is more efficient to call the + * two-argument version of this function with the non-zero arguments. + **********************************************************************/ + static real RF(real x, real y, real z); + + /** + * Complete symmetric integral of the first kind, + * RF with one argument zero. + * + * @param[in] x + * @param[in] y + * @return RF(\e x, \e y, 0). + **********************************************************************/ + static real RF(real x, real y); + + /** + * Degenerate symmetric integral of the first kind + * RC. + * + * @param[in] x + * @param[in] y + * @return RC(\e x, \e y) = + * RF(\e x, \e y, \e y). + * + * RC is defined in https://dlmf.nist.gov/19.2.E17 + * \f[ R_C(x, y) = \frac12 + * \int_0^\infty\frac1{\sqrt{t + x}(t + y)}\,dt \f] + **********************************************************************/ + static real RC(real x, real y); + + /** + * Symmetric integral of the second kind RG. + * + * @param[in] x + * @param[in] y + * @param[in] z + * @return RG(\e x, \e y, \e z). + * + * RG is defined in Carlson, eq 1.5 + * \f[ R_G(x, y, z) = \frac14 + * \int_0^\infty[(t + x) (t + y) (t + z)]^{-1/2} + * \biggl( + * \frac x{t + x} + \frac y{t + y} + \frac z{t + z} + * \biggr)t\,dt \f] + * See also https://dlmf.nist.gov/19.16.E3. + * If one of the arguments is zero, it is more efficient to call the + * two-argument version of this function with the non-zero arguments. + **********************************************************************/ + static real RG(real x, real y, real z); + + /** + * Complete symmetric integral of the second kind, + * RG with one argument zero. + * + * @param[in] x + * @param[in] y + * @return RG(\e x, \e y, 0). + **********************************************************************/ + static real RG(real x, real y); + + /** + * Symmetric integral of the third kind RJ. + * + * @param[in] x + * @param[in] y + * @param[in] z + * @param[in] p + * @return RJ(\e x, \e y, \e z, \e p). + * + * RJ is defined in https://dlmf.nist.gov/19.16.E2 + * \f[ R_J(x, y, z, p) = \frac32 + * \int_0^\infty + * [(t + x) (t + y) (t + z)]^{-1/2} (t + p)^{-1}\, dt \f] + **********************************************************************/ + static real RJ(real x, real y, real z, real p); + + /** + * Degenerate symmetric integral of the third kind + * RD. + * + * @param[in] x + * @param[in] y + * @param[in] z + * @return RD(\e x, \e y, \e z) = + * RJ(\e x, \e y, \e z, \e z). + * + * RD is defined in https://dlmf.nist.gov/19.16.E5 + * \f[ R_D(x, y, z) = \frac32 + * \int_0^\infty[(t + x) (t + y)]^{-1/2} (t + z)^{-3/2}\, dt \f] + **********************************************************************/ + static real RD(real x, real y, real z); + ///@} + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_ELLIPTICFUNCTION_HPP diff --git a/external/include/GeographicLib/GARS.hpp b/external/include/GeographicLib/GARS.hpp new file mode 100644 index 0000000..9cc1212 --- /dev/null +++ b/external/include/GeographicLib/GARS.hpp @@ -0,0 +1,143 @@ +/** + * \file GARS.hpp + * \brief Header for GeographicLib::GARS class + * + * Copyright (c) Charles Karney (2015-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GARS_HPP) +#define GEOGRAPHICLIB_GARS_HPP 1 + +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs string +# pragma warning (push) +# pragma warning (disable: 4251) +#endif + +namespace GeographicLib { + + /** + * \brief Conversions for the Global Area Reference System (GARS) + * + * The Global Area Reference System is described in + * - https://en.wikipedia.org/wiki/Global_Area_Reference_System + * - https://earth-info.nga.mil/index.php?dir=coordsys&action=coordsys#tab_gars + * . + * It provides a compact string representation of a geographic area + * (expressed as latitude and longitude). The classes Georef and Geohash + * implement similar compact representations. + * + * Example of use: + * \include example-GARS.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT GARS { + private: + typedef Math::real real; + static const char* const digits_; + static const char* const letters_; + enum { + lonorig_ = -180, // Origin for longitude + latorig_ = -90, // Origin for latitude + baselon_ = 10, // Base for longitude tiles + baselat_ = 24, // Base for latitude tiles + lonlen_ = 3, + latlen_ = 2, + baselen_ = lonlen_ + latlen_, + mult1_ = 2, // base precision = 1/2 degree + mult2_ = 2, // 6th char gives 2x more precision + mult3_ = 3, // 7th char gives 3x more precision + m_ = mult1_ * mult2_ * mult3_, + maxprec_ = 2, + maxlen_ = baselen_ + maxprec_, + }; + GARS(); // Disable constructor + + public: + + /** + * Convert from geographic coordinates to GARS. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[in] prec the precision of the resulting GARS. + * @param[out] gars the GARS string. + * @exception GeographicErr if \e lat is not in [−90°, + * 90°]. + * @exception std::bad_alloc if memory for \e gars can't be allocated. + * + * \e prec specifies the precision of \e gars as follows: + * - \e prec = 0 (min), 30' precision, e.g., 006AG; + * - \e prec = 1, 15' precision, e.g., 006AG3; + * - \e prec = 2 (max), 5' precision, e.g., 006AG39. + * + * If \e lat or \e lon is NaN, then \e gars is set to "INVALID". + **********************************************************************/ + static void Forward(real lat, real lon, int prec, std::string& gars); + + /** + * Convert from GARS to geographic coordinates. + * + * @param[in] gars the GARS. + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] prec the precision of \e gars. + * @param[in] centerp if true (the default) return the center of the + * \e gars, otherwise return the south-west corner. + * @exception GeographicErr if \e gars is illegal. + * + * The case of the letters in \e gars is ignored. \e prec is in the range + * [0, 2] and gives the precision of \e gars as follows: + * - \e prec = 0 (min), 30' precision, e.g., 006AG; + * - \e prec = 1, 15' precision, e.g., 006AG3; + * - \e prec = 2 (max), 5' precision, e.g., 006AG39. + * + * If the first 3 characters of \e gars are "INV", then \e lat and \e lon + * are set to NaN and \e prec is unchanged. + **********************************************************************/ + static void Reverse(const std::string& gars, real& lat, real& lon, + int& prec, bool centerp = true); + + /** + * The angular resolution of a GARS. + * + * @param[in] prec the precision of the GARS. + * @return the latitude-longitude resolution (degrees). + * + * Internally, \e prec is first put in the range [0, 2]. + **********************************************************************/ + static Math::real Resolution(int prec) { + return 1/real(prec <= 0 ? mult1_ : (prec == 1 ? mult1_ * mult2_ : + mult1_ * mult2_ * mult3_)); + } + + /** + * The GARS precision required to meet a given geographic resolution. + * + * @param[in] res the minimum of resolution in latitude and longitude + * (degrees). + * @return GARS precision. + * + * The returned length is in the range [0, 2]. + **********************************************************************/ + static int Precision(real res) { + using std::abs; res = abs(res); + for (int prec = 0; prec < maxprec_; ++prec) + if (Resolution(prec) <= res) + return prec; + return maxprec_; + } + + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_GARS_HPP diff --git a/external/include/GeographicLib/GeoCoords.hpp b/external/include/GeographicLib/GeoCoords.hpp new file mode 100644 index 0000000..95e9f2f --- /dev/null +++ b/external/include/GeographicLib/GeoCoords.hpp @@ -0,0 +1,553 @@ +/** + * \file GeoCoords.hpp + * \brief Header for GeographicLib::GeoCoords class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GEOCOORDS_HPP) +#define GEOGRAPHICLIB_GEOCOORDS_HPP 1 + +#include +#include + +namespace GeographicLib { + + /** + * \brief Conversion between geographic coordinates + * + * This class stores a geographic position which may be set via the + * constructors or Reset via + * - latitude and longitude + * - UTM or UPS coordinates + * - a string representation of these or an MGRS coordinate string + * + * The state consists of the latitude and longitude and the supplied UTM or + * UPS coordinates (possibly derived from the MGRS coordinates). If latitude + * and longitude were given then the UTM/UPS coordinates follows the standard + * conventions. + * + * The mutable state consists of the UTM or UPS coordinates for a alternate + * zone. A method SetAltZone is provided to set the alternate UPS/UTM zone. + * + * Methods are provided to return the geographic coordinates, the input UTM + * or UPS coordinates (and associated meridian convergence and scale), or + * alternate UTM or UPS coordinates (and their associated meridian + * convergence and scale). + * + * Once the input string has been parsed, you can print the result out in any + * of the formats, decimal degrees, degrees minutes seconds, MGRS, UTM/UPS. + * + * Example of use: + * \include example-GeoCoords.cpp + * + * GeoConvert is a command-line utility + * providing access to the functionality of GeoCoords. + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT GeoCoords { + private: + typedef Math::real real; + real _lat, _long, _easting, _northing, _gamma, _k; + bool _northp; + int _zone; // See UTMUPS::zonespec + mutable real _alt_easting, _alt_northing, _alt_gamma, _alt_k; + mutable int _alt_zone; + + void CopyToAlt() const { + _alt_easting = _easting; + _alt_northing = _northing; + _alt_gamma = _gamma; + _alt_k = _k; + _alt_zone = _zone; + } + static void UTMUPSString(int zone, bool northp, + real easting, real northing, + int prec, bool abbrev, std::string& utm); + void FixHemisphere(); + public: + + /** \name Initializing the GeoCoords object + **********************************************************************/ + ///@{ + /** + * The default constructor sets the coordinate as undefined. + **********************************************************************/ + GeoCoords() + : _lat(Math::NaN()) + , _long(Math::NaN()) + , _easting(Math::NaN()) + , _northing(Math::NaN()) + , _gamma(Math::NaN()) + , _k(Math::NaN()) + , _northp(false) + , _zone(UTMUPS::INVALID) + { CopyToAlt(); } + + /** + * Construct from a string. + * + * @param[in] s 1-element, 2-element, or 3-element string representation of + * the position. + * @param[in] centerp governs the interpretation of MGRS coordinates (see + * below). + * @param[in] longfirst governs the interpretation of geographic + * coordinates (see below). + * @exception GeographicErr if the \e s is malformed (see below). + * + * Parse as a string and interpret it as a geographic position. The input + * string is broken into space (or comma) separated pieces and Basic + * decision on which format is based on number of components + * -# MGRS + * -# "Lat Long" or "Long Lat" + * -# "Zone Easting Northing" or "Easting Northing Zone" + * + * The following inputs are approximately the same (Ar Ramadi Bridge, Iraq) + * - Latitude and Longitude + * - 33.44 43.27 + * - N33d26.4' E43d16.2' + * - 43d16'12"E 33d26'24"N + * - 43:16:12E 33:26:24 + * - MGRS + * - 38SLC30 + * - 38SLC391014 + * - 38SLC3918701405 + * - 37SHT9708 + * - UTM + * - 38n 339188 3701405 + * - 897039 3708229 37n + * + * Latitude and Longitude parsing: Latitude precedes longitude, + * unless a N, S, E, W hemisphere designator is used on one or both + * coordinates. If \e longfirst = true (default is false), then + * longitude precedes latitude in the absence of a hemisphere designator. + * Thus (with \e longfirst = false) + * - 40 -75 + * - N40 W75 + * - -75 N40 + * - 75W 40N + * - E-75 -40S + * . + * are all the same position. The coordinates may be given in + * decimal degrees, degrees and decimal minutes, degrees, minutes, + * seconds, etc. Use d, ', and " to mark off the degrees, + * minutes and seconds. Various alternative symbols for degrees, minutes, + * and seconds are allowed. Alternatively, use : to separate these + * components. A single addition or subtraction is allowed. (See + * DMS::Decode for details.) Thus + * - 40d30'30" + * - 40d30'30 + * - 40°30'30 + * - 40d30.5' + * - 40d30.5 + * - 40:30:30 + * - 40:30.5 + * - 40.508333333 + * - 40:30+0:0:30 + * - 40:31-0:0.5 + * . + * all specify the same angle. The leading sign applies to the following + * components so -1d30 is -(1+30/60) = −1.5. However, note + * that -1:30-0:0:15 is parsed as (-1:30) + (-0:0:15) = −(1+30/60) + * − (15/3600). Latitudes must be in the range [−90°, + * 90°]. Internally longitudes are reduced to the range + * [−180°, 180°]. + * + * UTM/UPS parsing: For UTM zones (−80° ≤ Lat < + * 84°), the zone designator is made up of a zone number (for 1 to 60) + * and a hemisphere letter (n or s), e.g., 38n (38north can also be used). + * The latitude band designer ([C--M] in the southern hemisphere and [N--X] + * in the northern) should NOT be used. (This is part of the MGRS + * coordinate.) The zone designator for the poles (where UPS is employed) + * is a hemisphere letter by itself, i.e., n or s (north or south can also + * be used). + * + * MGRS parsing interprets the grid references as square area at the + * specified precision (1m, 10m, 100m, etc.). If \e centerp = true (the + * default), the center of this square is then taken to be the precise + * position; thus: + * - 38SMB = 38n 450000 3650000 + * - 38SMB4484 = 38n 444500 3684500 + * - 38SMB44148470 = 38n 444145 3684705 + * . + * Otherwise, the "south-west" corner of the square is used, i.e., + * - 38SMB = 38n 400000 3600000 + * - 38SMB4484 = 38n 444000 3684000 + * - 38SMB44148470 = 38n 444140 3684700 + **********************************************************************/ + explicit GeoCoords(const std::string& s, + bool centerp = true, bool longfirst = false) + { Reset(s, centerp, longfirst); } + + /** + * Construct from geographic coordinates. + * + * @param[in] latitude (degrees). + * @param[in] longitude (degrees). + * @param[in] zone if specified, force the UTM/UPS representation to use a + * specified zone using the rules given in UTMUPS::zonespec. + * @exception GeographicErr if \e latitude is not in [−90°, + * 90°]. + * @exception GeographicErr if \e zone cannot be used for this location. + **********************************************************************/ + GeoCoords(real latitude, real longitude, int zone = UTMUPS::STANDARD) { + Reset(latitude, longitude, zone); + } + + /** + * Construct from UTM/UPS coordinates. + * + * @param[in] zone UTM zone (zero means UPS). + * @param[in] northp hemisphere (true means north, false means south). + * @param[in] easting (meters). + * @param[in] northing (meters). + * @exception GeographicErr if \e zone, \e easting, or \e northing is + * outside its allowed range. + **********************************************************************/ + GeoCoords(int zone, bool northp, real easting, real northing) { + Reset(zone, northp, easting, northing); + } + + /** + * Reset the location from a string. See + * GeoCoords(const std::string& s, bool centerp, bool longfirst). + * + * @param[in] s 1-element, 2-element, or 3-element string representation of + * the position. + * @param[in] centerp governs the interpretation of MGRS coordinates. + * @param[in] longfirst governs the interpretation of geographic + * coordinates. + * @exception GeographicErr if the \e s is malformed. + **********************************************************************/ + void Reset(const std::string& s, + bool centerp = true, bool longfirst = false); + + /** + * Reset the location in terms of geographic coordinates. See + * GeoCoords(real latitude, real longitude, int zone). + * + * @param[in] latitude (degrees). + * @param[in] longitude (degrees). + * @param[in] zone if specified, force the UTM/UPS representation to use a + * specified zone using the rules given in UTMUPS::zonespec. + * @exception GeographicErr if \e latitude is not in [−90°, + * 90°]. + * @exception GeographicErr if \e zone cannot be used for this location. + **********************************************************************/ + void Reset(real latitude, real longitude, int zone = UTMUPS::STANDARD) { + UTMUPS::Forward(latitude, longitude, + _zone, _northp, _easting, _northing, _gamma, _k, + zone); + _lat = latitude; + _long = longitude; + if (_long >= 180) _long -= 360; + else if (_long < -180) _long += 360; + CopyToAlt(); + } + + /** + * Reset the location in terms of UPS/UPS coordinates. See + * GeoCoords(int zone, bool northp, real easting, real northing). + * + * @param[in] zone UTM zone (zero means UPS). + * @param[in] northp hemisphere (true means north, false means south). + * @param[in] easting (meters). + * @param[in] northing (meters). + * @exception GeographicErr if \e zone, \e easting, or \e northing is + * outside its allowed range. + **********************************************************************/ + void Reset(int zone, bool northp, real easting, real northing) { + UTMUPS::Reverse(zone, northp, easting, northing, + _lat, _long, _gamma, _k); + _zone = zone; + _northp = northp; + _easting = easting; + _northing = northing; + FixHemisphere(); + CopyToAlt(); + } + ///@} + + /** \name Querying the GeoCoords object + **********************************************************************/ + ///@{ + /** + * @return latitude (degrees) + **********************************************************************/ + Math::real Latitude() const { return _lat; } + + /** + * @return longitude (degrees) + **********************************************************************/ + Math::real Longitude() const { return _long; } + + /** + * @return easting (meters) + **********************************************************************/ + Math::real Easting() const { return _easting; } + + /** + * @return northing (meters) + **********************************************************************/ + Math::real Northing() const { return _northing; } + + /** + * @return meridian convergence (degrees) for the UTM/UPS projection. + **********************************************************************/ + Math::real Convergence() const { return _gamma; } + + /** + * @return scale for the UTM/UPS projection. + **********************************************************************/ + Math::real Scale() const { return _k; } + + /** + * @return hemisphere (false means south, true means north). + **********************************************************************/ + bool Northp() const { return _northp; } + + /** + * @return hemisphere letter n or s. + **********************************************************************/ + char Hemisphere() const { return _northp ? 'n' : 's'; } + + /** + * @return the zone corresponding to the input (return 0 for UPS). + **********************************************************************/ + int Zone() const { return _zone; } + + ///@} + + /** \name Setting and querying the alternate zone + **********************************************************************/ + ///@{ + /** + * Specify alternate zone number. + * + * @param[in] zone zone number for the alternate representation. + * @exception GeographicErr if \e zone cannot be used for this location. + * + * See UTMUPS::zonespec for more information on the interpretation of \e + * zone. Note that \e zone == UTMUPS::STANDARD (the default) use the + * standard UPS or UTM zone, UTMUPS::MATCH does nothing retaining the + * existing alternate representation. Before this is called the alternate + * zone is the input zone. + **********************************************************************/ + void SetAltZone(int zone = UTMUPS::STANDARD) const { + if (zone == UTMUPS::MATCH) + return; + zone = UTMUPS::StandardZone(_lat, _long, zone); + if (zone == _zone) + CopyToAlt(); + else { + bool northp; + UTMUPS::Forward(_lat, _long, + _alt_zone, northp, + _alt_easting, _alt_northing, _alt_gamma, _alt_k, + zone); + } + } + + /** + * @return current alternate zone (return 0 for UPS). + **********************************************************************/ + int AltZone() const { return _alt_zone; } + + /** + * @return easting (meters) for alternate zone. + **********************************************************************/ + Math::real AltEasting() const { return _alt_easting; } + + /** + * @return northing (meters) for alternate zone. + **********************************************************************/ + Math::real AltNorthing() const { return _alt_northing; } + + /** + * @return meridian convergence (degrees) for alternate zone. + **********************************************************************/ + Math::real AltConvergence() const { return _alt_gamma; } + + /** + * @return scale for alternate zone. + **********************************************************************/ + Math::real AltScale() const { return _alt_k; } + ///@} + + /** \name String representations of the GeoCoords object + **********************************************************************/ + ///@{ + /** + * String representation with latitude and longitude as signed decimal + * degrees. + * + * @param[in] prec precision (relative to about 1m). + * @param[in] longfirst if true give longitude first (default = false) + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return decimal latitude/longitude string representation. + * + * Precision specifies accuracy of representation as follows: + * - prec = −5 (min), 1° + * - prec = 0, 10−5° (about 1m) + * - prec = 3, 10−8° + * - prec = 9 (max), 10−14° + **********************************************************************/ + std::string GeoRepresentation(int prec = 0, bool longfirst = false) const; + + /** + * String representation with latitude and longitude as degrees, minutes, + * seconds, and hemisphere. + * + * @param[in] prec precision (relative to about 1m) + * @param[in] longfirst if true give longitude first (default = false) + * @param[in] dmssep if non-null, use as the DMS separator character + * (instead of d, ', " delimiters). + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return DMS latitude/longitude string representation. + * + * Precision specifies accuracy of representation as follows: + * - prec = −5 (min), 1° + * - prec = −4, 0.1° + * - prec = −3, 1' + * - prec = −2, 0.1' + * - prec = −1, 1" + * - prec = 0, 0.1" (about 3m) + * - prec = 1, 0.01" + * - prec = 10 (max), 10−11" + **********************************************************************/ + std::string DMSRepresentation(int prec = 0, bool longfirst = false, + char dmssep = char(0)) + const; + + /** + * MGRS string. + * + * @param[in] prec precision (relative to about 1m). + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return MGRS string. + * + * This gives the coordinates of the enclosing grid square with size given + * by the precision. Thus 38n 444180 3684790 converted to a MGRS + * coordinate at precision −2 (100m) is 38SMB441847 and not + * 38SMB442848. \e prec specifies the precision of the MGRS string as + * follows: + * - prec = −6 (min), only the grid zone is returned, e.g., 38S + * - prec = −5, 100km, e.g., 38SMB + * - prec = −4, 10km + * - prec = −3, 1km + * - prec = −2, 100m + * - prec = −1, 10m + * - prec = 0, 1m + * - prec = 1, 0.1m + * - prec = 6 (max), 1μm + **********************************************************************/ + std::string MGRSRepresentation(int prec = 0) const; + + /** + * UTM/UPS string. + * + * @param[in] prec precision (relative to about 1m) + * @param[in] abbrev if true (the default) use abbreviated (n/s) notation + * for hemisphere; otherwise spell out the hemisphere (north/south) + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return UTM/UPS string representation: zone designator, easting, and + * northing. + * + * Precision specifies accuracy of representation as follows: + * - prec = −5 (min), 100km + * - prec = −3, 1km + * - prec = 0, 1m + * - prec = 3, 1mm + * - prec = 6, 1μm + * - prec = 9 (max), 1nm + **********************************************************************/ + std::string UTMUPSRepresentation(int prec = 0, bool abbrev = true) const; + + /** + * UTM/UPS string with hemisphere override. + * + * @param[in] northp hemisphere override + * @param[in] prec precision (relative to about 1m) + * @param[in] abbrev if true (the default) use abbreviated (n/s) notation + * for hemisphere; otherwise spell out the hemisphere (north/south) + * @exception GeographicErr if the hemisphere override attempts to change + * UPS N to UPS S or vice versa. + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return UTM/UPS string representation: zone designator, easting, and + * northing. + **********************************************************************/ + std::string UTMUPSRepresentation(bool northp, int prec = 0, + bool abbrev = true) const; + + /** + * MGRS string for the alternate zone. See GeoCoords::MGRSRepresentation. + * + * @param[in] prec precision (relative to about 1m). + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return MGRS string. + **********************************************************************/ + std::string AltMGRSRepresentation(int prec = 0) const; + + /** + * UTM/UPS string for the alternate zone. See + * GeoCoords::UTMUPSRepresentation. + * + * @param[in] prec precision (relative to about 1m) + * @param[in] abbrev if true (the default) use abbreviated (n/s) notation + * for hemisphere; otherwise spell out the hemisphere (north/south) + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return UTM/UPS string representation: zone designator, easting, and + * northing. + **********************************************************************/ + std::string AltUTMUPSRepresentation(int prec = 0, bool abbrev = true) + const; + + /** + * UTM/UPS string for the alternate zone, with hemisphere override. + * + * @param[in] northp hemisphere override + * @param[in] prec precision (relative to about 1m) + * @param[in] abbrev if true (the default) use abbreviated (n/s) notation + * for hemisphere; otherwise spell out the hemisphere (north/south) + * @exception GeographicErr if the hemisphere override attempts to change + * UPS n to UPS s or vice verse. + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return UTM/UPS string representation: zone designator, easting, and + * northing. + **********************************************************************/ + std::string AltUTMUPSRepresentation(bool northp, int prec = 0, + bool abbrev = true) const; + ///@} + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the WGS84 ellipsoid (meters). + * + * (The WGS84 value is returned because the UTM and UPS projections are + * based on this ellipsoid.) + **********************************************************************/ + Math::real EquatorialRadius() const { return UTMUPS::EquatorialRadius(); } + + /** + * @return \e f the flattening of the WGS84 ellipsoid. + * + * (The WGS84 value is returned because the UTM and UPS projections are + * based on this ellipsoid.) + **********************************************************************/ + Math::real Flattening() const { return UTMUPS::Flattening(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_GEOCOORDS_HPP diff --git a/external/include/GeographicLib/Geocentric.hpp b/external/include/GeographicLib/Geocentric.hpp new file mode 100644 index 0000000..186df9a --- /dev/null +++ b/external/include/GeographicLib/Geocentric.hpp @@ -0,0 +1,274 @@ +/** + * \file Geocentric.hpp + * \brief Header for GeographicLib::Geocentric class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GEOCENTRIC_HPP) +#define GEOGRAPHICLIB_GEOCENTRIC_HPP 1 + +#include +#include + +namespace GeographicLib { + + /** + * \brief %Geocentric coordinates + * + * Convert between geodetic coordinates latitude = \e lat, longitude = \e + * lon, height = \e h (measured vertically from the surface of the ellipsoid) + * to geocentric coordinates (\e X, \e Y, \e Z). The origin of geocentric + * coordinates is at the center of the earth. The \e Z axis goes thru the + * north pole, \e lat = 90°. The \e X axis goes thru \e lat = 0, + * \e lon = 0. %Geocentric coordinates are also known as earth centered, + * earth fixed (ECEF) coordinates. + * + * The conversion from geographic to geocentric coordinates is + * straightforward. For the reverse transformation we use + * - H. Vermeille, + * Direct + * transformation from geocentric coordinates to geodetic coordinates, + * J. Geodesy 76, 451--454 (2002). + * . + * Several changes have been made to ensure that the method returns accurate + * results for all finite inputs (even if \e h is infinite). The changes are + * described in Appendix B of + * - C. F. F. Karney, + * Geodesics + * on an ellipsoid of revolution, + * Feb. 2011; + * preprint + * arxiv:1102.1215v1. + * . + * Vermeille similarly updated his method in + * - H. Vermeille, + * + * An analytical method to transform geocentric into + * geodetic coordinates, J. Geodesy 85, 105--117 (2011). + * . + * See \ref geocentric for more information. + * + * The errors in these routines are close to round-off. Specifically, for + * points within 5000 km of the surface of the ellipsoid (either inside or + * outside the ellipsoid), the error is bounded by 7 nm (7 nanometers) for + * the WGS84 ellipsoid. See \ref geocentric for further information on the + * errors. + * + * Example of use: + * \include example-Geocentric.cpp + * + * CartConvert is a command-line utility + * providing access to the functionality of Geocentric and LocalCartesian. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT Geocentric { + private: + typedef Math::real real; + friend class LocalCartesian; + friend class MagneticCircle; // MagneticCircle uses Rotation + friend class MagneticModel; // MagneticModel uses IntForward + friend class GravityCircle; // GravityCircle uses Rotation + friend class GravityModel; // GravityModel uses IntForward + friend class NormalGravity; // NormalGravity uses IntForward + static const size_t dim_ = 3; + static const size_t dim2_ = dim_ * dim_; + real _a, _f, _e2, _e2m, _e2a, _e4a, _maxrad; + static void Rotation(real sphi, real cphi, real slam, real clam, + real M[dim2_]); + static void Rotate(const real M[dim2_], real x, real y, real z, + real& X, real& Y, real& Z) { + // Perform [X,Y,Z]^t = M.[x,y,z]^t + // (typically local cartesian to geocentric) + X = M[0] * x + M[1] * y + M[2] * z; + Y = M[3] * x + M[4] * y + M[5] * z; + Z = M[6] * x + M[7] * y + M[8] * z; + } + static void Unrotate(const real M[dim2_], real X, real Y, real Z, + real& x, real& y, real& z) { + // Perform [x,y,z]^t = M^t.[X,Y,Z]^t + // (typically geocentric to local cartesian) + x = M[0] * X + M[3] * Y + M[6] * Z; + y = M[1] * X + M[4] * Y + M[7] * Z; + z = M[2] * X + M[5] * Y + M[8] * Z; + } + void IntForward(real lat, real lon, real h, real& X, real& Y, real& Z, + real M[dim2_]) const; + void IntReverse(real X, real Y, real Z, real& lat, real& lon, real& h, + real M[dim2_]) const; + + public: + + /** + * Constructor for a ellipsoid with + * + * @param[in] a equatorial radius (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @exception GeographicErr if \e a or (1 − \e f) \e a is not + * positive. + **********************************************************************/ + Geocentric(real a, real f); + + /** + * A default constructor (for use by NormalGravity). + **********************************************************************/ + Geocentric() : _a(-1) {} + + /** + * Convert from geodetic to geocentric coordinates. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[in] h height of point above the ellipsoid (meters). + * @param[out] X geocentric coordinate (meters). + * @param[out] Y geocentric coordinate (meters). + * @param[out] Z geocentric coordinate (meters). + * + * \e lat should be in the range [−90°, 90°]. + **********************************************************************/ + void Forward(real lat, real lon, real h, real& X, real& Y, real& Z) + const { + if (Init()) + IntForward(lat, lon, h, X, Y, Z, NULL); + } + + /** + * Convert from geodetic to geocentric coordinates and return rotation + * matrix. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[in] h height of point above the ellipsoid (meters). + * @param[out] X geocentric coordinate (meters). + * @param[out] Y geocentric coordinate (meters). + * @param[out] Z geocentric coordinate (meters). + * @param[out] M if the length of the vector is 9, fill with the rotation + * matrix in row-major order. + * + * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can + * express \e v as \e column vectors in one of two ways + * - in east, north, up coordinates (where the components are relative to a + * local coordinate system at (\e lat, \e lon, \e h)); call this + * representation \e v1. + * - in geocentric \e X, \e Y, \e Z coordinates; call this representation + * \e v0. + * . + * Then we have \e v0 = \e M ⋅ \e v1. + **********************************************************************/ + void Forward(real lat, real lon, real h, real& X, real& Y, real& Z, + std::vector& M) + const { + if (!Init()) + return; + if (M.end() == M.begin() + dim2_) { + real t[dim2_]; + IntForward(lat, lon, h, X, Y, Z, t); + std::copy(t, t + dim2_, M.begin()); + } else + IntForward(lat, lon, h, X, Y, Z, NULL); + } + + /** + * Convert from geocentric to geodetic to coordinates. + * + * @param[in] X geocentric coordinate (meters). + * @param[in] Y geocentric coordinate (meters). + * @param[in] Z geocentric coordinate (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] h height of point above the ellipsoid (meters). + * + * In general, there are multiple solutions and the result which minimizes + * |h |is returned, i.e., (lat, lon) corresponds to + * the closest point on the ellipsoid. If there are still multiple + * solutions with different latitudes (applies only if \e Z = 0), then the + * solution with \e lat > 0 is returned. If there are still multiple + * solutions with different longitudes (applies only if \e X = \e Y = 0) + * then \e lon = 0 is returned. The value of \e h returned satisfies \e h + * ≥ − \e a (1 − e2) / sqrt(1 − + * e2 sin2\e lat). The value of \e lon + * returned is in the range [−180°, 180°]. + **********************************************************************/ + void Reverse(real X, real Y, real Z, real& lat, real& lon, real& h) + const { + if (Init()) + IntReverse(X, Y, Z, lat, lon, h, NULL); + } + + /** + * Convert from geocentric to geodetic to coordinates. + * + * @param[in] X geocentric coordinate (meters). + * @param[in] Y geocentric coordinate (meters). + * @param[in] Z geocentric coordinate (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] h height of point above the ellipsoid (meters). + * @param[out] M if the length of the vector is 9, fill with the rotation + * matrix in row-major order. + * + * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can + * express \e v as \e column vectors in one of two ways + * - in east, north, up coordinates (where the components are relative to a + * local coordinate system at (\e lat, \e lon, \e h)); call this + * representation \e v1. + * - in geocentric \e X, \e Y, \e Z coordinates; call this representation + * \e v0. + * . + * Then we have \e v1 = MT ⋅ \e v0, where + * MT is the transpose of \e M. + **********************************************************************/ + void Reverse(real X, real Y, real Z, real& lat, real& lon, real& h, + std::vector& M) + const { + if (!Init()) + return; + if (M.end() == M.begin() + dim2_) { + real t[dim2_]; + IntReverse(X, Y, Z, lat, lon, h, t); + std::copy(t, t + dim2_, M.begin()); + } else + IntReverse(X, Y, Z, lat, lon, h, NULL); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return true if the object has been initialized. + **********************************************************************/ + bool Init() const { return _a > 0; } + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const + { return Init() ? _a : Math::NaN(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the + * value used in the constructor. + **********************************************************************/ + Math::real Flattening() const + { return Init() ? _f : Math::NaN(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of Geocentric with the parameters for the WGS84 + * ellipsoid. + **********************************************************************/ + static const Geocentric& WGS84(); + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_GEOCENTRIC_HPP diff --git a/external/include/GeographicLib/Geodesic.hpp b/external/include/GeographicLib/Geodesic.hpp new file mode 100644 index 0000000..53fec25 --- /dev/null +++ b/external/include/GeographicLib/Geodesic.hpp @@ -0,0 +1,977 @@ +/** + * \file Geodesic.hpp + * \brief Header for GeographicLib::Geodesic class + * + * Copyright (c) Charles Karney (2009-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GEODESIC_HPP) +#define GEOGRAPHICLIB_GEODESIC_HPP 1 + +#include + +#if !defined(GEOGRAPHICLIB_GEODESIC_ORDER) +/** + * The order of the expansions used by Geodesic. + * GEOGRAPHICLIB_GEODESIC_ORDER can be set to any integer in [3, 8]. + **********************************************************************/ +# define GEOGRAPHICLIB_GEODESIC_ORDER \ + (GEOGRAPHICLIB_PRECISION == 2 ? 6 : \ + (GEOGRAPHICLIB_PRECISION == 1 ? 3 : \ + (GEOGRAPHICLIB_PRECISION == 3 ? 7 : 8))) +#endif + +namespace GeographicLib { + + class GeodesicLine; + + /** + * \brief %Geodesic calculations + * + * The shortest path between two points on a ellipsoid at (\e lat1, \e lon1) + * and (\e lat2, \e lon2) is called the geodesic. Its length is \e s12 and + * the geodesic from point 1 to point 2 has azimuths \e azi1 and \e azi2 at + * the two end points. (The azimuth is the heading measured clockwise from + * north. \e azi2 is the "forward" azimuth, i.e., the heading that takes you + * beyond point 2 not back to point 1.) In the figure below, latitude if + * labeled φ, longitude λ (with λ12 = + * λ2 − λ1), and azimuth α. + * + * spheroidal triangle + * + * Given \e lat1, \e lon1, \e azi1, and \e s12, we can determine \e lat2, \e + * lon2, and \e azi2. This is the \e direct geodesic problem and its + * solution is given by the function Geodesic::Direct. (If \e s12 is + * sufficiently large that the geodesic wraps more than halfway around the + * earth, there will be another geodesic between the points with a smaller \e + * s12.) + * + * Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi1, \e + * azi2, and \e s12. This is the \e inverse geodesic problem, whose solution + * is given by Geodesic::Inverse. Usually, the solution to the inverse + * problem is unique. In cases where there are multiple solutions (all with + * the same \e s12, of course), all the solutions can be easily generated + * once a particular solution is provided. + * + * The standard way of specifying the direct problem is the specify the + * distance \e s12 to the second point. However it is sometimes useful + * instead to specify the arc length \e a12 (in degrees) on the auxiliary + * sphere. This is a mathematical construct used in solving the geodesic + * problems. The solution of the direct problem in this form is provided by + * Geodesic::ArcDirect. An arc length in excess of 180° indicates that + * the geodesic is not a shortest path. In addition, the arc length between + * an equatorial crossing and the next extremum of latitude for a geodesic is + * 90°. + * + * This class can also calculate several other quantities related to + * geodesics. These are: + * - reduced length. If we fix the first point and increase \e azi1 + * by \e dazi1 (radians), the second point is displaced \e m12 \e dazi1 in + * the direction \e azi2 + 90°. The quantity \e m12 is called + * the "reduced length" and is symmetric under interchange of the two + * points. On a curved surface the reduced length obeys a symmetry + * relation, \e m12 + \e m21 = 0. On a flat surface, we have \e m12 = \e + * s12. The ratio s12/\e m12 gives the azimuthal scale for an + * azimuthal equidistant projection. + * - geodesic scale. Consider a reference geodesic and a second + * geodesic parallel to this one at point 1 and separated by a small + * distance \e dt. The separation of the two geodesics at point 2 is \e + * M12 \e dt where \e M12 is called the "geodesic scale". \e M21 is + * defined similarly (with the geodesics being parallel at point 2). On a + * flat surface, we have \e M12 = \e M21 = 1. The quantity 1/\e M12 gives + * the scale of the Cassini-Soldner projection. + * - area. The area between the geodesic from point 1 to point 2 and + * the equation is represented by \e S12; it is the area, measured + * counter-clockwise, of the geodesic quadrilateral with corners + * (lat1,lon1), (0,lon1), (0,lon2), and + * (lat2,lon2). It can be used to compute the area of any + * geodesic polygon. + * + * Overloaded versions of Geodesic::Direct, Geodesic::ArcDirect, and + * Geodesic::Inverse allow these quantities to be returned. In addition + * there are general functions Geodesic::GenDirect, and Geodesic::GenInverse + * which allow an arbitrary set of results to be computed. The quantities \e + * m12, \e M12, \e M21 which all specify the behavior of nearby geodesics + * obey addition rules. If points 1, 2, and 3 all lie on a single geodesic, + * then the following rules hold: + * - \e s13 = \e s12 + \e s23 + * - \e a13 = \e a12 + \e a23 + * - \e S13 = \e S12 + \e S23 + * - \e m13 = \e m12 \e M23 + \e m23 \e M21 + * - \e M13 = \e M12 \e M23 − (1 − \e M12 \e M21) \e m23 / \e m12 + * - \e M31 = \e M32 \e M21 − (1 − \e M23 \e M32) \e m12 / \e m23 + * + * Additional functionality is provided by the GeodesicLine class, which + * allows a sequence of points along a geodesic to be computed. + * + * The shortest distance returned by the solution of the inverse problem is + * (obviously) uniquely defined. However, in a few special cases there are + * multiple azimuths which yield the same shortest distance. Here is a + * catalog of those cases: + * - \e lat1 = −\e lat2 (with neither point at a pole). If \e azi1 = + * \e azi2, the geodesic is unique. Otherwise there are two geodesics and + * the second one is obtained by setting [\e azi1, \e azi2] → [\e + * azi2, \e azi1], [\e M12, \e M21] → [\e M21, \e M12], \e S12 → + * −\e S12. (This occurs when the longitude difference is near + * ±180° for oblate ellipsoids.) + * - \e lon2 = \e lon1 ± 180° (with neither point at a pole). If + * \e azi1 = 0° or ±180°, the geodesic is unique. Otherwise + * there are two geodesics and the second one is obtained by setting [\e + * azi1, \e azi2] → [−\e azi1, −\e azi2], \e S12 → + * −\e S12. (This occurs when \e lat2 is near −\e lat1 for + * prolate ellipsoids.) + * - Points 1 and 2 at opposite poles. There are infinitely many geodesics + * which can be generated by setting [\e azi1, \e azi2] → [\e azi1, \e + * azi2] + [\e d, −\e d], for arbitrary \e d. (For spheres, this + * prescription applies when points 1 and 2 are antipodal.) + * - \e s12 = 0 (coincident points). There are infinitely many geodesics + * which can be generated by setting [\e azi1, \e azi2] → + * [\e azi1, \e azi2] + [\e d, \e d], for arbitrary \e d. + * + * The calculations are accurate to better than 15 nm (15 nanometers) for the + * WGS84 ellipsoid. See Sec. 9 of + * arXiv:1102.1215v1 for + * details. The algorithms used by this class are based on series expansions + * using the flattening \e f as a small parameter. These are only accurate + * for |f| < 0.02; however reasonably accurate results will be + * obtained for |f| < 0.2. Here is a table of the approximate + * maximum error (expressed as a distance) for an ellipsoid with the same + * equatorial radius as the WGS84 ellipsoid and different values of the + * flattening.
+   *     |f|      error
+   *     0.01     25 nm
+   *     0.02     30 nm
+   *     0.05     10 um
+   *     0.1     1.5 mm
+   *     0.2     300 mm
+   * 
+ * For very eccentric ellipsoids, use GeodesicExact instead. + * + * The algorithms are described in + * - C. F. F. Karney, + * + * Algorithms for geodesics, + * J. Geodesy 87, 43--55 (2013); + * DOI: + * 10.1007/s00190-012-0578-z; + * addenda: + * + * geod-addenda.html. + * . + * For more information on geodesics see \ref geodesic. + * + * Example of use: + * \include example-Geodesic.cpp + * + * GeodSolve is a command-line utility + * providing access to the functionality of Geodesic and GeodesicLine. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT Geodesic { + private: + typedef Math::real real; + friend class GeodesicLine; + static const int nA1_ = GEOGRAPHICLIB_GEODESIC_ORDER; + static const int nC1_ = GEOGRAPHICLIB_GEODESIC_ORDER; + static const int nC1p_ = GEOGRAPHICLIB_GEODESIC_ORDER; + static const int nA2_ = GEOGRAPHICLIB_GEODESIC_ORDER; + static const int nC2_ = GEOGRAPHICLIB_GEODESIC_ORDER; + static const int nA3_ = GEOGRAPHICLIB_GEODESIC_ORDER; + static const int nA3x_ = nA3_; + static const int nC3_ = GEOGRAPHICLIB_GEODESIC_ORDER; + static const int nC3x_ = (nC3_ * (nC3_ - 1)) / 2; + static const int nC4_ = GEOGRAPHICLIB_GEODESIC_ORDER; + static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2; + // Size for temporary array + // nC = max(max(nC1_, nC1p_, nC2_) + 1, max(nC3_, nC4_)) + static const int nC_ = GEOGRAPHICLIB_GEODESIC_ORDER + 1; + static const unsigned maxit1_ = 20; + unsigned maxit2_; + real tiny_, tol0_, tol1_, tol2_, tolb_, xthresh_; + + enum captype { + CAP_NONE = 0U, + CAP_C1 = 1U<<0, + CAP_C1p = 1U<<1, + CAP_C2 = 1U<<2, + CAP_C3 = 1U<<3, + CAP_C4 = 1U<<4, + CAP_ALL = 0x1FU, + CAP_MASK = CAP_ALL, + OUT_ALL = 0x7F80U, + OUT_MASK = 0xFF80U, // Includes LONG_UNROLL + }; + + static real SinCosSeries(bool sinp, + real sinx, real cosx, const real c[], int n); + static real Astroid(real x, real y); + + real _a, _f, _f1, _e2, _ep2, _n, _b, _c2, _etol2; + real _A3x[nA3x_], _C3x[nC3x_], _C4x[nC4x_]; + + void Lengths(real eps, real sig12, + real ssig1, real csig1, real dn1, + real ssig2, real csig2, real dn2, + real cbet1, real cbet2, unsigned outmask, + real& s12s, real& m12a, real& m0, + real& M12, real& M21, real Ca[]) const; + real InverseStart(real sbet1, real cbet1, real dn1, + real sbet2, real cbet2, real dn2, + real lam12, real slam12, real clam12, + real& salp1, real& calp1, + real& salp2, real& calp2, real& dnm, + real Ca[]) const; + real Lambda12(real sbet1, real cbet1, real dn1, + real sbet2, real cbet2, real dn2, + real salp1, real calp1, real slam120, real clam120, + real& salp2, real& calp2, real& sig12, + real& ssig1, real& csig1, real& ssig2, real& csig2, + real& eps, real& domg12, + bool diffp, real& dlam12, real Ca[]) const; + real GenInverse(real lat1, real lon1, real lat2, real lon2, + unsigned outmask, real& s12, + real& salp1, real& calp1, real& salp2, real& calp2, + real& m12, real& M12, real& M21, real& S12) const; + + // These are Maxima generated functions to provide series approximations to + // the integrals for the ellipsoidal geodesic. + static real A1m1f(real eps); + static void C1f(real eps, real c[]); + static void C1pf(real eps, real c[]); + static real A2m1f(real eps); + static void C2f(real eps, real c[]); + + void A3coeff(); + real A3f(real eps) const; + void C3coeff(); + void C3f(real eps, real c[]) const; + void C4coeff(); + void C4f(real k2, real c[]) const; + + public: + + /** + * Bit masks for what calculations to do. These masks do double duty. + * They signify to the GeodesicLine::GeodesicLine constructor and to + * Geodesic::Line what capabilities should be included in the GeodesicLine + * object. They also specify which results to return in the general + * routines Geodesic::GenDirect and Geodesic::GenInverse routines. + * GeodesicLine::mask is a duplication of this enum. + **********************************************************************/ + enum mask { + /** + * No capabilities, no output. + * @hideinitializer + **********************************************************************/ + NONE = 0U, + /** + * Calculate latitude \e lat2. (It's not necessary to include this as a + * capability to GeodesicLine because this is included by default.) + * @hideinitializer + **********************************************************************/ + LATITUDE = 1U<<7 | CAP_NONE, + /** + * Calculate longitude \e lon2. + * @hideinitializer + **********************************************************************/ + LONGITUDE = 1U<<8 | CAP_C3, + /** + * Calculate azimuths \e azi1 and \e azi2. (It's not necessary to + * include this as a capability to GeodesicLine because this is included + * by default.) + * @hideinitializer + **********************************************************************/ + AZIMUTH = 1U<<9 | CAP_NONE, + /** + * Calculate distance \e s12. + * @hideinitializer + **********************************************************************/ + DISTANCE = 1U<<10 | CAP_C1, + /** + * Allow distance \e s12 to be used as input in the direct geodesic + * problem. + * @hideinitializer + **********************************************************************/ + DISTANCE_IN = 1U<<11 | CAP_C1 | CAP_C1p, + /** + * Calculate reduced length \e m12. + * @hideinitializer + **********************************************************************/ + REDUCEDLENGTH = 1U<<12 | CAP_C1 | CAP_C2, + /** + * Calculate geodesic scales \e M12 and \e M21. + * @hideinitializer + **********************************************************************/ + GEODESICSCALE = 1U<<13 | CAP_C1 | CAP_C2, + /** + * Calculate area \e S12. + * @hideinitializer + **********************************************************************/ + AREA = 1U<<14 | CAP_C4, + /** + * Unroll \e lon2 in the direct calculation. + * @hideinitializer + **********************************************************************/ + LONG_UNROLL = 1U<<15, + /** + * All capabilities, calculate everything. (LONG_UNROLL is not + * included in this mask.) + * @hideinitializer + **********************************************************************/ + ALL = OUT_ALL| CAP_ALL, + }; + + /** \name Constructor + **********************************************************************/ + ///@{ + /** + * Constructor for a ellipsoid with + * + * @param[in] a equatorial radius (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @exception GeographicErr if \e a or (1 − \e f) \e a is not + * positive. + **********************************************************************/ + Geodesic(real a, real f); + ///@} + + /** \name Direct geodesic problem specified in terms of distance. + **********************************************************************/ + ///@{ + /** + * Solve the direct geodesic problem where the length of the geodesic + * is specified in terms of distance. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] s12 distance between point 1 and point 2 (meters); it can be + * negative. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * @return \e a12 arc length of between point 1 and point 2 (degrees). + * + * \e lat1 should be in the range [−90°, 90°]. The values of + * \e lon2 and \e azi2 returned are in the range [−180°, + * 180°]. + * + * If either point is at a pole, the azimuth is defined by keeping the + * longitude fixed, writing \e lat = ±(90° − ε), + * and taking the limit ε → 0+. An arc length greater that + * 180° signifies a geodesic which is not a shortest path. (For a + * prolate ellipsoid, an additional condition is necessary for a shortest + * path: the longitudinal extent must not exceed of 180°.) + * + * The following functions are overloaded versions of Geodesic::Direct + * which omit some of the output parameters. Note, however, that the arc + * length is always computed and returned as the function value. + **********************************************************************/ + 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 { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE | AREA, + lat2, lon2, azi2, t, m12, M12, M21, S12); + } + + /** + * See the documentation for Geodesic::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE, + lat2, lon2, t, t, t, t, t, t); + } + + /** + * See the documentation for Geodesic::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2, real& azi2) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH, + lat2, lon2, azi2, t, t, t, t, t); + } + + /** + * See the documentation for Geodesic::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2, real& azi2, real& m12) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH | REDUCEDLENGTH, + lat2, lon2, azi2, t, m12, t, t, t); + } + + /** + * See the documentation for Geodesic::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2, real& azi2, + real& M12, real& M21) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH | GEODESICSCALE, + lat2, lon2, azi2, t, t, M12, M21, t); + } + + /** + * See the documentation for Geodesic::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2, real& azi2, + real& m12, real& M12, real& M21) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE, + lat2, lon2, azi2, t, m12, M12, M21, t); + } + ///@} + + /** \name Direct geodesic problem specified in terms of arc length. + **********************************************************************/ + ///@{ + /** + * Solve the direct geodesic problem where the length of the geodesic + * is specified in terms of arc length. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] a12 arc length between point 1 and point 2 (degrees); it can + * be negative. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] s12 distance between point 1 and point 2 (meters). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * + * \e lat1 should be in the range [−90°, 90°]. The values of + * \e lon2 and \e azi2 returned are in the range [−180°, + * 180°]. + * + * If either point is at a pole, the azimuth is defined by keeping the + * longitude fixed, writing \e lat = ±(90° − ε), + * and taking the limit ε → 0+. An arc length greater that + * 180° signifies a geodesic which is not a shortest path. (For a + * prolate ellipsoid, an additional condition is necessary for a shortest + * path: the longitudinal extent must not exceed of 180°.) + * + * The following functions are overloaded versions of Geodesic::Direct + * which omit some of the output parameters. + **********************************************************************/ + 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 { + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + REDUCEDLENGTH | GEODESICSCALE | AREA, + lat2, lon2, azi2, s12, m12, M12, M21, S12); + } + + /** + * See the documentation for Geodesic::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2) const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE, + lat2, lon2, t, t, t, t, t, t); + } + + /** + * See the documentation for Geodesic::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2, real& azi2) const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH, + lat2, lon2, azi2, t, t, t, t, t); + } + + /** + * See the documentation for Geodesic::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2, real& azi2, real& s12) + const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE, + lat2, lon2, azi2, s12, t, t, t, t); + } + + /** + * See the documentation for Geodesic::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2, real& azi2, + real& s12, real& m12) const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + REDUCEDLENGTH, + lat2, lon2, azi2, s12, m12, t, t, t); + } + + /** + * See the documentation for Geodesic::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2, real& azi2, real& s12, + real& M12, real& M21) const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + GEODESICSCALE, + lat2, lon2, azi2, s12, t, M12, M21, t); + } + + /** + * See the documentation for Geodesic::ArcDirect. + **********************************************************************/ + 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 { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + REDUCEDLENGTH | GEODESICSCALE, + lat2, lon2, azi2, s12, m12, M12, M21, t); + } + ///@} + + /** \name General version of the direct geodesic solution. + **********************************************************************/ + ///@{ + + /** + * The general direct geodesic problem. Geodesic::Direct and + * Geodesic::ArcDirect are defined in terms of this function. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] arcmode boolean flag determining the meaning of the \e + * s12_a12. + * @param[in] s12_a12 if \e arcmode is false, this is the distance between + * point 1 and point 2 (meters); otherwise it is the arc length between + * point 1 and point 2 (degrees); it can be negative. + * @param[in] outmask a bitor'ed combination of Geodesic::mask values + * specifying which of the following parameters should be set. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] s12 distance between point 1 and point 2 (meters). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * @return \e a12 arc length of between point 1 and point 2 (degrees). + * + * The Geodesic::mask values possible for \e outmask are + * - \e outmask |= Geodesic::LATITUDE for the latitude \e lat2; + * - \e outmask |= Geodesic::LONGITUDE for the latitude \e lon2; + * - \e outmask |= Geodesic::AZIMUTH for the latitude \e azi2; + * - \e outmask |= Geodesic::DISTANCE for the distance \e s12; + * - \e outmask |= Geodesic::REDUCEDLENGTH for the reduced length \e + * m12; + * - \e outmask |= Geodesic::GEODESICSCALE for the geodesic scales \e + * M12 and \e M21; + * - \e outmask |= Geodesic::AREA for the area \e S12; + * - \e outmask |= Geodesic::ALL for all of the above; + * - \e outmask |= Geodesic::LONG_UNROLL to unroll \e lon2 instead of + * wrapping it into the range [−180°, 180°]. + * . + * The function value \e a12 is always computed and returned and this + * equals \e s12_a12 is \e arcmode is true. If \e outmask includes + * Geodesic::DISTANCE and \e arcmode is false, then \e s12 = \e s12_a12. + * It is not necessary to include Geodesic::DISTANCE_IN in \e outmask; this + * is automatically included is \e arcmode is false. + * + * With the Geodesic::LONG_UNROLL bit set, the quantity \e lon2 − \e + * lon1 indicates how many times and in what sense the geodesic encircles + * the ellipsoid. + **********************************************************************/ + 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; + ///@} + + /** \name Inverse geodesic problem. + **********************************************************************/ + ///@{ + /** + * Solve the inverse geodesic problem. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] lat2 latitude of point 2 (degrees). + * @param[in] lon2 longitude of point 2 (degrees). + * @param[out] s12 distance between point 1 and point 2 (meters). + * @param[out] azi1 azimuth at point 1 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * @return \e a12 arc length of between point 1 and point 2 (degrees). + * + * \e lat1 and \e lat2 should be in the range [−90°, 90°]. + * The values of \e azi1 and \e azi2 returned are in the range + * [−180°, 180°]. + * + * If either point is at a pole, the azimuth is defined by keeping the + * longitude fixed, writing \e lat = ±(90° − ε), + * and taking the limit ε → 0+. + * + * The solution to the inverse problem is found using Newton's method. If + * this fails to converge (this is very unlikely in geodetic applications + * but does occur for very eccentric ellipsoids), then the bisection method + * is used to refine the solution. + * + * The following functions are overloaded versions of Geodesic::Inverse + * which omit some of the output parameters. Note, however, that the arc + * length is always computed and returned as the function value. + **********************************************************************/ + 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 { + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE | AREA, + s12, azi1, azi2, m12, M12, M21, S12); + } + + /** + * See the documentation for Geodesic::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12) const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE, + s12, t, t, t, t, t, t); + } + + /** + * See the documentation for Geodesic::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& azi1, real& azi2) const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + AZIMUTH, + t, azi1, azi2, t, t, t, t); + } + + /** + * See the documentation for Geodesic::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi1, real& azi2) + const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH, + s12, azi1, azi2, t, t, t, t); + } + + /** + * See the documentation for Geodesic::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi1, real& azi2, real& m12) + const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH | REDUCEDLENGTH, + s12, azi1, azi2, m12, t, t, t); + } + + /** + * See the documentation for Geodesic::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi1, real& azi2, + real& M12, real& M21) const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH | GEODESICSCALE, + s12, azi1, azi2, t, M12, M21, t); + } + + /** + * See the documentation for Geodesic::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi1, real& azi2, real& m12, + real& M12, real& M21) const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE, + s12, azi1, azi2, m12, M12, M21, t); + } + ///@} + + /** \name General version of inverse geodesic solution. + **********************************************************************/ + ///@{ + /** + * The general inverse geodesic calculation. Geodesic::Inverse is defined + * in terms of this function. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] lat2 latitude of point 2 (degrees). + * @param[in] lon2 longitude of point 2 (degrees). + * @param[in] outmask a bitor'ed combination of Geodesic::mask values + * specifying which of the following parameters should be set. + * @param[out] s12 distance between point 1 and point 2 (meters). + * @param[out] azi1 azimuth at point 1 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * @return \e a12 arc length of between point 1 and point 2 (degrees). + * + * The Geodesic::mask values possible for \e outmask are + * - \e outmask |= Geodesic::DISTANCE for the distance \e s12; + * - \e outmask |= Geodesic::AZIMUTH for the latitude \e azi2; + * - \e outmask |= Geodesic::REDUCEDLENGTH for the reduced length \e + * m12; + * - \e outmask |= Geodesic::GEODESICSCALE for the geodesic scales \e + * M12 and \e M21; + * - \e outmask |= Geodesic::AREA for the area \e S12; + * - \e outmask |= Geodesic::ALL for all of the above. + * . + * The arc length is always computed and returned as the function value. + **********************************************************************/ + Math::real GenInverse(real lat1, real lon1, real lat2, real lon2, + unsigned outmask, + real& s12, real& azi1, real& azi2, + real& m12, real& M12, real& M21, real& S12) const; + ///@} + + /** \name Interface to GeodesicLine. + **********************************************************************/ + ///@{ + + /** + * Set up to compute several points on a single geodesic. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] caps bitor'ed combination of Geodesic::mask values + * specifying the capabilities the GeodesicLine object should possess, + * i.e., which quantities can be returned in calls to + * GeodesicLine::Position. + * @return a GeodesicLine object. + * + * \e lat1 should be in the range [−90°, 90°]. + * + * The Geodesic::mask values are + * - \e caps |= Geodesic::LATITUDE for the latitude \e lat2; this is + * added automatically; + * - \e caps |= Geodesic::LONGITUDE for the latitude \e lon2; + * - \e caps |= Geodesic::AZIMUTH for the azimuth \e azi2; this is + * added automatically; + * - \e caps |= Geodesic::DISTANCE for the distance \e s12; + * - \e caps |= Geodesic::REDUCEDLENGTH for the reduced length \e m12; + * - \e caps |= Geodesic::GEODESICSCALE for the geodesic scales \e M12 + * and \e M21; + * - \e caps |= Geodesic::AREA for the area \e S12; + * - \e caps |= Geodesic::DISTANCE_IN permits the length of the + * geodesic to be given in terms of \e s12; without this capability the + * length can only be specified in terms of arc length; + * - \e caps |= Geodesic::ALL for all of the above. + * . + * The default value of \e caps is Geodesic::ALL. + * + * If the point is at a pole, the azimuth is defined by keeping \e lon1 + * fixed, writing \e lat1 = ±(90 − ε), and taking the + * limit ε → 0+. + **********************************************************************/ + GeodesicLine Line(real lat1, real lon1, real azi1, unsigned caps = ALL) + const; + + /** + * Define a GeodesicLine in terms of the inverse geodesic problem. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] lat2 latitude of point 2 (degrees). + * @param[in] lon2 longitude of point 2 (degrees). + * @param[in] caps bitor'ed combination of Geodesic::mask values + * specifying the capabilities the GeodesicLine object should possess, + * i.e., which quantities can be returned in calls to + * GeodesicLine::Position. + * @return a GeodesicLine object. + * + * This function sets point 3 of the GeodesicLine to correspond to point 2 + * of the inverse geodesic problem. + * + * \e lat1 and \e lat2 should be in the range [−90°, 90°]. + **********************************************************************/ + GeodesicLine InverseLine(real lat1, real lon1, real lat2, real lon2, + unsigned caps = ALL) const; + + /** + * Define a GeodesicLine in terms of the direct geodesic problem specified + * in terms of distance. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] s12 distance between point 1 and point 2 (meters); it can be + * negative. + * @param[in] caps bitor'ed combination of Geodesic::mask values + * specifying the capabilities the GeodesicLine object should possess, + * i.e., which quantities can be returned in calls to + * GeodesicLine::Position. + * @return a GeodesicLine object. + * + * This function sets point 3 of the GeodesicLine to correspond to point 2 + * of the direct geodesic problem. + * + * \e lat1 should be in the range [−90°, 90°]. + **********************************************************************/ + GeodesicLine DirectLine(real lat1, real lon1, real azi1, real s12, + unsigned caps = ALL) const; + + /** + * Define a GeodesicLine in terms of the direct geodesic problem specified + * in terms of arc length. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] a12 arc length between point 1 and point 2 (degrees); it can + * be negative. + * @param[in] caps bitor'ed combination of Geodesic::mask values + * specifying the capabilities the GeodesicLine object should possess, + * i.e., which quantities can be returned in calls to + * GeodesicLine::Position. + * @return a GeodesicLine object. + * + * This function sets point 3 of the GeodesicLine to correspond to point 2 + * of the direct geodesic problem. + * + * \e lat1 should be in the range [−90°, 90°]. + **********************************************************************/ + GeodesicLine ArcDirectLine(real lat1, real lon1, real azi1, real a12, + unsigned caps = ALL) const; + + /** + * Define a GeodesicLine in terms of the direct geodesic problem specified + * in terms of either distance or arc length. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] arcmode boolean flag determining the meaning of the \e + * s12_a12. + * @param[in] s12_a12 if \e arcmode is false, this is the distance between + * point 1 and point 2 (meters); otherwise it is the arc length between + * point 1 and point 2 (degrees); it can be negative. + * @param[in] caps bitor'ed combination of Geodesic::mask values + * specifying the capabilities the GeodesicLine object should possess, + * i.e., which quantities can be returned in calls to + * GeodesicLine::Position. + * @return a GeodesicLine object. + * + * This function sets point 3 of the GeodesicLine to correspond to point 2 + * of the direct geodesic problem. + * + * \e lat1 should be in the range [−90°, 90°]. + **********************************************************************/ + GeodesicLine GenDirectLine(real lat1, real lon1, real azi1, + bool arcmode, real s12_a12, + unsigned caps = ALL) const; + ///@} + + /** \name Inspector functions. + **********************************************************************/ + ///@{ + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _a; } + + /** + * @return \e f the flattening of the ellipsoid. This is the + * value used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _f; } + + /** + * @return total area of ellipsoid in meters2. The area of a + * polygon encircling a pole can be found by adding + * Geodesic::EllipsoidArea()/2 to the sum of \e S12 for each side of the + * polygon. + **********************************************************************/ + Math::real EllipsoidArea() const + { return 4 * Math::pi() * _c2; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of Geodesic with the parameters for the WGS84 + * ellipsoid. + **********************************************************************/ + static const Geodesic& WGS84(); + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_GEODESIC_HPP diff --git a/external/include/GeographicLib/GeodesicExact.hpp b/external/include/GeographicLib/GeodesicExact.hpp new file mode 100644 index 0000000..abb8da6 --- /dev/null +++ b/external/include/GeographicLib/GeodesicExact.hpp @@ -0,0 +1,869 @@ +/** + * \file GeodesicExact.hpp + * \brief Header for GeographicLib::GeodesicExact class + * + * Copyright (c) Charles Karney (2012-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GEODESICEXACT_HPP) +#define GEOGRAPHICLIB_GEODESICEXACT_HPP 1 + +#include +#include + +#if !defined(GEOGRAPHICLIB_GEODESICEXACT_ORDER) +/** + * The order of the expansions used by GeodesicExact. + **********************************************************************/ +# define GEOGRAPHICLIB_GEODESICEXACT_ORDER 30 +#endif + +namespace GeographicLib { + + class GeodesicLineExact; + + /** + * \brief Exact geodesic calculations + * + * The equations for geodesics on an ellipsoid can be expressed in terms of + * incomplete elliptic integrals. The Geodesic class expands these integrals + * in a series in the flattening \e f and this provides an accurate solution + * for \e f ∈ [-0.01, 0.01]. The GeodesicExact class computes the + * ellitpic integrals directly and so provides a solution which is valid for + * all \e f. However, in practice, its use should be limited to about + * b/\e a ∈ [0.01, 100] or \e f ∈ [−99, 0.99]. + * + * For the WGS84 ellipsoid, these classes are 2--3 times \e slower than the + * series solution and 2--3 times \e less \e accurate (because it's less easy + * to control round-off errors with the elliptic integral formulation); i.e., + * the error is about 40 nm (40 nanometers) instead of 15 nm. However the + * error in the series solution scales as f7 while the + * error in the elliptic integral solution depends weakly on \e f. If the + * quarter meridian distance is 10000 km and the ratio b/\e a = 1 + * − \e f is varied then the approximate maximum error (expressed as a + * distance) is
+   *       1 - f  error (nm)
+   *       1/128     387
+   *       1/64      345
+   *       1/32      269
+   *       1/16      210
+   *       1/8       115
+   *       1/4        69
+   *       1/2        36
+   *         1        15
+   *         2        25
+   *         4        96
+   *         8       318
+   *        16       985
+   *        32      2352
+   *        64      6008
+   *       128     19024
+   * 
+ * + * The computation of the area in these classes is via a 30th order series. + * This gives accurate results for b/\e a ∈ [1/2, 2]; the + * accuracy is about 8 decimal digits for b/\e a ∈ [1/4, 4]. + * + * See \ref geodellip for the formulation. See the documentation on the + * Geodesic class for additional information on the geodesic problems. + * + * Example of use: + * \include example-GeodesicExact.cpp + * + * GeodSolve is a command-line utility + * providing access to the functionality of GeodesicExact and + * GeodesicLineExact (via the -E option). + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT GeodesicExact { + private: + typedef Math::real real; + friend class GeodesicLineExact; + static const int nC4_ = GEOGRAPHICLIB_GEODESICEXACT_ORDER; + static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2; + static const unsigned maxit1_ = 20; + unsigned maxit2_; + real tiny_, tol0_, tol1_, tol2_, tolb_, xthresh_; + + enum captype { + CAP_NONE = 0U, + CAP_E = 1U<<0, + // Skip 1U<<1 for compatibility with Geodesic (not required) + CAP_D = 1U<<2, + CAP_H = 1U<<3, + CAP_C4 = 1U<<4, + CAP_ALL = 0x1FU, + CAP_MASK = CAP_ALL, + OUT_ALL = 0x7F80U, + OUT_MASK = 0xFF80U, // Includes LONG_UNROLL + }; + + static real CosSeries(real sinx, real cosx, const real c[], int n); + static real Astroid(real x, real y); + + real _a, _f, _f1, _e2, _ep2, _n, _b, _c2, _etol2; + real _C4x[nC4x_]; + + void Lengths(const EllipticFunction& E, + real sig12, + real ssig1, real csig1, real dn1, + real ssig2, real csig2, real dn2, + real cbet1, real cbet2, unsigned outmask, + real& s12s, real& m12a, real& m0, + real& M12, real& M21) const; + real InverseStart(EllipticFunction& E, + real sbet1, real cbet1, real dn1, + real sbet2, real cbet2, real dn2, + real lam12, real slam12, real clam12, + real& salp1, real& calp1, + real& salp2, real& calp2, real& dnm) const; + real Lambda12(real sbet1, real cbet1, real dn1, + real sbet2, real cbet2, real dn2, + real salp1, real calp1, real slam120, real clam120, + real& salp2, real& calp2, real& sig12, + real& ssig1, real& csig1, real& ssig2, real& csig2, + EllipticFunction& E, + real& domg12, bool diffp, real& dlam12) const; + real GenInverse(real lat1, real lon1, real lat2, real lon2, + unsigned outmask, real& s12, + real& salp1, real& calp1, real& salp2, real& calp2, + real& m12, real& M12, real& M21, real& S12) const; + + // These are Maxima generated functions to provide series approximations to + // the integrals for the area. + void C4coeff(); + void C4f(real k2, real c[]) const; + // Large coefficients are split so that lo contains the low 52 bits and hi + // the rest. This choice avoids double rounding with doubles and higher + // precision types. float coefficients will suffer double rounding; + // however the accuracy is already lousy for floats. + static Math::real reale(long long hi, long long lo) { + using std::ldexp; + return ldexp(real(hi), 52) + lo; + } + + public: + + /** + * Bit masks for what calculations to do. These masks do double duty. + * They signify to the GeodesicLineExact::GeodesicLineExact constructor and + * to GeodesicExact::Line what capabilities should be included in the + * GeodesicLineExact object. They also specify which results to return in + * the general routines GeodesicExact::GenDirect and + * GeodesicExact::GenInverse routines. GeodesicLineExact::mask is a + * duplication of this enum. + **********************************************************************/ + enum mask { + /** + * No capabilities, no output. + * @hideinitializer + **********************************************************************/ + NONE = 0U, + /** + * Calculate latitude \e lat2. (It's not necessary to include this as a + * capability to GeodesicLineExact because this is included by default.) + * @hideinitializer + **********************************************************************/ + LATITUDE = 1U<<7 | CAP_NONE, + /** + * Calculate longitude \e lon2. + * @hideinitializer + **********************************************************************/ + LONGITUDE = 1U<<8 | CAP_H, + /** + * Calculate azimuths \e azi1 and \e azi2. (It's not necessary to + * include this as a capability to GeodesicLineExact because this is + * included by default.) + * @hideinitializer + **********************************************************************/ + AZIMUTH = 1U<<9 | CAP_NONE, + /** + * Calculate distance \e s12. + * @hideinitializer + **********************************************************************/ + DISTANCE = 1U<<10 | CAP_E, + /** + * Allow distance \e s12 to be used as input in the direct geodesic + * problem. + * @hideinitializer + **********************************************************************/ + DISTANCE_IN = 1U<<11 | CAP_E, + /** + * Calculate reduced length \e m12. + * @hideinitializer + **********************************************************************/ + REDUCEDLENGTH = 1U<<12 | CAP_D, + /** + * Calculate geodesic scales \e M12 and \e M21. + * @hideinitializer + **********************************************************************/ + GEODESICSCALE = 1U<<13 | CAP_D, + /** + * Calculate area \e S12. + * @hideinitializer + **********************************************************************/ + AREA = 1U<<14 | CAP_C4, + /** + * Unroll \e lon2 in the direct calculation. + * @hideinitializer + **********************************************************************/ + LONG_UNROLL = 1U<<15, + /** + * All capabilities, calculate everything. (LONG_UNROLL is not + * included in this mask.) + * @hideinitializer + **********************************************************************/ + ALL = OUT_ALL| CAP_ALL, + }; + + /** \name Constructor + **********************************************************************/ + ///@{ + /** + * Constructor for a ellipsoid with + * + * @param[in] a equatorial radius (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @exception GeographicErr if \e a or (1 − \e f) \e a is not + * positive. + **********************************************************************/ + GeodesicExact(real a, real f); + ///@} + + /** \name Direct geodesic problem specified in terms of distance. + **********************************************************************/ + ///@{ + /** + * Perform the direct geodesic calculation where the length of the geodesic + * is specified in terms of distance. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] s12 distance between point 1 and point 2 (meters); it can be + * signed. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * @return \e a12 arc length of between point 1 and point 2 (degrees). + * + * \e lat1 should be in the range [−90°, 90°]. The values of + * \e lon2 and \e azi2 returned are in the range [−180°, + * 180°]. + * + * If either point is at a pole, the azimuth is defined by keeping the + * longitude fixed, writing \e lat = ±(90° − ε), + * and taking the limit ε → 0+. An arc length greater that + * 180° signifies a geodesic which is not a shortest path. (For a + * prolate ellipsoid, an additional condition is necessary for a shortest + * path: the longitudinal extent must not exceed of 180°.) + * + * The following functions are overloaded versions of GeodesicExact::Direct + * which omit some of the output parameters. Note, however, that the arc + * length is always computed and returned as the function value. + **********************************************************************/ + 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 { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE | AREA, + lat2, lon2, azi2, t, m12, M12, M21, S12); + } + + /** + * See the documentation for GeodesicExact::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE, + lat2, lon2, t, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicExact::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2, real& azi2) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH, + lat2, lon2, azi2, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicExact::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2, real& azi2, real& m12) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH | REDUCEDLENGTH, + lat2, lon2, azi2, t, m12, t, t, t); + } + + /** + * See the documentation for GeodesicExact::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2, real& azi2, + real& M12, real& M21) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH | GEODESICSCALE, + lat2, lon2, azi2, t, t, M12, M21, t); + } + + /** + * See the documentation for GeodesicExact::Direct. + **********************************************************************/ + Math::real Direct(real lat1, real lon1, real azi1, real s12, + real& lat2, real& lon2, real& azi2, + real& m12, real& M12, real& M21) + const { + real t; + return GenDirect(lat1, lon1, azi1, false, s12, + LATITUDE | LONGITUDE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE, + lat2, lon2, azi2, t, m12, M12, M21, t); + } + ///@} + + /** \name Direct geodesic problem specified in terms of arc length. + **********************************************************************/ + ///@{ + /** + * Perform the direct geodesic calculation where the length of the geodesic + * is specified in terms of arc length. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] a12 arc length between point 1 and point 2 (degrees); it can + * be signed. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] s12 distance between point 1 and point 2 (meters). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * + * \e lat1 should be in the range [−90°, 90°]. The values of + * \e lon2 and \e azi2 returned are in the range [−180°, + * 180°]. + * + * If either point is at a pole, the azimuth is defined by keeping the + * longitude fixed, writing \e lat = ±(90° − ε), + * and taking the limit ε → 0+. An arc length greater that + * 180° signifies a geodesic which is not a shortest path. (For a + * prolate ellipsoid, an additional condition is necessary for a shortest + * path: the longitudinal extent must not exceed of 180°.) + * + * The following functions are overloaded versions of GeodesicExact::Direct + * which omit some of the output parameters. + **********************************************************************/ + 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 { + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + REDUCEDLENGTH | GEODESICSCALE | AREA, + lat2, lon2, azi2, s12, m12, M12, M21, S12); + } + + /** + * See the documentation for GeodesicExact::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2) const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE, + lat2, lon2, t, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicExact::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2, real& azi2) const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH, + lat2, lon2, azi2, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicExact::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2, real& azi2, real& s12) + const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE, + lat2, lon2, azi2, s12, t, t, t, t); + } + + /** + * See the documentation for GeodesicExact::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2, real& azi2, + real& s12, real& m12) const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + REDUCEDLENGTH, + lat2, lon2, azi2, s12, m12, t, t, t); + } + + /** + * See the documentation for GeodesicExact::ArcDirect. + **********************************************************************/ + void ArcDirect(real lat1, real lon1, real azi1, real a12, + real& lat2, real& lon2, real& azi2, real& s12, + real& M12, real& M21) const { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + GEODESICSCALE, + lat2, lon2, azi2, s12, t, M12, M21, t); + } + + /** + * See the documentation for GeodesicExact::ArcDirect. + **********************************************************************/ + 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 { + real t; + GenDirect(lat1, lon1, azi1, true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + REDUCEDLENGTH | GEODESICSCALE, + lat2, lon2, azi2, s12, m12, M12, M21, t); + } + ///@} + + /** \name General version of the direct geodesic solution. + **********************************************************************/ + ///@{ + + /** + * The general direct geodesic calculation. GeodesicExact::Direct and + * GeodesicExact::ArcDirect are defined in terms of this function. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] arcmode boolean flag determining the meaning of the second + * parameter. + * @param[in] s12_a12 if \e arcmode is false, this is the distance between + * point 1 and point 2 (meters); otherwise it is the arc length between + * point 1 and point 2 (degrees); it can be signed. + * @param[in] outmask a bitor'ed combination of GeodesicExact::mask values + * specifying which of the following parameters should be set. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] s12 distance between point 1 and point 2 (meters). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * @return \e a12 arc length of between point 1 and point 2 (degrees). + * + * The GeodesicExact::mask values possible for \e outmask are + * - \e outmask |= GeodesicExact::LATITUDE for the latitude \e lat2; + * - \e outmask |= GeodesicExact::LONGITUDE for the latitude \e lon2; + * - \e outmask |= GeodesicExact::AZIMUTH for the latitude \e azi2; + * - \e outmask |= GeodesicExact::DISTANCE for the distance \e s12; + * - \e outmask |= GeodesicExact::REDUCEDLENGTH for the reduced length \e + * m12; + * - \e outmask |= GeodesicExact::GEODESICSCALE for the geodesic scales \e + * M12 and \e M21; + * - \e outmask |= GeodesicExact::AREA for the area \e S12; + * - \e outmask |= GeodesicExact::ALL for all of the above; + * - \e outmask |= GeodesicExact::LONG_UNROLL to unroll \e lon2 instead of + * wrapping it into the range [−180°, 180°]. + * . + * The function value \e a12 is always computed and returned and this + * equals \e s12_a12 is \e arcmode is true. If \e outmask includes + * GeodesicExact::DISTANCE and \e arcmode is false, then \e s12 = \e + * s12_a12. It is not necessary to include GeodesicExact::DISTANCE_IN in + * \e outmask; this is automatically included is \e arcmode is false. + * + * With the GeodesicExact::LONG_UNROLL bit set, the quantity \e lon2 + * − \e lon1 indicates how many times and in what sense the geodesic + * encircles the ellipsoid. + **********************************************************************/ + 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; + ///@} + + /** \name Inverse geodesic problem. + **********************************************************************/ + ///@{ + /** + * Perform the inverse geodesic calculation. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] lat2 latitude of point 2 (degrees). + * @param[in] lon2 longitude of point 2 (degrees). + * @param[out] s12 distance between point 1 and point 2 (meters). + * @param[out] azi1 azimuth at point 1 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * @return \e a12 arc length of between point 1 and point 2 (degrees). + * + * \e lat1 and \e lat2 should be in the range [−90°, 90°]. + * The values of \e azi1 and \e azi2 returned are in the range + * [−180°, 180°]. + * + * If either point is at a pole, the azimuth is defined by keeping the + * longitude fixed, writing \e lat = ±(90° − ε), + * and taking the limit ε → 0+. + * + * The following functions are overloaded versions of + * GeodesicExact::Inverse which omit some of the output parameters. Note, + * however, that the arc length is always computed and returned as the + * function value. + **********************************************************************/ + 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 { + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE | AREA, + s12, azi1, azi2, m12, M12, M21, S12); + } + + /** + * See the documentation for GeodesicExact::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12) const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE, + s12, t, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicExact::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& azi1, real& azi2) const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + AZIMUTH, + t, azi1, azi2, t, t, t, t); + } + + /** + * See the documentation for GeodesicExact::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi1, real& azi2) + const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH, + s12, azi1, azi2, t, t, t, t); + } + + /** + * See the documentation for GeodesicExact::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi1, real& azi2, real& m12) + const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH | REDUCEDLENGTH, + s12, azi1, azi2, m12, t, t, t); + } + + /** + * See the documentation for GeodesicExact::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi1, real& azi2, + real& M12, real& M21) const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH | GEODESICSCALE, + s12, azi1, azi2, t, M12, M21, t); + } + + /** + * See the documentation for GeodesicExact::Inverse. + **********************************************************************/ + Math::real Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi1, real& azi2, real& m12, + real& M12, real& M21) const { + real t; + return GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE, + s12, azi1, azi2, m12, M12, M21, t); + } + ///@} + + /** \name General version of inverse geodesic solution. + **********************************************************************/ + ///@{ + /** + * The general inverse geodesic calculation. GeodesicExact::Inverse is + * defined in terms of this function. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] lat2 latitude of point 2 (degrees). + * @param[in] lon2 longitude of point 2 (degrees). + * @param[in] outmask a bitor'ed combination of GeodesicExact::mask values + * specifying which of the following parameters should be set. + * @param[out] s12 distance between point 1 and point 2 (meters). + * @param[out] azi1 azimuth at point 1 (degrees). + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] m12 reduced length of geodesic (meters). + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless). + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless). + * @param[out] S12 area under the geodesic (meters2). + * @return \e a12 arc length of between point 1 and point 2 (degrees). + * + * The GeodesicExact::mask values possible for \e outmask are + * - \e outmask |= GeodesicExact::DISTANCE for the distance \e s12; + * - \e outmask |= GeodesicExact::AZIMUTH for the latitude \e azi2; + * - \e outmask |= GeodesicExact::REDUCEDLENGTH for the reduced length \e + * m12; + * - \e outmask |= GeodesicExact::GEODESICSCALE for the geodesic scales \e + * M12 and \e M21; + * - \e outmask |= GeodesicExact::AREA for the area \e S12; + * - \e outmask |= GeodesicExact::ALL for all of the above. + * . + * The arc length is always computed and returned as the function value. + **********************************************************************/ + Math::real GenInverse(real lat1, real lon1, real lat2, real lon2, + unsigned outmask, + real& s12, real& azi1, real& azi2, + real& m12, real& M12, real& M21, real& S12) const; + ///@} + + /** \name Interface to GeodesicLineExact. + **********************************************************************/ + ///@{ + + /** + * Set up to compute several points on a single geodesic. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] caps bitor'ed combination of GeodesicExact::mask values + * specifying the capabilities the GeodesicLineExact object should + * possess, i.e., which quantities can be returned in calls to + * GeodesicLineExact::Position. + * @return a GeodesicLineExact object. + * + * \e lat1 should be in the range [−90°, 90°]. + * + * The GeodesicExact::mask values are + * - \e caps |= GeodesicExact::LATITUDE for the latitude \e lat2; this is + * added automatically; + * - \e caps |= GeodesicExact::LONGITUDE for the latitude \e lon2; + * - \e caps |= GeodesicExact::AZIMUTH for the azimuth \e azi2; this is + * added automatically; + * - \e caps |= GeodesicExact::DISTANCE for the distance \e s12; + * - \e caps |= GeodesicExact::REDUCEDLENGTH for the reduced length \e m12; + * - \e caps |= GeodesicExact::GEODESICSCALE for the geodesic scales \e M12 + * and \e M21; + * - \e caps |= GeodesicExact::AREA for the area \e S12; + * - \e caps |= GeodesicExact::DISTANCE_IN permits the length of the + * geodesic to be given in terms of \e s12; without this capability the + * length can only be specified in terms of arc length; + * - \e caps |= GeodesicExact::ALL for all of the above. + * . + * The default value of \e caps is GeodesicExact::ALL which turns on all + * the capabilities. + * + * If the point is at a pole, the azimuth is defined by keeping \e lon1 + * fixed, writing \e lat1 = ±(90 − ε), and taking the + * limit ε → 0+. + **********************************************************************/ + GeodesicLineExact Line(real lat1, real lon1, real azi1, + unsigned caps = ALL) const; + + /** + * Define a GeodesicLineExact in terms of the inverse geodesic problem. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] lat2 latitude of point 2 (degrees). + * @param[in] lon2 longitude of point 2 (degrees). + * @param[in] caps bitor'ed combination of GeodesicExact::mask values + * specifying the capabilities the GeodesicLineExact object should + * possess, i.e., which quantities can be returned in calls to + * GeodesicLineExact::Position. + * @return a GeodesicLineExact object. + * + * This function sets point 3 of the GeodesicLineExact to correspond to + * point 2 of the inverse geodesic problem. + * + * \e lat1 and \e lat2 should be in the range [−90°, 90°]. + **********************************************************************/ + GeodesicLineExact InverseLine(real lat1, real lon1, real lat2, real lon2, + unsigned caps = ALL) const; + + /** + * Define a GeodesicLineExact in terms of the direct geodesic problem + * specified in terms of distance. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] s12 distance between point 1 and point 2 (meters); it can be + * negative. + * @param[in] caps bitor'ed combination of GeodesicExact::mask values + * specifying the capabilities the GeodesicLineExact object should + * possess, i.e., which quantities can be returned in calls to + * GeodesicLineExact::Position. + * @return a GeodesicLineExact object. + * + * This function sets point 3 of the GeodesicLineExact to correspond to + * point 2 of the direct geodesic problem. + * + * \e lat1 should be in the range [−90°, 90°]. + **********************************************************************/ + GeodesicLineExact DirectLine(real lat1, real lon1, real azi1, real s12, + unsigned caps = ALL) const; + + /** + * Define a GeodesicLineExact in terms of the direct geodesic problem + * specified in terms of arc length. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] a12 arc length between point 1 and point 2 (degrees); it can + * be negative. + * @param[in] caps bitor'ed combination of GeodesicExact::mask values + * specifying the capabilities the GeodesicLineExact object should + * possess, i.e., which quantities can be returned in calls to + * GeodesicLineExact::Position. + * @return a GeodesicLineExact object. + * + * This function sets point 3 of the GeodesicLineExact to correspond to + * point 2 of the direct geodesic problem. + * + * \e lat1 should be in the range [−90°, 90°]. + **********************************************************************/ + GeodesicLineExact ArcDirectLine(real lat1, real lon1, real azi1, real a12, + unsigned caps = ALL) const; + + /** + * Define a GeodesicLineExact in terms of the direct geodesic problem + * specified in terms of either distance or arc length. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] arcmode boolean flag determining the meaning of the \e + * s12_a12. + * @param[in] s12_a12 if \e arcmode is false, this is the distance between + * point 1 and point 2 (meters); otherwise it is the arc length between + * point 1 and point 2 (degrees); it can be negative. + * @param[in] caps bitor'ed combination of GeodesicExact::mask values + * specifying the capabilities the GeodesicLineExact object should + * possess, i.e., which quantities can be returned in calls to + * GeodesicLineExact::Position. + * @return a GeodesicLineExact object. + * + * This function sets point 3 of the GeodesicLineExact to correspond to + * point 2 of the direct geodesic problem. + * + * \e lat1 should be in the range [−90°, 90°]. + **********************************************************************/ + GeodesicLineExact GenDirectLine(real lat1, real lon1, real azi1, + bool arcmode, real s12_a12, + unsigned caps = ALL) const; + ///@} + + /** \name Inspector functions. + **********************************************************************/ + ///@{ + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _a; } + + /** + * @return \e f the flattening of the ellipsoid. This is the + * value used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _f; } + + /** + * @return total area of ellipsoid in meters2. The area of a + * polygon encircling a pole can be found by adding + * GeodesicExact::EllipsoidArea()/2 to the sum of \e S12 for each side of + * the polygon. + **********************************************************************/ + Math::real EllipsoidArea() const + { return 4 * Math::pi() * _c2; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of GeodesicExact with the parameters for the + * WGS84 ellipsoid. + **********************************************************************/ + static const GeodesicExact& WGS84(); + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_GEODESICEXACT_HPP diff --git a/external/include/GeographicLib/GeodesicLine.hpp b/external/include/GeographicLib/GeodesicLine.hpp new file mode 100644 index 0000000..f312096 --- /dev/null +++ b/external/include/GeographicLib/GeodesicLine.hpp @@ -0,0 +1,708 @@ +/** + * \file GeodesicLine.hpp + * \brief Header for GeographicLib::GeodesicLine class + * + * Copyright (c) Charles Karney (2009-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GEODESICLINE_HPP) +#define GEOGRAPHICLIB_GEODESICLINE_HPP 1 + +#include +#include + +namespace GeographicLib { + + /** + * \brief A geodesic line + * + * GeodesicLine facilitates the determination of a series of points on a + * single geodesic. The starting point (\e lat1, \e lon1) and the azimuth \e + * azi1 are specified in the constructor; alternatively, the Geodesic::Line + * method can be used to create a GeodesicLine. GeodesicLine.Position + * returns the location of point 2 a distance \e s12 along the geodesic. In + * addition, GeodesicLine.ArcPosition gives the position of point 2 an arc + * length \e a12 along the geodesic. + * + * You can register the position of a reference point 3 a distance (arc + * length), \e s13 (\e a13) along the geodesic with the + * GeodesicLine.SetDistance (GeodesicLine.SetArc) functions. Points a + * fractional distance along the line can be found by providing, for example, + * 0.5 * Distance() as an argument to GeodesicLine.Position. The + * Geodesic::InverseLine or Geodesic::DirectLine methods return GeodesicLine + * objects with point 3 set to the point 2 of the corresponding geodesic + * problem. GeodesicLine objects created with the public constructor or with + * Geodesic::Line have \e s13 and \e a13 set to NaNs. + * + * The default copy constructor and assignment operators work with this + * class. Similarly, a vector can be used to hold GeodesicLine objects. + * + * The calculations are accurate to better than 15 nm (15 nanometers). See + * Sec. 9 of + * arXiv:1102.1215v1 for + * details. The algorithms used by this class are based on series expansions + * using the flattening \e f as a small parameter. These are only accurate + * for |f| < 0.02; however reasonably accurate results will be + * obtained for |f| < 0.2. For very eccentric ellipsoids, use + * GeodesicLineExact instead. + * + * The algorithms are described in + * - C. F. F. Karney, + * + * Algorithms for geodesics, + * J. Geodesy 87, 43--55 (2013); + * DOI: + * 10.1007/s00190-012-0578-z; + * addenda: + * + * geod-addenda.html. + * . + * For more information on geodesics see \ref geodesic. + * + * Example of use: + * \include example-GeodesicLine.cpp + * + * GeodSolve is a command-line utility + * providing access to the functionality of Geodesic and GeodesicLine. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT GeodesicLine { + private: + typedef Math::real real; + friend class Geodesic; + static const int nC1_ = Geodesic::nC1_; + static const int nC1p_ = Geodesic::nC1p_; + static const int nC2_ = Geodesic::nC2_; + static const int nC3_ = Geodesic::nC3_; + static const int nC4_ = Geodesic::nC4_; + + real tiny_; + real _lat1, _lon1, _azi1; + real _a, _f, _b, _c2, _f1, _salp0, _calp0, _k2, + _salp1, _calp1, _ssig1, _csig1, _dn1, _stau1, _ctau1, _somg1, _comg1, + _A1m1, _A2m1, _A3c, _B11, _B21, _B31, _A4, _B41; + real _a13, _s13; + // index zero elements of _C1a, _C1pa, _C2a, _C3a are unused + real _C1a[nC1_ + 1], _C1pa[nC1p_ + 1], _C2a[nC2_ + 1], _C3a[nC3_], + _C4a[nC4_]; // all the elements of _C4a are used + unsigned _caps; + + void LineInit(const Geodesic& g, + real lat1, real lon1, + real azi1, real salp1, real calp1, + unsigned caps); + GeodesicLine(const Geodesic& g, + real lat1, real lon1, + real azi1, real salp1, real calp1, + unsigned caps, bool arcmode, real s13_a13); + + enum captype { + CAP_NONE = Geodesic::CAP_NONE, + CAP_C1 = Geodesic::CAP_C1, + CAP_C1p = Geodesic::CAP_C1p, + CAP_C2 = Geodesic::CAP_C2, + CAP_C3 = Geodesic::CAP_C3, + CAP_C4 = Geodesic::CAP_C4, + CAP_ALL = Geodesic::CAP_ALL, + CAP_MASK = Geodesic::CAP_MASK, + OUT_ALL = Geodesic::OUT_ALL, + OUT_MASK = Geodesic::OUT_MASK, + }; + public: + + /** + * Bit masks for what calculations to do. They signify to the + * GeodesicLine::GeodesicLine constructor and to Geodesic::Line what + * capabilities should be included in the GeodesicLine object. This is + * merely a duplication of Geodesic::mask. + **********************************************************************/ + enum mask { + /** + * No capabilities, no output. + * @hideinitializer + **********************************************************************/ + NONE = Geodesic::NONE, + /** + * Calculate latitude \e lat2. (It's not necessary to include this as a + * capability to GeodesicLine because this is included by default.) + * @hideinitializer + **********************************************************************/ + LATITUDE = Geodesic::LATITUDE, + /** + * Calculate longitude \e lon2. + * @hideinitializer + **********************************************************************/ + LONGITUDE = Geodesic::LONGITUDE, + /** + * Calculate azimuths \e azi1 and \e azi2. (It's not necessary to + * include this as a capability to GeodesicLine because this is included + * by default.) + * @hideinitializer + **********************************************************************/ + AZIMUTH = Geodesic::AZIMUTH, + /** + * Calculate distance \e s12. + * @hideinitializer + **********************************************************************/ + DISTANCE = Geodesic::DISTANCE, + /** + * Allow distance \e s12 to be used as input in the direct geodesic + * problem. + * @hideinitializer + **********************************************************************/ + DISTANCE_IN = Geodesic::DISTANCE_IN, + /** + * Calculate reduced length \e m12. + * @hideinitializer + **********************************************************************/ + REDUCEDLENGTH = Geodesic::REDUCEDLENGTH, + /** + * Calculate geodesic scales \e M12 and \e M21. + * @hideinitializer + **********************************************************************/ + GEODESICSCALE = Geodesic::GEODESICSCALE, + /** + * Calculate area \e S12. + * @hideinitializer + **********************************************************************/ + AREA = Geodesic::AREA, + /** + * Unroll \e lon2 in the direct calculation. + * @hideinitializer + **********************************************************************/ + LONG_UNROLL = Geodesic::LONG_UNROLL, + /** + * All capabilities, calculate everything. (LONG_UNROLL is not + * included in this mask.) + * @hideinitializer + **********************************************************************/ + ALL = Geodesic::ALL, + }; + + /** \name Constructors + **********************************************************************/ + ///@{ + + /** + * Constructor for a geodesic line staring at latitude \e lat1, longitude + * \e lon1, and azimuth \e azi1 (all in degrees). + * + * @param[in] g A Geodesic object used to compute the necessary information + * about the GeodesicLine. + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] caps bitor'ed combination of GeodesicLine::mask values + * specifying the capabilities the GeodesicLine object should possess, + * i.e., which quantities can be returned in calls to + * GeodesicLine::Position. + * + * \e lat1 should be in the range [−90°, 90°]. + * + * The GeodesicLine::mask values are + * - \e caps |= GeodesicLine::LATITUDE for the latitude \e lat2; this is + * added automatically; + * - \e caps |= GeodesicLine::LONGITUDE for the latitude \e lon2; + * - \e caps |= GeodesicLine::AZIMUTH for the latitude \e azi2; this is + * added automatically; + * - \e caps |= GeodesicLine::DISTANCE for the distance \e s12; + * - \e caps |= GeodesicLine::REDUCEDLENGTH for the reduced length \e m12; + * - \e caps |= GeodesicLine::GEODESICSCALE for the geodesic scales \e M12 + * and \e M21; + * - \e caps |= GeodesicLine::AREA for the area \e S12; + * - \e caps |= GeodesicLine::DISTANCE_IN permits the length of the + * geodesic to be given in terms of \e s12; without this capability the + * length can only be specified in terms of arc length; + * - \e caps |= GeodesicLine::ALL for all of the above. + * . + * The default value of \e caps is GeodesicLine::ALL. + * + * If the point is at a pole, the azimuth is defined by keeping \e lon1 + * fixed, writing \e lat1 = ±(90° − ε), and taking + * the limit ε → 0+. + **********************************************************************/ + GeodesicLine(const Geodesic& g, real lat1, real lon1, real azi1, + unsigned caps = ALL); + + /** + * A default constructor. If GeodesicLine::Position is called on the + * resulting object, it returns immediately (without doing any + * calculations). The object can be set with a call to Geodesic::Line. + * Use Init() to test whether object is still in this uninitialized state. + **********************************************************************/ + GeodesicLine() : _caps(0U) {} + ///@} + + /** \name Position in terms of distance + **********************************************************************/ + ///@{ + + /** + * Compute the position of point 2 which is a distance \e s12 (meters) from + * point 1. + * + * @param[in] s12 distance from point 1 to point 2 (meters); it can be + * negative. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees); requires that the + * GeodesicLine object was constructed with \e caps |= + * GeodesicLine::LONGITUDE. + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] m12 reduced length of geodesic (meters); requires that the + * GeodesicLine object was constructed with \e caps |= + * GeodesicLine::REDUCEDLENGTH. + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless); requires that the GeodesicLine object was constructed + * with \e caps |= GeodesicLine::GEODESICSCALE. + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless); requires that the GeodesicLine object was constructed + * with \e caps |= GeodesicLine::GEODESICSCALE. + * @param[out] S12 area under the geodesic (meters2); requires + * that the GeodesicLine object was constructed with \e caps |= + * GeodesicLine::AREA. + * @return \e a12 arc length from point 1 to point 2 (degrees). + * + * The values of \e lon2 and \e azi2 returned are in the range + * [−180°, 180°]. + * + * The GeodesicLine object \e must have been constructed with \e caps |= + * GeodesicLine::DISTANCE_IN; otherwise Math::NaN() is returned and no + * parameters are set. Requesting a value which the GeodesicLine object is + * not capable of computing is not an error; the corresponding argument + * will not be altered. + * + * The following functions are overloaded versions of + * GeodesicLine::Position which omit some of the output parameters. Note, + * however, that the arc length is always computed and returned as the + * function value. + **********************************************************************/ + Math::real Position(real s12, + real& lat2, real& lon2, real& azi2, + real& m12, real& M12, real& M21, + real& S12) const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE | AREA, + lat2, lon2, azi2, t, m12, M12, M21, S12); + } + + /** + * See the documentation for GeodesicLine::Position. + **********************************************************************/ + Math::real Position(real s12, real& lat2, real& lon2) const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE, + lat2, lon2, t, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicLine::Position. + **********************************************************************/ + Math::real Position(real s12, real& lat2, real& lon2, + real& azi2) const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | AZIMUTH, + lat2, lon2, azi2, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicLine::Position. + **********************************************************************/ + Math::real Position(real s12, real& lat2, real& lon2, + real& azi2, real& m12) const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | + AZIMUTH | REDUCEDLENGTH, + lat2, lon2, azi2, t, m12, t, t, t); + } + + /** + * See the documentation for GeodesicLine::Position. + **********************************************************************/ + Math::real Position(real s12, real& lat2, real& lon2, + real& azi2, real& M12, real& M21) + const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | + AZIMUTH | GEODESICSCALE, + lat2, lon2, azi2, t, t, M12, M21, t); + } + + /** + * See the documentation for GeodesicLine::Position. + **********************************************************************/ + Math::real Position(real s12, + real& lat2, real& lon2, real& azi2, + real& m12, real& M12, real& M21) + const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE, + lat2, lon2, azi2, t, m12, M12, M21, t); + } + ///@} + + /** \name Position in terms of arc length + **********************************************************************/ + ///@{ + + /** + * Compute the position of point 2 which is an arc length \e a12 (degrees) + * from point 1. + * + * @param[in] a12 arc length from point 1 to point 2 (degrees); it can + * be negative. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees); requires that the + * GeodesicLine object was constructed with \e caps |= + * GeodesicLine::LONGITUDE. + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] s12 distance from point 1 to point 2 (meters); requires + * that the GeodesicLine object was constructed with \e caps |= + * GeodesicLine::DISTANCE. + * @param[out] m12 reduced length of geodesic (meters); requires that the + * GeodesicLine object was constructed with \e caps |= + * GeodesicLine::REDUCEDLENGTH. + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless); requires that the GeodesicLine object was constructed + * with \e caps |= GeodesicLine::GEODESICSCALE. + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless); requires that the GeodesicLine object was constructed + * with \e caps |= GeodesicLine::GEODESICSCALE. + * @param[out] S12 area under the geodesic (meters2); requires + * that the GeodesicLine object was constructed with \e caps |= + * GeodesicLine::AREA. + * + * The values of \e lon2 and \e azi2 returned are in the range + * [−180°, 180°]. + * + * Requesting a value which the GeodesicLine object is not capable of + * computing is not an error; the corresponding argument will not be + * altered. + * + * The following functions are overloaded versions of + * GeodesicLine::ArcPosition which omit some of the output parameters. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12, real& m12, real& M12, real& M21, + real& S12) const { + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + REDUCEDLENGTH | GEODESICSCALE | AREA, + lat2, lon2, azi2, s12, m12, M12, M21, S12); + } + + /** + * See the documentation for GeodesicLine::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2) + const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE, + lat2, lon2, t, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicLine::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, + real& lat2, real& lon2, real& azi2) + const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH, + lat2, lon2, azi2, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicLine::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12) const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE, + lat2, lon2, azi2, s12, t, t, t, t); + } + + /** + * See the documentation for GeodesicLine::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12, real& m12) const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | + DISTANCE | REDUCEDLENGTH, + lat2, lon2, azi2, s12, m12, t, t, t); + } + + /** + * See the documentation for GeodesicLine::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12, real& M12, real& M21) + const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | + DISTANCE | GEODESICSCALE, + lat2, lon2, azi2, s12, t, M12, M21, t); + } + + /** + * See the documentation for GeodesicLine::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12, real& m12, real& M12, real& M21) + const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | + DISTANCE | REDUCEDLENGTH | GEODESICSCALE, + lat2, lon2, azi2, s12, m12, M12, M21, t); + } + ///@} + + /** \name The general position function. + **********************************************************************/ + ///@{ + + /** + * The general position function. GeodesicLine::Position and + * GeodesicLine::ArcPosition are defined in terms of this function. + * + * @param[in] arcmode boolean flag determining the meaning of the second + * parameter; if \e arcmode is false, then the GeodesicLine object must + * have been constructed with \e caps |= GeodesicLine::DISTANCE_IN. + * @param[in] s12_a12 if \e arcmode is false, this is the distance between + * point 1 and point 2 (meters); otherwise it is the arc length between + * point 1 and point 2 (degrees); it can be negative. + * @param[in] outmask a bitor'ed combination of GeodesicLine::mask values + * specifying which of the following parameters should be set. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees); requires that the + * GeodesicLine object was constructed with \e caps |= + * GeodesicLine::LONGITUDE. + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] s12 distance from point 1 to point 2 (meters); requires + * that the GeodesicLine object was constructed with \e caps |= + * GeodesicLine::DISTANCE. + * @param[out] m12 reduced length of geodesic (meters); requires that the + * GeodesicLine object was constructed with \e caps |= + * GeodesicLine::REDUCEDLENGTH. + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless); requires that the GeodesicLine object was constructed + * with \e caps |= GeodesicLine::GEODESICSCALE. + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless); requires that the GeodesicLine object was constructed + * with \e caps |= GeodesicLine::GEODESICSCALE. + * @param[out] S12 area under the geodesic (meters2); requires + * that the GeodesicLine object was constructed with \e caps |= + * GeodesicLine::AREA. + * @return \e a12 arc length from point 1 to point 2 (degrees). + * + * The GeodesicLine::mask values possible for \e outmask are + * - \e outmask |= GeodesicLine::LATITUDE for the latitude \e lat2; + * - \e outmask |= GeodesicLine::LONGITUDE for the latitude \e lon2; + * - \e outmask |= GeodesicLine::AZIMUTH for the latitude \e azi2; + * - \e outmask |= GeodesicLine::DISTANCE for the distance \e s12; + * - \e outmask |= GeodesicLine::REDUCEDLENGTH for the reduced length \e + * m12; + * - \e outmask |= GeodesicLine::GEODESICSCALE for the geodesic scales \e + * M12 and \e M21; + * - \e outmask |= GeodesicLine::AREA for the area \e S12; + * - \e outmask |= GeodesicLine::ALL for all of the above; + * - \e outmask |= GeodesicLine::LONG_UNROLL to unroll \e lon2 instead of + * reducing it into the range [−180°, 180°]. + * . + * Requesting a value which the GeodesicLine object is not capable of + * computing is not an error; the corresponding argument will not be + * altered. Note, however, that the arc length is always computed and + * returned as the function value. + * + * With the GeodesicLine::LONG_UNROLL bit set, the quantity \e lon2 − + * \e lon1 indicates how many times and in what sense the geodesic + * encircles the ellipsoid. + **********************************************************************/ + Math::real GenPosition(bool arcmode, real s12_a12, unsigned outmask, + real& lat2, real& lon2, real& azi2, + real& s12, real& m12, real& M12, real& M21, + real& S12) const; + ///@} + + /** \name Setting point 3 + **********************************************************************/ + ///@{ + + /** + * Specify position of point 3 in terms of distance. + * + * @param[in] s13 the distance from point 1 to point 3 (meters); it + * can be negative. + * + * This is only useful if the GeodesicLine object has been constructed + * with \e caps |= GeodesicLine::DISTANCE_IN. + **********************************************************************/ + void SetDistance(real s13); + + /** + * Specify position of point 3 in terms of arc length. + * + * @param[in] a13 the arc length from point 1 to point 3 (degrees); it + * can be negative. + * + * The distance \e s13 is only set if the GeodesicLine object has been + * constructed with \e caps |= GeodesicLine::DISTANCE. + **********************************************************************/ + void SetArc(real a13); + + /** + * Specify position of point 3 in terms of either distance or arc length. + * + * @param[in] arcmode boolean flag determining the meaning of the second + * parameter; if \e arcmode is false, then the GeodesicLine object must + * have been constructed with \e caps |= GeodesicLine::DISTANCE_IN. + * @param[in] s13_a13 if \e arcmode is false, this is the distance from + * point 1 to point 3 (meters); otherwise it is the arc length from + * point 1 to point 3 (degrees); it can be negative. + **********************************************************************/ + void GenSetDistance(bool arcmode, real s13_a13); + ///@} + + /** \name Inspector functions + **********************************************************************/ + ///@{ + + /** + * @return true if the object has been initialized. + **********************************************************************/ + bool Init() const { return _caps != 0U; } + + /** + * @return \e lat1 the latitude of point 1 (degrees). + **********************************************************************/ + Math::real Latitude() const + { return Init() ? _lat1 : Math::NaN(); } + + /** + * @return \e lon1 the longitude of point 1 (degrees). + **********************************************************************/ + Math::real Longitude() const + { return Init() ? _lon1 : Math::NaN(); } + + /** + * @return \e azi1 the azimuth (degrees) of the geodesic line at point 1. + **********************************************************************/ + Math::real Azimuth() const + { return Init() ? _azi1 : Math::NaN(); } + + /** + * The sine and cosine of \e azi1. + * + * @param[out] sazi1 the sine of \e azi1. + * @param[out] cazi1 the cosine of \e azi1. + **********************************************************************/ + void Azimuth(real& sazi1, real& cazi1) const + { if (Init()) { sazi1 = _salp1; cazi1 = _calp1; } } + + /** + * @return \e azi0 the azimuth (degrees) of the geodesic line as it crosses + * the equator in a northward direction. + * + * The result lies in [−90°, 90°]. + **********************************************************************/ + Math::real EquatorialAzimuth() const + { return Init() ? Math::atan2d(_salp0, _calp0) : Math::NaN(); } + + /** + * The sine and cosine of \e azi0. + * + * @param[out] sazi0 the sine of \e azi0. + * @param[out] cazi0 the cosine of \e azi0. + **********************************************************************/ + void EquatorialAzimuth(real& sazi0, real& cazi0) const + { if (Init()) { sazi0 = _salp0; cazi0 = _calp0; } } + + /** + * @return \e a1 the arc length (degrees) between the northward equatorial + * crossing and point 1. + * + * The result lies in (−180°, 180°]. + **********************************************************************/ + Math::real EquatorialArc() const { + return Init() ? Math::atan2d(_ssig1, _csig1) : Math::NaN(); + } + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value inherited from the Geodesic object used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const + { return Init() ? _a : Math::NaN(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the Geodesic object used in the constructor. + **********************************************************************/ + Math::real Flattening() const + { return Init() ? _f : Math::NaN(); } + + /** + * @return \e caps the computational capabilities that this object was + * constructed with. LATITUDE and AZIMUTH are always included. + **********************************************************************/ + unsigned Capabilities() const { return _caps; } + + /** + * Test what capabilities are available. + * + * @param[in] testcaps a set of bitor'ed GeodesicLine::mask values. + * @return true if the GeodesicLine object has all these capabilities. + **********************************************************************/ + bool Capabilities(unsigned testcaps) const { + testcaps &= OUT_ALL; + return (_caps & testcaps) == testcaps; + } + + /** + * The distance or arc length to point 3. + * + * @param[in] arcmode boolean flag determining the meaning of returned + * value. + * @return \e s13 if \e arcmode is false; \e a13 if \e arcmode is true. + **********************************************************************/ + Math::real GenDistance(bool arcmode) const + { return Init() ? (arcmode ? _a13 : _s13) : Math::NaN(); } + + /** + * @return \e s13, the distance to point 3 (meters). + **********************************************************************/ + Math::real Distance() const { return GenDistance(false); } + + /** + * @return \e a13, the arc length to point 3 (degrees). + **********************************************************************/ + Math::real Arc() const { return GenDistance(true); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_GEODESICLINE_HPP diff --git a/external/include/GeographicLib/GeodesicLineExact.hpp b/external/include/GeographicLib/GeodesicLineExact.hpp new file mode 100644 index 0000000..5fdf635 --- /dev/null +++ b/external/include/GeographicLib/GeodesicLineExact.hpp @@ -0,0 +1,673 @@ +/** + * \file GeodesicLineExact.hpp + * \brief Header for GeographicLib::GeodesicLineExact class + * + * Copyright (c) Charles Karney (2012-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GEODESICLINEEXACT_HPP) +#define GEOGRAPHICLIB_GEODESICLINEEXACT_HPP 1 + +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief An exact geodesic line + * + * GeodesicLineExact facilitates the determination of a series of points on a + * single geodesic. This is a companion to the GeodesicExact class. For + * additional information on this class see the documentation on the + * GeodesicLine class. + * + * Example of use: + * \include example-GeodesicLineExact.cpp + * + * GeodSolve is a command-line utility + * providing access to the functionality of GeodesicExact and + * GeodesicLineExact (via the -E option). + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT GeodesicLineExact { + private: + typedef Math::real real; + friend class GeodesicExact; + static const int nC4_ = GeodesicExact::nC4_; + + real tiny_; + real _lat1, _lon1, _azi1; + real _a, _f, _b, _c2, _f1, _e2, _salp0, _calp0, _k2, + _salp1, _calp1, _ssig1, _csig1, _dn1, _stau1, _ctau1, + _somg1, _comg1, _cchi1, + _A4, _B41, _E0, _D0, _H0, _E1, _D1, _H1; + real _a13, _s13; + real _C4a[nC4_]; // all the elements of _C4a are used + EllipticFunction _E; + unsigned _caps; + + void LineInit(const GeodesicExact& g, + real lat1, real lon1, + real azi1, real salp1, real calp1, + unsigned caps); + GeodesicLineExact(const GeodesicExact& g, + real lat1, real lon1, + real azi1, real salp1, real calp1, + unsigned caps, bool arcmode, real s13_a13); + + enum captype { + CAP_NONE = GeodesicExact::CAP_NONE, + CAP_E = GeodesicExact::CAP_E, + CAP_D = GeodesicExact::CAP_D, + CAP_H = GeodesicExact::CAP_H, + CAP_C4 = GeodesicExact::CAP_C4, + CAP_ALL = GeodesicExact::CAP_ALL, + CAP_MASK = GeodesicExact::CAP_MASK, + OUT_ALL = GeodesicExact::OUT_ALL, + OUT_MASK = GeodesicExact::OUT_MASK, + }; + public: + + /** + * Bit masks for what calculations to do. They signify to the + * GeodesicLineExact::GeodesicLineExact constructor and to + * GeodesicExact::Line what capabilities should be included in the + * GeodesicLineExact object. This is merely a duplication of + * GeodesicExact::mask. + **********************************************************************/ + enum mask { + /** + * No capabilities, no output. + * @hideinitializer + **********************************************************************/ + NONE = GeodesicExact::NONE, + /** + * Calculate latitude \e lat2. (It's not necessary to include this as a + * capability to GeodesicLineExact because this is included by default.) + * @hideinitializer + **********************************************************************/ + LATITUDE = GeodesicExact::LATITUDE, + /** + * Calculate longitude \e lon2. + * @hideinitializer + **********************************************************************/ + LONGITUDE = GeodesicExact::LONGITUDE, + /** + * Calculate azimuths \e azi1 and \e azi2. (It's not necessary to + * include this as a capability to GeodesicLineExact because this is + * included by default.) + * @hideinitializer + **********************************************************************/ + AZIMUTH = GeodesicExact::AZIMUTH, + /** + * Calculate distance \e s12. + * @hideinitializer + **********************************************************************/ + DISTANCE = GeodesicExact::DISTANCE, + /** + * Allow distance \e s12 to be used as input in the direct geodesic + * problem. + * @hideinitializer + **********************************************************************/ + DISTANCE_IN = GeodesicExact::DISTANCE_IN, + /** + * Calculate reduced length \e m12. + * @hideinitializer + **********************************************************************/ + REDUCEDLENGTH = GeodesicExact::REDUCEDLENGTH, + /** + * Calculate geodesic scales \e M12 and \e M21. + * @hideinitializer + **********************************************************************/ + GEODESICSCALE = GeodesicExact::GEODESICSCALE, + /** + * Calculate area \e S12. + * @hideinitializer + **********************************************************************/ + AREA = GeodesicExact::AREA, + /** + * Unroll \e lon2 in the direct calculation. + * @hideinitializer + **********************************************************************/ + LONG_UNROLL = GeodesicExact::LONG_UNROLL, + /** + * All capabilities, calculate everything. (LONG_UNROLL is not + * included in this mask.) + * @hideinitializer + **********************************************************************/ + ALL = GeodesicExact::ALL, + }; + + /** \name Constructors + **********************************************************************/ + ///@{ + + /** + * Constructor for a geodesic line staring at latitude \e lat1, longitude + * \e lon1, and azimuth \e azi1 (all in degrees). + * + * @param[in] g A GeodesicExact object used to compute the necessary + * information about the GeodesicLineExact. + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi1 azimuth at point 1 (degrees). + * @param[in] caps bitor'ed combination of GeodesicLineExact::mask values + * specifying the capabilities the GeodesicLineExact object should + * possess, i.e., which quantities can be returned in calls to + * GeodesicLine::Position. + * + * \e lat1 should be in the range [−90°, 90°]. + * + * The GeodesicLineExact::mask values are + * - \e caps |= GeodesicLineExact::LATITUDE for the latitude \e lat2; this + * is added automatically; + * - \e caps |= GeodesicLineExact::LONGITUDE for the latitude \e lon2; + * - \e caps |= GeodesicLineExact::AZIMUTH for the latitude \e azi2; this + * is added automatically; + * - \e caps |= GeodesicLineExact::DISTANCE for the distance \e s12; + * - \e caps |= GeodesicLineExact::REDUCEDLENGTH for the reduced length \e + m12; + * - \e caps |= GeodesicLineExact::GEODESICSCALE for the geodesic scales \e + * M12 and \e M21; + * - \e caps |= GeodesicLineExact::AREA for the area \e S12; + * - \e caps |= GeodesicLineExact::DISTANCE_IN permits the length of the + * geodesic to be given in terms of \e s12; without this capability the + * length can only be specified in terms of arc length; + * - \e caps |= GeodesicLineExact::ALL for all of the above. + * . + * The default value of \e caps is GeodesicLineExact::ALL. + * + * If the point is at a pole, the azimuth is defined by keeping \e lon1 + * fixed, writing \e lat1 = ±(90° − ε), and taking + * the limit ε → 0+. + **********************************************************************/ + GeodesicLineExact(const GeodesicExact& g, real lat1, real lon1, real azi1, + unsigned caps = ALL); + + /** + * A default constructor. If GeodesicLineExact::Position is called on the + * resulting object, it returns immediately (without doing any + * calculations). The object can be set with a call to + * GeodesicExact::Line. Use Init() to test whether object is still in this + * uninitialized state. + **********************************************************************/ + GeodesicLineExact() : _caps(0U) {} + ///@} + + /** \name Position in terms of distance + **********************************************************************/ + ///@{ + + /** + * Compute the position of point 2 which is a distance \e s12 (meters) + * from point 1. + * + * @param[in] s12 distance from point 1 to point 2 (meters); it can be + * signed. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees); requires that the + * GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::LONGITUDE. + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] m12 reduced length of geodesic (meters); requires that the + * GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::REDUCEDLENGTH. + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless); requires that the GeodesicLineExact object was + * constructed with \e caps |= GeodesicLineExact::GEODESICSCALE. + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless); requires that the GeodesicLineExact object was + * constructed with \e caps |= GeodesicLineExact::GEODESICSCALE. + * @param[out] S12 area under the geodesic (meters2); requires + * that the GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::AREA. + * @return \e a12 arc length from point 1 to point 2 (degrees). + * + * The values of \e lon2 and \e azi2 returned are in the range + * [−180°, 180°]. + * + * The GeodesicLineExact object \e must have been constructed with \e caps + * |= GeodesicLineExact::DISTANCE_IN; otherwise Math::NaN() is returned and + * no parameters are set. Requesting a value which the GeodesicLineExact + * object is not capable of computing is not an error; the corresponding + * argument will not be altered. + * + * The following functions are overloaded versions of + * GeodesicLineExact::Position which omit some of the output parameters. + * Note, however, that the arc length is always computed and returned as + * the function value. + **********************************************************************/ + Math::real Position(real s12, + real& lat2, real& lon2, real& azi2, + real& m12, real& M12, real& M21, + real& S12) const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE | AREA, + lat2, lon2, azi2, t, m12, M12, M21, S12); + } + + /** + * See the documentation for GeodesicLineExact::Position. + **********************************************************************/ + Math::real Position(real s12, real& lat2, real& lon2) const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE, + lat2, lon2, t, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicLineExact::Position. + **********************************************************************/ + Math::real Position(real s12, real& lat2, real& lon2, + real& azi2) const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | AZIMUTH, + lat2, lon2, azi2, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicLineExact::Position. + **********************************************************************/ + Math::real Position(real s12, real& lat2, real& lon2, + real& azi2, real& m12) const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | + AZIMUTH | REDUCEDLENGTH, + lat2, lon2, azi2, t, m12, t, t, t); + } + + /** + * See the documentation for GeodesicLineExact::Position. + **********************************************************************/ + Math::real Position(real s12, real& lat2, real& lon2, + real& azi2, real& M12, real& M21) + const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | + AZIMUTH | GEODESICSCALE, + lat2, lon2, azi2, t, t, M12, M21, t); + } + + /** + * See the documentation for GeodesicLineExact::Position. + **********************************************************************/ + Math::real Position(real s12, + real& lat2, real& lon2, real& azi2, + real& m12, real& M12, real& M21) + const { + real t; + return GenPosition(false, s12, + LATITUDE | LONGITUDE | AZIMUTH | + REDUCEDLENGTH | GEODESICSCALE, + lat2, lon2, azi2, t, m12, M12, M21, t); + } + ///@} + + /** \name Position in terms of arc length + **********************************************************************/ + ///@{ + + /** + * Compute the position of point 2 which is an arc length \e a12 (degrees) + * from point 1. + * + * @param[in] a12 arc length from point 1 to point 2 (degrees); it can + * be signed. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees); requires that the + * GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::LONGITUDE. + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] s12 distance from point 1 to point 2 (meters); requires + * that the GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::DISTANCE. + * @param[out] m12 reduced length of geodesic (meters); requires that the + * GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::REDUCEDLENGTH. + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless); requires that the GeodesicLineExact object was + * constructed with \e caps |= GeodesicLineExact::GEODESICSCALE. + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless); requires that the GeodesicLineExact object was + * constructed with \e caps |= GeodesicLineExact::GEODESICSCALE. + * @param[out] S12 area under the geodesic (meters2); requires + * that the GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::AREA. + * + * The values of \e lon2 and \e azi2 returned are in the range + * [−180°, 180°]. + * + * Requesting a value which the GeodesicLineExact object is not capable of + * computing is not an error; the corresponding argument will not be + * altered. + * + * The following functions are overloaded versions of + * GeodesicLineExact::ArcPosition which omit some of the output parameters. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12, real& m12, real& M12, real& M21, + real& S12) const { + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE | + REDUCEDLENGTH | GEODESICSCALE | AREA, + lat2, lon2, azi2, s12, m12, M12, M21, S12); + } + + /** + * See the documentation for GeodesicLineExact::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2) + const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE, + lat2, lon2, t, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicLineExact::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, + real& lat2, real& lon2, real& azi2) + const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH, + lat2, lon2, azi2, t, t, t, t, t); + } + + /** + * See the documentation for GeodesicLineExact::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12) const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | DISTANCE, + lat2, lon2, azi2, s12, t, t, t, t); + } + + /** + * See the documentation for GeodesicLineExact::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12, real& m12) const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | + DISTANCE | REDUCEDLENGTH, + lat2, lon2, azi2, s12, m12, t, t, t); + } + + /** + * See the documentation for GeodesicLineExact::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12, real& M12, real& M21) + const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | + DISTANCE | GEODESICSCALE, + lat2, lon2, azi2, s12, t, M12, M21, t); + } + + /** + * See the documentation for GeodesicLineExact::ArcPosition. + **********************************************************************/ + void ArcPosition(real a12, real& lat2, real& lon2, real& azi2, + real& s12, real& m12, real& M12, real& M21) + const { + real t; + GenPosition(true, a12, + LATITUDE | LONGITUDE | AZIMUTH | + DISTANCE | REDUCEDLENGTH | GEODESICSCALE, + lat2, lon2, azi2, s12, m12, M12, M21, t); + } + ///@} + + /** \name The general position function. + **********************************************************************/ + ///@{ + + /** + * The general position function. GeodesicLineExact::Position and + * GeodesicLineExact::ArcPosition are defined in terms of this function. + * + * @param[in] arcmode boolean flag determining the meaning of the second + * parameter; if \e arcmode is false, then the GeodesicLineExact object + * must have been constructed with \e caps |= + * GeodesicLineExact::DISTANCE_IN. + * @param[in] s12_a12 if \e arcmode is false, this is the distance between + * point 1 and point 2 (meters); otherwise it is the arc length between + * point 1 and point 2 (degrees); it can be signed. + * @param[in] outmask a bitor'ed combination of GeodesicLineExact::mask + * values specifying which of the following parameters should be set. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees); requires that the + * GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::LONGITUDE. + * @param[out] azi2 (forward) azimuth at point 2 (degrees). + * @param[out] s12 distance from point 1 to point 2 (meters); requires + * that the GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::DISTANCE. + * @param[out] m12 reduced length of geodesic (meters); requires that the + * GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::REDUCEDLENGTH. + * @param[out] M12 geodesic scale of point 2 relative to point 1 + * (dimensionless); requires that the GeodesicLineExact object was + * constructed with \e caps |= GeodesicLineExact::GEODESICSCALE. + * @param[out] M21 geodesic scale of point 1 relative to point 2 + * (dimensionless); requires that the GeodesicLineExact object was + * constructed with \e caps |= GeodesicLineExact::GEODESICSCALE. + * @param[out] S12 area under the geodesic (meters2); requires + * that the GeodesicLineExact object was constructed with \e caps |= + * GeodesicLineExact::AREA. + * @return \e a12 arc length from point 1 to point 2 (degrees). + * + * The GeodesicLineExact::mask values possible for \e outmask are + * - \e outmask |= GeodesicLineExact::LATITUDE for the latitude \e lat2; + * - \e outmask |= GeodesicLineExact::LONGITUDE for the latitude \e lon2; + * - \e outmask |= GeodesicLineExact::AZIMUTH for the latitude \e azi2; + * - \e outmask |= GeodesicLineExact::DISTANCE for the distance \e s12; + * - \e outmask |= GeodesicLineExact::REDUCEDLENGTH for the reduced length + * \e m12; + * - \e outmask |= GeodesicLineExact::GEODESICSCALE for the geodesic scales + * \e M12 and \e M21; + * - \e outmask |= GeodesicLineExact::AREA for the area \e S12; + * - \e outmask |= GeodesicLineExact::ALL for all of the above; + * - \e outmask |= GeodesicLineExact::LONG_UNROLL to unroll \e lon2 instead + * of wrapping it into the range [−180°, 180°]. + * . + * Requesting a value which the GeodesicLineExact object is not capable of + * computing is not an error; the corresponding argument will not be + * altered. Note, however, that the arc length is always computed and + * returned as the function value. + * + * With the GeodesicLineExact::LONG_UNROLL bit set, the quantity \e lon2 + * − \e lon1 indicates how many times and in what sense the geodesic + * encircles the ellipsoid. + **********************************************************************/ + Math::real GenPosition(bool arcmode, real s12_a12, unsigned outmask, + real& lat2, real& lon2, real& azi2, + real& s12, real& m12, real& M12, real& M21, + real& S12) const; + ///@} + + /** \name Setting point 3 + **********************************************************************/ + ///@{ + + /** + * Specify position of point 3 in terms of distance. + * + * @param[in] s13 the distance from point 1 to point 3 (meters); it + * can be negative. + * + * This is only useful if the GeodesicLineExact object has been constructed + * with \e caps |= GeodesicLineExact::DISTANCE_IN. + **********************************************************************/ + void SetDistance(real s13); + + /** + * Specify position of point 3 in terms of arc length. + * + * @param[in] a13 the arc length from point 1 to point 3 (degrees); it + * can be negative. + * + * The distance \e s13 is only set if the GeodesicLineExact object has been + * constructed with \e caps |= GeodesicLineExact::DISTANCE. + **********************************************************************/ + void SetArc(real a13); + + /** + * Specify position of point 3 in terms of either distance or arc length. + * + * @param[in] arcmode boolean flag determining the meaning of the second + * parameter; if \e arcmode is false, then the GeodesicLineExact object + * must have been constructed with \e caps |= + * GeodesicLineExact::DISTANCE_IN. + * @param[in] s13_a13 if \e arcmode is false, this is the distance from + * point 1 to point 3 (meters); otherwise it is the arc length from + * point 1 to point 3 (degrees); it can be negative. + **********************************************************************/ + void GenSetDistance(bool arcmode, real s13_a13); + + /** \name Inspector functions + **********************************************************************/ + ///@{ + + /** + * @return true if the object has been initialized. + **********************************************************************/ + bool Init() const { return _caps != 0U; } + + /** + * @return \e lat1 the latitude of point 1 (degrees). + **********************************************************************/ + Math::real Latitude() const + { return Init() ? _lat1 : Math::NaN(); } + + /** + * @return \e lon1 the longitude of point 1 (degrees). + **********************************************************************/ + Math::real Longitude() const + { return Init() ? _lon1 : Math::NaN(); } + + /** + * @return \e azi1 the azimuth (degrees) of the geodesic line at point 1. + **********************************************************************/ + Math::real Azimuth() const + { return Init() ? _azi1 : Math::NaN(); } + + /** + * The sine and cosine of \e azi1. + * + * @param[out] sazi1 the sine of \e azi1. + * @param[out] cazi1 the cosine of \e azi1. + **********************************************************************/ + void Azimuth(real& sazi1, real& cazi1) const + { if (Init()) { sazi1 = _salp1; cazi1 = _calp1; } } + + /** + * @return \e azi0 the azimuth (degrees) of the geodesic line as it crosses + * the equator in a northward direction. + * + * The result lies in [−90°, 90°]. + **********************************************************************/ + Math::real EquatorialAzimuth() const + { return Init() ? Math::atan2d(_salp0, _calp0) : Math::NaN(); } + + /** + * The sine and cosine of \e azi0. + * + * @param[out] sazi0 the sine of \e azi0. + * @param[out] cazi0 the cosine of \e azi0. + **********************************************************************/ + void EquatorialAzimuth(real& sazi0, real& cazi0) const + { if (Init()) { sazi0 = _salp0; cazi0 = _calp0; } } + + /** + * @return \e a1 the arc length (degrees) between the northward equatorial + * crossing and point 1. + * + * The result lies in (−180°, 180°]. + **********************************************************************/ + Math::real EquatorialArc() const { + using std::atan2; + return Init() ? atan2(_ssig1, _csig1) / Math::degree() : Math::NaN(); + } + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value inherited from the GeodesicExact object used in the + * constructor. + **********************************************************************/ + Math::real EquatorialRadius() const + { return Init() ? _a : Math::NaN(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the GeodesicExact object used in the constructor. + **********************************************************************/ + Math::real Flattening() const + { return Init() ? _f : Math::NaN(); } + + /** + * @return \e caps the computational capabilities that this object was + * constructed with. LATITUDE and AZIMUTH are always included. + **********************************************************************/ + unsigned Capabilities() const { return _caps; } + + /** + * Test what capabilities are available. + * + * @param[in] testcaps a set of bitor'ed GeodesicLineExact::mask values. + * @return true if the GeodesicLineExact object has all these capabilities. + **********************************************************************/ + bool Capabilities(unsigned testcaps) const { + testcaps &= OUT_ALL; + return (_caps & testcaps) == testcaps; + } + + /** + * The distance or arc length to point 3. + * + * @param[in] arcmode boolean flag determining the meaning of returned + * value. + * @return \e s13 if \e arcmode is false; \e a13 if \e arcmode is true. + **********************************************************************/ + Math::real GenDistance(bool arcmode) const + { return Init() ? (arcmode ? _a13 : _s13) : Math::NaN(); } + + /** + * @return \e s13, the distance to point 3 (meters). + **********************************************************************/ + Math::real Distance() const { return GenDistance(false); } + + /** + * @return \e a13, the arc length to point 3 (degrees). + **********************************************************************/ + Math::real Arc() const { return GenDistance(true); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_GEODESICLINEEXACT_HPP diff --git a/external/include/GeographicLib/Geohash.hpp b/external/include/GeographicLib/Geohash.hpp new file mode 100644 index 0000000..d7d1d8a --- /dev/null +++ b/external/include/GeographicLib/Geohash.hpp @@ -0,0 +1,180 @@ +/** + * \file Geohash.hpp + * \brief Header for GeographicLib::Geohash class + * + * Copyright (c) Charles Karney (2012-2017) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GEOHASH_HPP) +#define GEOGRAPHICLIB_GEOHASH_HPP 1 + +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs string +# pragma warning (push) +# pragma warning (disable: 4251) +#endif + +namespace GeographicLib { + + /** + * \brief Conversions for geohashes + * + * Geohashes are described in + * - https://en.wikipedia.org/wiki/Geohash + * - http://geohash.org/ + * . + * They provide a compact string representation of a particular geographic + * location (expressed as latitude and longitude), with the property that if + * trailing characters are dropped from the string the geographic location + * remains nearby. The classes Georef and GARS implement similar compact + * representations. + * + * Example of use: + * \include example-Geohash.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT Geohash { + private: + typedef Math::real real; + static const int maxlen_ = 18; + static const unsigned long long mask_ = 1ULL << 45; + static const char* const lcdigits_; + static const char* const ucdigits_; + Geohash(); // Disable constructor + + public: + + /** + * Convert from geographic coordinates to a geohash. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[in] len the length of the resulting geohash. + * @param[out] geohash the geohash. + * @exception GeographicErr if \e lat is not in [−90°, + * 90°]. + * @exception std::bad_alloc if memory for \e geohash can't be allocated. + * + * Internally, \e len is first put in the range [0, 18]. (\e len = 18 + * provides approximately 1μm precision.) + * + * If \e lat or \e lon is NaN, the returned geohash is "invalid". + **********************************************************************/ + static void Forward(real lat, real lon, int len, std::string& geohash); + + /** + * Convert from a geohash to geographic coordinates. + * + * @param[in] geohash the geohash. + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] len the length of the geohash. + * @param[in] centerp if true (the default) return the center of the + * geohash location, otherwise return the south-west corner. + * @exception GeographicErr if \e geohash contains illegal characters. + * + * Only the first 18 characters for \e geohash are considered. (18 + * characters provides approximately 1μm precision.) The case of the + * letters in \e geohash is ignored. + * + * If the first 3 characters of \e geohash are "inv", then \e lat and \e + * lon are set to NaN and \e len is unchanged. ("nan" is treated + * similarly.) + **********************************************************************/ + static void Reverse(const std::string& geohash, real& lat, real& lon, + int& len, bool centerp = true); + + /** + * The latitude resolution of a geohash. + * + * @param[in] len the length of the geohash. + * @return the latitude resolution (degrees). + * + * Internally, \e len is first put in the range [0, 18]. + **********************************************************************/ + static Math::real LatitudeResolution(int len) { + using std::ldexp; + len = (std::max)(0, (std::min)(int(maxlen_), len)); + return ldexp(real(180), -(5 * len / 2)); + } + + /** + * The longitude resolution of a geohash. + * + * @param[in] len the length of the geohash. + * @return the longitude resolution (degrees). + * + * Internally, \e len is first put in the range [0, 18]. + **********************************************************************/ + static Math::real LongitudeResolution(int len) { + using std::ldexp; + len = (std::max)(0, (std::min)(int(maxlen_), len)); + return ldexp(real(360), -(5 * len - 5 * len / 2)); + } + + /** + * The geohash length required to meet a given geographic resolution. + * + * @param[in] res the minimum of resolution in latitude and longitude + * (degrees). + * @return geohash length. + * + * The returned length is in the range [0, 18]. + **********************************************************************/ + static int GeohashLength(real res) { + using std::abs; res = abs(res); + for (int len = 0; len < maxlen_; ++len) + if (LongitudeResolution(len) <= res) + return len; + return maxlen_; + } + + /** + * The geohash length required to meet a given geographic resolution. + * + * @param[in] latres the resolution in latitude (degrees). + * @param[in] lonres the resolution in longitude (degrees). + * @return geohash length. + * + * The returned length is in the range [0, 18]. + **********************************************************************/ + static int GeohashLength(real latres, real lonres) { + using std::abs; + latres = abs(latres); + lonres = abs(lonres); + for (int len = 0; len < maxlen_; ++len) + if (LatitudeResolution(len) <= latres && + LongitudeResolution(len) <= lonres) + return len; + return maxlen_; + } + + /** + * The decimal geographic precision required to match a given geohash + * length. This is the number of digits needed after decimal point in a + * decimal degrees representation. + * + * @param[in] len the length of the geohash. + * @return the decimal precision (may be negative). + * + * Internally, \e len is first put in the range [0, 18]. The returned + * decimal precision is in the range [−2, 12]. + **********************************************************************/ + static int DecimalPrecision(int len) { + using std::floor; using std::log; + return -int(floor(log(LatitudeResolution(len))/log(Math::real(10)))); + } + + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_GEOHASH_HPP diff --git a/external/include/GeographicLib/Geoid.hpp b/external/include/GeographicLib/Geoid.hpp new file mode 100644 index 0000000..1320200 --- /dev/null +++ b/external/include/GeographicLib/Geoid.hpp @@ -0,0 +1,478 @@ +/** + * \file Geoid.hpp + * \brief Header for GeographicLib::Geoid class + * + * Copyright (c) Charles Karney (2009-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GEOID_HPP) +#define GEOGRAPHICLIB_GEOID_HPP 1 + +#include +#include +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs vector and constant conditional expressions +# pragma warning (push) +# pragma warning (disable: 4251 4127) +#endif + +#if !defined(GEOGRAPHICLIB_GEOID_PGM_PIXEL_WIDTH) +/** + * The size of the pixel data in the pgm data files for the geoids. 2 is the + * standard size corresponding to a maxval 216−1. Setting it + * to 4 uses a maxval of 232−1 and changes the extension for + * the data files from .pgm to .pgm4. Note that the format of these pgm4 files + * is a non-standard extension of the pgm format. + **********************************************************************/ +# define GEOGRAPHICLIB_GEOID_PGM_PIXEL_WIDTH 2 +#endif + +namespace GeographicLib { + + /** + * \brief Looking up the height of the geoid above the ellipsoid + * + * This class evaluates the height of one of the standard geoids, EGM84, + * EGM96, or EGM2008 by bilinear or cubic interpolation into a rectangular + * grid of data. These geoid models are documented in + * - EGM84: + * https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm84 + * - EGM96: + * https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm96 + * - EGM2008: + * https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm2008 + * + * The geoids are defined in terms of spherical harmonics. However in order + * to provide a quick and flexible method of evaluating the geoid heights, + * this class evaluates the height by interpolation into a grid of + * precomputed values. + * + * The height of the geoid above the ellipsoid, \e N, is sometimes called the + * geoid undulation. It can be used to convert a height above the ellipsoid, + * \e h, to the corresponding height above the geoid (the orthometric height, + * roughly the height above mean sea level), \e H, using the relations + * + *    \e h = \e N + \e H; + *   \e H = −\e N + \e h. + * + * See \ref geoid for details of how to install the data sets, the data + * format, estimates of the interpolation errors, and how to use caching. + * + * This class is typically \e not thread safe in that a single instantiation + * cannot be safely used by multiple threads because of the way the object + * reads the data set and because it maintains a single-cell cache. If + * multiple threads need to calculate geoid heights they should all construct + * thread-local instantiations. Alternatively, set the optional \e + * threadsafe parameter to true in the constructor. This causes the + * constructor to read all the data into memory and to turn off the + * single-cell caching which results in a Geoid object which \e is thread + * safe. + * + * Example of use: + * \include example-Geoid.cpp + * + * GeoidEval is a command-line utility + * providing access to the functionality of Geoid. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT Geoid { + private: + typedef Math::real real; +#if GEOGRAPHICLIB_GEOID_PGM_PIXEL_WIDTH != 4 + typedef unsigned short pixel_t; + static const unsigned pixel_size_ = 2; + static const unsigned pixel_max_ = 0xffffu; +#else + typedef unsigned pixel_t; + static const unsigned pixel_size_ = 4; + static const unsigned pixel_max_ = 0xffffffffu; +#endif + static const unsigned stencilsize_ = 12; + static const unsigned nterms_ = ((3 + 1) * (3 + 2))/2; // for a cubic fit + static const int c0_; + static const int c0n_; + static const int c0s_; + static const int c3_[stencilsize_ * nterms_]; + static const int c3n_[stencilsize_ * nterms_]; + static const int c3s_[stencilsize_ * nterms_]; + + std::string _name, _dir, _filename; + const bool _cubic; + const real _a, _e2, _degree, _eps; + mutable std::ifstream _file; + real _rlonres, _rlatres; + std::string _description, _datetime; + real _offset, _scale, _maxerror, _rmserror; + int _width, _height; + unsigned long long _datastart, _swidth; + bool _threadsafe; + // Area cache + mutable std::vector< std::vector > _data; + mutable bool _cache; + // NE corner and extent of cache + mutable int _xoffset, _yoffset, _xsize, _ysize; + // Cell cache + mutable int _ix, _iy; + mutable real _v00, _v01, _v10, _v11; + mutable real _t[nterms_]; + void filepos(int ix, int iy) const { + _file.seekg(std::streamoff + (_datastart + + pixel_size_ * (unsigned(iy)*_swidth + unsigned(ix)))); + } + real rawval(int ix, int iy) const { + if (ix < 0) + ix += _width; + else if (ix >= _width) + ix -= _width; + if (_cache && iy >= _yoffset && iy < _yoffset + _ysize && + ((ix >= _xoffset && ix < _xoffset + _xsize) || + (ix + _width >= _xoffset && ix + _width < _xoffset + _xsize))) { + return real(_data[iy - _yoffset] + [ix >= _xoffset ? ix - _xoffset : ix + _width - _xoffset]); + } else { + if (iy < 0 || iy >= _height) { + iy = iy < 0 ? -iy : 2 * (_height - 1) - iy; + ix += (ix < _width/2 ? 1 : -1) * _width/2; + } + try { + filepos(ix, iy); + // initial values to suppress warnings in case get fails + char a = 0, b = 0; + _file.get(a); + _file.get(b); + unsigned r = ((unsigned char)(a) << 8) | (unsigned char)(b); + if (pixel_size_ == 4) { + _file.get(a); + _file.get(b); + r = (r << 16) | ((unsigned char)(a) << 8) | (unsigned char)(b); + } + return real(r); + } + catch (const std::exception& e) { + // throw GeographicErr("Error reading " + _filename + ": " + // + e.what()); + // triggers complaints about the "binary '+'" under Visual Studio. + // So use '+=' instead. + std::string err("Error reading "); + err += _filename; + err += ": "; + err += e.what(); + throw GeographicErr(err); + } + } + } + real height(real lat, real lon) const; + Geoid(const Geoid&) = delete; // copy constructor not allowed + Geoid& operator=(const Geoid&) = delete; // copy assignment not allowed + public: + + /** + * Flags indicating conversions between heights above the geoid and heights + * above the ellipsoid. + **********************************************************************/ + enum convertflag { + /** + * The multiplier for converting from heights above the geoid to heights + * above the ellipsoid. + **********************************************************************/ + ELLIPSOIDTOGEOID = -1, + /** + * No conversion. + **********************************************************************/ + NONE = 0, + /** + * The multiplier for converting from heights above the ellipsoid to + * heights above the geoid. + **********************************************************************/ + GEOIDTOELLIPSOID = 1, + }; + + /** \name Setting up the geoid + **********************************************************************/ + ///@{ + /** + * Construct a geoid. + * + * @param[in] name the name of the geoid. + * @param[in] path (optional) directory for data file. + * @param[in] cubic (optional) interpolation method; false means bilinear, + * true (the default) means cubic. + * @param[in] threadsafe (optional), if true, construct a thread safe + * object. The default is false + * @exception GeographicErr if the data file cannot be found, is + * unreadable, or is corrupt. + * @exception GeographicErr if \e threadsafe is true but the memory + * necessary for caching the data can't be allocated. + * + * The data file is formed by appending ".pgm" to the name. If \e path is + * specified (and is non-empty), then the file is loaded from directory, \e + * path. Otherwise the path is given by DefaultGeoidPath(). If the \e + * threadsafe parameter is true, the data set is read into memory, the data + * file is closed, and single-cell caching is turned off; this results in a + * Geoid object which \e is thread safe. + **********************************************************************/ + explicit Geoid(const std::string& name, const std::string& path = "", + bool cubic = true, bool threadsafe = false); + + /** + * Set up a cache. + * + * @param[in] south latitude (degrees) of the south edge of the cached + * area. + * @param[in] west longitude (degrees) of the west edge of the cached area. + * @param[in] north latitude (degrees) of the north edge of the cached + * area. + * @param[in] east longitude (degrees) of the east edge of the cached area. + * @exception GeographicErr if the memory necessary for caching the data + * can't be allocated (in this case, you will have no cache and can try + * again with a smaller area). + * @exception GeographicErr if there's a problem reading the data. + * @exception GeographicErr if this is called on a threadsafe Geoid. + * + * Cache the data for the specified "rectangular" area bounded by the + * parallels \e south and \e north and the meridians \e west and \e east. + * \e east is always interpreted as being east of \e west, if necessary by + * adding 360° to its value. \e south and \e north should be in + * the range [−90°, 90°]. + **********************************************************************/ + void CacheArea(real south, real west, real north, real east) const; + + /** + * Cache all the data. + * + * @exception GeographicErr if the memory necessary for caching the data + * can't be allocated (in this case, you will have no cache and can try + * again with a smaller area). + * @exception GeographicErr if there's a problem reading the data. + * @exception GeographicErr if this is called on a threadsafe Geoid. + * + * On most computers, this is fast for data sets with grid resolution of 5' + * or coarser. For a 1' grid, the required RAM is 450MB; a 2.5' grid needs + * 72MB; and a 5' grid needs 18MB. + **********************************************************************/ + void CacheAll() const { CacheArea(real(-90), real(0), + real(90), real(360)); } + + /** + * Clear the cache. This never throws an error. (This does nothing with a + * thread safe Geoid.) + **********************************************************************/ + void CacheClear() const; + + ///@} + + /** \name Compute geoid heights + **********************************************************************/ + ///@{ + /** + * Compute the geoid height at a point + * + * @param[in] lat latitude of the point (degrees). + * @param[in] lon longitude of the point (degrees). + * @exception GeographicErr if there's a problem reading the data; this + * never happens if (\e lat, \e lon) is within a successfully cached + * area. + * @return the height of the geoid above the ellipsoid (meters). + * + * The latitude should be in [−90°, 90°]. + **********************************************************************/ + Math::real operator()(real lat, real lon) const { + return height(lat, lon); + } + + /** + * Convert a height above the geoid to a height above the ellipsoid and + * vice versa. + * + * @param[in] lat latitude of the point (degrees). + * @param[in] lon longitude of the point (degrees). + * @param[in] h height of the point (degrees). + * @param[in] d a Geoid::convertflag specifying the direction of the + * conversion; Geoid::GEOIDTOELLIPSOID means convert a height above the + * geoid to a height above the ellipsoid; Geoid::ELLIPSOIDTOGEOID means + * convert a height above the ellipsoid to a height above the geoid. + * @exception GeographicErr if there's a problem reading the data; this + * never happens if (\e lat, \e lon) is within a successfully cached + * area. + * @return converted height (meters). + **********************************************************************/ + Math::real ConvertHeight(real lat, real lon, real h, + convertflag d) const { + return h + real(d) * height(lat, lon); + } + + ///@} + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return geoid description, if available, in the data file; if + * absent, return "NONE". + **********************************************************************/ + const std::string& Description() const { return _description; } + + /** + * @return date of the data file; if absent, return "UNKNOWN". + **********************************************************************/ + const std::string& DateTime() const { return _datetime; } + + /** + * @return full file name used to load the geoid data. + **********************************************************************/ + const std::string& GeoidFile() const { return _filename; } + + /** + * @return "name" used to load the geoid data (from the first argument of + * the constructor). + **********************************************************************/ + const std::string& GeoidName() const { return _name; } + + /** + * @return directory used to load the geoid data. + **********************************************************************/ + const std::string& GeoidDirectory() const { return _dir; } + + /** + * @return interpolation method ("cubic" or "bilinear"). + **********************************************************************/ + const std::string Interpolation() const + { return std::string(_cubic ? "cubic" : "bilinear"); } + + /** + * @return estimate of the maximum interpolation and quantization error + * (meters). + * + * This relies on the value being stored in the data file. If the value is + * absent, return −1. + **********************************************************************/ + Math::real MaxError() const { return _maxerror; } + + /** + * @return estimate of the RMS interpolation and quantization error + * (meters). + * + * This relies on the value being stored in the data file. If the value is + * absent, return −1. + **********************************************************************/ + Math::real RMSError() const { return _rmserror; } + + /** + * @return offset (meters). + * + * This in used in converting from the pixel values in the data file to + * geoid heights. + **********************************************************************/ + Math::real Offset() const { return _offset; } + + /** + * @return scale (meters). + * + * This in used in converting from the pixel values in the data file to + * geoid heights. + **********************************************************************/ + Math::real Scale() const { return _scale; } + + /** + * @return true if the object is constructed to be thread safe. + **********************************************************************/ + bool ThreadSafe() const { return _threadsafe; } + + /** + * @return true if a data cache is active. + **********************************************************************/ + bool Cache() const { return _cache; } + + /** + * @return west edge of the cached area; the cache includes this edge. + **********************************************************************/ + Math::real CacheWest() const { + return _cache ? ((_xoffset + (_xsize == _width ? 0 : _cubic) + + _width/2) % _width - _width/2) / _rlonres : + 0; + } + + /** + * @return east edge of the cached area; the cache excludes this edge. + **********************************************************************/ + Math::real CacheEast() const { + return _cache ? + CacheWest() + + (_xsize - (_xsize == _width ? 0 : 1 + 2 * _cubic)) / _rlonres : + 0; + } + + /** + * @return north edge of the cached area; the cache includes this edge. + **********************************************************************/ + Math::real CacheNorth() const { + return _cache ? 90 - (_yoffset + _cubic) / _rlatres : 0; + } + + /** + * @return south edge of the cached area; the cache excludes this edge + * unless it's the south pole. + **********************************************************************/ + Math::real CacheSouth() const { + return _cache ? 90 - ( _yoffset + _ysize - 1 - _cubic) / _rlatres : 0; + } + + /** + * @return \e a the equatorial radius of the WGS84 ellipsoid (meters). + * + * (The WGS84 value is returned because the supported geoid models are all + * based on this ellipsoid.) + **********************************************************************/ + Math::real EquatorialRadius() const + { return Constants::WGS84_a(); } + + /** + * @return \e f the flattening of the WGS84 ellipsoid. + * + * (The WGS84 value is returned because the supported geoid models are all + * based on this ellipsoid.) + **********************************************************************/ + Math::real Flattening() const { return Constants::WGS84_f(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * @return the default path for geoid data files. + * + * This is the value of the environment variable GEOGRAPHICLIB_GEOID_PATH, + * if set; otherwise, it is $GEOGRAPHICLIB_DATA/geoids if the environment + * variable GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time + * default (/usr/local/share/GeographicLib/geoids on non-Windows systems + * and C:/ProgramData/GeographicLib/geoids on Windows systems). + **********************************************************************/ + static std::string DefaultGeoidPath(); + + /** + * @return the default name for the geoid. + * + * This is the value of the environment variable GEOGRAPHICLIB_GEOID_NAME, + * if set; otherwise, it is "egm96-5". The Geoid class does not use this + * function; it is just provided as a convenience for a calling program + * when constructing a Geoid object. + **********************************************************************/ + static std::string DefaultGeoidName(); + + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_GEOID_HPP diff --git a/external/include/GeographicLib/Georef.hpp b/external/include/GeographicLib/Georef.hpp new file mode 100644 index 0000000..9c3966f --- /dev/null +++ b/external/include/GeographicLib/Georef.hpp @@ -0,0 +1,161 @@ +/** + * \file Georef.hpp + * \brief Header for GeographicLib::Georef class + * + * Copyright (c) Charles Karney (2015-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GEOREF_HPP) +#define GEOGRAPHICLIB_GEOREF_HPP 1 + +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs string +# pragma warning (push) +# pragma warning (disable: 4251) +#endif + +namespace GeographicLib { + + /** + * \brief Conversions for the World Geographic Reference System (georef) + * + * The World Geographic Reference System is described in + * - https://en.wikipedia.org/wiki/Georef + * - https://web.archive.org/web/20161214054445/http://earth-info.nga.mil/GandG/coordsys/grids/georef.pdf + * . + * It provides a compact string representation of a geographic area + * (expressed as latitude and longitude). The classes GARS and Geohash + * implement similar compact representations. + * + * Example of use: + * \include example-Georef.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT Georef { + private: + typedef Math::real real; + static const char* const digits_; + static const char* const lontile_; + static const char* const lattile_; + static const char* const degrees_; + enum { + tile_ = 15, // The size of tile in degrees + lonorig_ = -180, // Origin for longitude + latorig_ = -90, // Origin for latitude + base_ = 10, // Base for minutes + baselen_ = 4, + maxprec_ = 11, // approximately equivalent to MGRS class + maxlen_ = baselen_ + 2 * maxprec_, + }; + Georef(); // Disable constructor + + public: + + /** + * Convert from geographic coordinates to georef. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[in] prec the precision of the resulting georef. + * @param[out] georef the georef string. + * @exception GeographicErr if \e lat is not in [−90°, + * 90°]. + * @exception std::bad_alloc if memory for \e georef can't be allocated. + * + * \e prec specifies the precision of \e georef as follows: + * - \e prec = −1 (min), 15° + * - \e prec = 0, 1° + * - \e prec = 1, converted to \e prec = 2 + * - \e prec = 2, 1' + * - \e prec = 3, 0.1' + * - \e prec = 4, 0.01' + * - \e prec = 5, 0.001' + * - … + * - \e prec = 11 (max), 10−9' + * + * If \e lat or \e lon is NaN, then \e georef is set to "INVALID". + **********************************************************************/ + static void Forward(real lat, real lon, int prec, std::string& georef); + + /** + * Convert from Georef to geographic coordinates. + * + * @param[in] georef the Georef. + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] prec the precision of \e georef. + * @param[in] centerp if true (the default) return the center + * \e georef, otherwise return the south-west corner. + * @exception GeographicErr if \e georef is illegal. + * + * The case of the letters in \e georef is ignored. \e prec is in the + * range [−1, 11] and gives the precision of \e georef as follows: + * - \e prec = −1 (min), 15° + * - \e prec = 0, 1° + * - \e prec = 1, not returned + * - \e prec = 2, 1' + * - \e prec = 3, 0.1' + * - \e prec = 4, 0.01' + * - \e prec = 5, 0.001' + * - … + * - \e prec = 11 (max), 10−9' + * + * If the first 3 characters of \e georef are "INV", then \e lat and \e lon + * are set to NaN and \e prec is unchanged. + **********************************************************************/ + static void Reverse(const std::string& georef, real& lat, real& lon, + int& prec, bool centerp = true); + + /** + * The angular resolution of a Georef. + * + * @param[in] prec the precision of the Georef. + * @return the latitude-longitude resolution (degrees). + * + * Internally, \e prec is first put in the range [−1, 11]. + **********************************************************************/ + static Math::real Resolution(int prec) { + if (prec < 1) + return real(prec < 0 ? 15 : 1); + else { + using std::pow; + // Treat prec = 1 as 2. + prec = (std::max)(2, (std::min)(int(maxprec_), prec)); + // Need extra real because, since C++11, pow(float, int) returns double + return 1/(60 * real(pow(real(base_), prec - 2))); + } + } + + /** + * The Georef precision required to meet a given geographic resolution. + * + * @param[in] res the minimum of resolution in latitude and longitude + * (degrees). + * @return Georef precision. + * + * The returned length is in the range [0, 11]. + **********************************************************************/ + static int Precision(real res) { + using std::abs; res = abs(res); + for (int prec = 0; prec < maxprec_; ++prec) { + if (prec == 1) + continue; + if (Resolution(prec) <= res) + return prec; + } + return maxprec_; + } + + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_GEOREF_HPP diff --git a/external/include/GeographicLib/Gnomonic.hpp b/external/include/GeographicLib/Gnomonic.hpp new file mode 100644 index 0000000..1448fb0 --- /dev/null +++ b/external/include/GeographicLib/Gnomonic.hpp @@ -0,0 +1,221 @@ +/** + * \file Gnomonic.hpp + * \brief Header for GeographicLib::Gnomonic class + * + * Copyright (c) Charles Karney (2010-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GNOMONIC_HPP) +#define GEOGRAPHICLIB_GNOMONIC_HPP 1 + +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief %Gnomonic projection + * + * %Gnomonic projection centered at an arbitrary position \e C on the + * ellipsoid. This projection is derived in Section 8 of + * - C. F. F. Karney, + * + * Algorithms for geodesics, + * J. Geodesy 87, 43--55 (2013); + * DOI: + * 10.1007/s00190-012-0578-z; + * addenda: + * + * geod-addenda.html. + * . + * The projection of \e P is defined as follows: compute the geodesic line + * from \e C to \e P; compute the reduced length \e m12, geodesic scale \e + * M12, and ρ = m12/\e M12; finally \e x = ρ sin \e azi1; \e + * y = ρ cos \e azi1, where \e azi1 is the azimuth of the geodesic at \e + * C. The Gnomonic::Forward and Gnomonic::Reverse methods also return the + * azimuth \e azi of the geodesic at \e P and reciprocal scale \e rk in the + * azimuthal direction. The scale in the radial direction if + * 1/rk2. + * + * For a sphere, ρ is reduces to \e a tan(s12/a), where \e + * s12 is the length of the geodesic from \e C to \e P, and the gnomonic + * projection has the property that all geodesics appear as straight lines. + * For an ellipsoid, this property holds only for geodesics interesting the + * centers. However geodesic segments close to the center are approximately + * straight. + * + * Consider a geodesic segment of length \e l. Let \e T be the point on the + * geodesic (extended if necessary) closest to \e C the center of the + * projection and \e t be the distance \e CT. To lowest order, the maximum + * deviation (as a true distance) of the corresponding gnomonic line segment + * (i.e., with the same end points) from the geodesic is
+ *
+ * (K(T) - K(C)) + * l2 \e t / 32.
+ *
+ * where \e K is the Gaussian curvature. + * + * This result applies for any surface. For an ellipsoid of revolution, + * consider all geodesics whose end points are within a distance \e r of \e + * C. For a given \e r, the deviation is maximum when the latitude of \e C + * is 45°, when endpoints are a distance \e r away, and when their + * azimuths from the center are ± 45° or ± 135°. + * To lowest order in \e r and the flattening \e f, the deviation is \e f + * (r/2a)3 \e r. + * + * The conversions all take place using a Geodesic object (by default + * Geodesic::WGS84()). For more information on geodesics see \ref geodesic. + * + * \warning The definition of this projection for a sphere is + * standard. However, there is no standard for how it should be extended to + * an ellipsoid. The choices are: + * - Declare that the projection is undefined for an ellipsoid. + * - Project to a tangent plane from the center of the ellipsoid. This + * causes great ellipses to appear as straight lines in the projection; + * i.e., it generalizes the spherical great circle to a great ellipse. + * This was proposed by independently by Bowring and Williams in 1997. + * - Project to the conformal sphere with the constant of integration chosen + * so that the values of the latitude match for the center point and + * perform a central projection onto the plane tangent to the conformal + * sphere at the center point. This causes normal sections through the + * center point to appear as straight lines in the projection; i.e., it + * generalizes the spherical great circle to a normal section. This was + * proposed by I. G. Letoval'tsev, Generalization of the gnomonic + * projection for a spheroid and the principal geodetic problems involved + * in the alignment of surface routes, Geodesy and Aerophotography (5), + * 271--274 (1963). + * - The projection given here. This causes geodesics close to the center + * point to appear as straight lines in the projection; i.e., it + * generalizes the spherical great circle to a geodesic. + * + * Example of use: + * \include example-Gnomonic.cpp + * + * GeodesicProj is a command-line utility + * providing access to the functionality of AzimuthalEquidistant, Gnomonic, + * and CassiniSoldner. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT Gnomonic { + private: + typedef Math::real real; + real eps0_, eps_; + Geodesic _earth; + real _a, _f; + // numit_ increased from 10 to 20 to fix convergence failure with high + // precision (e.g., GEOGRAPHICLIB_DIGITS=2000) calculations. Reverse uses + // Newton's method which converges quadratically and so numit_ = 10 would + // normally be big enough. However, since the Geodesic class is based on a + // series it is of limited accuracy; in particular, the derivative rules + // used by Reverse only hold approximately. Consequently, after a few + // iterations, the convergence in the Reverse falls back to improvements in + // each step by a constant (albeit small) factor. + static const int numit_ = 20; + public: + + /** + * Constructor for Gnomonic. + * + * @param[in] earth the Geodesic object to use for geodesic calculations. + * By default this uses the WGS84 ellipsoid. + **********************************************************************/ + explicit Gnomonic(const Geodesic& earth = Geodesic::WGS84()); + + /** + * Forward projection, from geographic to gnomonic. + * + * @param[in] lat0 latitude of center point of projection (degrees). + * @param[in] lon0 longitude of center point of projection (degrees). + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] azi azimuth of geodesic at point (degrees). + * @param[out] rk reciprocal of azimuthal scale at point. + * + * \e lat0 and \e lat should be in the range [−90°, 90°]. + * The scale of the projection is 1/rk2 in the "radial" + * direction, \e azi clockwise from true north, and is 1/\e rk in the + * direction perpendicular to this. If the point lies "over the horizon", + * i.e., if \e rk ≤ 0, then NaNs are returned for \e x and \e y (the + * correct values are returned for \e azi and \e rk). A call to Forward + * followed by a call to Reverse will return the original (\e lat, \e lon) + * (to within roundoff) provided the point in not over the horizon. + **********************************************************************/ + void Forward(real lat0, real lon0, real lat, real lon, + real& x, real& y, real& azi, real& rk) const; + + /** + * Reverse projection, from gnomonic to geographic. + * + * @param[in] lat0 latitude of center point of projection (degrees). + * @param[in] lon0 longitude of center point of projection (degrees). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] azi azimuth of geodesic at point (degrees). + * @param[out] rk reciprocal of azimuthal scale at point. + * + * \e lat0 should be in the range [−90°, 90°]. \e lat will + * be in the range [−90°, 90°] and \e lon will be in the + * range [−180°, 180°]. The scale of the projection is + * 1/rk2 in the "radial" direction, \e azi clockwise from + * true north, and is 1/\e rk in the direction perpendicular to this. Even + * though all inputs should return a valid \e lat and \e lon, it's possible + * that the procedure fails to converge for very large \e x or \e y; in + * this case NaNs are returned for all the output arguments. A call to + * Reverse followed by a call to Forward will return the original (\e x, \e + * y) (to roundoff). + **********************************************************************/ + void Reverse(real lat0, real lon0, real x, real y, + real& lat, real& lon, real& azi, real& rk) const; + + /** + * Gnomonic::Forward without returning the azimuth and scale. + **********************************************************************/ + void Forward(real lat0, real lon0, real lat, real lon, + real& x, real& y) const { + real azi, rk; + Forward(lat0, lon0, lat, lon, x, y, azi, rk); + } + + /** + * Gnomonic::Reverse without returning the azimuth and scale. + **********************************************************************/ + void Reverse(real lat0, real lon0, real x, real y, + real& lat, real& lon) const { + real azi, rk; + Reverse(lat0, lon0, x, y, lat, lon, azi, rk); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value inherited from the Geodesic object used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the Geodesic object used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _earth.Flattening(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_GNOMONIC_HPP diff --git a/external/include/GeographicLib/GravityCircle.hpp b/external/include/GeographicLib/GravityCircle.hpp new file mode 100644 index 0000000..4828907 --- /dev/null +++ b/external/include/GeographicLib/GravityCircle.hpp @@ -0,0 +1,287 @@ +/** + * \file GravityCircle.hpp + * \brief Header for GeographicLib::GravityCircle class + * + * Copyright (c) Charles Karney (2011-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GRAVITYCIRCLE_HPP) +#define GEOGRAPHICLIB_GRAVITYCIRCLE_HPP 1 + +#include +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief Gravity on a circle of latitude + * + * Evaluate the earth's gravity field on a circle of constant height and + * latitude. This uses a CircularEngine to pre-evaluate the inner sum of the + * spherical harmonic sum, allowing the values of the field at several + * different longitudes to be evaluated rapidly. + * + * Use GravityModel::Circle to create a GravityCircle object. (The + * constructor for this class is private.) + * + * See \ref gravityparallel for an example of using GravityCircle (together + * with OpenMP) to speed up the computation of geoid heights. + * + * Example of use: + * \include example-GravityCircle.cpp + * + * Gravity is a command-line utility providing + * access to the functionality of GravityModel and GravityCircle. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT GravityCircle { + private: + typedef Math::real real; + enum mask { + NONE = GravityModel::NONE, + GRAVITY = GravityModel::GRAVITY, + DISTURBANCE = GravityModel::DISTURBANCE, + DISTURBING_POTENTIAL = GravityModel::DISTURBING_POTENTIAL, + GEOID_HEIGHT = GravityModel::GEOID_HEIGHT, + SPHERICAL_ANOMALY = GravityModel::SPHERICAL_ANOMALY, + ALL = GravityModel::ALL, + }; + + unsigned _caps; + real _a, _f, _lat, _h, _Z, _Px, _invR, _cpsi, _spsi, + _cphi, _sphi, _amodel, _GMmodel, _dzonal0, + _corrmult, _gamma0, _gamma, _frot; + CircularEngine _gravitational, _disturbing, _correction; + + GravityCircle(mask caps, real a, real f, real lat, real h, + real Z, real P, real cphi, real sphi, + real amodel, real GMmodel, + real dzonal0, real corrmult, + real gamma0, real gamma, real frot, + const CircularEngine& gravitational, + const CircularEngine& disturbing, + const CircularEngine& correction); + + friend class GravityModel; // GravityModel calls the private constructor + Math::real W(real slam, real clam, + real& gX, real& gY, real& gZ) const; + Math::real V(real slam, real clam, + real& gX, real& gY, real& gZ) const; + Math::real InternalT(real slam, real clam, + real& deltaX, real& deltaY, real& deltaZ, + bool gradp, bool correct) const; + public: + /** + * A default constructor for the normal gravity. This sets up an + * uninitialized object which can be later replaced by the + * GravityModel::Circle. + **********************************************************************/ + GravityCircle() : _a(-1) {} + + /** \name Compute the gravitational field + **********************************************************************/ + ///@{ + /** + * Evaluate the gravity. + * + * @param[in] lon the geographic longitude (degrees). + * @param[out] gx the easterly component of the acceleration + * (m s−2). + * @param[out] gy the northerly component of the acceleration + * (m s−2). + * @param[out] gz the upward component of the acceleration + * (m s−2); this is usually negative. + * @return \e W the sum of the gravitational and centrifugal potentials + * (m2 s−2). + * + * The function includes the effects of the earth's rotation. + **********************************************************************/ + Math::real Gravity(real lon, real& gx, real& gy, real& gz) const; + + /** + * Evaluate the gravity disturbance vector. + * + * @param[in] lon the geographic longitude (degrees). + * @param[out] deltax the easterly component of the disturbance vector + * (m s−2). + * @param[out] deltay the northerly component of the disturbance vector + * (m s−2). + * @param[out] deltaz the upward component of the disturbance vector + * (m s−2). + * @return \e T the corresponding disturbing potential + * (m2 s−2). + **********************************************************************/ + Math::real Disturbance(real lon, real& deltax, real& deltay, real& deltaz) + const; + + /** + * Evaluate the geoid height. + * + * @param[in] lon the geographic longitude (degrees). + * @return \e N the height of the geoid above the reference ellipsoid + * (meters). + * + * Some approximations are made in computing the geoid height so that the + * results of the NGA codes are reproduced accurately. Details are given + * in \ref gravitygeoid. + **********************************************************************/ + Math::real GeoidHeight(real lon) const; + + /** + * Evaluate the components of the gravity anomaly vector using the + * spherical approximation. + * + * @param[in] lon the geographic longitude (degrees). + * @param[out] Dg01 the gravity anomaly (m s−2). + * @param[out] xi the northerly component of the deflection of the vertical + * (degrees). + * @param[out] eta the easterly component of the deflection of the vertical + * (degrees). + * + * The spherical approximation (see Heiskanen and Moritz, Sec 2-14) is used + * so that the results of the NGA codes are reproduced accurately. + * approximations used here. Details are given in \ref gravitygeoid. + **********************************************************************/ + void SphericalAnomaly(real lon, real& Dg01, real& xi, real& eta) + const; + + /** + * Evaluate the components of the acceleration due to gravity and the + * centrifugal acceleration in geocentric coordinates. + * + * @param[in] lon the geographic longitude (degrees). + * @param[out] gX the \e X component of the acceleration + * (m s−2). + * @param[out] gY the \e Y component of the acceleration + * (m s−2). + * @param[out] gZ the \e Z component of the acceleration + * (m s−2). + * @return \e W = \e V + Φ the sum of the gravitational and + * centrifugal potentials (m2 s−2). + **********************************************************************/ + Math::real W(real lon, real& gX, real& gY, real& gZ) const { + real slam, clam; + Math::sincosd(lon, slam, clam); + return W(slam, clam, gX, gY, gZ); + } + + /** + * Evaluate the components of the acceleration due to gravity in geocentric + * coordinates. + * + * @param[in] lon the geographic longitude (degrees). + * @param[out] GX the \e X component of the acceleration + * (m s−2). + * @param[out] GY the \e Y component of the acceleration + * (m s−2). + * @param[out] GZ the \e Z component of the acceleration + * (m s−2). + * @return \e V = \e W - Φ the gravitational potential + * (m2 s−2). + **********************************************************************/ + Math::real V(real lon, real& GX, real& GY, real& GZ) const { + real slam, clam; + Math::sincosd(lon, slam, clam); + return V(slam, clam, GX, GY, GZ); + } + + /** + * Evaluate the components of the gravity disturbance in geocentric + * coordinates. + * + * @param[in] lon the geographic longitude (degrees). + * @param[out] deltaX the \e X component of the gravity disturbance + * (m s−2). + * @param[out] deltaY the \e Y component of the gravity disturbance + * (m s−2). + * @param[out] deltaZ the \e Z component of the gravity disturbance + * (m s−2). + * @return \e T = \e W - \e U the disturbing potential (also called the + * anomalous potential) (m2 s−2). + **********************************************************************/ + Math::real T(real lon, real& deltaX, real& deltaY, real& deltaZ) + const { + real slam, clam; + Math::sincosd(lon, slam, clam); + return InternalT(slam, clam, deltaX, deltaY, deltaZ, true, true); + } + + /** + * Evaluate disturbing potential in geocentric coordinates. + * + * @param[in] lon the geographic longitude (degrees). + * @return \e T = \e W - \e U the disturbing potential (also called the + * anomalous potential) (m2 s−2). + **********************************************************************/ + Math::real T(real lon) const { + real slam, clam, dummy; + Math::sincosd(lon, slam, clam); + return InternalT(slam, clam, dummy, dummy, dummy, false, true); + } + + ///@} + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return true if the object has been initialized. + **********************************************************************/ + bool Init() const { return _a > 0; } + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value inherited from the GravityModel object used in the + * constructor. + **********************************************************************/ + Math::real EquatorialRadius() const + { return Init() ? _a : Math::NaN(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the GravityModel object used in the constructor. + **********************************************************************/ + Math::real Flattening() const + { return Init() ? _f : Math::NaN(); } + + /** + * @return the latitude of the circle (degrees). + **********************************************************************/ + Math::real Latitude() const + { return Init() ? _lat : Math::NaN(); } + + /** + * @return the height of the circle (meters). + **********************************************************************/ + Math::real Height() const + { return Init() ? _h : Math::NaN(); } + + /** + * @return \e caps the computational capabilities that this object was + * constructed with. + **********************************************************************/ + unsigned Capabilities() const { return _caps; } + + /** + * @param[in] testcaps a set of bitor'ed GravityModel::mask values. + * @return true if the GravityCircle object has all these capabilities. + **********************************************************************/ + bool Capabilities(unsigned testcaps) const { + return (_caps & testcaps) == testcaps; + } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_GRAVITYCIRCLE_HPP diff --git a/external/include/GeographicLib/GravityModel.hpp b/external/include/GeographicLib/GravityModel.hpp new file mode 100644 index 0000000..131294c --- /dev/null +++ b/external/include/GeographicLib/GravityModel.hpp @@ -0,0 +1,549 @@ +/** + * \file GravityModel.hpp + * \brief Header for GeographicLib::GravityModel class + * + * Copyright (c) Charles Karney (2011-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_GRAVITYMODEL_HPP) +#define GEOGRAPHICLIB_GRAVITYMODEL_HPP 1 + +#include +#include +#include +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs vector +# pragma warning (push) +# pragma warning (disable: 4251) +#endif + +namespace GeographicLib { + + class GravityCircle; + + /** + * \brief Model of the earth's gravity field + * + * Evaluate the earth's gravity field according to a model. The supported + * models treat only the gravitational field exterior to the mass of the + * earth. When computing the field at points near (but above) the surface of + * the earth a small correction can be applied to account for the mass of the + * atmosphere above the point in question; see \ref gravityatmos. + * Determining the height of the geoid above the ellipsoid entails correcting + * for the mass of the earth above the geoid. The egm96 and egm2008 include + * separate correction terms to account for this mass. + * + * Definitions and terminology (from Heiskanen and Moritz, Sec 2-13): + * - \e V = gravitational potential; + * - Φ = rotational potential; + * - \e W = \e V + Φ = \e T + \e U = total potential; + * - V0 = normal gravitation potential; + * - \e U = V0 + Φ = total normal potential; + * - \e T = \e W − \e U = \e V − V0 = anomalous + * or disturbing potential; + * - g = ∇\e W = γ + δ; + * - f = ∇Φ; + * - Γ = ∇V0; + * - γ = ∇\e U; + * - δ = ∇\e T = gravity disturbance vector + * = gPγP; + * - δ\e g = gravity disturbance = gP − + * γP; + * - Δg = gravity anomaly vector = gP + * − γQ; here the line \e PQ is + * perpendicular to ellipsoid and the potential at \e P equals the normal + * potential at \e Q; + * - Δ\e g = gravity anomaly = gP − + * γQ; + * - (ξ, η) deflection of the vertical, the difference in + * directions of gP and + * γQ, ξ = NS, η = EW. + * - \e X, \e Y, \e Z, geocentric coordinates; + * - \e x, \e y, \e z, local cartesian coordinates used to denote the east, + * north and up directions. + * + * See \ref gravity for details of how to install the gravity models and the + * data format. + * + * References: + * - W. A. Heiskanen and H. Moritz, Physical Geodesy (Freeman, San + * Francisco, 1967). + * + * Example of use: + * \include example-GravityModel.cpp + * + * Gravity is a command-line utility providing + * access to the functionality of GravityModel and GravityCircle. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT GravityModel { + private: + typedef Math::real real; + friend class GravityCircle; + static const int idlength_ = 8; + std::string _name, _dir, _description, _date, _filename, _id; + real _amodel, _GMmodel, _zeta0, _corrmult; + int _nmx, _mmx; + SphericalHarmonic::normalization _norm; + NormalGravity _earth; + std::vector _Cx, _Sx, _CC, _CS, _zonal; + real _dzonal0; // A left over contribution to _zonal. + SphericalHarmonic _gravitational; + SphericalHarmonic1 _disturbing; + SphericalHarmonic _correction; + void ReadMetadata(const std::string& name); + Math::real InternalT(real X, real Y, real Z, + real& deltaX, real& deltaY, real& deltaZ, + bool gradp, bool correct) const; + GravityModel(const GravityModel&) = delete; // copy constructor not allowed + // nor copy assignment + GravityModel& operator=(const GravityModel&) = delete; + + enum captype { + CAP_NONE = 0U, + CAP_G = 1U<<0, // implies potentials W and V + CAP_T = 1U<<1, + CAP_DELTA = 1U<<2 | CAP_T, // delta implies T? + CAP_C = 1U<<3, + CAP_GAMMA0 = 1U<<4, + CAP_GAMMA = 1U<<5, + CAP_ALL = 0x3FU, + }; + + public: + + /** + * Bit masks for the capabilities to be given to the GravityCircle object + * produced by Circle. + **********************************************************************/ + enum mask { + /** + * No capabilities. + * @hideinitializer + **********************************************************************/ + NONE = 0U, + /** + * Allow calls to GravityCircle::Gravity, GravityCircle::W, and + * GravityCircle::V. + * @hideinitializer + **********************************************************************/ + GRAVITY = CAP_G, + /** + * Allow calls to GravityCircle::Disturbance and GravityCircle::T. + * @hideinitializer + **********************************************************************/ + DISTURBANCE = CAP_DELTA, + /** + * Allow calls to GravityCircle::T(real lon) (i.e., computing the + * disturbing potential and not the gravity disturbance vector). + * @hideinitializer + **********************************************************************/ + DISTURBING_POTENTIAL = CAP_T, + /** + * Allow calls to GravityCircle::SphericalAnomaly. + * @hideinitializer + **********************************************************************/ + SPHERICAL_ANOMALY = CAP_DELTA | CAP_GAMMA, + /** + * Allow calls to GravityCircle::GeoidHeight. + * @hideinitializer + **********************************************************************/ + GEOID_HEIGHT = CAP_T | CAP_C | CAP_GAMMA0, + /** + * All capabilities. + * @hideinitializer + **********************************************************************/ + ALL = CAP_ALL, + }; + /** \name Setting up the gravity model + **********************************************************************/ + ///@{ + /** + * Construct a gravity model. + * + * @param[in] name the name of the model. + * @param[in] path (optional) directory for data file. + * @param[in] Nmax (optional) if non-negative, truncate the degree of the + * model this value. + * @param[in] Mmax (optional) if non-negative, truncate the order of the + * model this value. + * @exception GeographicErr if the data file cannot be found, is + * unreadable, or is corrupt, or if \e Mmax > \e Nmax. + * @exception std::bad_alloc if the memory necessary for storing the model + * can't be allocated. + * + * A filename is formed by appending ".egm" (World Gravity Model) to the + * name. If \e path is specified (and is non-empty), then the file is + * loaded from directory, \e path. Otherwise the path is given by + * DefaultGravityPath(). + * + * This file contains the metadata which specifies the properties of the + * model. The coefficients for the spherical harmonic sums are obtained + * from a file obtained by appending ".cof" to metadata file (so the + * filename ends in ".egm.cof"). + * + * If \e Nmax ≥ 0 and \e Mmax < 0, then \e Mmax is set to \e Nmax. + * After the model is loaded, the maximum degree and order of the model can + * be found by the Degree() and Order() methods. + **********************************************************************/ + explicit GravityModel(const std::string& name, + const std::string& path = "", + int Nmax = -1, int Mmax = -1); + ///@} + + /** \name Compute gravity in geodetic coordinates + **********************************************************************/ + ///@{ + /** + * Evaluate the gravity at an arbitrary point above (or below) the + * ellipsoid. + * + * @param[in] lat the geographic latitude (degrees). + * @param[in] lon the geographic longitude (degrees). + * @param[in] h the height above the ellipsoid (meters). + * @param[out] gx the easterly component of the acceleration + * (m s−2). + * @param[out] gy the northerly component of the acceleration + * (m s−2). + * @param[out] gz the upward component of the acceleration + * (m s−2); this is usually negative. + * @return \e W the sum of the gravitational and centrifugal potentials + * (m2 s−2). + * + * The function includes the effects of the earth's rotation. + **********************************************************************/ + Math::real Gravity(real lat, real lon, real h, + real& gx, real& gy, real& gz) const; + + /** + * Evaluate the gravity disturbance vector at an arbitrary point above (or + * below) the ellipsoid. + * + * @param[in] lat the geographic latitude (degrees). + * @param[in] lon the geographic longitude (degrees). + * @param[in] h the height above the ellipsoid (meters). + * @param[out] deltax the easterly component of the disturbance vector + * (m s−2). + * @param[out] deltay the northerly component of the disturbance vector + * (m s−2). + * @param[out] deltaz the upward component of the disturbance vector + * (m s−2). + * @return \e T the corresponding disturbing potential + * (m2 s−2). + **********************************************************************/ + Math::real Disturbance(real lat, real lon, real h, + real& deltax, real& deltay, real& deltaz) + const; + + /** + * Evaluate the geoid height. + * + * @param[in] lat the geographic latitude (degrees). + * @param[in] lon the geographic longitude (degrees). + * @return \e N the height of the geoid above the ReferenceEllipsoid() + * (meters). + * + * This calls NormalGravity::U for ReferenceEllipsoid(). Some + * approximations are made in computing the geoid height so that the + * results of the NGA codes are reproduced accurately. Details are given + * in \ref gravitygeoid. + **********************************************************************/ + Math::real GeoidHeight(real lat, real lon) const; + + /** + * Evaluate the components of the gravity anomaly vector using the + * spherical approximation. + * + * @param[in] lat the geographic latitude (degrees). + * @param[in] lon the geographic longitude (degrees). + * @param[in] h the height above the ellipsoid (meters). + * @param[out] Dg01 the gravity anomaly (m s−2). + * @param[out] xi the northerly component of the deflection of the vertical + * (degrees). + * @param[out] eta the easterly component of the deflection of the vertical + * (degrees). + * + * The spherical approximation (see Heiskanen and Moritz, Sec 2-14) is used + * so that the results of the NGA codes are reproduced accurately. + * approximations used here. Details are given in \ref gravitygeoid. + **********************************************************************/ + void SphericalAnomaly(real lat, real lon, real h, + real& Dg01, real& xi, real& eta) const; + ///@} + + /** \name Compute gravity in geocentric coordinates + **********************************************************************/ + ///@{ + /** + * Evaluate the components of the acceleration due to gravity and the + * centrifugal acceleration in geocentric coordinates. + * + * @param[in] X geocentric coordinate of point (meters). + * @param[in] Y geocentric coordinate of point (meters). + * @param[in] Z geocentric coordinate of point (meters). + * @param[out] gX the \e X component of the acceleration + * (m s−2). + * @param[out] gY the \e Y component of the acceleration + * (m s−2). + * @param[out] gZ the \e Z component of the acceleration + * (m s−2). + * @return \e W = \e V + Φ the sum of the gravitational and + * centrifugal potentials (m2 s−2). + * + * This calls NormalGravity::U for ReferenceEllipsoid(). + **********************************************************************/ + Math::real W(real X, real Y, real Z, + real& gX, real& gY, real& gZ) const; + + /** + * Evaluate the components of the acceleration due to gravity in geocentric + * coordinates. + * + * @param[in] X geocentric coordinate of point (meters). + * @param[in] Y geocentric coordinate of point (meters). + * @param[in] Z geocentric coordinate of point (meters). + * @param[out] GX the \e X component of the acceleration + * (m s−2). + * @param[out] GY the \e Y component of the acceleration + * (m s−2). + * @param[out] GZ the \e Z component of the acceleration + * (m s−2). + * @return \e V = \e W - Φ the gravitational potential + * (m2 s−2). + **********************************************************************/ + Math::real V(real X, real Y, real Z, + real& GX, real& GY, real& GZ) const; + + /** + * Evaluate the components of the gravity disturbance in geocentric + * coordinates. + * + * @param[in] X geocentric coordinate of point (meters). + * @param[in] Y geocentric coordinate of point (meters). + * @param[in] Z geocentric coordinate of point (meters). + * @param[out] deltaX the \e X component of the gravity disturbance + * (m s−2). + * @param[out] deltaY the \e Y component of the gravity disturbance + * (m s−2). + * @param[out] deltaZ the \e Z component of the gravity disturbance + * (m s−2). + * @return \e T = \e W - \e U the disturbing potential (also called the + * anomalous potential) (m2 s−2). + **********************************************************************/ + Math::real T(real X, real Y, real Z, + real& deltaX, real& deltaY, real& deltaZ) const + { return InternalT(X, Y, Z, deltaX, deltaY, deltaZ, true, true); } + + /** + * Evaluate disturbing potential in geocentric coordinates. + * + * @param[in] X geocentric coordinate of point (meters). + * @param[in] Y geocentric coordinate of point (meters). + * @param[in] Z geocentric coordinate of point (meters). + * @return \e T = \e W - \e U the disturbing potential (also called the + * anomalous potential) (m2 s−2). + **********************************************************************/ + Math::real T(real X, real Y, real Z) const { + real dummy; + return InternalT(X, Y, Z, dummy, dummy, dummy, false, true); + } + + /** + * Evaluate the components of the acceleration due to normal gravity and + * the centrifugal acceleration in geocentric coordinates. + * + * @param[in] X geocentric coordinate of point (meters). + * @param[in] Y geocentric coordinate of point (meters). + * @param[in] Z geocentric coordinate of point (meters). + * @param[out] gammaX the \e X component of the normal acceleration + * (m s−2). + * @param[out] gammaY the \e Y component of the normal acceleration + * (m s−2). + * @param[out] gammaZ the \e Z component of the normal acceleration + * (m s−2). + * @return \e U = V0 + Φ the sum of the + * normal gravitational and centrifugal potentials + * (m2 s−2). + * + * This calls NormalGravity::U for ReferenceEllipsoid(). + **********************************************************************/ + Math::real U(real X, real Y, real Z, + real& gammaX, real& gammaY, real& gammaZ) const + { return _earth.U(X, Y, Z, gammaX, gammaY, gammaZ); } + + /** + * Evaluate the centrifugal acceleration in geocentric coordinates. + * + * @param[in] X geocentric coordinate of point (meters). + * @param[in] Y geocentric coordinate of point (meters). + * @param[out] fX the \e X component of the centrifugal acceleration + * (m s−2). + * @param[out] fY the \e Y component of the centrifugal acceleration + * (m s−2). + * @return Φ the centrifugal potential (m2 + * s−2). + * + * This calls NormalGravity::Phi for ReferenceEllipsoid(). + **********************************************************************/ + Math::real Phi(real X, real Y, real& fX, real& fY) const + { return _earth.Phi(X, Y, fX, fY); } + ///@} + + /** \name Compute gravity on a circle of constant latitude + **********************************************************************/ + ///@{ + /** + * Create a GravityCircle object to allow the gravity field at many points + * with constant \e lat and \e h and varying \e lon to be computed + * efficiently. + * + * @param[in] lat latitude of the point (degrees). + * @param[in] h the height of the point above the ellipsoid (meters). + * @param[in] caps bitor'ed combination of GravityModel::mask values + * specifying the capabilities of the resulting GravityCircle object. + * @exception std::bad_alloc if the memory necessary for creating a + * GravityCircle can't be allocated. + * @return a GravityCircle object whose member functions computes the + * gravitational field at a particular values of \e lon. + * + * The GravityModel::mask values are + * - \e caps |= GravityModel::GRAVITY + * - \e caps |= GravityModel::DISTURBANCE + * - \e caps |= GravityModel::DISTURBING_POTENTIAL + * - \e caps |= GravityModel::SPHERICAL_ANOMALY + * - \e caps |= GravityModel::GEOID_HEIGHT + * . + * The default value of \e caps is GravityModel::ALL which turns on all the + * capabilities. If an unsupported function is invoked, it will return + * NaNs. Note that GravityModel::GEOID_HEIGHT will only be honored if \e h + * = 0. + * + * If the field at several points on a circle of latitude need to be + * calculated then creating a GravityCircle object and using its member + * functions will be substantially faster, especially for high-degree + * models. See \ref gravityparallel for an example of using GravityCircle + * (together with OpenMP) to speed up the computation of geoid heights. + **********************************************************************/ + GravityCircle Circle(real lat, real h, unsigned caps = ALL) const; + ///@} + + /** \name Inspector functions + **********************************************************************/ + ///@{ + + /** + * @return the NormalGravity object for the reference ellipsoid. + **********************************************************************/ + const NormalGravity& ReferenceEllipsoid() const { return _earth; } + + /** + * @return the description of the gravity model, if available, in the data + * file; if absent, return "NONE". + **********************************************************************/ + const std::string& Description() const { return _description; } + + /** + * @return date of the model; if absent, return "UNKNOWN". + **********************************************************************/ + const std::string& DateTime() const { return _date; } + + /** + * @return full file name used to load the gravity model. + **********************************************************************/ + const std::string& GravityFile() const { return _filename; } + + /** + * @return "name" used to load the gravity model (from the first argument + * of the constructor, but this may be overridden by the model file). + **********************************************************************/ + const std::string& GravityModelName() const { return _name; } + + /** + * @return directory used to load the gravity model. + **********************************************************************/ + const std::string& GravityModelDirectory() const { return _dir; } + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). + **********************************************************************/ + Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); } + + /** + * @return \e GM the mass constant of the model (m3 + * s−2); this is the product of \e G the gravitational + * constant and \e M the mass of the earth (usually including the mass of + * the earth's atmosphere). + **********************************************************************/ + Math::real MassConstant() const { return _GMmodel; } + + /** + * @return \e GM the mass constant of the ReferenceEllipsoid() + * (m3 s−2). + **********************************************************************/ + Math::real ReferenceMassConstant() const + { return _earth.MassConstant(); } + + /** + * @return ω the angular velocity of the model and the + * ReferenceEllipsoid() (rad s−1). + **********************************************************************/ + Math::real AngularVelocity() const + { return _earth.AngularVelocity(); } + + /** + * @return \e f the flattening of the ellipsoid. + **********************************************************************/ + Math::real Flattening() const { return _earth.Flattening(); } + + /** + * @return \e Nmax the maximum degree of the components of the model. + **********************************************************************/ + int Degree() const { return _nmx; } + + /** + * @return \e Mmax the maximum order of the components of the model. + **********************************************************************/ + int Order() const { return _mmx; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * @return the default path for gravity model data files. + * + * This is the value of the environment variable + * GEOGRAPHICLIB_GRAVITY_PATH, if set; otherwise, it is + * $GEOGRAPHICLIB_DATA/gravity if the environment variable + * GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default + * (/usr/local/share/GeographicLib/gravity on non-Windows systems and + * C:/ProgramData/GeographicLib/gravity on Windows systems). + **********************************************************************/ + static std::string DefaultGravityPath(); + + /** + * @return the default name for the gravity model. + * + * This is the value of the environment variable + * GEOGRAPHICLIB_GRAVITY_NAME, if set; otherwise, it is "egm96". The + * GravityModel class does not use this function; it is just provided as a + * convenience for a calling program when constructing a GravityModel + * object. + **********************************************************************/ + static std::string DefaultGravityName(); + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_GRAVITYMODEL_HPP diff --git a/external/include/GeographicLib/LambertConformalConic.hpp b/external/include/GeographicLib/LambertConformalConic.hpp new file mode 100644 index 0000000..da968e8 --- /dev/null +++ b/external/include/GeographicLib/LambertConformalConic.hpp @@ -0,0 +1,330 @@ +/** + * \file LambertConformalConic.hpp + * \brief Header for GeographicLib::LambertConformalConic class + * + * Copyright (c) Charles Karney (2010-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP) +#define GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP 1 + +#include + +namespace GeographicLib { + + /** + * \brief Lambert conformal conic projection + * + * Implementation taken from the report, + * - J. P. Snyder, + * Map Projections: A + * Working Manual, USGS Professional Paper 1395 (1987), + * pp. 107--109. + * + * This is a implementation of the equations in Snyder except that divided + * differences have been used to transform the expressions into ones which + * may be evaluated accurately and that Newton's method is used to invert the + * projection. In this implementation, the projection correctly becomes the + * Mercator projection or the polar stereographic projection when the + * standard latitude is the equator or a pole. The accuracy of the + * projections is about 10 nm (10 nanometers). + * + * The ellipsoid parameters, the standard parallels, and the scale on the + * standard parallels are set in the constructor. Internally, the case with + * two standard parallels is converted into a single standard parallel, the + * latitude of tangency (also the latitude of minimum scale), with a scale + * specified on this parallel. This latitude is also used as the latitude of + * origin which is returned by LambertConformalConic::OriginLatitude. The + * scale on the latitude of origin is given by + * LambertConformalConic::CentralScale. The case with two distinct standard + * parallels where one is a pole is singular and is disallowed. The central + * meridian (which is a trivial shift of the longitude) is specified as the + * \e lon0 argument of the LambertConformalConic::Forward and + * LambertConformalConic::Reverse functions. + * + * This class also returns the meridian convergence \e gamma and scale \e k. + * The meridian convergence is the bearing of grid north (the \e y axis) + * measured clockwise from true north. + * + * There is no provision in this + * class for specifying a false easting or false northing or a different + * latitude of origin. However these are can be simply included by the + * calling function. For example the Pennsylvania South state coordinate + * system ( + * EPSG:3364) is obtained by: + * \include example-LambertConformalConic.cpp + * + * ConicProj is a command-line utility + * providing access to the functionality of LambertConformalConic and + * AlbersEqualArea. + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT LambertConformalConic { + private: + typedef Math::real real; + real eps_, epsx_, ahypover_; + real _a, _f, _fm, _e2, _es; + real _sign, _n, _nc, _t0nm1, _scale, _lat0, _k0; + real _scbet0, _tchi0, _scchi0, _psi0, _nrho0, _drhomax; + static const int numit_ = 5; + static real hyp(real x) { + using std::hypot; + return hypot(real(1), x); + } + // Divided differences + // Definition: Df(x,y) = (f(x)-f(y))/(x-y) + // See: + // W. M. Kahan and R. J. Fateman, + // Symbolic computation of divided differences, + // SIGSAM Bull. 33(3), 7-28 (1999) + // https://doi.org/10.1145/334714.334716 + // http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf + // + // General rules + // h(x) = f(g(x)): Dh(x,y) = Df(g(x),g(y))*Dg(x,y) + // h(x) = f(x)*g(x): + // Dh(x,y) = Df(x,y)*g(x) + Dg(x,y)*f(y) + // = Df(x,y)*g(y) + Dg(x,y)*f(x) + // = Df(x,y)*(g(x)+g(y))/2 + Dg(x,y)*(f(x)+f(y))/2 + // + // hyp(x) = sqrt(1+x^2): Dhyp(x,y) = (x+y)/(hyp(x)+hyp(y)) + static real Dhyp(real x, real y, real hx, real hy) + // hx = hyp(x) + { return (x + y) / (hx + hy); } + // sn(x) = x/sqrt(1+x^2): Dsn(x,y) = (x+y)/((sn(x)+sn(y))*(1+x^2)*(1+y^2)) + static real Dsn(real x, real y, real sx, real sy) { + // sx = x/hyp(x) + real t = x * y; + return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) : + (x - y != 0 ? (sx - sy) / (x - y) : 1); + } + // Dlog1p(x,y) = log1p((x-y)/(1+y))/(x-y) + static real Dlog1p(real x, real y) { + using std::log1p; + real t = x - y; if (t < 0) { t = -t; y = x; } + return t != 0 ? log1p(t / (1 + y)) / t : 1 / (1 + x); + } + // Dexp(x,y) = exp((x+y)/2) * 2*sinh((x-y)/2)/(x-y) + static real Dexp(real x, real y) { + using std::sinh; using std::exp; + real t = (x - y)/2; + return (t != 0 ? sinh(t)/t : 1) * exp((x + y)/2); + } + // Dsinh(x,y) = 2*sinh((x-y)/2)/(x-y) * cosh((x+y)/2) + // cosh((x+y)/2) = (c+sinh(x)*sinh(y)/c)/2 + // c=sqrt((1+cosh(x))*(1+cosh(y))) + // cosh((x+y)/2) = sqrt( (sinh(x)*sinh(y) + cosh(x)*cosh(y) + 1)/2 ) + static real Dsinh(real x, real y, real sx, real sy, real cx, real cy) + // sx = sinh(x), cx = cosh(x) + { + // real t = (x - y)/2, c = sqrt((1 + cx) * (1 + cy)); + // return (t ? sinh(t)/t : real(1)) * (c + sx * sy / c) /2; + using std::sinh; using std::sqrt; + real t = (x - y)/2; + return (t != 0 ? sinh(t)/t : 1) * sqrt((sx * sy + cx * cy + 1) /2); + } + // Dasinh(x,y) = asinh((x-y)*(x+y)/(x*sqrt(1+y^2)+y*sqrt(1+x^2)))/(x-y) + // = asinh((x*sqrt(1+y^2)-y*sqrt(1+x^2)))/(x-y) + static real Dasinh(real x, real y, real hx, real hy) { + // hx = hyp(x) + using std::asinh; + real t = x - y; + return t != 0 ? + asinh(x*y > 0 ? t * (x + y) / (x*hy + y*hx) : x*hy - y*hx) / t : + 1 / hx; + } + // Deatanhe(x,y) = eatanhe((x-y)/(1-e^2*x*y))/(x-y) + real Deatanhe(real x, real y) const { + real t = x - y, d = 1 - _e2 * x * y; + return t != 0 ? Math::eatanhe(t / d, _es) / t : _e2 / d; + } + void Init(real sphi1, real cphi1, real sphi2, real cphi2, real k1); + public: + + /** + * Constructor with a single standard parallel. + * + * @param[in] a equatorial radius of ellipsoid (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @param[in] stdlat standard parallel (degrees), the circle of tangency. + * @param[in] k0 scale on the standard parallel. + * @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k0 is + * not positive. + * @exception GeographicErr if \e stdlat is not in [−90°, + * 90°]. + **********************************************************************/ + LambertConformalConic(real a, real f, real stdlat, real k0); + + /** + * Constructor with two standard parallels. + * + * @param[in] a equatorial radius of ellipsoid (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @param[in] stdlat1 first standard parallel (degrees). + * @param[in] stdlat2 second standard parallel (degrees). + * @param[in] k1 scale on the standard parallels. + * @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k1 is + * not positive. + * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in + * [−90°, 90°], or if either \e stdlat1 or \e + * stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2. + **********************************************************************/ + LambertConformalConic(real a, real f, real stdlat1, real stdlat2, real k1); + + /** + * Constructor with two standard parallels specified by sines and cosines. + * + * @param[in] a equatorial radius of ellipsoid (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @param[in] sinlat1 sine of first standard parallel. + * @param[in] coslat1 cosine of first standard parallel. + * @param[in] sinlat2 sine of second standard parallel. + * @param[in] coslat2 cosine of second standard parallel. + * @param[in] k1 scale on the standard parallels. + * @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k1 is + * not positive. + * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in + * [−90°, 90°], or if either \e stdlat1 or \e + * stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2. + * + * This allows parallels close to the poles to be specified accurately. + * This routine computes the latitude of origin and the scale at this + * latitude. In the case where \e lat1 and \e lat2 are different, the + * errors in this routines are as follows: if \e dlat = abs(\e lat2 − + * \e lat1) ≤ 160° and max(abs(\e lat1), abs(\e lat2)) ≤ 90 + * − min(0.0002, 2.2 × 10−6(180 − \e + * dlat), 6 × 10−8 dlat2) (in + * degrees), then the error in the latitude of origin is less than 4.5 + * × 10−14d and the relative error in the scale is + * less than 7 × 10−15. + **********************************************************************/ + LambertConformalConic(real a, real f, + real sinlat1, real coslat1, + real sinlat2, real coslat2, + real k1); + + /** + * Set the scale for the projection. + * + * @param[in] lat (degrees). + * @param[in] k scale at latitude \e lat (default 1). + * @exception GeographicErr \e k is not positive. + * @exception GeographicErr if \e lat is not in [−90°, + * 90°]. + **********************************************************************/ + void SetScale(real lat, real k = real(1)); + + /** + * Forward projection, from geographic to Lambert conformal conic. + * + * @param[in] lon0 central meridian longitude (degrees). + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * The latitude origin is given by LambertConformalConic::LatitudeOrigin(). + * No false easting or northing is added and \e lat should be in the range + * [−90°, 90°]. The error in the projection is less than + * about 10 nm (10 nanometers), true distance, and the errors in the + * meridian convergence and scale are consistent with this. The values of + * \e x and \e y returned for points which project to infinity (i.e., one + * or both of the poles) will be large but finite. + **********************************************************************/ + void Forward(real lon0, real lat, real lon, + real& x, real& y, real& gamma, real& k) const; + + /** + * Reverse projection, from Lambert conformal conic to geographic. + * + * @param[in] lon0 central meridian longitude (degrees). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * The latitude origin is given by LambertConformalConic::LatitudeOrigin(). + * No false easting or northing is added. The value of \e lon returned is + * in the range [−180°, 180°]. The error in the projection + * is less than about 10 nm (10 nanometers), true distance, and the errors + * in the meridian convergence and scale are consistent with this. + **********************************************************************/ + void Reverse(real lon0, real x, real y, + real& lat, real& lon, real& gamma, real& k) const; + + /** + * LambertConformalConic::Forward without returning the convergence and + * scale. + **********************************************************************/ + void Forward(real lon0, real lat, real lon, + real& x, real& y) const { + real gamma, k; + Forward(lon0, lat, lon, x, y, gamma, k); + } + + /** + * LambertConformalConic::Reverse without returning the convergence and + * scale. + **********************************************************************/ + void Reverse(real lon0, real x, real y, + real& lat, real& lon) const { + real gamma, k; + Reverse(lon0, x, y, lat, lon, gamma, k); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _a; } + + /** + * @return \e f the flattening of the ellipsoid. This is the + * value used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _f; } + + /** + * @return latitude of the origin for the projection (degrees). + * + * This is the latitude of minimum scale and equals the \e stdlat in the + * 1-parallel constructor and lies between \e stdlat1 and \e stdlat2 in the + * 2-parallel constructors. + **********************************************************************/ + Math::real OriginLatitude() const { return _lat0; } + + /** + * @return central scale for the projection. This is the scale on the + * latitude of origin. + **********************************************************************/ + Math::real CentralScale() const { return _k0; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of LambertConformalConic with the WGS84 + * ellipsoid, \e stdlat = 0, and \e k0 = 1. This degenerates to the + * Mercator projection. + **********************************************************************/ + static const LambertConformalConic& Mercator(); + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP diff --git a/external/include/GeographicLib/LocalCartesian.hpp b/external/include/GeographicLib/LocalCartesian.hpp new file mode 100644 index 0000000..abb4f11 --- /dev/null +++ b/external/include/GeographicLib/LocalCartesian.hpp @@ -0,0 +1,244 @@ +/** + * \file LocalCartesian.hpp + * \brief Header for GeographicLib::LocalCartesian class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_LOCALCARTESIAN_HPP) +#define GEOGRAPHICLIB_LOCALCARTESIAN_HPP 1 + +#include +#include + +namespace GeographicLib { + + /** + * \brief Local cartesian coordinates + * + * Convert between geodetic coordinates latitude = \e lat, longitude = \e + * lon, height = \e h (measured vertically from the surface of the ellipsoid) + * to local cartesian coordinates (\e x, \e y, \e z). The origin of local + * cartesian coordinate system is at \e lat = \e lat0, \e lon = \e lon0, \e h + * = \e h0. The \e z axis is normal to the ellipsoid; the \e y axis points + * due north. The plane \e z = - \e h0 is tangent to the ellipsoid. + * + * The conversions all take place via geocentric coordinates using a + * Geocentric object (by default Geocentric::WGS84()). + * + * Example of use: + * \include example-LocalCartesian.cpp + * + * CartConvert is a command-line utility + * providing access to the functionality of Geocentric and LocalCartesian. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT LocalCartesian { + private: + typedef Math::real real; + static const size_t dim_ = 3; + static const size_t dim2_ = dim_ * dim_; + Geocentric _earth; + real _lat0, _lon0, _h0; + real _x0, _y0, _z0, _r[dim2_]; + void IntForward(real lat, real lon, real h, real& x, real& y, real& z, + real M[dim2_]) const; + void IntReverse(real x, real y, real z, real& lat, real& lon, real& h, + real M[dim2_]) const; + void MatrixMultiply(real M[dim2_]) const; + public: + + /** + * Constructor setting the origin. + * + * @param[in] lat0 latitude at origin (degrees). + * @param[in] lon0 longitude at origin (degrees). + * @param[in] h0 height above ellipsoid at origin (meters); default 0. + * @param[in] earth Geocentric object for the transformation; default + * Geocentric::WGS84(). + * + * \e lat0 should be in the range [−90°, 90°]. + **********************************************************************/ + LocalCartesian(real lat0, real lon0, real h0 = 0, + const Geocentric& earth = Geocentric::WGS84()) + : _earth(earth) + { Reset(lat0, lon0, h0); } + + /** + * Default constructor. + * + * @param[in] earth Geocentric object for the transformation; default + * Geocentric::WGS84(). + * + * Sets \e lat0 = 0, \e lon0 = 0, \e h0 = 0. + **********************************************************************/ + explicit LocalCartesian(const Geocentric& earth = Geocentric::WGS84()) + : _earth(earth) + { Reset(real(0), real(0), real(0)); } + + /** + * Reset the origin. + * + * @param[in] lat0 latitude at origin (degrees). + * @param[in] lon0 longitude at origin (degrees). + * @param[in] h0 height above ellipsoid at origin (meters); default 0. + * + * \e lat0 should be in the range [−90°, 90°]. + **********************************************************************/ + void Reset(real lat0, real lon0, real h0 = 0); + + /** + * Convert from geodetic to local cartesian coordinates. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[in] h height of point above the ellipsoid (meters). + * @param[out] x local cartesian coordinate (meters). + * @param[out] y local cartesian coordinate (meters). + * @param[out] z local cartesian coordinate (meters). + * + * \e lat should be in the range [−90°, 90°]. + **********************************************************************/ + void Forward(real lat, real lon, real h, real& x, real& y, real& z) + const { + IntForward(lat, lon, h, x, y, z, NULL); + } + + /** + * Convert from geodetic to local cartesian coordinates and return rotation + * matrix. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[in] h height of point above the ellipsoid (meters). + * @param[out] x local cartesian coordinate (meters). + * @param[out] y local cartesian coordinate (meters). + * @param[out] z local cartesian coordinate (meters). + * @param[out] M if the length of the vector is 9, fill with the rotation + * matrix in row-major order. + * + * \e lat should be in the range [−90°, 90°]. + * + * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can + * express \e v as \e column vectors in one of two ways + * - in east, north, up coordinates (where the components are relative to a + * local coordinate system at (\e lat, \e lon, \e h)); call this + * representation \e v1. + * - in \e x, \e y, \e z coordinates (where the components are relative to + * the local coordinate system at (\e lat0, \e lon0, \e h0)); call this + * representation \e v0. + * . + * Then we have \e v0 = \e M ⋅ \e v1. + **********************************************************************/ + void Forward(real lat, real lon, real h, real& x, real& y, real& z, + std::vector& M) + const { + if (M.end() == M.begin() + dim2_) { + real t[dim2_]; + IntForward(lat, lon, h, x, y, z, t); + std::copy(t, t + dim2_, M.begin()); + } else + IntForward(lat, lon, h, x, y, z, NULL); + } + + /** + * Convert from local cartesian to geodetic coordinates. + * + * @param[in] x local cartesian coordinate (meters). + * @param[in] y local cartesian coordinate (meters). + * @param[in] z local cartesian coordinate (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] h height of point above the ellipsoid (meters). + * + * In general, there are multiple solutions and the result which minimizes + * |h |is returned, i.e., (lat, lon) corresponds to + * the closest point on the ellipsoid. The value of \e lon returned is in + * the range [−180°, 180°]. + **********************************************************************/ + void Reverse(real x, real y, real z, real& lat, real& lon, real& h) + const { + IntReverse(x, y, z, lat, lon, h, NULL); + } + + /** + * Convert from local cartesian to geodetic coordinates and return rotation + * matrix. + * + * @param[in] x local cartesian coordinate (meters). + * @param[in] y local cartesian coordinate (meters). + * @param[in] z local cartesian coordinate (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] h height of point above the ellipsoid (meters). + * @param[out] M if the length of the vector is 9, fill with the rotation + * matrix in row-major order. + * + * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can + * express \e v as \e column vectors in one of two ways + * - in east, north, up coordinates (where the components are relative to a + * local coordinate system at (\e lat, \e lon, \e h)); call this + * representation \e v1. + * - in \e x, \e y, \e z coordinates (where the components are relative to + * the local coordinate system at (\e lat0, \e lon0, \e h0)); call this + * representation \e v0. + * . + * Then we have \e v1 = MT ⋅ \e v0, where + * MT is the transpose of \e M. + **********************************************************************/ + void Reverse(real x, real y, real z, real& lat, real& lon, real& h, + std::vector& M) + const { + if (M.end() == M.begin() + dim2_) { + real t[dim2_]; + IntReverse(x, y, z, lat, lon, h, t); + std::copy(t, t + dim2_, M.begin()); + } else + IntReverse(x, y, z, lat, lon, h, NULL); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return latitude of the origin (degrees). + **********************************************************************/ + Math::real LatitudeOrigin() const { return _lat0; } + + /** + * @return longitude of the origin (degrees). + **********************************************************************/ + Math::real LongitudeOrigin() const { return _lon0; } + + /** + * @return height of the origin (meters). + **********************************************************************/ + Math::real HeightOrigin() const { return _h0; } + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value of \e a inherited from the Geocentric object used in the + * constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the Geocentric object used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _earth.Flattening(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_LOCALCARTESIAN_HPP diff --git a/external/include/GeographicLib/MGRS.hpp b/external/include/GeographicLib/MGRS.hpp new file mode 100644 index 0000000..b2cef75 --- /dev/null +++ b/external/include/GeographicLib/MGRS.hpp @@ -0,0 +1,361 @@ +/** + * \file MGRS.hpp + * \brief Header for GeographicLib::MGRS class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_MGRS_HPP) +#define GEOGRAPHICLIB_MGRS_HPP 1 + +#include +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs string +# pragma warning (push) +# pragma warning (disable: 4251) +#endif + +namespace GeographicLib { + + /** + * \brief Convert between UTM/UPS and %MGRS + * + * MGRS is defined in Chapter 3 of + * - J. W. Hager, L. L. Fry, S. S. Jacks, D. R. Hill, + * + * Datums, Ellipsoids, Grids, and Grid Reference Systems, + * Defense Mapping Agency, Technical Manual TM8358.1 (1990). + * . + * This document has been updated by the two NGA documents + * - + * Universal Grids and Grid Reference Systems, + * NGA.STND.0037 (2014). + * - + * The Universal Grids and the Transverse Mercator and Polar Stereographic + * Map Projections, NGA.SIG.0012 (2014). + * + * This implementation has the following properties: + * - The conversions are closed, i.e., output from Forward is legal input for + * Reverse and vice versa. Conversion in both directions preserve the + * UTM/UPS selection and the UTM zone. + * - Forward followed by Reverse and vice versa is approximately the + * identity. (This is affected in predictable ways by errors in + * determining the latitude band and by loss of precision in the MGRS + * coordinates.) + * - The trailing digits produced by Forward are consistent as the precision + * is varied. Specifically, the digits are obtained by operating on the + * easting with ⌊106 x⌋ and extracting the + * required digits from the resulting number (and similarly for the + * northing). + * - All MGRS coordinates truncate to legal 100 km blocks. All MGRS + * coordinates with a legal 100 km block prefix are legal (even though the + * latitude band letter may now belong to a neighboring band). + * - The range of UTM/UPS coordinates allowed for conversion to MGRS + * coordinates is the maximum consistent with staying within the letter + * ranges of the MGRS scheme. + * - All the transformations are implemented as static methods in the MGRS + * class. + * + * The NGA software package + * geotrans + * also provides conversions to and from MGRS. Version 3.0 (and earlier) + * suffers from some drawbacks: + * - Inconsistent rules are used to determine the whether a particular MGRS + * coordinate is legal. A more systematic approach is taken here. + * - The underlying projections are not very accurately implemented. + * + * Example of use: + * \include example-MGRS.cpp + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT MGRS { + private: + typedef Math::real real; + static const char* const hemispheres_; + static const char* const utmcols_[3]; + static const char* const utmrow_; + static const char* const upscols_[4]; + static const char* const upsrows_[2]; + static const char* const latband_; + static const char* const upsband_; + static const char* const digits_; + + static const int mineasting_[4]; + static const int maxeasting_[4]; + static const int minnorthing_[4]; + static const int maxnorthing_[4]; + enum { + base_ = 10, + // Top-level tiles are 10^5 m = 100 km on a side + tilelevel_ = 5, + // Period of UTM row letters + utmrowperiod_ = 20, + // Row letters are shifted by 5 for even zones + utmevenrowshift_ = 5, + // Maximum precision is um + maxprec_ = 5 + 6, + // For generating digits at maxprec + mult_ = 1000000, + }; + static void CheckCoords(bool utmp, bool& northp, real& x, real& y); + static int UTMRow(int iband, int icol, int irow); + + friend class UTMUPS; // UTMUPS::StandardZone calls LatitudeBand + // Return latitude band number [-10, 10) for the given latitude (degrees). + // The bands are reckoned in include their southern edges. + static int LatitudeBand(real lat) { + using std::floor; + int ilat = int(floor(lat)); + return (std::max)(-10, (std::min)(9, (ilat + 80)/8 - 10)); + } + // Return approximate latitude band number [-10, 10) for the given northing + // (meters). With this rule, each 100km tile would have a unique band + // letter corresponding to the latitude at the center of the tile. This + // function isn't currently used. + static int ApproxLatitudeBand(real y) { + // northing at tile center in units of tile = 100km + using std::floor; using std::abs; + real ya = floor( (std::min)(real(88), abs(y/tile_)) ) + + real(0.5); + // convert to lat (mult by 90/100) and then to band (divide by 8) + // the +1 fine tunes the boundary between bands 3 and 4 + int b = int(floor( ((ya * 9 + 1) / 10) / 8 )); + // For the northern hemisphere we have + // band rows num + // N 0 0:8 9 + // P 1 9:17 9 + // Q 2 18:26 9 + // R 3 27:34 8 + // S 4 35:43 9 + // T 5 44:52 9 + // U 6 53:61 9 + // V 7 62:70 9 + // W 8 71:79 9 + // X 9 80:94 15 + return y >= 0 ? b : -(b + 1); + } + // UTMUPS access these enums + enum { + tile_ = 100000, // Size MGRS blocks + minutmcol_ = 1, + maxutmcol_ = 9, + minutmSrow_ = 10, + maxutmSrow_ = 100, // Also used for UTM S false northing + minutmNrow_ = 0, // Also used for UTM N false northing + maxutmNrow_ = 95, + minupsSind_ = 8, // These 4 ind's apply to easting and northing + maxupsSind_ = 32, + minupsNind_ = 13, + maxupsNind_ = 27, + upseasting_ = 20, // Also used for UPS false northing + utmeasting_ = 5, // UTM false easting + // Difference between S hemisphere northing and N hemisphere northing + utmNshift_ = (maxutmSrow_ - minutmNrow_) * tile_ + }; + MGRS(); // Disable constructor + + public: + + /** + * Convert UTM or UPS coordinate to an MGRS coordinate. + * + * @param[in] zone UTM zone (zero means UPS). + * @param[in] northp hemisphere (true means north, false means south). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[in] prec precision relative to 100 km. + * @param[out] mgrs MGRS string. + * @exception GeographicErr if \e zone, \e x, or \e y is outside its + * allowed range. + * @exception GeographicErr if the memory for the MGRS string can't be + * allocated. + * + * \e prec specifies the precision of the MGRS string as follows: + * - \e prec = −1 (min), only the grid zone is returned + * - \e prec = 0, 100 km + * - \e prec = 1, 10 km + * - \e prec = 2, 1 km + * - \e prec = 3, 100 m + * - \e prec = 4, 10 m + * - \e prec = 5, 1 m + * - \e prec = 6, 0.1 m + * - … + * - \e prec = 11 (max), 1 μm + * + * UTM eastings are allowed to be in the range [100 km, 900 km], northings + * are allowed to be in in [0 km, 9500 km] for the northern hemisphere and + * in [1000 km, 10000 km] for the southern hemisphere. (However UTM + * northings can be continued across the equator. So the actual limits on + * the northings are [−9000 km, 9500 km] for the "northern" + * hemisphere and [1000 km, 19500 km] for the "southern" hemisphere.) + * + * UPS eastings/northings are allowed to be in the range [1300 km, 2700 km] + * in the northern hemisphere and in [800 km, 3200 km] in the southern + * hemisphere. + * + * The ranges are 100 km more restrictive than for the conversion between + * geographic coordinates and UTM and UPS given by UTMUPS. These + * restrictions are dictated by the allowed letters in MGRS coordinates. + * The choice of 9500 km for the maximum northing for northern hemisphere + * and of 1000 km as the minimum northing for southern hemisphere provide + * at least 0.5 degree extension into standard UPS zones. The upper ends + * of the ranges for the UPS coordinates is dictated by requiring symmetry + * about the meridians 0E and 90E. + * + * All allowed UTM and UPS coordinates may now be converted to legal MGRS + * coordinates with the proviso that eastings and northings on the upper + * boundaries are silently reduced by about 4 nm (4 nanometers) to place + * them \e within the allowed range. (This includes reducing a southern + * hemisphere northing of 10000 km by 4 nm so that it is placed in latitude + * band M.) The UTM or UPS coordinates are truncated to requested + * precision to determine the MGRS coordinate. Thus in UTM zone 38n, the + * square area with easting in [444 km, 445 km) and northing in [3688 km, + * 3689 km) maps to MGRS coordinate 38SMB4488 (at \e prec = 2, 1 km), + * Khulani Sq., Baghdad. + * + * The UTM/UPS selection and the UTM zone is preserved in the conversion to + * MGRS coordinate. Thus for \e zone > 0, the MGRS coordinate begins with + * the zone number followed by one of [C--M] for the southern + * hemisphere and [N--X] for the northern hemisphere. For \e zone = + * 0, the MGRS coordinates begins with one of [AB] for the southern + * hemisphere and [XY] for the northern hemisphere. + * + * The conversion to the MGRS is exact for prec in [0, 5] except that a + * neighboring latitude band letter may be given if the point is within 5nm + * of a band boundary. For prec in [6, 11], the conversion is accurate to + * roundoff. + * + * If \e prec = −1, then the "grid zone designation", e.g., 18T, is + * returned. This consists of the UTM zone number (absent for UPS) and the + * first letter of the MGRS string which labels the latitude band for UTM + * and the hemisphere for UPS. + * + * If \e x or \e y is NaN or if \e zone is UTMUPS::INVALID, the returned + * MGRS string is "INVALID". + * + * Return the result via a reference argument to avoid the overhead of + * allocating a potentially large number of small strings. If an error is + * thrown, then \e mgrs is unchanged. + **********************************************************************/ + static void Forward(int zone, bool northp, real x, real y, + int prec, std::string& mgrs); + + /** + * Convert UTM or UPS coordinate to an MGRS coordinate when the latitude is + * known. + * + * @param[in] zone UTM zone (zero means UPS). + * @param[in] northp hemisphere (true means north, false means south). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[in] lat latitude (degrees). + * @param[in] prec precision relative to 100 km. + * @param[out] mgrs MGRS string. + * @exception GeographicErr if \e zone, \e x, or \e y is outside its + * allowed range. + * @exception GeographicErr if \e lat is inconsistent with the given UTM + * coordinates. + * @exception std::bad_alloc if the memory for \e mgrs can't be allocated. + * + * The latitude is ignored for \e zone = 0 (UPS); otherwise the latitude is + * used to determine the latitude band and this is checked for consistency + * using the same tests as Reverse. + **********************************************************************/ + static void Forward(int zone, bool northp, real x, real y, real lat, + int prec, std::string& mgrs); + + /** + * Convert a MGRS coordinate to UTM or UPS coordinates. + * + * @param[in] mgrs MGRS string. + * @param[out] zone UTM zone (zero means UPS). + * @param[out] northp hemisphere (true means north, false means south). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] prec precision relative to 100 km. + * @param[in] centerp if true (default), return center of the MGRS square, + * else return SW (lower left) corner. + * @exception GeographicErr if \e mgrs is illegal. + * + * All conversions from MGRS to UTM/UPS are permitted provided the MGRS + * coordinate is a possible result of a conversion in the other direction. + * (The leading 0 may be dropped from an input MGRS coordinate for UTM + * zones 1--9.) In addition, MGRS coordinates with a neighboring + * latitude band letter are permitted provided that some portion of the + * 100 km block is within the given latitude band. Thus + * - 38VLS and 38WLS are allowed (latitude 64N intersects the square + * 38[VW]LS); but 38VMS is not permitted (all of 38WMS is north of 64N) + * - 38MPE and 38NPF are permitted (they straddle the equator); but 38NPE + * and 38MPF are not permitted (the equator does not intersect either + * block). + * - Similarly ZAB and YZB are permitted (they straddle the prime + * meridian); but YAB and ZZB are not (the prime meridian does not + * intersect either block). + * + * The UTM/UPS selection and the UTM zone is preserved in the conversion + * from MGRS coordinate. The conversion is exact for prec in [0, 5]. With + * \e centerp = true, the conversion from MGRS to geographic and back is + * stable. This is not assured if \e centerp = false. + * + * If a "grid zone designation" (for example, 18T or A) is given, then some + * suitable (but essentially arbitrary) point within that grid zone is + * returned. The main utility of the conversion is to allow \e zone and \e + * northp to be determined. In this case, the \e centerp parameter is + * ignored and \e prec is set to −1. + * + * If the first 3 characters of \e mgrs are "INV", then \e x and \e y are + * set to NaN, \e zone is set to UTMUPS::INVALID, and \e prec is set to + * −2. + * + * If an exception is thrown, then the arguments are unchanged. + **********************************************************************/ + static void Reverse(const std::string& mgrs, + int& zone, bool& northp, real& x, real& y, + int& prec, bool centerp = true); + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the WGS84 ellipsoid (meters). + * + * (The WGS84 value is returned because the UTM and UPS projections are + * based on this ellipsoid.) + **********************************************************************/ + static Math::real EquatorialRadius() { return UTMUPS::EquatorialRadius(); } + + /** + * @return \e f the flattening of the WGS84 ellipsoid. + * + * (The WGS84 value is returned because the UTM and UPS projections are + * based on this ellipsoid.) + **********************************************************************/ + static Math::real Flattening() { return UTMUPS::Flattening(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + static Math::real MajorRadius() { return EquatorialRadius(); } + ///@} + + /** + * Perform some checks on the UTMUPS coordinates on this ellipsoid. Throw + * an error if any of the assumptions made in the MGRS class is not true. + * This check needs to be carried out if the ellipsoid parameters (or the + * UTM/UPS scales) are ever changed. + **********************************************************************/ + static void Check(); + + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_MGRS_HPP diff --git a/external/include/GeographicLib/MagneticCircle.hpp b/external/include/GeographicLib/MagneticCircle.hpp new file mode 100644 index 0000000..515ddaf --- /dev/null +++ b/external/include/GeographicLib/MagneticCircle.hpp @@ -0,0 +1,204 @@ +/** + * \file MagneticCircle.hpp + * \brief Header for GeographicLib::MagneticCircle class + * + * Copyright (c) Charles Karney (2011-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_MAGNETICCIRCLE_HPP) +#define GEOGRAPHICLIB_MAGNETICCIRCLE_HPP 1 + +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief Geomagnetic field on a circle of latitude + * + * Evaluate the earth's magnetic field on a circle of constant height and + * latitude. This uses a CircularEngine to pre-evaluate the inner sum of the + * spherical harmonic sum, allowing the values of the field at several + * different longitudes to be evaluated rapidly. + * + * Use MagneticModel::Circle to create a MagneticCircle object. (The + * constructor for this class is private.) + * + * Example of use: + * \include example-MagneticCircle.cpp + * + * MagneticField is a command-line utility + * providing access to the functionality of MagneticModel and MagneticCircle. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT MagneticCircle { + private: + typedef Math::real real; + + real _a, _f, _lat, _h, _t, _cphi, _sphi, _t1, _dt0; + bool _interpolate, _constterm; + CircularEngine _circ0, _circ1, _circ2; + + MagneticCircle(real a, real f, real lat, real h, real t, + real cphi, real sphi, real t1, real dt0, + bool interpolate, + const CircularEngine& circ0, const CircularEngine& circ1) + : _a(a) + , _f(f) + , _lat(Math::LatFix(lat)) + , _h(h) + , _t(t) + , _cphi(cphi) + , _sphi(sphi) + , _t1(t1) + , _dt0(dt0) + , _interpolate(interpolate) + , _constterm(false) + , _circ0(circ0) + , _circ1(circ1) + {} + + MagneticCircle(real a, real f, real lat, real h, real t, + real cphi, real sphi, real t1, real dt0, + bool interpolate, + const CircularEngine& circ0, const CircularEngine& circ1, + const CircularEngine& circ2) + : _a(a) + , _f(f) + , _lat(lat) + , _h(h) + , _t(t) + , _cphi(cphi) + , _sphi(sphi) + , _t1(t1) + , _dt0(dt0) + , _interpolate(interpolate) + , _constterm(true) + , _circ0(circ0) + , _circ1(circ1) + , _circ2(circ2) + {} + + void Field(real lon, bool diffp, + real& Bx, real& By, real& Bz, + real& Bxt, real& Byt, real& Bzt) const; + + void FieldGeocentric(real slam, real clam, + real& BX, real& BY, real& BZ, + real& BXt, real& BYt, real& BZt) const; + + friend class MagneticModel; // MagneticModel calls the private constructor + + public: + + /** + * A default constructor for the normal gravity. This sets up an + * uninitialized object which can be later replaced by the + * MagneticModel::Circle. + **********************************************************************/ + MagneticCircle() : _a(-1) {} + + /** \name Compute the magnetic field + **********************************************************************/ + ///@{ + /** + * Evaluate the components of the geomagnetic field at a particular + * longitude. + * + * @param[in] lon longitude of the point (degrees). + * @param[out] Bx the easterly component of the magnetic field (nanotesla). + * @param[out] By the northerly component of the magnetic field + * (nanotesla). + * @param[out] Bz the vertical (up) component of the magnetic field + * (nanotesla). + **********************************************************************/ + void operator()(real lon, real& Bx, real& By, real& Bz) const { + real dummy; + Field(lon, false, Bx, By, Bz, dummy, dummy, dummy); + } + + /** + * Evaluate the components of the geomagnetic field and their time + * derivatives at a particular longitude. + * + * @param[in] lon longitude of the point (degrees). + * @param[out] Bx the easterly component of the magnetic field (nanotesla). + * @param[out] By the northerly component of the magnetic field + * (nanotesla). + * @param[out] Bz the vertical (up) component of the magnetic field + * (nanotesla). + * @param[out] Bxt the rate of change of \e Bx (nT/yr). + * @param[out] Byt the rate of change of \e By (nT/yr). + * @param[out] Bzt the rate of change of \e Bz (nT/yr). + **********************************************************************/ + void operator()(real lon, real& Bx, real& By, real& Bz, + real& Bxt, real& Byt, real& Bzt) const { + Field(lon, true, Bx, By, Bz, Bxt, Byt, Bzt); + } + + /** + * Evaluate the components of the geomagnetic field and their time + * derivatives at a particular longitude. + * + * @param[in] lon longitude of the point (degrees). + * @param[out] BX the \e X component of the magnetic field (nT). + * @param[out] BY the \e Y component of the magnetic field (nT). + * @param[out] BZ the \e Z component of the magnetic field (nT). + * @param[out] BXt the rate of change of \e BX (nT/yr). + * @param[out] BYt the rate of change of \e BY (nT/yr). + * @param[out] BZt the rate of change of \e BZ (nT/yr). + **********************************************************************/ + void FieldGeocentric(real lon, real& BX, real& BY, real& BZ, + real& BXt, real& BYt, real& BZt) const; + ///@} + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return true if the object has been initialized. + **********************************************************************/ + bool Init() const { return _a > 0; } + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value inherited from the MagneticModel object used in the + * constructor. + **********************************************************************/ + Math::real EquatorialRadius() const + { return Init() ? _a : Math::NaN(); } + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the MagneticModel object used in the constructor. + **********************************************************************/ + Math::real Flattening() const + { return Init() ? _f : Math::NaN(); } + /** + * @return the latitude of the circle (degrees). + **********************************************************************/ + Math::real Latitude() const + { return Init() ? _lat : Math::NaN(); } + /** + * @return the height of the circle (meters). + **********************************************************************/ + Math::real Height() const + { return Init() ? _h : Math::NaN(); } + /** + * @return the time (fractional years). + **********************************************************************/ + Math::real Time() const + { return Init() ? _t : Math::NaN(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_MAGNETICCIRCLE_HPP diff --git a/external/include/GeographicLib/MagneticModel.hpp b/external/include/GeographicLib/MagneticModel.hpp new file mode 100644 index 0000000..2d8239a --- /dev/null +++ b/external/include/GeographicLib/MagneticModel.hpp @@ -0,0 +1,406 @@ +/** + * \file MagneticModel.hpp + * \brief Header for GeographicLib::MagneticModel class + * + * Copyright (c) Charles Karney (2011-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_MAGNETICMODEL_HPP) +#define GEOGRAPHICLIB_MAGNETICMODEL_HPP 1 + +#include +#include +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs vector +# pragma warning (push) +# pragma warning (disable: 4251) +#endif + +namespace GeographicLib { + + class MagneticCircle; + + /** + * \brief Model of the earth's magnetic field + * + * Evaluate the earth's magnetic field according to a model. At present only + * internal magnetic fields are handled. These are due to the earth's code + * and crust; these vary slowly (over many years). Excluded are the effects + * of currents in the ionosphere and magnetosphere which have daily and + * annual variations. + * + * See \ref magnetic for details of how to install the magnetic models and + * the data format. + * + * See + * - General information: + * - http://geomag.org/models/index.html + * - WMM2010: + * - https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml + * - https://ngdc.noaa.gov/geomag/WMM/data/WMM2010/WMM2010COF.zip + * - WMM2015 (deprecated): + * - https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml + * - https://ngdc.noaa.gov/geomag/WMM/data/WMM2015/WMM2015COF.zip + * - WMM2015V2: + * - https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml + * - https://ngdc.noaa.gov/geomag/WMM/data/WMM2015/WMM2015v2COF.zip + * - WMM2020: + * - https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml + * - https://ngdc.noaa.gov/geomag/WMM/data/WMM2020/WMM2020COF.zip + * - IGRF11: + * - https://ngdc.noaa.gov/IAGA/vmod/igrf.html + * - https://ngdc.noaa.gov/IAGA/vmod/igrf11coeffs.txt + * - https://ngdc.noaa.gov/IAGA/vmod/geomag70_linux.tar.gz + * - EMM2010: + * - https://ngdc.noaa.gov/geomag/EMM/index.html + * - https://ngdc.noaa.gov/geomag/EMM/data/geomag/EMM2010_Sph_Windows_Linux.zip + * - EMM2015: + * - https://ngdc.noaa.gov/geomag/EMM/index.html + * - https://www.ngdc.noaa.gov/geomag/EMM/data/geomag/EMM2015_Sph_Linux.zip + * - EMM2017: + * - https://ngdc.noaa.gov/geomag/EMM/index.html + * - https://www.ngdc.noaa.gov/geomag/EMM/data/geomag/EMM2017_Sph_Linux.zip + * + * Example of use: + * \include example-MagneticModel.cpp + * + * MagneticField is a command-line utility + * providing access to the functionality of MagneticModel and MagneticCircle. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT MagneticModel { + private: + typedef Math::real real; + static const int idlength_ = 8; + std::string _name, _dir, _description, _date, _filename, _id; + real _t0, _dt0, _tmin, _tmax, _a, _hmin, _hmax; + int _Nmodels, _Nconstants, _nmx, _mmx; + SphericalHarmonic::normalization _norm; + Geocentric _earth; + std::vector< std::vector > _G; + std::vector< std::vector > _H; + std::vector _harm; + void Field(real t, real lat, real lon, real h, bool diffp, + real& Bx, real& By, real& Bz, + real& Bxt, real& Byt, real& Bzt) const; + void ReadMetadata(const std::string& name); + // copy constructor not allowed + MagneticModel(const MagneticModel&) = delete; + // nor copy assignment + MagneticModel& operator=(const MagneticModel&) = delete; + public: + + /** \name Setting up the magnetic model + **********************************************************************/ + ///@{ + /** + * Construct a magnetic model. + * + * @param[in] name the name of the model. + * @param[in] path (optional) directory for data file. + * @param[in] earth (optional) Geocentric object for converting + * coordinates; default Geocentric::WGS84(). + * @param[in] Nmax (optional) if non-negative, truncate the degree of the + * model this value. + * @param[in] Mmax (optional) if non-negative, truncate the order of the + * model this value. + * @exception GeographicErr if the data file cannot be found, is + * unreadable, or is corrupt, or if \e Mmax > \e Nmax. + * @exception std::bad_alloc if the memory necessary for storing the model + * can't be allocated. + * + * A filename is formed by appending ".wmm" (World Magnetic Model) to the + * name. If \e path is specified (and is non-empty), then the file is + * loaded from directory, \e path. Otherwise the path is given by the + * DefaultMagneticPath(). + * + * This file contains the metadata which specifies the properties of the + * model. The coefficients for the spherical harmonic sums are obtained + * from a file obtained by appending ".cof" to metadata file (so the + * filename ends in ".wwm.cof"). + * + * The model is not tied to a particular ellipsoidal model of the earth. + * The final earth argument to the constructor specifies an ellipsoid to + * allow geodetic coordinates to the transformed into the spherical + * coordinates used in the spherical harmonic sum. + * + * If \e Nmax ≥ 0 and \e Mmax < 0, then \e Mmax is set to \e Nmax. + * After the model is loaded, the maximum degree and order of the model can + * be found by the Degree() and Order() methods. + **********************************************************************/ + explicit MagneticModel(const std::string& name, + const std::string& path = "", + const Geocentric& earth = Geocentric::WGS84(), + int Nmax = -1, int Mmax = -1); + ///@} + + /** \name Compute the magnetic field + **********************************************************************/ + ///@{ + /** + * Evaluate the components of the geomagnetic field. + * + * @param[in] t the time (years). + * @param[in] lat latitude of the point (degrees). + * @param[in] lon longitude of the point (degrees). + * @param[in] h the height of the point above the ellipsoid (meters). + * @param[out] Bx the easterly component of the magnetic field (nanotesla). + * @param[out] By the northerly component of the magnetic field + * (nanotesla). + * @param[out] Bz the vertical (up) component of the magnetic field + * (nanotesla). + **********************************************************************/ + void operator()(real t, real lat, real lon, real h, + real& Bx, real& By, real& Bz) const { + real dummy; + Field(t, lat, lon, h, false, Bx, By, Bz, dummy, dummy, dummy); + } + + /** + * Evaluate the components of the geomagnetic field and their time + * derivatives + * + * @param[in] t the time (years). + * @param[in] lat latitude of the point (degrees). + * @param[in] lon longitude of the point (degrees). + * @param[in] h the height of the point above the ellipsoid (meters). + * @param[out] Bx the easterly component of the magnetic field (nanotesla). + * @param[out] By the northerly component of the magnetic field + * (nanotesla). + * @param[out] Bz the vertical (up) component of the magnetic field + * (nanotesla). + * @param[out] Bxt the rate of change of \e Bx (nT/yr). + * @param[out] Byt the rate of change of \e By (nT/yr). + * @param[out] Bzt the rate of change of \e Bz (nT/yr). + **********************************************************************/ + void operator()(real t, real lat, real lon, real h, + real& Bx, real& By, real& Bz, + real& Bxt, real& Byt, real& Bzt) const { + Field(t, lat, lon, h, true, Bx, By, Bz, Bxt, Byt, Bzt); + } + + /** + * Create a MagneticCircle object to allow the geomagnetic field at many + * points with constant \e lat, \e h, and \e t and varying \e lon to be + * computed efficiently. + * + * @param[in] t the time (years). + * @param[in] lat latitude of the point (degrees). + * @param[in] h the height of the point above the ellipsoid (meters). + * @exception std::bad_alloc if the memory necessary for creating a + * MagneticCircle can't be allocated. + * @return a MagneticCircle object whose MagneticCircle::operator()(real + * lon) member function computes the field at particular values of \e + * lon. + * + * If the field at several points on a circle of latitude need to be + * calculated then creating a MagneticCircle and using its member functions + * will be substantially faster, especially for high-degree models. + **********************************************************************/ + MagneticCircle Circle(real t, real lat, real h) const; + + /** + * Compute the magnetic field in geocentric coordinate. + * + * @param[in] t the time (years). + * @param[in] X geocentric coordinate (meters). + * @param[in] Y geocentric coordinate (meters). + * @param[in] Z geocentric coordinate (meters). + * @param[out] BX the \e X component of the magnetic field (nT). + * @param[out] BY the \e Y component of the magnetic field (nT). + * @param[out] BZ the \e Z component of the magnetic field (nT). + * @param[out] BXt the rate of change of \e BX (nT/yr). + * @param[out] BYt the rate of change of \e BY (nT/yr). + * @param[out] BZt the rate of change of \e BZ (nT/yr). + **********************************************************************/ + void FieldGeocentric(real t, real X, real Y, real Z, + real& BX, real& BY, real& BZ, + real& BXt, real& BYt, real& BZt) const; + + /** + * Compute various quantities dependent on the magnetic field. + * + * @param[in] Bx the \e x (easterly) component of the magnetic field (nT). + * @param[in] By the \e y (northerly) component of the magnetic field (nT). + * @param[in] Bz the \e z (vertical, up positive) component of the magnetic + * field (nT). + * @param[out] H the horizontal magnetic field (nT). + * @param[out] F the total magnetic field (nT). + * @param[out] D the declination of the field (degrees east of north). + * @param[out] I the inclination of the field (degrees down from + * horizontal). + **********************************************************************/ + static void FieldComponents(real Bx, real By, real Bz, + real& H, real& F, real& D, real& I) { + real Ht, Ft, Dt, It; + FieldComponents(Bx, By, Bz, real(0), real(1), real(0), + H, F, D, I, Ht, Ft, Dt, It); + } + + /** + * Compute various quantities dependent on the magnetic field and its rate + * of change. + * + * @param[in] Bx the \e x (easterly) component of the magnetic field (nT). + * @param[in] By the \e y (northerly) component of the magnetic field (nT). + * @param[in] Bz the \e z (vertical, up positive) component of the magnetic + * field (nT). + * @param[in] Bxt the rate of change of \e Bx (nT/yr). + * @param[in] Byt the rate of change of \e By (nT/yr). + * @param[in] Bzt the rate of change of \e Bz (nT/yr). + * @param[out] H the horizontal magnetic field (nT). + * @param[out] F the total magnetic field (nT). + * @param[out] D the declination of the field (degrees east of north). + * @param[out] I the inclination of the field (degrees down from + * horizontal). + * @param[out] Ht the rate of change of \e H (nT/yr). + * @param[out] Ft the rate of change of \e F (nT/yr). + * @param[out] Dt the rate of change of \e D (degrees/yr). + * @param[out] It the rate of change of \e I (degrees/yr). + **********************************************************************/ + static void FieldComponents(real Bx, real By, real Bz, + real Bxt, real Byt, real Bzt, + real& H, real& F, real& D, real& I, + real& Ht, real& Ft, real& Dt, real& It); + ///@} + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return the description of the magnetic model, if available, from the + * Description file in the data file; if absent, return "NONE". + **********************************************************************/ + const std::string& Description() const { return _description; } + + /** + * @return date of the model, if available, from the ReleaseDate field in + * the data file; if absent, return "UNKNOWN". + **********************************************************************/ + const std::string& DateTime() const { return _date; } + + /** + * @return full file name used to load the magnetic model. + **********************************************************************/ + const std::string& MagneticFile() const { return _filename; } + + /** + * @return "name" used to load the magnetic model (from the first argument + * of the constructor, but this may be overridden by the model file). + **********************************************************************/ + const std::string& MagneticModelName() const { return _name; } + + /** + * @return directory used to load the magnetic model. + **********************************************************************/ + const std::string& MagneticModelDirectory() const { return _dir; } + + /** + * @return the minimum height above the ellipsoid (in meters) for which + * this MagneticModel should be used. + * + * Because the model will typically provide useful results + * slightly outside the range of allowed heights, no check of \e t + * argument is made by MagneticModel::operator()() or + * MagneticModel::Circle. + **********************************************************************/ + Math::real MinHeight() const { return _hmin; } + + /** + * @return the maximum height above the ellipsoid (in meters) for which + * this MagneticModel should be used. + * + * Because the model will typically provide useful results + * slightly outside the range of allowed heights, no check of \e t + * argument is made by MagneticModel::operator()() or + * MagneticModel::Circle. + **********************************************************************/ + Math::real MaxHeight() const { return _hmax; } + + /** + * @return the minimum time (in years) for which this MagneticModel should + * be used. + * + * Because the model will typically provide useful results + * slightly outside the range of allowed times, no check of \e t + * argument is made by MagneticModel::operator()() or + * MagneticModel::Circle. + **********************************************************************/ + Math::real MinTime() const { return _tmin; } + + /** + * @return the maximum time (in years) for which this MagneticModel should + * be used. + * + * Because the model will typically provide useful results + * slightly outside the range of allowed times, no check of \e t + * argument is made by MagneticModel::operator()() or + * MagneticModel::Circle. + **********************************************************************/ + Math::real MaxTime() const { return _tmax; } + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value of \e a inherited from the Geocentric object used in the + * constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the Geocentric object used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _earth.Flattening(); } + + /** + * @return \e Nmax the maximum degree of the components of the model. + **********************************************************************/ + int Degree() const { return _nmx; } + + /** + * @return \e Mmax the maximum order of the components of the model. + **********************************************************************/ + int Order() const { return _mmx; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * @return the default path for magnetic model data files. + * + * This is the value of the environment variable + * GEOGRAPHICLIB_MAGNETIC_PATH, if set; otherwise, it is + * $GEOGRAPHICLIB_DATA/magnetic if the environment variable + * GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default + * (/usr/local/share/GeographicLib/magnetic on non-Windows systems and + * C:/ProgramData/GeographicLib/magnetic on Windows systems). + **********************************************************************/ + static std::string DefaultMagneticPath(); + + /** + * @return the default name for the magnetic model. + * + * This is the value of the environment variable + * GEOGRAPHICLIB_MAGNETIC_NAME, if set; otherwise, it is "wmm2020". The + * MagneticModel class does not use this function; it is just provided as a + * convenience for a calling program when constructing a MagneticModel + * object. + **********************************************************************/ + static std::string DefaultMagneticName(); + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_MAGNETICMODEL_HPP diff --git a/external/include/GeographicLib/Math.hpp b/external/include/GeographicLib/Math.hpp new file mode 100644 index 0000000..3093544 --- /dev/null +++ b/external/include/GeographicLib/Math.hpp @@ -0,0 +1,684 @@ +/** + * \file Math.hpp + * \brief Header for GeographicLib::Math class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +// Constants.hpp includes Math.hpp. Place this include outside Math.hpp's +// include guard to enforce this ordering. +#include + +#if !defined(GEOGRAPHICLIB_MATH_HPP) +#define GEOGRAPHICLIB_MATH_HPP 1 + +#if !defined(GEOGRAPHICLIB_WORDS_BIGENDIAN) +# define GEOGRAPHICLIB_WORDS_BIGENDIAN 0 +#endif + +#if !defined(GEOGRAPHICLIB_HAVE_LONG_DOUBLE) +# define GEOGRAPHICLIB_HAVE_LONG_DOUBLE 0 +#endif + +#if !defined(GEOGRAPHICLIB_PRECISION) +/** + * The precision of floating point numbers used in %GeographicLib. 1 means + * float (single precision); 2 (the default) means double; 3 means long double; + * 4 is reserved for quadruple precision. Nearly all the testing has been + * carried out with doubles and that's the recommended configuration. In order + * for long double to be used, GEOGRAPHICLIB_HAVE_LONG_DOUBLE needs to be + * defined. Note that with Microsoft Visual Studio, long double is the same as + * double. + **********************************************************************/ +# define GEOGRAPHICLIB_PRECISION 2 +#endif + +#include +#include +#include + +#if GEOGRAPHICLIB_PRECISION == 4 +#include +#include +#include +#elif GEOGRAPHICLIB_PRECISION == 5 +#include +#endif + +#if GEOGRAPHICLIB_PRECISION > 3 +// volatile keyword makes no sense for multiprec types +#define GEOGRAPHICLIB_VOLATILE +// Signal a convergence failure with multiprec types by throwing an exception +// at loop exit. +#define GEOGRAPHICLIB_PANIC \ + (throw GeographicLib::GeographicErr("Convergence failure"), false) +#else +#define GEOGRAPHICLIB_VOLATILE volatile +// Ignore convergence failures with standard floating points types by allowing +// loop to exit cleanly. +#define GEOGRAPHICLIB_PANIC false +#endif + +namespace GeographicLib { + + /** + * \brief Mathematical functions needed by %GeographicLib + * + * Define mathematical functions in order to localize system dependencies and + * to provide generic versions of the functions. In addition define a real + * type to be used by %GeographicLib. + * + * Example of use: + * \include example-Math.cpp + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT Math { + private: + void dummy(); // Static check for GEOGRAPHICLIB_PRECISION + Math(); // Disable constructor + public: + +#if GEOGRAPHICLIB_HAVE_LONG_DOUBLE + /** + * The extended precision type for real numbers, used for some testing. + * This is long double on computers with this type; otherwise it is double. + **********************************************************************/ + typedef long double extended; +#else + typedef double extended; +#endif + +#if GEOGRAPHICLIB_PRECISION == 2 + /** + * The real type for %GeographicLib. Nearly all the testing has been done + * with \e real = double. However, the algorithms should also work with + * float and long double (where available). (CAUTION: reasonable + * accuracy typically cannot be obtained using floats.) + **********************************************************************/ + typedef double real; +#elif GEOGRAPHICLIB_PRECISION == 1 + typedef float real; +#elif GEOGRAPHICLIB_PRECISION == 3 + typedef extended real; +#elif GEOGRAPHICLIB_PRECISION == 4 + typedef boost::multiprecision::float128 real; +#elif GEOGRAPHICLIB_PRECISION == 5 + typedef mpfr::mpreal real; +#else + typedef double real; +#endif + + /** + * @return the number of bits of precision in a real number. + **********************************************************************/ + static int digits(); + + /** + * Set the binary precision of a real number. + * + * @param[in] ndigits the number of bits of precision. + * @return the resulting number of bits of precision. + * + * This only has an effect when GEOGRAPHICLIB_PRECISION = 5. See also + * Utility::set_digits for caveats about when this routine should be + * called. + **********************************************************************/ + static int set_digits(int ndigits); + + /** + * @return the number of decimal digits of precision in a real number. + **********************************************************************/ + static int digits10(); + + /** + * Number of additional decimal digits of precision for real relative to + * double (0 for float). + **********************************************************************/ + static int extra_digits(); + + /** + * true if the machine is big-endian. + **********************************************************************/ + static const bool bigendian = GEOGRAPHICLIB_WORDS_BIGENDIAN; + + /** + * @tparam T the type of the returned value. + * @return π. + **********************************************************************/ + template static T pi() { + using std::atan2; + static const T pi = atan2(T(0), T(-1)); + return pi; + } + + /** + * @tparam T the type of the returned value. + * @return the number of radians in a degree. + **********************************************************************/ + template static T degree() { + static const T degree = pi() / 180; + return degree; + } + + /** + * Square a number. + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @return x2. + **********************************************************************/ + template static T sq(T x) + { return x * x; } + + /** + * The hypotenuse function avoiding underflow and overflow. + * + * @tparam T the type of the arguments and the returned value. + * @param[in] x + * @param[in] y + * @return sqrt(x2 + y2). + * + * \deprecated Use std::hypot(x, y). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::hypot(x, y)") + static T hypot(T x, T y); + + /** + * exp(\e x) − 1 accurate near \e x = 0. + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @return exp(\e x) − 1. + * + * \deprecated Use std::expm1(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::expm1(x)") + static T expm1(T x); + + /** + * log(1 + \e x) accurate near \e x = 0. + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @return log(1 + \e x). + * + * \deprecated Use std::log1p(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::log1p(x)") + static T log1p(T x); + + /** + * The inverse hyperbolic sine function. + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @return asinh(\e x). + * + * \deprecated Use std::asinh(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::asinh(x)") + static T asinh(T x); + + /** + * The inverse hyperbolic tangent function. + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @return atanh(\e x). + * + * \deprecated Use std::atanh(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::atanh(x)") + static T atanh(T x); + + /** + * Copy the sign. + * + * @tparam T the type of the argument. + * @param[in] x gives the magitude of the result. + * @param[in] y gives the sign of the result. + * @return value with the magnitude of \e x and with the sign of \e y. + * + * This routine correctly handles the case \e y = −0, returning + * &minus|x|. + * + * \deprecated Use std::copysign(x, y). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::copysign(x, y)") + static T copysign(T x, T y); + + /** + * The cube root function. + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @return the real cube root of \e x. + * + * \deprecated Use std::cbrt(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::cbrt(x)") + static T cbrt(T x); + + /** + * The remainder function. + * + * @tparam T the type of the arguments and the returned value. + * @param[in] x + * @param[in] y + * @return the remainder of \e x/\e y in the range [−\e y/2, \e y/2]. + * + * \deprecated Use std::remainder(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::remainder(x)") + static T remainder(T x, T y); + + /** + * The remquo function. + * + * @tparam T the type of the arguments and the returned value. + * @param[in] x + * @param[in] y + * @param[out] n the low 3 bits of the quotient + * @return the remainder of \e x/\e y in the range [−\e y/2, \e y/2]. + * + * \deprecated Use std::remquo(x, y, n). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::remquo(x, y, n)") + static T remquo(T x, T y, int* n); + + /** + * The round function. + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @return \e x round to the nearest integer (ties round away from 0). + * + * \deprecated Use std::round(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::round(x)") + static T round(T x); + + /** + * The lround function. + * + * @tparam T the type of the argument. + * @param[in] x + * @return \e x round to the nearest integer as a long int (ties round away + * from 0). + * + * If the result does not fit in a long int, the return value is undefined. + * + * \deprecated Use std::lround(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::lround(x)") + static long lround(T x); + + /** + * Fused multiply and add. + * + * @tparam T the type of the arguments and the returned value. + * @param[in] x + * @param[in] y + * @param[in] z + * @return xy + z, correctly rounded (on those platforms with + * support for the fma instruction). + * + * On platforms without the fma instruction, no attempt is + * made to improve on the result of a rounded multiplication followed by a + * rounded addition. + * + * \deprecated Use std::fma(x, y, z). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::fma(x, y, z)") + static T fma(T x, T y, T z); + + /** + * Normalize a two-vector. + * + * @tparam T the type of the argument and the returned value. + * @param[in,out] x on output set to x/hypot(x, y). + * @param[in,out] y on output set to y/hypot(x, y). + **********************************************************************/ + template static void norm(T& x, T& y) { +#if defined(_MSC_VER) && defined(_M_IX86) + // hypot for Visual Studio (A=win32) fails monotonicity, e.g., with + // x = 0.6102683302836215 + // y1 = 0.7906090004346522 + // y2 = y1 + 1e-16 + // the test + // hypot(x, y2) >= hypot(x, y1) + // fails. Reported 2021-03-14: + // https://developercommunity.visualstudio.com/t/1369259 + // See also: + // https://bugs.python.org/issue43088 + using std::sqrt; T h = sqrt(x * x + y * y); +#else + using std::hypot; T h = hypot(x, y); +#endif + x /= h; y /= h; + } + + /** + * The error-free sum of two numbers. + * + * @tparam T the type of the argument and the returned value. + * @param[in] u + * @param[in] v + * @param[out] t the exact error given by (\e u + \e v) - \e s. + * @return \e s = round(\e u + \e v). + * + * See D. E. Knuth, TAOCP, Vol 2, 4.2.2, Theorem B. (Note that \e t can be + * the same as one of the first two arguments.) + **********************************************************************/ + template static T sum(T u, T v, T& t); + + /** + * Evaluate a polynomial. + * + * @tparam T the type of the arguments and returned value. + * @param[in] N the order of the polynomial. + * @param[in] p the coefficient array (of size \e N + 1). + * @param[in] x the variable. + * @return the value of the polynomial. + * + * Evaluate y = ∑n=0..N + * pn xNn. + * Return 0 if \e N < 0. Return p0, if \e N = 0 (even + * if \e x is infinite or a nan). The evaluation uses Horner's method. + **********************************************************************/ + template static T polyval(int N, const T p[], T x) { + // This used to employ Math::fma; but that's too slow and it seemed not to + // improve the accuracy noticeably. This might change when there's direct + // hardware support for fma. + T y = N < 0 ? 0 : *p++; + while (--N >= 0) y = y * x + *p++; + return y; + } + + /** + * Normalize an angle. + * + * @tparam T the type of the argument and returned value. + * @param[in] x the angle in degrees. + * @return the angle reduced to the range (−180°, 180°]. + * + * The range of \e x is unrestricted. + **********************************************************************/ + template static T AngNormalize(T x) { + using std::remainder; + x = remainder(x, T(360)); return x != -180 ? x : 180; + } + + /** + * Normalize a latitude. + * + * @tparam T the type of the argument and returned value. + * @param[in] x the angle in degrees. + * @return x if it is in the range [−90°, 90°], otherwise + * return NaN. + **********************************************************************/ + template static T LatFix(T x) + { using std::abs; return abs(x) > 90 ? NaN() : x; } + + /** + * The exact difference of two angles reduced to + * (−180°, 180°]. + * + * @tparam T the type of the arguments and returned value. + * @param[in] x the first angle in degrees. + * @param[in] y the second angle in degrees. + * @param[out] e the error term in degrees. + * @return \e d, the truncated value of \e y − \e x. + * + * This computes \e z = \e y − \e x exactly, reduced to + * (−180°, 180°]; and then sets \e z = \e d + \e e where \e d + * is the nearest representable number to \e z and \e e is the truncation + * error. If \e d = −180, then \e e > 0; If \e d = 180, then \e e + * ≤ 0. + **********************************************************************/ + template static T AngDiff(T x, T y, T& e) { + using std::remainder; + T t, d = AngNormalize(sum(remainder(-x, T(360)), + remainder( y, T(360)), t)); + // Here y - x = d + t (mod 360), exactly, where d is in (-180,180] and + // abs(t) <= eps (eps = 2^-45 for doubles). The only case where the + // addition of t takes the result outside the range (-180,180] is d = 180 + // and t > 0. The case, d = -180 + eps, t = -eps, can't happen, since + // sum would have returned the exact result in such a case (i.e., given t + // = 0). + return sum(d == 180 && t > 0 ? -180 : d, t, e); + } + + /** + * Difference of two angles reduced to [−180°, 180°] + * + * @tparam T the type of the arguments and returned value. + * @param[in] x the first angle in degrees. + * @param[in] y the second angle in degrees. + * @return \e y − \e x, reduced to the range [−180°, + * 180°]. + * + * The result is equivalent to computing the difference exactly, reducing + * it to (−180°, 180°] and rounding the result. Note that + * this prescription allows −180° to be returned (e.g., if \e x + * is tiny and negative and \e y = 180°). + **********************************************************************/ + template static T AngDiff(T x, T y) + { T e; return AngDiff(x, y, e); } + + /** + * Coarsen a value close to zero. + * + * @tparam T the type of the argument and returned value. + * @param[in] x + * @return the coarsened value. + * + * The makes the smallest gap in \e x = 1/16 − nextafter(1/16, 0) = + * 1/257 for reals = 0.7 pm on the earth if \e x is an angle in + * degrees. (This is about 1000 times more resolution than we get with + * angles around 90°.) We use this to avoid having to deal with near + * singular cases when \e x is non-zero but tiny (e.g., + * 10−200). This converts −0 to +0; however tiny + * negative numbers get converted to −0. + **********************************************************************/ + template static T AngRound(T x); + + /** + * Evaluate the sine and cosine function with the argument in degrees + * + * @tparam T the type of the arguments. + * @param[in] x in degrees. + * @param[out] sinx sin(x). + * @param[out] cosx cos(x). + * + * The results obey exactly the elementary properties of the trigonometric + * functions, e.g., sin 9° = cos 81° = − sin 123456789°. + * If x = −0, then \e sinx = −0; this is the only case where + * −0 is returned. + **********************************************************************/ + template static void sincosd(T x, T& sinx, T& cosx); + + /** + * Evaluate the sine function with the argument in degrees + * + * @tparam T the type of the argument and the returned value. + * @param[in] x in degrees. + * @return sin(x). + **********************************************************************/ + template static T sind(T x); + + /** + * Evaluate the cosine function with the argument in degrees + * + * @tparam T the type of the argument and the returned value. + * @param[in] x in degrees. + * @return cos(x). + **********************************************************************/ + template static T cosd(T x); + + /** + * Evaluate the tangent function with the argument in degrees + * + * @tparam T the type of the argument and the returned value. + * @param[in] x in degrees. + * @return tan(x). + * + * If \e x = ±90°, then a suitably large (but finite) value is + * returned. + **********************************************************************/ + template static T tand(T x); + + /** + * Evaluate the atan2 function with the result in degrees + * + * @tparam T the type of the arguments and the returned value. + * @param[in] y + * @param[in] x + * @return atan2(y, x) in degrees. + * + * The result is in the range (−180° 180°]. N.B., + * atan2d(±0, −1) = +180°; atan2d(−ε, + * −1) = −180°, for ε positive and tiny; + * atan2d(±0, +1) = ±0°. + **********************************************************************/ + template static T atan2d(T y, T x); + + /** + * Evaluate the atan function with the result in degrees + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @return atan(x) in degrees. + **********************************************************************/ + template static T atand(T x); + + /** + * Evaluate e atanh(e x) + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @param[in] es the signed eccentricity = sign(e2) + * sqrt(|e2|) + * @return e atanh(e x) + * + * If e2 is negative (e is imaginary), the + * expression is evaluated in terms of atan. + **********************************************************************/ + template static T eatanhe(T x, T es); + + /** + * tanχ in terms of tanφ + * + * @tparam T the type of the argument and the returned value. + * @param[in] tau τ = tanφ + * @param[in] es the signed eccentricity = sign(e2) + * sqrt(|e2|) + * @return τ′ = tanχ + * + * See Eqs. (7--9) of + * C. F. F. Karney, + * + * Transverse Mercator with an accuracy of a few nanometers, + * J. Geodesy 85(8), 475--485 (Aug. 2011) + * (preprint + * arXiv:1002.1417). + **********************************************************************/ + template static T taupf(T tau, T es); + + /** + * tanφ in terms of tanχ + * + * @tparam T the type of the argument and the returned value. + * @param[in] taup τ′ = tanχ + * @param[in] es the signed eccentricity = sign(e2) + * sqrt(|e2|) + * @return τ = tanφ + * + * See Eqs. (19--21) of + * C. F. F. Karney, + * + * Transverse Mercator with an accuracy of a few nanometers, + * J. Geodesy 85(8), 475--485 (Aug. 2011) + * (preprint + * arXiv:1002.1417). + **********************************************************************/ + template static T tauf(T taup, T es); + + /** + * Test for finiteness. + * + * @tparam T the type of the argument. + * @param[in] x + * @return true if number is finite, false if NaN or infinite. + * + * \deprecated Use std::isfinite(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::isfinite(x)") + static bool isfinite(T x); + + /** + * The NaN (not a number) + * + * @tparam T the type of the returned value. + * @return NaN if available, otherwise return the max real of type T. + **********************************************************************/ + template static T NaN(); + + /** + * Test for NaN. + * + * @tparam T the type of the argument. + * @param[in] x + * @return true if argument is a NaN. + * + * \deprecated Use std::isnan(x). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use std::isnan(x)") + static bool isnan(T x); + + /** + * Infinity + * + * @tparam T the type of the returned value. + * @return infinity if available, otherwise return the max real. + **********************************************************************/ + template static T infinity(); + + /** + * Swap the bytes of a quantity + * + * @tparam T the type of the argument and the returned value. + * @param[in] x + * @return x with its bytes swapped. + **********************************************************************/ + template static T swab(T x) { + union { + T r; + unsigned char c[sizeof(T)]; + } b; + b.r = x; + for (int i = sizeof(T)/2; i--; ) + std::swap(b.c[i], b.c[sizeof(T) - 1 - i]); + return b.r; + } + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_MATH_HPP diff --git a/external/include/GeographicLib/NearestNeighbor.hpp b/external/include/GeographicLib/NearestNeighbor.hpp new file mode 100644 index 0000000..56edba2 --- /dev/null +++ b/external/include/GeographicLib/NearestNeighbor.hpp @@ -0,0 +1,837 @@ +/** + * \file NearestNeighbor.hpp + * \brief Header for GeographicLib::NearestNeighbor class + * + * Copyright (c) Charles Karney (2016-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_NEARESTNEIGHBOR_HPP) +#define GEOGRAPHICLIB_NEARESTNEIGHBOR_HPP 1 + +#include // for nth_element, max_element, etc. +#include +#include // for priority_queue +#include // for swap + pair +#include +#include +#include +#include +#include +// Only for GeographicLib::GeographicErr +#include + +#if defined(GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION) && \ + GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION +#include +#include +#include +#include +#endif + +#if defined(_MSC_VER) +// Squelch warnings about constant conditional expressions +# pragma warning (push) +# pragma warning (disable: 4127) +#endif + +namespace GeographicLib { + + /** + * \brief Nearest-neighbor calculations + * + * This class solves the nearest-neighbor problm using a vantage-point tree + * as described in \ref nearest. + * + * This class is templated so that it can handle arbitrary metric spaces as + * follows: + * + * @tparam dist_t the type used for measuring distances; it can be a real or + * signed integer type; in typical geodetic applications, \e dist_t might + * be double. + * @tparam pos_t the type for specifying the positions of points; geodetic + * application might bundled the latitude and longitude into a + * std::pair. + * @tparam distfun_t the type of a function object which takes takes two + * positions (of type \e pos_t) and returns the distance (of type \e + * dist_t); in geodetic applications, this might be a class which is + * constructed with a Geodesic object and which implements a member + * function with a signature dist_t operator() (const pos_t&, const + * pos_t&) const, which returns the geodesic distance between two + * points. + * + * \note The distance measure must satisfy the triangle inequality, \f$ + * d(a,c) \le d(a,b) + d(b,c) \f$ for all points \e a, \e b, \e c. The + * geodesic distance (given by Geodesic::Inverse) does, while the great + * ellipse distance and the rhumb line distance do not. If you use + * the ordinary Euclidean distance, i.e., \f$ \sqrt{(x_a-x_b)^2 + + * (y_a-y_b)^2} \f$ for two dimensions, don't be tempted to leave out the + * square root in the interests of "efficiency"; the squared distance does + * not satisfy the triangle inequality! + * + * \note This is a "header-only" implementation and, as such, depends in a + * minimal way on the rest of GeographicLib (the only dependency is through + * the use of GeographicLib::GeographicErr for handling compile-time and + * run-time exceptions). Therefore, it is easy to extract this class from + * the rest of GeographicLib and use it as a stand-alone facility. + * + * The \e dist_t type must support numeric_limits queries (specifically: + * is_signed, is_integer, max(), digits). + * + * The NearestNeighbor object is constructed with a vector of points (type \e + * pos_t) and a distance function (type \e distfun_t). However the object + * does \e not store the points. When querying the object with Search(), + * it's necessary to supply the same vector of points and the same distance + * function. + * + * There's no capability in this implementation to add or remove points from + * the set. Instead Initialize() should be called to re-initialize the + * object with the modified vector of points. + * + * Because of the overhead in constructing a NearestNeighbor object for a + * large set of points, functions Save() and Load() are provided to save the + * object to an external file. operator<<(), operator>>() and Boost + * serialization can also be used to save and restore a NearestNeighbor + * object. This is illustrated in the example. + * + * Example of use: + * \include example-NearestNeighbor.cpp + **********************************************************************/ + template + class NearestNeighbor { + // For tracking changes to the I/O format + static const int version = 1; + // This is what we get "free"; but if sizeof(dist_t) = 1 (unlikely), allow + // 4 slots (and this accommodates the default value bucket = 4). + static const int maxbucket = + (2 + ((4 * sizeof(dist_t)) / sizeof(int) >= 2 ? + (4 * sizeof(dist_t)) / sizeof(int) : 2)); + public: + + /** + * Default constructor for NearestNeighbor. + * + * This is equivalent to specifying an empty set of points. + **********************************************************************/ + NearestNeighbor() : _numpoints(0), _bucket(0), _cost(0) {} + + /** + * Constructor for NearestNeighbor. + * + * @param[in] pts a vector of points to include in the set. + * @param[in] dist the distance function object. + * @param[in] bucket the size of the buckets at the leaf nodes; this must + * lie in [0, 2 + 4*sizeof(dist_t)/sizeof(int)] (default 4). + * @exception GeographicErr if the value of \e bucket is out of bounds or + * the size of \e pts is too big for an int. + * @exception std::bad_alloc if memory for the tree can't be allocated. + * + * \e pts may contain coincident points (i.e., the distance between them + * vanishes); these are treated as distinct. + * + * The choice of \e bucket is a tradeoff between space and efficiency. A + * larger \e bucket decreases the size of the NearestNeighbor object which + * scales as pts.size() / max(1, bucket) and reduces the number of distance + * calculations to construct the object by log2(bucket) * pts.size(). + * However each search then requires about bucket additional distance + * calculations. + * + * \warning The distances computed by \e dist must satisfy the standard + * metric conditions. If not, the results are undefined. Neither the data + * in \e pts nor the query points should contain NaNs or infinities because + * such data violates the metric conditions. + * + * \warning The same arguments \e pts and \e dist must be provided + * to the Search() function. + **********************************************************************/ + NearestNeighbor(const std::vector& pts, const distfun_t& dist, + int bucket = 4) { + Initialize(pts, dist, bucket); + } + + /** + * Initialize or re-initialize NearestNeighbor. + * + * @param[in] pts a vector of points to include in the tree. + * @param[in] dist the distance function object. + * @param[in] bucket the size of the buckets at the leaf nodes; this must + * lie in [0, 2 + 4*sizeof(dist_t)/sizeof(int)] (default 4). + * @exception GeographicErr if the value of \e bucket is out of bounds or + * the size of \e pts is too big for an int. + * @exception std::bad_alloc if memory for the tree can't be allocated. + * + * See also the documentation on the constructor. + * + * If an exception is thrown, the state of the NearestNeighbor is + * unchanged. + **********************************************************************/ + void Initialize(const std::vector& pts, const distfun_t& dist, + int bucket = 4) { + static_assert(std::numeric_limits::is_signed, + "dist_t must be a signed type"); + if (!( 0 <= bucket && bucket <= maxbucket )) + throw GeographicLib::GeographicErr + ("bucket must lie in [0, 2 + 4*sizeof(dist_t)/sizeof(int)]"); + if (pts.size() > size_t(std::numeric_limits::max())) + throw GeographicLib::GeographicErr("pts array too big"); + // the pair contains distance+id + std::vector ids(pts.size()); + for (int k = int(ids.size()); k--;) + ids[k] = std::make_pair(dist_t(0), k); + int cost = 0; + std::vector tree; + init(pts, dist, bucket, tree, ids, cost, + 0, int(ids.size()), int(ids.size()/2)); + _tree.swap(tree); + _numpoints = int(pts.size()); + _bucket = bucket; + _mc = _sc = 0; + _cost = cost; _c1 = _k = _cmax = 0; + _cmin = std::numeric_limits::max(); + } + + /** + * Search the NearestNeighbor. + * + * @param[in] pts the vector of points used for initialization. + * @param[in] dist the distance function object used for initialization. + * @param[in] query the query point. + * @param[out] ind a vector of indices to the closest points found. + * @param[in] k the number of points to search for (default = 1). + * @param[in] maxdist only return points with distances of \e maxdist or + * less from \e query (default is the maximum \e dist_t). + * @param[in] mindist only return points with distances of more than + * \e mindist from \e query (default = −1). + * @param[in] exhaustive whether to do an exhaustive search (default true). + * @param[in] tol the tolerance on the results (default 0). + * @return the distance to the closest point found (−1 if no points + * are found). + * @exception GeographicErr if \e pts has a different size from that used + * to construct the object. + * + * The indices returned in \e ind are sorted by distance from \e query + * (closest first). + * + * The simplest invocation is with just the 4 non-optional arguments. This + * returns the closest distance and the index to the closest point in + * ind0. If there are several points equally close, then + * ind0 gives the index of an arbirary one of them. If + * there's no closest point (because the set of points is empty), then \e + * ind is empty and −1 is returned. + * + * With \e exhaustive = true and \e tol = 0 (their default values), this + * finds the indices of \e k closest neighbors to \e query whose distances + * to \e query are in (\e mindist, \e maxdist]. If \e mindist and \e + * maxdist have their default values, then these bounds have no effect. If + * \e query is one of the points in the tree, then set \e mindist = 0 to + * prevent this point (and other coincident points) from being returned. + * + * If \e exhaustive = false, exit as soon as \e k results satisfying the + * distance criteria are found. If less than \e k results are returned + * then the search was exhaustive even if \e exhaustive = false. + * + * If \e tol is positive, do an approximate search; in this case the + * results are to be interpreted as follows: if the k'th distance is + * \e dk, then all results with distances less than or equal \e dk − + * \e tol are correct; all others are suspect — there may be other + * closer results with distances greater or equal to \e dk − \e tol. + * If less than \e k results are found, then the search is exact. + * + * \e mindist should be used to exclude a "small" neighborhood of the query + * point (relative to the average spacing of the data). If \e mindist is + * large, the efficiency of the search deteriorates. + * + * \note Only the shortest distance is returned (as as the function value). + * The distances to other points (indexed by indj + * for \e j > 0) can be found by invoking \e dist again. + * + * \warning The arguments \e pts and \e dist must be identical to those + * used to initialize the NearestNeighbor; if not, this function will + * return some meaningless result (however, if the size of \e pts is wrong, + * this function throw an exception). + * + * \warning The query point cannot be a NaN or infinite because then the + * metric conditions are violated. + **********************************************************************/ + dist_t Search(const std::vector& pts, const distfun_t& dist, + const pos_t& query, + std::vector& ind, + int k = 1, + dist_t maxdist = std::numeric_limits::max(), + dist_t mindist = -1, + bool exhaustive = true, + dist_t tol = 0) const { + if (_numpoints != int(pts.size())) + throw GeographicLib::GeographicErr("pts array has wrong size"); + std::priority_queue results; + if (_numpoints > 0 && k > 0 && maxdist > mindist) { + // distance to the kth closest point so far + dist_t tau = maxdist; + // first is negative of how far query is outside boundary of node + // +1 if on boundary or inside + // second is node index + std::priority_queue todo; + todo.push(std::make_pair(dist_t(1), int(_tree.size()) - 1)); + int c = 0; + while (!todo.empty()) { + int n = todo.top().second; + dist_t d = -todo.top().first; + todo.pop(); + dist_t tau1 = tau - tol; + // compare tau and d again since tau may have become smaller. + if (!( n >= 0 && tau1 >= d )) continue; + const Node& current = _tree[n]; + dist_t dst = 0; // to suppress warning about uninitialized variable + bool exitflag = false, leaf = current.index < 0; + for (int i = 0; i < (leaf ? _bucket : 1); ++i) { + int index = leaf ? current.leaves[i] : current.index; + if (index < 0) break; + dst = dist(pts[index], query); + ++c; + + if (dst > mindist && dst <= tau) { + if (int(results.size()) == k) results.pop(); + results.push(std::make_pair(dst, index)); + if (int(results.size()) == k) { + if (exhaustive) + tau = results.top().first; + else { + exitflag = true; + break; + } + if (tau <= tol) { + exitflag = true; + break; + } + } + } + } + if (exitflag) break; + + if (current.index < 0) continue; + tau1 = tau - tol; + for (int l = 0; l < 2; ++l) { + if (current.data.child[l] >= 0 && + dst + current.data.upper[l] >= mindist) { + if (dst < current.data.lower[l]) { + d = current.data.lower[l] - dst; + if (tau1 >= d) + todo.push(std::make_pair(-d, current.data.child[l])); + } else if (dst > current.data.upper[l]) { + d = dst - current.data.upper[l]; + if (tau1 >= d) + todo.push(std::make_pair(-d, current.data.child[l])); + } else + todo.push(std::make_pair(dist_t(1), current.data.child[l])); + } + } + } + ++_k; + _c1 += c; + double omc = _mc; + _mc += (c - omc) / _k; + _sc += (c - omc) * (c - _mc); + if (c > _cmax) _cmax = c; + if (c < _cmin) _cmin = c; + } + + dist_t d = -1; + ind.resize(results.size()); + + for (int i = int(ind.size()); i--;) { + ind[i] = int(results.top().second); + if (i == 0) d = results.top().first; + results.pop(); + } + return d; + + } + + /** + * @return the total number of points in the set. + **********************************************************************/ + int NumPoints() const { return _numpoints; } + + /** + * Write the object to an I/O stream. + * + * @param[in,out] os the stream to write to. + * @param[in] bin if true (the default) save in binary mode. + * @exception std::bad_alloc if memory for the string representation of the + * object can't be allocated. + * + * The counters tracking the statistics of searches are not saved; however + * the initializtion cost is saved. The format of the binary saves is \e + * not portable. + * + * \note + * Boost serialization can also be used to save and restore a + * NearestNeighbor object. This requires that the + * GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION macro be defined. + **********************************************************************/ + void Save(std::ostream& os, bool bin = true) const { + int realspec = std::numeric_limits::digits * + (std::numeric_limits::is_integer ? -1 : 1); + if (bin) { + char id[] = "NearestNeighbor_"; + os.write(id, 16); + int buf[6]; + buf[0] = version; + buf[1] = realspec; + buf[2] = _bucket; + buf[3] = _numpoints; + buf[4] = int(_tree.size()); + buf[5] = _cost; + os.write(reinterpret_cast(buf), 6 * sizeof(int)); + for (int i = 0; i < int(_tree.size()); ++i) { + const Node& node = _tree[i]; + os.write(reinterpret_cast(&node.index), sizeof(int)); + if (node.index >= 0) { + os.write(reinterpret_cast(node.data.lower), + 2 * sizeof(dist_t)); + os.write(reinterpret_cast(node.data.upper), + 2 * sizeof(dist_t)); + os.write(reinterpret_cast(node.data.child), + 2 * sizeof(int)); + } else { + os.write(reinterpret_cast(node.leaves), + _bucket * sizeof(int)); + } + } + } else { + std::stringstream ostring; + // Ensure enough precision for type dist_t. With C++11, max_digits10 + // can be used instead. + if (!std::numeric_limits::is_integer) { + static const int prec + = int(std::ceil(std::numeric_limits::digits * + std::log10(2.0) + 1)); + ostring.precision(prec); + } + ostring << version << " " << realspec << " " << _bucket << " " + << _numpoints << " " << _tree.size() << " " << _cost; + for (int i = 0; i < int(_tree.size()); ++i) { + const Node& node = _tree[i]; + ostring << "\n" << node.index; + if (node.index >= 0) { + for (int l = 0; l < 2; ++l) + ostring << " " << node.data.lower[l] << " " << node.data.upper[l] + << " " << node.data.child[l]; + } else { + for (int l = 0; l < _bucket; ++l) + ostring << " " << node.leaves[l]; + } + } + os << ostring.str(); + } + } + + /** + * Read the object from an I/O stream. + * + * @param[in,out] is the stream to read from + * @param[in] bin if true (the default) load in binary mode. + * @exception GeographicErr if the state read from \e is is illegal. + * @exception std::bad_alloc if memory for the tree can't be allocated. + * + * The counters tracking the statistics of searches are reset by this + * operation. Binary data must have been saved on a machine with the same + * architecture. If an exception is thrown, the state of the + * NearestNeighbor is unchanged. + * + * \note + * Boost serialization can also be used to save and restore a + * NearestNeighbor object. This requires that the + * GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION macro be defined. + * + * \warning The same arguments \e pts and \e dist used for + * initialization must be provided to the Search() function. + **********************************************************************/ + void Load(std::istream& is, bool bin = true) { + int version1, realspec, bucket, numpoints, treesize, cost; + if (bin) { + char id[17]; + is.read(id, 16); + id[16] = '\0'; + if (!(std::strcmp(id, "NearestNeighbor_") == 0)) + throw GeographicLib::GeographicErr("Bad ID"); + is.read(reinterpret_cast(&version1), sizeof(int)); + is.read(reinterpret_cast(&realspec), sizeof(int)); + is.read(reinterpret_cast(&bucket), sizeof(int)); + is.read(reinterpret_cast(&numpoints), sizeof(int)); + is.read(reinterpret_cast(&treesize), sizeof(int)); + is.read(reinterpret_cast(&cost), sizeof(int)); + } else { + if (!( is >> version1 >> realspec >> bucket >> numpoints >> treesize + >> cost )) + throw GeographicLib::GeographicErr("Bad header"); + } + if (!( version1 == version )) + throw GeographicLib::GeographicErr("Incompatible version"); + if (!( realspec == std::numeric_limits::digits * + (std::numeric_limits::is_integer ? -1 : 1) )) + throw GeographicLib::GeographicErr("Different dist_t types"); + if (!( 0 <= bucket && bucket <= maxbucket )) + throw GeographicLib::GeographicErr("Bad bucket size"); + if (!( 0 <= treesize && treesize <= numpoints )) + throw + GeographicLib::GeographicErr("Bad number of points or tree size"); + if (!( 0 <= cost )) + throw GeographicLib::GeographicErr("Bad value for cost"); + std::vector tree; + tree.reserve(treesize); + for (int i = 0; i < treesize; ++i) { + Node node; + if (bin) { + is.read(reinterpret_cast(&node.index), sizeof(int)); + if (node.index >= 0) { + is.read(reinterpret_cast(node.data.lower), + 2 * sizeof(dist_t)); + is.read(reinterpret_cast(node.data.upper), + 2 * sizeof(dist_t)); + is.read(reinterpret_cast(node.data.child), + 2 * sizeof(int)); + } else { + is.read(reinterpret_cast(node.leaves), + bucket * sizeof(int)); + for (int l = bucket; l < maxbucket; ++l) + node.leaves[l] = 0; + } + } else { + if (!( is >> node.index )) + throw GeographicLib::GeographicErr("Bad index"); + if (node.index >= 0) { + for (int l = 0; l < 2; ++l) { + if (!( is >> node.data.lower[l] >> node.data.upper[l] + >> node.data.child[l] )) + throw GeographicLib::GeographicErr("Bad node data"); + } + } else { + // Must be at least one valid leaf followed by a sequence end + // markers (-1). + for (int l = 0; l < bucket; ++l) { + if (!( is >> node.leaves[l] )) + throw GeographicLib::GeographicErr("Bad leaf data"); + } + for (int l = bucket; l < maxbucket; ++l) + node.leaves[l] = 0; + } + } + node.Check(numpoints, treesize, bucket); + tree.push_back(node); + } + _tree.swap(tree); + _numpoints = numpoints; + _bucket = bucket; + _mc = _sc = 0; + _cost = cost; _c1 = _k = _cmax = 0; + _cmin = std::numeric_limits::max(); + } + + /** + * Write the object to stream \e os as text. + * + * @param[in,out] os the output stream. + * @param[in] t the NearestNeighbor object to be saved. + * @exception std::bad_alloc if memory for the string representation of the + * object can't be allocated. + **********************************************************************/ + friend std::ostream& operator<<(std::ostream& os, const NearestNeighbor& t) + { t.Save(os, false); return os; } + + /** + * Read the object from stream \e is as text. + * + * @param[in,out] is the input stream. + * @param[out] t the NearestNeighbor object to be loaded. + * @exception GeographicErr if the state read from \e is is illegal. + * @exception std::bad_alloc if memory for the tree can't be allocated. + **********************************************************************/ + friend std::istream& operator>>(std::istream& is, NearestNeighbor& t) + { t.Load(is, false); return is; } + + /** + * Swap with another NearestNeighbor object. + * + * @param[in,out] t the NearestNeighbor object to swap with. + **********************************************************************/ + void swap(NearestNeighbor& t) { + std::swap(_numpoints, t._numpoints); + std::swap(_bucket, t._bucket); + std::swap(_cost, t._cost); + _tree.swap(t._tree); + std::swap(_mc, t._mc); + std::swap(_sc, t._sc); + std::swap(_c1, t._c1); + std::swap(_k, t._k); + std::swap(_cmin, t._cmin); + std::swap(_cmax, t._cmax); + } + + /** + * The accumulated statistics on the searches so far. + * + * @param[out] setupcost the cost of initializing the NearestNeighbor. + * @param[out] numsearches the number of calls to Search(). + * @param[out] searchcost the total cost of the calls to Search(). + * @param[out] mincost the minimum cost of a Search(). + * @param[out] maxcost the maximum cost of a Search(). + * @param[out] mean the mean cost of a Search(). + * @param[out] sd the standard deviation in the cost of a Search(). + * + * Here "cost" measures the number of distance calculations needed. Note + * that the accumulation of statistics is \e not thread safe. + **********************************************************************/ + void Statistics(int& setupcost, int& numsearches, int& searchcost, + int& mincost, int& maxcost, + double& mean, double& sd) const { + setupcost = _cost; numsearches = _k; searchcost = _c1; + mincost = _cmin; maxcost = _cmax; + mean = _mc; sd = std::sqrt(_sc / (_k - 1)); + } + + /** + * Reset the counters for the accumulated statistics on the searches so + * far. + **********************************************************************/ + void ResetStatistics() const { + _mc = _sc = 0; + _c1 = _k = _cmax = 0; + _cmin = std::numeric_limits::max(); + } + + private: + // Package up a dist_t and an int. We will want to sort on the dist_t so + // put it first. + typedef std::pair item; + // \cond SKIP + class Node { + public: + struct bounds { + dist_t lower[2], upper[2]; // bounds on inner/outer distances + int child[2]; + }; + union { + bounds data; + int leaves[maxbucket]; + }; + int index; + + Node() + : index(-1) + { + for (int i = 0; i < 2; ++i) { + data.lower[i] = data.upper[i] = 0; + data.child[i] = -1; + } + } + + // Sanity check on a Node + void Check(int numpoints, int treesize, int bucket) const { + if (!( -1 <= index && index < numpoints )) + throw GeographicLib::GeographicErr("Bad index"); + if (index >= 0) { + if (!( -1 <= data.child[0] && data.child[0] < treesize && + -1 <= data.child[1] && data.child[1] < treesize )) + throw GeographicLib::GeographicErr("Bad child pointers"); + if (!( 0 <= data.lower[0] && data.lower[0] <= data.upper[0] && + data.upper[0] <= data.lower[1] && + data.lower[1] <= data.upper[1] )) + throw GeographicLib::GeographicErr("Bad bounds"); + } else { + // Must be at least one valid leaf followed by a sequence end markers + // (-1). + bool start = true; + for (int l = 0; l < bucket; ++l) { + if (!( (start ? + ((l == 0 ? 0 : -1) <= leaves[l] && leaves[l] < numpoints) : + leaves[l] == -1) )) + throw GeographicLib::GeographicErr("Bad leaf data"); + start = leaves[l] >= 0; + } + for (int l = bucket; l < maxbucket; ++l) { + if (leaves[l] != 0) + throw GeographicLib::GeographicErr("Bad leaf data"); + } + } + } + +#if defined(GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION) && \ + GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION + friend class boost::serialization::access; + template + void save(Archive& ar, const unsigned int) const { + ar & boost::serialization::make_nvp("index", index); + if (index < 0) + ar & boost::serialization::make_nvp("leaves", leaves); + else + ar & boost::serialization::make_nvp("lower", data.lower) + & boost::serialization::make_nvp("upper", data.upper) + & boost::serialization::make_nvp("child", data.child); + } + template + void load(Archive& ar, const unsigned int) { + ar & boost::serialization::make_nvp("index", index); + if (index < 0) + ar & boost::serialization::make_nvp("leaves", leaves); + else + ar & boost::serialization::make_nvp("lower", data.lower) + & boost::serialization::make_nvp("upper", data.upper) + & boost::serialization::make_nvp("child", data.child); + } + template + void serialize(Archive& ar, const unsigned int file_version) + { boost::serialization::split_member(ar, *this, file_version); } +#endif + }; + // \endcond +#if defined(GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION) && \ + GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION + friend class boost::serialization::access; + template void save(Archive& ar, const unsigned) const { + int realspec = std::numeric_limits::digits * + (std::numeric_limits::is_integer ? -1 : 1); + // Need to use version1, otherwise load error in debug mode on Linux: + // undefined reference to GeographicLib::NearestNeighbor<...>::version. + int version1 = version; + ar & boost::serialization::make_nvp("version", version1) + & boost::serialization::make_nvp("realspec", realspec) + & boost::serialization::make_nvp("bucket", _bucket) + & boost::serialization::make_nvp("numpoints", _numpoints) + & boost::serialization::make_nvp("cost", _cost) + & boost::serialization::make_nvp("tree", _tree); + } + template void load(Archive& ar, const unsigned) { + int version1, realspec, bucket, numpoints, cost; + ar & boost::serialization::make_nvp("version", version1); + if (version1 != version) + throw GeographicLib::GeographicErr("Incompatible version"); + std::vector tree; + ar & boost::serialization::make_nvp("realspec", realspec); + if (!( realspec == std::numeric_limits::digits * + (std::numeric_limits::is_integer ? -1 : 1) )) + throw GeographicLib::GeographicErr("Different dist_t types"); + ar & boost::serialization::make_nvp("bucket", bucket); + if (!( 0 <= bucket && bucket <= maxbucket )) + throw GeographicLib::GeographicErr("Bad bucket size"); + ar & boost::serialization::make_nvp("numpoints", numpoints) + & boost::serialization::make_nvp("cost", cost) + & boost::serialization::make_nvp("tree", tree); + if (!( 0 <= int(tree.size()) && int(tree.size()) <= numpoints )) + throw + GeographicLib::GeographicErr("Bad number of points or tree size"); + for (int i = 0; i < int(tree.size()); ++i) + tree[i].Check(numpoints, int(tree.size()), bucket); + _tree.swap(tree); + _numpoints = numpoints; + _bucket = bucket; + _mc = _sc = 0; + _cost = cost; _c1 = _k = _cmax = 0; + _cmin = std::numeric_limits::max(); + } + template + void serialize(Archive& ar, const unsigned int file_version) + { boost::serialization::split_member(ar, *this, file_version); } +#endif + + int _numpoints, _bucket, _cost; + std::vector _tree; + // Counters to track stastistics on the cost of searches + mutable double _mc, _sc; + mutable int _c1, _k, _cmin, _cmax; + + int init(const std::vector& pts, const distfun_t& dist, int bucket, + std::vector& tree, std::vector& ids, int& cost, + int l, int u, int vp) { + + if (u == l) + return -1; + Node node; + + if (u - l > (bucket == 0 ? 1 : bucket)) { + + // choose a vantage point and move it to the start + int i = vp; + std::swap(ids[l], ids[i]); + + int m = (u + l + 1) / 2; + + for (int k = l + 1; k < u; ++k) { + ids[k].first = dist(pts[ids[l].second], pts[ids[k].second]); + ++cost; + } + // partition around the median distance + std::nth_element(ids.begin() + l + 1, + ids.begin() + m, + ids.begin() + u); + node.index = ids[l].second; + if (m > l + 1) { // node.child[0] is possibly empty + typename std::vector::iterator + t = std::min_element(ids.begin() + l + 1, ids.begin() + m); + node.data.lower[0] = t->first; + t = std::max_element(ids.begin() + l + 1, ids.begin() + m); + node.data.upper[0] = t->first; + // Use point with max distance as vantage point; this point act as a + // "corner" point and leads to a good partition. + node.data.child[0] = init(pts, dist, bucket, tree, ids, cost, + l + 1, m, int(t - ids.begin())); + } + typename std::vector::iterator + t = std::max_element(ids.begin() + m, ids.begin() + u); + node.data.lower[1] = ids[m].first; + node.data.upper[1] = t->first; + // Use point with max distance as vantage point here too + node.data.child[1] = init(pts, dist, bucket, tree, ids, cost, + m, u, int(t - ids.begin())); + } else { + if (bucket == 0) + node.index = ids[l].second; + else { + node.index = -1; + // Sort the bucket entries so that the tree is independent of the + // implementation of nth_element. + std::sort(ids.begin() + l, ids.begin() + u); + for (int i = l; i < u; ++i) + node.leaves[i-l] = ids[i].second; + for (int i = u - l; i < bucket; ++i) + node.leaves[i] = -1; + for (int i = bucket; i < maxbucket; ++i) + node.leaves[i] = 0; + } + } + + tree.push_back(node); + return int(tree.size()) - 1; + } + + }; + +} // namespace GeographicLib + +namespace std { + + /** + * Swap two GeographicLib::NearestNeighbor objects. + * + * @tparam dist_t the type used for measuring distances. + * @tparam pos_t the type for specifying the positions of points. + * @tparam distfun_t the type for a function object which calculates + * distances between points. + * @param[in,out] a the first GeographicLib::NearestNeighbor to swap. + * @param[in,out] b the second GeographicLib::NearestNeighbor to swap. + **********************************************************************/ + template + void swap(GeographicLib::NearestNeighbor& a, + GeographicLib::NearestNeighbor& b) { + a.swap(b); + } + +} // namespace std + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_NEARESTNEIGHBOR_HPP diff --git a/external/include/GeographicLib/NormalGravity.hpp b/external/include/GeographicLib/NormalGravity.hpp new file mode 100644 index 0000000..07aa88e --- /dev/null +++ b/external/include/GeographicLib/NormalGravity.hpp @@ -0,0 +1,400 @@ +/** + * \file NormalGravity.hpp + * \brief Header for GeographicLib::NormalGravity class + * + * Copyright (c) Charles Karney (2011-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_NORMALGRAVITY_HPP) +#define GEOGRAPHICLIB_NORMALGRAVITY_HPP 1 + +#include +#include + +namespace GeographicLib { + + /** + * \brief The normal gravity of the earth + * + * "Normal" gravity refers to an idealization of the earth which is modeled + * as an rotating ellipsoid. The eccentricity of the ellipsoid, the rotation + * speed, and the distribution of mass within the ellipsoid are such that the + * ellipsoid is a "level ellipoid", a surface of constant potential + * (gravitational plus centrifugal). The acceleration due to gravity is + * therefore perpendicular to the surface of the ellipsoid. + * + * Because the distribution of mass within the ellipsoid is unspecified, only + * the potential exterior to the ellipsoid is well defined. In this class, + * the mass is assumed to be to concentrated on a "focal disc" of radius, + * (a2b2)1/2, where + * \e a is the equatorial radius of the ellipsoid and \e b is its polar + * semi-axis. In the case of an oblate ellipsoid, the mass is concentrated + * on a "focal rod" of length 2(b2 − + * a2)1/2. As a result the potential is well + * defined everywhere. + * + * There is a closed solution to this problem which is implemented here. + * Series "approximations" are only used to evaluate certain combinations of + * elementary functions where use of the closed expression results in a loss + * of accuracy for small arguments due to cancellation of the leading terms. + * However these series include sufficient terms to give full machine + * precision. + * + * Although the formulation used in this class applies to ellipsoids with + * arbitrary flattening, in practice, its use should be limited to about + * b/\e a ∈ [0.01, 100] or \e f ∈ [−99, 0.99]. + * + * Definitions: + * - V0, the gravitational contribution to the normal + * potential; + * - Φ, the rotational contribution to the normal potential; + * - \e U = V0 + Φ, the total potential; + * - Γ = ∇V0, the acceleration due to + * mass of the earth; + * - f = ∇Φ, the centrifugal acceleration; + * - γ = ∇\e U = Γ + f, the normal + * acceleration; + * - \e X, \e Y, \e Z, geocentric coordinates; + * - \e x, \e y, \e z, local cartesian coordinates used to denote the east, + * north and up directions. + * + * References: + * - C. Somigliana, Teoria generale del campo gravitazionale dell'ellissoide + * di rotazione, Mem. Soc. Astron. Ital, 4, 541--599 (1929). + * - W. A. Heiskanen and H. Moritz, Physical Geodesy (Freeman, San + * Francisco, 1967), Secs. 1-19, 2-7, 2-8 (2-9, 2-10), 6-2 (6-3). + * - B. Hofmann-Wellenhof, H. Moritz, Physical Geodesy (Second edition, + * Springer, 2006) https://doi.org/10.1007/978-3-211-33545-1 + * - H. Moritz, Geodetic Reference System 1980, J. Geodesy 54(3), 395-405 + * (1980) https://doi.org/10.1007/BF02521480 + * + * For more information on normal gravity see \ref normalgravity. + * + * Example of use: + * \include example-NormalGravity.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT NormalGravity { + private: + static const int maxit_ = 20; + typedef Math::real real; + friend class GravityModel; + real _a, _GM, _omega, _f, _J2, _omega2, _aomega2; + real _e2, _ep2, _b, _E, _U0, _gammae, _gammap, _Q0, _k, _fstar; + Geocentric _earth; + static real atanzz(real x, bool alt) { + // This routine obeys the identity + // atanzz(x, alt) = atanzz(-x/(1+x), !alt) + // + // Require x >= -1. Best to call with alt, s.t. x >= 0; this results in + // a call to atan, instead of asin, or to asinh, instead of atanh. + using std::sqrt; using std::abs; using std::atan; using std::asin; + using std::asinh; using std::atanh; + real z = sqrt(abs(x)); + return x == 0 ? 1 : + (alt ? + (!(x < 0) ? asinh(z) : asin(z)) / sqrt(abs(x) / (1 + x)) : + (!(x < 0) ? atan(z) : atanh(z)) / z); + } + static real atan7series(real x); + static real atan5series(real x); + static real Qf(real x, bool alt); + static real Hf(real x, bool alt); + static real QH3f(real x, bool alt); + real Jn(int n) const; + void Initialize(real a, real GM, real omega, real f_J2, bool geometricp); + public: + + /** \name Setting up the normal gravity + **********************************************************************/ + ///@{ + /** + * Constructor for the normal gravity. + * + * @param[in] a equatorial radius (meters). + * @param[in] GM mass constant of the ellipsoid + * (meters3/seconds2); this is the product of \e G + * the gravitational constant and \e M the mass of the earth (usually + * including the mass of the earth's atmosphere). + * @param[in] omega the angular velocity (rad s−1). + * @param[in] f_J2 either the flattening of the ellipsoid \e f or the + * the dynamical form factor \e J2. + * @param[out] geometricp if true (the default), then \e f_J2 denotes the + * flattening, else it denotes the dynamical form factor \e J2. + * @exception if \e a is not positive or if the other parameters do not + * obey the restrictions given below. + * + * The shape of the ellipsoid can be given in one of two ways: + * - geometrically (\e geomtricp = true), the ellipsoid is defined by the + * flattening \e f = (\e a − \e b) / \e a, where \e a and \e b are + * the equatorial radius and the polar semi-axis. The parameters should + * obey \e a > 0, \e f < 1. There are no restrictions on \e GM or + * \e omega, in particular, \e GM need not be positive. + * - physically (\e geometricp = false), the ellipsoid is defined by the + * dynamical form factor J2 = (\e C − \e A) / + * Ma2, where \e A and \e C are the equatorial and + * polar moments of inertia and \e M is the mass of the earth. The + * parameters should obey \e a > 0, \e GM > 0 and \e J2 < 1/3 + * − (omega2a3/GM) + * 8/(45π). There is no restriction on \e omega. + **********************************************************************/ + NormalGravity(real a, real GM, real omega, real f_J2, + bool geometricp = true); + + /** + * A default constructor for the normal gravity. This sets up an + * uninitialized object and is used by GravityModel which constructs this + * object before it has read in the parameters for the reference ellipsoid. + **********************************************************************/ + NormalGravity() : _a(-1) {} + ///@} + + /** \name Compute the gravity + **********************************************************************/ + ///@{ + /** + * Evaluate the gravity on the surface of the ellipsoid. + * + * @param[in] lat the geographic latitude (degrees). + * @return γ the acceleration due to gravity, positive downwards + * (m s−2). + * + * Due to the axial symmetry of the ellipsoid, the result is independent of + * the value of the longitude. This acceleration is perpendicular to the + * surface of the ellipsoid. It includes the effects of the earth's + * rotation. + **********************************************************************/ + Math::real SurfaceGravity(real lat) const; + + /** + * Evaluate the gravity at an arbitrary point above (or below) the + * ellipsoid. + * + * @param[in] lat the geographic latitude (degrees). + * @param[in] h the height above the ellipsoid (meters). + * @param[out] gammay the northerly component of the acceleration + * (m s−2). + * @param[out] gammaz the upward component of the acceleration + * (m s−2); this is usually negative. + * @return \e U the corresponding normal potential + * (m2 s−2). + * + * Due to the axial symmetry of the ellipsoid, the result is independent of + * the value of the longitude and the easterly component of the + * acceleration vanishes, \e gammax = 0. The function includes the effects + * of the earth's rotation. When \e h = 0, this function gives \e gammay = + * 0 and the returned value matches that of NormalGravity::SurfaceGravity. + **********************************************************************/ + Math::real Gravity(real lat, real h, real& gammay, real& gammaz) + const; + + /** + * Evaluate the components of the acceleration due to gravity and the + * centrifugal acceleration in geocentric coordinates. + * + * @param[in] X geocentric coordinate of point (meters). + * @param[in] Y geocentric coordinate of point (meters). + * @param[in] Z geocentric coordinate of point (meters). + * @param[out] gammaX the \e X component of the acceleration + * (m s−2). + * @param[out] gammaY the \e Y component of the acceleration + * (m s−2). + * @param[out] gammaZ the \e Z component of the acceleration + * (m s−2). + * @return \e U = V0 + Φ the sum of the + * gravitational and centrifugal potentials + * (m2 s−2). + * + * The acceleration given by γ = ∇\e U = + * ∇V0 + ∇Φ = Γ + f. + **********************************************************************/ + Math::real U(real X, real Y, real Z, + real& gammaX, real& gammaY, real& gammaZ) const; + + /** + * Evaluate the components of the acceleration due to the gravitational + * force in geocentric coordinates. + * + * @param[in] X geocentric coordinate of point (meters). + * @param[in] Y geocentric coordinate of point (meters). + * @param[in] Z geocentric coordinate of point (meters). + * @param[out] GammaX the \e X component of the acceleration due to the + * gravitational force (m s−2). + * @param[out] GammaY the \e Y component of the acceleration due to the + * @param[out] GammaZ the \e Z component of the acceleration due to the + * gravitational force (m s−2). + * @return V0 the gravitational potential + * (m2 s−2). + * + * This function excludes the centrifugal acceleration and is appropriate + * to use for space applications. In terrestrial applications, the + * function NormalGravity::U (which includes this effect) should usually be + * used. + **********************************************************************/ + Math::real V0(real X, real Y, real Z, + real& GammaX, real& GammaY, real& GammaZ) const; + + /** + * Evaluate the centrifugal acceleration in geocentric coordinates. + * + * @param[in] X geocentric coordinate of point (meters). + * @param[in] Y geocentric coordinate of point (meters). + * @param[out] fX the \e X component of the centrifugal acceleration + * (m s−2). + * @param[out] fY the \e Y component of the centrifugal acceleration + * (m s−2). + * @return Φ the centrifugal potential (m2 + * s−2). + * + * Φ is independent of \e Z, thus \e fZ = 0. This function + * NormalGravity::U sums the results of NormalGravity::V0 and + * NormalGravity::Phi. + **********************************************************************/ + Math::real Phi(real X, real Y, real& fX, real& fY) const; + ///@} + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return true if the object has been initialized. + **********************************************************************/ + bool Init() const { return _a > 0; } + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const + { return Init() ? _a : Math::NaN(); } + + /** + * @return \e GM the mass constant of the ellipsoid + * (m3 s−2). This is the value used in the + * constructor. + **********************************************************************/ + Math::real MassConstant() const + { return Init() ? _GM : Math::NaN(); } + + /** + * @return Jn the dynamical form factors of the + * ellipsoid. + * + * If \e n = 2 (the default), this is the value of J2 + * used in the constructor. Otherwise it is the zonal coefficient of the + * Legendre harmonic sum of the normal gravitational potential. Note that + * Jn = 0 if \e n is odd. In most gravity + * applications, fully normalized Legendre functions are used and the + * corresponding coefficient is Cn0 = + * −Jn / sqrt(2 \e n + 1). + **********************************************************************/ + Math::real DynamicalFormFactor(int n = 2) const + { return Init() ? ( n == 2 ? _J2 : Jn(n)) : Math::NaN(); } + + /** + * @return ω the angular velocity of the ellipsoid (rad + * s−1). This is the value used in the constructor. + **********************************************************************/ + Math::real AngularVelocity() const + { return Init() ? _omega : Math::NaN(); } + + /** + * @return f the flattening of the ellipsoid (\e a − \e b)/\e + * a. + **********************************************************************/ + Math::real Flattening() const + { return Init() ? _f : Math::NaN(); } + + /** + * @return γe the normal gravity at equator (m + * s−2). + **********************************************************************/ + Math::real EquatorialGravity() const + { return Init() ? _gammae : Math::NaN(); } + + /** + * @return γp the normal gravity at poles (m + * s−2). + **********************************************************************/ + Math::real PolarGravity() const + { return Init() ? _gammap : Math::NaN(); } + + /** + * @return f* the gravity flattening (γp − + * γe) / γe. + **********************************************************************/ + Math::real GravityFlattening() const + { return Init() ? _fstar : Math::NaN(); } + + /** + * @return U0 the constant normal potential for the + * surface of the ellipsoid (m2 s−2). + **********************************************************************/ + Math::real SurfacePotential() const + { return Init() ? _U0 : Math::NaN(); } + + /** + * @return the Geocentric object used by this instance. + **********************************************************************/ + const Geocentric& Earth() const { return _earth; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of NormalGravity for the WGS84 ellipsoid. + **********************************************************************/ + static const NormalGravity& WGS84(); + + /** + * A global instantiation of NormalGravity for the GRS80 ellipsoid. + **********************************************************************/ + static const NormalGravity& GRS80(); + + /** + * Compute the flattening from the dynamical form factor. + * + * @param[in] a equatorial radius (meters). + * @param[in] GM mass constant of the ellipsoid + * (meters3/seconds2); this is the product of \e G + * the gravitational constant and \e M the mass of the earth (usually + * including the mass of the earth's atmosphere). + * @param[in] omega the angular velocity (rad s−1). + * @param[in] J2 the dynamical form factor. + * @return \e f the flattening of the ellipsoid. + * + * This routine requires \e a > 0, \e GM > 0, \e J2 < 1/3 − + * omega2a3/GM 8/(45π). A + * NaN is returned if these conditions do not hold. The restriction to + * positive \e GM is made because for negative \e GM two solutions are + * possible. + **********************************************************************/ + static Math::real J2ToFlattening(real a, real GM, real omega, real J2); + + /** + * Compute the dynamical form factor from the flattening. + * + * @param[in] a equatorial radius (meters). + * @param[in] GM mass constant of the ellipsoid + * (meters3/seconds2); this is the product of \e G + * the gravitational constant and \e M the mass of the earth (usually + * including the mass of the earth's atmosphere). + * @param[in] omega the angular velocity (rad s−1). + * @param[in] f the flattening of the ellipsoid. + * @return \e J2 the dynamical form factor. + * + * This routine requires \e a > 0, \e GM ≠ 0, \e f < 1. The + * values of these parameters are not checked. + **********************************************************************/ + static Math::real FlatteningToJ2(real a, real GM, real omega, real f); + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_NORMALGRAVITY_HPP diff --git a/external/include/GeographicLib/OSGB.hpp b/external/include/GeographicLib/OSGB.hpp new file mode 100644 index 0000000..c2e7797 --- /dev/null +++ b/external/include/GeographicLib/OSGB.hpp @@ -0,0 +1,255 @@ +/** + * \file OSGB.hpp + * \brief Header for GeographicLib::OSGB class + * + * Copyright (c) Charles Karney (2010-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_OSGB_HPP) +#define GEOGRAPHICLIB_OSGB_HPP 1 + +#include +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs string +# pragma warning (push) +# pragma warning (disable: 4251) +#endif + +namespace GeographicLib { + + /** + * \brief Ordnance Survey grid system for Great Britain + * + * The class implements the coordinate system used by the Ordnance Survey for + * maps of Great Britain and conversions to the grid reference system. + * + * See + * - + * A guide to coordinate systems in Great Britain + * - + * Guide to the National Grid + * + * \warning the latitudes and longitudes for the Ordnance Survey grid + * system do not use the WGS84 datum. Do not use the values returned by this + * class in the UTMUPS, MGRS, or Geoid classes without first converting the + * datum (and vice versa). + * + * Example of use: + * \include example-OSGB.cpp + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT OSGB { + private: + typedef Math::real real; + static const char* const letters_; + static const char* const digits_; + static const TransverseMercator& OSGBTM(); + enum { + base_ = 10, + tile_ = 100000, + tilelevel_ = 5, + tilegrid_ = 5, + tileoffx_ = 2 * tilegrid_, + tileoffy_ = 1 * tilegrid_, + minx_ = - tileoffx_ * tile_, + miny_ = - tileoffy_ * tile_, + maxx_ = (tilegrid_*tilegrid_ - tileoffx_) * tile_, + maxy_ = (tilegrid_*tilegrid_ - tileoffy_) * tile_, + // Maximum precision is um + maxprec_ = 5 + 6, + }; + static real computenorthoffset(); + static void CheckCoords(real x, real y); + OSGB(); // Disable constructor + public: + + /** + * Forward projection, from geographic to OSGB coordinates. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * \e lat should be in the range [−90°, 90°]. + **********************************************************************/ + static void Forward(real lat, real lon, + real& x, real& y, real& gamma, real& k) { + OSGBTM().Forward(OriginLongitude(), lat, lon, x, y, gamma, k); + x += FalseEasting(); + y += computenorthoffset(); + } + + /** + * Reverse projection, from OSGB coordinates to geographic. + * + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * The value of \e lon returned is in the range [−180°, + * 180°]. + **********************************************************************/ + + static void Reverse(real x, real y, + real& lat, real& lon, real& gamma, real& k) { + x -= FalseEasting(); + y -= computenorthoffset(); + OSGBTM().Reverse(OriginLongitude(), x, y, lat, lon, gamma, k); + } + + /** + * OSGB::Forward without returning the convergence and scale. + **********************************************************************/ + static void Forward(real lat, real lon, real& x, real& y) { + real gamma, k; + Forward(lat, lon, x, y, gamma, k); + } + + /** + * OSGB::Reverse without returning the convergence and scale. + **********************************************************************/ + static void Reverse(real x, real y, real& lat, real& lon) { + real gamma, k; + Reverse(x, y, lat, lon, gamma, k); + } + + /** + * Convert OSGB coordinates to a grid reference. + * + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[in] prec precision relative to 100 km. + * @param[out] gridref National Grid reference. + * @exception GeographicErr if \e prec, \e x, or \e y is outside its + * allowed range. + * @exception std::bad_alloc if the memory for \e gridref can't be + * allocatied. + * + * \e prec specifies the precision of the grid reference string as follows: + * - prec = 0 (min), 100km + * - prec = 1, 10km + * - prec = 2, 1km + * - prec = 3, 100m + * - prec = 4, 10m + * - prec = 5, 1m + * - prec = 6, 0.1m + * - prec = 11 (max), 1μm + * + * The easting must be in the range [−1000 km, 1500 km) and the + * northing must be in the range [−500 km, 2000 km). These bounds + * are consistent with rules for the letter designations for the grid + * system. + * + * If \e x or \e y is NaN, the returned grid reference is "INVALID". + **********************************************************************/ + static void GridReference(real x, real y, int prec, std::string& gridref); + + /** + * Convert OSGB coordinates to a grid reference. + * + * @param[in] gridref National Grid reference. + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] prec precision relative to 100 km. + * @param[in] centerp if true (default), return center of the grid square, + * else return SW (lower left) corner. + * @exception GeographicErr if \e gridref is illegal. + * + * The grid reference must be of the form: two letters (not including I) + * followed by an even number of digits (up to 22). + * + * If the first 2 characters of \e gridref are "IN", then \e x and \e y are + * set to NaN and \e prec is set to −2. + **********************************************************************/ + static void GridReference(const std::string& gridref, + real& x, real& y, int& prec, + bool centerp = true); + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the Airy 1830 ellipsoid (meters). + * + * This is 20923713 ft converted to meters using the rule 1 ft = + * 109.48401603−10 m. The Airy 1830 value is returned + * because the OSGB projection is based on this ellipsoid. The conversion + * factor from feet to meters is the one used for the 1936 retriangulation + * of Britain; see Section A.1 (p. 37) of A guide to coordinate systems + * in Great Britain, v2.2 (Dec. 2013). + **********************************************************************/ + static Math::real EquatorialRadius() { + // result is about 6377563.3960320664406 m + using std::pow; + return pow(real(10), real(48401603 - 100000000) / 100000000) + * real(20923713); + } + + /** + * @return \e f the inverse flattening of the Airy 1830 ellipsoid. + * + * For the Airy 1830 ellipsoid, \e a = 20923713 ft and \e b = 20853810 ft; + * thus the flattening = (20923713 − 20853810)/20923713 = + * 7767/2324857 = 1/299.32496459... (The Airy 1830 value is returned + * because the OSGB projection is based on this ellipsoid.) + **********************************************************************/ + static Math::real Flattening() + { return real(20923713 - 20853810) / real(20923713); } + + /** + * @return \e k0 central scale for the OSGB projection (0.9996012717...). + * + * C. J. Mugnier, Grids & Datums, PE&RS, Oct. 2003, states that + * this is defined as 109.9998268−10. + **********************************************************************/ + static Math::real CentralScale() { + using std::pow; + return pow(real(10), real(9998268 - 10000000) / 10000000); + } + + /** + * @return latitude of the origin for the OSGB projection (49 degrees). + **********************************************************************/ + static Math::real OriginLatitude() { return real(49); } + + /** + * @return longitude of the origin for the OSGB projection (−2 + * degrees). + **********************************************************************/ + static Math::real OriginLongitude() { return real(-2); } + + /** + * @return false northing the OSGB projection (−100000 meters). + **********************************************************************/ + static Math::real FalseNorthing() { return real(-100000); } + + /** + * @return false easting the OSGB projection (400000 meters). + **********************************************************************/ + static Math::real FalseEasting() { return real(400000); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + static Math::real MajorRadius() { return EquatorialRadius(); } + ///@} + + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_OSGB_HPP diff --git a/external/include/GeographicLib/PolarStereographic.hpp b/external/include/GeographicLib/PolarStereographic.hpp new file mode 100644 index 0000000..e828706 --- /dev/null +++ b/external/include/GeographicLib/PolarStereographic.hpp @@ -0,0 +1,160 @@ +/** + * \file PolarStereographic.hpp + * \brief Header for GeographicLib::PolarStereographic class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP) +#define GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP 1 + +#include + +namespace GeographicLib { + + /** + * \brief Polar stereographic projection + * + * Implementation taken from the report, + * - J. P. Snyder, + * Map Projections: A + * Working Manual, USGS Professional Paper 1395 (1987), + * pp. 160--163. + * + * This is a straightforward implementation of the equations in Snyder except + * that Newton's method is used to invert the projection. + * + * This class also returns the meridian convergence \e gamma and scale \e k. + * The meridian convergence is the bearing of grid north (the \e y axis) + * measured clockwise from true north. + * + * Example of use: + * \include example-PolarStereographic.cpp + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT PolarStereographic { + private: + typedef Math::real real; + real _a, _f, _e2, _es, _e2m, _c; + real _k0; + public: + + /** + * Constructor for a ellipsoid with + * + * @param[in] a equatorial radius (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @param[in] k0 central scale factor. + * @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k0 is + * not positive. + **********************************************************************/ + PolarStereographic(real a, real f, real k0); + + /** + * Set the scale for the projection. + * + * @param[in] lat (degrees) assuming \e northp = true. + * @param[in] k scale at latitude \e lat (default 1). + * @exception GeographicErr \e k is not positive. + * @exception GeographicErr if \e lat is not in (−90°, + * 90°]. + **********************************************************************/ + void SetScale(real lat, real k = real(1)); + + /** + * Forward projection, from geographic to polar stereographic. + * + * @param[in] northp the pole which is the center of projection (true means + * north, false means south). + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * No false easting or northing is added. \e lat should be in the range + * (−90°, 90°] for \e northp = true and in the range + * [−90°, 90°) for \e northp = false. + **********************************************************************/ + void Forward(bool northp, real lat, real lon, + real& x, real& y, real& gamma, real& k) const; + + /** + * Reverse projection, from polar stereographic to geographic. + * + * @param[in] northp the pole which is the center of projection (true means + * north, false means south). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * No false easting or northing is added. The value of \e lon returned is + * in the range [−180°, 180°]. + **********************************************************************/ + void Reverse(bool northp, real x, real y, + real& lat, real& lon, real& gamma, real& k) const; + + /** + * PolarStereographic::Forward without returning the convergence and scale. + **********************************************************************/ + void Forward(bool northp, real lat, real lon, + real& x, real& y) const { + real gamma, k; + Forward(northp, lat, lon, x, y, gamma, k); + } + + /** + * PolarStereographic::Reverse without returning the convergence and scale. + **********************************************************************/ + void Reverse(bool northp, real x, real y, + real& lat, real& lon) const { + real gamma, k; + Reverse(northp, x, y, lat, lon, gamma, k); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _a; } + + /** + * @return \e f the flattening of the ellipsoid. This is the value used in + * the constructor. + **********************************************************************/ + Math::real Flattening() const { return _f; } + + /** + * The central scale for the projection. This is the value of \e k0 used + * in the constructor and is the scale at the pole unless overridden by + * PolarStereographic::SetScale. + **********************************************************************/ + Math::real CentralScale() const { return _k0; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of PolarStereographic with the WGS84 ellipsoid + * and the UPS scale factor. However, unlike UPS, no false easting or + * northing is added. + **********************************************************************/ + static const PolarStereographic& UPS(); + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP diff --git a/external/include/GeographicLib/PolygonArea.hpp b/external/include/GeographicLib/PolygonArea.hpp new file mode 100644 index 0000000..f94b32c --- /dev/null +++ b/external/include/GeographicLib/PolygonArea.hpp @@ -0,0 +1,325 @@ +/** + * \file PolygonArea.hpp + * \brief Header for GeographicLib::PolygonAreaT class + * + * Copyright (c) Charles Karney (2010-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_POLYGONAREA_HPP) +#define GEOGRAPHICLIB_POLYGONAREA_HPP 1 + +#include +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief Polygon areas + * + * This computes the area of a polygon whose edges are geodesics using the + * method given in Section 6 of + * - C. F. F. Karney, + * + * Algorithms for geodesics, + * J. Geodesy 87, 43--55 (2013); + * DOI: + * 10.1007/s00190-012-0578-z; + * addenda: + * + * geod-addenda.html. + * + * Arbitrarily complex polygons are allowed. In the case self-intersecting + * of polygons the area is accumulated "algebraically", e.g., the areas of + * the 2 loops in a figure-8 polygon will partially cancel. + * + * This class lets you add vertices and edges one at a time to the polygon. + * The sequence must start with a vertex and thereafter vertices and edges + * can be added in any order. Any vertex after the first creates a new edge + * which is the \e shortest geodesic from the previous vertex. In some + * cases there may be two or many such shortest geodesics and the area is + * then not uniquely defined. In this case, either add an intermediate + * vertex or add the edge \e as an edge (by defining its direction and + * length). + * + * The area and perimeter are accumulated at two times the standard floating + * point precision to guard against the loss of accuracy with many-sided + * polygons. At any point you can ask for the perimeter and area so far. + * There's an option to treat the points as defining a polyline instead of a + * polygon; in that case, only the perimeter is computed. + * + * This is a templated class to allow it to be used with Geodesic, + * GeodesicExact, and Rhumb. GeographicLib::PolygonArea, + * GeographicLib::PolygonAreaExact, and GeographicLib::PolygonAreaRhumb are + * typedefs for these cases. + * + * For GeographicLib::PolygonArea (edges defined by Geodesic), an upper bound + * on the error is about 0.1 m2 per vertex. However this is a + * wildly pessimistic estimate in most cases. A more realistic estimate of + * the error is given by a test involving 107 approximately + * regular polygons on the WGS84 ellipsoid. The centers and the orientations + * of the polygons were uniformly distributed, the number of vertices was + * log-uniformly distributed in [3, 300], and the center to vertex distance + * log-uniformly distributed in [0.1 m, 9000 km]. + * + * Using double precision (the standard precision for GeographicLib), the + * maximum error in the perimeter was 200 nm, and the maximum error in the + * area was
+   *     0.0013 m^2 for perimeter < 10 km
+   *     0.0070 m^2 for perimeter < 100 km
+   *     0.070 m^2 for perimeter < 1000 km
+   *     0.11 m^2 for all perimeters
+   * 
+ * The errors are given in terms of the perimeter, because it is expected + * that the errors depend mainly on the number of edges and the edge lengths. + * + * Using long doubles (GEOGRPAHICLIB_PRECISION = 3), the maximum error in the + * perimeter was 200 pm, and the maximum error in the area was
+   *     0.7 mm^2 for perim < 10 km
+   *     3.2 mm^2 for perimeter < 100 km
+   *     21 mm^2 for perimeter < 1000 km
+   *     45 mm^2 for all perimeters
+   * 
+ * + * @tparam GeodType the geodesic class to use. + * + * Example of use: + * \include example-PolygonArea.cpp + * + * Planimeter is a command-line utility + * providing access to the functionality of PolygonAreaT. + **********************************************************************/ + + template + class PolygonAreaT { + private: + typedef Math::real real; + GeodType _earth; + real _area0; // Full ellipsoid area + bool _polyline; // Assume polyline (don't close and skip area) + unsigned _mask; + unsigned _num; + int _crossings; + Accumulator<> _areasum, _perimetersum; + real _lat0, _lon0, _lat1, _lon1; + static int transit(real lon1, real lon2) { + // Return 1 or -1 if crossing prime meridian in east or west direction. + // Otherwise return zero. + // Compute lon12 the same way as Geodesic::Inverse. + lon1 = Math::AngNormalize(lon1); + lon2 = Math::AngNormalize(lon2); + real lon12 = Math::AngDiff(lon1, lon2); + // Treat 0 as negative in these tests. This balances +/- 180 being + // treated as positive, i.e., +180. + int cross = + lon1 <= 0 && lon2 > 0 && lon12 > 0 ? 1 : + (lon2 <= 0 && lon1 > 0 && lon12 < 0 ? -1 : 0); + return cross; + } + // an alternate version of transit to deal with longitudes in the direct + // problem. + static int transitdirect(real lon1, real lon2) { + // Compute exactly the parity of + // int(ceil(lon2 / 360)) - int(ceil(lon1 / 360)) + using std::remainder; + lon1 = remainder(lon1, real(720)); + lon2 = remainder(lon2, real(720)); + return ( (lon2 <= 0 && lon2 > -360 ? 1 : 0) - + (lon1 <= 0 && lon1 > -360 ? 1 : 0) ); + } + void Remainder(Accumulator<>& a) const { a.remainder(_area0); } + void Remainder(real& a) const { + using std::remainder; + a = remainder(a, _area0); + } + template + void AreaReduce(T& area, int crossings, bool reverse, bool sign) const; + public: + + /** + * Constructor for PolygonAreaT. + * + * @param[in] earth the Geodesic object to use for geodesic calculations. + * @param[in] polyline if true that treat the points as defining a polyline + * instead of a polygon (default = false). + **********************************************************************/ + PolygonAreaT(const GeodType& earth, bool polyline = false) + : _earth(earth) + , _area0(_earth.EllipsoidArea()) + , _polyline(polyline) + , _mask(GeodType::LATITUDE | GeodType::LONGITUDE | GeodType::DISTANCE | + (_polyline ? GeodType::NONE : + GeodType::AREA | GeodType::LONG_UNROLL)) + { Clear(); } + + /** + * Clear PolygonAreaT, allowing a new polygon to be started. + **********************************************************************/ + void Clear() { + _num = 0; + _crossings = 0; + _areasum = 0; + _perimetersum = 0; + _lat0 = _lon0 = _lat1 = _lon1 = Math::NaN(); + } + + /** + * Add a point to the polygon or polyline. + * + * @param[in] lat the latitude of the point (degrees). + * @param[in] lon the longitude of the point (degrees). + * + * \e lat should be in the range [−90°, 90°]. + **********************************************************************/ + void AddPoint(real lat, real lon); + + /** + * Add an edge to the polygon or polyline. + * + * @param[in] azi azimuth at current point (degrees). + * @param[in] s distance from current point to next point (meters). + * + * This does nothing if no points have been added yet. Use + * PolygonAreaT::CurrentPoint to determine the position of the new vertex. + **********************************************************************/ + void AddEdge(real azi, real s); + + /** + * Return the results so far. + * + * @param[in] reverse if true then clockwise (instead of counter-clockwise) + * traversal counts as a positive area. + * @param[in] sign if true then return a signed result for the area if + * the polygon is traversed in the "wrong" direction instead of returning + * the area for the rest of the earth. + * @param[out] perimeter the perimeter of the polygon or length of the + * polyline (meters). + * @param[out] area the area of the polygon (meters2); only set + * if \e polyline is false in the constructor. + * @return the number of points. + * + * More points can be added to the polygon after this call. + **********************************************************************/ + unsigned Compute(bool reverse, bool sign, + real& perimeter, real& area) const; + + /** + * Return the results assuming a tentative final test point is added; + * however, the data for the test point is not saved. This lets you report + * a running result for the perimeter and area as the user moves the mouse + * cursor. Ordinary floating point arithmetic is used to accumulate the + * data for the test point; thus the area and perimeter returned are less + * accurate than if PolygonAreaT::AddPoint and PolygonAreaT::Compute are + * used. + * + * @param[in] lat the latitude of the test point (degrees). + * @param[in] lon the longitude of the test point (degrees). + * @param[in] reverse if true then clockwise (instead of counter-clockwise) + * traversal counts as a positive area. + * @param[in] sign if true then return a signed result for the area if + * the polygon is traversed in the "wrong" direction instead of returning + * the area for the rest of the earth. + * @param[out] perimeter the approximate perimeter of the polygon or length + * of the polyline (meters). + * @param[out] area the approximate area of the polygon + * (meters2); only set if polyline is false in the + * constructor. + * @return the number of points. + * + * \e lat should be in the range [−90°, 90°]. + **********************************************************************/ + unsigned TestPoint(real lat, real lon, bool reverse, bool sign, + real& perimeter, real& area) const; + + /** + * Return the results assuming a tentative final test point is added via an + * azimuth and distance; however, the data for the test point is not saved. + * This lets you report a running result for the perimeter and area as the + * user moves the mouse cursor. Ordinary floating point arithmetic is used + * to accumulate the data for the test point; thus the area and perimeter + * returned are less accurate than if PolygonAreaT::AddEdge and + * PolygonAreaT::Compute are used. + * + * @param[in] azi azimuth at current point (degrees). + * @param[in] s distance from current point to final test point (meters). + * @param[in] reverse if true then clockwise (instead of counter-clockwise) + * traversal counts as a positive area. + * @param[in] sign if true then return a signed result for the area if + * the polygon is traversed in the "wrong" direction instead of returning + * the area for the rest of the earth. + * @param[out] perimeter the approximate perimeter of the polygon or length + * of the polyline (meters). + * @param[out] area the approximate area of the polygon + * (meters2); only set if polyline is false in the + * constructor. + * @return the number of points. + **********************************************************************/ + unsigned TestEdge(real azi, real s, bool reverse, bool sign, + real& perimeter, real& area) const; + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value inherited from the Geodesic object used in the constructor. + **********************************************************************/ + + Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the Geodesic object used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _earth.Flattening(); } + + /** + * Report the previous vertex added to the polygon or polyline. + * + * @param[out] lat the latitude of the point (degrees). + * @param[out] lon the longitude of the point (degrees). + * + * If no points have been added, then NaNs are returned. Otherwise, \e lon + * will be in the range [−180°, 180°]. + **********************************************************************/ + void CurrentPoint(real& lat, real& lon) const + { lat = _lat1; lon = _lon1; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + }; + + /** + * @relates PolygonAreaT + * + * Polygon areas using Geodesic. This should be used if the flattening is + * small. + **********************************************************************/ + typedef PolygonAreaT PolygonArea; + + /** + * @relates PolygonAreaT + * + * Polygon areas using GeodesicExact. (But note that the implementation of + * areas in GeodesicExact uses a high order series and this is only accurate + * for modest flattenings.) + **********************************************************************/ + typedef PolygonAreaT PolygonAreaExact; + + /** + * @relates PolygonAreaT + * + * Polygon areas using Rhumb. + **********************************************************************/ + typedef PolygonAreaT PolygonAreaRhumb; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_POLYGONAREA_HPP diff --git a/external/include/GeographicLib/Rhumb.hpp b/external/include/GeographicLib/Rhumb.hpp new file mode 100644 index 0000000..0cb8afd --- /dev/null +++ b/external/include/GeographicLib/Rhumb.hpp @@ -0,0 +1,621 @@ +/** + * \file Rhumb.hpp + * \brief Header for GeographicLib::Rhumb and GeographicLib::RhumbLine classes + * + * Copyright (c) Charles Karney (2014-2021) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_RHUMB_HPP) +#define GEOGRAPHICLIB_RHUMB_HPP 1 + +#include +#include + +#if !defined(GEOGRAPHICLIB_RHUMBAREA_ORDER) +/** + * The order of the series approximation used in rhumb area calculations. + * GEOGRAPHICLIB_RHUMBAREA_ORDER can be set to any integer in [4, 8]. + **********************************************************************/ +# define GEOGRAPHICLIB_RHUMBAREA_ORDER \ + (GEOGRAPHICLIB_PRECISION == 2 ? 6 : \ + (GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8)) +#endif + +namespace GeographicLib { + + class RhumbLine; + template class PolygonAreaT; + + /** + * \brief Solve of the direct and inverse rhumb problems. + * + * The path of constant azimuth between two points on a ellipsoid at (\e + * lat1, \e lon1) and (\e lat2, \e lon2) is called the rhumb line (also + * called the loxodrome). Its length is \e s12 and its azimuth is \e azi12. + * (The azimuth is the heading measured clockwise from north.) + * + * Given \e lat1, \e lon1, \e azi12, and \e s12, we can determine \e lat2, + * and \e lon2. This is the \e direct rhumb problem and its solution is + * given by the function Rhumb::Direct. + * + * Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi12 + * and \e s12. This is the \e inverse rhumb problem, whose solution is given + * by Rhumb::Inverse. This finds the shortest such rhumb line, i.e., the one + * that wraps no more than half way around the earth. If the end points are + * on opposite meridians, there are two shortest rhumb lines and the + * east-going one is chosen. + * + * These routines also optionally calculate the area under the rhumb line, \e + * S12. This is the area, measured counter-clockwise, of the rhumb line + * quadrilateral with corners (lat1,lon1), (0,lon1), + * (0,lon2), and (lat2,lon2). + * + * Note that rhumb lines may be appreciably longer (up to 50%) than the + * corresponding Geodesic. For example the distance between London Heathrow + * and Tokyo Narita via the rhumb line is 11400 km which is 18% longer than + * the geodesic distance 9600 km. + * + * For more information on rhumb lines see \ref rhumb. + * + * Example of use: + * \include example-Rhumb.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT Rhumb { + private: + typedef Math::real real; + friend class RhumbLine; + template friend class PolygonAreaT; + Ellipsoid _ell; + bool _exact; + real _c2; + static const int tm_maxord = GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER; + static const int maxpow_ = GEOGRAPHICLIB_RHUMBAREA_ORDER; + // _R[0] unused + real _R[maxpow_ + 1]; + static real gd(real x) + { using std::atan; using std::sinh; return atan(sinh(x)); } + + // Use divided differences to determine (mu2 - mu1) / (psi2 - psi1) + // accurately + // + // Definition: Df(x,y,d) = (f(x) - f(y)) / (x - y) + // See: + // W. M. Kahan and R. J. Fateman, + // Symbolic computation of divided differences, + // SIGSAM Bull. 33(3), 7-28 (1999) + // https://doi.org/10.1145/334714.334716 + // http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf + + static real Dlog(real x, real y) { + using std::sqrt; using std::asinh; + real t = x - y; + // Change + // + // atanh(t / (x + y)) + // + // to + // + // asinh(t / (2 * sqrt(x*y))) + // + // to avoid taking atanh(1) when x is large and y is 1. N.B., this + // routine is invoked with positive x and y, so no need to guard against + // taking the sqrt of a negative quantity. This fixes bogus results for + // the area being returning when an endpoint is at a pole. + return t != 0 ? 2 * asinh(t / (2 * sqrt(x*y))) / t : 1 / x; + } + // N.B., x and y are in degrees + static real Dtan(real x, real y) { + real d = x - y, tx = Math::tand(x), ty = Math::tand(y), txy = tx * ty; + return d != 0 ? + (2 * txy > -1 ? (1 + txy) * Math::tand(d) : tx - ty) / + (d * Math::degree()) : + 1 + txy; + } + static real Datan(real x, real y) { + using std::atan; + real d = x - y, xy = x * y; + return d != 0 ? + (2 * xy > -1 ? atan( d / (1 + xy) ) : atan(x) - atan(y)) / d : + 1 / (1 + xy); + } + static real Dsin(real x, real y) { + using std::sin; using std::cos; + real d = (x - y) / 2; + return cos((x + y)/2) * (d != 0 ? sin(d) / d : 1); + } + static real Dsinh(real x, real y) { + using std::sinh; using std::cosh; + real d = (x - y) / 2; + return cosh((x + y) / 2) * (d != 0 ? sinh(d) / d : 1); + } + static real Dcosh(real x, real y) { + using std::sinh; + real d = (x - y) / 2; + return sinh((x + y) / 2) * (d != 0 ? sinh(d) / d : 1); + } + static real Dasinh(real x, real y) { + using std::asinh; using std::hypot; + real d = x - y, + hx = hypot(real(1), x), hy = hypot(real(1), y); + return d != 0 ? + asinh(x*y > 0 ? d * (x + y) / (x*hy + y*hx) : x*hy - y*hx) / d : + 1 / hx; + } + static real Dgd(real x, real y) { + using std::sinh; + return Datan(sinh(x), sinh(y)) * Dsinh(x, y); + } + // N.B., x and y are the tangents of the angles + static real Dgdinv(real x, real y) + { return Dasinh(x, y) / Datan(x, y); } + // Copied from LambertConformalConic... + // Deatanhe(x,y) = eatanhe((x-y)/(1-e^2*x*y))/(x-y) + real Deatanhe(real x, real y) const { + real t = x - y, d = 1 - _ell._e2 * x * y; + return t != 0 ? Math::eatanhe(t / d, _ell._es) / t : _ell._e2 / d; + } + // (E(x) - E(y)) / (x - y) -- E = incomplete elliptic integral of 2nd kind + real DE(real x, real y) const; + // (mux - muy) / (phix - phiy) using elliptic integrals + real DRectifying(real latx, real laty) const; + // (psix - psiy) / (phix - phiy) + real DIsometric(real latx, real laty) const; + + // (sum(c[j]*sin(2*j*x),j=1..n) - sum(c[j]*sin(2*j*x),j=1..n)) / (x - y) + static real SinCosSeries(bool sinp, + real x, real y, const real c[], int n); + // (mux - muy) / (chix - chiy) using Krueger's series + real DConformalToRectifying(real chix, real chiy) const; + // (chix - chiy) / (mux - muy) using Krueger's series + real DRectifyingToConformal(real mux, real muy) const; + + // (mux - muy) / (psix - psiy) + // N.B., psix and psiy are in degrees + real DIsometricToRectifying(real psix, real psiy) const; + // (psix - psiy) / (mux - muy) + real DRectifyingToIsometric(real mux, real muy) const; + + real MeanSinXi(real psi1, real psi2) const; + + // The following two functions (with lots of ignored arguments) mimic the + // interface to the corresponding Geodesic function. These are needed by + // PolygonAreaT. + void GenDirect(real lat1, real lon1, real azi12, + bool, real s12, unsigned outmask, + real& lat2, real& lon2, real&, real&, real&, real&, real&, + real& S12) const { + GenDirect(lat1, lon1, azi12, s12, outmask, lat2, lon2, S12); + } + void GenInverse(real lat1, real lon1, real lat2, real lon2, + unsigned outmask, real& s12, real& azi12, + real&, real& , real& , real& , real& S12) const { + GenInverse(lat1, lon1, lat2, lon2, outmask, s12, azi12, S12); + } + public: + + /** + * Bit masks for what calculations to do. They specify which results to + * return in the general routines Rhumb::GenDirect and Rhumb::GenInverse + * routines. RhumbLine::mask is a duplication of this enum. + **********************************************************************/ + enum mask { + /** + * No output. + * @hideinitializer + **********************************************************************/ + NONE = 0U, + /** + * Calculate latitude \e lat2. + * @hideinitializer + **********************************************************************/ + LATITUDE = 1U<<7, + /** + * Calculate longitude \e lon2. + * @hideinitializer + **********************************************************************/ + LONGITUDE = 1U<<8, + /** + * Calculate azimuth \e azi12. + * @hideinitializer + **********************************************************************/ + AZIMUTH = 1U<<9, + /** + * Calculate distance \e s12. + * @hideinitializer + **********************************************************************/ + DISTANCE = 1U<<10, + /** + * Calculate area \e S12. + * @hideinitializer + **********************************************************************/ + AREA = 1U<<14, + /** + * Unroll \e lon2 in the direct calculation. + * @hideinitializer + **********************************************************************/ + LONG_UNROLL = 1U<<15, + /** + * Calculate everything. (LONG_UNROLL is not included in this mask.) + * @hideinitializer + **********************************************************************/ + ALL = 0x7F80U, + }; + + /** + * Constructor for a ellipsoid with + * + * @param[in] a equatorial radius (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @param[in] exact if true (the default) use an addition theorem for + * elliptic integrals to compute divided differences; otherwise use + * series expansion (accurate for |f| < 0.01). + * @exception GeographicErr if \e a or (1 − \e f) \e a is not + * positive. + * + * See \ref rhumb, for a detailed description of the \e exact parameter. + **********************************************************************/ + Rhumb(real a, real f, bool exact = true); + + /** + * Solve the direct rhumb problem returning also the area. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi12 azimuth of the rhumb line (degrees). + * @param[in] s12 distance between point 1 and point 2 (meters); it can be + * negative. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] S12 area under the rhumb line (meters2). + * + * \e lat1 should be in the range [−90°, 90°]. The value of + * \e lon2 returned is in the range [−180°, 180°]. + * + * If point 1 is a pole, the cosine of its latitude is taken to be + * 1/ε2 (where ε is 2-52). This + * position, which is extremely close to the actual pole, allows the + * calculation to be carried out in finite terms. If \e s12 is large + * enough that the rhumb line crosses a pole, the longitude of point 2 + * is indeterminate (a NaN is returned for \e lon2 and \e S12). + **********************************************************************/ + void Direct(real lat1, real lon1, real azi12, real s12, + real& lat2, real& lon2, real& S12) const { + GenDirect(lat1, lon1, azi12, s12, + LATITUDE | LONGITUDE | AREA, lat2, lon2, S12); + } + + /** + * Solve the direct rhumb problem without the area. + **********************************************************************/ + void Direct(real lat1, real lon1, real azi12, real s12, + real& lat2, real& lon2) const { + real t; + GenDirect(lat1, lon1, azi12, s12, LATITUDE | LONGITUDE, lat2, lon2, t); + } + + /** + * The general direct rhumb problem. Rhumb::Direct is defined in terms + * of this function. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi12 azimuth of the rhumb line (degrees). + * @param[in] s12 distance between point 1 and point 2 (meters); it can be + * negative. + * @param[in] outmask a bitor'ed combination of Rhumb::mask values + * specifying which of the following parameters should be set. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] S12 area under the rhumb line (meters2). + * + * The Rhumb::mask values possible for \e outmask are + * - \e outmask |= Rhumb::LATITUDE for the latitude \e lat2; + * - \e outmask |= Rhumb::LONGITUDE for the latitude \e lon2; + * - \e outmask |= Rhumb::AREA for the area \e S12; + * - \e outmask |= Rhumb::ALL for all of the above; + * - \e outmask |= Rhumb::LONG_UNROLL to unroll \e lon2 instead of wrapping + * it into the range [−180°, 180°]. + * . + * With the Rhumb::LONG_UNROLL bit set, the quantity \e lon2 − + * \e lon1 indicates how many times and in what sense the rhumb line + * encircles the ellipsoid. + **********************************************************************/ + void GenDirect(real lat1, real lon1, real azi12, real s12, + unsigned outmask, real& lat2, real& lon2, real& S12) const; + + /** + * Solve the inverse rhumb problem returning also the area. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] lat2 latitude of point 2 (degrees). + * @param[in] lon2 longitude of point 2 (degrees). + * @param[out] s12 rhumb distance between point 1 and point 2 (meters). + * @param[out] azi12 azimuth of the rhumb line (degrees). + * @param[out] S12 area under the rhumb line (meters2). + * + * The shortest rhumb line is found. If the end points are on opposite + * meridians, there are two shortest rhumb lines and the east-going one is + * chosen. \e lat1 and \e lat2 should be in the range [−90°, + * 90°]. The value of \e azi12 returned is in the range + * [−180°, 180°]. + * + * If either point is a pole, the cosine of its latitude is taken to be + * 1/ε2 (where ε is 2-52). This + * position, which is extremely close to the actual pole, allows the + * calculation to be carried out in finite terms. + **********************************************************************/ + void Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi12, real& S12) const { + GenInverse(lat1, lon1, lat2, lon2, + DISTANCE | AZIMUTH | AREA, s12, azi12, S12); + } + + /** + * Solve the inverse rhumb problem without the area. + **********************************************************************/ + void Inverse(real lat1, real lon1, real lat2, real lon2, + real& s12, real& azi12) const { + real t; + GenInverse(lat1, lon1, lat2, lon2, DISTANCE | AZIMUTH, s12, azi12, t); + } + + /** + * The general inverse rhumb problem. Rhumb::Inverse is defined in terms + * of this function. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] lat2 latitude of point 2 (degrees). + * @param[in] lon2 longitude of point 2 (degrees). + * @param[in] outmask a bitor'ed combination of Rhumb::mask values + * specifying which of the following parameters should be set. + * @param[out] s12 rhumb distance between point 1 and point 2 (meters). + * @param[out] azi12 azimuth of the rhumb line (degrees). + * @param[out] S12 area under the rhumb line (meters2). + * + * The Rhumb::mask values possible for \e outmask are + * - \e outmask |= Rhumb::DISTANCE for the latitude \e s12; + * - \e outmask |= Rhumb::AZIMUTH for the latitude \e azi12; + * - \e outmask |= Rhumb::AREA for the area \e S12; + * - \e outmask |= Rhumb::ALL for all of the above; + **********************************************************************/ + void GenInverse(real lat1, real lon1, real lat2, real lon2, + unsigned outmask, + real& s12, real& azi12, real& S12) const; + + /** + * Set up to compute several points on a single rhumb line. + * + * @param[in] lat1 latitude of point 1 (degrees). + * @param[in] lon1 longitude of point 1 (degrees). + * @param[in] azi12 azimuth of the rhumb line (degrees). + * @return a RhumbLine object. + * + * \e lat1 should be in the range [−90°, 90°]. + * + * If point 1 is a pole, the cosine of its latitude is taken to be + * 1/ε2 (where ε is 2-52). This + * position, which is extremely close to the actual pole, allows the + * calculation to be carried out in finite terms. + **********************************************************************/ + RhumbLine Line(real lat1, real lon1, real azi12) const; + + /** \name Inspector functions. + **********************************************************************/ + ///@{ + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _ell.EquatorialRadius(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the + * value used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _ell.Flattening(); } + + /** + * @return total area of ellipsoid in meters2. The area of a + * polygon encircling a pole can be found by adding + * Geodesic::EllipsoidArea()/2 to the sum of \e S12 for each side of the + * polygon. + **********************************************************************/ + Math::real EllipsoidArea() const { return _ell.Area(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of Rhumb with the parameters for the WGS84 + * ellipsoid. + **********************************************************************/ + static const Rhumb& WGS84(); + }; + + /** + * \brief Find a sequence of points on a single rhumb line. + * + * RhumbLine facilitates the determination of a series of points on a single + * rhumb line. The starting point (\e lat1, \e lon1) and the azimuth \e + * azi12 are specified in the call to Rhumb::Line which returns a RhumbLine + * object. RhumbLine.Position returns the location of point 2 (and, + * optionally, the corresponding area, \e S12) a distance \e s12 along the + * rhumb line. + * + * There is no public constructor for this class. (Use Rhumb::Line to create + * an instance.) The Rhumb object used to create a RhumbLine must stay in + * scope as long as the RhumbLine. + * + * Example of use: + * \include example-RhumbLine.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT RhumbLine { + private: + typedef Math::real real; + friend class Rhumb; + const Rhumb& _rh; + bool _exact; // TODO: RhumbLine::_exact is unused; retire + real _lat1, _lon1, _azi12, _salp, _calp, _mu1, _psi1, _r1; + // copy assignment not allowed + RhumbLine& operator=(const RhumbLine&) = delete; + RhumbLine(const Rhumb& rh, real lat1, real lon1, real azi12, + bool exact); + public: + /** + * Construction is via default copy constructor. + **********************************************************************/ + RhumbLine(const RhumbLine&) = default; + /** + * This is a duplication of Rhumb::mask. + **********************************************************************/ + enum mask { + /** + * No output. + * @hideinitializer + **********************************************************************/ + NONE = Rhumb::NONE, + /** + * Calculate latitude \e lat2. + * @hideinitializer + **********************************************************************/ + LATITUDE = Rhumb::LATITUDE, + /** + * Calculate longitude \e lon2. + * @hideinitializer + **********************************************************************/ + LONGITUDE = Rhumb::LONGITUDE, + /** + * Calculate azimuth \e azi12. + * @hideinitializer + **********************************************************************/ + AZIMUTH = Rhumb::AZIMUTH, + /** + * Calculate distance \e s12. + * @hideinitializer + **********************************************************************/ + DISTANCE = Rhumb::DISTANCE, + /** + * Calculate area \e S12. + * @hideinitializer + **********************************************************************/ + AREA = Rhumb::AREA, + /** + * Unroll \e lon2 in the direct calculation. + * @hideinitializer + **********************************************************************/ + LONG_UNROLL = Rhumb::LONG_UNROLL, + /** + * Calculate everything. (LONG_UNROLL is not included in this mask.) + * @hideinitializer + **********************************************************************/ + ALL = Rhumb::ALL, + }; + + /** + * Compute the position of point 2 which is a distance \e s12 (meters) from + * point 1. The area is also computed. + * + * @param[in] s12 distance between point 1 and point 2 (meters); it can be + * negative. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] S12 area under the rhumb line (meters2). + * + * The value of \e lon2 returned is in the range [−180°, + * 180°]. + * + * If \e s12 is large enough that the rhumb line crosses a pole, the + * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and + * \e S12). + **********************************************************************/ + void Position(real s12, real& lat2, real& lon2, real& S12) const { + GenPosition(s12, LATITUDE | LONGITUDE | AREA, lat2, lon2, S12); + } + + /** + * Compute the position of point 2 which is a distance \e s12 (meters) from + * point 1. The area is not computed. + **********************************************************************/ + void Position(real s12, real& lat2, real& lon2) const { + real t; + GenPosition(s12, LATITUDE | LONGITUDE, lat2, lon2, t); + } + + /** + * The general position routine. RhumbLine::Position is defined in term so + * this function. + * + * @param[in] s12 distance between point 1 and point 2 (meters); it can be + * negative. + * @param[in] outmask a bitor'ed combination of RhumbLine::mask values + * specifying which of the following parameters should be set. + * @param[out] lat2 latitude of point 2 (degrees). + * @param[out] lon2 longitude of point 2 (degrees). + * @param[out] S12 area under the rhumb line (meters2). + * + * The RhumbLine::mask values possible for \e outmask are + * - \e outmask |= RhumbLine::LATITUDE for the latitude \e lat2; + * - \e outmask |= RhumbLine::LONGITUDE for the latitude \e lon2; + * - \e outmask |= RhumbLine::AREA for the area \e S12; + * - \e outmask |= RhumbLine::ALL for all of the above; + * - \e outmask |= RhumbLine::LONG_UNROLL to unroll \e lon2 instead of + * wrapping it into the range [−180°, 180°]. + * . + * With the RhumbLine::LONG_UNROLL bit set, the quantity \e lon2 − \e + * lon1 indicates how many times and in what sense the rhumb line encircles + * the ellipsoid. + * + * If \e s12 is large enough that the rhumb line crosses a pole, the + * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and + * \e S12). + **********************************************************************/ + void GenPosition(real s12, unsigned outmask, + real& lat2, real& lon2, real& S12) const; + + /** \name Inspector functions + **********************************************************************/ + ///@{ + + /** + * @return \e lat1 the latitude of point 1 (degrees). + **********************************************************************/ + Math::real Latitude() const { return _lat1; } + + /** + * @return \e lon1 the longitude of point 1 (degrees). + **********************************************************************/ + Math::real Longitude() const { return _lon1; } + + /** + * @return \e azi12 the azimuth of the rhumb line (degrees). + **********************************************************************/ + Math::real Azimuth() const { return _azi12; } + + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value inherited from the Rhumb object used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _rh.EquatorialRadius(); } + + /** + * @return \e f the flattening of the ellipsoid. This is the value + * inherited from the Rhumb object used in the constructor. + **********************************************************************/ + Math::real Flattening() const { return _rh.Flattening(); } + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_RHUMB_HPP diff --git a/external/include/GeographicLib/SphericalEngine.hpp b/external/include/GeographicLib/SphericalEngine.hpp new file mode 100644 index 0000000..8b8ad38 --- /dev/null +++ b/external/include/GeographicLib/SphericalEngine.hpp @@ -0,0 +1,384 @@ +/** + * \file SphericalEngine.hpp + * \brief Header for GeographicLib::SphericalEngine class + * + * Copyright (c) Charles Karney (2011-2019) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_SPHERICALENGINE_HPP) +#define GEOGRAPHICLIB_SPHERICALENGINE_HPP 1 + +#include +#include +#include + +#if defined(_MSC_VER) +// Squelch warnings about dll vs vector +# pragma warning (push) +# pragma warning (disable: 4251) +#endif + +namespace GeographicLib { + + class CircularEngine; + + /** + * \brief The evaluation engine for SphericalHarmonic + * + * This serves as the backend to SphericalHarmonic, SphericalHarmonic1, and + * SphericalHarmonic2. Typically end-users will not have to access this + * class directly. + * + * See SphericalEngine.cpp for more information on the implementation. + * + * Example of use: + * \include example-SphericalEngine.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT SphericalEngine { + private: + typedef Math::real real; + // CircularEngine needs access to sqrttable, scale + friend class CircularEngine; + // Return the table of the square roots of integers + static std::vector& sqrttable(); + // An internal scaling of the coefficients to avoid overflow in + // intermediate calculations. + static real scale() { + using std::pow; + static const real + // Need extra real because, since C++11, pow(float, int) returns double + s = real(pow(real(std::numeric_limits::radix), + -3 * (std::numeric_limits::max_exponent < (1<<14) ? + std::numeric_limits::max_exponent : (1<<14)) + / 5)); + return s; + } + // Move latitudes near the pole off the axis by this amount. + static real eps() { + using std::sqrt; + return std::numeric_limits::epsilon() * + sqrt(std::numeric_limits::epsilon()); + } + SphericalEngine(); // Disable constructor + public: + /** + * Supported normalizations for associated Legendre polynomials. + **********************************************************************/ + enum normalization { + /** + * Fully normalized associated Legendre polynomials. See + * SphericalHarmonic::FULL for documentation. + * + * @hideinitializer + **********************************************************************/ + FULL = 0, + /** + * Schmidt semi-normalized associated Legendre polynomials. See + * SphericalHarmonic::SCHMIDT for documentation. + * + * @hideinitializer + **********************************************************************/ + SCHMIDT = 1, + }; + + /** + * \brief Package up coefficients for SphericalEngine + * + * This packages up the \e C, \e S coefficients and information about how + * the coefficients are stored into a single structure. This allows a + * vector of type SphericalEngine::coeff to be passed to + * SphericalEngine::Value. This class also includes functions to aid + * indexing into \e C and \e S. + * + * The storage layout of the coefficients is documented in + * SphericalHarmonic and SphericalHarmonic::SphericalHarmonic. + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT coeff { + private: + int _Nx, _nmx, _mmx; + std::vector::const_iterator _Cnm; + std::vector::const_iterator _Snm; + public: + /** + * A default constructor + **********************************************************************/ + coeff() : _Nx(-1) , _nmx(-1) , _mmx(-1) {} + /** + * The general constructor. + * + * @param[in] C a vector of coefficients for the cosine terms. + * @param[in] S a vector of coefficients for the sine terms. + * @param[in] N the degree giving storage layout for \e C and \e S. + * @param[in] nmx the maximum degree to be used. + * @param[in] mmx the maximum order to be used. + * @exception GeographicErr if \e N, \e nmx, and \e mmx do not satisfy + * \e N ≥ \e nmx ≥ \e mmx ≥ −1. + * @exception GeographicErr if \e C or \e S is not big enough to hold the + * coefficients. + * @exception std::bad_alloc if the memory for the square root table + * can't be allocated. + **********************************************************************/ + coeff(const std::vector& C, + const std::vector& S, + int N, int nmx, int mmx) + : _Nx(N) + , _nmx(nmx) + , _mmx(mmx) + , _Cnm(C.begin()) + , _Snm(S.begin()) + { + if (!((_Nx >= _nmx && _nmx >= _mmx && _mmx >= 0) || + // If mmx = -1 then the sums are empty so require nmx = -1 also. + (_nmx == -1 && _mmx == -1))) + throw GeographicErr("Bad indices for coeff"); + if (!(index(_nmx, _mmx) < int(C.size()) && + index(_nmx, _mmx) < int(S.size()) + (_Nx + 1))) + throw GeographicErr("Arrays too small in coeff"); + SphericalEngine::RootTable(_nmx); + } + /** + * The constructor for full coefficient vectors. + * + * @param[in] C a vector of coefficients for the cosine terms. + * @param[in] S a vector of coefficients for the sine terms. + * @param[in] N the maximum degree and order. + * @exception GeographicErr if \e N does not satisfy \e N ≥ −1. + * @exception GeographicErr if \e C or \e S is not big enough to hold the + * coefficients. + * @exception std::bad_alloc if the memory for the square root table + * can't be allocated. + **********************************************************************/ + coeff(const std::vector& C, + const std::vector& S, + int N) + : _Nx(N) + , _nmx(N) + , _mmx(N) + , _Cnm(C.begin()) + , _Snm(S.begin()) + { + if (!(_Nx >= -1)) + throw GeographicErr("Bad indices for coeff"); + if (!(index(_nmx, _mmx) < int(C.size()) && + index(_nmx, _mmx) < int(S.size()) + (_Nx + 1))) + throw GeographicErr("Arrays too small in coeff"); + SphericalEngine::RootTable(_nmx); + } + /** + * @return \e N the degree giving storage layout for \e C and \e S. + **********************************************************************/ + int N() const { return _Nx; } + /** + * @return \e nmx the maximum degree to be used. + **********************************************************************/ + int nmx() const { return _nmx; } + /** + * @return \e mmx the maximum order to be used. + **********************************************************************/ + int mmx() const { return _mmx; } + /** + * The one-dimensional index into \e C and \e S. + * + * @param[in] n the degree. + * @param[in] m the order. + * @return the one-dimensional index. + **********************************************************************/ + int index(int n, int m) const + { return m * _Nx - m * (m - 1) / 2 + n; } + /** + * An element of \e C. + * + * @param[in] k the one-dimensional index. + * @return the value of the \e C coefficient. + **********************************************************************/ + Math::real Cv(int k) const { return *(_Cnm + k); } + /** + * An element of \e S. + * + * @param[in] k the one-dimensional index. + * @return the value of the \e S coefficient. + **********************************************************************/ + Math::real Sv(int k) const { return *(_Snm + (k - (_Nx + 1))); } + /** + * An element of \e C with checking. + * + * @param[in] k the one-dimensional index. + * @param[in] n the requested degree. + * @param[in] m the requested order. + * @param[in] f a multiplier. + * @return the value of the \e C coefficient multiplied by \e f in \e n + * and \e m are in range else 0. + **********************************************************************/ + Math::real Cv(int k, int n, int m, real f) const + { return m > _mmx || n > _nmx ? 0 : *(_Cnm + k) * f; } + /** + * An element of \e S with checking. + * + * @param[in] k the one-dimensional index. + * @param[in] n the requested degree. + * @param[in] m the requested order. + * @param[in] f a multiplier. + * @return the value of the \e S coefficient multiplied by \e f in \e n + * and \e m are in range else 0. + **********************************************************************/ + Math::real Sv(int k, int n, int m, real f) const + { return m > _mmx || n > _nmx ? 0 : *(_Snm + (k - (_Nx + 1))) * f; } + + /** + * The size of the coefficient vector for the cosine terms. + * + * @param[in] N the maximum degree. + * @param[in] M the maximum order. + * @return the size of the vector of cosine terms as stored in column + * major order. + **********************************************************************/ + static int Csize(int N, int M) + { return (M + 1) * (2 * N - M + 2) / 2; } + + /** + * The size of the coefficient vector for the sine terms. + * + * @param[in] N the maximum degree. + * @param[in] M the maximum order. + * @return the size of the vector of cosine terms as stored in column + * major order. + **********************************************************************/ + static int Ssize(int N, int M) + { return Csize(N, M) - (N + 1); } + + /** + * Load coefficients from a binary stream. + * + * @param[in] stream the input stream. + * @param[in,out] N The maximum degree of the coefficients. + * @param[in,out] M The maximum order of the coefficients. + * @param[out] C The vector of cosine coefficients. + * @param[out] S The vector of sine coefficients. + * @param[in] truncate if false (the default) then \e N and \e M are + * determined by the values in the binary stream; otherwise, the input + * values of \e N and \e M are used to truncate the coefficients read + * from the stream at the given degree and order. + * @exception GeographicErr if \e N and \e M do not satisfy \e N ≥ + * \e M ≥ −1. + * @exception GeographicErr if there's an error reading the data. + * @exception std::bad_alloc if the memory for \e C or \e S can't be + * allocated. + * + * \e N and \e M are read as 4-byte ints. \e C and \e S are resized to + * accommodate all the coefficients (with the \e m = 0 coefficients for + * \e S excluded) and the data for these coefficients read as 8-byte + * doubles. The coefficients are stored in column major order. The + * bytes in the stream should use little-endian ordering. IEEE floating + * point is assumed for the coefficients. + **********************************************************************/ + static void readcoeffs(std::istream& stream, int& N, int& M, + std::vector& C, std::vector& S, + bool truncate = false); + }; + + /** + * Evaluate a spherical harmonic sum and its gradient. + * + * @tparam gradp should the gradient be calculated. + * @tparam norm the normalization for the associated Legendre polynomials. + * @tparam L the number of terms in the coefficients. + * @param[in] c an array of coeff objects. + * @param[in] f array of coefficient multipliers. f[0] should be 1. + * @param[in] x the \e x component of the cartesian position. + * @param[in] y the \e y component of the cartesian position. + * @param[in] z the \e z component of the cartesian position. + * @param[in] a the normalizing radius. + * @param[out] gradx the \e x component of the gradient. + * @param[out] grady the \e y component of the gradient. + * @param[out] gradz the \e z component of the gradient. + * @result the spherical harmonic sum. + * + * See the SphericalHarmonic class for the definition of the sum. The + * coefficients used by this function are, for example, c[0].Cv + f[1] * + * c[1].Cv + ... + f[L−1] * c[L−1].Cv. (Note that f[0] is \e + * not used.) The upper limits on the sum are determined by c[0].nmx() and + * c[0].mmx(); these limits apply to \e all the components of the + * coefficients. The parameters \e gradp, \e norm, and \e L are template + * parameters, to allow more optimization to be done at compile time. + * + * Clenshaw summation is used which permits the evaluation of the sum + * without the need to allocate temporary arrays. Thus this function never + * throws an exception. + **********************************************************************/ + template + static Math::real Value(const coeff c[], const real f[], + real x, real y, real z, real a, + real& gradx, real& grady, real& gradz); + + /** + * Create a CircularEngine object + * + * @tparam gradp should the gradient be calculated. + * @tparam norm the normalization for the associated Legendre polynomials. + * @tparam L the number of terms in the coefficients. + * @param[in] c an array of coeff objects. + * @param[in] f array of coefficient multipliers. f[0] should be 1. + * @param[in] p the radius of the circle = sqrt(x2 + + * y2). + * @param[in] z the height of the circle. + * @param[in] a the normalizing radius. + * @exception std::bad_alloc if the memory for the CircularEngine can't be + * allocated. + * @result the CircularEngine object. + * + * If you need to evaluate the spherical harmonic sum for several points + * with constant \e f, \e p = sqrt(x2 + + * y2), \e z, and \e a, it is more efficient to construct + * call SphericalEngine::Circle to give a CircularEngine object and then + * call CircularEngine::operator()() with arguments x/\e p and + * y/\e p. + **********************************************************************/ + template + static CircularEngine Circle(const coeff c[], const real f[], + real p, real z, real a); + /** + * Check that the static table of square roots is big enough and enlarge it + * if necessary. + * + * @param[in] N the maximum degree to be used in SphericalEngine. + * @exception std::bad_alloc if the memory for the square root table can't + * be allocated. + * + * Typically, there's no need for an end-user to call this routine, because + * the constructors for SphericalEngine::coeff do so. However, since this + * updates a static table, there's a possible race condition in a + * multi-threaded environment. Because this routine does nothing if the + * table is already large enough, one way to avoid race conditions is to + * call this routine at program start up (when it's still single threaded), + * supplying the largest degree that your program will use. E.g., \code + GeographicLib::SphericalEngine::RootTable(2190); + \endcode + * suffices to accommodate extant magnetic and gravity models. + **********************************************************************/ + static void RootTable(int N); + + /** + * Clear the static table of square roots and release the memory. Call + * this only when you are sure you no longer will be using SphericalEngine. + * Your program will crash if you call SphericalEngine after calling this + * routine. + * + * \warning It's safest not to call this routine at all. (The space used + * by the table is modest.) + **********************************************************************/ + static void ClearRootTable() { + std::vector temp(0); + sqrttable().swap(temp); + } + }; + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_SPHERICALENGINE_HPP diff --git a/external/include/GeographicLib/SphericalHarmonic.hpp b/external/include/GeographicLib/SphericalHarmonic.hpp new file mode 100644 index 0000000..38da9ba --- /dev/null +++ b/external/include/GeographicLib/SphericalHarmonic.hpp @@ -0,0 +1,356 @@ +/** + * \file SphericalHarmonic.hpp + * \brief Header for GeographicLib::SphericalHarmonic class + * + * Copyright (c) Charles Karney (2011-2019) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_SPHERICALHARMONIC_HPP) +#define GEOGRAPHICLIB_SPHERICALHARMONIC_HPP 1 + +#include +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief Spherical harmonic series + * + * This class evaluates the spherical harmonic sum \verbatim + V(x, y, z) = sum(n = 0..N)[ q^(n+1) * sum(m = 0..n)[ + (C[n,m] * cos(m*lambda) + S[n,m] * sin(m*lambda)) * + P[n,m](cos(theta)) ] ] + \endverbatim + * where + * - p2 = x2 + y2, + * - r2 = p2 + z2, + * - \e q = a/r, + * - θ = atan2(\e p, \e z) = the spherical \e colatitude, + * - λ = atan2(\e y, \e x) = the longitude. + * - Pnm(\e t) is the associated Legendre polynomial of + * degree \e n and order \e m. + * + * Two normalizations are supported for Pnm + * - fully normalized denoted by SphericalHarmonic::FULL. + * - Schmidt semi-normalized denoted by SphericalHarmonic::SCHMIDT. + * + * Clenshaw summation is used for the sums over both \e n and \e m. This + * allows the computation to be carried out without the need for any + * temporary arrays. See SphericalEngine.cpp for more information on the + * implementation. + * + * References: + * - C. W. Clenshaw, + * + * A note on the summation of Chebyshev series, + * %Math. Tables Aids Comput. 9(51), 118--120 (1955). + * - R. E. Deakin, Derivatives of the earth's potentials, Geomatics + * Research Australasia 68, 31--60, (June 1998). + * - W. A. Heiskanen and H. Moritz, Physical Geodesy, (Freeman, San + * Francisco, 1967). (See Sec. 1-14, for a definition of Pbar.) + * - S. A. Holmes and W. E. Featherstone, + * + * A unified approach to the Clenshaw summation and the recursive + * computation of very high degree and order normalised associated Legendre + * functions, J. Geodesy 76(5), 279--299 (2002). + * - C. C. Tscherning and K. Poder, + * + * Some geodetic applications of Clenshaw summation, + * Boll. Geod. Sci. Aff. 41(4), 349--375 (1982). + * + * Example of use: + * \include example-SphericalHarmonic.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT SphericalHarmonic { + public: + /** + * Supported normalizations for the associated Legendre polynomials. + **********************************************************************/ + enum normalization { + /** + * Fully normalized associated Legendre polynomials. + * + * These are defined by + * Pnmfull(\e z) + * = (−1)m + * sqrt(\e k (2\e n + 1) (\e n − \e m)! / (\e n + \e m)!) + * Pnm(\e z), where + * Pnm(\e z) is Ferrers + * function (also known as the Legendre function on the cut or the + * associated Legendre polynomial) https://dlmf.nist.gov/14.7.E10 and + * \e k = 1 for \e m = 0 and \e k = 2 otherwise. + * + * The mean squared value of + * Pnmfull(cosθ) + * cos(mλ) and + * Pnmfull(cosθ) + * sin(mλ) over the sphere is 1. + * + * @hideinitializer + **********************************************************************/ + FULL = SphericalEngine::FULL, + /** + * Schmidt semi-normalized associated Legendre polynomials. + * + * These are defined by + * Pnmschmidt(\e z) + * = (−1)m + * sqrt(\e k (\e n − \e m)! / (\e n + \e m)!) + * Pnm(\e z), where + * Pnm(\e z) is Ferrers + * function (also known as the Legendre function on the cut or the + * associated Legendre polynomial) https://dlmf.nist.gov/14.7.E10 and + * \e k = 1 for \e m = 0 and \e k = 2 otherwise. + * + * The mean squared value of + * Pnmschmidt(cosθ) + * cos(mλ) and + * Pnmschmidt(cosθ) + * sin(mλ) over the sphere is 1/(2\e n + 1). + * + * @hideinitializer + **********************************************************************/ + SCHMIDT = SphericalEngine::SCHMIDT, + }; + + private: + typedef Math::real real; + SphericalEngine::coeff _c[1]; + real _a; + unsigned _norm; + + public: + /** + * Constructor with a full set of coefficients specified. + * + * @param[in] C the coefficients Cnm. + * @param[in] S the coefficients Snm. + * @param[in] N the maximum degree and order of the sum + * @param[in] a the reference radius appearing in the definition of the + * sum. + * @param[in] norm the normalization for the associated Legendre + * polynomials, either SphericalHarmonic::FULL (the default) or + * SphericalHarmonic::SCHMIDT. + * @exception GeographicErr if \e N does not satisfy \e N ≥ −1. + * @exception GeographicErr if \e C or \e S is not big enough to hold the + * coefficients. + * + * The coefficients Cnm and + * Snm are stored in the one-dimensional vectors + * \e C and \e S which must contain (\e N + 1)(\e N + 2)/2 and \e N (\e N + + * 1)/2 elements, respectively, stored in "column-major" order. Thus for + * \e N = 3, the order would be: + * C00, + * C10, + * C20, + * C30, + * C11, + * C21, + * C31, + * C22, + * C32, + * C33. + * In general the (\e n,\e m) element is at index \e m \e N − \e m + * (\e m − 1)/2 + \e n. The layout of \e S is the same except that + * the first column is omitted (since the \e m = 0 terms never contribute + * to the sum) and the 0th element is S11 + * + * The class stores pointers to the first elements of \e C and \e S. + * These arrays should not be altered or destroyed during the lifetime of a + * SphericalHarmonic object. + **********************************************************************/ + SphericalHarmonic(const std::vector& C, + const std::vector& S, + int N, real a, unsigned norm = FULL) + : _a(a) + , _norm(norm) + { _c[0] = SphericalEngine::coeff(C, S, N); } + + /** + * Constructor with a subset of coefficients specified. + * + * @param[in] C the coefficients Cnm. + * @param[in] S the coefficients Snm. + * @param[in] N the degree used to determine the layout of \e C and \e S. + * @param[in] nmx the maximum degree used in the sum. The sum over \e n is + * from 0 thru \e nmx. + * @param[in] mmx the maximum order used in the sum. The sum over \e m is + * from 0 thru min(\e n, \e mmx). + * @param[in] a the reference radius appearing in the definition of the + * sum. + * @param[in] norm the normalization for the associated Legendre + * polynomials, either SphericalHarmonic::FULL (the default) or + * SphericalHarmonic::SCHMIDT. + * @exception GeographicErr if \e N, \e nmx, and \e mmx do not satisfy + * \e N ≥ \e nmx ≥ \e mmx ≥ −1. + * @exception GeographicErr if \e C or \e S is not big enough to hold the + * coefficients. + * + * The class stores pointers to the first elements of \e C and \e S. + * These arrays should not be altered or destroyed during the lifetime of a + * SphericalHarmonic object. + **********************************************************************/ + SphericalHarmonic(const std::vector& C, + const std::vector& S, + int N, int nmx, int mmx, + real a, unsigned norm = FULL) + : _a(a) + , _norm(norm) + { _c[0] = SphericalEngine::coeff(C, S, N, nmx, mmx); } + + /** + * A default constructor so that the object can be created when the + * constructor for another object is initialized. This default object can + * then be reset with the default copy assignment operator. + **********************************************************************/ + SphericalHarmonic() {} + + /** + * Compute the spherical harmonic sum. + * + * @param[in] x cartesian coordinate. + * @param[in] y cartesian coordinate. + * @param[in] z cartesian coordinate. + * @return \e V the spherical harmonic sum. + * + * This routine requires constant memory and thus never throws an + * exception. + **********************************************************************/ + Math::real operator()(real x, real y, real z) const { + real f[] = {1}; + real v = 0; + real dummy; + switch (_norm) { + case FULL: + v = SphericalEngine::Value + (_c, f, x, y, z, _a, dummy, dummy, dummy); + break; + case SCHMIDT: + default: // To avoid compiler warnings + v = SphericalEngine::Value + (_c, f, x, y, z, _a, dummy, dummy, dummy); + break; + } + return v; + } + + /** + * Compute a spherical harmonic sum and its gradient. + * + * @param[in] x cartesian coordinate. + * @param[in] y cartesian coordinate. + * @param[in] z cartesian coordinate. + * @param[out] gradx \e x component of the gradient + * @param[out] grady \e y component of the gradient + * @param[out] gradz \e z component of the gradient + * @return \e V the spherical harmonic sum. + * + * This is the same as the previous function, except that the components of + * the gradients of the sum in the \e x, \e y, and \e z directions are + * computed. This routine requires constant memory and thus never throws + * an exception. + **********************************************************************/ + Math::real operator()(real x, real y, real z, + real& gradx, real& grady, real& gradz) const { + real f[] = {1}; + real v = 0; + switch (_norm) { + case FULL: + v = SphericalEngine::Value + (_c, f, x, y, z, _a, gradx, grady, gradz); + break; + case SCHMIDT: + default: // To avoid compiler warnings + v = SphericalEngine::Value + (_c, f, x, y, z, _a, gradx, grady, gradz); + break; + } + return v; + } + + /** + * Create a CircularEngine to allow the efficient evaluation of several + * points on a circle of latitude. + * + * @param[in] p the radius of the circle. + * @param[in] z the height of the circle above the equatorial plane. + * @param[in] gradp if true the returned object will be able to compute the + * gradient of the sum. + * @exception std::bad_alloc if the memory for the CircularEngine can't be + * allocated. + * @return the CircularEngine object. + * + * SphericalHarmonic::operator()() exchanges the order of the sums in the + * definition, i.e., ∑n = 0..N + * ∑m = 0..n becomes ∑m = + * 0..Nn = m..N. + * SphericalHarmonic::Circle performs the inner sum over degree \e n (which + * entails about N2 operations). Calling + * CircularEngine::operator()() on the returned object performs the outer + * sum over the order \e m (about \e N operations). + * + * Here's an example of computing the spherical sum at a sequence of + * longitudes without using a CircularEngine object \code + SphericalHarmonic h(...); // Create the SphericalHarmonic object + double r = 2, lat = 33, lon0 = 44, dlon = 0.01; + double + phi = lat * Math::degree(), + z = r * sin(phi), p = r * cos(phi); + for (int i = 0; i <= 100; ++i) { + real + lon = lon0 + i * dlon, + lam = lon * Math::degree(); + std::cout << lon << " " << h(p * cos(lam), p * sin(lam), z) << "\n"; + } + \endcode + * Here is the same calculation done using a CircularEngine object. This + * will be about N/2 times faster. \code + SphericalHarmonic h(...); // Create the SphericalHarmonic object + double r = 2, lat = 33, lon0 = 44, dlon = 0.01; + double + phi = lat * Math::degree(), + z = r * sin(phi), p = r * cos(phi); + CircularEngine c(h(p, z, false)); // Create the CircularEngine object + for (int i = 0; i <= 100; ++i) { + real + lon = lon0 + i * dlon; + std::cout << lon << " " << c(lon) << "\n"; + } + \endcode + **********************************************************************/ + CircularEngine Circle(real p, real z, bool gradp) const { + real f[] = {1}; + switch (_norm) { + case FULL: + return gradp ? + SphericalEngine::Circle + (_c, f, p, z, _a) : + SphericalEngine::Circle + (_c, f, p, z, _a); + break; + case SCHMIDT: + default: // To avoid compiler warnings + return gradp ? + SphericalEngine::Circle + (_c, f, p, z, _a) : + SphericalEngine::Circle + (_c, f, p, z, _a); + break; + } + } + + /** + * @return the zeroth SphericalEngine::coeff object. + **********************************************************************/ + const SphericalEngine::coeff& Coefficients() const + { return _c[0]; } + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_SPHERICALHARMONIC_HPP diff --git a/external/include/GeographicLib/SphericalHarmonic1.hpp b/external/include/GeographicLib/SphericalHarmonic1.hpp new file mode 100644 index 0000000..8cedf28 --- /dev/null +++ b/external/include/GeographicLib/SphericalHarmonic1.hpp @@ -0,0 +1,283 @@ +/** + * \file SphericalHarmonic1.hpp + * \brief Header for GeographicLib::SphericalHarmonic1 class + * + * Copyright (c) Charles Karney (2011) and licensed under + * the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_SPHERICALHARMONIC1_HPP) +#define GEOGRAPHICLIB_SPHERICALHARMONIC1_HPP 1 + +#include +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief Spherical harmonic series with a correction to the coefficients + * + * This classes is similar to SphericalHarmonic, except that the coefficients + * Cnm are replaced by + * Cnm + \e tau C'nm (and + * similarly for Snm). + * + * Example of use: + * \include example-SphericalHarmonic1.cpp + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT SphericalHarmonic1 { + public: + /** + * Supported normalizations for associate Legendre polynomials. + **********************************************************************/ + enum normalization { + /** + * Fully normalized associated Legendre polynomials. See + * SphericalHarmonic::FULL for documentation. + * + * @hideinitializer + **********************************************************************/ + FULL = SphericalEngine::FULL, + /** + * Schmidt semi-normalized associated Legendre polynomials. See + * SphericalHarmonic::SCHMIDT for documentation. + * + * @hideinitializer + **********************************************************************/ + SCHMIDT = SphericalEngine::SCHMIDT, + }; + + private: + typedef Math::real real; + SphericalEngine::coeff _c[2]; + real _a; + unsigned _norm; + + public: + /** + * Constructor with a full set of coefficients specified. + * + * @param[in] C the coefficients Cnm. + * @param[in] S the coefficients Snm. + * @param[in] N the maximum degree and order of the sum + * @param[in] C1 the coefficients C'nm. + * @param[in] S1 the coefficients S'nm. + * @param[in] N1 the maximum degree and order of the correction + * coefficients C'nm and + * S'nm. + * @param[in] a the reference radius appearing in the definition of the + * sum. + * @param[in] norm the normalization for the associated Legendre + * polynomials, either SphericalHarmonic1::FULL (the default) or + * SphericalHarmonic1::SCHMIDT. + * @exception GeographicErr if \e N and \e N1 do not satisfy \e N ≥ + * \e N1 ≥ −1. + * @exception GeographicErr if any of the vectors of coefficients is not + * large enough. + * + * See SphericalHarmonic for the way the coefficients should be stored. + * + * The class stores pointers to the first elements of \e C, \e S, \e + * C', and \e S'. These arrays should not be altered or destroyed during + * the lifetime of a SphericalHarmonic object. + **********************************************************************/ + SphericalHarmonic1(const std::vector& C, + const std::vector& S, + int N, + const std::vector& C1, + const std::vector& S1, + int N1, + real a, unsigned norm = FULL) + : _a(a) + , _norm(norm) { + if (!(N1 <= N)) + throw GeographicErr("N1 cannot be larger that N"); + _c[0] = SphericalEngine::coeff(C, S, N); + _c[1] = SphericalEngine::coeff(C1, S1, N1); + } + + /** + * Constructor with a subset of coefficients specified. + * + * @param[in] C the coefficients Cnm. + * @param[in] S the coefficients Snm. + * @param[in] N the degree used to determine the layout of \e C and \e S. + * @param[in] nmx the maximum degree used in the sum. The sum over \e n is + * from 0 thru \e nmx. + * @param[in] mmx the maximum order used in the sum. The sum over \e m is + * from 0 thru min(\e n, \e mmx). + * @param[in] C1 the coefficients C'nm. + * @param[in] S1 the coefficients S'nm. + * @param[in] N1 the degree used to determine the layout of \e C' and \e + * S'. + * @param[in] nmx1 the maximum degree used for \e C' and \e S'. + * @param[in] mmx1 the maximum order used for \e C' and \e S'. + * @param[in] a the reference radius appearing in the definition of the + * sum. + * @param[in] norm the normalization for the associated Legendre + * polynomials, either SphericalHarmonic1::FULL (the default) or + * SphericalHarmonic1::SCHMIDT. + * @exception GeographicErr if the parameters do not satisfy \e N ≥ \e + * nmx ≥ \e mmx ≥ −1; \e N1 ≥ \e nmx1 ≥ \e mmx1 ≥ + * −1; \e N ≥ \e N1; \e nmx ≥ \e nmx1; \e mmx ≥ \e mmx1. + * @exception GeographicErr if any of the vectors of coefficients is not + * large enough. + * + * The class stores pointers to the first elements of \e C, \e S, \e + * C', and \e S'. These arrays should not be altered or destroyed during + * the lifetime of a SphericalHarmonic object. + **********************************************************************/ + SphericalHarmonic1(const std::vector& C, + const std::vector& S, + int N, int nmx, int mmx, + const std::vector& C1, + const std::vector& S1, + int N1, int nmx1, int mmx1, + real a, unsigned norm = FULL) + : _a(a) + , _norm(norm) { + if (!(nmx1 <= nmx)) + throw GeographicErr("nmx1 cannot be larger that nmx"); + if (!(mmx1 <= mmx)) + throw GeographicErr("mmx1 cannot be larger that mmx"); + _c[0] = SphericalEngine::coeff(C, S, N, nmx, mmx); + _c[1] = SphericalEngine::coeff(C1, S1, N1, nmx1, mmx1); + } + + /** + * A default constructor so that the object can be created when the + * constructor for another object is initialized. This default object can + * then be reset with the default copy assignment operator. + **********************************************************************/ + SphericalHarmonic1() {} + + /** + * Compute a spherical harmonic sum with a correction term. + * + * @param[in] tau multiplier for correction coefficients \e C' and \e S'. + * @param[in] x cartesian coordinate. + * @param[in] y cartesian coordinate. + * @param[in] z cartesian coordinate. + * @return \e V the spherical harmonic sum. + * + * This routine requires constant memory and thus never throws + * an exception. + **********************************************************************/ + Math::real operator()(real tau, real x, real y, real z) const { + real f[] = {1, tau}; + real v = 0; + real dummy; + switch (_norm) { + case FULL: + v = SphericalEngine::Value + (_c, f, x, y, z, _a, dummy, dummy, dummy); + break; + case SCHMIDT: + default: // To avoid compiler warnings + v = SphericalEngine::Value + (_c, f, x, y, z, _a, dummy, dummy, dummy); + break; + } + return v; + } + + /** + * Compute a spherical harmonic sum with a correction term and its + * gradient. + * + * @param[in] tau multiplier for correction coefficients \e C' and \e S'. + * @param[in] x cartesian coordinate. + * @param[in] y cartesian coordinate. + * @param[in] z cartesian coordinate. + * @param[out] gradx \e x component of the gradient + * @param[out] grady \e y component of the gradient + * @param[out] gradz \e z component of the gradient + * @return \e V the spherical harmonic sum. + * + * This is the same as the previous function, except that the components of + * the gradients of the sum in the \e x, \e y, and \e z directions are + * computed. This routine requires constant memory and thus never throws + * an exception. + **********************************************************************/ + Math::real operator()(real tau, real x, real y, real z, + real& gradx, real& grady, real& gradz) const { + real f[] = {1, tau}; + real v = 0; + switch (_norm) { + case FULL: + v = SphericalEngine::Value + (_c, f, x, y, z, _a, gradx, grady, gradz); + break; + case SCHMIDT: + default: // To avoid compiler warnings + v = SphericalEngine::Value + (_c, f, x, y, z, _a, gradx, grady, gradz); + break; + } + return v; + } + + /** + * Create a CircularEngine to allow the efficient evaluation of several + * points on a circle of latitude at a fixed value of \e tau. + * + * @param[in] tau the multiplier for the correction coefficients. + * @param[in] p the radius of the circle. + * @param[in] z the height of the circle above the equatorial plane. + * @param[in] gradp if true the returned object will be able to compute the + * gradient of the sum. + * @exception std::bad_alloc if the memory for the CircularEngine can't be + * allocated. + * @return the CircularEngine object. + * + * SphericalHarmonic1::operator()() exchanges the order of the sums in the + * definition, i.e., ∑n = 0..N + * ∑m = 0..n becomes ∑m = + * 0..Nn = m..N. + * SphericalHarmonic1::Circle performs the inner sum over degree \e n + * (which entails about N2 operations). Calling + * CircularEngine::operator()() on the returned object performs the outer + * sum over the order \e m (about \e N operations). + * + * See SphericalHarmonic::Circle for an example of its use. + **********************************************************************/ + CircularEngine Circle(real tau, real p, real z, bool gradp) const { + real f[] = {1, tau}; + switch (_norm) { + case FULL: + return gradp ? + SphericalEngine::Circle + (_c, f, p, z, _a) : + SphericalEngine::Circle + (_c, f, p, z, _a); + break; + case SCHMIDT: + default: // To avoid compiler warnings + return gradp ? + SphericalEngine::Circle + (_c, f, p, z, _a) : + SphericalEngine::Circle + (_c, f, p, z, _a); + break; + } + } + + /** + * @return the zeroth SphericalEngine::coeff object. + **********************************************************************/ + const SphericalEngine::coeff& Coefficients() const + { return _c[0]; } + /** + * @return the first SphericalEngine::coeff object. + **********************************************************************/ + const SphericalEngine::coeff& Coefficients1() const + { return _c[1]; } + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_SPHERICALHARMONIC1_HPP diff --git a/external/include/GeographicLib/SphericalHarmonic2.hpp b/external/include/GeographicLib/SphericalHarmonic2.hpp new file mode 100644 index 0000000..a0de495 --- /dev/null +++ b/external/include/GeographicLib/SphericalHarmonic2.hpp @@ -0,0 +1,320 @@ +/** + * \file SphericalHarmonic2.hpp + * \brief Header for GeographicLib::SphericalHarmonic2 class + * + * Copyright (c) Charles Karney (2011-2012) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_SPHERICALHARMONIC2_HPP) +#define GEOGRAPHICLIB_SPHERICALHARMONIC2_HPP 1 + +#include +#include +#include +#include + +namespace GeographicLib { + + /** + * \brief Spherical harmonic series with two corrections to the coefficients + * + * This classes is similar to SphericalHarmonic, except that the coefficients + * Cnm are replaced by + * Cnm + \e tau' C'nm + \e + * tau'' C''nm (and similarly for + * Snm). + * + * Example of use: + * \include example-SphericalHarmonic2.cpp + **********************************************************************/ + + // Don't include the GEOGRPAHIC_EXPORT because this header-only class isn't + // used by any other classes in the library. + class /*GEOGRAPHICLIB_EXPORT*/ SphericalHarmonic2 { + public: + /** + * Supported normalizations for associate Legendre polynomials. + **********************************************************************/ + enum normalization { + /** + * Fully normalized associated Legendre polynomials. See + * SphericalHarmonic::FULL for documentation. + * + * @hideinitializer + **********************************************************************/ + FULL = SphericalEngine::FULL, + /** + * Schmidt semi-normalized associated Legendre polynomials. See + * SphericalHarmonic::SCHMIDT for documentation. + * + * @hideinitializer + **********************************************************************/ + SCHMIDT = SphericalEngine::SCHMIDT, + }; + + private: + typedef Math::real real; + SphericalEngine::coeff _c[3]; + real _a; + unsigned _norm; + + public: + /** + * Constructor with a full set of coefficients specified. + * + * @param[in] C the coefficients Cnm. + * @param[in] S the coefficients Snm. + * @param[in] N the maximum degree and order of the sum + * @param[in] C1 the coefficients C'nm. + * @param[in] S1 the coefficients S'nm. + * @param[in] N1 the maximum degree and order of the first correction + * coefficients C'nm and + * S'nm. + * @param[in] C2 the coefficients C''nm. + * @param[in] S2 the coefficients S''nm. + * @param[in] N2 the maximum degree and order of the second correction + * coefficients C'nm and + * S'nm. + * @param[in] a the reference radius appearing in the definition of the + * sum. + * @param[in] norm the normalization for the associated Legendre + * polynomials, either SphericalHarmonic2::FULL (the default) or + * SphericalHarmonic2::SCHMIDT. + * @exception GeographicErr if \e N and \e N1 do not satisfy \e N ≥ + * \e N1 ≥ −1, and similarly for \e N2. + * @exception GeographicErr if any of the vectors of coefficients is not + * large enough. + * + * See SphericalHarmonic for the way the coefficients should be stored. \e + * N1 and \e N2 should satisfy \e N1 ≤ \e N and \e N2 ≤ \e N. + * + * The class stores pointers to the first elements of \e C, \e S, \e + * C', \e S', \e C'', and \e S''. These arrays should not be altered or + * destroyed during the lifetime of a SphericalHarmonic object. + **********************************************************************/ + SphericalHarmonic2(const std::vector& C, + const std::vector& S, + int N, + const std::vector& C1, + const std::vector& S1, + int N1, + const std::vector& C2, + const std::vector& S2, + int N2, + real a, unsigned norm = FULL) + : _a(a) + , _norm(norm) { + if (!(N1 <= N && N2 <= N)) + throw GeographicErr("N1 and N2 cannot be larger that N"); + _c[0] = SphericalEngine::coeff(C, S, N); + _c[1] = SphericalEngine::coeff(C1, S1, N1); + _c[2] = SphericalEngine::coeff(C2, S2, N2); + } + + /** + * Constructor with a subset of coefficients specified. + * + * @param[in] C the coefficients Cnm. + * @param[in] S the coefficients Snm. + * @param[in] N the degree used to determine the layout of \e C and \e S. + * @param[in] nmx the maximum degree used in the sum. The sum over \e n is + * from 0 thru \e nmx. + * @param[in] mmx the maximum order used in the sum. The sum over \e m is + * from 0 thru min(\e n, \e mmx). + * @param[in] C1 the coefficients C'nm. + * @param[in] S1 the coefficients S'nm. + * @param[in] N1 the degree used to determine the layout of \e C' and \e + * S'. + * @param[in] nmx1 the maximum degree used for \e C' and \e S'. + * @param[in] mmx1 the maximum order used for \e C' and \e S'. + * @param[in] C2 the coefficients C''nm. + * @param[in] S2 the coefficients S''nm. + * @param[in] N2 the degree used to determine the layout of \e C'' and \e + * S''. + * @param[in] nmx2 the maximum degree used for \e C'' and \e S''. + * @param[in] mmx2 the maximum order used for \e C'' and \e S''. + * @param[in] a the reference radius appearing in the definition of the + * sum. + * @param[in] norm the normalization for the associated Legendre + * polynomials, either SphericalHarmonic2::FULL (the default) or + * SphericalHarmonic2::SCHMIDT. + * @exception GeographicErr if the parameters do not satisfy \e N ≥ \e + * nmx ≥ \e mmx ≥ −1; \e N1 ≥ \e nmx1 ≥ \e mmx1 ≥ + * −1; \e N ≥ \e N1; \e nmx ≥ \e nmx1; \e mmx ≥ \e mmx1; + * and similarly for \e N2, \e nmx2, and \e mmx2. + * @exception GeographicErr if any of the vectors of coefficients is not + * large enough. + * + * The class stores pointers to the first elements of \e C, \e S, \e + * C', \e S', \e C'', and \e S''. These arrays should not be altered or + * destroyed during the lifetime of a SphericalHarmonic object. + **********************************************************************/ + SphericalHarmonic2(const std::vector& C, + const std::vector& S, + int N, int nmx, int mmx, + const std::vector& C1, + const std::vector& S1, + int N1, int nmx1, int mmx1, + const std::vector& C2, + const std::vector& S2, + int N2, int nmx2, int mmx2, + real a, unsigned norm = FULL) + : _a(a) + , _norm(norm) { + if (!(nmx1 <= nmx && nmx2 <= nmx)) + throw GeographicErr("nmx1 and nmx2 cannot be larger that nmx"); + if (!(mmx1 <= mmx && mmx2 <= mmx)) + throw GeographicErr("mmx1 and mmx2 cannot be larger that mmx"); + _c[0] = SphericalEngine::coeff(C, S, N, nmx, mmx); + _c[1] = SphericalEngine::coeff(C1, S1, N1, nmx1, mmx1); + _c[2] = SphericalEngine::coeff(C2, S2, N2, nmx2, mmx2); + } + + /** + * A default constructor so that the object can be created when the + * constructor for another object is initialized. This default object can + * then be reset with the default copy assignment operator. + **********************************************************************/ + SphericalHarmonic2() {} + + /** + * Compute a spherical harmonic sum with two correction terms. + * + * @param[in] tau1 multiplier for correction coefficients \e C' and \e S'. + * @param[in] tau2 multiplier for correction coefficients \e C'' and \e + * S''. + * @param[in] x cartesian coordinate. + * @param[in] y cartesian coordinate. + * @param[in] z cartesian coordinate. + * @return \e V the spherical harmonic sum. + * + * This routine requires constant memory and thus never throws an + * exception. + **********************************************************************/ + Math::real operator()(real tau1, real tau2, real x, real y, real z) + const { + real f[] = {1, tau1, tau2}; + real v = 0; + real dummy; + switch (_norm) { + case FULL: + v = SphericalEngine::Value + (_c, f, x, y, z, _a, dummy, dummy, dummy); + break; + case SCHMIDT: + default: // To avoid compiler warnings + v = SphericalEngine::Value + (_c, f, x, y, z, _a, dummy, dummy, dummy); + break; + } + return v; + } + + /** + * Compute a spherical harmonic sum with two correction terms and its + * gradient. + * + * @param[in] tau1 multiplier for correction coefficients \e C' and \e S'. + * @param[in] tau2 multiplier for correction coefficients \e C'' and \e + * S''. + * @param[in] x cartesian coordinate. + * @param[in] y cartesian coordinate. + * @param[in] z cartesian coordinate. + * @param[out] gradx \e x component of the gradient + * @param[out] grady \e y component of the gradient + * @param[out] gradz \e z component of the gradient + * @return \e V the spherical harmonic sum. + * + * This is the same as the previous function, except that the components of + * the gradients of the sum in the \e x, \e y, and \e z directions are + * computed. This routine requires constant memory and thus never throws + * an exception. + **********************************************************************/ + Math::real operator()(real tau1, real tau2, real x, real y, real z, + real& gradx, real& grady, real& gradz) const { + real f[] = {1, tau1, tau2}; + real v = 0; + switch (_norm) { + case FULL: + v = SphericalEngine::Value + (_c, f, x, y, z, _a, gradx, grady, gradz); + break; + case SCHMIDT: + default: // To avoid compiler warnings + v = SphericalEngine::Value + (_c, f, x, y, z, _a, gradx, grady, gradz); + break; + } + return v; + } + + /** + * Create a CircularEngine to allow the efficient evaluation of several + * points on a circle of latitude at fixed values of \e tau1 and \e tau2. + * + * @param[in] tau1 multiplier for correction coefficients \e C' and \e S'. + * @param[in] tau2 multiplier for correction coefficients \e C'' and \e + * S''. + * @param[in] p the radius of the circle. + * @param[in] z the height of the circle above the equatorial plane. + * @param[in] gradp if true the returned object will be able to compute the + * gradient of the sum. + * @exception std::bad_alloc if the memory for the CircularEngine can't be + * allocated. + * @return the CircularEngine object. + * + * SphericalHarmonic2::operator()() exchanges the order of the sums in the + * definition, i.e., ∑n = 0..N + * ∑m = 0..n becomes ∑m = + * 0..Nn = m..N.. + * SphericalHarmonic2::Circle performs the inner sum over degree \e n + * (which entails about N2 operations). Calling + * CircularEngine::operator()() on the returned object performs the outer + * sum over the order \e m (about \e N operations). + * + * See SphericalHarmonic::Circle for an example of its use. + **********************************************************************/ + CircularEngine Circle(real tau1, real tau2, real p, real z, bool gradp) + const { + real f[] = {1, tau1, tau2}; + switch (_norm) { + case FULL: + return gradp ? + SphericalEngine::Circle + (_c, f, p, z, _a) : + SphericalEngine::Circle + (_c, f, p, z, _a); + break; + case SCHMIDT: + default: // To avoid compiler warnings + return gradp ? + SphericalEngine::Circle + (_c, f, p, z, _a) : + SphericalEngine::Circle + (_c, f, p, z, _a); + break; + } + } + + /** + * @return the zeroth SphericalEngine::coeff object. + **********************************************************************/ + const SphericalEngine::coeff& Coefficients() const + { return _c[0]; } + /** + * @return the first SphericalEngine::coeff object. + **********************************************************************/ + const SphericalEngine::coeff& Coefficients1() const + { return _c[1]; } + /** + * @return the second SphericalEngine::coeff object. + **********************************************************************/ + const SphericalEngine::coeff& Coefficients2() const + { return _c[2]; } + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_SPHERICALHARMONIC2_HPP diff --git a/external/include/GeographicLib/TransverseMercator.hpp b/external/include/GeographicLib/TransverseMercator.hpp new file mode 100644 index 0000000..2eed3dc --- /dev/null +++ b/external/include/GeographicLib/TransverseMercator.hpp @@ -0,0 +1,206 @@ +/** + * \file TransverseMercator.hpp + * \brief Header for GeographicLib::TransverseMercator class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP) +#define GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP 1 + +#include + +#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER) +/** + * The order of the series approximation used in TransverseMercator. + * GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER can be set to any integer in [4, 8]. + **********************************************************************/ +# define GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER \ + (GEOGRAPHICLIB_PRECISION == 2 ? 6 : \ + (GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8)) +#endif + +namespace GeographicLib { + + /** + * \brief Transverse Mercator projection + * + * This uses Krüger's method which evaluates the projection and its + * inverse in terms of a series. See + * - L. Krüger, + * Konforme + * Abbildung des Erdellipsoids in der Ebene (Conformal mapping of the + * ellipsoidal earth to the plane), Royal Prussian Geodetic Institute, New + * Series 52, 172 pp. (1912). + * - C. F. F. Karney, + * + * Transverse Mercator with an accuracy of a few nanometers, + * J. Geodesy 85(8), 475--485 (Aug. 2011); + * preprint + * arXiv:1002.1417. + * + * Krüger's method has been extended from 4th to 6th order. The maximum + * error is 5 nm (5 nanometers), ground distance, for all positions within 35 + * degrees of the central meridian. The error in the convergence is 2 + * × 10−15" and the relative error in the scale + * is 6 × 10−12%%. See Sec. 4 of + * arXiv:1002.1417 for details. + * The speed penalty in going to 6th order is only about 1%. + * + * There's a singularity in the projection at φ = 0°, λ + * − λ0 = ±(1 − \e e)90° (≈ + * ±82.6° for the WGS84 ellipsoid), where \e e is the + * eccentricity. Beyond this point, the series ceases to converge and the + * results from this method will be garbage. To be on the safe side, don't + * use this method if the angular distance from the central meridian exceeds + * (1 − 2e)90° (≈ 75° for the WGS84 ellipsoid) + * + * TransverseMercatorExact is an alternative implementation of the projection + * using exact formulas which yield accurate (to 8 nm) results over the + * entire ellipsoid. + * + * The ellipsoid parameters and the central scale are set in the constructor. + * The central meridian (which is a trivial shift of the longitude) is + * specified as the \e lon0 argument of the TransverseMercator::Forward and + * TransverseMercator::Reverse functions. The latitude of origin is taken to + * be the equator. There is no provision in this class for specifying a + * false easting or false northing or a different latitude of origin. + * However these are can be simply included by the calling function. For + * example, the UTMUPS class applies the false easting and false northing for + * the UTM projections. A more complicated example is the British National + * Grid ( + * EPSG:7405) which requires the use of a latitude of origin. This is + * implemented by the GeographicLib::OSGB class. + * + * This class also returns the meridian convergence \e gamma and scale \e k. + * The meridian convergence is the bearing of grid north (the \e y axis) + * measured clockwise from true north. + * + * See TransverseMercator.cpp for more information on the implementation. + * + * See \ref transversemercator for a discussion of this projection. + * + * Example of use: + * \include example-TransverseMercator.cpp + * + * TransverseMercatorProj is a + * command-line utility providing access to the functionality of + * TransverseMercator and TransverseMercatorExact. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT TransverseMercator { + private: + typedef Math::real real; + static const int maxpow_ = GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER; + static const int numit_ = 5; + real _a, _f, _k0, _e2, _es, _e2m, _c, _n; + // _alp[0] and _bet[0] unused + real _a1, _b1, _alp[maxpow_ + 1], _bet[maxpow_ + 1]; + friend class Ellipsoid; // For access to taupf, tauf. + public: + + /** + * Constructor for a ellipsoid with + * + * @param[in] a equatorial radius (meters). + * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere. + * Negative \e f gives a prolate ellipsoid. + * @param[in] k0 central scale factor. + * @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k0 is + * not positive. + **********************************************************************/ + TransverseMercator(real a, real f, real k0); + + /** + * Forward projection, from geographic to transverse Mercator. + * + * @param[in] lon0 central meridian of the projection (degrees). + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * No false easting or northing is added. \e lat should be in the range + * [−90°, 90°]. + **********************************************************************/ + void Forward(real lon0, real lat, real lon, + real& x, real& y, real& gamma, real& k) const; + + /** + * Reverse projection, from transverse Mercator to geographic. + * + * @param[in] lon0 central meridian of the projection (degrees). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * No false easting or northing is added. The value of \e lon returned is + * in the range [−180°, 180°]. + **********************************************************************/ + void Reverse(real lon0, real x, real y, + real& lat, real& lon, real& gamma, real& k) const; + + /** + * TransverseMercator::Forward without returning the convergence and scale. + **********************************************************************/ + void Forward(real lon0, real lat, real lon, + real& x, real& y) const { + real gamma, k; + Forward(lon0, lat, lon, x, y, gamma, k); + } + + /** + * TransverseMercator::Reverse without returning the convergence and scale. + **********************************************************************/ + void Reverse(real lon0, real x, real y, + real& lat, real& lon) const { + real gamma, k; + Reverse(lon0, x, y, lat, lon, gamma, k); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _a; } + + /** + * @return \e f the flattening of the ellipsoid. This is the value used in + * the constructor. + **********************************************************************/ + Math::real Flattening() const { return _f; } + + /** + * @return \e k0 central scale for the projection. This is the value of \e + * k0 used in the constructor and is the scale on the central meridian. + **********************************************************************/ + Math::real CentralScale() const { return _k0; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of TransverseMercator with the WGS84 ellipsoid + * and the UTM scale factor. However, unlike UTM, no false easting or + * northing is added. + **********************************************************************/ + static const TransverseMercator& UTM(); + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP diff --git a/external/include/GeographicLib/TransverseMercatorExact.hpp b/external/include/GeographicLib/TransverseMercatorExact.hpp new file mode 100644 index 0000000..d81f0c8 --- /dev/null +++ b/external/include/GeographicLib/TransverseMercatorExact.hpp @@ -0,0 +1,264 @@ +/** + * \file TransverseMercatorExact.hpp + * \brief Header for GeographicLib::TransverseMercatorExact class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP) +#define GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP 1 + +#include +#include + +namespace GeographicLib { + + /** + * \brief An exact implementation of the transverse Mercator projection + * + * Implementation of the Transverse Mercator Projection given in + * - L. P. Lee, + * Conformal + * Projections Based On Jacobian Elliptic Functions, Part V of + * Conformal Projections Based on Elliptic Functions, + * (B. V. Gutsell, Toronto, 1976), 128pp., + * ISBN: 0919870163 + * (also appeared as: + * Monograph 16, Suppl. No. 1 to Canadian Cartographer, Vol 13). + * - C. F. F. Karney, + * + * Transverse Mercator with an accuracy of a few nanometers, + * J. Geodesy 85(8), 475--485 (Aug. 2011); + * preprint + * arXiv:1002.1417. + * + * Lee gives the correct results for forward and reverse transformations + * subject to the branch cut rules (see the description of the \e extendp + * argument to the constructor). The maximum error is about 8 nm (8 + * nanometers), ground distance, for the forward and reverse transformations. + * The error in the convergence is 2 × 10−15", + * the relative error in the scale is 7 × 10−12%%. + * See Sec. 3 of + * arXiv:1002.1417 for details. + * The method is "exact" in the sense that the errors are close to the + * round-off limit and that no changes are needed in the algorithms for them + * to be used with reals of a higher precision. Thus the errors using long + * double (with a 64-bit fraction) are about 2000 times smaller than using + * double (with a 53-bit fraction). + * + * This algorithm is about 4.5 times slower than the 6th-order Krüger + * method, TransverseMercator, taking about 11 us for a combined forward and + * reverse projection on a 2.66 GHz Intel machine (g++, version 4.3.0, -O3). + * + * The ellipsoid parameters and the central scale are set in the constructor. + * The central meridian (which is a trivial shift of the longitude) is + * specified as the \e lon0 argument of the TransverseMercatorExact::Forward + * and TransverseMercatorExact::Reverse functions. The latitude of origin is + * taken to be the equator. See the documentation on TransverseMercator for + * how to include a false easting, false northing, or a latitude of origin. + * + * See tm-grid.kmz, for an + * illustration of the transverse Mercator grid in Google Earth. + * + * This class also returns the meridian convergence \e gamma and scale \e k. + * The meridian convergence is the bearing of grid north (the \e y axis) + * measured clockwise from true north. + * + * See TransverseMercatorExact.cpp for more information on the + * implementation. + * + * See \ref transversemercator for a discussion of this projection. + * + * Example of use: + * \include example-TransverseMercatorExact.cpp + * + * TransverseMercatorProj is a + * command-line utility providing access to the functionality of + * TransverseMercator and TransverseMercatorExact. + **********************************************************************/ + + class GEOGRAPHICLIB_EXPORT TransverseMercatorExact { + private: + typedef Math::real real; + static const int numit_ = 10; + real tol_, tol2_, taytol_; + real _a, _f, _k0, _mu, _mv, _e; + bool _extendp; + EllipticFunction _Eu, _Ev; + + void zeta(real u, real snu, real cnu, real dnu, + real v, real snv, real cnv, real dnv, + real& taup, real& lam) const; + + void dwdzeta(real u, real snu, real cnu, real dnu, + real v, real snv, real cnv, real dnv, + real& du, real& dv) const; + + bool zetainv0(real psi, real lam, real& u, real& v) const; + void zetainv(real taup, real lam, real& u, real& v) const; + + void sigma(real u, real snu, real cnu, real dnu, + real v, real snv, real cnv, real dnv, + real& xi, real& eta) const; + + void dwdsigma(real u, real snu, real cnu, real dnu, + real v, real snv, real cnv, real dnv, + real& du, real& dv) const; + + bool sigmainv0(real xi, real eta, real& u, real& v) const; + void sigmainv(real xi, real eta, real& u, real& v) const; + + void Scale(real tau, real lam, + real snu, real cnu, real dnu, + real snv, real cnv, real dnv, + real& gamma, real& k) const; + + public: + + /** + * Constructor for a ellipsoid with + * + * @param[in] a equatorial radius (meters). + * @param[in] f flattening of ellipsoid. + * @param[in] k0 central scale factor. + * @param[in] extendp use extended domain. + * @exception GeographicErr if \e a, \e f, or \e k0 is not positive. + * + * The transverse Mercator projection has a branch point singularity at \e + * lat = 0 and \e lon − \e lon0 = 90 (1 − \e e) or (for + * TransverseMercatorExact::UTM) x = 18381 km, y = 0m. The \e extendp + * argument governs where the branch cut is placed. With \e extendp = + * false, the "standard" convention is followed, namely the cut is placed + * along \e x > 18381 km, \e y = 0m. Forward can be called with any \e lat + * and \e lon then produces the transformation shown in Lee, Fig 46. + * Reverse analytically continues this in the ± \e x direction. As + * a consequence, Reverse may map multiple points to the same geographic + * location; for example, for TransverseMercatorExact::UTM, \e x = + * 22051449.037349 m, \e y = −7131237.022729 m and \e x = + * 29735142.378357 m, \e y = 4235043.607933 m both map to \e lat = + * −2°, \e lon = 88°. + * + * With \e extendp = true, the branch cut is moved to the lower left + * quadrant. The various symmetries of the transverse Mercator projection + * can be used to explore the projection on any sheet. In this mode the + * domains of \e lat, \e lon, \e x, and \e y are restricted to + * - the union of + * - \e lat in [0, 90] and \e lon − \e lon0 in [0, 90] + * - \e lat in (-90, 0] and \e lon − \e lon0 in [90 (1 − \e + e), 90] + * - the union of + * - x/(\e k0 \e a) in [0, ∞) and + * y/(\e k0 \e a) in [0, E(e2)] + * - x/(\e k0 \e a) in [K(1 − e2) − + * E(1 − e2), ∞) and y/(\e k0 \e + * a) in (−∞, 0] + * . + * See Sec. 5 of + * arXiv:1002.1417 for a full + * discussion of the treatment of the branch cut. + * + * The method will work for all ellipsoids used in terrestrial geodesy. + * The method cannot be applied directly to the case of a sphere (\e f = 0) + * because some the constants characterizing this method diverge in that + * limit, and in practice, \e f should be larger than about + * numeric_limits::epsilon(). However, TransverseMercator treats the + * sphere exactly. + **********************************************************************/ + TransverseMercatorExact(real a, real f, real k0, bool extendp = false); + + /** + * Forward projection, from geographic to transverse Mercator. + * + * @param[in] lon0 central meridian of the projection (degrees). + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * No false easting or northing is added. \e lat should be in the range + * [−90°, 90°]. + **********************************************************************/ + void Forward(real lon0, real lat, real lon, + real& x, real& y, real& gamma, real& k) const; + + /** + * Reverse projection, from transverse Mercator to geographic. + * + * @param[in] lon0 central meridian of the projection (degrees). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * + * No false easting or northing is added. The value of \e lon returned is + * in the range [−180°, 180°]. + **********************************************************************/ + void Reverse(real lon0, real x, real y, + real& lat, real& lon, real& gamma, real& k) const; + + /** + * TransverseMercatorExact::Forward without returning the convergence and + * scale. + **********************************************************************/ + void Forward(real lon0, real lat, real lon, + real& x, real& y) const { + real gamma, k; + Forward(lon0, lat, lon, x, y, gamma, k); + } + + /** + * TransverseMercatorExact::Reverse without returning the convergence and + * scale. + **********************************************************************/ + void Reverse(real lon0, real x, real y, + real& lat, real& lon) const { + real gamma, k; + Reverse(lon0, x, y, lat, lon, gamma, k); + } + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the ellipsoid (meters). This is + * the value used in the constructor. + **********************************************************************/ + Math::real EquatorialRadius() const { return _a; } + + /** + * @return \e f the flattening of the ellipsoid. This is the value used in + * the constructor. + **********************************************************************/ + Math::real Flattening() const { return _f; } + + /** + * @return \e k0 central scale for the projection. This is the value of \e + * k0 used in the constructor and is the scale on the central meridian. + **********************************************************************/ + Math::real CentralScale() const { return _k0; } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + Math::real MajorRadius() const { return EquatorialRadius(); } + ///@} + + /** + * A global instantiation of TransverseMercatorExact with the WGS84 + * ellipsoid and the UTM scale factor. However, unlike UTM, no false + * easting or northing is added. + **********************************************************************/ + static const TransverseMercatorExact& UTM(); + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP diff --git a/external/include/GeographicLib/UTMUPS.hpp b/external/include/GeographicLib/UTMUPS.hpp new file mode 100644 index 0000000..e949ee9 --- /dev/null +++ b/external/include/GeographicLib/UTMUPS.hpp @@ -0,0 +1,428 @@ +/** + * \file UTMUPS.hpp + * \brief Header for GeographicLib::UTMUPS class + * + * Copyright (c) Charles Karney (2008-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_UTMUPS_HPP) +#define GEOGRAPHICLIB_UTMUPS_HPP 1 + +#include + +namespace GeographicLib { + + /** + * \brief Convert between geographic coordinates and UTM/UPS + * + * UTM and UPS are defined + * - J. W. Hager, J. F. Behensky, and B. W. Drew, + * + * The Universal Grids: Universal Transverse Mercator (UTM) and Universal + * Polar Stereographic (UPS), Defense Mapping Agency, Technical Manual + * TM8358.2 (1989). + * . + * Section 2-3 defines UTM and section 3-2.4 defines UPS. This document also + * includes approximate algorithms for the computation of the underlying + * transverse Mercator and polar stereographic projections. Here we + * substitute much more accurate algorithms given by + * GeographicLib:TransverseMercator and GeographicLib:PolarStereographic. + * These are the algorithms recommended by the NGA document + * - + * The Universal Grids and the Transverse Mercator and Polar Stereographic + * Map Projections, NGA.SIG.0012 (2014). + * + * In this implementation, the conversions are closed, i.e., output from + * Forward is legal input for Reverse and vice versa. The error is about 5nm + * in each direction. However, the conversion from legal UTM/UPS coordinates + * to geographic coordinates and back might throw an error if the initial + * point is within 5nm of the edge of the allowed range for the UTM/UPS + * coordinates. + * + * The simplest way to guarantee the closed property is to define allowed + * ranges for the eastings and northings for UTM and UPS coordinates. The + * UTM boundaries are the same for all zones. (The only place the + * exceptional nature of the zone boundaries is evident is when converting to + * UTM/UPS coordinates requesting the standard zone.) The MGRS lettering + * scheme imposes natural limits on UTM/UPS coordinates which may be + * converted into MGRS coordinates. For the conversion to/from geographic + * coordinates these ranges have been extended by 100km in order to provide a + * generous overlap between UTM and UPS and between UTM zones. + * + * The NGA software package + * geotrans + * also provides conversions to and from UTM and UPS. Version 2.4.2 (and + * earlier) suffers from some drawbacks: + * - Inconsistent rules are used to determine the whether a particular UTM or + * UPS coordinate is legal. A more systematic approach is taken here. + * - The underlying projections are not very accurately implemented. + * + * The GeographicLib::UTMUPS::EncodeZone encodes the UTM zone and hemisphere + * to allow UTM/UPS coordinated to be displayed as, for example, "38N 444500 + * 3688500". According to NGA.SIG.0012_2.0.0_UTMUPS the use of "N" to denote + * "north" in the context is not allowed (since a upper case letter in this + * context denotes the MGRS latitude band). Consequently, as of version + * 1.36, EncodeZone uses the lower case letters "n" and "s" to denote the + * hemisphere. In addition EncodeZone accepts an optional final argument \e + * abbrev, which, if false, results in the hemisphere being spelled out as in + * "38north". + * + * Example of use: + * \include example-UTMUPS.cpp + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT UTMUPS { + private: + typedef Math::real real; + static const int falseeasting_[4]; + static const int falsenorthing_[4]; + static const int mineasting_[4]; + static const int maxeasting_[4]; + static const int minnorthing_[4]; + static const int maxnorthing_[4]; + static const int epsg01N = 32601; // EPSG code for UTM 01N + static const int epsg60N = 32660; // EPSG code for UTM 60N + static const int epsgN = 32661; // EPSG code for UPS N + static const int epsg01S = 32701; // EPSG code for UTM 01S + static const int epsg60S = 32760; // EPSG code for UTM 60S + static const int epsgS = 32761; // EPSG code for UPS S + static real CentralMeridian(int zone) + { return real(6 * zone - 183); } + // Throw an error if easting or northing are outside standard ranges. If + // throwp = false, return bool instead. + static bool CheckCoords(bool utmp, bool northp, real x, real y, + bool msgrlimits = false, bool throwp = true); + UTMUPS(); // Disable constructor + + public: + + /** + * In this class we bring together the UTM and UPS coordinates systems. + * The UTM divides the earth between latitudes −80° and 84° + * into 60 zones numbered 1 thru 60. Zone assign zone number 0 to the UPS + * regions, covering the two poles. Within UTMUPS, non-negative zone + * numbers refer to one of the "physical" zones, 0 for UPS and [1, 60] for + * UTM. Negative "pseudo-zone" numbers are used to select one of the + * physical zones. + **********************************************************************/ + enum zonespec { + /** + * The smallest pseudo-zone number. + **********************************************************************/ + MINPSEUDOZONE = -4, + /** + * A marker for an undefined or invalid zone. Equivalent to NaN. + **********************************************************************/ + INVALID = -4, + /** + * If a coordinate already include zone information (e.g., it is an MGRS + * coordinate), use that, otherwise apply the UTMUPS::STANDARD rules. + **********************************************************************/ + MATCH = -3, + /** + * Apply the standard rules for UTM zone assigment extending the UTM zone + * to each pole to give a zone number in [1, 60]. For example, use UTM + * zone 38 for longitude in [42°, 48°). The rules include the + * Norway and Svalbard exceptions. + **********************************************************************/ + UTM = -2, + /** + * Apply the standard rules for zone assignment to give a zone number in + * [0, 60]. If the latitude is not in [−80°, 84°), then + * use UTMUPS::UPS = 0, otherwise apply the rules for UTMUPS::UTM. The + * tests on latitudes and longitudes are all closed on the lower end open + * on the upper. Thus for UTM zone 38, latitude is in [−80°, + * 84°) and longitude is in [42°, 48°). + **********************************************************************/ + STANDARD = -1, + /** + * The largest pseudo-zone number. + **********************************************************************/ + MAXPSEUDOZONE = -1, + /** + * The smallest physical zone number. + **********************************************************************/ + MINZONE = 0, + /** + * The zone number used for UPS + **********************************************************************/ + UPS = 0, + /** + * The smallest UTM zone number. + **********************************************************************/ + MINUTMZONE = 1, + /** + * The largest UTM zone number. + **********************************************************************/ + MAXUTMZONE = 60, + /** + * The largest physical zone number. + **********************************************************************/ + MAXZONE = 60, + }; + + /** + * The standard zone. + * + * @param[in] lat latitude (degrees). + * @param[in] lon longitude (degrees). + * @param[in] setzone zone override (optional). If omitted, use the + * standard rules for picking the zone. If \e setzone is given then use + * that zone if it is non-negative, otherwise apply the rules given in + * UTMUPS::zonespec. + * @exception GeographicErr if \e setzone is outside the range + * [UTMUPS::MINPSEUDOZONE, UTMUPS::MAXZONE] = [−4, 60]. + * + * This is exact. + **********************************************************************/ + static int StandardZone(real lat, real lon, int setzone = STANDARD); + + /** + * Forward projection, from geographic to UTM/UPS. + * + * @param[in] lat latitude of point (degrees). + * @param[in] lon longitude of point (degrees). + * @param[out] zone the UTM zone (zero means UPS). + * @param[out] northp hemisphere (true means north, false means south). + * @param[out] x easting of point (meters). + * @param[out] y northing of point (meters). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * @param[in] setzone zone override (optional). + * @param[in] mgrslimits if true enforce the stricter MGRS limits on the + * coordinates (default = false). + * @exception GeographicErr if \e lat is not in [−90°, + * 90°]. + * @exception GeographicErr if the resulting \e x or \e y is out of allowed + * range (see Reverse); in this case, these arguments are unchanged. + * + * If \e setzone is omitted, use the standard rules for picking the zone. + * If \e setzone is given then use that zone if it is non-negative, + * otherwise apply the rules given in UTMUPS::zonespec. The accuracy of + * the conversion is about 5nm. + * + * The northing \e y jumps by UTMUPS::UTMShift() when crossing the equator + * in the southerly direction. Sometimes it is useful to remove this + * discontinuity in \e y by extending the "northern" hemisphere using + * UTMUPS::Transfer: + * \code + double lat = -1, lon = 123; + int zone; + bool northp; + double x, y, gamma, k; + GeographicLib::UTMUPS::Forward(lat, lon, zone, northp, x, y, gamma, k); + GeographicLib::UTMUPS::Transfer(zone, northp, x, y, + zone, true, x, y, zone); + northp = true; + \endcode + **********************************************************************/ + static void Forward(real lat, real lon, + int& zone, bool& northp, real& x, real& y, + real& gamma, real& k, + int setzone = STANDARD, bool mgrslimits = false); + + /** + * Reverse projection, from UTM/UPS to geographic. + * + * @param[in] zone the UTM zone (zero means UPS). + * @param[in] northp hemisphere (true means north, false means south). + * @param[in] x easting of point (meters). + * @param[in] y northing of point (meters). + * @param[out] lat latitude of point (degrees). + * @param[out] lon longitude of point (degrees). + * @param[out] gamma meridian convergence at point (degrees). + * @param[out] k scale of projection at point. + * @param[in] mgrslimits if true enforce the stricter MGRS limits on the + * coordinates (default = false). + * @exception GeographicErr if \e zone, \e x, or \e y is out of allowed + * range; this this case the arguments are unchanged. + * + * The accuracy of the conversion is about 5nm. + * + * UTM eastings are allowed to be in the range [0km, 1000km], northings are + * allowed to be in in [0km, 9600km] for the northern hemisphere and in + * [900km, 10000km] for the southern hemisphere. However UTM northings + * can be continued across the equator. So the actual limits on the + * northings are [-9100km, 9600km] for the "northern" hemisphere and + * [900km, 19600km] for the "southern" hemisphere. + * + * UPS eastings and northings are allowed to be in the range [1200km, + * 2800km] in the northern hemisphere and in [700km, 3300km] in the + * southern hemisphere. + * + * These ranges are 100km larger than allowed for the conversions to MGRS. + * (100km is the maximum extra padding consistent with eastings remaining + * non-negative.) This allows generous overlaps between zones and UTM and + * UPS. If \e mgrslimits = true, then all the ranges are shrunk by 100km + * so that they agree with the stricter MGRS ranges. No checks are + * performed besides these (e.g., to limit the distance outside the + * standard zone boundaries). + **********************************************************************/ + static void Reverse(int zone, bool northp, real x, real y, + real& lat, real& lon, real& gamma, real& k, + bool mgrslimits = false); + + /** + * UTMUPS::Forward without returning convergence and scale. + **********************************************************************/ + static void Forward(real lat, real lon, + int& zone, bool& northp, real& x, real& y, + int setzone = STANDARD, bool mgrslimits = false) { + real gamma, k; + Forward(lat, lon, zone, northp, x, y, gamma, k, setzone, mgrslimits); + } + + /** + * UTMUPS::Reverse without returning convergence and scale. + **********************************************************************/ + static void Reverse(int zone, bool northp, real x, real y, + real& lat, real& lon, bool mgrslimits = false) { + real gamma, k; + Reverse(zone, northp, x, y, lat, lon, gamma, k, mgrslimits); + } + + /** + * Transfer UTM/UPS coordinated from one zone to another. + * + * @param[in] zonein the UTM zone for \e xin and \e yin (or zero for UPS). + * @param[in] northpin hemisphere for \e xin and \e yin (true means north, + * false means south). + * @param[in] xin easting of point (meters) in \e zonein. + * @param[in] yin northing of point (meters) in \e zonein. + * @param[in] zoneout the requested UTM zone for \e xout and \e yout (or + * zero for UPS). + * @param[in] northpout hemisphere for \e xout output and \e yout. + * @param[out] xout easting of point (meters) in \e zoneout. + * @param[out] yout northing of point (meters) in \e zoneout. + * @param[out] zone the actual UTM zone for \e xout and \e yout (or zero + * for UPS); this equals \e zoneout if \e zoneout ≥ 0. + * @exception GeographicErr if \e zonein is out of range (see below). + * @exception GeographicErr if \e zoneout is out of range (see below). + * @exception GeographicErr if \e xin or \e yin fall outside their allowed + * ranges (see UTMUPS::Reverse). + * @exception GeographicErr if \e xout or \e yout fall outside their + * allowed ranges (see UTMUPS::Reverse). + * + * \e zonein must be in the range [UTMUPS::MINZONE, UTMUPS::MAXZONE] = [0, + * 60] with \e zonein = UTMUPS::UPS, 0, indicating UPS. \e zonein may + * also be UTMUPS::INVALID. + * + * \e zoneout must be in the range [UTMUPS::MINPSEUDOZONE, UTMUPS::MAXZONE] + * = [-4, 60]. If \e zoneout < UTMUPS::MINZONE then the rules give in + * the documentation of UTMUPS::zonespec are applied, and \e zone is set to + * the actual zone used for output. + * + * (\e xout, \e yout) can overlap with (\e xin, \e yin). + **********************************************************************/ + static void Transfer(int zonein, bool northpin, real xin, real yin, + int zoneout, bool northpout, real& xout, real& yout, + int& zone); + + /** + * Decode a UTM/UPS zone string. + * + * @param[in] zonestr string representation of zone and hemisphere. + * @param[out] zone the UTM zone (zero means UPS). + * @param[out] northp hemisphere (true means north, false means south). + * @exception GeographicErr if \e zonestr is malformed. + * + * For UTM, \e zonestr has the form of a zone number in the range + * [UTMUPS::MINUTMZONE, UTMUPS::MAXUTMZONE] = [1, 60] followed by a + * hemisphere letter, n or s (or "north" or "south" spelled out). For UPS, + * it consists just of the hemisphere letter (or the spelled out + * hemisphere). The returned value of \e zone is UTMUPS::UPS = 0 for UPS. + * Note well that "38s" indicates the southern hemisphere of zone 38 and + * not latitude band S, 32° ≤ \e lat < 40°. n, 01s, 2n, 38s, + * south, 3north are legal. 0n, 001s, +3n, 61n, 38P are illegal. INV is a + * special value for which the returned value of \e is UTMUPS::INVALID. + **********************************************************************/ + static void DecodeZone(const std::string& zonestr, + int& zone, bool& northp); + + /** + * Encode a UTM/UPS zone string. + * + * @param[in] zone the UTM zone (zero means UPS). + * @param[in] northp hemisphere (true means north, false means south). + * @param[in] abbrev if true (the default) use abbreviated (n/s) notation + * for hemisphere; otherwise spell out the hemisphere (north/south) + * @exception GeographicErr if \e zone is out of range (see below). + * @exception std::bad_alloc if memoy for the string can't be allocated. + * @return string representation of zone and hemisphere. + * + * \e zone must be in the range [UTMUPS::MINZONE, UTMUPS::MAXZONE] = [0, + * 60] with \e zone = UTMUPS::UPS, 0, indicating UPS (but the resulting + * string does not contain "0"). \e zone may also be UTMUPS::INVALID, in + * which case the returned string is "inv". This reverses + * UTMUPS::DecodeZone. + **********************************************************************/ + static std::string EncodeZone(int zone, bool northp, bool abbrev = true); + + /** + * Decode EPSG. + * + * @param[in] epsg the EPSG code. + * @param[out] zone the UTM zone (zero means UPS). + * @param[out] northp hemisphere (true means north, false means south). + * + * EPSG (European Petroleum Survery Group) codes are a way to refer to many + * different projections. DecodeEPSG decodes those referring to UTM or UPS + * projections for the WGS84 ellipsoid. If the code does not refer to one + * of these projections, \e zone is set to UTMUPS::INVALID. See + * https://www.spatialreference.org/ref/epsg/ + **********************************************************************/ + static void DecodeEPSG(int epsg, int& zone, bool& northp); + + /** + * Encode zone as EPSG. + * + * @param[in] zone the UTM zone (zero means UPS). + * @param[in] northp hemisphere (true means north, false means south). + * @return EPSG code (or -1 if \e zone is not in the range + * [UTMUPS::MINZONE, UTMUPS::MAXZONE] = [0, 60]) + * + * Convert \e zone and \e northp to the corresponding EPSG (European + * Petroleum Survery Group) codes + **********************************************************************/ + static int EncodeEPSG(int zone, bool northp); + + /** + * @return shift (meters) necessary to align north and south halves of a + * UTM zone (107). + **********************************************************************/ + static Math::real UTMShift(); + + /** \name Inspector functions + **********************************************************************/ + ///@{ + /** + * @return \e a the equatorial radius of the WGS84 ellipsoid (meters). + * + * (The WGS84 value is returned because the UTM and UPS projections are + * based on this ellipsoid.) + **********************************************************************/ + static Math::real EquatorialRadius() + { return Constants::WGS84_a(); } + + /** + * @return \e f the flattening of the WGS84 ellipsoid. + * + * (The WGS84 value is returned because the UTM and UPS projections are + * based on this ellipsoid.) + **********************************************************************/ + static Math::real Flattening() + { return Constants::WGS84_f(); } + + /** + * \deprecated An old name for EquatorialRadius(). + **********************************************************************/ + GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()") + static Math::real MajorRadius() { return EquatorialRadius(); } + ///@} + + }; + +} // namespace GeographicLib + +#endif // GEOGRAPHICLIB_UTMUPS_HPP diff --git a/external/include/GeographicLib/Utility.hpp b/external/include/GeographicLib/Utility.hpp new file mode 100644 index 0000000..21322bd --- /dev/null +++ b/external/include/GeographicLib/Utility.hpp @@ -0,0 +1,733 @@ +/** + * \file Utility.hpp + * \brief Header for GeographicLib::Utility class + * + * Copyright (c) Charles Karney (2011-2020) and licensed + * under the MIT/X11 License. For more information, see + * https://geographiclib.sourceforge.io/ + **********************************************************************/ + +#if !defined(GEOGRAPHICLIB_UTILITY_HPP) +#define GEOGRAPHICLIB_UTILITY_HPP 1 + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +// Squelch warnings about constant conditional expressions and unsafe gmtime +# pragma warning (push) +# pragma warning (disable: 4127 4996) +#endif + +namespace GeographicLib { + + /** + * \brief Some utility routines for %GeographicLib + * + * Example of use: + * \include example-Utility.cpp + **********************************************************************/ + class GEOGRAPHICLIB_EXPORT Utility { + private: + static bool gregorian(int y, int m, int d) { + // The original cut over to the Gregorian calendar in Pope Gregory XIII's + // time had 1582-10-04 followed by 1582-10-15. Here we implement the + // switch over used by the English-speaking world where 1752-09-02 was + // followed by 1752-09-14. We also assume that the year always begins + // with January 1, whereas in reality it often was reckoned to begin in + // March. + return 100 * (100 * y + m) + d >= 17520914; // or 15821015 + } + static bool gregorian(int s) { + return s >= 639799; // 1752-09-14 + } + public: + + /** + * Convert a date to the day numbering sequentially starting with + * 0001-01-01 as day 1. + * + * @param[in] y the year (must be positive). + * @param[in] m the month, Jan = 1, etc. (must be positive). Default = 1. + * @param[in] d the day of the month (must be positive). Default = 1. + * @return the sequential day number. + **********************************************************************/ + static int day(int y, int m = 1, int d = 1) { + // Convert from date to sequential day and vice versa + // + // Here is some code to convert a date to sequential day and vice + // versa. The sequential day is numbered so that January 1, 1 AD is day 1 + // (a Saturday). So this is offset from the "Julian" day which starts the + // numbering with 4713 BC. + // + // This is inspired by a talk by John Conway at the John von Neumann + // National Supercomputer Center when he described his Doomsday algorithm + // for figuring the day of the week. The code avoids explicitly doing ifs + // (except for the decision of whether to use the Julian or Gregorian + // calendar). Instead the equivalent result is achieved using integer + // arithmetic. I got this idea from the routine for the day of the week + // in MACLisp (I believe that that routine was written by Guy Steele). + // + // There are three issues to take care of + // + // 1. the rules for leap years, + // 2. the inconvenient placement of leap days at the end of February, + // 3. the irregular pattern of month lengths. + // + // We deal with these as follows: + // + // 1. Leap years are given by simple rules which are straightforward to + // accommodate. + // + // 2. We simplify the calculations by moving January and February to the + // previous year. Here we internally number the months March–December, + // January, February as 0–9, 10, 11. + // + // 3. The pattern of month lengths from March through January is regular + // with a 5-month period—31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31. The + // 5-month period is 153 days long. Since February is now at the end of + // the year, we don't need to include its length in this part of the + // calculation. + bool greg = gregorian(y, m, d); + y += (m + 9) / 12 - 1; // Move Jan and Feb to previous year, + m = (m + 9) % 12; // making March month 0. + return + (1461 * y) / 4 // Julian years converted to days. Julian year is 365 + + // 1/4 = 1461/4 days. + // Gregorian leap year corrections. The 2 offset with respect to the + // Julian calendar synchronizes the vernal equinox with that at the + // time of the Council of Nicea (325 AD). + + (greg ? (y / 100) / 4 - (y / 100) + 2 : 0) + + (153 * m + 2) / 5 // The zero-based start of the m'th month + + d - 1 // The zero-based day + - 305; // The number of days between March 1 and December 31. + // This makes 0001-01-01 day 1 + } + + /** + * Convert a date to the day numbering sequentially starting with + * 0001-01-01 as day 1. + * + * @param[in] y the year (must be positive). + * @param[in] m the month, Jan = 1, etc. (must be positive). Default = 1. + * @param[in] d the day of the month (must be positive). Default = 1. + * @param[in] check whether to check the date. + * @exception GeographicErr if the date is invalid and \e check is true. + * @return the sequential day number. + **********************************************************************/ + static int day(int y, int m, int d, bool check) { + int s = day(y, m, d); + if (!check) + return s; + int y1, m1, d1; + date(s, y1, m1, d1); + if (!(s > 0 && y == y1 && m == m1 && d == d1)) + throw GeographicErr("Invalid date " + + str(y) + "-" + str(m) + "-" + str(d) + + (s > 0 ? "; use " + + str(y1) + "-" + str(m1) + "-" + str(d1) : + " before 0001-01-01")); + return s; + } + + /** + * Given a day (counting from 0001-01-01 as day 1), return the date. + * + * @param[in] s the sequential day number (must be positive) + * @param[out] y the year. + * @param[out] m the month, Jan = 1, etc. + * @param[out] d the day of the month. + **********************************************************************/ + static void date(int s, int& y, int& m, int& d) { + int c = 0; + bool greg = gregorian(s); + s += 305; // s = 0 on March 1, 1BC + if (greg) { + s -= 2; // The 2 day Gregorian offset + // Determine century with the Gregorian rules for leap years. The + // Gregorian year is 365 + 1/4 - 1/100 + 1/400 = 146097/400 days. + c = (4 * s + 3) / 146097; + s -= (c * 146097) / 4; // s = 0 at beginning of century + } + y = (4 * s + 3) / 1461; // Determine the year using Julian rules. + s -= (1461 * y) / 4; // s = 0 at start of year, i.e., March 1 + y += c * 100; // Assemble full year + m = (5 * s + 2) / 153; // Determine the month + s -= (153 * m + 2) / 5; // s = 0 at beginning of month + d = s + 1; // Determine day of month + y += (m + 2) / 12; // Move Jan and Feb back to original year + m = (m + 2) % 12 + 1; // Renumber the months so January = 1 + } + + /** + * Given a date as a string in the format yyyy, yyyy-mm, or yyyy-mm-dd, + * return the numeric values for the year, month, and day. No checking is + * done on these values. The string "now" is interpreted as the present + * date (in UTC). + * + * @param[in] s the date in string format. + * @param[out] y the year. + * @param[out] m the month, Jan = 1, etc. + * @param[out] d the day of the month. + * @exception GeographicErr is \e s is malformed. + **********************************************************************/ + static void date(const std::string& s, int& y, int& m, int& d) { + if (s == "now") { + std::time_t t = std::time(0); + struct tm* now = gmtime(&t); + y = now->tm_year + 1900; + m = now->tm_mon + 1; + d = now->tm_mday; + return; + } + int y1, m1 = 1, d1 = 1; + const char* digits = "0123456789"; + std::string::size_type p1 = s.find_first_not_of(digits); + if (p1 == std::string::npos) + y1 = val(s); + else if (s[p1] != '-') + throw GeographicErr("Delimiter not hyphen in date " + s); + else if (p1 == 0) + throw GeographicErr("Empty year field in date " + s); + else { + y1 = val(s.substr(0, p1)); + if (++p1 == s.size()) + throw GeographicErr("Empty month field in date " + s); + std::string::size_type p2 = s.find_first_not_of(digits, p1); + if (p2 == std::string::npos) + m1 = val(s.substr(p1)); + else if (s[p2] != '-') + throw GeographicErr("Delimiter not hyphen in date " + s); + else if (p2 == p1) + throw GeographicErr("Empty month field in date " + s); + else { + m1 = val(s.substr(p1, p2 - p1)); + if (++p2 == s.size()) + throw GeographicErr("Empty day field in date " + s); + d1 = val(s.substr(p2)); + } + } + y = y1; m = m1; d = d1; + } + + /** + * Given the date, return the day of the week. + * + * @param[in] y the year (must be positive). + * @param[in] m the month, Jan = 1, etc. (must be positive). + * @param[in] d the day of the month (must be positive). + * @return the day of the week with Sunday, Monday--Saturday = 0, + * 1--6. + **********************************************************************/ + static int dow(int y, int m, int d) { return dow(day(y, m, d)); } + + /** + * Given the sequential day, return the day of the week. + * + * @param[in] s the sequential day (must be positive). + * @return the day of the week with Sunday, Monday--Saturday = 0, + * 1--6. + **********************************************************************/ + static int dow(int s) { + return (s + 5) % 7; // The 5 offset makes day 1 (0001-01-01) a Saturday. + } + + /** + * Convert a string representing a date to a fractional year. + * + * @tparam T the type of the argument. + * @param[in] s the string to be converted. + * @exception GeographicErr if \e s can't be interpreted as a date. + * @return the fractional year. + * + * The string is first read as an ordinary number (e.g., 2010 or 2012.5); + * if this is successful, the value is returned. Otherwise the string + * should be of the form yyyy-mm or yyyy-mm-dd and this is converted to a + * number with 2010-01-01 giving 2010.0 and 2012-07-03 giving 2012.5. + **********************************************************************/ + template static T fractionalyear(const std::string& s) { + try { + return val(s); + } + catch (const std::exception&) {} + int y, m, d; + date(s, y, m, d); + int t = day(y, m, d, true); + return T(y) + T(t - day(y)) / T(day(y + 1) - day(y)); + } + + /** + * Convert a object of type T to a string. + * + * @tparam T the type of the argument. + * @param[in] x the value to be converted. + * @param[in] p the precision used (default −1). + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return the string representation. + * + * If \e p ≥ 0, then the number fixed format is used with p bits of + * precision. With p < 0, there is no manipulation of the format. + **********************************************************************/ + template static std::string str(T x, int p = -1) { + std::ostringstream s; + if (p >= 0) s << std::fixed << std::setprecision(p); + s << x; return s.str(); + } + + /** + * Convert a Math::real object to a string. + * + * @param[in] x the value to be converted. + * @param[in] p the precision used (default −1). + * @exception std::bad_alloc if memory for the string can't be allocated. + * @return the string representation. + * + * If \e p ≥ 0, then the number fixed format is used with p bits of + * precision. With p < 0, there is no manipulation of the format. This is + * an overload of str which deals with inf and nan. + **********************************************************************/ + static std::string str(Math::real x, int p = -1) { + using std::isfinite; + if (!isfinite(x)) + return x < 0 ? std::string("-inf") : + (x > 0 ? std::string("inf") : std::string("nan")); + std::ostringstream s; +#if GEOGRAPHICLIB_PRECISION == 4 + // boost-quadmath treats precision == 0 as "use as many digits as + // necessary" (see https://svn.boost.org/trac/boost/ticket/10103), so... + using std::floor; using std::fmod; + if (p == 0) { + x += Math::real(0.5); + Math::real ix = floor(x); + // Implement the "round ties to even" rule + x = (ix == x && fmod(ix, Math::real(2)) == 1) ? ix - 1 : ix; + s << std::fixed << std::setprecision(1) << x; + std::string r(s.str()); + // strip off trailing ".0" + return r.substr(0, (std::max)(int(r.size()) - 2, 0)); + } +#endif + if (p >= 0) s << std::fixed << std::setprecision(p); + s << x; return s.str(); + } + + /** + * Trim the white space from the beginning and end of a string. + * + * @param[in] s the string to be trimmed + * @return the trimmed string + **********************************************************************/ + static std::string trim(const std::string& s) { + unsigned + beg = 0, + end = unsigned(s.size()); + while (beg < end && isspace(s[beg])) + ++beg; + while (beg < end && isspace(s[end - 1])) + --end; + return std::string(s, beg, end-beg); + } + + /** + * Convert a string to type T. + * + * @tparam T the type of the return value. + * @param[in] s the string to be converted. + * @exception GeographicErr is \e s is not readable as a T. + * @return object of type T. + * + * White space at the beginning and end of \e s is ignored. + * + * Special handling is provided for some types. + * + * If T is a floating point type, then inf and nan are recognized. + * + * If T is bool, then \e s should either be string a representing 0 (false) + * or 1 (true) or one of the strings + * - "false", "f", "nil", "no", "n", "off", or "" meaning false, + * - "true", "t", "yes", "y", or "on" meaning true; + * . + * case is ignored. + * + * If T is std::string, then \e s is returned (with the white space at the + * beginning and end removed). + **********************************************************************/ + template static T val(const std::string& s) { + // If T is bool, then the specialization val() defined below is + // used. + T x; + std::string errmsg, t(trim(s)); + do { // Executed once (provides the ability to break) + std::istringstream is(t); + if (!(is >> x)) { + errmsg = "Cannot decode " + t; + break; + } + int pos = int(is.tellg()); // Returns -1 at end of string? + if (!(pos < 0 || pos == int(t.size()))) { + errmsg = "Extra text " + t.substr(pos) + " at end of " + t; + break; + } + return x; + } while (false); + x = std::numeric_limits::is_integer ? 0 : nummatch(t); + if (x == 0) + throw GeographicErr(errmsg); + return x; + } + /** + * \deprecated An old name for val(s). + **********************************************************************/ + template + GEOGRAPHICLIB_DEPRECATED("Use Utility::val(s)") + static T num(const std::string& s) { + return val(s); + } + + /** + * Match "nan" and "inf" (and variants thereof) in a string. + * + * @tparam T the type of the return value (this should be a floating point + * type). + * @param[in] s the string to be matched. + * @return appropriate special value (±∞, nan) or 0 if none is + * found. + * + * White space is not allowed at the beginning or end of \e s. + **********************************************************************/ + template static T nummatch(const std::string& s) { + if (s.length() < 3) + return 0; + std::string t(s); + for (std::string::iterator p = t.begin(); p != t.end(); ++p) + *p = char(std::toupper(*p)); + for (size_t i = s.length(); i--;) + t[i] = char(std::toupper(s[i])); + int sign = t[0] == '-' ? -1 : 1; + std::string::size_type p0 = t[0] == '-' || t[0] == '+' ? 1 : 0; + std::string::size_type p1 = t.find_last_not_of('0'); + if (p1 == std::string::npos || p1 + 1 < p0 + 3) + return 0; + // Strip off sign and trailing 0s + t = t.substr(p0, p1 + 1 - p0); // Length at least 3 + if (t == "NAN" || t == "1.#QNAN" || t == "1.#SNAN" || t == "1.#IND" || + t == "1.#R") + return Math::NaN(); + else if (t == "INF" || t == "1.#INF") + return sign * Math::infinity(); + return 0; + } + + /** + * Read a simple fraction, e.g., 3/4, from a string to an object of type T. + * + * @tparam T the type of the return value. + * @param[in] s the string to be converted. + * @exception GeographicErr is \e s is not readable as a fraction of type + * T. + * @return object of type T + * + * \note The msys shell under Windows converts arguments which look like + * pathnames into their Windows equivalents. As a result the argument + * "-1/300" gets mangled into something unrecognizable. A workaround is to + * use a floating point number in the numerator, i.e., "-1.0/300". (Recent + * versions of the msys shell appear \e not to have this problem.) + **********************************************************************/ + template static T fract(const std::string& s) { + std::string::size_type delim = s.find('/'); + return + !(delim != std::string::npos && delim >= 1 && delim + 2 <= s.size()) ? + val(s) : + // delim in [1, size() - 2] + val(s.substr(0, delim)) / val(s.substr(delim + 1)); + } + + /** + * Lookup up a character in a string. + * + * @param[in] s the string to be searched. + * @param[in] c the character to look for. + * @return the index of the first occurrence character in the string or + * −1 is the character is not present. + * + * \e c is converted to upper case before search \e s. Therefore, it is + * intended that \e s should not contain any lower case letters. + **********************************************************************/ + static int lookup(const std::string& s, char c) { + std::string::size_type r = s.find(char(std::toupper(c))); + return r == std::string::npos ? -1 : int(r); + } + + /** + * Lookup up a character in a char*. + * + * @param[in] s the char* string to be searched. + * @param[in] c the character to look for. + * @return the index of the first occurrence character in the string or + * −1 is the character is not present. + * + * \e c is converted to upper case before search \e s. Therefore, it is + * intended that \e s should not contain any lower case letters. + **********************************************************************/ + static int lookup(const char* s, char c) { + const char* p = std::strchr(s, std::toupper(c)); + return p != NULL ? int(p - s) : -1; + } + + /** + * Read data of type ExtT from a binary stream to an array of type IntT. + * The data in the file is in (bigendp ? big : little)-endian format. + * + * @tparam ExtT the type of the objects in the binary stream (external). + * @tparam IntT the type of the objects in the array (internal). + * @tparam bigendp true if the external storage format is big-endian. + * @param[in] str the input stream containing the data of type ExtT + * (external). + * @param[out] array the output array of type IntT (internal). + * @param[in] num the size of the array. + * @exception GeographicErr if the data cannot be read. + **********************************************************************/ + template + static void readarray(std::istream& str, IntT array[], size_t num) { +#if GEOGRAPHICLIB_PRECISION < 4 + if (sizeof(IntT) == sizeof(ExtT) && + std::numeric_limits::is_integer == + std::numeric_limits::is_integer) + { + // Data is compatible (aside from the issue of endian-ness). + str.read(reinterpret_cast(array), num * sizeof(ExtT)); + if (!str.good()) + throw GeographicErr("Failure reading data"); + if (bigendp != Math::bigendian) { // endian mismatch -> swap bytes + for (size_t i = num; i--;) + array[i] = Math::swab(array[i]); + } + } + else +#endif + { + const int bufsize = 1024; // read this many values at a time + ExtT buffer[bufsize]; // temporary buffer + int k = int(num); // data values left to read + int i = 0; // index into output array + while (k) { + int n = (std::min)(k, bufsize); + str.read(reinterpret_cast(buffer), n * sizeof(ExtT)); + if (!str.good()) + throw GeographicErr("Failure reading data"); + for (int j = 0; j < n; ++j) + // fix endian-ness and cast to IntT + array[i++] = IntT(bigendp == Math::bigendian ? buffer[j] : + Math::swab(buffer[j])); + k -= n; + } + } + return; + } + + /** + * Read data of type ExtT from a binary stream to a vector array of type + * IntT. The data in the file is in (bigendp ? big : little)-endian + * format. + * + * @tparam ExtT the type of the objects in the binary stream (external). + * @tparam IntT the type of the objects in the array (internal). + * @tparam bigendp true if the external storage format is big-endian. + * @param[in] str the input stream containing the data of type ExtT + * (external). + * @param[out] array the output vector of type IntT (internal). + * @exception GeographicErr if the data cannot be read. + **********************************************************************/ + template + static void readarray(std::istream& str, std::vector& array) { + if (array.size() > 0) + readarray(str, &array[0], array.size()); + } + + /** + * Write data in an array of type IntT as type ExtT to a binary stream. + * The data in the file is in (bigendp ? big : little)-endian format. + * + * @tparam ExtT the type of the objects in the binary stream (external). + * @tparam IntT the type of the objects in the array (internal). + * @tparam bigendp true if the external storage format is big-endian. + * @param[out] str the output stream for the data of type ExtT (external). + * @param[in] array the input array of type IntT (internal). + * @param[in] num the size of the array. + * @exception GeographicErr if the data cannot be written. + **********************************************************************/ + template + static void writearray(std::ostream& str, const IntT array[], size_t num) + { +#if GEOGRAPHICLIB_PRECISION < 4 + if (sizeof(IntT) == sizeof(ExtT) && + std::numeric_limits::is_integer == + std::numeric_limits::is_integer && + bigendp == Math::bigendian) + { + // Data is compatible (including endian-ness). + str.write(reinterpret_cast(array), num * sizeof(ExtT)); + if (!str.good()) + throw GeographicErr("Failure writing data"); + } + else +#endif + { + const int bufsize = 1024; // write this many values at a time + ExtT buffer[bufsize]; // temporary buffer + int k = int(num); // data values left to write + int i = 0; // index into output array + while (k) { + int n = (std::min)(k, bufsize); + for (int j = 0; j < n; ++j) + // cast to ExtT and fix endian-ness + buffer[j] = bigendp == Math::bigendian ? ExtT(array[i++]) : + Math::swab(ExtT(array[i++])); + str.write(reinterpret_cast(buffer), n * sizeof(ExtT)); + if (!str.good()) + throw GeographicErr("Failure writing data"); + k -= n; + } + } + return; + } + + /** + * Write data in an array of type IntT as type ExtT to a binary stream. + * The data in the file is in (bigendp ? big : little)-endian format. + * + * @tparam ExtT the type of the objects in the binary stream (external). + * @tparam IntT the type of the objects in the array (internal). + * @tparam bigendp true if the external storage format is big-endian. + * @param[out] str the output stream for the data of type ExtT (external). + * @param[in] array the input vector of type IntT (internal). + * @exception GeographicErr if the data cannot be written. + **********************************************************************/ + template + static void writearray(std::ostream& str, std::vector& array) { + if (array.size() > 0) + writearray(str, &array[0], array.size()); + } + + /** + * Parse a KEY [=] VALUE line. + * + * @param[in] line the input line. + * @param[out] key the KEY. + * @param[out] value the VALUE. + * @param[in] delim delimiter to separate KEY and VALUE, if NULL use first + * space character. + * @exception std::bad_alloc if memory for the internal strings can't be + * allocated. + * @return whether a key was found. + * + * A "#" character and everything after it are discarded and the result + * trimmed of leading and trailing white space. Use the delimiter + * character (or, if it is NULL, the first white space) to separate \e key + * and \e value. \e key and \e value are trimmed of leading and trailing + * white space. If \e key is empty, then \e value is set to "" and false + * is returned. + **********************************************************************/ + static bool ParseLine(const std::string& line, + std::string& key, std::string& value, + char delim); + + /** + * Parse a KEY VALUE line. + * + * @param[in] line the input line. + * @param[out] key the KEY. + * @param[out] value the VALUE. + * @exception std::bad_alloc if memory for the internal strings can't be + * allocated. + * @return whether a key was found. + * + * \note This is a transition routine. At some point \e delim will be made + * an optional argument in the previous version of ParseLine and this + * version will be removed. + **********************************************************************/ + + static bool ParseLine(const std::string& line, + std::string& key, std::string& value); + + /** + * Set the binary precision of a real number. + * + * @param[in] ndigits the number of bits of precision. If ndigits is 0 + * (the default), then determine the precision from the environment + * variable GEOGRAPHICLIB_DIGITS. If this is undefined, use ndigits = + * 256 (i.e., about 77 decimal digits). + * @return the resulting number of bits of precision. + * + * This only has an effect when GEOGRAPHICLIB_PRECISION = 5. The + * precision should only be set once and before calls to any other + * GeographicLib functions. (Several functions, for example Math::pi(), + * cache the return value in a static local variable. The precision needs + * to be set before a call to any such functions.) In multi-threaded + * applications, it is necessary also to set the precision in each thread + * (see the example GeoidToGTX.cpp). + **********************************************************************/ + static int set_digits(int ndigits = 0); + + }; + + /** + * The specialization of Utility::val() for strings. + **********************************************************************/ + template<> inline std::string Utility::val(const std::string& s) + { return trim(s); } + + /** + * The specialization of Utility::val() for bools. + **********************************************************************/ + template<> inline bool Utility::val(const std::string& s) { + std::string t(trim(s)); + if (t.empty()) return false; + bool x; + { + std::istringstream is(t); + if (is >> x) { + int pos = int(is.tellg()); // Returns -1 at end of string? + if (!(pos < 0 || pos == int(t.size()))) + throw GeographicErr("Extra text " + t.substr(pos) + + " at end of " + t); + return x; + } + } + for (std::string::iterator p = t.begin(); p != t.end(); ++p) + *p = char(std::tolower(*p)); + switch (t[0]) { // already checked that t isn't empty + case 'f': + if (t == "f" || t == "false") return false; + break; + case 'n': + if (t == "n" || t == "nil" || t == "no") return false; + break; + case 'o': + if (t == "off") return false; + else if (t == "on") return true; + break; + case 't': + if (t == "t" || t == "true") return true; + break; + case 'y': + if (t == "y" || t == "yes") return true; + break; + default: + break; + } + throw GeographicErr("Cannot decode " + t + " as a bool"); + } + +} // namespace GeographicLib + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif // GEOGRAPHICLIB_UTILITY_HPP diff --git a/external/lib/Geographic.lib b/external/lib/Geographic.lib new file mode 100644 index 0000000000000000000000000000000000000000..3a0599b72fefbb501a42e3cfed8a80e49b9038e3 GIT binary patch literal 6131358 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%0A~pX}YC|feLT3H6^`UI#Q*5 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%0Agy%1ZD425yb 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