File indexing completed on 2025-01-18 09:35:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
0017 #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
0018
0019 #ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
0020 #include <type_traits>
0021 #endif
0022
0023 #include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
0024 #include <boost/geometry/core/static_assert.hpp>
0025
0026 #include <boost/geometry/index/detail/algorithms/bounds.hpp>
0027 #include <boost/geometry/index/detail/algorithms/content.hpp>
0028 #include <boost/geometry/index/detail/rtree/node/node.hpp>
0029 #include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
0030 #include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
0031 #include <boost/geometry/index/detail/rtree/options.hpp>
0032
0033 #include <boost/geometry/util/condition.hpp>
0034
0035 namespace boost { namespace geometry { namespace index {
0036
0037 namespace detail { namespace rtree {
0038
0039
0040 template
0041 <
0042 typename MembersHolder,
0043 typename ChooseNextNodeTag = typename MembersHolder::options_type::choose_next_node_tag
0044 >
0045 class choose_next_node;
0046
0047 template <typename MembersHolder>
0048 class choose_next_node<MembersHolder, choose_by_content_diff_tag>
0049 {
0050 public:
0051 typedef typename MembersHolder::box_type box_type;
0052 typedef typename MembersHolder::parameters_type parameters_type;
0053
0054 typedef typename MembersHolder::node node;
0055 typedef typename MembersHolder::internal_node internal_node;
0056 typedef typename MembersHolder::leaf leaf;
0057
0058 typedef typename rtree::elements_type<internal_node>::type children_type;
0059
0060 typedef typename index::detail::default_content_result<box_type>::type content_type;
0061
0062 template <typename Indexable>
0063 static inline size_t apply(internal_node & n,
0064 Indexable const& indexable,
0065 parameters_type const& parameters,
0066 size_t )
0067 {
0068 children_type & children = rtree::elements(n);
0069
0070 BOOST_GEOMETRY_INDEX_ASSERT(!children.empty(), "can't choose the next node if children are empty");
0071
0072 size_t children_count = children.size();
0073
0074
0075 size_t choosen_index = 0;
0076 content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
0077 content_type smallest_content = (std::numeric_limits<content_type>::max)();
0078
0079
0080 for ( size_t i = 0 ; i < children_count ; ++i )
0081 {
0082 typedef typename children_type::value_type child_type;
0083 child_type const& ch_i = children[i];
0084
0085
0086 box_type box_exp(ch_i.first);
0087 index::detail::expand(box_exp, indexable,
0088 index::detail::get_strategy(parameters));
0089
0090
0091 content_type content = index::detail::content(box_exp);
0092 content_type content_diff = content - index::detail::content(ch_i.first);
0093
0094
0095 if ( content_diff < smallest_content_diff ||
0096 ( content_diff == smallest_content_diff && content < smallest_content ) )
0097 {
0098 smallest_content_diff = content_diff;
0099 smallest_content = content;
0100 choosen_index = i;
0101 }
0102 }
0103
0104 return choosen_index;
0105 }
0106 };
0107
0108
0109
0110
0111 template
0112 <
0113 typename MembersHolder,
0114 typename RedistributeTag = typename MembersHolder::options_type::redistribute_tag
0115 >
0116 struct redistribute_elements
0117 {
0118 BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0119 "Not implemented for this RedistributeTag type.",
0120 MembersHolder, RedistributeTag);
0121 };
0122
0123
0124
0125
0126 template
0127 <
0128 typename MembersHolder,
0129 typename SplitTag = typename MembersHolder::options_type::split_tag
0130 >
0131 class split
0132 {
0133 BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0134 "Not implemented for this SplitTag type.",
0135 MembersHolder, SplitTag);
0136 };
0137
0138
0139 template <typename MembersHolder>
0140 class split<MembersHolder, split_default_tag>
0141 {
0142 protected:
0143 typedef typename MembersHolder::parameters_type parameters_type;
0144 typedef typename MembersHolder::box_type box_type;
0145 typedef typename MembersHolder::translator_type translator_type;
0146 typedef typename MembersHolder::allocators_type allocators_type;
0147 typedef typename MembersHolder::size_type size_type;
0148
0149 typedef typename MembersHolder::node node;
0150 typedef typename MembersHolder::internal_node internal_node;
0151 typedef typename MembersHolder::leaf leaf;
0152
0153 typedef typename MembersHolder::node_pointer node_pointer;
0154
0155 public:
0156 typedef index::detail::varray<
0157 typename rtree::elements_type<internal_node>::type::value_type,
0158 1
0159 > nodes_container_type;
0160
0161 template <typename Node>
0162 static inline void apply(nodes_container_type & additional_nodes,
0163 Node & n,
0164 box_type & n_box,
0165 parameters_type const& parameters,
0166 translator_type const& translator,
0167 allocators_type & allocators)
0168 {
0169
0170
0171
0172 node_pointer n2_ptr = rtree::create_node<allocators_type, Node>::apply(allocators);
0173
0174 Node & n2 = rtree::get<Node>(*n2_ptr);
0175
0176 BOOST_TRY
0177 {
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 box_type box2;
0189 redistribute_elements<MembersHolder>
0190 ::apply(n, n2, n_box, box2, parameters, translator, allocators);
0191
0192
0193 BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n).size() &&
0194 rtree::elements(n).size() <= parameters.get_max_elements(),
0195 "unexpected number of elements");
0196 BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n2).size() &&
0197 rtree::elements(n2).size() <= parameters.get_max_elements(),
0198 "unexpected number of elements");
0199
0200
0201 additional_nodes.push_back(rtree::make_ptr_pair(box2, n2_ptr));
0202 }
0203 BOOST_CATCH(...)
0204 {
0205
0206
0207
0208 typename rtree::elements_type<Node>::type & elements = rtree::elements(n);
0209 size_type const max_size = parameters.get_max_elements();
0210 if (elements.size() > max_size)
0211 {
0212 rtree::destroy_element<MembersHolder>::apply(elements[max_size], allocators);
0213 elements.pop_back();
0214 }
0215
0216 rtree::visitors::destroy<MembersHolder>::apply(n2_ptr, allocators);
0217
0218 BOOST_RETHROW
0219 }
0220 BOOST_CATCH_END
0221 }
0222 };
0223
0224
0225
0226 namespace visitors { namespace detail {
0227
0228 template <typename InternalNode, typename InternalNodePtr, typename SizeType>
0229 struct insert_traverse_data
0230 {
0231 typedef typename rtree::elements_type<InternalNode>::type elements_type;
0232 typedef typename elements_type::value_type element_type;
0233 typedef typename elements_type::size_type elements_size_type;
0234 typedef SizeType size_type;
0235
0236 insert_traverse_data()
0237 : parent(0), current_child_index(0), current_level(0)
0238 {}
0239
0240 void move_to_next_level(InternalNodePtr new_parent,
0241 elements_size_type new_child_index)
0242 {
0243 parent = new_parent;
0244 current_child_index = new_child_index;
0245 ++current_level;
0246 }
0247
0248 bool current_is_root() const
0249 {
0250 return 0 == parent;
0251 }
0252
0253 elements_type & parent_elements() const
0254 {
0255 BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");
0256 return rtree::elements(*parent);
0257 }
0258
0259 element_type & current_element() const
0260 {
0261 BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");
0262 return rtree::elements(*parent)[current_child_index];
0263 }
0264
0265 InternalNodePtr parent;
0266 elements_size_type current_child_index;
0267 size_type current_level;
0268 };
0269
0270
0271 template <typename Element, typename MembersHolder>
0272 class insert
0273 : public MembersHolder::visitor
0274 {
0275 protected:
0276 typedef typename MembersHolder::box_type box_type;
0277 typedef typename MembersHolder::value_type value_type;
0278 typedef typename MembersHolder::parameters_type parameters_type;
0279 typedef typename MembersHolder::translator_type translator_type;
0280 typedef typename MembersHolder::allocators_type allocators_type;
0281
0282 typedef typename MembersHolder::node node;
0283 typedef typename MembersHolder::internal_node internal_node;
0284 typedef typename MembersHolder::leaf leaf;
0285
0286 typedef rtree::subtree_destroyer<MembersHolder> subtree_destroyer;
0287 typedef typename allocators_type::node_pointer node_pointer;
0288 typedef typename allocators_type::size_type size_type;
0289
0290
0291 typedef internal_node * internal_node_pointer;
0292
0293 inline insert(node_pointer & root,
0294 size_type & leafs_level,
0295 Element const& element,
0296 parameters_type const& parameters,
0297 translator_type const& translator,
0298 allocators_type & allocators,
0299 size_type relative_level = 0
0300 )
0301 : m_element(element)
0302 , m_parameters(parameters)
0303 , m_translator(translator)
0304 , m_relative_level(relative_level)
0305 , m_level(leafs_level - relative_level)
0306 , m_root_node(root)
0307 , m_leafs_level(leafs_level)
0308 , m_traverse_data()
0309 , m_allocators(allocators)
0310 {
0311 BOOST_GEOMETRY_INDEX_ASSERT(m_relative_level <= leafs_level, "unexpected level value");
0312 BOOST_GEOMETRY_INDEX_ASSERT(m_level <= m_leafs_level, "unexpected level value");
0313 BOOST_GEOMETRY_INDEX_ASSERT(0 != m_root_node, "there is no root node");
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323 index::detail::bounds(rtree::element_indexable(m_element, m_translator),
0324 m_element_bounds,
0325 index::detail::get_strategy(m_parameters));
0326
0327 #ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
0328
0329
0330
0331 if (BOOST_GEOMETRY_CONDITION((
0332 std::is_same<Element, value_type>::value
0333 && ! index::detail::is_bounding_geometry
0334 <
0335 typename indexable_type<translator_type>::type
0336 >::value )) )
0337 {
0338 geometry::detail::expand_by_epsilon(m_element_bounds);
0339 }
0340 #endif
0341 }
0342
0343 template <typename Visitor>
0344 inline void traverse(Visitor & visitor, internal_node & n)
0345 {
0346
0347 size_t choosen_node_index = rtree::choose_next_node<MembersHolder>
0348 ::apply(n, rtree::element_indexable(m_element, m_translator),
0349 m_parameters,
0350 m_leafs_level - m_traverse_data.current_level);
0351
0352
0353 index::detail::expand(
0354 rtree::elements(n)[choosen_node_index].first,
0355 m_element_bounds,
0356 index::detail::get_strategy(m_parameters));
0357
0358
0359 traverse_apply_visitor(visitor, n, choosen_node_index);
0360 }
0361
0362
0363
0364 template <typename Node>
0365 inline void post_traverse(Node &n)
0366 {
0367 BOOST_GEOMETRY_INDEX_ASSERT(m_traverse_data.current_is_root() ||
0368 &n == &rtree::get<Node>(*m_traverse_data.current_element().second),
0369 "if node isn't the root current_child_index should be valid");
0370
0371
0372 if ( m_parameters.get_max_elements() < rtree::elements(n).size() )
0373 {
0374
0375
0376 split(n);
0377 }
0378 }
0379
0380 template <typename Visitor>
0381 inline void traverse_apply_visitor(Visitor & visitor, internal_node &n, size_t choosen_node_index)
0382 {
0383
0384 insert_traverse_data<internal_node, internal_node_pointer, size_type>
0385 backup_traverse_data = m_traverse_data;
0386
0387
0388 m_traverse_data.move_to_next_level(&n, choosen_node_index);
0389
0390
0391 rtree::apply_visitor(visitor, *rtree::elements(n)[choosen_node_index].second);
0392
0393
0394 m_traverse_data = backup_traverse_data;
0395 }
0396
0397
0398
0399 template <typename Node>
0400 inline void split(Node & n) const
0401 {
0402 typedef rtree::split<MembersHolder> split_algo;
0403
0404 typename split_algo::nodes_container_type additional_nodes;
0405 box_type n_box;
0406
0407 split_algo::apply(additional_nodes, n, n_box, m_parameters, m_translator, m_allocators);
0408
0409 BOOST_GEOMETRY_INDEX_ASSERT(additional_nodes.size() == 1, "unexpected number of additional nodes");
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422 subtree_destroyer additional_node_ptr(additional_nodes[0].second, m_allocators);
0423
0424 #ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
0425
0426
0427
0428 if (BOOST_GEOMETRY_CONDITION((
0429 std::is_same<Node, leaf>::value
0430 && ! index::detail::is_bounding_geometry
0431 <
0432 typename indexable_type<translator_type>::type
0433 >::value )))
0434 {
0435 geometry::detail::expand_by_epsilon(n_box);
0436 geometry::detail::expand_by_epsilon(additional_nodes[0].first);
0437 }
0438 #endif
0439
0440
0441 if ( !m_traverse_data.current_is_root() )
0442 {
0443
0444 m_traverse_data.current_element().first = n_box;
0445
0446 m_traverse_data.parent_elements().push_back(additional_nodes[0]);
0447 }
0448
0449 else
0450 {
0451 BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*m_root_node), "node should be the root");
0452
0453
0454 subtree_destroyer new_root(rtree::create_node<allocators_type, internal_node>::apply(m_allocators), m_allocators);
0455
0456 BOOST_TRY
0457 {
0458 rtree::elements(rtree::get<internal_node>(*new_root)).push_back(rtree::make_ptr_pair(n_box, m_root_node));
0459 rtree::elements(rtree::get<internal_node>(*new_root)).push_back(additional_nodes[0]);
0460 }
0461 BOOST_CATCH(...)
0462 {
0463
0464 rtree::elements(rtree::get<internal_node>(*new_root)).clear();
0465 BOOST_RETHROW
0466 }
0467 BOOST_CATCH_END
0468
0469 m_root_node = new_root.get();
0470 ++m_leafs_level;
0471
0472 new_root.release();
0473 }
0474
0475 additional_node_ptr.release();
0476 }
0477
0478
0479
0480 Element const& m_element;
0481 box_type m_element_bounds;
0482 parameters_type const& m_parameters;
0483 translator_type const& m_translator;
0484 size_type const m_relative_level;
0485 size_type const m_level;
0486
0487 node_pointer & m_root_node;
0488 size_type & m_leafs_level;
0489
0490
0491 insert_traverse_data<internal_node, internal_node_pointer, size_type> m_traverse_data;
0492
0493 allocators_type & m_allocators;
0494 };
0495
0496 }
0497
0498
0499 template
0500 <
0501 typename Element,
0502 typename MembersHolder,
0503 typename InsertTag = typename MembersHolder::options_type::insert_tag
0504 >
0505 class insert;
0506
0507
0508
0509
0510
0511 template <typename Element, typename MembersHolder>
0512 class insert<Element, MembersHolder, insert_default_tag>
0513 : public detail::insert<Element, MembersHolder>
0514 {
0515 public:
0516 typedef detail::insert<Element, MembersHolder> base;
0517
0518 typedef typename base::parameters_type parameters_type;
0519 typedef typename base::translator_type translator_type;
0520 typedef typename base::allocators_type allocators_type;
0521
0522 typedef typename base::node node;
0523 typedef typename base::internal_node internal_node;
0524 typedef typename base::leaf leaf;
0525
0526 typedef typename base::node_pointer node_pointer;
0527 typedef typename base::size_type size_type;
0528
0529 inline insert(node_pointer & root,
0530 size_type & leafs_level,
0531 Element const& element,
0532 parameters_type const& parameters,
0533 translator_type const& translator,
0534 allocators_type & allocators,
0535 size_type relative_level = 0
0536 )
0537 : base(root, leafs_level, element, parameters, translator, allocators, relative_level)
0538 {}
0539
0540 inline void operator()(internal_node & n)
0541 {
0542 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
0543
0544 if ( base::m_traverse_data.current_level < base::m_level )
0545 {
0546
0547 base::traverse(*this, n);
0548 }
0549 else
0550 {
0551 BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");
0552
0553 BOOST_TRY
0554 {
0555
0556 rtree::elements(n).push_back(base::m_element);
0557 }
0558 BOOST_CATCH(...)
0559 {
0560
0561
0562 rtree::visitors::destroy<MembersHolder>::apply(base::m_element.second, base::m_allocators);
0563
0564 BOOST_RETHROW
0565 }
0566 BOOST_CATCH_END
0567 }
0568
0569 base::post_traverse(n);
0570 }
0571
0572 inline void operator()(leaf &)
0573 {
0574 BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");
0575 }
0576 };
0577
0578
0579 template <typename MembersHolder>
0580 class insert<typename MembersHolder::value_type, MembersHolder, insert_default_tag>
0581 : public detail::insert<typename MembersHolder::value_type, MembersHolder>
0582 {
0583 public:
0584 typedef detail::insert<typename MembersHolder::value_type, MembersHolder> base;
0585
0586 typedef typename base::value_type value_type;
0587 typedef typename base::parameters_type parameters_type;
0588 typedef typename base::translator_type translator_type;
0589 typedef typename base::allocators_type allocators_type;
0590
0591 typedef typename base::node node;
0592 typedef typename base::internal_node internal_node;
0593 typedef typename base::leaf leaf;
0594
0595 typedef typename base::node_pointer node_pointer;
0596 typedef typename base::size_type size_type;
0597
0598 inline insert(node_pointer & root,
0599 size_type & leafs_level,
0600 value_type const& value,
0601 parameters_type const& parameters,
0602 translator_type const& translator,
0603 allocators_type & allocators,
0604 size_type relative_level = 0
0605 )
0606 : base(root, leafs_level, value, parameters, translator, allocators, relative_level)
0607 {}
0608
0609 inline void operator()(internal_node & n)
0610 {
0611 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
0612 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");
0613
0614
0615 base::traverse(*this, n);
0616
0617 base::post_traverse(n);
0618 }
0619
0620 inline void operator()(leaf & n)
0621 {
0622 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level, "unexpected level");
0623 BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
0624 base::m_level == (std::numeric_limits<size_t>::max)(), "unexpected level");
0625
0626 rtree::elements(n).push_back(base::m_element);
0627
0628 base::post_traverse(n);
0629 }
0630 };
0631
0632 }}}
0633
0634 }}}
0635
0636 #endif