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