distance_pythagoras.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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/math.hpp>
  19. #include <boost/geometry/util/calculation_type.hpp>
  20. namespace boost { namespace geometry
  21. {
  22. namespace strategy { namespace distance
  23. {
  24. #ifndef DOXYGEN_NO_DETAIL
  25. namespace detail
  26. {
  27. template <size_t I, typename T>
  28. struct compute_pythagoras
  29. {
  30. template <typename Point1, typename Point2>
  31. static inline T apply(Point1 const& p1, Point2 const& p2)
  32. {
  33. T const c1 = boost::numeric_cast<T>(get<I-1>(p1));
  34. T const c2 = boost::numeric_cast<T>(get<I-1>(p2));
  35. T const d = c1 - c2;
  36. return d * d + compute_pythagoras<I-1, T>::apply(p1, p2);
  37. }
  38. };
  39. template <typename T>
  40. struct compute_pythagoras<0, T>
  41. {
  42. template <typename Point1, typename Point2>
  43. static inline T apply(Point1 const&, Point2 const&)
  44. {
  45. return boost::numeric_cast<T>(0);
  46. }
  47. };
  48. }
  49. #endif // DOXYGEN_NO_DETAIL
  50. namespace comparable
  51. {
  52. /*!
  53. \brief Strategy to calculate comparable distance between two points
  54. \ingroup strategies
  55. \tparam Point1 \tparam_first_point
  56. \tparam Point2 \tparam_second_point
  57. \tparam CalculationType \tparam_calculation
  58. */
  59. template <typename CalculationType = void>
  60. class pythagoras
  61. {
  62. public :
  63. template <typename Point1, typename Point2>
  64. struct calculation_type
  65. : util::calculation_type::geometric::binary
  66. <
  67. Point1,
  68. Point2,
  69. CalculationType,
  70. double,
  71. double
  72. >
  73. {};
  74. template <typename Point1, typename Point2>
  75. static inline typename calculation_type<Point1, Point2>::type
  76. apply(Point1 const& p1, Point2 const& p2)
  77. {
  78. BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point1>) );
  79. BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
  80. // Calculate distance using Pythagoras
  81. // (Leave comment above for Doxygen)
  82. assert_dimension_equal<Point1, Point2>();
  83. return detail::compute_pythagoras
  84. <
  85. dimension<Point1>::value,
  86. typename calculation_type<Point1, Point2>::type
  87. >::apply(p1, p2);
  88. }
  89. };
  90. } // namespace comparable
  91. /*!
  92. \brief Strategy to calculate the distance between two points
  93. \ingroup strategies
  94. \tparam CalculationType \tparam_calculation
  95. \qbk{
  96. [heading Notes]
  97. [note Can be used for points with two\, three or more dimensions]
  98. [heading See also]
  99. [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
  100. }
  101. */
  102. template
  103. <
  104. typename CalculationType = void
  105. >
  106. class pythagoras
  107. {
  108. public :
  109. template <typename P1, typename P2>
  110. struct calculation_type
  111. : util::calculation_type::geometric::binary
  112. <
  113. P1,
  114. P2,
  115. CalculationType,
  116. double,
  117. double // promote integer to double
  118. >
  119. {};
  120. /*!
  121. \brief applies the distance calculation using pythagoras
  122. \return the calculated distance (including taking the square root)
  123. \param p1 first point
  124. \param p2 second point
  125. */
  126. template <typename P1, typename P2>
  127. static inline typename calculation_type<P1, P2>::type
  128. apply(P1 const& p1, P2 const& p2)
  129. {
  130. // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
  131. return math::sqrt
  132. (
  133. boost::numeric_cast<typename calculation_type<P1, P2>::type>
  134. (
  135. comparable::pythagoras<CalculationType>::apply(p1, p2)
  136. )
  137. );
  138. }
  139. };
  140. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  141. namespace services
  142. {
  143. template <typename CalculationType>
  144. struct tag<pythagoras<CalculationType> >
  145. {
  146. typedef strategy_tag_distance_point_point type;
  147. };
  148. template <typename CalculationType, typename P1, typename P2>
  149. struct return_type<distance::pythagoras<CalculationType>, P1, P2>
  150. : pythagoras<CalculationType>::template calculation_type<P1, P2>
  151. {};
  152. template <typename CalculationType>
  153. struct comparable_type<pythagoras<CalculationType> >
  154. {
  155. typedef comparable::pythagoras<CalculationType> type;
  156. };
  157. template <typename CalculationType>
  158. struct get_comparable<pythagoras<CalculationType> >
  159. {
  160. typedef comparable::pythagoras<CalculationType> comparable_type;
  161. public :
  162. static inline comparable_type apply(pythagoras<CalculationType> const& )
  163. {
  164. return comparable_type();
  165. }
  166. };
  167. template <typename CalculationType, typename Point1, typename Point2>
  168. struct result_from_distance<pythagoras<CalculationType>, Point1, Point2>
  169. {
  170. private :
  171. typedef typename return_type<pythagoras<CalculationType>, Point1, Point2>::type return_type;
  172. public :
  173. template <typename T>
  174. static inline return_type apply(pythagoras<CalculationType> const& , T const& value)
  175. {
  176. return return_type(value);
  177. }
  178. };
  179. // Specializations for comparable::pythagoras
  180. template <typename CalculationType>
  181. struct tag<comparable::pythagoras<CalculationType> >
  182. {
  183. typedef strategy_tag_distance_point_point type;
  184. };
  185. template <typename CalculationType, typename P1, typename P2>
  186. struct return_type<comparable::pythagoras<CalculationType>, P1, P2>
  187. : comparable::pythagoras<CalculationType>::template calculation_type<P1, P2>
  188. {};
  189. template <typename CalculationType>
  190. struct comparable_type<comparable::pythagoras<CalculationType> >
  191. {
  192. typedef comparable::pythagoras<CalculationType> type;
  193. };
  194. template <typename CalculationType>
  195. struct get_comparable<comparable::pythagoras<CalculationType> >
  196. {
  197. typedef comparable::pythagoras<CalculationType> comparable_type;
  198. public :
  199. static inline comparable_type apply(comparable::pythagoras<CalculationType> const& )
  200. {
  201. return comparable_type();
  202. }
  203. };
  204. template <typename CalculationType, typename Point1, typename Point2>
  205. struct result_from_distance<comparable::pythagoras<CalculationType>, Point1, Point2>
  206. {
  207. private :
  208. typedef typename return_type<comparable::pythagoras<CalculationType>, Point1, Point2>::type return_type;
  209. public :
  210. template <typename T>
  211. static inline return_type apply(comparable::pythagoras<CalculationType> const& , T const& value)
  212. {
  213. return_type const v = value;
  214. return v * v;
  215. }
  216. };
  217. template <typename Point1, typename Point2>
  218. struct default_strategy
  219. <
  220. point_tag, point_tag, Point1, Point2, cartesian_tag, cartesian_tag
  221. >
  222. {
  223. typedef pythagoras<> type;
  224. };
  225. } // namespace services
  226. #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  227. }} // namespace strategy::distance
  228. }} // namespace boost::geometry
  229. #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP