119 lines
3.7 KiB
C++
119 lines
3.7 KiB
C++
// Boost.Geometry
|
|
|
|
// Copyright (c) 2022, Oracle and/or its affiliates.
|
|
|
|
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
|
|
|
// Licensed under the Boost Software License version 1.0.
|
|
// http://www.boost.org/users/license.html
|
|
|
|
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_MAKE_RTREE_HPP
|
|
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_MAKE_RTREE_HPP
|
|
|
|
#include <vector>
|
|
|
|
#include <boost/range/begin.hpp>
|
|
#include <boost/range/end.hpp>
|
|
#include <boost/range/size.hpp>
|
|
|
|
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
|
|
#include <boost/geometry/algorithms/detail/visit.hpp>
|
|
#include <boost/geometry/algorithms/envelope.hpp>
|
|
#include <boost/geometry/index/rtree.hpp>
|
|
#include <boost/geometry/strategies/index/services.hpp>
|
|
#include <boost/geometry/views/detail/random_access_view.hpp>
|
|
|
|
namespace boost { namespace geometry
|
|
{
|
|
|
|
|
|
#ifndef DOXYGEN_NO_DETAIL
|
|
namespace detail
|
|
{
|
|
|
|
|
|
template <typename GC>
|
|
using gc_make_rtree_box_t = geometry::model::box
|
|
<
|
|
geometry::model::point
|
|
<
|
|
typename geometry::coordinate_type<GC>::type,
|
|
geometry::dimension<GC>::value,
|
|
typename geometry::coordinate_system<GC>::type
|
|
>
|
|
>;
|
|
|
|
|
|
template <typename GC, typename Strategy>
|
|
inline auto gc_make_rtree_iterators(GC& gc, Strategy const& strategy)
|
|
{
|
|
using box_t = gc_make_rtree_box_t<GC>;
|
|
using iter_t = typename boost::range_iterator<GC>::type;
|
|
|
|
using rtree_param_t = index::rstar<4>;
|
|
using rtree_parameters_t = index::parameters<rtree_param_t, Strategy>;
|
|
using value_t = std::pair<box_t, iter_t>;
|
|
using rtree_t = index::rtree<value_t, rtree_parameters_t>;
|
|
|
|
// TODO: get rid of the temporary vector
|
|
auto const size = boost::size(gc);
|
|
std::vector<value_t> values;
|
|
values.reserve(size);
|
|
|
|
visit_breadth_first_impl<true>::apply([&](auto const& g, auto iter)
|
|
{
|
|
box_t b = geometry::return_envelope<box_t>(g, strategy);
|
|
detail::expand_by_epsilon(b);
|
|
values.emplace_back(b, iter);
|
|
return true;
|
|
}, gc);
|
|
|
|
return rtree_t(values.begin(), values.end(), rtree_parameters_t(rtree_param_t(), strategy));
|
|
}
|
|
|
|
|
|
template <typename GCView, typename Strategy>
|
|
inline auto gc_make_rtree_indexes(GCView const& gc, Strategy const& strategy)
|
|
{
|
|
// Alternatively only take random_access_view<GC>
|
|
static const bool is_random_access = is_random_access_range<GCView>::value;
|
|
static const bool is_not_recursive = ! is_geometry_collection_recursive<GCView>::value;
|
|
BOOST_GEOMETRY_STATIC_ASSERT((is_random_access && is_not_recursive),
|
|
"This algorithm requires random-access, non-recursive geometry collection or view.",
|
|
GCView);
|
|
|
|
using box_t = gc_make_rtree_box_t<GCView>;
|
|
|
|
using rtree_param_t = index::rstar<4>;
|
|
using rtree_parameters_t = index::parameters<rtree_param_t, Strategy>;
|
|
using value_t = std::pair<box_t, std::size_t>;
|
|
using rtree_t = index::rtree<value_t, rtree_parameters_t>;
|
|
|
|
// TODO: get rid of the temporary vector
|
|
std::size_t const size = boost::size(gc);
|
|
std::vector<value_t> values;
|
|
values.reserve(size);
|
|
|
|
auto const begin = boost::begin(gc);
|
|
for (std::size_t i = 0; i < size; ++i)
|
|
{
|
|
traits::iter_visit<GCView>::apply([&](auto const& g)
|
|
{
|
|
box_t b = geometry::return_envelope<box_t>(g, strategy);
|
|
detail::expand_by_epsilon(b);
|
|
values.emplace_back(b, i);
|
|
}, begin + i);
|
|
}
|
|
|
|
return rtree_t(values.begin(), values.end(), rtree_parameters_t(rtree_param_t(), strategy));
|
|
}
|
|
|
|
|
|
} // namespace detail
|
|
#endif // DOXYGEN_NO_DETAIL
|
|
|
|
|
|
}} // namespace boost::geometry
|
|
|
|
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_MAKE_RTREE_HPP
|