distance_pythagoras.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  3. // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. // This file was modified by Oracle on 2018.
  6. // Modifications copyright (c) 2018, Oracle and/or its affiliates.
  7. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  8. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  9. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  10. // Use, modification and distribution is subject to the Boost Software License,
  11. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  12. // http://www.boost.org/LICENSE_1_0.txt)
  13. #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
  14. #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
  15. #include <boost/geometry/core/access.hpp>
  16. #include <boost/geometry/geometries/concepts/point_concept.hpp>
  17. #include <boost/geometry/strategies/distance.hpp>
  18. #include <boost/geometry/util/calculation_type.hpp>
  19. #include <boost/geometry/util/math.hpp>
  20. #include <boost/geometry/util/numeric_cast.hpp>
  21. namespace boost { namespace geometry
  22. {
  23. namespace strategy { namespace distance
  24. {
  25. #ifndef DOXYGEN_NO_DETAIL
  26. namespace detail
  27. {
  28. template <size_t I, typename T>
  29. struct compute_pythagoras
  30. {
  31. template <typename Point1, typename Point2>
  32. static inline T apply(Point1 const& p1, Point2 const& p2)
  33. {
  34. T const c1 = util::numeric_cast<T>(get<I-1>(p1));
  35. T const c2 = util::numeric_cast<T>(get<I-1>(p2));
  36. T const d = c1 - c2;
  37. return d * d + compute_pythagoras<I-1, T>::apply(p1, p2);
  38. }
  39. };
  40. template <typename T>
  41. struct compute_pythagoras<0, T>
  42. {
  43. template <typename Point1, typename Point2>
  44. static inline T apply(Point1 const&, Point2 const&)
  45. {
  46. return util::numeric_cast<T>(0);
  47. }
  48. };
  49. }
  50. #endif // DOXYGEN_NO_DETAIL
  51. namespace comparable
  52. {
  53. /*!
  54. \brief Strategy to calculate comparable distance between two points
  55. \ingroup strategies
  56. \tparam Point1 \tparam_first_point
  57. \tparam Point2 \tparam_second_point
  58. \tparam CalculationType \tparam_calculation
  59. */
  60. template <typename CalculationType = void>
  61. class pythagoras
  62. {
  63. public :
  64. template <typename Point1, typename Point2>
  65. struct calculation_type
  66. : util::calculation_type::geometric::binary
  67. <
  68. Point1,
  69. Point2,
  70. CalculationType,
  71. double,
  72. double
  73. >
  74. {};
  75. template <typename Point1, typename Point2>
  76. static inline typename calculation_type<Point1, Point2>::type
  77. apply(Point1 const& p1, Point2 const& p2)
  78. {
  79. BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point1>) );
  80. BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
  81. // Calculate distance using Pythagoras
  82. // (Leave comment above for Doxygen)
  83. assert_dimension_equal<Point1, Point2>();
  84. return detail::compute_pythagoras
  85. <
  86. dimension<Point1>::value,
  87. typename calculation_type<Point1, Point2>::type
  88. >::apply(p1, p2);
  89. }
  90. };
  91. } // namespace comparable
  92. /*!
  93. \brief Strategy to calculate the distance between two points
  94. \ingroup strategies
  95. \tparam CalculationType \tparam_calculation
  96. \qbk{
  97. [heading Notes]
  98. [note Can be used for points with two\, three or more dimensions]
  99. [heading See also]
  100. [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
  101. }
  102. */
  103. template
  104. <
  105. typename CalculationType = void
  106. >
  107. class pythagoras
  108. {
  109. public :
  110. template <typename P1, typename P2>
  111. struct calculation_type
  112. : util::calculation_type::geometric::binary
  113. <
  114. P1,
  115. P2,
  116. CalculationType,
  117. double,
  118. double // promote integer to double
  119. >
  120. {};
  121. /*!
  122. \brief applies the distance calculation using pythagoras
  123. \return the calculated distance (including taking the square root)
  124. \param p1 first point
  125. \param p2 second point
  126. */
  127. template <typename P1, typename P2>
  128. static inline typename calculation_type<P1, P2>::type
  129. apply(P1 const& p1, P2 const& p2)
  130. {
  131. // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
  132. return math::sqrt
  133. (
  134. util::numeric_cast<typename calculation_type<P1, P2>::type>
  135. (
  136. comparable::pythagoras<CalculationType>::apply(p1, p2)
  137. )
  138. );
  139. }
  140. };
  141. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  142. namespace services
  143. {
  144. template <typename CalculationType>
  145. struct tag<pythagoras<CalculationType> >
  146. {
  147. typedef strategy_tag_distance_point_point type;
  148. };
  149. template <typename CalculationType, typename P1, typename P2>
  150. struct return_type<distance::pythagoras<CalculationType>, P1, P2>
  151. : pythagoras<CalculationType>::template calculation_type<P1, P2>
  152. {};
  153. template <typename CalculationType>
  154. struct comparable_type<pythagoras<CalculationType> >
  155. {
  156. typedef comparable::pythagoras<CalculationType> type;
  157. };
  158. template <typename CalculationType>
  159. struct get_comparable<pythagoras<CalculationType> >
  160. {
  161. typedef comparable::pythagoras<CalculationType> comparable_type;
  162. public :
  163. static inline comparable_type apply(pythagoras<CalculationType> const& )
  164. {
  165. return comparable_type();
  166. }
  167. };
  168. template <typename CalculationType, typename Point1, typename Point2>
  169. struct result_from_distance<pythagoras<CalculationType>, Point1, Point2>
  170. {
  171. private :
  172. typedef typename return_type<pythagoras<CalculationType>, Point1, Point2>::type return_type;
  173. public :
  174. template <typename T>
  175. static inline return_type apply(pythagoras<CalculationType> const& , T const& value)
  176. {
  177. return return_type(value);
  178. }
  179. };
  180. // Specializations for comparable::pythagoras
  181. template <typename CalculationType>
  182. struct tag<comparable::pythagoras<CalculationType> >
  183. {
  184. typedef strategy_tag_distance_point_point type;
  185. };
  186. template <typename CalculationType, typename P1, typename P2>
  187. struct return_type<comparable::pythagoras<CalculationType>, P1, P2>
  188. : comparable::pythagoras<CalculationType>::template calculation_type<P1, P2>
  189. {};
  190. template <typename CalculationType>
  191. struct comparable_type<comparable::pythagoras<CalculationType> >
  192. {
  193. typedef comparable::pythagoras<CalculationType> type;
  194. };
  195. template <typename CalculationType>
  196. struct get_comparable<comparable::pythagoras<CalculationType> >
  197. {
  198. typedef comparable::pythagoras<CalculationType> comparable_type;
  199. public :
  200. static inline comparable_type apply(comparable::pythagoras<CalculationType> const& )
  201. {
  202. return comparable_type();
  203. }
  204. };
  205. template <typename CalculationType, typename Point1, typename Point2>
  206. struct result_from_distance<comparable::pythagoras<CalculationType>, Point1, Point2>
  207. {
  208. private :
  209. typedef typename return_type<comparable::pythagoras<CalculationType>, Point1, Point2>::type return_type;
  210. public :
  211. template <typename T>
  212. static inline return_type apply(comparable::pythagoras<CalculationType> const& , T const& value)
  213. {
  214. return_type const v = value;
  215. return v * v;
  216. }
  217. };
  218. template <typename Point1, typename Point2>
  219. struct default_strategy
  220. <
  221. point_tag, point_tag, Point1, Point2, cartesian_tag, cartesian_tag
  222. >
  223. {
  224. typedef pythagoras<> type;
  225. };
  226. } // namespace services
  227. #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  228. }} // namespace strategy::distance
  229. }} // namespace boost::geometry
  230. #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP