1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. 4 // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. 5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. 6 7 // This file was modified by Oracle on 2018. 8 // Modifications copyright (c) 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_DISTANCE_PYTHAGORAS_HPP 20 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP 21 22 23 #include <boost/geometry/core/access.hpp> 24 25 #include <boost/geometry/geometries/concepts/point_concept.hpp> 26 27 #include <boost/geometry/strategies/distance.hpp> 28 29 #include <boost/geometry/util/math.hpp> 30 #include <boost/geometry/util/calculation_type.hpp> 31 32 33 namespace boost { namespace geometry 34 { 35 36 namespace strategy { namespace distance 37 { 38 39 #ifndef DOXYGEN_NO_DETAIL 40 namespace detail 41 { 42 43 template <size_t I, typename T> 44 struct compute_pythagoras 45 { 46 template <typename Point1, typename Point2> applyboost::geometry::strategy::distance::detail::compute_pythagoras47 static inline T apply(Point1 const& p1, Point2 const& p2) 48 { 49 T const c1 = boost::numeric_cast<T>(get<I-1>(p1)); 50 T const c2 = boost::numeric_cast<T>(get<I-1>(p2)); 51 T const d = c1 - c2; 52 return d * d + compute_pythagoras<I-1, T>::apply(p1, p2); 53 } 54 }; 55 56 template <typename T> 57 struct compute_pythagoras<0, T> 58 { 59 template <typename Point1, typename Point2> applyboost::geometry::strategy::distance::detail::compute_pythagoras60 static inline T apply(Point1 const&, Point2 const&) 61 { 62 return boost::numeric_cast<T>(0); 63 } 64 }; 65 66 } 67 #endif // DOXYGEN_NO_DETAIL 68 69 70 namespace comparable 71 { 72 73 /*! 74 \brief Strategy to calculate comparable distance between two points 75 \ingroup strategies 76 \tparam Point1 \tparam_first_point 77 \tparam Point2 \tparam_second_point 78 \tparam CalculationType \tparam_calculation 79 */ 80 template <typename CalculationType = void> 81 class pythagoras 82 { 83 public : 84 85 template <typename Point1, typename Point2> 86 struct calculation_type 87 : util::calculation_type::geometric::binary 88 < 89 Point1, 90 Point2, 91 CalculationType, 92 double, 93 double 94 > 95 {}; 96 97 template <typename Point1, typename Point2> 98 static inline typename calculation_type<Point1, Point2>::type apply(Point1 const & p1,Point2 const & p2)99 apply(Point1 const& p1, Point2 const& p2) 100 { 101 BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point1>) ); 102 BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) ); 103 104 // Calculate distance using Pythagoras 105 // (Leave comment above for Doxygen) 106 107 assert_dimension_equal<Point1, Point2>(); 108 109 return detail::compute_pythagoras 110 < 111 dimension<Point1>::value, 112 typename calculation_type<Point1, Point2>::type 113 >::apply(p1, p2); 114 } 115 }; 116 117 } // namespace comparable 118 119 120 /*! 121 \brief Strategy to calculate the distance between two points 122 \ingroup strategies 123 \tparam CalculationType \tparam_calculation 124 125 \qbk{ 126 [heading Notes] 127 [note Can be used for points with two\, three or more dimensions] 128 [heading See also] 129 [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)] 130 } 131 132 */ 133 template 134 < 135 typename CalculationType = void 136 > 137 class pythagoras 138 { 139 public : 140 141 template <typename P1, typename P2> 142 struct calculation_type 143 : util::calculation_type::geometric::binary 144 < 145 P1, 146 P2, 147 CalculationType, 148 double, 149 double // promote integer to double 150 > 151 {}; 152 153 /*! 154 \brief applies the distance calculation using pythagoras 155 \return the calculated distance (including taking the square root) 156 \param p1 first point 157 \param p2 second point 158 */ 159 template <typename P1, typename P2> 160 static inline typename calculation_type<P1, P2>::type apply(P1 const & p1,P2 const & p2)161 apply(P1 const& p1, P2 const& p2) 162 { 163 // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call 164 return math::sqrt 165 ( 166 boost::numeric_cast<typename calculation_type<P1, P2>::type> 167 ( 168 comparable::pythagoras<CalculationType>::apply(p1, p2) 169 ) 170 ); 171 } 172 }; 173 174 175 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 176 namespace services 177 { 178 179 template <typename CalculationType> 180 struct tag<pythagoras<CalculationType> > 181 { 182 typedef strategy_tag_distance_point_point type; 183 }; 184 185 186 template <typename CalculationType, typename P1, typename P2> 187 struct return_type<distance::pythagoras<CalculationType>, P1, P2> 188 : pythagoras<CalculationType>::template calculation_type<P1, P2> 189 {}; 190 191 192 template <typename CalculationType> 193 struct comparable_type<pythagoras<CalculationType> > 194 { 195 typedef comparable::pythagoras<CalculationType> type; 196 }; 197 198 199 template <typename CalculationType> 200 struct get_comparable<pythagoras<CalculationType> > 201 { 202 typedef comparable::pythagoras<CalculationType> comparable_type; 203 public : applyboost::geometry::strategy::distance::services::get_comparable204 static inline comparable_type apply(pythagoras<CalculationType> const& ) 205 { 206 return comparable_type(); 207 } 208 }; 209 210 211 template <typename CalculationType, typename Point1, typename Point2> 212 struct result_from_distance<pythagoras<CalculationType>, Point1, Point2> 213 { 214 private : 215 typedef typename return_type<pythagoras<CalculationType>, Point1, Point2>::type return_type; 216 public : 217 template <typename T> applyboost::geometry::strategy::distance::services::result_from_distance218 static inline return_type apply(pythagoras<CalculationType> const& , T const& value) 219 { 220 return return_type(value); 221 } 222 }; 223 224 225 // Specializations for comparable::pythagoras 226 template <typename CalculationType> 227 struct tag<comparable::pythagoras<CalculationType> > 228 { 229 typedef strategy_tag_distance_point_point type; 230 }; 231 232 233 template <typename CalculationType, typename P1, typename P2> 234 struct return_type<comparable::pythagoras<CalculationType>, P1, P2> 235 : comparable::pythagoras<CalculationType>::template calculation_type<P1, P2> 236 {}; 237 238 239 240 241 template <typename CalculationType> 242 struct comparable_type<comparable::pythagoras<CalculationType> > 243 { 244 typedef comparable::pythagoras<CalculationType> type; 245 }; 246 247 248 template <typename CalculationType> 249 struct get_comparable<comparable::pythagoras<CalculationType> > 250 { 251 typedef comparable::pythagoras<CalculationType> comparable_type; 252 public : applyboost::geometry::strategy::distance::services::get_comparable253 static inline comparable_type apply(comparable::pythagoras<CalculationType> const& ) 254 { 255 return comparable_type(); 256 } 257 }; 258 259 260 template <typename CalculationType, typename Point1, typename Point2> 261 struct result_from_distance<comparable::pythagoras<CalculationType>, Point1, Point2> 262 { 263 private : 264 typedef typename return_type<comparable::pythagoras<CalculationType>, Point1, Point2>::type return_type; 265 public : 266 template <typename T> applyboost::geometry::strategy::distance::services::result_from_distance267 static inline return_type apply(comparable::pythagoras<CalculationType> const& , T const& value) 268 { 269 return_type const v = value; 270 return v * v; 271 } 272 }; 273 274 275 template <typename Point1, typename Point2> 276 struct default_strategy 277 < 278 point_tag, point_tag, Point1, Point2, cartesian_tag, cartesian_tag 279 > 280 { 281 typedef pythagoras<> type; 282 }; 283 284 285 } // namespace services 286 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 287 288 289 }} // namespace strategy::distance 290 291 292 }} // namespace boost::geometry 293 294 295 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP 296