EasyNav Plugins
Loading...
Searching...
No Matches
bonxai.hpp
Go to the documentation of this file.
1/*
2 * Copyright Contributors to the Bonxai Project
3 * Copyright Contributors to the OpenVDB Project
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
8 */
9
10#pragma once
11
12#include <algorithm>
13#include <cmath>
14#include <cstdint>
15#include <limits>
16#include <memory>
17#include <stdexcept>
18#include <type_traits>
19#include <unordered_map>
20#include <utility>
21#include <vector>
22
23#include "grid_allocator.hpp"
24#include "grid_coord.hpp"
25#include "mask.hpp"
26
27namespace Bonxai
28{
29
30// empty data structure used exclusively in BinaryVoxelGrid
31struct EmptyVoxel {};
32
40template<typename DataT>
41class Grid {
42private:
43 uint8_t dim_ = 0;
44 // total number of elements in the cube
45 uint32_t size_ = 0;
46
47 DataT * data_ = nullptr;
48 Bonxai::Mask mask_;
49 bool external_memory_ = false;
50
51public:
52 Grid(size_t log2dim)
53 : dim_(1 << log2dim),
54 mask_(log2dim)
55 {
56 if constexpr (!std::is_same_v<DataT, EmptyVoxel>) {
57 size_ = dim_ * dim_ * dim_;
58 data_ = new DataT[size_];
59 }
60 }
61
62 Grid(size_t log2dim, DataT * preAllocatedMemory)
63 : dim_(1 << log2dim),
64 data_(preAllocatedMemory),
65 mask_(log2dim),
66 external_memory_(true) {}
67
68 Grid(const Grid & other) = delete;
69 Grid & operator=(const Grid & other) = delete;
70
71 Grid(Grid && other);
72 Grid & operator=(Grid && other);
73
75 {
76 if (data_ != nullptr && !external_memory_) {
77 delete[] data_;
78 }
79 }
80
81 [[nodiscard]] size_t memUsage() const;
82
83 [[nodiscard]] size_t size() const
84 {
85 return size_;
86 }
87
88 [[nodiscard]] Bonxai::Mask & mask()
89 {
90 return mask_;
91 }
92
93 [[nodiscard]] const Bonxai::Mask & mask() const
94 {
95 return mask_;
96 }
97
98 [[nodiscard]] DataT & cell(size_t index)
99 {
100 static_assert(
101 !std::is_same_v<DataT, EmptyVoxel>, "Cells have no value, when DataT == EmptyVoxel");
102 return data_[index];
103 }
104
105 [[nodiscard]] const DataT & cell(size_t index) const
106 {
107 static_assert(
108 !std::is_same_v<DataT, EmptyVoxel>, "Cells have no value, when DataT == EmptyVoxel");
109 return data_[index];
110 }
111};
112
113//----------------------------------------------------------
114
116{
117 // reset the entire grid, freeing all the memory allocated so far
119 // keep the memory allocated, but set all the cells to OFF
121};
122
123template<typename DataT>
125private:
126 uint32_t INNER_BITS;
127 uint32_t LEAF_BITS;
128 uint32_t Log2N;
129 double resolution;
130 double inv_resolution;
131 uint32_t INNER_MASK;
132 uint32_t LEAF_MASK;
133
134 GridBlockAllocator<DataT> leaf_block_allocator_;
135
136public:
139 using RootMap = std::unordered_map<CoordT, InnerGrid>;
140
147 explicit VoxelGrid(double voxel_size, uint8_t inner_bits = 2, uint8_t leaf_bits = 3);
148
149 VoxelGrid(const VoxelGrid &) = delete;
150 VoxelGrid & operator=(const VoxelGrid &) = delete;
151
152 VoxelGrid(VoxelGrid && other) = default;
153 VoxelGrid & operator=(VoxelGrid && other) = default;
154
155 uint32_t innetBits() const
156 {
157 return INNER_BITS;
158 }
159 uint32_t leafBits() const
160 {
161 return LEAF_BITS;
162 }
163 double voxelSize() const
164 {
165 return resolution;
166 }
167
168 const RootMap & rootMap() const
169 {
170 return root_map;
171 }
173 {
174 return root_map;
175 }
176
178 [[nodiscard]] size_t memUsage() const;
179
186
188 [[nodiscard]] size_t activeCellsCount() const;
189
191 [[nodiscard]] CoordT posToCoord(double x, double y, double z) const;
192
194 [[nodiscard]] CoordT posToCoord(const Point3D & pos) const
195 {
196 return posToCoord(pos.x, pos.y, pos.z);
197 }
198
200 [[nodiscard]] Point3D coordToPos(const CoordT & coord) const;
201
209 template<class VisitorFunction>
210 void forEachCell(VisitorFunction func) const;
211
219 template<class VisitorFunction>
220 void forEachCell(VisitorFunction func)
221 {
222 static_cast<const VoxelGrid *>(this)->forEachCell(func);
223 }
224
226
227 // You should never use this function directly. It is exposed in the public API only
228 // for special cases, such as serialization or testing
229 std::shared_ptr<LeafGrid> allocateLeafGrid();
230
232public:
234 : grid_(grid) {}
235
241 [[nodiscard]] const DataT * value(const CoordT & coord) const;
242
247 [[nodiscard]] bool isCellOn(const CoordT & coord) const;
248
250 [[nodiscard]] const InnerGrid * lastInnerGrid() const
251 {
252 return prev_inner_ptr_;
253 }
254
256 [[nodiscard]] const LeafGrid * lastLeafGrid() const
257 {
258 return prev_leaf_ptr_;
259 }
260
261 [[nodiscard]] const LeafGrid * getLeafGrid(const CoordT & coord) const;
262
263protected:
265 mutable CoordT prev_root_coord_ = {std::numeric_limits<int32_t>::max(), 0, 0};
266 mutable CoordT prev_inner_coord_ = {std::numeric_limits<int32_t>::max(), 0, 0};
267 mutable const InnerGrid * prev_inner_ptr_ = nullptr;
268 mutable const LeafGrid * prev_leaf_ptr_ = nullptr;
269 };
270
276 class Accessor : public ConstAccessor {
277public:
279 : ConstAccessor(grid),
280 mutable_grid_(grid) {}
281
289 bool setValue(const CoordT & coord, const DataT & value);
290
296 [[nodiscard]] DataT * value(const CoordT & coord, bool create_if_missing = false);
297
306 bool setCellOn(const CoordT & coord, const DataT & default_value = DataT());
307
313 bool setCellOff(const CoordT & coord);
314
323 [[nodiscard]] LeafGrid * getLeafGrid(const CoordT & coord, bool create_if_missing = false);
324
325private:
326 VoxelGrid & mutable_grid_;
327 CoordT prev_root_coord_ = {std::numeric_limits<int32_t>::max(), 0, 0};
328 CoordT prev_inner_coord_ = {std::numeric_limits<int32_t>::max(), 0, 0};
329 InnerGrid * prev_inner_ptr_ = nullptr;
330 LeafGrid * prev_leaf_ptr_ = nullptr;
331 };
332
333 Accessor createAccessor()
334 {
335 return Accessor(*this);
336 }
337
338 ConstAccessor createConstAccessor() const
339 {
340 return ConstAccessor(*this);
341 }
342
343 [[nodiscard]] CoordT getRootKey(const CoordT & coord) const;
344
345 [[nodiscard]] CoordT getInnerKey(const CoordT & coord) const;
346
347 [[nodiscard]] uint32_t getInnerIndex(const CoordT & coord) const;
348
349 [[nodiscard]] uint32_t getLeafIndex(const CoordT & coord) const;
350
351private:
352 RootMap root_map;
353};
354
356
357//----------------------------------------------------
358//----------------- Implementations ------------------
359//----------------------------------------------------
360
361template<typename DataT>
362inline Grid<DataT>::Grid(Grid && other)
363: dim_(other.dim_),
364 size_(other.size_),
365 mask_(std::move(other.mask_))
366{
367 std::swap(data_, other.data_);
368}
369
370template<typename DataT>
372{
373 dim_ = other.dim_;
374 size_ = other.size_;
375 mask_ = std::move(other.mask_);
376 std::swap(data_, other.data_);
377 return *this;
378}
379
380template<typename DataT>
381inline size_t Grid<DataT>::memUsage() const
382{
383 auto mem = mask_.memUsage() + sizeof(uint8_t) + sizeof(uint32_t) + sizeof(DataT *);
384 if (!std::is_same_v<DataT, EmptyVoxel>&& !external_memory_) {
385 mem += sizeof(DataT) * size_;
386 }
387 return mem;
388}
389
390template<typename DataT>
392{
393 std::vector<CoordT> keys_to_delete;
394 for (auto & [key, inner_grid] : root_map) {
395 for (auto inner_it = inner_grid.mask().beginOn(); inner_it; ++inner_it) {
396 const int32_t inner_index = *inner_it;
397 auto & leaf_grid = inner_grid.cell(inner_index);
398 if (leaf_grid->mask().isOff()) {
399 inner_grid.mask().setOff(inner_index);
400 leaf_grid.reset();
401 }
402 }
403 if (inner_grid.mask().isOff()) {
404 keys_to_delete.push_back(key);
405 }
406 }
407 for (const auto & key : keys_to_delete) {
408 root_map.erase(key);
409 }
410 leaf_block_allocator_.releaseUnusedMemory();
411}
412
413template<typename DataT>
414inline VoxelGrid<DataT>::VoxelGrid(double voxel_size, uint8_t inner_bits, uint8_t leaf_bits)
415: INNER_BITS(inner_bits),
416 LEAF_BITS(leaf_bits),
417 Log2N(INNER_BITS + LEAF_BITS),
418 resolution(voxel_size),
419 inv_resolution(1.0 / resolution),
420 INNER_MASK((1 << INNER_BITS) - 1),
421 LEAF_MASK((1 << LEAF_BITS) - 1),
422 leaf_block_allocator_(leaf_bits)
423{
424 if (LEAF_BITS < 1 || INNER_BITS < 1) {
425 throw std::runtime_error("The minimum value of the inner_bits and leaf_bits should be 1");
426 }
427}
428
429template<typename DataT>
430inline CoordT VoxelGrid<DataT>::posToCoord(double x, double y, double z) const
431{
432 return {
433 static_cast<int32_t>(std::floor(x * inv_resolution)),
434 static_cast<int32_t>(std::floor(y * inv_resolution)),
435 static_cast<int32_t>(std::floor(z * inv_resolution))};
436}
437
438template<typename DataT>
439inline Point3D VoxelGrid<DataT>::coordToPos(const CoordT & coord) const
440{
441 return {
442 (static_cast<double>(coord.x)) * resolution, (static_cast<double>(coord.y)) * resolution,
443 (static_cast<double>(coord.z)) * resolution};
444}
445
446template<typename DataT>
447inline CoordT VoxelGrid<DataT>::getRootKey(const CoordT & coord) const
448{
449 const int32_t MASK = ~((1 << Log2N) - 1);
450 return {coord.x & MASK, coord.y & MASK, coord.z & MASK};
451}
452
453template<typename DataT>
454inline CoordT VoxelGrid<DataT>::getInnerKey(const CoordT & coord) const
455{
456 const int32_t MASK = ~((1 << LEAF_BITS) - 1);
457 return {coord.x & MASK, coord.y & MASK, coord.z & MASK};
458}
459
460template<typename DataT>
461inline uint32_t VoxelGrid<DataT>::getInnerIndex(const CoordT & coord) const
462{
463 // clang-format off
464 return ((coord.x >> LEAF_BITS) & INNER_MASK) |
465 (((coord.y >> LEAF_BITS) & INNER_MASK) << INNER_BITS) |
466 (((coord.z >> LEAF_BITS) & INNER_MASK) << (INNER_BITS * 2));
467 // clang-format on
468}
469
470template<typename DataT>
471inline uint32_t VoxelGrid<DataT>::getLeafIndex(const CoordT & coord) const
472{
473 // clang-format off
474 return (coord.x & LEAF_MASK) |
475 ((coord.y & LEAF_MASK) << LEAF_BITS) |
476 ((coord.z & LEAF_MASK) << (LEAF_BITS * 2));
477 // clang-format on
478}
479
480template<typename DataT>
481inline bool VoxelGrid<DataT>::Accessor::setValue(const CoordT & coord, const DataT & value)
482{
483 static_assert(
484 !std::is_same_v<DataT, EmptyVoxel>,
485 "You can not access a value when using type EmptyVoxel. Use "
486 "setCellOn / setCellOff");
487
488 const CoordT inner_key = mutable_grid_.getInnerKey(coord);
489 if (inner_key != prev_inner_coord_ || prev_leaf_ptr_ == nullptr) {
490 prev_leaf_ptr_ = getLeafGrid(coord, true);
491 prev_inner_coord_ = inner_key;
492 }
493
494 const uint32_t index = mutable_grid_.getLeafIndex(coord);
495 const bool was_on = prev_leaf_ptr_->mask().setOn(index);
496 prev_leaf_ptr_->cell(index) = value;
497 return was_on;
498}
499
500//----------------------------------
501template<typename DataT>
502inline DataT * VoxelGrid<DataT>::Accessor::value(const CoordT & coord, bool create_if_missing)
503{
504 static_assert(
505 !std::is_same_v<DataT, EmptyVoxel>,
506 "You can not access a value when using type EmptyVoxel. Use "
507 "isCellOn / setCellOn / setCellOff");
508
509 const CoordT inner_key = mutable_grid_.getInnerKey(coord);
510
511 if (inner_key != prev_inner_coord_) {
512 prev_leaf_ptr_ = getLeafGrid(coord, create_if_missing);
513 prev_inner_coord_ = inner_key;
514 }
515
516 if (prev_leaf_ptr_) {
517 const uint32_t index = mutable_grid_.getLeafIndex(coord);
518 if (prev_leaf_ptr_->mask().isOn(index)) {
519 return &(prev_leaf_ptr_->cell(index));
520 } else if (create_if_missing) {
521 prev_leaf_ptr_->mask().setOn(index);
522 prev_leaf_ptr_->cell(index) = {};
523 return &(prev_leaf_ptr_->cell(index));
524 }
525 }
526 return nullptr;
527}
528
529template<typename DataT>
530inline const DataT * VoxelGrid<DataT>::ConstAccessor::value(const CoordT & coord) const
531{
532 static_assert(
533 !std::is_same_v<DataT, EmptyVoxel>,
534 "You can not access a value when using type EmptyVoxel. Use isCellOn");
535
536 const CoordT inner_key = grid_.getInnerKey(coord);
537
538 if (inner_key != prev_inner_coord_) {
540 prev_inner_coord_ = inner_key;
541 }
542
543 if (prev_leaf_ptr_) {
544 const uint32_t index = grid_.getLeafIndex(coord);
545 if (prev_leaf_ptr_->mask().isOn(index)) {
546 return &(prev_leaf_ptr_->cell(index));
547 }
548 }
549 return nullptr;
550}
551
552template<typename DataT>
553inline bool VoxelGrid<DataT>::ConstAccessor::isCellOn(const CoordT & coord) const
554{
555 const CoordT inner_key = grid_.getInnerKey(coord);
556
557 if (inner_key != prev_inner_coord_) {
559 prev_inner_coord_ = inner_key;
560 }
561
562 if (prev_leaf_ptr_) {
563 const uint32_t index = grid_.getLeafIndex(coord);
564 if (prev_leaf_ptr_->mask().isOn(index)) {
565 return true;
566 }
567 }
568 return false;
569}
570
571//----------------------------------
572template<typename DataT>
573inline bool VoxelGrid<DataT>::Accessor::setCellOn(const CoordT & coord, const DataT & default_value)
574{
575 const CoordT inner_key = mutable_grid_.getInnerKey(coord);
576
577 if (inner_key != prev_inner_coord_) {
578 prev_leaf_ptr_ = getLeafGrid(coord, true);
579 prev_inner_coord_ = inner_key;
580 }
581 uint32_t index = mutable_grid_.getLeafIndex(coord);
582 bool was_on = prev_leaf_ptr_->mask().setOn(index);
583 if constexpr (!std::is_same_v<DataT, EmptyVoxel>) {
584 if (!was_on) {
585 prev_leaf_ptr_->cell(index) = default_value;
586 }
587 }
588 return was_on;
589}
590
591//----------------------------------
592template<typename DataT>
594{
595 const CoordT inner_key = mutable_grid_.getInnerKey(coord);
596
597 if (inner_key != prev_inner_coord_) {
598 prev_leaf_ptr_ = getLeafGrid(coord, false);
599 prev_inner_coord_ = inner_key;
600 }
601 if (prev_leaf_ptr_) {
602 uint32_t index = mutable_grid_.getLeafIndex(coord);
603 return prev_leaf_ptr_->mask().setOff(index);
604 }
605 return false;
606}
607
608//----------------------------------
609template<typename DataT>
610inline typename std::shared_ptr<Grid<DataT>> VoxelGrid<DataT>::allocateLeafGrid()
611{
612 if constexpr (std::is_trivial_v<DataT>&& !std::is_same_v<DataT, EmptyVoxel>) {
613 auto allocated = leaf_block_allocator_.allocateBlock();
614 DataT * memory_block = allocated.first;
615 auto deleter = [deleter_impl = std::move(allocated.second)](LeafGrid * ptr) {
616 deleter_impl();
617 ptr->~LeafGrid();
618 delete ptr;
619 };
620 return std::shared_ptr<LeafGrid>(new LeafGrid(LEAF_BITS, memory_block), deleter);
621 } else {
622 return std::make_shared<LeafGrid>(LEAF_BITS);
623 }
624}
625
626template<typename DataT>
628 const CoordT & coord, bool create_if_missing)
629{
630 InnerGrid * inner_ptr = prev_inner_ptr_;
631 const CoordT root_key = mutable_grid_.getRootKey(coord);
632
633 if (root_key != prev_root_coord_ || !inner_ptr) {
634 auto it = mutable_grid_.root_map.find(root_key);
635 if (it == mutable_grid_.root_map.end()) {
636 if (!create_if_missing) {
637 return nullptr;
638 }
639 it = mutable_grid_.root_map.insert({root_key, InnerGrid(mutable_grid_.INNER_BITS)}).first;
640 }
641 inner_ptr = &(it->second);
642 // update the cache
643 prev_root_coord_ = root_key;
644 prev_inner_ptr_ = inner_ptr;
645 }
646
647 const uint32_t inner_index = mutable_grid_.getInnerIndex(coord);
648 auto & inner_data = inner_ptr->cell(inner_index);
649
650 if (create_if_missing) {
651 if (!inner_ptr->mask().setOn(inner_index)) {
652 inner_data = mutable_grid_.allocateLeafGrid();
653 }
654 } else {
655 if (!inner_ptr->mask().isOn(inner_index)) {
656 return nullptr;
657 }
658 }
659 return inner_data.get();
660}
661
662template<typename DataT>
664 const CoordT & coord) const
665{
666 const InnerGrid * inner_ptr = prev_inner_ptr_;
667 const CoordT root_key = grid_.getRootKey(coord);
668
669 if (root_key != prev_root_coord_ || !inner_ptr) {
670 auto it = grid_.root_map.find(root_key);
671 if (it == grid_.root_map.end()) {
672 return nullptr;
673 }
674 inner_ptr = &(it->second);
675 // update the cache
676 prev_root_coord_ = root_key;
677 prev_inner_ptr_ = inner_ptr;
678 }
679
680 const uint32_t inner_index = grid_.getInnerIndex(coord);
681 const auto & inner_data = inner_ptr->cell(inner_index);
682
683 if (!inner_ptr->mask().isOn(inner_index)) {
684 return nullptr;
685 }
686 return inner_data.get();
687}
688
689template<typename DataT>
690inline size_t VoxelGrid<DataT>::memUsage() const
691{
692 size_t total_size = 0;
693
694 for (unsigned i = 0; i < root_map.bucket_count(); ++i) {
695 size_t bucket_size = root_map.bucket_size(i);
696 if (bucket_size == 0) {
697 total_size++;
698 } else {
699 total_size += bucket_size;
700 }
701 }
702
703 total_size += root_map.size() * (sizeof(CoordT) + sizeof(void *));
704
705 for (const auto & [key, inner_grid] : root_map) {
706 total_size += inner_grid.memUsage();
707 for (auto inner_it = inner_grid.mask().beginOn(); inner_it; ++inner_it) {
708 const int32_t inner_index = *inner_it;
709 auto & leaf_grid = inner_grid.cell(inner_index);
710 total_size += leaf_grid->memUsage();
711 }
712 }
713 // if we are using the memory pool, leaf_grid->memUsage() did not return the right
714 // value
715 total_size += leaf_block_allocator_.memUsage();
716 return total_size;
717}
718
719template<typename DataT>
721{
722 if (opt == CLEAR_MEMORY) {
723 root_map.clear();
724 leaf_block_allocator_.clear();
725 return;
726 }
727 auto accessor = createAccessor();
728 forEachCell([&accessor, this](DataT &, const CoordT & coord) {accessor.setCellOff(coord);});
729}
730
731template<typename DataT>
733{
734 size_t total_size = 0;
735
736 for (const auto & [key, inner_grid] : root_map) {
737 for (auto inner_it = inner_grid.mask().beginOn(); inner_it; ++inner_it) {
738 const int32_t inner_index = *inner_it;
739 auto & leaf_grid = inner_grid.cell(inner_index);
740 total_size += leaf_grid->mask().countOn();
741 }
742 }
743 return total_size;
744}
745
746//----------------------------------
747template<typename DataT>
748template<class VisitorFunction>
749inline void VoxelGrid<DataT>::forEachCell(VisitorFunction func) const
750{
751 const int32_t MASK_LEAF = ((1 << LEAF_BITS) - 1);
752 const int32_t MASK_INNER = ((1 << INNER_BITS) - 1);
753
754 for (auto & map_it : root_map) {
755 const auto & [xA, yA, zA] = (map_it.first);
756 const InnerGrid & inner_grid = map_it.second;
757 const auto & mask2 = inner_grid.mask();
758
759 for (auto inner_it = mask2.beginOn(); inner_it; ++inner_it) {
760 const int32_t inner_index = *inner_it;
761 const int32_t INNER_BITS_2 = INNER_BITS * 2;
762 // clang-format off
763 int32_t xB = xA | ((inner_index & MASK_INNER) << LEAF_BITS);
764 int32_t yB = yA | (((inner_index >> INNER_BITS) & MASK_INNER) << LEAF_BITS);
765 int32_t zB = zA | (((inner_index >> (INNER_BITS_2)) & MASK_INNER) << LEAF_BITS);
766 // clang-format on
767
768 const auto & leaf_grid = inner_grid.cell(inner_index);
769 const auto & mask1 = leaf_grid->mask();
770
771 for (auto leaf_it = mask1.beginOn(); leaf_it; ++leaf_it) {
772 const int32_t leaf_index = *leaf_it;
773 const int32_t LEAF_BITS_2 = LEAF_BITS * 2;
774 CoordT pos = {
775 xB | (leaf_index & MASK_LEAF), yB | ((leaf_index >> LEAF_BITS) & MASK_LEAF),
776 zB | ((leaf_index >> (LEAF_BITS_2)) & MASK_LEAF)};
777 // apply the visitor
778 if constexpr (std::is_same_v<DataT, EmptyVoxel>) {
779 EmptyVoxel dummy{};
780 func(dummy, pos);
781 } else {
782 func(leaf_grid->cell(leaf_index), pos);
783 }
784 }
785 }
786 }
787}
788
789} // namespace Bonxai
The GridBlockAllocator is used to pre-allocate the meory of multiple Grids in "chunks".
Definition grid_allocator.hpp:30
The Grid class is used to store data in a cube.
Definition bonxai.hpp:41
size_t memUsage() const
Definition bonxai.hpp:381
Grid(const Grid &other)=delete
~Grid()
Definition bonxai.hpp:74
Grid & operator=(const Grid &other)=delete
Grid(size_t log2dim, DataT *preAllocatedMemory)
Definition bonxai.hpp:62
size_t size() const
Definition bonxai.hpp:83
Bonxai::Mask & mask()
Definition bonxai.hpp:88
const DataT & cell(size_t index) const
Definition bonxai.hpp:105
Grid(Grid &&other)
Definition bonxai.hpp:362
const Bonxai::Mask & mask() const
Definition bonxai.hpp:93
Grid & operator=(Grid &&other)
Definition bonxai.hpp:371
Grid(size_t log2dim)
Definition bonxai.hpp:52
DataT & cell(size_t index)
Definition bonxai.hpp:98
Definition mask.hpp:20
bool isOn(uint32_t n) const
Return true if the given bit is set.
Definition mask.hpp:356
bool setOn(uint32_t n)
Definition mask.hpp:381
bool setCellOff(const CoordT &coord)
setCellOff will disable a cell without deleting its content.
Definition bonxai.hpp:593
bool setCellOn(const CoordT &coord, const DataT &default_value=DataT())
setCellOn is similar to setValue, but the value is changed only if the cell has been created,...
Definition bonxai.hpp:573
Accessor(VoxelGrid &grid)
Definition bonxai.hpp:278
LeafGrid * getLeafGrid(const CoordT &coord, bool create_if_missing=false)
getLeafGrid gets the pointer to the LeafGrid containing the cell.
Definition bonxai.hpp:627
bool setValue(const CoordT &coord, const DataT &value)
setValue of a cell.
Definition bonxai.hpp:481
EmptyVoxel * value(const CoordT &coord, bool create_if_missing=false)
Definition bonxai.hpp:502
const InnerGrid * prev_inner_ptr_
Definition bonxai.hpp:267
CoordT prev_root_coord_
Definition bonxai.hpp:265
const VoxelGrid & grid_
Definition bonxai.hpp:264
ConstAccessor(const VoxelGrid &grid)
Definition bonxai.hpp:233
bool isCellOn(const CoordT &coord) const
isCellOn only check if a cell is in "On" state
Definition bonxai.hpp:553
const LeafGrid * lastLeafGrid() const
lastLeafGrid returns the pointer to the LeafGrid in the cache.
Definition bonxai.hpp:256
const LeafGrid * prev_leaf_ptr_
Definition bonxai.hpp:268
const InnerGrid * lastInnerGrid() const
lastInnerGrid returns the pointer to the InnerGrid in the cache.
Definition bonxai.hpp:250
CoordT prev_inner_coord_
Definition bonxai.hpp:266
const LeafGrid * getLeafGrid(const CoordT &coord) const
Definition bonxai.hpp:663
const DataT * value(const CoordT &coord) const
value getter.
Definition bonxai.hpp:530
Definition bonxai.hpp:124
uint32_t innetBits() const
Definition bonxai.hpp:155
Grid< std::shared_ptr< LeafGrid > > InnerGrid
Definition bonxai.hpp:138
size_t memUsage() const
getMemoryUsage returns the amount of bytes used by this data structure
Definition bonxai.hpp:690
ConstAccessor createConstAccessor() const
Definition bonxai.hpp:338
CoordT posToCoord(const Point3D &pos) const
posToCoord is used to convert real coordinates to CoordT indices.
Definition bonxai.hpp:194
Accessor createAccessor()
Definition bonxai.hpp:333
void forEachCell(VisitorFunction func)
forEachCell apply a function of type:
Definition bonxai.hpp:220
VoxelGrid(double voxel_size, uint8_t inner_bits=2, uint8_t leaf_bits=3)
VoxelGrid constructor.
Definition bonxai.hpp:414
uint32_t leafBits() const
Definition bonxai.hpp:159
void clear(ClearOption opt)
Definition bonxai.hpp:720
const RootMap & rootMap() const
Definition bonxai.hpp:168
VoxelGrid & operator=(VoxelGrid &&other)=default
uint32_t getInnerIndex(const CoordT &coord) const
Definition bonxai.hpp:461
CoordT getInnerKey(const CoordT &coord) const
Definition bonxai.hpp:454
Grid< DataT > LeafGrid
Definition bonxai.hpp:137
VoxelGrid(VoxelGrid &&other)=default
double voxelSize() const
Definition bonxai.hpp:163
CoordT getRootKey(const CoordT &coord) const
Definition bonxai.hpp:447
RootMap & rootMap()
Definition bonxai.hpp:172
VoxelGrid(const VoxelGrid &)=delete
uint32_t getLeafIndex(const CoordT &coord) const
Definition bonxai.hpp:471
std::shared_ptr< LeafGrid > allocateLeafGrid()
Definition bonxai.hpp:610
void forEachCell(VisitorFunction func) const
forEachCell apply a function of type:
Definition bonxai.hpp:749
CoordT posToCoord(double x, double y, double z) const
posToCoord is used to convert real coordinates to CoordT indices.
Definition bonxai.hpp:430
size_t activeCellsCount() const
Return the total number of active cells.
Definition bonxai.hpp:732
VoxelGrid & operator=(const VoxelGrid &)=delete
void releaseUnusedMemory()
Try freeing memory; this will discard grids where all the cells are OFF.
Definition bonxai.hpp:391
Point3D coordToPos(const CoordT &coord) const
coordToPos converts CoordT indices to Point3D.
Definition bonxai.hpp:439
std::unordered_map< CoordT, InnerGrid > RootMap
Definition bonxai.hpp:139
Definition bonxai.hpp:28
VoxelGrid< EmptyVoxel > BinaryVoxelGrid
Definition bonxai.hpp:355
ClearOption
Definition bonxai.hpp:116
@ CLEAR_MEMORY
Definition bonxai.hpp:118
@ SET_ALL_CELLS_OFF
Definition bonxai.hpp:120
Definition grid_coord.hpp:226
Definition grid_coord.hpp:67
int32_t z
Definition grid_coord.hpp:70
int32_t y
Definition grid_coord.hpp:69
int32_t x
Definition grid_coord.hpp:68
Definition bonxai.hpp:31
Definition grid_coord.hpp:34
double z
Definition grid_coord.hpp:37
double y
Definition grid_coord.hpp:36
double x
Definition grid_coord.hpp:35