normalize_spheroidal_box_coordinates.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2015-2022, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
  8. #define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
  9. #include <boost/geometry/core/assert.hpp>
  10. #include <boost/geometry/util/math.hpp>
  11. #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
  12. namespace boost { namespace geometry
  13. {
  14. namespace math
  15. {
  16. #ifndef DOXYGEN_NO_DETAIL
  17. namespace detail
  18. {
  19. template <typename Units, typename CoordinateType, bool IsEquatorial = true>
  20. class normalize_spheroidal_box_coordinates
  21. {
  22. private:
  23. typedef normalize_spheroidal_coordinates<Units, CoordinateType> normalize;
  24. typedef constants_on_spheroid<CoordinateType, Units> constants;
  25. static inline bool is_band(CoordinateType const& longitude1,
  26. CoordinateType const& longitude2)
  27. {
  28. return math::larger_or_equals(math::abs(longitude1 - longitude2),
  29. constants::period());
  30. }
  31. public:
  32. static inline void apply(CoordinateType& longitude1,
  33. CoordinateType& latitude1,
  34. CoordinateType& longitude2,
  35. CoordinateType& latitude2,
  36. bool band)
  37. {
  38. normalize::apply(longitude1, latitude1, false);
  39. normalize::apply(longitude2, latitude2, false);
  40. latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude1);
  41. latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude2);
  42. if (math::equals(latitude1, constants::min_latitude())
  43. && math::equals(latitude2, constants::min_latitude()))
  44. {
  45. // box degenerates to the south pole
  46. longitude1 = longitude2 = CoordinateType(0);
  47. }
  48. else if (math::equals(latitude1, constants::max_latitude())
  49. && math::equals(latitude2, constants::max_latitude()))
  50. {
  51. // box degenerates to the north pole
  52. longitude1 = longitude2 = CoordinateType(0);
  53. }
  54. else if (band)
  55. {
  56. // the box is a band between two small circles (parallel
  57. // to the equator) on the spheroid
  58. longitude1 = constants::min_longitude();
  59. longitude2 = constants::max_longitude();
  60. }
  61. else if (longitude1 > longitude2)
  62. {
  63. // the box crosses the antimeridian, so we need to adjust
  64. // the longitudes
  65. longitude2 += constants::period();
  66. }
  67. latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude1);
  68. latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude2);
  69. #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
  70. BOOST_GEOMETRY_ASSERT(! math::larger(latitude1, latitude2));
  71. BOOST_GEOMETRY_ASSERT(! math::smaller(latitude1, constants::min_latitude()));
  72. BOOST_GEOMETRY_ASSERT(! math::larger(latitude2, constants::max_latitude()));
  73. #endif
  74. BOOST_GEOMETRY_ASSERT(! math::larger(longitude1, longitude2));
  75. BOOST_GEOMETRY_ASSERT(! math::smaller(longitude1, constants::min_longitude()));
  76. BOOST_GEOMETRY_ASSERT(! math::larger(longitude2 - longitude1, constants::period()));
  77. }
  78. static inline void apply(CoordinateType& longitude1,
  79. CoordinateType& latitude1,
  80. CoordinateType& longitude2,
  81. CoordinateType& latitude2)
  82. {
  83. bool const band = is_band(longitude1, longitude2);
  84. apply(longitude1, latitude1, longitude2, latitude2, band);
  85. }
  86. };
  87. } // namespace detail
  88. #endif // DOXYGEN_NO_DETAIL
  89. /*!
  90. \brief Short utility to normalize the coordinates of a box on a spheroid
  91. \tparam Units The units of the coordindate system in the spheroid
  92. \tparam CoordinateType The type of the coordinates
  93. \param longitude1 Minimum longitude of the box
  94. \param latitude1 Minimum latitude of the box
  95. \param longitude2 Maximum longitude of the box
  96. \param latitude2 Maximum latitude of the box
  97. \ingroup utility
  98. */
  99. template <typename Units, typename CoordinateType>
  100. inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
  101. CoordinateType& latitude1,
  102. CoordinateType& longitude2,
  103. CoordinateType& latitude2)
  104. {
  105. detail::normalize_spheroidal_box_coordinates
  106. <
  107. Units, CoordinateType
  108. >::apply(longitude1, latitude1, longitude2, latitude2);
  109. }
  110. template <typename Units, bool IsEquatorial, typename CoordinateType>
  111. inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
  112. CoordinateType& latitude1,
  113. CoordinateType& longitude2,
  114. CoordinateType& latitude2)
  115. {
  116. detail::normalize_spheroidal_box_coordinates
  117. <
  118. Units, CoordinateType, IsEquatorial
  119. >::apply(longitude1, latitude1, longitude2, latitude2);
  120. }
  121. /*!
  122. \brief Short utility to normalize the coordinates of a box on a spheroid
  123. \tparam Units The units of the coordindate system in the spheroid
  124. \tparam CoordinateType The type of the coordinates
  125. \param longitude1 Minimum longitude of the box
  126. \param latitude1 Minimum latitude of the box
  127. \param longitude2 Maximum longitude of the box
  128. \param latitude2 Maximum latitude of the box
  129. \param band Indicates whether the box should be treated as a band or
  130. not and avoid the computation done in the other version of the function
  131. \ingroup utility
  132. */
  133. template <typename Units, typename CoordinateType>
  134. inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
  135. CoordinateType& latitude1,
  136. CoordinateType& longitude2,
  137. CoordinateType& latitude2,
  138. bool band)
  139. {
  140. detail::normalize_spheroidal_box_coordinates
  141. <
  142. Units, CoordinateType
  143. >::apply(longitude1, latitude1, longitude2, latitude2, band);
  144. }
  145. template <typename Units, bool IsEquatorial, typename CoordinateType>
  146. inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
  147. CoordinateType& latitude1,
  148. CoordinateType& longitude2,
  149. CoordinateType& latitude2,
  150. bool band)
  151. {
  152. detail::normalize_spheroidal_box_coordinates
  153. <
  154. Units, CoordinateType, IsEquatorial
  155. >::apply(longitude1, latitude1, longitude2, latitude2, band);
  156. }
  157. } // namespace math
  158. }} // namespace boost::geometry
  159. #endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP