HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tree.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /// @file tree/Tree.h
5 
6 #ifndef OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
7 #define OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
8 
9 #include <openvdb/Types.h>
10 #include <openvdb/Metadata.h>
11 #include <openvdb/math/Math.h>
12 #include <openvdb/math/BBox.h>
13 #include <openvdb/tools/Count.h> // tools::countActiveVoxels(), tools::memUsage(), tools::minMax()
14 #include <openvdb/util/Formats.h>
15 #include <openvdb/util/logging.h>
16 #include <openvdb/util/Assert.h>
17 #include <openvdb/Platform.h>
18 #include "RootNode.h"
19 #include "InternalNode.h"
20 #include "LeafNode.h"
21 #include "TreeIterator.h"
22 #include "ValueAccessor.h"
23 #include <tbb/concurrent_hash_map.h>
24 #include <cstdint>
25 #include <iostream>
26 #include <mutex>
27 #include <sstream>
28 #include <vector>
29 
30 
31 namespace openvdb {
33 namespace OPENVDB_VERSION_NAME {
34 namespace tree {
35 
36 /// @brief Base class for typed trees
38 {
39 public:
42 
43  TreeBase() = default;
44  TreeBase(const TreeBase&) = default;
45  TreeBase& operator=(const TreeBase&) = delete; // disallow assignment
46  virtual ~TreeBase() = default;
47 
48  /// Return the name of this tree's type.
49  virtual const Name& type() const = 0;
50 
51  /// Return the name of the type of a voxel's value (e.g., "float" or "vec3d").
52  virtual Name valueType() const = 0;
53 
54  /// Return @c true if this tree is of the same type as the template parameter.
55  template<typename TreeType>
56  bool isType() const { return (this->type() == TreeType::treeType()); }
57 
58  /// Return a pointer to a deep copy of this tree
59  virtual TreeBase::Ptr copy() const = 0;
60 
61  //
62  // Tree methods
63  //
64  /// @brief Return this tree's background value wrapped as metadata.
65  /// @note Query the metadata object for the value's type.
66  virtual Metadata::Ptr getBackgroundValue() const { return Metadata::Ptr(); }
67 
68  /// @brief Return in @a bbox the axis-aligned bounding box of all
69  /// active tiles and leaf nodes with active values.
70  /// @details This is faster than calling evalActiveVoxelBoundingBox,
71  /// which visits the individual active voxels, and hence
72  /// evalLeafBoundingBox produces a less tight, i.e. approximate, bbox.
73  /// @return @c false if the bounding box is empty (in which case
74  /// the bbox is set to its default value).
75  virtual bool evalLeafBoundingBox(CoordBBox& bbox) const = 0;
76 
77  /// @brief Return in @a dim the dimensions of the axis-aligned bounding box
78  /// of all leaf nodes.
79  /// @return @c false if the bounding box is empty.
80  virtual bool evalLeafDim(Coord& dim) const = 0;
81 
82  /// @brief Return in @a bbox the axis-aligned bounding box of all
83  /// active voxels and tiles.
84  /// @details This method produces a more accurate, i.e. tighter,
85  /// bounding box than evalLeafBoundingBox which is approximate but
86  /// faster.
87  /// @return @c false if the bounding box is empty (in which case
88  /// the bbox is set to its default value).
89  virtual bool evalActiveVoxelBoundingBox(CoordBBox& bbox) const = 0;
90 
91  /// @brief Return in @a dim the dimensions of the axis-aligned bounding box of all
92  /// active voxels. This is a tighter bounding box than the leaf node bounding box.
93  /// @return @c false if the bounding box is empty.
94  virtual bool evalActiveVoxelDim(Coord& dim) const = 0;
95 
96  virtual void getIndexRange(CoordBBox& bbox) const = 0;
97 
98  /// @brief Replace with background tiles any nodes whose voxel buffers
99  /// have not yet been allocated.
100  /// @details Typically, unallocated nodes are leaf nodes whose voxel buffers
101  /// are not yet resident in memory because delayed loading is in effect.
102  /// @sa readNonresidentBuffers, io::File::open
103  virtual void clipUnallocatedNodes() = 0;
104  /// Return the total number of unallocated leaf nodes residing in this tree.
105 #if OPENVDB_ABI_VERSION_NUMBER >= 12
106  virtual Index64 unallocatedLeafCount() const = 0;
107 #else
108  virtual Index32 unallocatedLeafCount() const = 0;
109 #endif
110 
111 
112  //
113  // Statistics
114  //
115  /// @brief Return the depth of this tree.
116  ///
117  /// A tree with only a root node and leaf nodes has depth 2, for example.
118  virtual Index treeDepth() const = 0;
119  /// Return the number of leaf nodes.
120 #if OPENVDB_ABI_VERSION_NUMBER >= 12
121  virtual Index64 leafCount() const = 0;
122 #else
123  virtual Index32 leafCount() const = 0;
124 #endif
125  /// Return a vector with node counts. The number of nodes of type NodeType
126  /// is given as element NodeType::LEVEL in the return vector. Thus, the size
127  /// of this vector corresponds to the height (or depth) of this tree.
128 #if OPENVDB_ABI_VERSION_NUMBER >= 12
129  virtual std::vector<Index64> nodeCount() const = 0;
130 #else
131  virtual std::vector<Index32> nodeCount() const = 0;
132 #endif
133  /// Return the number of non-leaf nodes.
134 #if OPENVDB_ABI_VERSION_NUMBER >= 12
135  virtual Index64 nonLeafCount() const = 0;
136 #else
137  virtual Index32 nonLeafCount() const = 0;
138 #endif
139  /// Return the number of active voxels stored in leaf nodes.
140  virtual Index64 activeLeafVoxelCount() const = 0;
141  /// Return the number of inactive voxels stored in leaf nodes.
142  virtual Index64 inactiveLeafVoxelCount() const = 0;
143  /// Return the total number of active voxels.
144  virtual Index64 activeVoxelCount() const = 0;
145  /// Return the number of inactive voxels within the bounding box of all active voxels.
146  virtual Index64 inactiveVoxelCount() const = 0;
147  /// Return the total number of active tiles.
148  virtual Index64 activeTileCount() const = 0;
149 
150  /// Return the total amount of memory in bytes occupied by this tree.
151  virtual Index64 memUsage() const { return 0; }
152 
153 
154  //
155  // I/O methods
156  //
157  /// @brief Read the tree topology from a stream.
158  ///
159  /// This will read the tree structure and tile values, but not voxel data.
160  virtual void readTopology(std::istream&, bool saveFloatAsHalf = false);
161  /// @brief Write the tree topology to a stream.
162  ///
163  /// This will write the tree structure and tile values, but not voxel data.
164  virtual void writeTopology(std::ostream&, bool saveFloatAsHalf = false) const;
165 
166  /// Read all data buffers for this tree.
167  virtual void readBuffers(std::istream&, bool saveFloatAsHalf = false) = 0;
168  /// Read all of this tree's data buffers that intersect the given bounding box.
169  virtual void readBuffers(std::istream&, const CoordBBox&, bool saveFloatAsHalf = false) = 0;
170  /// @brief Read all of this tree's data buffers that are not yet resident in memory
171  /// (because delayed loading is in effect).
172  /// @details If this tree was read from a memory-mapped file, this operation
173  /// disconnects the tree from the file.
174  /// @sa clipUnallocatedNodes, io::File::open, io::MappedFile
175  virtual void readNonresidentBuffers() const = 0;
176  /// Write out all the data buffers for this tree.
177  virtual void writeBuffers(std::ostream&, bool saveFloatAsHalf = false) const = 0;
178 
179  /// @brief Print statistics, memory usage and other information about this tree.
180  /// @param os a stream to which to write textual information
181  /// @param verboseLevel 1: print tree configuration only;
182  /// 2: include node and voxel statistics;
183  /// 3: include memory usage;
184  /// 4: include minimum and maximum voxel values
185  /// @warning @a verboseLevel 4 forces loading of any unallocated nodes.
186  virtual void print(std::ostream& os = std::cout, int verboseLevel = 1) const;
187 };
188 
189 
190 ////////////////////////////////////////
191 
192 
193 template<typename _RootNodeType>
194 class Tree: public TreeBase
195 {
196 public:
199 
200  using RootNodeType = _RootNodeType;
203  using LeafNodeType = typename RootNodeType::LeafNodeType;
204 
205  static const Index DEPTH = RootNodeType::LEVEL + 1;
206 
211 
212  /// @brief ValueConverter<T>::Type is the type of a tree having the same
213  /// hierarchy as this tree but a different value type, T.
214  ///
215  /// For example, FloatTree::ValueConverter<double>::Type is equivalent to DoubleTree.
216  /// @note If the source tree type is a template argument, it might be necessary
217  /// to write "typename SourceTree::template ValueConverter<T>::Type".
218  template<typename OtherValueType>
219  struct ValueConverter {
221  };
222 
223 
224  Tree() {}
225 
226  Tree& operator=(const Tree&) = delete; // disallow assignment
227 
228  /// Deep copy constructor
229  Tree(const Tree& other): TreeBase(other), mRoot(other.mRoot)
230  {
231  }
232 
233  /// @brief Value conversion deep copy constructor
234  ///
235  /// Deep copy a tree of the same configuration as this tree type but a different
236  /// ValueType, casting the other tree's values to this tree's ValueType.
237  /// @throw TypeError if the other tree's configuration doesn't match this tree's
238  /// or if this tree's ValueType is not constructible from the other tree's ValueType.
239  template<typename OtherRootType>
240  explicit Tree(const Tree<OtherRootType>& other): TreeBase(other), mRoot(other.root())
241  {
242  }
243 
244  /// @brief Topology copy constructor from a tree of a different type
245  ///
246  /// Copy the structure, i.e., the active states of tiles and voxels, of another
247  /// tree of a possibly different type, but don't copy any tile or voxel values.
248  /// Instead, initialize tiles and voxels with the given active and inactive values.
249  /// @param other a tree having (possibly) a different ValueType
250  /// @param inactiveValue background value for this tree, and the value to which
251  /// all inactive tiles and voxels are initialized
252  /// @param activeValue value to which active tiles and voxels are initialized
253  /// @throw TypeError if the other tree's configuration doesn't match this tree's.
254  template<typename OtherTreeType>
255  Tree(const OtherTreeType& other,
256  const ValueType& inactiveValue,
257  const ValueType& activeValue,
258  TopologyCopy):
259  TreeBase(other),
260  mRoot(other.root(), inactiveValue, activeValue, TopologyCopy())
261  {
262  }
263 
264  /// @brief Topology copy constructor from a tree of a different type
265  ///
266  /// @note This topology copy constructor is generally faster than
267  /// the one that takes both a foreground and a background value.
268  ///
269  /// Copy the structure, i.e., the active states of tiles and voxels, of another
270  /// tree of a possibly different type, but don't copy any tile or voxel values.
271  /// Instead, initialize tiles and voxels with the given background value.
272  /// @param other a tree having (possibly) a different ValueType
273  /// @param background the value to which tiles and voxels are initialized
274  /// @throw TypeError if the other tree's configuration doesn't match this tree's.
275  template<typename OtherTreeType>
276  Tree(const OtherTreeType& other, const ValueType& background, TopologyCopy):
277  TreeBase(other),
278  mRoot(other.root(), background, TopologyCopy())
279  {
280  }
281 
282  /// Empty tree constructor
283  Tree(const ValueType& background): mRoot(background) {}
284 
285  ~Tree() override { this->clear(); releaseAllAccessors(); }
286 
287  /// Return a pointer to a deep copy of this tree
288  TreeBase::Ptr copy() const override { return TreeBase::Ptr(new Tree(*this)); }
289 
290  /// Return the name of the type of a voxel's value (e.g., "float" or "vec3d")
291  Name valueType() const override { return typeNameAsString<ValueType>(); }
292 
293  /// Return the name of this type of tree.
294  static const Name& treeType();
295  /// Return the name of this type of tree.
296  const Name& type() const override { return this->treeType(); }
297 
298  bool operator==(const Tree&) const { OPENVDB_THROW(NotImplementedError, ""); }
299  bool operator!=(const Tree&) const { OPENVDB_THROW(NotImplementedError, ""); }
300 
301  //@{
302  /// Return this tree's root node.
303  RootNodeType& root() { return mRoot; }
304  const RootNodeType& root() const { return mRoot; }
305  //@}
306 
307 
308  //
309  // Tree methods
310  //
311  /// @brief Return @c true if the given tree has the same node and active value
312  /// topology as this tree, whether or not it has the same @c ValueType.
313  template<typename OtherRootNodeType>
314  bool hasSameTopology(const Tree<OtherRootNodeType>& other) const;
315 
316  bool evalLeafBoundingBox(CoordBBox& bbox) const override;
317  bool evalActiveVoxelBoundingBox(CoordBBox& bbox) const override;
318  bool evalActiveVoxelDim(Coord& dim) const override;
319  bool evalLeafDim(Coord& dim) const override;
320 
321  /// @brief Traverse the type hierarchy of nodes, and return, in @a dims, a list
322  /// of the Log2Dims of nodes in order from RootNode to LeafNode.
323  /// @note Because RootNodes are resizable, the RootNode Log2Dim is 0 for all trees.
324  static void getNodeLog2Dims(std::vector<Index>& dims);
325 
326 
327  //
328  // I/O methods
329  //
330  /// @brief Read the tree topology from a stream.
331  ///
332  /// This will read the tree structure and tile values, but not voxel data.
333  void readTopology(std::istream&, bool saveFloatAsHalf = false) override;
334  /// @brief Write the tree topology to a stream.
335  ///
336  /// This will write the tree structure and tile values, but not voxel data.
337  void writeTopology(std::ostream&, bool saveFloatAsHalf = false) const override;
338  /// Read all data buffers for this tree.
339  void readBuffers(std::istream&, bool saveFloatAsHalf = false) override;
340  /// Read all of this tree's data buffers that intersect the given bounding box.
341  void readBuffers(std::istream&, const CoordBBox&, bool saveFloatAsHalf = false) override;
342  /// @brief Read all of this tree's data buffers that are not yet resident in memory
343  /// (because delayed loading is in effect).
344  /// @details If this tree was read from a memory-mapped file, this operation
345  /// disconnects the tree from the file.
346  /// @sa clipUnallocatedNodes, io::File::open, io::MappedFile
347  void readNonresidentBuffers() const override;
348  /// Write out all data buffers for this tree.
349  void writeBuffers(std::ostream&, bool saveFloatAsHalf = false) const override;
350 
351  void print(std::ostream& os = std::cout, int verboseLevel = 1) const override;
352 
353 
354  //
355  // Statistics
356  //
357  /// @brief Return the depth of this tree.
358  ///
359  /// A tree with only a root node and leaf nodes has depth 2, for example.
360  Index treeDepth() const override { return DEPTH; }
361  /// Return the number of leaf nodes.
362 #if OPENVDB_ABI_VERSION_NUMBER >= 12
363  Index64 leafCount() const override { return mRoot.leafCount(); }
364 #else
365  Index32 leafCount() const override { return static_cast<Index32>(mRoot.leafCount()); }
366 #endif
367  /// Return a vector with node counts. The number of nodes of type NodeType
368  /// is given as element NodeType::LEVEL in the return vector. Thus, the size
369  /// of this vector corresponds to the height (or depth) of this tree.
370 #if OPENVDB_ABI_VERSION_NUMBER >= 12
371  std::vector<Index64> nodeCount() const override
372  {
373  std::vector<Index64> vec(DEPTH, 0);
374  mRoot.nodeCount( vec );
375  return vec;// Named Return Value Optimization
376  }
377 #else
378  std::vector<Index32> nodeCount() const override
379  {
380  std::vector<Index32> vec(DEPTH, 0);
382  mRoot.nodeCount( vec );
384  return vec;// Named Return Value Optimization
385  }
386 #endif
387  /// Return the number of non-leaf nodes.
388 #if OPENVDB_ABI_VERSION_NUMBER >= 12
389  Index64 nonLeafCount() const override { return mRoot.nonLeafCount(); }
390 #else
391  Index32 nonLeafCount() const override { return static_cast<Index32>(mRoot.nonLeafCount()); }
392 #endif
393  /// Return the number of active voxels stored in leaf nodes.
394  Index64 activeLeafVoxelCount() const override { return tools::countActiveLeafVoxels(*this); }
395  /// Return the number of inactive voxels stored in leaf nodes.
397  /// Return the total number of active voxels.
398  Index64 activeVoxelCount() const override { return tools::countActiveVoxels(*this); }
399  /// Return the number of inactive voxels within the bounding box of all active voxels.
400  Index64 inactiveVoxelCount() const override { return tools::countInactiveVoxels(*this); }
401  /// Return the total number of active tiles.
402  Index64 activeTileCount() const override { return tools::countActiveTiles(*this); }
403 
404  Index64 memUsage() const override { return tools::memUsage(*this); }
405 
406 
407  //
408  // Voxel access methods (using signed indexing)
409  //
410  /// Return the value of the voxel at the given coordinates.
411  const ValueType& getValue(const Coord& xyz) const;
412  /// @brief Return the value of the voxel at the given coordinates
413  /// and update the given accessor's node cache.
414  template<typename AccessT> const ValueType& getValue(const Coord& xyz, AccessT&) const;
415 
416  /// @brief Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides.
417  /// @details If (x, y, z) isn't explicitly represented in the tree (i.e., it is
418  /// implicitly a background voxel), return -1.
419  int getValueDepth(const Coord& xyz) const;
420 
421  /// Set the active state of the voxel at the given coordinates but don't change its value.
422  void setActiveState(const Coord& xyz, bool on);
423  /// Set the value of the voxel at the given coordinates but don't change its active state.
424  void setValueOnly(const Coord& xyz, const ValueType& value);
425  /// Mark the voxel at the given coordinates as active but don't change its value.
426  void setValueOn(const Coord& xyz);
427  /// Set the value of the voxel at the given coordinates and mark the voxel as active.
428  void setValueOn(const Coord& xyz, const ValueType& value);
429  /// Set the value of the voxel at the given coordinates and mark the voxel as active.
430  void setValue(const Coord& xyz, const ValueType& value);
431  /// @brief Set the value of the voxel at the given coordinates, mark the voxel as active,
432  /// and update the given accessor's node cache.
433  template<typename AccessT> void setValue(const Coord& xyz, const ValueType& value, AccessT&);
434  /// Mark the voxel at the given coordinates as inactive but don't change its value.
435  void setValueOff(const Coord& xyz);
436  /// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
437  void setValueOff(const Coord& xyz, const ValueType& value);
438 
439  /// @brief Apply a functor to the value of the voxel at the given coordinates
440  /// and mark the voxel as active.
441  /// @details Provided that the functor can be inlined, this is typically
442  /// significantly faster than calling getValue() followed by setValueOn().
443  /// @param xyz the coordinates of a voxel whose value is to be modified
444  /// @param op a functor of the form <tt>void op(ValueType&) const</tt> that modifies
445  /// its argument in place
446  /// @par Example:
447  /// @code
448  /// Coord xyz(1, 0, -2);
449  /// // Multiply the value of a voxel by a constant and mark the voxel as active.
450  /// floatTree.modifyValue(xyz, [](float& f) { f *= 0.25; }); // C++11
451  /// // Set the value of a voxel to the maximum of its current value and 0.25,
452  /// // and mark the voxel as active.
453  /// floatTree.modifyValue(xyz, [](float& f) { f = std::max(f, 0.25f); }); // C++11
454  /// @endcode
455  /// @note The functor is not guaranteed to be called only once.
456  /// @see tools::foreach()
457  template<typename ModifyOp>
458  void modifyValue(const Coord& xyz, const ModifyOp& op);
459 
460  /// @brief Apply a functor to the voxel at the given coordinates.
461  /// @details Provided that the functor can be inlined, this is typically
462  /// significantly faster than calling getValue() followed by setValue().
463  /// @param xyz the coordinates of a voxel to be modified
464  /// @param op a functor of the form <tt>void op(ValueType&, bool&) const</tt> that
465  /// modifies its arguments, a voxel's value and active state, in place
466  /// @par Example:
467  /// @code
468  /// Coord xyz(1, 0, -2);
469  /// // Multiply the value of a voxel by a constant and mark the voxel as inactive.
470  /// floatTree.modifyValueAndActiveState(xyz,
471  /// [](float& f, bool& b) { f *= 0.25; b = false; }); // C++11
472  /// // Set the value of a voxel to the maximum of its current value and 0.25,
473  /// // but don't change the voxel's active state.
474  /// floatTree.modifyValueAndActiveState(xyz,
475  /// [](float& f, bool&) { f = std::max(f, 0.25f); }); // C++11
476  /// @endcode
477  /// @note The functor is not guaranteed to be called only once.
478  /// @see tools::foreach()
479  template<typename ModifyOp>
480  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op);
481 
482  /// @brief Get the value of the voxel at the given coordinates.
483  /// @return @c true if the value is active.
484  bool probeValue(const Coord& xyz, ValueType& value) const;
485 
486  /// Return @c true if the value at the given coordinates is active.
487  bool isValueOn(const Coord& xyz) const { return mRoot.isValueOn(xyz); }
488  /// Return @c true if the value at the given coordinates is inactive.
489  bool isValueOff(const Coord& xyz) const { return !this->isValueOn(xyz); }
490  /// Return @c true if this tree has any active tiles.
491  bool hasActiveTiles() const { return mRoot.hasActiveTiles(); }
492 
493  /// Set all voxels that lie outside the given axis-aligned box to the background.
494  void clip(const CoordBBox&);
495  /// @brief Replace with background tiles any nodes whose voxel buffers
496  /// have not yet been allocated.
497  /// @details Typically, unallocated nodes are leaf nodes whose voxel buffers
498  /// are not yet resident in memory because delayed loading is in effect.
499  /// @sa readNonresidentBuffers, io::File::open
500  void clipUnallocatedNodes() override;
501 
502  /// Return the total number of unallocated leaf nodes residing in this tree.
503 #if OPENVDB_ABI_VERSION_NUMBER >= 12
504  Index64 unallocatedLeafCount() const override;
505 #else
506  Index32 unallocatedLeafCount() const override;
507 #endif
508 
509  //@{
510  /// @brief Set all voxels within a given axis-aligned box to a constant value.
511  /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box
512  /// @param value the value to which to set voxels within the box
513  /// @param active if true, mark voxels within the box as active,
514  /// otherwise mark them as inactive
515  /// @note This operation generates a sparse, but not always optimally sparse,
516  /// representation of the filled box. Follow fill operations with a prune()
517  /// operation for optimal sparseness.
518  void sparseFill(const CoordBBox& bbox, const ValueType& value, bool active = true);
519  void fill(const CoordBBox& bbox, const ValueType& value, bool active = true)
520  {
521  this->sparseFill(bbox, value, active);
522  }
523  //@}
524 
525  /// @brief Set all voxels within a given axis-aligned box to a constant value
526  /// and ensure that those voxels are all represented at the leaf level.
527  /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box.
528  /// @param value the value to which to set voxels within the box.
529  /// @param active if true, mark voxels within the box as active,
530  /// otherwise mark them as inactive.
531  /// @sa voxelizeActiveTiles()
532  void denseFill(const CoordBBox& bbox, const ValueType& value, bool active = true);
533 
534  /// @brief Densify active tiles, i.e., replace them with leaf-level active voxels.
535  ///
536  /// @param threaded if true, this operation is multi-threaded (over the internal nodes).
537  ///
538  /// @warning This method can explode the tree's memory footprint, especially if it
539  /// contains active tiles at the upper levels (in particular the root level)!
540  ///
541  /// @sa denseFill()
542  void voxelizeActiveTiles(bool threaded = true);
543 
544  /// @brief Reduce the memory footprint of this tree by replacing with tiles
545  /// any nodes whose values are all the same (optionally to within a tolerance)
546  /// and have the same active state.
547  /// @warning Will soon be deprecated!
548  void prune(const ValueType& tolerance = zeroVal<ValueType>())
549  {
550  this->clearAllAccessors();
551  mRoot.prune(tolerance);
552  }
553 
554  /// @brief Add the given leaf node to this tree, creating a new branch if necessary.
555  /// If a leaf node with the same origin already exists, replace it.
556  ///
557  /// @warning Ownership of the leaf is transferred to the tree so
558  /// the client code should not attempt to delete the leaf pointer!
559  void addLeaf(LeafNodeType* leaf) { OPENVDB_ASSERT(leaf); mRoot.addLeaf(leaf); }
560 
561  /// @brief Add a tile containing voxel (x, y, z) at the specified tree level,
562  /// creating a new branch if necessary. Delete any existing lower-level nodes
563  /// that contain (x, y, z).
564  /// @note @a level must be less than this tree's depth.
565  void addTile(Index level, const Coord& xyz, const ValueType& value, bool active);
566 
567  /// @brief Return a pointer to the node of type @c NodeT that contains voxel (x, y, z)
568  /// and replace it with a tile of the specified value and state.
569  /// If no such node exists, leave the tree unchanged and return @c nullptr.
570  /// @note The caller takes ownership of the node and is responsible for deleting it.
571  template<typename NodeT>
572  NodeT* stealNode(const Coord& xyz, const ValueType& value, bool active);
573 
574  /// @brief Return a pointer to the leaf node that contains voxel (x, y, z).
575  /// If no such node exists, create one that preserves the values and
576  /// active states of all voxels.
577  /// @details Use this method to preallocate a static tree topology over which to
578  /// safely perform multithreaded processing.
579  LeafNodeType* touchLeaf(const Coord& xyz);
580 
581  //@{
582  /// @brief Return a pointer to the node of type @c NodeType that contains
583  /// voxel (x, y, z). If no such node exists, return @c nullptr.
584  template<typename NodeType> NodeType* probeNode(const Coord& xyz);
585  template<typename NodeType> const NodeType* probeConstNode(const Coord& xyz) const;
586  template<typename NodeType> const NodeType* probeNode(const Coord& xyz) const;
587  //@}
588 
589  //@{
590  /// @brief Return a pointer to the leaf node that contains voxel (x, y, z).
591  /// If no such node exists, return @c nullptr.
592  LeafNodeType* probeLeaf(const Coord& xyz);
593  const LeafNodeType* probeConstLeaf(const Coord& xyz) const;
594  const LeafNodeType* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
595  //@}
596 
597  //@{
598  /// @brief Adds all nodes of a certain type to a container with the following API:
599  /// @code
600  /// struct ArrayT {
601  /// using value_type = ...; // the type of node to be added to the array
602  /// void push_back(value_type nodePtr); // add a node to the array
603  /// };
604  /// @endcode
605  /// @details An example of a wrapper around a c-style array is:
606  /// @code
607  /// struct MyArray {
608  /// using value_type = LeafType*;
609  /// value_type* ptr;
610  /// MyArray(value_type* array) : ptr(array) {}
611  /// void push_back(value_type leaf) { *ptr++ = leaf; }
612  ///};
613  /// @endcode
614  /// @details An example that constructs a list of pointer to all leaf nodes is:
615  /// @code
616  /// std::vector<const LeafNodeType*> array;//most std contains have the required API
617  /// array.reserve(tree.leafCount());//this is a fast preallocation.
618  /// tree.getNodes(array);
619  /// @endcode
620  template<typename ArrayT> void getNodes(ArrayT& array);
621  template<typename ArrayT> void getNodes(ArrayT& array) const;
622  //@}
623 
624  /// @brief Steals all nodes of a certain type from the tree and
625  /// adds them to a container with the following API:
626  /// @code
627  /// struct ArrayT {
628  /// using value_type = ...; // the type of node to be added to the array
629  /// void push_back(value_type nodePtr); // add a node to the array
630  /// };
631  /// @endcode
632  /// @details An example of a wrapper around a c-style array is:
633  /// @code
634  /// struct MyArray {
635  /// using value_type = LeafType*;
636  /// value_type* ptr;
637  /// MyArray(value_type* array) : ptr(array) {}
638  /// void push_back(value_type leaf) { *ptr++ = leaf; }
639  ///};
640  /// @endcode
641  /// @details An example that constructs a list of pointer to all leaf nodes is:
642  /// @code
643  /// std::vector<const LeafNodeType*> array;//most std contains have the required API
644  /// array.reserve(tree.leafCount());//this is a fast preallocation.
645  /// tree.stealNodes(array);
646  /// @endcode
647  template<typename ArrayT>
648  void stealNodes(ArrayT& array) { this->clearAllAccessors(); mRoot.stealNodes(array); }
649  template<typename ArrayT>
650  void stealNodes(ArrayT& array, const ValueType& value, bool state)
651  {
652  this->clearAllAccessors();
653  mRoot.stealNodes(array, value, state);
654  }
655 
656  //
657  // Aux methods
658  //
659  /// @brief Return @c true if this tree contains no nodes other than
660  /// the root node and no tiles other than background tiles.
661  bool empty() const { return mRoot.empty(); }
662 
663  /// Remove all tiles from this tree and all nodes other than the root node.
664  void clear();
665 
666  /// @brief Return an accessor that provides random read and write access
667  /// to this tree's voxels.
668  /// @details The accessor is safe in the sense that it is registered with this tree.
670  /// @brief Return an unsafe accessor that provides random read and write access
671  /// to this tree's voxels.
672  /// @details The accessor is unsafe in the sense that it is not registered
673  /// with this tree's tree. In some rare cases this can give a performance advantage
674  /// over a registered accessor, but it is unsafe if the tree topology is modified.
675  /// @warning Only use this method if you're an expert and know the
676  /// risks of using an unregistered accessor (see tree/ValueAccessor.h)
678  /// Return an accessor that provides random read-only access to this tree's voxels.
679  ConstAccessor getAccessor() const;
680  /// Return an accessor that provides random read-only access to this tree's voxels.
682  /// @brief Return an unsafe accessor that provides random read-only access
683  /// to this tree's voxels.
684  /// @details The accessor is unsafe in the sense that it is not registered
685  /// with this tree. In some rare cases this can give a performance advantage
686  /// over a registered accessor, but it is unsafe if the tree topology is modified.
687  /// @warning Only use this method if you're an expert and know the
688  /// risks of using an unregistered accessor (see tree/ValueAccessor.h)
690 
691  /// Clear all registered accessors.
692  void clearAllAccessors();
693 
694  //@{
695  /// @brief Register an accessor for this tree. Registered accessors are
696  /// automatically cleared whenever one of this tree's nodes is deleted.
699  //@}
700 
701  //@{
702  /// Dummy implementations
705  //@}
706 
707  //@{
708  /// Deregister an accessor so that it is no longer automatically cleared.
711  //@}
712 
713  //@{
714  /// Dummy implementations
717  //@}
718 
719  /// @brief Return this tree's background value wrapped as metadata.
720  /// @note Query the metadata object for the value's type.
721  Metadata::Ptr getBackgroundValue() const override;
722 
723  /// @brief Return this tree's background value.
724  ///
725  /// @note Use tools::changeBackground to efficiently modify the
726  /// background values. Else use tree.root().setBackground, which
727  /// is serial and hence slower.
728  const ValueType& background() const { return mRoot.background(); }
729 
730  /// Min and max are both inclusive.
731  void getIndexRange(CoordBBox& bbox) const override { mRoot.getIndexRange(bbox); }
732 
733  /// @brief Efficiently merge another tree into this tree using one of several schemes.
734  /// @details This operation is primarily intended to combine trees that are mostly
735  /// non-overlapping (for example, intermediate trees from computations that are
736  /// parallelized across disjoint regions of space).
737  /// @note This operation is not guaranteed to produce an optimally sparse tree.
738  /// Follow merge() with prune() for optimal sparseness.
739  /// @warning This operation always empties the other tree.
740  void merge(Tree& other, MergePolicy = MERGE_ACTIVE_STATES);
741 
742  /// @brief Union this tree's set of active values with the active values
743  /// of the other tree, whose @c ValueType may be different.
744  /// @details The resulting state of a value is active if the corresponding value
745  /// was already active OR if it is active in the other tree. Also, a resulting
746  /// value maps to a voxel if the corresponding value already mapped to a voxel
747  /// OR if it is a voxel in the other tree. Thus, a resulting value can only
748  /// map to a tile if the corresponding value already mapped to a tile
749  /// AND if it is a tile value in other tree.
750  ///
751  /// @note This operation modifies only active states, not values.
752  /// Specifically, active tiles and voxels in this tree are not changed, and
753  /// tiles or voxels that were inactive in this tree but active in the other tree
754  /// are marked as active in this tree but left with their original values.
755  ///
756  /// @note If preserveTiles is true, any active tile in this topology
757  /// will not be densified by overlapping child topology.
758  template<typename OtherRootNodeType>
759  void topologyUnion(const Tree<OtherRootNodeType>& other, const bool preserveTiles = false);
760 
761  /// @brief Intersects this tree's set of active values with the active values
762  /// of the other tree, whose @c ValueType may be different.
763  /// @details The resulting state of a value is active only if the corresponding
764  /// value was already active AND if it is active in the other tree. Also, a
765  /// resulting value maps to a voxel if the corresponding value
766  /// already mapped to an active voxel in either of the two grids
767  /// and it maps to an active tile or voxel in the other grid.
768  ///
769  /// @note This operation can delete branches in this grid if they
770  /// overlap with inactive tiles in the other grid. Likewise active
771  /// voxels can be turned into inactive voxels resulting in leaf
772  /// nodes with no active values. Thus, it is recommended to
773  /// subsequently call tools::pruneInactive.
774  template<typename OtherRootNodeType>
776 
777  /// @brief Difference this tree's set of active values with the active values
778  /// of the other tree, whose @c ValueType may be different. So a
779  /// resulting voxel will be active only if the original voxel is
780  /// active in this tree and inactive in the other tree.
781  ///
782  /// @note This operation can delete branches in this grid if they
783  /// overlap with active tiles in the other grid. Likewise active
784  /// voxels can be turned into inactive voxels resulting in leaf
785  /// nodes with no active values. Thus, it is recommended to
786  /// subsequently call tools::pruneInactive.
787  template<typename OtherRootNodeType>
788  void topologyDifference(const Tree<OtherRootNodeType>& other);
789 
790  /// For a given function @c f, use sparse traversal to compute <tt>f(this, other)</tt>
791  /// over all corresponding pairs of values (tile or voxel) of this tree and the other tree
792  /// and store the result in this tree.
793  /// This method is typically more space-efficient than the two-tree combine2(),
794  /// since it moves rather than copies nodes from the other tree into this tree.
795  /// @note This operation always empties the other tree.
796  /// @param other a tree of the same type as this tree
797  /// @param op a functor of the form <tt>void op(const T& a, const T& b, T& result)</tt>,
798  /// where @c T is this tree's @c ValueType, that computes
799  /// <tt>result = f(a, b)</tt>
800  /// @param prune if true, prune the resulting tree one branch at a time (this is usually
801  /// more space-efficient than pruning the entire tree in one pass)
802  ///
803  /// @par Example:
804  /// Compute the per-voxel difference between two floating-point trees,
805  /// @c aTree and @c bTree, and store the result in @c aTree (leaving @c bTree empty).
806  /// @code
807  /// {
808  /// struct Local {
809  /// static inline void diff(const float& a, const float& b, float& result) {
810  /// result = a - b;
811  /// }
812  /// };
813  /// aTree.combine(bTree, Local::diff);
814  /// }
815  /// @endcode
816  ///
817  /// @par Example:
818  /// Compute <tt>f * a + (1 - f) * b</tt> over all voxels of two floating-point trees,
819  /// @c aTree and @c bTree, and store the result in @c aTree (leaving @c bTree empty).
820  /// @code
821  /// namespace {
822  /// struct Blend {
823  /// Blend(float f): frac(f) {}
824  /// inline void operator()(const float& a, const float& b, float& result) const {
825  /// result = frac * a + (1.0 - frac) * b;
826  /// }
827  /// float frac;
828  /// };
829  /// }
830  /// {
831  /// aTree.combine(bTree, Blend(0.25)); // 0.25 * a + 0.75 * b
832  /// }
833  /// @endcode
834  template<typename CombineOp>
835  void combine(Tree& other, CombineOp& op, bool prune = false);
836  template<typename CombineOp>
837  void combine(Tree& other, const CombineOp& op, bool prune = false);
838 
839  /// Like combine(), but with
840  /// @param other a tree of the same type as this tree
841  /// @param op a functor of the form <tt>void op(CombineArgs<ValueType>& args)</tt> that
842  /// computes <tt>args.setResult(f(args.a(), args.b()))</tt> and, optionally,
843  /// <tt>args.setResultIsActive(g(args.aIsActive(), args.bIsActive()))</tt>
844  /// for some functions @c f and @c g
845  /// @param prune if true, prune the resulting tree one branch at a time (this is usually
846  /// more space-efficient than pruning the entire tree in one pass)
847  ///
848  /// This variant passes not only the @em a and @em b values but also the active states
849  /// of the @em a and @em b values to the functor, which may then return, by calling
850  /// @c args.setResultIsActive(), a computed active state for the result value.
851  /// By default, the result is active if either the @em a or the @em b value is active.
852  ///
853  /// @see openvdb/Types.h for the definition of the CombineArgs struct.
854  ///
855  /// @par Example:
856  /// Replace voxel values in floating-point @c aTree with corresponding values
857  /// from floating-point @c bTree (leaving @c bTree empty) wherever the @c bTree
858  /// values are larger. Also, preserve the active states of any transferred values.
859  /// @code
860  /// {
861  /// struct Local {
862  /// static inline void max(CombineArgs<float>& args) {
863  /// if (args.b() > args.a()) {
864  /// // Transfer the B value and its active state.
865  /// args.setResult(args.b());
866  /// args.setResultIsActive(args.bIsActive());
867  /// } else {
868  /// // Preserve the A value and its active state.
869  /// args.setResult(args.a());
870  /// args.setResultIsActive(args.aIsActive());
871  /// }
872  /// }
873  /// };
874  /// aTree.combineExtended(bTree, Local::max);
875  /// }
876  /// @endcode
877  template<typename ExtendedCombineOp>
878  void combineExtended(Tree& other, ExtendedCombineOp& op, bool prune = false);
879  template<typename ExtendedCombineOp>
880  void combineExtended(Tree& other, const ExtendedCombineOp& op, bool prune = false);
881 
882  /// For a given function @c f, use sparse traversal to compute <tt>f(a, b)</tt> over all
883  /// corresponding pairs of values (tile or voxel) of trees A and B and store the result
884  /// in this tree.
885  /// @param a,b two trees with the same configuration (levels and node dimensions)
886  /// as this tree but with the B tree possibly having a different value type
887  /// @param op a functor of the form <tt>void op(const T1& a, const T2& b, T1& result)</tt>,
888  /// where @c T1 is this tree's and the A tree's @c ValueType and @c T2 is the
889  /// B tree's @c ValueType, that computes <tt>result = f(a, b)</tt>
890  /// @param prune if true, prune the resulting tree one branch at a time (this is usually
891  /// more space-efficient than pruning the entire tree in one pass)
892  ///
893  /// @throw TypeError if the B tree's configuration doesn't match this tree's
894  /// or if this tree's ValueType is not constructible from the B tree's ValueType.
895  ///
896  /// @par Example:
897  /// Compute the per-voxel difference between two floating-point trees,
898  /// @c aTree and @c bTree, and store the result in a third tree.
899  /// @code
900  /// {
901  /// struct Local {
902  /// static inline void diff(const float& a, const float& b, float& result) {
903  /// result = a - b;
904  /// }
905  /// };
906  /// FloatTree resultTree;
907  /// resultTree.combine2(aTree, bTree, Local::diff);
908  /// }
909  /// @endcode
910  template<typename CombineOp, typename OtherTreeType /*= Tree*/>
911  void combine2(const Tree& a, const OtherTreeType& b, CombineOp& op, bool prune = false);
912  template<typename CombineOp, typename OtherTreeType /*= Tree*/>
913  void combine2(const Tree& a, const OtherTreeType& b, const CombineOp& op, bool prune = false);
914 
915  /// Like combine2(), but with
916  /// @param a,b two trees with the same configuration (levels and node dimensions)
917  /// as this tree but with the B tree possibly having a different value type
918  /// @param op a functor of the form <tt>void op(CombineArgs<T1, T2>& args)</tt>, where
919  /// @c T1 is this tree's and the A tree's @c ValueType and @c T2 is the B tree's
920  /// @c ValueType, that computes <tt>args.setResult(f(args.a(), args.b()))</tt>
921  /// and, optionally,
922  /// <tt>args.setResultIsActive(g(args.aIsActive(), args.bIsActive()))</tt>
923  /// for some functions @c f and @c g
924  /// @param prune if true, prune the resulting tree one branch at a time (this is usually
925  /// more space-efficient than pruning the entire tree in one pass)
926  /// This variant passes not only the @em a and @em b values but also the active states
927  /// of the @em a and @em b values to the functor, which may then return, by calling
928  /// <tt>args.setResultIsActive()</tt>, a computed active state for the result value.
929  /// By default, the result is active if either the @em a or the @em b value is active.
930  ///
931  /// @throw TypeError if the B tree's configuration doesn't match this tree's
932  /// or if this tree's ValueType is not constructible from the B tree's ValueType.
933  ///
934  /// @see openvdb/Types.h for the definition of the CombineArgs struct.
935  ///
936  /// @par Example:
937  /// Compute the per-voxel maximum values of two single-precision floating-point trees,
938  /// @c aTree and @c bTree, and store the result in a third tree. Set the active state
939  /// of each output value to that of the larger of the two input values.
940  /// @code
941  /// {
942  /// struct Local {
943  /// static inline void max(CombineArgs<float>& args) {
944  /// if (args.b() > args.a()) {
945  /// // Transfer the B value and its active state.
946  /// args.setResult(args.b());
947  /// args.setResultIsActive(args.bIsActive());
948  /// } else {
949  /// // Preserve the A value and its active state.
950  /// args.setResult(args.a());
951  /// args.setResultIsActive(args.aIsActive());
952  /// }
953  /// }
954  /// };
955  /// FloatTree aTree = ...;
956  /// FloatTree bTree = ...;
957  /// FloatTree resultTree;
958  /// resultTree.combine2Extended(aTree, bTree, Local::max);
959  /// }
960  /// @endcode
961  ///
962  /// @par Example:
963  /// Compute the per-voxel maximum values of a double-precision and a single-precision
964  /// floating-point tree, @c aTree and @c bTree, and store the result in a third,
965  /// double-precision tree. Set the active state of each output value to that of
966  /// the larger of the two input values.
967  /// @code
968  /// {
969  /// struct Local {
970  /// static inline void max(CombineArgs<double, float>& args) {
971  /// if (args.b() > args.a()) {
972  /// // Transfer the B value and its active state.
973  /// args.setResult(args.b());
974  /// args.setResultIsActive(args.bIsActive());
975  /// } else {
976  /// // Preserve the A value and its active state.
977  /// args.setResult(args.a());
978  /// args.setResultIsActive(args.aIsActive());
979  /// }
980  /// }
981  /// };
982  /// DoubleTree aTree = ...;
983  /// FloatTree bTree = ...;
984  /// DoubleTree resultTree;
985  /// resultTree.combine2Extended(aTree, bTree, Local::max);
986  /// }
987  /// @endcode
988  template<typename ExtendedCombineOp, typename OtherTreeType /*= Tree*/>
989  void combine2Extended(const Tree& a, const OtherTreeType& b, ExtendedCombineOp& op,
990  bool prune = false);
991  template<typename ExtendedCombineOp, typename OtherTreeType /*= Tree*/>
992  void combine2Extended(const Tree& a, const OtherTreeType& b, const ExtendedCombineOp&,
993  bool prune = false);
994 
995  //
996  // Iteration
997  //
998  //@{
999  /// Return an iterator over children of the root node.
1000  typename RootNodeType::ChildOnCIter beginRootChildren() const { return mRoot.cbeginChildOn(); }
1001  typename RootNodeType::ChildOnCIter cbeginRootChildren() const { return mRoot.cbeginChildOn(); }
1002  typename RootNodeType::ChildOnIter beginRootChildren() { return mRoot.beginChildOn(); }
1003  //@}
1004 
1005  //@{
1006  /// Return an iterator over non-child entries of the root node's table.
1007  typename RootNodeType::ChildOffCIter beginRootTiles() const { return mRoot.cbeginChildOff(); }
1008  typename RootNodeType::ChildOffCIter cbeginRootTiles() const { return mRoot.cbeginChildOff(); }
1009  typename RootNodeType::ChildOffIter beginRootTiles() { return mRoot.beginChildOff(); }
1010  //@}
1011 
1012  //@{
1013  /// Return an iterator over all entries of the root node's table.
1014  typename RootNodeType::ChildAllCIter beginRootDense() const { return mRoot.cbeginChildAll(); }
1015  typename RootNodeType::ChildAllCIter cbeginRootDense() const { return mRoot.cbeginChildAll(); }
1016  typename RootNodeType::ChildAllIter beginRootDense() { return mRoot.beginChildAll(); }
1017  //@}
1018 
1019 
1020  //@{
1021  /// Iterator over all nodes in this tree
1024  //@}
1025 
1026  //@{
1027  /// Iterator over all leaf nodes in this tree
1030  //@}
1031 
1032  //@{
1033  /// Return an iterator over all nodes in this tree.
1034  NodeIter beginNode() { return NodeIter(*this); }
1035  NodeCIter beginNode() const { return NodeCIter(*this); }
1036  NodeCIter cbeginNode() const { return NodeCIter(*this); }
1037  //@}
1038 
1039  //@{
1040  /// Return an iterator over all leaf nodes in this tree.
1041  LeafIter beginLeaf() { return LeafIter(*this); }
1042  LeafCIter beginLeaf() const { return LeafCIter(*this); }
1043  LeafCIter cbeginLeaf() const { return LeafCIter(*this); }
1044  //@}
1045 
1052 
1053  //@{
1054  /// Return an iterator over all values (tile and voxel) across all nodes.
1056  ValueAllCIter beginValueAll() const { return ValueAllCIter(*this); }
1057  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(*this); }
1058  //@}
1059  //@{
1060  /// Return an iterator over active values (tile and voxel) across all nodes.
1061  ValueOnIter beginValueOn() { return ValueOnIter(*this); }
1062  ValueOnCIter beginValueOn() const { return ValueOnCIter(*this); }
1063  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(*this); }
1064  //@}
1065  //@{
1066  /// Return an iterator over inactive values (tile and voxel) across all nodes.
1068  ValueOffCIter beginValueOff() const { return ValueOffCIter(*this); }
1069  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(*this); }
1070  //@}
1071 
1072  /// @brief Return an iterator of type @c IterT (for example, begin<ValueOnIter>() is
1073  /// equivalent to beginValueOn()).
1074  template<typename IterT> IterT begin();
1075  /// @brief Return a const iterator of type CIterT (for example, cbegin<ValueOnCIter>()
1076  /// is equivalent to cbeginValueOn()).
1077  template<typename CIterT> CIterT cbegin() const;
1078 
1079 
1080 protected:
1081  using AccessorRegistry = tbb::concurrent_hash_map<ValueAccessorBase<Tree, true>*, bool>;
1082  using ConstAccessorRegistry = tbb::concurrent_hash_map<ValueAccessorBase<const Tree, true>*, bool>;
1083 
1084  /// @brief Notify all registered accessors, by calling ValueAccessor::release(),
1085  /// that this tree is about to be deleted.
1086  void releaseAllAccessors();
1087 
1088  // TBB body object used to deallocates nodes in parallel.
1089  template<typename NodeType>
1091  DeallocateNodes(std::vector<NodeType*>& nodes)
1092  : mNodes(nodes.empty() ? nullptr : &nodes.front()) { }
1093  void operator()(const tbb::blocked_range<size_t>& range) const {
1094  for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
1095  delete mNodes[n]; mNodes[n] = nullptr;
1096  }
1097  }
1098  NodeType ** const mNodes;
1099  };
1100 
1101  //
1102  // Data members
1103  //
1104  RootNodeType mRoot; // root node of the tree
1107 }; // end of Tree class
1108 
1109 
1110 /// @brief Tree3<T, N1, N2>::Type is the type of a three-level tree
1111 /// (Root, Internal, Leaf) with value type T and
1112 /// internal and leaf node log dimensions N1 and N2, respectively.
1113 /// @note This is NOT the standard tree configuration (Tree4 is).
1114 template<typename T, Index N1=4, Index N2=3>
1115 struct Tree3 {
1117 };
1118 
1119 
1120 /// @brief Tree4<T, N1, N2, N3>::Type is the type of a four-level tree
1121 /// (Root, Internal, Internal, Leaf) with value type T and
1122 /// internal and leaf node log dimensions N1, N2 and N3, respectively.
1123 /// @note This is the standard tree configuration.
1124 template<typename T, Index N1=5, Index N2=4, Index N3=3>
1125 struct Tree4 {
1127 };
1128 
1129 /// @brief Tree5<T, N1, N2, N3, N4>::Type is the type of a five-level tree
1130 /// (Root, Internal, Internal, Internal, Leaf) with value type T and
1131 /// internal and leaf node log dimensions N1, N2, N3 and N4, respectively.
1132 /// @note This is NOT the standard tree configuration (Tree4 is).
1133 template<typename T, Index N1=6, Index N2=5, Index N3=4, Index N4=3>
1134 struct Tree5 {
1135  using Type =
1137 };
1138 
1139 
1140 ////////////////////////////////////////
1141 
1142 
1143 inline void
1144 TreeBase::readTopology(std::istream& is, bool /*saveFloatAsHalf*/)
1145 {
1146  int32_t bufferCount;
1147  is.read(reinterpret_cast<char*>(&bufferCount), sizeof(int32_t));
1148  if (bufferCount != 1) OPENVDB_LOG_WARN("multi-buffer trees are no longer supported");
1149 }
1150 
1151 
1152 inline void
1153 TreeBase::writeTopology(std::ostream& os, bool /*saveFloatAsHalf*/) const
1154 {
1155  int32_t bufferCount = 1;
1156  os.write(reinterpret_cast<char*>(&bufferCount), sizeof(int32_t));
1157 }
1158 
1159 
1160 inline void
1161 TreeBase::print(std::ostream& os, int /*verboseLevel*/) const
1162 {
1163  os << " Tree Type: " << type()
1164  << " Active Voxel Count: " << activeVoxelCount() << std::endl
1165  << " Active tile Count: " << activeTileCount() << std::endl
1166  << " Inactive Voxel Count: " << inactiveVoxelCount() << std::endl
1167  << " Leaf Node Count: " << leafCount() << std::endl
1168  << " Non-leaf Node Count: " << nonLeafCount() << std::endl;
1169 }
1170 
1171 
1172 ////////////////////////////////////////
1173 
1174 
1175 //
1176 // Type traits for tree iterators
1177 //
1178 
1179 /// @brief TreeIterTraits provides, for all tree iterators, a begin(tree) function
1180 /// that returns an iterator over a tree of arbitrary type.
1181 template<typename TreeT, typename IterT> struct TreeIterTraits;
1182 
1183 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOnIter> {
1184  static typename TreeT::RootNodeType::ChildOnIter begin(TreeT& tree) {
1185  return tree.beginRootChildren();
1186  }
1187 };
1188 
1189 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOnCIter> {
1190  static typename TreeT::RootNodeType::ChildOnCIter begin(const TreeT& tree) {
1191  return tree.cbeginRootChildren();
1192  }
1193 };
1194 
1195 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOffIter> {
1196  static typename TreeT::RootNodeType::ChildOffIter begin(TreeT& tree) {
1197  return tree.beginRootTiles();
1198  }
1199 };
1200 
1201 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOffCIter> {
1202  static typename TreeT::RootNodeType::ChildOffCIter begin(const TreeT& tree) {
1203  return tree.cbeginRootTiles();
1204  }
1205 };
1206 
1207 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildAllIter> {
1208  static typename TreeT::RootNodeType::ChildAllIter begin(TreeT& tree) {
1209  return tree.beginRootDense();
1210  }
1211 };
1212 
1213 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildAllCIter> {
1214  static typename TreeT::RootNodeType::ChildAllCIter begin(const TreeT& tree) {
1215  return tree.cbeginRootDense();
1216  }
1217 };
1218 
1219 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::NodeIter> {
1220  static typename TreeT::NodeIter begin(TreeT& tree) { return tree.beginNode(); }
1221 };
1222 
1223 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::NodeCIter> {
1224  static typename TreeT::NodeCIter begin(const TreeT& tree) { return tree.cbeginNode(); }
1225 };
1226 
1227 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::LeafIter> {
1228  static typename TreeT::LeafIter begin(TreeT& tree) { return tree.beginLeaf(); }
1229 };
1230 
1231 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::LeafCIter> {
1232  static typename TreeT::LeafCIter begin(const TreeT& tree) { return tree.cbeginLeaf(); }
1233 };
1234 
1235 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOnIter> {
1236  static typename TreeT::ValueOnIter begin(TreeT& tree) { return tree.beginValueOn(); }
1237 };
1238 
1239 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOnCIter> {
1240  static typename TreeT::ValueOnCIter begin(const TreeT& tree) { return tree.cbeginValueOn(); }
1241 };
1242 
1243 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOffIter> {
1244  static typename TreeT::ValueOffIter begin(TreeT& tree) { return tree.beginValueOff(); }
1245 };
1246 
1247 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOffCIter> {
1248  static typename TreeT::ValueOffCIter begin(const TreeT& tree) { return tree.cbeginValueOff(); }
1249 };
1250 
1251 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueAllIter> {
1252  static typename TreeT::ValueAllIter begin(TreeT& tree) { return tree.beginValueAll(); }
1253 };
1254 
1255 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueAllCIter> {
1256  static typename TreeT::ValueAllCIter begin(const TreeT& tree) { return tree.cbeginValueAll(); }
1257 };
1258 
1259 
1260 template<typename RootNodeType>
1261 template<typename IterT>
1262 inline IterT
1264 {
1265  return TreeIterTraits<Tree, IterT>::begin(*this);
1266 }
1267 
1268 
1269 template<typename RootNodeType>
1270 template<typename IterT>
1271 inline IterT
1273 {
1274  return TreeIterTraits<Tree, IterT>::begin(*this);
1275 }
1276 
1277 
1278 ////////////////////////////////////////
1279 
1280 
1281 template<typename RootNodeType>
1282 void
1283 Tree<RootNodeType>::readTopology(std::istream& is, bool saveFloatAsHalf)
1284 {
1285  this->clearAllAccessors();
1286  TreeBase::readTopology(is, saveFloatAsHalf);
1287  mRoot.readTopology(is, saveFloatAsHalf);
1288 }
1289 
1290 
1291 template<typename RootNodeType>
1292 void
1293 Tree<RootNodeType>::writeTopology(std::ostream& os, bool saveFloatAsHalf) const
1294 {
1295  TreeBase::writeTopology(os, saveFloatAsHalf);
1296  mRoot.writeTopology(os, saveFloatAsHalf);
1297 }
1298 
1299 
1300 template<typename RootNodeType>
1301 inline void
1302 Tree<RootNodeType>::readBuffers(std::istream &is, bool saveFloatAsHalf)
1303 {
1304  this->clearAllAccessors();
1305  mRoot.readBuffers(is, saveFloatAsHalf);
1306 }
1307 
1308 
1309 template<typename RootNodeType>
1310 inline void
1311 Tree<RootNodeType>::readBuffers(std::istream &is, const CoordBBox& bbox, bool saveFloatAsHalf)
1312 {
1313  this->clearAllAccessors();
1314  mRoot.readBuffers(is, bbox, saveFloatAsHalf);
1315 }
1316 
1317 
1318 template<typename RootNodeType>
1319 inline void
1321 {
1322  for (LeafCIter it = this->cbeginLeaf(); it; ++it) {
1323  // Retrieving the value of a leaf voxel forces loading of the leaf node's voxel buffer.
1324  it->getValue(Index(0));
1325  }
1326 }
1327 
1328 
1329 template<typename RootNodeType>
1330 inline void
1331 Tree<RootNodeType>::writeBuffers(std::ostream &os, bool saveFloatAsHalf) const
1332 {
1333  mRoot.writeBuffers(os, saveFloatAsHalf);
1334 }
1335 
1336 
1337 template<typename RootNodeType>
1338 template<typename ArrayT>
1339 inline void
1341 {
1344  "getNodes() does not work for the RootNode. Use Tree::root()");
1345  mRoot.getNodes(array);
1346 }
1347 
1348 
1349 template<typename RootNodeType>
1350 template<typename ArrayT>
1351 inline void
1352 Tree<RootNodeType>::getNodes(ArrayT& array) const
1353 {
1356  "getNodes() does not work for the RootNode. Use Tree::root()");
1357  mRoot.getNodes(array);
1358 }
1359 
1360 
1361 template<typename RootNodeType>
1362 inline void
1364 {
1365  std::vector<LeafNodeType*> leafnodes;
1366  this->stealNodes(leafnodes);
1367 
1368  tbb::parallel_for(tbb::blocked_range<size_t>(0, leafnodes.size()),
1369  DeallocateNodes<LeafNodeType>(leafnodes));
1370 
1371  std::vector<typename RootNodeType::ChildNodeType*> internalNodes;
1372  this->stealNodes(internalNodes);
1373 
1374  tbb::parallel_for(tbb::blocked_range<size_t>(0, internalNodes.size()),
1376 
1377  mRoot.clear();
1378 
1379  this->clearAllAccessors();
1380 }
1381 
1382 
1383 ////////////////////////////////////////
1384 
1385 
1386 template<typename RootNodeType>
1389 {
1390  return Accessor(*this);
1391 }
1392 
1393 template<typename RootNodeType>
1396 {
1397  return UnsafeAccessor(*this);
1398 }
1399 
1400 template<typename RootNodeType>
1403 {
1404  return ConstAccessor(*this);
1405 }
1406 
1407 template<typename RootNodeType>
1410 {
1411  return ConstAccessor(*this);
1412 }
1413 
1414 template<typename RootNodeType>
1417 {
1418  return ConstUnsafeAccessor(*this);
1419 }
1420 
1421 template<typename RootNodeType>
1422 inline void
1424 {
1425  typename AccessorRegistry::accessor a;
1426  mAccessorRegistry.insert(a, &accessor);
1427 }
1428 
1429 
1430 template<typename RootNodeType>
1431 inline void
1433 {
1434  typename ConstAccessorRegistry::accessor a;
1435  mConstAccessorRegistry.insert(a, &accessor);
1436 }
1437 
1438 
1439 template<typename RootNodeType>
1440 inline void
1442 {
1443  mAccessorRegistry.erase(&accessor);
1444 }
1445 
1446 
1447 template<typename RootNodeType>
1448 inline void
1450 {
1451  mConstAccessorRegistry.erase(&accessor);
1452 }
1453 
1454 
1455 template<typename RootNodeType>
1456 inline void
1458 {
1459  for (typename AccessorRegistry::iterator it = mAccessorRegistry.begin();
1460  it != mAccessorRegistry.end(); ++it)
1461  {
1462  if (it->first) it->first->clear();
1463  }
1464 
1465  for (typename ConstAccessorRegistry::iterator it = mConstAccessorRegistry.begin();
1466  it != mConstAccessorRegistry.end(); ++it)
1467  {
1468  if (it->first) it->first->clear();
1469  }
1470 }
1471 
1472 
1473 template<typename RootNodeType>
1474 inline void
1476 {
1477  mAccessorRegistry.erase(nullptr);
1478  for (typename AccessorRegistry::iterator it = mAccessorRegistry.begin();
1479  it != mAccessorRegistry.end(); ++it)
1480  {
1481  it->first->release();
1482  }
1483  mAccessorRegistry.clear();
1484 
1485  mAccessorRegistry.erase(nullptr);
1486  for (typename ConstAccessorRegistry::iterator it = mConstAccessorRegistry.begin();
1487  it != mConstAccessorRegistry.end(); ++it)
1488  {
1489  it->first->release();
1490  }
1491  mConstAccessorRegistry.clear();
1492 }
1493 
1494 
1495 ////////////////////////////////////////
1496 
1497 
1498 template<typename RootNodeType>
1499 inline const typename RootNodeType::ValueType&
1500 Tree<RootNodeType>::getValue(const Coord& xyz) const
1501 {
1502  return mRoot.getValue(xyz);
1503 }
1504 
1505 
1506 template<typename RootNodeType>
1507 template<typename AccessT>
1508 inline const typename RootNodeType::ValueType&
1509 Tree<RootNodeType>::getValue(const Coord& xyz, AccessT& accessor) const
1510 {
1511  return accessor.getValue(xyz);
1512 }
1513 
1514 
1515 template<typename RootNodeType>
1516 inline int
1517 Tree<RootNodeType>::getValueDepth(const Coord& xyz) const
1518 {
1519  return mRoot.getValueDepth(xyz);
1520 }
1521 
1522 
1523 template<typename RootNodeType>
1524 inline void
1526 {
1527  mRoot.setValueOff(xyz);
1528 }
1529 
1530 
1531 template<typename RootNodeType>
1532 inline void
1534 {
1535  mRoot.setValueOff(xyz, value);
1536 }
1537 
1538 
1539 template<typename RootNodeType>
1540 inline void
1541 Tree<RootNodeType>::setActiveState(const Coord& xyz, bool on)
1542 {
1543  mRoot.setActiveState(xyz, on);
1544 }
1545 
1546 
1547 template<typename RootNodeType>
1548 inline void
1550 {
1551  mRoot.setValueOn(xyz, value);
1552 }
1553 
1554 template<typename RootNodeType>
1555 inline void
1557 {
1558  mRoot.setValueOnly(xyz, value);
1559 }
1560 
1561 template<typename RootNodeType>
1562 template<typename AccessT>
1563 inline void
1564 Tree<RootNodeType>::setValue(const Coord& xyz, const ValueType& value, AccessT& accessor)
1565 {
1566  accessor.setValue(xyz, value);
1567 }
1568 
1569 
1570 template<typename RootNodeType>
1571 inline void
1573 {
1574  mRoot.setActiveState(xyz, true);
1575 }
1576 
1577 
1578 template<typename RootNodeType>
1579 inline void
1581 {
1582  mRoot.setValueOn(xyz, value);
1583 }
1584 
1585 
1586 template<typename RootNodeType>
1587 template<typename ModifyOp>
1588 inline void
1589 Tree<RootNodeType>::modifyValue(const Coord& xyz, const ModifyOp& op)
1590 {
1591  mRoot.modifyValue(xyz, op);
1592 }
1593 
1594 
1595 template<typename RootNodeType>
1596 template<typename ModifyOp>
1597 inline void
1598 Tree<RootNodeType>::modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1599 {
1600  mRoot.modifyValueAndActiveState(xyz, op);
1601 }
1602 
1603 
1604 template<typename RootNodeType>
1605 inline bool
1607 {
1608  return mRoot.probeValue(xyz, value);
1609 }
1610 
1611 
1612 ////////////////////////////////////////
1613 
1614 
1615 template<typename RootNodeType>
1616 inline void
1618  const ValueType& value, bool active)
1619 {
1620  mRoot.addTile(level, xyz, value, active);
1621 }
1622 
1623 
1624 template<typename RootNodeType>
1625 template<typename NodeT>
1626 inline NodeT*
1627 Tree<RootNodeType>::stealNode(const Coord& xyz, const ValueType& value, bool active)
1628 {
1629  this->clearAllAccessors();
1630  return mRoot.template stealNode<NodeT>(xyz, value, active);
1631 }
1632 
1633 
1634 template<typename RootNodeType>
1635 inline typename RootNodeType::LeafNodeType*
1637 {
1638  return mRoot.touchLeaf(xyz);
1639 }
1640 
1641 
1642 template<typename RootNodeType>
1643 inline typename RootNodeType::LeafNodeType*
1645 {
1646  return mRoot.probeLeaf(xyz);
1647 }
1648 
1649 
1650 template<typename RootNodeType>
1651 inline const typename RootNodeType::LeafNodeType*
1652 Tree<RootNodeType>::probeConstLeaf(const Coord& xyz) const
1653 {
1654  return mRoot.probeConstLeaf(xyz);
1655 }
1656 
1657 
1658 template<typename RootNodeType>
1659 template<typename NodeType>
1660 inline NodeType*
1662 {
1663  return mRoot.template probeNode<NodeType>(xyz);
1664 }
1665 
1666 
1667 template<typename RootNodeType>
1668 template<typename NodeType>
1669 inline const NodeType*
1670 Tree<RootNodeType>::probeNode(const Coord& xyz) const
1671 {
1672  return this->template probeConstNode<NodeType>(xyz);
1673 }
1674 
1675 
1676 template<typename RootNodeType>
1677 template<typename NodeType>
1678 inline const NodeType*
1679 Tree<RootNodeType>::probeConstNode(const Coord& xyz) const
1680 {
1681  return mRoot.template probeConstNode<NodeType>(xyz);
1682 }
1683 
1684 
1685 ////////////////////////////////////////
1686 
1687 
1688 template<typename RootNodeType>
1689 inline void
1691 {
1692  this->clearAllAccessors();
1693  return mRoot.clip(bbox);
1694 }
1695 
1696 
1697 template<typename RootNodeType>
1698 inline void
1700 {
1701  this->clearAllAccessors();
1702  for (LeafIter it = this->beginLeaf(); it; ) {
1703  const LeafNodeType* leaf = it.getLeaf();
1704  ++it; // advance the iterator before deleting the leaf node
1705  if (!leaf->isAllocated()) {
1706  this->addTile(/*level=*/0, leaf->origin(), this->background(), /*active=*/false);
1707  }
1708  }
1709 }
1710 
1711 #if OPENVDB_ABI_VERSION_NUMBER >= 12
1712 template<typename RootNodeType>
1713 inline Index64
1715 {
1716  Index64 sum = 0;
1717  for (auto it = this->cbeginLeaf(); it; ++it) if (!it->isAllocated()) ++sum;
1718  return sum;
1719 }
1720 #else
1721 template<typename RootNodeType>
1722 inline Index32
1724 {
1725  Index32 sum = 0;
1726  for (auto it = this->cbeginLeaf(); it; ++it) if (!it->isAllocated()) ++sum;
1727  return sum;
1728 }
1729 #endif
1730 
1731 
1732 template<typename RootNodeType>
1733 inline void
1735 {
1736  this->clearAllAccessors();
1737  return mRoot.sparseFill(bbox, value, active);
1738 }
1739 
1740 
1741 template<typename RootNodeType>
1742 inline void
1744 {
1745  this->clearAllAccessors();
1746  return mRoot.denseFill(bbox, value, active);
1747 }
1748 
1749 
1750 template<typename RootNodeType>
1751 inline void
1753 {
1754  this->clearAllAccessors();
1755  mRoot.voxelizeActiveTiles(threaded);
1756 }
1757 
1758 
1759 template<typename RootNodeType>
1762 {
1764  if (Metadata::isRegisteredType(valueType())) {
1765  using MetadataT = TypedMetadata<ValueType>;
1766  result = Metadata::createMetadata(valueType());
1767  if (result->typeName() == MetadataT::staticTypeName()) {
1768  MetadataT* m = static_cast<MetadataT*>(result.get());
1769  m->value() = mRoot.background();
1770  }
1771  }
1772  return result;
1773 }
1774 
1775 
1776 ////////////////////////////////////////
1777 
1778 
1779 template<typename RootNodeType>
1780 inline void
1782 {
1783  this->clearAllAccessors();
1784  other.clearAllAccessors();
1785  switch (policy) {
1786  case MERGE_ACTIVE_STATES:
1787  mRoot.template merge<MERGE_ACTIVE_STATES>(other.mRoot); break;
1788  case MERGE_NODES:
1789  mRoot.template merge<MERGE_NODES>(other.mRoot); break;
1791  mRoot.template merge<MERGE_ACTIVE_STATES_AND_NODES>(other.mRoot); break;
1792  }
1793 }
1794 
1795 
1796 template<typename RootNodeType>
1797 template<typename OtherRootNodeType>
1798 inline void
1799 Tree<RootNodeType>::topologyUnion(const Tree<OtherRootNodeType>& other, const bool preserveTiles)
1800 {
1801  this->clearAllAccessors();
1802  mRoot.topologyUnion(other.root(), preserveTiles);
1803 }
1804 
1805 template<typename RootNodeType>
1806 template<typename OtherRootNodeType>
1807 inline void
1809 {
1810  this->clearAllAccessors();
1811  mRoot.topologyIntersection(other.root());
1812 }
1813 
1814 template<typename RootNodeType>
1815 template<typename OtherRootNodeType>
1816 inline void
1818 {
1819  this->clearAllAccessors();
1820  mRoot.topologyDifference(other.root());
1821 }
1822 
1823 ////////////////////////////////////////
1824 
1825 
1826 /// @brief Helper class to adapt a three-argument (a, b, result) CombineOp functor
1827 /// into a single-argument functor that accepts a CombineArgs struct
1828 template<typename AValueT, typename CombineOp, typename BValueT = AValueT>
1830 {
1831  CombineOpAdapter(CombineOp& _op): op(_op) {}
1832 
1834  op(args.a(), args.b(), args.result());
1835  }
1836 
1837  CombineOp& op;
1838 };
1839 
1840 
1841 template<typename RootNodeType>
1842 template<typename CombineOp>
1843 inline void
1844 Tree<RootNodeType>::combine(Tree& other, CombineOp& op, bool prune)
1845 {
1847  this->combineExtended(other, extendedOp, prune);
1848 }
1849 
1850 
1851 /// @internal This overload is needed (for ICC and GCC, but not for VC) to disambiguate
1852 /// code like this: <tt>aTree.combine(bTree, MyCombineOp(...))</tt>.
1853 template<typename RootNodeType>
1854 template<typename CombineOp>
1855 inline void
1856 Tree<RootNodeType>::combine(Tree& other, const CombineOp& op, bool prune)
1857 {
1859  this->combineExtended(other, extendedOp, prune);
1860 }
1861 
1862 
1863 template<typename RootNodeType>
1864 template<typename ExtendedCombineOp>
1865 inline void
1866 Tree<RootNodeType>::combineExtended(Tree& other, ExtendedCombineOp& op, bool prune)
1867 {
1868  this->clearAllAccessors();
1869  mRoot.combine(other.root(), op, prune);
1870 }
1871 
1872 
1873 /// @internal This overload is needed (for ICC and GCC, but not for VC) to disambiguate
1874 /// code like this: <tt>aTree.combineExtended(bTree, MyCombineOp(...))</tt>.
1875 template<typename RootNodeType>
1876 template<typename ExtendedCombineOp>
1877 inline void
1878 Tree<RootNodeType>::combineExtended(Tree& other, const ExtendedCombineOp& op, bool prune)
1879 {
1880  this->clearAllAccessors();
1881  mRoot.template combine<const ExtendedCombineOp>(other.mRoot, op, prune);
1882 }
1883 
1884 
1885 template<typename RootNodeType>
1886 template<typename CombineOp, typename OtherTreeType>
1887 inline void
1888 Tree<RootNodeType>::combine2(const Tree& a, const OtherTreeType& b, CombineOp& op, bool prune)
1889 {
1891  this->combine2Extended(a, b, extendedOp, prune);
1892 }
1893 
1894 
1895 /// @internal This overload is needed (for ICC and GCC, but not for VC) to disambiguate
1896 /// code like this: <tt>tree.combine2(aTree, bTree, MyCombineOp(...))</tt>.
1897 template<typename RootNodeType>
1898 template<typename CombineOp, typename OtherTreeType>
1899 inline void
1900 Tree<RootNodeType>::combine2(const Tree& a, const OtherTreeType& b, const CombineOp& op, bool prune)
1901 {
1903  this->combine2Extended(a, b, extendedOp, prune);
1904 }
1905 
1906 
1907 template<typename RootNodeType>
1908 template<typename ExtendedCombineOp, typename OtherTreeType>
1909 inline void
1910 Tree<RootNodeType>::combine2Extended(const Tree& a, const OtherTreeType& b,
1911  ExtendedCombineOp& op, bool prune)
1912 {
1913  this->clearAllAccessors();
1914  mRoot.combine2(a.root(), b.root(), op, prune);
1915 }
1916 
1917 
1918 /// @internal This overload is needed (for ICC and GCC, but not for VC) to disambiguate
1919 /// code like the following, where the functor argument is a temporary:
1920 /// <tt>tree.combine2Extended(aTree, bTree, MyCombineOp(...))</tt>.
1921 template<typename RootNodeType>
1922 template<typename ExtendedCombineOp, typename OtherTreeType>
1923 inline void
1924 Tree<RootNodeType>::combine2Extended(const Tree& a, const OtherTreeType& b,
1925  const ExtendedCombineOp& op, bool prune)
1926 {
1927  this->clearAllAccessors();
1928  mRoot.template combine2<const ExtendedCombineOp>(a.root(), b.root(), op, prune);
1929 }
1930 
1931 
1932 ////////////////////////////////////////
1933 
1934 
1935 template<typename RootNodeType>
1936 inline const Name&
1938 {
1939  static std::string sTreeTypeName = []()
1940  {
1941  // @todo use RootNode::NodeChain::foreach() instead
1942  std::vector<Index> dims;
1943  Tree::getNodeLog2Dims(dims);
1944  std::ostringstream ostr;
1945  ostr << "Tree_" << typeNameAsString<BuildType>();
1946  for (size_t i = 1, N = dims.size(); i < N; ++i) { // start from 1 to skip the RootNode
1947  ostr << "_" << dims[i];
1948  }
1949  return ostr.str();
1950  }();
1951  return sTreeTypeName;
1952 }
1953 
1954 
1955 template<typename RootNodeType>
1956 template<typename OtherRootNodeType>
1957 inline bool
1959 {
1960  return mRoot.hasSameTopology(other.root());
1961 }
1962 
1963 
1964 template<typename RootNodeType>
1965 inline bool
1967 {
1968  bbox.reset(); // default invalid bbox
1969 
1970  if (this->empty()) return false; // empty
1971 
1972  mRoot.evalActiveBoundingBox(bbox, false);
1973 
1974  return !bbox.empty();
1975 }
1976 
1977 template<typename RootNodeType>
1978 inline bool
1980 {
1981  bbox.reset(); // default invalid bbox
1982 
1983  if (this->empty()) return false; // empty
1984 
1985  mRoot.evalActiveBoundingBox(bbox, true);
1986 
1987  return !bbox.empty();
1988 }
1989 
1990 
1991 template<typename RootNodeType>
1992 inline bool
1994 {
1995  CoordBBox bbox;
1996  bool notEmpty = this->evalActiveVoxelBoundingBox(bbox);
1997  dim = bbox.extents();
1998  return notEmpty;
1999 }
2000 
2001 
2002 template<typename RootNodeType>
2003 inline bool
2005 {
2006  CoordBBox bbox;
2007  bool notEmpty = this->evalLeafBoundingBox(bbox);
2008  dim = bbox.extents();
2009  return notEmpty;
2010 }
2011 
2012 
2013 template<typename RootNodeType>
2014 inline void
2015 Tree<RootNodeType>::getNodeLog2Dims(std::vector<Index>& dims)
2016 {
2017  dims.clear();
2018  RootNodeType::getNodeLog2Dims(dims);
2019 }
2020 
2021 
2022 template<typename RootNodeType>
2023 inline void
2024 Tree<RootNodeType>::print(std::ostream& os, int verboseLevel) const
2025 {
2026  if (verboseLevel <= 0) return;
2027 
2028  /// @todo Consider using hboost::io::ios_precision_saver instead.
2029  struct OnExit {
2030  std::ostream& os;
2031  std::streamsize savedPrecision;
2032  OnExit(std::ostream& _os): os(_os), savedPrecision(os.precision()) {}
2033  ~OnExit() { os.precision(savedPrecision); }
2034  };
2035  OnExit restorePrecision(os);
2036 
2037  std::vector<Index> dims;
2038  Tree::getNodeLog2Dims(dims);// leaf is the last element
2039 
2040  os << "Information about Tree:\n"
2041  << " Type: " << this->type() << "\n";
2042 
2043  os << " Configuration:\n";
2044 
2045  if (verboseLevel <= 1) {
2046  // Print node types and sizes.
2047  os << " Root(" << mRoot.getTableSize() << ")";
2048  if (dims.size() > 1) {
2049  for (size_t i = 1, N = dims.size() - 1; i < N; ++i) {
2050  os << ", Internal(" << (1 << dims[i]) << "^3)";
2051  }
2052  os << ", Leaf(" << (1 << dims.back()) << "^3)\n";
2053  }
2054  os << " Background value: " << mRoot.background() << "\n";
2055  return;
2056  }
2057 
2058  // The following is tree information that is expensive to extract.
2059 
2060  ValueType minVal = zeroVal<ValueType>(), maxVal = zeroVal<ValueType>();
2061  if (verboseLevel > 3) {
2062  // This forces loading of all non-resident nodes.
2064  minVal = extrema.min();
2065  maxVal = extrema.max();
2066  }
2067 
2068  const auto nodeCount = this->nodeCount();//fast
2069  const Index64 leafCount = nodeCount.front();// leaf is the first element
2070  OPENVDB_ASSERT(dims.size() == nodeCount.size());
2071 
2072  Index64 totalNodeCount = 0;
2073  for (size_t i = 0; i < nodeCount.size(); ++i) totalNodeCount += nodeCount[i];
2074 
2075  // Print node types, counts and sizes.
2076  os << " Root(1 x " << mRoot.getTableSize() << ")";
2077  if (dims.size() >= 2) {
2078  for (size_t i = 1, N = dims.size() - 1; i < N; ++i) {
2079  os << ", Internal(" << util::formattedInt(nodeCount[N - i]);
2080  os << " x " << (1 << dims[i]) << "^3)";
2081  }
2082  os << ", Leaf(" << util::formattedInt(leafCount);
2083  os << " x " << (1 << dims.back()) << "^3)\n";
2084  }
2085  os << " Background value: " << mRoot.background() << "\n";
2086 
2087  // Statistics of topology and values
2088 
2089  if (verboseLevel > 3) {
2090  os << " Min value: " << minVal << "\n";
2091  os << " Max value: " << maxVal << "\n";
2092  }
2093 
2094  const Index64
2095  numActiveVoxels = this->activeVoxelCount(),
2096  numActiveLeafVoxels = this->activeLeafVoxelCount(),
2097  numActiveTiles = this->activeTileCount();
2098 
2099  os << " Number of active voxels: " << util::formattedInt(numActiveVoxels) << "\n";
2100  os << " Number of active tiles: " << util::formattedInt(numActiveTiles) << "\n";
2101 
2102  Coord dim(0, 0, 0);
2103  Index64 totalVoxels = 0;
2104  if (numActiveVoxels) { // nonempty
2105  CoordBBox bbox;
2106  this->evalActiveVoxelBoundingBox(bbox);
2107  dim = bbox.extents();
2108  totalVoxels = dim.x() * uint64_t(dim.y()) * dim.z();
2109 
2110  os << " Bounding box of active voxels: " << bbox << "\n";
2111  os << " Dimensions of active voxels: "
2112  << dim[0] << " x " << dim[1] << " x " << dim[2] << "\n";
2113 
2114  const double activeRatio = (100.0 * double(numActiveVoxels)) / double(totalVoxels);
2115  os << " Percentage of active voxels: " << std::setprecision(3) << activeRatio << "%\n";
2116 
2117  if (leafCount > 0) {
2118  const double fillRatio = (100.0 * double(numActiveLeafVoxels))
2119  / (double(leafCount) * double(LeafNodeType::NUM_VOXELS));
2120  os << " Average leaf node fill ratio: " << fillRatio << "%\n";
2121  }
2122 
2123  if (verboseLevel > 2) {
2124  Index64 sum = 0;// count the number of unallocated leaf nodes
2125  for (auto it = this->cbeginLeaf(); it; ++it) if (!it->isAllocated()) ++sum;
2126  os << " Number of unallocated nodes: "
2127  << util::formattedInt(sum) << " ("
2128  << (100.0 * double(sum) / double(totalNodeCount)) << "%)\n";
2129  }
2130  } else {
2131  os << " Tree is empty!\n";
2132  }
2133  os << std::flush;
2134 
2135  if (verboseLevel == 2) return;
2136 
2137  // Memory footprint in bytes
2138  const Index64
2139  actualMem = this->memUsage(),
2140  denseMem = sizeof(ValueType) * totalVoxels,
2141  voxelsMem = sizeof(ValueType) * numActiveLeafVoxels;
2142  ///< @todo not accurate for BoolTree (and probably should count tile values)
2143 
2144  os << "Memory footprint:\n";
2145  util::printBytes(os, actualMem, " Actual: ");
2146  util::printBytes(os, voxelsMem, " Active leaf voxels: ");
2147 
2148  if (numActiveVoxels) {
2149  util::printBytes(os, denseMem, " Dense equivalent: ");
2150  os << " Actual footprint is " << (100.0 * double(actualMem) / double(denseMem))
2151  << "% of an equivalent dense volume\n";
2152  os << " Leaf voxel footprint is " << (100.0 * double(voxelsMem) / double(actualMem))
2153  << "% of actual footprint\n";
2154  }
2155 }
2156 
2157 } // namespace tree
2158 } // namespace OPENVDB_VERSION_NAME
2159 } // namespace openvdb
2160 
2161 #endif // OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
virtual Index64 activeTileCount() const =0
Return the total number of active tiles.
const AValueType & result() const
Get the output value.
Definition: Types.h:680
tbb::concurrent_hash_map< ValueAccessorBase< Tree, true > *, bool > AccessorRegistry
Definition: Tree.h:1081
type
Definition: core.h:556
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOnCIter > ValueOnCIter
Definition: Tree.h:1049
virtual void readTopology(std::istream &, bool saveFloatAsHalf=false)
Read the tree topology from a stream.
Definition: Tree.h:1144
ValueOffIter beginValueOff()
Return an iterator over inactive values (tile and voxel) across all nodes.
Definition: Tree.h:1067
void releaseAccessor(ValueAccessorBase< Tree, true > &) const
Deregister an accessor so that it is no longer automatically cleared.
Definition: Tree.h:1441
UnsafeAccessor getUnsafeAccessor()
Return an unsafe accessor that provides random read and write access to this tree's voxels...
Definition: Tree.h:1395
bool operator==(const Tree &) const
Definition: Tree.h:298
virtual void writeTopology(std::ostream &, bool saveFloatAsHalf=false) const
Write the tree topology to a stream.
Definition: Tree.h:1153
bool hasSameTopology(const Tree< OtherRootNodeType > &other) const
Return true if the given tree has the same node and active value topology as this tree...
Definition: Tree.h:1958
Definition: ImfName.h:28
void writeBuffers(std::ostream &, bool saveFloatAsHalf=false) const override
Write out all data buffers for this tree.
Definition: Tree.h:1331
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:635
GLenum GLint * range
Definition: glcorearb.h:1925
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: Tree.h:1572
virtual Index64 memUsage() const
Return the total amount of memory in bytes occupied by this tree.
Definition: Tree.h:151
LeafIteratorBase< Tree, typename RootNodeType::ChildOnIter > LeafIter
Iterator over all leaf nodes in this tree.
Definition: Tree.h:1028
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition: Tree.h:519
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Definition: Tree.h:650
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1043
ValueAccessor< Tree, false > UnsafeAccessor
Definition: Tree.h:209
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: Tree.h:1598
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: Tree.h:1752
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: Tree.h:1589
virtual Metadata::Ptr getBackgroundValue() const
Return this tree's background value wrapped as metadata.
Definition: Tree.h:66
void attachAccessor(ValueAccessorBase< Tree, false > &) const
Dummy implementations.
Definition: Tree.h:703
static const Name & treeType()
Return the name of this type of tree.
Definition: Tree.h:1937
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOnIter > ValueOnIter
Definition: Tree.h:1048
void addLeaf(LeafNodeType *leaf)
Add the given leaf node to this tree, creating a new branch if necessary. If a leaf node with the sam...
Definition: Tree.h:559
RootNodeType::ChildOffCIter cbeginRootTiles() const
Return an iterator over non-child entries of the root node's table.
Definition: Tree.h:1008
Index64 inactiveVoxelCount() const override
Return the number of inactive voxels within the bounding box of all active voxels.
Definition: Tree.h:400
static Metadata::Ptr createMetadata(const Name &typeName)
Create new metadata of the given type.
void stealNodes(ArrayT &array)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:...
Definition: Tree.h:648
GLsizei const GLfloat * value
Definition: glcorearb.h:824
void addTile(Index level, const Coord &xyz, const ValueType &value, bool active)
Add a tile containing voxel (x, y, z) at the specified tree level, creating a new branch if necessary...
Definition: Tree.h:1617
Index64 countActiveLeafVoxels(const TreeT &tree, bool threaded=true)
Return the total number of active voxels stored in leaf nodes.
Definition: Count.h:436
Index64 memUsage(const TreeT &tree, bool threaded=true)
Return the total amount of memory in bytes occupied by this tree.
Definition: Count.h:493
int getValueDepth(const Coord &xyz) const
Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides.
Definition: Tree.h:1517
TreeIterTraits provides, for all tree iterators, a begin(tree) function that returns an iterator over...
Definition: Tree.h:1181
void sparseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition: Tree.h:1734
Index64 countInactiveVoxels(const TreeT &tree, bool threaded=true)
Return the total number of inactive voxels in the tree.
Definition: Count.h:461
Base class for tree-traversal iterators over all nodes.
Definition: TreeIterator.h:936
#define OPENVDB_LOG_WARN(mesg)
Definition: logging.h:277
ValueAllCIter beginValueAll() const
Return an iterator over all values (tile and voxel) across all nodes.
Definition: Tree.h:1056
DeallocateNodes(std::vector< NodeType * > &nodes)
Definition: Tree.h:1091
GLint level
Definition: glcorearb.h:108
RootNodeType::ChildOffCIter beginRootTiles() const
Return an iterator over non-child entries of the root node's table.
Definition: Tree.h:1007
NodeIteratorBase< Tree, typename RootNodeType::ChildOnIter > NodeIter
Iterator over all nodes in this tree.
Definition: Tree.h:1022
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
Tree(const OtherTreeType &other, const ValueType &inactiveValue, const ValueType &activeValue, TopologyCopy)
Topology copy constructor from a tree of a different type.
Definition: Tree.h:255
RootNodeType::ChildAllCIter cbeginRootDense() const
Return an iterator over all entries of the root node's table.
Definition: Tree.h:1015
RootNodeType & root()
Return this tree's root node.
Definition: Tree.h:303
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:246
The Value Accessor Implementation and API methods. The majoirty of the API matches the API of a compa...
Definition: ValueAccessor.h:68
virtual Index64 activeVoxelCount() const =0
Return the total number of active voxels.
**But if you need a result
Definition: thread.h:622
tree::TreeBase TreeBase
Definition: Grid.h:26
TreeValueIteratorBase< Tree, typename RootNodeType::ValueAllIter > ValueAllIter
Definition: Tree.h:1046
virtual Index32 leafCount() const =0
Return the number of leaf nodes.
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueAllCIter > ValueAllCIter
Definition: Tree.h:1047
Tree(const ValueType &background)
Empty tree constructor.
Definition: Tree.h:283
bool isValueOff(const Coord &xyz) const
Return true if the value at the given coordinates is inactive.
Definition: Tree.h:489
Index32 unallocatedLeafCount() const override
Return the total number of unallocated leaf nodes residing in this tree.
Definition: Tree.h:1723
void readNonresidentBuffers() const override
Read all of this tree's data buffers that are not yet resident in memory (because delayed loading is ...
Definition: Tree.h:1320
ValueAccessor< Tree, true > Accessor
Definition: Tree.h:207
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: Tree.h:1690
Index64 memUsage() const override
Return the total amount of memory in bytes occupied by this tree.
Definition: Tree.h:404
ValueOffCIter cbeginValueOff() const
Return an iterator over inactive values (tile and voxel) across all nodes.
Definition: Tree.h:1069
RootNodeType::ChildOffIter beginRootTiles()
Return an iterator over non-child entries of the root node's table.
Definition: Tree.h:1009
Index64 countActiveTiles(const TreeT &tree, bool threaded=true)
Return the total number of active tiles in the tree.
Definition: Count.h:482
bool operator!=(const Tree &) const
Definition: Tree.h:299
void topologyIntersection(const Tree< OtherRootNodeType > &other)
Intersects this tree's set of active values with the active values of the other tree, whose ValueType may be different.
Definition: Tree.h:1808
void releaseAllAccessors()
Notify all registered accessors, by calling ValueAccessor::release(), that this tree is about to be d...
Definition: Tree.h:1475
virtual Index64 inactiveVoxelCount() const =0
Return the number of inactive voxels within the bounding box of all active voxels.
Tree4<T, N1, N2, N3>::Type is the type of a four-level tree (Root, Internal, Internal, Leaf) with value type T and internal and leaf node log dimensions N1, N2 and N3, respectively.
Definition: Tree.h:1125
bool evalActiveVoxelBoundingBox(CoordBBox &bbox) const override
Return in bbox the axis-aligned bounding box of all active voxels and tiles.
Definition: Tree.h:1979
ConstUnsafeAccessor getConstUnsafeAccessor()
Return an unsafe accessor that provides random read-only access to this tree's voxels.
Definition: Tree.h:1416
ValueAllIter beginValueAll()
Return an iterator over all values (tile and voxel) across all nodes.
Definition: Tree.h:1055
Tree & operator=(const Tree &)=delete
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: Tree.h:1525
std::shared_ptr< T > SharedPtr
Definition: Types.h:95
void clear()
Remove all tiles from this tree and all nodes other than the root node.
Definition: Tree.h:1363
void topologyDifference(const Tree< OtherRootNodeType > &other)
Difference this tree's set of active values with the active values of the other tree, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this tree and inactive in the other tree.
Definition: Tree.h:1817
SYS_FORCE_INLINE const_iterator end() const
const AValueType & a() const
Get the A input value.
Definition: Types.h:675
static bool isRegisteredType(const Name &typeName)
Return true if the given type is known by the metadata type registry.
RootNodeType::ChildOnCIter beginRootChildren() const
Return an iterator over children of the root node.
Definition: Tree.h:1000
Name valueType() const override
Return the name of the type of a voxel's value (e.g., "float" or "vec3d")
Definition: Tree.h:291
GLdouble n
Definition: glcorearb.h:2008
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: Tree.h:1340
Utility routines to output nicely-formatted numeric values.
void readBuffers(std::istream &, bool saveFloatAsHalf=false) override
Read all data buffers for this tree.
Definition: Tree.h:1302
const ValueType & background() const
Return this tree's background value.
Definition: Tree.h:728
bool isType() const
Return true if this tree is of the same type as the template parameter.
Definition: Tree.h:56
ConstAccessor getConstAccessor() const
Return an accessor that provides random read-only access to this tree's voxels.
Definition: Tree.h:1409
tbb::concurrent_hash_map< ValueAccessorBase< const Tree, true > *, bool > ConstAccessorRegistry
Definition: Tree.h:1082
#define OPENVDB_API
Definition: Platform.h:291
LeafCIter beginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1042
void operator()(CombineArgs< AValueT, BValueT > &args) const
Definition: Tree.h:1833
ValueAccessors are designed to help accelerate accesses into the OpenVDB Tree structures by storing c...
void print(std::ostream &os=std::cout, int verboseLevel=1) const override
Print statistics, memory usage and other information about this tree.
Definition: Tree.h:2024
BBox< Coord > CoordBBox
Definition: NanoVDB.h:2516
Index64 countInactiveLeafVoxels(const TreeT &tree, bool threaded=true)
Return the total number of inactive voxels stored in leaf nodes.
Definition: Count.h:471
void merge(Tree &other, MergePolicy=MERGE_ACTIVE_STATES)
Efficiently merge another tree into this tree using one of several schemes.
Definition: Tree.h:1781
Index64 activeTileCount() const override
Return the total number of active tiles.
Definition: Tree.h:402
Templated metadata class to hold specific types.
Definition: Metadata.h:122
LeafIter beginLeaf()
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1041
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
TreeBase::Ptr copy() const override
Return a pointer to a deep copy of this tree.
Definition: Tree.h:288
Index64 activeLeafVoxelCount() const override
Return the number of active voxels stored in leaf nodes.
Definition: Tree.h:394
void releaseAccessor(ValueAccessorBase< Tree, false > &) const
Dummy implementations.
Definition: Tree.h:715
LeafIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > LeafCIter
Iterator over all leaf nodes in this tree.
Definition: Tree.h:1029
Index32 leafCount() const override
Return the number of leaf nodes.
Definition: Tree.h:365
void attachAccessor(ValueAccessorBase< Tree, true > &) const
Register an accessor for this tree. Registered accessors are automatically cleared whenever one of th...
Definition: Tree.h:1423
NodeCIter beginNode() const
Return an iterator over all nodes in this tree.
Definition: Tree.h:1035
OIIO_UTIL_API void parallel_for(int32_t begin, int32_t end, function_view< void(int32_t)> task, paropt opt=0)
bool evalActiveVoxelDim(Coord &dim) const override
Return in dim the dimensions of the axis-aligned bounding box of all active voxels. This is a tighter bounding box than the leaf node bounding box.
Definition: Tree.h:1993
ValueConverter<T>::Type is the type of a tree having the same hierarchy as this tree but a different ...
Definition: Tree.h:219
const RootNodeType & root() const
Return this tree's root node.
Definition: Tree.h:304
Functions to count tiles, nodes or voxels in a grid.
Tree3<T, N1, N2>::Type is the type of a three-level tree (Root, Internal, Leaf) with value type T and...
Definition: Tree.h:1115
const ValueType & max() const
Return the maximum value.
Definition: Stats.h:60
Helper class to adapt a three-argument (a, b, result) CombineOp functor into a single-argument functo...
Definition: Tree.h:1829
bool probeValue(const Coord &xyz, ValueType &value) const
Get the value of the voxel at the given coordinates.
Definition: Tree.h:1606
#define OPENVDB_NO_DEPRECATION_WARNING_BEGIN
Bracket code with OPENVDB_NO_DEPRECATION_WARNING_BEGIN/_END, to inhibit warnings about deprecated cod...
Definition: Platform.h:217
ValueOffCIter beginValueOff() const
Return an iterator over inactive values (tile and voxel) across all nodes.
Definition: Tree.h:1068
const NodeType * probeConstNode(const Coord &xyz) const
Return a pointer to the node of type NodeType that contains voxel (x, y, z). If no such node exists...
Definition: Tree.h:1679
Index64 inactiveLeafVoxelCount() const override
Return the number of inactive voxels stored in leaf nodes.
Definition: Tree.h:396
const LeafNodeType * probeLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: Tree.h:594
Templated class to compute the minimum and maximum values.
Definition: Stats.h:31
void attachAccessor(ValueAccessorBase< const Tree, false > &) const
Dummy implementations.
Definition: Tree.h:704
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
void operator()(const tbb::blocked_range< size_t > &range) const
Definition: Tree.h:1093
This base class for ValueAccessors manages registration of an accessor with a tree so that the tree c...
bool evalLeafBoundingBox(CoordBBox &bbox) const override
Return in bbox the axis-aligned bounding box of all active tiles and leaf nodes with active values...
Definition: Tree.h:1966
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate active
typename RootNodeType::ValueType ValueType
Definition: Tree.h:201
NodeIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > NodeCIter
Iterator over all nodes in this tree.
Definition: Tree.h:1023
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOffIter > ValueOffIter
Definition: Tree.h:1050
The root node of an OpenVDB tree.
bool hasActiveTiles() const
Return true if this tree has any active tiles.
Definition: Tree.h:491
void releaseAccessor(ValueAccessorBase< const Tree, false > &) const
Dummy implementations.
Definition: Tree.h:716
CIterT cbegin() const
Return a const iterator of type CIterT (for example, cbegin<ValueOnCIter>() is equivalent to cbeginVa...
ValueAllCIter cbeginValueAll() const
Return an iterator over all values (tile and voxel) across all nodes.
Definition: Tree.h:1057
Base class for typed trees.
Definition: Tree.h:37
Index64 activeVoxelCount() const override
Return the total number of active voxels.
Definition: Tree.h:398
Index32 nonLeafCount() const override
Return the number of non-leaf nodes.
Definition: Tree.h:391
virtual Index32 nonLeafCount() const =0
Return the number of non-leaf nodes.
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOffCIter > ValueOffCIter
Definition: Tree.h:1051
static void getNodeLog2Dims(std::vector< Index > &dims)
Traverse the type hierarchy of nodes, and return, in dims, a list of the Log2Dims of nodes in order f...
Definition: Tree.h:2015
Accessor getAccessor()
Return an accessor that provides random read and write access to this tree's voxels.
Definition: Tree.h:1388
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: Tree.h:1500
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:203
Tree(const Tree &other)
Deep copy constructor.
Definition: Tree.h:229
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:587
ConstAccessorRegistry mConstAccessorRegistry
Definition: Tree.h:1106
ValueOnCIter beginValueOn() const
Return an iterator over active values (tile and voxel) across all nodes.
Definition: Tree.h:1062
void readTopology(std::istream &, bool saveFloatAsHalf=false) override
Read the tree topology from a stream.
Definition: Tree.h:1283
Index64 countActiveVoxels(const TreeT &tree, bool threaded=true)
Return the total number of active voxels in the tree.
Definition: Count.h:413
virtual void print(std::ostream &os=std::cout, int verboseLevel=1) const
Print statistics, memory usage and other information about this tree.
Definition: Tree.h:1161
const ValueType & min() const
Return the minimum value.
Definition: Stats.h:57
LeafData & operator=(const LeafData &)=delete
typename RootNodeType::BuildType BuildType
Definition: Tree.h:202
math::MinMax< typename TreeT::ValueType > minMax(const TreeT &tree, bool threaded=true)
Return the minimum and maximum active values in this tree.
Definition: Count.h:516
ValueAccessor< const Tree, true > ConstAccessor
Definition: Tree.h:208
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: Tree.h:1652
#define OPENVDB_NO_DEPRECATION_WARNING_END
Definition: Platform.h:218
ValueOnIter beginValueOn()
Return an iterator over active values (tile and voxel) across all nodes.
Definition: Tree.h:1061
Base class for tree-traversal iterators over tile and voxel values.
Definition: TreeIterator.h:617
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: Tree.h:1549
RootNodeType::ChildAllIter beginRootDense()
Return an iterator over all entries of the root node's table.
Definition: Tree.h:1016
NodeCIter cbeginNode() const
Return an iterator over all nodes in this tree.
Definition: Tree.h:1036
RootNodeType::ChildOnIter beginRootChildren()
Return an iterator over children of the root node.
Definition: Tree.h:1002
NodeT * stealNode(const Coord &xyz, const ValueType &value, bool active)
Return a pointer to the node of type NodeT that contains voxel (x, y, z) and replace it with a tile o...
Definition: Tree.h:1627
void getIndexRange(CoordBBox &bbox) const override
Min and max are both inclusive.
Definition: Tree.h:731
GA_API const UT_StringHolder N
FormattedInt< IntT > formattedInt(IntT n)
Definition: Formats.h:118
ValueAccessor< const Tree, false > ConstUnsafeAccessor
Definition: Tree.h:210
SharedPtr< const TreeBase > ConstPtr
Definition: Tree.h:41
void combine2Extended(const Tree &a, const OtherTreeType &b, ExtendedCombineOp &op, bool prune=false)
Definition: Tree.h:1910
**If you just want to fire and args
Definition: thread.h:618
RootNodeType::ChildOnCIter cbeginRootChildren() const
Return an iterator over children of the root node.
Definition: Tree.h:1001
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: Tree.h:1644
void combine2(const Tree &a, const OtherTreeType &b, CombineOp &op, bool prune=false)
Definition: Tree.h:1888
OPENVDB_API int printBytes(std::ostream &os, uint64_t bytes, const std::string &head="", const std::string &tail="\n", bool exact=false, int width=8, int precision=3)
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node of type NodeType that contains voxel (x, y, z). If no such node exists...
Definition: Tree.h:1661
const Name & type() const override
Return the name of this type of tree.
Definition: Tree.h:296
void clipUnallocatedNodes() override
Replace with background tiles any nodes whose voxel buffers have not yet been allocated.
Definition: Tree.h:1699
RootNodeType::ChildAllCIter beginRootDense() const
Return an iterator over all entries of the root node's table.
Definition: Tree.h:1014
Fp4 BuildType
Definition: NanoVDB.h:5565
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:750
const BValueType & b() const
Get the B input value.
Definition: Types.h:677
ValueOnCIter cbeginValueOn() const
Return an iterator over active values (tile and voxel) across all nodes.
Definition: Tree.h:1063
virtual const Name & type() const =0
Return the name of this tree's type.
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:335
Metadata::Ptr getBackgroundValue() const override
Return this tree's background value wrapped as metadata.
Definition: Tree.h:1761
NodeIter beginNode()
Return an iterator over all nodes in this tree.
Definition: Tree.h:1034
bool isValueOn(const Coord &xyz) const
Return true if the value at the given coordinates is active.
Definition: Tree.h:487
bool evalLeafDim(Coord &dim) const override
Return in dim the dimensions of the axis-aligned bounding box of all leaf nodes.
Definition: Tree.h:2004
IterT begin()
Return an iterator of type IterT (for example, begin<ValueOnIter>() is equivalent to beginValueOn())...
Definition: Tree.h:1263
void prune(const ValueType &tolerance=zeroVal< ValueType >())
Reduce the memory footprint of this tree by replacing with tiles any nodes whose values are all the s...
Definition: Tree.h:548
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one that preserves the values and active states of all voxels.
Definition: Tree.h:1636
Tree(const OtherTreeType &other, const ValueType &background, TopologyCopy)
Topology copy constructor from a tree of a different type.
Definition: Tree.h:276
bool empty() const
Return true if this tree contains no nodes other than the root node and no tiles other than backgroun...
Definition: Tree.h:661
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition: Tree.h:1541
FMT_INLINE void print(format_string< T...> fmt, T &&...args)
Definition: core.h:2903
std::vector< Index32 > nodeCount() const override
Definition: Tree.h:378
void denseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value and ensure that those voxels are a...
Definition: Tree.h:1743
void topologyUnion(const Tree< OtherRootNodeType > &other, const bool preserveTiles=false)
Union this tree's set of active values with the active values of the other tree, whose ValueType may ...
Definition: Tree.h:1799
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:119
bool ValueType
Definition: NanoVDB.h:5729
state
Definition: core.h:2289
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition: Tree.h:1556
math::Extrema extrema(const IterT &iter, bool threaded=true)
Iterate over a scalar grid and compute extrema (min/max) of the values of the voxels that are visited...
Definition: Statistics.h:354
Tree5<T, N1, N2, N3, N4>::Type is the type of a five-level tree (Root, Internal, Internal, Internal, Leaf) with value type T and internal and leaf node log dimensions N1, N2, N3 and N4, respectively.
Definition: Tree.h:1134
void combine(Tree &other, CombineOp &op, bool prune=false)
Definition: Tree.h:1844
Internal table nodes for OpenVDB trees.
Index treeDepth() const override
Return the depth of this tree.
Definition: Tree.h:360
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
void combineExtended(Tree &other, ExtendedCombineOp &op, bool prune=false)
Definition: Tree.h:1866
void clearAllAccessors()
Clear all registered accessors.
Definition: Tree.h:1457
void writeTopology(std::ostream &, bool saveFloatAsHalf=false) const override
Write the tree topology to a stream.
Definition: Tree.h:1293
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels) ...
Tree(const Tree< OtherRootType > &other)
Value conversion deep copy constructor.
Definition: Tree.h:240