remove.hpp 14 KB

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