1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. 4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. 5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. 6 7 // This file was modified by Oracle on 2015-2018. 8 // Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. 9 10 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 11 12 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library 13 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. 14 15 // Use, modification and distribution is subject to the Boost Software License, 16 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 17 // http://www.boost.org/LICENSE_1_0.txt) 18 19 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP 20 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP 21 22 23 #include <boost/geometry/core/access.hpp> 24 #include <boost/geometry/core/coordinate_dimension.hpp> 25 #include <boost/geometry/core/cs.hpp> 26 #include <boost/geometry/strategies/covered_by.hpp> 27 #include <boost/geometry/strategies/within.hpp> 28 #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> 29 30 31 namespace boost { namespace geometry { namespace strategy 32 { 33 34 namespace within 35 { 36 37 #ifndef DOXYGEN_NO_DETAIL 38 namespace detail 39 { 40 41 struct within_coord 42 { 43 template <typename Value1, typename Value2> applyboost::geometry::strategy::within::detail::within_coord44 static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) 45 { 46 return value > min_value && value < max_value; 47 } 48 }; 49 50 struct covered_by_coord 51 { 52 template <typename Value1, typename Value2> applyboost::geometry::strategy::within::detail::covered_by_coord53 static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) 54 { 55 return value >= min_value && value <= max_value; 56 } 57 }; 58 59 template <typename Geometry, std::size_t Dimension, typename CSTag> 60 struct within_range 61 : within_coord 62 {}; 63 64 65 template <typename Geometry, std::size_t Dimension, typename CSTag> 66 struct covered_by_range 67 : covered_by_coord 68 {}; 69 70 71 // NOTE: the result would be the same if instead of structs defined below 72 // the above xxx_range were used with the following arguments: 73 // (min_value + diff_min, min_value, max_value) 74 struct within_longitude_diff 75 { 76 template <typename CalcT> applyboost::geometry::strategy::within::detail::within_longitude_diff77 static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value) 78 { 79 CalcT const c0 = 0; 80 return diff_min > c0 81 && (min_value + diff_min < max_value 82 /*|| max_value - diff_min > min_value*/); 83 } 84 }; 85 86 struct covered_by_longitude_diff 87 { 88 template <typename CalcT> applyboost::geometry::strategy::within::detail::covered_by_longitude_diff89 static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value) 90 { 91 return min_value + diff_min <= max_value 92 /*|| max_value - diff_min >= min_value*/; 93 } 94 }; 95 96 97 template <typename Geometry, 98 typename CoordCheck, 99 typename DiffCheck> 100 struct longitude_range 101 { 102 template <typename Value1, typename Value2> applyboost::geometry::strategy::within::detail::longitude_range103 static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) 104 { 105 typedef typename select_most_precise 106 < 107 Value1, Value2 108 >::type calc_t; 109 typedef typename geometry::detail::cs_angular_units<Geometry>::type units_t; 110 typedef math::detail::constants_on_spheroid<calc_t, units_t> constants; 111 112 if (CoordCheck::apply(value, min_value, max_value)) 113 { 114 return true; 115 } 116 117 // min <= max <=> diff >= 0 118 calc_t const diff_ing = max_value - min_value; 119 120 // if containing covers the whole globe it contains all 121 if (diff_ing >= constants::period()) 122 { 123 return true; 124 } 125 126 // calculate positive longitude translation with min_value as origin 127 calc_t const diff_min = math::longitude_distance_unsigned<units_t, calc_t>(min_value, value); 128 129 return DiffCheck::template apply<calc_t>(diff_min, min_value, max_value); 130 } 131 }; 132 133 134 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag 135 template <typename Geometry> 136 struct within_range<Geometry, 0, spherical_tag> 137 : longitude_range<Geometry, within_coord, within_longitude_diff> 138 {}; 139 140 141 template <typename Geometry> 142 struct covered_by_range<Geometry, 0, spherical_tag> 143 : longitude_range<Geometry, covered_by_coord, covered_by_longitude_diff> 144 {}; 145 146 147 template 148 < 149 template <typename, std::size_t, typename> class SubStrategy, 150 typename CSTag, // cartesian_tag or spherical_tag 151 std::size_t Dimension, 152 std::size_t DimensionCount 153 > 154 struct relate_point_box_loop 155 { 156 template <typename Point, typename Box> applyboost::geometry::strategy::within::detail::relate_point_box_loop157 static inline bool apply(Point const& point, Box const& box) 158 { 159 if (! SubStrategy<Point, Dimension, CSTag>::apply(get<Dimension>(point), 160 get<min_corner, Dimension>(box), 161 get<max_corner, Dimension>(box)) 162 ) 163 { 164 return false; 165 } 166 167 return relate_point_box_loop 168 < 169 SubStrategy, 170 CSTag, 171 Dimension + 1, DimensionCount 172 >::apply(point, box); 173 } 174 }; 175 176 177 template 178 < 179 template <typename, std::size_t, typename> class SubStrategy, 180 typename CSTag, 181 std::size_t DimensionCount 182 > 183 struct relate_point_box_loop<SubStrategy, CSTag, DimensionCount, DimensionCount> 184 { 185 template <typename Point, typename Box> applyboost::geometry::strategy::within::detail::relate_point_box_loop186 static inline bool apply(Point const& , Box const& ) 187 { 188 return true; 189 } 190 }; 191 192 } // namespace detail 193 #endif // DOXYGEN_NO_DETAIL 194 195 struct cartesian_point_box 196 { 197 template <typename Point, typename Box> applyboost::geometry::strategy::within::cartesian_point_box198 static inline bool apply(Point const& point, Box const& box) 199 { 200 return detail::relate_point_box_loop 201 < 202 detail::within_range, 203 cartesian_tag, 204 0, dimension<Point>::value 205 >::apply(point, box); 206 } 207 }; 208 209 struct spherical_point_box 210 { 211 template <typename Point, typename Box> applyboost::geometry::strategy::within::spherical_point_box212 static inline bool apply(Point const& point, Box const& box) 213 { 214 return detail::relate_point_box_loop 215 < 216 detail::within_range, 217 spherical_tag, 218 0, dimension<Point>::value 219 >::apply(point, box); 220 } 221 }; 222 223 224 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 225 namespace services 226 { 227 228 template <typename Point, typename Box> 229 struct default_strategy 230 < 231 Point, Box, 232 point_tag, box_tag, 233 pointlike_tag, areal_tag, 234 cartesian_tag, cartesian_tag 235 > 236 { 237 typedef within::cartesian_point_box type; 238 }; 239 240 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag 241 template <typename Point, typename Box> 242 struct default_strategy 243 < 244 Point, Box, 245 point_tag, box_tag, 246 pointlike_tag, areal_tag, 247 spherical_tag, spherical_tag 248 > 249 { 250 typedef within::spherical_point_box type; 251 }; 252 253 254 } // namespace services 255 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 256 257 } // namespace within 258 259 namespace covered_by 260 { 261 262 struct cartesian_point_box 263 { 264 template <typename Point, typename Box> applyboost::geometry::strategy::covered_by::cartesian_point_box265 static inline bool apply(Point const& point, Box const& box) 266 { 267 return within::detail::relate_point_box_loop 268 < 269 within::detail::covered_by_range, 270 cartesian_tag, 271 0, dimension<Point>::value 272 >::apply(point, box); 273 } 274 }; 275 276 struct spherical_point_box 277 { 278 template <typename Point, typename Box> applyboost::geometry::strategy::covered_by::spherical_point_box279 static inline bool apply(Point const& point, Box const& box) 280 { 281 return within::detail::relate_point_box_loop 282 < 283 within::detail::covered_by_range, 284 spherical_tag, 285 0, dimension<Point>::value 286 >::apply(point, box); 287 } 288 }; 289 290 291 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 292 namespace services 293 { 294 295 296 template <typename Point, typename Box> 297 struct default_strategy 298 < 299 Point, Box, 300 point_tag, box_tag, 301 pointlike_tag, areal_tag, 302 cartesian_tag, cartesian_tag 303 > 304 { 305 typedef covered_by::cartesian_point_box type; 306 }; 307 308 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag 309 template <typename Point, typename Box> 310 struct default_strategy 311 < 312 Point, Box, 313 point_tag, box_tag, 314 pointlike_tag, areal_tag, 315 spherical_tag, spherical_tag 316 > 317 { 318 typedef covered_by::spherical_point_box type; 319 }; 320 321 322 } // namespace services 323 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 324 325 326 } // namespace covered_by 327 328 329 }}} // namespace boost::geometry::strategy 330 331 332 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP 333