1#ifndef TATOOINE_CELLTREE_H
2#define TATOOINE_CELLTREE_H
20template <
typename Celltree,
typename Real, std::size_t NumDimensions,
21 std::size_t NumVerticesPerSimplex>
24template <
typename Celltree,
typename real_type>
32 return *
dynamic_cast<Celltree const*
>(
this);
37 auto const& c = as_celltree();
38 auto cur_aabb = c.axis_aligned_bounding_box();
46 std::vector<std::size_t>& possible_collisions)
const ->
void {
47 auto const& c = as_celltree();
48 auto const& n = c.node(ni);
50 auto const begin_it =
begin(c.cell_handles()) + n.as_leaf().start;
51 auto const end_it = begin_it + n.as_leaf().size;
53 std::copy(begin_it, end_it, std::back_inserter(possible_collisions));
56 auto sub_aabb = cur_aabb;
57 sub_aabb.min(n.dim) = n.as_split().right_min;
58 if (sub_aabb.check_intersection(r)) {
59 collect_possible_intersections(r, n.right_child_index(), sub_aabb,
64 auto sub_aabb = cur_aabb;
65 sub_aabb.max(n.dim) = n.as_split().left_max;
66 if (sub_aabb.check_intersection(r)) {
67 collect_possible_intersections(r, n.left_child_index(), sub_aabb,
75 auto const& c = as_celltree();
77 std::vector<std::size_t> possible_collisions;
78 if (cur_aabb.check_intersection(r)) {
79 collect_possible_intersections(r, 0, cur_aabb, possible_collisions);
81 return possible_collisions;
87template <
typename Mesh>
90 Mesh::num_dimensions(),
91 Mesh::num_vertices_per_simplex()> {
94 Mesh::num_vertices_per_simplex()>;
96 static constexpr auto
num_dimensions() -> std::size_t {
return Mesh::num_dimensions(); }
98 return Mesh::num_vertices_per_simplex();
132 as_leaf().start = other.as_leaf().start;
133 as_leaf().size = other.as_leaf().size;
135 as_split().left_max = other.as_split().left_max;
136 as_split().right_min = other.as_split().right_min;
143 as_leaf().start = other.as_leaf().start;
144 as_leaf().size = other.as_leaf().size;
146 as_split().left_max = other.as_split().left_max;
147 as_split().right_min = other.as_split().right_min;
199 auto& initial_node =
m_nodes.emplace_back();
201 initial_node.as_leaf().start = 0;
213 auto& initial_node =
m_nodes.emplace_back();
215 initial_node.as_leaf().start = 0;
216 initial_node.as_leaf().size =
222 constexpr auto mesh() const -> auto const& {
return *
m_mesh; }
224 constexpr auto node(std::size_t
const i)
const ->
auto const& {
233 constexpr auto node(std::size_t
const i) ->
auto& {
return m_nodes[i]; }
238 template <std::size_t... Seq>
240 std::uint8_t
const dim,
241 std::index_sequence<Seq...> )
const {
242 auto const cell_vertex_handles =
mesh().simplex_at(cell_idx);
246 template <std::size_t... Seq>
248 std::uint8_t
const dim,
249 std::index_sequence<Seq...> )
const {
250 auto const cell_vertex_handles =
mesh().simplex_at(cell_idx);
254 template <std::size_t... Seq>
255 constexpr auto cell_center(std::size_t
const cell_idx, std::uint8_t
const dim,
256 std::index_sequence<Seq...> )
const {
257 auto const cell_vertex_handles =
mesh().simplex_at(cell_idx);
266 return mesh().axis_aligned_bounding_box();
270 std::vector<std::size_t> cells;
277 template <std::size_t... Seq>
279 std::vector<std::size_t>& cells,
280 std::index_sequence<Seq...> seq)
const ->
void {
281 auto const& n =
node(cur_node_idx);
283 auto const vertex_handles =
mesh().simplex_at(n.as_leaf().start);
285 Mesh::num_vertices_per_simplex()>::ones();
288 ((A(Seq, i) =
mesh()[std::get<Seq>(vertex_handles)](i)), ...);
293 auto const barycentric_coordinates = *
solve(A, b);
294 auto is_inside =
true;
296 for (std::size_t i = 0; i < Mesh::num_vertices_per_simplex(); ++i) {
297 is_inside &= barycentric_coordinates(0) >= -eps;
298 is_inside &= barycentric_coordinates(0) <= 1 + eps;
303 std::back_inserter(cells));
306 if (x(n.dim) <= n.as_split().left_max &&
307 x(n.dim) < n.as_split().right_min) {
308 cells_at(x, n.left_child_index(), cells, seq);
309 }
else if (x(n.dim) >= n.as_split().right_min &&
310 x(n.dim) > n.as_split().left_max) {
311 cells_at(x, n.right_child_index(), cells, seq);
312 }
else if (x(n.dim) <= n.as_split().left_max &&
313 x(n.dim) >= n.as_split().right_min) {
315 cells_at(x, n.left_child_index(), cells, seq);
316 cells_at(x, n.right_child_index(), cells, seq);
322 template <std::size_t... Seq>
324 std::index_sequence<Seq...> )
const {
325 assert(
node(ni).is_leaf());
326 auto aabb = make_array<num_dimensions()>(std::tuple{
328 std::numeric_limits<typename node_type::float_type>::max(),
329 -std::numeric_limits<typename node_type::float_type>::max()});
331 std::get<0>(
aabb[dim]) =
static_cast<std::uint8_t
>(dim);
334 auto const end_it = begin_it +
node(ni).as_leaf().size;
335 for (
auto cell_it = begin_it; cell_it != end_it; ++cell_it) {
336 auto const cell_vertex_handles =
mesh().simplex_at(*cell_it);
339 mesh()[std::get<Seq>(cell_vertex_handles)](dim)...);
341 mesh()[std::get<Seq>(cell_vertex_handles)](dim)...);
344 auto split_dim = std::numeric_limits<std::uint8_t>::max();
348 auto const extent =
max -
min;
349 if (extent > max_extent) {
354 return aabb[split_dim];
359 assert(
node(ni).is_leaf());
360 std::size_t left_child_index;
363 left_child_index =
nodes().size();
364 node(ni).set_left_child_index(left_child_index);
365 nodes().emplace_back();
366 nodes().emplace_back();
368 return left_child_index;
371 template <std::size_t... Seq>
373 std::size_t
const max_level) {
374 if (
node(ni).as_leaf().
size > 1 && level < max_level) {
375 std::cout <<
"splitting node at index " << ni <<
'\n';
376 split(ni, level, max_level);
378 std::cout <<
"leaf at level " << level <<
"[" <<
node(ni).as_leaf().start
379 <<
", " <<
node(ni).as_leaf().size <<
"]" <<
'\n';
383 template <std::size_t... Seq>
384 auto split(std::size_t
const ni, std::size_t
const level, std::size_t
const max_level) {
385 split(ni, level, max_level,
389 template <std::size_t... Seq>
390 auto split(std::size_t
const ni, std::size_t
const level, std::size_t
const max_level,
391 std::index_sequence<Seq...> seq) ->
void {
392 assert(
node(ni).is_leaf());
394 auto const ri = li + 1;
405 template <std::size_t... Seq>
407 std::uint8_t
const split_dim,
408 std::index_sequence<Seq...> seq) {
411 auto const cur_start =
node(ni).as_leaf().start;
412 auto const cur_size =
node(ni).as_leaf().size;
413 auto const lstart = cur_start;
414 auto const lsize = cur_size / 2;
415 auto const rstart = lstart + lsize;
416 auto const rsize = cur_size - lsize;
419 assert(lsize + rsize == cur_size);
420 assert(rstart + rsize == cur_start + cur_size);
423 node(li).as_leaf().start = lstart;
424 node(li).as_leaf().size = lsize;
427 node(ri).as_leaf().start = rstart;
428 node(ri).as_leaf().size = rsize;
430 node(ni).dim = split_dim;
431 node(ni).as_split().left_max = lmax;
432 node(ni).as_split().right_min = rmin;
436 template <std::size_t... Seq>
440 std::index_sequence<Seq...> seq) {
443 auto min_cost = std::numeric_limits<real_type>::max();
444 auto best_lsize = std::numeric_limits<std::uint32_t>::max();
445 auto cur_lsize = std::uint32_t(1);
448 auto const end_it = start_it +
node(ni).as_leaf().size - 1;
449 for (
auto cell_it = start_it; cell_it != end_it; ++cell_it) {
452 auto const cur_cost =
453 (cur_lmax -
min) * cur_lsize -
454 (
max - cur_rmin) * (
node(ni).as_leaf().size - cur_lsize);
456 if (cur_cost < min_cost) {
458 best_lmax = cur_lmax;
459 best_rmin = cur_rmin;
460 best_lsize = cur_lsize;
466 node(li).as_leaf().start =
node(ni).as_leaf().start;
467 node(li).as_leaf().size = best_lsize;
470 node(ri).as_leaf().start =
node(ni).as_leaf().start + best_lsize;
471 node(ri).as_leaf().size =
node(ni).as_leaf().size - best_lsize;
473 node(ni).dim = split_dim;
474 node(ni).as_split().left_max = best_lmax;
475 node(ni).as_split().right_min = best_rmin;
479 template <std::size_t... Seq>
481 std::index_sequence<Seq...> seq) {
482 auto comparator = [
this, ni, dim, seq](
auto const i,
auto const j) {
486 auto const end_it = begin_it +
node(ni).as_leaf().size;
487 std::sort(begin_it, end_it, comparator);
494 std::vector<vec<real_type, 3>> positions;
495 std::vector<std::vector<std::size_t>>
indices;
498 parent_bounding_box);
499 f.write_points(positions);
506 std::vector<std::vector<std::size_t>>&
indices, std::size_t cur_node_idx,
509 std::size_t cur_level = 0, std::size_t cur_idx = 0) -> std::size_t {
510 if (
node(cur_node_idx).is_leaf()) {
520 {cur_idx, cur_idx + 1, cur_idx + 2, cur_idx + 3, cur_idx});
522 {cur_idx + 4, cur_idx + 5, cur_idx + 6, cur_idx + 7, cur_idx + 4});
523 indices.push_back({cur_idx, cur_idx + 4});
524 indices.push_back({cur_idx + 1, cur_idx + 5});
525 indices.push_back({cur_idx + 2, cur_idx + 6});
526 indices.push_back({cur_idx + 3, cur_idx + 7});
529 auto sub_aabb =
aabb;
530 sub_aabb.max(
node(cur_node_idx).dim) =
531 node(cur_node_idx).as_split().left_max;
533 positions,
indices,
node(cur_node_idx).left_child_index(), sub_aabb,
534 cur_level + 1, cur_idx);
536 sub_aabb.max(
node(cur_node_idx).dim) =
aabb.
max(
node(cur_node_idx).dim);
537 sub_aabb.min(
node(cur_node_idx).dim) =
538 node(cur_node_idx).as_split().right_min;
540 positions,
indices,
node(cur_node_idx).right_child_index(), sub_aabb,
541 cur_level + 1, cur_idx);
547template <
typename Mesh>
549template <
typename Mesh,
typename Real, std::
size_t NumDimensions>
554template <
typename Mesh>
562 return is_celltree<std::decay_t<T>>();
Definition: vtk_legacy.h:448
Definition: vtp_writer.h:3
Definition: algorithm.h:6
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322
constexpr auto is_celltree()
Definition: celltree.h:557
axis_aligned_bounding_box< Real, NumDimensions > aabb
Definition: axis_aligned_bounding_box.h:553
auto solve(polynomial< Real, 1 > const &p) -> std::vector< Real >
solve a + b*x
Definition: polynomial.h:187
constexpr auto max(A &&a, B &&b)
Definition: math.h:20
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
auto next(Iter iter)
Definition: iterator_facade.h:325
constexpr auto min(A &&a, B &&b)
Definition: math.h:15
Definition: axis_aligned_bounding_box.h:103
pos_type m_min
Definition: axis_aligned_bounding_box.h:118
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
Definition: celltree.h:111
index_type size
Definition: celltree.h:112
index_type start
Definition: celltree.h:112
Definition: celltree.h:108
float_type left_max
Definition: celltree.h:109
float_type right_min
Definition: celltree.h:109
Definition: celltree.h:104
auto as_leaf() const -> auto const &
Definition: celltree.h:164
type_t type
Definition: celltree.h:125
auto set_left_child_index(std::size_t const i)
Definition: celltree.h:159
double float_type
Definition: celltree.h:105
constexpr auto operator=(node_type const &other) noexcept -> node_type &
Definition: celltree.h:139
constexpr auto is_leaf() const
Definition: celltree.h:150
auto as_split() -> auto &
Definition: celltree.h:168
constexpr node_type()=default
std::uint8_t dim
Definition: celltree.h:119
auto as_leaf() -> auto &
Definition: celltree.h:160
auto right_child_index() const
Definition: celltree.h:155
auto left_child_index() const
Definition: celltree.h:151
constexpr node_type(node_type const &other) noexcept
Definition: celltree.h:129
std::uint32_t index_type
Definition: celltree.h:106
std::size_t m_left_child_index
Definition: celltree.h:122
auto as_split() const -> auto const &
Definition: celltree.h:172
Definition: celltree.h:91
std::vector< std::size_t > m_cell_handles
Definition: celltree.h:182
auto cells_at(vec_t const &x) const
Definition: celltree.h:269
auto write_vtk_collect_positions_and_indices(std::vector< vec< real_type, num_dimensions()> > &positions, std::vector< std::vector< std::size_t > > &indices, std::size_t cur_node_idx, tatooine::axis_aligned_bounding_box< real_type, num_dimensions()> const &aabb, std::size_t cur_level=0, std::size_t cur_idx=0) -> std::size_t
Definition: celltree.h:504
celltree(celltree const &)=default
celltree(celltree &&) noexcept=default
constexpr auto min_cell_boundary(std::size_t const cell_idx, std::uint8_t const dim, std::index_sequence< Seq... >) const
Definition: celltree.h:239
constexpr auto indices() -> auto &
Definition: celltree.h:235
constexpr auto axis_aligned_bounding_box() const
Definition: celltree.h:265
auto cells_at(vec_t const &x, std::size_t const cur_node_idx, std::vector< std::size_t > &cells, std::index_sequence< Seq... > seq) const -> void
Definition: celltree.h:278
Mesh const * m_mesh
Definition: celltree.h:180
static constexpr auto num_vertices_per_simplex()
Definition: celltree.h:97
constexpr auto node(std::size_t const i) const -> auto const &
Definition: celltree.h:224
vec< real_type, num_dimensions()> m_max
Definition: celltree.h:183
auto add_children(std::size_t const ni)
Definition: celltree.h:358
auto split_with_median(std::size_t const ni, std::size_t const li, std::size_t const ri, std::uint8_t const split_dim, std::index_sequence< Seq... > seq)
Definition: celltree.h:406
auto split(std::size_t const ni, std::size_t const level, std::size_t const max_level, std::index_sequence< Seq... > seq) -> void
Definition: celltree.h:390
constexpr auto nodes() const -> auto const &
Definition: celltree.h:227
auto split_with_heuristic(std::size_t const ni, std::size_t const li, std::size_t const ri, std::uint8_t const split_dim, real_type const min, real_type const max, std::index_sequence< Seq... > seq)
TODO heuristic not working correctly.
Definition: celltree.h:437
static constexpr auto num_dimensions() -> std::size_t
Definition: celltree.h:96
celltree(Mesh const &mesh, vec< real_type, num_dimensions()> const &min, vec< real_type, num_dimensions()> const &max)
Definition: celltree.h:206
constexpr auto mesh() -> auto &
Definition: celltree.h:231
auto sort_indices(std::size_t const ni, std::uint8_t const dim, std::index_sequence< Seq... > seq)
Definition: celltree.h:480
auto split_if_necessary(std::size_t const ni, std::size_t const level, std::size_t const max_level)
Definition: celltree.h:372
constexpr auto indices() const -> auto const &
Definition: celltree.h:228
auto write_vtk(filesystem::path const &path)
Definition: celltree.h:491
vec< real_type, num_dimensions()> m_min
Definition: celltree.h:183
constexpr auto nodes() -> auto &
Definition: celltree.h:234
constexpr auto max_cell_boundary(std::size_t const cell_idx, std::uint8_t const dim, std::index_sequence< Seq... >) const
Definition: celltree.h:247
typename Mesh::real_type real_type
Definition: celltree.h:95
constexpr auto node(std::size_t const i) -> auto &
Definition: celltree.h:233
constexpr auto cell_handles() const -> auto const &
Definition: celltree.h:223
auto split_dimension(std::size_t const ni, std::index_sequence< Seq... >) const
Definition: celltree.h:323
constexpr auto cell_center(std::size_t const cell_idx, std::uint8_t const dim, std::index_sequence< Seq... >) const
Definition: celltree.h:255
std::vector< node_type > m_nodes
Definition: celltree.h:181
constexpr auto cell_handles() -> auto &
Definition: celltree.h:232
constexpr auto mesh() const -> auto const &
Definition: celltree.h:222
auto split(std::size_t const ni, std::size_t const level, std::size_t const max_level)
Definition: celltree.h:384
auto as_celltree() const -> auto const &
Definition: celltree.h:31
auto collect_possible_intersections(ray< real_type, 3 > const &r, std::size_t const ni, tatooine::axis_aligned_bounding_box< real_type, 3 > const &cur_aabb, std::vector< std::size_t > &possible_collisions) const -> void
Definition: celltree.h:43
auto collect_possible_intersections(ray< real_type, 3 > const &r) const
Definition: celltree.h:74
auto check_intersection(ray_type const &, real_type const =0) const -> optional_intersection_type override
Definition: celltree.h:34
Definition: celltree.h:22
Definition: celltree.h:553
auto axis_aligned_bounding_box() const
Definition: pointset.h:183
Definition: ray_intersectable.h:10
std::optional< intersection_type > optional_intersection_type
Definition: ray_intersectable.h:14
real_type real_type
Definition: ray_intersectable.h:11
auto simplices() const
Definition: unstructured_simplicial_grid.h:515
Definition: celltree.h:114
split_node_t split
Definition: celltree.h:115
leaf_node_type leaf
Definition: celltree.h:116