Tatooine
kdtree.h
Go to the documentation of this file.
1#ifndef TATOOINE_KDTREE_H
2#define TATOOINE_KDTREE_H
3//==============================================================================
6
7#include <functional>
8#include <set>
9//==============================================================================
10namespace tatooine {
11//==============================================================================
12template <typename Mesh>
13struct kdtree : aabb<typename Mesh::real_type, Mesh::num_dimensions()> {
14 static constexpr auto num_dimensions() -> std::size_t { return Mesh::num_dimensions(); }
15 using real_type = typename Mesh::real_type;
20 using parent_type::max;
21 using parent_type::min;
22 using typename parent_type::vec_type;
23 using vertex_handle = typename Mesh::vertex_handle;
24 friend class std::unique_ptr<this_type>;
26
27 private:
28 Mesh const* m_mesh;
29 size_t m_level;
31 std::vector<vertex_handle> m_vertex_handles;
32 std::vector<size_t> m_triangle_handles;
33 std::array<std::unique_ptr<kdtree>, 2> m_children;
34 static constexpr size_t default_max_depth = 64;
35
36 public:
37 explicit kdtree(Mesh const& mesh, size_t const max_depth = default_max_depth)
38 : m_mesh{&mesh}, m_level{0}, m_max_depth{max_depth} {
39 auto min = vec_type::ones() * std::numeric_limits<real_type>::infinity();
40 auto max = -vec_type::ones() * std::numeric_limits<real_type>::infinity();
41 for (auto v : mesh.vertices()) {
42 for (size_t i = 0; i < num_dimensions(); ++i) {
43 min(i) = std::min(min(i), mesh[v](i));
44 max(i) = std::max(max(i), mesh[v](i));
45 }
46 }
47 this->min() = min;
48 this->max() = max;
49
50 m_vertex_handles.resize(mesh.vertices().size());
53 }
54 virtual ~kdtree() = default;
55
56 private:
57 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58 kdtree(Mesh const& mesh, vec_type const& min, vec_type const& max,
59 size_t const level, size_t const max_depth)
61 m_mesh{&mesh},
62 m_level{level},
63 m_max_depth{max_depth} {}
64
65 public:
66 auto mesh() const -> auto const& { return *m_mesh; }
67 //------------------------------------------------------------------------------
68 auto num_vertex_handles() const { return size(m_vertex_handles); }
70 //------------------------------------------------------------------------------
71 // auto insert_vertex(size_t const vertex_idx) -> bool {
72 // if (!is_inside(mesh().vertex_at(vertex_idx))) {
73 // return false;
74 // }
75 // if (is_splitted()) {
76 // if ()
77 // } else {
78 // m_vertex_handles.push_back(vertex_idx);
79 // split_if_necessary();
80 // }
81 // return true;
82 //}
83 //----------------------------------------------------------------------------
84 auto split_if_necessary() -> void {
85 if (num_vertex_handles() > 1 && !is_at_max_depth()) {
86 split();
87 }
88 }
89 //----------------------------------------------------------------------------
90 constexpr auto is_splitted() const { return m_children.front() != nullptr; }
91 constexpr auto holds_vertices() const { return !m_vertex_handles.empty(); }
92 constexpr auto is_at_max_depth() const { return m_level == m_max_depth; }
93
94 private:
95 //----------------------------------------------------------------------------
96 auto distribute_vertices(size_t const split_index,
97 real_type const split_pos) {
98 for (auto const v : m_vertex_handles) {
99 if (mesh()[v](split_index) <= split_pos) {
100 m_children[0]->m_vertex_handles.push_back(v);
101 }
102 if (mesh()[v](split_index) >= split_pos) {
103 m_children[1]->m_vertex_handles.push_back(v);
104 }
105 }
106 m_vertex_handles.clear();
107 }
108 //----------------------------------------------------------------------------
109 auto split() {
110 auto min0 = this->min();
111 auto max0 = this->max();
112 auto min1 = this->min();
113 auto max1 = this->max();
114 auto split_index = std::numeric_limits<size_t>::max();
115 auto split_pos = std::numeric_limits<real_type>::max();
116 auto max_space_range = real_type(0);
117 auto dim_positions = std::vector<real_type>{};
118
119 for (size_t i = 0; i < num_dimensions(); ++i) {
120 for (auto const v : m_vertex_handles) {
121 dim_positions.push_back(mesh()[v](i));
122 }
123 std::sort(begin(dim_positions), end(dim_positions));
124 if (auto const space = dim_positions.back() - dim_positions.front();
125 space > max_space_range) {
126 max_space_range = space;
127 split_index = i;
128
129 size_t const i0 = size(dim_positions) / 2;
130 split_pos = (dim_positions[i0] + dim_positions[i0 - 1]) / 2;
131 }
132 dim_positions.clear();
133 }
134 assert(split_index != std::numeric_limits<size_t>::max());
135 max0(split_index) = split_pos;
136 min1(split_index) = split_pos;
137
138 m_children[0] = std::unique_ptr<this_type>(
139 new this_type{mesh(), min0, max0, m_level + 1, m_max_depth});
140 m_children[1] = std::unique_ptr<this_type>(
141 new this_type{mesh(), min1, max1, m_level + 1, m_max_depth});
142 distribute_vertices(split_index, split_pos);
143 m_children[0]->split_if_necessary();
144 m_children[1]->split_if_necessary();
145 }
146 //----------------------------------------------------------------------------
147 public:
148 auto write_vtk(filesystem::path const& path) {
150 f.write_header();
151 std::vector<vec<real_type, num_dimensions()>> positions;
152 std::vector<std::vector<size_t>> indices;
153 write_vtk_collect_positions_and_indices(positions, indices);
154 f.write_points(positions);
155 f.write_lines(indices);
156 }
157 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158 private:
160 std::vector<vec<real_type, num_dimensions()>>& positions,
161 std::vector<std::vector<size_t>>& indices, size_t cur_idx = 0) -> size_t {
162 if constexpr (num_dimensions() == 2) {
163 positions.push_back(vec{min(0), min(1)});
164 positions.push_back(vec{max(0), min(1)});
165 positions.push_back(vec{max(0), max(1)});
166 positions.push_back(vec{min(0), max(1)});
167 indices.push_back(
168 {cur_idx, cur_idx + 1, cur_idx + 2, cur_idx + 3, cur_idx});
169 cur_idx += 4;
170 if (is_splitted()) {
171 for (auto& child : m_children) {
172 cur_idx = child->write_vtk_collect_positions_and_indices(
173 positions, indices, cur_idx);
174 }
175 }
176 return cur_idx;
177 } else if constexpr (num_dimensions() == 3) {
178 positions.push_back(vec{min(0), min(1), min(2)});
179 positions.push_back(vec{max(0), min(1), min(2)});
180 positions.push_back(vec{max(0), max(1), min(2)});
181 positions.push_back(vec{min(0), max(1), min(2)});
182 positions.push_back(vec{min(0), min(1), max(2)});
183 positions.push_back(vec{max(0), min(1), max(2)});
184 positions.push_back(vec{max(0), max(1), max(2)});
185 positions.push_back(vec{min(0), max(1), max(2)});
186 indices.push_back(
187 {cur_idx, cur_idx + 1, cur_idx + 2, cur_idx + 3, cur_idx});
188 indices.push_back(
189 {cur_idx + 4, cur_idx + 5, cur_idx + 6, cur_idx + 7, cur_idx + 4});
190 indices.push_back({cur_idx, cur_idx + 4});
191 indices.push_back({cur_idx + 1, cur_idx + 5});
192 indices.push_back({cur_idx + 2, cur_idx + 6});
193 indices.push_back({cur_idx + 3, cur_idx + 7});
194 cur_idx += 8;
195 if (is_splitted()) {
196 for (auto& child : m_children) {
197 cur_idx = child->write_vtk_collect_positions_and_indices(
198 positions, indices, cur_idx);
199 }
200 }
201 return cur_idx;
202 }
203 }
204};
205template <typename T>
206struct is_kdtree_impl : std::false_type {};
207template <typename Mesh>
208struct is_kdtree_impl<kdtree<Mesh>> : std::true_type {};
209template <typename T>
210constexpr auto is_kdtree() {
211 return is_kdtree_impl<std::decay_t<T>>::value;
212}
213template <typename T>
214constexpr auto is_kdtree(T&&) {
215 return is_kdtree<std::decay_t<T>>();
216}
217//==============================================================================
218} // namespace tatooine
219//==============================================================================
220#endif
Definition: mesh.h:16
auto & vertices(face f)
Definition: mesh.h:427
Definition: vtk_legacy.h:448
Definition: algorithm.h:6
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
constexpr auto is_kdtree()
Definition: kdtree.h:210
Definition: axis_aligned_bounding_box.h:103
vec< Real, NumDimensions > vec_type
Definition: axis_aligned_bounding_box.h:108
auto constexpr is_inside(pos_type const &p) const
Definition: axis_aligned_bounding_box.h:191
auto constexpr max() const -> auto const &
Definition: axis_aligned_bounding_box.h:156
auto constexpr min() const -> auto const &
Definition: axis_aligned_bounding_box.h:151
constexpr auto is_simplex_inside(vec< Real, 2 > const &x0, vec< Real, 2 > const &x1, vec< Real, 2 > const &x2) const
Definition: axis_aligned_bounding_box.h:254
Definition: kdtree.h:206
Definition: kdtree.h:13
auto num_triangle_handles() const
Definition: kdtree.h:69
static constexpr auto num_dimensions() -> std::size_t
Definition: kdtree.h:14
auto mesh() const -> auto const &
Definition: kdtree.h:66
typename Mesh::real_type real_type
Definition: kdtree.h:15
size_t m_max_depth
Definition: kdtree.h:30
auto split_if_necessary() -> void
Definition: kdtree.h:84
size_t m_level
Definition: kdtree.h:29
auto constexpr max() const -> auto const &
Definition: axis_aligned_bounding_box.h:156
std::array< std::unique_ptr< kdtree >, 2 > m_children
Definition: kdtree.h:33
constexpr auto is_at_max_depth() const
Definition: kdtree.h:92
constexpr auto holds_vertices() const
Definition: kdtree.h:91
static constexpr size_t default_max_depth
Definition: kdtree.h:34
typename Mesh::vertex_handle vertex_handle
Definition: kdtree.h:23
Mesh const * m_mesh
Definition: kdtree.h:28
auto constexpr min() const -> auto const &
Definition: axis_aligned_bounding_box.h:151
std::vector< vertex_handle > m_vertex_handles
Definition: kdtree.h:31
auto write_vtk_collect_positions_and_indices(std::vector< vec< real_type, num_dimensions()> > &positions, std::vector< std::vector< size_t > > &indices, size_t cur_idx=0) -> size_t
Definition: kdtree.h:159
auto distribute_vertices(size_t const split_index, real_type const split_pos)
Definition: kdtree.h:96
auto num_vertex_handles() const
Definition: kdtree.h:68
kdtree(Mesh const &mesh, vec_type const &min, vec_type const &max, size_t const level, size_t const max_depth)
Definition: kdtree.h:58
auto split()
Definition: kdtree.h:109
constexpr auto is_splitted() const
Definition: kdtree.h:90
auto write_vtk(filesystem::path const &path)
Definition: kdtree.h:148
virtual ~kdtree()=default
kdtree(Mesh const &mesh, size_t const max_depth=default_max_depth)
Definition: kdtree.h:37
std::vector< size_t > m_triangle_handles
Definition: kdtree.h:32
static auto constexpr ones()
Definition: vec.h:28