remove.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // Boost.Geometry Index
  2. //
  3. // R-tree removing visitor implementation
  4. //
  5. // Copyright (c) 2011-2017 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_REMOVE_HPP
  16. #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
  17. #include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
  18. #include <boost/geometry/index/parameters.hpp>
  19. #include <boost/geometry/index/detail/algorithms/bounds.hpp>
  20. #include <boost/geometry/index/detail/rtree/node/node.hpp>
  21. #include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
  22. #include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
  23. #include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>
  24. #include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
  25. #include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
  26. namespace boost { namespace geometry { namespace index {
  27. namespace detail { namespace rtree { namespace visitors {
  28. // Default remove algorithm
  29. template <typename MembersHolder>
  30. class remove
  31. : public MembersHolder::visitor
  32. {
  33. typedef typename MembersHolder::box_type box_type;
  34. typedef typename MembersHolder::value_type value_type;
  35. typedef typename MembersHolder::parameters_type parameters_type;
  36. typedef typename MembersHolder::translator_type translator_type;
  37. typedef typename MembersHolder::allocators_type allocators_type;
  38. typedef typename MembersHolder::node node;
  39. typedef typename MembersHolder::internal_node internal_node;
  40. typedef typename MembersHolder::leaf leaf;
  41. typedef rtree::subtree_destroyer<MembersHolder> subtree_destroyer;
  42. typedef typename allocators_type::node_pointer node_pointer;
  43. typedef typename allocators_type::size_type size_type;
  44. typedef typename rtree::elements_type<internal_node>::type::size_type internal_size_type;
  45. //typedef typename Allocators::internal_node_pointer internal_node_pointer;
  46. typedef internal_node * internal_node_pointer;
  47. public:
  48. inline remove(node_pointer & root,
  49. size_type & leafs_level,
  50. value_type const& value,
  51. parameters_type const& parameters,
  52. translator_type const& translator,
  53. allocators_type & allocators)
  54. : m_value(value)
  55. , m_parameters(parameters)
  56. , m_translator(translator)
  57. , m_allocators(allocators)
  58. , m_root_node(root)
  59. , m_leafs_level(leafs_level)
  60. , m_is_value_removed(false)
  61. , m_parent(0)
  62. , m_current_child_index(0)
  63. , m_current_level(0)
  64. , m_is_underflow(false)
  65. {
  66. // TODO
  67. // assert - check if Value/Box is correct
  68. }
  69. inline void operator()(internal_node & n)
  70. {
  71. typedef typename rtree::elements_type<internal_node>::type children_type;
  72. children_type & children = rtree::elements(n);
  73. // traverse children which boxes intersects value's box
  74. internal_size_type child_node_index = 0;
  75. for ( ; child_node_index < children.size() ; ++child_node_index )
  76. {
  77. if ( index::detail::covered_by_bounds(m_translator(m_value),
  78. children[child_node_index].first,
  79. index::detail::get_strategy(m_parameters)) )
  80. {
  81. // next traversing step
  82. traverse_apply_visitor(n, child_node_index); // MAY THROW
  83. if ( m_is_value_removed )
  84. break;
  85. }
  86. }
  87. // value was found and removed
  88. if ( m_is_value_removed )
  89. {
  90. typedef typename rtree::elements_type<internal_node>::type elements_type;
  91. typedef typename elements_type::iterator element_iterator;
  92. elements_type & elements = rtree::elements(n);
  93. // underflow occured - child node should be removed
  94. if ( m_is_underflow )
  95. {
  96. element_iterator underfl_el_it = elements.begin() + child_node_index;
  97. size_type relative_level = m_leafs_level - m_current_level;
  98. // move node to the container - store node's relative level as well and return new underflow state
  99. // NOTE: if the min elements number is 1, then after an underflow
  100. // here the child elements count is 0, so it's not required to store this node,
  101. // it could just be destroyed
  102. m_is_underflow = store_underflowed_node(elements, underfl_el_it, relative_level); // MAY THROW (E: alloc, copy)
  103. }
  104. // n is not root - adjust aabb
  105. if ( 0 != m_parent )
  106. {
  107. // underflow state should be ok here
  108. // note that there may be less than min_elems elements in root
  109. // so this condition should be checked only here
  110. BOOST_GEOMETRY_INDEX_ASSERT((elements.size() < m_parameters.get_min_elements()) == m_is_underflow, "unexpected state");
  111. rtree::elements(*m_parent)[m_current_child_index].first
  112. = rtree::elements_box<box_type>(elements.begin(), elements.end(), m_translator,
  113. index::detail::get_strategy(m_parameters));
  114. }
  115. // n is root node
  116. else
  117. {
  118. BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root_node), "node must be the root");
  119. // reinsert elements from removed nodes (underflows)
  120. reinsert_removed_nodes_elements(); // MAY THROW (V, E: alloc, copy, N: alloc)
  121. // shorten the tree
  122. // NOTE: if the min elements number is 1, then after underflow
  123. // here the number of elements may be equal to 0
  124. // this can occur only for the last removed element
  125. if ( rtree::elements(n).size() <= 1 )
  126. {
  127. node_pointer root_to_destroy = m_root_node;
  128. if ( rtree::elements(n).size() == 0 )
  129. m_root_node = 0;
  130. else
  131. m_root_node = rtree::elements(n)[0].second;
  132. --m_leafs_level;
  133. rtree::destroy_node<allocators_type, internal_node>::apply(m_allocators, root_to_destroy);
  134. }
  135. }
  136. }
  137. }
  138. inline void operator()(leaf & n)
  139. {
  140. typedef typename rtree::elements_type<leaf>::type elements_type;
  141. elements_type & elements = rtree::elements(n);
  142. // find value and remove it
  143. for ( typename elements_type::iterator it = elements.begin() ; it != elements.end() ; ++it )
  144. {
  145. if ( m_translator.equals(*it, m_value, index::detail::get_strategy(m_parameters)) )
  146. {
  147. rtree::move_from_back(elements, it); // MAY THROW (V: copy)
  148. elements.pop_back();
  149. m_is_value_removed = true;
  150. break;
  151. }
  152. }
  153. // if value was removed
  154. if ( m_is_value_removed )
  155. {
  156. BOOST_GEOMETRY_INDEX_ASSERT(0 < m_parameters.get_min_elements(), "min number of elements is too small");
  157. // calc underflow
  158. m_is_underflow = elements.size() < m_parameters.get_min_elements();
  159. // n is not root - adjust aabb
  160. if ( 0 != m_parent )
  161. {
  162. rtree::elements(*m_parent)[m_current_child_index].first
  163. = rtree::values_box<box_type>(elements.begin(), elements.end(), m_translator,
  164. index::detail::get_strategy(m_parameters));
  165. }
  166. }
  167. }
  168. bool is_value_removed() const
  169. {
  170. return m_is_value_removed;
  171. }
  172. private:
  173. typedef std::vector< std::pair<size_type, node_pointer> > underflow_nodes;
  174. void traverse_apply_visitor(internal_node &n, internal_size_type choosen_node_index)
  175. {
  176. // save previous traverse inputs and set new ones
  177. internal_node_pointer parent_bckup = m_parent;
  178. internal_size_type current_child_index_bckup = m_current_child_index;
  179. size_type current_level_bckup = m_current_level;
  180. m_parent = &n;
  181. m_current_child_index = choosen_node_index;
  182. ++m_current_level;
  183. // next traversing step
  184. rtree::apply_visitor(*this, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V, E: alloc, copy, N: alloc)
  185. // restore previous traverse inputs
  186. m_parent = parent_bckup;
  187. m_current_child_index = current_child_index_bckup;
  188. m_current_level = current_level_bckup;
  189. }
  190. bool store_underflowed_node(
  191. typename rtree::elements_type<internal_node>::type & elements,
  192. typename rtree::elements_type<internal_node>::type::iterator underfl_el_it,
  193. size_type relative_level)
  194. {
  195. // move node to the container - store node's relative level as well
  196. m_underflowed_nodes.push_back(std::make_pair(relative_level, underfl_el_it->second)); // MAY THROW (E: alloc, copy)
  197. BOOST_TRY
  198. {
  199. // NOTE: those are elements of the internal node which means that copy/move shouldn't throw
  200. // Though it's safer in case if the pointer type could throw in copy ctor.
  201. // In the future this try-catch block could be removed.
  202. rtree::move_from_back(elements, underfl_el_it); // MAY THROW (E: copy)
  203. elements.pop_back();
  204. }
  205. BOOST_CATCH(...)
  206. {
  207. m_underflowed_nodes.pop_back();
  208. BOOST_RETHROW // RETHROW
  209. }
  210. BOOST_CATCH_END
  211. // calc underflow
  212. return elements.size() < m_parameters.get_min_elements();
  213. }
  214. static inline bool is_leaf(node const& n)
  215. {
  216. visitors::is_leaf<MembersHolder> ilv;
  217. rtree::apply_visitor(ilv, n);
  218. return ilv.result;
  219. }
  220. void reinsert_removed_nodes_elements()
  221. {
  222. typename underflow_nodes::reverse_iterator it = m_underflowed_nodes.rbegin();
  223. BOOST_TRY
  224. {
  225. // reinsert elements from removed nodes
  226. // begin with levels closer to the root
  227. for ( ; it != m_underflowed_nodes.rend() ; ++it )
  228. {
  229. // it->first is an index of a level of a node, not children
  230. // counted from the leafs level
  231. bool const node_is_leaf = it->first == 1;
  232. BOOST_GEOMETRY_INDEX_ASSERT(node_is_leaf == is_leaf(*it->second), "unexpected condition");
  233. if ( node_is_leaf )
  234. {
  235. reinsert_node_elements(rtree::get<leaf>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)
  236. rtree::destroy_node<allocators_type, leaf>::apply(m_allocators, it->second);
  237. }
  238. else
  239. {
  240. reinsert_node_elements(rtree::get<internal_node>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)
  241. rtree::destroy_node<allocators_type, internal_node>::apply(m_allocators, it->second);
  242. }
  243. }
  244. //m_underflowed_nodes.clear();
  245. }
  246. BOOST_CATCH(...)
  247. {
  248. // destroy current and remaining nodes
  249. for ( ; it != m_underflowed_nodes.rend() ; ++it )
  250. {
  251. rtree::visitors::destroy<MembersHolder>::apply(it->second, m_allocators);
  252. }
  253. //m_underflowed_nodes.clear();
  254. BOOST_RETHROW // RETHROW
  255. }
  256. BOOST_CATCH_END
  257. }
  258. template <typename Node>
  259. void reinsert_node_elements(Node &n, size_type node_relative_level)
  260. {
  261. typedef typename rtree::elements_type<Node>::type elements_type;
  262. elements_type & elements = rtree::elements(n);
  263. typename elements_type::iterator it = elements.begin();
  264. BOOST_TRY
  265. {
  266. for ( ; it != elements.end() ; ++it )
  267. {
  268. visitors::insert<typename elements_type::value_type, MembersHolder>
  269. insert_v(m_root_node, m_leafs_level, *it,
  270. m_parameters, m_translator, m_allocators,
  271. node_relative_level - 1);
  272. rtree::apply_visitor(insert_v, *m_root_node); // MAY THROW (V, E: alloc, copy, N: alloc)
  273. }
  274. }
  275. BOOST_CATCH(...)
  276. {
  277. ++it;
  278. rtree::destroy_elements<MembersHolder>::apply(it, elements.end(), m_allocators);
  279. elements.clear();
  280. BOOST_RETHROW // RETHROW
  281. }
  282. BOOST_CATCH_END
  283. }
  284. value_type const& m_value;
  285. parameters_type const& m_parameters;
  286. translator_type const& m_translator;
  287. allocators_type & m_allocators;
  288. node_pointer & m_root_node;
  289. size_type & m_leafs_level;
  290. bool m_is_value_removed;
  291. underflow_nodes m_underflowed_nodes;
  292. // traversing input parameters
  293. internal_node_pointer m_parent;
  294. internal_size_type m_current_child_index;
  295. size_type m_current_level;
  296. // traversing output parameters
  297. bool m_is_underflow;
  298. };
  299. }}} // namespace detail::rtree::visitors
  300. }}} // namespace boost::geometry::index
  301. #endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP