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