Wayverb
ndim_tree.h
1 #pragma once
2 
3 #include "core/geo/box.h"
4 #include "core/indexing.h"
5 #include "core/spatial_division/range.h"
6 
7 #include <memory>
8 
9 namespace wayverb {
10 namespace core {
11 namespace detail {
12 
13 template <size_t n,
14  typename aabb_type = detail::range_t<n>,
15  typename next_boundaries_type = std::array<aabb_type, (1 << n)>>
16 next_boundaries_type next_boundaries(const aabb_type& parent) {
17  using vt = detail::range_value_t<n>;
18 
19  const auto c = centre(parent);
20 
21  const auto root_aabb = aabb_type(parent.get_min(), c);
22  const auto d = dimensions(root_aabb);
23 
24  next_boundaries_type ret;
25 
26  for (size_t i = 0; i != ret.size(); ++i) {
27  const auto relative = indexing::relative_position<n>(i);
28  ret[i] = root_aabb + d * vt{relative};
29  }
30 
31  return ret;
32 }
33 
34 } // namespace detail
35 
37 template <size_t n>
38 class ndim_tree final {
39 public:
40  using aabb_type = detail::range_t<n>;
41  using node_array = std::array<ndim_tree, (1 << n)>;
42 
45  using item_checker = std::function<bool(size_t, const aabb_type& aabb)>;
46 
47  ndim_tree() = default;
48  ndim_tree(size_t depth,
49  const item_checker& callback,
50  const util::aligned::vector<size_t>& to_test,
51  const aabb_type& aabb)
52  : aabb_{aabb}
53  , items_{compute_contained_items(callback, to_test, aabb)}
54  , nodes_{compute_nodes(depth, callback, items_, aabb)} {}
55 
56  aabb_type get_aabb() const { return aabb_; }
57  bool has_nodes() const { return nodes_ != nullptr; }
58  const node_array& get_nodes() const { return *nodes_; }
59  util::aligned::vector<size_t> get_items() const { return items_; }
60 
61  size_t get_side() const {
62  return nodes_ ? 2 * nodes_->front().get_side() : 1;
63  }
64 
65 private:
66  using next_boundaries_type = std::array<aabb_type, (1 << n)>;
67 
68  static util::aligned::vector<size_t> compute_contained_items(
69  const item_checker& callback,
70  const util::aligned::vector<size_t>& to_test,
71  const aabb_type& aabb) {
72  util::aligned::vector<size_t> ret;
73  std::copy_if(begin(to_test),
74  end(to_test),
75  std::back_inserter(ret),
76  [&](auto i) { return callback(i, aabb); });
77  return ret;
78  }
79 
80  static std::unique_ptr<node_array> compute_nodes(
81  size_t depth,
82  const item_checker& callback,
83  const util::aligned::vector<size_t>& to_test,
84  const aabb_type& aabb) {
85  if (!depth) {
86  return nullptr;
87  }
88 
89  const auto next = detail::next_boundaries<n>(aabb);
90  auto ret = std::make_unique<std::array<ndim_tree, (1 << n)>>();
91  std::transform(
92  begin(next), end(next), ret->begin(), [&](const auto& i) {
93  return ndim_tree(depth - 1, callback, to_test, i);
94  });
95  return ret;
96  }
97 
98  aabb_type aabb_; // the bounding box of the node
99  util::aligned::vector<size_t> items_; // indices of contained items
100  std::unique_ptr<node_array> nodes_; // contained nodes
101 };
102 } // namespace core
103 } // namespace wayverb
std::function< bool(size_t, const aabb_type &aabb)> item_checker
Definition: ndim_tree.h:45
A generic interface for spatial division algorithms (octree, quadtree)
Definition: ndim_tree.h:38
Definition: voxel_structs.h:9
Definition: traits.cpp:2
Definition: range.h:12
Definition: traits.h:46
Definition: capsule_base.h:9