normalize.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2015-2025, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  4. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  5. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  6. // Licensed under the Boost Software License version 1.0.
  7. // http://www.boost.org/users/license.html
  8. #ifndef BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP
  9. #define BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP
  10. #include <cstddef>
  11. #include <type_traits>
  12. #include <boost/geometry/core/access.hpp>
  13. #include <boost/geometry/core/coordinate_system.hpp>
  14. #include <boost/geometry/core/coordinate_type.hpp>
  15. #include <boost/geometry/core/cs.hpp>
  16. #include <boost/geometry/core/tag.hpp>
  17. #include <boost/geometry/core/tags.hpp>
  18. #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
  19. #include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp>
  20. #include <boost/geometry/util/numeric_cast.hpp>
  21. #include <boost/geometry/views/detail/indexed_point_view.hpp>
  22. namespace boost { namespace geometry
  23. {
  24. namespace strategy { namespace normalize
  25. {
  26. #ifndef DOXYGEN_NO_DETAIL
  27. namespace detail
  28. {
  29. struct do_nothing
  30. {
  31. template <typename GeometryIn, typename GeometryOut>
  32. static inline void apply(GeometryIn const&, GeometryOut&)
  33. {
  34. }
  35. };
  36. template <std::size_t Dimension, std::size_t DimensionCount>
  37. struct assign_loop
  38. {
  39. template <typename CoordinateType, typename PointIn, typename PointOut>
  40. static inline void apply(CoordinateType const& longitude,
  41. CoordinateType const& latitude,
  42. PointIn const& point_in,
  43. PointOut& point_out)
  44. {
  45. geometry::set<Dimension>(point_out, util::numeric_cast
  46. <
  47. coordinate_type_t<PointOut>
  48. >(geometry::get<Dimension>(point_in)));
  49. assign_loop
  50. <
  51. Dimension + 1, DimensionCount
  52. >::apply(longitude, latitude, point_in, point_out);
  53. }
  54. };
  55. template <std::size_t DimensionCount>
  56. struct assign_loop<DimensionCount, DimensionCount>
  57. {
  58. template <typename CoordinateType, typename PointIn, typename PointOut>
  59. static inline void apply(CoordinateType const&,
  60. CoordinateType const&,
  61. PointIn const&,
  62. PointOut&)
  63. {
  64. }
  65. };
  66. template <std::size_t DimensionCount>
  67. struct assign_loop<0, DimensionCount>
  68. {
  69. template <typename CoordinateType, typename PointIn, typename PointOut>
  70. static inline void apply(CoordinateType const& longitude,
  71. CoordinateType const& latitude,
  72. PointIn const& point_in,
  73. PointOut& point_out)
  74. {
  75. geometry::set<0>(point_out, util::numeric_cast<coordinate_type_t<PointOut>>(longitude));
  76. assign_loop
  77. <
  78. 1, DimensionCount
  79. >::apply(longitude, latitude, point_in, point_out);
  80. }
  81. };
  82. template <std::size_t DimensionCount>
  83. struct assign_loop<1, DimensionCount>
  84. {
  85. template <typename CoordinateType, typename PointIn, typename PointOut>
  86. static inline void apply(CoordinateType const& longitude,
  87. CoordinateType const& latitude,
  88. PointIn const& point_in,
  89. PointOut& point_out)
  90. {
  91. geometry::set<1>(point_out, util::numeric_cast
  92. <
  93. coordinate_type_t<PointOut>
  94. >(latitude));
  95. assign_loop
  96. <
  97. 2, DimensionCount
  98. >::apply(longitude, latitude, point_in, point_out);
  99. }
  100. };
  101. template <typename PointIn, typename PointOut, bool IsEquatorial = true>
  102. struct normalize_point
  103. {
  104. static inline void apply(PointIn const& point_in, PointOut& point_out, bool exact = true)
  105. {
  106. using in_coordinate_type = coordinate_type_t<PointIn>;
  107. in_coordinate_type longitude = geometry::get<0>(point_in);
  108. in_coordinate_type latitude = geometry::get<1>(point_in);
  109. math::normalize_spheroidal_coordinates
  110. <
  111. typename geometry::detail::cs_angular_units<PointIn>::type,
  112. IsEquatorial,
  113. in_coordinate_type
  114. >(longitude, latitude, exact);
  115. assign_loop
  116. <
  117. 0, dimension<PointIn>::value
  118. >::apply(longitude, latitude, point_in, point_out);
  119. }
  120. };
  121. template <typename BoxIn, typename BoxOut, bool IsEquatorial = true>
  122. class normalize_box
  123. {
  124. template <typename UnitsIn, typename UnitsOut, typename CoordinateInType>
  125. static inline void apply_to_coordinates(CoordinateInType& lon_min,
  126. CoordinateInType& lat_min,
  127. CoordinateInType& lon_max,
  128. CoordinateInType& lat_max,
  129. BoxIn const& box_in,
  130. BoxOut& box_out)
  131. {
  132. geometry::detail::indexed_point_view<BoxOut, min_corner> p_min_out(box_out);
  133. assign_loop
  134. <
  135. 0, dimension<BoxIn>::value
  136. >::apply(lon_min,
  137. lat_min,
  138. geometry::detail::indexed_point_view
  139. <
  140. BoxIn const, min_corner
  141. >(box_in),
  142. p_min_out);
  143. geometry::detail::indexed_point_view<BoxOut, max_corner> p_max_out(box_out);
  144. assign_loop
  145. <
  146. 0, dimension<BoxIn>::value
  147. >::apply(lon_max,
  148. lat_max,
  149. geometry::detail::indexed_point_view
  150. <
  151. BoxIn const, max_corner
  152. >(box_in),
  153. p_max_out);
  154. }
  155. public:
  156. static inline void apply(BoxIn const& box_in, BoxOut& box_out)
  157. {
  158. using in_coordinate_type = coordinate_type_t<BoxIn>;
  159. in_coordinate_type lon_min = geometry::get<min_corner, 0>(box_in);
  160. in_coordinate_type lat_min = geometry::get<min_corner, 1>(box_in);
  161. in_coordinate_type lon_max = geometry::get<max_corner, 0>(box_in);
  162. in_coordinate_type lat_max = geometry::get<max_corner, 1>(box_in);
  163. math::normalize_spheroidal_box_coordinates
  164. <
  165. typename geometry::detail::cs_angular_units<BoxIn>::type,
  166. IsEquatorial,
  167. in_coordinate_type
  168. >(lon_min, lat_min, lon_max, lat_max);
  169. apply_to_coordinates
  170. <
  171. typename geometry::detail::cs_angular_units<BoxIn>::type,
  172. typename geometry::detail::cs_angular_units<BoxOut>::type
  173. >(lon_min, lat_min, lon_max, lat_max, box_in, box_out);
  174. }
  175. };
  176. } // namespace detail
  177. #endif // DOXYGEN_NO_DETAIL
  178. struct cartesian_point
  179. : detail::do_nothing
  180. {};
  181. struct cartesian_box
  182. : detail::do_nothing
  183. {};
  184. struct spherical_point
  185. {
  186. template <typename PointIn, typename PointOut>
  187. static inline void apply(PointIn const& point_in, PointOut& point_out, bool exact = true)
  188. {
  189. detail::normalize_point
  190. <
  191. PointIn, PointOut,
  192. (! std::is_same<cs_tag_t<PointIn>, spherical_polar_tag>::value)
  193. >::apply(point_in, point_out, exact);
  194. }
  195. };
  196. struct spherical_box
  197. {
  198. template <typename BoxIn, typename BoxOut>
  199. static inline void apply(BoxIn const& box_in, BoxOut& box_out)
  200. {
  201. detail::normalize_box
  202. <
  203. BoxIn, BoxOut,
  204. (! std::is_same<cs_tag_t<BoxIn>, spherical_polar_tag>::value)
  205. >::apply(box_in, box_out);
  206. }
  207. };
  208. }} // namespace strategy::normalize
  209. }} // namespace boost::geometry
  210. #endif // BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP