deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
rtree.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2018 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_numerics_rtree_h
14#define dealii_numerics_rtree_h
15
16#include <deal.II/base/config.h>
17
18#include <deal.II/base/point.h>
20
24
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>
31
32#include <memory>
33#include <type_traits>
34#include <utility>
35
36
38
39namespace internal
40{
41 namespace RTreeImplementation
42 {
48 {};
49 } // namespace RTreeImplementation
50} // namespace internal
51
154template <typename LeafType,
155 typename IndexType = boost::geometry::index::linear<16>,
156 typename IndexableGetter =
157 boost::geometry::index::indexable<LeafType>>
158using RTree =
159 boost::geometry::index::rtree<LeafType, IndexType, IndexableGetter>;
160
170template <typename RTreeType>
172 boost::geometry::index::detail::rtree::utilities::view<RTreeType>;
173
181template <typename IndexType = boost::geometry::index::linear<16>,
182 typename LeafTypeIterator,
183 typename IndexableGetter = boost::geometry::index::indexable<
184 typename LeafTypeIterator::value_type>>
186pack_rtree(const LeafTypeIterator &begin, const LeafTypeIterator &end);
187
198template <typename IndexType = boost::geometry::index::linear<16>,
199 typename ContainerType,
200 typename IndexableGetter = boost::geometry::index::indexable<
201 typename ContainerType::value_type>>
203pack_rtree(const ContainerType &container);
204
223template <typename Container>
225{
226public:
232 typename boost::geometry::index::indexable<typename Container::value_type>;
233
237 using result_type = typename IndexableGetter::result_type;
238
242 using size_t = typename Container::size_type;
243
247 explicit IndexableGetterFromIndices(const Container &c)
248 : container(c)
249 {}
250
255 operator()(size_t i) const
256 {
257 return getter(container[i]);
258 }
259
260private:
264 const Container &container;
265
271};
272
327template <typename IndexType = boost::geometry::index::linear<16>,
328 typename ContainerType>
329RTree<typename ContainerType::size_type,
330 IndexType,
332pack_rtree_of_indices(const ContainerType &container);
333
416template <
417 typename RTreeType,
418 typename InternalVisitor = internal::RTreeImplementation::EmptyVisitor,
419 typename LeafVisitor = internal::RTreeImplementation::EmptyVisitor,
420 typename ElementVisitor = internal::RTreeImplementation::EmptyVisitor,
421 typename IndexableVisitor = internal::RTreeImplementation::EmptyVisitor>
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,
429 true>
430{
434 static constexpr unsigned int dim =
435 boost::geometry::dimension<typename RTreeType::indexable_type>::value;
436
441 typename boost::geometry::index::detail::rtree::internal_node<
447
451 using leaf_type = typename boost::geometry::index::detail::rtree::leaf<
457
461 using value_type = typename RTreeType::value_type;
462
466 using indexable_type = typename RTreeType::indexable_type;
467
472
477
481 static constexpr bool has_internal_visitor =
482 !std::is_same_v<InternalVisitor, empty_visitor>;
483
487 static constexpr bool has_leaf_visitor =
488 !std::is_same_v<LeafVisitor, empty_visitor>;
489
493 static constexpr bool has_element_visitor =
494 !std::is_same_v<ElementVisitor, empty_visitor>;
495
499 static constexpr bool has_indexable_visitor =
500 !std::is_same_v<IndexableVisitor, empty_visitor>;
501
516 InternalVisitor internal_node_visitor;
517
525 LeafVisitor leaf_visitor;
526
534 ElementVisitor element_visitor;
535
546 IndexableVisitor indexable_visitor;
547
553 void
555
561 void
563
571 RTreeFunctionalVisitor(const RTreeType &tree,
572 InternalVisitor internal_node_visitor = {},
573 LeafVisitor leaf_visitor = {},
574 ElementVisitor element_visitor = {},
575 IndexableVisitor indexable_visitor = {});
576
577 std::size_t current_level;
579};
580
634template <
635 typename RTreeType,
636 typename InternalVisitor = internal::RTreeImplementation::EmptyVisitor,
637 typename LeafVisitor = internal::RTreeImplementation::EmptyVisitor,
638 typename ElementVisitor = internal::RTreeImplementation::EmptyVisitor,
639 typename IndexableVisitor = internal::RTreeImplementation::EmptyVisitor>
640void
641visit_rtree(const RTreeType &tree,
642 InternalVisitor internal_node_visitor = {},
643 LeafVisitor leaf_visitor = {},
644 ElementVisitor element_visitor = {},
645 IndexableVisitor indexable_visitor = {});
646
647
698template <typename Rtree>
699inline std::vector<BoundingBox<
700 boost::geometry::dimension<typename Rtree::indexable_type>::value>>
701extract_rtree_level(const Rtree &tree, const unsigned int level);
702
703
704
714template <typename Rtree>
715std::vector<std::vector<BoundingBox<
716 boost::geometry::dimension<typename Rtree::indexable_type>::value>>>
717extract_children_of_level(const Rtree &tree, const unsigned int level);
718
719
720
721// Inline and template functions
722#ifndef DOXYGEN
723
724template <typename IndexType,
725 typename LeafTypeIterator,
726 typename IndexableGetter>
728pack_rtree(const LeafTypeIterator &begin, const LeafTypeIterator &end)
729{
730 return RTree<typename LeafTypeIterator::value_type,
731 IndexType,
732 IndexableGetter>(begin, end);
733}
734
735
736
737template <typename IndexType, typename ContainerType, typename IndexableGetter>
739pack_rtree(const ContainerType &container)
740{
741 return pack_rtree<IndexType, decltype(container.begin()), IndexableGetter>(
742 container.begin(), container.end());
743}
744
745
746
747template <typename IndexType, typename ContainerType>
748RTree<typename ContainerType::size_type,
749 IndexType,
751pack_rtree_of_indices(const ContainerType &container)
752{
753 // We need an array that holds the indices we want to pack. The rtree
754 // implementation in BOOST, for reasons not entirely clear, insists
755 // on using a reference to the elements of the range. This is fine if
756 // the indices are stored in a container, so that's what we do.
757 // (It would be nice if we could just pass a std::ranges::iota_view
758 // instead, but that has no nested 'reference' type, and this then
759 // trips up BOOST rtree.)
760 std::vector<typename ContainerType::size_type> indices(container.size());
761 for (typename ContainerType::size_type i = 0; i < container.size(); ++i)
762 indices[i] = i;
763
764 return RTree<typename ContainerType::size_type,
765 IndexType,
767 indices.begin(),
768 indices.end(),
769 IndexType(),
771}
772
773
774
775template <typename RTreeType,
776 typename InternalVisitor,
777 typename LeafVisitor,
778 typename ElementVisitor,
779 typename IndexableVisitor>
780void
781RTreeFunctionalVisitor<RTreeType,
782 InternalVisitor,
783 LeafVisitor,
784 ElementVisitor,
785 IndexableVisitor>::operator()(internal_node_type &node)
786{
787 const std::size_t level_backup = current_level;
788 for (const auto &element :
789 boost::geometry::index::detail::rtree::elements(node))
790 {
792 boost::geometry::convert(element.first, box);
793
794 const std::size_t child_level = level_backup;
795
796 if (auto *leaf_ptr = boost::get<leaf_type>(&*element.second))
797 {
798 if constexpr (has_leaf_visitor)
799 leaf_visitor(child_level, node, box, *leaf_ptr);
800 }
801 else if (auto *internal_ptr =
802 boost::get<internal_node_type>(&*element.second))
803 {
804 if constexpr (has_internal_visitor)
805 internal_node_visitor(child_level, node, box, *internal_ptr);
806 }
807
808 current_level = child_level + 1;
809 boost::geometry::index::detail::rtree::apply_visitor(*this,
810 *element.second);
811 }
812 current_level = level_backup;
813}
814
815
816
817template <typename RTreeType,
818 typename InternalVisitor,
819 typename LeafVisitor,
820 typename ElementVisitor,
821 typename IndexableVisitor>
822void
823RTreeFunctionalVisitor<RTreeType,
824 InternalVisitor,
825 LeafVisitor,
826 ElementVisitor,
827 IndexableVisitor>::operator()(leaf_type &leaf)
828{
829 for (const auto &element :
830 boost::geometry::index::detail::rtree::elements(leaf))
831 {
832 if constexpr (has_element_visitor)
833 element_visitor(leaf, element);
834 if constexpr (has_indexable_visitor)
835 {
836 auto idx = translator(element);
837 indexable_visitor(leaf, idx);
838 }
839 }
840}
841
842
843
844template <typename RTreeType,
845 typename InternalVisitor,
846 typename LeafVisitor,
847 typename ElementVisitor,
848 typename IndexableVisitor>
849RTreeFunctionalVisitor<RTreeType,
850 InternalVisitor,
851 LeafVisitor,
852 ElementVisitor,
853 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))
863 , current_level(0)
864 , translator(RTreeView<RTreeType>(tree).translator())
865{
866 static_assert(!has_internal_visitor ||
867 std::is_invocable_r_v<void,
868 InternalVisitor,
869 const std::size_t &,
870 const internal_node_type &,
871 const BoundingBox<dim> &,
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)");
875
876 static_assert(
877 !has_leaf_visitor || std::is_invocable_r_v<void,
878 LeafVisitor,
879 const std::size_t &,
880 const internal_node_type &,
881 const BoundingBox<dim> &,
882 const leaf_type &>,
883 "leaf_visitor must be callable with (std::size_t, internal_node_type, "
884 "BoundingBox<dim>, leaf_type)");
885
886 static_assert(
887 !has_element_visitor || std::is_invocable_r_v<void,
888 ElementVisitor,
889 const leaf_type &,
890 const value_type &>,
891 "element_visitor must be callable with (leaf_type, value_type)");
892
893 static_assert(
894 !has_indexable_visitor || std::is_invocable_r_v<void,
895 IndexableVisitor,
896 const leaf_type &,
897 const indexable_type &>,
898 "indexable_visitor must be callable with (leaf_type, indexable_type)");
899
900 RTreeView<RTreeType> rtv(tree);
901 rtv.apply_visitor(*this);
902}
903
904
905
906template <typename RTreeType,
907 typename InternalVisitor,
908 typename LeafVisitor,
909 typename ElementVisitor,
910 typename IndexableVisitor>
911void
912visit_rtree(const RTreeType &tree,
913 InternalVisitor internal_node_visitor,
914 LeafVisitor leaf_visitor,
915 ElementVisitor element_visitor,
916 IndexableVisitor indexable_visitor)
917{
918 RTreeFunctionalVisitor<RTreeType,
919 std::decay_t<InternalVisitor>,
920 std::decay_t<LeafVisitor>,
921 std::decay_t<ElementVisitor>,
922 std::decay_t<IndexableVisitor>>
923 visitor(tree,
924 std::move(internal_node_visitor),
925 std::move(leaf_visitor),
926 std::move(element_visitor),
927 std::move(indexable_visitor));
928}
929
930
931
932template <typename Rtree>
933inline std::vector<BoundingBox<
934 boost::geometry::dimension<typename Rtree::indexable_type>::value>>
935extract_rtree_level(const Rtree &tree, const unsigned int level)
936{
937 constexpr unsigned int dim =
938 boost::geometry::dimension<typename Rtree::indexable_type>::value;
939
940 std::vector<BoundingBox<dim>> boxes;
941
942 unsigned int n_levels_in_tree = n_levels(tree);
943
944 if (n_levels_in_tree == 0)
945 {
946 // The algorithm below does not work for `n_levels_in_tree==0`, which
947 // might happen if the number entries in the tree is too small. In this
948 // case, simply return a single bounding box.
949 boxes.resize(1);
950 boost::geometry::convert(tree.bounds(), boxes[0]);
951 }
952 else
953 {
954 const unsigned int target_level =
955 std::min<unsigned int>(level, n_levels_in_tree - 1);
956
957 using Visitor = RTreeFunctionalVisitor<Rtree>;
958 using InternalNode = typename Visitor::internal_node_type;
959 using LeafNode = typename Visitor::leaf_type;
960 const auto node_visitor = [&](const std::size_t &current_level,
961 const InternalNode &,
962 const BoundingBox<dim> &box,
963 const InternalNode &) {
964 if (current_level == target_level)
965 boxes.push_back(box);
966 };
967 const auto leaf_visitor = [&](const std::size_t &current_level,
968 const InternalNode &,
969 const BoundingBox<dim> &box,
970 const LeafNode &) {
971 if (current_level == target_level)
972 boxes.push_back(box);
973 };
974 visit_rtree(tree, node_visitor, leaf_visitor);
975 }
976
977 return boxes;
978}
979
980
981
982template <class Rtree>
983unsigned int
984n_levels(const Rtree &tree)
985{
986 boost::geometry::index::detail::rtree::utilities::view<Rtree> rtv(tree);
987 return rtv.depth();
988}
989
990
991template <typename Rtree>
992inline std::vector<std::vector<BoundingBox<
993 boost::geometry::dimension<typename Rtree::indexable_type>::value>>>
994extract_children_of_level(const Rtree &tree, const unsigned int level)
995{
996 constexpr unsigned int dim =
997 boost::geometry::dimension<typename Rtree::indexable_type>::value;
998
999 unsigned int n_levels_in_tree = n_levels(tree);
1000
1001 std::vector<std::vector<BoundingBox<dim>>> boxes_in_boxes;
1002
1003 if (n_levels_in_tree == 0)
1004 {
1005 // The below algorithm does not work for `rtv.depth()==0`, which might
1006 // happen if the number entries in the tree is too small.
1007 // In this case, simply return a single bounding box.
1008 boxes_in_boxes.resize(1);
1009 boxes_in_boxes[0].resize(1);
1010 boost::geometry::convert(tree.bounds(), boxes_in_boxes[0][0]);
1011 }
1012 else
1013 {
1014 const unsigned int target_level =
1015 std::min<unsigned int>(level, n_levels_in_tree - 1);
1016
1017 // Track all nodes on target_level and collect their children (level
1018 // target_level+1) grouped per parent. Depth-first visitation guarantees
1019 // children immediately follow their parent, so a simple counter suffices.
1020 std::size_t current_parent_index = 0;
1021 std::size_t node_counter = 0;
1022
1023 const auto internal = [&](const std::size_t current_level,
1024 const auto &,
1025 const BoundingBox<dim> &child_box,
1026 const auto &) {
1027 // Register nodes that live on the target level so their children can
1028 // be grouped.
1029 if (current_level == target_level)
1030 {
1031 current_parent_index = node_counter++;
1032 boxes_in_boxes.emplace_back();
1033 return;
1034 }
1035
1036 // Record children of nodes on the target level.
1037 if (current_level == target_level + 1)
1038 boxes_in_boxes[current_parent_index].push_back(child_box);
1039 };
1040
1041 const auto leaf = [&](const std::size_t current_level,
1042 const auto &,
1043 const BoundingBox<dim> &child_box,
1044 const auto &) {
1045 if (current_level == target_level + 1)
1046 boxes_in_boxes[current_parent_index].push_back(child_box);
1047 };
1048
1049 visit_rtree(tree, internal, leaf);
1050 }
1051
1052 return boxes_in_boxes;
1053}
1054
1055
1056
1057#endif
1058
1060
1061#endif
*  iterator end()
*  *  iterator begin()
result_type operator()(size_t i) const
Definition rtree.h:255
const Container & container
Definition rtree.h:264
typename Container::size_type size_t
Definition rtree.h:242
IndexableGetter getter
Definition rtree.h:270
typename boost::geometry::index::indexable< typename Container::value_type > IndexableGetter
Definition rtree.h:232
typename IndexableGetter::result_type result_type
Definition rtree.h:237
IndexableGetterFromIndices(const Container &c)
Definition rtree.h:247
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:636
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition config.h:680
unsigned int level
Definition grid_out.cc:4642
STL namespace.
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
Definition rtree.h:159
boost::geometry::index::detail::rtree::utilities::view< RTreeType > RTreeView
Definition rtree.h:172
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
Definition rtree.h:493
static constexpr bool has_leaf_visitor
Definition rtree.h:487
typename RTreeType::indexable_type indexable_type
Definition rtree.h:466
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
Definition rtree.h:446
typename RTreeView< RTreeType >::translator_type translator_type
Definition rtree.h:471
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
Definition rtree.h:456
translator_type translator
Definition rtree.h:578
static constexpr bool has_indexable_visitor
Definition rtree.h:499
RTreeFunctionalVisitor(const RTreeType &tree, InternalVisitor internal_node_visitor={}, LeafVisitor leaf_visitor={}, ElementVisitor element_visitor={}, IndexableVisitor indexable_visitor={})
IndexableVisitor indexable_visitor
Definition rtree.h:546
InternalVisitor internal_node_visitor
Definition rtree.h:516
ElementVisitor element_visitor
Definition rtree.h:534
static constexpr unsigned int dim
Definition rtree.h:434
std::size_t current_level
Definition rtree.h:577
void operator()(internal_node_type &node)
typename RTreeType::value_type value_type
Definition rtree.h:461
LeafVisitor leaf_visitor
Definition rtree.h:525
static constexpr bool has_internal_visitor
Definition rtree.h:481