add boost on mac
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree R*-tree next node choosing algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2019 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/content.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/node.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
template <typename Value, typename Options, typename Box, typename Allocators>
|
||||
class choose_next_node<Value, Options, Box, Allocators, choose_by_overlap_diff_tag>
|
||||
{
|
||||
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type children_type;
|
||||
typedef typename children_type::value_type child_type;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
public:
|
||||
template <typename Indexable>
|
||||
static inline size_t apply(internal_node & n,
|
||||
Indexable const& indexable,
|
||||
parameters_type const& parameters,
|
||||
size_t node_relative_level)
|
||||
{
|
||||
::boost::ignore_unused(parameters);
|
||||
|
||||
children_type & children = rtree::elements(n);
|
||||
|
||||
// children are leafs
|
||||
if ( node_relative_level <= 1 )
|
||||
{
|
||||
return choose_by_minimum_overlap_cost(children, indexable, parameters.get_overlap_cost_threshold());
|
||||
}
|
||||
// children are internal nodes
|
||||
else
|
||||
return choose_by_minimum_content_cost(children, indexable);
|
||||
}
|
||||
|
||||
private:
|
||||
struct child_contents
|
||||
{
|
||||
content_type content_diff;
|
||||
content_type content;
|
||||
size_t i;
|
||||
|
||||
void set(size_t i_, content_type const& content_, content_type const& content_diff_)
|
||||
{
|
||||
i = i_;
|
||||
content = content_;
|
||||
content_diff = content_diff_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable>
|
||||
static inline size_t choose_by_minimum_overlap_cost(children_type const& children,
|
||||
Indexable const& indexable,
|
||||
size_t overlap_cost_threshold)
|
||||
{
|
||||
const size_t children_count = children.size();
|
||||
|
||||
content_type min_content_diff = (std::numeric_limits<content_type>::max)();
|
||||
content_type min_content = (std::numeric_limits<content_type>::max)();
|
||||
size_t choosen_index = 0;
|
||||
|
||||
// create container of children sorted by content enlargement needed to include the new value
|
||||
typename rtree::container_from_elements_type<children_type, child_contents>::type
|
||||
children_contents(children_count);
|
||||
|
||||
for ( size_t i = 0 ; i < children_count ; ++i )
|
||||
{
|
||||
child_type const& ch_i = children[i];
|
||||
|
||||
// expanded child node's box
|
||||
Box box_exp(ch_i.first);
|
||||
geometry::expand(box_exp, indexable);
|
||||
|
||||
// areas difference
|
||||
content_type content = index::detail::content(box_exp);
|
||||
content_type content_diff = content - index::detail::content(ch_i.first);
|
||||
|
||||
children_contents[i].set(i, content, content_diff);
|
||||
|
||||
if ( content_diff < min_content_diff ||
|
||||
(content_diff == min_content_diff && content < min_content) )
|
||||
{
|
||||
min_content_diff = content_diff;
|
||||
min_content = content;
|
||||
choosen_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
// is this assumption ok? if min_content_diff == 0 there is no overlap increase?
|
||||
|
||||
if ( min_content_diff < -std::numeric_limits<double>::epsilon() || std::numeric_limits<double>::epsilon() < min_content_diff )
|
||||
{
|
||||
size_t first_n_children_count = children_count;
|
||||
if ( 0 < overlap_cost_threshold && overlap_cost_threshold < children.size() )
|
||||
{
|
||||
first_n_children_count = overlap_cost_threshold;
|
||||
// rearrange by content_diff
|
||||
// in order to calculate nearly minimum overlap cost
|
||||
index::detail::nth_element(children_contents.begin(), children_contents.begin() + first_n_children_count, children_contents.end(), content_diff_less);
|
||||
}
|
||||
|
||||
// calculate minimum or nearly minimum overlap cost
|
||||
choosen_index = choose_by_minimum_overlap_cost_first_n(children, indexable, first_n_children_count, children_count, children_contents);
|
||||
}
|
||||
|
||||
return choosen_index;
|
||||
}
|
||||
|
||||
static inline bool content_diff_less(child_contents const& p1, child_contents const& p2)
|
||||
{
|
||||
return p1.content_diff < p2.content_diff
|
||||
|| (p1.content_diff == p2.content_diff && (p1.content) < (p2.content));
|
||||
}
|
||||
|
||||
template <typename Indexable, typename ChildrenContents>
|
||||
static inline size_t choose_by_minimum_overlap_cost_first_n(children_type const& children,
|
||||
Indexable const& indexable,
|
||||
size_t const first_n_children_count,
|
||||
size_t const children_count,
|
||||
ChildrenContents const& children_contents)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(first_n_children_count <= children_count, "unexpected value");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(children_contents.size() == children_count, "unexpected number of elements");
|
||||
|
||||
// choose index with smallest overlap change value, or content change or smallest content
|
||||
size_t choosen_index = 0;
|
||||
content_type smallest_overlap_diff = (std::numeric_limits<content_type>::max)();
|
||||
content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
|
||||
content_type smallest_content = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
// for each child node
|
||||
for (size_t first_i = 0 ; first_i < first_n_children_count ; ++first_i)
|
||||
{
|
||||
size_t i = children_contents[first_i].i;
|
||||
content_type const& content = children_contents[first_i].content;
|
||||
content_type const& content_diff = children_contents[first_i].content_diff;
|
||||
|
||||
child_type const& ch_i = children[i];
|
||||
|
||||
Box box_exp(ch_i.first);
|
||||
// calculate expanded box of child node ch_i
|
||||
geometry::expand(box_exp, indexable);
|
||||
|
||||
content_type overlap_diff = 0;
|
||||
|
||||
// calculate overlap
|
||||
for ( size_t j = 0 ; j < children_count ; ++j )
|
||||
{
|
||||
if ( i != j )
|
||||
{
|
||||
child_type const& ch_j = children[j];
|
||||
|
||||
content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first);
|
||||
if ( overlap_exp < -std::numeric_limits<content_type>::epsilon() || std::numeric_limits<content_type>::epsilon() < overlap_exp )
|
||||
{
|
||||
overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update result
|
||||
if ( overlap_diff < smallest_overlap_diff ||
|
||||
( overlap_diff == smallest_overlap_diff && ( content_diff < smallest_content_diff ||
|
||||
( content_diff == smallest_content_diff && content < smallest_content ) )
|
||||
) )
|
||||
{
|
||||
smallest_overlap_diff = overlap_diff;
|
||||
smallest_content_diff = content_diff;
|
||||
smallest_content = content;
|
||||
choosen_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return choosen_index;
|
||||
}
|
||||
|
||||
template <typename Indexable>
|
||||
static inline size_t choose_by_minimum_content_cost(children_type const& children, Indexable const& indexable)
|
||||
{
|
||||
size_t children_count = children.size();
|
||||
|
||||
// choose index with smallest content change or smallest content
|
||||
size_t choosen_index = 0;
|
||||
content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
|
||||
content_type smallest_content = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
// choose the child which requires smallest box expansion to store the indexable
|
||||
for ( size_t i = 0 ; i < children_count ; ++i )
|
||||
{
|
||||
child_type const& ch_i = children[i];
|
||||
|
||||
// expanded child node's box
|
||||
Box box_exp(ch_i.first);
|
||||
geometry::expand(box_exp, indexable);
|
||||
|
||||
// areas difference
|
||||
content_type content = index::detail::content(box_exp);
|
||||
content_type content_diff = content - index::detail::content(ch_i.first);
|
||||
|
||||
// update the result
|
||||
if ( content_diff < smallest_content_diff ||
|
||||
( content_diff == smallest_content_diff && content < smallest_content ) )
|
||||
{
|
||||
smallest_content_diff = content_diff;
|
||||
smallest_content = content;
|
||||
choosen_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return choosen_index;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP
|
||||
@@ -0,0 +1,593 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree R*-tree insert algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/content.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
namespace rstar {
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class remove_elements_to_reinsert
|
||||
{
|
||||
public:
|
||||
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
//typedef typename Allocators::internal_node_pointer internal_node_pointer;
|
||||
typedef internal_node * internal_node_pointer;
|
||||
|
||||
template <typename ResultElements, typename Node>
|
||||
static inline void apply(ResultElements & result_elements,
|
||||
Node & n,
|
||||
internal_node_pointer parent,
|
||||
size_t current_child_index,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators)
|
||||
{
|
||||
typedef typename rtree::elements_type<Node>::type elements_type;
|
||||
typedef typename elements_type::value_type element_type;
|
||||
typedef typename geometry::point_type<Box>::type point_type;
|
||||
// TODO: awulkiew - change second point_type to the point type of the Indexable?
|
||||
typedef typename
|
||||
geometry::default_comparable_distance_result<point_type>::type
|
||||
comparable_distance_type;
|
||||
|
||||
elements_type & elements = rtree::elements(n);
|
||||
|
||||
const size_t elements_count = parameters.get_max_elements() + 1;
|
||||
const size_t reinserted_elements_count = (::std::min)(parameters.get_reinserted_elements(), elements_count - parameters.get_min_elements());
|
||||
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(parent, "node shouldn't be the root node");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected elements number");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < reinserted_elements_count, "wrong value of elements to reinsert");
|
||||
|
||||
// calculate current node's center
|
||||
point_type node_center;
|
||||
geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center);
|
||||
|
||||
// fill the container of centers' distances of children from current node's center
|
||||
typedef typename index::detail::rtree::container_from_elements_type<
|
||||
elements_type,
|
||||
std::pair<comparable_distance_type, element_type>
|
||||
>::type sorted_elements_type;
|
||||
|
||||
sorted_elements_type sorted_elements;
|
||||
// If constructor is used instead of resize() MS implementation leaks here
|
||||
sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
|
||||
|
||||
for ( typename elements_type::const_iterator it = elements.begin() ;
|
||||
it != elements.end() ; ++it )
|
||||
{
|
||||
point_type element_center;
|
||||
geometry::centroid( rtree::element_indexable(*it, translator), element_center);
|
||||
sorted_elements.push_back(std::make_pair(
|
||||
geometry::comparable_distance(node_center, element_center),
|
||||
*it)); // MAY THROW (V, E: copy)
|
||||
}
|
||||
|
||||
// sort elements by distances from center
|
||||
std::partial_sort(
|
||||
sorted_elements.begin(),
|
||||
sorted_elements.begin() + reinserted_elements_count,
|
||||
sorted_elements.end(),
|
||||
distances_dsc<comparable_distance_type, element_type>); // MAY THROW, BASIC (V, E: copy)
|
||||
|
||||
// copy elements which will be reinserted
|
||||
result_elements.clear();
|
||||
result_elements.reserve(reinserted_elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
|
||||
for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() ;
|
||||
it != sorted_elements.begin() + reinserted_elements_count ; ++it )
|
||||
{
|
||||
result_elements.push_back(it->second); // MAY THROW (V, E: copy)
|
||||
}
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
// copy remaining elements to the current node
|
||||
elements.clear();
|
||||
elements.reserve(elements_count - reinserted_elements_count); // SHOULDN'T THROW (new_size <= old size)
|
||||
for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() + reinserted_elements_count;
|
||||
it != sorted_elements.end() ; ++it )
|
||||
{
|
||||
elements.push_back(it->second); // MAY THROW (V, E: copy)
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
elements.clear();
|
||||
|
||||
for ( typename sorted_elements_type::iterator it = sorted_elements.begin() ;
|
||||
it != sorted_elements.end() ; ++it )
|
||||
{
|
||||
destroy_element<Value, Options, Translator, Box, Allocators>::apply(it->second, allocators);
|
||||
}
|
||||
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
::boost::ignore_unused(parameters);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Distance, typename El>
|
||||
static inline bool distances_asc(
|
||||
std::pair<Distance, El> const& d1,
|
||||
std::pair<Distance, El> const& d2)
|
||||
{
|
||||
return d1.first < d2.first;
|
||||
}
|
||||
|
||||
template <typename Distance, typename El>
|
||||
static inline bool distances_dsc(
|
||||
std::pair<Distance, El> const& d1,
|
||||
std::pair<Distance, El> const& d2)
|
||||
{
|
||||
return d1.first > d2.first;
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Box, typename Allocators>
|
||||
struct level_insert_elements_type
|
||||
{
|
||||
typedef typename rtree::elements_type<
|
||||
typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Options, typename Box, typename Allocators>
|
||||
struct level_insert_elements_type<0, Value, Value, Options, Box, Allocators>
|
||||
{
|
||||
typedef typename rtree::elements_type<
|
||||
typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct level_insert_base
|
||||
: public detail::insert<Element, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
typedef detail::insert<Element, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename level_insert_elements_type<InsertIndex, Element, Value, Options, Box, Allocators>::type elements_type;
|
||||
typedef typename index::detail::rtree::container_from_elements_type<
|
||||
elements_type,
|
||||
typename elements_type::value_type
|
||||
>::type result_elements_type;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
inline level_insert_base(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Element const& element,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level)
|
||||
: base(root, leafs_level, element, parameters, translator, allocators, relative_level)
|
||||
, result_relative_level(0)
|
||||
{}
|
||||
|
||||
template <typename Node>
|
||||
inline void handle_possible_reinsert_or_split_of_root(Node &n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(result_elements.empty(), "reinsert should be handled only once for level");
|
||||
|
||||
result_relative_level = base::m_leafs_level - base::m_traverse_data.current_level;
|
||||
|
||||
// overflow
|
||||
if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
|
||||
{
|
||||
// node isn't root node
|
||||
if ( !base::m_traverse_data.current_is_root() )
|
||||
{
|
||||
// NOTE: exception-safety
|
||||
// After an exception result_elements may contain garbage, don't use it
|
||||
rstar::remove_elements_to_reinsert<Value, Options, Translator, Box, Allocators>::apply(
|
||||
result_elements, n,
|
||||
base::m_traverse_data.parent, base::m_traverse_data.current_child_index,
|
||||
base::m_parameters, base::m_translator, base::m_allocators); // MAY THROW, BASIC (V, E: alloc, copy)
|
||||
}
|
||||
// node is root node
|
||||
else
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*base::m_root_node), "node should be the root node");
|
||||
base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
inline void handle_possible_split(Node &n) const
|
||||
{
|
||||
// overflow
|
||||
if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
|
||||
{
|
||||
base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
inline void recalculate_aabb_if_necessary(Node const& n) const
|
||||
{
|
||||
if ( !result_elements.empty() && !base::m_traverse_data.current_is_root() )
|
||||
{
|
||||
// calulate node's new box
|
||||
recalculate_aabb(n);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
inline void recalculate_aabb(Node const& n) const
|
||||
{
|
||||
base::m_traverse_data.current_element().first =
|
||||
elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);
|
||||
}
|
||||
|
||||
inline void recalculate_aabb(leaf const& n) const
|
||||
{
|
||||
base::m_traverse_data.current_element().first =
|
||||
values_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);
|
||||
}
|
||||
|
||||
size_type result_relative_level;
|
||||
result_elements_type result_elements;
|
||||
};
|
||||
|
||||
template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct level_insert
|
||||
: public level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
typedef level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
inline level_insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Element const& element,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level)
|
||||
: base(root, leafs_level, element, parameters, translator, allocators, relative_level)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
|
||||
|
||||
if ( base::m_traverse_data.current_level < base::m_level )
|
||||
{
|
||||
// next traversing step
|
||||
base::traverse(*this, n); // MAY THROW (E: alloc, copy, N: alloc)
|
||||
|
||||
// further insert
|
||||
if ( 0 < InsertIndex )
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
|
||||
|
||||
if ( base::m_traverse_data.current_level == base::m_level - 1 )
|
||||
{
|
||||
base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
// push new child node
|
||||
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
// NOTE: exception-safety
|
||||
// if the insert fails above, the element won't be stored in the tree, so delete it
|
||||
|
||||
rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(base::m_element.second, base::m_allocators);
|
||||
rtree::apply_visitor(del_v, *base::m_element.second);
|
||||
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
// first insert
|
||||
if ( 0 == InsertIndex )
|
||||
{
|
||||
base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
|
||||
}
|
||||
// not the first insert
|
||||
else
|
||||
{
|
||||
base::handle_possible_split(n); // MAY THROW (E: alloc, N: alloc)
|
||||
}
|
||||
}
|
||||
|
||||
base::recalculate_aabb_if_necessary(n);
|
||||
}
|
||||
|
||||
inline void operator()(leaf &)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t InsertIndex, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct level_insert<InsertIndex, Value, Value, Options, Translator, Box, Allocators>
|
||||
: public level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
typedef level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
inline level_insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Value const& v,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level)
|
||||
: base(root, leafs_level, v, parameters, translator, allocators, relative_level)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");
|
||||
|
||||
// next traversing step
|
||||
base::traverse(*this, n); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
|
||||
|
||||
if ( base::m_traverse_data.current_level == base::m_level - 1 )
|
||||
{
|
||||
base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
|
||||
}
|
||||
|
||||
base::recalculate_aabb_if_necessary(n);
|
||||
}
|
||||
|
||||
inline void operator()(leaf & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
|
||||
"unexpected level");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
|
||||
base::m_level == (std::numeric_limits<size_t>::max)(),
|
||||
"unexpected level");
|
||||
|
||||
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
|
||||
|
||||
base::handle_possible_split(n); // MAY THROW (V: alloc, copy, N: alloc)
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct level_insert<0, Value, Value, Options, Translator, Box, Allocators>
|
||||
: public level_insert_base<0, Value, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
typedef level_insert_base<0, Value, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
inline level_insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Value const& v,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level)
|
||||
: base(root, leafs_level, v, parameters, translator, allocators, relative_level)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level,
|
||||
"unexpected level");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level,
|
||||
"unexpected level");
|
||||
|
||||
// next traversing step
|
||||
base::traverse(*this, n); // MAY THROW (V: alloc, copy, N: alloc)
|
||||
|
||||
base::recalculate_aabb_if_necessary(n);
|
||||
}
|
||||
|
||||
inline void operator()(leaf & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
|
||||
"unexpected level");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
|
||||
base::m_level == (std::numeric_limits<size_t>::max)(),
|
||||
"unexpected level");
|
||||
|
||||
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
|
||||
|
||||
base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (V: alloc, copy, N: alloc)
|
||||
|
||||
base::recalculate_aabb_if_necessary(n);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rstar
|
||||
|
||||
// R*-tree insert visitor
|
||||
// After passing the Element to insert visitor the Element is managed by the tree
|
||||
// I.e. one should not delete the node passed to the insert visitor after exception is thrown
|
||||
// because this visitor may delete it
|
||||
template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class insert<Element, Value, Options, Translator, Box, Allocators, insert_reinsert_tag>
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
|
||||
{
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
public:
|
||||
inline insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Element const& element,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level = 0)
|
||||
: m_root(root), m_leafs_level(leafs_level), m_element(element)
|
||||
, m_parameters(parameters), m_translator(translator)
|
||||
, m_relative_level(relative_level), m_allocators(allocators)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node & n)
|
||||
{
|
||||
boost::ignore_unused(n);
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root), "current node should be the root");
|
||||
|
||||
// Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
|
||||
if ( m_parameters.get_reinserted_elements() > 0 )
|
||||
{
|
||||
rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(
|
||||
m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
|
||||
|
||||
rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
|
||||
if ( !lins_v.result_elements.empty() )
|
||||
{
|
||||
recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(
|
||||
m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
|
||||
|
||||
rtree::apply_visitor(ins_v, *m_root);
|
||||
}
|
||||
}
|
||||
|
||||
inline void operator()(leaf & n)
|
||||
{
|
||||
boost::ignore_unused(n);
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<leaf>(*m_root), "current node should be the root");
|
||||
|
||||
// Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
|
||||
if ( m_parameters.get_reinserted_elements() > 0 )
|
||||
{
|
||||
rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(
|
||||
m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
|
||||
|
||||
rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
|
||||
// we're in the root, so root should be split and there should be no elements to reinsert
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(lins_v.result_elements.empty(), "unexpected state");
|
||||
}
|
||||
else
|
||||
{
|
||||
visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(
|
||||
m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
|
||||
|
||||
rtree::apply_visitor(ins_v, *m_root);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Elements>
|
||||
inline void recursive_reinsert(Elements & elements, size_t relative_level)
|
||||
{
|
||||
typedef typename Elements::value_type element_type;
|
||||
|
||||
// reinsert children starting from the minimum distance
|
||||
typename Elements::reverse_iterator it = elements.rbegin();
|
||||
for ( ; it != elements.rend() ; ++it)
|
||||
{
|
||||
rstar::level_insert<1, element_type, Value, Options, Translator, Box, Allocators> lins_v(
|
||||
m_root, m_leafs_level, *it, m_parameters, m_translator, m_allocators, relative_level);
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
++it;
|
||||
for ( ; it != elements.rend() ; ++it)
|
||||
rtree::destroy_element<Value, Options, Translator, Box, Allocators>::apply(*it, m_allocators);
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(relative_level + 1 == lins_v.result_relative_level, "unexpected level");
|
||||
|
||||
// non-root relative level
|
||||
if ( lins_v.result_relative_level < m_leafs_level && !lins_v.result_elements.empty())
|
||||
{
|
||||
recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node_pointer & m_root;
|
||||
size_type & m_leafs_level;
|
||||
Element const& m_element;
|
||||
|
||||
parameters_type const& m_parameters;
|
||||
Translator const& m_translator;
|
||||
|
||||
size_type m_relative_level;
|
||||
|
||||
Allocators & m_allocators;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
|
||||
@@ -0,0 +1,472 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree R*-tree split algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/margin.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/bounded_view.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/node.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
namespace rstar {
|
||||
|
||||
template <typename Element, typename Translator, typename Tag, size_t Corner, size_t AxisIndex>
|
||||
class element_axis_corner_less
|
||||
{
|
||||
typedef typename rtree::element_indexable_type<Element, Translator>::type indexable_type;
|
||||
typedef typename geometry::point_type<indexable_type>::type point_type;
|
||||
typedef geometry::model::box<point_type> bounds_type;
|
||||
typedef index::detail::bounded_view<indexable_type, bounds_type> bounded_view_type;
|
||||
|
||||
public:
|
||||
element_axis_corner_less(Translator const& tr)
|
||||
: m_tr(tr)
|
||||
{}
|
||||
|
||||
bool operator()(Element const& e1, Element const& e2) const
|
||||
{
|
||||
bounded_view_type bounded_ind1(rtree::element_indexable(e1, m_tr));
|
||||
bounded_view_type bounded_ind2(rtree::element_indexable(e2, m_tr));
|
||||
|
||||
return geometry::get<Corner, AxisIndex>(bounded_ind1)
|
||||
< geometry::get<Corner, AxisIndex>(bounded_ind2);
|
||||
}
|
||||
|
||||
private:
|
||||
Translator const& m_tr;
|
||||
};
|
||||
|
||||
template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>
|
||||
class element_axis_corner_less<Element, Translator, box_tag, Corner, AxisIndex>
|
||||
{
|
||||
public:
|
||||
element_axis_corner_less(Translator const& tr)
|
||||
: m_tr(tr)
|
||||
{}
|
||||
|
||||
bool operator()(Element const& e1, Element const& e2) const
|
||||
{
|
||||
return geometry::get<Corner, AxisIndex>(rtree::element_indexable(e1, m_tr))
|
||||
< geometry::get<Corner, AxisIndex>(rtree::element_indexable(e2, m_tr));
|
||||
}
|
||||
|
||||
private:
|
||||
Translator const& m_tr;
|
||||
};
|
||||
|
||||
template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>
|
||||
class element_axis_corner_less<Element, Translator, point_tag, Corner, AxisIndex>
|
||||
{
|
||||
public:
|
||||
element_axis_corner_less(Translator const& tr)
|
||||
: m_tr(tr)
|
||||
{}
|
||||
|
||||
bool operator()(Element const& e1, Element const& e2) const
|
||||
{
|
||||
return geometry::get<AxisIndex>(rtree::element_indexable(e1, m_tr))
|
||||
< geometry::get<AxisIndex>(rtree::element_indexable(e2, m_tr));
|
||||
}
|
||||
|
||||
private:
|
||||
Translator const& m_tr;
|
||||
};
|
||||
|
||||
template <typename Box, size_t Corner, size_t AxisIndex>
|
||||
struct choose_split_axis_and_index_for_corner
|
||||
{
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_index,
|
||||
margin_type & sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
typedef typename Elements::value_type element_type;
|
||||
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
|
||||
typedef typename tag<indexable_type>::type indexable_tag;
|
||||
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == parameters.get_max_elements() + 1, "wrong number of elements");
|
||||
|
||||
// copy elements
|
||||
Elements elements_copy(elements); // MAY THROW, STRONG (alloc, copy)
|
||||
|
||||
size_t const index_first = parameters.get_min_elements();
|
||||
size_t const index_last = parameters.get_max_elements() - parameters.get_min_elements() + 2;
|
||||
|
||||
// sort elements
|
||||
element_axis_corner_less<element_type, Translator, indexable_tag, Corner, AxisIndex> elements_less(translator);
|
||||
std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// {
|
||||
// typename Elements::iterator f = elements_copy.begin() + index_first;
|
||||
// typename Elements::iterator l = elements_copy.begin() + index_last;
|
||||
// // NOTE: for stdlibc++ shipped with gcc 4.8.2 std::nth_element is replaced with std::sort anyway
|
||||
// index::detail::nth_element(elements_copy.begin(), f, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// index::detail::nth_element(f, l, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// std::sort(f, l, elements_less); // MAY THROW, BASIC (copy)
|
||||
// }
|
||||
|
||||
// init outputs
|
||||
choosen_index = index_first;
|
||||
sum_of_margins = 0;
|
||||
smallest_overlap = (std::numeric_limits<content_type>::max)();
|
||||
smallest_content = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
// calculate sum of margins for all distributions
|
||||
for ( size_t i = index_first ; i < index_last ; ++i )
|
||||
{
|
||||
// TODO - awulkiew: may be optimized - box of group 1 may be initialized with
|
||||
// box of min_elems number of elements and expanded for each iteration by another element
|
||||
|
||||
Box box1 = rtree::elements_box<Box>(elements_copy.begin(), elements_copy.begin() + i, translator);
|
||||
Box box2 = rtree::elements_box<Box>(elements_copy.begin() + i, elements_copy.end(), translator);
|
||||
|
||||
sum_of_margins += index::detail::comparable_margin(box1) + index::detail::comparable_margin(box2);
|
||||
|
||||
content_type ovl = index::detail::intersection_content(box1, box2);
|
||||
content_type con = index::detail::content(box1) + index::detail::content(box2);
|
||||
|
||||
// TODO - shouldn't here be < instead of <= ?
|
||||
if ( ovl < smallest_overlap || (ovl == smallest_overlap && con <= smallest_content) )
|
||||
{
|
||||
choosen_index = i;
|
||||
smallest_overlap = ovl;
|
||||
smallest_content = con;
|
||||
}
|
||||
}
|
||||
|
||||
::boost::ignore_unused(parameters);
|
||||
}
|
||||
};
|
||||
|
||||
//template <typename Box, size_t AxisIndex, typename ElementIndexableTag>
|
||||
//struct choose_split_axis_and_index_for_axis
|
||||
//{
|
||||
// BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (ElementIndexableTag));
|
||||
//};
|
||||
|
||||
template <typename Box, size_t AxisIndex, typename ElementIndexableTag>
|
||||
struct choose_split_axis_and_index_for_axis
|
||||
{
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_corner,
|
||||
size_t & choosen_index,
|
||||
margin_type & sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
size_t index1 = 0;
|
||||
margin_type som1 = 0;
|
||||
content_type ovl1 = (std::numeric_limits<content_type>::max)();
|
||||
content_type con1 = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
choose_split_axis_and_index_for_corner<Box, min_corner, AxisIndex>
|
||||
::apply(elements, index1,
|
||||
som1, ovl1, con1,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
size_t index2 = 0;
|
||||
margin_type som2 = 0;
|
||||
content_type ovl2 = (std::numeric_limits<content_type>::max)();
|
||||
content_type con2 = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
choose_split_axis_and_index_for_corner<Box, max_corner, AxisIndex>
|
||||
::apply(elements, index2,
|
||||
som2, ovl2, con2,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
sum_of_margins = som1 + som2;
|
||||
|
||||
if ( ovl1 < ovl2 || (ovl1 == ovl2 && con1 <= con2) )
|
||||
{
|
||||
choosen_corner = min_corner;
|
||||
choosen_index = index1;
|
||||
smallest_overlap = ovl1;
|
||||
smallest_content = con1;
|
||||
}
|
||||
else
|
||||
{
|
||||
choosen_corner = max_corner;
|
||||
choosen_index = index2;
|
||||
smallest_overlap = ovl2;
|
||||
smallest_content = con2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box, size_t AxisIndex>
|
||||
struct choose_split_axis_and_index_for_axis<Box, AxisIndex, point_tag>
|
||||
{
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_corner,
|
||||
size_t & choosen_index,
|
||||
margin_type & sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
choose_split_axis_and_index_for_corner<Box, min_corner, AxisIndex>
|
||||
::apply(elements, choosen_index,
|
||||
sum_of_margins, smallest_overlap, smallest_content,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
choosen_corner = min_corner;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box, size_t Dimension>
|
||||
struct choose_split_axis_and_index
|
||||
{
|
||||
BOOST_STATIC_ASSERT(0 < Dimension);
|
||||
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_axis,
|
||||
size_t & choosen_corner,
|
||||
size_t & choosen_index,
|
||||
margin_type & smallest_sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
typedef typename rtree::element_indexable_type<typename Elements::value_type, Translator>::type element_indexable_type;
|
||||
|
||||
choose_split_axis_and_index<Box, Dimension - 1>
|
||||
::apply(elements, choosen_axis, choosen_corner, choosen_index,
|
||||
smallest_sum_of_margins, smallest_overlap, smallest_content,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
margin_type sum_of_margins = 0;
|
||||
|
||||
size_t corner = min_corner;
|
||||
size_t index = 0;
|
||||
|
||||
content_type overlap_val = (std::numeric_limits<content_type>::max)();
|
||||
content_type content_val = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
choose_split_axis_and_index_for_axis<
|
||||
Box,
|
||||
Dimension - 1,
|
||||
typename tag<element_indexable_type>::type
|
||||
>::apply(elements, corner, index, sum_of_margins, overlap_val, content_val, parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
if ( sum_of_margins < smallest_sum_of_margins )
|
||||
{
|
||||
choosen_axis = Dimension - 1;
|
||||
choosen_corner = corner;
|
||||
choosen_index = index;
|
||||
smallest_sum_of_margins = sum_of_margins;
|
||||
smallest_overlap = overlap_val;
|
||||
smallest_content = content_val;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct choose_split_axis_and_index<Box, 1>
|
||||
{
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_axis,
|
||||
size_t & choosen_corner,
|
||||
size_t & choosen_index,
|
||||
margin_type & smallest_sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
typedef typename rtree::element_indexable_type<typename Elements::value_type, Translator>::type element_indexable_type;
|
||||
|
||||
choosen_axis = 0;
|
||||
|
||||
choose_split_axis_and_index_for_axis<
|
||||
Box,
|
||||
0,
|
||||
typename tag<element_indexable_type>::type
|
||||
>::apply(elements, choosen_corner, choosen_index, smallest_sum_of_margins, smallest_overlap, smallest_content, parameters, translator); // MAY THROW
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t Corner, size_t Dimension, size_t I = 0>
|
||||
struct nth_element
|
||||
{
|
||||
BOOST_STATIC_ASSERT(0 < Dimension);
|
||||
BOOST_STATIC_ASSERT(I < Dimension);
|
||||
|
||||
template <typename Elements, typename Translator>
|
||||
static inline void apply(Elements & elements, const size_t axis, const size_t index, Translator const& tr)
|
||||
{
|
||||
//BOOST_GEOMETRY_INDEX_ASSERT(axis < Dimension, "unexpected axis value");
|
||||
|
||||
if ( axis != I )
|
||||
{
|
||||
nth_element<Corner, Dimension, I + 1>::apply(elements, axis, index, tr); // MAY THROW, BASIC (copy)
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef typename Elements::value_type element_type;
|
||||
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
|
||||
typedef typename tag<indexable_type>::type indexable_tag;
|
||||
|
||||
element_axis_corner_less<element_type, Translator, indexable_tag, Corner, I> less(tr);
|
||||
index::detail::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t Corner, size_t Dimension>
|
||||
struct nth_element<Corner, Dimension, Dimension>
|
||||
{
|
||||
template <typename Elements, typename Translator>
|
||||
static inline void apply(Elements & /*elements*/, const size_t /*axis*/, const size_t /*index*/, Translator const& /*tr*/)
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace rstar
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct redistribute_elements<Value, Options, Translator, Box, Allocators, rstar_tag>
|
||||
{
|
||||
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
static const size_t dimension = geometry::dimension<Box>::value;
|
||||
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Node>
|
||||
static inline void apply(
|
||||
Node & n,
|
||||
Node & second_node,
|
||||
Box & box1,
|
||||
Box & box2,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators)
|
||||
{
|
||||
typedef typename rtree::elements_type<Node>::type elements_type;
|
||||
typedef typename elements_type::value_type element_type;
|
||||
|
||||
elements_type & elements1 = rtree::elements(n);
|
||||
elements_type & elements2 = rtree::elements(second_node);
|
||||
|
||||
// copy original elements - use in-memory storage (std::allocator)
|
||||
// TODO: move if noexcept
|
||||
typedef typename rtree::container_from_elements_type<elements_type, element_type>::type
|
||||
container_type;
|
||||
container_type elements_copy(elements1.begin(), elements1.end()); // MAY THROW, STRONG
|
||||
container_type elements_backup(elements1.begin(), elements1.end()); // MAY THROW, STRONG
|
||||
|
||||
size_t split_axis = 0;
|
||||
size_t split_corner = 0;
|
||||
size_t split_index = parameters.get_min_elements();
|
||||
margin_type smallest_sum_of_margins = (std::numeric_limits<margin_type>::max)();
|
||||
content_type smallest_overlap = (std::numeric_limits<content_type>::max)();
|
||||
content_type smallest_content = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
// NOTE: this function internally copies passed elements
|
||||
// why not pass mutable elements and use the same container for all axes/corners
|
||||
// and again, the same below calling partial_sort/nth_element
|
||||
// It would be even possible to not re-sort/find nth_element if the axis/corner
|
||||
// was found for the last sorting - last combination of axis/corner
|
||||
rstar::choose_split_axis_and_index<Box, dimension>
|
||||
::apply(elements_copy,
|
||||
split_axis, split_corner, split_index,
|
||||
smallest_sum_of_margins, smallest_overlap, smallest_content,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
// TODO: awulkiew - get rid of following static_casts?
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(split_axis < dimension, "unexpected value");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(split_corner == static_cast<size_t>(min_corner) || split_corner == static_cast<size_t>(max_corner), "unexpected value");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= split_index && split_index <= parameters.get_max_elements() - parameters.get_min_elements() + 1, "unexpected value");
|
||||
|
||||
// TODO: consider using nth_element
|
||||
if ( split_corner == static_cast<size_t>(min_corner) )
|
||||
{
|
||||
rstar::nth_element<min_corner, dimension>
|
||||
::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
|
||||
}
|
||||
else
|
||||
{
|
||||
rstar::nth_element<max_corner, dimension>
|
||||
::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
|
||||
}
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
// copy elements to nodes
|
||||
elements1.assign(elements_copy.begin(), elements_copy.begin() + split_index); // MAY THROW, BASIC
|
||||
elements2.assign(elements_copy.begin() + split_index, elements_copy.end()); // MAY THROW, BASIC
|
||||
|
||||
// calculate boxes
|
||||
box1 = rtree::elements_box<Box>(elements1.begin(), elements1.end(), translator);
|
||||
box2 = rtree::elements_box<Box>(elements2.begin(), elements2.end(), translator);
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
//elements_copy.clear();
|
||||
elements1.clear();
|
||||
elements2.clear();
|
||||
|
||||
rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);
|
||||
//elements_backup.clear();
|
||||
|
||||
BOOST_RETHROW // RETHROW, BASIC
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
|
||||
@@ -0,0 +1,18 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree R*-tree algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/rstar/insert.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP
|
||||
Reference in New Issue
Block a user