stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -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,90 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// n-dimensional bounds
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_BOUNDS_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/bounded_view.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
namespace dispatch {
|
||||
|
||||
template <typename Geometry,
|
||||
typename Bounds,
|
||||
typename TagGeometry = typename geometry::tag<Geometry>::type,
|
||||
typename TagBounds = typename geometry::tag<Bounds>::type>
|
||||
struct bounds
|
||||
{
|
||||
static inline void apply(Geometry const& g, Bounds & b)
|
||||
{
|
||||
geometry::convert(g, b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry, typename Bounds>
|
||||
struct bounds<Geometry, Bounds, segment_tag, box_tag>
|
||||
{
|
||||
static inline void apply(Geometry const& g, Bounds & b)
|
||||
{
|
||||
index::detail::bounded_view<Geometry, Bounds> v(g);
|
||||
geometry::convert(v, b);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Geometry, typename Bounds>
|
||||
inline void bounds(Geometry const& g, Bounds & b)
|
||||
{
|
||||
concepts::check_concepts_and_equal_dimensions<Geometry const, Bounds>();
|
||||
dispatch::bounds<Geometry, Bounds>::apply(g, b);
|
||||
}
|
||||
|
||||
namespace dispatch {
|
||||
|
||||
template <typename Geometry,
|
||||
typename TagGeometry = typename geometry::tag<Geometry>::type>
|
||||
struct return_ref_or_bounds
|
||||
{
|
||||
typedef Geometry const& result_type;
|
||||
|
||||
static inline result_type apply(Geometry const& g)
|
||||
{
|
||||
return g;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct return_ref_or_bounds<Geometry, segment_tag>
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
typedef geometry::model::box<point_type> bounds_type;
|
||||
typedef index::detail::bounded_view<Geometry, bounds_type> result_type;
|
||||
|
||||
static inline result_type apply(Geometry const& g)
|
||||
{
|
||||
return result_type(g);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Geometry>
|
||||
inline
|
||||
typename dispatch::return_ref_or_bounds<Geometry>::result_type
|
||||
return_ref_or_bounds(Geometry const& g)
|
||||
{
|
||||
return dispatch::return_ref_or_bounds<Geometry>::apply(g);
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// squared distance between point and centroid of the box or point
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_comparable_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_comparable_distance_result<Point, BoxIndexable>::type result_type;
|
||||
|
||||
inline static result_type apply(Point const& pt, BoxIndexable const& i)
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type point_coord_t;
|
||||
typedef typename 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_comparable_distance_result<Point, Indexable>::type
|
||||
comparable_distance_centroid(Point const& pt, Indexable const& i)
|
||||
{
|
||||
return detail::sum_for_indexable<
|
||||
Point,
|
||||
Indexable,
|
||||
typename tag<Indexable>::type,
|
||||
detail::comparable_distance_centroid_tag,
|
||||
dimension<Indexable>::value
|
||||
>::apply(pt, i);
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // #define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// squared distance between point and furthest point of the box or point
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_comparable_distance_result<Point, BoxIndexable>::type result_type;
|
||||
|
||||
inline static result_type apply(Point const& pt, BoxIndexable const& i)
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type point_coord_t;
|
||||
typedef typename 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_comparable_distance_result<Point, Indexable>::type
|
||||
comparable_distance_far(Point const& pt, Indexable const& i)
|
||||
{
|
||||
return detail::sum_for_indexable<
|
||||
Point,
|
||||
Indexable,
|
||||
typename tag<Indexable>::type,
|
||||
detail::comparable_distance_far_tag,
|
||||
dimension<Indexable>::value
|
||||
>::apply(pt, i);
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// squared distance between point and nearest point of the box or point
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_comparable_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_comparable_distance_result<Point, BoxIndexable>::type result_type;
|
||||
|
||||
inline static result_type apply(Point const& pt, BoxIndexable const& i)
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type point_coord_t;
|
||||
typedef typename 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_comparable_distance_result<Point, Indexable>::type
|
||||
comparable_distance_near(Point const& pt, Indexable const& i)
|
||||
{
|
||||
return detail::sum_for_indexable<
|
||||
Point,
|
||||
Indexable,
|
||||
typename tag<Indexable>::type,
|
||||
detail::comparable_distance_near_tag,
|
||||
dimension<Indexable>::value
|
||||
>::apply(pt, i);
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// n-dimensional content (hypervolume) - 2d area, 3d volume, ...
|
||||
//
|
||||
// Copyright (c) 2011-2014 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 coordinate_type<Indexable>::type,
|
||||
long double
|
||||
>::type type;
|
||||
};
|
||||
|
||||
namespace dispatch {
|
||||
|
||||
template <typename Box,
|
||||
std::size_t CurrentDimension = dimension<Box>::value>
|
||||
struct content_box
|
||||
{
|
||||
BOOST_STATIC_ASSERT(0 < CurrentDimension);
|
||||
|
||||
static inline typename detail::default_content_result<Box>::type apply(Box const& b)
|
||||
{
|
||||
return content_box<Box, CurrentDimension - 1>::apply(b) *
|
||||
( get<max_corner, CurrentDimension - 1>(b) - get<min_corner, CurrentDimension - 1>(b) );
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct content_box<Box, 1>
|
||||
{
|
||||
static inline typename detail::default_content_result<Box>::type apply(Box const& b)
|
||||
{
|
||||
return get<max_corner, 0>(b) - get<min_corner, 0>(b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable, typename Tag>
|
||||
struct content
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_AND_TAG, (Indexable, Tag));
|
||||
};
|
||||
|
||||
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_box<Indexable>::apply(b);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Indexable>
|
||||
typename default_content_result<Indexable>::type content(Indexable const& b)
|
||||
{
|
||||
return dispatch::content
|
||||
<
|
||||
Indexable,
|
||||
typename tag<Indexable>::type
|
||||
>::apply(b);
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// 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_dispatch(T const& v1, T const& v2, boost::mpl::bool_<true> const& /*is_integral*/)
|
||||
{
|
||||
return v1 < v2 ? v2 - v1 : v1 - v2;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T diff_abs_dispatch(T const& v1, T const& v2, boost::mpl::bool_<false> const& /*is_integral*/)
|
||||
{
|
||||
return ::fabs(v1 - v2);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T diff_abs(T const& v1, T const& v2)
|
||||
{
|
||||
typedef boost::mpl::bool_<
|
||||
boost::is_integral<T>::value
|
||||
> is_integral;
|
||||
return diff_abs_dispatch(v1, v2, is_integral());
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// boxes union/intersection area/volume
|
||||
//
|
||||
// Copyright (c) 2011-2016 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/strategies/intersection_strategies.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;
|
||||
if ( 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
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// n-dimensional Indexable validity check
|
||||
//
|
||||
// Copyright (c) 2011-2014 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
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
namespace dispatch {
|
||||
|
||||
template <typename Box,
|
||||
std::size_t Dimension = geometry::dimension<Box>::value>
|
||||
struct is_valid_box
|
||||
{
|
||||
static inline bool apply(Box const& b)
|
||||
{
|
||||
return is_valid_box<Box, Dimension - 1>::apply(b) &&
|
||||
( get<min_corner, Dimension - 1>(b) <= get<max_corner, Dimension - 1>(b) );
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct is_valid_box<Box, 1>
|
||||
{
|
||||
static inline bool apply(Box const& b)
|
||||
{
|
||||
return get<min_corner, 0>(b) <= get<max_corner, 0>(b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable,
|
||||
typename Tag = typename geometry::tag<Indexable>::type>
|
||||
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>::apply(b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable>
|
||||
struct is_valid<Indexable, segment_tag>
|
||||
{
|
||||
static inline bool apply(Indexable const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Indexable>
|
||||
inline bool is_valid(Indexable const& b)
|
||||
{
|
||||
// CONSIDER: detection of NaNs
|
||||
// e.g. by comparison of b with copy of b
|
||||
|
||||
return dispatch::is_valid<Indexable>::apply(b);
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_DETAIL_INDEX_ALGORITHMS_IS_VALID_HPP
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// n-dimensional box's margin value (hypersurface), 2d perimeter, 3d surface, etc...
|
||||
//
|
||||
// Copyright (c) 2011-2014 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
|
||||
|
||||
// WARNING! comparable_margin() will work only if the same Geometries are compared
|
||||
// so it shouldn't be used in the case of Variants!
|
||||
|
||||
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,
|
||||
// std::size_t CurrentDimension,
|
||||
// std::size_t EdgeDimension = dimension<Box>::value>
|
||||
//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, std::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, std::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,
|
||||
// std::size_t CurrentDimension = dimension<Box>::value>
|
||||
//struct margin_for_each_dimension
|
||||
//{
|
||||
// BOOST_STATIC_ASSERT(0 < CurrentDimension);
|
||||
//
|
||||
// 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>::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>::apply(b);
|
||||
// }
|
||||
//};
|
||||
|
||||
// TODO - test if this definition of margin is ok for Dimension > 2
|
||||
// Now it's sum of edges lengths
|
||||
// maybe margin_for_each_dimension should be used to get more or less hypersurface?
|
||||
|
||||
template <typename Box,
|
||||
std::size_t CurrentDimension = dimension<Box>::value>
|
||||
struct simple_margin_for_each_dimension
|
||||
{
|
||||
BOOST_STATIC_ASSERT(0 < CurrentDimension);
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
namespace dispatch {
|
||||
|
||||
template <typename Geometry, typename Tag>
|
||||
struct comparable_margin
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY, (Geometry, Tag));
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct comparable_margin<Geometry, point_tag>
|
||||
{
|
||||
typedef typename default_margin_result<Geometry>::type result_type;
|
||||
|
||||
static inline result_type apply(Geometry const& ) { return 0; }
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct comparable_margin<Box, box_tag>
|
||||
{
|
||||
typedef typename default_margin_result<Box>::type result_type;
|
||||
|
||||
static inline result_type apply(Box const& g)
|
||||
{
|
||||
//return detail::margin_for_each_dimension<Box>::apply(g);
|
||||
return detail::simple_margin_for_each_dimension<Box>::apply(g);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Geometry>
|
||||
typename default_margin_result<Geometry>::type comparable_margin(Geometry const& g)
|
||||
{
|
||||
return dispatch::comparable_margin<
|
||||
Geometry,
|
||||
typename tag<Geometry>::type
|
||||
>::apply(g);
|
||||
}
|
||||
|
||||
//template <typename Box>
|
||||
//typename default_margin_result<Box>::type margin(Box const& b)
|
||||
//{
|
||||
// return 2 * detail::margin_for_each_dimension<Box>::apply(b);
|
||||
//}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// minmaxdist used in R-tree k nearest neighbors query
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_comparable_distance_result<Point, BoxIndexable>::type result_type;
|
||||
|
||||
inline static result_type apply(Point const& pt, BoxIndexable const& i, result_type const& maxd)
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type point_coord_t;
|
||||
typedef typename 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_comparable_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_comparable_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,
|
||||
dimension<Indexable>::value
|
||||
>::apply(pt, i, maxd);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is comparable distace.
|
||||
*/
|
||||
template <typename Point, typename Indexable>
|
||||
typename geometry::default_comparable_distance_result<Point, Indexable>::type
|
||||
minmaxdist(Point const& pt, Indexable const& i)
|
||||
{
|
||||
return detail::minmaxdist_impl<
|
||||
Point,
|
||||
Indexable,
|
||||
typename tag<Indexable>::type
|
||||
>::apply(pt, i);
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
// See https://svn.boost.org/trac/boost/ticket/12861
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58800
|
||||
// https://gcc.gnu.org/develop.html#timeline
|
||||
// 20120920 4.7.2 - no bug
|
||||
// 20130322 4.8.0 - no bug
|
||||
// 20130411 4.7.3 - no bug
|
||||
// 20130531 4.8.1 - no bug
|
||||
// 20131016 4.8.2 - bug
|
||||
// 20140422 4.9.0 - fixed
|
||||
// 20140522 4.8.3 - fixed
|
||||
// 20140612 4.7.4 - fixed
|
||||
// 20140716 4.9.1 - fixed
|
||||
#if defined(__GLIBCXX__) && (__GLIBCXX__ == 20131016)
|
||||
|
||||
#warning "std::nth_element replaced with std::sort, libstdc++ bug workaround.";
|
||||
|
||||
template <typename RandomIt>
|
||||
void nth_element(RandomIt first, RandomIt , RandomIt last)
|
||||
{
|
||||
std::sort(first, last);
|
||||
}
|
||||
|
||||
template <typename RandomIt, typename Compare>
|
||||
void nth_element(RandomIt first, RandomIt , RandomIt last, Compare comp)
|
||||
{
|
||||
std::sort(first, last, comp);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename RandomIt>
|
||||
void nth_element(RandomIt first, RandomIt nth, RandomIt last)
|
||||
{
|
||||
std::nth_element(first, nth, last);
|
||||
}
|
||||
|
||||
template <typename RandomIt, typename Compare>
|
||||
void nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp)
|
||||
{
|
||||
std::nth_element(first, nth, last, comp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// n-dimensional box-linestring intersection
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_PATH_INTERSECTION_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/segment_intersection.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
namespace dispatch {
|
||||
|
||||
template <typename Indexable, typename Geometry, typename IndexableTag, typename GeometryTag>
|
||||
struct path_intersection
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_OR_INDEXABLE, (path_intersection));
|
||||
};
|
||||
|
||||
// TODO: FP type must be used as a relative distance type!
|
||||
// and default_distance_result can be some user-defined int type
|
||||
// BUT! This code is experimental and probably won't be released at all
|
||||
// since more flexible user-defined-nearest predicate should be added instead
|
||||
|
||||
template <typename Indexable, typename Segment>
|
||||
struct path_intersection<Indexable, Segment, box_tag, segment_tag>
|
||||
{
|
||||
typedef typename default_distance_result<typename point_type<Segment>::type>::type comparable_distance_type;
|
||||
|
||||
static inline bool apply(Indexable const& b, Segment const& segment, comparable_distance_type & comparable_distance)
|
||||
{
|
||||
typedef typename point_type<Segment>::type point_type;
|
||||
point_type p1, p2;
|
||||
geometry::detail::assign_point_from_index<0>(segment, p1);
|
||||
geometry::detail::assign_point_from_index<1>(segment, p2);
|
||||
return index::detail::segment_intersection(b, p1, p2, comparable_distance);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable, typename Linestring>
|
||||
struct path_intersection<Indexable, Linestring, box_tag, linestring_tag>
|
||||
{
|
||||
typedef typename default_length_result<Linestring>::type comparable_distance_type;
|
||||
|
||||
static inline bool apply(Indexable const& b, Linestring const& path, comparable_distance_type & comparable_distance)
|
||||
{
|
||||
typedef typename ::boost::range_value<Linestring>::type point_type;
|
||||
typedef typename ::boost::range_const_iterator<Linestring>::type const_iterator;
|
||||
typedef typename ::boost::range_size<Linestring>::type size_type;
|
||||
|
||||
const size_type count = ::boost::size(path);
|
||||
|
||||
if ( count == 2 )
|
||||
{
|
||||
return index::detail::segment_intersection(b, *::boost::begin(path), *(::boost::begin(path)+1), comparable_distance);
|
||||
}
|
||||
else if ( 2 < count )
|
||||
{
|
||||
const_iterator it0 = ::boost::begin(path);
|
||||
const_iterator it1 = ::boost::begin(path) + 1;
|
||||
const_iterator last = ::boost::end(path);
|
||||
|
||||
comparable_distance = 0;
|
||||
|
||||
for ( ; it1 != last ; ++it0, ++it1 )
|
||||
{
|
||||
typename default_distance_result<point_type, point_type>::type
|
||||
dist = geometry::distance(*it0, *it1);
|
||||
|
||||
comparable_distance_type rel_dist;
|
||||
if ( index::detail::segment_intersection(b, *it0, *it1, rel_dist) )
|
||||
{
|
||||
comparable_distance += dist * rel_dist;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
comparable_distance += dist;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Indexable, typename SegmentOrLinestring>
|
||||
struct default_path_intersection_distance_type
|
||||
{
|
||||
typedef typename dispatch::path_intersection<
|
||||
Indexable, SegmentOrLinestring,
|
||||
typename tag<Indexable>::type,
|
||||
typename tag<SegmentOrLinestring>::type
|
||||
>::comparable_distance_type type;
|
||||
};
|
||||
|
||||
template <typename Indexable, typename SegmentOrLinestring> inline
|
||||
bool path_intersection(Indexable const& b,
|
||||
SegmentOrLinestring const& path,
|
||||
typename default_path_intersection_distance_type<Indexable, SegmentOrLinestring>::type & comparable_distance)
|
||||
{
|
||||
// TODO check Indexable and Linestring concepts
|
||||
|
||||
return dispatch::path_intersection<
|
||||
Indexable, SegmentOrLinestring,
|
||||
typename tag<Indexable>::type,
|
||||
typename tag<SegmentOrLinestring>::type
|
||||
>::apply(b, path, comparable_distance);
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// n-dimensional box-segment intersection
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_SEGMENT_INTERSECTION_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
//template <typename Indexable, typename Point>
|
||||
//struct default_relative_distance_type
|
||||
//{
|
||||
// typedef typename select_most_precise<
|
||||
// typename select_most_precise<
|
||||
// typename coordinate_type<Indexable>::type,
|
||||
// typename coordinate_type<Point>::type
|
||||
// >::type,
|
||||
// float // TODO - use bigger type, calculated from the size of coordinate types
|
||||
// >::type type;
|
||||
//
|
||||
//
|
||||
// BOOST_MPL_ASSERT_MSG((!::boost::is_unsigned<type>::value),
|
||||
// THIS_TYPE_SHOULDNT_BE_UNSIGNED, (type));
|
||||
//};
|
||||
|
||||
namespace dispatch {
|
||||
|
||||
template <typename Box, typename Point, size_t I>
|
||||
struct box_segment_intersection_dim
|
||||
{
|
||||
BOOST_STATIC_ASSERT(0 <= dimension<Box>::value);
|
||||
BOOST_STATIC_ASSERT(0 <= dimension<Point>::value);
|
||||
BOOST_STATIC_ASSERT(I < size_t(dimension<Box>::value));
|
||||
BOOST_STATIC_ASSERT(I < size_t(dimension<Point>::value));
|
||||
BOOST_STATIC_ASSERT(dimension<Point>::value == dimension<Box>::value);
|
||||
|
||||
// WARNING! - RelativeDistance must be IEEE float for this to work
|
||||
|
||||
template <typename RelativeDistance>
|
||||
static inline bool apply(Box const& b, Point const& p0, Point const& p1,
|
||||
RelativeDistance & t_near, RelativeDistance & t_far)
|
||||
{
|
||||
RelativeDistance ray_d = geometry::get<I>(p1) - geometry::get<I>(p0);
|
||||
RelativeDistance tn = ( geometry::get<min_corner, I>(b) - geometry::get<I>(p0) ) / ray_d;
|
||||
RelativeDistance tf = ( geometry::get<max_corner, I>(b) - geometry::get<I>(p0) ) / ray_d;
|
||||
if ( tf < tn )
|
||||
::std::swap(tn, tf);
|
||||
|
||||
if ( t_near < tn )
|
||||
t_near = tn;
|
||||
if ( tf < t_far )
|
||||
t_far = tf;
|
||||
|
||||
return 0 <= t_far && t_near <= t_far;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box, typename Point, size_t CurrentDimension>
|
||||
struct box_segment_intersection
|
||||
{
|
||||
BOOST_STATIC_ASSERT(0 < CurrentDimension);
|
||||
|
||||
typedef box_segment_intersection_dim<Box, Point, CurrentDimension - 1> for_dim;
|
||||
|
||||
template <typename RelativeDistance>
|
||||
static inline bool apply(Box const& b, Point const& p0, Point const& p1,
|
||||
RelativeDistance & t_near, RelativeDistance & t_far)
|
||||
{
|
||||
return box_segment_intersection<Box, Point, CurrentDimension - 1>::apply(b, p0, p1, t_near, t_far)
|
||||
&& for_dim::apply(b, p0, p1, t_near, t_far);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box, typename Point>
|
||||
struct box_segment_intersection<Box, Point, 1>
|
||||
{
|
||||
typedef box_segment_intersection_dim<Box, Point, 0> for_dim;
|
||||
|
||||
template <typename RelativeDistance>
|
||||
static inline bool apply(Box const& b, Point const& p0, Point const& p1,
|
||||
RelativeDistance & t_near, RelativeDistance & t_far)
|
||||
{
|
||||
return for_dim::apply(b, p0, p1, t_near, t_far);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable, typename Point, typename Tag>
|
||||
struct segment_intersection
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_GEOMETRY, (segment_intersection));
|
||||
};
|
||||
|
||||
template <typename Indexable, typename Point>
|
||||
struct segment_intersection<Indexable, Point, point_tag>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), SEGMENT_POINT_INTERSECTION_UNAVAILABLE, (segment_intersection));
|
||||
};
|
||||
|
||||
template <typename Indexable, typename Point>
|
||||
struct segment_intersection<Indexable, Point, box_tag>
|
||||
{
|
||||
typedef dispatch::box_segment_intersection<Indexable, Point, dimension<Indexable>::value> impl;
|
||||
|
||||
template <typename RelativeDistance>
|
||||
static inline bool apply(Indexable const& b, Point const& p0, Point const& p1, RelativeDistance & relative_distance)
|
||||
{
|
||||
|
||||
// TODO: this ASSERT CHECK is wrong for user-defined CoordinateTypes!
|
||||
|
||||
static const bool check = !::boost::is_integral<RelativeDistance>::value;
|
||||
BOOST_MPL_ASSERT_MSG(check, RELATIVE_DISTANCE_MUST_BE_FLOATING_POINT_TYPE, (RelativeDistance));
|
||||
|
||||
RelativeDistance t_near = -(::std::numeric_limits<RelativeDistance>::max)();
|
||||
RelativeDistance t_far = (::std::numeric_limits<RelativeDistance>::max)();
|
||||
|
||||
return impl::apply(b, p0, p1, t_near, t_far) &&
|
||||
(t_near <= 1) &&
|
||||
( relative_distance = 0 < t_near ? t_near : 0, true );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Indexable, typename Point, typename RelativeDistance> inline
|
||||
bool segment_intersection(Indexable const& b,
|
||||
Point const& p0,
|
||||
Point const& p1,
|
||||
RelativeDistance & relative_distance)
|
||||
{
|
||||
// TODO check Indexable and Point concepts
|
||||
|
||||
return dispatch::segment_intersection<
|
||||
Indexable, Point,
|
||||
typename tag<Indexable>::type
|
||||
>::apply(b, p0, p1, relative_distance);
|
||||
}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
|
||||
+80
@@ -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
|
||||
+76
@@ -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
|
||||
+33
@@ -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
|
||||
@@ -0,0 +1,19 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
|
||||
#undef BOOST_GEOMETRY_INDEX_ASSERT
|
||||
|
||||
#define BOOST_GEOMETRY_INDEX_ASSERT(CONDITION, TEXT_MSG) \
|
||||
BOOST_GEOMETRY_ASSERT_MSG(CONDITION, TEXT_MSG)
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
|
||||
@@ -0,0 +1,215 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// This view makes possible to treat some simple primitives as its bounding geometry
|
||||
// e.g. box, nsphere, etc.
|
||||
//
|
||||
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
|
||||
namespace boost { namespace geometry {
|
||||
|
||||
namespace index { namespace detail {
|
||||
|
||||
template <typename Geometry,
|
||||
typename BoundingGeometry,
|
||||
typename Tag = typename geometry::tag<Geometry>::type,
|
||||
typename BoundingTag = typename geometry::tag<BoundingGeometry>::type,
|
||||
typename CSystem = typename geometry::coordinate_system<Geometry>::type>
|
||||
struct bounded_view
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(false),
|
||||
NOT_IMPLEMENTED_FOR_THOSE_GEOMETRIES,
|
||||
(BoundingTag, Tag));
|
||||
};
|
||||
|
||||
|
||||
// Segment -> Box
|
||||
|
||||
template <typename Segment, typename Box>
|
||||
struct bounded_view<Segment, Box, segment_tag, box_tag, cs::cartesian>
|
||||
{
|
||||
public:
|
||||
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
explicit bounded_view(Segment const& segment)
|
||||
: m_segment(segment)
|
||||
{}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
inline coordinate_type get_min() const
|
||||
{
|
||||
return boost::numeric_cast<coordinate_type>(
|
||||
(std::min)( geometry::get<0, Dimension>(m_segment),
|
||||
geometry::get<1, Dimension>(m_segment) ) );
|
||||
}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
inline coordinate_type get_max() const
|
||||
{
|
||||
return boost::numeric_cast<coordinate_type>(
|
||||
(std::max)( geometry::get<0, Dimension>(m_segment),
|
||||
geometry::get<1, Dimension>(m_segment) ) );
|
||||
}
|
||||
|
||||
private:
|
||||
Segment const& m_segment;
|
||||
};
|
||||
|
||||
template <typename Segment, typename Box, typename CSystem>
|
||||
struct bounded_view<Segment, Box, segment_tag, box_tag, CSystem>
|
||||
{
|
||||
public:
|
||||
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
explicit bounded_view(Segment const& segment)
|
||||
{
|
||||
geometry::envelope(segment, m_box);
|
||||
}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
inline coordinate_type get_min() const
|
||||
{
|
||||
return geometry::get<min_corner, Dimension>(m_box);
|
||||
}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
inline coordinate_type get_max() const
|
||||
{
|
||||
return geometry::get<max_corner, Dimension>(m_box);
|
||||
}
|
||||
|
||||
private:
|
||||
Box m_box;
|
||||
};
|
||||
|
||||
// Box -> Box
|
||||
|
||||
template <typename BoxIn, typename Box, typename CSystem>
|
||||
struct bounded_view<BoxIn, Box, box_tag, box_tag, CSystem>
|
||||
{
|
||||
public:
|
||||
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
explicit bounded_view(BoxIn const& box)
|
||||
: m_box(box)
|
||||
{}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
inline coordinate_type get_min() const
|
||||
{
|
||||
return boost::numeric_cast<coordinate_type>(
|
||||
geometry::get<min_corner, Dimension>(m_box) );
|
||||
}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
inline coordinate_type get_max() const
|
||||
{
|
||||
return boost::numeric_cast<coordinate_type>(
|
||||
geometry::get<max_corner, Dimension>(m_box) );
|
||||
}
|
||||
|
||||
private:
|
||||
BoxIn const& m_box;
|
||||
};
|
||||
|
||||
// Point -> Box
|
||||
|
||||
template <typename Point, typename Box, typename CSystem>
|
||||
struct bounded_view<Point, Box, point_tag, box_tag, CSystem>
|
||||
{
|
||||
public:
|
||||
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
explicit bounded_view(Point const& point)
|
||||
: m_point(point)
|
||||
{}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
inline coordinate_type get_min() const
|
||||
{
|
||||
return boost::numeric_cast<coordinate_type>(
|
||||
geometry::get<Dimension>(m_point) );
|
||||
}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
inline coordinate_type get_max() const
|
||||
{
|
||||
return boost::numeric_cast<coordinate_type>(
|
||||
geometry::get<Dimension>(m_point) );
|
||||
}
|
||||
|
||||
private:
|
||||
Point const& m_point;
|
||||
};
|
||||
|
||||
}} // namespace index::detail
|
||||
|
||||
// XXX -> Box
|
||||
|
||||
#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
|
||||
namespace traits
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Box, typename Tag, typename CSystem>
|
||||
struct tag< index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> >
|
||||
{
|
||||
typedef box_tag type;
|
||||
};
|
||||
|
||||
template <typename Geometry, typename Box, typename Tag, typename CSystem>
|
||||
struct point_type< index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> >
|
||||
{
|
||||
typedef typename point_type<Box>::type type;
|
||||
};
|
||||
|
||||
template <typename Geometry, typename Box, typename Tag, typename CSystem, std::size_t Dimension>
|
||||
struct indexed_access<index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem>,
|
||||
min_corner, Dimension>
|
||||
{
|
||||
typedef index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> box_type;
|
||||
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
static inline coordinate_type get(box_type const& b)
|
||||
{
|
||||
return b.template get_min<Dimension>();
|
||||
}
|
||||
|
||||
//static inline void set(box_type & b, coordinate_type const& value)
|
||||
//{
|
||||
// BOOST_GEOMETRY_INDEX_ASSERT(false, "unable to modify a box through view");
|
||||
//}
|
||||
};
|
||||
|
||||
template <typename Geometry, typename Box, typename Tag, typename CSystem, std::size_t Dimension>
|
||||
struct indexed_access<index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem>,
|
||||
max_corner, Dimension>
|
||||
{
|
||||
typedef index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> box_type;
|
||||
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
static inline coordinate_type get(box_type const& b)
|
||||
{
|
||||
return b.template get_max<Dimension>();
|
||||
}
|
||||
|
||||
//static inline void set(box_type & b, coordinate_type const& value)
|
||||
//{
|
||||
// BOOST_GEOMETRY_INDEX_ASSERT(false, "unable to modify a box through view");
|
||||
//}
|
||||
};
|
||||
|
||||
} // namespace traits
|
||||
#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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
|
||||
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4512) // assignment operator could not be generated
|
||||
#pragma warning (disable : 4127) // conditional expression is constant
|
||||
|
||||
// temporary?
|
||||
#pragma warning (disable : 4180) // qualifier applied to function type has no meaning
|
||||
|
||||
#endif //BOOST_MSVC
|
||||
|
||||
@@ -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
|
||||
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Spatial index distance predicates, calculators and checkers
|
||||
// used in nearest query - specialized for envelopes
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_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/algorithms/path_intersection.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/tags.hpp>
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
// calculate_distance
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
template <typename Predicate, typename Indexable, typename Tag>
|
||||
struct calculate_distance
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), INVALID_PREDICATE_OR_TAG, (calculate_distance));
|
||||
};
|
||||
|
||||
// this handles nearest() with default Point parameter, to_nearest() and bounds
|
||||
template <typename PointRelation, typename Indexable, typename Tag>
|
||||
struct calculate_distance< predicates::nearest<PointRelation>, Indexable, Tag >
|
||||
{
|
||||
typedef detail::relation<PointRelation> relation;
|
||||
typedef typename relation::value_type point_type;
|
||||
typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;
|
||||
|
||||
static inline bool apply(predicates::nearest<PointRelation> const& p, Indexable const& i, result_type & result)
|
||||
{
|
||||
result = geometry::comparable_distance(relation::value(p.point_or_relation), i);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point, typename Indexable>
|
||||
struct calculate_distance< predicates::nearest< to_centroid<Point> >, Indexable, value_tag>
|
||||
{
|
||||
typedef Point point_type;
|
||||
typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;
|
||||
|
||||
static inline bool apply(predicates::nearest< to_centroid<Point> > const& p, Indexable const& i, result_type & result)
|
||||
{
|
||||
result = index::detail::comparable_distance_centroid(p.point_or_relation.value, i);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point, typename Indexable>
|
||||
struct calculate_distance< predicates::nearest< to_furthest<Point> >, Indexable, value_tag>
|
||||
{
|
||||
typedef Point point_type;
|
||||
typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;
|
||||
|
||||
static inline bool apply(predicates::nearest< to_furthest<Point> > const& p, Indexable const& i, result_type & result)
|
||||
{
|
||||
result = index::detail::comparable_distance_far(p.point_or_relation.value, i);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename SegmentOrLinestring, typename Indexable, typename Tag>
|
||||
struct calculate_distance< predicates::path<SegmentOrLinestring>, Indexable, Tag>
|
||||
{
|
||||
typedef typename index::detail::default_path_intersection_distance_type<
|
||||
Indexable, SegmentOrLinestring
|
||||
>::type result_type;
|
||||
|
||||
static inline bool apply(predicates::path<SegmentOrLinestring> const& p, Indexable const& i, result_type & result)
|
||||
{
|
||||
return index::detail::path_intersection(i, p.geometry, result);
|
||||
}
|
||||
};
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_RTREE_DISTANCE_PREDICATES_HPP
|
||||
@@ -0,0 +1,87 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_EXCEPTION_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP
|
||||
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#include <stdexcept>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#else
|
||||
#include <cstdlib>
|
||||
#include <boost/geometry/index/detail/assert.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
inline void throw_runtime_error(const char * str)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(str));
|
||||
}
|
||||
|
||||
inline void throw_logic_error(const char * str)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::logic_error(str));
|
||||
}
|
||||
|
||||
inline void throw_invalid_argument(const char * str)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument(str));
|
||||
}
|
||||
|
||||
inline void throw_length_error(const char * str)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::length_error(str));
|
||||
}
|
||||
|
||||
inline void throw_out_of_range(const char * str)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range(str));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void throw_runtime_error(const char * str)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(!"runtime_error thrown", str);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
inline void throw_logic_error(const char * str)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(!"logic_error thrown", str);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
inline void throw_invalid_argument(const char * str)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(!"invalid_argument thrown", str);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
inline void throw_length_error(const char * str)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(!"length_error thrown", str);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
inline void throw_out_of_range(const char * str)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(!"out_of_range thrown", str);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_IS_BOUNDING_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_IS_BOUNDING_GEOMETRY_HPP
|
||||
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename geometry::tag<Geometry>::type
|
||||
>
|
||||
struct is_bounding_geometry
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct is_bounding_geometry<Box, box_tag>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
}}}} // namespave boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_IS_BOUNDING_GEOMETRY_HPP
|
||||
@@ -0,0 +1,47 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_IS_INDEXABLE_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_IS_INDEXABLE_HPP
|
||||
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename geometry::tag<Geometry>::type
|
||||
>
|
||||
struct is_indexable
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct is_indexable<Point, geometry::point_tag>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct is_indexable<Box, geometry::box_tag>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <typename Segment>
|
||||
struct is_indexable<Segment, geometry::segment_tag>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
}}}} // namespave boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_IS_INDEXABLE_HPP
|
||||
@@ -0,0 +1,42 @@
|
||||
// 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/range.hpp>
|
||||
#include <boost/mpl/aux_/has_type.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
//#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_META_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_META_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
template <typename T>
|
||||
struct is_range
|
||||
: ::boost::mpl::aux::has_type< ::boost::range_iterator<T> >
|
||||
{};
|
||||
|
||||
//template <typename T, typename V, bool IsRange>
|
||||
//struct is_range_of_convertible_values_impl
|
||||
// : ::boost::is_convertible<typename ::boost::range_value<T>::type, V>
|
||||
//{};
|
||||
//
|
||||
//template <typename T, typename V>
|
||||
//struct is_range_of_convertible_values_impl<T, V, false>
|
||||
// : ::boost::mpl::bool_<false>
|
||||
//{};
|
||||
//
|
||||
//template <typename T, typename V>
|
||||
//struct is_range_of_convertible_values
|
||||
// : is_range_of_convertible_values_impl<T, V, is_range<T>::value>
|
||||
//{};
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_META_HPP
|
||||
@@ -0,0 +1,831 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Spatial query predicates definition and checks.
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
|
||||
|
||||
//#include <utility>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/tags.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
namespace predicates {
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
// predicates
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
template <typename Fun, bool IsFunction>
|
||||
struct satisfies_impl
|
||||
{
|
||||
satisfies_impl() : fun(NULL) {}
|
||||
satisfies_impl(Fun f) : fun(f) {}
|
||||
Fun * fun;
|
||||
};
|
||||
|
||||
template <typename Fun>
|
||||
struct satisfies_impl<Fun, false>
|
||||
{
|
||||
satisfies_impl() {}
|
||||
satisfies_impl(Fun const& f) : fun(f) {}
|
||||
Fun fun;
|
||||
};
|
||||
|
||||
template <typename Fun, bool Negated>
|
||||
struct satisfies
|
||||
: satisfies_impl<Fun, ::boost::is_function<Fun>::value>
|
||||
{
|
||||
typedef satisfies_impl<Fun, ::boost::is_function<Fun>::value> base;
|
||||
|
||||
satisfies() {}
|
||||
satisfies(Fun const& f) : base(f) {}
|
||||
satisfies(base const& b) : base(b) {}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
struct contains_tag {};
|
||||
struct covered_by_tag {};
|
||||
struct covers_tag {};
|
||||
struct disjoint_tag {};
|
||||
struct intersects_tag {};
|
||||
struct overlaps_tag {};
|
||||
struct touches_tag {};
|
||||
struct within_tag {};
|
||||
|
||||
template <typename Geometry, typename Tag, bool Negated>
|
||||
struct spatial_predicate
|
||||
{
|
||||
spatial_predicate() {}
|
||||
spatial_predicate(Geometry const& g) : geometry(g) {}
|
||||
Geometry geometry;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
// CONSIDER: separated nearest<> and path<> may be replaced by
|
||||
// nearest_predicate<Geometry, Tag>
|
||||
// where Tag = point_tag | path_tag
|
||||
// IMPROVEMENT: user-defined nearest predicate allowing to define
|
||||
// all or only geometrical aspects of the search
|
||||
|
||||
template <typename PointOrRelation>
|
||||
struct nearest
|
||||
{
|
||||
nearest()
|
||||
// : count(0)
|
||||
{}
|
||||
nearest(PointOrRelation const& por, unsigned k)
|
||||
: point_or_relation(por)
|
||||
, count(k)
|
||||
{}
|
||||
PointOrRelation point_or_relation;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
template <typename SegmentOrLinestring>
|
||||
struct path
|
||||
{
|
||||
path()
|
||||
// : count(0)
|
||||
{}
|
||||
path(SegmentOrLinestring const& g, unsigned k)
|
||||
: geometry(g)
|
||||
, count(k)
|
||||
{}
|
||||
SegmentOrLinestring geometry;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
} // namespace predicates
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
// predicate_check
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
template <typename Predicate, typename Tag>
|
||||
struct predicate_check
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(false),
|
||||
NOT_IMPLEMENTED_FOR_THIS_PREDICATE_OR_TAG,
|
||||
(predicate_check));
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
template <typename Fun>
|
||||
struct predicate_check<predicates::satisfies<Fun, false>, value_tag>
|
||||
{
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(predicates::satisfies<Fun, false> const& p, Value const& v, Indexable const&)
|
||||
{
|
||||
return p.fun(v);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Fun>
|
||||
struct predicate_check<predicates::satisfies<Fun, true>, value_tag>
|
||||
{
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(predicates::satisfies<Fun, true> const& p, Value const& v, Indexable const&)
|
||||
{
|
||||
return !p.fun(v);
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
template <typename Tag>
|
||||
struct spatial_predicate_call
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
|
||||
};
|
||||
|
||||
template <>
|
||||
struct spatial_predicate_call<predicates::contains_tag>
|
||||
{
|
||||
template <typename G1, typename G2>
|
||||
static inline bool apply(G1 const& g1, G2 const& g2)
|
||||
{
|
||||
return geometry::within(g2, g1);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct spatial_predicate_call<predicates::covered_by_tag>
|
||||
{
|
||||
template <typename G1, typename G2>
|
||||
static inline bool apply(G1 const& g1, G2 const& g2)
|
||||
{
|
||||
return geometry::covered_by(g1, g2);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct spatial_predicate_call<predicates::covers_tag>
|
||||
{
|
||||
template <typename G1, typename G2>
|
||||
static inline bool apply(G1 const& g1, G2 const& g2)
|
||||
{
|
||||
return geometry::covered_by(g2, g1);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct spatial_predicate_call<predicates::disjoint_tag>
|
||||
{
|
||||
template <typename G1, typename G2>
|
||||
static inline bool apply(G1 const& g1, G2 const& g2)
|
||||
{
|
||||
return geometry::disjoint(g1, g2);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct spatial_predicate_call<predicates::intersects_tag>
|
||||
{
|
||||
template <typename G1, typename G2>
|
||||
static inline bool apply(G1 const& g1, G2 const& g2)
|
||||
{
|
||||
return geometry::intersects(g1, g2);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct spatial_predicate_call<predicates::overlaps_tag>
|
||||
{
|
||||
template <typename G1, typename G2>
|
||||
static inline bool apply(G1 const& g1, G2 const& g2)
|
||||
{
|
||||
return geometry::overlaps(g1, g2);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct spatial_predicate_call<predicates::touches_tag>
|
||||
{
|
||||
template <typename G1, typename G2>
|
||||
static inline bool apply(G1 const& g1, G2 const& g2)
|
||||
{
|
||||
return geometry::touches(g1, g2);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct spatial_predicate_call<predicates::within_tag>
|
||||
{
|
||||
template <typename G1, typename G2>
|
||||
static inline bool apply(G1 const& g1, G2 const& g2)
|
||||
{
|
||||
return geometry::within(g1, g2);
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
// spatial predicate
|
||||
template <typename Geometry, typename Tag>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, value_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
|
||||
{
|
||||
return spatial_predicate_call<Tag>::apply(i, p.geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// negated spatial predicate
|
||||
template <typename Geometry, typename Tag>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, value_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
|
||||
{
|
||||
return !spatial_predicate_call<Tag>::apply(i, p.geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
template <typename DistancePredicates>
|
||||
struct predicate_check<predicates::nearest<DistancePredicates>, value_tag>
|
||||
{
|
||||
template <typename Value, typename Box>
|
||||
static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Linestring>
|
||||
struct predicate_check<predicates::path<Linestring>, value_tag>
|
||||
{
|
||||
template <typename Value, typename Box>
|
||||
static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
// predicates_check for bounds
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
template <typename Fun, bool Negated>
|
||||
struct predicate_check<predicates::satisfies<Fun, Negated>, bounds_tag>
|
||||
{
|
||||
template <typename Value, typename Box>
|
||||
static bool apply(predicates::satisfies<Fun, Negated> const&, Value const&, Box const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
// NOT NEGATED
|
||||
// value_tag bounds_tag
|
||||
// ---------------------------
|
||||
// contains(I,G) covers(I,G)
|
||||
// covered_by(I,G) intersects(I,G)
|
||||
// covers(I,G) covers(I,G)
|
||||
// disjoint(I,G) !covered_by(I,G)
|
||||
// intersects(I,G) intersects(I,G)
|
||||
// overlaps(I,G) intersects(I,G) - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
|
||||
// touches(I,G) intersects(I,G)
|
||||
// within(I,G) intersects(I,G) - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
|
||||
|
||||
// spatial predicate - default
|
||||
template <typename Geometry, typename Tag>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
|
||||
{
|
||||
return spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// spatial predicate - contains
|
||||
template <typename Geometry>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, false>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, false> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
|
||||
{
|
||||
return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// spatial predicate - covers
|
||||
template <typename Geometry>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, false>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, false> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
|
||||
{
|
||||
return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// spatial predicate - disjoint
|
||||
template <typename Geometry>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
|
||||
{
|
||||
return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// NEGATED
|
||||
// value_tag bounds_tag
|
||||
// ---------------------------
|
||||
// !contains(I,G) TRUE
|
||||
// !covered_by(I,G) !covered_by(I,G)
|
||||
// !covers(I,G) TRUE
|
||||
// !disjoint(I,G) !disjoint(I,G)
|
||||
// !intersects(I,G) !covered_by(I,G)
|
||||
// !overlaps(I,G) TRUE
|
||||
// !touches(I,G) !intersects(I,G)
|
||||
// !within(I,G) !within(I,G)
|
||||
|
||||
// negated spatial predicate - default
|
||||
template <typename Geometry, typename Tag>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
|
||||
{
|
||||
return !spatial_predicate_call<Tag>::apply(i, p.geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// negated spatial predicate - contains
|
||||
template <typename Geometry>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, true>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, true> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& , Value const&, Indexable const& )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// negated spatial predicate - covers
|
||||
template <typename Geometry>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, true>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, true> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& , Value const&, Indexable const& )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// negated spatial predicate - intersects
|
||||
template <typename Geometry>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, predicates::intersects_tag, true>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, predicates::intersects_tag, true> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
|
||||
{
|
||||
return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// negated spatial predicate - overlaps
|
||||
template <typename Geometry>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& , Value const&, Indexable const& )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// negated spatial predicate - touches
|
||||
template <typename Geometry>
|
||||
struct predicate_check<predicates::spatial_predicate<Geometry, predicates::touches_tag, true>, bounds_tag>
|
||||
{
|
||||
typedef predicates::spatial_predicate<Geometry, predicates::touches_tag, true> Pred;
|
||||
|
||||
template <typename Value, typename Indexable>
|
||||
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
|
||||
{
|
||||
return !spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
template <typename DistancePredicates>
|
||||
struct predicate_check<predicates::nearest<DistancePredicates>, bounds_tag>
|
||||
{
|
||||
template <typename Value, typename Box>
|
||||
static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Linestring>
|
||||
struct predicate_check<predicates::path<Linestring>, bounds_tag>
|
||||
{
|
||||
template <typename Value, typename Box>
|
||||
static inline bool apply(predicates::path<Linestring> 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, unsigned First, unsigned Last>
|
||||
struct predicates_check_impl
|
||||
{
|
||||
static const bool check = First < 1 && Last <= 1 && First <= Last;
|
||||
BOOST_MPL_ASSERT_MSG((check), 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;
|
||||
static const bool check = First < pred_len && Last <= pred_len && First <= Last;
|
||||
BOOST_MPL_ASSERT_MSG((check), 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_distance
|
||||
{
|
||||
static const unsigned value = 0;
|
||||
};
|
||||
|
||||
template <typename DistancePredicates>
|
||||
struct predicates_is_distance< predicates::nearest<DistancePredicates> >
|
||||
{
|
||||
static const unsigned value = 1;
|
||||
};
|
||||
|
||||
template <typename Linestring>
|
||||
struct predicates_is_distance< predicates::path<Linestring> >
|
||||
{
|
||||
static const unsigned value = 1;
|
||||
};
|
||||
|
||||
// predicates_count_nearest
|
||||
|
||||
template <typename T>
|
||||
struct predicates_count_distance
|
||||
{
|
||||
static const unsigned value = predicates_is_distance<T>::value;
|
||||
};
|
||||
|
||||
//template <typename F, typename S>
|
||||
//struct predicates_count_distance< std::pair<F, S> >
|
||||
//{
|
||||
// static const unsigned value = predicates_is_distance<F>::value
|
||||
// + predicates_is_distance<S>::value;
|
||||
//};
|
||||
|
||||
template <typename Tuple, unsigned N>
|
||||
struct predicates_count_distance_tuple
|
||||
{
|
||||
static const unsigned value =
|
||||
predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value
|
||||
+ predicates_count_distance_tuple<Tuple, N-1>::value;
|
||||
};
|
||||
|
||||
template <typename Tuple>
|
||||
struct predicates_count_distance_tuple<Tuple, 1>
|
||||
{
|
||||
static const unsigned value =
|
||||
predicates_is_distance<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_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
|
||||
//{
|
||||
// static const unsigned value = predicates_count_distance_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_distance< boost::tuples::cons<Head, Tail> >
|
||||
{
|
||||
static const unsigned value = predicates_count_distance_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_distance
|
||||
{
|
||||
static const unsigned value = predicates_is_distance<T>::value ? 0 : 1;
|
||||
};
|
||||
|
||||
//template <typename F, typename S>
|
||||
//struct predicates_find_distance< std::pair<F, S> >
|
||||
//{
|
||||
// static const unsigned value = predicates_is_distance<F>::value ? 0 :
|
||||
// (predicates_is_distance<S>::value ? 1 : 2);
|
||||
//};
|
||||
|
||||
template <typename Tuple, unsigned N>
|
||||
struct predicates_find_distance_tuple
|
||||
{
|
||||
static const bool is_found = predicates_find_distance_tuple<Tuple, N-1>::is_found
|
||||
|| predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value;
|
||||
|
||||
static const unsigned value = predicates_find_distance_tuple<Tuple, N-1>::is_found ?
|
||||
predicates_find_distance_tuple<Tuple, N-1>::value :
|
||||
(predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value ?
|
||||
N-1 : boost::tuples::length<Tuple>::value);
|
||||
};
|
||||
|
||||
template <typename Tuple>
|
||||
struct predicates_find_distance_tuple<Tuple, 1>
|
||||
{
|
||||
static const bool is_found = predicates_is_distance<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_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
|
||||
//{
|
||||
// static const unsigned value = predicates_find_distance_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_distance< boost::tuples::cons<Head, Tail> >
|
||||
{
|
||||
static const unsigned value = predicates_find_distance_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
|
||||
@@ -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
|
||||
@@ -0,0 +1,122 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree iterators
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
|
||||
|
||||
template <typename Value, typename Allocators>
|
||||
struct end_iterator
|
||||
{
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Value value_type;
|
||||
typedef typename Allocators::const_reference reference;
|
||||
typedef typename Allocators::difference_type difference_type;
|
||||
typedef typename Allocators::const_pointer pointer;
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");
|
||||
pointer p(0);
|
||||
return *p;
|
||||
}
|
||||
|
||||
const value_type * operator->() const
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");
|
||||
const value_type * p = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
end_iterator & operator++()
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");
|
||||
return *this;
|
||||
}
|
||||
|
||||
end_iterator operator++(int)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(end_iterator const& /*l*/, end_iterator const& /*r*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class iterator
|
||||
{
|
||||
typedef visitors::iterator<Value, Options, Translator, Box, Allocators> visitor_type;
|
||||
typedef typename visitor_type::node_pointer node_pointer;
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Value value_type;
|
||||
typedef typename Allocators::const_reference reference;
|
||||
typedef typename Allocators::difference_type difference_type;
|
||||
typedef typename Allocators::const_pointer pointer;
|
||||
|
||||
inline iterator()
|
||||
{}
|
||||
|
||||
inline iterator(node_pointer root)
|
||||
{
|
||||
m_visitor.initialize(root);
|
||||
}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
return m_visitor.dereference();
|
||||
}
|
||||
|
||||
const value_type * operator->() const
|
||||
{
|
||||
return boost::addressof(m_visitor.dereference());
|
||||
}
|
||||
|
||||
iterator & operator++()
|
||||
{
|
||||
m_visitor.increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int)
|
||||
{
|
||||
iterator temp = *this;
|
||||
this->operator++();
|
||||
return temp;
|
||||
}
|
||||
|
||||
friend bool operator==(iterator const& l, iterator const& r)
|
||||
{
|
||||
return l.m_visitor == r.m_visitor;
|
||||
}
|
||||
|
||||
friend bool operator==(iterator const& l, end_iterator<Value, Allocators> const& /*r*/)
|
||||
{
|
||||
return l.m_visitor.is_end();
|
||||
}
|
||||
|
||||
friend bool operator==(end_iterator<Value, Allocators> const& /*l*/, iterator const& r)
|
||||
{
|
||||
return r.m_visitor.is_end();
|
||||
}
|
||||
|
||||
private:
|
||||
visitor_type m_visitor;
|
||||
};
|
||||
|
||||
}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP
|
||||
+16
@@ -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
@@ -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
@@ -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
|
||||
+446
@@ -0,0 +1,446 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree linear split algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2008 Federico J. Fernandez.
|
||||
// Copyright (c) 2011-2014 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/bounded_view.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/node.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
namespace linear {
|
||||
|
||||
template <typename R, typename T>
|
||||
inline R difference_dispatch(T const& from, T const& to, ::boost::mpl::bool_<false> const& /*is_unsigned*/)
|
||||
{
|
||||
return to - from;
|
||||
}
|
||||
|
||||
template <typename R, typename T>
|
||||
inline R difference_dispatch(T const& from, T const& to, ::boost::mpl::bool_<true> const& /*is_unsigned*/)
|
||||
{
|
||||
return from <= to ? R(to - from) : -R(from - to);
|
||||
}
|
||||
|
||||
template <typename R, typename T>
|
||||
inline R difference(T const& from, T const& to)
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(!boost::is_unsigned<R>::value, RESULT_CANT_BE_UNSIGNED, (R));
|
||||
|
||||
typedef ::boost::mpl::bool_<
|
||||
boost::is_unsigned<T>::value
|
||||
> is_unsigned;
|
||||
|
||||
return difference_dispatch<R>(from, to, is_unsigned());
|
||||
}
|
||||
|
||||
// TODO: awulkiew
|
||||
// In general, all aerial Indexables in the tree with box-like nodes will be analyzed as boxes
|
||||
// because they must fit into larger box. Therefore the algorithm could be the same for Bounds type.
|
||||
// E.g. if Bounds type is sphere, Indexables probably should be analyzed as spheres.
|
||||
// 1. View could be provided to 'see' all Indexables as Bounds type.
|
||||
// Not ok in the case of big types like Ring, however it's possible that Rings won't be supported,
|
||||
// only simple types. Even then if we consider storing Box inside the Sphere we must calculate
|
||||
// the bounding sphere 2x for each box because there are 2 loops. For each calculation this means
|
||||
// 4-2d or 8-3d expansions or -, / and sqrt().
|
||||
// 2. Additional container could be used and reused if the Indexable type is other than the Bounds type.
|
||||
|
||||
// IMPORTANT!
|
||||
// Still probably the best way would be providing specialized algorithms for each Indexable-Bounds pair!
|
||||
// Probably on pick_seeds algorithm level - For Bounds=Sphere seeds would be choosen differently
|
||||
|
||||
// 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.
|
||||
|
||||
// The following struct/method was adapted for the preliminary version of the R-tree. Then it was called:
|
||||
// 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, typename Tag, 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 coordinate_type<indexable_type>::type coordinate_type;
|
||||
|
||||
typedef typename boost::mpl::if_c<
|
||||
boost::is_integral<coordinate_type>::value,
|
||||
double,
|
||||
coordinate_type
|
||||
>::type separation_type;
|
||||
|
||||
typedef typename geometry::point_type<indexable_type>::type point_type;
|
||||
typedef geometry::model::box<point_type> bounds_type;
|
||||
typedef index::detail::bounded_view<indexable_type, bounds_type> bounded_view_type;
|
||||
|
||||
static inline void apply(Elements const& elements,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator,
|
||||
separation_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
|
||||
bounded_view_type bounded_indexable_0(rtree::element_indexable(elements[0], translator));
|
||||
coordinate_type lowest_low = geometry::get<min_corner, DimensionIndex>(bounded_indexable_0);
|
||||
coordinate_type highest_high = geometry::get<max_corner, DimensionIndex>(bounded_indexable_0);
|
||||
|
||||
// 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 )
|
||||
{
|
||||
bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator));
|
||||
coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(bounded_indexable);
|
||||
coordinate_type max_coord = geometry::get<max_corner, DimensionIndex>(bounded_indexable);
|
||||
|
||||
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;
|
||||
bounded_view_type bounded_indexable_hl(rtree::element_indexable(elements[highest_low_index], translator));
|
||||
coordinate_type highest_low = geometry::get<min_corner, DimensionIndex>(bounded_indexable_hl);
|
||||
for ( size_t i = highest_low_index ; i < elements_count ; ++i )
|
||||
{
|
||||
bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator));
|
||||
coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(bounded_indexable);
|
||||
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;
|
||||
|
||||
// highest_low - lowest_high
|
||||
separation = difference<separation_type>(lowest_high, highest_low);
|
||||
// BOOST_GEOMETRY_INDEX_ASSERT(0 <= width);
|
||||
if ( std::numeric_limits<coordinate_type>::epsilon() < width )
|
||||
separation /= width;
|
||||
|
||||
seed1 = highest_low_index;
|
||||
seed2 = lowest_high_index;
|
||||
|
||||
::boost::ignore_unused_variable_warning(parameters);
|
||||
}
|
||||
};
|
||||
|
||||
// Version for points doesn't calculate normalized separation since it would always be equal to 1
|
||||
// It returns two seeds most distant to each other, separation is equal to distance
|
||||
template <typename Elements, typename Parameters, typename Translator, size_t DimensionIndex>
|
||||
struct find_greatest_normalized_separation<Elements, Parameters, Translator, point_tag, DimensionIndex>
|
||||
{
|
||||
typedef typename Elements::value_type element_type;
|
||||
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
|
||||
typedef typename coordinate_type<indexable_type>::type coordinate_type;
|
||||
|
||||
typedef coordinate_type separation_type;
|
||||
|
||||
static inline void apply(Elements const& elements,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator,
|
||||
separation_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 = geometry::get<DimensionIndex>(rtree::element_indexable(elements[0], translator));
|
||||
coordinate_type highest = geometry::get<DimensionIndex>(rtree::element_indexable(elements[0], translator));
|
||||
size_t lowest_index = 0;
|
||||
size_t highest_index = 0;
|
||||
for ( size_t i = 1 ; i < elements_count ; ++i )
|
||||
{
|
||||
coordinate_type coord = geometry::get<DimensionIndex>(rtree::element_indexable(elements[i], translator));
|
||||
|
||||
if ( coord < lowest )
|
||||
{
|
||||
lowest = coord;
|
||||
lowest_index = i;
|
||||
}
|
||||
|
||||
if ( highest < coord )
|
||||
{
|
||||
highest = coord;
|
||||
highest_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
separation = highest - lowest;
|
||||
seed1 = lowest_index;
|
||||
seed2 = highest_index;
|
||||
|
||||
if ( lowest_index == highest_index )
|
||||
seed2 = (lowest_index + 1) % elements_count; // % is just in case since if this is true lowest_index is 0
|
||||
|
||||
::boost::ignore_unused_variable_warning(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 find_greatest_normalized_separation<
|
||||
Elements, Parameters, Translator,
|
||||
typename tag<indexable_type>::type, Dimension - 1
|
||||
> find_norm_sep;
|
||||
|
||||
typedef typename find_norm_sep::separation_type separation_type;
|
||||
|
||||
static inline void apply(Elements const& elements,
|
||||
Parameters const& parameters,
|
||||
Translator const& tr,
|
||||
separation_type & separation,
|
||||
size_t & seed1,
|
||||
size_t & seed2)
|
||||
{
|
||||
pick_seeds_impl<Elements, Parameters, Translator, Dimension - 1>::apply(elements, parameters, tr, separation, seed1, seed2);
|
||||
|
||||
separation_type current_separation;
|
||||
size_t s1, s2;
|
||||
find_norm_sep::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 coordinate_type<indexable_type>::type coordinate_type;
|
||||
|
||||
typedef find_greatest_normalized_separation<
|
||||
Elements, Parameters, Translator,
|
||||
typename tag<indexable_type>::type, 0
|
||||
> find_norm_sep;
|
||||
|
||||
typedef typename find_norm_sep::separation_type separation_type;
|
||||
|
||||
static inline void apply(Elements const& elements,
|
||||
Parameters const& parameters,
|
||||
Translator const& tr,
|
||||
separation_type & separation,
|
||||
size_t & seed1,
|
||||
size_t & seed2)
|
||||
{
|
||||
find_norm_sep::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>
|
||||
inline void pick_seeds(Elements const& elements,
|
||||
Parameters const& parameters,
|
||||
Translator const& tr,
|
||||
size_t & seed1,
|
||||
size_t & seed2)
|
||||
{
|
||||
typedef typename Elements::value_type element_type;
|
||||
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
|
||||
|
||||
typedef pick_seeds_impl
|
||||
<
|
||||
Elements, Parameters, Translator,
|
||||
geometry::dimension<indexable_type>::value
|
||||
> impl;
|
||||
typedef typename impl::separation_type separation_type;
|
||||
|
||||
separation_type separation = 0;
|
||||
impl::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::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 - use in-memory storage (std::allocator)
|
||||
// TODO: move if noexcept
|
||||
typedef typename rtree::container_from_elements_type<elements_type, element_type>::type
|
||||
container_type;
|
||||
container_type elements_copy(elements1.begin(), elements1.end()); // MAY THROW, STRONG (alloc, copy)
|
||||
|
||||
// calculate initial seeds
|
||||
size_t seed1 = 0;
|
||||
size_t seed2 = 0;
|
||||
linear::pick_seeds(elements_copy, parameters, translator, seed1, seed2);
|
||||
|
||||
// prepare nodes' elements containers
|
||||
elements1.clear();
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(elements2.empty(), "unexpected container state");
|
||||
|
||||
BOOST_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
|
||||
detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), box1);
|
||||
detail::bounds(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
elements1.clear();
|
||||
elements2.clear();
|
||||
|
||||
rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_copy, allocators);
|
||||
//elements_copy.clear();
|
||||
|
||||
BOOST_RETHROW // RETHROW, BASIC
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_REDISTRIBUTE_ELEMENTS_HPP
|
||||
+85
@@ -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,212 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree nodes
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_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/node_elements.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp>
|
||||
|
||||
//#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
|
||||
//#include <boost/geometry/index/detail/rtree/node/weak_dynamic.hpp>
|
||||
//#include <boost/geometry/index/detail/rtree/node/weak_static.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/variant_visitor.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/node/variant_dynamic.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/node/variant_static.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
|
||||
#include <boost/geometry/index/detail/is_bounding_geometry.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;
|
||||
|
||||
// Only here to suppress 'uninitialized local variable used' warning
|
||||
// until the suggestion below is not implemented
|
||||
geometry::assign_inverse(result);
|
||||
|
||||
//BOOST_GEOMETRY_INDEX_ASSERT(first != last, "non-empty range required");
|
||||
// NOTE: this is not elegant temporary solution,
|
||||
// reference to box could be passed as parameter and bool returned
|
||||
if ( first == last )
|
||||
return result;
|
||||
|
||||
detail::bounds(element_indexable(*first, tr), result);
|
||||
++first;
|
||||
|
||||
for ( ; first != last ; ++first )
|
||||
geometry::expand(result, element_indexable(*first, tr));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Enlarge bounds of a leaf node WRT epsilon if needed.
|
||||
// It's because Points and Segments are compared WRT machine epsilon.
|
||||
// This ensures that leafs bounds correspond to the stored elements.
|
||||
// NOTE: this is done only if the Indexable is not a Box
|
||||
// in the future don't do it also for NSphere
|
||||
template <typename Box, typename FwdIter, typename Translator>
|
||||
inline Box values_box(FwdIter first, FwdIter last, Translator const& tr)
|
||||
{
|
||||
typedef typename std::iterator_traits<FwdIter>::value_type element_type;
|
||||
BOOST_MPL_ASSERT_MSG((is_leaf_element<element_type>::value),
|
||||
SHOULD_BE_CALLED_ONLY_FOR_LEAF_ELEMENTS,
|
||||
(element_type));
|
||||
|
||||
Box result = elements_box<Box>(first, last, tr);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
|
||||
if (BOOST_GEOMETRY_CONDITION((
|
||||
! is_bounding_geometry
|
||||
<
|
||||
typename indexable_type<Translator>::type
|
||||
>::value)))
|
||||
{
|
||||
geometry::detail::expand_by_epsilon(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
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::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
|
||||
inline static void apply(typename internal_node::elements_type::value_type & element, Allocators & allocators)
|
||||
{
|
||||
subtree_destroyer 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
|
||||
{
|
||||
template <typename Range>
|
||||
inline static void apply(Range & elements, Allocators & allocators)
|
||||
{
|
||||
apply(boost::begin(elements), boost::end(elements), allocators);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline static void apply(It first, It last, Allocators & allocators)
|
||||
{
|
||||
typedef boost::mpl::bool_<
|
||||
boost::is_same<
|
||||
Value, typename std::iterator_traits<It>::value_type
|
||||
>::value
|
||||
> is_range_of_values;
|
||||
|
||||
apply_dispatch(first, last, allocators, is_range_of_values());
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename It>
|
||||
inline static void apply_dispatch(It first, It last, Allocators & allocators,
|
||||
boost::mpl::bool_<false> const& /*is_range_of_values*/)
|
||||
{
|
||||
typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
|
||||
for ( ; first != last ; ++first )
|
||||
{
|
||||
subtree_destroyer dummy(first->second, allocators);
|
||||
first->second = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline static void apply_dispatch(It /*first*/, It /*last*/, Allocators & /*allocators*/,
|
||||
boost::mpl::bool_<true> const& /*is_range_of_values*/)
|
||||
{}
|
||||
};
|
||||
|
||||
// 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
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree node elements access
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_ELEMENTS_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_ELEMENTS_HPP
|
||||
|
||||
#include <boost/container/vector.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
|
||||
#include <boost/geometry/index/detail/varray.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/node/pairs.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
// is leaf element
|
||||
|
||||
template <typename Element>
|
||||
struct is_leaf_element
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <typename First, typename Pointer>
|
||||
struct is_leaf_element< rtree::ptr_pair<First, Pointer> >
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
template <typename OldValue, size_t N, typename NewValue>
|
||||
struct container_from_elements_type<detail::varray<OldValue, N>, NewValue>
|
||||
{
|
||||
typedef detail::varray<NewValue, N> type;
|
||||
};
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_ELEMENTS_HPP
|
||||
@@ -0,0 +1,71 @@
|
||||
// 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);
|
||||
}
|
||||
|
||||
// TODO: It this will be used, rename it to unique_ptr_pair and possibly use unique_ptr.
|
||||
|
||||
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
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree scoped deallocator
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
template <typename Alloc>
|
||||
class scoped_deallocator
|
||||
{
|
||||
scoped_deallocator(scoped_deallocator const&);
|
||||
scoped_deallocator & operator=(scoped_deallocator const&);
|
||||
public:
|
||||
typedef typename Alloc::pointer pointer;
|
||||
inline scoped_deallocator(pointer p, Alloc & a)
|
||||
: m_ptr(p), m_alloc(a)
|
||||
{}
|
||||
inline ~scoped_deallocator()
|
||||
{
|
||||
if ( m_ptr )
|
||||
{
|
||||
boost::container::allocator_traits<Alloc>::deallocate(m_alloc, m_ptr, 1);
|
||||
}
|
||||
}
|
||||
inline void release()
|
||||
{
|
||||
m_ptr = 0;
|
||||
}
|
||||
private:
|
||||
pointer m_ptr;
|
||||
Alloc & m_alloc;
|
||||
};
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree subtree scoped destroyer
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SUBTREE_DESTROYED_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SUBTREE_DESTROYED_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 subtree_destroyer
|
||||
{
|
||||
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename Allocators::node_pointer pointer;
|
||||
|
||||
subtree_destroyer(subtree_destroyer const&);
|
||||
subtree_destroyer & operator=(subtree_destroyer const&);
|
||||
|
||||
public:
|
||||
subtree_destroyer(pointer ptr, Allocators & allocators)
|
||||
: m_ptr(ptr)
|
||||
, m_allocators(allocators)
|
||||
{}
|
||||
|
||||
~subtree_destroyer()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset(pointer ptr = 0)
|
||||
{
|
||||
if ( m_ptr && m_ptr != 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_SUBTREE_DESTROYED_HPP
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree nodes based on Boost.Variant, storing dynamic-size containers
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_VARIANT_DYNAMIC_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_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 variant_internal_node
|
||||
{
|
||||
typedef boost::container::vector
|
||||
<
|
||||
rtree::ptr_pair<Box, typename Allocators::node_pointer>,
|
||||
typename Allocators::node_allocator_type::template rebind
|
||||
<
|
||||
rtree::ptr_pair<Box, typename Allocators::node_pointer>
|
||||
>::other
|
||||
> elements_type;
|
||||
|
||||
template <typename Al>
|
||||
inline variant_internal_node(Al const& al)
|
||||
: elements(al)
|
||||
{}
|
||||
|
||||
elements_type elements;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
struct variant_leaf
|
||||
{
|
||||
typedef boost::container::vector
|
||||
<
|
||||
Value,
|
||||
typename Allocators::node_allocator_type::template rebind
|
||||
<
|
||||
Value
|
||||
>::other
|
||||
> elements_type;
|
||||
|
||||
template <typename Al>
|
||||
inline variant_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_variant_dynamic_tag>
|
||||
{
|
||||
typedef boost::variant<
|
||||
variant_leaf<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>,
|
||||
variant_internal_node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct internal_node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>
|
||||
{
|
||||
typedef variant_internal_node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag> type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct leaf<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>
|
||||
{
|
||||
typedef variant_leaf<Value, Parameters, Box, Allocators, node_variant_dynamic_tag> type;
|
||||
};
|
||||
|
||||
// visitor traits
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
|
||||
struct visitor<Value, Parameters, Box, Allocators, node_variant_dynamic_tag, IsVisitableConst>
|
||||
{
|
||||
typedef static_visitor<> type;
|
||||
};
|
||||
|
||||
// allocators
|
||||
|
||||
template <typename Allocator, typename Value, typename Parameters, typename Box>
|
||||
class allocators<Allocator, Value, Parameters, Box, node_variant_dynamic_tag>
|
||||
: public Allocator::template rebind<
|
||||
typename node<
|
||||
Value, Parameters, Box,
|
||||
allocators<Allocator, Value, Parameters, Box, node_variant_dynamic_tag>,
|
||||
node_variant_dynamic_tag
|
||||
>::type
|
||||
>::other
|
||||
{
|
||||
typedef typename Allocator::template rebind<
|
||||
Value
|
||||
>::other value_allocator_type;
|
||||
|
||||
public:
|
||||
typedef Allocator allocator_type;
|
||||
|
||||
typedef Value value_type;
|
||||
typedef typename value_allocator_type::reference reference;
|
||||
typedef typename value_allocator_type::const_reference const_reference;
|
||||
typedef typename value_allocator_type::size_type size_type;
|
||||
typedef typename value_allocator_type::difference_type difference_type;
|
||||
typedef typename value_allocator_type::pointer pointer;
|
||||
typedef typename value_allocator_type::const_pointer const_pointer;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename node<Value, Parameters, Box, allocators, node_variant_dynamic_tag>::type
|
||||
>::other::pointer node_pointer;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename node<Value, Parameters, Box, allocators, node_variant_dynamic_tag>::type
|
||||
>::other node_allocator_type;
|
||||
|
||||
inline allocators()
|
||||
: node_allocator_type()
|
||||
{}
|
||||
|
||||
template <typename Alloc>
|
||||
inline explicit allocators(Alloc const& alloc)
|
||||
: node_allocator_type(alloc)
|
||||
{}
|
||||
|
||||
inline allocators(BOOST_FWD_REF(allocators) a)
|
||||
: node_allocator_type(boost::move(a.node_allocator()))
|
||||
{}
|
||||
|
||||
inline allocators & operator=(BOOST_FWD_REF(allocators) a)
|
||||
{
|
||||
node_allocator() = boost::move(a.node_allocator());
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
inline allocators & operator=(allocators const& a)
|
||||
{
|
||||
node_allocator() = a.node_allocator();
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
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_variant_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_runtime_error("boost::geometry::index::rtree node creation failed");
|
||||
|
||||
scoped_deallocator<AllocNode> deallocator(p, alloc_node);
|
||||
|
||||
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_variant_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,
|
||||
variant_internal_node<Value, Parameters, Box, Allocators, Tag>
|
||||
>
|
||||
{
|
||||
static inline typename Allocators::node_pointer
|
||||
apply(Allocators & allocators)
|
||||
{
|
||||
return create_variant_node<
|
||||
typename Allocators::node_pointer,
|
||||
variant_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,
|
||||
variant_leaf<Value, Parameters, Box, Allocators, Tag>
|
||||
>
|
||||
{
|
||||
static inline typename Allocators::node_pointer
|
||||
apply(Allocators & allocators)
|
||||
{
|
||||
return create_variant_node<
|
||||
typename Allocators::node_pointer,
|
||||
variant_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,
|
||||
variant_internal_node<Value, Parameters, Box, Allocators, Tag>
|
||||
>
|
||||
{
|
||||
static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
|
||||
{
|
||||
destroy_variant_node<
|
||||
variant_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,
|
||||
variant_leaf<Value, Parameters, Box, Allocators, Tag>
|
||||
>
|
||||
{
|
||||
static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
|
||||
{
|
||||
destroy_variant_node<
|
||||
variant_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_VARIANT_DYNAMIC_HPP
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree nodes based on Boost.Variant, storing static-size containers
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_VARIANT_STATIC_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_STATIC_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
// nodes default types
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct variant_internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag>
|
||||
{
|
||||
typedef detail::varray<
|
||||
rtree::ptr_pair<Box, typename Allocators::node_pointer>,
|
||||
Parameters::max_elements + 1
|
||||
> elements_type;
|
||||
|
||||
template <typename Alloc>
|
||||
inline variant_internal_node(Alloc const&) {}
|
||||
|
||||
elements_type elements;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct variant_leaf<Value, Parameters, Box, Allocators, node_variant_static_tag>
|
||||
{
|
||||
typedef detail::varray<
|
||||
Value,
|
||||
Parameters::max_elements + 1
|
||||
> elements_type;
|
||||
|
||||
template <typename Alloc>
|
||||
inline variant_leaf(Alloc const&) {}
|
||||
|
||||
elements_type elements;
|
||||
};
|
||||
|
||||
// nodes traits
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct node<Value, Parameters, Box, Allocators, node_variant_static_tag>
|
||||
{
|
||||
typedef boost::variant<
|
||||
variant_leaf<Value, Parameters, Box, Allocators, node_variant_static_tag>,
|
||||
variant_internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag>
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag>
|
||||
{
|
||||
typedef variant_internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag> type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct leaf<Value, Parameters, Box, Allocators, node_variant_static_tag>
|
||||
{
|
||||
typedef variant_leaf<Value, Parameters, Box, Allocators, node_variant_static_tag> type;
|
||||
};
|
||||
|
||||
// visitor traits
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
|
||||
struct visitor<Value, Parameters, Box, Allocators, node_variant_static_tag, IsVisitableConst>
|
||||
{
|
||||
typedef static_visitor<> type;
|
||||
};
|
||||
|
||||
// allocators
|
||||
|
||||
template <typename Allocator, typename Value, typename Parameters, typename Box>
|
||||
class allocators<Allocator, Value, Parameters, Box, node_variant_static_tag>
|
||||
: public Allocator::template rebind<
|
||||
typename node<
|
||||
Value, Parameters, Box,
|
||||
allocators<Allocator, Value, Parameters, Box, node_variant_static_tag>,
|
||||
node_variant_static_tag
|
||||
>::type
|
||||
>::other
|
||||
{
|
||||
typedef typename Allocator::template rebind<
|
||||
Value
|
||||
>::other value_allocator_type;
|
||||
|
||||
public:
|
||||
typedef Allocator allocator_type;
|
||||
|
||||
typedef Value value_type;
|
||||
typedef value_type & reference;
|
||||
typedef const value_type & const_reference;
|
||||
typedef typename value_allocator_type::size_type size_type;
|
||||
typedef typename value_allocator_type::difference_type difference_type;
|
||||
typedef typename value_allocator_type::pointer pointer;
|
||||
typedef typename value_allocator_type::const_pointer const_pointer;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename node<Value, Parameters, Box, allocators, node_variant_static_tag>::type
|
||||
>::other::pointer node_pointer;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename node<Value, Parameters, Box, allocators, node_variant_static_tag>::type
|
||||
>::other node_allocator_type;
|
||||
|
||||
inline allocators()
|
||||
: node_allocator_type()
|
||||
{}
|
||||
|
||||
template <typename Alloc>
|
||||
inline explicit allocators(Alloc const& alloc)
|
||||
: node_allocator_type(alloc)
|
||||
{}
|
||||
|
||||
inline allocators(BOOST_FWD_REF(allocators) a)
|
||||
: node_allocator_type(boost::move(a.node_allocator()))
|
||||
{}
|
||||
|
||||
inline allocators & operator=(BOOST_FWD_REF(allocators) a)
|
||||
{
|
||||
node_allocator() = boost::move(a.node_allocator());
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
inline allocators & operator=(allocators const& a)
|
||||
{
|
||||
node_allocator() = a.node_allocator();
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_STATIC_HPP
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree nodes static visitor related code
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_VARIANT_VISITOR_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_VISITOR_HPP
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
#include <boost/variant/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 variant_internal_node;
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
struct variant_leaf;
|
||||
|
||||
// nodes conversion
|
||||
|
||||
template <typename V, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
inline V & get(
|
||||
boost::variant<
|
||||
variant_leaf<Value, Parameters, Box, Allocators, Tag>,
|
||||
variant_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<
|
||||
variant_leaf<Value, Parameters, Box, Allocators, Tag>,
|
||||
variant_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<
|
||||
variant_leaf<Value, Parameters, Box, Allocators, Tag>,
|
||||
variant_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_VARIANT_VISITOR_HPP
|
||||
+294
@@ -0,0 +1,294 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree nodes based on static conversion, storing dynamic-size containers
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_WEAK_DYNAMIC_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
struct weak_internal_node
|
||||
: public weak_node<Value, Parameters, Box, Allocators, Tag>
|
||||
{
|
||||
typedef boost::container::vector
|
||||
<
|
||||
rtree::ptr_pair<Box, typename Allocators::node_pointer>,
|
||||
typename Allocators::internal_node_allocator_type::template rebind
|
||||
<
|
||||
rtree::ptr_pair<Box, typename Allocators::node_pointer>
|
||||
>::other
|
||||
> elements_type;
|
||||
|
||||
template <typename Al>
|
||||
inline weak_internal_node(Al const& al)
|
||||
: elements(al)
|
||||
{}
|
||||
|
||||
elements_type elements;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
struct weak_leaf
|
||||
: public weak_node<Value, Parameters, Box, Allocators, Tag>
|
||||
{
|
||||
typedef boost::container::vector
|
||||
<
|
||||
Value,
|
||||
typename Allocators::leaf_allocator_type::template rebind
|
||||
<
|
||||
Value
|
||||
>::other
|
||||
> elements_type;
|
||||
|
||||
template <typename Al>
|
||||
inline weak_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_weak_dynamic_tag>
|
||||
{
|
||||
typedef weak_node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag> type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct internal_node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag>
|
||||
{
|
||||
typedef weak_internal_node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag> type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct leaf<Value, Parameters, Box, Allocators, node_weak_dynamic_tag>
|
||||
{
|
||||
typedef weak_leaf<Value, Parameters, Box, Allocators, node_weak_dynamic_tag> type;
|
||||
};
|
||||
|
||||
// visitor traits
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
|
||||
struct visitor<Value, Parameters, Box, Allocators, node_weak_dynamic_tag, IsVisitableConst>
|
||||
{
|
||||
typedef weak_visitor<Value, Parameters, Box, Allocators, node_weak_dynamic_tag, IsVisitableConst> type;
|
||||
};
|
||||
|
||||
// allocators
|
||||
|
||||
template <typename Allocator, typename Value, typename Parameters, typename Box>
|
||||
class allocators<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>
|
||||
: public Allocator::template rebind<
|
||||
typename internal_node<
|
||||
Value, Parameters, Box,
|
||||
allocators<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>,
|
||||
node_weak_dynamic_tag
|
||||
>::type
|
||||
>::other
|
||||
, public Allocator::template rebind<
|
||||
typename leaf<
|
||||
Value, Parameters, Box,
|
||||
allocators<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>,
|
||||
node_weak_dynamic_tag
|
||||
>::type
|
||||
>::other
|
||||
{
|
||||
typedef typename Allocator::template rebind<
|
||||
Value
|
||||
>::other value_allocator_type;
|
||||
|
||||
public:
|
||||
typedef Allocator allocator_type;
|
||||
|
||||
typedef Value value_type;
|
||||
typedef typename value_allocator_type::reference reference;
|
||||
typedef typename value_allocator_type::const_reference const_reference;
|
||||
typedef typename value_allocator_type::size_type size_type;
|
||||
typedef typename value_allocator_type::difference_type difference_type;
|
||||
typedef typename value_allocator_type::pointer pointer;
|
||||
typedef typename value_allocator_type::const_pointer const_pointer;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename node<Value, Parameters, Box, allocators, node_weak_dynamic_tag>::type
|
||||
>::other::pointer node_pointer;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename internal_node<Value, Parameters, Box, allocators, node_weak_dynamic_tag>::type
|
||||
>::other internal_node_allocator_type;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename leaf<Value, Parameters, Box, allocators, node_weak_dynamic_tag>::type
|
||||
>::other leaf_allocator_type;
|
||||
|
||||
inline allocators()
|
||||
: internal_node_allocator_type()
|
||||
, leaf_allocator_type()
|
||||
{}
|
||||
|
||||
template <typename Alloc>
|
||||
inline explicit allocators(Alloc 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()))
|
||||
{}
|
||||
|
||||
inline allocators & operator=(BOOST_FWD_REF(allocators) a)
|
||||
{
|
||||
internal_node_allocator() = ::boost::move(a.internal_node_allocator());
|
||||
leaf_allocator() = ::boost::move(a.leaf_allocator());
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
inline allocators & operator=(allocators const& a)
|
||||
{
|
||||
internal_node_allocator() = a.internal_node_allocator();
|
||||
leaf_allocator() = a.leaf_allocator();
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
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_weak_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_runtime_error("boost::geometry::index::rtree node creation failed");
|
||||
|
||||
scoped_deallocator<AllocNode> deallocator(p, alloc_node);
|
||||
|
||||
Al::construct(alloc_node, boost::addressof(*p), alloc_node);
|
||||
|
||||
deallocator.release();
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
// destroy_node_impl
|
||||
|
||||
template <typename Node>
|
||||
struct destroy_weak_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,
|
||||
weak_internal_node<Value, Parameters, Box, Allocators, Tag>
|
||||
>
|
||||
{
|
||||
static inline typename Allocators::node_pointer
|
||||
apply(Allocators & allocators)
|
||||
{
|
||||
return create_weak_node<
|
||||
typename Allocators::node_pointer,
|
||||
weak_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,
|
||||
weak_leaf<Value, Parameters, Box, Allocators, Tag>
|
||||
>
|
||||
{
|
||||
static inline typename Allocators::node_pointer
|
||||
apply(Allocators & allocators)
|
||||
{
|
||||
return create_weak_node<
|
||||
typename Allocators::node_pointer,
|
||||
weak_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,
|
||||
weak_internal_node<Value, Parameters, Box, Allocators, Tag>
|
||||
>
|
||||
{
|
||||
static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
|
||||
{
|
||||
destroy_weak_node<
|
||||
weak_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,
|
||||
weak_leaf<Value, Parameters, Box, Allocators, Tag>
|
||||
>
|
||||
{
|
||||
static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
|
||||
{
|
||||
destroy_weak_node<
|
||||
weak_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_WEAK_DYNAMIC_HPP
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree nodes based on static conversion, storing static-size containers
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_WEAK_STATIC_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_STATIC_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct weak_internal_node<Value, Parameters, Box, Allocators, node_weak_static_tag>
|
||||
: public weak_node<Value, Parameters, Box, Allocators, node_weak_static_tag>
|
||||
{
|
||||
typedef detail::varray<
|
||||
rtree::ptr_pair<Box, typename Allocators::node_pointer>,
|
||||
Parameters::max_elements + 1
|
||||
> elements_type;
|
||||
|
||||
template <typename Alloc>
|
||||
inline weak_internal_node(Alloc const&) {}
|
||||
|
||||
elements_type elements;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct weak_leaf<Value, Parameters, Box, Allocators, node_weak_static_tag>
|
||||
: public weak_node<Value, Parameters, Box, Allocators, node_weak_static_tag>
|
||||
{
|
||||
typedef detail::varray<
|
||||
Value,
|
||||
Parameters::max_elements + 1
|
||||
> elements_type;
|
||||
|
||||
template <typename Alloc>
|
||||
inline weak_leaf(Alloc const&) {}
|
||||
|
||||
elements_type elements;
|
||||
};
|
||||
|
||||
// nodes traits
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct node<Value, Parameters, Box, Allocators, node_weak_static_tag>
|
||||
{
|
||||
typedef weak_node<Value, Parameters, Box, Allocators, node_weak_static_tag> type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct internal_node<Value, Parameters, Box, Allocators, node_weak_static_tag>
|
||||
{
|
||||
typedef weak_internal_node<Value, Parameters, Box, Allocators, node_weak_static_tag> type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators>
|
||||
struct leaf<Value, Parameters, Box, Allocators, node_weak_static_tag>
|
||||
{
|
||||
typedef weak_leaf<Value, Parameters, Box, Allocators, node_weak_static_tag> type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
|
||||
struct visitor<Value, Parameters, Box, Allocators, node_weak_static_tag, IsVisitableConst>
|
||||
{
|
||||
typedef weak_visitor<Value, Parameters, Box, Allocators, node_weak_static_tag, IsVisitableConst> type;
|
||||
};
|
||||
|
||||
// allocators
|
||||
|
||||
template <typename Allocator, typename Value, typename Parameters, typename Box>
|
||||
class allocators<Allocator, Value, Parameters, Box, node_weak_static_tag>
|
||||
: public Allocator::template rebind<
|
||||
typename internal_node<
|
||||
Value, Parameters, Box,
|
||||
allocators<Allocator, Value, Parameters, Box, node_weak_static_tag>,
|
||||
node_weak_static_tag
|
||||
>::type
|
||||
>::other
|
||||
, public Allocator::template rebind<
|
||||
typename leaf<
|
||||
Value, Parameters, Box,
|
||||
allocators<Allocator, Value, Parameters, Box, node_weak_static_tag>,
|
||||
node_weak_static_tag
|
||||
>::type
|
||||
>::other
|
||||
{
|
||||
typedef typename Allocator::template rebind<
|
||||
Value
|
||||
>::other value_allocator_type;
|
||||
|
||||
public:
|
||||
typedef Allocator allocator_type;
|
||||
|
||||
typedef Value value_type;
|
||||
typedef value_type & reference;
|
||||
typedef const value_type & const_reference;
|
||||
typedef typename value_allocator_type::size_type size_type;
|
||||
typedef typename value_allocator_type::difference_type difference_type;
|
||||
typedef typename value_allocator_type::pointer pointer;
|
||||
typedef typename value_allocator_type::const_pointer const_pointer;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename node<Value, Parameters, Box, allocators, node_weak_static_tag>::type
|
||||
>::other::pointer node_pointer;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename internal_node<Value, Parameters, Box, allocators, node_weak_static_tag>::type
|
||||
>::other internal_node_allocator_type;
|
||||
|
||||
typedef typename Allocator::template rebind<
|
||||
typename leaf<Value, Parameters, Box, allocators, node_weak_static_tag>::type
|
||||
>::other leaf_allocator_type;
|
||||
|
||||
inline allocators()
|
||||
: internal_node_allocator_type()
|
||||
, leaf_allocator_type()
|
||||
{}
|
||||
|
||||
template <typename Alloc>
|
||||
inline explicit allocators(Alloc 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()))
|
||||
{}
|
||||
|
||||
inline allocators & operator=(BOOST_FWD_REF(allocators) a)
|
||||
{
|
||||
internal_node_allocator() = ::boost::move(a.internal_node_allocator());
|
||||
leaf_allocator() = ::boost::move(a.leaf_allocator());
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
inline allocators & operator=(allocators const& a)
|
||||
{
|
||||
internal_node_allocator() = a.internal_node_allocator();
|
||||
leaf_allocator() = a.leaf_allocator();
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
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_WEAK_STATIC_HPP
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree nodes weak visitor and nodes base type
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_WEAK_VISITOR_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_VISITOR_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
// empty visitor
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag, bool IsVisitableConst>
|
||||
struct weak_visitor {};
|
||||
|
||||
// node
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
struct weak_node {};
|
||||
|
||||
// nodes variants forward declarations
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
struct weak_internal_node;
|
||||
|
||||
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
struct weak_leaf;
|
||||
|
||||
// nodes conversion
|
||||
|
||||
template <typename Derived, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
inline Derived & get(weak_node<Value, Parameters, Box, Allocators, Tag> & n)
|
||||
{
|
||||
return static_cast<Derived&>(n);
|
||||
}
|
||||
|
||||
// apply visitor
|
||||
|
||||
template <typename Visitor, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
|
||||
inline void apply_visitor(Visitor & v,
|
||||
weak_node<Value, Parameters, Box, Allocators, Tag> & n,
|
||||
bool is_internal_node)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(&n, "null ptr");
|
||||
if ( is_internal_node )
|
||||
{
|
||||
typedef weak_internal_node<Value, Parameters, Box, Allocators, Tag> internal_node;
|
||||
v(get<internal_node>(n));
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef weak_leaf<Value, Parameters, Box, Allocators, Tag> leaf;
|
||||
v(get<leaf>(n));
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_DYNAMIC_VISITOR_HPP
|
||||
@@ -0,0 +1,155 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree options, algorithms, parameters
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_variant_dynamic_tag {};
|
||||
struct node_variant_static_tag {};
|
||||
//struct node_weak_dynamic_tag {};
|
||||
//struct node_weak_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_variant_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_variant_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_variant_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_variant_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_variant_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_variant_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_variant_dynamic_tag
|
||||
> type;
|
||||
};
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_OPTIONS_HPP
|
||||
+465
@@ -0,0 +1,465 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree initial packing
|
||||
//
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
|
||||
|
||||
namespace pack_utils {
|
||||
|
||||
template <std::size_t Dimension>
|
||||
struct biggest_edge
|
||||
{
|
||||
BOOST_STATIC_ASSERT(0 < Dimension);
|
||||
template <typename Box>
|
||||
static inline void apply(Box const& box, typename coordinate_type<Box>::type & length, std::size_t & dim_index)
|
||||
{
|
||||
biggest_edge<Dimension-1>::apply(box, length, dim_index);
|
||||
typename coordinate_type<Box>::type curr
|
||||
= geometry::get<max_corner, Dimension-1>(box) - geometry::get<min_corner, Dimension-1>(box);
|
||||
if ( length < curr )
|
||||
{
|
||||
dim_index = Dimension - 1;
|
||||
length = curr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct biggest_edge<1>
|
||||
{
|
||||
template <typename Box>
|
||||
static inline void apply(Box const& box, typename coordinate_type<Box>::type & length, std::size_t & dim_index)
|
||||
{
|
||||
dim_index = 0;
|
||||
length = geometry::get<max_corner, 0>(box) - geometry::get<min_corner, 0>(box);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t I>
|
||||
struct point_entries_comparer
|
||||
{
|
||||
template <typename PointEntry>
|
||||
bool operator()(PointEntry const& e1, PointEntry const& e2) const
|
||||
{
|
||||
return geometry::get<I>(e1.first) < geometry::get<I>(e2.first);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t I, std::size_t Dimension>
|
||||
struct nth_element_and_half_boxes
|
||||
{
|
||||
template <typename EIt, typename Box>
|
||||
static inline void apply(EIt first, EIt median, EIt last, Box const& box, Box & left, Box & right, std::size_t dim_index)
|
||||
{
|
||||
if ( I == dim_index )
|
||||
{
|
||||
index::detail::nth_element(first, median, last, point_entries_comparer<I>());
|
||||
|
||||
geometry::convert(box, left);
|
||||
geometry::convert(box, right);
|
||||
typename coordinate_type<Box>::type edge_len
|
||||
= geometry::get<max_corner, I>(box) - geometry::get<min_corner, I>(box);
|
||||
typename coordinate_type<Box>::type median
|
||||
= geometry::get<min_corner, I>(box) + edge_len / 2;
|
||||
geometry::set<max_corner, I>(left, median);
|
||||
geometry::set<min_corner, I>(right, median);
|
||||
}
|
||||
else
|
||||
nth_element_and_half_boxes<I+1, Dimension>::apply(first, median, last, box, left, right, dim_index);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t Dimension>
|
||||
struct nth_element_and_half_boxes<Dimension, Dimension>
|
||||
{
|
||||
template <typename EIt, typename Box>
|
||||
static inline void apply(EIt , EIt , EIt , Box const& , Box & , Box & , std::size_t ) {}
|
||||
};
|
||||
|
||||
} // namespace pack_utils
|
||||
|
||||
// STR leafs number are calculated as rcount/max
|
||||
// and the number of splitting planes for each dimension as (count/max)^(1/dimension)
|
||||
// <-> for dimension==2 -> sqrt(count/max)
|
||||
//
|
||||
// The main flaw of this algorithm is that the resulting tree will have bad structure for:
|
||||
// 1. non-uniformly distributed elements
|
||||
// Statistic check could be performed, e.g. based on variance of lengths of elements edges for each dimension
|
||||
// 2. elements distributed mainly along one axis
|
||||
// Calculate bounding box of all elements and then number of dividing planes for a dimension
|
||||
// from the length of BB edge for this dimension (more or less assuming that elements are uniformly-distributed squares)
|
||||
//
|
||||
// Another thing is that the last node may have less elements than Max or even Min.
|
||||
// The number of splitting planes must be chosen more carefully than count/max
|
||||
//
|
||||
// This algorithm is something between STR and TGS
|
||||
// it is more similar to the top-down recursive kd-tree creation algorithm
|
||||
// using object median split and split axis of greatest BB edge
|
||||
// BB is only used as a hint (assuming objects are distributed uniformly)
|
||||
//
|
||||
// Implemented algorithm guarantees that the number of elements in nodes will be between Min and Max
|
||||
// and that nodes are packed as tightly as possible
|
||||
// e.g. for 177 values Max = 5 and Min = 2 it will construct the following tree:
|
||||
// ROOT 177
|
||||
// L1 125 52
|
||||
// L2 25 25 25 25 25 25 17 10
|
||||
// L3 5x5 5x5 5x5 5x5 5x5 5x5 3x5+2 2x5
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class pack
|
||||
{
|
||||
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;
|
||||
typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
typedef typename geometry::point_type<Box>::type point_type;
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
typedef typename detail::default_content_result<Box>::type content_type;
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
static const std::size_t dimension = geometry::dimension<point_type>::value;
|
||||
|
||||
typedef typename rtree::container_from_elements_type<
|
||||
typename rtree::elements_type<leaf>::type,
|
||||
std::size_t
|
||||
>::type values_counts_container;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type internal_elements;
|
||||
typedef typename internal_elements::value_type internal_element;
|
||||
|
||||
public:
|
||||
// Arbitrary iterators
|
||||
template <typename InIt> inline static
|
||||
node_pointer apply(InIt first, InIt last, size_type & values_count, size_type & leafs_level,
|
||||
parameters_type const& parameters, Translator const& translator, Allocators & allocators)
|
||||
{
|
||||
typedef typename std::iterator_traits<InIt>::difference_type diff_type;
|
||||
|
||||
diff_type diff = std::distance(first, last);
|
||||
if ( diff <= 0 )
|
||||
return node_pointer(0);
|
||||
|
||||
typedef std::pair<point_type, InIt> entry_type;
|
||||
std::vector<entry_type> entries;
|
||||
|
||||
values_count = static_cast<size_type>(diff);
|
||||
entries.reserve(values_count);
|
||||
|
||||
expandable_box<Box> hint_box;
|
||||
for ( ; first != last ; ++first )
|
||||
{
|
||||
// NOTE: support for iterators not returning true references adapted
|
||||
// to Geometry concept and default translator returning true reference
|
||||
// An alternative would be to dereference the iterator and translate
|
||||
// in one expression each time the indexable was needed.
|
||||
typename std::iterator_traits<InIt>::reference in_ref = *first;
|
||||
typename Translator::result_type indexable = translator(in_ref);
|
||||
|
||||
// NOTE: added for consistency with insert()
|
||||
// CONSIDER: alternative - ignore invalid indexable or throw an exception
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(detail::is_valid(indexable), "Indexable is invalid");
|
||||
|
||||
hint_box.expand(indexable);
|
||||
|
||||
point_type pt;
|
||||
geometry::centroid(indexable, pt);
|
||||
entries.push_back(std::make_pair(pt, first));
|
||||
}
|
||||
|
||||
subtree_elements_counts subtree_counts = calculate_subtree_elements_counts(values_count, parameters, leafs_level);
|
||||
internal_element el = per_level(entries.begin(), entries.end(), hint_box.get(), values_count, subtree_counts,
|
||||
parameters, translator, allocators);
|
||||
|
||||
return el.second;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename BoxType>
|
||||
class expandable_box
|
||||
{
|
||||
public:
|
||||
expandable_box()
|
||||
: m_initialized(false)
|
||||
{}
|
||||
|
||||
template <typename Indexable>
|
||||
explicit expandable_box(Indexable const& indexable)
|
||||
: m_initialized(true)
|
||||
{
|
||||
detail::bounds(indexable, m_box);
|
||||
}
|
||||
|
||||
template <typename Indexable>
|
||||
void expand(Indexable const& indexable)
|
||||
{
|
||||
if ( !m_initialized )
|
||||
{
|
||||
// it's guaranteed that the Box will be initialized
|
||||
// only for Points, Boxes and Segments but that's ok
|
||||
// since only those Geometries can be stored
|
||||
detail::bounds(indexable, m_box);
|
||||
m_initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry::expand(m_box, indexable);
|
||||
}
|
||||
}
|
||||
|
||||
void expand_by_epsilon()
|
||||
{
|
||||
geometry::detail::expand_by_epsilon(m_box);
|
||||
}
|
||||
|
||||
BoxType const& get() const
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(m_initialized, "uninitialized envelope accessed");
|
||||
return m_box;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_initialized;
|
||||
BoxType m_box;
|
||||
};
|
||||
|
||||
struct subtree_elements_counts
|
||||
{
|
||||
subtree_elements_counts(std::size_t ma, std::size_t mi) : maxc(ma), minc(mi) {}
|
||||
std::size_t maxc;
|
||||
std::size_t minc;
|
||||
};
|
||||
|
||||
template <typename EIt> inline static
|
||||
internal_element per_level(EIt first, EIt last, Box const& hint_box, std::size_t values_count, subtree_elements_counts const& subtree_counts,
|
||||
parameters_type const& parameters, Translator const& translator, Allocators & allocators)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count,
|
||||
"unexpected parameters");
|
||||
|
||||
if ( subtree_counts.maxc <= 1 )
|
||||
{
|
||||
// ROOT or LEAF
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(values_count <= parameters.get_max_elements(),
|
||||
"too big number of elements");
|
||||
// if !root check m_parameters.get_min_elements() <= count
|
||||
|
||||
// create new leaf node
|
||||
node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A)
|
||||
subtree_destroyer auto_remover(n, allocators);
|
||||
leaf & l = rtree::get<leaf>(*n);
|
||||
|
||||
// reserve space for values
|
||||
rtree::elements(l).reserve(values_count); // MAY THROW (A)
|
||||
|
||||
// calculate values box and copy values
|
||||
// initialize the box explicitly to avoid GCC-4.4 uninitialized variable warnings with O2
|
||||
expandable_box<Box> elements_box(translator(*(first->second)));
|
||||
rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)
|
||||
for ( ++first ; first != last ; ++first )
|
||||
{
|
||||
// NOTE: push_back() must be called at the end in order to support move_iterator.
|
||||
// The iterator is dereferenced 2x (no temporary reference) to support
|
||||
// non-true reference types and move_iterator without boost::forward<>.
|
||||
elements_box.expand(translator(*(first->second)));
|
||||
rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
|
||||
// Enlarge bounds of a leaf node.
|
||||
// It's because Points and Segments are compared WRT machine epsilon
|
||||
// This ensures that leafs bounds correspond to the stored elements
|
||||
// NOTE: this is done only if the Indexable is a different kind of Geometry
|
||||
// than the bounds (only Box for now). Spatial predicates are checked
|
||||
// the same way for Geometry of the same kind.
|
||||
if ( BOOST_GEOMETRY_CONDITION((
|
||||
! index::detail::is_bounding_geometry
|
||||
<
|
||||
typename indexable_type<Translator>::type
|
||||
>::value )) )
|
||||
{
|
||||
elements_box.expand_by_epsilon();
|
||||
}
|
||||
#endif
|
||||
|
||||
auto_remover.release();
|
||||
return internal_element(elements_box.get(), n);
|
||||
}
|
||||
|
||||
// calculate next max and min subtree counts
|
||||
subtree_elements_counts next_subtree_counts = subtree_counts;
|
||||
next_subtree_counts.maxc /= parameters.get_max_elements();
|
||||
next_subtree_counts.minc /= parameters.get_max_elements();
|
||||
|
||||
// create new internal node
|
||||
node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A)
|
||||
subtree_destroyer auto_remover(n, allocators);
|
||||
internal_node & in = rtree::get<internal_node>(*n);
|
||||
|
||||
// reserve space for values
|
||||
std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts);
|
||||
rtree::elements(in).reserve(nodes_count); // MAY THROW (A)
|
||||
// calculate values box and copy values
|
||||
expandable_box<Box> elements_box;
|
||||
|
||||
per_level_packets(first, last, hint_box, values_count, subtree_counts, next_subtree_counts,
|
||||
rtree::elements(in), elements_box,
|
||||
parameters, translator, allocators);
|
||||
|
||||
auto_remover.release();
|
||||
return internal_element(elements_box.get(), n);
|
||||
}
|
||||
|
||||
template <typename EIt, typename ExpandableBox> inline static
|
||||
void per_level_packets(EIt first, EIt last, Box const& hint_box,
|
||||
std::size_t values_count,
|
||||
subtree_elements_counts const& subtree_counts,
|
||||
subtree_elements_counts const& next_subtree_counts,
|
||||
internal_elements & elements, ExpandableBox & elements_box,
|
||||
parameters_type const& parameters, Translator const& translator, Allocators & allocators)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count,
|
||||
"unexpected parameters");
|
||||
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(subtree_counts.minc <= values_count,
|
||||
"too small number of elements");
|
||||
|
||||
// only one packet
|
||||
if ( values_count <= subtree_counts.maxc )
|
||||
{
|
||||
// the end, move to the next level
|
||||
internal_element el = per_level(first, last, hint_box, values_count, next_subtree_counts,
|
||||
parameters, translator, allocators);
|
||||
|
||||
// in case if push_back() do throw here
|
||||
// and even if this is not probable (previously reserved memory, nonthrowing pairs copy)
|
||||
// this case is also tested by exceptions test.
|
||||
subtree_destroyer auto_remover(el.second, allocators);
|
||||
// this container should have memory allocated, reserve() called outside
|
||||
elements.push_back(el); // MAY THROW (A?,C) - however in normal conditions shouldn't
|
||||
auto_remover.release();
|
||||
|
||||
elements_box.expand(el.first);
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t median_count = calculate_median_count(values_count, subtree_counts);
|
||||
EIt median = first + median_count;
|
||||
|
||||
coordinate_type greatest_length;
|
||||
std::size_t greatest_dim_index = 0;
|
||||
pack_utils::biggest_edge<dimension>::apply(hint_box, greatest_length, greatest_dim_index);
|
||||
Box left, right;
|
||||
pack_utils::nth_element_and_half_boxes<0, dimension>
|
||||
::apply(first, median, last, hint_box, left, right, greatest_dim_index);
|
||||
|
||||
per_level_packets(first, median, left,
|
||||
median_count, subtree_counts, next_subtree_counts,
|
||||
elements, elements_box,
|
||||
parameters, translator, allocators);
|
||||
per_level_packets(median, last, right,
|
||||
values_count - median_count, subtree_counts, next_subtree_counts,
|
||||
elements, elements_box,
|
||||
parameters, translator, allocators);
|
||||
}
|
||||
|
||||
inline static
|
||||
subtree_elements_counts calculate_subtree_elements_counts(std::size_t elements_count, parameters_type const& parameters, size_type & leafs_level)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(parameters);
|
||||
|
||||
subtree_elements_counts res(1, 1);
|
||||
leafs_level = 0;
|
||||
|
||||
std::size_t smax = parameters.get_max_elements();
|
||||
for ( ; smax < elements_count ; smax *= parameters.get_max_elements(), ++leafs_level )
|
||||
res.maxc = smax;
|
||||
|
||||
res.minc = parameters.get_min_elements() * (res.maxc / parameters.get_max_elements());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline static
|
||||
std::size_t calculate_nodes_count(std::size_t count,
|
||||
subtree_elements_counts const& subtree_counts)
|
||||
{
|
||||
std::size_t n = count / subtree_counts.maxc;
|
||||
std::size_t r = count % subtree_counts.maxc;
|
||||
|
||||
if ( 0 < r && r < subtree_counts.minc )
|
||||
{
|
||||
std::size_t count_minus_min = count - subtree_counts.minc;
|
||||
n = count_minus_min / subtree_counts.maxc;
|
||||
r = count_minus_min % subtree_counts.maxc;
|
||||
++n;
|
||||
}
|
||||
|
||||
if ( 0 < r )
|
||||
++n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
inline static
|
||||
std::size_t calculate_median_count(std::size_t count,
|
||||
subtree_elements_counts const& subtree_counts)
|
||||
{
|
||||
// e.g. for max = 5, min = 2, count = 52, subtree_max = 25, subtree_min = 10
|
||||
|
||||
std::size_t n = count / subtree_counts.maxc; // e.g. 52 / 25 = 2
|
||||
std::size_t r = count % subtree_counts.maxc; // e.g. 52 % 25 = 2
|
||||
std::size_t median_count = (n / 2) * subtree_counts.maxc; // e.g. 2 / 2 * 25 = 25
|
||||
|
||||
if ( 0 != r ) // e.g. 0 != 2
|
||||
{
|
||||
if ( subtree_counts.minc <= r ) // e.g. 10 <= 2 == false
|
||||
{
|
||||
//BOOST_GEOMETRY_INDEX_ASSERT(0 < n, "unexpected value");
|
||||
median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((2+1)/2) * 25 which would be ok, but not in all cases
|
||||
}
|
||||
else // r < subtree_counts.second // e.g. 2 < 10 == true
|
||||
{
|
||||
std::size_t count_minus_min = count - subtree_counts.minc; // e.g. 52 - 10 = 42
|
||||
n = count_minus_min / subtree_counts.maxc; // e.g. 42 / 25 = 1
|
||||
r = count_minus_min % subtree_counts.maxc; // e.g. 42 % 25 = 17
|
||||
if ( r == 0 ) // e.g. false
|
||||
{
|
||||
// n can't be equal to 0 because then there wouldn't be any element in the other node
|
||||
//BOOST_GEOMETRY_INDEX_ASSERT(0 < n, "unexpected value");
|
||||
median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((1+1)/2) * 25 which would be ok, but not in all cases
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( n == 0 ) // e.g. false
|
||||
median_count = r; // if calculated -> 17 which is wrong!
|
||||
else
|
||||
median_count = ((n+2)/2) * subtree_counts.maxc; // e.g. ((1+2)/2) * 25 = 25
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return median_count;
|
||||
}
|
||||
};
|
||||
|
||||
}}}}} // namespace boost::geometry::index::detail::rtree
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP
|
||||
+16
@@ -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
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree quadratic split algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_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/bounded_view.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/node.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
namespace quadratic {
|
||||
|
||||
template <typename Box, typename Elements, typename Parameters, typename Translator>
|
||||
inline void pick_seeds(Elements const& elements,
|
||||
Parameters const& parameters,
|
||||
Translator const& tr,
|
||||
size_t & seed1,
|
||||
size_t & seed2)
|
||||
{
|
||||
typedef typename Elements::value_type element_type;
|
||||
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
|
||||
typedef Box box_type;
|
||||
typedef typename index::detail::default_content_result<box_type>::type content_type;
|
||||
typedef index::detail::bounded_view<indexable_type, box_type> bounded_indexable_view;
|
||||
|
||||
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;
|
||||
detail::bounds(ind1, enlarged_box);
|
||||
geometry::expand(enlarged_box, ind2);
|
||||
|
||||
bounded_indexable_view bounded_ind1(ind1);
|
||||
bounded_indexable_view bounded_ind2(ind2);
|
||||
content_type free_content = ( index::detail::content(enlarged_box)
|
||||
- index::detail::content(bounded_ind1) )
|
||||
- index::detail::content(bounded_ind2);
|
||||
|
||||
if ( greatest_free_content < free_content )
|
||||
{
|
||||
greatest_free_content = free_content;
|
||||
seed1 = i;
|
||||
seed2 = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::boost::ignore_unused_variable_warning(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;
|
||||
|
||||
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 - use in-memory storage (std::allocator)
|
||||
// TODO: move if noexcept
|
||||
typedef typename rtree::container_from_elements_type<elements_type, element_type>::type
|
||||
container_type;
|
||||
container_type elements_copy(elements1.begin(), elements1.end()); // MAY THROW, STRONG (alloc, copy)
|
||||
container_type elements_backup(elements1.begin(), elements1.end()); // MAY THROW, STRONG (alloc, copy)
|
||||
|
||||
// calculate initial seeds
|
||||
size_t seed1 = 0;
|
||||
size_t seed2 = 0;
|
||||
quadratic::pick_seeds<Box>(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");
|
||||
|
||||
BOOST_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
|
||||
detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), box1);
|
||||
detail::bounds(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 container_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 container_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;
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
//elements_copy.clear();
|
||||
elements1.clear();
|
||||
elements2.clear();
|
||||
|
||||
rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);
|
||||
//elements_backup.clear();
|
||||
|
||||
BOOST_RETHROW // RETHROW, BASIC
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
// 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
|
||||
+387
@@ -0,0 +1,387 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree query iterators
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
//#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
|
||||
|
||||
template <typename Value, typename Allocators>
|
||||
struct end_query_iterator
|
||||
{
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Value value_type;
|
||||
typedef typename Allocators::const_reference reference;
|
||||
typedef typename Allocators::difference_type difference_type;
|
||||
typedef typename Allocators::const_pointer pointer;
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");
|
||||
pointer p(0);
|
||||
return *p;
|
||||
}
|
||||
|
||||
const value_type * operator->() const
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");
|
||||
const value_type * p = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
end_query_iterator & operator++()
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");
|
||||
return *this;
|
||||
}
|
||||
|
||||
end_query_iterator operator++(int)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(end_query_iterator const& /*l*/, end_query_iterator const& /*r*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
|
||||
class spatial_query_iterator
|
||||
{
|
||||
typedef visitors::spatial_query_incremental<Value, Options, Translator, Box, Allocators, Predicates> visitor_type;
|
||||
typedef typename visitor_type::node_pointer node_pointer;
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Value value_type;
|
||||
typedef typename Allocators::const_reference reference;
|
||||
typedef typename Allocators::difference_type difference_type;
|
||||
typedef typename Allocators::const_pointer pointer;
|
||||
|
||||
inline spatial_query_iterator()
|
||||
{}
|
||||
|
||||
inline spatial_query_iterator(Translator const& t, Predicates const& p)
|
||||
: m_visitor(t, p)
|
||||
{}
|
||||
|
||||
inline spatial_query_iterator(node_pointer root, Translator const& t, Predicates const& p)
|
||||
: m_visitor(t, p)
|
||||
{
|
||||
m_visitor.initialize(root);
|
||||
}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
return m_visitor.dereference();
|
||||
}
|
||||
|
||||
const value_type * operator->() const
|
||||
{
|
||||
return boost::addressof(m_visitor.dereference());
|
||||
}
|
||||
|
||||
spatial_query_iterator & operator++()
|
||||
{
|
||||
m_visitor.increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
spatial_query_iterator operator++(int)
|
||||
{
|
||||
spatial_query_iterator temp = *this;
|
||||
this->operator++();
|
||||
return temp;
|
||||
}
|
||||
|
||||
friend bool operator==(spatial_query_iterator const& l, spatial_query_iterator const& r)
|
||||
{
|
||||
return l.m_visitor == r.m_visitor;
|
||||
}
|
||||
|
||||
friend bool operator==(spatial_query_iterator const& l, end_query_iterator<Value, Allocators> const& /*r*/)
|
||||
{
|
||||
return l.m_visitor.is_end();
|
||||
}
|
||||
|
||||
friend bool operator==(end_query_iterator<Value, Allocators> const& /*l*/, spatial_query_iterator const& r)
|
||||
{
|
||||
return r.m_visitor.is_end();
|
||||
}
|
||||
|
||||
private:
|
||||
visitor_type m_visitor;
|
||||
};
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, unsigned NearestPredicateIndex>
|
||||
class distance_query_iterator
|
||||
{
|
||||
typedef visitors::distance_query_incremental<Value, Options, Translator, Box, Allocators, Predicates, NearestPredicateIndex> visitor_type;
|
||||
typedef typename visitor_type::node_pointer node_pointer;
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Value value_type;
|
||||
typedef typename Allocators::const_reference reference;
|
||||
typedef typename Allocators::difference_type difference_type;
|
||||
typedef typename Allocators::const_pointer pointer;
|
||||
|
||||
inline distance_query_iterator()
|
||||
{}
|
||||
|
||||
inline distance_query_iterator(Translator const& t, Predicates const& p)
|
||||
: m_visitor(t, p)
|
||||
{}
|
||||
|
||||
inline distance_query_iterator(node_pointer root, Translator const& t, Predicates const& p)
|
||||
: m_visitor(t, p)
|
||||
{
|
||||
m_visitor.initialize(root);
|
||||
}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
return m_visitor.dereference();
|
||||
}
|
||||
|
||||
const value_type * operator->() const
|
||||
{
|
||||
return boost::addressof(m_visitor.dereference());
|
||||
}
|
||||
|
||||
distance_query_iterator & operator++()
|
||||
{
|
||||
m_visitor.increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
distance_query_iterator operator++(int)
|
||||
{
|
||||
distance_query_iterator temp = *this;
|
||||
this->operator++();
|
||||
return temp;
|
||||
}
|
||||
|
||||
friend bool operator==(distance_query_iterator const& l, distance_query_iterator const& r)
|
||||
{
|
||||
return l.m_visitor == r.m_visitor;
|
||||
}
|
||||
|
||||
friend bool operator==(distance_query_iterator const& l, end_query_iterator<Value, Allocators> const& /*r*/)
|
||||
{
|
||||
return l.m_visitor.is_end();
|
||||
}
|
||||
|
||||
friend bool operator==(end_query_iterator<Value, Allocators> const& /*l*/, distance_query_iterator const& r)
|
||||
{
|
||||
return r.m_visitor.is_end();
|
||||
}
|
||||
|
||||
private:
|
||||
visitor_type m_visitor;
|
||||
};
|
||||
|
||||
|
||||
template <typename L, typename R>
|
||||
inline bool operator!=(L const& l, R const& r)
|
||||
{
|
||||
return !(l == r);
|
||||
}
|
||||
|
||||
|
||||
template <typename Value, typename Allocators>
|
||||
class query_iterator_base
|
||||
{
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Value value_type;
|
||||
typedef typename Allocators::const_reference reference;
|
||||
typedef typename Allocators::difference_type difference_type;
|
||||
typedef typename Allocators::const_pointer pointer;
|
||||
|
||||
virtual ~query_iterator_base() {}
|
||||
|
||||
virtual query_iterator_base * clone() const = 0;
|
||||
|
||||
virtual bool is_end() const = 0;
|
||||
virtual reference dereference() const = 0;
|
||||
virtual void increment() = 0;
|
||||
virtual bool equals(query_iterator_base const&) const = 0;
|
||||
};
|
||||
|
||||
template <typename Value, typename Allocators, typename Iterator>
|
||||
class query_iterator_wrapper
|
||||
: public query_iterator_base<Value, Allocators>
|
||||
{
|
||||
typedef query_iterator_base<Value, Allocators> base_t;
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Value value_type;
|
||||
typedef typename Allocators::const_reference reference;
|
||||
typedef typename Allocators::difference_type difference_type;
|
||||
typedef typename Allocators::const_pointer pointer;
|
||||
|
||||
query_iterator_wrapper() : m_iterator() {}
|
||||
explicit query_iterator_wrapper(Iterator const& it) : m_iterator(it) {}
|
||||
|
||||
virtual base_t * clone() const { return new query_iterator_wrapper(m_iterator); }
|
||||
|
||||
virtual bool is_end() const { return m_iterator == end_query_iterator<Value, Allocators>(); }
|
||||
virtual reference dereference() const { return *m_iterator; }
|
||||
virtual void increment() { ++m_iterator; }
|
||||
virtual bool equals(base_t const& r) const
|
||||
{
|
||||
const query_iterator_wrapper * p = dynamic_cast<const query_iterator_wrapper *>(boost::addressof(r));
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(p, "iterators can't be compared");
|
||||
return m_iterator == p->m_iterator;
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator m_iterator;
|
||||
};
|
||||
|
||||
|
||||
template <typename Value, typename Allocators>
|
||||
class query_iterator
|
||||
{
|
||||
typedef query_iterator_base<Value, Allocators> iterator_base;
|
||||
typedef boost::scoped_ptr<iterator_base> iterator_ptr;
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Value value_type;
|
||||
typedef typename Allocators::const_reference reference;
|
||||
typedef typename Allocators::difference_type difference_type;
|
||||
typedef typename Allocators::const_pointer pointer;
|
||||
|
||||
query_iterator()
|
||||
{}
|
||||
|
||||
template <typename It>
|
||||
query_iterator(It const& it)
|
||||
: m_ptr(static_cast<iterator_base*>(
|
||||
new query_iterator_wrapper<Value, Allocators, It>(it) ))
|
||||
{}
|
||||
|
||||
query_iterator(end_query_iterator<Value, Allocators> const& /*it*/)
|
||||
{}
|
||||
|
||||
query_iterator(query_iterator const& o)
|
||||
: m_ptr(o.m_ptr.get() ? o.m_ptr->clone() : 0)
|
||||
{}
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
|
||||
query_iterator & operator=(query_iterator const& o)
|
||||
{
|
||||
if ( this != boost::addressof(o) )
|
||||
{
|
||||
m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
query_iterator(query_iterator && o)
|
||||
: m_ptr(0)
|
||||
{
|
||||
m_ptr.swap(o.m_ptr);
|
||||
}
|
||||
query_iterator & operator=(query_iterator && o)
|
||||
{
|
||||
if ( this != boost::addressof(o) )
|
||||
{
|
||||
m_ptr.swap(o.m_ptr);
|
||||
o.m_ptr.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#else // !BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(query_iterator)
|
||||
public:
|
||||
query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)
|
||||
{
|
||||
if ( this != boost::addressof(o) )
|
||||
{
|
||||
m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
query_iterator(BOOST_RV_REF(query_iterator) o)
|
||||
: m_ptr(0)
|
||||
{
|
||||
m_ptr.swap(o.m_ptr);
|
||||
}
|
||||
query_iterator & operator=(BOOST_RV_REF(query_iterator) o)
|
||||
{
|
||||
if ( this != boost::addressof(o) )
|
||||
{
|
||||
m_ptr.swap(o.m_ptr);
|
||||
o.m_ptr.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
return m_ptr->dereference();
|
||||
}
|
||||
|
||||
const value_type * operator->() const
|
||||
{
|
||||
return boost::addressof(m_ptr->dereference());
|
||||
}
|
||||
|
||||
query_iterator & operator++()
|
||||
{
|
||||
m_ptr->increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_iterator operator++(int)
|
||||
{
|
||||
query_iterator temp = *this;
|
||||
this->operator++();
|
||||
return temp;
|
||||
}
|
||||
|
||||
friend bool operator==(query_iterator const& l, query_iterator const& r)
|
||||
{
|
||||
if ( l.m_ptr.get() )
|
||||
{
|
||||
if ( r.m_ptr.get() )
|
||||
return l.m_ptr->equals(*r.m_ptr);
|
||||
else
|
||||
return l.m_ptr->is_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( r.m_ptr.get() )
|
||||
return r.m_ptr->is_end();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
iterator_ptr m_ptr;
|
||||
};
|
||||
|
||||
}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree R*-tree next node choosing algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_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/nth_element.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/node.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
template <typename Value, typename Options, typename Box, typename Allocators>
|
||||
class choose_next_node<Value, Options, Box, Allocators, choose_by_overlap_diff_tag>
|
||||
{
|
||||
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type children_type;
|
||||
typedef typename children_type::value_type child_type;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
public:
|
||||
template <typename Indexable>
|
||||
static inline size_t apply(internal_node & n,
|
||||
Indexable const& indexable,
|
||||
parameters_type const& parameters,
|
||||
size_t node_relative_level)
|
||||
{
|
||||
::boost::ignore_unused_variable_warning(parameters);
|
||||
|
||||
children_type & children = rtree::elements(n);
|
||||
|
||||
// children are leafs
|
||||
if ( node_relative_level <= 1 )
|
||||
{
|
||||
return choose_by_minimum_overlap_cost(children, indexable, parameters.get_overlap_cost_threshold());
|
||||
}
|
||||
// children are internal nodes
|
||||
else
|
||||
return choose_by_minimum_content_cost(children, indexable);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Indexable>
|
||||
static inline size_t choose_by_minimum_overlap_cost(children_type const& children,
|
||||
Indexable const& indexable,
|
||||
size_t overlap_cost_threshold)
|
||||
{
|
||||
const size_t children_count = children.size();
|
||||
|
||||
content_type min_content_diff = (std::numeric_limits<content_type>::max)();
|
||||
content_type min_content = (std::numeric_limits<content_type>::max)();
|
||||
size_t choosen_index = 0;
|
||||
|
||||
// create container of children sorted by content enlargement needed to include the new value
|
||||
typedef boost::tuple<size_t, content_type, content_type> child_contents;
|
||||
|
||||
typename rtree::container_from_elements_type<children_type, child_contents>::type children_contents;
|
||||
children_contents.resize(children_count);
|
||||
|
||||
for ( size_t i = 0 ; i < children_count ; ++i )
|
||||
{
|
||||
child_type const& ch_i = children[i];
|
||||
|
||||
// expanded child node's box
|
||||
Box box_exp(ch_i.first);
|
||||
geometry::expand(box_exp, indexable);
|
||||
|
||||
// areas difference
|
||||
content_type content = index::detail::content(box_exp);
|
||||
content_type content_diff = content - index::detail::content(ch_i.first);
|
||||
|
||||
children_contents[i] = boost::make_tuple(i, content_diff, content);
|
||||
|
||||
if ( content_diff < min_content_diff ||
|
||||
(content_diff == min_content_diff && content < min_content) )
|
||||
{
|
||||
min_content_diff = content_diff;
|
||||
min_content = content;
|
||||
choosen_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
// is this assumption ok? if min_content_diff == 0 there is no overlap increase?
|
||||
|
||||
if ( min_content_diff < -std::numeric_limits<double>::epsilon() || std::numeric_limits<double>::epsilon() < min_content_diff )
|
||||
{
|
||||
size_t first_n_children_count = children_count;
|
||||
if ( 0 < overlap_cost_threshold && overlap_cost_threshold < children.size() )
|
||||
{
|
||||
first_n_children_count = overlap_cost_threshold;
|
||||
// rearrange by content_diff
|
||||
// in order to calculate nearly minimum overlap cost
|
||||
index::detail::nth_element(children_contents.begin(), children_contents.begin() + first_n_children_count, children_contents.end(), content_diff_less);
|
||||
}
|
||||
|
||||
// calculate minimum or nearly minimum overlap cost
|
||||
choosen_index = choose_by_minimum_overlap_cost_first_n(children, indexable, first_n_children_count, children_count, children_contents);
|
||||
}
|
||||
|
||||
return choosen_index;
|
||||
}
|
||||
|
||||
static inline bool content_diff_less(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, typename ChildrenContents>
|
||||
static inline size_t choose_by_minimum_overlap_cost_first_n(children_type const& children,
|
||||
Indexable const& indexable,
|
||||
size_t const first_n_children_count,
|
||||
size_t const children_count,
|
||||
ChildrenContents const& children_contents)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(first_n_children_count <= children_count, "unexpected value");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(children_contents.size() == children_count, "unexpected number of elements");
|
||||
|
||||
// choose index with smallest overlap change value, or content change or smallest content
|
||||
size_t choosen_index = 0;
|
||||
content_type smallest_overlap_diff = (std::numeric_limits<content_type>::max)();
|
||||
content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
|
||||
content_type smallest_content = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
// for each child node
|
||||
for (size_t i = 0 ; i < first_n_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);
|
||||
|
||||
content_type overlap_diff = 0;
|
||||
|
||||
// calculate overlap
|
||||
for ( size_t j = 0 ; j < children_count ; ++j )
|
||||
{
|
||||
if ( i != j )
|
||||
{
|
||||
child_type const& ch_j = children[j];
|
||||
|
||||
content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first);
|
||||
if ( overlap_exp < -std::numeric_limits<content_type>::epsilon() || std::numeric_limits<content_type>::epsilon() < overlap_exp )
|
||||
{
|
||||
overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
content_type content = boost::get<2>(children_contents[i]);
|
||||
content_type content_diff = boost::get<1>(children_contents[i]);
|
||||
|
||||
// update result
|
||||
if ( overlap_diff < smallest_overlap_diff ||
|
||||
( overlap_diff == smallest_overlap_diff && ( content_diff < smallest_content_diff ||
|
||||
( content_diff == smallest_content_diff && content < smallest_content ) )
|
||||
) )
|
||||
{
|
||||
smallest_overlap_diff = overlap_diff;
|
||||
smallest_content_diff = content_diff;
|
||||
smallest_content = content;
|
||||
choosen_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return choosen_index;
|
||||
}
|
||||
|
||||
template <typename Indexable>
|
||||
static inline size_t choose_by_minimum_content_cost(children_type const& children, Indexable const& indexable)
|
||||
{
|
||||
size_t children_count = children.size();
|
||||
|
||||
// choose index with smallest content change or smallest content
|
||||
size_t choosen_index = 0;
|
||||
content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
|
||||
content_type smallest_content = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
// choose the child which requires smallest box expansion to store the indexable
|
||||
for ( size_t i = 0 ; i < children_count ; ++i )
|
||||
{
|
||||
child_type const& ch_i = children[i];
|
||||
|
||||
// expanded child node's box
|
||||
Box box_exp(ch_i.first);
|
||||
geometry::expand(box_exp, indexable);
|
||||
|
||||
// areas difference
|
||||
content_type content = index::detail::content(box_exp);
|
||||
content_type content_diff = content - index::detail::content(ch_i.first);
|
||||
|
||||
// update the result
|
||||
if ( content_diff < smallest_content_diff ||
|
||||
( content_diff == smallest_content_diff && content < smallest_content ) )
|
||||
{
|
||||
smallest_content_diff = content_diff;
|
||||
smallest_content = content;
|
||||
choosen_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return choosen_index;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP
|
||||
+591
@@ -0,0 +1,591 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree R*-tree insert algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/content.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
namespace rstar {
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class remove_elements_to_reinsert
|
||||
{
|
||||
public:
|
||||
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
//typedef typename Allocators::internal_node_pointer internal_node_pointer;
|
||||
typedef internal_node * internal_node_pointer;
|
||||
|
||||
template <typename ResultElements, typename Node>
|
||||
static inline void apply(ResultElements & result_elements,
|
||||
Node & n,
|
||||
internal_node_pointer parent,
|
||||
size_t current_child_index,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators)
|
||||
{
|
||||
typedef typename rtree::elements_type<Node>::type elements_type;
|
||||
typedef typename elements_type::value_type element_type;
|
||||
typedef typename geometry::point_type<Box>::type point_type;
|
||||
// TODO: awulkiew - change second point_type to the point type of the Indexable?
|
||||
typedef typename
|
||||
geometry::default_comparable_distance_result<point_type>::type
|
||||
comparable_distance_type;
|
||||
|
||||
elements_type & elements = rtree::elements(n);
|
||||
|
||||
const size_t elements_count = parameters.get_max_elements() + 1;
|
||||
const size_t reinserted_elements_count = (::std::min)(parameters.get_reinserted_elements(), elements_count - parameters.get_min_elements());
|
||||
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(parent, "node shouldn't be the root node");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected elements number");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < reinserted_elements_count, "wrong value of elements to reinsert");
|
||||
|
||||
// calculate current node's center
|
||||
point_type node_center;
|
||||
geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center);
|
||||
|
||||
// fill the container of centers' distances of children from current node's center
|
||||
typedef typename index::detail::rtree::container_from_elements_type<
|
||||
elements_type,
|
||||
std::pair<comparable_distance_type, element_type>
|
||||
>::type sorted_elements_type;
|
||||
|
||||
sorted_elements_type sorted_elements;
|
||||
// If constructor is used instead of resize() MS implementation leaks here
|
||||
sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
|
||||
|
||||
for ( typename elements_type::const_iterator it = elements.begin() ;
|
||||
it != elements.end() ; ++it )
|
||||
{
|
||||
point_type element_center;
|
||||
geometry::centroid( rtree::element_indexable(*it, translator), element_center);
|
||||
sorted_elements.push_back(std::make_pair(
|
||||
geometry::comparable_distance(node_center, element_center),
|
||||
*it)); // MAY THROW (V, E: copy)
|
||||
}
|
||||
|
||||
// sort elements by distances from center
|
||||
std::partial_sort(
|
||||
sorted_elements.begin(),
|
||||
sorted_elements.begin() + reinserted_elements_count,
|
||||
sorted_elements.end(),
|
||||
distances_dsc<comparable_distance_type, element_type>); // MAY THROW, BASIC (V, E: copy)
|
||||
|
||||
// copy elements which will be reinserted
|
||||
result_elements.clear();
|
||||
result_elements.reserve(reinserted_elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
|
||||
for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() ;
|
||||
it != sorted_elements.begin() + reinserted_elements_count ; ++it )
|
||||
{
|
||||
result_elements.push_back(it->second); // MAY THROW (V, E: copy)
|
||||
}
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
// copy remaining elements to the current node
|
||||
elements.clear();
|
||||
elements.reserve(elements_count - reinserted_elements_count); // SHOULDN'T THROW (new_size <= old size)
|
||||
for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() + reinserted_elements_count;
|
||||
it != sorted_elements.end() ; ++it )
|
||||
{
|
||||
elements.push_back(it->second); // MAY THROW (V, E: copy)
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
elements.clear();
|
||||
|
||||
for ( typename sorted_elements_type::iterator it = sorted_elements.begin() ;
|
||||
it != sorted_elements.end() ; ++it )
|
||||
{
|
||||
destroy_element<Value, Options, Translator, Box, Allocators>::apply(it->second, allocators);
|
||||
}
|
||||
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
::boost::ignore_unused_variable_warning(parameters);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Distance, typename El>
|
||||
static inline bool distances_asc(
|
||||
std::pair<Distance, El> const& d1,
|
||||
std::pair<Distance, El> const& d2)
|
||||
{
|
||||
return d1.first < d2.first;
|
||||
}
|
||||
|
||||
template <typename Distance, typename El>
|
||||
static inline bool distances_dsc(
|
||||
std::pair<Distance, El> const& d1,
|
||||
std::pair<Distance, El> const& d2)
|
||||
{
|
||||
return d1.first > d2.first;
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Box, typename Allocators>
|
||||
struct level_insert_elements_type
|
||||
{
|
||||
typedef typename rtree::elements_type<
|
||||
typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <typename Value, typename Options, typename Box, typename Allocators>
|
||||
struct level_insert_elements_type<0, Value, Value, Options, Box, Allocators>
|
||||
{
|
||||
typedef typename rtree::elements_type<
|
||||
typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct level_insert_base
|
||||
: public detail::insert<Element, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
typedef detail::insert<Element, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename level_insert_elements_type<InsertIndex, Element, Value, Options, Box, Allocators>::type elements_type;
|
||||
typedef typename index::detail::rtree::container_from_elements_type<
|
||||
elements_type,
|
||||
typename elements_type::value_type
|
||||
>::type result_elements_type;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
inline level_insert_base(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Element const& element,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level)
|
||||
: base(root, leafs_level, element, parameters, translator, allocators, relative_level)
|
||||
, result_relative_level(0)
|
||||
{}
|
||||
|
||||
template <typename Node>
|
||||
inline void handle_possible_reinsert_or_split_of_root(Node &n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(result_elements.empty(), "reinsert should be handled only once for level");
|
||||
|
||||
result_relative_level = base::m_leafs_level - base::m_traverse_data.current_level;
|
||||
|
||||
// overflow
|
||||
if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
|
||||
{
|
||||
// node isn't root node
|
||||
if ( !base::m_traverse_data.current_is_root() )
|
||||
{
|
||||
// NOTE: exception-safety
|
||||
// After an exception result_elements may contain garbage, don't use it
|
||||
rstar::remove_elements_to_reinsert<Value, Options, Translator, Box, Allocators>::apply(
|
||||
result_elements, n,
|
||||
base::m_traverse_data.parent, base::m_traverse_data.current_child_index,
|
||||
base::m_parameters, base::m_translator, base::m_allocators); // MAY THROW, BASIC (V, E: alloc, copy)
|
||||
}
|
||||
// node is root node
|
||||
else
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*base::m_root_node), "node should be the root node");
|
||||
base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
inline void handle_possible_split(Node &n) const
|
||||
{
|
||||
// overflow
|
||||
if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
|
||||
{
|
||||
base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
inline void recalculate_aabb_if_necessary(Node const& n) const
|
||||
{
|
||||
if ( !result_elements.empty() && !base::m_traverse_data.current_is_root() )
|
||||
{
|
||||
// calulate node's new box
|
||||
recalculate_aabb(n);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
inline void recalculate_aabb(Node const& n) const
|
||||
{
|
||||
base::m_traverse_data.current_element().first =
|
||||
elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);
|
||||
}
|
||||
|
||||
inline void recalculate_aabb(leaf const& n) const
|
||||
{
|
||||
base::m_traverse_data.current_element().first =
|
||||
values_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);
|
||||
}
|
||||
|
||||
size_type result_relative_level;
|
||||
result_elements_type result_elements;
|
||||
};
|
||||
|
||||
template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct level_insert
|
||||
: public level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
typedef level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
inline level_insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Element const& element,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level)
|
||||
: base(root, leafs_level, element, parameters, translator, allocators, relative_level)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
|
||||
|
||||
if ( base::m_traverse_data.current_level < base::m_level )
|
||||
{
|
||||
// next traversing step
|
||||
base::traverse(*this, n); // MAY THROW (E: alloc, copy, N: alloc)
|
||||
|
||||
// further insert
|
||||
if ( 0 < InsertIndex )
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
|
||||
|
||||
if ( base::m_traverse_data.current_level == base::m_level - 1 )
|
||||
{
|
||||
base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
// push new child node
|
||||
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
// NOTE: exception-safety
|
||||
// if the insert fails above, the element won't be stored in the tree, so delete it
|
||||
|
||||
rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(base::m_element.second, base::m_allocators);
|
||||
rtree::apply_visitor(del_v, *base::m_element.second);
|
||||
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
// first insert
|
||||
if ( 0 == InsertIndex )
|
||||
{
|
||||
base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
|
||||
}
|
||||
// not the first insert
|
||||
else
|
||||
{
|
||||
base::handle_possible_split(n); // MAY THROW (E: alloc, N: alloc)
|
||||
}
|
||||
}
|
||||
|
||||
base::recalculate_aabb_if_necessary(n);
|
||||
}
|
||||
|
||||
inline void operator()(leaf &)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t InsertIndex, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct level_insert<InsertIndex, Value, Value, Options, Translator, Box, Allocators>
|
||||
: public level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
typedef level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
inline level_insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Value const& v,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level)
|
||||
: base(root, leafs_level, v, parameters, translator, allocators, relative_level)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");
|
||||
|
||||
// next traversing step
|
||||
base::traverse(*this, n); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
|
||||
|
||||
if ( base::m_traverse_data.current_level == base::m_level - 1 )
|
||||
{
|
||||
base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
|
||||
}
|
||||
|
||||
base::recalculate_aabb_if_necessary(n);
|
||||
}
|
||||
|
||||
inline void operator()(leaf & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
|
||||
"unexpected level");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
|
||||
base::m_level == (std::numeric_limits<size_t>::max)(),
|
||||
"unexpected level");
|
||||
|
||||
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
|
||||
|
||||
base::handle_possible_split(n); // MAY THROW (V: alloc, copy, N: alloc)
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct level_insert<0, Value, Value, Options, Translator, Box, Allocators>
|
||||
: public level_insert_base<0, Value, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
typedef level_insert_base<0, Value, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
inline level_insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Value const& v,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level)
|
||||
: base(root, leafs_level, v, parameters, translator, allocators, relative_level)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level,
|
||||
"unexpected level");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level,
|
||||
"unexpected level");
|
||||
|
||||
// next traversing step
|
||||
base::traverse(*this, n); // MAY THROW (V: alloc, copy, N: alloc)
|
||||
|
||||
base::recalculate_aabb_if_necessary(n);
|
||||
}
|
||||
|
||||
inline void operator()(leaf & n)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
|
||||
"unexpected level");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
|
||||
base::m_level == (std::numeric_limits<size_t>::max)(),
|
||||
"unexpected level");
|
||||
|
||||
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
|
||||
|
||||
base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (V: alloc, copy, N: alloc)
|
||||
|
||||
base::recalculate_aabb_if_necessary(n);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rstar
|
||||
|
||||
// R*-tree insert visitor
|
||||
// After passing the Element to insert visitor the Element is managed by the tree
|
||||
// I.e. one should not delete the node passed to the insert visitor after exception is thrown
|
||||
// because this visitor may delete it
|
||||
template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class insert<Element, Value, Options, Translator, Box, Allocators, insert_reinsert_tag>
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
|
||||
{
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
public:
|
||||
inline insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Element const& element,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level = 0)
|
||||
: m_root(root), m_leafs_level(leafs_level), m_element(element)
|
||||
, m_parameters(parameters), m_translator(translator)
|
||||
, m_relative_level(relative_level), m_allocators(allocators)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node & n)
|
||||
{
|
||||
boost::ignore_unused(n);
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root), "current node should be the root");
|
||||
|
||||
// Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
|
||||
if ( m_parameters.get_reinserted_elements() > 0 )
|
||||
{
|
||||
rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(
|
||||
m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
|
||||
|
||||
rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
|
||||
if ( !lins_v.result_elements.empty() )
|
||||
{
|
||||
recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(
|
||||
m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
|
||||
|
||||
rtree::apply_visitor(ins_v, *m_root);
|
||||
}
|
||||
}
|
||||
|
||||
inline void operator()(leaf & n)
|
||||
{
|
||||
boost::ignore_unused(n);
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<leaf>(*m_root), "current node should be the root");
|
||||
|
||||
// Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
|
||||
if ( m_parameters.get_reinserted_elements() > 0 )
|
||||
{
|
||||
rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(
|
||||
m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
|
||||
|
||||
rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
|
||||
// we're in the root, so root should be split and there should be no elements to reinsert
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(lins_v.result_elements.empty(), "unexpected state");
|
||||
}
|
||||
else
|
||||
{
|
||||
visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(
|
||||
m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
|
||||
|
||||
rtree::apply_visitor(ins_v, *m_root);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Elements>
|
||||
inline void recursive_reinsert(Elements & elements, size_t relative_level)
|
||||
{
|
||||
typedef typename Elements::value_type element_type;
|
||||
|
||||
// reinsert children starting from the minimum distance
|
||||
typename Elements::reverse_iterator it = elements.rbegin();
|
||||
for ( ; it != elements.rend() ; ++it)
|
||||
{
|
||||
rstar::level_insert<1, element_type, Value, Options, Translator, Box, Allocators> lins_v(
|
||||
m_root, m_leafs_level, *it, m_parameters, m_translator, m_allocators, relative_level);
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
++it;
|
||||
for ( ; it != elements.rend() ; ++it)
|
||||
rtree::destroy_element<Value, Options, Translator, Box, Allocators>::apply(*it, m_allocators);
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(relative_level + 1 == lins_v.result_relative_level, "unexpected level");
|
||||
|
||||
// non-root relative level
|
||||
if ( lins_v.result_relative_level < m_leafs_level && !lins_v.result_elements.empty())
|
||||
{
|
||||
recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node_pointer & m_root;
|
||||
size_type & m_leafs_level;
|
||||
Element const& m_element;
|
||||
|
||||
parameters_type const& m_parameters;
|
||||
Translator const& m_translator;
|
||||
|
||||
size_type m_relative_level;
|
||||
|
||||
Allocators & m_allocators;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
|
||||
+470
@@ -0,0 +1,470 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree R*-tree split algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/margin.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/bounded_view.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/node.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
namespace rstar {
|
||||
|
||||
template <typename Element, typename Translator, typename Tag, size_t Corner, size_t AxisIndex>
|
||||
class element_axis_corner_less
|
||||
{
|
||||
typedef typename rtree::element_indexable_type<Element, Translator>::type indexable_type;
|
||||
typedef typename geometry::point_type<indexable_type>::type point_type;
|
||||
typedef geometry::model::box<point_type> bounds_type;
|
||||
typedef index::detail::bounded_view<indexable_type, bounds_type> bounded_view_type;
|
||||
|
||||
public:
|
||||
element_axis_corner_less(Translator const& tr)
|
||||
: m_tr(tr)
|
||||
{}
|
||||
|
||||
bool operator()(Element const& e1, Element const& e2) const
|
||||
{
|
||||
bounded_view_type bounded_ind1(rtree::element_indexable(e1, m_tr));
|
||||
bounded_view_type bounded_ind2(rtree::element_indexable(e2, m_tr));
|
||||
|
||||
return geometry::get<Corner, AxisIndex>(bounded_ind1)
|
||||
< geometry::get<Corner, AxisIndex>(bounded_ind2);
|
||||
}
|
||||
|
||||
private:
|
||||
Translator const& m_tr;
|
||||
};
|
||||
|
||||
template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>
|
||||
class element_axis_corner_less<Element, Translator, box_tag, Corner, AxisIndex>
|
||||
{
|
||||
public:
|
||||
element_axis_corner_less(Translator const& tr)
|
||||
: m_tr(tr)
|
||||
{}
|
||||
|
||||
bool operator()(Element const& e1, Element const& e2) const
|
||||
{
|
||||
return geometry::get<Corner, AxisIndex>(rtree::element_indexable(e1, m_tr))
|
||||
< geometry::get<Corner, AxisIndex>(rtree::element_indexable(e2, m_tr));
|
||||
}
|
||||
|
||||
private:
|
||||
Translator const& m_tr;
|
||||
};
|
||||
|
||||
template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>
|
||||
class element_axis_corner_less<Element, Translator, point_tag, Corner, AxisIndex>
|
||||
{
|
||||
public:
|
||||
element_axis_corner_less(Translator const& tr)
|
||||
: m_tr(tr)
|
||||
{}
|
||||
|
||||
bool operator()(Element const& e1, Element const& e2) const
|
||||
{
|
||||
return geometry::get<AxisIndex>(rtree::element_indexable(e1, m_tr))
|
||||
< geometry::get<AxisIndex>(rtree::element_indexable(e2, m_tr));
|
||||
}
|
||||
|
||||
private:
|
||||
Translator const& m_tr;
|
||||
};
|
||||
|
||||
template <typename Box, size_t Corner, size_t AxisIndex>
|
||||
struct choose_split_axis_and_index_for_corner
|
||||
{
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_index,
|
||||
margin_type & sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
typedef typename Elements::value_type element_type;
|
||||
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
|
||||
typedef typename tag<indexable_type>::type indexable_tag;
|
||||
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == parameters.get_max_elements() + 1, "wrong number of elements");
|
||||
|
||||
// copy elements
|
||||
Elements elements_copy(elements); // MAY THROW, STRONG (alloc, copy)
|
||||
|
||||
size_t const index_first = parameters.get_min_elements();
|
||||
size_t const index_last = parameters.get_max_elements() - parameters.get_min_elements() + 2;
|
||||
|
||||
// sort elements
|
||||
element_axis_corner_less<element_type, Translator, indexable_tag, Corner, AxisIndex> elements_less(translator);
|
||||
std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// {
|
||||
// typename Elements::iterator f = elements_copy.begin() + index_first;
|
||||
// typename Elements::iterator l = elements_copy.begin() + index_last;
|
||||
// // NOTE: for stdlibc++ shipped with gcc 4.8.2 std::nth_element is replaced with std::sort anyway
|
||||
// index::detail::nth_element(elements_copy.begin(), f, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// index::detail::nth_element(f, l, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// std::sort(f, l, elements_less); // MAY THROW, BASIC (copy)
|
||||
// }
|
||||
|
||||
// init outputs
|
||||
choosen_index = index_first;
|
||||
sum_of_margins = 0;
|
||||
smallest_overlap = (std::numeric_limits<content_type>::max)();
|
||||
smallest_content = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
// calculate sum of margins for all distributions
|
||||
for ( size_t i = index_first ; i < index_last ; ++i )
|
||||
{
|
||||
// TODO - awulkiew: may be optimized - box of group 1 may be initialized with
|
||||
// box of min_elems number of elements and expanded for each iteration by another element
|
||||
|
||||
Box box1 = rtree::elements_box<Box>(elements_copy.begin(), elements_copy.begin() + i, translator);
|
||||
Box box2 = rtree::elements_box<Box>(elements_copy.begin() + i, elements_copy.end(), translator);
|
||||
|
||||
sum_of_margins += index::detail::comparable_margin(box1) + index::detail::comparable_margin(box2);
|
||||
|
||||
content_type ovl = index::detail::intersection_content(box1, box2);
|
||||
content_type con = index::detail::content(box1) + index::detail::content(box2);
|
||||
|
||||
// TODO - shouldn't here be < instead of <= ?
|
||||
if ( ovl < smallest_overlap || (ovl == smallest_overlap && con <= smallest_content) )
|
||||
{
|
||||
choosen_index = i;
|
||||
smallest_overlap = ovl;
|
||||
smallest_content = con;
|
||||
}
|
||||
}
|
||||
|
||||
::boost::ignore_unused_variable_warning(parameters);
|
||||
}
|
||||
};
|
||||
|
||||
//template <typename Box, size_t AxisIndex, typename ElementIndexableTag>
|
||||
//struct choose_split_axis_and_index_for_axis
|
||||
//{
|
||||
// BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (ElementIndexableTag));
|
||||
//};
|
||||
|
||||
template <typename Box, size_t AxisIndex, typename ElementIndexableTag>
|
||||
struct choose_split_axis_and_index_for_axis
|
||||
{
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_corner,
|
||||
size_t & choosen_index,
|
||||
margin_type & sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
size_t index1 = 0;
|
||||
margin_type som1 = 0;
|
||||
content_type ovl1 = (std::numeric_limits<content_type>::max)();
|
||||
content_type con1 = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
choose_split_axis_and_index_for_corner<Box, min_corner, AxisIndex>
|
||||
::apply(elements, index1,
|
||||
som1, ovl1, con1,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
size_t index2 = 0;
|
||||
margin_type som2 = 0;
|
||||
content_type ovl2 = (std::numeric_limits<content_type>::max)();
|
||||
content_type con2 = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
choose_split_axis_and_index_for_corner<Box, max_corner, AxisIndex>
|
||||
::apply(elements, index2,
|
||||
som2, ovl2, con2,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
sum_of_margins = som1 + som2;
|
||||
|
||||
if ( ovl1 < ovl2 || (ovl1 == ovl2 && con1 <= con2) )
|
||||
{
|
||||
choosen_corner = min_corner;
|
||||
choosen_index = index1;
|
||||
smallest_overlap = ovl1;
|
||||
smallest_content = con1;
|
||||
}
|
||||
else
|
||||
{
|
||||
choosen_corner = max_corner;
|
||||
choosen_index = index2;
|
||||
smallest_overlap = ovl2;
|
||||
smallest_content = con2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box, size_t AxisIndex>
|
||||
struct choose_split_axis_and_index_for_axis<Box, AxisIndex, point_tag>
|
||||
{
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_corner,
|
||||
size_t & choosen_index,
|
||||
margin_type & sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
choose_split_axis_and_index_for_corner<Box, min_corner, AxisIndex>
|
||||
::apply(elements, choosen_index,
|
||||
sum_of_margins, smallest_overlap, smallest_content,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
choosen_corner = min_corner;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box, size_t Dimension>
|
||||
struct choose_split_axis_and_index
|
||||
{
|
||||
BOOST_STATIC_ASSERT(0 < Dimension);
|
||||
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_axis,
|
||||
size_t & choosen_corner,
|
||||
size_t & choosen_index,
|
||||
margin_type & smallest_sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
typedef typename rtree::element_indexable_type<typename Elements::value_type, Translator>::type element_indexable_type;
|
||||
|
||||
choose_split_axis_and_index<Box, Dimension - 1>
|
||||
::apply(elements, choosen_axis, choosen_corner, choosen_index,
|
||||
smallest_sum_of_margins, smallest_overlap, smallest_content,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
margin_type sum_of_margins = 0;
|
||||
|
||||
size_t corner = min_corner;
|
||||
size_t index = 0;
|
||||
|
||||
content_type overlap_val = (std::numeric_limits<content_type>::max)();
|
||||
content_type content_val = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
choose_split_axis_and_index_for_axis<
|
||||
Box,
|
||||
Dimension - 1,
|
||||
typename tag<element_indexable_type>::type
|
||||
>::apply(elements, corner, index, sum_of_margins, overlap_val, content_val, parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
if ( sum_of_margins < smallest_sum_of_margins )
|
||||
{
|
||||
choosen_axis = Dimension - 1;
|
||||
choosen_corner = corner;
|
||||
choosen_index = index;
|
||||
smallest_sum_of_margins = sum_of_margins;
|
||||
smallest_overlap = overlap_val;
|
||||
smallest_content = content_val;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct choose_split_axis_and_index<Box, 1>
|
||||
{
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Elements, typename Parameters, typename Translator>
|
||||
static inline void apply(Elements const& elements,
|
||||
size_t & choosen_axis,
|
||||
size_t & choosen_corner,
|
||||
size_t & choosen_index,
|
||||
margin_type & smallest_sum_of_margins,
|
||||
content_type & smallest_overlap,
|
||||
content_type & smallest_content,
|
||||
Parameters const& parameters,
|
||||
Translator const& translator)
|
||||
{
|
||||
typedef typename rtree::element_indexable_type<typename Elements::value_type, Translator>::type element_indexable_type;
|
||||
|
||||
choosen_axis = 0;
|
||||
|
||||
choose_split_axis_and_index_for_axis<
|
||||
Box,
|
||||
0,
|
||||
typename tag<element_indexable_type>::type
|
||||
>::apply(elements, choosen_corner, choosen_index, smallest_sum_of_margins, smallest_overlap, smallest_content, parameters, translator); // MAY THROW
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t Corner, size_t Dimension, size_t I = 0>
|
||||
struct nth_element
|
||||
{
|
||||
BOOST_STATIC_ASSERT(0 < Dimension);
|
||||
BOOST_STATIC_ASSERT(I < Dimension);
|
||||
|
||||
template <typename Elements, typename Translator>
|
||||
static inline void apply(Elements & elements, const size_t axis, const size_t index, Translator const& tr)
|
||||
{
|
||||
//BOOST_GEOMETRY_INDEX_ASSERT(axis < Dimension, "unexpected axis value");
|
||||
|
||||
if ( axis != I )
|
||||
{
|
||||
nth_element<Corner, Dimension, I + 1>::apply(elements, axis, index, tr); // MAY THROW, BASIC (copy)
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef typename Elements::value_type element_type;
|
||||
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
|
||||
typedef typename tag<indexable_type>::type indexable_tag;
|
||||
|
||||
element_axis_corner_less<element_type, Translator, indexable_tag, Corner, I> less(tr);
|
||||
index::detail::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t Corner, size_t Dimension>
|
||||
struct nth_element<Corner, Dimension, Dimension>
|
||||
{
|
||||
template <typename Elements, typename Translator>
|
||||
static inline void apply(Elements & /*elements*/, const size_t /*axis*/, const size_t /*index*/, Translator const& /*tr*/)
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace rstar
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct redistribute_elements<Value, Options, Translator, Box, Allocators, rstar_tag>
|
||||
{
|
||||
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
static const size_t dimension = geometry::dimension<Box>::value;
|
||||
|
||||
typedef typename index::detail::default_margin_result<Box>::type margin_type;
|
||||
typedef typename index::detail::default_content_result<Box>::type content_type;
|
||||
|
||||
template <typename Node>
|
||||
static inline void apply(
|
||||
Node & n,
|
||||
Node & second_node,
|
||||
Box & box1,
|
||||
Box & box2,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators)
|
||||
{
|
||||
typedef typename rtree::elements_type<Node>::type elements_type;
|
||||
typedef typename elements_type::value_type element_type;
|
||||
|
||||
elements_type & elements1 = rtree::elements(n);
|
||||
elements_type & elements2 = rtree::elements(second_node);
|
||||
|
||||
// copy original elements - use in-memory storage (std::allocator)
|
||||
// TODO: move if noexcept
|
||||
typedef typename rtree::container_from_elements_type<elements_type, element_type>::type
|
||||
container_type;
|
||||
container_type elements_copy(elements1.begin(), elements1.end()); // MAY THROW, STRONG
|
||||
container_type elements_backup(elements1.begin(), elements1.end()); // MAY THROW, STRONG
|
||||
|
||||
size_t split_axis = 0;
|
||||
size_t split_corner = 0;
|
||||
size_t split_index = parameters.get_min_elements();
|
||||
margin_type smallest_sum_of_margins = (std::numeric_limits<margin_type>::max)();
|
||||
content_type smallest_overlap = (std::numeric_limits<content_type>::max)();
|
||||
content_type smallest_content = (std::numeric_limits<content_type>::max)();
|
||||
|
||||
// NOTE: this function internally copies passed elements
|
||||
// why not pass mutable elements and use the same container for all axes/corners
|
||||
// and again, the same below calling partial_sort/nth_element
|
||||
// It would be even possible to not re-sort/find nth_element if the axis/corner
|
||||
// was found for the last sorting - last combination of axis/corner
|
||||
rstar::choose_split_axis_and_index<Box, dimension>
|
||||
::apply(elements_copy,
|
||||
split_axis, split_corner, split_index,
|
||||
smallest_sum_of_margins, smallest_overlap, smallest_content,
|
||||
parameters, translator); // MAY THROW, STRONG
|
||||
|
||||
// TODO: awulkiew - get rid of following static_casts?
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(split_axis < dimension, "unexpected value");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(split_corner == static_cast<size_t>(min_corner) || split_corner == static_cast<size_t>(max_corner), "unexpected value");
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= split_index && split_index <= parameters.get_max_elements() - parameters.get_min_elements() + 1, "unexpected value");
|
||||
|
||||
// TODO: consider using nth_element
|
||||
if ( split_corner == static_cast<size_t>(min_corner) )
|
||||
{
|
||||
rstar::nth_element<min_corner, dimension>
|
||||
::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
|
||||
}
|
||||
else
|
||||
{
|
||||
rstar::nth_element<max_corner, dimension>
|
||||
::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
|
||||
}
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
// copy elements to nodes
|
||||
elements1.assign(elements_copy.begin(), elements_copy.begin() + split_index); // MAY THROW, BASIC
|
||||
elements2.assign(elements_copy.begin() + split_index, elements_copy.end()); // MAY THROW, BASIC
|
||||
|
||||
// calculate boxes
|
||||
box1 = rtree::elements_box<Box>(elements1.begin(), elements1.end(), translator);
|
||||
box2 = rtree::elements_box<Box>(elements2.begin(), elements2.end(), translator);
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
//elements_copy.clear();
|
||||
elements1.clear();
|
||||
elements2.clear();
|
||||
|
||||
rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);
|
||||
//elements_backup.clear();
|
||||
|
||||
BOOST_RETHROW // RETHROW, BASIC
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::rtree
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
|
||||
@@ -0,0 +1,18 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree R*-tree algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/rstar/insert.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree boxes validating visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_BOXES_OK_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_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 utilities {
|
||||
|
||||
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 = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
|
||||
|
||||
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 = rtree::values_box<Box>(elements.begin(), elements.end(), m_tr);
|
||||
|
||||
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
|
||||
|
||||
template <typename Rtree> inline
|
||||
bool are_boxes_ok(Rtree const& tree, bool exact_match = true)
|
||||
{
|
||||
typedef utilities::view<Rtree> RTV;
|
||||
RTV rtv(tree);
|
||||
|
||||
visitors::are_boxes_ok<
|
||||
typename RTV::value_type,
|
||||
typename RTV::options_type,
|
||||
typename RTV::translator_type,
|
||||
typename RTV::box_type,
|
||||
typename RTV::allocators_type
|
||||
> v(rtv.translator(), exact_match);
|
||||
|
||||
rtv.apply_visitor(v);
|
||||
|
||||
return v.result;
|
||||
}
|
||||
|
||||
}}}}}} // namespace boost::geometry::index::detail::rtree::utilities
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_BOXES_OK_HPP
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree nodes elements numbers validating visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_COUNTS_OK_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_COUNTS_OK_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/node.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
|
||||
|
||||
namespace visitors {
|
||||
|
||||
template <typename Value, typename Options, typename Box, typename Allocators>
|
||||
class are_counts_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;
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
public:
|
||||
inline are_counts_ok(parameters_type const& parameters)
|
||||
: result(true), m_current_level(0), m_parameters(parameters)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// root internal node shouldn't contain 0 elements
|
||||
if ( elements.empty()
|
||||
|| !check_count(elements) )
|
||||
{
|
||||
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() && result == true ;
|
||||
++it)
|
||||
{
|
||||
rtree::apply_visitor(*this, *it->second);
|
||||
}
|
||||
|
||||
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 ( ( m_current_level > 0 && elements.empty() )
|
||||
|| !check_count(elements) )
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool result;
|
||||
|
||||
private:
|
||||
template <typename Elements>
|
||||
bool check_count(Elements const& elements)
|
||||
{
|
||||
// root may contain count < min but should never contain count > max
|
||||
return elements.size() <= m_parameters.get_max_elements()
|
||||
&& ( elements.size() >= m_parameters.get_min_elements()
|
||||
|| m_current_level == 0 );
|
||||
}
|
||||
|
||||
size_t m_current_level;
|
||||
parameters_type const& m_parameters;
|
||||
};
|
||||
|
||||
} // namespace visitors
|
||||
|
||||
template <typename Rtree> inline
|
||||
bool are_counts_ok(Rtree const& tree)
|
||||
{
|
||||
typedef utilities::view<Rtree> RTV;
|
||||
RTV rtv(tree);
|
||||
|
||||
visitors::are_counts_ok<
|
||||
typename RTV::value_type,
|
||||
typename RTV::options_type,
|
||||
typename RTV::box_type,
|
||||
typename RTV::allocators_type
|
||||
> v(tree.parameters());
|
||||
|
||||
rtv.apply_visitor(v);
|
||||
|
||||
return v.result;
|
||||
}
|
||||
|
||||
}}}}}} // namespace boost::geometry::index::detail::rtree::utilities
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_COUNTS_OK_HPP
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// 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_UTILITIES_ARE_LEVELS_OK_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_LEVELS_OK_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/node.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
|
||||
|
||||
namespace visitors {
|
||||
|
||||
template <typename Value, typename Options, 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()
|
||||
: result(true), 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:
|
||||
size_t m_leafs_level;
|
||||
size_t m_current_level;
|
||||
};
|
||||
|
||||
} // namespace visitors
|
||||
|
||||
template <typename Rtree> inline
|
||||
bool are_levels_ok(Rtree const& tree)
|
||||
{
|
||||
typedef utilities::view<Rtree> RTV;
|
||||
RTV rtv(tree);
|
||||
|
||||
visitors::are_levels_ok<
|
||||
typename RTV::value_type,
|
||||
typename RTV::options_type,
|
||||
typename RTV::box_type,
|
||||
typename RTV::allocators_type
|
||||
> v;
|
||||
|
||||
rtv.apply_visitor(v);
|
||||
|
||||
return v.result;
|
||||
}
|
||||
|
||||
}}}}}} // namespace boost::geometry::index::detail::rtree::utilities
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_LEVELS_OK_HPP
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
// 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_UTILITIES_GL_DRAW_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
namespace utilities {
|
||||
|
||||
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 coordinate_type<Point>::type z)
|
||||
{
|
||||
typename coordinate_type<Point>::type const& x = geometry::get<0>(p);
|
||||
typename coordinate_type<Point>::type const& y = geometry::get<1>(p);
|
||||
/*glBegin(GL_POINT);
|
||||
glVertex3f(x, y, z);
|
||||
glEnd();*/
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(x+1, y, z);
|
||||
glVertex3f(x, y+1, z);
|
||||
glVertex3f(x-1, y, z);
|
||||
glVertex3f(x, y-1, 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 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 Segment, size_t Dimension>
|
||||
struct gl_draw_segment
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct gl_draw_segment<Segment, 2>
|
||||
{
|
||||
static inline void apply(Segment const& s, typename coordinate_type<Segment>::type z)
|
||||
{
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(geometry::get<0, 0>(s), geometry::get<0, 1>(s), z);
|
||||
glVertex3f(geometry::get<1, 0>(s), geometry::get<1, 1>(s), z);
|
||||
glEnd();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable, typename Tag>
|
||||
struct gl_draw_indexable
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct gl_draw_indexable<Box, box_tag>
|
||||
: gl_draw_box<Box, geometry::dimension<Box>::value>
|
||||
{};
|
||||
|
||||
template <typename Point>
|
||||
struct gl_draw_indexable<Point, point_tag>
|
||||
: gl_draw_point<Point, geometry::dimension<Point>::value>
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct gl_draw_indexable<Segment, segment_tag>
|
||||
: gl_draw_segment<Segment, geometry::dimension<Segment>::value>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Indexable> inline
|
||||
void gl_draw_indexable(Indexable const& i, typename coordinate_type<Indexable>::type z)
|
||||
{
|
||||
dispatch::gl_draw_indexable<
|
||||
Indexable,
|
||||
typename tag<Indexable>::type
|
||||
>::apply(i, z);
|
||||
}
|
||||
|
||||
} // namespace utilities
|
||||
|
||||
namespace rtree { namespace utilities {
|
||||
|
||||
namespace visitors {
|
||||
|
||||
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 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::utilities::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::utilities::gl_draw_indexable(tr(*it), level_rel * z_mul);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Translator const& tr;
|
||||
size_t level_f;
|
||||
size_t level_l;
|
||||
typename coordinate_type<Box>::type z_mul;
|
||||
|
||||
size_t level;
|
||||
};
|
||||
|
||||
} // namespace visitors
|
||||
|
||||
template <typename Rtree> inline
|
||||
void gl_draw(Rtree const& tree,
|
||||
size_t level_first = 0,
|
||||
size_t level_last = (std::numeric_limits<size_t>::max)(),
|
||||
typename coordinate_type<
|
||||
typename Rtree::bounds_type
|
||||
>::type z_coord_level_multiplier = 1
|
||||
)
|
||||
{
|
||||
typedef utilities::view<Rtree> RTV;
|
||||
RTV rtv(tree);
|
||||
|
||||
if ( !tree.empty() )
|
||||
{
|
||||
glColor3f(0.75f, 0.75f, 0.75f);
|
||||
detail::utilities::gl_draw_indexable(tree.bounds(), 0);
|
||||
}
|
||||
|
||||
visitors::gl_draw<
|
||||
typename RTV::value_type,
|
||||
typename RTV::options_type,
|
||||
typename RTV::translator_type,
|
||||
typename RTV::box_type,
|
||||
typename RTV::allocators_type
|
||||
> gl_draw_v(rtv.translator(), level_first, level_last, z_coord_level_multiplier);
|
||||
|
||||
rtv.apply_visitor(gl_draw_v);
|
||||
}
|
||||
|
||||
}} // namespace rtree::utilities
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
// 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_UTILITIES_PRINT_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_PRINT_HPP
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
namespace utilities {
|
||||
|
||||
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
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
|
||||
};
|
||||
|
||||
template <typename Indexable>
|
||||
struct print_indexable<Indexable, box_tag>
|
||||
{
|
||||
static const size_t dimension = geometry::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 = geometry::dimension<Indexable>::value;
|
||||
|
||||
static inline void apply(std::ostream &os, Indexable const& i)
|
||||
{
|
||||
os << '(';
|
||||
print_point<Indexable, dimension>::apply(os, i);
|
||||
os << ')';
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable>
|
||||
struct print_indexable<Indexable, segment_tag>
|
||||
{
|
||||
static const size_t dimension = geometry::dimension<Indexable>::value;
|
||||
|
||||
static inline void apply(std::ostream &os, Indexable const& i)
|
||||
{
|
||||
os << '(';
|
||||
print_corner<Indexable, 0, dimension>::apply(os, i);
|
||||
os << ")-(";
|
||||
print_corner<Indexable, 1, dimension>::apply(os, i);
|
||||
os << ')';
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Indexable> inline
|
||||
void print_indexable(std::ostream & os, Indexable const& i)
|
||||
{
|
||||
dispatch::print_indexable<
|
||||
Indexable,
|
||||
typename tag<Indexable>::type
|
||||
>::apply(os, i);
|
||||
}
|
||||
|
||||
} // namespace utilities
|
||||
|
||||
namespace rtree { namespace utilities {
|
||||
|
||||
namespace visitors {
|
||||
|
||||
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::utilities::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::utilities::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 visitors
|
||||
|
||||
template <typename Rtree> inline
|
||||
void print(std::ostream & os, Rtree const& tree)
|
||||
{
|
||||
typedef utilities::view<Rtree> RTV;
|
||||
RTV rtv(tree);
|
||||
|
||||
visitors::print<
|
||||
typename RTV::value_type,
|
||||
typename RTV::options_type,
|
||||
typename RTV::translator_type,
|
||||
typename RTV::box_type,
|
||||
typename RTV::allocators_type
|
||||
> print_v(os, rtv.translator());
|
||||
rtv.apply_visitor(print_v);
|
||||
}
|
||||
|
||||
}} // namespace rtree::utilities
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_PRINT_HPP
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree visitor collecting basic statistics
|
||||
//
|
||||
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2013 Mateusz Loskot, London, UK.
|
||||
//
|
||||
// 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_UTILITIES_STATISTICS_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_STATISTICS_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
|
||||
|
||||
namespace visitors {
|
||||
|
||||
template <typename Value, typename Options, typename Box, typename Allocators>
|
||||
struct statistics : 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 statistics()
|
||||
: level(0)
|
||||
, levels(1) // count root
|
||||
, nodes(0)
|
||||
, leaves(0)
|
||||
, values(0)
|
||||
, values_min(0)
|
||||
, values_max(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);
|
||||
|
||||
++nodes; // count node
|
||||
|
||||
size_t const level_backup = level;
|
||||
++level;
|
||||
|
||||
levels += level++ > levels ? 1 : 0; // count level (root already counted)
|
||||
|
||||
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);
|
||||
|
||||
++leaves; // count leaves
|
||||
|
||||
std::size_t const v = elements.size();
|
||||
// count values spread per node and total
|
||||
values_min = (std::min)(values_min == 0 ? v : values_min, v);
|
||||
values_max = (std::max)(values_max, v);
|
||||
values += v;
|
||||
}
|
||||
|
||||
std::size_t level;
|
||||
std::size_t levels;
|
||||
std::size_t nodes;
|
||||
std::size_t leaves;
|
||||
std::size_t values;
|
||||
std::size_t values_min;
|
||||
std::size_t values_max;
|
||||
};
|
||||
|
||||
} // namespace visitors
|
||||
|
||||
template <typename Rtree> inline
|
||||
boost::tuple<std::size_t, std::size_t, std::size_t, std::size_t, std::size_t, std::size_t>
|
||||
statistics(Rtree const& tree)
|
||||
{
|
||||
typedef utilities::view<Rtree> RTV;
|
||||
RTV rtv(tree);
|
||||
|
||||
visitors::statistics<
|
||||
typename RTV::value_type,
|
||||
typename RTV::options_type,
|
||||
typename RTV::box_type,
|
||||
typename RTV::allocators_type
|
||||
> stats_v;
|
||||
|
||||
rtv.apply_visitor(stats_v);
|
||||
|
||||
return boost::make_tuple(stats_v.levels, stats_v.nodes, stats_v.leaves, stats_v.values, stats_v.values_min, stats_v.values_max);
|
||||
}
|
||||
|
||||
}}}}}} // namespace boost::geometry::index::detail::rtree::utilities
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_STATISTICS_HPP
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Rtree utilities view
|
||||
//
|
||||
// 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_UTILITIES_VIEW_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_VIEW_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace utilities {
|
||||
|
||||
template <typename Rtree>
|
||||
class view
|
||||
{
|
||||
public:
|
||||
typedef typename Rtree::size_type size_type;
|
||||
|
||||
typedef typename Rtree::translator_type translator_type;
|
||||
typedef typename Rtree::value_type value_type;
|
||||
typedef typename Rtree::options_type options_type;
|
||||
typedef typename Rtree::box_type box_type;
|
||||
typedef typename Rtree::allocators_type allocators_type;
|
||||
|
||||
view(Rtree const& rt) : m_rtree(rt) {}
|
||||
|
||||
template <typename Visitor>
|
||||
void apply_visitor(Visitor & vis) const
|
||||
{
|
||||
m_rtree.apply_visitor(vis);
|
||||
}
|
||||
|
||||
// This will most certainly be removed in the future
|
||||
translator_type translator() const
|
||||
{
|
||||
return m_rtree.translator();
|
||||
}
|
||||
|
||||
// This will probably be removed in the future
|
||||
size_type depth() const
|
||||
{
|
||||
return m_rtree.depth();
|
||||
}
|
||||
|
||||
private:
|
||||
view(view const&);
|
||||
view & operator=(view const&);
|
||||
|
||||
Rtree const& m_rtree;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::utilities
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_VIEW_HPP
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree node children box calculating visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_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::values_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
@@ -0,0 +1,92 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree deep copying visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_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::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
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)
|
||||
subtree_destroyer 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
|
||||
subtree_destroyer 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)
|
||||
subtree_destroyer 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
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree count visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 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>
|
||||
struct count_helper
|
||||
{
|
||||
template <typename Translator>
|
||||
static inline typename Translator::result_type indexable(Indexable const& i, Translator const&)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
template <typename Translator>
|
||||
static inline bool equals(Indexable const& i, Value const& v, Translator const& tr)
|
||||
{
|
||||
return geometry::equals(i, tr(v));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Value>
|
||||
struct count_helper<Value, Value>
|
||||
{
|
||||
template <typename Translator>
|
||||
static inline typename Translator::result_type indexable(Value const& v, Translator const& tr)
|
||||
{
|
||||
return tr(v);
|
||||
}
|
||||
template <typename Translator>
|
||||
static inline bool equals(Value const& v1, Value const& v2, Translator const& tr)
|
||||
{
|
||||
return tr.equals(v1, v2);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueOrIndexable, 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;
|
||||
|
||||
typedef count_helper<ValueOrIndexable, Value> count_help;
|
||||
|
||||
inline count(ValueOrIndexable const& vori, Translator const& t)
|
||||
: value_or_indexable(vori), 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(
|
||||
return_ref_or_bounds(
|
||||
count_help::indexable(value_or_indexable, tr)),
|
||||
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 ( count_help::equals(value_or_indexable, *it, tr) )
|
||||
{
|
||||
++found_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ValueOrIndexable const& value_or_indexable;
|
||||
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
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree destroying visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 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 & l)
|
||||
{
|
||||
boost::ignore_unused(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
|
||||
+588
@@ -0,0 +1,588 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree distance (knn, path, etc. ) query visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 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_DISTANCE_QUERY_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
template <typename Value, typename Translator, typename DistanceType, typename OutIt>
|
||||
class distance_query_result
|
||||
{
|
||||
public:
|
||||
typedef DistanceType distance_type;
|
||||
|
||||
inline explicit distance_query_result(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 has_enough_neighbors() const
|
||||
{
|
||||
return m_count <= m_neighbors.size();
|
||||
}
|
||||
|
||||
inline distance_type greatest_comparable_distance() const
|
||||
{
|
||||
// greatest 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;
|
||||
};
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename Options,
|
||||
typename Translator,
|
||||
typename Box,
|
||||
typename Allocators,
|
||||
typename Predicates,
|
||||
unsigned DistancePredicateIndex,
|
||||
typename OutIter
|
||||
>
|
||||
class distance_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::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
|
||||
typedef typename nearest_predicate_access::type nearest_predicate_type;
|
||||
typedef typename indexable_type<Translator>::type indexable_type;
|
||||
|
||||
typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
|
||||
typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> calculate_node_distance;
|
||||
typedef typename calculate_value_distance::result_type value_distance_type;
|
||||
typedef typename calculate_node_distance::result_type node_distance_type;
|
||||
|
||||
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
|
||||
inline distance_query(parameters_type const& parameters, Translator const& translator, Predicates const& pred, OutIter out_it)
|
||||
: m_parameters(parameters), m_translator(translator)
|
||||
, m_pred(pred)
|
||||
, m_result(nearest_predicate_access::get(m_pred).count, out_it)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
|
||||
// array of active nodes
|
||||
typedef typename index::detail::rtree::container_from_elements_type<
|
||||
elements_type,
|
||||
std::pair<node_distance_type, typename Allocators::node_pointer>
|
||||
>::type active_branch_list_type;
|
||||
|
||||
active_branch_list_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_distance_type node_distance;
|
||||
// if distance isn't ok - move to the next node
|
||||
if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if current node is further than found neighbors - don't analyze it
|
||||
if ( m_result.has_enough_neighbors() &&
|
||||
is_node_prunable(m_result.greatest_comparable_distance(), node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// add current node's data into the list
|
||||
active_branch_list.push_back( std::make_pair(node_distance, 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 ( typename active_branch_list_type::const_iterator it = active_branch_list.begin();
|
||||
it != active_branch_list.end() ; ++it )
|
||||
{
|
||||
// if current node is further than furthest neighbor, the rest of nodes also will be further
|
||||
if ( m_result.has_enough_neighbors() &&
|
||||
is_node_prunable(m_result.greatest_comparable_distance(), it->first) )
|
||||
break;
|
||||
|
||||
rtree::apply_visitor(*this, *(it->second));
|
||||
}
|
||||
|
||||
// ALTERNATIVE VERSION - use heap instead of sorted container
|
||||
// It seems to be faster for greater MaxElements and slower otherwise
|
||||
// CONSIDER: using one global container/heap for active branches
|
||||
// instead of a sorted container per level
|
||||
// This would also change the way how branches are traversed!
|
||||
// The same may be applied to the iterative version which btw suffers
|
||||
// from the copying of the whole containers on resize of the ABLs container
|
||||
|
||||
//// make a heap
|
||||
//std::make_heap(active_branch_list.begin(), active_branch_list.end(), abl_greater);
|
||||
|
||||
//// recursively visit nodes
|
||||
//while ( !active_branch_list.empty() )
|
||||
//{
|
||||
// //if current node is further than furthest neighbor, the rest of nodes also will be further
|
||||
// if ( m_result.has_enough_neighbors()
|
||||
// && is_node_prunable(m_result.greatest_comparable_distance(), active_branch_list.front().first) )
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
|
||||
// rtree::apply_visitor(*this, *(active_branch_list.front().second));
|
||||
|
||||
// std::pop_heap(active_branch_list.begin(), active_branch_list.end(), abl_greater);
|
||||
// active_branch_list.pop_back();
|
||||
//}
|
||||
}
|
||||
|
||||
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_distance_type value_distance;
|
||||
// if distance is ok
|
||||
if ( calculate_value_distance::apply(predicate(), m_translator(*it), value_distance) )
|
||||
{
|
||||
// store value
|
||||
m_result.store(*it, value_distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t finish()
|
||||
{
|
||||
return m_result.finish();
|
||||
}
|
||||
|
||||
private:
|
||||
static inline bool abl_less(
|
||||
std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
|
||||
std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
|
||||
{
|
||||
return p1.first < p2.first;
|
||||
}
|
||||
|
||||
//static inline bool abl_greater(
|
||||
// std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
|
||||
// std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
|
||||
//{
|
||||
// return p1.first > p2.first;
|
||||
//}
|
||||
|
||||
template <typename Distance>
|
||||
static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)
|
||||
{
|
||||
return greatest_dist <= d;
|
||||
}
|
||||
|
||||
nearest_predicate_type const& predicate() const
|
||||
{
|
||||
return nearest_predicate_access::get(m_pred);
|
||||
}
|
||||
|
||||
parameters_type const& m_parameters;
|
||||
Translator const& m_translator;
|
||||
|
||||
Predicates m_pred;
|
||||
distance_query_result<Value, Translator, value_distance_type, OutIter> m_result;
|
||||
};
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename Options,
|
||||
typename Translator,
|
||||
typename Box,
|
||||
typename Allocators,
|
||||
typename Predicates,
|
||||
unsigned DistancePredicateIndex
|
||||
>
|
||||
class distance_query_incremental
|
||||
: 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::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
|
||||
typedef typename nearest_predicate_access::type nearest_predicate_type;
|
||||
typedef typename indexable_type<Translator>::type indexable_type;
|
||||
|
||||
typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
|
||||
typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> calculate_node_distance;
|
||||
typedef typename calculate_value_distance::result_type value_distance_type;
|
||||
typedef typename calculate_node_distance::result_type node_distance_type;
|
||||
|
||||
typedef typename Allocators::size_type size_type;
|
||||
typedef typename Allocators::const_reference const_reference;
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
|
||||
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type internal_elements;
|
||||
typedef typename internal_elements::const_iterator internal_iterator;
|
||||
typedef typename rtree::elements_type<leaf>::type leaf_elements;
|
||||
|
||||
typedef std::pair<node_distance_type, node_pointer> branch_data;
|
||||
typedef typename index::detail::rtree::container_from_elements_type<
|
||||
internal_elements, branch_data
|
||||
>::type active_branch_list_type;
|
||||
struct internal_stack_element
|
||||
{
|
||||
internal_stack_element() : current_branch(0) {}
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
// Required in c++03 for containers using Boost.Move
|
||||
internal_stack_element & operator=(internal_stack_element const& o)
|
||||
{
|
||||
branches = o.branches;
|
||||
current_branch = o.current_branch;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
active_branch_list_type branches;
|
||||
typename active_branch_list_type::size_type current_branch;
|
||||
};
|
||||
typedef std::vector<internal_stack_element> internal_stack_type;
|
||||
|
||||
inline distance_query_incremental()
|
||||
: m_translator(NULL)
|
||||
// , m_pred()
|
||||
, current_neighbor((std::numeric_limits<size_type>::max)())
|
||||
// , next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())
|
||||
{}
|
||||
|
||||
inline distance_query_incremental(Translator const& translator, Predicates const& pred)
|
||||
: m_translator(::boost::addressof(translator))
|
||||
, m_pred(pred)
|
||||
, current_neighbor((std::numeric_limits<size_type>::max)())
|
||||
|
||||
, next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < max_count(), "k must be greather than 0");
|
||||
}
|
||||
|
||||
const_reference dereference() const
|
||||
{
|
||||
return *(neighbors[current_neighbor].second);
|
||||
}
|
||||
|
||||
void initialize(node_pointer root)
|
||||
{
|
||||
rtree::apply_visitor(*this, *root);
|
||||
increment();
|
||||
}
|
||||
|
||||
void increment()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
size_type new_neighbor = current_neighbor == (std::numeric_limits<size_type>::max)() ? 0 : current_neighbor + 1;
|
||||
|
||||
if ( internal_stack.empty() )
|
||||
{
|
||||
if ( new_neighbor < neighbors.size() )
|
||||
current_neighbor = new_neighbor;
|
||||
else
|
||||
{
|
||||
current_neighbor = (std::numeric_limits<size_type>::max)();
|
||||
// clear() is used to disable the condition above
|
||||
neighbors.clear();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
active_branch_list_type & branches = internal_stack.back().branches;
|
||||
typename active_branch_list_type::size_type & current_branch = internal_stack.back().current_branch;
|
||||
|
||||
if ( branches.size() <= current_branch )
|
||||
{
|
||||
internal_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// if there are no nodes which can have closer values, set new value
|
||||
if ( new_neighbor < neighbors.size() &&
|
||||
// here must be < because otherwise neighbours may be sorted in different order
|
||||
// if there is another value with equal distance
|
||||
neighbors[new_neighbor].first < next_closest_node_distance )
|
||||
{
|
||||
current_neighbor = new_neighbor;
|
||||
return;
|
||||
}
|
||||
|
||||
// if node is further than the furthest neighbour, following nodes also will be further
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(neighbors.size() <= max_count(), "unexpected neighbours count");
|
||||
if ( max_count() <= neighbors.size() &&
|
||||
is_node_prunable(neighbors.back().first, branches[current_branch].first) )
|
||||
{
|
||||
// stop traversing current level
|
||||
internal_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// new level - must increment current_branch before traversing of another level (mem reallocation)
|
||||
++current_branch;
|
||||
rtree::apply_visitor(*this, *(branches[current_branch - 1].second));
|
||||
|
||||
next_closest_node_distance = calc_closest_node_distance(internal_stack.begin(), internal_stack.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_end() const
|
||||
{
|
||||
return (std::numeric_limits<size_type>::max)() == current_neighbor;
|
||||
}
|
||||
|
||||
friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(l.current_neighbor != r.current_neighbor ||
|
||||
(std::numeric_limits<size_type>::max)() == l.current_neighbor ||
|
||||
(std::numeric_limits<size_type>::max)() == r.current_neighbor ||
|
||||
l.neighbors[l.current_neighbor].second == r.neighbors[r.current_neighbor].second,
|
||||
"not corresponding iterators");
|
||||
return l.current_neighbor == r.current_neighbor;
|
||||
}
|
||||
|
||||
// Put node's elements into the list of active branches if those elements meets predicates
|
||||
// and distance predicates(currently not used)
|
||||
// and aren't further than found neighbours (if there is enough neighbours)
|
||||
inline void operator()(internal_node const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// add new element
|
||||
internal_stack.resize(internal_stack.size()+1);
|
||||
|
||||
// fill active branch list 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_distance_type node_distance;
|
||||
// if distance isn't ok - move to the next node
|
||||
if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if current node is further than found neighbors - don't analyze it
|
||||
if ( max_count() <= neighbors.size() &&
|
||||
is_node_prunable(neighbors.back().first, node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// add current node's data into the list
|
||||
internal_stack.back().branches.push_back( std::make_pair(node_distance, it->second) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( internal_stack.back().branches.empty() )
|
||||
internal_stack.pop_back();
|
||||
else
|
||||
// sort array
|
||||
std::sort(internal_stack.back().branches.begin(), internal_stack.back().branches.end(), abl_less);
|
||||
}
|
||||
|
||||
// Put values into the list of neighbours if those values meets predicates
|
||||
// and distance predicates(currently not used)
|
||||
// and aren't further than already found neighbours (if there is enough neighbours)
|
||||
inline void operator()(leaf const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<leaf>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// store distance to the furthest neighbour
|
||||
bool not_enough_neighbors = neighbors.size() < max_count();
|
||||
value_distance_type greatest_distance = !not_enough_neighbors ? neighbors.back().first : (std::numeric_limits<value_distance_type>::max)();
|
||||
|
||||
// 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_distance_type value_distance;
|
||||
// if distance is ok
|
||||
if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it), value_distance) )
|
||||
{
|
||||
// if there is not enough values or current value is closer than furthest neighbour
|
||||
if ( not_enough_neighbors || value_distance < greatest_distance )
|
||||
{
|
||||
neighbors.push_back(std::make_pair(value_distance, boost::addressof(*it)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort array
|
||||
std::sort(neighbors.begin(), neighbors.end(), neighbors_less);
|
||||
// remove furthest values
|
||||
if ( max_count() < neighbors.size() )
|
||||
neighbors.resize(max_count());
|
||||
}
|
||||
|
||||
private:
|
||||
static inline bool abl_less(std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
|
||||
std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
|
||||
{
|
||||
return p1.first < p2.first;
|
||||
}
|
||||
|
||||
static inline bool neighbors_less(std::pair<value_distance_type, const Value *> const& p1,
|
||||
std::pair<value_distance_type, const Value *> const& p2)
|
||||
{
|
||||
return p1.first < p2.first;
|
||||
}
|
||||
|
||||
node_distance_type
|
||||
calc_closest_node_distance(typename internal_stack_type::const_iterator first,
|
||||
typename internal_stack_type::const_iterator last)
|
||||
{
|
||||
node_distance_type result = (std::numeric_limits<node_distance_type>::max)();
|
||||
for ( ; first != last ; ++first )
|
||||
{
|
||||
if ( first->branches.size() <= first->current_branch )
|
||||
continue;
|
||||
|
||||
node_distance_type curr_dist = first->branches[first->current_branch].first;
|
||||
if ( curr_dist < result )
|
||||
result = curr_dist;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)
|
||||
{
|
||||
return greatest_dist <= d;
|
||||
}
|
||||
|
||||
inline unsigned max_count() const
|
||||
{
|
||||
return nearest_predicate_access::get(m_pred).count;
|
||||
}
|
||||
|
||||
nearest_predicate_type const& predicate() const
|
||||
{
|
||||
return nearest_predicate_access::get(m_pred);
|
||||
}
|
||||
|
||||
const Translator * m_translator;
|
||||
|
||||
Predicates m_pred;
|
||||
|
||||
internal_stack_type internal_stack;
|
||||
std::vector< std::pair<value_distance_type, const Value *> > neighbors;
|
||||
size_type current_neighbor;
|
||||
node_distance_type next_closest_node_distance;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
|
||||
+573
@@ -0,0 +1,573 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree inserting visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
|
||||
#include <boost/geometry/util/condition.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::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
|
||||
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 destroyer for automatic destruction on exception
|
||||
subtree_destroyer 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, typename SizeType>
|
||||
struct insert_traverse_data
|
||||
{
|
||||
typedef typename rtree::elements_type<InternalNode>::type elements_type;
|
||||
typedef typename elements_type::value_type element_type;
|
||||
typedef typename elements_type::size_type elements_size_type;
|
||||
typedef SizeType size_type;
|
||||
|
||||
insert_traverse_data()
|
||||
: parent(0), current_child_index(0), current_level(0)
|
||||
{}
|
||||
|
||||
void move_to_next_level(InternalNodePtr new_parent,
|
||||
elements_size_type 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;
|
||||
elements_size_type current_child_index;
|
||||
size_type 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::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
//typedef typename Allocators::internal_node_pointer internal_node_pointer;
|
||||
typedef internal_node * internal_node_pointer;
|
||||
|
||||
inline insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Element const& element,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level = 0
|
||||
)
|
||||
: m_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
|
||||
|
||||
// When a value is inserted, during the tree traversal bounds of nodes
|
||||
// on a path from the root to a leaf must be expanded. So prepare
|
||||
// a bounding object at the beginning to not do it later for each node.
|
||||
// NOTE: This is actually only needed because conditionally the bounding
|
||||
// object may be expanded below. Otherwise the indexable could be
|
||||
// directly used instead
|
||||
index::detail::bounds(rtree::element_indexable(m_element, m_translator), m_element_bounds);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
|
||||
// Enlarge it in case if it's not bounding geometry type.
|
||||
// It's because Points and Segments are compared WRT machine epsilon
|
||||
// This ensures that leafs bounds correspond to the stored elements
|
||||
if (BOOST_GEOMETRY_CONDITION((
|
||||
boost::is_same<Element, Value>::value
|
||||
&& ! index::detail::is_bounding_geometry
|
||||
<
|
||||
typename indexable_type<Translator>::type
|
||||
>::value )) )
|
||||
{
|
||||
geometry::detail::expand_by_epsilon(m_element_bounds);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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,
|
||||
m_element_bounds
|
||||
/*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() )
|
||||
{
|
||||
// NOTE: If the exception is thrown current node may contain more than MAX elements or be empty.
|
||||
// Furthermore it may be empty root - internal node.
|
||||
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, size_type>
|
||||
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
|
||||
subtree_destroyer additional_node_ptr(additional_nodes[0].second, m_allocators);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
|
||||
// Enlarge bounds of a leaf node.
|
||||
// It's because Points and Segments are compared WRT machine epsilon
|
||||
// This ensures that leafs' bounds correspond to the stored elements.
|
||||
if (BOOST_GEOMETRY_CONDITION((
|
||||
boost::is_same<Node, leaf>::value
|
||||
&& ! index::detail::is_bounding_geometry
|
||||
<
|
||||
typename indexable_type<Translator>::type
|
||||
>::value )))
|
||||
{
|
||||
geometry::detail::expand_by_epsilon(n_box);
|
||||
geometry::detail::expand_by_epsilon(additional_nodes[0].first);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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
|
||||
subtree_destroyer new_root(rtree::create_node<Allocators, internal_node>::apply(m_allocators), m_allocators); // MAY THROW, STRONG (N:alloc)
|
||||
|
||||
BOOST_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)
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
// clear new root to not delete in the ~subtree_destroyer() potentially stored old root node
|
||||
rtree::elements(rtree::get<internal_node>(*new_root)).clear();
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
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;
|
||||
Box m_element_bounds;
|
||||
parameters_type const& m_parameters;
|
||||
Translator const& m_translator;
|
||||
size_type const m_relative_level;
|
||||
size_type const m_level;
|
||||
|
||||
node_pointer & m_root_node;
|
||||
size_type & m_leafs_level;
|
||||
|
||||
// traversing input parameters
|
||||
insert_traverse_data<internal_node, internal_node_pointer, size_type> 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;
|
||||
typedef typename base::size_type size_type;
|
||||
|
||||
inline insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Element const& element,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type relative_level = 0
|
||||
)
|
||||
: 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");
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
// push new child node
|
||||
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
|
||||
}
|
||||
BOOST_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);
|
||||
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
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;
|
||||
typedef typename base::size_type size_type;
|
||||
|
||||
inline insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Value const& value,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators,
|
||||
size_type 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
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree leaf node checking visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_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;
|
||||
|
||||
is_leaf()
|
||||
: result(false)
|
||||
{}
|
||||
|
||||
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
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree iterator visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_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 iterator
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::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::size_type size_type;
|
||||
typedef typename Allocators::const_reference const_reference;
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;
|
||||
typedef typename rtree::elements_type<leaf>::type leaf_elements;
|
||||
typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;
|
||||
|
||||
inline iterator()
|
||||
: m_values(NULL)
|
||||
, m_current()
|
||||
{}
|
||||
|
||||
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_internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));
|
||||
}
|
||||
|
||||
inline void operator()(leaf const& n)
|
||||
{
|
||||
m_values = ::boost::addressof(rtree::elements(n));
|
||||
m_current = rtree::elements(n).begin();
|
||||
}
|
||||
|
||||
const_reference dereference() const
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(m_values, "not dereferencable");
|
||||
return *m_current;
|
||||
}
|
||||
|
||||
void initialize(node_pointer root)
|
||||
{
|
||||
rtree::apply_visitor(*this, *root);
|
||||
search_value();
|
||||
}
|
||||
|
||||
void increment()
|
||||
{
|
||||
++m_current;
|
||||
search_value();
|
||||
}
|
||||
|
||||
void search_value()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// if leaf is choosen, move to the next value in leaf
|
||||
if ( m_values )
|
||||
{
|
||||
// there are more values in the current leaf
|
||||
if ( m_current != m_values->end() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
// no more values, clear current leaf
|
||||
else
|
||||
{
|
||||
m_values = 0;
|
||||
}
|
||||
}
|
||||
// if leaf isn't choosen, move to the next leaf
|
||||
else
|
||||
{
|
||||
// return if there is no more nodes to traverse
|
||||
if ( m_internal_stack.empty() )
|
||||
return;
|
||||
|
||||
// no more children in current node, remove it from stack
|
||||
if ( m_internal_stack.back().first == m_internal_stack.back().second )
|
||||
{
|
||||
m_internal_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
internal_iterator it = m_internal_stack.back().first;
|
||||
++m_internal_stack.back().first;
|
||||
|
||||
// push the next node to the stack
|
||||
rtree::apply_visitor(*this, *(it->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_end() const
|
||||
{
|
||||
return 0 == m_values;
|
||||
}
|
||||
|
||||
friend bool operator==(iterator const& l, iterator const& r)
|
||||
{
|
||||
return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;
|
||||
const leaf_elements * m_values;
|
||||
leaf_iterator m_current;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
|
||||
+344
@@ -0,0 +1,344 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree removing visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_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::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type::size_type internal_size_type;
|
||||
|
||||
//typedef typename Allocators::internal_node_pointer internal_node_pointer;
|
||||
typedef internal_node * internal_node_pointer;
|
||||
|
||||
public:
|
||||
inline remove(node_pointer & root,
|
||||
size_type & 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
|
||||
internal_size_type child_node_index = 0;
|
||||
for ( ; child_node_index < children.size() ; ++child_node_index )
|
||||
{
|
||||
if ( geometry::covered_by(
|
||||
return_ref_or_bounds(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_type 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
|
||||
// NOTE: if the min elements number is 1, then after an underflow
|
||||
// here the child elements count is 0, so it's not required to store this node,
|
||||
// it could just be destroyed
|
||||
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
|
||||
// NOTE: if the min elements number is 1, then after underflow
|
||||
// here the number of elements may be equal to 0
|
||||
// this can occur only for the last removed element
|
||||
if ( rtree::elements(n).size() <= 1 )
|
||||
{
|
||||
node_pointer root_to_destroy = m_root_node;
|
||||
if ( rtree::elements(n).size() == 0 )
|
||||
m_root_node = 0;
|
||||
else
|
||||
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 )
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_parameters.get_min_elements(), "min number of elements is too small");
|
||||
|
||||
// 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::values_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_type, node_pointer> > UnderflowNodes;
|
||||
|
||||
void traverse_apply_visitor(internal_node &n, internal_size_type choosen_node_index)
|
||||
{
|
||||
// save previous traverse inputs and set new ones
|
||||
internal_node_pointer parent_bckup = m_parent;
|
||||
internal_size_type current_child_index_bckup = m_current_child_index;
|
||||
size_type 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_type 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)
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
// NOTE: those are elements of the internal node which means that copy/move shouldn't throw
|
||||
// Though it's safer in case if the pointer type could throw in copy ctor.
|
||||
// In the future this try-catch block could be removed.
|
||||
rtree::move_from_back(elements, underfl_el_it); // MAY THROW (E: copy)
|
||||
elements.pop_back();
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
m_underflowed_nodes.pop_back();
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
// calc underflow
|
||||
return elements.size() < m_parameters.get_min_elements();
|
||||
}
|
||||
|
||||
static inline bool is_leaf(node const& n)
|
||||
{
|
||||
visitors::is_leaf<Value, Options, Box, Allocators> ilv;
|
||||
rtree::apply_visitor(ilv, n);
|
||||
return ilv.result;
|
||||
}
|
||||
|
||||
void reinsert_removed_nodes_elements()
|
||||
{
|
||||
typename UnderflowNodes::reverse_iterator it = m_underflowed_nodes.rbegin();
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
// reinsert elements from removed nodes
|
||||
// begin with levels closer to the root
|
||||
for ( ; it != m_underflowed_nodes.rend() ; ++it )
|
||||
{
|
||||
// it->first is an index of a level of a node, not children
|
||||
// counted from the leafs level
|
||||
bool const node_is_leaf = it->first == 1;
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(node_is_leaf == is_leaf(*it->second), "unexpected condition");
|
||||
if ( node_is_leaf )
|
||||
{
|
||||
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();
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
// destroy current and remaining nodes
|
||||
for ( ; it != m_underflowed_nodes.rend() ; ++it )
|
||||
{
|
||||
subtree_destroyer dummy(it->second, m_allocators);
|
||||
}
|
||||
|
||||
//m_underflowed_nodes.clear();
|
||||
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
void reinsert_node_elements(Node &n, size_type 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();
|
||||
BOOST_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)
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
++it;
|
||||
rtree::destroy_elements<Value, Options, Translator, Box, Allocators>
|
||||
::apply(it, elements.end(), m_allocators);
|
||||
elements.clear();
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
Value const& m_value;
|
||||
parameters_type const& m_parameters;
|
||||
Translator const& m_translator;
|
||||
Allocators & m_allocators;
|
||||
|
||||
node_pointer & m_root_node;
|
||||
size_type & m_leafs_level;
|
||||
|
||||
bool m_is_value_removed;
|
||||
UnderflowNodes m_underflowed_nodes;
|
||||
|
||||
// traversing input parameters
|
||||
internal_node_pointer m_parent;
|
||||
internal_size_type m_current_child_index;
|
||||
size_type 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
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree spatial query visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 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;
|
||||
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
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_type found_count;
|
||||
};
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
|
||||
class spatial_query_incremental
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::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::size_type size_type;
|
||||
typedef typename Allocators::const_reference const_reference;
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;
|
||||
typedef typename rtree::elements_type<leaf>::type leaf_elements;
|
||||
typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;
|
||||
|
||||
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
|
||||
inline spatial_query_incremental()
|
||||
: m_translator(NULL)
|
||||
// , m_pred()
|
||||
, m_values(NULL)
|
||||
, m_current()
|
||||
{}
|
||||
|
||||
inline spatial_query_incremental(Translator const& t, Predicates const& p)
|
||||
: m_translator(::boost::addressof(t))
|
||||
, m_pred(p)
|
||||
, m_values(NULL)
|
||||
, m_current()
|
||||
{}
|
||||
|
||||
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_internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));
|
||||
}
|
||||
|
||||
inline void operator()(leaf const& n)
|
||||
{
|
||||
m_values = ::boost::addressof(rtree::elements(n));
|
||||
m_current = rtree::elements(n).begin();
|
||||
}
|
||||
|
||||
const_reference dereference() const
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(m_values, "not dereferencable");
|
||||
return *m_current;
|
||||
}
|
||||
|
||||
void initialize(node_pointer root)
|
||||
{
|
||||
rtree::apply_visitor(*this, *root);
|
||||
search_value();
|
||||
}
|
||||
|
||||
void increment()
|
||||
{
|
||||
++m_current;
|
||||
search_value();
|
||||
}
|
||||
|
||||
void search_value()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// if leaf is choosen, move to the next value in leaf
|
||||
if ( m_values )
|
||||
{
|
||||
if ( m_current != m_values->end() )
|
||||
{
|
||||
// return if next value is found
|
||||
Value const& v = *m_current;
|
||||
if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, v, (*m_translator)(v)) )
|
||||
return;
|
||||
|
||||
++m_current;
|
||||
}
|
||||
// no more values, clear current leaf
|
||||
else
|
||||
{
|
||||
m_values = 0;
|
||||
}
|
||||
}
|
||||
// if leaf isn't choosen, move to the next leaf
|
||||
else
|
||||
{
|
||||
// return if there is no more nodes to traverse
|
||||
if ( m_internal_stack.empty() )
|
||||
return;
|
||||
|
||||
// no more children in current node, remove it from stack
|
||||
if ( m_internal_stack.back().first == m_internal_stack.back().second )
|
||||
{
|
||||
m_internal_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
internal_iterator it = m_internal_stack.back().first;
|
||||
++m_internal_stack.back().first;
|
||||
|
||||
// next node is found, push it to the stack
|
||||
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
|
||||
rtree::apply_visitor(*this, *(it->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_end() const
|
||||
{
|
||||
return 0 == m_values;
|
||||
}
|
||||
|
||||
friend bool operator==(spatial_query_incremental const& l, spatial_query_incremental const& r)
|
||||
{
|
||||
return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const Translator * m_translator;
|
||||
|
||||
Predicates m_pred;
|
||||
|
||||
std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;
|
||||
const leaf_elements * m_values;
|
||||
leaf_iterator m_current;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
|
||||
@@ -0,0 +1,585 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
|
||||
|
||||
//#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
//#include <boost/serialization/nvp.hpp>
|
||||
|
||||
// TODO
|
||||
// how about using the unsigned type capable of storing Max in compile-time versions?
|
||||
|
||||
// TODO
|
||||
// - add wrappers for Point and Box and implement serialize for those wrappers instead of
|
||||
// raw geometries
|
||||
// PROBLEM: after implementing this, how Values would be set?
|
||||
// - store the name of the parameters to know how to load and detect errors
|
||||
// - in the header, once store info about the Indexable and Bounds types (geometry type, point CS, Dim, etc.)
|
||||
// each geometry save without this info
|
||||
|
||||
// TODO - move to index/detail/serialization.hpp
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
// TODO - use boost::move?
|
||||
template<typename T>
|
||||
class serialization_storage
|
||||
{
|
||||
public:
|
||||
template <typename Archive>
|
||||
serialization_storage(Archive & ar, unsigned int version)
|
||||
{
|
||||
boost::serialization::load_construct_data_adl(ar, this->address(), version);
|
||||
}
|
||||
~serialization_storage()
|
||||
{
|
||||
this->address()->~T();
|
||||
}
|
||||
T * address()
|
||||
{
|
||||
return static_cast<T*>(m_storage.address());
|
||||
}
|
||||
private:
|
||||
boost::aligned_storage<sizeof(T), boost::alignment_of<T>::value> m_storage;
|
||||
};
|
||||
|
||||
// TODO - save and load item_version? see: collections_load_imp and collections_save_imp
|
||||
// this should be done once for the whole container
|
||||
// versions of all used types should be stored
|
||||
|
||||
template <typename T, typename Archive> inline
|
||||
T serialization_load(const char * name, Archive & ar)
|
||||
{
|
||||
namespace bs = boost::serialization;
|
||||
serialization_storage<T> storage(ar, bs::version<T>::value); // load_construct_data
|
||||
ar >> boost::serialization::make_nvp(name, *storage.address()); // serialize
|
||||
//ar >> *storage.address(); // serialize
|
||||
return *storage.address();
|
||||
}
|
||||
|
||||
template <typename T, typename Archive> inline
|
||||
void serialization_save(T const& t, const char * name, Archive & ar)
|
||||
{
|
||||
namespace bs = boost::serialization;
|
||||
bs::save_construct_data_adl(ar, boost::addressof(t), bs::version<T>::value); // save_construct_data
|
||||
ar << boost::serialization::make_nvp(name, t); // serialize
|
||||
//ar << t; // serialize
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
// TODO - move to index/serialization/rtree.hpp
|
||||
namespace boost { namespace serialization {
|
||||
|
||||
// boost::geometry::index::linear
|
||||
|
||||
template<class Archive, size_t Max, size_t Min>
|
||||
void save_construct_data(Archive & ar, const boost::geometry::index::linear<Max, Min> * params, unsigned int )
|
||||
{
|
||||
size_t max = params->get_max_elements(), min = params->get_min_elements();
|
||||
ar << boost::serialization::make_nvp("max", max);
|
||||
ar << boost::serialization::make_nvp("min", min);
|
||||
}
|
||||
template<class Archive, size_t Max, size_t Min>
|
||||
void load_construct_data(Archive & ar, boost::geometry::index::linear<Max, Min> * params, unsigned int )
|
||||
{
|
||||
size_t max, min;
|
||||
ar >> boost::serialization::make_nvp("max", max);
|
||||
ar >> boost::serialization::make_nvp("min", min);
|
||||
if ( max != params->get_max_elements() || min != params->get_min_elements() )
|
||||
// TODO change exception type
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
|
||||
// the constructor musn't be called for this type
|
||||
//::new(params)boost::geometry::index::linear<Max, Min>();
|
||||
}
|
||||
template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::linear<Max, Min> &, unsigned int) {}
|
||||
|
||||
// boost::geometry::index::quadratic
|
||||
|
||||
template<class Archive, size_t Max, size_t Min>
|
||||
void save_construct_data(Archive & ar, const boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
|
||||
{
|
||||
size_t max = params->get_max_elements(), min = params->get_min_elements();
|
||||
ar << boost::serialization::make_nvp("max", max);
|
||||
ar << boost::serialization::make_nvp("min", min);
|
||||
}
|
||||
template<class Archive, size_t Max, size_t Min>
|
||||
void load_construct_data(Archive & ar, boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
|
||||
{
|
||||
size_t max, min;
|
||||
ar >> boost::serialization::make_nvp("max", max);
|
||||
ar >> boost::serialization::make_nvp("min", min);
|
||||
if ( max != params->get_max_elements() || min != params->get_min_elements() )
|
||||
// TODO change exception type
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
|
||||
// the constructor musn't be called for this type
|
||||
//::new(params)boost::geometry::index::quadratic<Max, Min>();
|
||||
}
|
||||
template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::quadratic<Max, Min> &, unsigned int) {}
|
||||
|
||||
// boost::geometry::index::rstar
|
||||
|
||||
template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
|
||||
void save_construct_data(Archive & ar, const boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
|
||||
{
|
||||
size_t max = params->get_max_elements()
|
||||
, min = params->get_min_elements()
|
||||
, re = params->get_reinserted_elements()
|
||||
, oct = params->get_overlap_cost_threshold();
|
||||
ar << boost::serialization::make_nvp("max", max);
|
||||
ar << boost::serialization::make_nvp("min", min);
|
||||
ar << boost::serialization::make_nvp("re", re);
|
||||
ar << boost::serialization::make_nvp("oct", oct);
|
||||
}
|
||||
template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
|
||||
void load_construct_data(Archive & ar, boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
|
||||
{
|
||||
size_t max, min, re, oct;
|
||||
ar >> boost::serialization::make_nvp("max", max);
|
||||
ar >> boost::serialization::make_nvp("min", min);
|
||||
ar >> boost::serialization::make_nvp("re", re);
|
||||
ar >> boost::serialization::make_nvp("oct", oct);
|
||||
if ( max != params->get_max_elements() || min != params->get_min_elements() ||
|
||||
re != params->get_reinserted_elements() || oct != params->get_overlap_cost_threshold() )
|
||||
// TODO change exception type
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
|
||||
// the constructor musn't be called for this type
|
||||
//::new(params)boost::geometry::index::rstar<Max, Min, RE, OCT>();
|
||||
}
|
||||
template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
|
||||
void serialize(Archive &, boost::geometry::index::rstar<Max, Min, RE, OCT> &, unsigned int) {}
|
||||
|
||||
// boost::geometry::index::dynamic_linear
|
||||
|
||||
template<class Archive>
|
||||
inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_linear * params, unsigned int )
|
||||
{
|
||||
size_t max = params->get_max_elements(), min = params->get_min_elements();
|
||||
ar << boost::serialization::make_nvp("max", max);
|
||||
ar << boost::serialization::make_nvp("min", min);
|
||||
}
|
||||
template<class Archive>
|
||||
inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_linear * params, unsigned int )
|
||||
{
|
||||
size_t max, min;
|
||||
ar >> boost::serialization::make_nvp("max", max);
|
||||
ar >> boost::serialization::make_nvp("min", min);
|
||||
::new(params)boost::geometry::index::dynamic_linear(max, min);
|
||||
}
|
||||
template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_linear &, unsigned int) {}
|
||||
|
||||
// boost::geometry::index::dynamic_quadratic
|
||||
|
||||
template<class Archive>
|
||||
inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_quadratic * params, unsigned int )
|
||||
{
|
||||
size_t max = params->get_max_elements(), min = params->get_min_elements();
|
||||
ar << boost::serialization::make_nvp("max", max);
|
||||
ar << boost::serialization::make_nvp("min", min);
|
||||
}
|
||||
template<class Archive>
|
||||
inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_quadratic * params, unsigned int )
|
||||
{
|
||||
size_t max, min;
|
||||
ar >> boost::serialization::make_nvp("max", max);
|
||||
ar >> boost::serialization::make_nvp("min", min);
|
||||
::new(params)boost::geometry::index::dynamic_quadratic(max, min);
|
||||
}
|
||||
template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_quadratic &, unsigned int) {}
|
||||
|
||||
// boost::geometry::index::dynamic_rstar
|
||||
|
||||
template<class Archive>
|
||||
inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_rstar * params, unsigned int )
|
||||
{
|
||||
size_t max = params->get_max_elements()
|
||||
, min = params->get_min_elements()
|
||||
, re = params->get_reinserted_elements()
|
||||
, oct = params->get_overlap_cost_threshold();
|
||||
ar << boost::serialization::make_nvp("max", max);
|
||||
ar << boost::serialization::make_nvp("min", min);
|
||||
ar << boost::serialization::make_nvp("re", re);
|
||||
ar << boost::serialization::make_nvp("oct", oct);
|
||||
}
|
||||
template<class Archive>
|
||||
inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_rstar * params, unsigned int )
|
||||
{
|
||||
size_t max, min, re, oct;
|
||||
ar >> boost::serialization::make_nvp("max", max);
|
||||
ar >> boost::serialization::make_nvp("min", min);
|
||||
ar >> boost::serialization::make_nvp("re", re);
|
||||
ar >> boost::serialization::make_nvp("oct", oct);
|
||||
::new(params)boost::geometry::index::dynamic_rstar(max, min, re, oct);
|
||||
}
|
||||
template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_rstar &, unsigned int) {}
|
||||
|
||||
}} // boost::serialization
|
||||
|
||||
// TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
template <typename P, size_t I = 0, size_t D = geometry::dimension<P>::value>
|
||||
struct serialize_point
|
||||
{
|
||||
template <typename Archive>
|
||||
static inline void save(Archive & ar, P const& p, unsigned int version)
|
||||
{
|
||||
typename coordinate_type<P>::type c = get<I>(p);
|
||||
ar << boost::serialization::make_nvp("c", c);
|
||||
serialize_point<P, I+1, D>::save(ar, p, version);
|
||||
}
|
||||
|
||||
template <typename Archive>
|
||||
static inline void load(Archive & ar, P & p, unsigned int version)
|
||||
{
|
||||
typename geometry::coordinate_type<P>::type c;
|
||||
ar >> boost::serialization::make_nvp("c", c);
|
||||
set<I>(p, c);
|
||||
serialize_point<P, I+1, D>::load(ar, p, version);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename P, size_t D>
|
||||
struct serialize_point<P, D, D>
|
||||
{
|
||||
template <typename Archive> static inline void save(Archive &, P const&, unsigned int) {}
|
||||
template <typename Archive> static inline void load(Archive &, P &, unsigned int) {}
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
// TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
|
||||
namespace boost { namespace serialization {
|
||||
|
||||
template<class Archive, typename T, size_t D, typename C>
|
||||
void save(Archive & ar, boost::geometry::model::point<T, D, C> const& p, unsigned int version)
|
||||
{
|
||||
boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::save(ar, p, version);
|
||||
}
|
||||
template<class Archive, typename T, size_t D, typename C>
|
||||
void load(Archive & ar, boost::geometry::model::point<T, D, C> & p, unsigned int version)
|
||||
{
|
||||
boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::load(ar, p, version);
|
||||
}
|
||||
template<class Archive, typename T, size_t D, typename C>
|
||||
inline void serialize(Archive & ar, boost::geometry::model::point<T, D, C> & o, const unsigned int version) { split_free(ar, o, version); }
|
||||
|
||||
template<class Archive, typename P>
|
||||
inline void serialize(Archive & ar, boost::geometry::model::box<P> & b, const unsigned int)
|
||||
{
|
||||
ar & boost::serialization::make_nvp("min", b.min_corner());
|
||||
ar & boost::serialization::make_nvp("max", b.max_corner());
|
||||
}
|
||||
|
||||
}} // boost::serialization
|
||||
|
||||
// TODO - move to index/detail/rtree/visitors/save.hpp
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
// TODO move saving and loading of the rtree outside the rtree, this will require adding some kind of members_view
|
||||
|
||||
template <typename Archive, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class save
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::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;
|
||||
|
||||
save(Archive & archive, unsigned int version)
|
||||
: m_archive(archive), m_version(version)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// CONSIDER: change to elements_type::size_type or size_type
|
||||
// or use fixed-size type like uint32 or even uint16?
|
||||
size_t s = elements.size();
|
||||
m_archive << boost::serialization::make_nvp("s", s);
|
||||
|
||||
for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
|
||||
{
|
||||
serialization_save(it->first, "b", m_archive);
|
||||
|
||||
rtree::apply_visitor(*this, *it->second);
|
||||
}
|
||||
}
|
||||
|
||||
inline void operator()(leaf const& l)
|
||||
{
|
||||
typedef typename rtree::elements_type<leaf>::type elements_type;
|
||||
//typedef typename elements_type::size_type elements_size;
|
||||
elements_type const& elements = rtree::elements(l);
|
||||
|
||||
// CONSIDER: change to elements_type::size_type or size_type
|
||||
// or use fixed-size type like uint32 or even uint16?
|
||||
size_t s = elements.size();
|
||||
m_archive << boost::serialization::make_nvp("s", s);
|
||||
|
||||
for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
|
||||
{
|
||||
serialization_save(*it, "v", m_archive);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Archive & m_archive;
|
||||
unsigned int m_version;
|
||||
};
|
||||
|
||||
}}}}}} // boost::geometry::index::detail::rtree::visitors
|
||||
|
||||
// TODO - move to index/detail/rtree/load.hpp
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class load
|
||||
{
|
||||
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::node_pointer node_pointer;
|
||||
typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
public:
|
||||
template <typename Archive> inline static
|
||||
node_pointer apply(Archive & ar, unsigned int version, size_type leafs_level, size_type & values_count, parameters_type const& parameters, Translator const& translator, Allocators & allocators)
|
||||
{
|
||||
values_count = 0;
|
||||
return raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Archive> inline static
|
||||
node_pointer raw_apply(Archive & ar, unsigned int version, size_type leafs_level, size_type & values_count, parameters_type const& parameters, Translator const& translator, Allocators & allocators, size_type current_level = 0)
|
||||
{
|
||||
//BOOST_GEOMETRY_INDEX_ASSERT(current_level <= leafs_level, "invalid parameter");
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
typedef typename elements_type::value_type element_type;
|
||||
//typedef typename elements_type::size_type elements_size;
|
||||
|
||||
// CONSIDER: change to elements_type::size_type or size_type
|
||||
// or use fixed-size type like uint32 or even uint16?
|
||||
size_t elements_count;
|
||||
ar >> boost::serialization::make_nvp("s", elements_count);
|
||||
|
||||
if ( elements_count < parameters.get_min_elements() || parameters.get_max_elements() < elements_count )
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("rtree loading error"));
|
||||
|
||||
if ( current_level < leafs_level )
|
||||
{
|
||||
node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A)
|
||||
subtree_destroyer auto_remover(n, allocators);
|
||||
internal_node & in = rtree::get<internal_node>(*n);
|
||||
|
||||
elements_type & elements = rtree::elements(in);
|
||||
|
||||
elements.reserve(elements_count); // MAY THROW (A)
|
||||
|
||||
for ( size_t i = 0 ; i < elements_count ; ++i )
|
||||
{
|
||||
typedef typename elements_type::value_type::first_type box_type;
|
||||
box_type b = serialization_load<box_type>("b", ar);
|
||||
node_pointer n = raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators, current_level+1); // recursive call
|
||||
elements.push_back(element_type(b, n));
|
||||
}
|
||||
|
||||
auto_remover.release();
|
||||
return n;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(current_level == leafs_level, "unexpected value");
|
||||
|
||||
node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A)
|
||||
subtree_destroyer auto_remover(n, allocators);
|
||||
leaf & l = rtree::get<leaf>(*n);
|
||||
|
||||
typedef typename rtree::elements_type<leaf>::type elements_type;
|
||||
typedef typename elements_type::value_type element_type;
|
||||
elements_type & elements = rtree::elements(l);
|
||||
|
||||
values_count += elements_count;
|
||||
|
||||
elements.reserve(elements_count); // MAY THROW (A)
|
||||
|
||||
for ( size_t i = 0 ; i < elements_count ; ++i )
|
||||
{
|
||||
element_type el = serialization_load<element_type>("v", ar); // MAY THROW (C)
|
||||
elements.push_back(el); // MAY THROW (C)
|
||||
}
|
||||
|
||||
auto_remover.release();
|
||||
return n;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}}}}} // boost::geometry::index::detail::rtree
|
||||
|
||||
// TODO - move to index/detail/rtree/private_view.hpp
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
|
||||
|
||||
template <typename Rtree>
|
||||
class const_private_view
|
||||
{
|
||||
public:
|
||||
typedef typename Rtree::size_type size_type;
|
||||
|
||||
typedef typename Rtree::translator_type translator_type;
|
||||
typedef typename Rtree::value_type value_type;
|
||||
typedef typename Rtree::options_type options_type;
|
||||
typedef typename Rtree::box_type box_type;
|
||||
typedef typename Rtree::allocators_type allocators_type;
|
||||
|
||||
const_private_view(Rtree const& rt) : m_rtree(rt) {}
|
||||
|
||||
typedef typename Rtree::members_holder members_holder;
|
||||
|
||||
members_holder const& members() const { return m_rtree.m_members; }
|
||||
|
||||
private:
|
||||
const_private_view(const_private_view const&);
|
||||
const_private_view & operator=(const_private_view const&);
|
||||
|
||||
Rtree const& m_rtree;
|
||||
};
|
||||
|
||||
template <typename Rtree>
|
||||
class private_view
|
||||
{
|
||||
public:
|
||||
typedef typename Rtree::size_type size_type;
|
||||
|
||||
typedef typename Rtree::translator_type translator_type;
|
||||
typedef typename Rtree::value_type value_type;
|
||||
typedef typename Rtree::options_type options_type;
|
||||
typedef typename Rtree::box_type box_type;
|
||||
typedef typename Rtree::allocators_type allocators_type;
|
||||
|
||||
private_view(Rtree & rt) : m_rtree(rt) {}
|
||||
|
||||
typedef typename Rtree::members_holder members_holder;
|
||||
|
||||
members_holder & members() { return m_rtree.m_members; }
|
||||
members_holder const& members() const { return m_rtree.m_members; }
|
||||
|
||||
private:
|
||||
private_view(private_view const&);
|
||||
private_view & operator=(private_view const&);
|
||||
|
||||
Rtree & m_rtree;
|
||||
};
|
||||
|
||||
}}}}} // namespace boost::geometry::index::detail::rtree
|
||||
|
||||
// TODO - move to index/serialization/rtree.hpp
|
||||
namespace boost { namespace serialization {
|
||||
|
||||
template<class Archive, typename V, typename P, typename I, typename E, typename A>
|
||||
void save(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
|
||||
{
|
||||
namespace detail = boost::geometry::index::detail;
|
||||
|
||||
typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
|
||||
typedef detail::rtree::const_private_view<rtree> view;
|
||||
typedef typename view::translator_type translator_type;
|
||||
typedef typename view::value_type value_type;
|
||||
typedef typename view::options_type options_type;
|
||||
typedef typename view::box_type box_type;
|
||||
typedef typename view::allocators_type allocators_type;
|
||||
|
||||
view tree(rt);
|
||||
|
||||
detail::serialization_save(tree.members().parameters(), "parameters", ar);
|
||||
|
||||
ar << boost::serialization::make_nvp("values_count", tree.members().values_count);
|
||||
ar << boost::serialization::make_nvp("leafs_level", tree.members().leafs_level);
|
||||
|
||||
if ( tree.members().values_count )
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(tree.members().root, "root shouldn't be null_ptr");
|
||||
|
||||
detail::rtree::visitors::save<Archive, value_type, options_type, translator_type, box_type, allocators_type> save_v(ar, version);
|
||||
detail::rtree::apply_visitor(save_v, *tree.members().root);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive, typename V, typename P, typename I, typename E, typename A>
|
||||
void load(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
|
||||
{
|
||||
namespace detail = boost::geometry::index::detail;
|
||||
|
||||
typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
|
||||
typedef detail::rtree::private_view<rtree> view;
|
||||
typedef typename view::size_type size_type;
|
||||
typedef typename view::translator_type translator_type;
|
||||
typedef typename view::value_type value_type;
|
||||
typedef typename view::options_type options_type;
|
||||
typedef typename view::box_type box_type;
|
||||
typedef typename view::allocators_type allocators_type;
|
||||
|
||||
typedef typename options_type::parameters_type parameters_type;
|
||||
typedef typename allocators_type::node_pointer node_pointer;
|
||||
typedef detail::rtree::subtree_destroyer<value_type, options_type, translator_type, box_type, allocators_type> subtree_destroyer;
|
||||
|
||||
view tree(rt);
|
||||
|
||||
parameters_type params = detail::serialization_load<parameters_type>("parameters", ar);
|
||||
|
||||
size_type values_count, leafs_level;
|
||||
ar >> boost::serialization::make_nvp("values_count", values_count);
|
||||
ar >> boost::serialization::make_nvp("leafs_level", leafs_level);
|
||||
|
||||
node_pointer n(0);
|
||||
if ( 0 < values_count )
|
||||
{
|
||||
size_type loaded_values_count = 0;
|
||||
n = detail::rtree::load<value_type, options_type, translator_type, box_type, allocators_type>
|
||||
::apply(ar, version, leafs_level, loaded_values_count, params, tree.members().translator(), tree.members().allocators()); // MAY THROW
|
||||
|
||||
subtree_destroyer remover(n, tree.members().allocators());
|
||||
if ( loaded_values_count != values_count )
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("unexpected number of values")); // TODO change exception type
|
||||
remover.release();
|
||||
}
|
||||
|
||||
tree.members().parameters() = params;
|
||||
tree.members().values_count = values_count;
|
||||
tree.members().leafs_level = leafs_level;
|
||||
|
||||
subtree_destroyer remover(tree.members().root, tree.members().allocators());
|
||||
tree.members().root = n;
|
||||
}
|
||||
|
||||
template<class Archive, typename V, typename P, typename I, typename E, typename A> inline
|
||||
void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
|
||||
{
|
||||
split_free(ar, rt, version);
|
||||
}
|
||||
|
||||
template<class Archive, typename V, typename P, typename I, typename E, typename A> inline
|
||||
void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
|
||||
{
|
||||
split_free(ar, rt, version);
|
||||
}
|
||||
|
||||
}} // boost::serialization
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,204 @@
|
||||
// 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 = 0,
|
||||
size_t N = boost::tuples::length<Tuple>::value>
|
||||
struct push_back
|
||||
{
|
||||
typedef
|
||||
boost::tuples::cons<
|
||||
typename boost::tuples::element<I, Tuple>::type,
|
||||
typename push_back<Tuple, T, I+1, N>::type
|
||||
> type;
|
||||
|
||||
static type apply(Tuple const& tup, T const& t)
|
||||
{
|
||||
return
|
||||
type(
|
||||
boost::get<I>(tup),
|
||||
push_back<Tuple, T, I+1, N>::apply(tup, t)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Tuple, typename T, size_t N>
|
||||
struct push_back<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
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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/swap.hpp>
|
||||
//#include <boost/type_traits/is_empty.hpp>
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
template<class T>
|
||||
static inline void assign_cond(T & l, T const& r, boost::mpl::bool_<true> const&)
|
||||
{
|
||||
l = r;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static inline void assign_cond(T &, T const&, boost::mpl::bool_<false> const&) {}
|
||||
|
||||
template<class T>
|
||||
static inline void move_cond(T & l, T & r, boost::mpl::bool_<true> const&)
|
||||
{
|
||||
l = ::boost::move(r);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static inline void move_cond(T &, T &, boost::mpl::bool_<false> const&) {}
|
||||
|
||||
template <typename T> inline
|
||||
void swap_cond(T & l, T & r, boost::mpl::bool_<true> const&)
|
||||
{
|
||||
::boost::swap(l, r);
|
||||
}
|
||||
|
||||
template <typename T> inline
|
||||
void swap_cond(T &, T &, boost::mpl::bool_<false> const&) {}
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,760 @@
|
||||
// Boost.Geometry
|
||||
//
|
||||
// varray details
|
||||
//
|
||||
// Copyright (c) 2012-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2011-2013 Andrew Hundt.
|
||||
//
|
||||
// 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_DETAIL_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/remove_reference.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/type_traits/has_trivial_move_constructor.hpp>
|
||||
#include <boost/type_traits/has_trivial_move_assign.hpp>
|
||||
//#include <boost/type_traits/has_nothrow_constructor.hpp>
|
||||
//#include <boost/type_traits/has_nothrow_copy.hpp>
|
||||
//#include <boost/type_traits/has_nothrow_assign.hpp>
|
||||
//#include <boost/type_traits/has_nothrow_destructor.hpp>
|
||||
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
|
||||
// TODO - move vectors iterators optimization to the other, optional file instead of checking defines?
|
||||
|
||||
#if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
|
||||
#include <vector>
|
||||
#include <boost/container/vector.hpp>
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace varray_detail {
|
||||
|
||||
template <typename I>
|
||||
struct are_elements_contiguous : boost::is_pointer<I>
|
||||
{};
|
||||
|
||||
// EXPERIMENTAL - not finished
|
||||
// Conditional setup - mark vector iterators defined in known implementations
|
||||
// as iterators pointing to contiguous ranges
|
||||
|
||||
#if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
|
||||
|
||||
template <typename Pointer>
|
||||
struct are_elements_contiguous<
|
||||
boost::container::container_detail::vector_const_iterator<Pointer>
|
||||
> : boost::true_type
|
||||
{};
|
||||
|
||||
template <typename Pointer>
|
||||
struct are_elements_contiguous<
|
||||
boost::container::container_detail::vector_iterator<Pointer>
|
||||
> : boost::true_type
|
||||
{};
|
||||
|
||||
#if defined(BOOST_DINKUMWARE_STDLIB)
|
||||
|
||||
template <typename T>
|
||||
struct are_elements_contiguous<
|
||||
std::_Vector_const_iterator<T>
|
||||
> : boost::true_type
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
struct are_elements_contiguous<
|
||||
std::_Vector_iterator<T>
|
||||
> : boost::true_type
|
||||
{};
|
||||
|
||||
#elif defined(BOOST_GNU_STDLIB)
|
||||
|
||||
template <typename P, typename T, typename A>
|
||||
struct are_elements_contiguous<
|
||||
__gnu_cxx::__normal_iterator<P, std::vector<T, A> >
|
||||
> : boost::true_type
|
||||
{};
|
||||
|
||||
#elif defined(_LIBCPP_VERSION)
|
||||
|
||||
// TODO - test it first
|
||||
//template <typename P>
|
||||
//struct are_elements_contiguous<
|
||||
// __wrap_iter<P>
|
||||
//> : boost::true_type
|
||||
//{};
|
||||
|
||||
#else // OTHER_STDLIB
|
||||
|
||||
// TODO - add other iterators implementations
|
||||
|
||||
#endif // STDLIB
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
|
||||
|
||||
// True if iterator values are the same and both iterators points to the ranges of contiguous elements
|
||||
|
||||
template <typename I, typename O>
|
||||
struct are_corresponding :
|
||||
::boost::mpl::and_<
|
||||
::boost::is_same<
|
||||
::boost::remove_const<
|
||||
typename ::boost::iterator_value<I>::type
|
||||
>,
|
||||
::boost::remove_const<
|
||||
typename ::boost::iterator_value<O>::type
|
||||
>
|
||||
>,
|
||||
are_elements_contiguous<I>,
|
||||
are_elements_contiguous<O>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename I, typename V>
|
||||
struct is_corresponding_value :
|
||||
::boost::is_same<
|
||||
::boost::remove_const<
|
||||
typename ::boost::iterator_value<I>::type
|
||||
>,
|
||||
::boost::remove_const<V>
|
||||
>
|
||||
{};
|
||||
|
||||
// destroy(I, I)
|
||||
|
||||
template <typename I>
|
||||
void destroy_dispatch(I /*first*/, I /*last*/,
|
||||
boost::true_type const& /*has_trivial_destructor*/)
|
||||
{}
|
||||
|
||||
template <typename I>
|
||||
void destroy_dispatch(I first, I last,
|
||||
boost::false_type const& /*has_trivial_destructor*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
for ( ; first != last ; ++first )
|
||||
first->~value_type();
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
void destroy(I first, I last)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
destroy_dispatch(first, last, has_trivial_destructor<value_type>());
|
||||
}
|
||||
|
||||
// destroy(I)
|
||||
|
||||
template <typename I>
|
||||
void destroy_dispatch(I /*pos*/,
|
||||
boost::true_type const& /*has_trivial_destructor*/)
|
||||
{}
|
||||
|
||||
template <typename I>
|
||||
void destroy_dispatch(I pos,
|
||||
boost::false_type const& /*has_trivial_destructor*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
pos->~value_type();
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
void destroy(I pos)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
destroy_dispatch(pos, has_trivial_destructor<value_type>());
|
||||
}
|
||||
|
||||
// copy(I, I, O)
|
||||
|
||||
template <typename I, typename O>
|
||||
inline O copy_dispatch(I first, I last, O dst,
|
||||
boost::mpl::bool_<true> const& /*use_memmove*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
typename boost::iterator_difference<I>::type d = std::distance(first, last);
|
||||
|
||||
::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
|
||||
return dst + d;
|
||||
}
|
||||
|
||||
template <typename I, typename O>
|
||||
inline O copy_dispatch(I first, I last, O dst,
|
||||
boost::mpl::bool_<false> const& /*use_memmove*/)
|
||||
{
|
||||
return std::copy(first, last, dst); // may throw
|
||||
}
|
||||
|
||||
template <typename I, typename O>
|
||||
inline O copy(I first, I last, O dst)
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::and_<
|
||||
are_corresponding<I, O>,
|
||||
::boost::has_trivial_assign<
|
||||
typename ::boost::iterator_value<O>::type
|
||||
>
|
||||
>::type
|
||||
use_memmove;
|
||||
|
||||
return copy_dispatch(first, last, dst, use_memmove()); // may throw
|
||||
}
|
||||
|
||||
// uninitialized_copy(I, I, O)
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O uninitialized_copy_dispatch(I first, I last, O dst,
|
||||
boost::mpl::bool_<true> const& /*use_memcpy*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
typename boost::iterator_difference<I>::type d = std::distance(first, last);
|
||||
|
||||
::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
|
||||
return dst + d;
|
||||
}
|
||||
|
||||
template <typename I, typename F>
|
||||
inline
|
||||
F uninitialized_copy_dispatch(I first, I last, F dst,
|
||||
boost::mpl::bool_<false> const& /*use_memcpy*/)
|
||||
{
|
||||
return std::uninitialized_copy(first, last, dst); // may throw
|
||||
}
|
||||
|
||||
template <typename I, typename F>
|
||||
inline
|
||||
F uninitialized_copy(I first, I last, F dst)
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::and_<
|
||||
are_corresponding<I, F>,
|
||||
::boost::has_trivial_copy<
|
||||
typename ::boost::iterator_value<F>::type
|
||||
>
|
||||
>::type
|
||||
use_memcpy;
|
||||
|
||||
return uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw
|
||||
}
|
||||
|
||||
// uninitialized_move(I, I, O)
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O uninitialized_move_dispatch(I first, I last, O dst,
|
||||
boost::mpl::bool_<true> const& /*use_memcpy*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
typename boost::iterator_difference<I>::type d = std::distance(first, last);
|
||||
|
||||
::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
|
||||
return dst + d;
|
||||
}
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O uninitialized_move_dispatch(I first, I last, O dst,
|
||||
boost::mpl::bool_<false> const& /*use_memcpy*/)
|
||||
{
|
||||
//return boost::uninitialized_move(first, last, dst); // may throw
|
||||
|
||||
O o = dst;
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
typedef typename std::iterator_traits<O>::value_type value_type;
|
||||
for (; first != last; ++first, ++o )
|
||||
new (boost::addressof(*o)) value_type(boost::move(*first));
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
destroy(dst, o);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O uninitialized_move(I first, I last, O dst)
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::and_<
|
||||
are_corresponding<I, O>,
|
||||
::boost::has_trivial_copy<
|
||||
typename ::boost::iterator_value<O>::type
|
||||
>
|
||||
>::type
|
||||
use_memcpy;
|
||||
|
||||
return uninitialized_move_dispatch(first, last, dst, use_memcpy()); // may throw
|
||||
}
|
||||
|
||||
// TODO - move uses memmove - implement 2nd version using memcpy?
|
||||
|
||||
// move(I, I, O)
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O move_dispatch(I first, I last, O dst,
|
||||
boost::mpl::bool_<true> const& /*use_memmove*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
typename boost::iterator_difference<I>::type d = std::distance(first, last);
|
||||
|
||||
::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
|
||||
return dst + d;
|
||||
}
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O move_dispatch(I first, I last, O dst,
|
||||
boost::mpl::bool_<false> const& /*use_memmove*/)
|
||||
{
|
||||
return boost::move(first, last, dst); // may throw
|
||||
}
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O move(I first, I last, O dst)
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::and_<
|
||||
are_corresponding<I, O>,
|
||||
::boost::has_trivial_assign<
|
||||
typename ::boost::iterator_value<O>::type
|
||||
>
|
||||
>::type
|
||||
use_memmove;
|
||||
|
||||
return move_dispatch(first, last, dst, use_memmove()); // may throw
|
||||
}
|
||||
|
||||
// move_backward(BDI, BDI, BDO)
|
||||
|
||||
template <typename BDI, typename BDO>
|
||||
inline
|
||||
BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
|
||||
boost::mpl::bool_<true> const& /*use_memmove*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<BDI>::type value_type;
|
||||
typename boost::iterator_difference<BDI>::type d = std::distance(first, last);
|
||||
|
||||
BDO foo(dst - d);
|
||||
::memmove(boost::addressof(*foo), boost::addressof(*first), sizeof(value_type) * d);
|
||||
return foo;
|
||||
}
|
||||
|
||||
template <typename BDI, typename BDO>
|
||||
inline
|
||||
BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
|
||||
boost::mpl::bool_<false> const& /*use_memmove*/)
|
||||
{
|
||||
return boost::move_backward(first, last, dst); // may throw
|
||||
}
|
||||
|
||||
template <typename BDI, typename BDO>
|
||||
inline
|
||||
BDO move_backward(BDI first, BDI last, BDO dst)
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::and_<
|
||||
are_corresponding<BDI, BDO>,
|
||||
::boost::has_trivial_assign<
|
||||
typename ::boost::iterator_value<BDO>::type
|
||||
>
|
||||
>::type
|
||||
use_memmove;
|
||||
|
||||
return move_backward_dispatch(first, last, dst, use_memmove()); // may throw
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct has_nothrow_move : public
|
||||
::boost::mpl::or_<
|
||||
boost::mpl::bool_<
|
||||
::boost::has_nothrow_move<
|
||||
typename ::boost::remove_const<T>::type
|
||||
>::value
|
||||
>,
|
||||
boost::mpl::bool_<
|
||||
::boost::has_nothrow_move<T>::value
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
// uninitialized_move_if_noexcept(I, I, O)
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/)
|
||||
{ return varray_detail::uninitialized_move(first, last, dst); }
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/)
|
||||
{ return varray_detail::uninitialized_copy(first, last, dst); }
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O uninitialized_move_if_noexcept(I first, I last, O dst)
|
||||
{
|
||||
typedef typename has_nothrow_move<
|
||||
typename ::boost::iterator_value<O>::type
|
||||
>::type use_move;
|
||||
|
||||
return uninitialized_move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
|
||||
}
|
||||
|
||||
// move_if_noexcept(I, I, O)
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/)
|
||||
{ return move(first, last, dst); }
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/)
|
||||
{ return copy(first, last, dst); }
|
||||
|
||||
template <typename I, typename O>
|
||||
inline
|
||||
O move_if_noexcept(I first, I last, O dst)
|
||||
{
|
||||
typedef typename has_nothrow_move<
|
||||
typename ::boost::iterator_value<O>::type
|
||||
>::type use_move;
|
||||
|
||||
return move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
|
||||
}
|
||||
|
||||
// uninitialized_fill(I, I)
|
||||
|
||||
template <typename I>
|
||||
inline
|
||||
void uninitialized_fill_dispatch(I /*first*/, I /*last*/,
|
||||
boost::true_type const& /*has_trivial_constructor*/,
|
||||
boost::true_type const& /*disable_trivial_init*/)
|
||||
{}
|
||||
|
||||
template <typename I>
|
||||
inline
|
||||
void uninitialized_fill_dispatch(I first, I last,
|
||||
boost::true_type const& /*has_trivial_constructor*/,
|
||||
boost::false_type const& /*disable_trivial_init*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
for ( ; first != last ; ++first )
|
||||
new (boost::addressof(*first)) value_type();
|
||||
}
|
||||
|
||||
template <typename I, typename DisableTrivialInit>
|
||||
inline
|
||||
void uninitialized_fill_dispatch(I first, I last,
|
||||
boost::false_type const& /*has_trivial_constructor*/,
|
||||
DisableTrivialInit const& /*not_used*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
I it = first;
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
for ( ; it != last ; ++it )
|
||||
new (boost::addressof(*it)) value_type(); // may throw
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
destroy(first, it);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
template <typename I, typename DisableTrivialInit>
|
||||
inline
|
||||
void uninitialized_fill(I first, I last, DisableTrivialInit const& disable_trivial_init)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type value_type;
|
||||
uninitialized_fill_dispatch(first, last, boost::has_trivial_constructor<value_type>(), disable_trivial_init); // may throw
|
||||
}
|
||||
|
||||
// construct(I)
|
||||
|
||||
template <typename I>
|
||||
inline
|
||||
void construct_dispatch(boost::mpl::bool_<true> const& /*dont_init*/, I /*pos*/)
|
||||
{}
|
||||
|
||||
template <typename I>
|
||||
inline
|
||||
void construct_dispatch(boost::mpl::bool_<false> const& /*dont_init*/, I pos)
|
||||
{
|
||||
typedef typename ::boost::iterator_value<I>::type value_type;
|
||||
new (static_cast<void*>(::boost::addressof(*pos))) value_type(); // may throw
|
||||
}
|
||||
|
||||
template <typename DisableTrivialInit, typename I>
|
||||
inline
|
||||
void construct(DisableTrivialInit const&, I pos)
|
||||
{
|
||||
typedef typename ::boost::iterator_value<I>::type value_type;
|
||||
typedef typename ::boost::mpl::and_<
|
||||
boost::has_trivial_constructor<value_type>,
|
||||
DisableTrivialInit
|
||||
>::type dont_init;
|
||||
|
||||
construct_dispatch(dont_init(), pos); // may throw
|
||||
}
|
||||
|
||||
// construct(I, V)
|
||||
|
||||
template <typename I, typename V>
|
||||
inline
|
||||
void construct_copy_dispatch(I pos, V const& v,
|
||||
boost::mpl::bool_<true> const& /*use_memcpy*/)
|
||||
{
|
||||
::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
|
||||
}
|
||||
|
||||
template <typename I, typename P>
|
||||
inline
|
||||
void construct_copy_dispatch(I pos, P const& p,
|
||||
boost::mpl::bool_<false> const& /*use_memcpy*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type V;
|
||||
new (static_cast<void*>(boost::addressof(*pos))) V(p); // may throw
|
||||
}
|
||||
|
||||
template <typename DisableTrivialInit, typename I, typename P>
|
||||
inline
|
||||
void construct(DisableTrivialInit const&,
|
||||
I pos, P const& p)
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::and_<
|
||||
is_corresponding_value<I, P>,
|
||||
::boost::has_trivial_copy<P>
|
||||
>::type
|
||||
use_memcpy;
|
||||
|
||||
construct_copy_dispatch(pos, p, use_memcpy()); // may throw
|
||||
}
|
||||
|
||||
// Needed by push_back(V &&)
|
||||
|
||||
template <typename I, typename V>
|
||||
inline
|
||||
void construct_move_dispatch(I pos, V const& v,
|
||||
boost::mpl::bool_<true> const& /*use_memcpy*/)
|
||||
{
|
||||
::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
|
||||
}
|
||||
|
||||
template <typename I, typename P>
|
||||
inline
|
||||
void construct_move_dispatch(I pos, BOOST_RV_REF(P) p,
|
||||
boost::mpl::bool_<false> const& /*use_memcpy*/)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type V;
|
||||
new (static_cast<void*>(boost::addressof(*pos))) V(::boost::move(p)); // may throw
|
||||
}
|
||||
|
||||
template <typename DisableTrivialInit, typename I, typename P>
|
||||
inline
|
||||
void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p)
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::and_<
|
||||
is_corresponding_value<I, P>,
|
||||
::boost::has_trivial_move_constructor<P>
|
||||
>::type
|
||||
use_memcpy;
|
||||
|
||||
construct_move_dispatch(pos, ::boost::move(p), use_memcpy()); // may throw
|
||||
}
|
||||
|
||||
// Needed by emplace_back() and emplace()
|
||||
|
||||
#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename DisableTrivialInit, typename I, class ...Args>
|
||||
inline
|
||||
void construct(DisableTrivialInit const&,
|
||||
I pos,
|
||||
BOOST_FWD_REF(Args) ...args)
|
||||
{
|
||||
typedef typename boost::iterator_value<I>::type V;
|
||||
new (static_cast<void*>(boost::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw
|
||||
}
|
||||
|
||||
#else // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
// BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 const& p0
|
||||
// !BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 && p0
|
||||
// which means that version with one parameter may take V const& v
|
||||
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT(N) \
|
||||
template <typename DisableTrivialInit, typename I, typename P BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
|
||||
inline \
|
||||
void construct(DisableTrivialInit const&, \
|
||||
I pos, \
|
||||
BOOST_FWD_REF(P) p \
|
||||
BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
|
||||
{ \
|
||||
typedef typename boost::iterator_value<I>::type V; \
|
||||
new \
|
||||
(static_cast<void*>(boost::addressof(*pos))) \
|
||||
V(boost::forward<P>(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); /*may throw*/ \
|
||||
} \
|
||||
|
||||
BOOST_MOVE_ITERATE_1TO9(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT)
|
||||
#undef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT
|
||||
|
||||
#endif // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
|
||||
|
||||
// assign(I, V)
|
||||
|
||||
template <typename I, typename V>
|
||||
inline
|
||||
void assign_copy_dispatch(I pos, V const& v,
|
||||
boost::mpl::bool_<true> const& /*use_memcpy*/)
|
||||
{
|
||||
// TODO - use memmove here?
|
||||
::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
|
||||
}
|
||||
|
||||
template <typename I, typename V>
|
||||
inline
|
||||
void assign_copy_dispatch(I pos, V const& v,
|
||||
boost::mpl::bool_<false> const& /*use_memcpy*/)
|
||||
{
|
||||
*pos = v; // may throw
|
||||
}
|
||||
|
||||
template <typename I, typename V>
|
||||
inline
|
||||
void assign(I pos, V const& v)
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::and_<
|
||||
is_corresponding_value<I, V>,
|
||||
::boost::has_trivial_assign<V>
|
||||
>::type
|
||||
use_memcpy;
|
||||
|
||||
assign_copy_dispatch(pos, v, use_memcpy()); // may throw
|
||||
}
|
||||
|
||||
template <typename I, typename V>
|
||||
inline
|
||||
void assign_move_dispatch(I pos, V const& v,
|
||||
boost::mpl::bool_<true> const& /*use_memcpy*/)
|
||||
{
|
||||
// TODO - use memmove here?
|
||||
::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
|
||||
}
|
||||
|
||||
template <typename I, typename V>
|
||||
inline
|
||||
void assign_move_dispatch(I pos, BOOST_RV_REF(V) v,
|
||||
boost::mpl::bool_<false> const& /*use_memcpy*/)
|
||||
{
|
||||
*pos = boost::move(v); // may throw
|
||||
}
|
||||
|
||||
template <typename I, typename V>
|
||||
inline
|
||||
void assign(I pos, BOOST_RV_REF(V) v)
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::and_<
|
||||
is_corresponding_value<I, V>,
|
||||
::boost::has_trivial_move_assign<V>
|
||||
>::type
|
||||
use_memcpy;
|
||||
|
||||
assign_move_dispatch(pos, ::boost::move(v), use_memcpy());
|
||||
}
|
||||
|
||||
// uninitialized_copy_s
|
||||
|
||||
template <typename I, typename F>
|
||||
inline std::size_t uninitialized_copy_s(I first, I last, F dest, std::size_t max_count)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
F it = dest;
|
||||
|
||||
BOOST_TRY
|
||||
{
|
||||
for ( ; first != last ; ++it, ++first, ++count )
|
||||
{
|
||||
if ( max_count <= count )
|
||||
return (std::numeric_limits<std::size_t>::max)();
|
||||
|
||||
// dummy 0 as DisableTrivialInit
|
||||
construct(0, it, *first); // may throw
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
destroy(dest, it);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// scoped_destructor
|
||||
|
||||
template<class T>
|
||||
class scoped_destructor
|
||||
{
|
||||
public:
|
||||
scoped_destructor(T * ptr) : m_ptr(ptr) {}
|
||||
|
||||
~scoped_destructor()
|
||||
{
|
||||
if(m_ptr)
|
||||
destroy(m_ptr);
|
||||
}
|
||||
|
||||
void release() { m_ptr = 0; }
|
||||
|
||||
private:
|
||||
T * m_ptr;
|
||||
};
|
||||
|
||||
}}}}} // namespace boost::geometry::index::detail::varray_detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP
|
||||
@@ -0,0 +1,204 @@
|
||||
// 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
|
||||
|
||||
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
|
||||
|
||||
/*!
|
||||
\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);
|
||||
}
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
|
||||
|
||||
// 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
|
||||
@@ -0,0 +1,267 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Copyright (c) 2011-2016 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>
|
||||
#include <boost/geometry/index/indexable.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
template <typename Geometry,
|
||||
typename Tag = typename geometry::tag<Geometry>::type>
|
||||
struct equals
|
||||
{
|
||||
inline static bool apply(Geometry const& g1, Geometry const& g2)
|
||||
{
|
||||
return geometry::equals(g1, g2);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry, typename Tag>
|
||||
struct equals<Geometry *, Tag>
|
||||
{
|
||||
inline static bool apply(const Geometry * g1, const Geometry * g2)
|
||||
{
|
||||
return g1 == g2;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct equals<T, void>
|
||||
{
|
||||
inline static bool apply(T const& v1, T const& v2)
|
||||
{
|
||||
return v1 == v2;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct equals<T *, void>
|
||||
{
|
||||
inline static bool apply(const T * v1, const T * 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>::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;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Consider this: Since equal_to<> is using geometry::equals() it's possible that
|
||||
// two compared Indexables are not exactly the same! They will be spatially equal
|
||||
// but not strictly equal. Consider 2 Segments with reversed order of points.
|
||||
// Therefore it's possible that during the Value removal different value will be
|
||||
// removed than the one that was passed.
|
||||
|
||||
/*!
|
||||
\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.
|
||||
\tparam IsIndexable If true, Values are compared using boost::geometry::equals() functions.
|
||||
*/
|
||||
template <typename Value,
|
||||
bool IsIndexable = is_indexable<Value>::value>
|
||||
struct equal_to
|
||||
{
|
||||
/*! \brief The type of result returned by function object. */
|
||||
typedef bool result_type;
|
||||
|
||||
/*!
|
||||
\brief Compare values. If Value is a Geometry geometry::equals() function is used.
|
||||
|
||||
\param l First value.
|
||||
\param r Second value.
|
||||
\return true if values are equal.
|
||||
*/
|
||||
inline bool operator()(Value const& l, Value const& r) const
|
||||
{
|
||||
return detail::equals<Value>::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>, false>
|
||||
{
|
||||
/*! \brief The type of result returned by function object. */
|
||||
typedef bool result_type;
|
||||
|
||||
/*!
|
||||
\brief Compare values. If pair<> Value member is a Geometry geometry::equals() function is used.
|
||||
|
||||
\param l First value.
|
||||
\param r Second value.
|
||||
\return true if values are equal.
|
||||
*/
|
||||
inline bool operator()(std::pair<T1, T2> const& l, std::pair<T1, T2> const& r) const
|
||||
{
|
||||
return detail::equals<T1>::apply(l.first, r.first)
|
||||
&& detail::equals<T2>::apply(l.second, r.second);
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief The function object comparing Values.
|
||||
|
||||
This specialization compares values of type boost::tuple<...>.
|
||||
It compares all members of the tuple from the first one to the last one.
|
||||
*/
|
||||
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>, false>
|
||||
{
|
||||
typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> value_type;
|
||||
|
||||
/*! \brief The type of result returned by function object. */
|
||||
typedef bool result_type;
|
||||
|
||||
/*!
|
||||
\brief Compare values. If tuple<> Value member is a Geometry geometry::equals() function is used.
|
||||
|
||||
\param l First value.
|
||||
\param r Second value.
|
||||
\return true if values are equal.
|
||||
*/
|
||||
inline 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::detail
|
||||
|
||||
#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>::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;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief The function object comparing Values.
|
||||
|
||||
This specialization compares values of type std::tuple<Args...>.
|
||||
It's defined if the compiler supports tuples and variadic templates.
|
||||
It compares all members of the tuple from the first one to the last one.
|
||||
*/
|
||||
template <typename ...Args>
|
||||
struct equal_to<std::tuple<Args...>, false>
|
||||
{
|
||||
typedef std::tuple<Args...> value_type;
|
||||
|
||||
/*! \brief The type of result returned by function object. */
|
||||
typedef bool result_type;
|
||||
|
||||
/*!
|
||||
\brief Compare values. If tuple<> Value member is a Geometry geometry::equals() function is used.
|
||||
|
||||
\param l First value.
|
||||
\param r Second value.
|
||||
\return true if values are equal.
|
||||
*/
|
||||
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::detail
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
/*!
|
||||
\brief The function object comparing Values.
|
||||
|
||||
The default version handles Values which are Indexables, std::pair<T1, T2>, boost::tuple<...>
|
||||
and std::tuple<...> if STD tuples and variadic templates are supported.
|
||||
All members are compared from left to right, Geometries using boost::geometry::equals() function,
|
||||
other types using operator==.
|
||||
|
||||
\tparam Value The type of objects which are compared by this function object.
|
||||
*/
|
||||
template <typename Value>
|
||||
struct equal_to
|
||||
: detail::equal_to<Value>
|
||||
{
|
||||
/*! \brief The type of result returned by function object. */
|
||||
typedef typename detail::equal_to<Value>::result_type result_type;
|
||||
|
||||
/*!
|
||||
\brief Compare Values.
|
||||
|
||||
\param l First value.
|
||||
\param r Second value.
|
||||
\return true if Values are equal.
|
||||
*/
|
||||
inline bool operator()(Value const& l, Value const& r) const
|
||||
{
|
||||
return detail::equal_to<Value>::operator()(l ,r);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP
|
||||
@@ -0,0 +1,196 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/is_indexable.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { 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>, boost::tuple<Indexable, ...>
|
||||
and std::tuple<Indexable, ...>.
|
||||
|
||||
\tparam Value The Value type which may be translated directly to the Indexable.
|
||||
\tparam IsIndexable If true, the const reference to Value is returned.
|
||||
*/
|
||||
template <typename Value, bool IsIndexable = is_indexable<Value>::value>
|
||||
struct indexable
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(detail::is_indexable<Value>::value),
|
||||
NOT_VALID_INDEXABLE_TYPE,
|
||||
(Value)
|
||||
);
|
||||
|
||||
/*! \brief The type of result returned by function object. */
|
||||
typedef Value const& result_type;
|
||||
|
||||
/*!
|
||||
\brief Return indexable extracted from the value.
|
||||
|
||||
\param v The value.
|
||||
\return The indexable.
|
||||
*/
|
||||
inline 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>, false>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(detail::is_indexable<Indexable>::value),
|
||||
NOT_VALID_INDEXABLE_TYPE,
|
||||
(Indexable)
|
||||
);
|
||||
|
||||
/*! \brief The type of result returned by function object. */
|
||||
typedef Indexable const& result_type;
|
||||
|
||||
/*!
|
||||
\brief Return indexable extracted from the value.
|
||||
|
||||
\param v The value.
|
||||
\return The indexable.
|
||||
*/
|
||||
inline 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>, false>
|
||||
{
|
||||
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)
|
||||
);
|
||||
|
||||
/*! \brief The type of result returned by function object. */
|
||||
typedef Indexable const& result_type;
|
||||
|
||||
/*!
|
||||
\brief Return indexable extracted from the value.
|
||||
|
||||
\param v The value.
|
||||
\return The indexable.
|
||||
*/
|
||||
inline result_type operator()(value_type const& v) const
|
||||
{
|
||||
return boost::get<0>(v);
|
||||
}
|
||||
};
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
/*!
|
||||
\brief The function object extracting Indexable from Value.
|
||||
|
||||
This specialization translates from std::tuple<Indexable, Args...>.
|
||||
It's defined if the compiler supports tuples and variadic templates.
|
||||
|
||||
\tparam Indexable The Indexable type.
|
||||
*/
|
||||
template <typename Indexable, typename ...Args>
|
||||
struct indexable<std::tuple<Indexable, Args...>, false>
|
||||
{
|
||||
typedef std::tuple<Indexable, Args...> value_type;
|
||||
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(detail::is_indexable<Indexable>::value),
|
||||
NOT_VALID_INDEXABLE_TYPE,
|
||||
(Indexable)
|
||||
);
|
||||
|
||||
/*! \brief The type of result returned by function object. */
|
||||
typedef Indexable const& result_type;
|
||||
|
||||
/*!
|
||||
\brief Return indexable extracted from the value.
|
||||
|
||||
\param v The value.
|
||||
\return The indexable.
|
||||
*/
|
||||
result_type operator()(value_type const& v) const
|
||||
{
|
||||
return std::get<0>(v);
|
||||
}
|
||||
};
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
/*!
|
||||
\brief The function object extracting Indexable from Value.
|
||||
|
||||
It translates Value object to Indexable object. By default, it can handle Values which are Indexables,
|
||||
std::pair<Indexable, T2>, boost::tuple<Indexable, ...> and std::tuple<Indexable, ...> if STD tuples
|
||||
and variadic templates are supported.
|
||||
|
||||
\tparam Value The Value type which may be translated directly to the Indexable.
|
||||
*/
|
||||
template <typename Value>
|
||||
struct indexable
|
||||
: detail::indexable<Value>
|
||||
{
|
||||
/*! \brief The type of result returned by function object. It should be const Indexable reference. */
|
||||
typedef typename detail::indexable<Value>::result_type result_type;
|
||||
|
||||
/*!
|
||||
\brief Return indexable extracted from the value.
|
||||
|
||||
\param v The value.
|
||||
\return The indexable.
|
||||
*/
|
||||
inline result_type operator()(Value const& v) const
|
||||
{
|
||||
return detail::indexable<Value>::operator()(v);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
|
||||
@@ -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
|
||||
@@ -0,0 +1,258 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree algorithms parameters
|
||||
//
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
|
||||
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/exception.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <size_t MaxElements>
|
||||
struct default_min_elements_s
|
||||
{
|
||||
static const size_t raw_value = (MaxElements * 3) / 10;
|
||||
static const size_t value = 1 <= raw_value ? raw_value : 1;
|
||||
};
|
||||
|
||||
inline size_t default_min_elements_d()
|
||||
{
|
||||
return (std::numeric_limits<size_t>::max)();
|
||||
}
|
||||
|
||||
inline size_t default_min_elements_d_calc(size_t max_elements, size_t min_elements)
|
||||
{
|
||||
if ( default_min_elements_d() == min_elements )
|
||||
{
|
||||
size_t raw_value = (max_elements * 3) / 10;
|
||||
return 1 <= raw_value ? raw_value : 1;
|
||||
}
|
||||
|
||||
return min_elements;
|
||||
}
|
||||
|
||||
template <size_t MaxElements>
|
||||
struct default_rstar_reinserted_elements_s
|
||||
{
|
||||
static const size_t value = (MaxElements * 3) / 10;
|
||||
};
|
||||
|
||||
inline size_t default_rstar_reinserted_elements_d()
|
||||
{
|
||||
return (std::numeric_limits<size_t>::max)();
|
||||
}
|
||||
|
||||
inline size_t default_rstar_reinserted_elements_d_calc(size_t max_elements, size_t reinserted_elements)
|
||||
{
|
||||
if ( default_rstar_reinserted_elements_d() == reinserted_elements )
|
||||
{
|
||||
return (max_elements * 3) / 10;
|
||||
}
|
||||
|
||||
return reinserted_elements;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/*!
|
||||
\brief Linear r-tree creation algorithm parameters.
|
||||
|
||||
\tparam MaxElements Maximum number of elements in nodes.
|
||||
\tparam MinElements Minimum number of elements in nodes. Default: 0.3*Max.
|
||||
*/
|
||||
template <size_t MaxElements,
|
||||
size_t MinElements = detail::default_min_elements_s<MaxElements>::value>
|
||||
struct linear
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),
|
||||
INVALID_STATIC_MIN_MAX_PARAMETERS, (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. Default: 0.3*Max.
|
||||
*/
|
||||
template <size_t MaxElements,
|
||||
size_t MinElements = detail::default_min_elements_s<MaxElements>::value>
|
||||
struct quadratic
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),
|
||||
INVALID_STATIC_MIN_MAX_PARAMETERS, (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; }
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief R*-tree creation algorithm parameters.
|
||||
|
||||
\tparam MaxElements Maximum number of elements in nodes.
|
||||
\tparam MinElements Minimum number of elements in nodes. Default: 0.3*Max.
|
||||
\tparam ReinsertedElements The number of elements reinserted by forced reinsertions algorithm.
|
||||
If 0 forced reinsertions are disabled. Maximum value is Max+1-Min.
|
||||
Greater values are truncated. Default: 0.3*Max.
|
||||
\tparam OverlapCostThreshold The number of most suitable leafs taken into account while choosing
|
||||
the leaf node to which currently inserted value will be added. If
|
||||
value is in range (0, MaxElements) - the algorithm calculates
|
||||
nearly minimum overlap cost, otherwise all leafs are analyzed
|
||||
and true minimum overlap cost is calculated. Default: 32.
|
||||
*/
|
||||
template <size_t MaxElements,
|
||||
size_t MinElements = detail::default_min_elements_s<MaxElements>::value,
|
||||
size_t ReinsertedElements = detail::default_rstar_reinserted_elements_s<MaxElements>::value,
|
||||
size_t OverlapCostThreshold = 32>
|
||||
struct rstar
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),
|
||||
INVALID_STATIC_MIN_MAX_PARAMETERS, (rstar));
|
||||
|
||||
static const size_t max_elements = MaxElements;
|
||||
static const size_t min_elements = MinElements;
|
||||
static const size_t reinserted_elements = ReinsertedElements;
|
||||
static const size_t overlap_cost_threshold = OverlapCostThreshold;
|
||||
|
||||
static size_t get_max_elements() { return MaxElements; }
|
||||
static size_t get_min_elements() { return MinElements; }
|
||||
static size_t get_reinserted_elements() { return ReinsertedElements; }
|
||||
static size_t get_overlap_cost_threshold() { return OverlapCostThreshold; }
|
||||
};
|
||||
|
||||
//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. Default: 0.3*Max.
|
||||
*/
|
||||
explicit dynamic_linear(size_t max_elements,
|
||||
size_t min_elements = detail::default_min_elements_d())
|
||||
: m_max_elements(max_elements)
|
||||
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
|
||||
{
|
||||
if (!(0 < m_min_elements && 2*m_min_elements <= m_max_elements+1))
|
||||
detail::throw_invalid_argument("invalid min or/and max parameters of dynamic_linear");
|
||||
}
|
||||
|
||||
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. Default: 0.3*Max.
|
||||
*/
|
||||
explicit dynamic_quadratic(size_t max_elements,
|
||||
size_t min_elements = detail::default_min_elements_d())
|
||||
: m_max_elements(max_elements)
|
||||
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
|
||||
{
|
||||
if (!(0 < m_min_elements && 2*m_min_elements <= m_max_elements+1))
|
||||
detail::throw_invalid_argument("invalid min or/and max parameters of dynamic_quadratic");
|
||||
}
|
||||
|
||||
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 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. Default: 0.3*Max.
|
||||
\param reinserted_elements The number of elements reinserted by forced reinsertions algorithm.
|
||||
If 0 forced reinsertions are disabled. Maximum value is Max-Min+1.
|
||||
Greater values are truncated. Default: 0.3*Max.
|
||||
\param overlap_cost_threshold The number of most suitable leafs taken into account while choosing
|
||||
the leaf node to which currently inserted value will be added. If
|
||||
value is in range (0, MaxElements) - the algorithm calculates
|
||||
nearly minimum overlap cost, otherwise all leafs are analyzed
|
||||
and true minimum overlap cost is calculated. Default: 32.
|
||||
*/
|
||||
explicit dynamic_rstar(size_t max_elements,
|
||||
size_t min_elements = detail::default_min_elements_d(),
|
||||
size_t reinserted_elements = detail::default_rstar_reinserted_elements_d(),
|
||||
size_t overlap_cost_threshold = 32)
|
||||
: m_max_elements(max_elements)
|
||||
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
|
||||
, m_reinserted_elements(detail::default_rstar_reinserted_elements_d_calc(max_elements, reinserted_elements))
|
||||
, m_overlap_cost_threshold(overlap_cost_threshold)
|
||||
{
|
||||
if (!(0 < m_min_elements && 2*m_min_elements <= m_max_elements+1))
|
||||
detail::throw_invalid_argument("invalid min or/and max parameters of dynamic_rstar");
|
||||
}
|
||||
|
||||
size_t get_max_elements() const { return m_max_elements; }
|
||||
size_t get_min_elements() const { return m_min_elements; }
|
||||
size_t get_reinserted_elements() const { return m_reinserted_elements; }
|
||||
size_t get_overlap_cost_threshold() const { return m_overlap_cost_threshold; }
|
||||
|
||||
private:
|
||||
size_t m_max_elements;
|
||||
size_t m_min_elements;
|
||||
size_t m_reinserted_elements;
|
||||
size_t m_overlap_cost_threshold;
|
||||
};
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
|
||||
@@ -0,0 +1,421 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Spatial query predicates
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_PREDICATES_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_PREDICATES_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 contains() predicate.
|
||||
|
||||
Generate a predicate defining Value and Geometry relationship.
|
||||
Value will be returned by the query if <tt>bg::within(Geometry, Indexable)</tt>
|
||||
returns true.
|
||||
|
||||
\par Example
|
||||
\verbatim
|
||||
bgi::query(spatial_index, bgi::contains(box), std::back_inserter(result));
|
||||
\endverbatim
|
||||
|
||||
\ingroup predicates
|
||||
|
||||
\tparam Geometry The Geometry type.
|
||||
|
||||
\param g The Geometry object.
|
||||
*/
|
||||
template <typename Geometry> inline
|
||||
detail::predicates::spatial_predicate<Geometry, detail::predicates::contains_tag, false>
|
||||
contains(Geometry const& g)
|
||||
{
|
||||
return detail::predicates::spatial_predicate
|
||||
<
|
||||
Geometry,
|
||||
detail::predicates::contains_tag,
|
||||
false
|
||||
>(g);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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::predicates::spatial_predicate<Geometry, detail::predicates::covered_by_tag, false>
|
||||
covered_by(Geometry const& g)
|
||||
{
|
||||
return detail::predicates::spatial_predicate
|
||||
<
|
||||
Geometry,
|
||||
detail::predicates::covered_by_tag,
|
||||
false
|
||||
>(g);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Generate \c covers() predicate.
|
||||
|
||||
Generate a predicate defining Value and Geometry relationship.
|
||||
Value will be returned by the query if <tt>bg::covered_by(Geometry, Indexable)</tt>
|
||||
returns true.
|
||||
|
||||
\par Example
|
||||
\verbatim
|
||||
bgi::query(spatial_index, bgi::covers(box), std::back_inserter(result));
|
||||
\endverbatim
|
||||
|
||||
\ingroup predicates
|
||||
|
||||
\tparam Geometry The Geometry type.
|
||||
|
||||
\param g The Geometry object.
|
||||
*/
|
||||
template <typename Geometry> inline
|
||||
detail::predicates::spatial_predicate<Geometry, detail::predicates::covers_tag, false>
|
||||
covers(Geometry const& g)
|
||||
{
|
||||
return detail::predicates::spatial_predicate
|
||||
<
|
||||
Geometry,
|
||||
detail::predicates::covers_tag,
|
||||
false
|
||||
>(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::predicates::spatial_predicate<Geometry, detail::predicates::disjoint_tag, false>
|
||||
disjoint(Geometry const& g)
|
||||
{
|
||||
return detail::predicates::spatial_predicate
|
||||
<
|
||||
Geometry,
|
||||
detail::predicates::disjoint_tag,
|
||||
false
|
||||
>(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::predicates::spatial_predicate<Geometry, detail::predicates::intersects_tag, false>
|
||||
intersects(Geometry const& g)
|
||||
{
|
||||
return detail::predicates::spatial_predicate
|
||||
<
|
||||
Geometry,
|
||||
detail::predicates::intersects_tag,
|
||||
false
|
||||
>(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::predicates::spatial_predicate<Geometry, detail::predicates::overlaps_tag, false>
|
||||
overlaps(Geometry const& g)
|
||||
{
|
||||
return detail::predicates::spatial_predicate
|
||||
<
|
||||
Geometry,
|
||||
detail::predicates::overlaps_tag,
|
||||
false
|
||||
>(g);
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
|
||||
|
||||
/*!
|
||||
\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::predicates::spatial_predicate<Geometry, detail::predicates::touches_tag, false>
|
||||
touches(Geometry const& g)
|
||||
{
|
||||
return detail::predicates::spatial_predicate
|
||||
<
|
||||
Geometry,
|
||||
detail::predicates::touches_tag,
|
||||
false
|
||||
>(g);
|
||||
}
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
|
||||
|
||||
/*!
|
||||
\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::predicates::spatial_predicate<Geometry, detail::predicates::within_tag, false>
|
||||
within(Geometry const& g)
|
||||
{
|
||||
return detail::predicates::spatial_predicate
|
||||
<
|
||||
Geometry,
|
||||
detail::predicates::within_tag,
|
||||
false
|
||||
>(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::predicates::satisfies<UnaryPredicate, false>
|
||||
satisfies(UnaryPredicate const& pred)
|
||||
{
|
||||
return detail::predicates::satisfies<UnaryPredicate, false>(pred);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Generate nearest() predicate.
|
||||
|
||||
When nearest predicate is passed to the query, k-nearest neighbour search will be performed.
|
||||
\c nearest() predicate takes a \c Geometry from which distances to \c Values are calculated
|
||||
and the maximum number of \c Values that should be returned. Internally
|
||||
boost::geometry::comparable_distance() is used to perform the calculation.
|
||||
|
||||
\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(box, 5), std::back_inserter(result));
|
||||
\endverbatim
|
||||
|
||||
\warning
|
||||
Only one \c nearest() predicate may be used in a query.
|
||||
|
||||
\ingroup predicates
|
||||
|
||||
\param geometry The geometry from which distance is calculated.
|
||||
\param k The maximum number of values to return.
|
||||
*/
|
||||
template <typename Geometry> inline
|
||||
detail::predicates::nearest<Geometry>
|
||||
nearest(Geometry const& geometry, unsigned k)
|
||||
{
|
||||
return detail::predicates::nearest<Geometry>(geometry, k);
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
|
||||
|
||||
/*!
|
||||
\brief Generate path() predicate.
|
||||
|
||||
When path predicate is passed to the query, the returned values are k values along the path closest to
|
||||
its begin. \c path() predicate takes a \c Segment or a \c Linestring defining the path and the maximum
|
||||
number of \c Values that should be returned.
|
||||
|
||||
\par Example
|
||||
\verbatim
|
||||
bgi::query(spatial_index, bgi::path(segment, 5), std::back_inserter(result));
|
||||
bgi::query(spatial_index, bgi::path(linestring, 5) && bgi::intersects(box), std::back_inserter(result));
|
||||
\endverbatim
|
||||
|
||||
\warning
|
||||
Only one distance predicate (\c nearest() or \c path()) may be used in a query.
|
||||
|
||||
\ingroup predicates
|
||||
|
||||
\param linestring The path along which distance is calculated.
|
||||
\param k The maximum number of values to return.
|
||||
*/
|
||||
template <typename SegmentOrLinestring> inline
|
||||
detail::predicates::path<SegmentOrLinestring>
|
||||
path(SegmentOrLinestring const& linestring, unsigned k)
|
||||
{
|
||||
return detail::predicates::path<SegmentOrLinestring>(linestring, k);
|
||||
}
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
|
||||
|
||||
namespace detail { namespace predicates {
|
||||
|
||||
// operator! generators
|
||||
|
||||
template <typename Fun, bool Negated> inline
|
||||
satisfies<Fun, !Negated>
|
||||
operator!(satisfies<Fun, Negated> const& p)
|
||||
{
|
||||
return satisfies<Fun, !Negated>(p);
|
||||
}
|
||||
|
||||
template <typename Geometry, typename Tag, bool Negated> inline
|
||||
spatial_predicate<Geometry, Tag, !Negated>
|
||||
operator!(spatial_predicate<Geometry, Tag, Negated> const& p)
|
||||
{
|
||||
return spatial_predicate<Geometry, Tag, !Negated>(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<
|
||||
boost::tuples::cons<Head, Tail>, Pred
|
||||
>::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<
|
||||
bt::cons<Head, Tail>, Pred
|
||||
>::apply(t, p);
|
||||
}
|
||||
|
||||
}} // namespace detail::predicates
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_PREDICATES_HPP
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user