diff options
Diffstat (limited to 'boost/geometry/index/detail/rtree/pack_create.hpp')
-rw-r--r-- | boost/geometry/index/detail/rtree/pack_create.hpp | 66 |
1 files changed, 51 insertions, 15 deletions
diff --git a/boost/geometry/index/detail/rtree/pack_create.hpp b/boost/geometry/index/detail/rtree/pack_create.hpp index b7be41ab2b..ce07d293db 100644 --- a/boost/geometry/index/detail/rtree/pack_create.hpp +++ b/boost/geometry/index/detail/rtree/pack_create.hpp @@ -11,6 +11,9 @@ #ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP +#include <boost/geometry/algorithms/expand.hpp> +#include <boost/geometry/index/detail/algorithms/bounds.hpp> + namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace pack_utils { @@ -157,8 +160,7 @@ public: values_count = static_cast<size_type>(diff); entries.reserve(values_count); - Box hint_box; - geometry::assign_inverse(hint_box); + expandable_box<Box> hint_box; for ( ; first != last ; ++first ) { // NOTE: support for iterators not returning true references adapted @@ -172,7 +174,7 @@ public: // CONSIDER: alternative - ignore invalid indexable or throw an exception BOOST_GEOMETRY_INDEX_ASSERT(detail::is_valid(indexable), "Indexable is invalid"); - geometry::expand(hint_box, indexable); + hint_box.expand(indexable); point_type pt; geometry::centroid(indexable, pt); @@ -180,13 +182,49 @@ public: } subtree_elements_counts subtree_counts = calculate_subtree_elements_counts(values_count, parameters, leafs_level); - internal_element el = per_level(entries.begin(), entries.end(), hint_box, values_count, subtree_counts, + internal_element el = per_level(entries.begin(), entries.end(), hint_box.get(), values_count, subtree_counts, parameters, translator, allocators); return el.second; } private: + template <typename BoxType> + class expandable_box + { + public: + expandable_box() + : m_initialized(false) + {} + + template <typename Indexable> + void expand(Indexable const& indexable) + { + if ( !m_initialized ) + { + // it's guaranteed that the Box will be initialized + // only for Points, Boxes and Segments but that's ok + // since only those Geometries can be stored + detail::bounds(indexable, m_box); + m_initialized = true; + } + else + { + geometry::expand(m_box, indexable); + } + } + + BoxType const& get() const + { + BOOST_GEOMETRY_INDEX_ASSERT(m_initialized, "uninitialized envelope accessed"); + return m_box; + } + + private: + bool m_initialized; + BoxType m_box; + }; + struct subtree_elements_counts { subtree_elements_counts(std::size_t ma, std::size_t mi) : maxc(ma), minc(mi) {} @@ -216,19 +254,18 @@ private: // reserve space for values rtree::elements(l).reserve(values_count); // MAY THROW (A) // calculate values box and copy values - Box elements_box; - geometry::assign_inverse(elements_box); + expandable_box<Box> elements_box; for ( ; first != last ; ++first ) { // NOTE: push_back() must be called at the end in order to support move_iterator. // The iterator is dereferenced 2x (no temporary reference) to support // non-true reference types and move_iterator without boost::forward<>. - geometry::expand(elements_box, translator(*(first->second))); + elements_box.expand(translator(*(first->second))); rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C) } auto_remover.release(); - return internal_element(elements_box, n); + return internal_element(elements_box.get(), n); } // calculate next max and min subtree counts @@ -245,23 +282,22 @@ private: std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts); rtree::elements(in).reserve(nodes_count); // MAY THROW (A) // calculate values box and copy values - Box elements_box; - geometry::assign_inverse(elements_box); - + expandable_box<Box> elements_box; + per_level_packets(first, last, hint_box, values_count, subtree_counts, next_subtree_counts, rtree::elements(in), elements_box, parameters, translator, allocators); auto_remover.release(); - return internal_element(elements_box, n); + return internal_element(elements_box.get(), n); } - template <typename EIt> inline static + template <typename EIt, typename ExpandableBox> inline static void per_level_packets(EIt first, EIt last, Box const& hint_box, std::size_t values_count, subtree_elements_counts const& subtree_counts, subtree_elements_counts const& next_subtree_counts, - internal_elements & elements, Box & elements_box, + internal_elements & elements, ExpandableBox & elements_box, parameters_type const& parameters, Translator const& translator, Allocators & allocators) { BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count, @@ -285,7 +321,7 @@ private: elements.push_back(el); // MAY THROW (A?,C) - however in normal conditions shouldn't auto_remover.release(); - geometry::expand(elements_box, el.first); + elements_box.expand(el.first); return; } |