distance_pythagoras_box_box.hpp 8.8 KB

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