1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2015-2018, Oracle and/or its affiliates. 4 5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle 6 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 7 8 // Licensed under the Boost Software License version 1.0. 9 // http://www.boost.org/users/license.html 10 11 #ifndef BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP 12 #define BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP 13 14 #include <cstddef> 15 16 #include <boost/numeric/conversion/cast.hpp> 17 18 #include <boost/geometry/core/access.hpp> 19 #include <boost/geometry/core/coordinate_system.hpp> 20 #include <boost/geometry/core/coordinate_type.hpp> 21 #include <boost/geometry/core/cs.hpp> 22 #include <boost/geometry/core/tag.hpp> 23 #include <boost/geometry/core/tags.hpp> 24 25 #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> 26 #include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp> 27 28 #include <boost/geometry/views/detail/indexed_point_view.hpp> 29 30 31 namespace boost { namespace geometry 32 { 33 34 namespace strategy { namespace normalize 35 { 36 37 #ifndef DOXYGEN_NO_DETAIL 38 namespace detail 39 { 40 41 struct do_nothing 42 { 43 template <typename GeometryIn, typename GeometryOut> applyboost::geometry::strategy::normalize::detail::do_nothing44 static inline void apply(GeometryIn const&, GeometryOut&) 45 { 46 } 47 }; 48 49 50 template <std::size_t Dimension, std::size_t DimensionCount> 51 struct assign_loop 52 { 53 template <typename CoordinateType, typename PointIn, typename PointOut> applyboost::geometry::strategy::normalize::detail::assign_loop54 static inline void apply(CoordinateType const& longitude, 55 CoordinateType const& latitude, 56 PointIn const& point_in, 57 PointOut& point_out) 58 { 59 geometry::set<Dimension>(point_out, boost::numeric_cast 60 < 61 typename coordinate_type<PointOut>::type 62 >(geometry::get<Dimension>(point_in))); 63 64 assign_loop 65 < 66 Dimension + 1, DimensionCount 67 >::apply(longitude, latitude, point_in, point_out); 68 } 69 }; 70 71 template <std::size_t DimensionCount> 72 struct assign_loop<DimensionCount, DimensionCount> 73 { 74 template <typename CoordinateType, typename PointIn, typename PointOut> applyboost::geometry::strategy::normalize::detail::assign_loop75 static inline void apply(CoordinateType const&, 76 CoordinateType const&, 77 PointIn const&, 78 PointOut&) 79 { 80 } 81 }; 82 83 template <std::size_t DimensionCount> 84 struct assign_loop<0, DimensionCount> 85 { 86 template <typename CoordinateType, typename PointIn, typename PointOut> applyboost::geometry::strategy::normalize::detail::assign_loop87 static inline void apply(CoordinateType const& longitude, 88 CoordinateType const& latitude, 89 PointIn const& point_in, 90 PointOut& point_out) 91 { 92 geometry::set<0>(point_out, boost::numeric_cast 93 < 94 typename coordinate_type<PointOut>::type 95 >(longitude)); 96 97 assign_loop 98 < 99 1, DimensionCount 100 >::apply(longitude, latitude, point_in, point_out); 101 } 102 }; 103 104 template <std::size_t DimensionCount> 105 struct assign_loop<1, DimensionCount> 106 { 107 template <typename CoordinateType, typename PointIn, typename PointOut> applyboost::geometry::strategy::normalize::detail::assign_loop108 static inline void apply(CoordinateType const& longitude, 109 CoordinateType const& latitude, 110 PointIn const& point_in, 111 PointOut& point_out) 112 { 113 geometry::set<1>(point_out, boost::numeric_cast 114 < 115 typename coordinate_type<PointOut>::type 116 >(latitude)); 117 118 assign_loop 119 < 120 2, DimensionCount 121 >::apply(longitude, latitude, point_in, point_out); 122 } 123 }; 124 125 126 template <typename PointIn, typename PointOut, bool IsEquatorial = true> 127 struct normalize_point 128 { applyboost::geometry::strategy::normalize::detail::normalize_point129 static inline void apply(PointIn const& point_in, PointOut& point_out) 130 { 131 typedef typename coordinate_type<PointIn>::type in_coordinate_type; 132 133 in_coordinate_type longitude = geometry::get<0>(point_in); 134 in_coordinate_type latitude = geometry::get<1>(point_in); 135 136 math::normalize_spheroidal_coordinates 137 < 138 typename geometry::detail::cs_angular_units<PointIn>::type, 139 IsEquatorial, 140 in_coordinate_type 141 >(longitude, latitude); 142 143 assign_loop 144 < 145 0, dimension<PointIn>::value 146 >::apply(longitude, latitude, point_in, point_out); 147 } 148 }; 149 150 151 template <typename BoxIn, typename BoxOut, bool IsEquatorial = true> 152 class normalize_box 153 { 154 template <typename UnitsIn, typename UnitsOut, typename CoordinateInType> apply_to_coordinates(CoordinateInType & lon_min,CoordinateInType & lat_min,CoordinateInType & lon_max,CoordinateInType & lat_max,BoxIn const & box_in,BoxOut & box_out)155 static inline void apply_to_coordinates(CoordinateInType& lon_min, 156 CoordinateInType& lat_min, 157 CoordinateInType& lon_max, 158 CoordinateInType& lat_max, 159 BoxIn const& box_in, 160 BoxOut& box_out) 161 { 162 geometry::detail::indexed_point_view<BoxOut, min_corner> p_min_out(box_out); 163 assign_loop 164 < 165 0, dimension<BoxIn>::value 166 >::apply(lon_min, 167 lat_min, 168 geometry::detail::indexed_point_view 169 < 170 BoxIn const, min_corner 171 >(box_in), 172 p_min_out); 173 174 geometry::detail::indexed_point_view<BoxOut, max_corner> p_max_out(box_out); 175 assign_loop 176 < 177 0, dimension<BoxIn>::value 178 >::apply(lon_max, 179 lat_max, 180 geometry::detail::indexed_point_view 181 < 182 BoxIn const, max_corner 183 >(box_in), 184 p_max_out); 185 } 186 187 public: apply(BoxIn const & box_in,BoxOut & box_out)188 static inline void apply(BoxIn const& box_in, BoxOut& box_out) 189 { 190 typedef typename coordinate_type<BoxIn>::type in_coordinate_type; 191 192 in_coordinate_type lon_min = geometry::get<min_corner, 0>(box_in); 193 in_coordinate_type lat_min = geometry::get<min_corner, 1>(box_in); 194 in_coordinate_type lon_max = geometry::get<max_corner, 0>(box_in); 195 in_coordinate_type lat_max = geometry::get<max_corner, 1>(box_in); 196 197 math::normalize_spheroidal_box_coordinates 198 < 199 typename geometry::detail::cs_angular_units<BoxIn>::type, 200 IsEquatorial, 201 in_coordinate_type 202 >(lon_min, lat_min, lon_max, lat_max); 203 204 apply_to_coordinates 205 < 206 typename geometry::detail::cs_angular_units<BoxIn>::type, 207 typename geometry::detail::cs_angular_units<BoxOut>::type 208 >(lon_min, lat_min, lon_max, lat_max, box_in, box_out); 209 } 210 }; 211 212 213 } // namespace detail 214 #endif // DOXYGEN_NO_DETAIL 215 216 struct cartesian_point 217 : detail::do_nothing 218 {}; 219 220 struct cartesian_box 221 : detail::do_nothing 222 {}; 223 224 struct spherical_point 225 { 226 template <typename PointIn, typename PointOut> applyboost::geometry::strategy::normalize::spherical_point227 static inline void apply(PointIn const& point_in, PointOut& point_out) 228 { 229 detail::normalize_point 230 < 231 PointIn, PointOut, 232 boost::mpl::not_ 233 < 234 boost::is_same 235 < 236 typename cs_tag<PointIn>::type, 237 spherical_polar_tag 238 > 239 >::value 240 >::apply(point_in, point_out); 241 } 242 }; 243 244 struct spherical_box 245 { 246 template <typename BoxIn, typename BoxOut> applyboost::geometry::strategy::normalize::spherical_box247 static inline void apply(BoxIn const& box_in, BoxOut& box_out) 248 { 249 detail::normalize_box 250 < 251 BoxIn, BoxOut, 252 boost::mpl::not_ 253 < 254 boost::is_same 255 < 256 typename cs_tag<BoxIn>::type, 257 spherical_polar_tag 258 > 259 >::value 260 >::apply(box_in, box_out); 261 } 262 }; 263 264 }} // namespace strategy::normalize 265 266 }} // namespace boost::geometry 267 268 #endif // BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP 269