index copied from branches to trunk

[SVN r83638]
This commit is contained in:
Adam Wulkiewicz
2013-03-30 01:20:27 +00:00
67 changed files with 12919 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
// Boost.Geometry Index
//
// Query range adaptor
//
// 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_ADAPTORS_QUERY_HPP
#define BOOST_GEOMETRY_INDEX_ADAPTORS_QUERY_HPP
/*!
\defgroup adaptors Adaptors (boost::geometry::index::adaptors::)
*/
namespace boost { namespace geometry { namespace index {
namespace adaptors {
namespace detail {
template <typename Index>
class query_range
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_INDEX,
(query_range));
typedef int* iterator;
typedef const int* const_iterator;
template <typename Predicates>
inline query_range(
Index const&,
Predicates const&)
{}
inline iterator begin() { return 0; }
inline iterator end() { return 0; }
inline const_iterator begin() const { return 0; }
inline const_iterator end() const { return 0; }
};
// TODO: awulkiew - consider removing reference from predicates
template<typename Predicates>
struct query
{
inline explicit query(Predicates const& pred)
: predicates(pred)
{}
Predicates const& predicates;
};
template<typename Index, typename Predicates>
index::adaptors::detail::query_range<Index>
operator|(
Index const& si,
index::adaptors::detail::query<Predicates> const& f)
{
return index::adaptors::detail::query_range<Index>(si, f.predicates);
}
} // namespace detail
/*!
\brief The query index adaptor generator.
\ingroup adaptors
\param pred Predicates.
*/
template <typename Predicates>
detail::query<Predicates>
queried(Predicates const& pred)
{
return detail::query<Predicates>(pred);
}
} // namespace adaptors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_ADAPTORS_QUERY_HPP

View File

@@ -0,0 +1,77 @@
// Boost.Geometry Index
//
// squared distance between point and centroid of the box or point
//
// 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_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
struct comparable_distance_centroid_tag {};
template <
typename Point,
typename PointIndexable,
size_t N>
struct sum_for_indexable<Point, PointIndexable, point_tag, comparable_distance_centroid_tag, N>
{
typedef typename geometry::default_distance_result<Point, PointIndexable>::type result_type;
inline static result_type apply(Point const& pt, PointIndexable const& i)
{
return geometry::comparable_distance(pt, i);
}
};
template <
typename Point,
typename BoxIndexable,
size_t DimensionIndex>
struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_distance_centroid_tag, DimensionIndex>
{
typedef typename geometry::default_distance_result<Point, BoxIndexable>::type result_type;
inline static result_type apply(Point const& pt, BoxIndexable const& i)
{
typedef typename index::detail::traits::coordinate_type<Point>::type point_coord_t;
typedef typename index::detail::traits::coordinate_type<BoxIndexable>::type indexable_coord_t;
point_coord_t pt_c = geometry::get<DimensionIndex>(pt);
indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);
indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);
indexable_coord_t ind_c_avg = ind_c_min + (ind_c_max - ind_c_min) / 2;
// TODO: awulkiew - is (ind_c_min + ind_c_max) / 2 safe?
result_type diff = detail::diff_abs(ind_c_avg, pt_c);
return diff * diff;
}
};
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
comparable_distance_centroid(Point const& pt, Indexable const& i)
{
return detail::sum_for_indexable<
Point,
Indexable,
typename index::detail::traits::tag<Indexable>::type,
detail::comparable_distance_centroid_tag,
index::detail::traits::dimension<Indexable>::value
>::apply(pt, i);
}
}}}} // namespace boost::geometry::index::detail
#endif // #define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP

View File

@@ -0,0 +1,66 @@
// Boost.Geometry Index
//
// squared distance between point and furthest point of the box or point
//
// 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_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
// minmaxdist component
struct comparable_distance_far_tag {};
template <
typename Point,
typename BoxIndexable,
size_t DimensionIndex>
struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_distance_far_tag, DimensionIndex>
{
typedef typename geometry::default_distance_result<Point, BoxIndexable>::type result_type;
inline static result_type apply(Point const& pt, BoxIndexable const& i)
{
typedef typename index::detail::traits::coordinate_type<Point>::type point_coord_t;
typedef typename index::detail::traits::coordinate_type<BoxIndexable>::type indexable_coord_t;
point_coord_t pt_c = geometry::get<DimensionIndex>(pt);
indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);
indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);
result_type further_diff = 0;
if ( (ind_c_min + ind_c_max) / 2 <= pt_c )
further_diff = pt_c - ind_c_min;
else
further_diff = detail::diff_abs(pt_c, ind_c_max); // unsigned values protection
return further_diff * further_diff;
}
};
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
comparable_distance_far(Point const& pt, Indexable const& i)
{
return detail::sum_for_indexable<
Point,
Indexable,
typename index::detail::traits::tag<Indexable>::type,
detail::comparable_distance_far_tag,
index::detail::traits::dimension<Indexable>::value
>::apply(pt, i);
}
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP

View File

@@ -0,0 +1,77 @@
// Boost.Geometry Index
//
// squared distance between point and nearest point of the box or point
//
// 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_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
struct comparable_distance_near_tag {};
template <
typename Point,
typename PointIndexable,
size_t N>
struct sum_for_indexable<Point, PointIndexable, point_tag, comparable_distance_near_tag, N>
{
typedef typename geometry::default_distance_result<Point, PointIndexable>::type result_type;
inline static result_type apply(Point const& pt, PointIndexable const& i)
{
return geometry::comparable_distance(pt, i);
}
};
template <
typename Point,
typename BoxIndexable,
size_t DimensionIndex>
struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_distance_near_tag, DimensionIndex>
{
typedef typename geometry::default_distance_result<Point, BoxIndexable>::type result_type;
inline static result_type apply(Point const& pt, BoxIndexable const& i)
{
typedef typename index::detail::traits::coordinate_type<Point>::type point_coord_t;
typedef typename index::detail::traits::coordinate_type<BoxIndexable>::type indexable_coord_t;
point_coord_t pt_c = geometry::get<DimensionIndex>(pt);
indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);
indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);
result_type diff = 0;
if ( pt_c < ind_c_min )
diff = ind_c_min - pt_c;
else if ( ind_c_max < pt_c )
diff = pt_c - ind_c_max;
return diff * diff;
}
};
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
comparable_distance_near(Point const& pt, Indexable const& i)
{
return detail::sum_for_indexable<
Point,
Indexable,
typename index::detail::traits::tag<Indexable>::type,
detail::comparable_distance_near_tag,
index::detail::traits::dimension<Indexable>::value
>::apply(pt, i);
}
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP

View File

@@ -0,0 +1,85 @@
// Boost.Geometry Index
//
// n-dimensional box's content (hypervolume) - 2d area, 3d volume, ...
//
// 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_ALGORITHMS_CONTENT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP
namespace boost { namespace geometry { namespace index { namespace detail {
template <typename Indexable>
struct default_content_result
{
typedef typename select_most_precise<
typename detail::traits::coordinate_type<Indexable>::type,
long double
>::type type;
};
namespace dispatch {
template <typename Box, size_t CurrentDimension>
struct content_for_each_dimension
{
BOOST_STATIC_ASSERT(0 < CurrentDimension);
BOOST_STATIC_ASSERT(CurrentDimension <= traits::dimension<Box>::value);
static inline typename detail::default_content_result<Box>::type apply(Box const& b)
{
return content_for_each_dimension<Box, CurrentDimension - 1>::apply(b) *
( detail::get<max_corner, CurrentDimension - 1>(b) - detail::get<min_corner, CurrentDimension - 1>(b) );
}
};
template <typename Box>
struct content_for_each_dimension<Box, 1>
{
static inline typename detail::default_content_result<Box>::type apply(Box const& b)
{
return detail::get<max_corner, 0>(b) - detail::get<min_corner, 0>(b);
}
};
template <typename Indexable, typename Tag>
struct content
{
// TODO: awulkiew - static assert?
};
template <typename Indexable>
struct content<Indexable, point_tag>
{
static typename detail::default_content_result<Indexable>::type apply(Indexable const&)
{
return 0;
}
};
template <typename Indexable>
struct content<Indexable, box_tag>
{
static typename default_content_result<Indexable>::type apply(Indexable const& b)
{
return dispatch::content_for_each_dimension<Indexable, detail::traits::dimension<Indexable>::value>::apply(b);
}
};
} // namespace dispatch
template <typename Indexable>
typename default_content_result<Indexable>::type content(Indexable const& b)
{
return dispatch::content<Indexable,
typename detail::traits::tag<Indexable>::type
>::apply(b);
}
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP

View File

@@ -0,0 +1,24 @@
// Boost.Geometry Index
//
// Abs of difference
//
// 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_ALGORITHMS_DIFF_ABS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP
namespace boost { namespace geometry { namespace index { namespace detail {
template <typename T>
inline T diff_abs(T const& v1, T const& v2)
{
return v1 < v2 ? v2 - v1 : v1 - v2;
}
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP

View File

@@ -0,0 +1,36 @@
// Boost.Geometry Index
//
// boxes union/intersection area/volume
//
// 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_ALGORITHMS_INTERSECTION_CONTENT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
/**
* \brief Compute the area of the intersection of b1 and b2
*/
template <typename Box>
inline typename default_content_result<Box>::type intersection_content(Box const& box1, Box const& box2)
{
if ( geometry::intersects(box1, box2) )
{
Box box_intersection;
geometry::intersection(box1, box2, box_intersection);
return detail::content(box_intersection);
}
return 0;
}
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP

View File

@@ -0,0 +1,79 @@
// Boost.Geometry Index
//
// n-dimensional box's / point validity check
//
// 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_ALGORITHMS_IS_VALID_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_IS_VALID_HPP
namespace boost { namespace geometry { namespace index { namespace detail {
namespace dispatch {
template <typename Box, size_t Dimension>
struct is_valid_box
{
BOOST_MPL_ASSERT_MSG(
(0 < Dimension && Dimension <= detail::traits::dimension<Box>::value),
INVALID_DIMENSION_PARAMETER,
(is_valid_box));
static inline bool apply(Box const& b)
{
return is_valid_box<Box, Dimension - 1>::apply(b) &&
( detail::get<min_corner, Dimension - 1>(b) <= detail::get<max_corner, Dimension - 1>(b) );
}
};
template <typename Box>
struct is_valid_box<Box, 1>
{
static inline bool apply(Box const& b)
{
return detail::get<min_corner, 0>(b) <= detail::get<max_corner, 0>(b);
}
};
template <typename Indexable, typename Tag>
struct is_valid
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_INDEXABLE,
(is_valid));
};
template <typename Indexable>
struct is_valid<Indexable, point_tag>
{
static inline bool apply(Indexable const&)
{
return true;
}
};
template <typename Indexable>
struct is_valid<Indexable, box_tag>
{
static inline bool apply(Indexable const& b)
{
return dispatch::is_valid_box<Indexable, detail::traits::dimension<Indexable>::value>::apply(b);
}
};
} // namespace dispatch
template <typename Indexable>
inline bool is_valid(Indexable const& b)
{
return dispatch::is_valid<Indexable, typename detail::traits::tag<Indexable>::type>::apply(b);
}
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_DETAIL_INDEX_ALGORITHMS_IS_VALID_HPP

View File

@@ -0,0 +1,128 @@
// Boost.Geometry Index
//
// n-dimensional box's margin value (hypersurface), 2d perimeter, 3d surface, etc...
//
// 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_ALGORITHMS_MARGIN_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
namespace boost { namespace geometry { namespace index { namespace detail {
template <typename Box>
struct default_margin_result
{
typedef typename select_most_precise<
typename coordinate_type<Box>::type,
long double
>::type type;
};
//template <typename Box, size_t CurrentDimension, size_t EdgeDimension>
//struct margin_for_each_edge
//{
// BOOST_STATIC_ASSERT(0 < CurrentDimension);
// BOOST_STATIC_ASSERT(0 < EdgeDimension);
//
// static inline typename default_margin_result<Box>::type apply(Box const& b)
// {
// return margin_for_each_edge<Box, CurrentDimension, EdgeDimension - 1>::apply(b) *
// ( geometry::get<max_corner, EdgeDimension - 1>(b) - geometry::get<min_corner, EdgeDimension - 1>(b) );
// }
//};
//
//template <typename Box, size_t CurrentDimension>
//struct margin_for_each_edge<Box, CurrentDimension, CurrentDimension>
//{
// BOOST_STATIC_ASSERT(0 < CurrentDimension);
//
// static inline typename default_margin_result<Box>::type apply(Box const& b)
// {
// return margin_for_each_edge<Box, CurrentDimension, CurrentDimension - 1>::apply(b);
// }
//};
//
//template <typename Box, size_t CurrentDimension>
//struct margin_for_each_edge<Box, CurrentDimension, 1>
//{
// BOOST_STATIC_ASSERT(0 < CurrentDimension);
//
// static inline typename default_margin_result<Box>::type apply(Box const& b)
// {
// return geometry::get<max_corner, 0>(b) - geometry::get<min_corner, 0>(b);
// }
//};
//
//template <typename Box>
//struct margin_for_each_edge<Box, 1, 1>
//{
// static inline typename default_margin_result<Box>::type apply(Box const& /*b*/)
// {
// return 1;
// }
//};
//
//template <typename Box, size_t CurrentDimension>
//struct margin_for_each_dimension
//{
// BOOST_STATIC_ASSERT(0 < CurrentDimension);
// BOOST_STATIC_ASSERT(CurrentDimension <= detail::traits::dimension<Box>::value);
//
// static inline typename default_margin_result<Box>::type apply(Box const& b)
// {
// return margin_for_each_dimension<Box, CurrentDimension - 1>::apply(b) +
// margin_for_each_edge<Box, CurrentDimension, detail::traits::dimension<Box>::value>::apply(b);
// }
//};
//
//template <typename Box>
//struct margin_for_each_dimension<Box, 1>
//{
// static inline typename default_margin_result<Box>::type apply(Box const& b)
// {
// return margin_for_each_edge<Box, 1, detail::traits::dimension<Box>::value>::apply(b);
// }
//};
template <typename Box, size_t CurrentDimension>
struct simple_margin_for_each_dimension
{
BOOST_STATIC_ASSERT(0 < CurrentDimension);
BOOST_STATIC_ASSERT(CurrentDimension <= detail::traits::dimension<Box>::value);
static inline typename default_margin_result<Box>::type apply(Box const& b)
{
return simple_margin_for_each_dimension<Box, CurrentDimension - 1>::apply(b) +
geometry::get<max_corner, CurrentDimension - 1>(b) - geometry::get<min_corner, CurrentDimension - 1>(b);
}
};
template <typename Box>
struct simple_margin_for_each_dimension<Box, 1>
{
static inline typename default_margin_result<Box>::type apply(Box const& b)
{
return geometry::get<max_corner, 0>(b) - geometry::get<min_corner, 0>(b);
}
};
template <typename Box>
typename default_margin_result<Box>::type comparable_margin(Box const& b)
{
//return detail::margin_for_each_dimension<Box, detail::traits::dimension<Box>::value>::apply(b);
return detail::simple_margin_for_each_dimension<Box, detail::traits::dimension<Box>::value>::apply(b);
}
//template <typename Box>
//typename default_margin_result<Box>::type margin(Box const& b)
//{
// return 2 * detail::margin_for_each_dimension<Box, detail::traits::dimension<Box>::value>::apply(b);
//}
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP

View File

@@ -0,0 +1,119 @@
// Boost.Geometry Index
//
// minmaxdist used in R-tree k nearest neighbors query
//
// 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_ALGORITHMS_MINMAXDIST_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
#include <boost/geometry/index/detail/algorithms/smallest_for_indexable.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
struct minmaxdist_tag {};
template <
typename Point,
typename BoxIndexable,
size_t DimensionIndex>
struct smallest_for_indexable_dimension<Point, BoxIndexable, box_tag, minmaxdist_tag, DimensionIndex>
{
typedef typename geometry::default_distance_result<Point, BoxIndexable>::type result_type;
inline static result_type apply(Point const& pt, BoxIndexable const& i, result_type const& maxd)
{
typedef typename index::traits::coordinate_type<Point>::type point_coord_t;
typedef typename index::traits::coordinate_type<BoxIndexable>::type indexable_coord_t;
point_coord_t pt_c = geometry::get<DimensionIndex>(pt);
indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);
indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);
indexable_coord_t ind_c_avg = ind_c_min + (ind_c_max - ind_c_min) / 2;
// TODO: awulkiew - is (ind_c_min + ind_c_max) / 2 safe?
// TODO: awulkiew - optimize! don't calculate 2x pt_c <= ind_c_avg
// take particular case pt_c == ind_c_avg into account
result_type closer_comp = 0;
if ( pt_c <= ind_c_avg )
closer_comp = detail::diff_abs(pt_c, ind_c_min); // unsigned values protection
else
closer_comp = ind_c_max - pt_c;
result_type further_comp = 0;
if ( ind_c_avg <= pt_c )
further_comp = pt_c - ind_c_min;
else
further_comp = detail::diff_abs(pt_c, ind_c_max); // unsigned values protection
return (maxd + closer_comp * closer_comp) - further_comp * further_comp;
}
};
template <typename Point, typename Indexable, typename IndexableTag>
struct minmaxdist_impl
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,
(minmaxdist_impl));
};
template <typename Point, typename Indexable>
struct minmaxdist_impl<Point, Indexable, point_tag>
{
typedef typename geometry::default_distance_result<Point, Indexable>::type result_type;
inline static result_type apply(Point const& pt, Indexable const& i)
{
return geometry::comparable_distance(pt, i);
}
};
template <typename Point, typename Indexable>
struct minmaxdist_impl<Point, Indexable, box_tag>
{
typedef typename geometry::default_distance_result<Point, Indexable>::type result_type;
inline static result_type apply(Point const& pt, Indexable const& i)
{
result_type maxd = geometry::comparable_distance(pt, i);
return smallest_for_indexable<
Point,
Indexable,
box_tag,
minmaxdist_tag,
index::traits::dimension<Indexable>::value
>::apply(pt, i, maxd);
}
};
/**
* This is comparable distace.
*/
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
minmaxdist(Point const& pt, Indexable const& i)
{
return detail::minmaxdist_impl<
Point,
Indexable,
typename index::traits::tag<Indexable>::type
>::apply(pt, i);
}
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP

View File

@@ -0,0 +1,80 @@
// Boost.Geometry Index
//
// Get smallest value calculated for indexable's dimensions, used in R-tree k nearest neighbors query
//
// 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_ALGORITHMS_SMALLEST_FOR_INDEXABLE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SMALLEST_FOR_INDEXABLE_HPP
namespace boost { namespace geometry { namespace index { namespace detail {
template <
typename Geometry,
typename Indexable,
typename IndexableTag,
typename AlgoTag,
size_t DimensionIndex>
struct smallest_for_indexable_dimension
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,
(smallest_for_indexable_dimension));
};
template <
typename Geometry,
typename Indexable,
typename IndexableTag,
typename AlgoTag,
size_t N>
struct smallest_for_indexable
{
typedef typename smallest_for_indexable_dimension<
Geometry, Indexable, IndexableTag, AlgoTag, N - 1
>::result_type result_type;
template <typename Data>
inline static result_type apply(Geometry const& g, Indexable const& i, Data const& data)
{
result_type r1 = smallest_for_indexable<
Geometry, Indexable, IndexableTag, AlgoTag, N - 1
>::apply(g, i, data);
result_type r2 = smallest_for_indexable_dimension<
Geometry, Indexable, IndexableTag, AlgoTag, N - 1
>::apply(g, i, data);
return r1 < r2 ? r1 : r2;
}
};
template <
typename Geometry,
typename Indexable,
typename IndexableTag,
typename AlgoTag>
struct smallest_for_indexable<Geometry, Indexable, IndexableTag, AlgoTag, 1>
{
typedef typename smallest_for_indexable_dimension<
Geometry, Indexable, IndexableTag, AlgoTag, 0
>::result_type result_type;
template <typename Data>
inline static result_type apply(Geometry const& g, Indexable const& i, Data const& data)
{
return
smallest_for_indexable_dimension<
Geometry, Indexable, IndexableTag, AlgoTag, 0
>::apply(g, i, data);
}
};
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SMALLEST_FOR_INDEXABLE_HPP

View File

@@ -0,0 +1,76 @@
// Boost.Geometry Index
//
// Sum values calculated for indexable's dimensions, used e.g. in R-tree k nearest neighbors query
//
// 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_ALGORITHMS_SUM_FOR_INDEXABLE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SUM_FOR_INDEXABLE_HPP
namespace boost { namespace geometry { namespace index { namespace detail {
template <
typename Geometry,
typename Indexable,
typename IndexableTag,
typename AlgoTag,
size_t DimensionIndex>
struct sum_for_indexable_dimension
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,
(sum_for_indexable_dimension));
};
template <
typename Geometry,
typename Indexable,
typename IndexableTag,
typename AlgoTag,
size_t N>
struct sum_for_indexable
{
typedef typename sum_for_indexable_dimension<
Geometry, Indexable, IndexableTag, AlgoTag, N - 1
>::result_type result_type;
inline static result_type apply(Geometry const& g, Indexable const& i)
{
return
sum_for_indexable<
Geometry, Indexable, IndexableTag, AlgoTag, N - 1
>::apply(g, i) +
sum_for_indexable_dimension<
Geometry, Indexable, IndexableTag, AlgoTag, N - 1
>::apply(g, i);
}
};
template <
typename Geometry,
typename Indexable,
typename IndexableTag,
typename AlgoTag>
struct sum_for_indexable<Geometry, Indexable, IndexableTag, AlgoTag, 1>
{
typedef typename sum_for_indexable_dimension<
Geometry, Indexable, IndexableTag, AlgoTag, 0
>::result_type result_type;
inline static result_type apply(Geometry const& g, Indexable const& i)
{
return
sum_for_indexable_dimension<
Geometry, Indexable, IndexableTag, AlgoTag, 0
>::apply(g, i);
}
};
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SUM_FOR_INDEXABLE_HPP

View File

@@ -0,0 +1,33 @@
// Boost.Geometry Index
//
// boxes union/sum area/volume
//
// Copyright (c) 2008 Federico J. Fernandez.
// 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_ALGORITHMS_UNION_CONTENT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_UNION_CONTENT_HPP
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
/**
* \brief Compute the area of the union of b1 and b2
*/
template <typename Box, typename Geometry>
inline typename default_content_result<Box>::type union_content(Box const& b, Geometry const& g)
{
Box expanded_box(b);
geometry::expand(expanded_box, g);
return detail::content(expanded_box);
}
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_UNION_CONTENT_HPP

View File

@@ -0,0 +1,27 @@
// Boost.Geometry Index
//
// 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)
#include <boost/assert.hpp>
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
#define BOOST_GEOMETRY_INDEX_ASSERT(CONDITION, TEXT_MSG) \
BOOST_ASSERT_MSG(CONDITION, TEXT_MSG)
#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
#define BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(PARAM)
#else
#define BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(PARAM) PARAM
#endif
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP

View File

@@ -0,0 +1,24 @@
// Boost.Geometry Index
//
// 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)
#include <boost/config.hpp>
#ifdef BOOST_MSVC
#define BOOST_GEOMETRY_INDEX_DETAIL_USE_PARAM(A) (void)A;
#pragma warning (push)
#pragma warning (disable : 4512) // assignment operator could not be generated
#pragma warning (disable : 4127) // conditional expression is constant
#else //BOOST_MSVC
#define BOOST_GEOMETRY_INDEX_DETAIL_USE_PARAM(A)
#endif //BOOST_MSVC

View File

@@ -0,0 +1,12 @@
// Boost.Geometry Index
//
// 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)
#if defined BOOST_MSVC
#pragma warning (pop)
#endif

View File

@@ -0,0 +1,866 @@
// Boost.Geometry Index
//
// Spatial index distance predicates, calculators and checkers
// used in nearest query - specialized for envelopes
//
// 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_DISTANCE_PREDICATES_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_DISTANCE_PREDICATES_HPP
#include <boost/geometry/index/detail/algorithms/comparable_distance_near.hpp>
#include <boost/geometry/index/detail/algorithms/comparable_distance_far.hpp>
#include <boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp>
#include <boost/geometry/index/detail/tuples.hpp>
#include <boost/geometry/index/detail/tags.hpp>
// TODO - optimization
// For Boxes and Points all types of distances may be calculated
// - near, far and centroid. For points those are the same distance
// calculate them for Boxes only!
// for Points calculate only 1 distance
namespace boost { namespace geometry { namespace index { namespace detail {
// ------------------------------------------------------------------ //
// relations
// ------------------------------------------------------------------ //
template <typename T>
struct to_nearest
{
to_nearest(T const& v) : value(v) {}
T value;
};
template <typename T>
struct to_centroid
{
to_centroid(T const& v) : value(v) {}
T value;
};
template <typename T>
struct to_furthest
{
to_furthest(T const& v) : value(v) {}
T value;
};
// tags
struct to_nearest_tag {};
struct to_centroid_tag {};
struct to_furthest_tag {};
// ------------------------------------------------------------------ //
// relation traits and access
// ------------------------------------------------------------------ //
template <typename T>
struct relation
{
typedef T value_type;
typedef to_nearest_tag tag;
static inline T const& value(T const& v) { return v; }
static inline T & value(T & v) { return v; }
};
template <typename T>
struct relation< to_nearest<T> >
{
typedef T value_type;
typedef to_nearest_tag tag;
static inline T const& value(to_nearest<T> const& r) { return r.value; }
static inline T & value(to_nearest<T> & r) { return r.value; }
};
template <typename T>
struct relation< to_centroid<T> >
{
typedef T value_type;
typedef to_centroid_tag tag;
static inline T const& value(to_centroid<T> const& r) { return r.value; }
static inline T & value(to_centroid<T> & r) { return r.value; }
};
template <typename T>
struct relation< to_furthest<T> >
{
typedef T value_type;
typedef to_furthest_tag tag;
static inline T const& value(to_furthest<T> const& r) { return r.value; }
static inline T & value(to_furthest<T> & r) { return r.value; }
};
// ------------------------------------------------------------------ //
// distance predicates
// ------------------------------------------------------------------ //
//template <typename PointRelation>
//struct unbounded
// : nonassignable
//{
// inline explicit unbounded(PointRelation const& pr)
// : point_relation(pr)
// {}
//
// PointRelation point_relation;
//};
//
//template <typename PointRelation, typename MinRelation>
//struct min_bounded
// : nonassignable
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, point_type>::type distance_type;
//
// inline min_bounded(PointRelation const& pr, MinRelation const& min_rel)
// : point_relation(pr)
// , comparable_min(
// relation<MinRelation>::value(min_rel) *
// relation<MinRelation>::value(min_rel) )
// {}
//
// PointRelation point_relation;
// distance_type comparable_min;
//};
//
//template <typename PointRelation, typename MaxRelation>
//struct max_bounded
// : nonassignable
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, point_type>::type distance_type;
//
// inline max_bounded(PointRelation const& pr, MaxRelation const& max_rel)
// : point_relation(pr)
// , comparable_max(
// relation<MaxRelation>::value(max_rel) *
// relation<MaxRelation>::value(max_rel) )
// {}
//
// PointRelation point_relation;
// distance_type comparable_max;
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation>
//struct bounded
// : nonassignable
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, point_type>::type distance_type;
//
// inline bounded(PointRelation const& pr, MinRelation const& min_rel, MaxRelation const& max_rel)
// : point_relation(pr)
// , comparable_min(
// relation<MinRelation>::value(min_rel) *
// relation<MinRelation>::value(min_rel) )
// , comparable_max(
// relation<MaxRelation>::value(max_rel) *
// relation<MaxRelation>::value(max_rel) )
// {}
//
// PointRelation point_relation;
// distance_type comparable_min;
// distance_type comparable_max;
//};
// ------------------------------------------------------------------ //
// point_relation trait
// ------------------------------------------------------------------ //
template <typename PointRelation>
struct point_relation
{
typedef PointRelation type;
};
//template <typename PointRelation>
//struct point_relation< detail::unbounded<PointRelation> >
//{
// typedef PointRelation type;
//};
//
//template <typename PointRelation, typename MinRelation>
//struct point_relation< detail::min_bounded<PointRelation, MinRelation> >
//{
// typedef PointRelation type;
//};
//
//template <typename PointRelation, typename MaxRelation>
//struct point_relation< detail::max_bounded<PointRelation, MaxRelation> >
//{
// typedef PointRelation type;
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation>
//struct point_relation< detail::bounded<PointRelation, MinRelation, MaxRelation> >
//{
// typedef PointRelation type;
//};
// ------------------------------------------------------------------ //
// helpers
// ------------------------------------------------------------------ //
// algorithms
// cdist
template <typename T, typename Tag>
struct cdist
{
T value;
};
// cdist_merge
template <typename CDistTuple, typename CDist>
struct cdist_merge
{
typedef typename detail::tuples::add_unique<
CDistTuple,
CDist
>::type type;
};
template <typename T, typename Tag, typename OtherTag>
struct cdist_merge<
cdist<T, Tag>,
cdist<T, OtherTag> >
{
typedef boost::tuple<
cdist<T, Tag>,
cdist<T, OtherTag>
> type;
};
template <typename T, typename Tag>
struct cdist_merge<
cdist<T, Tag>,
cdist<T, Tag> >
{
typedef cdist<T, Tag> type;
};
// cdist_value_type
template <typename CDistTuple>
struct cdist_value
{
typedef typename cdist_value<
typename boost::tuples::element<0, CDistTuple>::type
>::type type;
template <typename Tag>
static inline type & get(CDistTuple & cdtup)
{
return boost::get<
tuples::find_index<
CDistTuple,
cdist<type, Tag>
>::value
>(cdtup).value;
}
template <typename Tag>
static inline type const& get(CDistTuple const& cdtup)
{
return boost::get<
tuples::find_index<
CDistTuple,
cdist<type, Tag>
>::value
>(cdtup).value;
}
};
template <typename T, typename Tag>
struct cdist_value<
cdist<T, Tag>
>
{
typedef T type;
template <typename Tag2>
static inline type & get(cdist<T, Tag> & cd)
{
BOOST_MPL_ASSERT_MSG(
(boost::is_same< cdist<T, Tag2>, cdist<T, Tag> >::value),
TAGS_DO_NOT_MATCH,
(cdist_value));
return cd.value;
}
template <typename Tag2>
static inline type const& get(cdist<T, Tag> const& cd)
{
BOOST_MPL_ASSERT_MSG(
(boost::is_same< cdist<T, Tag2>, cdist<T, Tag> >::value),
TAGS_DO_NOT_MATCH,
(cdist_value));
return cd.value;
}
};
// distances_calc_impl_rel
template <typename RelDist>
struct distances_calc_impl_rel
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_RELATION,
(distances_calc_impl_rel));
};
template <typename T>
struct distances_calc_impl_rel<
cdist<T, detail::to_nearest_tag>
>
{
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
static inline apply(Point const& p, Indexable const& i)
{
return index::detail::comparable_distance_near(p, i);
}
};
template <typename T>
struct distances_calc_impl_rel<
cdist<T, detail::to_centroid_tag>
>
{
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
static inline apply(Point const& p, Indexable const& i)
{
return index::detail::comparable_distance_centroid(p, i);
}
};
template <typename T>
struct distances_calc_impl_rel<
cdist<T, detail::to_furthest_tag>
>
{
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
static inline apply(Point const& p, Indexable const& i)
{
return index::detail::comparable_distance_far(p, i);
}
};
// distances_calc_impl_tuple
template <typename Distances, typename Point, typename Indexable, unsigned N>
struct distances_calc_impl_tuple
{
// TODO MPL ASSERT 0 < N
static inline void apply(Distances & d, Point const& p, Indexable const&i)
{
boost::get<N - 1>(d).value =
distances_calc_impl_rel<
typename boost::tuples::element<N - 1, Distances>::type
>::apply(p, i);
distances_calc_impl_tuple<
Distances,
Point,
Indexable,
N - 1
>::apply(d, p, i);
}
};
template <typename Distances, typename Point, typename Indexable>
struct distances_calc_impl_tuple<Distances, Point, Indexable, 1>
{
static inline void apply(Distances & d, Point const& p, Indexable const&i)
{
boost::get<0>(d).value =
distances_calc_impl_rel<
typename boost::tuples::element<0, Distances>::type
>::apply(p, i);
}
};
// distances_calc_impl
template <typename Distances, typename Point, typename Indexable>
struct distances_calc_impl
{
static inline void apply(Distances & d, Point const& p, Indexable const&i)
{
distances_calc_impl_tuple<
Distances,
Point,
Indexable,
boost::tuples::length<Distances>::value
>::apply(d, p, i);
}
};
template <typename T, typename Tag, typename Point, typename Indexable>
struct distances_calc_impl<
cdist<T, Tag>,
Point,
Indexable
>
{
static inline void apply(cdist<T, Tag> & d, Point const& p, Indexable const&i)
{
d.value = distances_calc_impl_rel<
cdist<T, Tag>
>::apply(p, i);
}
};
// ------------------------------------------------------------------ //
// distance_calc and distances_predicates_check
// ------------------------------------------------------------------ //
template <typename PointRelation, typename Indexable, typename Tag>
struct distances_calc
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TAG,
(distances_calc));
};
template <typename PointRelation, typename Indexable, typename Tag>
struct distances_predicates_check
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TAG,
(distances_predicates_check));
};
// ------------------------------------------------------------------ //
// distance_calc for value_tag
// ------------------------------------------------------------------ //
template <typename PointRelation, typename Indexable>
struct distances_calc<PointRelation, Indexable, value_tag>
{
typedef typename detail::relation<PointRelation>::value_type point_type;
typedef typename detail::relation<PointRelation>::tag point_relation_tag;
typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
typedef detail::cdist<distance_type, point_relation_tag> result_type;
static inline result_type apply(PointRelation const& p, Indexable const& i)
{
result_type res;
distances_calc_impl<result_type, point_type, Indexable>
::apply(res, relation<PointRelation>::value(p), i);
return res;
}
};
//template <typename PointRelation, typename Indexable>
//struct distances_calc<
// detail::unbounded<PointRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename detail::relation<PointRelation>::tag point_relation_tag;
// typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
//
// typedef detail::cdist<distance_type, point_relation_tag> result_type;
//
// static inline result_type apply(detail::unbounded<PointRelation> const& pp, Indexable const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Indexable>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename Indexable>
//struct distances_calc<
// detail::min_bounded<PointRelation, MinRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename detail::relation<PointRelation>::tag point_relation_tag;
// typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
// typedef typename detail::relation<MinRelation>::tag min_relation_tag;
//
// typedef typename detail::cdist_merge<
// cdist<distance_type, point_relation_tag>,
// cdist<distance_type, min_relation_tag>
// >::type result_type;
//
// static inline result_type apply(detail::min_bounded<PointRelation, MinRelation> const& pp, Indexable const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Indexable>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MaxRelation, typename Indexable>
//struct distances_calc<
// detail::max_bounded<PointRelation, MaxRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename detail::relation<PointRelation>::tag point_relation_tag;
// typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
// typedef typename detail::relation<MaxRelation>::tag max_relation_tag;
//
// typedef typename detail::cdist_merge<
// cdist<distance_type, point_relation_tag>,
// cdist<distance_type, max_relation_tag>
// >::type result_type;
//
// static inline result_type apply(detail::max_bounded<PointRelation, MaxRelation> const& pp, Indexable const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Indexable>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation, typename Indexable>
//struct distances_calc<
// detail::bounded<PointRelation, MinRelation, MaxRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename detail::relation<PointRelation>::tag point_relation_tag;
// typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
// typedef typename detail::relation<MinRelation>::tag min_relation_tag;
// typedef typename detail::relation<MaxRelation>::tag max_relation_tag;
//
// typedef typename detail::cdist_merge<
// typename detail::cdist_merge<
// cdist<distance_type, point_relation_tag>,
// cdist<distance_type, min_relation_tag>
// >::type,
// cdist<distance_type, max_relation_tag>
// >::type result_type;
//
// static inline result_type apply(
// detail::bounded<PointRelation, MinRelation, MaxRelation> const& pp,
// Indexable const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Indexable>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
// ------------------------------------------------------------------ //
// distance_predicates_check for value_tag
// ------------------------------------------------------------------ //
template <typename PointRelation, typename Indexable>
struct distances_predicates_check<PointRelation, Indexable, value_tag>
{
template <typename Distances>
static inline bool apply(PointRelation const&, Distances const&)
{
return true;
}
};
//template <typename PointRelation, typename Indexable>
//struct distances_predicates_check<
// detail::unbounded<PointRelation>,
// Indexable,
// value_tag
//>
//{
// template <typename Distances>
// static inline bool apply(detail::unbounded<PointRelation> const&, Distances const&)
// {
// return true;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename Indexable>
//struct distances_predicates_check<
// detail::min_bounded<PointRelation, MinRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<MinRelation>::tag min_relation_tag;
//
// template <typename Distances>
// static inline bool apply(
// detail::min_bounded<PointRelation, MinRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_min <=
// detail::cdist_value<Distances>::template get<min_relation_tag>(d);
// }
//};
//
//template <typename PointRelation, typename MaxRelation, typename Indexable>
//struct distances_predicates_check<
// detail::max_bounded<PointRelation, MaxRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<MaxRelation>::tag max_relation_tag;
//
// template <typename Distances>
// static inline bool apply(
// detail::max_bounded<PointRelation, MaxRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_max <=
// detail::cdist_value<Distances>::template get<max_relation_tag>(d);
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation, typename Indexable>
//struct distances_predicates_check<
// detail::bounded<PointRelation, MinRelation, MaxRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<MinRelation>::tag min_relation_tag;
// typedef typename detail::relation<MaxRelation>::tag max_relation_tag;
//
// template <typename Distances>
// static inline bool apply(
// detail::bounded<PointRelation, MinRelation, MaxRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_min
// <= detail::cdist_value<Distances>::template get<min_relation_tag>(d)
// && detail::cdist_value<Distances>::template get<max_relation_tag>(d)
// <= pred.comparable_max;
// }
//};
// ------------------------------------------------------------------ //
// distance_calc for bounds_tag
// ------------------------------------------------------------------ //
template <typename PointRelation, typename Box>
struct distances_calc<
PointRelation,
Box,
bounds_tag>
{
typedef typename detail::relation<PointRelation>::value_type point_type;
typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
typedef detail::cdist<distance_type, detail::to_nearest_tag> result_type;
static inline result_type apply(PointRelation const& p, Box const& i)
{
result_type res;
distances_calc_impl<result_type, point_type, Box>
::apply(res, relation<PointRelation>::value(p), i);
return res;
}
};
//template <typename PointRelation, typename Box>
//struct distances_calc<
// detail::unbounded<PointRelation>,
// Box,
// bounds_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
//
// typedef detail::cdist<distance_type, detail::to_nearest_tag> result_type;
//
// static inline result_type apply(detail::unbounded<PointRelation> const& pp, Box const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Box>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename Box>
//struct distances_calc<
// detail::min_bounded<PointRelation, MinRelation>,
// Box,
// bounds_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
//
// typedef typename detail::cdist_merge<
// cdist<distance_type, detail::to_nearest_tag>,
// cdist<distance_type, detail::to_furthest_tag>
// >::type result_type;
//
// static inline result_type apply(detail::min_bounded<PointRelation, MinRelation> const& pp, Box const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Box>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MaxRelation, typename Box>
//struct distances_calc<
// detail::max_bounded<PointRelation, MaxRelation>,
// Box,
// bounds_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
//
// typedef cdist<distance_type, detail::to_nearest_tag> result_type;
//
// static inline result_type apply(detail::max_bounded<PointRelation, MaxRelation> const& pp, Box const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Box>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation, typename Box>
//struct distances_calc<
// detail::bounded<PointRelation, MinRelation, MaxRelation>,
// Box,
// bounds_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
//
// typedef typename detail::cdist_merge<
// cdist<distance_type, detail::to_nearest_tag>,
// cdist<distance_type, detail::to_furthest_tag>
// >::type result_type;
//
// static inline result_type apply(detail::bounded<PointRelation, MinRelation, MaxRelation> const& pp, Box const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Box>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
// ------------------------------------------------------------------ //
// distance_predicates_check for bounds_tag
// ------------------------------------------------------------------ //
template <typename PointRelation, typename Box>
struct distances_predicates_check<
PointRelation,
Box,
bounds_tag>
{
template <typename Distances>
static inline bool apply(PointRelation const&, Distances const&)
{
return true;
}
};
//template <typename PointRelation, typename Box>
//struct distances_predicates_check<
// detail::unbounded<PointRelation>,
// Box,
// bounds_tag>
//{
// template <typename Distances>
// static inline bool apply(
// detail::unbounded<PointRelation> const&,
// Distances const&)
// {
// return true;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename Box>
//struct distances_predicates_check<
// detail::min_bounded<PointRelation, MinRelation>,
// Box,
// bounds_tag>
//{
// template <typename Distances>
// static inline bool apply(
// detail::min_bounded<PointRelation, MinRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_min
// <= cdist_value<Distances>::template get<detail::to_furthest_tag>(d);
// }
//};
//
//template <typename PointRelation, typename MaxRelation, typename Box>
//struct distances_predicates_check<
// detail::max_bounded<PointRelation, MaxRelation>,
// Box,
// bounds_tag>
//{
// template <typename Distances>
// static inline bool apply(
// detail::max_bounded<PointRelation, MaxRelation> const& pred,
// Distances const& d)
// {
// return cdist_value<Distances>::template get<detail::to_nearest_tag>(d)
// <= pred.comparable_max;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation, typename Box>
//struct distances_predicates_check<
// detail::bounded<PointRelation, MinRelation, MaxRelation>,
// Box,
// bounds_tag>
//{
// template <typename Distances>
// static inline bool apply(
// detail::bounded<PointRelation, MinRelation, MaxRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_min
// <= cdist_value<Distances>::template get<detail::to_furthest_tag>(d)
// && cdist_value<Distances>::template get<detail::to_nearest_tag>(d)
// <= pred.comparable_max;
// }
//};
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_RTREE_DISTANCE_PREDICATES_HPP

View File

@@ -0,0 +1,139 @@
// Boost.Geometry Index
//
// Indexable's traits and related functions
//
// 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_INDEXABLE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_INDEXABLE_HPP
namespace boost { namespace geometry { namespace index { namespace detail {
namespace dispatch {
template <typename Indexable, typename IndexableTag>
struct point_type
{
typedef void type;
};
template <typename Indexable>
struct point_type<Indexable, geometry::box_tag>
{
typedef typename geometry::traits::point_type<Indexable>::type type;
};
template <typename Indexable>
struct point_type<Indexable, geometry::point_tag>
{
typedef Indexable type;
};
} // namespace dispatch
namespace traits {
template <typename Indexable>
struct point_type
{
typedef typename dispatch::point_type<
Indexable,
typename geometry::traits::tag<Indexable>::type
>::type type;
};
template <typename Indexable>
struct coordinate_system
{
typedef typename geometry::traits::coordinate_system<
typename point_type<Indexable>::type
>::type type;
};
template <typename Indexable>
struct coordinate_type
{
typedef typename geometry::traits::coordinate_type<
typename point_type<Indexable>::type
>::type type;
};
template <typename Indexable>
struct dimension
{
static const size_t value =
geometry::traits::dimension<
typename point_type<Indexable>::type
>::value;
};
template <typename Indexable>
struct tag
{
typedef typename geometry::traits::tag<
Indexable
>::type type;
};
} // namespace traits
namespace dispatch {
template <size_t Corner, size_t DimensionIndex, typename Indexable, typename IndexableTag>
struct indexable_indexed_access {};
template <size_t Corner, size_t DimensionIndex, typename Indexable>
struct indexable_indexed_access<Corner, DimensionIndex, Indexable, box_tag>
{
typedef typename traits::point_type<Indexable>::type point_type;
typedef typename traits::coordinate_type<point_type>::type coordinate_type;
static inline coordinate_type get(Indexable const& i)
{
return geometry::get<Corner, DimensionIndex>(i);
}
};
template <size_t Corner, size_t DimensionIndex, typename Indexable>
struct indexable_indexed_access<Corner, DimensionIndex, Indexable, point_tag>
{
typedef typename traits::coordinate_type<Indexable>::type coordinate_type;
static inline coordinate_type get(Indexable const& i)
{
return geometry::get<DimensionIndex>(i);
}
};
} // namespace dispatch
template <size_t Corner, size_t DimensionIndex, typename Indexable>
typename traits::coordinate_type<Indexable>::type get(Indexable const& i)
{
return dispatch::indexable_indexed_access<
Corner,
DimensionIndex,
Indexable,
typename geometry::traits::tag<Indexable>::type
>::get(i);
}
template <typename Indexable>
struct default_box_type
{
typedef geometry::model::box<
geometry::model::point<
typename traits::coordinate_type<Indexable>::type,
traits::dimension<Indexable>::value,
typename traits::coordinate_system<Indexable>::type
>
> type;
};
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_INDEXABLE_HPP

View File

@@ -0,0 +1,903 @@
// Boost.Geometry Index
//
// Spatial query predicates definition and checks.
//
// 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_PREDICATES_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
#include <boost/geometry/index/predicates.hpp>
#include <boost/geometry/index/detail/tags.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
// ------------------------------------------------------------------ //
// predicates
// ------------------------------------------------------------------ //
//struct empty {};
template <typename Fun>
struct satisfies
{
satisfies(Fun const& f) : fun(f) {}
Fun const& fun;
};
template <typename Geometry>
struct covered_by
{
covered_by(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
template <typename Geometry>
struct disjoint
{
disjoint(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
template <typename Geometry>
struct intersects
{
intersects(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
template <typename Geometry>
struct overlaps
{
overlaps(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
//template <typename Geometry>
//struct touches
//{
// touches(Geometry const& g) : geometry(g) {}
// Geometry geometry;
//};
template <typename Geometry>
struct within
{
within(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
template <typename Geometry>
struct not_covered_by
{
not_covered_by(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
template <typename Geometry>
struct not_disjoint
{
not_disjoint(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
template <typename Geometry>
struct not_intersects
{
not_intersects(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
template <typename Geometry>
struct not_overlaps
{
not_overlaps(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
//template <typename Geometry>
//struct not_touches
//{
// not_touches(Geometry const& g) : geometry(g) {}
// Geometry geometry;
//};
template <typename Geometry>
struct not_within
{
not_within(Geometry const& g) : geometry(g) {}
Geometry const& geometry;
};
template <typename DistancePredicates>
struct nearest
{
nearest(DistancePredicates const& dpred, unsigned k)
: distance_predicates(dpred)
, count(k)
{}
DistancePredicates const& distance_predicates;
unsigned count;
};
// ------------------------------------------------------------------ //
// is_predicate
// ------------------------------------------------------------------ //
//template <typename P> struct is_predicate { static const bool value = false; };
////template <> struct is_predicate< empty > { static const bool value = true; };
//template <typename UP> struct is_predicate< satisfies<UP> > { static const bool value = true; };
//template <typename G> struct is_predicate< covered_by<G> > { static const bool value = true; };
//template <typename G> struct is_predicate< disjoint<G> > { static const bool value = true; };
//template <typename G> struct is_predicate< intersects<G> > { static const bool value = true; };
//template <typename G> struct is_predicate< overlaps<G> > { static const bool value = true; };
////template <typename G> struct is_predicate< touches<G> > { static const bool value = true; };
//template <typename G> struct is_predicate< within<G> > { static const bool value = true; };
//template <typename G> struct is_predicate< not_covered_by<G> > { static const bool value = true; };
//template <typename G> struct is_predicate< not_disjoint<G> > { static const bool value = true; };
//template <typename G> struct is_predicate< not_intersects<G> > { static const bool value = true; };
//template <typename G> struct is_predicate< not_overlaps<G> > { static const bool value = true; };
////template <typename G> struct is_predicate< not_touches<G> > { static const bool value = true; };
//template <typename G> struct is_predicate< not_within<G> > { static const bool value = true; };
//template <typename P> struct is_predicate< nearest<P> > { static const bool value = true; };
// ------------------------------------------------------------------ //
// predicate_check_default
// ------------------------------------------------------------------ //
//template <typename GeometryOrUnary, typename GeometryTag, typename Tag>
//struct predicate_check_default
//{
// BOOST_MPL_ASSERT_MSG(
// (false),
// NOT_IMPLEMENTED_FOR_THESE_TAGS,
// (predicate_check_default));
//};
// ------------------------------------------------------------------ //
// predicate_check
// ------------------------------------------------------------------ //
template <typename Predicate, typename Tag>
struct predicate_check
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_PREDICATE_OR_TAG,
(predicate_check));
};
// ------------------------------------------------------------------ //
// predicate_check_default for value
// ------------------------------------------------------------------ //
//template <typename Geometry, typename GeometryTag>
//struct predicate_check_default<Geometry, GeometryTag, value_tag>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(Geometry const& g, Value const&, Indexable const& i)
// {
// return geometry::intersects(i, g);
// }
//};
//
//template <typename Unary>
//struct predicate_check_default<Unary, void, value_tag>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(Unary const& u, Value const& v, Indexable const&)
// {
// return u(v);
// }
//};
// ------------------------------------------------------------------ //
// predicate_check for value
// ------------------------------------------------------------------ //
//template <typename GeometryOrUnary>
//struct predicate_check<GeometryOrUnary, value_tag>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(GeometryOrUnary const& g, Value const& v, Indexable const& i)
// {
// return predicate_check_default<
// GeometryOrUnary, typename geometry::traits::tag<GeometryOrUnary>::type, bounds_tag
// >::apply(g, v, i);
// }
//};
//template <>
//struct predicate_check<empty, value_tag>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(empty const&, Value const&, Indexable const&)
// {
// return true;
// }
//};
template <typename Fun>
struct predicate_check<satisfies<Fun>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(satisfies<Fun> const& p, Value const& v, Indexable const&)
{
return p.fun(v);
}
};
template <typename Geometry>
struct predicate_check<covered_by<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(covered_by<Geometry> const& p, Value const&, Indexable const& i)
{
return geometry::covered_by(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<disjoint<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(disjoint<Geometry> const& p, Value const&, Indexable const& i)
{
return geometry::disjoint(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<intersects<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(intersects<Geometry> const& p, Value const&, Indexable const& i)
{
return geometry::intersects(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<overlaps<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(overlaps<Geometry> const& p, Value const&, Indexable const& i)
{
return geometry::overlaps(i, p.geometry);
}
};
//template <typename Geometry>
//struct predicate_check<touches<Geometry>, value_tag>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(touches<Geometry> const& p, Value const&, Indexable const& i)
// {
// return geometry::touches(i, p.geometry);
// }
//};
template <typename Geometry>
struct predicate_check<within<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(within<Geometry> const& p, Value const&, Indexable const& i)
{
return geometry::within(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<not_covered_by<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(not_covered_by<Geometry> const& p, Value const&, Indexable const& i)
{
return !geometry::covered_by(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<not_disjoint<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(not_disjoint<Geometry> const& p, Value const&, Indexable const& i)
{
return !geometry::disjoint(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<not_intersects<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(not_intersects<Geometry> const& p, Value const&, Indexable const& i)
{
return !geometry::intersects(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<not_overlaps<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(not_overlaps<Geometry> const& p, Value const&, Indexable const& i)
{
return !geometry::overlaps(i, p.geometry);
}
};
//template <typename Geometry>
//struct predicate_check<not_touches<Geometry>, value_tag>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(not_touches<Geometry> const& p, Value const&, Indexable const& i)
// {
// return !geometry::touches(i, p.geometry);
// }
//};
template <typename Geometry>
struct predicate_check<not_within<Geometry>, value_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(not_within<Geometry> const& p, Value const&, Indexable const& i)
{
return !geometry::within(i, p.geometry);
}
};
template <typename DistancePredicates>
struct predicate_check<nearest<DistancePredicates>, value_tag>
{
template <typename Value, typename Box>
static inline bool apply(nearest<DistancePredicates> const&, Value const&, Box const&)
{
return true;
}
};
// ------------------------------------------------------------------ //
// predicate_check_default for bounds
// ------------------------------------------------------------------ //
//template <typename Geometry, typename GeometryTag>
//struct predicate_check_default<Geometry, GeometryTag, bounds_tag>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(Geometry const& g, Value const&, Indexable const& i)
// {
// return geometry::intersects(i, g);
// }
//};
//
//template <typename Unary>
//struct predicate_check_default<Unary, void, bounds_tag>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(Unary const&, Value const&, Indexable const&)
// {
// return true;
// }
//};
// ------------------------------------------------------------------ //
// predicates_chec for bounds
// ------------------------------------------------------------------ //
//template <typename GeometryOrUnary>
//struct predicate_check<GeometryOrUnary, bounds_tag>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(GeometryOrUnary const& g, Value const& v, Indexable const& i)
// {
// return predicate_check_default<
// GeometryOrUnary, typename geometry::traits::tag<GeometryOrUnary>::type, bounds_tag
// >::apply(g, v, i);
// }
//};
//template <>
//struct predicate_check<empty, bounds_tag>
//{
// template <typename Geometry, typename Value, typename Indexable>
// static inline bool apply(Geometry const&, Value const&, Indexable const&)
// {
// return true;
// }
//};
template <typename Fun>
struct predicate_check<satisfies<Fun>, bounds_tag>
{
template <typename Value, typename Box>
static bool apply(satisfies<Fun> const&, Value const&, Box const&)
{
return true;
}
};
template <typename Geometry>
struct predicate_check<covered_by<Geometry>, bounds_tag>
{
template <typename Value, typename Box>
static bool apply(covered_by<Geometry> const& p, Value const&, Box const& i)
{
return geometry::intersects(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<disjoint<Geometry>, bounds_tag>
{
template <typename Value, typename Box>
static bool apply(disjoint<Geometry> const& p, Value const&, Box const& i)
{
return !geometry::covered_by(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<intersects<Geometry>, bounds_tag>
{
template <typename Value, typename Indexable>
static inline bool apply(intersects<Geometry> const& p, Value const&, Indexable const& i)
{
return geometry::intersects(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<overlaps<Geometry>, bounds_tag>
{
template <typename Value, typename Box>
static inline bool apply(overlaps<Geometry> const& p, Value const&, Box const& i)
{
// TODO: awulkiew - possibly change to the version without border case
// e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
return geometry::intersects(i, p.geometry);
}
};
//template <typename Geometry>
//struct predicate_check<touches<Geometry>, bounds_tag>
//{
// template <typename Value, typename Box>
// static bool apply(touches<Geometry> const& p, Value const&, Box const& i)
// {
// return geometry::intersects(i, p.geometry);
// }
//};
template <typename Geometry>
struct predicate_check<within<Geometry>, bounds_tag>
{
template <typename Value, typename Box>
static bool apply(within<Geometry> const& p, Value const&, Box const& i)
{
// TODO: awulkiew - possibly change to the version without border case
// e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
return geometry::intersects(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<not_covered_by<Geometry>, bounds_tag>
{
template <typename Value, typename Box>
static bool apply(not_covered_by<Geometry> const& p, Value const&, Box const& i)
{
return !geometry::covered_by(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<not_disjoint<Geometry>, bounds_tag>
{
template <typename Value, typename Box>
static bool apply(not_disjoint<Geometry> const& p, Value const&, Box const& i)
{
return !geometry::disjoint(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<not_intersects<Geometry>, bounds_tag>
{
template <typename Value, typename Box>
static bool apply(not_intersects<Geometry> const& p, Value const&, Box const& i)
{
return !geometry::covered_by(i, p.geometry);
}
};
template <typename Geometry>
struct predicate_check<not_overlaps<Geometry>, bounds_tag>
{
template <typename Value, typename Box>
static bool apply(not_overlaps<Geometry> const& , Value const&, Box const& )
{
return true;
}
};
//template <typename Geometry>
//struct predicate_check<not_touches<Geometry>, bounds_tag>
//{
// template <typename Value, typename Box>
// static bool apply(not_touches<Geometry> const& p, Value const&, Box const& i)
// {
// return !geometry::intersects(i, p.geometry);
// }
//};
template <typename Geometry>
struct predicate_check<not_within<Geometry>, bounds_tag>
{
template <typename Value, typename Box>
static bool apply(not_within<Geometry> const& p, Value const&, Box const& i)
{
return !geometry::within(i, p.geometry);
}
};
template <typename DistancePredicates>
struct predicate_check<nearest<DistancePredicates>, bounds_tag>
{
template <typename Value, typename Box>
static inline bool apply(nearest<DistancePredicates> const&, Value const&, Box const&)
{
return true;
}
};
// ------------------------------------------------------------------ //
// predicates_length
// ------------------------------------------------------------------ //
template <typename T>
struct predicates_length
{
static const unsigned value = 1;
};
//template <typename F, typename S>
//struct predicates_length< std::pair<F, S> >
//{
// static const unsigned value = 2;
//};
//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
//struct predicates_length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
//{
// static const unsigned value = boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value;
//};
template <typename Head, typename Tail>
struct predicates_length< boost::tuples::cons<Head, Tail> >
{
static const unsigned value = boost::tuples::length< boost::tuples::cons<Head, Tail> >::value;
};
// ------------------------------------------------------------------ //
// predicates_element
// ------------------------------------------------------------------ //
template <unsigned I, typename T>
struct predicates_element
{
BOOST_MPL_ASSERT_MSG((I < 1), INVALID_INDEX, (predicates_element));
typedef T type;
static type const& get(T const& p) { return p; }
};
//template <unsigned I, typename F, typename S>
//struct predicates_element< I, std::pair<F, S> >
//{
// BOOST_MPL_ASSERT_MSG((I < 2), INVALID_INDEX, (predicates_element));
//
// typedef F type;
// static type const& get(std::pair<F, S> const& p) { return p.first; }
//};
//
//template <typename F, typename S>
//struct predicates_element< 1, std::pair<F, S> >
//{
// typedef S type;
// static type const& get(std::pair<F, S> const& p) { return p.second; }
//};
//
//template <unsigned I, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
//struct predicates_element< I, boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
//{
// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> predicate_type;
//
// typedef typename boost::tuples::element<I, predicate_type>::type type;
// static type const& get(predicate_type const& p) { return boost::get<I>(p); }
//};
template <unsigned I, typename Head, typename Tail>
struct predicates_element< I, boost::tuples::cons<Head, Tail> >
{
typedef boost::tuples::cons<Head, Tail> predicate_type;
typedef typename boost::tuples::element<I, predicate_type>::type type;
static type const& get(predicate_type const& p) { return boost::get<I>(p); }
};
// ------------------------------------------------------------------ //
// predicates_check
// ------------------------------------------------------------------ //
//template <typename PairPredicates, typename Tag, unsigned First, unsigned Last>
//struct predicates_check_pair {};
//
//template <typename PairPredicates, typename Tag, unsigned I>
//struct predicates_check_pair<PairPredicates, Tag, I, I>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(PairPredicates const& , Value const& , Indexable const& )
// {
// return true;
// }
//};
//
//template <typename PairPredicates, typename Tag>
//struct predicates_check_pair<PairPredicates, Tag, 0, 1>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)
// {
// return predicate_check<typename PairPredicates::first_type, Tag>::apply(p.first, v, i);
// }
//};
//
//template <typename PairPredicates, typename Tag>
//struct predicates_check_pair<PairPredicates, Tag, 1, 2>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)
// {
// return predicate_check<typename PairPredicates::second_type, Tag>::apply(p.second, v, i);
// }
//};
//
//template <typename PairPredicates, typename Tag>
//struct predicates_check_pair<PairPredicates, Tag, 0, 2>
//{
// template <typename Value, typename Indexable>
// static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)
// {
// return predicate_check<typename PairPredicates::first_type, Tag>::apply(p.first, v, i)
// && predicate_check<typename PairPredicates::second_type, Tag>::apply(p.second, v, i);
// }
//};
template <typename TuplePredicates, typename Tag, unsigned First, unsigned Last>
struct predicates_check_tuple
{
template <typename Value, typename Indexable>
static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i)
{
return
predicate_check<
typename boost::tuples::element<First, TuplePredicates>::type,
Tag
>::apply(boost::get<First>(p), v, i) &&
predicates_check_tuple<TuplePredicates, Tag, First+1, Last>::apply(p, v, i);
}
};
template <typename TuplePredicates, typename Tag, unsigned First>
struct predicates_check_tuple<TuplePredicates, Tag, First, First>
{
template <typename Value, typename Indexable>
static inline bool apply(TuplePredicates const& , Value const& , Indexable const& )
{
return true;
}
};
template <typename Predicate, typename Tag, size_t First, size_t Last>
struct predicates_check_impl
{
BOOST_MPL_ASSERT_MSG((First < 1 && Last <= 1 && First <= Last), INVALID_INDEXES, (predicates_check_impl));
template <typename Value, typename Indexable>
static inline bool apply(Predicate const& p, Value const& v, Indexable const& i)
{
return predicate_check<Predicate, Tag>::apply(p, v, i);
}
};
//template <typename Predicate1, typename Predicate2, typename Tag, size_t First, size_t Last>
//struct predicates_check_impl<std::pair<Predicate1, Predicate2>, Tag, First, Last>
//{
// BOOST_MPL_ASSERT_MSG((First < 2 && Last <= 2 && First <= Last), INVALID_INDEXES, (predicates_check_impl));
//
// template <typename Value, typename Indexable>
// static inline bool apply(std::pair<Predicate1, Predicate2> const& p, Value const& v, Indexable const& i)
// {
// return predicate_check<Predicate1, Tag>::apply(p.first, v, i)
// && predicate_check<Predicate2, Tag>::apply(p.second, v, i);
// }
//};
//
//template <
// typename T0, typename T1, typename T2, typename T3, typename T4,
// typename T5, typename T6, typename T7, typename T8, typename T9,
// typename Tag, unsigned First, unsigned Last
//>
//struct predicates_check_impl<
// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
// Tag, First, Last
//>
//{
// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> predicates_type;
//
// static const unsigned pred_len = boost::tuples::length<predicates_type>::value;
// BOOST_MPL_ASSERT_MSG((First < pred_len && Last <= pred_len && First <= Last), INVALID_INDEXES, (predicates_check_impl));
//
// template <typename Value, typename Indexable>
// static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i)
// {
// return predicates_check_tuple<
// predicates_type,
// Tag, First, Last
// >::apply(p, v, i);
// }
//};
template <typename Head, typename Tail, typename Tag, unsigned First, unsigned Last>
struct predicates_check_impl<
boost::tuples::cons<Head, Tail>,
Tag, First, Last
>
{
typedef boost::tuples::cons<Head, Tail> predicates_type;
static const unsigned pred_len = boost::tuples::length<predicates_type>::value;
BOOST_MPL_ASSERT_MSG((First < pred_len && Last <= pred_len && First <= Last), INVALID_INDEXES, (predicates_check_impl));
template <typename Value, typename Indexable>
static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i)
{
return predicates_check_tuple<
predicates_type,
Tag, First, Last
>::apply(p, v, i);
}
};
template <typename Tag, unsigned First, unsigned Last, typename Predicates, typename Value, typename Indexable>
inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i)
{
return detail::predicates_check_impl<Predicates, Tag, First, Last>
::apply(p, v, i);
}
// ------------------------------------------------------------------ //
// nearest predicate helpers
// ------------------------------------------------------------------ //
// predicates_is_nearest
template <typename P>
struct predicates_is_nearest
{
static const unsigned value = 0;
};
template <typename DistancePredicates>
struct predicates_is_nearest< nearest<DistancePredicates> >
{
static const unsigned value = 1;
};
// predicates_count_nearest
template <typename T>
struct predicates_count_nearest
{
static const unsigned value = predicates_is_nearest<T>::value;
};
//template <typename F, typename S>
//struct predicates_count_nearest< std::pair<F, S> >
//{
// static const unsigned value = predicates_is_nearest<F>::value
// + predicates_is_nearest<S>::value;
//};
template <typename Tuple, unsigned N>
struct predicates_count_nearest_tuple
{
static const unsigned value =
predicates_is_nearest<typename boost::tuples::element<N-1, Tuple>::type>::value
+ predicates_count_nearest_tuple<Tuple, N-1>::value;
};
template <typename Tuple>
struct predicates_count_nearest_tuple<Tuple, 1>
{
static const unsigned value =
predicates_is_nearest<typename boost::tuples::element<0, Tuple>::type>::value;
};
//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
//struct predicates_count_nearest< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
//{
// static const unsigned value = predicates_count_nearest_tuple<
// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
// boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value
// >::value;
//};
template <typename Head, typename Tail>
struct predicates_count_nearest< boost::tuples::cons<Head, Tail> >
{
static const unsigned value = predicates_count_nearest_tuple<
boost::tuples::cons<Head, Tail>,
boost::tuples::length< boost::tuples::cons<Head, Tail> >::value
>::value;
};
// predicates_find_nearest
template <typename T>
struct predicates_find_nearest
{
static const unsigned value = predicates_is_nearest<T>::value ? 0 : 1;
};
//template <typename F, typename S>
//struct predicates_find_nearest< std::pair<F, S> >
//{
// static const unsigned value = predicates_is_nearest<F>::value ? 0 :
// (predicates_is_nearest<S>::value ? 1 : 2);
//};
template <typename Tuple, unsigned N>
struct predicates_find_nearest_tuple
{
static const bool is_found = predicates_find_nearest_tuple<Tuple, N-1>::is_found
|| predicates_is_nearest<typename boost::tuples::element<N-1, Tuple>::type>::value;
static const unsigned value = predicates_find_nearest_tuple<Tuple, N-1>::is_found ?
predicates_find_nearest_tuple<Tuple, N-1>::value :
(predicates_is_nearest<typename boost::tuples::element<N-1, Tuple>::type>::value ?
N-1 : boost::tuples::length<Tuple>::value);
};
template <typename Tuple>
struct predicates_find_nearest_tuple<Tuple, 1>
{
static const bool is_found = predicates_is_nearest<typename boost::tuples::element<0, Tuple>::type>::value;
static const unsigned value = is_found ? 0 : boost::tuples::length<Tuple>::value;
};
//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
//struct predicates_find_nearest< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
//{
// static const unsigned value = predicates_find_nearest_tuple<
// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
// boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value
// >::value;
//};
template <typename Head, typename Tail>
struct predicates_find_nearest< boost::tuples::cons<Head, Tail> >
{
static const unsigned value = predicates_find_nearest_tuple<
boost::tuples::cons<Head, Tail>,
boost::tuples::length< boost::tuples::cons<Head, Tail> >::value
>::value;
};
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP

View File

@@ -0,0 +1,171 @@
// Boost.Geometry Index
//
// 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_PUSHABLE_ARRAY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_PUSHABLE_ARRAY_HPP
#include <boost/array.hpp>
#include <boost/geometry/index/detail/assert.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
template <typename Element, size_t Capacity>
class pushable_array
{
typedef typename boost::array<Element, Capacity> array_type;
public:
typedef typename array_type::value_type value_type;
typedef typename array_type::size_type size_type;
typedef typename array_type::iterator iterator;
typedef typename array_type::const_iterator const_iterator;
typedef typename array_type::reverse_iterator reverse_iterator;
typedef typename array_type::const_reverse_iterator const_reverse_iterator;
typedef typename array_type::reference reference;
typedef typename array_type::const_reference const_reference;
inline pushable_array()
: m_size(0)
{}
inline explicit pushable_array(size_type s)
: m_size(s)
{
BOOST_GEOMETRY_INDEX_ASSERT(s <= Capacity, "size too big");
}
inline void resize(size_type s)
{
BOOST_GEOMETRY_INDEX_ASSERT(s <= Capacity, "size too big");
m_size = s;
}
inline void reserve(size_type /*s*/)
{
//BOOST_GEOMETRY_INDEX_ASSERT(s <= Capacity, "size too big");
// do nothing
}
inline Element & operator[](size_type i)
{
BOOST_GEOMETRY_INDEX_ASSERT(i < m_size, "index of the element outside the container");
return m_array[i];
}
inline Element const& operator[](size_type i) const
{
BOOST_GEOMETRY_INDEX_ASSERT(i < m_size, "index of the element outside the container");
return m_array[i];
}
inline Element const& front() const
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
return m_array.front();
}
inline Element & front()
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
return m_array.front();
}
inline Element const& back() const
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
return *(begin() + (m_size - 1));
}
inline Element & back()
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
return *(begin() + (m_size - 1));
}
inline iterator begin()
{
return m_array.begin();
}
inline iterator end()
{
return m_array.begin() + m_size;
}
inline const_iterator begin() const
{
return m_array.begin();
}
inline const_iterator end() const
{
return m_array.begin() + m_size;
}
inline reverse_iterator rbegin()
{
return reverse_iterator(end());
}
inline reverse_iterator rend()
{
return reverse_iterator(begin());
}
inline const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
}
inline const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
inline void clear()
{
m_size = 0;
}
inline void push_back(Element const& v)
{
BOOST_GEOMETRY_INDEX_ASSERT(m_size < Capacity, "can't further increase the size of the container");
m_array[m_size] = v;
++m_size;
}
inline void pop_back()
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
--m_size;
}
inline bool empty() const
{
return m_size == 0;
}
inline size_t size() const
{
return m_size;
}
inline size_t capacity() const
{
return Capacity;
}
private:
boost::array<Element, Capacity> m_array;
size_type m_size;
};
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_PUSHABLE_ARRAY_HPP

View File

@@ -0,0 +1,54 @@
// Boost.Geometry Index
//
// R-tree queries range adaptors
//
// 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_ADAPTORS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP
#include <deque>
#include <boost/static_assert.hpp>
#include <boost/geometry/index/adaptors/query.hpp>
namespace boost { namespace geometry { namespace index {
template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
class rtree;
namespace adaptors { namespace detail {
template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
class query_range< index::rtree<Value, Options, IndexableGetter, EqualTo, Allocator> >
{
public:
typedef std::vector<Value> result_type;
typedef typename result_type::iterator iterator;
typedef typename result_type::const_iterator const_iterator;
template <typename Predicates> inline
query_range(index::rtree<Value, Options, IndexableGetter, EqualTo, Allocator> const& rtree,
Predicates const& pred)
{
rtree.query(pred, std::back_inserter(m_result));
}
inline iterator begin() { return m_result.begin(); }
inline iterator end() { return m_result.end(); }
inline const_iterator begin() const { return m_result.begin(); }
inline const_iterator end() const { return m_result.end(); }
private:
result_type m_result;
};
}} // namespace adaptors::detail
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP

View File

@@ -0,0 +1,16 @@
// Boost.Geometry Index
//
// R-tree kmeans 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_KMEANS_KMEANS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP
#include <boost/geometry/index/rtree/kmeans/split.hpp>
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP

View File

@@ -0,0 +1,87 @@
// Boost.Geometry Index
//
// R-tree kmeans split 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_KMEANS_SPLIT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP
#include <boost/geometry/index/rtree/node/node.hpp>
#include <boost/geometry/index/rtree/visitors/insert.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
namespace kmeans {
// some details
} // namespace kmeans
// split_kmeans_tag
// OR
// split_clusters_tag and redistribute_kmeans_tag - then redistribute will probably slightly different interface
// or some other than "redistribute"
// 1. for this algorithm one probably MUST USE NON-STATIC NODES with node_default_tag
// or the algorithm must be changed somehow - to not store additional nodes in the current node
// but return excessive element/elements container instead (possibly pushable_array<1> or std::vector)
// this would also cause building of smaller trees since +1 element in nodes wouldn't be needed in different redistributing algorithms
// 2. it is probably possible to add e.g. 2 levels of tree in one insert
// Edge case is that every node split generates M + 1 children, in parent containing M nodes
// result is 2M + 1 nodes in parent on this level
// On next level the same, next the same and so on.
// We have Depth*M+1 nodes in the root
// The tree may then gain some > 1 levels in one insert
// split::apply() manages this but special attention is required
// which algorithm should be used to choose current node in traversing while inserting?
// some of the currently used ones or some using mean values as well?
// TODO
// 1. Zmienic troche algorytm zeby przekazywal nadmiarowe elementy do split
// i pobieral ze split nadmiarowe elementy rodzica
// W zaleznosci od algorytmu w rozny sposob - l/q/r* powinny zwracac np pushable_array<1>
// wtedy tez is_overerflow (z R* insert?) bedzie nieportrzebne
// Dla kmeans zapewne std::vector, jednak w wezlach nadal moglaby byc pushable_array
// 2. Fajnie byloby tez uproscic te wszystkie parametry root,parent,index itd. Mozliwe ze okazalyby sie zbedne
// 3. Sprawdzyc czasy wykonywania i zajetosc pamieci
// 4. Pamietac o parametryzacji kontenera z nadmiarowymi elementami
// PS. Z R* reinsertami moze byc masakra
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class split<Value, Options, Translator, Box, Allocators, split_kmeans_tag>
{
protected:
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;
public:
template <typename Node>
static inline void apply(node* & root_node,
size_t & leafs_level,
Node & n,
internal_node *parent_node,
size_t current_child_index,
Translator const& tr,
Allocators & allocators)
{
}
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP

View File

@@ -0,0 +1,16 @@
// Boost.Geometry Index
//
// R-tree linear 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_LINEAR_LINEAR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_LINEAR_HPP
#include <boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp>
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_LINEAR_HPP

View File

@@ -0,0 +1,333 @@
// Boost.Geometry Index
//
// R-tree linear split algorithm implementation
//
// Copyright (c) 2008 Federico J. Fernandez.
// 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_LINEAR_REDISTRIBUTE_ELEMENTS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_REDISTRIBUTE_ELEMENTS_HPP
#include <boost/type_traits/is_unsigned.hpp>
#include <boost/geometry/index/detail/algorithms/content.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 linear {
// TODO: awulkiew - there are loops inside find_greatest_normalized_separation::apply()
// iteration is done for each DimensionIndex.
// Separations and seeds for all DimensionIndex(es) could be calculated at once, stored, then the greatest would be choosen.
// TODO: Implement separate version for Points
// What if width calculated inside find_greatest_normalized_separation::apply() is near 0?
// What epsilon should be taken to calculation and what would be the value of resulting separation?
// from void find_normalized_separations(std::vector<Box> const& boxes, T& separation, unsigned int& first, unsigned int& second) const
template <typename Elements, typename Parameters, typename Translator, size_t DimensionIndex>
struct find_greatest_normalized_separation
{
typedef typename Elements::value_type element_type;
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef typename index::detail::traits::coordinate_type<indexable_type>::type coordinate_type;
static inline void apply(Elements const& elements,
Parameters const& parameters,
Translator const& translator,
coordinate_type & separation,
size_t & seed1,
size_t & seed2)
{
const size_t elements_count = parameters.get_max_elements() + 1;
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected number of elements");
BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");
// find the lowest low, highest high
coordinate_type lowest_low = index::detail::get<min_corner, DimensionIndex>(rtree::element_indexable(elements[0], translator));
coordinate_type highest_high = index::detail::get<max_corner, DimensionIndex>(rtree::element_indexable(elements[0], translator));
// and the lowest high
coordinate_type lowest_high = highest_high;
size_t lowest_high_index = 0;
for ( size_t i = 1 ; i < elements_count ; ++i )
{
coordinate_type min_coord = index::detail::get<min_corner, DimensionIndex>(rtree::element_indexable(elements[i], translator));
coordinate_type max_coord = index::detail::get<max_corner, DimensionIndex>(rtree::element_indexable(elements[i], translator));
if ( max_coord < lowest_high )
{
lowest_high = max_coord;
lowest_high_index = i;
}
if ( min_coord < lowest_low )
lowest_low = min_coord;
if ( highest_high < max_coord )
highest_high = max_coord;
}
// find the highest low
size_t highest_low_index = lowest_high_index == 0 ? 1 : 0;
coordinate_type highest_low = index::detail::get<min_corner, DimensionIndex>(rtree::element_indexable(elements[highest_low_index], translator));
for ( size_t i = highest_low_index ; i < elements_count ; ++i )
{
coordinate_type min_coord = index::detail::get<min_corner, DimensionIndex>(rtree::element_indexable(elements[i], translator));
if ( highest_low < min_coord &&
i != lowest_high_index )
{
highest_low = min_coord;
highest_low_index = i;
}
}
coordinate_type const width = highest_high - lowest_low;
// TODO: awulkiew - following separation calculation has two flaws:
// 1. for floating point numbers width should be compared witn some EPS
// 2. separation calculation won't work for unsigned numbers
// but there should be possible to calculate negative value (cast to some floating point type?)
// Temporary workaround
BOOST_STATIC_ASSERT(!boost::is_unsigned<coordinate_type>::value);
if ( width == 0 )
separation = 0;
// (highest_low - lowest_high) == 0
else
separation = (highest_low - lowest_high) / width;
seed1 = highest_low_index;
seed2 = lowest_high_index;
BOOST_GEOMETRY_INDEX_DETAIL_USE_PARAM(parameters)
}
};
template <typename Elements, typename Parameters, typename Translator, size_t Dimension>
struct pick_seeds_impl
{
BOOST_STATIC_ASSERT(0 < Dimension);
typedef typename Elements::value_type element_type;
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef typename index::detail::traits::coordinate_type<indexable_type>::type coordinate_type;
static inline void apply(Elements const& elements,
Parameters const& parameters,
Translator const& tr,
coordinate_type & separation,
size_t & seed1,
size_t & seed2)
{
pick_seeds_impl<Elements, Parameters, Translator, Dimension - 1>::apply(elements, parameters, tr, separation, seed1, seed2);
coordinate_type current_separation;
size_t s1, s2;
find_greatest_normalized_separation<Elements, Parameters, Translator, Dimension - 1>::apply(elements, parameters, tr, current_separation, s1, s2);
// in the old implementation different operator was used: <= (y axis prefered)
if ( separation < current_separation )
{
separation = current_separation;
seed1 = s1;
seed2 = s2;
}
}
};
template <typename Elements, typename Parameters, typename Translator>
struct pick_seeds_impl<Elements, Parameters, Translator, 1>
{
typedef typename Elements::value_type element_type;
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef typename index::detail::traits::coordinate_type<indexable_type>::type coordinate_type;
static inline void apply(Elements const& elements,
Parameters const& parameters,
Translator const& tr,
coordinate_type & separation,
size_t & seed1,
size_t & seed2)
{
find_greatest_normalized_separation<Elements, Parameters, Translator, 0>::apply(elements, parameters, tr, separation, seed1, seed2);
}
};
// from void linear_pick_seeds(node_pointer const& n, unsigned int &seed1, unsigned int &seed2) const
template <typename Elements, typename Parameters, typename Translator>
struct pick_seeds
{
typedef typename Elements::value_type element_type;
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef typename index::detail::traits::coordinate_type<indexable_type>::type coordinate_type;
static const size_t dimension = index::detail::traits::dimension<indexable_type>::value;
static inline void apply(Elements const& elements,
Parameters const& parameters,
Translator const& tr,
size_t & seed1,
size_t & seed2)
{
coordinate_type separation = 0;
pick_seeds_impl<Elements, Parameters, Translator, dimension>::apply(elements, parameters, tr, separation, seed1, seed2);
}
};
} // namespace linear
// from void split_node(node_pointer const& n, node_pointer& n1, node_pointer& n2) const
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
struct redistribute_elements<Value, Options, Translator, Box, Allocators, linear_tag>
{
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;
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;
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef typename index::detail::traits::coordinate_type<indexable_type>::type coordinate_type;
typedef typename index::detail::default_content_result<Box>::type content_type;
elements_type & elements1 = rtree::elements(n);
elements_type & elements2 = rtree::elements(second_node);
const size_t elements1_count = parameters.get_max_elements() + 1;
BOOST_GEOMETRY_INDEX_ASSERT(elements1.size() == elements1_count, "unexpected number of elements");
// copy original elements
elements_type elements_copy(elements1); // MAY THROW, STRONG (alloc, copy)
// calculate initial seeds
size_t seed1 = 0;
size_t seed2 = 0;
linear::pick_seeds<
elements_type,
parameters_type,
Translator
>::apply(elements_copy, parameters, translator, seed1, seed2);
// prepare nodes' elements containers
elements1.clear();
BOOST_GEOMETRY_INDEX_ASSERT(elements2.empty(), "unexpected container state");
try
{
// add seeds
elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy)
elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)
// calculate boxes
geometry::convert(rtree::element_indexable(elements_copy[seed1], translator), box1);
geometry::convert(rtree::element_indexable(elements_copy[seed2], translator), box2);
// initialize areas
content_type content1 = index::detail::content(box1);
content_type content2 = index::detail::content(box2);
BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements1_count, "unexpected elements number");
size_t remaining = elements1_count - 2;
// redistribute the rest of the elements
for ( size_t i = 0 ; i < elements1_count ; ++i )
{
if (i != seed1 && i != seed2)
{
element_type const& elem = elements_copy[i];
indexable_type const& indexable = rtree::element_indexable(elem, translator);
// if there is small number of elements left and the number of elements in node is lesser than min_elems
// just insert them to this node
if ( elements1.size() + remaining <= parameters.get_min_elements() )
{
elements1.push_back(elem); // MAY THROW, STRONG (copy)
geometry::expand(box1, indexable);
content1 = index::detail::content(box1);
}
else if ( elements2.size() + remaining <= parameters.get_min_elements() )
{
elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
geometry::expand(box2, indexable);
content2 = index::detail::content(box2);
}
// choose better node and insert element
else
{
// calculate enlarged boxes and areas
Box enlarged_box1(box1);
Box enlarged_box2(box2);
geometry::expand(enlarged_box1, indexable);
geometry::expand(enlarged_box2, indexable);
content_type enlarged_content1 = index::detail::content(enlarged_box1);
content_type enlarged_content2 = index::detail::content(enlarged_box2);
content_type content_increase1 = enlarged_content1 - content1;
content_type content_increase2 = enlarged_content2 - content2;
// choose group which box content have to be enlarged least or has smaller content or has fewer elements
if ( content_increase1 < content_increase2 ||
( content_increase1 == content_increase2 && content1 < content2 ) ||
( content1 == content2 && elements1.size() <= elements2.size() ) )
{
elements1.push_back(elem); // MAY THROW, STRONG (copy)
box1 = enlarged_box1;
content1 = enlarged_content1;
}
else
{
elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
box2 = enlarged_box2;
content2 = enlarged_content2;
}
}
BOOST_GEOMETRY_INDEX_ASSERT(0 < remaining, "unexpected value");
--remaining;
}
}
}
catch (...)
{
elements1.clear();
elements2.clear();
rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_copy, allocators);
//elements_copy.clear();
throw; // RETHROW, BASIC
}
}
};
}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_REDISTRIBUTE_ELEMENTS_HPP

View File

@@ -0,0 +1,38 @@
// Boost.Geometry Index
//
// R-tree auto deallocator
//
// 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_NODE_AUTO_DEALLOCATOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_AUTO_DEALLOCATOR_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
template <typename Alloc>
class auto_deallocator
{
auto_deallocator(auto_deallocator const&);
auto_deallocator & operator=(auto_deallocator const&);
public:
typedef typename Alloc::pointer pointer;
inline auto_deallocator(Alloc & a, pointer p) : m_alloc(a), m_ptr(p) {}
inline ~auto_deallocator() { if ( m_ptr ) boost::container::allocator_traits<Alloc>::deallocate(m_alloc, m_ptr, 1); }
inline void release() { m_ptr = 0; }
inline pointer ptr() { return m_ptr; }
private:
Alloc & m_alloc;
pointer m_ptr;
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_AUTO_DEALLOCATOR_HPP

View File

@@ -0,0 +1,85 @@
// Boost.Geometry Index
//
// R-tree node concept
//
// 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_NODE_CONCEPT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_CONCEPT_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct node
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
(node));
};
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct internal_node
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
(internal_node));
};
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct leaf
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
(leaf));
};
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag, bool IsVisitableConst>
struct visitor
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
(visitor));
};
template <typename Allocator, typename Value, typename Parameters, typename Box, typename Tag>
class allocators
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
(allocators));
};
template <typename Allocators, typename Node>
struct create_node
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_NODE_TYPE,
(create_node));
};
template <typename Allocators, typename Node>
struct destroy_node
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_NODE_TYPE,
(destroy_node));
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_CONCEPT_HPP

View File

@@ -0,0 +1,88 @@
// Boost.Geometry Index
//
// R-tree nodes dynamic visitor and nodes base type
//
// 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_NODE_DYNAMIC_VISITOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_DYNAMIC_VISITOR_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// visitor forward declaration
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag, bool IsVisitableConst>
struct dynamic_visitor;
// node
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct dynamic_node
{
virtual ~dynamic_node() {}
virtual void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, Tag, false> &) = 0;
virtual void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, Tag, true> &) const = 0;
};
// nodes variants forward declarations
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct dynamic_internal_node;
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct dynamic_leaf;
// visitor
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct dynamic_visitor<Value, Parameters, Box, Allocators, Tag, true>
{
typedef dynamic_internal_node<Value, Parameters, Box, Allocators, Tag> internal_node;
typedef dynamic_leaf<Value, Parameters, Box, Allocators, Tag> leaf;
virtual ~dynamic_visitor() {}
virtual void operator()(internal_node const&) = 0;
virtual void operator()(leaf const&) = 0;
};
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct dynamic_visitor<Value, Parameters, Box, Allocators, Tag, false>
{
typedef dynamic_internal_node<Value, Parameters, Box, Allocators, Tag> internal_node;
typedef dynamic_leaf<Value, Parameters, Box, Allocators, Tag> leaf;
virtual ~dynamic_visitor() {}
virtual void operator()(internal_node &) = 0;
virtual void operator()(leaf &) = 0;
};
// nodes conversion
template <typename Derived, typename Parameters, typename Value, typename Box, typename Allocators, typename Tag>
inline Derived & get(dynamic_node<Value, Parameters, Box, Allocators, Tag> & n)
{
BOOST_GEOMETRY_INDEX_ASSERT(dynamic_cast<Derived*>(&n), "can't cast to a Derived type");
return static_cast<Derived&>(n);
}
// apply visitor
template <typename Visitor, typename Visitable>
inline void apply_visitor(Visitor & v, Visitable & n)
{
BOOST_GEOMETRY_INDEX_ASSERT(&n, "null ptr");
n.apply_visitor(v);
}
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_DYNAMIC_VISITOR_HPP

View File

@@ -0,0 +1,173 @@
// Boost.Geometry Index
//
// R-tree nodes
//
// 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_NODE_NODE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_HPP
#include <boost/container/vector.hpp>
#include <boost/geometry/index/detail/varray.hpp>
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/node/pairs.hpp>
#include <boost/geometry/index/detail/rtree/node/auto_deallocator.hpp>
#include <boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp>
#include <boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp>
#include <boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp>
#include <boost/geometry/index/detail/rtree/node/static_visitor.hpp>
#include <boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp>
#include <boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp>
#include <boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// elements box
template <typename Box, typename FwdIter, typename Translator>
inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr)
{
Box result;
if ( first == last )
{
geometry::assign_inverse(result);
return result;
}
geometry::convert(element_indexable(*first, tr), result);
++first;
for ( ; first != last ; ++first )
geometry::expand(result, element_indexable(*first, tr));
return result;
}
// destroys subtree if the element is internal node's element
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
struct destroy_element
{
typedef typename Options::parameters_type parameters_type;
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 rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
inline static void apply(typename internal_node::elements_type::value_type & element, Allocators & allocators)
{
node_auto_ptr dummy(element.second, allocators);
element.second = 0;
}
inline static void apply(typename leaf::elements_type::value_type &, Allocators &) {}
};
// destroys stored subtrees if internal node's elements are passed
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
struct destroy_elements
{
typedef typename Options::parameters_type parameters_type;
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 rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
inline static void apply(typename internal_node::elements_type & elements, Allocators & allocators)
{
for ( size_t i = 0 ; i < elements.size() ; ++i )
{
node_auto_ptr dummy(elements[i].second, allocators);
elements[i].second = 0;
}
}
inline static void apply(typename leaf::elements_type &, Allocators &)
{}
inline static void apply(typename internal_node::elements_type::iterator first,
typename internal_node::elements_type::iterator last,
Allocators & allocators)
{
for ( ; first != last ; ++first )
{
node_auto_ptr dummy(first->second, allocators);
first->second = 0;
}
}
inline static void apply(typename leaf::elements_type::iterator /*first*/,
typename leaf::elements_type::iterator /*last*/,
Allocators & /*allocators*/)
{}
};
// clears node, deletes all subtrees stored in node
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
struct clear_node
{
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;
inline static void apply(node & node, Allocators & allocators)
{
rtree::visitors::is_leaf<Value, Options, Box, Allocators> ilv;
rtree::apply_visitor(ilv, node);
if ( ilv.result )
{
apply(rtree::get<leaf>(node), allocators);
}
else
{
apply(rtree::get<internal_node>(node), allocators);
}
}
inline static void apply(internal_node & internal_node, Allocators & allocators)
{
destroy_elements<Value, Options, Translator, Box, Allocators>::apply(rtree::elements(internal_node), allocators);
rtree::elements(internal_node).clear();
}
inline static void apply(leaf & leaf, Allocators &)
{
rtree::elements(leaf).clear();
}
};
template <typename Container, typename Iterator>
void move_from_back(Container & container, Iterator it)
{
BOOST_GEOMETRY_INDEX_ASSERT(!container.empty(), "cannot copy from empty container");
Iterator back_it = container.end();
--back_it;
if ( it != back_it )
{
*it = boost::move(*back_it); // MAY THROW (copy)
}
}
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_HPP

View File

@@ -0,0 +1,79 @@
// Boost.Geometry Index
//
// R-tree node auto ptr
//
// 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_NODE_NODE_AUTO_PTR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_AUTO_PTR_HPP
#include <boost/noncopyable.hpp>
#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class node_auto_ptr
: boost::noncopyable
{
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
typedef typename Allocators::node_pointer pointer;
public:
node_auto_ptr(pointer ptr, Allocators & allocators)
: m_ptr(ptr)
, m_allocators(allocators)
{}
~node_auto_ptr()
{
reset();
}
void reset(pointer ptr = 0)
{
if ( m_ptr )
{
detail::rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(m_ptr, m_allocators);
detail::rtree::apply_visitor(del_v, *m_ptr);
}
m_ptr = ptr;
}
void release()
{
m_ptr = 0;
}
pointer get() const
{
return m_ptr;
}
node & operator*() const
{
return *m_ptr;
}
pointer operator->() const
{
return m_ptr;
}
private:
pointer m_ptr;
Allocators & m_allocators;
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_AUTO_PTR_HPP

View File

@@ -0,0 +1,329 @@
// Boost.Geometry Index
//
// R-tree nodes based on run-time polymorphism, storing std::vectors
//
// 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_NODE_NODE_DEFAULT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct dynamic_internal_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
: public dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
{
typedef typename Allocators::leaf_allocator_type::template rebind<
rtree::ptr_pair<Box, typename Allocators::node_pointer>
>::other elements_allocator_type;
typedef boost::container::vector<
rtree::ptr_pair<Box, typename Allocators::node_pointer>,
elements_allocator_type
> elements_type;
template <typename Al>
inline dynamic_internal_node(Al const& al)
: elements(al)
{}
void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, false> & v) { v(*this); }
void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, true> & v) const { v(*this); }
elements_type elements;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct dynamic_leaf<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
: public dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
{
typedef typename Allocators::leaf_allocator_type::template rebind<
Value
>::other elements_allocator_type;
typedef boost::container::vector<
Value,
elements_allocator_type
> elements_type;
template <typename Al>
inline dynamic_leaf(Al const& al)
: elements(al)
{}
void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, false> & v) { v(*this); }
void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, true> & v) const { v(*this); }
elements_type elements;
};
// nodes traits
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
{
typedef dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag> type;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct internal_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
{
typedef dynamic_internal_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag> type;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct leaf<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
{
typedef dynamic_leaf<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag> type;
};
// visitor traits
template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
struct visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, IsVisitableConst>
{
typedef dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, IsVisitableConst> type;
};
// element's indexable type
template <typename Element, typename Translator>
struct element_indexable_type
{
typedef typename indexable_type<Translator>::type type;
};
template <typename First, typename Pointer, typename Translator>
struct element_indexable_type<
rtree::ptr_pair<First, Pointer>,
Translator
>
{
typedef First type;
};
// element's indexable getter
template <typename Element, typename Translator>
typename result_type<Translator>::type
element_indexable(Element const& el, Translator const& tr)
{
return tr(el);
}
template <typename First, typename Pointer, typename Translator>
First const&
element_indexable(rtree::ptr_pair<First, Pointer> const& el, Translator const& /*tr*/)
{
return el.first;
}
// nodes elements
template <typename Node>
struct elements_type
{
typedef typename Node::elements_type type;
};
template <typename Node>
inline typename elements_type<Node>::type &
elements(Node & n)
{
return n.elements;
}
template <typename Node>
inline typename elements_type<Node>::type const&
elements(Node const& n)
{
return n.elements;
}
// elements derived type
template <typename Elements, typename NewValue>
struct container_from_elements_type
{
typedef boost::container::vector<NewValue> type;
};
// allocators
template <typename Allocator, typename Value, typename Parameters, typename Box>
class allocators<Allocator, Value, Parameters, Box, node_d_mem_dynamic_tag>
: public Allocator::template rebind<
typename internal_node<Value, Parameters, Box, allocators<Allocator, Value, Parameters, Box, node_d_mem_dynamic_tag>, node_d_mem_dynamic_tag>::type
>::other
, public Allocator::template rebind<
typename leaf<Value, Parameters, Box, allocators<Allocator, Value, Parameters, Box, node_d_mem_dynamic_tag>, node_d_mem_dynamic_tag>::type
>::other
{
public:
typedef typename Allocator::size_type size_type;
typedef typename Allocator::template rebind<
typename node<Value, Parameters, Box, allocators, node_d_mem_dynamic_tag>::type
>::other::pointer node_pointer;
typedef typename Allocator::template rebind<
typename internal_node<Value, Parameters, Box, allocators, node_d_mem_dynamic_tag>::type
>::other::pointer internal_node_pointer;
typedef typename Allocator::template rebind<
typename internal_node<Value, Parameters, Box, allocators, node_d_mem_dynamic_tag>::type
>::other internal_node_allocator_type;
typedef typename Allocator::template rebind<
typename leaf<Value, Parameters, Box, allocators, node_d_mem_dynamic_tag>::type
>::other leaf_allocator_type;
inline allocators()
: internal_node_allocator_type()
, leaf_allocator_type()
{}
inline explicit allocators(Allocator const& alloc)
: internal_node_allocator_type(alloc)
, leaf_allocator_type(alloc)
{}
inline allocators(BOOST_FWD_REF(allocators) a)
: internal_node_allocator_type(boost::move(a.internal_node_allocator()))
, leaf_allocator_type(boost::move(a.leaf_allocator()))
{}
void swap(allocators & a)
{
boost::swap(internal_node_allocator(), a.internal_node_allocator());
boost::swap(leaf_allocator(), a.leaf_allocator());
}
bool operator==(allocators const& a) const { return leaf_allocator() == a.leaf_allocator(); }
template <typename Alloc>
bool operator==(Alloc const& a) const { return leaf_allocator() == leaf_allocator_type(a); }
Allocator allocator() const { return Allocator(leaf_allocator()); }
internal_node_allocator_type & internal_node_allocator() { return *this; }
internal_node_allocator_type const& internal_node_allocator() const { return *this; }
leaf_allocator_type & leaf_allocator() { return *this; }
leaf_allocator_type const& leaf_allocator() const { return *this; }
};
// create_node_impl
template <typename BaseNodePtr, typename Node>
struct create_dynamic_node
{
template <typename AllocNode>
static inline BaseNodePtr apply(AllocNode & alloc_node)
{
typedef boost::container::allocator_traits<AllocNode> Al;
typedef typename Al::pointer P;
P p = Al::allocate(alloc_node, 1);
if ( 0 == p )
throw std::bad_alloc(); // TODO throw different exception
auto_deallocator<AllocNode> deallocator(alloc_node, p);
Al::construct(alloc_node, boost::addressof(*p), alloc_node);
deallocator.release();
return p;
}
};
// destroy_node_impl
template <typename Node>
struct destroy_dynamic_node
{
template <typename AllocNode, typename BaseNodePtr>
static inline void apply(AllocNode & alloc_node, BaseNodePtr n)
{
typedef boost::container::allocator_traits<AllocNode> Al;
typedef typename Al::pointer P;
P p(&static_cast<Node&>(rtree::get<Node>(*n)));
Al::destroy(alloc_node, boost::addressof(*p));
Al::deallocate(alloc_node, p, 1);
}
};
// create_node
template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
struct create_node<
Allocators,
dynamic_internal_node<Value, Parameters, Box, Allocators, Tag>
>
{
static inline typename Allocators::node_pointer
apply(Allocators & allocators)
{
return create_dynamic_node<
typename Allocators::node_pointer,
dynamic_internal_node<Value, Parameters, Box, Allocators, Tag>
>::apply(allocators.internal_node_allocator());
}
};
template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
struct create_node<
Allocators,
dynamic_leaf<Value, Parameters, Box, Allocators, Tag>
>
{
static inline typename Allocators::node_pointer
apply(Allocators & allocators)
{
return create_dynamic_node<
typename Allocators::node_pointer,
dynamic_leaf<Value, Parameters, Box, Allocators, Tag>
>::apply(allocators.leaf_allocator());
}
};
// destroy_node
template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
struct destroy_node<
Allocators,
dynamic_internal_node<Value, Parameters, Box, Allocators, Tag>
>
{
static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
{
destroy_dynamic_node<
dynamic_internal_node<Value, Parameters, Box, Allocators, Tag>
>::apply(allocators.internal_node_allocator(), n);
}
};
template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
struct destroy_node<
Allocators,
dynamic_leaf<Value, Parameters, Box, Allocators, Tag>
>
{
static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
{
destroy_dynamic_node<
dynamic_leaf<Value, Parameters, Box, Allocators, Tag>
>::apply(allocators.leaf_allocator(), n);
}
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_HPP

View File

@@ -0,0 +1,172 @@
// Boost.Geometry Index
//
// R-tree nodes based on runtime-polymorphism, storing static-size containers
//
// 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_NODE_NODE_DEFAULT_STATIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct dynamic_internal_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
: public dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
{
typedef typename Allocators::leaf_allocator_type::template rebind<
rtree::ptr_pair<Box, typename Allocators::node_pointer>
>::other elements_allocator_type;
typedef detail::varray<
rtree::ptr_pair<Box, typename Allocators::node_pointer>,
Parameters::max_elements + 1,
elements_allocator_type
> elements_type;
template <typename Alloc>
inline dynamic_internal_node(Alloc const&) {}
void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, false> & v) { v(*this); }
void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, true> & v) const { v(*this); }
elements_type elements;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct dynamic_leaf<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
: public dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
{
typedef typename Allocators::leaf_allocator_type::template rebind<
Value
>::other elements_allocator_type;
typedef detail::varray<
Value,
Parameters::max_elements + 1,
elements_allocator_type
> elements_type;
template <typename Alloc>
inline dynamic_leaf(Alloc const&) {}
void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, false> & v) { v(*this); }
void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, true> & v) const { v(*this); }
elements_type elements;
};
// nodes traits
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
{
typedef dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag> type;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct internal_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
{
typedef dynamic_internal_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag> type;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct leaf<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
{
typedef dynamic_leaf<Value, Parameters, Box, Allocators, node_d_mem_static_tag> type;
};
template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
struct visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, IsVisitableConst>
{
typedef dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, IsVisitableConst> type;
};
// elements derived type
template <typename OldValue, size_t N, typename A, typename NewValue>
struct container_from_elements_type<detail::varray<OldValue, N, A>, NewValue>
{
typedef detail::varray<NewValue, N> type;
};
// allocators
template <typename Allocator, typename Value, typename Parameters, typename Box>
class allocators<Allocator, Value, Parameters, Box, node_d_mem_static_tag>
: public Allocator::template rebind<
typename internal_node<
Value, Parameters, Box,
allocators<Allocator, Value, Parameters, Box, node_d_mem_static_tag>,
node_d_mem_static_tag
>::type
>::other
, public Allocator::template rebind<
typename leaf<
Value, Parameters, Box,
allocators<Allocator, Value, Parameters, Box, node_d_mem_static_tag>,
node_d_mem_static_tag
>::type
>::other
{
public:
typedef typename Allocator::size_type size_type;
typedef typename Allocator::template rebind<
typename node<Value, Parameters, Box, allocators, node_d_mem_static_tag>::type
>::other::pointer node_pointer;
typedef typename Allocator::template rebind<
typename internal_node<Value, Parameters, Box, allocators, node_d_mem_static_tag>::type
>::other::pointer internal_node_pointer;
typedef typename Allocator::template rebind<
typename internal_node<Value, Parameters, Box, allocators, node_d_mem_static_tag>::type
>::other internal_node_allocator_type;
typedef typename Allocator::template rebind<
typename leaf<Value, Parameters, Box, allocators, node_d_mem_static_tag>::type
>::other leaf_allocator_type;
inline allocators()
: internal_node_allocator_type()
, leaf_allocator_type()
{}
inline explicit allocators(Allocator const& alloc)
: internal_node_allocator_type(alloc)
, leaf_allocator_type(alloc)
{}
inline allocators(BOOST_FWD_REF(allocators) a)
: internal_node_allocator_type(boost::move(a.internal_node_allocator()))
, leaf_allocator_type(boost::move(a.leaf_allocator()))
{}
void swap(allocators & a)
{
boost::swap(internal_node_allocator(), a.internal_node_allocator());
boost::swap(leaf_allocator(), a.leaf_allocator());
}
bool operator==(allocators const& a) const { return leaf_allocator() == a.leaf_allocator(); }
template <typename Alloc>
bool operator==(Alloc const& a) const { return leaf_allocator() == leaf_allocator_type(a); }
Allocator allocator() const { return Allocator(leaf_allocator()); }
internal_node_allocator_type & internal_node_allocator() { return *this; }
internal_node_allocator_type const& internal_node_allocator() const { return *this; }
leaf_allocator_type & leaf_allocator() { return *this; }
leaf_allocator_type const& leaf_allocator() const{ return *this; }
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_HPP

View File

@@ -0,0 +1,249 @@
// Boost.Geometry Index
//
// R-tree nodes based on Boost.Variant, storing std::vectors
//
// 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_NODE_NODE_DEFAULT_VARIANT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_VARIANT_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// nodes default types
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct static_internal_node
{
typedef typename Allocators::node_allocator_type::template rebind<
rtree::ptr_pair<Box, typename Allocators::node_pointer>
>::other elements_allocator_type;
typedef boost::container::vector<
rtree::ptr_pair<Box, typename Allocators::node_pointer>,
elements_allocator_type
> elements_type;
template <typename Al>
inline static_internal_node(Al const& al)
: elements(al)
{}
elements_type elements;
};
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct static_leaf
{
typedef typename Allocators::node_allocator_type::template rebind<
Value
>::other elements_allocator_type;
typedef boost::container::vector<
Value,
elements_allocator_type
> elements_type;
template <typename Al>
inline static_leaf(Al const& al)
: elements(al)
{}
elements_type elements;
};
// nodes traits
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct node<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>
{
typedef boost::variant<
static_leaf<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>,
static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>
> type;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct internal_node<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>
{
typedef static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag> type;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct leaf<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>
{
typedef static_leaf<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag> type;
};
// visitor traits
template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
struct visitor<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag, IsVisitableConst>
{
typedef static_visitor<> type;
};
// allocators
template <typename Allocator, typename Value, typename Parameters, typename Box>
class allocators<Allocator, Value, Parameters, Box, node_s_mem_dynamic_tag>
: public Allocator::template rebind<
typename node<Value, Parameters, Box, allocators<Allocator, Value, Parameters, Box, node_s_mem_dynamic_tag>, node_s_mem_dynamic_tag>::type
>::other
{
public:
typedef typename Allocator::size_type size_type;
typedef typename Allocator::template rebind<
typename node<Value, Parameters, Box, allocators, node_s_mem_dynamic_tag>::type
>::other::pointer node_pointer;
typedef typename Allocator::template rebind<
typename internal_node<Value, Parameters, Box, allocators, node_s_mem_dynamic_tag>::type
>::other::pointer internal_node_pointer;
typedef typename Allocator::template rebind<
typename node<Value, Parameters, Box, allocators, node_s_mem_dynamic_tag>::type
>::other node_allocator_type;
inline allocators()
: node_allocator_type()
{}
inline explicit allocators(Allocator const& alloc)
: node_allocator_type(alloc)
{}
inline allocators(BOOST_FWD_REF(allocators) a)
: node_allocator_type(boost::move(a.node_allocator()))
{}
void swap(allocators & a)
{
boost::swap(node_allocator(), a.node_allocator());
}
bool operator==(allocators const& a) const { return node_allocator() == a.node_allocator(); }
template <typename Alloc>
bool operator==(Alloc const& a) const { return node_allocator() == node_allocator_type(a); }
Allocator allocator() const { return Allocator(node_allocator()); }
node_allocator_type & node_allocator() { return *this; }
node_allocator_type const& node_allocator() const { return *this; }
};
// create_node_variant
template <typename VariantPtr, typename Node>
struct create_static_node
{
template <typename AllocNode>
static inline VariantPtr apply(AllocNode & alloc_node)
{
typedef boost::container::allocator_traits<AllocNode> Al;
typedef typename Al::pointer P;
P p = Al::allocate(alloc_node, 1);
if ( 0 == p )
throw std::bad_alloc();
auto_deallocator<AllocNode> deallocator(alloc_node, p);
Al::construct(alloc_node, boost::addressof(*p), Node(alloc_node)); // implicit cast to Variant
deallocator.release();
return p;
}
};
// destroy_node_variant
template <typename Node>
struct destroy_static_node
{
template <typename AllocNode, typename VariantPtr>
static inline void apply(AllocNode & alloc_node, VariantPtr n)
{
typedef boost::container::allocator_traits<AllocNode> Al;
Al::destroy(alloc_node, boost::addressof(*n));
Al::deallocate(alloc_node, n, 1);
}
};
// create_node
template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
struct create_node<
Allocators,
static_internal_node<Value, Parameters, Box, Allocators, Tag>
>
{
static inline typename Allocators::node_pointer
apply(Allocators & allocators)
{
return create_static_node<
typename Allocators::node_pointer,
static_internal_node<Value, Parameters, Box, Allocators, Tag>
>::apply(allocators.node_allocator());
}
};
template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
struct create_node<
Allocators,
static_leaf<Value, Parameters, Box, Allocators, Tag>
>
{
static inline typename Allocators::node_pointer
apply(Allocators & allocators)
{
return create_static_node<
typename Allocators::node_pointer,
static_leaf<Value, Parameters, Box, Allocators, Tag>
>::apply(allocators.node_allocator());
}
};
// destroy_node
template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
struct destroy_node<
Allocators,
static_internal_node<Value, Parameters, Box, Allocators, Tag>
>
{
static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
{
destroy_static_node<
static_internal_node<Value, Parameters, Box, Allocators, Tag>
>::apply(allocators.node_allocator(), n);
}
};
template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
struct destroy_node<
Allocators,
static_leaf<Value, Parameters, Box, Allocators, Tag>
>
{
static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
{
destroy_static_node<
static_leaf<Value, Parameters, Box, Allocators, Tag>
>::apply(allocators.node_allocator(), n);
}
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_VARIANT_HPP

View File

@@ -0,0 +1,177 @@
// Boost.Geometry Index
//
// R-tree nodes based on Boost.Variant, storing static-size containers
//
// 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_NODE_NODE_DEFAULT_STATIC_VARIANT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_VARIANT_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// nodes default types
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
{
typedef typename Allocators::node_allocator_type::template rebind<
rtree::ptr_pair<Box, typename Allocators::node_pointer>
>::other elements_allocator_type;
typedef detail::varray<
rtree::ptr_pair<Box, typename Allocators::node_pointer>,
Parameters::max_elements + 1,
elements_allocator_type
> elements_type;
template <typename Alloc>
inline static_internal_node(Alloc const&) {}
elements_type elements;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
{
typedef typename Allocators::node_allocator_type::template rebind<
Value
>::other elements_allocator_type;
typedef detail::varray<
Value,
Parameters::max_elements + 1,
elements_allocator_type
> elements_type;
template <typename Alloc>
inline static_leaf(Alloc const&) {}
elements_type elements;
};
// nodes traits
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
{
typedef boost::variant<
static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>,
static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
> type;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
{
typedef static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag> type;
};
template <typename Value, typename Parameters, typename Box, typename Allocators>
struct leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
{
typedef static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag> type;
};
// visitor traits
template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
struct visitor<Value, Parameters, Box, Allocators, node_s_mem_static_tag, IsVisitableConst>
{
typedef static_visitor<> type;
};
// allocators
template <typename Allocator, typename Value, typename Parameters, typename Box>
struct allocators<Allocator, Value, Parameters, Box, node_s_mem_static_tag>
: public Allocator::template rebind<
typename node<Value, Parameters, Box, allocators<Allocator, Value, Parameters, Box, node_s_mem_static_tag>, node_s_mem_static_tag>::type
>::other
{
public:
typedef typename Allocator::size_type size_type;
typedef typename Allocator::template rebind<
typename node<Value, Parameters, Box, allocators, node_s_mem_static_tag>::type
>::other::pointer node_pointer;
typedef typename Allocator::template rebind<
typename internal_node<Value, Parameters, Box, allocators, node_s_mem_static_tag>::type
>::other::pointer internal_node_pointer;
typedef typename Allocator::template rebind<
typename node<Value, Parameters, Box, allocators, node_s_mem_static_tag>::type
>::other node_allocator_type;
inline allocators()
: node_allocator_type()
{}
inline explicit allocators(Allocator const& alloc)
: node_allocator_type(alloc)
{}
inline allocators(BOOST_FWD_REF(allocators) a)
: node_allocator_type(boost::move(a.node_allocator()))
{}
void swap(allocators & a)
{
boost::swap(node_allocator(), a.node_allocator());
}
bool operator==(allocators const& a) const { return node_allocator() == a.node_allocator(); }
template <typename Alloc>
bool operator==(Alloc const& a) const { return node_allocator() == node_allocator_type(a); }
Allocator allocator() const { return Allocator(node_allocator()); }
node_allocator_type & node_allocator() { return *this; }
node_allocator_type const& node_allocator() const { return *this; }
};
// create_node
template <typename Allocators, typename Value, typename Parameters, typename Box>
struct create_node<
Allocators,
static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
>
{
static inline typename Allocators::node_pointer
apply(Allocators & allocators)
{
return create_static_node<
typename Allocators::node_pointer,
static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
>::template apply(allocators.node_allocator());
}
};
template <typename Allocators, typename Value, typename Parameters, typename Box>
struct create_node<
Allocators,
static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
>
{
static inline typename Allocators::node_pointer
apply(Allocators & allocators)
{
return create_static_node<
typename Allocators::node_pointer,
static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
>::template apply(allocators.node_allocator());
}
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_VARIANT_HPP

View File

@@ -0,0 +1,69 @@
// Boost.Geometry Index
//
// Pairs intended to be used internally in nodes.
//
// 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_NODE_PAIRS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_PAIRS_HPP
#include <boost/move/move.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
template <typename First, typename Pointer>
class ptr_pair
{
public:
typedef First first_type;
typedef Pointer second_type;
ptr_pair(First const& f, Pointer s) : first(f), second(s) {}
ptr_pair(ptr_pair const& p) : first(p.first), second(p.second) {}
ptr_pair & operator=(ptr_pair const& p) { first = p.first; second = p.second; return *this; }
first_type first;
second_type second;
};
template <typename First, typename Pointer> inline
ptr_pair<First, Pointer>
make_ptr_pair(First const& f, Pointer s)
{
return ptr_pair<First, Pointer>(f, s);
}
template <typename First, typename Pointer>
class exclusive_ptr_pair
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(exclusive_ptr_pair)
public:
typedef First first_type;
typedef Pointer second_type;
exclusive_ptr_pair(First const& f, Pointer s) : first(f), second(s) {}
// INFO - members aren't really moved!
exclusive_ptr_pair(BOOST_RV_REF(exclusive_ptr_pair) p) : first(p.first), second(p.second) { p.second = 0; }
exclusive_ptr_pair & operator=(BOOST_RV_REF(exclusive_ptr_pair) p) { first = p.first; second = p.second; p.second = 0; return *this; }
first_type first;
second_type second;
};
template <typename First, typename Pointer> inline
exclusive_ptr_pair<First, Pointer>
make_exclusive_ptr_pair(First const& f, Pointer s)
{
return exclusive_ptr_pair<First, Pointer>(f, s);
}
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_PAIRS_HPP

View File

@@ -0,0 +1,66 @@
// Boost.Geometry Index
//
// R-tree nodes static visitor related code
//
// 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_NODE_STATIC_VISITOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_STATIC_VISITOR_HPP
#include <boost/variant.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// nodes variants forward declarations
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct static_internal_node;
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct static_leaf;
// nodes conversion
template <typename V, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
inline V & get(
boost::variant<
static_leaf<Value, Parameters, Box, Allocators, Tag>,
static_internal_node<Value, Parameters, Box, Allocators, Tag>
> & v)
{
return boost::get<V>(v);
}
// apply visitor
template <typename Visitor, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
inline void apply_visitor(Visitor & v,
boost::variant<
static_leaf<Value, Parameters, Box, Allocators, Tag>,
static_internal_node<Value, Parameters, Box, Allocators, Tag>
> & n)
{
boost::apply_visitor(v, n);
}
template <typename Visitor, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
inline void apply_visitor(Visitor & v,
boost::variant<
static_leaf<Value, Parameters, Box, Allocators, Tag>,
static_internal_node<Value, Parameters, Box, Allocators, Tag>
> const& n)
{
boost::apply_visitor(v, n);
}
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_STATIC_VISITOR_HPP

View File

@@ -0,0 +1,155 @@
// Boost.Geometry Index
//
// R-tree options, algorithms, parameters
//
// 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_OPTIONS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_OPTIONS_HPP
#include <boost/geometry/index/parameters.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// InsertTag
struct insert_default_tag {};
struct insert_reinsert_tag {};
// ChooseNextNodeTag
struct choose_by_content_diff_tag {};
struct choose_by_overlap_diff_tag {};
// SplitTag
struct split_default_tag {};
//struct split_kmeans_tag {};
// RedistributeTag
struct linear_tag {};
struct quadratic_tag {};
struct rstar_tag {};
// NodeTag
struct node_d_mem_dynamic_tag {};
struct node_d_mem_static_tag {};
struct node_s_mem_dynamic_tag {};
struct node_s_mem_static_tag {};
template <typename Parameters, typename InsertTag, typename ChooseNextNodeTag, typename SplitTag, typename RedistributeTag, typename NodeTag>
struct options
{
typedef Parameters parameters_type;
typedef InsertTag insert_tag;
typedef ChooseNextNodeTag choose_next_node_tag;
typedef SplitTag split_tag;
typedef RedistributeTag redistribute_tag;
typedef NodeTag node_tag;
};
template <typename Parameters>
struct options_type
{
// TODO: awulkiew - use static assert
};
template <size_t MaxElements, size_t MinElements>
struct options_type< index::linear<MaxElements, MinElements> >
{
typedef options<
index::linear<MaxElements, MinElements>,
insert_default_tag,
choose_by_content_diff_tag,
split_default_tag,
linear_tag,
node_d_mem_static_tag
> type;
};
template <size_t MaxElements, size_t MinElements>
struct options_type< index::quadratic<MaxElements, MinElements> >
{
typedef options<
index::quadratic<MaxElements, MinElements>,
insert_default_tag,
choose_by_content_diff_tag,
split_default_tag,
quadratic_tag,
node_d_mem_static_tag
> type;
};
template <size_t MaxElements, size_t MinElements, size_t OverlapCostThreshold, size_t ReinsertedElements>
struct options_type< index::rstar<MaxElements, MinElements, OverlapCostThreshold, ReinsertedElements> >
{
typedef options<
index::rstar<MaxElements, MinElements, OverlapCostThreshold, ReinsertedElements>,
insert_reinsert_tag,
choose_by_overlap_diff_tag,
split_default_tag,
rstar_tag,
node_d_mem_static_tag
> type;
};
//template <size_t MaxElements, size_t MinElements>
//struct options_type< kmeans<MaxElements, MinElements> >
//{
// typedef options<
// kmeans<MaxElements, MinElements>,
// insert_default_tag,
// choose_by_content_diff_tag, // change it?
// split_kmeans_tag,
// int, // dummy tag - not used for now
// node_d_mem_static_tag
// > type;
//};
template <>
struct options_type< index::dynamic_linear >
{
typedef options<
index::dynamic_linear,
insert_default_tag,
choose_by_content_diff_tag,
split_default_tag,
linear_tag,
node_d_mem_dynamic_tag
> type;
};
template <>
struct options_type< index::dynamic_quadratic >
{
typedef options<
index::dynamic_quadratic,
insert_default_tag,
choose_by_content_diff_tag,
split_default_tag,
quadratic_tag,
node_d_mem_dynamic_tag
> type;
};
template <>
struct options_type< index::dynamic_rstar >
{
typedef options<
index::dynamic_rstar,
insert_reinsert_tag,
choose_by_overlap_diff_tag,
split_default_tag,
rstar_tag,
node_d_mem_dynamic_tag
> type;
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_OPTIONS_HPP

View File

@@ -0,0 +1,16 @@
// Boost.Geometry Index
//
// R-tree quadratic 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_QUADRATIC_QUADRATIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_QUADRATIC_HPP
#include <boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp>
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_QUADRATIC_HPP

View File

@@ -0,0 +1,293 @@
// Boost.Geometry Index
//
// R-tree quadratic split 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_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP
#include <algorithm>
#include <boost/geometry/index/detail/algorithms/content.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/insert.hpp>
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
namespace quadratic {
template <typename Elements, typename Parameters, typename Translator, typename Box>
struct pick_seeds
{
typedef typename Elements::value_type element_type;
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef typename index::detail::traits::coordinate_type<indexable_type>::type coordinate_type;
typedef Box box_type;
typedef typename index::detail::default_content_result<box_type>::type content_type;
static inline void apply(Elements const& elements,
Parameters const& parameters,
Translator const& tr,
size_t & seed1,
size_t & seed2)
{
const size_t elements_count = parameters.get_max_elements() + 1;
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "wrong number of elements");
BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");
content_type greatest_free_content = 0;
seed1 = 0;
seed2 = 1;
for ( size_t i = 0 ; i < elements_count - 1 ; ++i )
{
for ( size_t j = i + 1 ; j < elements_count ; ++j )
{
indexable_type const& ind1 = rtree::element_indexable(elements[i], tr);
indexable_type const& ind2 = rtree::element_indexable(elements[j], tr);
box_type enlarged_box;
geometry::convert(ind1, enlarged_box);
geometry::expand(enlarged_box, ind2);
content_type free_content = (index::detail::content(enlarged_box) - index::detail::content(ind1)) - index::detail::content(ind2);
if ( greatest_free_content < free_content )
{
greatest_free_content = free_content;
seed1 = i;
seed2 = j;
}
}
}
BOOST_GEOMETRY_INDEX_DETAIL_USE_PARAM(parameters)
}
};
} // namespace quadratic
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
struct redistribute_elements<Value, Options, Translator, Box, Allocators, quadratic_tag>
{
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 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;
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef typename index::detail::traits::coordinate_type<indexable_type>::type coordinate_type;
elements_type & elements1 = rtree::elements(n);
elements_type & elements2 = rtree::elements(second_node);
BOOST_GEOMETRY_INDEX_ASSERT(elements1.size() == parameters.get_max_elements() + 1, "unexpected elements number");
// copy original elements
elements_type elements_copy(elements1); // MAY THROW, STRONG (alloc, copy)
elements_type elements_backup(elements1); // MAY THROW, STRONG (alloc, copy)
// calculate initial seeds
size_t seed1 = 0;
size_t seed2 = 0;
quadratic::pick_seeds<
elements_type,
parameters_type,
Translator,
Box
>::apply(elements_copy, parameters, translator, seed1, seed2);
// prepare nodes' elements containers
elements1.clear();
BOOST_GEOMETRY_INDEX_ASSERT(elements2.empty(), "second node's elements container should be empty");
try
{
// add seeds
elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy)
elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)
// calculate boxes
geometry::convert(rtree::element_indexable(elements_copy[seed1], translator), box1);
geometry::convert(rtree::element_indexable(elements_copy[seed2], translator), box2);
// remove seeds
if (seed1 < seed2)
{
rtree::move_from_back(elements_copy, elements_copy.begin() + seed2); // MAY THROW, STRONG (copy)
elements_copy.pop_back();
rtree::move_from_back(elements_copy, elements_copy.begin() + seed1); // MAY THROW, STRONG (copy)
elements_copy.pop_back();
}
else
{
rtree::move_from_back(elements_copy, elements_copy.begin() + seed1); // MAY THROW, STRONG (copy)
elements_copy.pop_back();
rtree::move_from_back(elements_copy, elements_copy.begin() + seed2); // MAY THROW, STRONG (copy)
elements_copy.pop_back();
}
// initialize areas
content_type content1 = index::detail::content(box1);
content_type content2 = index::detail::content(box2);
size_t remaining = elements_copy.size();
// redistribute the rest of the elements
while ( !elements_copy.empty() )
{
typename elements_type::reverse_iterator el_it = elements_copy.rbegin();
bool insert_into_group1 = false;
size_t elements1_count = elements1.size();
size_t elements2_count = elements2.size();
// if there is small number of elements left and the number of elements in node is lesser than min_elems
// just insert them to this node
if ( elements1_count + remaining <= parameters.get_min_elements() )
{
insert_into_group1 = true;
}
else if ( elements2_count + remaining <= parameters.get_min_elements() )
{
insert_into_group1 = false;
}
// insert the best element
else
{
// find element with minimum groups areas increses differences
content_type content_increase1 = 0;
content_type content_increase2 = 0;
el_it = pick_next(elements_copy.rbegin(), elements_copy.rend(),
box1, box2, content1, content2, translator,
content_increase1, content_increase2);
if ( content_increase1 < content_increase2 ||
( content_increase1 == content_increase2 && content1 < content2 ) ||
( content1 == content2 && elements1_count <= elements2_count ) )
{
insert_into_group1 = true;
}
else
{
insert_into_group1 = false;
}
}
// move element to the choosen group
element_type const& elem = *el_it;
indexable_type const& indexable = rtree::element_indexable(elem, translator);
if ( insert_into_group1 )
{
elements1.push_back(elem); // MAY THROW, STRONG (copy)
geometry::expand(box1, indexable);
content1 = index::detail::content(box1);
}
else
{
elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
geometry::expand(box2, indexable);
content2 = index::detail::content(box2);
}
BOOST_GEOMETRY_INDEX_ASSERT(!elements_copy.empty(), "expected more elements");
typename elements_type::iterator el_it_base = el_it.base();
rtree::move_from_back(elements_copy, --el_it_base); // MAY THROW, STRONG (copy)
elements_copy.pop_back();
BOOST_GEOMETRY_INDEX_ASSERT(0 < remaining, "expected more remaining elements");
--remaining;
}
}
catch(...)
{
//elements_copy.clear();
elements1.clear();
elements2.clear();
rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);
//elements_backup.clear();
throw; // RETHROW, BASIC
}
}
// TODO: awulkiew - change following function to static member of the pick_next class?
template <typename It>
static inline It pick_next(It first, It last,
Box const& box1, Box const& box2,
content_type const& content1, content_type const& content2,
Translator const& translator,
content_type & out_content_increase1, content_type & out_content_increase2)
{
typedef typename boost::iterator_value<It>::type element_type;
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
content_type greatest_content_incrase_diff = 0;
It out_it = first;
out_content_increase1 = 0;
out_content_increase2 = 0;
// find element with greatest difference between increased group's boxes areas
for ( It el_it = first ; el_it != last ; ++el_it )
{
indexable_type const& indexable = rtree::element_indexable(*el_it, translator);
// calculate enlarged boxes and areas
Box enlarged_box1(box1);
Box enlarged_box2(box2);
geometry::expand(enlarged_box1, indexable);
geometry::expand(enlarged_box2, indexable);
content_type enlarged_content1 = index::detail::content(enlarged_box1);
content_type enlarged_content2 = index::detail::content(enlarged_box2);
content_type content_incrase1 = (enlarged_content1 - content1);
content_type content_incrase2 = (enlarged_content2 - content2);
content_type content_incrase_diff = content_incrase1 < content_incrase2 ?
content_incrase2 - content_incrase1 : content_incrase1 - content_incrase2;
if ( greatest_content_incrase_diff < content_incrase_diff )
{
greatest_content_incrase_diff = content_incrase_diff;
out_it = el_it;
out_content_increase1 = content_incrase1;
out_content_increase2 = content_incrase2;
}
}
return out_it;
}
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP

View File

@@ -0,0 +1,246 @@
// Boost.Geometry Index
//
// R-tree R*-tree next node choosing 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_CHOOSE_NEXT_NODE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP
#include <algorithm>
#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/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)
{
children_type & children = rtree::elements(n);
// children are leafs
if ( node_relative_level <= 1 )
{
if ( 0 < parameters.get_overlap_cost_threshold() &&
parameters.get_overlap_cost_threshold() < children.size() )
return choose_by_nearly_minimum_overlap_cost(children, indexable, parameters.get_overlap_cost_threshold());
else
return choose_by_minimum_overlap_cost(children, indexable);
}
// children are internal nodes
else
return choose_by_minimum_content_cost(children, indexable);
BOOST_GEOMETRY_INDEX_DETAIL_USE_PARAM(parameters)
}
private:
template <typename Indexable>
static inline size_t choose_by_minimum_overlap_cost(children_type const& children,
Indexable const& indexable)
{
size_t children_count = children.size();
// 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 i = 0 ; i < children_count ; ++i )
{
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);
// calculate content and content diff
content_type content = index::detail::content(ch_i.first);
content_type content_diff = index::detail::content(box_exp) - content;
content_type overlap = 0;
content_type overlap_exp = 0;
// calculate overlap
for ( size_t j = 0 ; j < children_count ; ++j )
{
if ( i != j )
{
child_type const& ch_j = children[j];
overlap += index::detail::intersection_content(ch_i.first, ch_j.first);
overlap_exp += index::detail::intersection_content(box_exp, ch_j.first);
}
}
content_type overlap_diff = overlap_exp - overlap;
// 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_nearly_minimum_overlap_cost(children_type const& children,
Indexable const& indexable,
size_t overlap_cost_threshold)
{
const size_t children_count = children.size();
// create container of children sorted by content enlargement needed to include the new value
std::vector< boost::tuple<size_t, content_type, content_type> > sorted_children(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);
sorted_children[i] = boost::make_tuple(i, content_diff, content);
}
// sort by content_diff
std::sort(sorted_children.begin(), sorted_children.end(), content_diff_less);
BOOST_GEOMETRY_INDEX_ASSERT(overlap_cost_threshold <= children_count, "there are not enough children");
// for overlap_cost_threshold child nodes find the one with smallest overlap value
size_t choosen_index = 0;
content_type smallest_overlap_diff = (std::numeric_limits<content_type>::max)();
// for each node
for (size_t i = 0 ; i < overlap_cost_threshold ; ++i )
{
size_t child_index = boost::get<0>(sorted_children[i]);
typedef typename children_type::value_type child_type;
child_type const& ch_i = children[child_index];
Box box_exp(ch_i.first);
// calculate expanded box of child node ch_i
geometry::expand(box_exp, indexable);
content_type overlap = 0;
content_type overlap_exp = 0;
// calculate overlap
for ( size_t j = 0 ; j < children_count ; ++j )
{
if ( child_index != j )
{
child_type const& ch_j = children[j];
overlap += index::detail::intersection_content(ch_i.first, ch_j.first);
overlap_exp += index::detail::intersection_content(box_exp, ch_j.first);
}
}
content_type overlap_diff = overlap_exp - overlap;
// update result
if ( overlap_diff < smallest_overlap_diff )
{
smallest_overlap_diff = overlap_diff;
choosen_index = child_index;
}
}
return choosen_index;
}
static inline bool content_diff_less(boost::tuple<size_t, content_type, content_type> const& p1, boost::tuple<size_t, content_type, content_type> const& p2)
{
return boost::get<1>(p1) < boost::get<1>(p2) ||
(boost::get<1>(p1) == boost::get<1>(p2) && boost::get<2>(p1) < boost::get<2>(p2));
}
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

View File

@@ -0,0 +1,542 @@
// Boost.Geometry Index
//
// R-tree R*-tree insert 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_INSERT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_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;
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_distance_result<point_type>::type distance_type;
elements_type & elements = rtree::elements(n);
const size_t elements_count = parameters.get_max_elements() + 1;
const size_t reinserted_elements_count = parameters.get_reinserted_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<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<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)
}
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)
}
}
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);
}
throw; // RETHROW
}
BOOST_GEOMETRY_INDEX_DETAIL_USE_PARAM(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;
inline level_insert_base(node_pointer & root,
size_t & leafs_level,
Element const& element,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators,
size_t 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 &n) const
{
if ( !result_elements.empty() && !base::m_traverse_data.current_is_root() )
{
// calulate node's new box
base::m_traverse_data.current_element().first =
elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);
}
}
size_t 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;
inline level_insert(node_pointer & root,
size_t & leafs_level,
Element const& element,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators,
size_t 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");
try
{
// push new child node
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
}
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);
throw; // RETHROW
}
// 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;
inline level_insert(node_pointer & root,
size_t & leafs_level,
Value const& v,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators,
size_t 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;
inline level_insert(node_pointer & root,
size_t & leafs_level,
Value const& v,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators,
size_t 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;
public:
inline insert(node_pointer & root,
size_t & leafs_level,
Element const& element,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators,
size_t 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 & BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(n))
{
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root), "current node should be the root");
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)
}
}
inline void operator()(leaf & BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(n))
{
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<leaf>(*m_root), "current node should be the root");
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");
}
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);
try
{
rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
}
catch(...)
{
++it;
for ( ; it != elements.rend() ; ++it)
rtree::destroy_element<Value, Options, Translator, Box, Allocators>::apply(*it, m_allocators);
throw; // RETHROW
}
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_t & m_leafs_level;
Element const& m_element;
parameters_type const& m_parameters;
Translator const& m_translator;
size_t m_relative_level;
Allocators & m_allocators;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP

View File

@@ -0,0 +1,407 @@
// Boost.Geometry Index
//
// R-tree R*-tree split 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_REDISTRIBUTE_ELEMENTS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
#include <boost/geometry/index/detail/algorithms/margin.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, size_t Corner, size_t AxisIndex>
class element_axis_corner_less
{
public:
element_axis_corner_less(Translator const& tr)
: m_tr(tr)
{}
bool operator()(Element const& e1, Element const& e2) const
{
return index::detail::get<Corner, AxisIndex>(rtree::element_indexable(e1, m_tr))
< index::detail::get<Corner, AxisIndex>(rtree::element_indexable(e2, m_tr));
}
private:
Translator const& m_tr;
};
template <typename Parameters, 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 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;
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)
// sort elements
element_axis_corner_less<element_type, Translator, Corner, AxisIndex> elements_less(translator);
std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
// init outputs
choosen_index = parameters.get_min_elements();
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
size_t index_last = parameters.get_max_elements() - parameters.get_min_elements() + 2;
for ( size_t i = parameters.get_min_elements() ; 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);
if ( ovl < smallest_overlap || (ovl == smallest_overlap && con <= smallest_content) )
{
choosen_index = i;
smallest_overlap = ovl;
smallest_content = con;
}
}
BOOST_GEOMETRY_INDEX_DETAIL_USE_PARAM(parameters)
}
};
template <typename Parameters, typename Box, size_t AxisIndex, typename ElementIndexableTag>
struct choose_split_axis_and_index_for_axis
{
//BOOST_STATIC_ASSERT(0);
};
template <typename Parameters, typename Box, size_t AxisIndex>
struct choose_split_axis_and_index_for_axis<Parameters, Box, AxisIndex, box_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 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<Parameters, 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<Parameters, 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 Parameters, typename Box, size_t AxisIndex>
struct choose_split_axis_and_index_for_axis<Parameters, 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 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<Parameters, 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 Parameters, 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 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<Parameters, 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<
Parameters,
Box,
Dimension - 1,
typename index::detail::traits::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 Parameters, typename Box>
struct choose_split_axis_and_index<Parameters, 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 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<
Parameters,
Box,
0,
typename index::detail::traits::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>
struct partial_sort
{
BOOST_STATIC_ASSERT(0 < Dimension);
template <typename Elements, typename Translator>
static inline void apply(Elements & elements, const size_t axis, const size_t index, Translator const& tr)
{
if ( axis < Dimension - 1 )
{
partial_sort<Corner, Dimension - 1>::apply(elements, axis, index, tr); // MAY THROW, BASIC (copy)
}
else
{
BOOST_GEOMETRY_INDEX_ASSERT(axis == Dimension - 1, "unexpected axis value");
typedef typename Elements::value_type element_type;
element_axis_corner_less<element_type, Translator, Corner, Dimension - 1> less(tr);
std::partial_sort(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
}
}
};
template <size_t Corner>
struct partial_sort<Corner, 1>
{
template <typename Elements, typename Translator>
static inline void apply(Elements & elements,
const size_t BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(axis),
const size_t index,
Translator const& tr)
{
BOOST_GEOMETRY_INDEX_ASSERT(axis == 0, "unexpected axis value");
typedef typename Elements::value_type element_type;
element_axis_corner_less<element_type, Translator, Corner, 0> less(tr);
std::partial_sort(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
}
};
} // 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 = index::detail::traits::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;
elements_type & elements1 = rtree::elements(n);
elements_type & elements2 = rtree::elements(second_node);
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)();
rstar::choose_split_axis_and_index<
typename Options::parameters_type,
Box,
index::detail::traits::dimension<Box>::value
>::apply(elements1,
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 < index::detail::traits::dimension<Box>::value, "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");
// copy original elements
elements_type elements_copy(elements1); // MAY THROW, STRONG
elements_type elements_backup(elements1); // MAY THROW, STRONG
// TODO: awulkiew - check if std::partial_sort produces the same result as std::sort
if ( split_corner == static_cast<size_t>(min_corner) )
rstar::partial_sort<min_corner, dimension>
::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
else
rstar::partial_sort<max_corner, dimension>
::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
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);
}
catch(...)
{
//elements_copy.clear();
elements1.clear();
elements2.clear();
rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);
//elements_backup.clear();
throw; // RETHROW, BASIC
}
}
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP

View File

@@ -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

View File

@@ -0,0 +1,144 @@
// Boost.Geometry Index
//
// R-tree boxes validating visitor 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_VISITORS_ARE_BOXES_OK_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ARE_BOXES_OK_HPP
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/index/detail/rtree/node/node.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
namespace visitors {
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class are_boxes_ok
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
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;
public:
are_boxes_ok(Translator const& tr, bool exact_match)
: result(false), m_tr(tr), m_is_root(true), m_exact_match(exact_match)
{}
void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
if (elements.empty())
{
result = false;
return;
}
Box box_bckup = m_box;
bool is_root_bckup = m_is_root;
m_is_root = false;
for ( typename elements_type::const_iterator it = elements.begin();
it != elements.end() ; ++it)
{
m_box = it->first;
rtree::apply_visitor(*this, *it->second);
if ( result == false )
return;
}
m_box = box_bckup;
m_is_root = is_root_bckup;
Box box_exp;
geometry::convert(elements.front().first, box_exp);
for( typename elements_type::const_iterator it = elements.begin() + 1;
it != elements.end() ; ++it)
{
geometry::expand(box_exp, it->first);
}
if ( m_exact_match )
result = m_is_root || geometry::equals(box_exp, m_box);
else
result = m_is_root || geometry::covered_by(box_exp, m_box);
}
void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
// non-root node
if (!m_is_root)
{
if ( elements.empty() )
{
result = false;
return;
}
Box box_exp;
geometry::convert(m_tr(elements.front()), box_exp);
for(typename elements_type::const_iterator it = elements.begin() + 1;
it != elements.end() ; ++it)
{
geometry::expand(box_exp, m_tr(*it));
}
if ( m_exact_match )
result = geometry::equals(box_exp, m_box);
else
result = geometry::covered_by(box_exp, m_box);
}
else
result = true;
}
bool result;
private:
Translator const& m_tr;
Box m_box;
bool m_is_root;
bool m_exact_match;
};
} // namespace visitors
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_DEBUG_INTERFACE
#error "To use are_boxes_ok BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_DEBUG_INTERFACE should be defined before including the rtree"
#endif
template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
bool are_boxes_ok(index::rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree,
bool exact_match = true)
{
typedef index::rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> rt;
detail::rtree::visitors::are_boxes_ok<
typename rt::value_type,
typename rt::options_type,
typename rt::translator_type,
typename rt::box_type,
typename rt::allocators_type
> v(tree.translator(), exact_match);
tree.apply_visitor(v);
return v.result;
}
}}}}} // namespace boost::geometry::index::detail::rtree
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ARE_BOXES_OK_HPP

View File

@@ -0,0 +1,114 @@
// Boost.Geometry Index
//
// R-tree levels validating visitor 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_VISITORS_ARE_LEVELS_OK_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ARE_LEVELS_OK_HPP
#include <boost/geometry/index/detail/rtree/node/node.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
namespace visitors {
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class are_levels_ok
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
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;
public:
inline are_levels_ok(Translator const& tr)
: result(true), m_tr(tr), m_leafs_level((std::numeric_limits<size_t>::max)()), m_current_level(0)
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
if (elements.empty())
{
result = false;
return;
}
size_t current_level_backup = m_current_level;
++m_current_level;
for ( typename elements_type::const_iterator it = elements.begin();
it != elements.end() ; ++it)
{
rtree::apply_visitor(*this, *it->second);
if ( result == false )
return;
}
m_current_level = current_level_backup;
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
// empty leaf in non-root node
if (0 < m_current_level && elements.empty())
{
result = false;
return;
}
if ( m_leafs_level == (std::numeric_limits<size_t>::max)() )
{
m_leafs_level = m_current_level;
}
else if ( m_leafs_level != m_current_level )
{
result = false;
}
}
bool result;
private:
Translator const& m_tr;
size_t m_leafs_level;
size_t m_current_level;
};
} // namespace visitors
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_DEBUG_INTERFACE
#error "To use are_levels_ok() BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_DEBUG_INTERFACE should be defined before including the rtree"
#endif
template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
bool are_levels_ok(index::rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)
{
typedef index::rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> rt;
detail::rtree::visitors::are_levels_ok<
typename rt::value_type,
typename rt::options_type,
typename rt::translator_type,
typename rt::box_type,
typename rt::allocators_type
> v(tree.translator());
tree.apply_visitor(v);
return v.result;
}
}}}}} // namespace boost::geometry::index::detail::rtree
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ARE_LEVELS_OK_HPP

View File

@@ -0,0 +1,55 @@
// Boost.Geometry Index
//
// R-tree node children box calculating visitor 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_VISITORS_CHILDREN_BOX_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class children_box
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
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;
public:
inline children_box(Box & result, Translator const& tr)
: m_result(result), m_tr(tr)
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
m_result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
m_result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
}
private:
Box & m_result;
Translator const& m_tr;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP

View File

@@ -0,0 +1,92 @@
// Boost.Geometry Index
//
// R-tree deep copying visitor 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_VISITORS_COPY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class copy
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
{
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 rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
typedef typename Allocators::node_pointer node_pointer;
explicit inline copy(Allocators & allocators)
: result(0)
, m_allocators(allocators)
{}
inline void operator()(internal_node & n)
{
node_pointer raw_new_node = rtree::create_node<Allocators, internal_node>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)
node_auto_ptr new_node(raw_new_node, m_allocators);
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type & elements = rtree::elements(n);
elements_type & elements_dst = rtree::elements(rtree::get<internal_node>(*new_node));
for (typename elements_type::iterator it = elements.begin();
it != elements.end(); ++it)
{
rtree::apply_visitor(*this, *it->second); // MAY THROW (V, E: alloc, copy, N: alloc)
// for exception safety
node_auto_ptr auto_result(result, m_allocators);
elements_dst.push_back( rtree::make_ptr_pair(it->first, result) ); // MAY THROW, STRONG (E: alloc, copy)
auto_result.release();
}
result = new_node.get();
new_node.release();
}
inline void operator()(leaf & l)
{
node_pointer raw_new_node = rtree::create_node<Allocators, leaf>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)
node_auto_ptr new_node(raw_new_node, m_allocators);
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type & elements = rtree::elements(l);
elements_type & elements_dst = rtree::elements(rtree::get<leaf>(*new_node));
for (typename elements_type::iterator it = elements.begin();
it != elements.end(); ++it)
{
elements_dst.push_back(*it); // MAY THROW, STRONG (V: alloc, copy)
}
result = new_node.get();
new_node.release();
}
node_pointer result;
private:
Allocators & m_allocators;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP

View File

@@ -0,0 +1,118 @@
// Boost.Geometry Index
//
// R-tree count visitor 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_VISITORS_COUNT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename Indexable, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
struct count
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
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;
inline count(Indexable const& i, Translator const& t)
: indexable(i), tr(t), found_count(0)
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
// traverse nodes meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
if ( geometry::covered_by(indexable, it->first) )
rtree::apply_visitor(*this, *it->second);
}
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
// get all values meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
// if value meets predicates
if ( geometry::equals(indexable, tr(*it)) )
{
++found_count;
}
}
}
Indexable const& indexable;
Translator const& tr;
typename Allocators::size_type found_count;
};
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
struct count<Value, Value, Options, Translator, Box, Allocators>
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
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;
inline count(Value const& v, Translator const& t)
: value(v), tr(t), found_count(0)
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
// traverse nodes meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
if ( geometry::covered_by(tr(value), it->first) )
rtree::apply_visitor(*this, *it->second);
}
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
// get all values meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
// if value meets predicates
if ( tr.equals(value, *it) )
{
++found_count;
}
}
}
Value const& value;
Translator const& tr;
typename Allocators::size_type found_count;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP

View File

@@ -0,0 +1,70 @@
// Boost.Geometry Index
//
// R-tree destroying visitor 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_VISITORS_DELETE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class destroy
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
{
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 Allocators::node_pointer node_pointer;
inline destroy(node_pointer root_node, Allocators & allocators)
: m_current_node(root_node)
, m_allocators(allocators)
{}
inline void operator()(internal_node & n)
{
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_current_node), "invalid pointers");
node_pointer node_to_destroy = m_current_node;
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type & elements = rtree::elements(n);
for (typename elements_type::iterator it = elements.begin();
it != elements.end(); ++it)
{
m_current_node = it->second;
rtree::apply_visitor(*this, *m_current_node);
it->second = 0;
}
rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, node_to_destroy);
}
inline void operator()(leaf & BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(l))
{
BOOST_GEOMETRY_INDEX_ASSERT(&l == &rtree::get<leaf>(*m_current_node), "invalid pointers");
rtree::destroy_node<Allocators, leaf>::apply(m_allocators, m_current_node);
}
private:
node_pointer m_current_node;
Allocators & m_allocators;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP

View File

@@ -0,0 +1,221 @@
// Boost.Geometry Index
//
// R-tree OpenGL drawing visitor 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_VISITORS_GL_DRAW_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_GL_DRAW_HPP
#include <boost/geometry/index/detail/indexable.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
namespace dispatch {
template <typename Point, size_t Dimension>
struct gl_draw_point
{};
template <typename Point>
struct gl_draw_point<Point, 2>
{
static inline void apply(Point const& p, typename index::detail::traits::coordinate_type<Point>::type z)
{
glBegin(GL_POINT);
glVertex3f(geometry::get<0>(p), geometry::get<1>(p), z);
glEnd();
}
};
template <typename Box, size_t Dimension>
struct gl_draw_box
{};
template <typename Box>
struct gl_draw_box<Box, 2>
{
static inline void apply(Box const& b, typename index::detail::traits::coordinate_type<Box>::type z)
{
glBegin(GL_LINE_LOOP);
glVertex3f(geometry::get<min_corner, 0>(b), geometry::get<min_corner, 1>(b), z);
glVertex3f(geometry::get<max_corner, 0>(b), geometry::get<min_corner, 1>(b), z);
glVertex3f(geometry::get<max_corner, 0>(b), geometry::get<max_corner, 1>(b), z);
glVertex3f(geometry::get<min_corner, 0>(b), geometry::get<max_corner, 1>(b), z);
glEnd();
}
};
template <typename Indexable, typename Tag>
struct gl_draw_indexable
{
};
template <typename Indexable>
struct gl_draw_indexable<Indexable, box_tag>
{
static const size_t dimension = index::detail::traits::dimension<Indexable>::value;
static inline void apply(Indexable const& i, typename index::detail::traits::coordinate_type<Indexable>::type z)
{
gl_draw_box<Indexable, dimension>::apply(i, z);
}
};
template <typename Indexable>
struct gl_draw_indexable<Indexable, point_tag>
{
static const size_t dimension = index::detail::traits::dimension<Indexable>::value;
static inline void apply(Indexable const& i, typename index::detail::traits::coordinate_type<Indexable>::type z)
{
gl_draw_point<Indexable, dimension>::apply(i, z);
}
};
} // namespace dispatch
namespace detail {
template <typename Indexable>
inline void gl_draw_indexable(Indexable const& i, typename index::detail::traits::coordinate_type<Indexable>::type z)
{
dispatch::gl_draw_indexable<
Indexable,
typename index::detail::traits::tag<Indexable>::type
>::apply(i, z);
}
} // namespace detail
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
struct gl_draw : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
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;
inline gl_draw(Translator const& t,
size_t level_first = 0,
size_t level_last = (std::numeric_limits<size_t>::max)(),
typename index::detail::traits::coordinate_type<Box>::type z_coord_level_multiplier = 1
)
: tr(t)
, level_f(level_first)
, level_l(level_last)
, z_mul(z_coord_level_multiplier)
, level(0)
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
if ( level_f <= level )
{
size_t level_rel = level - level_f;
if ( level_rel == 0 )
glColor3f(0.75f, 0.0f, 0.0f);
else if ( level_rel == 1 )
glColor3f(0.0f, 0.75f, 0.0f);
else if ( level_rel == 2 )
glColor3f(0.0f, 0.0f, 0.75f);
else if ( level_rel == 3 )
glColor3f(0.75f, 0.75f, 0.0f);
else if ( level_rel == 4 )
glColor3f(0.75f, 0.0f, 0.75f);
else if ( level_rel == 5 )
glColor3f(0.0f, 0.75f, 0.75f);
else
glColor3f(0.5f, 0.5f, 0.5f);
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
detail::gl_draw_indexable(it->first, level_rel * z_mul);
}
}
size_t level_backup = level;
++level;
if ( level < level_l )
{
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
rtree::apply_visitor(*this, *it->second);
}
}
level = level_backup;
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
if ( level_f <= level )
{
size_t level_rel = level - level_f;
glColor3f(0.25f, 0.25f, 0.25f);
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
detail::gl_draw_indexable(tr(*it), level_rel * z_mul);
}
}
}
Translator const& tr;
size_t level_f;
size_t level_l;
typename index::detail::traits::coordinate_type<Box>::type z_mul;
size_t level;
};
}}} // namespace detail::rtree::visitors
template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
void gl_draw(rtree<Value, Options, IndexableGetter, EqualTo, Allocator> const& tree,
size_t level_first = 0,
size_t level_last = (std::numeric_limits<size_t>::max)(),
typename index::detail::traits::coordinate_type<
typename rtree<Value, Options, IndexableGetter, EqualTo, Allocator>::box_type
>::type z_coord_level_multiplier = 1
)
{
typedef rtree<Value, Options, IndexableGetter, EqualTo, Allocator> rtree_type;
typedef typename rtree_type::value_type value_type;
typedef typename rtree_type::options_type options_type;
typedef typename rtree_type::translator_type translator_type;
typedef typename rtree_type::box_type box_type;
typedef typename rtree_type::allocators_type allocators_type;
if ( !tree.empty() )
{
glColor3f(0.75f, 0.75f, 0.75f);
detail::rtree::visitors::detail::gl_draw_indexable(tree.bounds(), 0);
}
detail::rtree::visitors::gl_draw<value_type, options_type, translator_type, box_type, allocators_type>
gl_draw_v(tree.translator(), level_first, level_last, z_coord_level_multiplier);
tree.apply_visitor(gl_draw_v);
}
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_GL_DRAW_HPP

View File

@@ -0,0 +1,511 @@
// Boost.Geometry Index
//
// R-tree inserting visitor 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_VISITORS_INSERT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
#include <boost/geometry/index/detail/algorithms/content.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// Default choose_next_node
template <typename Value, typename Options, typename Box, typename Allocators, typename ChooseNextNodeTag>
class choose_next_node;
template <typename Value, typename Options, typename Box, typename Allocators>
class choose_next_node<Value, Options, Box, Allocators, choose_by_content_diff_tag>
{
public:
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 rtree::elements_type<internal_node>::type children_type;
typedef typename index::detail::default_content_result<Box>::type content_type;
template <typename Indexable>
static inline size_t apply(internal_node & n,
Indexable const& indexable,
parameters_type const& /*parameters*/,
size_t /*node_relative_level*/)
{
children_type & children = rtree::elements(n);
BOOST_GEOMETRY_INDEX_ASSERT(!children.empty(), "can't choose the next node if children are empty");
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)();
// caculate areas and areas of all nodes' boxes
for ( size_t i = 0 ; i < children_count ; ++i )
{
typedef typename children_type::value_type child_type;
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;
}
};
// ----------------------------------------------------------------------- //
// Not implemented here
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename RedistributeTag>
struct redistribute_elements
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_REDISTRIBUTE_TAG_TYPE,
(redistribute_elements));
};
// ----------------------------------------------------------------------- //
// Split algorithm
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename SplitTag>
class split
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_SPLIT_TAG_TYPE,
(split));
};
// Default split algorithm
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class split<Value, Options, Translator, Box, Allocators, split_default_tag>
{
protected:
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 rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
public:
typedef index::detail::varray<
typename rtree::elements_type<internal_node>::type::value_type,
1
> nodes_container_type;
template <typename Node>
static inline void apply(nodes_container_type & additional_nodes,
Node & n,
Box & n_box,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators)
{
// TODO - consider creating nodes always with sufficient memory allocated
// create additional node, use auto ptr for automatic destruction on exception
node_auto_ptr second_node(rtree::create_node<Allocators, Node>::apply(allocators), allocators); // MAY THROW, STRONG (N: alloc)
// create reference to the newly created node
Node & n2 = rtree::get<Node>(*second_node);
// NOTE: thread-safety
// After throwing an exception by redistribute_elements the original node may be not changed or
// both nodes may be empty. In both cases the tree won't be valid r-tree.
// The alternative is to create 2 (or more) additional nodes here and store backup info
// in the original node, then, if exception was thrown, the node would always have more than max
// elements.
// The alternative is to use moving semantics in the implementations of redistribute_elements,
// it will be possible to throw from boost::move() in the case of e.g. static size nodes.
// redistribute elements
Box box2;
redistribute_elements<
Value,
Options,
Translator,
Box,
Allocators,
typename Options::redistribute_tag
>::apply(n, n2, n_box, box2, parameters, translator, allocators); // MAY THROW (V, E: alloc, copy, copy)
// check numbers of elements
BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n).size() &&
rtree::elements(n).size() <= parameters.get_max_elements(),
"unexpected number of elements");
BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n2).size() &&
rtree::elements(n2).size() <= parameters.get_max_elements(),
"unexpected number of elements");
// return the list of newly created nodes (this algorithm returns one)
additional_nodes.push_back(rtree::make_ptr_pair(box2, second_node.get())); // MAY THROW, STRONG (alloc, copy)
// release the ptr
second_node.release();
}
};
// ----------------------------------------------------------------------- //
namespace visitors { namespace detail {
template <typename InternalNode, typename InternalNodePtr>
struct insert_traverse_data
{
typedef typename rtree::elements_type<InternalNode>::type elements_type;
typedef typename elements_type::value_type element_type;
insert_traverse_data()
: parent(0), current_child_index(0), current_level(0)
{}
void move_to_next_level(InternalNodePtr new_parent, size_t new_child_index)
{
parent = new_parent;
current_child_index = new_child_index;
++current_level;
}
bool current_is_root() const
{
return 0 == parent;
}
elements_type & parent_elements() const
{
BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");
return rtree::elements(*parent);
}
element_type & current_element() const
{
BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");
return rtree::elements(*parent)[current_child_index];
}
InternalNodePtr parent;
size_t current_child_index;
size_t current_level;
};
// Default insert visitor
template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class insert
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
{
protected:
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 rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
typedef typename Allocators::node_pointer node_pointer;
typedef typename Allocators::internal_node_pointer internal_node_pointer;
inline insert(node_pointer & root,
size_t & leafs_level,
Element const& element,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators,
size_t relative_level = 0
)
: m_element(element)
, m_parameters(parameters)
, m_translator(translator)
, m_relative_level(relative_level)
, m_level(leafs_level - relative_level)
, m_root_node(root)
, m_leafs_level(leafs_level)
, m_traverse_data()
, m_allocators(allocators)
{
BOOST_GEOMETRY_INDEX_ASSERT(m_relative_level <= leafs_level, "unexpected level value");
BOOST_GEOMETRY_INDEX_ASSERT(m_level <= m_leafs_level, "unexpected level value");
BOOST_GEOMETRY_INDEX_ASSERT(0 != m_root_node, "there is no root node");
// TODO
// assert - check if Box is correct
}
template <typename Visitor>
inline void traverse(Visitor & visitor, internal_node & n)
{
// choose next node
size_t choosen_node_index = rtree::choose_next_node<Value, Options, Box, Allocators, typename Options::choose_next_node_tag>::
apply(n, rtree::element_indexable(m_element, m_translator), m_parameters, m_leafs_level - m_traverse_data.current_level);
// expand the node to contain value
geometry::expand(
rtree::elements(n)[choosen_node_index].first,
rtree::element_indexable(m_element, m_translator));
// next traversing step
traverse_apply_visitor(visitor, n, choosen_node_index); // MAY THROW (V, E: alloc, copy, N:alloc)
}
// TODO: awulkiew - change post_traverse name to handle_overflow or overflow_treatment?
template <typename Node>
inline void post_traverse(Node &n)
{
BOOST_GEOMETRY_INDEX_ASSERT(m_traverse_data.current_is_root() ||
&n == &rtree::get<Node>(*m_traverse_data.current_element().second),
"if node isn't the root current_child_index should be valid");
// handle overflow
if ( m_parameters.get_max_elements() < rtree::elements(n).size() )
{
split(n); // MAY THROW (V, E: alloc, copy, N:alloc)
}
}
template <typename Visitor>
inline void traverse_apply_visitor(Visitor & visitor, internal_node &n, size_t choosen_node_index)
{
// save previous traverse inputs and set new ones
insert_traverse_data<internal_node, internal_node_pointer> backup_traverse_data = m_traverse_data;
// calculate new traverse inputs
m_traverse_data.move_to_next_level(&n, choosen_node_index);
// next traversing step
rtree::apply_visitor(visitor, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V, E: alloc, copy, N:alloc)
// restore previous traverse inputs
m_traverse_data = backup_traverse_data;
}
// TODO: consider - split result returned as OutIter is faster than reference to the container. Why?
template <typename Node>
inline void split(Node & n) const
{
typedef rtree::split<Value, Options, Translator, Box, Allocators, typename Options::split_tag> split_algo;
typename split_algo::nodes_container_type additional_nodes;
Box n_box;
split_algo::apply(additional_nodes, n, n_box, m_parameters, m_translator, m_allocators); // MAY THROW (V, E: alloc, copy, N:alloc)
BOOST_GEOMETRY_INDEX_ASSERT(additional_nodes.size() == 1, "unexpected number of additional nodes");
// TODO add all additional nodes
// For kmeans algorithm:
// elements number may be greater than node max elements count
// split and reinsert must take node with some elements count
// and container of additional elements (std::pair<Box, node*>s or Values)
// and translator + allocators
// where node_elements_count + additional_elements > node_max_elements_count
// What with elements other than std::pair<Box, node*> ?
// Implement template <node_tag> struct node_element_type or something like that
// for exception safety
node_auto_ptr additional_node_ptr(additional_nodes[0].second, m_allocators);
// node is not the root - just add the new node
if ( !m_traverse_data.current_is_root() )
{
// update old node's box
m_traverse_data.current_element().first = n_box;
// add new node to parent's children
m_traverse_data.parent_elements().push_back(additional_nodes[0]); // MAY THROW, STRONG (V, E: alloc, copy)
}
// node is the root - add level
else
{
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*m_root_node), "node should be the root");
// create new root and add nodes
node_auto_ptr new_root(rtree::create_node<Allocators, internal_node>::apply(m_allocators), m_allocators); // MAY THROW, STRONG (N:alloc)
try {
rtree::elements(rtree::get<internal_node>(*new_root)).push_back(rtree::make_ptr_pair(n_box, m_root_node)); // MAY THROW, STRONG (E:alloc, copy)
rtree::elements(rtree::get<internal_node>(*new_root)).push_back(additional_nodes[0]); // MAY THROW, STRONG (E:alloc, copy)
} catch (...) {
// clear new root to not delete in the ~node_auto_ptr() potentially stored old root node
rtree::elements(rtree::get<internal_node>(*new_root)).clear();
throw; // RETHROW
}
m_root_node = new_root.get();
++m_leafs_level;
new_root.release();
}
additional_node_ptr.release();
}
// TODO: awulkiew - implement dispatchable split::apply to enable additional nodes creation
Element const& m_element;
parameters_type const& m_parameters;
Translator const& m_translator;
const size_t m_relative_level;
const size_t m_level;
node_pointer & m_root_node;
size_t & m_leafs_level;
// traversing input parameters
insert_traverse_data<internal_node, internal_node_pointer> m_traverse_data;
Allocators & m_allocators;
};
} // namespace detail
// Insert visitor forward declaration
template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename InsertTag>
class insert;
// Default insert visitor used for nodes elements
// 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_default_tag>
: public detail::insert<Element, Value, Options, Translator, Box, Allocators>
{
public:
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 Options::parameters_type parameters_type;
typedef typename base::node_pointer node_pointer;
inline insert(node_pointer & root,
size_t & leafs_level,
Element & element,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators,
size_t relative_level = 0
)
: 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)
}
else
{
BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");
try
{
// push new child node
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
}
catch(...)
{
// if the insert fails above, the element won't be stored in the tree
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);
throw; // RETHROW
}
}
base::post_traverse(n); // MAY THROW (E: alloc, copy, N: alloc)
}
inline void operator()(leaf &)
{
BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");
}
};
// Default insert visitor specialized for Values elements
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class insert<Value, Value, Options, Translator, Box, Allocators, insert_default_tag>
: public detail::insert<Value, Value, Options, Translator, Box, Allocators>
{
public:
typedef detail::insert<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 base::node_pointer node_pointer;
inline insert(node_pointer & root,
size_t & leafs_level,
Value const& value,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators,
size_t relative_level = 0
)
: base(root, leafs_level, value, 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)
base::post_traverse(n); // MAY THROW (E: alloc, copy, N: alloc)
}
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::post_traverse(n); // MAY THROW (V: alloc, copy, N: alloc)
}
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP

View File

@@ -0,0 +1,41 @@
// Boost.Geometry Index
//
// R-tree leaf node checking visitor 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_VISITORS_IS_LEAF_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename Value, typename Options, typename Box, typename Allocators>
struct is_leaf : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
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;
inline void operator()(internal_node const&)
{
result = false;
}
inline void operator()(leaf const&)
{
result = true;
}
bool result;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP

View File

@@ -0,0 +1,338 @@
// Boost.Geometry Index
//
// R-tree k nearest neighbour query visitor 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_VISITORS_NEAREST_QUERY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_NEAREST_QUERY_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
// TODO: awulkiew - maby it's a good idea to check if curr_mindist < comp_mindist and then check predicates
// in store() or break store to 2 functions e.g. should_store() and store()
// - well not with this algorithm of storing k-th neighbor
//template <typename Value, typename Translator, typename Point>
//struct nearest_query_result_one
//{
//public:
// typedef typename geometry::default_distance_result<
// Point,
// typename translator::indexable_type<Translator>::type
// >::type distance_type;
//
// inline nearest_query_result_one(Value & value)
// : m_value(value)
// , m_comp_dist((std::numeric_limits<distance_type>::max)())
// {}
//
// inline void store(Value const& val, distance_type const& curr_comp_dist)
// {
// if ( curr_comp_dist < m_comp_dist )
// {
// m_comp_dist = curr_comp_dist;
// m_value = val;
// }
// }
//
// inline bool is_comparable_distance_valid() const
// {
// return m_comp_dist < (std::numeric_limits<distance_type>::max)();
// }
//
// inline distance_type comparable_distance() const
// {
// return m_comp_dist;
// }
//
// inline size_t finish()
// {
// return is_comparable_distance_valid() ? 1 : 0;
// }
//
//private:
// Value & m_value;
// distance_type m_comp_dist;
//};
template <typename Value, typename Translator, typename Point, typename OutIt>
struct nearest_query_result_k
{
public:
typedef typename geometry::default_distance_result<
Point,
typename indexable_type<Translator>::type
>::type distance_type;
inline explicit nearest_query_result_k(size_t k, OutIt out_it)
: m_count(k), m_out_it(out_it)
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_count, "Number of neighbors should be greater than 0");
m_neighbors.reserve(m_count);
}
inline void store(Value const& val, distance_type const& curr_comp_dist)
{
if ( m_neighbors.size() < m_count )
{
m_neighbors.push_back(std::make_pair(curr_comp_dist, val));
if ( m_neighbors.size() == m_count )
std::make_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
}
else
{
if ( curr_comp_dist < m_neighbors.front().first )
{
std::pop_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
m_neighbors.back().first = curr_comp_dist;
m_neighbors.back().second = val;
std::push_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
}
}
}
inline bool is_comparable_distance_valid() const
{
return m_neighbors.size() == m_count;
}
inline distance_type comparable_distance() const
{
// smallest distance is in the first neighbor only
// if there is at least m_count values found
// this is just for safety reasons since is_comparable_distance_valid() is checked earlier
// TODO - may be replaced by ASSERT
return m_neighbors.size() < m_count
? (std::numeric_limits<distance_type>::max)()
: m_neighbors.front().first;
}
inline size_t finish()
{
typedef typename std::vector< std::pair<distance_type, Value> >::const_iterator neighbors_iterator;
for ( neighbors_iterator it = m_neighbors.begin() ; it != m_neighbors.end() ; ++it, ++m_out_it )
*m_out_it = it->second;
return m_neighbors.size();
}
private:
inline static bool neighbors_less(
std::pair<distance_type, Value> const& p1,
std::pair<distance_type, Value> const& p2)
{
return p1.first < p2.first;
}
size_t m_count;
OutIt m_out_it;
std::vector< std::pair<distance_type, Value> > m_neighbors;
distance_type m_biggest_comp_dist;
};
// TODO: awulkiew - add additional pruning before adding nodes to the ABL
template <
typename Value,
typename Options,
typename Translator,
typename Box,
typename Allocators,
typename DistancesPredicates,
typename Predicates,
typename Result
>
class nearest_query
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
public:
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 index::detail::distances_calc<DistancesPredicates, Box, index::detail::bounds_tag> node_distances_calc;
typedef typename node_distances_calc::result_type node_distances_type;
typedef index::detail::distances_predicates_check<DistancesPredicates, Box, index::detail::bounds_tag> node_distances_predicates_check;
typedef index::detail::distances_calc<
DistancesPredicates,
typename indexable_type<Translator>::type,
index::detail::value_tag
> value_distances_calc;
typedef typename value_distances_calc::result_type value_distances_type;
typedef index::detail::distances_predicates_check<
DistancesPredicates,
typename indexable_type<Translator>::type,
index::detail::value_tag
> value_distances_predicates_check;
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
inline nearest_query(parameters_type const& parameters, Translator const& translator, DistancesPredicates const& dist_pred, Predicates const& pred, Result & r)
: m_parameters(parameters), m_translator(translator)
, m_dist_pred(dist_pred), m_pred(pred)
, m_result(r)
{}
//TODO: awulkiew - consider this approach: store one, global vector of active branches, add branches only if mindist is ok
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
// array of active nodes
typename index::detail::rtree::container_from_elements_type<
elements_type,
std::pair<node_distances_type, typename Allocators::node_pointer>
>::type active_branch_list;
active_branch_list.reserve(m_parameters.get_max_elements());
elements_type const& elements = rtree::elements(n);
// fill array of nodes meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
// if current node meets predicates
// 0 - dummy value
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
{
// calculate node's distance(s) for distance predicate
node_distances_type node_dist_data = node_distances_calc::apply(m_dist_pred, it->first);
// TODO: awulkiew - consider at first calculating near distance only,
// comparing it with m_result.comparable_distance if it's valid,
// after that calculate the rest of distances and check predicates
// if current node is further than found neighbors - don't analyze it
if ( m_result.is_comparable_distance_valid() &&
is_node_prunable(m_result.comparable_distance(), node_dist_data) )
{
continue;
}
// if current node distance(s) meets distance predicate
if ( node_distances_predicates_check::apply(m_dist_pred, node_dist_data) )
{
// add current node's data into the list
active_branch_list.push_back( std::make_pair(node_dist_data, it->second) );
}
}
}
// if there aren't any nodes in ABL - return
if ( active_branch_list.empty() )
return;
// sort array
std::sort(active_branch_list.begin(), active_branch_list.end(), abl_less);
// recursively visit nodes
for ( size_t i = 0 ;; ++i )
{
// prune nodes
prune_nodes(active_branch_list);
if ( active_branch_list.size() <= i )
break;
rtree::apply_visitor(*this, *active_branch_list[i].second);
}
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
// search leaf for closest value meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
// if value meets predicates
if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, *it, m_translator(*it)) )
{
// calculate values distance for distance predicate
value_distances_type distances = value_distances_calc::apply(m_dist_pred, m_translator(*it));
// TODO: awulkiew - consider at first calculating point relation distance only,
// comparing it with m_result.comparable_distance if it's valid,
// after that calculate the rest of distances and check predicates
// if distance meets distance predicate
if ( value_distances_predicates_check::apply(m_dist_pred, distances) )
{
typedef typename index::detail::point_relation<DistancesPredicates>::type point_relation_type;
typedef typename index::detail::relation<point_relation_type>::tag point_relation_tag;
// store value
m_result.store(
*it,
index::detail::cdist_value<value_distances_type>
::template get<point_relation_tag>(distances)
);
}
}
}
}
private:
template <typename ActiveBranchList>
inline void prune_nodes(ActiveBranchList & abl) const
{
// if some value were found
if ( m_result.is_comparable_distance_valid() )
{
// prune if box's mindist is further than value's mindist
while ( !abl.empty() &&
is_node_prunable(m_result.comparable_distance(), abl.back().first) )
{
abl.pop_back();
}
}
}
static inline bool abl_less(
std::pair<node_distances_type, typename Allocators::node_pointer> const& p1,
std::pair<node_distances_type, typename Allocators::node_pointer> const& p2)
{
return index::detail::cdist_value<node_distances_type>
::template get<index::detail::to_nearest_tag>(p1.first)
< index::detail::cdist_value<node_distances_type>
::template get<index::detail::to_nearest_tag>(p2.first);
}
template <typename Distance>
static inline bool is_node_prunable(Distance const& smallest_dist, node_distances_type const& d)
{
return smallest_dist
< index::detail::cdist_value<node_distances_type>
::template get<index::detail::to_nearest_tag>(d);
}
parameters_type const& m_parameters;
Translator const& m_translator;
DistancesPredicates m_dist_pred;
Predicates m_pred;
Result & m_result;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_NEAREST_QUERY_HPP

View File

@@ -0,0 +1,197 @@
// Boost.Geometry Index
//
// R-tree ostreaming visitor 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_VISITORS_PRINT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_PRINT_HPP
#include <iostream>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
namespace dispatch {
template <typename Point, size_t Dimension>
struct print_point
{
BOOST_STATIC_ASSERT(0 < Dimension);
static inline void apply(std::ostream & os, Point const& p)
{
print_point<Point, Dimension - 1>::apply(os, p);
os << ", " << geometry::get<Dimension - 1>(p);
}
};
template <typename Point>
struct print_point<Point, 1>
{
static inline void apply(std::ostream & os, Point const& p)
{
os << geometry::get<0>(p);
}
};
template <typename Box, size_t Corner, size_t Dimension>
struct print_corner
{
BOOST_STATIC_ASSERT(0 < Dimension);
static inline void apply(std::ostream & os, Box const& b)
{
print_corner<Box, Corner, Dimension - 1>::apply(os, b);
os << ", " << geometry::get<Corner, Dimension - 1>(b);
}
};
template <typename Box, size_t Corner>
struct print_corner<Box, Corner, 1>
{
static inline void apply(std::ostream & os, Box const& b)
{
os << geometry::get<Corner, 0>(b);
}
};
template <typename Indexable, typename Tag>
struct print_indexable
{
};
template <typename Indexable>
struct print_indexable<Indexable, box_tag>
{
static const size_t dimension = index::detail::traits::dimension<Indexable>::value;
static inline void apply(std::ostream &os, Indexable const& i)
{
os << '(';
print_corner<Indexable, min_corner, dimension>::apply(os, i);
os << ")x(";
print_corner<Indexable, max_corner, dimension>::apply(os, i);
os << ')';
}
};
template <typename Indexable>
struct print_indexable<Indexable, point_tag>
{
static const size_t dimension = index::detail::traits::dimension<Indexable>::value;
static inline void apply(std::ostream &os, Indexable const& i)
{
os << '(';
print_point<Indexable, dimension>::apply(os, i);
os << ')';
}
};
} // namespace dispatch
namespace detail {
template <typename Indexable>
inline void print_indexable(std::ostream & os, Indexable const& i)
{
dispatch::print_indexable<
Indexable,
typename geometry::traits::tag<Indexable>::type
>::apply(os, i);
}
} // namespace detail
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
struct print : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
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;
inline print(std::ostream & o, Translator const& t)
: os(o), tr(t), level(0)
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
spaces(level) << "INTERNAL NODE - L:" << level << " Ch:" << elements.size() << " @:" << &n << '\n';
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
spaces(level);
detail::print_indexable(os, it->first);
os << " ->" << it->second << '\n';
}
size_t level_backup = level;
++level;
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
rtree::apply_visitor(*this, *it->second);
}
level = level_backup;
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
spaces(level) << "LEAF - L:" << level << " V:" << elements.size() << " @:" << &n << '\n';
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
spaces(level);
detail::print_indexable(os, tr(*it));
os << '\n';
}
}
inline std::ostream & spaces(size_t level)
{
for ( size_t i = 0 ; i < 2 * level ; ++i )
os << ' ';
return os;
}
std::ostream & os;
Translator const& tr;
size_t level;
};
}}} // namespace detail::rtree::visitors
template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
std::ostream & operator<<(std::ostream & os, rtree<Value, Options, IndexableGetter, EqualTo, Allocator> const& tree)
{
typedef rtree<Value, Options, IndexableGetter, EqualTo, Allocator> rtree_type;
typedef typename rtree_type::value_type value_type;
typedef typename rtree_type::options_type options_type;
typedef typename rtree_type::translator_type translator_type;
typedef typename rtree_type::box_type box_type;
typedef typename rtree_type::allocators_type allocators_type;
detail::rtree::visitors::print<value_type, options_type, translator_type, box_type, allocators_type> print_v(os, tree.translator());
tree.apply_visitor(print_v);
return os;
}
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_PRINT_HPP

View File

@@ -0,0 +1,311 @@
// Boost.Geometry Index
//
// R-tree removing visitor 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_VISITORS_REMOVE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
// Default remove algorithm
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class remove
: 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 rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
typedef typename Allocators::node_pointer node_pointer;
typedef typename Allocators::internal_node_pointer internal_node_pointer;
public:
inline remove(node_pointer & root,
size_t & leafs_level,
Value const& value,
parameters_type const& parameters,
Translator const& translator,
Allocators & allocators)
: m_value(value)
, m_parameters(parameters)
, m_translator(translator)
, m_allocators(allocators)
, m_root_node(root)
, m_leafs_level(leafs_level)
, m_is_value_removed(false)
, m_parent(0)
, m_current_child_index(0)
, m_current_level(0)
, m_is_underflow(false)
{
// TODO
// assert - check if Value/Box is correct
}
inline void operator()(internal_node & n)
{
typedef typename rtree::elements_type<internal_node>::type children_type;
children_type & children = rtree::elements(n);
// traverse children which boxes intersects value's box
size_t child_node_index = 0;
for ( ; child_node_index < children.size() ; ++child_node_index )
{
if ( geometry::covered_by(m_translator(m_value), children[child_node_index].first) )
{
// next traversing step
traverse_apply_visitor(n, child_node_index); // MAY THROW
if ( m_is_value_removed )
break;
}
}
// value was found and removed
if ( m_is_value_removed )
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
typedef typename elements_type::iterator element_iterator;
elements_type & elements = rtree::elements(n);
// underflow occured - child node should be removed
if ( m_is_underflow )
{
element_iterator underfl_el_it = elements.begin() + child_node_index;
size_t relative_level = m_leafs_level - m_current_level;
// move node to the container - store node's relative level as well and return new underflow state
m_is_underflow = store_underflowed_node(elements, underfl_el_it, relative_level); // MAY THROW (E: alloc, copy)
}
// n is not root - adjust aabb
if ( 0 != m_parent )
{
// underflow state should be ok here
// note that there may be less than min_elems elements in root
// so this condition should be checked only here
BOOST_GEOMETRY_INDEX_ASSERT((elements.size() < m_parameters.get_min_elements()) == m_is_underflow, "unexpected state");
rtree::elements(*m_parent)[m_current_child_index].first
= rtree::elements_box<Box>(elements.begin(), elements.end(), m_translator);
}
// n is root node
else
{
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root_node), "node must be the root");
// reinsert elements from removed nodes (underflows)
reinsert_removed_nodes_elements(); // MAY THROW (V, E: alloc, copy, N: alloc)
// shorten the tree
if ( rtree::elements(n).size() == 1 )
{
node_pointer root_to_destroy = m_root_node;
m_root_node = rtree::elements(n)[0].second;
--m_leafs_level;
rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, root_to_destroy);
}
}
}
}
inline void operator()(leaf & n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type & elements = rtree::elements(n);
// find value and remove it
for ( typename elements_type::iterator it = elements.begin() ; it != elements.end() ; ++it )
{
if ( m_translator.equals(*it, m_value) )
{
rtree::move_from_back(elements, it); // MAY THROW (V: copy)
elements.pop_back();
m_is_value_removed = true;
break;
}
}
// if value was removed
if ( m_is_value_removed )
{
// calc underflow
m_is_underflow = elements.size() < m_parameters.get_min_elements();
// n is not root - adjust aabb
if ( 0 != m_parent )
{
rtree::elements(*m_parent)[m_current_child_index].first
= rtree::elements_box<Box>(elements.begin(), elements.end(), m_translator);
}
}
}
bool is_value_removed() const
{
return m_is_value_removed;
}
private:
typedef std::vector< std::pair<size_t, node_pointer> > UnderflowNodes;
void traverse_apply_visitor(internal_node &n, size_t choosen_node_index)
{
// save previous traverse inputs and set new ones
internal_node_pointer parent_bckup = m_parent;
size_t current_child_index_bckup = m_current_child_index;
size_t current_level_bckup = m_current_level;
m_parent = &n;
m_current_child_index = choosen_node_index;
++m_current_level;
// next traversing step
rtree::apply_visitor(*this, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V, E: alloc, copy, N: alloc)
// restore previous traverse inputs
m_parent = parent_bckup;
m_current_child_index = current_child_index_bckup;
m_current_level = current_level_bckup;
}
bool store_underflowed_node(
typename rtree::elements_type<internal_node>::type & elements,
typename rtree::elements_type<internal_node>::type::iterator underfl_el_it,
size_t relative_level)
{
// move node to the container - store node's relative level as well
m_underflowed_nodes.push_back(std::make_pair(relative_level, underfl_el_it->second)); // MAY THROW (E: alloc, copy)
try
{
rtree::move_from_back(elements, underfl_el_it); // MAY THROW (E: copy)
elements.pop_back();
}
catch(...)
{
m_underflowed_nodes.pop_back();
throw; // RETHROW
}
// calc underflow
return elements.size() < m_parameters.get_min_elements();
}
void reinsert_removed_nodes_elements()
{
typename UnderflowNodes::reverse_iterator it = m_underflowed_nodes.rbegin();
try
{
// reinsert elements from removed nodes
// begin with levels closer to the root
for ( ; it != m_underflowed_nodes.rend() ; ++it )
{
is_leaf<Value, Options, Box, Allocators> ilv;
rtree::apply_visitor(ilv, *it->second);
if ( ilv.result )
{
reinsert_node_elements(rtree::get<leaf>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)
rtree::destroy_node<Allocators, leaf>::apply(m_allocators, it->second);
}
else
{
reinsert_node_elements(rtree::get<internal_node>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)
rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, it->second);
}
}
//m_underflowed_nodes.clear();
}
catch(...)
{
// destroy current and remaining nodes
for ( ; it != m_underflowed_nodes.rend() ; ++it )
{
node_auto_ptr dummy(it->second, m_allocators);
}
//m_underflowed_nodes.clear();
throw; // RETHROW
}
}
template <typename Node>
void reinsert_node_elements(Node &n, size_t node_relative_level)
{
typedef typename rtree::elements_type<Node>::type elements_type;
elements_type & elements = rtree::elements(n);
typename elements_type::iterator it = elements.begin();
try
{
for ( ; it != elements.end() ; ++it )
{
visitors::insert<
typename elements_type::value_type,
Value, Options, Translator, Box, Allocators,
typename Options::insert_tag
> insert_v(
m_root_node, m_leafs_level, *it,
m_parameters, m_translator, m_allocators,
node_relative_level - 1);
rtree::apply_visitor(insert_v, *m_root_node); // MAY THROW (V, E: alloc, copy, N: alloc)
}
}
catch(...)
{
++it;
rtree::destroy_elements<Value, Options, Translator, Box, Allocators>
::apply(it, elements.end(), m_allocators);
elements.clear();
throw; // RETHROW
}
}
Value const& m_value;
parameters_type const& m_parameters;
Translator const& m_translator;
Allocators & m_allocators;
node_pointer & m_root_node;
size_t & m_leafs_level;
bool m_is_value_removed;
UnderflowNodes m_underflowed_nodes;
// traversing input parameters
internal_node_pointer m_parent;
size_t m_current_child_index;
size_t m_current_level;
// traversing output parameters
bool m_is_underflow;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP

View File

@@ -0,0 +1,80 @@
// Boost.Geometry Index
//
// R-tree spatial query visitor 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_VISITORS_SPATIAL_QUERY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, typename OutIter>
struct spatial_query
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
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;
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
inline spatial_query(Translator const& t, Predicates const& p, OutIter out_it)
: tr(t), pred(p), out_iter(out_it), found_count(0)
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
// traverse nodes meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
// if node meets predicates
// 0 - dummy value
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(pred, 0, it->first) )
rtree::apply_visitor(*this, *it->second);
}
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
// get all values meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
// if value meets predicates
if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(pred, *it, tr(*it)) )
{
out_iter = *it;
++out_iter;
++found_count;
}
}
}
Translator const& tr;
Predicates pred;
OutIter out_iter;
size_t found_count;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP

View File

@@ -0,0 +1,25 @@
// Boost.Geometry Index
//
// Tags used by the predicates checks 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_TAGS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_TAGS_HPP
namespace boost { namespace geometry { namespace index {
namespace detail {
struct value_tag {};
struct bounds_tag {};
} // namespace detail
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_RTREE_TAGS_HPP

View File

@@ -0,0 +1,60 @@
// Boost.Geometry Index
//
// 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_TRANSLATOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_TRANSLATOR_HPP
namespace boost { namespace geometry { namespace index {
namespace detail {
template <typename IndexableGetter, typename EqualTo>
struct translator
: public IndexableGetter
, public EqualTo
{
typedef typename IndexableGetter::result_type result_type;
translator(IndexableGetter const& i, EqualTo const& e)
: IndexableGetter(i), EqualTo(e)
{}
template <typename Value>
result_type operator()(Value const& value) const
{
return IndexableGetter::operator()(value);
}
template <typename Value>
bool equals(Value const& v1, Value const& v2) const
{
return EqualTo::operator()(v1, v2);
}
};
template <typename IndexableGetter>
struct result_type
{
typedef typename IndexableGetter::result_type type;
};
template <typename IndexableGetter>
struct indexable_type
{
typedef typename boost::remove_const<
typename boost::remove_reference<
typename result_type<IndexableGetter>::type
>::type
>::type type;
};
} // namespace detail
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_TRANSLATOR_HPP

View File

@@ -0,0 +1,201 @@
// Boost.Geometry Index
//
// 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_TUPLES_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_TUPLES_HPP
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/is_same.hpp>
// TODO move this to index/tuples and separate algorithms
namespace boost { namespace geometry { namespace index { namespace detail {
namespace tuples {
// find_index
namespace detail {
template <typename Tuple, typename El, size_t N>
struct find_index;
template <typename Tuple, typename El, size_t N, typename CurrentEl>
struct find_index_impl
{
static const size_t value = find_index<Tuple, El, N - 1>::value;
};
template <typename Tuple, typename El, size_t N>
struct find_index_impl<Tuple, El, N, El>
{
static const size_t value = N - 1;
};
template <typename Tuple, typename El, typename CurrentEl>
struct find_index_impl<Tuple, El, 1, CurrentEl>
{
BOOST_MPL_ASSERT_MSG(
(false),
ELEMENT_NOT_FOUND,
(find_index_impl));
};
template <typename Tuple, typename El>
struct find_index_impl<Tuple, El, 1, El>
{
static const size_t value = 0;
};
template <typename Tuple, typename El, size_t N>
struct find_index
{
static const size_t value =
find_index_impl<
Tuple,
El,
N,
typename boost::tuples::element<N - 1, Tuple>::type
>::value;
};
} // namespace detail
template <typename Tuple, typename El>
struct find_index
{
static const size_t value =
detail::find_index<
Tuple,
El,
boost::tuples::length<Tuple>::value
>::value;
};
// has
namespace detail {
template <typename Tuple, typename El, size_t N>
struct has
{
static const bool value
= boost::is_same<
typename boost::tuples::element<N - 1, Tuple>::type,
El
>::value
|| has<Tuple, El, N - 1>::value;
};
template <typename Tuple, typename El>
struct has<Tuple, El, 1>
{
static const bool value
= boost::is_same<
typename boost::tuples::element<0, Tuple>::type,
El
>::value;
};
} // namespace detail
template <typename Tuple, typename El>
struct has
{
static const bool value
= detail::has<
Tuple,
El,
boost::tuples::length<Tuple>::value
>::value;
};
// add
template <typename Tuple, typename El>
struct add
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TUPLE_TYPE,
(add));
};
template <typename T1, typename T>
struct add<boost::tuple<T1>, T>
{
typedef boost::tuple<T1, T> type;
};
template <typename T1, typename T2, typename T>
struct add<boost::tuple<T1, T2>, T>
{
typedef boost::tuple<T1, T2, T> type;
};
// add_if
template <typename Tuple, typename El, bool Cond>
struct add_if
{
typedef Tuple type;
};
template <typename Tuple, typename El>
struct add_if<Tuple, El, true>
{
typedef typename add<Tuple, El>::type type;
};
// add_unique
template <typename Tuple, typename El>
struct add_unique
{
typedef typename add_if<
Tuple,
El,
!has<Tuple, El>::value
>::type type;
};
template <typename Tuple, typename T, size_t I, size_t N>
struct push_back_impl
{
typedef
boost::tuples::cons<
typename boost::tuples::element<I, Tuple>::type,
typename push_back_impl<Tuple, T, I+1, N>::type
> type;
static type apply(Tuple const& tup, T const& t)
{
return
type(
boost::get<I>(tup),
push_back_impl<Tuple, T, I+1, N>::apply(tup, t)
);
}
};
template <typename Tuple, typename T, size_t N>
struct push_back_impl<Tuple, T, N, N>
{
typedef boost::tuples::cons<T, boost::tuples::null_type> type;
static type apply(Tuple const&, T const& t)
{
return type(t, boost::tuples::null_type());
}
};
} // namespace tuples
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_TAGS_HPP

View File

@@ -0,0 +1,881 @@
// Boost.Geometry Index
//
// 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_VARRAY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP
#include <cstddef>
#include <stdexcept>
#include <boost/move/move.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/geometry/index/detail/assert.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
template <typename V>
struct varray_default_alloc
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef V * pointer;
typedef const V * const_pointer;
};
template <typename Value, size_t Capacity, typename Al = varray_default_alloc<Value> >
class varray
{
BOOST_MPL_ASSERT_MSG(
(0 < Capacity),
INVALID_CAPACITY,
(varray));
BOOST_COPYABLE_AND_MOVABLE(varray)
public:
typedef Value value_type;
typedef Value& reference;
typedef Value const& const_reference;
typedef typename Al::size_type size_type;
typedef typename Al::difference_type difference_type;
typedef typename Al::pointer pointer;
typedef typename Al::const_pointer const_pointer;
typedef pointer iterator;
typedef const_pointer const_iterator;
typedef boost::reverse_iterator<iterator> reverse_iterator;
typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
// nothrow
varray()
: m_size(0)
{}
// strong
explicit varray(size_type count)
: m_size(0)
{
resize(count); // may throw
}
// strong
varray(size_type count, value_type const& value)
: m_size(0)
{
resize(count, value); // may throw
}
// strong
varray(varray const& other)
: m_size(other.m_size)
{
this->uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw
}
// strong
varray(BOOST_RV_REF(varray) other)
: m_size(other.m_size)
{
this->uninitialized_move(other.begin(), other.end(), this->begin()); // may throw
}
// strong
template <typename Iterator>
varray(Iterator first, Iterator last)
: m_size(0)
{
assign(first, last); // may throw
}
// basic
varray & operator=(BOOST_COPY_ASSIGN_REF(varray) other)
{
assign(other.begin(), other.end()); // may throw
return *this;
}
// basic
varray & operator=(BOOST_RV_REF(varray) other)
{
assign(other.begin(), other.end()); // may throw
return *this;
}
// nothrow
~varray()
{
this->destroy(this->begin(), this->end());
}
// strong
void resize(size_type count)
{
if ( count < m_size )
{
this->destroy(this->begin() + count, this->end());
}
else
{
check_capacity(count);
this->construct(this->end(), this->begin() + count); // may throw
}
m_size = count; // update end
}
// strong
void resize(size_type count, value_type const& value)
{
if ( count < m_size )
{
this->destroy(this->begin() + count, this->end());
}
else
{
check_capacity(count);
std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw
}
m_size = count; // update end
}
// nothrow
void reserve(size_type count)
{
check_capacity(count);
}
// strong
void push_back(value_type const& value)
{
check_capacity(m_size + 1);
this->uninitialized_fill(this->end(), value); // may throw
++m_size; // update end
}
void push_back(BOOST_RV_REF(value_type) value)
{
check_capacity(m_size + 1);
this->uninitialized_fill(this->end(), value); // may throw
++m_size; // update end
}
// nothrow
void pop_back()
{
check_empty();
//--m_size; // update end
//this->destroy(this->end());
// safer and more intuitive version
this->destroy(this->end() - 1);
--m_size; // update end
}
// basic
void insert(iterator position, value_type const& value)
{
check_iterator_end_eq(position);
check_capacity(m_size + 1);
if ( position == this->end() )
{
this->uninitialized_fill(position, value); // may throw
++m_size; // update end
}
else
{
// TODO - should following lines check for exception and revert to the old size?
this->uninitialized_fill(this->end(), *(this->end() - 1)); // may throw
++m_size; // update end
this->move_backward(position, this->end() - 2, this->end() - 1); // may throw
this->fill(position, value); // may throw
}
}
// basic
void insert(iterator position, size_type count, value_type const& value)
{
check_iterator_end_eq(position);
check_capacity(m_size + count);
if ( position == this->end() )
{
std::uninitialized_fill(position, position + count, value); // may throw
m_size += count; // update end
}
else
{
difference_type to_move = std::distance(position, this->end());
// TODO - should following lines check for exception and revert to the old size?
if ( count < static_cast<size_type>(to_move) )
{
this->uninitialized_copy(this->end() - count, this->end(), this->end()); // may throw
m_size += count; // update end
this->move_backward(position, position + to_move - count, this->end() - count); // may throw
std::fill_n(position, count, value); // may throw
}
else
{
std::uninitialized_fill(this->end(), position + count, value); // may throw
m_size += count - to_move; // update end
this->uninitialized_copy(position, position + to_move, position + count); // may throw
m_size += to_move; // update end
std::fill_n(position, to_move, value); // may throw
}
}
}
// basic
template <typename Iterator>
void insert(iterator position, Iterator first, Iterator last)
{
typedef typename boost::iterator_traversal<Iterator>::type traversal;
this->insert_dispatch(position, first, last, traversal());
}
// basic
void erase(iterator position)
{
check_iterator_end_neq(position);
this->move(position + 1, this->end(), position); // may throw
this->destroy(this->end() - 1);
--m_size;
}
// basic
void erase(iterator first, iterator last)
{
check_iterator_end_eq(first);
check_iterator_end_eq(last);
difference_type n = std::distance(first, last);
BOOST_ASSERT_MSG(0 <= n, "invalid range");
this->move(last, this->end(), first); // may throw
this->destroy(this->end() - n, this->end());
m_size -= n;
}
// basic
template <typename Iterator>
void assign(Iterator first, Iterator last)
{
typedef typename boost::iterator_traversal<Iterator>::type traversal;
this->assign_dispatch(first, last, traversal()); // may throw
}
// basic
void assign(size_type count, value_type const& value)
{
if ( count < m_size )
{
std::fill_n(this->begin(), count, value);
this->destroy(this->begin() + count, this->end());
}
else
{
check_capacity(count);
std::fill_n(this->begin(), m_size, value);
std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw
}
m_size = count; // update end
}
// nothrow
void clear()
{
this->destroy(this->begin(), this->end());
m_size = 0; // update end
}
// strong
Value & at(size_type i)
{
if ( m_size <= i )
throw std::out_of_range("index out of bounds");
return *(this->begin() + i);
}
// strong
Value const& at(size_type i) const
{
if ( m_size <= i )
throw std::out_of_range("index out of bounds");
return *(this->begin() + i);
}
// nothrow
Value & operator[](size_type i)
{
BOOST_ASSERT_MSG(i < m_size, "index out of bounds");
return *(this->begin() + i);
}
// nothrow
Value const& operator[](size_type i) const
{
BOOST_ASSERT_MSG(i < m_size, "index out of bounds");
return *(this->begin() + i);
}
// nothrow
Value & front()
{
check_empty();
return *(this->begin());
}
// nothrow
Value const& front() const
{
check_empty();
return *(this->begin());
}
// nothrow
Value & back()
{
check_empty();
return *(this->end() - 1);
}
// nothrow
Value const& back() const
{
check_empty();
return *(this->end() - 1);
}
// nothrow
Value * data() { return this->ptr(); }
const Value * data() const { return this->ptr(); }
// nothrow
iterator begin() { return this->ptr(); }
const_iterator begin() const { return this->ptr(); }
const_iterator cbegin() const { return this->ptr(); }
iterator end() { return this->begin() + m_size; }
const_iterator end() const { return this->begin() + m_size; }
const_iterator cend() const { return this->cbegin() + m_size; }
// nothrow
reverse_iterator rbegin() { return reverse_iterator(this->end()); }
const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
reverse_iterator rend() { return reverse_iterator(this->begin()); }
const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
// nothrow
static size_type capacity() { return Capacity; }
static size_type max_size() { return Capacity; }
size_type size() const { return m_size; }
bool empty() const { return 0 == m_size; }
private:
// insert
template <typename Iterator>
void insert_dispatch(iterator position, Iterator first, Iterator last, boost::random_access_traversal_tag const&)
{
check_iterator_end_eq(position);
difference_type count = std::distance(first, last);
check_capacity(m_size + count);
if ( position == this->end() )
{
this->uninitialized_copy(first, last, position); // may throw
m_size += count; // update end
}
else
{
this->insert_in_the_middle(position, first, last, count); // may throw
}
}
template <typename Iterator, typename Traversal>
void insert_dispatch(iterator position, Iterator first, Iterator last, Traversal const& /*not_random_access*/)
{
check_iterator_end_eq(position);
if ( position == this->end() )
{
std::pair<bool, size_type> copy_data =
this->uninitialized_copy_checked(first, last, position, std::distance(position, this->begin() + Capacity)); // may throw
check_capacity(copy_data.first ? m_size + copy_data.second : Capacity + 1);
m_size += copy_data.second;
}
else
{
difference_type count = std::distance(first, last);
check_capacity(m_size + count);
this->insert_in_the_middle(position, first, last, count); // may throw
}
}
template <typename Iterator>
void insert_in_the_middle(iterator position, Iterator first, Iterator last, difference_type count)
{
difference_type to_move = std::distance(position, this->end());
// TODO - should following lines check for exception and revert to the old size?
if ( count < to_move )
{
this->uninitialized_copy(this->end() - count, this->end(), this->end()); // may throw
m_size += count; // update end
this->move_backward(position, position + to_move - count, this->end() - count); // may throw
this->copy(first, last, position); // may throw
}
else
{
Iterator middle_iter = first;
std::advance(middle_iter, to_move);
this->uninitialized_copy(middle_iter, last, this->end()); // may throw
m_size += count - to_move; // update end
this->uninitialized_copy(position, position + to_move, position + count); // may throw
m_size += to_move; // update end
this->copy(first, middle_iter, position) ; // may throw
}
}
// assign
template <typename Iterator>
void assign_dispatch(Iterator first, Iterator last, boost::random_access_traversal_tag const& /*not_random_access*/)
{
size_type s = std::distance(first, last);
check_capacity(s);
if ( m_size <= s )
{
this->copy(first, first + m_size, this->begin()); // may throw
// TODO - perform uninitialized_copy first?
this->uninitialized_copy(first + m_size, last, this->end()); // may throw
}
else
{
this->copy(first, last, this->begin()); // may throw
this->destroy(this->begin() + s, this->end());
}
m_size = s; // update end
}
template <typename Iterator, typename Traversal>
void assign_dispatch(Iterator first, Iterator last, Traversal const& /*not_random_access*/)
{
size_type s = 0;
iterator it = this->begin();
for ( ; it != this->end() && first != last ; ++it, ++first, ++s )
*it = *first; // may throw
this->destroy(it, this->end());
std::pair<bool, size_type> copy_data =
this->uninitialized_copy_checked(first, last, it, std::distance(it, this->begin() + Capacity)); // may throw
s += copy_data.second;
check_capacity(copy_data.first ? s : Capacity + 1);
m_size = s; // update end
}
// uninitialized_copy_checked
template <typename Iterator>
std::pair<bool, size_type> uninitialized_copy_checked(Iterator first, Iterator last, iterator dest, size_type max_count)
{
size_type count = 0;
iterator it = dest;
try
{
for ( ; first != last ; ++it, ++first, ++count )
{
if ( max_count <= count )
return std::make_pair(false, count);
this->uninitialized_fill(it, *first); // may throw
}
}
catch(...)
{
this->destroy(dest, it);
throw;
}
return std::make_pair(true, count);
}
// copy
template <typename Iterator>
void copy(Iterator first, Iterator last, iterator dst)
{
typedef typename
mpl::and_<
has_trivial_assign<value_type>,
mpl::or_<
is_same<Iterator, value_type *>,
is_same<Iterator, const value_type *>
>,
mpl::or_<
is_same<iterator, value_type *>,
is_same<iterator, const value_type *>
>
>::type
use_memcpy;
this->copy_dispatch(first, last, dst, use_memcpy()); // may throw
}
void copy_dispatch(const value_type * first, const value_type * last, value_type * dst,
boost::mpl::bool_<true> const& /*use_memcpy*/)
{
::memmove(dst, first, sizeof(value_type) * std::distance(first, last));
}
template <typename Iterator>
void copy_dispatch(Iterator first, Iterator last, iterator dst,
boost::mpl::bool_<false> const& /*use_memcpy*/)
{
std::copy(first, last, dst); // may throw
}
// uninitialized_copy
template <typename Iterator>
void uninitialized_copy(Iterator first, Iterator last, iterator dst)
{
typedef typename
mpl::and_<
has_trivial_copy<value_type>,
mpl::or_<
is_same<Iterator, value_type *>,
is_same<Iterator, const value_type *>
>,
mpl::or_<
is_same<iterator, value_type *>,
is_same<iterator, const value_type *>
>
>::type
use_memcpy;
this->uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw
}
void uninitialized_copy_dispatch(const value_type * first, const value_type * last, value_type * dst,
boost::mpl::bool_<true> const& /*use_memcpy*/)
{
::memcpy(dst, first, sizeof(value_type) * std::distance(first, last));
}
template <typename Iterator>
void uninitialized_copy_dispatch(Iterator first, Iterator last, iterator dst,
boost::mpl::bool_<false> const& /*use_memcpy*/)
{
std::uninitialized_copy(first, last, dst); // may throw
}
// uninitialized_fill
template <typename V>
void uninitialized_fill(iterator dst, V const& v)
{
typedef typename
mpl::and_<
has_trivial_copy<value_type>,
is_same<V, value_type>
>::type
use_memcpy;
uninitialized_fill_dispatch(dst, v, use_memcpy()); // may throw
}
void uninitialized_fill_dispatch(iterator dst, value_type const& v,
boost::mpl::bool_<true> const& /*use_memcpy*/)
{
// TODO - check if value_type has operator& defined and call this version only if it hasn't
const value_type * vptr = &v;
::memcpy(&(*dst), vptr, sizeof(value_type));
}
template <typename V>
void uninitialized_fill_dispatch(iterator dst, V const& v,
boost::mpl::bool_<false> const& /*use_memcpy*/)
{
new (&(*dst)) value_type(v); // may throw
}
template <typename V>
void uninitialized_fill(iterator dst, BOOST_RV_REF(V) v)
{
// TODO optimized version if has_trivial_move
new (&(*dst)) value_type(v); // may throw
}
// move
template <typename Iterator>
void move(Iterator first, Iterator last, iterator dst)
{
typedef typename
mpl::and_<
has_trivial_assign<value_type>,
mpl::or_<
is_same<Iterator, value_type *>,
is_same<Iterator, const value_type *>
>,
mpl::or_<
is_same<iterator, value_type *>,
is_same<iterator, const value_type *>
>
>::type
use_memcpy;
this->move_dispatch(first, last, dst, use_memcpy()); // may throw
}
void move_dispatch(const value_type * first, const value_type * last, value_type * dst,
boost::mpl::bool_<true> const& /*use_mem*/)
{
::memmove(dst, first, sizeof(value_type) * std::distance(first, last));
}
template <typename Iterator>
void move_dispatch(Iterator first, Iterator last, iterator dst,
boost::mpl::bool_<false> const& /*use_mem*/)
{
std::copy(first, last, dst); // may throw
}
// move_backward
void move_backward(iterator first, iterator last, iterator dst)
{
typedef typename
mpl::and_<
has_trivial_assign<value_type>,
mpl::or_<
is_same<iterator, value_type *>,
is_same<iterator, const value_type *>
>
>::type
use_memcpy;
this->move_backward_dispatch(first, last, dst, use_memcpy()); // may throw
}
void move_backward_dispatch(value_type * first, value_type * last, value_type * dst,
boost::mpl::bool_<true> const& /*has_trivial_assign*/)
{
difference_type n = std::distance(first, last);
::memmove(dst - n, first, sizeof(value_type) * n);
}
void move_backward_dispatch(iterator first, iterator last, iterator dst,
boost::mpl::bool_<false> const& /*has_trivial_assign*/)
{
std::copy_backward(first, last, dst); // may throw
}
// uninitialized_fill
template <typename V>
void fill(iterator dst, V const& v)
{
fill_dispatch(dst, v, has_trivial_assign<value_type>()); // may throw
}
void fill_dispatch(iterator ptr, value_type const& v,
boost::true_type const& /*has_trivial_assign*/)
{
// TODO - check if value_type has operator& defined and call this version only if it hasn't
const value_type * vptr = &v;
::memcpy(&(*ptr), vptr, sizeof(value_type));
}
template <typename V>
void fill_dispatch(iterator ptr, V const& v,
boost::false_type const& /*has_trivial_assign*/)
{
*ptr = v; // may throw
}
// destroy
void destroy(iterator first, iterator last)
{
this->destroy_dispatch(first, last, has_trivial_destructor<value_type>());
}
void destroy_dispatch(iterator /*first*/, iterator /*last*/,
boost::true_type const& /*has_trivial_destructor*/)
{}
void destroy_dispatch(iterator first, iterator last,
boost::false_type const& /*has_trivial_destructor*/)
{
for ( ; first != last ; ++first )
first->~value_type();
}
// destroy
void destroy(iterator it)
{
this->destroy_dispatch(it, has_trivial_destructor<value_type>());
}
void destroy_dispatch(iterator /*ptr*/,
boost::true_type const& /*has_trivial_destructor*/)
{}
void destroy_dispatch(iterator ptr,
boost::false_type const& /*has_trivial_destructor*/)
{
ptr->~value_type();
}
// uninitialized_move
template <typename Iterator>
void uninitialized_move(Iterator first, Iterator last, iterator dst)
{
iterator o = dst;
try
{
for (; first != last; ++first, ++o )
new (boost::addressof(*o)) value_type(boost::move(*first));
}
catch(...)
{
destroy(dst, o);
throw;
}
}
// construct
void construct(iterator first, iterator last)
{
this->construct_dispatch(first, last, has_trivial_constructor<value_type>()); // may throw
}
void construct_dispatch(iterator /*first*/, iterator /*last*/,
boost::true_type const& /*has_trivial_constructor*/)
{}
void construct_dispatch(iterator first, iterator last,
boost::false_type const& /*has_trivial_constructor*/)
{
iterator it = first;
try
{
for ( ; it != last ; ++it )
new (&(*it)) value_type(); // may throw
}
catch(...)
{
this->destroy(first, it);
throw;
}
}
void check_capacity(size_type BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(s)) const
{
BOOST_ASSERT_MSG(s <= Capacity, "size can't exceed the capacity");
//if ( Capacity < s ) throw std::bad_alloc();
}
void check_empty() const
{
BOOST_ASSERT_MSG(0 < m_size, "the container is empty");
}
void check_iterator_end_neq(const_iterator position) const
{
BOOST_ASSERT_MSG(this->begin() <= position && position < this->end(), "iterator out of bounds");
/*BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(
difference_type dist = std::distance(this->begin(), position);
)
BOOST_ASSERT_MSG(
0 <= dist &&
( sizeof(dist) <= sizeof(m_size) ?
(static_cast<size_type>(dist) < m_size) :
( dist < static_cast<difference_type>(m_size))
), "invalid iterator"
);*/
}
void check_iterator_end_eq(const_iterator position) const
{
BOOST_ASSERT_MSG(this->begin() <= position && position <= this->end(), "iterator out of bounds");
/*BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(
difference_type dist = std::distance(this->begin(), position);
)
BOOST_ASSERT_MSG(
0 <= dist &&
( sizeof(dist) <= sizeof(m_size) ?
(static_cast<size_type>(dist) <= m_size) :
( dist <= static_cast<difference_type>(m_size))
), "invalid iterator"
);*/
}
pointer ptr()
{
return pointer(static_cast<value_type *>(m_storage.address()));
}
const_pointer ptr() const
{
return const_pointer(static_cast<const value_type *>(m_storage.address()));
}
boost::aligned_storage<sizeof(Value[Capacity]), boost::alignment_of<Value[Capacity]>::value> m_storage;
size_type m_size;
};
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP

View File

@@ -0,0 +1,200 @@
// Boost.Geometry Index
//
// Spatial index distance predicates, calculators and checkers used in nearest neighbor query
//
// 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_DISTANCE_PREDICATES_HPP
#define BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP
#include <boost/geometry/index/detail/distance_predicates.hpp>
/*!
\defgroup nearest_relations Nearest relations (boost::geometry::index::)
*/
namespace boost { namespace geometry { namespace index {
// relations generators
/*!
\brief Generate to_nearest() relationship.
Generate a nearest query Point and Value's Indexable relationship while calculating
distances. This function may be used to define that knn query should calculate distances
as smallest as possible between query Point and Indexable's points. In other words it
should be the distance to the nearest Indexable's point. This function may be also used
to define distances bounds which indicates that Indexable's nearest point should be
closer or further than value v. This is default relation.
\ingroup nearest_relations
\tparam T Type of wrapped object. This may be a Point for PointRelation or CoordinateType for
MinRelation or MaxRelation
\param v Point or distance value.
*/
template <typename T>
detail::to_nearest<T> to_nearest(T const& v)
{
return detail::to_nearest<T>(v);
}
/*!
\brief Generate to_centroid() relationship.
Generate a nearest query Point and Value's Indexable relationship while calculating
distances. This function may be used to define that knn query should calculate distances
between query Point and Indexable's centroid. This function may be also used
to define distances bounds which indicates that Indexable's centroid should be
closer or further than value v.
\ingroup nearest_relations
\tparam T Type of wrapped object. This may be a Point for PointRelation or some CoordinateType for
MinRelation or MaxRelation
\param v Point or distance value.
*/
template <typename T>
detail::to_centroid<T> to_centroid(T const& v)
{
return detail::to_centroid<T>(v);
}
/*!
\brief Generate to_furthest() relationship.
Generate a nearest query Point and Value's Indexable relationship while calculating
distances. This function may be used to define that knn query should calculate distances
as biggest as possible between query Point and Indexable's points. In other words it
should be the distance to the furthest Indexable's point. This function may be also used
to define distances bounds which indicates that Indexable's furthest point should be
closer or further than value v.
\ingroup nearest_relations
\tparam T Type of wrapped object. This may be a Point for PointRelation or some CoordinateType for
MinRelation or MaxRelation
\param v Point or distance value.
*/
template <typename T>
detail::to_furthest<T> to_furthest(T const& v)
{
return detail::to_furthest<T>(v);
}
// distance predicates generators
/*!
\brief Generate unbounded() distance predicate.
Generate a distance predicate. This defines distances bounds which are used by knn query.
This function indicates that there is no distance bounds and Values should be returned
if distances between Point and Indexable are the smallest. Distance calculation is defined
by PointRelation. This is default nearest predicate.
\ingroup distance_predicates
\tparam PointRelation PointRelation type.
\param pr The point relation. This may be generated by \c index::to_nearest(),
\c index::to_centroid() or \c index::to_furthest() with \c Point passed as a parameter.
*/
//template <typename PointRelation>
//inline detail::unbounded<PointRelation>
//unbounded(PointRelation const& pr)
//{
// return detail::unbounded<PointRelation>(pr);
//}
/*!
\brief Generate min_bounded() distance predicate.
Generate a distance predicate. This defines distances bounds which are used by knn query.
This function indicates that Values should be returned only if distances between Point and
Indexable are greater or equal to some min_distance passed in MinRelation. Check for closest Value is
defined by PointRelation. So it is possible e.g. to return Values with centroids closest to some
Point but only if nearest points are further than some distance.
\ingroup distance_predicates
\tparam PointRelation PointRelation type.
\tparam MinRelation MinRelation type.
\param pr The point relation. This may be generated by \c to_nearest(),
\c to_centroid() or \c to_furthest() with \c Point passed as a parameter.
\param minr The minimum bound relation. This may be generated by \c to_nearest(),
\c to_centroid() or \c to_furthest() with distance value passed as a parameter.
*/
//template <typename PointRelation, typename MinRelation>
//inline detail::min_bounded<PointRelation, MinRelation>
//min_bounded(PointRelation const& pr, MinRelation const& minr)
//{
// return detail::min_bounded<PointRelation, MinRelation>(pr, minr);
//}
/*!
\brief Generate max_bounded() distance predicate.
Generate a distance predicate. This defines distances bounds which are used by knn query.
This function indicates that Values should be returned only if distances between Point and
Indexable are lesser or equal to some max_distance passed in MaxRelation. Check for closest Value is
defined by PointRelation. So it is possible e.g. to return Values with centroids closest to some
Point but only if nearest points are closer than some distance.
\ingroup distance_predicates
\tparam PointRelation PointRelation type.
\tparam MaxRelation MaxRelation type.
\param pr The point relation. This may be generated by \c to_nearest(),
\c to_centroid() or \c to_furthest() with \c Point passed as a parameter.
\param maxr The maximum bound relation. This may be generated by \c to_nearest(),
\c to_centroid() or \c to_furthest() with distance value passed as a parameter.
*/
//template <typename PointRelation, typename MaxRelation>
//inline detail::max_bounded<PointRelation, MaxRelation>
//max_bounded(PointRelation const& pr, MaxRelation const& maxr)
//{
// return detail::max_bounded<PointRelation, MaxRelation>(pr, maxr);
//}
/*!
\brief Generate bounded() distance predicate.
Generate a distance predicate. This defines distances bounds which are used by knn query.
This function indicates that Values should be returned only if distances between Point and
Indexable are greater or equal to some min_distance passed in MinRelation and lesser or equal to
some max_distance passed in MaxRelation. Check for closest Value is defined by PointRelation.
So it is possible e.g. to return Values with centroids closest to some Point but only if nearest
points are further than some distance and closer than some other distance.
\ingroup distance_predicates
\tparam PointRelation PointRelation type.
\tparam MinRelation MinRelation type.
\tparam MaxRelation MaxRelation type.
\param pr The point relation. This may be generated by \c to_nearest(),
\c to_centroid() or \c to_furthest() with \c Point passed as a parameter.
\param minr The minimum bound relation. This may be generated by \c to_nearest(),
\c to_centroid() or \c to_furthest() with distance value passed as a parameter.
\param maxr The maximum bound relation. This may be generated by \c to_nearest(),
\c to_centroid() or \c to_furthest() with distance value passed as a parameter.
*/
//template <typename PointRelation, typename MinRelation, typename MaxRelation>
//inline detail::bounded<PointRelation, MinRelation, MaxRelation>
//bounded(PointRelation const& pr, MinRelation const& minr, MaxRelation const& maxr)
//{
// return detail::bounded<PointRelation, MinRelation, MaxRelation>(pr, minr, maxr);
//}
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP

View File

@@ -0,0 +1,178 @@
// Boost.Geometry Index
//
// 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_EQUAL_TO_HPP
#define BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP
#include <boost/geometry/algorithms/equals.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail {
template <typename Geometry, typename Tag>
struct equals
{
static bool apply(Geometry const& g1, Geometry const& g2)
{
return geometry::equals(g1, g2);
}
};
template <typename T>
struct equals<T, void>
{
static bool apply(T const& v1, T const& v2)
{
return v1 == v2;
}
};
template <typename Tuple, size_t I, size_t N>
struct tuple_equals
{
inline static bool apply(Tuple const& t1, Tuple const& t2)
{
typedef typename boost::tuples::element<I, Tuple>::type T;
return
equals<
T, typename geometry::traits::tag<T>::type
>::apply(boost::get<I>(t1), boost::get<I>(t2))
&&
tuple_equals<Tuple, I+1, N>::apply(t1, t2);
}
};
template <typename Tuple, size_t I>
struct tuple_equals<Tuple, I, I>
{
inline static bool apply(Tuple const&, Tuple const&)
{
return true;
}
};
} // namespace detail
/*!
\brief The function object comparing Values.
It compares Geometries using geometry::equals() function. Other types are compared using operator==.
The default version handles Values which are Indexables.
This template is also specialized for std::pair<T1, T2> and boost::tuple<...>.
\tparam Value The type of objects which are compared by this function object.
*/
template <typename Value>
struct equal_to
{
typedef bool result_type;
bool operator()(Value const& l, Value const& r) const
{
return detail::equals<Value, typename geometry::traits::tag<Value>::type>::apply(l ,r);
}
};
/*!
\brief The function object comparing Values.
This specialization compares values of type std::pair<T1, T2>.
It compares pairs' first values, then second values.
\tparam T1 The first type.
\tparam T2 The second type.
*/
template <typename T1, typename T2>
struct equal_to< std::pair<T1, T2> >
{
typedef bool result_type;
bool operator()(std::pair<T1, T2> const& l, std::pair<T1, T2> const& r) const
{
typedef detail::equals<T1, typename geometry::traits::tag<T1>::type> equals1;
typedef detail::equals<T2, typename geometry::traits::tag<T2>::type> equals2;
return equals1::apply(l.first, r.first) && equals2::apply(l.second, r.second);
}
};
/*!
\brief The function object comparing Values.
This specialization compares values of type boost::tuple<...>.
It compares values stored in tuple in range [0, length<tuple<...>>::value).
*/
template <typename T0, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9>
struct equal_to< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
{
typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> value_type;
typedef bool result_type;
bool operator()(value_type const& l, value_type const& r) const
{
return detail::tuple_equals<
value_type, 0, boost::tuples::length<value_type>::value
>::apply(l ,r);
}
};
}}} // namespace boost::geometry::index
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <tuple>
namespace boost { namespace geometry { namespace index {
namespace detail {
template <typename Tuple, size_t I, size_t N>
struct std_tuple_equals
{
inline static bool apply(Tuple const& t1, Tuple const& t2)
{
typedef typename std::tuple_element<I, Tuple>::type T;
return
equals<
T, typename geometry::traits::tag<T>::type
>::apply(std::get<I>(t1), std::get<I>(t2))
&&
std_tuple_equals<Tuple, I+1, N>::apply(t1, t2);
}
};
template <typename Tuple, size_t I>
struct std_tuple_equals<Tuple, I, I>
{
inline static bool apply(Tuple const&, Tuple const&)
{
return true;
}
};
} // namespace detail
template <typename ...Args>
struct equal_to< std::tuple<Args...> >
{
typedef std::tuple<Args...> value_type;
typedef bool result_type;
bool operator()(value_type const& l, value_type const& r) const
{
return detail::std_tuple_equals<
value_type, 0, std::tuple_size<value_type>::value
>::apply(l ,r);
}
};
}}} // namespace boost::geometry::index
#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#endif // BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP

View File

@@ -0,0 +1,140 @@
// Boost.Geometry Index
//
// 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_INDEXABLE_HPP
#define BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail {
template <typename Geometry, typename GeometryTag>
struct is_indexable_impl { static const bool value = false; };
template <typename Point>
struct is_indexable_impl<Point, geometry::point_tag> { static const bool value = true; };
template <typename Box>
struct is_indexable_impl<Box, geometry::box_tag> { static const bool value = true; };
template <typename Indexable>
struct is_indexable
{
static const bool value =
is_indexable_impl<Indexable, typename geometry::traits::tag<Indexable>::type>::value;
};
} // namespace detail
/*!
\brief The function object extracting Indexable from Value.
It translates Value object to Indexable object. The default version handles Values which are Indexables.
This template is also specialized for std::pair<Indexable, T2> and boost::tuple<Indexable, ...>.
\tparam Value The Value type which may be translated directly to the Indexable.
*/
template <typename Value>
struct indexable
{
BOOST_MPL_ASSERT_MSG(
(detail::is_indexable<Value>::value),
NOT_VALID_INDEXABLE_TYPE,
(Value)
);
typedef Value const& result_type;
result_type operator()(Value const& v) const
{
return v;
}
};
/*!
\brief The function object extracting Indexable from Value.
This specialization translates from std::pair<Indexable, T2>.
\tparam Indexable The Indexable type.
\tparam T2 The second type.
*/
template <typename Indexable, typename T2>
struct indexable< std::pair<Indexable, T2> >
{
BOOST_MPL_ASSERT_MSG(
(detail::is_indexable<Indexable>::value),
NOT_VALID_INDEXABLE_TYPE,
(Indexable)
);
typedef Indexable const& result_type;
result_type operator()(std::pair<Indexable, T2> const& v) const
{
return v.first;
}
};
/*!
\brief The function object extracting Indexable from Value.
This specialization translates from boost::tuple<Indexable, ...>.
\tparam Indexable The Indexable type.
*/
template <typename Indexable, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9>
struct indexable< boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
{
typedef boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9> value_type;
BOOST_MPL_ASSERT_MSG(
(detail::is_indexable<Indexable>::value),
NOT_VALID_INDEXABLE_TYPE,
(Indexable)
);
typedef Indexable const& result_type;
result_type operator()(value_type const& v) const
{
return boost::get<0>(v);
}
};
}}} // namespace boost::geometry::index
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <tuple>
namespace boost { namespace geometry { namespace index {
template <typename Indexable, typename ...Args>
struct indexable< std::tuple<Indexable, Args...> >
{
typedef std::tuple<Indexable, Args...> value_type;
BOOST_MPL_ASSERT_MSG(
(detail::is_indexable<Indexable>::value),
NOT_VALID_INDEXABLE_TYPE,
(Indexable)
);
typedef Indexable const& result_type;
result_type operator()(value_type const& v) const
{
return std::get<0>(v);
}
};
}}} // namespace boost::geometry::index
#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#endif // BOOST_GEOMETRY_INDEX_INDEXABLE_HPP

View File

@@ -0,0 +1,78 @@
// Boost.Geometry Index
//
// Insert iterator
//
// 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_INSERTER_HPP
#define BOOST_GEOMETRY_INDEX_INSERTER_HPP
#include <iterator>
/*!
\defgroup inserters Inserters (boost::geometry::index::)
*/
namespace boost { namespace geometry { namespace index {
template <class Container>
class insert_iterator :
public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
typedef Container container_type;
inline explicit insert_iterator(Container & c)
: container(&c)
{}
insert_iterator & operator=(typename Container::value_type const& value)
{
container->insert(value);
return *this;
}
insert_iterator & operator* ()
{
return *this;
}
insert_iterator & operator++ ()
{
return *this;
}
insert_iterator operator++(int)
{
return *this;
}
private:
Container * container;
};
/*!
\brief Insert iterator generator.
Returns insert iterator capable to insert values to the container
(spatial index) which has member function insert(value_type const&) defined.
\ingroup inserters
\param c The reference to the container (spatial index) to which values will be inserted.
\return The insert iterator inserting values to the container.
*/
template <typename Container>
insert_iterator<Container> inserter(Container & c)
{
return insert_iterator<Container>(c);
}
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_INSERTER_HPP

View File

@@ -0,0 +1,204 @@
// Boost.Geometry Index
//
// R-tree algorithms parameters
//
// 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_PARAMETERS_HPP
#define BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
#include <limits>
namespace boost { namespace geometry { namespace index {
// TODO: awulkiew - implement those:
//if ( m_min_elems_per_node < 1 )
// m_min_elems_per_node = 1;
//if ( m_max_elems_per_node < 2 )
// m_max_elems_per_node = 2;
/*!
\brief Linear r-tree creation algorithm parameters.
\tparam MaxElements Maximum number of elements in nodes.
\tparam MinElements Minimum number of elements in nodes.
*/
template <size_t MaxElements, size_t MinElements>
struct linear
{
static const size_t max_elements = MaxElements;
static const size_t min_elements = MinElements;
static size_t get_max_elements() { return MaxElements; }
static size_t get_min_elements() { return MinElements; }
};
/*!
\brief Quadratic r-tree creation algorithm parameters.
\tparam MaxElements Maximum number of elements in nodes.
\tparam MinElements Minimum number of elements in nodes.
*/
template <size_t MaxElements, size_t MinElements>
struct quadratic
{
static const size_t max_elements = MaxElements;
static const size_t min_elements = MinElements;
static size_t get_max_elements() { return MaxElements; }
static size_t get_min_elements() { return MinElements; }
};
namespace detail {
template <size_t MaxElements>
struct default_rstar_reinserted_elements_s
{
static const size_t value = (MaxElements * 3) / 10;
};
} // namespace detail
/*!
\brief R*-tree creation algorithm parameters.
\tparam MaxElements Maximum number of elements in nodes.
\tparam MinElements Minimum number of elements in nodes.
\tparam OverlapCostThreshold The number of leaf node children elements above which
nearly minimum overlap cost is calculated instead of minimum
overlap cost. If 0 minimum overlap cost is always calculated.
\tparam ReinsertedElements Number of elements reinserted by forced reinsertions algorithm.
*/
template <size_t MaxElements,
size_t MinElements,
size_t OverlapCostThreshold = 0,
size_t ReinsertedElements = detail::default_rstar_reinserted_elements_s<MaxElements>::value
>
struct rstar
{
static const size_t max_elements = MaxElements;
static const size_t min_elements = MinElements;
static const size_t overlap_cost_threshold = OverlapCostThreshold;
static const size_t reinserted_elements = ReinsertedElements;
static size_t get_max_elements() { return MaxElements; }
static size_t get_min_elements() { return MinElements; }
static size_t get_overlap_cost_threshold() { return OverlapCostThreshold; }
static size_t get_reinserted_elements() { return ReinsertedElements; }
};
//template <size_t MaxElements, size_t MinElements>
//struct kmeans
//{
// static const size_t max_elements = MaxElements;
// static const size_t min_elements = MinElements;
//};
/*!
\brief Linear r-tree creation algorithm parameters - run-time version.
*/
class dynamic_linear
{
public:
/*!
\brief The constructor.
\param max_elements Maximum number of elements in nodes.
\param min_elements Minimum number of elements in nodes.
*/
dynamic_linear(size_t max_elements, size_t min_elements)
: m_max_elements(max_elements)
, m_min_elements(min_elements)
{}
size_t get_max_elements() const { return m_max_elements; }
size_t get_min_elements() const { return m_min_elements; }
private:
size_t m_max_elements;
size_t m_min_elements;
};
/*!
\brief Quadratic r-tree creation algorithm parameters - run-time version.
*/
class dynamic_quadratic
{
public:
/*!
\brief The constructor.
\param max_elements Maximum number of elements in nodes.
\param min_elements Minimum number of elements in nodes.
*/
dynamic_quadratic(size_t max_elements, size_t min_elements)
: m_max_elements(max_elements)
, m_min_elements(min_elements)
{}
size_t get_max_elements() const { return m_max_elements; }
size_t get_min_elements() const { return m_min_elements; }
private:
size_t m_max_elements;
size_t m_min_elements;
};
namespace detail {
inline size_t default_rstar_reinserted_elements_d()
{
return (std::numeric_limits<size_t>::max)();
};
} // namespace detail
/*!
\brief R*-tree creation algorithm parameters - run-time version.
*/
class dynamic_rstar
{
public:
/*!
\brief The constructor.
\param max_elements Maximum number of elements in nodes.
\param min_elements Minimum number of elements in nodes.
\param overlap_cost_threshold The number of leaf node children elements above which
nearly minimum overlap cost is calculated instead of minimum
overlap cost. If 0 minimum overlap cost is always calculated.
\param reinserted_elements Number of elements reinserted by forced reinsertions algorithm.
*/
dynamic_rstar(size_t max_elements,
size_t min_elements,
size_t overlap_cost_threshold = 0,
size_t reinserted_elements = detail::default_rstar_reinserted_elements_d())
: m_max_elements(max_elements)
, m_min_elements(min_elements)
, m_overlap_cost_threshold(overlap_cost_threshold)
, m_reinserted_elements(
detail::default_rstar_reinserted_elements_d() == reinserted_elements ?
(max_elements * 3) / 10 :
reinserted_elements
)
{}
size_t get_max_elements() const { return m_max_elements; }
size_t get_min_elements() const { return m_min_elements; }
size_t get_overlap_cost_threshold() const { return m_overlap_cost_threshold; }
size_t get_reinserted_elements() const { return m_reinserted_elements; }
private:
size_t m_max_elements;
size_t m_min_elements;
size_t m_overlap_cost_threshold;
size_t m_reinserted_elements;
};
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_PARAMETERS_HPP

View File

@@ -0,0 +1,373 @@
// Boost.Geometry Index
//
// Spatial query predicates
//
// 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_PREDICATES_HPP
#define BOOST_GEOMETRY_INDEX_PREDICATES_HPP
#include <utility>
#include <boost/tuple/tuple.hpp>
#include <boost/mpl/assert.hpp>
// TODO: awulkiew - temporary
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/index/detail/predicates.hpp>
#include <boost/geometry/index/detail/tuples.hpp>
/*!
\defgroup predicates Predicates (boost::geometry::index::)
*/
namespace boost { namespace geometry { namespace index {
/*!
\brief Generate \c covered_by() predicate.
Generate a predicate defining Value and Geometry relationship.
Value will be returned by the query if <tt>bg::covered_by(Indexable, Geometry)</tt>
returns true.
\par Example
\verbatim
bgi::query(spatial_index, bgi::covered_by(box), std::back_inserter(result));
\endverbatim
\ingroup predicates
\tparam Geometry The Geometry type.
\param g The Geometry object.
*/
template <typename Geometry>
inline detail::covered_by<Geometry> covered_by(Geometry const& g)
{
return detail::covered_by<Geometry>(g);
}
/*!
\brief Generate \c disjoint() predicate.
Generate a predicate defining Value and Geometry relationship.
Value will be returned by the query if <tt>bg::disjoint(Indexable, Geometry)</tt>
returns true.
\par Example
\verbatim
bgi::query(spatial_index, bgi::disjoint(box), std::back_inserter(result));
\endverbatim
\ingroup predicates
\tparam Geometry The Geometry type.
\param g The Geometry object.
*/
template <typename Geometry>
inline detail::disjoint<Geometry> disjoint(Geometry const& g)
{
return detail::disjoint<Geometry>(g);
}
/*!
\brief Generate \c intersects() predicate.
Generate a predicate defining Value and Geometry relationship.
Value will be returned by the query if <tt>bg::intersects(Indexable, Geometry)</tt>
returns true.
\par Example
\verbatim
bgi::query(spatial_index, bgi::intersects(box), std::back_inserter(result));
bgi::query(spatial_index, bgi::intersects(ring), std::back_inserter(result));
bgi::query(spatial_index, bgi::intersects(polygon), std::back_inserter(result));
\endverbatim
\ingroup predicates
\tparam Geometry The Geometry type.
\param g The Geometry object.
*/
template <typename Geometry>
inline detail::intersects<Geometry> intersects(Geometry const& g)
{
return detail::intersects<Geometry>(g);
}
/*!
\brief Generate \c overlaps() predicate.
Generate a predicate defining Value and Geometry relationship.
Value will be returned by the query if <tt>bg::overlaps(Indexable, Geometry)</tt>
returns true.
\par Example
\verbatim
bgi::query(spatial_index, bgi::overlaps(box), std::back_inserter(result));
\endverbatim
\ingroup predicates
\tparam Geometry The Geometry type.
\param g The Geometry object.
*/
template <typename Geometry>
inline detail::overlaps<Geometry> overlaps(Geometry const& g)
{
return detail::overlaps<Geometry>(g);
}
//*!
//\brief Generate \c touches() predicate.
//
//Generate a predicate defining Value and Geometry relationship.
//Value will be returned by the query if <tt>bg::touches(Indexable, Geometry)</tt>
//returns true.
//
//\ingroup predicates
//
//\tparam Geometry The Geometry type.
//
//\param g The Geometry object.
//*/
//template <typename Geometry>
//inline detail::touches<Geometry> touches(Geometry const& g)
//{
// return detail::touches<Geometry>(g);
//}
/*!
\brief Generate \c within() predicate.
Generate a predicate defining Value and Geometry relationship.
Value will be returned by the query if <tt>bg::within(Indexable, Geometry)</tt>
returns true.
\par Example
\verbatim
bgi::query(spatial_index, bgi::within(box), std::back_inserter(result));
\endverbatim
\ingroup predicates
\tparam Geometry The Geometry type.
\param g The Geometry object.
*/
template <typename Geometry>
inline detail::within<Geometry> within(Geometry const& g)
{
return detail::within<Geometry>(g);
}
/*!
\brief Generate satisfies() predicate.
A wrapper around user-defined UnaryPredicate checking if Value should be returned by spatial query.
\par Example
\verbatim
bool is_red(__value__ const& v) { return v.is_red(); }
struct is_red_o {
template <typename Value> bool operator()(__value__ const& v) { return v.is_red(); }
}
// ...
rt.query(index::intersects(box) && index::satisfies(is_red),
std::back_inserter(result));
rt.query(index::intersects(box) && index::satisfies(is_red_o()),
std::back_inserter(result));
#ifndef BOOST_NO_CXX11_LAMBDAS
rt.query(index::intersects(box) && index::satisfies([](__value__ const& v) { return v.is_red(); }),
std::back_inserter(result));
#endif
\endverbatim
\ingroup predicates
\tparam UnaryPredicate A type of unary predicate function or function object.
\param pred The unary predicate function or function object.
*/
template <typename UnaryPredicate>
inline detail::satisfies<UnaryPredicate> satisfies(UnaryPredicate const& pred)
{
return detail::satisfies<UnaryPredicate>(pred);
}
/*!
\brief Generate nearest() predicate.
When nearest predicate is passed to the query, k-nearest neighbour search will be performed.
The simplest way of defining the knn query is passing a \c Point to which \c Values must be closest.
It is possible to define how distance between values and query Point is calculated. This is done by passing PointRelation.
It can be generated by following functions:
\li \c boost::geometry::index::to_nearest() - default,
\li \c boost::geometry::index::to_centroid(),
\li \c boost::geometry::index::to_furthest().
\par Example
\verbatim
bgi::query(spatial_index, bgi::nearest(pt, 5), std::back_inserter(result));
bgi::query(spatial_index, bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result));
bgi::query(spatial_index, bgi::nearest(bgi::to_centroid(pt), 5) && bgi::within(box), std::back_inserter(result));
\endverbatim
\warning
Only one \c nearest() predicate may be used in a query.
\ingroup predicates
\param point_relation The point or relation describing how the distance will be calculated.
\param k The maximum number of values to return.
*/
template <typename PointOrRelation> inline
detail::nearest<PointOrRelation>
nearest(PointOrRelation const& point_relation, unsigned k)
{
return detail::nearest<PointOrRelation>(point_relation, k);
}
namespace detail {
// operator! generators
template <typename Geometry>
not_covered_by<Geometry>
operator!(covered_by<Geometry> const& p)
{
return not_covered_by<Geometry>(p.geometry);
}
template <typename Geometry>
covered_by<Geometry>
operator!(not_covered_by<Geometry> const& p)
{
return covered_by<Geometry>(p.geometry);
}
template <typename Geometry>
not_disjoint<Geometry>
operator!(disjoint<Geometry> const& p)
{
return not_disjoint<Geometry>(p.geometry);
}
template <typename Geometry>
disjoint<Geometry>
operator!(not_disjoint<Geometry> const& p)
{
return disjoint<Geometry>(p.geometry);
}
template <typename Geometry>
not_intersects<Geometry>
operator!(intersects<Geometry> const& p)
{
return not_intersects<Geometry>(p.geometry);
}
template <typename Geometry>
intersects<Geometry>
operator!(not_intersects<Geometry> const& p)
{
return intersects<Geometry>(p.geometry);
}
template <typename Geometry>
not_overlaps<Geometry>
operator!(overlaps<Geometry> const& p)
{
return not_overlaps<Geometry>(p.geometry);
}
template <typename Geometry>
overlaps<Geometry>
operator!(not_overlaps<Geometry> const& p)
{
return overlaps<Geometry>(p.geometry);
}
//template <typename Geometry>
//not_touches<Geometry>
//operator!(touches<Geometry> const& p)
//{
// return not_touches<Geometry>(p.geometry);
//}
//
//template <typename Geometry>
//touches<Geometry>
//operator!(not_touches<Geometry> const& p)
//{
// return touches<Geometry>(p.geometry);
//}
template <typename Geometry>
not_within<Geometry>
operator!(within<Geometry> const& p)
{
return not_within<Geometry>(p.geometry);
}
template <typename Geometry>
within<Geometry>
operator!(not_within<Geometry> const& p)
{
return within<Geometry>(p.geometry);
}
// operator&& generators
template <typename Pred1, typename Pred2> inline
boost::tuples::cons<
Pred1,
boost::tuples::cons<Pred2, boost::tuples::null_type>
>
operator&&(Pred1 const& p1, Pred2 const& p2)
{
/*typedef typename boost::mpl::if_c<is_predicate<Pred1>::value, Pred1, Pred1 const&>::type stored1;
typedef typename boost::mpl::if_c<is_predicate<Pred2>::value, Pred2, Pred2 const&>::type stored2;*/
namespace bt = boost::tuples;
return
bt::cons< Pred1, bt::cons<Pred2, bt::null_type> >
( p1, bt::cons<Pred2, bt::null_type>(p2, bt::null_type()) );
}
template <typename Head, typename Tail, typename Pred> inline
typename tuples::push_back_impl<
boost::tuples::cons<Head, Tail>,
Pred,
0,
boost::tuples::length<boost::tuples::cons<Head, Tail> >::value
>::type
operator&&(boost::tuples::cons<Head, Tail> const& t, Pred const& p)
{
//typedef typename boost::mpl::if_c<is_predicate<Pred>::value, Pred, Pred const&>::type stored;
namespace bt = boost::tuples;
return
tuples::push_back_impl<
bt::cons<Head, Tail>, Pred, 0, bt::length< bt::cons<Head, Tail> >::value
>::apply(t, p);
}
} // namespace detail
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_PREDICATES_HPP

File diff suppressed because it is too large Load Diff