annotate DEPENDENCIES/generic/include/boost/geometry/index/detail/rtree/rstar/insert.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Boost.Geometry Index
Chris@16 2 //
Chris@16 3 // R-tree R*-tree insert algorithm implementation
Chris@16 4 //
Chris@101 5 // Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
Chris@16 6 //
Chris@16 7 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 9 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 10
Chris@16 11 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
Chris@16 12 #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
Chris@16 13
Chris@16 14 #include <boost/geometry/index/detail/algorithms/content.hpp>
Chris@16 15
Chris@16 16 namespace boost { namespace geometry { namespace index {
Chris@16 17
Chris@16 18 namespace detail { namespace rtree { namespace visitors {
Chris@16 19
Chris@16 20 namespace rstar {
Chris@16 21
Chris@16 22 template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
Chris@16 23 class remove_elements_to_reinsert
Chris@16 24 {
Chris@16 25 public:
Chris@16 26 typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
Chris@16 27 typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
Chris@16 28 typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
Chris@16 29
Chris@16 30 typedef typename Options::parameters_type parameters_type;
Chris@16 31
Chris@16 32 //typedef typename Allocators::internal_node_pointer internal_node_pointer;
Chris@16 33 typedef internal_node * internal_node_pointer;
Chris@16 34
Chris@16 35 template <typename ResultElements, typename Node>
Chris@16 36 static inline void apply(ResultElements & result_elements,
Chris@16 37 Node & n,
Chris@16 38 internal_node_pointer parent,
Chris@16 39 size_t current_child_index,
Chris@16 40 parameters_type const& parameters,
Chris@16 41 Translator const& translator,
Chris@16 42 Allocators & allocators)
Chris@16 43 {
Chris@16 44 typedef typename rtree::elements_type<Node>::type elements_type;
Chris@16 45 typedef typename elements_type::value_type element_type;
Chris@16 46 typedef typename geometry::point_type<Box>::type point_type;
Chris@16 47 // TODO: awulkiew - change second point_type to the point type of the Indexable?
Chris@101 48 typedef typename
Chris@101 49 geometry::default_comparable_distance_result<point_type>::type
Chris@101 50 comparable_distance_type;
Chris@16 51
Chris@16 52 elements_type & elements = rtree::elements(n);
Chris@16 53
Chris@16 54 const size_t elements_count = parameters.get_max_elements() + 1;
Chris@16 55 const size_t reinserted_elements_count = (::std::min)(parameters.get_reinserted_elements(), elements_count - parameters.get_min_elements());
Chris@16 56
Chris@16 57 BOOST_GEOMETRY_INDEX_ASSERT(parent, "node shouldn't be the root node");
Chris@16 58 BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected elements number");
Chris@16 59 BOOST_GEOMETRY_INDEX_ASSERT(0 < reinserted_elements_count, "wrong value of elements to reinsert");
Chris@16 60
Chris@16 61 // calculate current node's center
Chris@16 62 point_type node_center;
Chris@16 63 geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center);
Chris@16 64
Chris@16 65 // fill the container of centers' distances of children from current node's center
Chris@16 66 typedef typename index::detail::rtree::container_from_elements_type<
Chris@16 67 elements_type,
Chris@101 68 std::pair<comparable_distance_type, element_type>
Chris@16 69 >::type sorted_elements_type;
Chris@101 70
Chris@16 71 sorted_elements_type sorted_elements;
Chris@16 72 // If constructor is used instead of resize() MS implementation leaks here
Chris@16 73 sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
Chris@16 74
Chris@16 75 for ( typename elements_type::const_iterator it = elements.begin() ;
Chris@16 76 it != elements.end() ; ++it )
Chris@16 77 {
Chris@16 78 point_type element_center;
Chris@16 79 geometry::centroid( rtree::element_indexable(*it, translator), element_center);
Chris@16 80 sorted_elements.push_back(std::make_pair(
Chris@16 81 geometry::comparable_distance(node_center, element_center),
Chris@16 82 *it)); // MAY THROW (V, E: copy)
Chris@16 83 }
Chris@16 84
Chris@16 85 // sort elements by distances from center
Chris@16 86 std::partial_sort(
Chris@16 87 sorted_elements.begin(),
Chris@16 88 sorted_elements.begin() + reinserted_elements_count,
Chris@16 89 sorted_elements.end(),
Chris@101 90 distances_dsc<comparable_distance_type, element_type>); // MAY THROW, BASIC (V, E: copy)
Chris@16 91
Chris@16 92 // copy elements which will be reinserted
Chris@16 93 result_elements.clear();
Chris@16 94 result_elements.reserve(reinserted_elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
Chris@16 95 for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() ;
Chris@16 96 it != sorted_elements.begin() + reinserted_elements_count ; ++it )
Chris@16 97 {
Chris@16 98 result_elements.push_back(it->second); // MAY THROW (V, E: copy)
Chris@16 99 }
Chris@16 100
Chris@16 101 BOOST_TRY
Chris@16 102 {
Chris@16 103 // copy remaining elements to the current node
Chris@16 104 elements.clear();
Chris@16 105 elements.reserve(elements_count - reinserted_elements_count); // SHOULDN'T THROW (new_size <= old size)
Chris@16 106 for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() + reinserted_elements_count;
Chris@16 107 it != sorted_elements.end() ; ++it )
Chris@16 108 {
Chris@16 109 elements.push_back(it->second); // MAY THROW (V, E: copy)
Chris@16 110 }
Chris@16 111 }
Chris@16 112 BOOST_CATCH(...)
Chris@16 113 {
Chris@16 114 elements.clear();
Chris@16 115
Chris@16 116 for ( typename sorted_elements_type::iterator it = sorted_elements.begin() ;
Chris@16 117 it != sorted_elements.end() ; ++it )
Chris@16 118 {
Chris@16 119 destroy_element<Value, Options, Translator, Box, Allocators>::apply(it->second, allocators);
Chris@16 120 }
Chris@16 121
Chris@16 122 BOOST_RETHROW // RETHROW
Chris@16 123 }
Chris@16 124 BOOST_CATCH_END
Chris@16 125
Chris@16 126 ::boost::ignore_unused_variable_warning(parameters);
Chris@16 127 }
Chris@16 128
Chris@16 129 private:
Chris@16 130 template <typename Distance, typename El>
Chris@16 131 static inline bool distances_asc(
Chris@16 132 std::pair<Distance, El> const& d1,
Chris@16 133 std::pair<Distance, El> const& d2)
Chris@16 134 {
Chris@16 135 return d1.first < d2.first;
Chris@16 136 }
Chris@16 137
Chris@16 138 template <typename Distance, typename El>
Chris@16 139 static inline bool distances_dsc(
Chris@16 140 std::pair<Distance, El> const& d1,
Chris@16 141 std::pair<Distance, El> const& d2)
Chris@16 142 {
Chris@16 143 return d1.first > d2.first;
Chris@16 144 }
Chris@16 145 };
Chris@16 146
Chris@16 147 template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Box, typename Allocators>
Chris@16 148 struct level_insert_elements_type
Chris@16 149 {
Chris@16 150 typedef typename rtree::elements_type<
Chris@16 151 typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type
Chris@16 152 >::type type;
Chris@16 153 };
Chris@16 154
Chris@16 155 template <typename Value, typename Options, typename Box, typename Allocators>
Chris@16 156 struct level_insert_elements_type<0, Value, Value, Options, Box, Allocators>
Chris@16 157 {
Chris@16 158 typedef typename rtree::elements_type<
Chris@16 159 typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type
Chris@16 160 >::type type;
Chris@16 161 };
Chris@16 162
Chris@16 163 template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
Chris@16 164 struct level_insert_base
Chris@16 165 : public detail::insert<Element, Value, Options, Translator, Box, Allocators>
Chris@16 166 {
Chris@16 167 typedef detail::insert<Element, Value, Options, Translator, Box, Allocators> base;
Chris@16 168 typedef typename base::node node;
Chris@16 169 typedef typename base::internal_node internal_node;
Chris@16 170 typedef typename base::leaf leaf;
Chris@16 171
Chris@16 172 typedef typename level_insert_elements_type<InsertIndex, Element, Value, Options, Box, Allocators>::type elements_type;
Chris@16 173 typedef typename index::detail::rtree::container_from_elements_type<
Chris@16 174 elements_type,
Chris@16 175 typename elements_type::value_type
Chris@16 176 >::type result_elements_type;
Chris@16 177
Chris@16 178 typedef typename Options::parameters_type parameters_type;
Chris@16 179
Chris@16 180 typedef typename Allocators::node_pointer node_pointer;
Chris@101 181 typedef typename Allocators::size_type size_type;
Chris@16 182
Chris@16 183 inline level_insert_base(node_pointer & root,
Chris@101 184 size_type & leafs_level,
Chris@16 185 Element const& element,
Chris@16 186 parameters_type const& parameters,
Chris@16 187 Translator const& translator,
Chris@16 188 Allocators & allocators,
Chris@101 189 size_type relative_level)
Chris@16 190 : base(root, leafs_level, element, parameters, translator, allocators, relative_level)
Chris@16 191 , result_relative_level(0)
Chris@16 192 {}
Chris@16 193
Chris@16 194 template <typename Node>
Chris@16 195 inline void handle_possible_reinsert_or_split_of_root(Node &n)
Chris@16 196 {
Chris@16 197 BOOST_GEOMETRY_INDEX_ASSERT(result_elements.empty(), "reinsert should be handled only once for level");
Chris@16 198
Chris@16 199 result_relative_level = base::m_leafs_level - base::m_traverse_data.current_level;
Chris@16 200
Chris@16 201 // overflow
Chris@16 202 if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
Chris@16 203 {
Chris@16 204 // node isn't root node
Chris@16 205 if ( !base::m_traverse_data.current_is_root() )
Chris@16 206 {
Chris@16 207 // NOTE: exception-safety
Chris@16 208 // After an exception result_elements may contain garbage, don't use it
Chris@16 209 rstar::remove_elements_to_reinsert<Value, Options, Translator, Box, Allocators>::apply(
Chris@16 210 result_elements, n,
Chris@16 211 base::m_traverse_data.parent, base::m_traverse_data.current_child_index,
Chris@16 212 base::m_parameters, base::m_translator, base::m_allocators); // MAY THROW, BASIC (V, E: alloc, copy)
Chris@16 213 }
Chris@16 214 // node is root node
Chris@16 215 else
Chris@16 216 {
Chris@16 217 BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*base::m_root_node), "node should be the root node");
Chris@16 218 base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)
Chris@16 219 }
Chris@16 220 }
Chris@16 221 }
Chris@16 222
Chris@16 223 template <typename Node>
Chris@16 224 inline void handle_possible_split(Node &n) const
Chris@16 225 {
Chris@16 226 // overflow
Chris@16 227 if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
Chris@16 228 {
Chris@16 229 base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)
Chris@16 230 }
Chris@16 231 }
Chris@16 232
Chris@16 233 template <typename Node>
Chris@16 234 inline void recalculate_aabb_if_necessary(Node &n) const
Chris@16 235 {
Chris@16 236 if ( !result_elements.empty() && !base::m_traverse_data.current_is_root() )
Chris@16 237 {
Chris@16 238 // calulate node's new box
Chris@16 239 base::m_traverse_data.current_element().first =
Chris@16 240 elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);
Chris@16 241 }
Chris@16 242 }
Chris@16 243
Chris@101 244 size_type result_relative_level;
Chris@16 245 result_elements_type result_elements;
Chris@16 246 };
Chris@16 247
Chris@16 248 template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
Chris@16 249 struct level_insert
Chris@16 250 : public level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators>
Chris@16 251 {
Chris@16 252 typedef level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators> base;
Chris@16 253 typedef typename base::node node;
Chris@16 254 typedef typename base::internal_node internal_node;
Chris@16 255 typedef typename base::leaf leaf;
Chris@16 256
Chris@16 257 typedef typename Options::parameters_type parameters_type;
Chris@16 258
Chris@16 259 typedef typename Allocators::node_pointer node_pointer;
Chris@101 260 typedef typename Allocators::size_type size_type;
Chris@16 261
Chris@16 262 inline level_insert(node_pointer & root,
Chris@101 263 size_type & leafs_level,
Chris@16 264 Element const& element,
Chris@16 265 parameters_type const& parameters,
Chris@16 266 Translator const& translator,
Chris@16 267 Allocators & allocators,
Chris@101 268 size_type relative_level)
Chris@16 269 : base(root, leafs_level, element, parameters, translator, allocators, relative_level)
Chris@16 270 {}
Chris@16 271
Chris@16 272 inline void operator()(internal_node & n)
Chris@16 273 {
Chris@16 274 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
Chris@16 275
Chris@16 276 if ( base::m_traverse_data.current_level < base::m_level )
Chris@16 277 {
Chris@16 278 // next traversing step
Chris@16 279 base::traverse(*this, n); // MAY THROW (E: alloc, copy, N: alloc)
Chris@16 280
Chris@16 281 // further insert
Chris@16 282 if ( 0 < InsertIndex )
Chris@16 283 {
Chris@16 284 BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
Chris@16 285
Chris@16 286 if ( base::m_traverse_data.current_level == base::m_level - 1 )
Chris@16 287 {
Chris@16 288 base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
Chris@16 289 }
Chris@16 290 }
Chris@16 291 }
Chris@16 292 else
Chris@16 293 {
Chris@16 294 BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");
Chris@16 295
Chris@16 296 BOOST_TRY
Chris@16 297 {
Chris@16 298 // push new child node
Chris@16 299 rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
Chris@16 300 }
Chris@16 301 BOOST_CATCH(...)
Chris@16 302 {
Chris@16 303 // NOTE: exception-safety
Chris@16 304 // if the insert fails above, the element won't be stored in the tree, so delete it
Chris@16 305
Chris@16 306 rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(base::m_element.second, base::m_allocators);
Chris@16 307 rtree::apply_visitor(del_v, *base::m_element.second);
Chris@16 308
Chris@16 309 BOOST_RETHROW // RETHROW
Chris@16 310 }
Chris@16 311 BOOST_CATCH_END
Chris@16 312
Chris@16 313 // first insert
Chris@16 314 if ( 0 == InsertIndex )
Chris@16 315 {
Chris@16 316 base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
Chris@16 317 }
Chris@16 318 // not the first insert
Chris@16 319 else
Chris@16 320 {
Chris@16 321 base::handle_possible_split(n); // MAY THROW (E: alloc, N: alloc)
Chris@16 322 }
Chris@16 323 }
Chris@16 324
Chris@16 325 base::recalculate_aabb_if_necessary(n);
Chris@16 326 }
Chris@16 327
Chris@16 328 inline void operator()(leaf &)
Chris@16 329 {
Chris@16 330 BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");
Chris@16 331 }
Chris@16 332 };
Chris@16 333
Chris@16 334 template <size_t InsertIndex, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
Chris@16 335 struct level_insert<InsertIndex, Value, Value, Options, Translator, Box, Allocators>
Chris@16 336 : public level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators>
Chris@16 337 {
Chris@16 338 typedef level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators> base;
Chris@16 339 typedef typename base::node node;
Chris@16 340 typedef typename base::internal_node internal_node;
Chris@16 341 typedef typename base::leaf leaf;
Chris@16 342
Chris@16 343 typedef typename Options::parameters_type parameters_type;
Chris@16 344
Chris@16 345 typedef typename Allocators::node_pointer node_pointer;
Chris@101 346 typedef typename Allocators::size_type size_type;
Chris@16 347
Chris@16 348 inline level_insert(node_pointer & root,
Chris@101 349 size_type & leafs_level,
Chris@16 350 Value const& v,
Chris@16 351 parameters_type const& parameters,
Chris@16 352 Translator const& translator,
Chris@16 353 Allocators & allocators,
Chris@101 354 size_type relative_level)
Chris@16 355 : base(root, leafs_level, v, parameters, translator, allocators, relative_level)
Chris@16 356 {}
Chris@16 357
Chris@16 358 inline void operator()(internal_node & n)
Chris@16 359 {
Chris@16 360 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
Chris@16 361 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");
Chris@16 362
Chris@16 363 // next traversing step
Chris@16 364 base::traverse(*this, n); // MAY THROW (V, E: alloc, copy, N: alloc)
Chris@16 365
Chris@16 366 BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
Chris@16 367
Chris@16 368 if ( base::m_traverse_data.current_level == base::m_level - 1 )
Chris@16 369 {
Chris@16 370 base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
Chris@16 371 }
Chris@16 372
Chris@16 373 base::recalculate_aabb_if_necessary(n);
Chris@16 374 }
Chris@16 375
Chris@16 376 inline void operator()(leaf & n)
Chris@16 377 {
Chris@16 378 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
Chris@16 379 "unexpected level");
Chris@16 380 BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
Chris@16 381 base::m_level == (std::numeric_limits<size_t>::max)(),
Chris@16 382 "unexpected level");
Chris@16 383
Chris@16 384 rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
Chris@16 385
Chris@16 386 base::handle_possible_split(n); // MAY THROW (V: alloc, copy, N: alloc)
Chris@16 387 }
Chris@16 388 };
Chris@16 389
Chris@16 390 template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
Chris@16 391 struct level_insert<0, Value, Value, Options, Translator, Box, Allocators>
Chris@16 392 : public level_insert_base<0, Value, Value, Options, Translator, Box, Allocators>
Chris@16 393 {
Chris@16 394 typedef level_insert_base<0, Value, Value, Options, Translator, Box, Allocators> base;
Chris@16 395 typedef typename base::node node;
Chris@16 396 typedef typename base::internal_node internal_node;
Chris@16 397 typedef typename base::leaf leaf;
Chris@16 398
Chris@16 399 typedef typename Options::parameters_type parameters_type;
Chris@16 400
Chris@16 401 typedef typename Allocators::node_pointer node_pointer;
Chris@101 402 typedef typename Allocators::size_type size_type;
Chris@16 403
Chris@16 404 inline level_insert(node_pointer & root,
Chris@101 405 size_type & leafs_level,
Chris@16 406 Value const& v,
Chris@16 407 parameters_type const& parameters,
Chris@16 408 Translator const& translator,
Chris@16 409 Allocators & allocators,
Chris@101 410 size_type relative_level)
Chris@16 411 : base(root, leafs_level, v, parameters, translator, allocators, relative_level)
Chris@16 412 {}
Chris@16 413
Chris@16 414 inline void operator()(internal_node & n)
Chris@16 415 {
Chris@16 416 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level,
Chris@16 417 "unexpected level");
Chris@16 418 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level,
Chris@16 419 "unexpected level");
Chris@16 420
Chris@16 421 // next traversing step
Chris@16 422 base::traverse(*this, n); // MAY THROW (V: alloc, copy, N: alloc)
Chris@16 423
Chris@16 424 base::recalculate_aabb_if_necessary(n);
Chris@16 425 }
Chris@16 426
Chris@16 427 inline void operator()(leaf & n)
Chris@16 428 {
Chris@16 429 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
Chris@16 430 "unexpected level");
Chris@16 431 BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
Chris@16 432 base::m_level == (std::numeric_limits<size_t>::max)(),
Chris@16 433 "unexpected level");
Chris@16 434
Chris@16 435 rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
Chris@16 436
Chris@16 437 base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (V: alloc, copy, N: alloc)
Chris@16 438
Chris@16 439 base::recalculate_aabb_if_necessary(n);
Chris@16 440 }
Chris@16 441 };
Chris@16 442
Chris@16 443 } // namespace rstar
Chris@16 444
Chris@16 445 // R*-tree insert visitor
Chris@16 446 // After passing the Element to insert visitor the Element is managed by the tree
Chris@16 447 // I.e. one should not delete the node passed to the insert visitor after exception is thrown
Chris@16 448 // because this visitor may delete it
Chris@16 449 template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
Chris@16 450 class insert<Element, Value, Options, Translator, Box, Allocators, insert_reinsert_tag>
Chris@16 451 : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
Chris@16 452 {
Chris@16 453 typedef typename Options::parameters_type parameters_type;
Chris@16 454
Chris@16 455 typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
Chris@16 456 typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
Chris@16 457 typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
Chris@16 458
Chris@16 459 typedef typename Allocators::node_pointer node_pointer;
Chris@101 460 typedef typename Allocators::size_type size_type;
Chris@16 461
Chris@16 462 public:
Chris@16 463 inline insert(node_pointer & root,
Chris@101 464 size_type & leafs_level,
Chris@16 465 Element const& element,
Chris@16 466 parameters_type const& parameters,
Chris@16 467 Translator const& translator,
Chris@16 468 Allocators & allocators,
Chris@101 469 size_type relative_level = 0)
Chris@16 470 : m_root(root), m_leafs_level(leafs_level), m_element(element)
Chris@16 471 , m_parameters(parameters), m_translator(translator)
Chris@16 472 , m_relative_level(relative_level), m_allocators(allocators)
Chris@16 473 {}
Chris@16 474
Chris@101 475 inline void operator()(internal_node & n)
Chris@16 476 {
Chris@101 477 boost::ignore_unused(n);
Chris@16 478 BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root), "current node should be the root");
Chris@16 479
Chris@16 480 // Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
Chris@16 481 if ( m_parameters.get_reinserted_elements() > 0 )
Chris@16 482 {
Chris@16 483 rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(
Chris@16 484 m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
Chris@16 485
Chris@16 486 rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
Chris@16 487
Chris@16 488 if ( !lins_v.result_elements.empty() )
Chris@16 489 {
Chris@16 490 recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)
Chris@16 491 }
Chris@16 492 }
Chris@16 493 else
Chris@16 494 {
Chris@16 495 visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(
Chris@16 496 m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
Chris@16 497
Chris@16 498 rtree::apply_visitor(ins_v, *m_root);
Chris@16 499 }
Chris@16 500 }
Chris@16 501
Chris@101 502 inline void operator()(leaf & n)
Chris@16 503 {
Chris@101 504 boost::ignore_unused(n);
Chris@16 505 BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<leaf>(*m_root), "current node should be the root");
Chris@16 506
Chris@16 507 // Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
Chris@16 508 if ( m_parameters.get_reinserted_elements() > 0 )
Chris@16 509 {
Chris@16 510 rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(
Chris@16 511 m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
Chris@16 512
Chris@16 513 rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
Chris@16 514
Chris@16 515 // we're in the root, so root should be split and there should be no elements to reinsert
Chris@16 516 BOOST_GEOMETRY_INDEX_ASSERT(lins_v.result_elements.empty(), "unexpected state");
Chris@16 517 }
Chris@16 518 else
Chris@16 519 {
Chris@16 520 visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(
Chris@16 521 m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
Chris@16 522
Chris@16 523 rtree::apply_visitor(ins_v, *m_root);
Chris@16 524 }
Chris@16 525 }
Chris@16 526
Chris@16 527 private:
Chris@16 528 template <typename Elements>
Chris@16 529 inline void recursive_reinsert(Elements & elements, size_t relative_level)
Chris@16 530 {
Chris@16 531 typedef typename Elements::value_type element_type;
Chris@16 532
Chris@16 533 // reinsert children starting from the minimum distance
Chris@16 534 typename Elements::reverse_iterator it = elements.rbegin();
Chris@16 535 for ( ; it != elements.rend() ; ++it)
Chris@16 536 {
Chris@16 537 rstar::level_insert<1, element_type, Value, Options, Translator, Box, Allocators> lins_v(
Chris@16 538 m_root, m_leafs_level, *it, m_parameters, m_translator, m_allocators, relative_level);
Chris@16 539
Chris@16 540 BOOST_TRY
Chris@16 541 {
Chris@16 542 rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
Chris@16 543 }
Chris@16 544 BOOST_CATCH(...)
Chris@16 545 {
Chris@16 546 ++it;
Chris@16 547 for ( ; it != elements.rend() ; ++it)
Chris@16 548 rtree::destroy_element<Value, Options, Translator, Box, Allocators>::apply(*it, m_allocators);
Chris@16 549 BOOST_RETHROW // RETHROW
Chris@16 550 }
Chris@16 551 BOOST_CATCH_END
Chris@16 552
Chris@16 553 BOOST_GEOMETRY_INDEX_ASSERT(relative_level + 1 == lins_v.result_relative_level, "unexpected level");
Chris@16 554
Chris@16 555 // non-root relative level
Chris@16 556 if ( lins_v.result_relative_level < m_leafs_level && !lins_v.result_elements.empty())
Chris@16 557 {
Chris@16 558 recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)
Chris@16 559 }
Chris@16 560 }
Chris@16 561 }
Chris@16 562
Chris@16 563 node_pointer & m_root;
Chris@101 564 size_type & m_leafs_level;
Chris@16 565 Element const& m_element;
Chris@16 566
Chris@16 567 parameters_type const& m_parameters;
Chris@16 568 Translator const& m_translator;
Chris@16 569
Chris@101 570 size_type m_relative_level;
Chris@16 571
Chris@16 572 Allocators & m_allocators;
Chris@16 573 };
Chris@16 574
Chris@16 575 }}} // namespace detail::rtree::visitors
Chris@16 576
Chris@16 577 }}} // namespace boost::geometry::index
Chris@16 578
Chris@16 579 #endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP