range_to_range.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014, 2019, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP
  8. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP
  9. #include <cstddef>
  10. #include <iterator>
  11. #include <utility>
  12. #include <boost/geometry/core/assert.hpp>
  13. #include <boost/geometry/core/point_type.hpp>
  14. #include <boost/geometry/strategies/distance.hpp>
  15. #include <boost/geometry/algorithms/dispatch/distance.hpp>
  16. #include <boost/geometry/index/rtree.hpp>
  17. namespace boost { namespace geometry
  18. {
  19. #ifndef DOXYGEN_NO_DETAIL
  20. namespace detail { namespace closest_feature
  21. {
  22. // returns a pair of a objects where the first is an object of the
  23. // r-tree range and the second an object of the query range that
  24. // realizes the closest feature of the two ranges
  25. class range_to_range_rtree
  26. {
  27. private:
  28. template
  29. <
  30. typename RTreeRangeIterator,
  31. typename QueryRangeIterator,
  32. typename Strategy,
  33. typename RTreeValueType,
  34. typename Distance
  35. >
  36. static inline void apply(RTreeRangeIterator rtree_first,
  37. RTreeRangeIterator rtree_last,
  38. QueryRangeIterator queries_first,
  39. QueryRangeIterator queries_last,
  40. Strategy const& strategy,
  41. RTreeValueType& rtree_min,
  42. QueryRangeIterator& qit_min,
  43. Distance& dist_min)
  44. {
  45. typedef strategy::index::services::from_strategy
  46. <
  47. Strategy
  48. > index_strategy_from;
  49. typedef index::parameters
  50. <
  51. index::linear<8>, typename index_strategy_from::type
  52. > index_parameters_type;
  53. typedef index::rtree<RTreeValueType, index_parameters_type> rtree_type;
  54. BOOST_GEOMETRY_ASSERT( rtree_first != rtree_last );
  55. BOOST_GEOMETRY_ASSERT( queries_first != queries_last );
  56. Distance const zero = Distance(0);
  57. dist_min = zero;
  58. // create -- packing algorithm
  59. rtree_type rt(rtree_first, rtree_last,
  60. index_parameters_type(index::linear<8>(),
  61. index_strategy_from::get(strategy)));
  62. RTreeValueType t_v;
  63. bool first = true;
  64. for (QueryRangeIterator qit = queries_first;
  65. qit != queries_last; ++qit, first = false)
  66. {
  67. std::size_t n = rt.query(index::nearest(*qit, 1), &t_v);
  68. BOOST_GEOMETRY_ASSERT( n > 0 );
  69. // n above is unused outside BOOST_GEOMETRY_ASSERT,
  70. // hence the call to boost::ignore_unused below
  71. //
  72. // however, t_v (initialized by the call to rt.query(...))
  73. // is used below, which is why we cannot put the call to
  74. // rt.query(...) inside BOOST_GEOMETRY_ASSERT
  75. boost::ignore_unused(n);
  76. Distance dist = dispatch::distance
  77. <
  78. RTreeValueType,
  79. typename std::iterator_traits
  80. <
  81. QueryRangeIterator
  82. >::value_type,
  83. Strategy
  84. >::apply(t_v, *qit, strategy);
  85. if (first || dist < dist_min)
  86. {
  87. dist_min = dist;
  88. rtree_min = t_v;
  89. qit_min = qit;
  90. if ( math::equals(dist_min, zero) )
  91. {
  92. return;
  93. }
  94. }
  95. }
  96. }
  97. public:
  98. template <typename RTreeRangeIterator, typename QueryRangeIterator>
  99. struct return_type
  100. {
  101. typedef std::pair
  102. <
  103. typename std::iterator_traits<RTreeRangeIterator>::value_type,
  104. QueryRangeIterator
  105. > type;
  106. };
  107. template
  108. <
  109. typename RTreeRangeIterator,
  110. typename QueryRangeIterator,
  111. typename Strategy,
  112. typename Distance
  113. >
  114. static inline typename return_type
  115. <
  116. RTreeRangeIterator, QueryRangeIterator
  117. >::type apply(RTreeRangeIterator rtree_first,
  118. RTreeRangeIterator rtree_last,
  119. QueryRangeIterator queries_first,
  120. QueryRangeIterator queries_last,
  121. Strategy const& strategy,
  122. Distance& dist_min)
  123. {
  124. typedef typename std::iterator_traits
  125. <
  126. RTreeRangeIterator
  127. >::value_type rtree_value_type;
  128. rtree_value_type rtree_min;
  129. QueryRangeIterator qit_min;
  130. apply(rtree_first, rtree_last, queries_first, queries_last,
  131. strategy, rtree_min, qit_min, dist_min);
  132. return std::make_pair(rtree_min, qit_min);
  133. }
  134. template
  135. <
  136. typename RTreeRangeIterator,
  137. typename QueryRangeIterator,
  138. typename Strategy
  139. >
  140. static inline typename return_type
  141. <
  142. RTreeRangeIterator, QueryRangeIterator
  143. >::type apply(RTreeRangeIterator rtree_first,
  144. RTreeRangeIterator rtree_last,
  145. QueryRangeIterator queries_first,
  146. QueryRangeIterator queries_last,
  147. Strategy const& strategy)
  148. {
  149. typedef typename std::iterator_traits
  150. <
  151. RTreeRangeIterator
  152. >::value_type rtree_value_type;
  153. typename strategy::distance::services::return_type
  154. <
  155. Strategy,
  156. typename point_type<rtree_value_type>::type,
  157. typename point_type
  158. <
  159. typename std::iterator_traits
  160. <
  161. QueryRangeIterator
  162. >::value_type
  163. >::type
  164. >::type dist_min;
  165. return apply(rtree_first, rtree_last, queries_first, queries_last,
  166. strategy, dist_min);
  167. }
  168. };
  169. }} // namespace detail::closest_feature
  170. #endif // DOXYGEN_NO_DETAIL
  171. }} // namespace boost::geometry
  172. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP