mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-10 23:42:12 +00:00
index copied from branches to trunk
[SVN r83638]
This commit is contained in:
88
include/boost/geometry/index/adaptors/query.hpp
Normal file
88
include/boost/geometry/index/adaptors/query.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
85
include/boost/geometry/index/detail/algorithms/content.hpp
Normal file
85
include/boost/geometry/index/detail/algorithms/content.hpp
Normal 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
|
||||
24
include/boost/geometry/index/detail/algorithms/diff_abs.hpp
Normal file
24
include/boost/geometry/index/detail/algorithms/diff_abs.hpp
Normal 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
|
||||
@@ -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
|
||||
79
include/boost/geometry/index/detail/algorithms/is_valid.hpp
Normal file
79
include/boost/geometry/index/detail/algorithms/is_valid.hpp
Normal 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
|
||||
128
include/boost/geometry/index/detail/algorithms/margin.hpp
Normal file
128
include/boost/geometry/index/detail/algorithms/margin.hpp
Normal 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
|
||||
119
include/boost/geometry/index/detail/algorithms/minmaxdist.hpp
Normal file
119
include/boost/geometry/index/detail/algorithms/minmaxdist.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
27
include/boost/geometry/index/detail/assert.hpp
Normal file
27
include/boost/geometry/index/detail/assert.hpp
Normal 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
|
||||
24
include/boost/geometry/index/detail/config_begin.hpp
Normal file
24
include/boost/geometry/index/detail/config_begin.hpp
Normal 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
|
||||
|
||||
12
include/boost/geometry/index/detail/config_end.hpp
Normal file
12
include/boost/geometry/index/detail/config_end.hpp
Normal 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
|
||||
|
||||
866
include/boost/geometry/index/detail/distance_predicates.hpp
Normal file
866
include/boost/geometry/index/detail/distance_predicates.hpp
Normal 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
|
||||
139
include/boost/geometry/index/detail/indexable.hpp
Normal file
139
include/boost/geometry/index/detail/indexable.hpp
Normal 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
|
||||
903
include/boost/geometry/index/detail/predicates.hpp
Normal file
903
include/boost/geometry/index/detail/predicates.hpp
Normal 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
|
||||
171
include/boost/geometry/index/detail/pushable_array.hpp
Normal file
171
include/boost/geometry/index/detail/pushable_array.hpp
Normal 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
|
||||
54
include/boost/geometry/index/detail/rtree/adaptors.hpp
Normal file
54
include/boost/geometry/index/detail/rtree/adaptors.hpp
Normal 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
|
||||
16
include/boost/geometry/index/detail/rtree/kmeans/kmeans.hpp
Normal file
16
include/boost/geometry/index/detail/rtree/kmeans/kmeans.hpp
Normal 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
|
||||
87
include/boost/geometry/index/detail/rtree/kmeans/split.hpp
Normal file
87
include/boost/geometry/index/detail/rtree/kmeans/split.hpp
Normal 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
|
||||
16
include/boost/geometry/index/detail/rtree/linear/linear.hpp
Normal file
16
include/boost/geometry/index/detail/rtree/linear/linear.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
85
include/boost/geometry/index/detail/rtree/node/concept.hpp
Normal file
85
include/boost/geometry/index/detail/rtree/node/concept.hpp
Normal 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
|
||||
@@ -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
|
||||
173
include/boost/geometry/index/detail/rtree/node/node.hpp
Normal file
173
include/boost/geometry/index/detail/rtree/node/node.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
69
include/boost/geometry/index/detail/rtree/node/pairs.hpp
Normal file
69
include/boost/geometry/index/detail/rtree/node/pairs.hpp
Normal 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
|
||||
@@ -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
|
||||
155
include/boost/geometry/index/detail/rtree/options.hpp
Normal file
155
include/boost/geometry/index/detail/rtree/options.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
542
include/boost/geometry/index/detail/rtree/rstar/insert.hpp
Normal file
542
include/boost/geometry/index/detail/rtree/rstar/insert.hpp
Normal 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
|
||||
@@ -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
|
||||
18
include/boost/geometry/index/detail/rtree/rstar/rstar.hpp
Normal file
18
include/boost/geometry/index/detail/rtree/rstar/rstar.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
92
include/boost/geometry/index/detail/rtree/visitors/copy.hpp
Normal file
92
include/boost/geometry/index/detail/rtree/visitors/copy.hpp
Normal 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
|
||||
118
include/boost/geometry/index/detail/rtree/visitors/count.hpp
Normal file
118
include/boost/geometry/index/detail/rtree/visitors/count.hpp
Normal 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
|
||||
@@ -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
|
||||
221
include/boost/geometry/index/detail/rtree/visitors/gl_draw.hpp
Normal file
221
include/boost/geometry/index/detail/rtree/visitors/gl_draw.hpp
Normal 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
|
||||
511
include/boost/geometry/index/detail/rtree/visitors/insert.hpp
Normal file
511
include/boost/geometry/index/detail/rtree/visitors/insert.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
197
include/boost/geometry/index/detail/rtree/visitors/print.hpp
Normal file
197
include/boost/geometry/index/detail/rtree/visitors/print.hpp
Normal 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
|
||||
311
include/boost/geometry/index/detail/rtree/visitors/remove.hpp
Normal file
311
include/boost/geometry/index/detail/rtree/visitors/remove.hpp
Normal 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
|
||||
@@ -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
|
||||
25
include/boost/geometry/index/detail/tags.hpp
Normal file
25
include/boost/geometry/index/detail/tags.hpp
Normal 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
|
||||
60
include/boost/geometry/index/detail/translator.hpp
Normal file
60
include/boost/geometry/index/detail/translator.hpp
Normal 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
|
||||
201
include/boost/geometry/index/detail/tuples.hpp
Normal file
201
include/boost/geometry/index/detail/tuples.hpp
Normal 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
|
||||
881
include/boost/geometry/index/detail/varray.hpp
Normal file
881
include/boost/geometry/index/detail/varray.hpp
Normal 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
|
||||
200
include/boost/geometry/index/distance_predicates.hpp
Normal file
200
include/boost/geometry/index/distance_predicates.hpp
Normal 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
|
||||
178
include/boost/geometry/index/equal_to.hpp
Normal file
178
include/boost/geometry/index/equal_to.hpp
Normal 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
|
||||
140
include/boost/geometry/index/indexable.hpp
Normal file
140
include/boost/geometry/index/indexable.hpp
Normal 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
|
||||
78
include/boost/geometry/index/inserter.hpp
Normal file
78
include/boost/geometry/index/inserter.hpp
Normal 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
|
||||
204
include/boost/geometry/index/parameters.hpp
Normal file
204
include/boost/geometry/index/parameters.hpp
Normal 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
|
||||
373
include/boost/geometry/index/predicates.hpp
Normal file
373
include/boost/geometry/index/predicates.hpp
Normal 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
|
||||
1469
include/boost/geometry/index/rtree.hpp
Normal file
1469
include/boost/geometry/index/rtree.hpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user