File indexing completed on 2025-01-18 09:35:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
0017 #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
0018
0019 #include <type_traits>
0020
0021 #include <boost/core/ignore_unused.hpp>
0022
0023 #include <boost/geometry/algorithms/centroid.hpp>
0024 #include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
0025
0026 #include <boost/geometry/index/detail/algorithms/content.hpp>
0027 #include <boost/geometry/index/detail/rtree/node/concept.hpp>
0028 #include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
0029 #include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
0030
0031 namespace boost { namespace geometry { namespace index {
0032
0033 namespace detail { namespace rtree { namespace visitors {
0034
0035 namespace rstar {
0036
0037
0038 template <typename Point1, typename Point2, typename Strategy>
0039 struct comparable_distance
0040 {
0041 typedef typename geometry::comparable_distance_result
0042 <
0043 Point1, Point2, Strategy
0044 >::type result_type;
0045
0046 static inline result_type call(Point1 const& p1, Point2 const& p2, Strategy const& s)
0047 {
0048 return geometry::comparable_distance(p1, p2, s);
0049 }
0050 };
0051
0052 template <typename Point1, typename Point2>
0053 struct comparable_distance<Point1, Point2, default_strategy>
0054 {
0055 typedef typename geometry::default_comparable_distance_result
0056 <
0057 Point1, Point2
0058 >::type result_type;
0059
0060 static inline result_type call(Point1 const& p1, Point2 const& p2, default_strategy const& )
0061 {
0062 return geometry::comparable_distance(p1, p2);
0063 }
0064 };
0065
0066 template <typename MembersHolder>
0067 class remove_elements_to_reinsert
0068 {
0069 public:
0070 typedef typename MembersHolder::box_type box_type;
0071 typedef typename MembersHolder::parameters_type parameters_type;
0072 typedef typename MembersHolder::translator_type translator_type;
0073 typedef typename MembersHolder::allocators_type allocators_type;
0074
0075 typedef typename MembersHolder::node node;
0076 typedef typename MembersHolder::internal_node internal_node;
0077 typedef typename MembersHolder::leaf leaf;
0078
0079
0080 typedef internal_node * internal_node_pointer;
0081
0082 template <typename ResultElements, typename Node>
0083 static inline void apply(ResultElements & result_elements,
0084 Node & n,
0085 internal_node_pointer parent,
0086 size_t current_child_index,
0087 parameters_type const& parameters,
0088 translator_type const& translator,
0089 allocators_type & allocators)
0090 {
0091 typedef typename rtree::elements_type<Node>::type elements_type;
0092 typedef typename elements_type::value_type element_type;
0093 typedef typename geometry::point_type<box_type>::type point_type;
0094 typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
0095
0096 typedef rstar::comparable_distance
0097 <
0098 point_type, point_type, strategy_type
0099 > comparable_distance_pp;
0100 typedef typename comparable_distance_pp::result_type comparable_distance_type;
0101
0102 elements_type & elements = rtree::elements(n);
0103
0104 const size_t elements_count = parameters.get_max_elements() + 1;
0105 const size_t reinserted_elements_count = (::std::min)(parameters.get_reinserted_elements(), elements_count - parameters.get_min_elements());
0106
0107 BOOST_GEOMETRY_INDEX_ASSERT(parent, "node shouldn't be the root node");
0108 BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected elements number");
0109 BOOST_GEOMETRY_INDEX_ASSERT(0 < reinserted_elements_count, "wrong value of elements to reinsert");
0110
0111 auto const& strategy = index::detail::get_strategy(parameters);
0112
0113
0114 point_type node_center;
0115 geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center,
0116 strategy);
0117
0118
0119 typedef typename index::detail::rtree::container_from_elements_type<
0120 elements_type,
0121 std::pair<comparable_distance_type, element_type>
0122 >::type sorted_elements_type;
0123
0124 sorted_elements_type sorted_elements;
0125
0126 sorted_elements.reserve(elements_count);
0127
0128 for ( typename elements_type::const_iterator it = elements.begin() ;
0129 it != elements.end() ; ++it )
0130 {
0131 point_type element_center;
0132 geometry::centroid(rtree::element_indexable(*it, translator), element_center,
0133 strategy);
0134 sorted_elements.push_back(std::make_pair(
0135 comparable_distance_pp::call(node_center, element_center, strategy),
0136 *it));
0137 }
0138
0139
0140 std::partial_sort(
0141 sorted_elements.begin(),
0142 sorted_elements.begin() + reinserted_elements_count,
0143 sorted_elements.end(),
0144 distances_dsc<comparable_distance_type, element_type>);
0145
0146
0147 result_elements.clear();
0148 result_elements.reserve(reinserted_elements_count);
0149 for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() ;
0150 it != sorted_elements.begin() + reinserted_elements_count ; ++it )
0151 {
0152 result_elements.push_back(it->second);
0153 }
0154
0155 BOOST_TRY
0156 {
0157
0158 elements.clear();
0159 elements.reserve(elements_count - reinserted_elements_count);
0160 for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() + reinserted_elements_count;
0161 it != sorted_elements.end() ; ++it )
0162 {
0163 elements.push_back(it->second);
0164 }
0165 }
0166 BOOST_CATCH(...)
0167 {
0168 elements.clear();
0169
0170 for ( typename sorted_elements_type::iterator it = sorted_elements.begin() ;
0171 it != sorted_elements.end() ; ++it )
0172 {
0173 destroy_element<MembersHolder>::apply(it->second, allocators);
0174 }
0175
0176 BOOST_RETHROW
0177 }
0178 BOOST_CATCH_END
0179
0180 ::boost::ignore_unused(parameters);
0181 }
0182
0183 private:
0184 template <typename Distance, typename El>
0185 static inline bool distances_asc(
0186 std::pair<Distance, El> const& d1,
0187 std::pair<Distance, El> const& d2)
0188 {
0189 return d1.first < d2.first;
0190 }
0191
0192 template <typename Distance, typename El>
0193 static inline bool distances_dsc(
0194 std::pair<Distance, El> const& d1,
0195 std::pair<Distance, El> const& d2)
0196 {
0197 return d1.first > d2.first;
0198 }
0199 };
0200
0201 template
0202 <
0203 size_t InsertIndex,
0204 typename Element,
0205 typename MembersHolder,
0206 bool IsValue = std::is_same<Element, typename MembersHolder::value_type>::value
0207 >
0208 struct level_insert_elements_type
0209 {
0210 typedef typename rtree::elements_type<
0211 typename rtree::internal_node<
0212 typename MembersHolder::value_type,
0213 typename MembersHolder::parameters_type,
0214 typename MembersHolder::box_type,
0215 typename MembersHolder::allocators_type,
0216 typename MembersHolder::node_tag
0217 >::type
0218 >::type type;
0219 };
0220
0221 template <typename Value, typename MembersHolder>
0222 struct level_insert_elements_type<0, Value, MembersHolder, true>
0223 {
0224 typedef typename rtree::elements_type<
0225 typename rtree::leaf<
0226 typename MembersHolder::value_type,
0227 typename MembersHolder::parameters_type,
0228 typename MembersHolder::box_type,
0229 typename MembersHolder::allocators_type,
0230 typename MembersHolder::node_tag
0231 >::type
0232 >::type type;
0233 };
0234
0235 template <size_t InsertIndex, typename Element, typename MembersHolder>
0236 struct level_insert_base
0237 : public detail::insert<Element, MembersHolder>
0238 {
0239 typedef detail::insert<Element, MembersHolder> base;
0240 typedef typename base::node node;
0241 typedef typename base::internal_node internal_node;
0242 typedef typename base::leaf leaf;
0243
0244 typedef typename level_insert_elements_type<InsertIndex, Element, MembersHolder>::type elements_type;
0245 typedef typename index::detail::rtree::container_from_elements_type<
0246 elements_type,
0247 typename elements_type::value_type
0248 >::type result_elements_type;
0249
0250 typedef typename MembersHolder::box_type box_type;
0251 typedef typename MembersHolder::parameters_type parameters_type;
0252 typedef typename MembersHolder::translator_type translator_type;
0253 typedef typename MembersHolder::allocators_type allocators_type;
0254
0255 typedef typename allocators_type::node_pointer node_pointer;
0256 typedef typename allocators_type::size_type size_type;
0257
0258 inline level_insert_base(node_pointer & root,
0259 size_type & leafs_level,
0260 Element const& element,
0261 parameters_type const& parameters,
0262 translator_type const& translator,
0263 allocators_type & allocators,
0264 size_type relative_level)
0265 : base(root, leafs_level, element, parameters, translator, allocators, relative_level)
0266 , result_relative_level(0)
0267 {}
0268
0269 template <typename Node>
0270 inline void handle_possible_reinsert_or_split_of_root(Node &n)
0271 {
0272 BOOST_GEOMETRY_INDEX_ASSERT(result_elements.empty(), "reinsert should be handled only once for level");
0273
0274 result_relative_level = base::m_leafs_level - base::m_traverse_data.current_level;
0275
0276
0277 if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
0278 {
0279
0280 if ( !base::m_traverse_data.current_is_root() )
0281 {
0282
0283
0284 rstar::remove_elements_to_reinsert<MembersHolder>::apply(
0285 result_elements, n,
0286 base::m_traverse_data.parent, base::m_traverse_data.current_child_index,
0287 base::m_parameters, base::m_translator, base::m_allocators);
0288 }
0289
0290 else
0291 {
0292 BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*base::m_root_node), "node should be the root node");
0293 base::split(n);
0294 }
0295 }
0296 }
0297
0298 template <typename Node>
0299 inline void handle_possible_split(Node &n) const
0300 {
0301
0302 if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
0303 {
0304 base::split(n);
0305 }
0306 }
0307
0308 template <typename Node>
0309 inline void recalculate_aabb_if_necessary(Node const& n) const
0310 {
0311 if ( !result_elements.empty() && !base::m_traverse_data.current_is_root() )
0312 {
0313
0314 recalculate_aabb(n);
0315 }
0316 }
0317
0318 template <typename Node>
0319 inline void recalculate_aabb(Node const& n) const
0320 {
0321 base::m_traverse_data.current_element().first =
0322 elements_box<box_type>(rtree::elements(n).begin(), rtree::elements(n).end(),
0323 base::m_translator,
0324 index::detail::get_strategy(base::m_parameters));
0325 }
0326
0327 inline void recalculate_aabb(leaf const& n) const
0328 {
0329 base::m_traverse_data.current_element().first =
0330 values_box<box_type>(rtree::elements(n).begin(), rtree::elements(n).end(),
0331 base::m_translator,
0332 index::detail::get_strategy(base::m_parameters));
0333 }
0334
0335 size_type result_relative_level;
0336 result_elements_type result_elements;
0337 };
0338
0339 template
0340 <
0341 size_t InsertIndex,
0342 typename Element,
0343 typename MembersHolder,
0344 bool IsValue = std::is_same<Element, typename MembersHolder::value_type>::value
0345 >
0346 struct level_insert
0347 : public level_insert_base<InsertIndex, Element, MembersHolder>
0348 {
0349 typedef level_insert_base<InsertIndex, Element, MembersHolder> base;
0350 typedef typename base::node node;
0351 typedef typename base::internal_node internal_node;
0352 typedef typename base::leaf leaf;
0353
0354 typedef typename base::parameters_type parameters_type;
0355 typedef typename base::translator_type translator_type;
0356 typedef typename base::allocators_type allocators_type;
0357
0358 typedef typename base::node_pointer node_pointer;
0359 typedef typename base::size_type size_type;
0360
0361 inline level_insert(node_pointer & root,
0362 size_type & leafs_level,
0363 Element const& element,
0364 parameters_type const& parameters,
0365 translator_type const& translator,
0366 allocators_type & allocators,
0367 size_type relative_level)
0368 : base(root, leafs_level, element, parameters, translator, allocators, relative_level)
0369 {}
0370
0371 inline void operator()(internal_node & n)
0372 {
0373 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
0374
0375 if ( base::m_traverse_data.current_level < base::m_level )
0376 {
0377
0378 base::traverse(*this, n);
0379
0380
0381 if ( 0 < InsertIndex )
0382 {
0383 BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
0384
0385 if ( base::m_traverse_data.current_level == base::m_level - 1 )
0386 {
0387 base::handle_possible_reinsert_or_split_of_root(n);
0388 }
0389 }
0390 }
0391 else
0392 {
0393 BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");
0394
0395 BOOST_TRY
0396 {
0397
0398 rtree::elements(n).push_back(base::m_element);
0399 }
0400 BOOST_CATCH(...)
0401 {
0402
0403
0404
0405 rtree::visitors::destroy<MembersHolder>::apply(base::m_element.second, base::m_allocators);
0406
0407 BOOST_RETHROW
0408 }
0409 BOOST_CATCH_END
0410
0411
0412 if ( 0 == InsertIndex )
0413 {
0414 base::handle_possible_reinsert_or_split_of_root(n);
0415 }
0416
0417 else
0418 {
0419 base::handle_possible_split(n);
0420 }
0421 }
0422
0423 base::recalculate_aabb_if_necessary(n);
0424 }
0425
0426 inline void operator()(leaf &)
0427 {
0428 BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");
0429 }
0430 };
0431
0432 template <size_t InsertIndex, typename Value, typename MembersHolder>
0433 struct level_insert<InsertIndex, Value, MembersHolder, true>
0434 : public level_insert_base<InsertIndex, typename MembersHolder::value_type, MembersHolder>
0435 {
0436 typedef level_insert_base<InsertIndex, typename MembersHolder::value_type, MembersHolder> base;
0437 typedef typename base::node node;
0438 typedef typename base::internal_node internal_node;
0439 typedef typename base::leaf leaf;
0440
0441 typedef typename MembersHolder::value_type value_type;
0442 typedef typename base::parameters_type parameters_type;
0443 typedef typename base::translator_type translator_type;
0444 typedef typename base::allocators_type allocators_type;
0445
0446 typedef typename base::node_pointer node_pointer;
0447 typedef typename base::size_type size_type;
0448
0449 inline level_insert(node_pointer & root,
0450 size_type & leafs_level,
0451 value_type const& v,
0452 parameters_type const& parameters,
0453 translator_type const& translator,
0454 allocators_type & allocators,
0455 size_type relative_level)
0456 : base(root, leafs_level, v, parameters, translator, allocators, relative_level)
0457 {}
0458
0459 inline void operator()(internal_node & n)
0460 {
0461 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
0462 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");
0463
0464
0465 base::traverse(*this, n);
0466
0467 BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
0468
0469 if ( base::m_traverse_data.current_level == base::m_level - 1 )
0470 {
0471 base::handle_possible_reinsert_or_split_of_root(n);
0472 }
0473
0474 base::recalculate_aabb_if_necessary(n);
0475 }
0476
0477 inline void operator()(leaf & n)
0478 {
0479 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
0480 "unexpected level");
0481 BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
0482 base::m_level == (std::numeric_limits<size_t>::max)(),
0483 "unexpected level");
0484
0485 rtree::elements(n).push_back(base::m_element);
0486
0487 base::handle_possible_split(n);
0488 }
0489 };
0490
0491 template <typename Value, typename MembersHolder>
0492 struct level_insert<0, Value, MembersHolder, true>
0493 : public level_insert_base<0, typename MembersHolder::value_type, MembersHolder>
0494 {
0495 typedef level_insert_base<0, typename MembersHolder::value_type, MembersHolder> base;
0496 typedef typename base::node node;
0497 typedef typename base::internal_node internal_node;
0498 typedef typename base::leaf leaf;
0499
0500 typedef typename MembersHolder::value_type value_type;
0501 typedef typename base::parameters_type parameters_type;
0502 typedef typename base::translator_type translator_type;
0503 typedef typename base::allocators_type allocators_type;
0504
0505 typedef typename base::node_pointer node_pointer;
0506 typedef typename base::size_type size_type;
0507
0508 inline level_insert(node_pointer & root,
0509 size_type & leafs_level,
0510 value_type const& v,
0511 parameters_type const& parameters,
0512 translator_type const& translator,
0513 allocators_type & allocators,
0514 size_type relative_level)
0515 : base(root, leafs_level, v, parameters, translator, allocators, relative_level)
0516 {}
0517
0518 inline void operator()(internal_node & n)
0519 {
0520 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level,
0521 "unexpected level");
0522 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level,
0523 "unexpected level");
0524
0525
0526 base::traverse(*this, n);
0527
0528 base::recalculate_aabb_if_necessary(n);
0529 }
0530
0531 inline void operator()(leaf & n)
0532 {
0533 BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
0534 "unexpected level");
0535 BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
0536 base::m_level == (std::numeric_limits<size_t>::max)(),
0537 "unexpected level");
0538
0539 rtree::elements(n).push_back(base::m_element);
0540
0541 base::handle_possible_reinsert_or_split_of_root(n);
0542
0543 base::recalculate_aabb_if_necessary(n);
0544 }
0545 };
0546
0547 }
0548
0549
0550
0551
0552
0553 template <typename Element, typename MembersHolder>
0554 class insert<Element, MembersHolder, insert_reinsert_tag>
0555 : public MembersHolder::visitor
0556 {
0557 typedef typename MembersHolder::parameters_type parameters_type;
0558 typedef typename MembersHolder::translator_type translator_type;
0559 typedef typename MembersHolder::allocators_type allocators_type;
0560
0561 typedef typename MembersHolder::node node;
0562 typedef typename MembersHolder::internal_node internal_node;
0563 typedef typename MembersHolder::leaf leaf;
0564
0565 typedef typename allocators_type::node_pointer node_pointer;
0566 typedef typename allocators_type::size_type size_type;
0567
0568 public:
0569 inline insert(node_pointer & root,
0570 size_type & leafs_level,
0571 Element const& element,
0572 parameters_type const& parameters,
0573 translator_type const& translator,
0574 allocators_type & allocators,
0575 size_type relative_level = 0)
0576 : m_root(root), m_leafs_level(leafs_level), m_element(element)
0577 , m_parameters(parameters), m_translator(translator)
0578 , m_relative_level(relative_level), m_allocators(allocators)
0579 {}
0580
0581 inline void operator()(internal_node & n)
0582 {
0583 boost::ignore_unused(n);
0584 BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root), "current node should be the root");
0585
0586
0587 if ( m_parameters.get_reinserted_elements() > 0 )
0588 {
0589 rstar::level_insert<0, Element, MembersHolder> lins_v(
0590 m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
0591
0592 rtree::apply_visitor(lins_v, *m_root);
0593
0594 if ( !lins_v.result_elements.empty() )
0595 {
0596 recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level);
0597 }
0598 }
0599 else
0600 {
0601 visitors::insert<Element, MembersHolder, insert_default_tag> ins_v(
0602 m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
0603
0604 rtree::apply_visitor(ins_v, *m_root);
0605 }
0606 }
0607
0608 inline void operator()(leaf & n)
0609 {
0610 boost::ignore_unused(n);
0611 BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<leaf>(*m_root), "current node should be the root");
0612
0613
0614 if ( m_parameters.get_reinserted_elements() > 0 )
0615 {
0616 rstar::level_insert<0, Element, MembersHolder> lins_v(
0617 m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
0618
0619 rtree::apply_visitor(lins_v, *m_root);
0620
0621
0622 BOOST_GEOMETRY_INDEX_ASSERT(lins_v.result_elements.empty(), "unexpected state");
0623 }
0624 else
0625 {
0626 visitors::insert<Element, MembersHolder, insert_default_tag> ins_v(
0627 m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
0628
0629 rtree::apply_visitor(ins_v, *m_root);
0630 }
0631 }
0632
0633 private:
0634 template <typename Elements>
0635 inline void recursive_reinsert(Elements & elements, size_t relative_level)
0636 {
0637 typedef typename Elements::value_type element_type;
0638
0639
0640 typename Elements::reverse_iterator it = elements.rbegin();
0641 for ( ; it != elements.rend() ; ++it)
0642 {
0643 rstar::level_insert<1, element_type, MembersHolder> lins_v(
0644 m_root, m_leafs_level, *it, m_parameters, m_translator, m_allocators, relative_level);
0645
0646 BOOST_TRY
0647 {
0648 rtree::apply_visitor(lins_v, *m_root);
0649 }
0650 BOOST_CATCH(...)
0651 {
0652 ++it;
0653 for ( ; it != elements.rend() ; ++it)
0654 rtree::destroy_element<MembersHolder>::apply(*it, m_allocators);
0655 BOOST_RETHROW
0656 }
0657 BOOST_CATCH_END
0658
0659 BOOST_GEOMETRY_INDEX_ASSERT(relative_level + 1 == lins_v.result_relative_level, "unexpected level");
0660
0661
0662 if ( lins_v.result_relative_level < m_leafs_level && !lins_v.result_elements.empty())
0663 {
0664 recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level);
0665 }
0666 }
0667 }
0668
0669 node_pointer & m_root;
0670 size_type & m_leafs_level;
0671 Element const& m_element;
0672
0673 parameters_type const& m_parameters;
0674 translator_type const& m_translator;
0675
0676 size_type m_relative_level;
0677
0678 allocators_type & m_allocators;
0679 };
0680
0681 }}}
0682
0683 }}}
0684
0685 #endif