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-2017. 8 // Modifications copyright (c) 2015-2017, 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/strategies/covered_by.hpp> 26 #include <boost/geometry/strategies/within.hpp> 27 #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> 28 29 30 namespace boost { namespace geometry { namespace strategy 31 { 32 33 namespace within 34 { 35 36 struct within_coord 37 { 38 template <typename Value1, typename Value2> applyboost::geometry::strategy::within::within_coord39 static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) 40 { 41 return value > min_value && value < max_value; 42 } 43 }; 44 45 struct covered_by_coord 46 { 47 template <typename Value1, typename Value2> applyboost::geometry::strategy::within::covered_by_coord48 static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) 49 { 50 return value >= min_value && value <= max_value; 51 } 52 }; 53 54 template <typename Geometry, std::size_t Dimension, typename CSTag> 55 struct within_range 56 : within_coord 57 {}; 58 59 60 template <typename Geometry, std::size_t Dimension, typename CSTag> 61 struct covered_by_range 62 : covered_by_coord 63 {}; 64 65 66 // NOTE: the result would be the same if instead of structs defined below 67 // the above xxx_range were used with the following arguments: 68 // (min_value + diff_min, min_value, max_value) 69 struct within_longitude_diff 70 { 71 template <typename CalcT> applyboost::geometry::strategy::within::within_longitude_diff72 static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value) 73 { 74 CalcT const c0 = 0; 75 return diff_min > c0 76 && (min_value + diff_min < max_value 77 /*|| max_value - diff_min > min_value*/); 78 } 79 }; 80 81 struct covered_by_longitude_diff 82 { 83 template <typename CalcT> applyboost::geometry::strategy::within::covered_by_longitude_diff84 static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value) 85 { 86 return min_value + diff_min <= max_value 87 /*|| max_value - diff_min >= min_value*/; 88 } 89 }; 90 91 92 template <typename Geometry, 93 typename CoordCheck, 94 typename DiffCheck> 95 struct longitude_range 96 { 97 template <typename Value1, typename Value2> applyboost::geometry::strategy::within::longitude_range98 static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) 99 { 100 typedef typename select_most_precise 101 < 102 Value1, Value2 103 >::type calc_t; 104 typedef typename coordinate_system<Geometry>::type::units units_t; 105 typedef math::detail::constants_on_spheroid<calc_t, units_t> constants; 106 107 if (CoordCheck::apply(value, min_value, max_value)) 108 { 109 return true; 110 } 111 112 // min <= max <=> diff >= 0 113 calc_t const diff_ing = max_value - min_value; 114 115 // if containing covers the whole globe it contains all 116 if (diff_ing >= constants::period()) 117 { 118 return true; 119 } 120 121 // calculate positive longitude translation with min_value as origin 122 calc_t const diff_min = math::longitude_distance_unsigned<units_t, calc_t>(min_value, value); 123 124 return DiffCheck::template apply<calc_t>(diff_min, min_value, max_value); 125 } 126 }; 127 128 129 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag 130 template <typename Geometry> 131 struct within_range<Geometry, 0, spherical_tag> 132 : longitude_range<Geometry, within_coord, within_longitude_diff> 133 {}; 134 135 136 template <typename Geometry> 137 struct covered_by_range<Geometry, 0, spherical_tag> 138 : longitude_range<Geometry, covered_by_coord, covered_by_longitude_diff> 139 {}; 140 141 142 template 143 < 144 template <typename, std::size_t, typename> class SubStrategy, 145 typename Point, 146 typename Box, 147 std::size_t Dimension, 148 std::size_t DimensionCount 149 > 150 struct relate_point_box_loop 151 { applyboost::geometry::strategy::within::relate_point_box_loop152 static inline bool apply(Point const& point, Box const& box) 153 { 154 typedef typename tag_cast<typename cs_tag<Point>::type, spherical_tag>::type cs_tag_t; 155 156 if (! SubStrategy<Point, Dimension, cs_tag_t>::apply(get<Dimension>(point), 157 get<min_corner, Dimension>(box), 158 get<max_corner, Dimension>(box)) 159 ) 160 { 161 return false; 162 } 163 164 return relate_point_box_loop 165 < 166 SubStrategy, 167 Point, Box, 168 Dimension + 1, DimensionCount 169 >::apply(point, box); 170 } 171 }; 172 173 174 template 175 < 176 template <typename, std::size_t, typename> class SubStrategy, 177 typename Point, 178 typename Box, 179 std::size_t DimensionCount 180 > 181 struct relate_point_box_loop<SubStrategy, Point, Box, DimensionCount, DimensionCount> 182 { applyboost::geometry::strategy::within::relate_point_box_loop183 static inline bool apply(Point const& , Box const& ) 184 { 185 return true; 186 } 187 }; 188 189 190 template 191 < 192 typename Point, 193 typename Box, 194 template <typename, std::size_t, typename> class SubStrategy = within_range 195 > 196 struct point_in_box 197 { applyboost::geometry::strategy::within::point_in_box198 static inline bool apply(Point const& point, Box const& box) 199 { 200 return relate_point_box_loop 201 < 202 SubStrategy, 203 Point, Box, 204 0, dimension<Point>::type::value 205 >::apply(point, box); 206 } 207 }; 208 209 210 } // namespace within 211 212 213 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 214 215 216 namespace within { namespace services 217 { 218 219 template <typename Point, typename Box> 220 struct default_strategy 221 < 222 Point, Box, 223 point_tag, box_tag, 224 pointlike_tag, areal_tag, 225 cartesian_tag, cartesian_tag 226 > 227 { 228 typedef within::point_in_box<Point, Box> type; 229 }; 230 231 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag 232 template <typename Point, typename Box> 233 struct default_strategy 234 < 235 Point, Box, 236 point_tag, box_tag, 237 pointlike_tag, areal_tag, 238 spherical_tag, spherical_tag 239 > 240 { 241 typedef within::point_in_box<Point, Box> type; 242 }; 243 244 245 }} // namespace within::services 246 247 248 namespace covered_by { namespace services 249 { 250 251 252 template <typename Point, typename Box> 253 struct default_strategy 254 < 255 Point, Box, 256 point_tag, box_tag, 257 pointlike_tag, areal_tag, 258 cartesian_tag, cartesian_tag 259 > 260 { 261 typedef within::point_in_box 262 < 263 Point, Box, 264 within::covered_by_range 265 > type; 266 }; 267 268 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag 269 template <typename Point, typename Box> 270 struct default_strategy 271 < 272 Point, Box, 273 point_tag, box_tag, 274 pointlike_tag, areal_tag, 275 spherical_tag, spherical_tag 276 > 277 { 278 typedef within::point_in_box 279 < 280 Point, Box, 281 within::covered_by_range 282 > type; 283 }; 284 285 286 }} // namespace covered_by::services 287 288 289 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 290 291 292 }}} // namespace boost::geometry::strategy 293 294 295 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP 296