distance_query.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. // Boost.Geometry Index
  2. //
  3. // R-tree distance (knn, path, etc. ) query visitor implementation
  4. //
  5. // Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
  6. //
  7. // This file was modified by Oracle on 2019-2023.
  8. // Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
  9. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  10. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  11. //
  12. // Use, modification and distribution is subject to the Boost Software License,
  13. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  14. // http://www.boost.org/LICENSE_1_0.txt)
  15. #ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
  16. #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
  17. #include <queue>
  18. #include <boost/geometry/index/detail/distance_predicates.hpp>
  19. #include <boost/geometry/index/detail/predicates.hpp>
  20. #include <boost/geometry/index/detail/priority_dequeue.hpp>
  21. #include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
  22. #include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
  23. #include <boost/geometry/index/detail/translator.hpp>
  24. #include <boost/geometry/index/parameters.hpp>
  25. namespace boost { namespace geometry { namespace index {
  26. namespace detail { namespace rtree { namespace visitors {
  27. struct pair_first_less
  28. {
  29. template <typename First, typename Second>
  30. inline bool operator()(std::pair<First, Second> const& p1,
  31. std::pair<First, Second> const& p2) const
  32. {
  33. return p1.first < p2.first;
  34. }
  35. };
  36. struct pair_first_greater
  37. {
  38. template <typename First, typename Second>
  39. inline bool operator()(std::pair<First, Second> const& p1,
  40. std::pair<First, Second> const& p2) const
  41. {
  42. return p1.first > p2.first;
  43. }
  44. };
  45. template <typename T, typename Comp>
  46. struct priority_dequeue : index::detail::priority_dequeue<T, std::vector<T>, Comp>
  47. {
  48. priority_dequeue() = default;
  49. //void reserve(typename std::vector<T>::size_type n)
  50. //{
  51. // this->c.reserve(n);
  52. //}
  53. //void clear()
  54. //{
  55. // this->c.clear();
  56. //}
  57. };
  58. template <typename T, typename Comp>
  59. struct priority_queue : std::priority_queue<T, std::vector<T>, Comp>
  60. {
  61. priority_queue() = default;
  62. //void reserve(typename std::vector<T>::size_type n)
  63. //{
  64. // this->c.reserve(n);
  65. //}
  66. void clear()
  67. {
  68. this->c.clear();
  69. }
  70. };
  71. struct branch_data_comp
  72. {
  73. template <typename BranchData>
  74. bool operator()(BranchData const& b1, BranchData const& b2) const
  75. {
  76. return b1.distance > b2.distance || (b1.distance == b2.distance && b1.reverse_level > b2.reverse_level);
  77. }
  78. };
  79. template <typename DistanceType, typename Value>
  80. class distance_query_result
  81. {
  82. using neighbor_data = std::pair<DistanceType, const Value *>;
  83. using neighbors_type = std::vector<neighbor_data>;
  84. using size_type = typename neighbors_type::size_type;
  85. public:
  86. inline distance_query_result(size_type k)
  87. : m_count(k)
  88. {
  89. m_neighbors.reserve(m_count);
  90. }
  91. // NOTE: Do not call if max_count() == 0
  92. inline void store(DistanceType const& distance, const Value * value_ptr)
  93. {
  94. if (m_neighbors.size() < m_count)
  95. {
  96. m_neighbors.push_back(std::make_pair(distance, value_ptr));
  97. if (m_neighbors.size() == m_count)
  98. {
  99. std::make_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
  100. }
  101. }
  102. else if (distance < m_neighbors.front().first)
  103. {
  104. std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
  105. m_neighbors.back().first = distance;
  106. m_neighbors.back().second = value_ptr;
  107. std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
  108. }
  109. }
  110. // NOTE: Do not call if max_count() == 0
  111. inline bool ignore_branch(DistanceType const& distance) const
  112. {
  113. return m_neighbors.size() == m_count
  114. && m_neighbors.front().first <= distance;
  115. }
  116. template <typename OutIt>
  117. inline size_type finish(OutIt out_it) const
  118. {
  119. for (auto const& p : m_neighbors)
  120. {
  121. *out_it = *(p.second);
  122. ++out_it;
  123. }
  124. return m_neighbors.size();
  125. }
  126. size_type max_count() const
  127. {
  128. return m_count;
  129. }
  130. private:
  131. size_type m_count;
  132. neighbors_type m_neighbors;
  133. };
  134. template <typename MembersHolder, typename Predicates>
  135. class distance_query
  136. {
  137. typedef typename MembersHolder::value_type value_type;
  138. typedef typename MembersHolder::box_type box_type;
  139. typedef typename MembersHolder::parameters_type parameters_type;
  140. typedef typename MembersHolder::translator_type translator_type;
  141. typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
  142. typedef typename MembersHolder::node node;
  143. typedef typename MembersHolder::internal_node internal_node;
  144. typedef typename MembersHolder::leaf leaf;
  145. typedef index::detail::predicates_element
  146. <
  147. index::detail::predicates_find_distance<Predicates>::value, Predicates
  148. > nearest_predicate_access;
  149. typedef typename nearest_predicate_access::type nearest_predicate_type;
  150. typedef typename indexable_type<translator_type>::type indexable_type;
  151. typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, strategy_type, value_tag> calculate_value_distance;
  152. typedef index::detail::calculate_distance<nearest_predicate_type, box_type, strategy_type, bounds_tag> calculate_node_distance;
  153. typedef typename calculate_value_distance::result_type value_distance_type;
  154. typedef typename calculate_node_distance::result_type node_distance_type;
  155. typedef typename MembersHolder::size_type size_type;
  156. typedef typename MembersHolder::node_pointer node_pointer;
  157. using neighbor_data = std::pair<value_distance_type, const value_type *>;
  158. using neighbors_type = std::vector<neighbor_data>;
  159. struct branch_data
  160. {
  161. branch_data(node_distance_type d, size_type rl, node_pointer p)
  162. : distance(d), reverse_level(rl), ptr(p)
  163. {}
  164. node_distance_type distance;
  165. size_type reverse_level;
  166. node_pointer ptr;
  167. };
  168. using branches_type = priority_queue<branch_data, branch_data_comp>;
  169. public:
  170. distance_query(MembersHolder const& members, Predicates const& pred)
  171. : m_tr(members.translator())
  172. , m_strategy(index::detail::get_strategy(members.parameters()))
  173. , m_pred(pred)
  174. {
  175. m_neighbors.reserve((std::min)(members.values_count, size_type(max_count())));
  176. //m_branches.reserve(members.parameters().get_min_elements() * members.leafs_level); ?
  177. // min, max or average?
  178. }
  179. template <typename OutIter>
  180. size_type apply(MembersHolder const& members, OutIter out_it)
  181. {
  182. return apply(members.root, members.leafs_level, out_it);
  183. }
  184. private:
  185. template <typename OutIter>
  186. size_type apply(node_pointer ptr, size_type reverse_level, OutIter out_it)
  187. {
  188. namespace id = index::detail;
  189. if (max_count() <= 0)
  190. {
  191. return 0;
  192. }
  193. for (;;)
  194. {
  195. if (reverse_level > 0)
  196. {
  197. internal_node& n = rtree::get<internal_node>(*ptr);
  198. // fill array of nodes meeting predicates
  199. for (auto const& p : rtree::elements(n))
  200. {
  201. node_distance_type node_distance; // for distance predicate
  202. // if current node meets predicates (0 is dummy value)
  203. if (id::predicates_check<id::bounds_tag>(m_pred, 0, p.first, m_strategy)
  204. // and if distance is ok
  205. && calculate_node_distance::apply(predicate(), p.first, m_strategy, node_distance)
  206. // and if current node is closer than the furthest neighbor
  207. && ! ignore_branch(node_distance))
  208. {
  209. // add current node's data into the list
  210. m_branches.push(branch_data(node_distance, reverse_level - 1, p.second));
  211. }
  212. }
  213. }
  214. else
  215. {
  216. leaf& n = rtree::get<leaf>(*ptr);
  217. // search leaf for closest value meeting predicates
  218. for (auto const& v : rtree::elements(n))
  219. {
  220. value_distance_type value_distance; // for distance predicate
  221. // if value meets predicates
  222. if (id::predicates_check<id::value_tag>(m_pred, v, m_tr(v), m_strategy)
  223. // and if distance is ok
  224. && calculate_value_distance::apply(predicate(), m_tr(v), m_strategy, value_distance))
  225. {
  226. // store value
  227. store_value(value_distance, boost::addressof(v));
  228. }
  229. }
  230. }
  231. if (m_branches.empty()
  232. || ignore_branch(m_branches.top().distance))
  233. {
  234. break;
  235. }
  236. ptr = m_branches.top().ptr;
  237. reverse_level = m_branches.top().reverse_level;
  238. m_branches.pop();
  239. }
  240. for (auto const& p : m_neighbors)
  241. {
  242. *out_it = *(p.second);
  243. ++out_it;
  244. }
  245. return m_neighbors.size();
  246. }
  247. bool ignore_branch(node_distance_type const& node_distance) const
  248. {
  249. return m_neighbors.size() == max_count()
  250. && m_neighbors.front().first <= node_distance;
  251. }
  252. void store_value(value_distance_type value_distance, const value_type * value_ptr)
  253. {
  254. if (m_neighbors.size() < max_count())
  255. {
  256. m_neighbors.push_back(std::make_pair(value_distance, value_ptr));
  257. if (m_neighbors.size() == max_count())
  258. {
  259. std::make_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
  260. }
  261. }
  262. else if (value_distance < m_neighbors.front().first)
  263. {
  264. std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
  265. m_neighbors.back() = std::make_pair(value_distance, value_ptr);
  266. std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
  267. }
  268. }
  269. std::size_t max_count() const
  270. {
  271. return nearest_predicate_access::get(m_pred).count;
  272. }
  273. nearest_predicate_type const& predicate() const
  274. {
  275. return nearest_predicate_access::get(m_pred);
  276. }
  277. translator_type const& m_tr;
  278. strategy_type m_strategy;
  279. Predicates const& m_pred;
  280. branches_type m_branches;
  281. neighbors_type m_neighbors;
  282. };
  283. template <typename MembersHolder, typename Predicates>
  284. class distance_query_incremental
  285. {
  286. typedef typename MembersHolder::value_type value_type;
  287. typedef typename MembersHolder::box_type box_type;
  288. typedef typename MembersHolder::parameters_type parameters_type;
  289. typedef typename MembersHolder::translator_type translator_type;
  290. typedef typename MembersHolder::allocators_type allocators_type;
  291. typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
  292. typedef typename MembersHolder::node node;
  293. typedef typename MembersHolder::internal_node internal_node;
  294. typedef typename MembersHolder::leaf leaf;
  295. typedef index::detail::predicates_element
  296. <
  297. index::detail::predicates_find_distance<Predicates>::value, Predicates
  298. > nearest_predicate_access;
  299. typedef typename nearest_predicate_access::type nearest_predicate_type;
  300. typedef typename indexable_type<translator_type>::type indexable_type;
  301. typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, strategy_type, value_tag> calculate_value_distance;
  302. typedef index::detail::calculate_distance<nearest_predicate_type, box_type, strategy_type, bounds_tag> calculate_node_distance;
  303. typedef typename calculate_value_distance::result_type value_distance_type;
  304. typedef typename calculate_node_distance::result_type node_distance_type;
  305. typedef typename allocators_type::size_type size_type;
  306. typedef typename allocators_type::const_reference const_reference;
  307. typedef typename allocators_type::node_pointer node_pointer;
  308. typedef typename rtree::elements_type<internal_node>::type internal_elements;
  309. typedef typename internal_elements::const_iterator internal_iterator;
  310. typedef typename rtree::elements_type<leaf>::type leaf_elements;
  311. using neighbor_data = std::pair<value_distance_type, const value_type *>;
  312. using neighbors_type = priority_dequeue<neighbor_data, pair_first_greater>;
  313. struct branch_data
  314. {
  315. branch_data(node_distance_type d, size_type rl, node_pointer p)
  316. : distance(d), reverse_level(rl), ptr(p)
  317. {}
  318. node_distance_type distance;
  319. size_type reverse_level;
  320. node_pointer ptr;
  321. };
  322. using branches_type = priority_queue<branch_data, branch_data_comp>;
  323. public:
  324. inline distance_query_incremental()
  325. : m_tr(nullptr)
  326. // , m_strategy()
  327. // , m_pred()
  328. , m_neighbors_count(0)
  329. , m_neighbor_ptr(nullptr)
  330. {}
  331. inline distance_query_incremental(Predicates const& pred)
  332. : m_tr(nullptr)
  333. // , m_strategy()
  334. , m_pred(pred)
  335. , m_neighbors_count(0)
  336. , m_neighbor_ptr(nullptr)
  337. {}
  338. inline distance_query_incremental(MembersHolder const& members, Predicates const& pred)
  339. : m_tr(::boost::addressof(members.translator()))
  340. , m_strategy(index::detail::get_strategy(members.parameters()))
  341. , m_pred(pred)
  342. , m_neighbors_count(0)
  343. , m_neighbor_ptr(nullptr)
  344. {}
  345. const_reference dereference() const
  346. {
  347. return *m_neighbor_ptr;
  348. }
  349. void initialize(MembersHolder const& members)
  350. {
  351. if (0 < max_count())
  352. {
  353. apply(members.root, members.leafs_level);
  354. increment();
  355. }
  356. }
  357. void increment()
  358. {
  359. for (;;)
  360. {
  361. if (m_branches.empty())
  362. {
  363. // there exists a next closest neighbor so we can increment
  364. if (! m_neighbors.empty())
  365. {
  366. m_neighbor_ptr = m_neighbors.top().second;
  367. ++m_neighbors_count;
  368. m_neighbors.pop_top();
  369. }
  370. else
  371. {
  372. // there aren't any neighbors left, end
  373. m_neighbor_ptr = nullptr;
  374. m_neighbors_count = max_count();
  375. }
  376. return;
  377. }
  378. else
  379. {
  380. branch_data const& closest_branch = m_branches.top();
  381. // if next neighbor is closer or as close as the closest branch, set next neighbor
  382. if (! m_neighbors.empty() && m_neighbors.top().first <= closest_branch.distance )
  383. {
  384. m_neighbor_ptr = m_neighbors.top().second;
  385. ++m_neighbors_count;
  386. m_neighbors.pop_top();
  387. return;
  388. }
  389. BOOST_GEOMETRY_INDEX_ASSERT(m_neighbors_count + m_neighbors.size() <= max_count(), "unexpected neighbors count");
  390. // if there is enough neighbors and there is no closer branch
  391. if (ignore_branch_or_value(closest_branch.distance))
  392. {
  393. m_branches.clear();
  394. continue;
  395. }
  396. else
  397. {
  398. node_pointer ptr = closest_branch.ptr;
  399. size_type reverse_level = closest_branch.reverse_level;
  400. m_branches.pop();
  401. apply(ptr, reverse_level);
  402. }
  403. }
  404. }
  405. }
  406. bool is_end() const
  407. {
  408. return m_neighbor_ptr == nullptr;
  409. }
  410. friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r)
  411. {
  412. return l.m_neighbors_count == r.m_neighbors_count;
  413. }
  414. private:
  415. void apply(node_pointer ptr, size_type reverse_level)
  416. {
  417. namespace id = index::detail;
  418. // Put node's elements into the list of active branches if those elements meets predicates
  419. // and distance predicates(currently not used)
  420. // and aren't further than found neighbours (if there is enough neighbours)
  421. if (reverse_level > 0)
  422. {
  423. internal_node& n = rtree::get<internal_node>(*ptr);
  424. // fill active branch list array of nodes meeting predicates
  425. for (auto const& p : rtree::elements(n))
  426. {
  427. node_distance_type node_distance; // for distance predicate
  428. // if current node meets predicates (0 is dummy value)
  429. if (id::predicates_check<id::bounds_tag>(m_pred, 0, p.first, m_strategy)
  430. // and if distance is ok
  431. && calculate_node_distance::apply(predicate(), p.first, m_strategy, node_distance)
  432. // and if current node is closer than the furthest neighbor
  433. && ! ignore_branch_or_value(node_distance))
  434. {
  435. // add current node into the queue
  436. m_branches.push(branch_data(node_distance, reverse_level - 1, p.second));
  437. }
  438. }
  439. }
  440. // Put values into the list of neighbours if those values meets predicates
  441. // and distance predicates(currently not used)
  442. // and aren't further than already found neighbours (if there is enough neighbours)
  443. else
  444. {
  445. leaf& n = rtree::get<leaf>(*ptr);
  446. // search leaf for closest value meeting predicates
  447. for (auto const& v : rtree::elements(n))
  448. {
  449. value_distance_type value_distance; // for distance predicate
  450. // if value meets predicates
  451. if (id::predicates_check<id::value_tag>(m_pred, v, (*m_tr)(v), m_strategy)
  452. // and if distance is ok
  453. && calculate_value_distance::apply(predicate(), (*m_tr)(v), m_strategy, value_distance)
  454. // and if current value is closer than the furthest neighbor
  455. && ! ignore_branch_or_value(value_distance))
  456. {
  457. // add current value into the queue
  458. m_neighbors.push(std::make_pair(value_distance, boost::addressof(v)));
  459. // remove unneeded value
  460. if (m_neighbors_count + m_neighbors.size() > max_count())
  461. {
  462. m_neighbors.pop_bottom();
  463. }
  464. }
  465. }
  466. }
  467. }
  468. template <typename Distance>
  469. bool ignore_branch_or_value(Distance const& distance)
  470. {
  471. return m_neighbors_count + m_neighbors.size() == max_count()
  472. && (m_neighbors.empty() || m_neighbors.bottom().first <= distance);
  473. }
  474. std::size_t max_count() const
  475. {
  476. return nearest_predicate_access::get(m_pred).count;
  477. }
  478. nearest_predicate_type const& predicate() const
  479. {
  480. return nearest_predicate_access::get(m_pred);
  481. }
  482. const translator_type * m_tr;
  483. strategy_type m_strategy;
  484. Predicates m_pred;
  485. branches_type m_branches;
  486. neighbors_type m_neighbors;
  487. size_type m_neighbors_count;
  488. const value_type * m_neighbor_ptr;
  489. };
  490. }}} // namespace detail::rtree::visitors
  491. }}} // namespace boost::geometry::index
  492. #endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP