/** * \file Constants.hpp * \brief Header for GeographicLib::Constants class * * Copyright (c) Charles Karney (2008-2024) 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 // 1900 vc14 (2015) First version of VS to include enough C++11 support // 191[0-6] vc15 (2017) First version of VS to include enough C++17 support // 192[0-9] vc16 (2019) // 1930-1944 vc17 (2022) // vc18 (2026) #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 #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() = delete; // 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() / Math::dm; } /** * @return the number of radians in an arcsecond. **********************************************************************/ static Math::real arcsecond() { return Math::degree() / Math::ds; } /** \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 Triaxial ellipsoid parameters * * These parameters are close to the values given by Milan Bursa, Vladimira * Fialova, "Parameters of the Earth's tri-axial level ellipsoid", Studia * Geophysica et Geodaetica 37(1), 1-13 (1993). * - longitude of major axis = −14.93° ± 0.05° * - \e a = 6378171.36 m ± 0.30 m * - \e a / (\e a − \e c) = 297.7738 ± 0.0003 * - \e a / (\e a − \e b) = 91449 ± 60 * . * which gives: \e a = 6378171.36 m, \e b = 6378101.61 m, \e c = 6356751.84 * m. Here take the semiaxes to be whole numbers of meters, with (\e a + * \e b)/2 = WGS84_a(), \e a − \e b = 70 m, \e c = round(WGS84_a() * * (1 - WGS84_f())). This gives * - \e a = 6378172 m * - \e b = 6378102 m * - \e c = 6356752 m * - \e lon0 = −14.93° **********************************************************************/ ///@{ /** * @tparam T the type of the returned value. * @return the major semiaxis of a triaxial approximation to the Earth, \e * a, in m (= 6378172). **********************************************************************/ template static T Triaxial_Earth_a() { return WGS84_a() + 70/real(2); } /** * @tparam T the type of the returned value. * @return the median semiaxis of a triaxial approximation to the Earth, \e * b, in m (= 6378102). **********************************************************************/ template static T Triaxial_Earth_b() { return WGS84_a() - 70/real(2); } /** * @tparam T the type of the returned value. * @return the minor semiaxis of a triaxial approximation to the Earth, \e * c, in m (= 6356752). **********************************************************************/ template static T Triaxial_Earth_c() { using std::round; return round(WGS84_a() * (1 - WGS84_f())); } /** * @tparam T the type of the returned value. * @return the longitude, with respect to Greenwich, of the major semiaxis * of of a triaxial approximation to the Earth, \e lon0, in degrees (= * −14.93). **********************************************************************/ template static T Triaxial_Earth_lon0() { return T(1493) / 100; } ///@} /** \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