1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2008-2014 Bruno Lalande, Paris, France. 4 // Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands. 5 // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. 6 7 // This file was modified by Oracle on 2014, 2018. 8 // Modifications copyright (c) 2014, 2018, Oracle and/or its affiliates. 9 10 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle 11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 12 13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library 14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. 15 16 // Use, modification and distribution is subject to the Boost Software License, 17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 18 // http://www.boost.org/LICENSE_1_0.txt) 19 20 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP 21 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP 22 23 24 #include <boost/geometry/core/access.hpp> 25 #include <boost/geometry/core/point_type.hpp> 26 27 #include <boost/geometry/geometries/concepts/point_concept.hpp> 28 29 #include <boost/geometry/strategies/distance.hpp> 30 31 #include <boost/geometry/util/math.hpp> 32 #include <boost/geometry/util/calculation_type.hpp> 33 34 35 36 namespace boost { namespace geometry 37 { 38 39 namespace strategy { namespace distance 40 { 41 42 #ifndef DOXYGEN_NO_DETAIL 43 namespace detail 44 { 45 46 template <std::size_t I> 47 struct compute_pythagoras_box_box 48 { 49 template <typename Box1, typename Box2, typename T> applyboost::geometry::strategy::distance::detail::compute_pythagoras_box_box50 static inline void apply(Box1 const& box1, Box2 const& box2, T& result) 51 { 52 T const b1_min_coord = 53 boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box1)); 54 T const b1_max_coord = 55 boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box1)); 56 57 T const b2_min_coord = 58 boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box2)); 59 T const b2_max_coord = 60 boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box2)); 61 62 if ( b1_max_coord < b2_min_coord ) 63 { 64 T diff = b2_min_coord - b1_max_coord; 65 result += diff * diff; 66 } 67 if ( b1_min_coord > b2_max_coord ) 68 { 69 T diff = b1_min_coord - b2_max_coord; 70 result += diff * diff; 71 } 72 73 compute_pythagoras_box_box<I-1>::apply(box1, box2, result); 74 } 75 }; 76 77 template <> 78 struct compute_pythagoras_box_box<0> 79 { 80 template <typename Box1, typename Box2, typename T> applyboost::geometry::strategy::distance::detail::compute_pythagoras_box_box81 static inline void apply(Box1 const&, Box2 const&, T&) 82 { 83 } 84 }; 85 86 } 87 #endif // DOXYGEN_NO_DETAIL 88 89 90 namespace comparable 91 { 92 93 /*! 94 \brief Strategy to calculate comparable distance between two boxes 95 \ingroup strategies 96 \tparam Box1 \tparam_first_box 97 \tparam Box2 \tparam_second_box 98 \tparam CalculationType \tparam_calculation 99 */ 100 template <typename CalculationType = void> 101 class pythagoras_box_box 102 { 103 public : 104 105 template <typename Box1, typename Box2> 106 struct calculation_type 107 { 108 typedef typename util::calculation_type::geometric::binary 109 < 110 Box1, 111 Box2, 112 CalculationType 113 >::type type; 114 }; 115 116 template <typename Box1, typename Box2> 117 static inline typename calculation_type<Box1, Box2>::type apply(Box1 const & box1,Box2 const & box2)118 apply(Box1 const& box1, Box2 const& box2) 119 { 120 BOOST_CONCEPT_ASSERT 121 ( (concepts::ConstPoint<typename point_type<Box1>::type>) ); 122 BOOST_CONCEPT_ASSERT 123 ( (concepts::ConstPoint<typename point_type<Box2>::type>) ); 124 125 // Calculate distance using Pythagoras 126 // (Leave comment above for Doxygen) 127 128 assert_dimension_equal<Box1, Box2>(); 129 130 typename calculation_type<Box1, Box2>::type result(0); 131 132 detail::compute_pythagoras_box_box 133 < 134 dimension<Box1>::value 135 >::apply(box1, box2, result); 136 137 return result; 138 } 139 }; 140 141 } // namespace comparable 142 143 144 /*! 145 \brief Strategy to calculate the distance between two boxes 146 \ingroup strategies 147 \tparam CalculationType \tparam_calculation 148 149 \qbk{ 150 [heading Notes] 151 [note Can be used for boxes with two\, three or more dimensions] 152 [heading See also] 153 [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)] 154 } 155 156 */ 157 template 158 < 159 typename CalculationType = void 160 > 161 class pythagoras_box_box 162 { 163 public : 164 165 template <typename Box1, typename Box2> 166 struct calculation_type 167 : util::calculation_type::geometric::binary 168 < 169 Box1, 170 Box2, 171 CalculationType, 172 double, 173 double // promote integer to double 174 > 175 {}; 176 177 /*! 178 \brief applies the distance calculation using pythagoras_box_box 179 \return the calculated distance (including taking the square root) 180 \param box1 first box 181 \param box2 second box 182 */ 183 template <typename Box1, typename Box2> 184 static inline typename calculation_type<Box1, Box2>::type apply(Box1 const & box1,Box2 const & box2)185 apply(Box1 const& box1, Box2 const& box2) 186 { 187 // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call 188 return math::sqrt 189 ( 190 boost::numeric_cast<typename calculation_type 191 < 192 Box1, Box2 193 >::type> 194 ( 195 comparable::pythagoras_box_box 196 < 197 CalculationType 198 >::apply(box1, box2) 199 ) 200 ); 201 } 202 }; 203 204 205 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 206 namespace services 207 { 208 209 template <typename CalculationType> 210 struct tag<pythagoras_box_box<CalculationType> > 211 { 212 typedef strategy_tag_distance_box_box type; 213 }; 214 215 216 template <typename CalculationType, typename Box1, typename Box2> 217 struct return_type<distance::pythagoras_box_box<CalculationType>, Box1, Box2> 218 : pythagoras_box_box<CalculationType>::template calculation_type<Box1, Box2> 219 {}; 220 221 222 template <typename CalculationType> 223 struct comparable_type<pythagoras_box_box<CalculationType> > 224 { 225 typedef comparable::pythagoras_box_box<CalculationType> type; 226 }; 227 228 229 template <typename CalculationType> 230 struct get_comparable<pythagoras_box_box<CalculationType> > 231 { 232 typedef comparable::pythagoras_box_box<CalculationType> comparable_type; 233 public : 234 static inline comparable_type applyboost::geometry::strategy::distance::services::get_comparable235 apply(pythagoras_box_box<CalculationType> const& ) 236 { 237 return comparable_type(); 238 } 239 }; 240 241 242 template <typename CalculationType, typename Box1, typename Box2> 243 struct result_from_distance<pythagoras_box_box<CalculationType>, Box1, Box2> 244 { 245 private: 246 typedef typename return_type 247 < 248 pythagoras_box_box<CalculationType>, Box1, Box2 249 >::type return_type; 250 public: 251 template <typename T> 252 static inline return_type applyboost::geometry::strategy::distance::services::result_from_distance253 apply(pythagoras_box_box<CalculationType> const& , T const& value) 254 { 255 return return_type(value); 256 } 257 }; 258 259 260 // Specializations for comparable::pythagoras_box_box 261 template <typename CalculationType> 262 struct tag<comparable::pythagoras_box_box<CalculationType> > 263 { 264 typedef strategy_tag_distance_box_box type; 265 }; 266 267 268 template <typename CalculationType, typename Box1, typename Box2> 269 struct return_type<comparable::pythagoras_box_box<CalculationType>, Box1, Box2> 270 : comparable::pythagoras_box_box 271 < 272 CalculationType 273 >::template calculation_type<Box1, Box2> 274 {}; 275 276 277 278 279 template <typename CalculationType> 280 struct comparable_type<comparable::pythagoras_box_box<CalculationType> > 281 { 282 typedef comparable::pythagoras_box_box<CalculationType> type; 283 }; 284 285 286 template <typename CalculationType> 287 struct get_comparable<comparable::pythagoras_box_box<CalculationType> > 288 { 289 typedef comparable::pythagoras_box_box<CalculationType> comparable_type; 290 public : applyboost::geometry::strategy::distance::services::get_comparable291 static inline comparable_type apply(comparable_type const& ) 292 { 293 return comparable_type(); 294 } 295 }; 296 297 298 template <typename CalculationType, typename Box1, typename Box2> 299 struct result_from_distance 300 < 301 comparable::pythagoras_box_box<CalculationType>, Box1, Box2 302 > 303 { 304 private : 305 typedef typename return_type 306 < 307 comparable::pythagoras_box_box<CalculationType>, Box1, Box2 308 >::type return_type; 309 public : 310 template <typename T> 311 static inline return_type applyboost::geometry::strategy::distance::services::result_from_distance312 apply(comparable::pythagoras_box_box<CalculationType> const&, 313 T const& value) 314 { 315 return_type const v = value; 316 return v * v; 317 } 318 }; 319 320 321 template <typename BoxPoint1, typename BoxPoint2> 322 struct default_strategy 323 < 324 box_tag, box_tag, BoxPoint1, BoxPoint2, cartesian_tag, cartesian_tag 325 > 326 { 327 typedef pythagoras_box_box<> type; 328 }; 329 330 331 } // namespace services 332 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 333 334 335 }} // namespace strategy::distance 336 337 338 }} // namespace boost::geometry 339 340 341 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP 342