13#ifndef dealii_numerics_rtree_h
14#define dealii_numerics_rtree_h
26#include <boost/geometry/algorithms/buffer.hpp>
27#include <boost/geometry/algorithms/distance.hpp>
28#include <boost/geometry/index/rtree.hpp>
29#include <boost/geometry/strategies/strategies.hpp>
41 namespace RTreeImplementation
154template <
typename LeafType,
155 typename IndexType = boost::geometry::index::linear<16>,
156 typename IndexableGetter =
157 boost::geometry::index::indexable<LeafType>>
159 boost::geometry::index::rtree<LeafType, IndexType, IndexableGetter>;
170template <
typename RTreeType>
172 boost::geometry::index::detail::rtree::utilities::view<RTreeType>;
181template <
typename IndexType = boost::geometry::index::linear<16>,
182 typename LeafTypeIterator,
183 typename IndexableGetter = boost::geometry::index::indexable<
184 typename LeafTypeIterator::value_type>>
198template <
typename IndexType = boost::geometry::index::linear<16>,
199 typename ContainerType,
200 typename IndexableGetter = boost::geometry::index::indexable<
201 typename ContainerType::value_type>>
223template <
typename Container>
232 typename boost::geometry::index::indexable<typename Container::value_type>;
242 using size_t =
typename Container::size_type;
327template <
typename IndexType = boost::geometry::index::linear<16>,
328 typename ContainerType>
329RTree<
typename ContainerType::size_type,
423 :
public boost::geometry::index::detail::rtree::visitor<
424 typename RTreeView<RTreeType>::value_type,
425 typename RTreeView<RTreeType>::options_type::parameters_type,
426 typename RTreeView<RTreeType>::box_type,
427 typename RTreeView<RTreeType>::allocators_type,
428 typename RTreeView<RTreeType>::options_type::node_tag,
434 static constexpr unsigned int dim =
435 boost::geometry::dimension<typename RTreeType::indexable_type>::value;
441 typename boost::geometry::index::detail::rtree::internal_node<
451 using leaf_type =
typename boost::geometry::index::detail::rtree::leaf<
482 !std::is_same_v<InternalVisitor, empty_visitor>;
488 !std::is_same_v<LeafVisitor, empty_visitor>;
494 !std::is_same_v<ElementVisitor, empty_visitor>;
500 !std::is_same_v<IndexableVisitor, empty_visitor>;
642 InternalVisitor internal_node_visitor = {},
643 LeafVisitor leaf_visitor = {},
644 ElementVisitor element_visitor = {},
645 IndexableVisitor indexable_visitor = {});
698template <
typename Rtree>
700 boost::geometry::dimension<typename Rtree::indexable_type>::value>>
714template <
typename Rtree>
716 boost::geometry::dimension<typename Rtree::indexable_type>::value>>>
724template <
typename IndexType,
725 typename LeafTypeIterator,
726 typename IndexableGetter>
730 return RTree<
typename LeafTypeIterator::value_type,
737template <
typename IndexType,
typename ContainerType,
typename IndexableGetter>
741 return pack_rtree<IndexType,
decltype(container.begin()), IndexableGetter>(
742 container.begin(), container.end());
747template <
typename IndexType,
typename ContainerType>
748RTree<
typename ContainerType::size_type,
760 std::vector<typename ContainerType::size_type> indices(container.size());
761 for (
typename ContainerType::size_type i = 0; i < container.size(); ++i)
764 return RTree<
typename ContainerType::size_type,
775template <
typename RTreeType,
776 typename InternalVisitor,
777 typename LeafVisitor,
778 typename ElementVisitor,
779 typename IndexableVisitor>
785 IndexableVisitor>::operator()(internal_node_type &node)
787 const std::size_t level_backup = current_level;
788 for (
const auto &element :
789 boost::geometry::
index::detail::rtree::elements(node))
792 boost::geometry::convert(element.first, box);
794 const std::size_t child_level = level_backup;
796 if (
auto *leaf_ptr = boost::get<leaf_type>(&*element.second))
798 if constexpr (has_leaf_visitor)
799 leaf_visitor(child_level, node, box, *leaf_ptr);
801 else if (
auto *internal_ptr =
802 boost::get<internal_node_type>(&*element.second))
804 if constexpr (has_internal_visitor)
805 internal_node_visitor(child_level, node, box, *internal_ptr);
808 current_level = child_level + 1;
809 boost::geometry::index::detail::rtree::apply_visitor(*
this,
812 current_level = level_backup;
817template <
typename RTreeType,
818 typename InternalVisitor,
819 typename LeafVisitor,
820 typename ElementVisitor,
821 typename IndexableVisitor>
827 IndexableVisitor>::operator()(leaf_type &leaf)
829 for (
const auto &element :
830 boost::geometry::
index::detail::rtree::elements(leaf))
832 if constexpr (has_element_visitor)
833 element_visitor(leaf, element);
834 if constexpr (has_indexable_visitor)
836 auto idx = translator(element);
837 indexable_visitor(leaf, idx);
844template <
typename RTreeType,
845 typename InternalVisitor,
846 typename LeafVisitor,
847 typename ElementVisitor,
848 typename IndexableVisitor>
854 RTreeFunctionalVisitor(
const RTreeType &tree,
855 InternalVisitor internal_node_visitor,
856 LeafVisitor leaf_visitor,
857 ElementVisitor element_visitor,
858 IndexableVisitor indexable_visitor)
859 : internal_node_visitor(
std::move(internal_node_visitor))
860 , leaf_visitor(
std::move(leaf_visitor))
861 , element_visitor(
std::move(element_visitor))
862 , indexable_visitor(
std::move(indexable_visitor))
864 , translator(
RTreeView<RTreeType>(tree).translator())
866 static_assert(!has_internal_visitor ||
867 std::is_invocable_r_v<void,
870 const internal_node_type &,
872 const internal_node_type &>,
873 "internal_node_visitor must be callable with (std::size_t, "
874 "internal_node_type, BoundingBox<dim>, internal_node_type)");
877 !has_leaf_visitor || std::is_invocable_r_v<void,
880 const internal_node_type &,
883 "leaf_visitor must be callable with (std::size_t, internal_node_type, "
884 "BoundingBox<dim>, leaf_type)");
887 !has_element_visitor || std::is_invocable_r_v<void,
891 "element_visitor must be callable with (leaf_type, value_type)");
894 !has_indexable_visitor || std::is_invocable_r_v<void,
897 const indexable_type &>,
898 "indexable_visitor must be callable with (leaf_type, indexable_type)");
901 rtv.apply_visitor(*
this);
906template <
typename RTreeType,
907 typename InternalVisitor,
908 typename LeafVisitor,
909 typename ElementVisitor,
910 typename IndexableVisitor>
913 InternalVisitor internal_node_visitor,
914 LeafVisitor leaf_visitor,
915 ElementVisitor element_visitor,
916 IndexableVisitor indexable_visitor)
919 std::decay_t<InternalVisitor>,
920 std::decay_t<LeafVisitor>,
921 std::decay_t<ElementVisitor>,
922 std::decay_t<IndexableVisitor>>
924 std::move(internal_node_visitor),
925 std::move(leaf_visitor),
926 std::move(element_visitor),
927 std::move(indexable_visitor));
932template <
typename Rtree>
934 boost::geometry::dimension<typename Rtree::indexable_type>::value>>
937 constexpr unsigned int dim =
938 boost::geometry::dimension<typename Rtree::indexable_type>::value;
940 std::vector<BoundingBox<dim>> boxes;
942 unsigned int n_levels_in_tree = n_levels(tree);
944 if (n_levels_in_tree == 0)
950 boost::geometry::convert(tree.bounds(), boxes[0]);
954 const unsigned int target_level =
955 std::min<unsigned int>(
level, n_levels_in_tree - 1);
958 using InternalNode =
typename Visitor::internal_node_type;
959 using LeafNode =
typename Visitor::leaf_type;
960 const auto node_visitor = [&](
const std::size_t ¤t_level,
961 const InternalNode &,
963 const InternalNode &) {
964 if (current_level == target_level)
965 boxes.push_back(box);
967 const auto leaf_visitor = [&](
const std::size_t ¤t_level,
968 const InternalNode &,
971 if (current_level == target_level)
972 boxes.push_back(box);
982template <
class Rtree>
984n_levels(
const Rtree &tree)
986 boost::geometry::index::detail::rtree::utilities::view<Rtree> rtv(tree);
991template <
typename Rtree>
993 boost::geometry::dimension<typename Rtree::indexable_type>::value>>>
996 constexpr unsigned int dim =
997 boost::geometry::dimension<typename Rtree::indexable_type>::value;
999 unsigned int n_levels_in_tree = n_levels(tree);
1001 std::vector<std::vector<BoundingBox<dim>>> boxes_in_boxes;
1003 if (n_levels_in_tree == 0)
1008 boxes_in_boxes.resize(1);
1009 boxes_in_boxes[0].resize(1);
1010 boost::geometry::convert(tree.bounds(), boxes_in_boxes[0][0]);
1014 const unsigned int target_level =
1015 std::min<unsigned int>(
level, n_levels_in_tree - 1);
1020 std::size_t current_parent_index = 0;
1021 std::size_t node_counter = 0;
1023 const auto internal = [&](
const std::size_t current_level,
1029 if (current_level == target_level)
1031 current_parent_index = node_counter++;
1032 boxes_in_boxes.emplace_back();
1037 if (current_level == target_level + 1)
1038 boxes_in_boxes[current_parent_index].push_back(child_box);
1041 const auto leaf = [&](
const std::size_t current_level,
1045 if (current_level == target_level + 1)
1046 boxes_in_boxes[current_parent_index].push_back(child_box);
1052 return boxes_in_boxes;
result_type operator()(size_t i) const
const Container & container
typename Container::size_type size_t
typename boost::geometry::index::indexable< typename Container::value_type > IndexableGetter
typename IndexableGetter::result_type result_type
IndexableGetterFromIndices(const Container &c)
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
std::vector< BoundingBox< boost::geometry::dimension< typename Rtree::indexable_type >::value > > extract_rtree_level(const Rtree &tree, const unsigned int level)
boost::geometry::index::rtree< LeafType, IndexType, IndexableGetter > RTree
boost::geometry::index::detail::rtree::utilities::view< RTreeType > RTreeView
std::vector< std::vector< BoundingBox< boost::geometry::dimension< typename Rtree::indexable_type >::value > > > extract_children_of_level(const Rtree &tree, const unsigned int level)
void visit_rtree(const RTreeType &tree, InternalVisitor internal_node_visitor={}, LeafVisitor leaf_visitor={}, ElementVisitor element_visitor={}, IndexableVisitor indexable_visitor={})
RTree< typename LeafTypeIterator::value_type, IndexType, IndexableGetter > pack_rtree(const LeafTypeIterator &begin, const LeafTypeIterator &end)
RTree< typename ContainerType::size_type, IndexType, IndexableGetterFromIndices< ContainerType > > pack_rtree_of_indices(const ContainerType &container)
static constexpr bool has_element_visitor
static constexpr bool has_leaf_visitor
typename RTreeType::indexable_type indexable_type
void operator()(leaf_type &leaf)
typename boost::geometry::index::detail::rtree::internal_node< typename RTreeView< RTreeType >::value_type, typename RTreeView< RTreeType >::options_type::parameters_type, typename RTreeView< RTreeType >::box_type, typename RTreeView< RTreeType >::allocators_type, typename RTreeView< RTreeType >::options_type::node_tag >::type internal_node_type
typename RTreeView< RTreeType >::translator_type translator_type
typename boost::geometry::index::detail::rtree::leaf< typename RTreeView< RTreeType >::value_type, typename RTreeView< RTreeType >::options_type::parameters_type, typename RTreeView< RTreeType >::box_type, typename RTreeView< RTreeType >::allocators_type, typename RTreeView< RTreeType >::options_type::node_tag >::type leaf_type
translator_type translator
static constexpr bool has_indexable_visitor
RTreeFunctionalVisitor(const RTreeType &tree, InternalVisitor internal_node_visitor={}, LeafVisitor leaf_visitor={}, ElementVisitor element_visitor={}, IndexableVisitor indexable_visitor={})
IndexableVisitor indexable_visitor
InternalVisitor internal_node_visitor
ElementVisitor element_visitor
static constexpr unsigned int dim
std::size_t current_level
void operator()(internal_node_type &node)
typename RTreeType::value_type value_type
static constexpr bool has_internal_visitor