gnomonic_spheroid.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Boost.Geometry
  2. // Copyright (c) 2016 Oracle and/or its affiliates.
  3. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  4. // Use, modification and distribution is subject to the Boost Software License,
  5. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_GEOMETRY_FORMULAS_GNOMONIC_SPHEROID_HPP
  8. #define BOOST_GEOMETRY_FORMULAS_GNOMONIC_SPHEROID_HPP
  9. #include <boost/geometry/core/radius.hpp>
  10. #include <boost/geometry/util/condition.hpp>
  11. #include <boost/geometry/util/math.hpp>
  12. #include <boost/geometry/formulas/andoyer_inverse.hpp>
  13. #include <boost/geometry/formulas/flattening.hpp>
  14. #include <boost/geometry/formulas/thomas_inverse.hpp>
  15. #include <boost/geometry/formulas/vincenty_direct.hpp>
  16. #include <boost/geometry/formulas/vincenty_inverse.hpp>
  17. namespace boost { namespace geometry { namespace formula
  18. {
  19. /*!
  20. \brief Gnomonic projection on spheroid (ellipsoid of revolution).
  21. \author See
  22. - Charles F.F Karney, Algorithms for geodesics, 2011
  23. https://arxiv.org/pdf/1109.4448.pdf
  24. */
  25. template <
  26. typename CT,
  27. template <typename, bool, bool, bool, bool ,bool> class Inverse,
  28. template <typename, bool, bool, bool, bool> class Direct
  29. >
  30. class gnomonic_spheroid
  31. {
  32. typedef Inverse<CT, false, true, true, true, true> inverse_type;
  33. typedef typename inverse_type::result_type inverse_result;
  34. typedef Direct<CT, false, false, true, true> direct_quantities_type;
  35. typedef Direct<CT, true, false, false, false> direct_coordinates_type;
  36. typedef typename direct_coordinates_type::result_type direct_result;
  37. public:
  38. template <typename Spheroid>
  39. static inline bool forward(CT const& lon0, CT const& lat0,
  40. CT const& lon, CT const& lat,
  41. CT & x, CT & y,
  42. Spheroid const& spheroid)
  43. {
  44. inverse_result i_res = inverse_type::apply(lon0, lat0, lon, lat, spheroid);
  45. CT const& m = i_res.reduced_length;
  46. CT const& M = i_res.geodesic_scale;
  47. if (math::smaller_or_equals(M, CT(0)))
  48. {
  49. return false;
  50. }
  51. CT rho = m / M;
  52. x = sin(i_res.azimuth) * rho;
  53. y = cos(i_res.azimuth) * rho;
  54. return true;
  55. }
  56. template <typename Spheroid>
  57. static inline bool inverse(CT const& lon0, CT const& lat0,
  58. CT const& x, CT const& y,
  59. CT & lon, CT & lat,
  60. Spheroid const& spheroid)
  61. {
  62. CT const a = get_radius<0>(spheroid);
  63. CT const ds_threshold = a * std::numeric_limits<CT>::epsilon(); // TODO: 0 for non-fundamental type
  64. CT const azimuth = atan2(x, y);
  65. CT const rho = math::sqrt(math::sqr(x) + math::sqr(y)); // use hypot?
  66. CT distance = a * atan(rho / a);
  67. bool found = false;
  68. for (int i = 0 ; i < 10 ; ++i)
  69. {
  70. direct_result d_res = direct_quantities_type::apply(lon0, lat0, distance, azimuth, spheroid);
  71. CT const& m = d_res.reduced_length;
  72. CT const& M = d_res.geodesic_scale;
  73. if (math::smaller_or_equals(M, CT(0)))
  74. {
  75. // found = false;
  76. return found;
  77. }
  78. CT const drho = m / M - rho; // rho = m / M
  79. CT const ds = drho * math::sqr(M); // drho/ds = 1/M^2
  80. distance -= ds;
  81. // ds_threshold may be 0
  82. if (math::abs(ds) <= ds_threshold)
  83. {
  84. found = true;
  85. break;
  86. }
  87. }
  88. if (found)
  89. {
  90. direct_result d_res = direct_coordinates_type::apply(lon0, lat0, distance, azimuth, spheroid);
  91. lon = d_res.lon2;
  92. lat = d_res.lat2;
  93. }
  94. return found;
  95. }
  96. };
  97. }}} // namespace boost::geometry::formula
  98. #endif // BOOST_GEOMETRY_FORMULAS_GNOMONIC_SPHEROID_HPP