DGtal 2.1.0
Loading...
Searching...
No Matches
DigitalSetByOctree.h
1
16
28
29#pragma once
30
31// Inclusions
32#include "DGtal/base/Common.h"
33#include "DGtal/kernel/domains/HyperRectDomain.h"
35
36//#include "DGtal/io/Display3D.h"
37
38
39namespace DGtal
40{
68 template <class Space>
70 {
71 public:
72 template<class>
73 friend class SVOWriter;
74 template<class>
75 friend class SVOReader;
76
77 using DimIndex = std::uint8_t;
79 using Size = size_t;
80
81 // Only HyperRectDomain are supported
83 using Point = typename Domain::Point;
84
85 // Define a value type for this class to be somewhat compatible
86 // with image-based code.
87 using Value = void;
88
91
92 static constexpr CellIndex CELL_COUNT = (1 << D);
93 static constexpr CellIndex INVALID_IDX = std::numeric_limits<CellIndex>::max();
94
95 // For each child node, store on which side of the octree split it is.
96 static constexpr std::array<std::array<DimIndex, D>, CELL_COUNT> SIDES_FROM_INDEX = []()
97 {
98 std::array<std::array<DimIndex, D>, CELL_COUNT> sides_from_index{};
99 for (CellIndex i = 0; i < CELL_COUNT; ++i)
100 {
101 CellIndex coord = i;
102 for (DimIndex d = 0; d < D; ++d)
103 {
104 sides_from_index[i][d] = coord % 2;
105 coord /= 2;
106 }
107 }
108
109 return sides_from_index;
110 }();
111
117 struct Node
118 {
120 {
121 for (CellIndex i = 0; i < CELL_COUNT; ++i)
123 }
124
126 };
127
136 {
139 std::vector<DimIndex> code;
140
141 bool operator<(const ComputationCacheKey& other) const
142 {
143 if (parentLvl != other.parentLvl) return parentLvl < other.parentLvl;
144 if (parentIdx != other.parentIdx) return parentIdx < other.parentIdx;
145 return code < other.code;
146 }
147 };
148
153 {
154 Domain domain; //< Domain represented by the node
155 CellIndex lvl; //< Level of the node
156 CellIndex idx; //< Index of the node
157 CellIndex currentChildIdx; //< Which child is currently explored.
158
159 bool operator==(const TraversalMemory& other) const
160 {
161 return lvl == other.lvl && idx == other.idx && currentChildIdx == other.currentChildIdx;
162 }
163 };
164
169 {
170 public:
171 friend class DigitalSetByOctree;
172
173 // Should be std::output_iterator_tag, but CDigitalSet
174 // does not allow this; so we upgrade the category
175 using iterator_category = std::forward_iterator_tag;
176 using difference_type = std::ptrdiff_t;
180
185 {
186 myContainer = container;
187 }
188
197 {
198 myContainer = container;
199 myMemory.push_back(std::move(init));
200
201 findNextLeaf();
202 }
203
212 std::vector<TraversalMemory>& memory)
213 {
214 myContainer = container;
215 myMemory = memory;
216 }
217
224 bool operator==(const OctreeIterator& other) const
225 {
226 if (myContainer != other.myContainer) return false;
227 if (myMemory.size() != other.myMemory.size()) return false;
228
229 if (myMemory.size() != 0)
230 {
231 return myMemory.back() == other.myMemory.back();
232 }
233 return true;
234 }
235
239 bool operator!=(const OctreeIterator& other) const
240 {
241 return !(*this == other);
242 }
243
248 {
249 const auto& sides = SIDES_FROM_INDEX[myMemory.back().currentChildIdx];
250 return splitDomain(myMemory.back().domain, sides.data()).lowerBound();
251 }
252
257 {
258 findNextLeaf();
259 return *this;
260 }
261
266 {
267 auto it = *this;
268 findNextLeaf();
269 return it;
270 }
271 private:
276 private:
277 const DigitalSetByOctree* myContainer; //< Pointer to the original octree
278 std::vector<TraversalMemory> myMemory; //< Current traversal information
279 };
280
283
295
299 const Domain& domain() const { return *myAdmissibleDomain; }
300
305 public:
317 void insert(const Point& p);
318
331 void insertNew(const Point& p) { insert(p); }
332
339 bool operator()(const Point& p) const { return find(p) != end(); }
340
347 Iterator find(const Point& p) const;
348
352 size_t size() const { return mySize; }
353
357 bool empty() const { return size() == 0; }
358
364 size_t memoryFootprint() const
365 {
366 size_t count = 0;
367 for (CellIndex i = 0; i < myNodes.size(); ++i)
368 count += myNodes[i].capacity() * sizeof(Node);
369 return count;
370 }
371
379 void clear()
380 {
381 myNodes.clear();
383 }
384
393 size_t erase(const Iterator& it);
394
402 {
403 size_t count = 0;
404 for (; begin != end; ++begin)
405 count += erase(begin);
406 return count;
407 }
408
414 size_t erase(const Point& p)
415 {
416 return erase(find(p));
417 }
418
431 {
432 for (CellIndex i = 0; i < myNodes.size(); ++i)
433 myNodes[i].shrink_to_fit();
434 }
435
445 {
446 if (myState == State::OCTREE)
447 {
448 for (auto it = other.begin(); it != other.end(); ++it)
449 insert(*it);
450 }
451 return *this;
452 }
453
461 template<typename It>
462 void computeComplement(It out) const
463 {
464 DigitalSetByOctree complement(*myDomain);
465 for (auto it = myDomain->begin(); it != myDomain->end(); ++it)
466 {
467 if (!this->operator()(*it))
468 {
469 *out = *it;
470 ++out;
471 }
472 }
473 }
474
483 template<class DSet>
484 void assignFromComplement(const DSet& other)
485 {
486 if (myState == State::OCTREE)
487 {
488 clear();
489 for (auto it = myDomain->begin(); it != myDomain->end(); ++it)
490 {
491 if (!other(*it))
492 insert(*it);
493 }
494 }
495 }
496
505 void computeBoundingBox(Point& lb, Point& ub) const
506 {
507 lb = myDomain->upperBound();
508 ub = myDomain->lowerBound();
509
510 for (auto it = begin(); it != end(); ++it)
511 {
512 const auto p = *it;
513 for (DimIndex d = 0; d < D; d++)
514 {
515 lb[d] = std::min(lb[d], p[d]);
516 ub[d] = std::max(ub[d], p[d]);
517 }
518 }
519 }
520
525 {
526 TraversalMemory mem;
527 mem.domain = *myDomain;
528 mem.lvl = 0;
529 mem.idx = 0;
530 mem.currentChildIdx = INVALID_IDX;
531
532 return Iterator(this, mem);
533 }
534
538 Iterator begin() { return static_cast<const DigitalSetByOctree&>(*this).begin(); }
539
543 Iterator end() { return Iterator(this); }
544
548 Iterator end() const { return Iterator(this); }
549
550 public:
555
556 template<class Func>
557 auto computeFunction(OctreeIterator start, OctreeIterator end, CellIndex range, const Func& f);
558
564 void dumpOctree() const;
565 private:
572 static Domain splitDomain(const Domain& domain, const DimIndex* sides);
573
574 private:
581 enum class State
582 {
583 OCTREE = 1,
584 DAG = 2
585 };
586
587
588 private:
589 // We store two domains:
590 // - myDomain is the domain used for computation, that
591 // requires its size to be whole power of two for
592 // computationnal purposes
593 // - myAdmissibleDomain is the domain of points that can be
594 // stored within the octree. It shares the same lower bound
595 // with domain, but its upper bound is lowered by one.
596 CowPtr<Domain> myAdmissibleDomain; // Domain of point that are allowed.
597 CowPtr<Domain> myDomain; // Pointer to domain, as required by CDigitalSet.
598 State myState = State::OCTREE; // Current state
599
600 size_t mySize; // Current number of stored voxel.
601 std::vector<std::vector<Node>> myNodes; // Nodes storage
602 };
603};
604
605#include "DigitalSetByOctree.ih"
Aim: Copy on write shared pointer.
Definition CowPtr.h:68
void insert(const Point &p)
Inserts a new point in the octree.
Iterator begin()
Returns an iterator to the begining of the octree.
auto computeFunction(OctreeIterator start, OctreeIterator end, CellIndex range, const Func &f)
size_t erase(const Iterator &it)
Remove a voxel from the octree.
DigitalSetByOctree & operator+=(const DigitalSetByOctree &other)
Appends an octree to another.
size_t erase(Iterator begin, Iterator end)
Removes a range of voxels.
bool operator()(const Point &p) const
Check if a voxel is set or not.
void clear()
Removes all nodes from the octree.
std::vector< std::vector< Node > > myNodes
Iterator end() const
Returns an iterator to the end of the octree.
Iterator find(const Point &p) const
Finds a point within the Octree.
bool empty() const
Check if the octree is empty or not.
size_t size() const
Returns the number of voxel in the set.
static Domain splitDomain(const Domain &domain, const DimIndex *sides)
Helper function to split and select among 2^D subdomains.
CowPtr< Domain > domainPointer() const
Returns the domain of the voxels.
static constexpr std::array< std::array< DimIndex, D >, CELL_COUNT > SIDES_FROM_INDEX
void computeComplement(It out) const
Computes the complement of the octree.
State
The state the container is in.
HyperRectDomain< Space > Domain
void dumpOctree() const
Dumps the octree to std out.
void insertNew(const Point &p)
Inserts a new point in the octree.
void shrinkToFit()
Shrinks storage to reduce memory usage.
DigitalSetByOctree(const Domain &d)
Constructor from a domain.
void convertToDAG()
Converts the octree to DAG.
static constexpr DGtal::Dimension D
typename Space::UnsignedInteger CellIndex
Iterator end()
Returns an iterator to the end of the octree.
size_t memoryFootprint() const
Returns the memory occupied by node storage in bytes.
const Domain & domain() const
Returns the domain of the digital set.
void computeBoundingBox(Point &lb, Point &ub) const
Computes the bounding box of stored points.
typename Domain::Point Point
size_t erase(const Point &p)
Removes a voxel from the octree.
void assignFromComplement(const DSet &other)
Assigns the octree as the complement of another set.
static constexpr DGtal::Dimension dimension
Aim: Parallelepidec region of a digital space, model of a 'CDomain'.
const Point & lowerBound() const
NumberTraits< Integer >::UnsignedVersion UnsignedInteger
Definition SpaceND.h:104
static const Dimension dimension
Definition SpaceND.h:132
DGtal is the top-level namespace which contains all DGtal functions and types.
DGtal::uint32_t Dimension
Definition Common.h:119
Helper struct for computing local estimators.
bool operator<(const ComputationCacheKey &other) const
OctreeIterator(const DigitalSetByOctree *container, std::vector< TraversalMemory > &memory)
Constructor from an entire traversal.
bool operator==(const OctreeIterator &other) const
Compares two iterator.
OctreeIterator & operator++()
Prefix increment.
void findNextLeaf()
Finds the next leaf, if any.
OctreeIterator(const DigitalSetByOctree *container, TraversalMemory init)
Constructor from any node to explore subtree.
bool operator!=(const OctreeIterator &other) const
Not equal comparison operator.
std::vector< TraversalMemory > myMemory
OctreeIterator(const DigitalSetByOctree *container)
Constuctor to end of an octree.
OctreeIterator operator++(int)
Postfix increment.
Point operator*() const
Dereference operator.
Helper struct to store traversal and go to next leaf.
bool operator==(const TraversalMemory &other) const
K init(Point(0, 0, 0), Point(512, 512, 512), true)