OpenVDB 12.1.0

Loading...
Searching...
No Matches
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 {
32 OPENVDB_USE_VERSION_NAMESPACE
33 namespace OPENVDB_VERSION_NAME {
34 namespace tree {
35
36/// @brief Base class for typed trees
37 class OPENVDB_API TreeBase
38{
39 public:
40 using Ptr = SharedPtr<TreeBase>;
41 using ConstPtr = SharedPtr<const TreeBase>;
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:
197 using Ptr = SharedPtr<Tree>;
198 using ConstPtr = SharedPtr<const Tree>;
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
207 using Accessor = ValueAccessor<Tree, true>;
208 using ConstAccessor = ValueAccessor<const Tree, true>;
209 using UnsafeAccessor = ValueAccessor<Tree, false>;
210 using ConstUnsafeAccessor = ValueAccessor<const Tree, false>;
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 {
220 using Type = Tree<typename RootNodeType::template ValueConverter<OtherValueType>::Type>;
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);
381 OPENVDB_NO_DEPRECATION_WARNING_BEGIN
382 mRoot.nodeCount( vec );
383 OPENVDB_NO_DEPRECATION_WARNING_END
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.
396 Index64 inactiveLeafVoxelCount() const override { return tools::countInactiveLeafVoxels(*this); }
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
707 void attachAccessor(ValueAccessorBase<Tree, false>&) const {}
708 void attachAccessor(ValueAccessorBase<const Tree, false>&) const {}
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
719 void releaseAccessor(ValueAccessorBase<Tree, false>&) const {}
720 void releaseAccessor(ValueAccessorBase<const Tree, false>&) const {}
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
1026 using NodeIter = NodeIteratorBase<Tree, typename RootNodeType::ChildOnIter>;
1027 using NodeCIter = NodeIteratorBase<const Tree, typename RootNodeType::ChildOnCIter>;
1028 //@}
1029
1030 //@{
1031 /// Iterator over all leaf nodes in this tree
1032 using LeafIter = LeafIteratorBase<Tree, typename RootNodeType::ChildOnIter>;
1033 using LeafCIter = LeafIteratorBase<const Tree, typename RootNodeType::ChildOnCIter>;
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
1050 using ValueAllIter = TreeValueIteratorBase<Tree, typename RootNodeType::ValueAllIter>;
1051 using ValueAllCIter = TreeValueIteratorBase<const Tree, typename RootNodeType::ValueAllCIter>;
1052 using ValueOnIter = TreeValueIteratorBase<Tree, typename RootNodeType::ValueOnIter>;
1053 using ValueOnCIter = TreeValueIteratorBase<const Tree, typename RootNodeType::ValueOnCIter>;
1054 using ValueOffIter = TreeValueIteratorBase<Tree, typename RootNodeType::ValueOffIter>;
1055 using ValueOffCIter = TreeValueIteratorBase<const Tree, typename RootNodeType::ValueOffCIter>;
1056
1057 //@{
1058 /// Return an iterator over all values (tile and voxel) across all nodes.
1059 ValueAllIter beginValueAll() { return ValueAllIter(*this); }
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.
1071 ValueOffIter beginValueOff() { return ValueOffIter(*this); }
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>
1094 struct DeallocateNodes {
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
1109 mutable AccessorRegistry mAccessorRegistry;
1110 mutable ConstAccessorRegistry mConstAccessorRegistry;
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 {
1120 using Type = Tree<RootNode<InternalNode<LeafNode<T, N2>, N1>>>;
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 {
1130 using Type = Tree<RootNode<InternalNode<InternalNode<LeafNode<T, N3>, N2>, N1>>>;
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 =
1140 Tree<RootNode<InternalNode<InternalNode<InternalNode<LeafNode<T, N4>, N3>, N2>, N1>>>;
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
1267 Tree<RootNodeType>::begin()
1268{
1269 return TreeIterTraits<Tree, IterT>::begin(*this);
1270}
1271
1272
1273 template<typename RootNodeType>
1274 template<typename IterT>
1275 inline IterT
1276 Tree<RootNodeType>::cbegin() const
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
1324 Tree<RootNodeType>::readNonresidentBuffers() const
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
1344 Tree<RootNodeType>::getNodes(ArrayT& array)
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
1367 Tree<RootNodeType>::clear()
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()),
1379 DeallocateNodes<typename RootNodeType::ChildNodeType>(internalNodes));
1380
1381 mRoot.clear();
1382
1383 this->clearAllAccessors();
1384}
1385
1386
1387////////////////////////////////////////
1388
1389
1390 template<typename RootNodeType>
1391 typename Tree<RootNodeType>::Accessor
1392 Tree<RootNodeType>::getAccessor()
1393{
1394 return Accessor(*this);
1395}
1396
1397 template<typename RootNodeType>
1398 typename Tree<RootNodeType>::UnsafeAccessor
1399 Tree<RootNodeType>::getUnsafeAccessor()
1400{
1401 return UnsafeAccessor(*this);
1402}
1403
1404 template<typename RootNodeType>
1405 typename Tree<RootNodeType>::ConstAccessor
1406 Tree<RootNodeType>::getAccessor() const
1407{
1408 return ConstAccessor(*this);
1409}
1410
1411 template<typename RootNodeType>
1412 typename Tree<RootNodeType>::ConstAccessor
1413 Tree<RootNodeType>::getConstAccessor() const
1414{
1415 return ConstAccessor(*this);
1416}
1417
1418 template<typename RootNodeType>
1419 typename Tree<RootNodeType>::ConstUnsafeAccessor
1420 Tree<RootNodeType>::getConstUnsafeAccessor()
1421{
1422 return ConstUnsafeAccessor(*this);
1423}
1424
1425 template<typename RootNodeType>
1426 inline void
1427 Tree<RootNodeType>::attachAccessor(ValueAccessorBase<Tree, true>& accessor) const
1428{
1429 typename AccessorRegistry::accessor a;
1430 mAccessorRegistry.insert(a, &accessor);
1431}
1432
1433
1434 template<typename RootNodeType>
1435 inline void
1436 Tree<RootNodeType>::attachAccessor(ValueAccessorBase<const Tree, true>& accessor) const
1437{
1438 typename ConstAccessorRegistry::accessor a;
1439 mConstAccessorRegistry.insert(a, &accessor);
1440}
1441
1442
1443 template<typename RootNodeType>
1444 inline void
1445 Tree<RootNodeType>::releaseAccessor(ValueAccessorBase<Tree, true>& accessor) const
1446{
1447 mAccessorRegistry.erase(&accessor);
1448}
1449
1450
1451 template<typename RootNodeType>
1452 inline void
1453 Tree<RootNodeType>::releaseAccessor(ValueAccessorBase<const Tree, true>& accessor) const
1454{
1455 mConstAccessorRegistry.erase(&accessor);
1456}
1457
1458
1459 template<typename RootNodeType>
1460 inline void
1461 Tree<RootNodeType>::clearAllAccessors()
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
1479 Tree<RootNodeType>::releaseAllAccessors()
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
1529 Tree<RootNodeType>::setValueOff(const Coord& xyz)
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
1576 Tree<RootNodeType>::setValueOn(const Coord& xyz)
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*
1640 Tree<RootNodeType>::touchLeaf(const Coord& xyz)
1641{
1642 return mRoot.touchLeaf(xyz);
1643}
1644
1645
1646 template<typename RootNodeType>
1647 inline typename RootNodeType::LeafNodeType*
1648 Tree<RootNodeType>::probeLeaf(const Coord& xyz)
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*
1665 Tree<RootNodeType>::probeNode(const Coord& xyz)
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
1703 Tree<RootNodeType>::clipUnallocatedNodes()
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
1718 Tree<RootNodeType>::unallocatedLeafCount() const
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
1727 Tree<RootNodeType>::unallocatedLeafCount() const
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
1756 Tree<RootNodeType>::voxelizeActiveTiles(bool threaded)
1757{
1758 this->clearAllAccessors();
1759 mRoot.voxelizeActiveTiles(threaded);
1760}
1761
1762
1763 template<typename RootNodeType>
1764 Metadata::Ptr
1765 Tree<RootNodeType>::getBackgroundValue() const
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
1785 Tree<RootNodeType>::merge(Tree& other, MergePolicy policy)
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;
1794 case MERGE_ACTIVE_STATES_AND_NODES:
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
1812 Tree<RootNodeType>::topologyIntersection(const Tree<OtherRootNodeType>& other)
1813{
1814 this->clearAllAccessors();
1815 mRoot.topologyIntersection(other.root());
1816}
1817
1818 template<typename RootNodeType>
1819 template<typename OtherRootNodeType>
1820 inline void
1821 Tree<RootNodeType>::topologyDifference(const Tree<OtherRootNodeType>& other)
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>
1833 struct CombineOpAdapter
1834{
1835 CombineOpAdapter(CombineOp& _op): op(_op) {}
1836
1837 void operator()(CombineArgs<AValueT, BValueT>& args) const {
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{
1850 CombineOpAdapter<ValueType, CombineOp> extendedOp(op);
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{
1862 CombineOpAdapter<ValueType, const CombineOp> extendedOp(op);
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{
1894 CombineOpAdapter<ValueType, CombineOp, typename OtherTreeType::ValueType> extendedOp(op);
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{
1906 CombineOpAdapter<ValueType, const CombineOp, typename OtherTreeType::ValueType> extendedOp(op);
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&
1941 Tree<RootNodeType>::treeType()
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
1962 Tree<RootNodeType>::hasSameTopology(const Tree<OtherRootNodeType>& other) const
1963{
1964 return mRoot.hasSameTopology(other.root());
1965}
1966
1967
1968 template<typename RootNodeType>
1969 inline bool
1970 Tree<RootNodeType>::evalLeafBoundingBox(CoordBBox& bbox) const
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
1983 Tree<RootNodeType>::evalActiveVoxelBoundingBox(CoordBBox& bbox) const
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
1997 Tree<RootNodeType>::evalActiveVoxelDim(Coord& dim) const
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
2008 Tree<RootNodeType>::evalLeafDim(Coord& dim) const
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
2019 Tree<RootNodeType>::evalMinMax(ValueType& minVal, ValueType& maxVal) const
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.
2083 const math::MinMax<ValueType> extrema = tools::minMax(*this);
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
Assert.h
OPENVDB_ASSERT
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
BBox.h
Count.h
Functions to count tiles, nodes or voxels in a grid.
Formats.h
Utility routines to output nicely-formatted numeric values.
InternalNode.h
Internal table nodes for OpenVDB trees.
LeafNode.h
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Metadata.h
Platform.h
OPENVDB_NO_DEPRECATION_WARNING_END
#define OPENVDB_NO_DEPRECATION_WARNING_END
Definition Platform.h:218
OPENVDB_NO_DEPRECATION_WARNING_BEGIN
#define OPENVDB_NO_DEPRECATION_WARNING_BEGIN
Bracket code with OPENVDB_NO_DEPRECATION_WARNING_BEGIN/_END, to inhibit warnings about deprecated cod...
Definition Platform.h:217
OPENVDB_API
#define OPENVDB_API
Definition Platform.h:291
OPENVDB_DEPRECATED_MESSAGE
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition Platform.h:171
RootNode.h
The root node of an OpenVDB tree.
TreeIterator.h
ValueAccessor.h
ValueAccessors are designed to help accelerate accesses into the OpenVDB Tree structures by storing c...
openvdb::v12_1::CombineArgs
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition Types.h:640
openvdb::v12_1::CombineArgs::result
const AValueType & result() const
Get the output value.
Definition Types.h:684
openvdb::v12_1::CombineArgs::b
const BValueType & b() const
Get the B input value.
Definition Types.h:681
openvdb::v12_1::CombineArgs::a
const AValueType & a() const
Get the A input value.
Definition Types.h:679
openvdb::v12_1::Metadata::createMetadata
static Metadata::Ptr createMetadata(const Name &typeName)
Create new metadata of the given type.
openvdb::v12_1::Metadata::isRegisteredType
static bool isRegisteredType(const Name &typeName)
Return true if the given type is known by the metadata type registry.
openvdb::v12_1::Metadata::Ptr
SharedPtr< Metadata > Ptr
Definition Metadata.h:27
openvdb::v12_1::NotImplementedError
Definition Exceptions.h:61
openvdb::v12_1::TopologyCopy
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:754
openvdb::v12_1::TypedMetadata
Templated metadata class to hold specific types.
Definition Metadata.h:123
openvdb::v12_1::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
openvdb::v12_1::math::CoordBBox::extents
Coord extents() const
Definition Coord.h:385
openvdb::v12_1::math::CoordBBox::empty
bool empty() const
Return true if this bounding box is empty (i.e., encloses no coordinates).
Definition Coord.h:359
openvdb::v12_1::math::CoordBBox::reset
void reset()
Definition Coord.h:330
openvdb::v12_1::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
openvdb::v12_1::math::Coord::y
Int32 y() const
Definition Coord.h:132
openvdb::v12_1::math::Coord::x
Int32 x() const
Definition Coord.h:131
openvdb::v12_1::math::Coord::z
Int32 z() const
Definition Coord.h:133
openvdb::v12_1::math::Extrema::min
double min() const
Return the minimum value.
Definition Stats.h:122
openvdb::v12_1::math::Extrema::max
double max() const
Return the maximum value.
Definition Stats.h:125
openvdb::v12_1::math::MinMax
Templated class to compute the minimum and maximum values.
Definition Stats.h:32
openvdb::v12_1::tree::LeafIteratorBase
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels)
Definition TreeIterator.h:1188
openvdb::v12_1::tree::NodeIteratorBase
Base class for tree-traversal iterators over all nodes.
Definition TreeIterator.h:937
openvdb::v12_1::tree::RootNode::ChildAllIter
DenseIter< RootNode, MapIter, ChildType, ValueType > ChildAllIter
Definition RootNode.h:366
openvdb::v12_1::tree::RootNode::LeafNodeType
typename ChildType::LeafNodeType LeafNodeType
Definition RootNode.h:43
openvdb::v12_1::tree::RootNode::ChildOnIter
ChildIter< RootNode, MapIter, ChildOnPred, ChildType > ChildOnIter
Definition RootNode.h:362
openvdb::v12_1::tree::RootNode::ChildOffCIter
ValueIter< const RootNode, MapCIter, ChildOffPred, ValueType > ChildOffCIter
Definition RootNode.h:365
openvdb::v12_1::tree::RootNode::LEVEL
static const Index LEVEL
Definition RootNode.h:47
openvdb::v12_1::tree::RootNode::ValueType
typename ChildType::ValueType ValueType
Definition RootNode.h:44
openvdb::v12_1::tree::RootNode::BuildType
typename ChildType::BuildType BuildType
Definition RootNode.h:45
openvdb::v12_1::tree::RootNode::ChildAllCIter
DenseIter< const RootNode, MapCIter, const ChildType, const ValueType > ChildAllCIter
Definition RootNode.h:367
openvdb::v12_1::tree::RootNode::ChildOffIter
ValueIter< RootNode, MapIter, ChildOffPred, const ValueType > ChildOffIter
Definition RootNode.h:364
openvdb::v12_1::tree::RootNode::ChildOnCIter
ChildIter< const RootNode, MapCIter, ChildOnPred, const ChildType > ChildOnCIter
Definition RootNode.h:363
openvdb::v12_1::tree::TreeBase::valueType
virtual Name valueType() const =0
Return the name of the type of a voxel's value (e.g., "float" or "vec3d").
openvdb::v12_1::tree::TreeBase::type
virtual const Name & type() const =0
Return the name of this tree's type.
openvdb::v12_1::tree::TreeBase::writeTopology
virtual void writeTopology(std::ostream &, bool saveFloatAsHalf=false) const
Write the tree topology to a stream.
Definition Tree.h:1157
openvdb::v12_1::tree::TreeBase::unallocatedLeafCount
virtual Index64 unallocatedLeafCount() const =0
Return the total number of unallocated leaf nodes residing in this tree.
openvdb::v12_1::tree::TreeBase::~TreeBase
virtual ~TreeBase()=default
openvdb::v12_1::tree::TreeBase::activeLeafVoxelCount
virtual Index64 activeLeafVoxelCount() const =0
Return the number of active voxels stored in leaf nodes.
openvdb::v12_1::tree::TreeBase::nodeCount
virtual std::vector< Index64 > nodeCount() const =0
openvdb::v12_1::tree::TreeBase::readBuffers
virtual void readBuffers(std::istream &, bool saveFloatAsHalf=false)=0
Read all data buffers for this tree.
openvdb::v12_1::tree::TreeBase::isType
bool isType() const
Return true if this tree is of the same type as the template parameter.
Definition Tree.h:56
openvdb::v12_1::tree::TreeBase::writeBuffers
virtual void writeBuffers(std::ostream &, bool saveFloatAsHalf=false) const =0
Write out all the data buffers for this tree.
openvdb::v12_1::tree::TreeBase::leafCount
virtual Index64 leafCount() const =0
Return the number of leaf nodes.
openvdb::v12_1::tree::TreeBase::getBackgroundValue
virtual Metadata::Ptr getBackgroundValue() const
Return this tree's background value wrapped as metadata.
Definition Tree.h:66
openvdb::v12_1::tree::TreeBase::nonLeafCount
virtual Index64 nonLeafCount() const =0
Return the number of non-leaf nodes.
openvdb::v12_1::tree::TreeBase::TreeBase
TreeBase()=default
openvdb::v12_1::tree::TreeBase::print
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
openvdb::v12_1::tree::TreeBase::readBuffers
virtual void readBuffers(std::istream &, const CoordBBox &, bool saveFloatAsHalf=false)=0
Read all of this tree's data buffers that intersect the given bounding box.
openvdb::v12_1::tree::TreeBase::getIndexRange
virtual void getIndexRange(CoordBBox &bbox) const =0
openvdb::v12_1::tree::TreeBase::activeVoxelCount
virtual Index64 activeVoxelCount() const =0
Return the total number of active voxels.
openvdb::v12_1::tree::TreeBase::inactiveVoxelCount
virtual Index64 inactiveVoxelCount() const =0
Return the number of inactive voxels within the bounding box of all active voxels.
openvdb::v12_1::tree::TreeBase::clipUnallocatedNodes
virtual void clipUnallocatedNodes()=0
Replace with background tiles any nodes whose voxel buffers have not yet been allocated.
openvdb::v12_1::tree::TreeBase::readNonresidentBuffers
virtual void readNonresidentBuffers() const =0
Read all of this tree's data buffers that are not yet resident in memory (because delayed loading is ...
openvdb::v12_1::tree::TreeBase::inactiveLeafVoxelCount
virtual Index64 inactiveLeafVoxelCount() const =0
Return the number of inactive voxels stored in leaf nodes.
openvdb::v12_1::tree::TreeBase::memUsage
virtual Index64 memUsage() const
Return the total amount of memory in bytes occupied by this tree.
Definition Tree.h:151
openvdb::v12_1::tree::TreeBase::copy
virtual TreeBase::Ptr copy() const =0
Return a pointer to a deep copy of this tree.
openvdb::v12_1::tree::TreeBase::Ptr
SharedPtr< TreeBase > Ptr
Definition Tree.h:40
openvdb::v12_1::tree::TreeBase::evalLeafDim
virtual bool evalLeafDim(Coord &dim) const =0
Return in dim the dimensions of the axis-aligned bounding box of all leaf nodes.
openvdb::v12_1::tree::TreeBase::evalActiveVoxelBoundingBox
virtual bool evalActiveVoxelBoundingBox(CoordBBox &bbox) const =0
Return in bbox the axis-aligned bounding box of all active voxels and tiles.
openvdb::v12_1::tree::TreeBase::treeDepth
virtual Index treeDepth() const =0
Return the depth of this tree.
openvdb::v12_1::tree::TreeBase::activeTileCount
virtual Index64 activeTileCount() const =0
Return the total number of active tiles.
openvdb::v12_1::tree::TreeBase::ConstPtr
SharedPtr< const TreeBase > ConstPtr
Definition Tree.h:41
openvdb::v12_1::tree::TreeBase::evalActiveVoxelDim
virtual bool evalActiveVoxelDim(Coord &dim) const =0
Return in dim the dimensions of the axis-aligned bounding box of all active voxels....
openvdb::v12_1::tree::TreeBase::evalLeafBoundingBox
virtual bool evalLeafBoundingBox(CoordBBox &bbox) const =0
Return in bbox the axis-aligned bounding box of all active tiles and leaf nodes with active values.
openvdb::v12_1::tree::TreeBase::operator=
TreeBase & operator=(const TreeBase &)=delete
openvdb::v12_1::tree::TreeBase::TreeBase
TreeBase(const TreeBase &)=default
openvdb::v12_1::tree::TreeBase::readTopology
virtual void readTopology(std::istream &, bool saveFloatAsHalf=false)
Read the tree topology from a stream.
Definition Tree.h:1148
openvdb::v12_1::tree::TreeValueIteratorBase
Base class for tree-traversal iterators over tile and voxel values.
Definition TreeIterator.h:618
openvdb::v12_1::tree::Tree
Definition Tree.h:195
openvdb::v12_1::tree::Tree::readTopology
void readTopology(std::istream &, bool saveFloatAsHalf=false) override
Read the tree topology from a stream.
Definition Tree.h:1287
openvdb::v12_1::tree::Tree::beginRootDense
RootNodeType::ChildAllCIter beginRootDense() const
Return an iterator over all entries of the root node's table.
Definition Tree.h:1018
openvdb::v12_1::tree::Tree::getBackgroundValue
Metadata::Ptr getBackgroundValue() const override
Return this tree's background value wrapped as metadata.
Definition Tree.h:1765
openvdb::v12_1::tree::Tree::getValueDepth
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
openvdb::v12_1::tree::Tree::hasSameTopology
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
openvdb::v12_1::tree::Tree::unallocatedLeafCount
Index64 unallocatedLeafCount() const override
Return the total number of unallocated leaf nodes residing in this tree.
Definition Tree.h:1718
openvdb::v12_1::tree::Tree::cbegin
CIterT cbegin() const
Return a const iterator of type CIterT (for example, cbegin<ValueOnCIter>() is equivalent to cbeginVa...
openvdb::v12_1::tree::Tree::evalActiveVoxelBoundingBox
bool evalActiveVoxelBoundingBox(CoordBBox &bbox) const override
Return in bbox the axis-aligned bounding box of all active voxels and tiles.
Definition Tree.h:1983
openvdb::v12_1::tree::Tree::stealNode
NodeT * stealNode(const Coord &xyz, const ValueType &value, bool active)
Return a pointer to the node of type NodeT that contains voxel (x, y, z) and replace it with a tile o...
Definition Tree.h:1631
openvdb::v12_1::tree::Tree::releaseAccessor
void releaseAccessor(ValueAccessorBase< Tree, false > &) const
Dummy implementations.
Definition Tree.h:719
openvdb::v12_1::tree::Tree::probeNode
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node of type NodeType that contains voxel (x, y, z). If no such node exists,...
Definition Tree.h:1665
openvdb::v12_1::tree::Tree::probeNode
const NodeType * probeNode(const Coord &xyz) const
Definition Tree.h:1674
openvdb::v12_1::tree::Tree::combine
void combine(Tree &other, CombineOp &op, bool prune=false)
Definition Tree.h:1848
openvdb::v12_1::tree::Tree::getValue
const ValueType & getValue(const Coord &xyz, AccessT &) const
Return the value of the voxel at the given coordinates and update the given accessor's node cache.
openvdb::v12_1::tree::Tree::releaseAccessor
void releaseAccessor(ValueAccessorBase< const Tree, false > &) const
Definition Tree.h:720
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::mConstAccessorRegistry
ConstAccessorRegistry mConstAccessorRegistry
Definition Tree.h:1110
openvdb::v12_1::tree::Tree::isValueOn
bool isValueOn(const Coord &xyz) const
Return true if the value at the given coordinates is active.
Definition Tree.h:491
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::root
RootNodeType & root()
Definition Tree.h:303
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueOffIter
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOffIter > ValueOffIter
Definition Tree.h:1054
openvdb::v12_1::tree::Tree::Tree
Tree(const Tree &other)
Deep copy constructor.
Definition Tree.h:229
openvdb::v12_1::tree::Tree::cbeginRootTiles
RootNodeType::ChildOffCIter cbeginRootTiles() const
Definition Tree.h:1012
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueOffCIter
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOffCIter > ValueOffCIter
Definition Tree.h:1055
openvdb::v12_1::tree::Tree::beginLeaf
LeafCIter beginLeaf() const
Definition Tree.h:1046
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::Accessor
ValueAccessor< Tree, true > Accessor
Definition Tree.h:207
openvdb::v12_1::tree::Tree::writeBuffers
void writeBuffers(std::ostream &, bool saveFloatAsHalf=false) const override
Write out all data buffers for this tree.
Definition Tree.h:1335
openvdb::v12_1::tree::Tree::writeTopology
void writeTopology(std::ostream &, bool saveFloatAsHalf=false) const override
Write the tree topology to a stream.
Definition Tree.h:1297
openvdb::v12_1::tree::Tree::cbeginValueOff
ValueOffCIter cbeginValueOff() const
Definition Tree.h:1073
openvdb::v12_1::tree::Tree::Tree
Tree(const Tree< OtherRootType > &other)
Value conversion deep copy constructor.
Definition Tree.h:240
openvdb::v12_1::tree::Tree::probeConstLeaf
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition Tree.h:1656
openvdb::v12_1::tree::Tree::begin
IterT begin()
Return an iterator of type IterT (for example, begin<ValueOnIter>() is equivalent to beginValueOn()).
Definition Tree.h:1267
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::memUsage
Index64 memUsage() const override
Definition Tree.h:408
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::clearAllAccessors
void clearAllAccessors()
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::evalMinMax
void evalMinMax(ValueType &min, ValueType &max) const
openvdb::v12_1::tree::Tree::merge
void merge(Tree &other, MergePolicy=MERGE_ACTIVE_STATES)
Efficiently merge another tree into this tree using one of several schemes.
Definition Tree.h:1785
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueAllCIter
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueAllCIter > ValueAllCIter
Definition Tree.h:1051
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::RootNodeType
tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > RootNodeType
Definition Tree.h:200
openvdb::v12_1::tree::Tree::beginRootDense
RootNodeType::ChildAllIter beginRootDense()
Definition Tree.h:1020
openvdb::v12_1::tree::Tree::getAccessor
Accessor getAccessor()
Return an accessor that provides random read and write access to this tree's voxels.
Definition Tree.h:1392
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::UnsafeAccessor
ValueAccessor< Tree, false > UnsafeAccessor
Definition Tree.h:209
openvdb::v12_1::tree::Tree::cbeginLeaf
LeafCIter cbeginLeaf() const
Definition Tree.h:1047
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::LeafCIter
LeafIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > LeafCIter
Definition Tree.h:1033
openvdb::v12_1::tree::Tree::type
const Name & type() const override
Return the name of this type of tree.
Definition Tree.h:296
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::DEPTH
static const Index DEPTH
Definition Tree.h:205
openvdb::v12_1::tree::Tree::beginRootTiles
RootNodeType::ChildOffIter beginRootTiles()
Definition Tree.h:1013
openvdb::v12_1::tree::Tree::getNodes
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition Tree.h:1344
openvdb::v12_1::tree::Tree::readBuffers
void readBuffers(std::istream &, const CoordBBox &, bool saveFloatAsHalf=false) override
Read all of this tree's data buffers that intersect the given bounding box.
Definition Tree.h:1315
openvdb::v12_1::tree::Tree::treeType
static const Name & treeType()
Return the name of this type of tree.
Definition Tree.h:1941
openvdb::v12_1::tree::Tree::voxelizeActiveTiles
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition Tree.h:1756
openvdb::v12_1::tree::Tree::beginRootChildren
RootNodeType::ChildOnCIter beginRootChildren() const
Return an iterator over children of the root node.
Definition Tree.h:1004
openvdb::v12_1::tree::Tree::combine
void combine(Tree &other, const CombineOp &op, bool prune=false)
Definition Tree.h:1860
openvdb::v12_1::tree::Tree::operator!=
bool operator!=(const Tree &) const
Definition Tree.h:299
openvdb::v12_1::tree::Tree::Tree
Tree()
Definition Tree.h:224
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::mAccessorRegistry
AccessorRegistry mAccessorRegistry
Definition Tree.h:1109
openvdb::v12_1::tree::Tree::clip
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition Tree.h:1694
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ConstAccessor
ValueAccessor< const Tree, true > ConstAccessor
Definition Tree.h:208
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::mRoot
RootNodeType mRoot
Definition Tree.h:1108
openvdb::v12_1::tree::Tree::cbeginValueAll
ValueAllCIter cbeginValueAll() const
Definition Tree.h:1061
openvdb::v12_1::tree::Tree::prune
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
openvdb::v12_1::tree::Tree::probeLeaf
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition Tree.h:1648
openvdb::v12_1::tree::Tree::topologyIntersection
void topologyIntersection(const Tree< OtherRootNodeType > &other)
Intersects this tree's set of active values with the active values of the other tree,...
Definition Tree.h:1812
openvdb::v12_1::tree::Tree::releaseAccessor
void releaseAccessor(ValueAccessorBase< Tree, true > &) const
Deregister an accessor so that it is no longer automatically cleared.
Definition Tree.h:1445
openvdb::v12_1::tree::Tree::touchLeaf
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition Tree.h:1640
openvdb::v12_1::tree::Tree::beginRootChildren
RootNodeType::ChildOnIter beginRootChildren()
Definition Tree.h:1006
openvdb::v12_1::tree::Tree::leafCount
Index64 leafCount() const override
Return the number of leaf nodes.
Definition Tree.h:363
openvdb::v12_1::tree::Tree::beginValueOn
ValueOnCIter beginValueOn() const
Definition Tree.h:1066
openvdb::v12_1::tree::Tree::operator==
bool operator==(const Tree &) const
Definition Tree.h:298
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::Ptr
SharedPtr< Tree > Ptr
Definition Tree.h:197
openvdb::v12_1::tree::Tree::attachAccessor
void attachAccessor(ValueAccessorBase< Tree, true > &) const
Register an accessor for this tree. Registered accessors are automatically cleared whenever one of th...
Definition Tree.h:1427
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::NodeIter
NodeIteratorBase< Tree, typename RootNodeType::ChildOnIter > NodeIter
Definition Tree.h:1026
openvdb::v12_1::tree::Tree::activeLeafVoxelCount
Index64 activeLeafVoxelCount() const override
Return the number of active voxels stored in leaf nodes.
Definition Tree.h:394
openvdb::v12_1::tree::Tree::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition Tree.h:1602
openvdb::v12_1::tree::Tree::getConstUnsafeAccessor
ConstUnsafeAccessor getConstUnsafeAccessor()
Return an unsafe accessor that provides random read-only access to this tree's voxels.
Definition Tree.h:1420
openvdb::v12_1::tree::Tree::combine2Extended
void combine2Extended(const Tree &a, const OtherTreeType &b, const ExtendedCombineOp &, bool prune=false)
Definition Tree.h:1928
openvdb::v12_1::tree::Tree::inactiveVoxelCount
Index64 inactiveVoxelCount() const override
Return the number of inactive voxels within the bounding box of all active voxels.
Definition Tree.h:400
openvdb::v12_1::tree::Tree::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition Tree.h:1560
openvdb::v12_1::tree::Tree::empty
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
openvdb::v12_1::tree::Tree::activeVoxelCount
Index64 activeVoxelCount() const override
Return the total number of active voxels.
Definition Tree.h:398
openvdb::v12_1::tree::Tree::inactiveLeafVoxelCount
Index64 inactiveLeafVoxelCount() const override
Return the number of inactive voxels stored in leaf nodes.
Definition Tree.h:396
openvdb::v12_1::tree::Tree::fill
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Definition Tree.h:523
openvdb::v12_1::tree::Tree::beginValueOff
ValueOffCIter beginValueOff() const
Definition Tree.h:1072
openvdb::v12_1::tree::Tree::addLeaf
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
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueAllIter
TreeValueIteratorBase< Tree, typename RootNodeType::ValueAllIter > ValueAllIter
Definition Tree.h:1050
openvdb::v12_1::tree::Tree::beginRootTiles
RootNodeType::ChildOffCIter beginRootTiles() const
Return an iterator over non-child entries of the root node's table.
Definition Tree.h:1011
openvdb::v12_1::tree::Tree::combineExtended
void combineExtended(Tree &other, ExtendedCombineOp &op, bool prune=false)
Definition Tree.h:1870
openvdb::v12_1::tree::Tree::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition Tree.h:1537
openvdb::v12_1::tree::Tree::addTile
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
openvdb::v12_1::tree::Tree::releaseAccessor
void releaseAccessor(ValueAccessorBase< const Tree, true > &) const
Definition Tree.h:1453
openvdb::v12_1::tree::Tree::probeValue
bool probeValue(const Coord &xyz, ValueType &value) const
Get the value of the voxel at the given coordinates.
Definition Tree.h:1610
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueOnCIter
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOnCIter > ValueOnCIter
Definition Tree.h:1053
openvdb::v12_1::tree::Tree::setActiveState
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition Tree.h:1545
openvdb::v12_1::tree::Tree::beginValueOn
ValueOnIter beginValueOn()
Return an iterator over active values (tile and voxel) across all nodes.
Definition Tree.h:1065
openvdb::v12_1::tree::Tree::topologyDifference
void topologyDifference(const Tree< OtherRootNodeType > &other)
Difference this tree's set of active values with the active values of the other tree,...
Definition Tree.h:1821
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::releaseAllAccessors
void releaseAllAccessors()
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::BuildType
typename RootNodeType::BuildType BuildType
Definition Tree.h:202
openvdb::v12_1::tree::Tree::setValue
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
openvdb::v12_1::tree::Tree::combine2Extended
void combine2Extended(const Tree &a, const OtherTreeType &b, ExtendedCombineOp &op, bool prune=false)
Definition Tree.h:1914
openvdb::v12_1::tree::Tree::activeTileCount
Index64 activeTileCount() const override
Return the total number of active tiles.
Definition Tree.h:402
openvdb::v12_1::tree::Tree::setValueOff
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition Tree.h:1529
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ConstAccessorRegistry
tbb::concurrent_hash_map< ValueAccessorBase< const Tree, true > *, bool > ConstAccessorRegistry
Definition Tree.h:1086
openvdb::v12_1::tree::Tree::cbeginValueOn
ValueOnCIter cbeginValueOn() const
Definition Tree.h:1067
openvdb::v12_1::tree::Tree::copy
TreeBase::Ptr copy() const override
Return a pointer to a deep copy of this tree.
Definition Tree.h:288
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueType
typename RootNodeType::ValueType ValueType
Definition Tree.h:201
openvdb::v12_1::tree::Tree::attachAccessor
void attachAccessor(ValueAccessorBase< Tree, false > &) const
Dummy implementations.
Definition Tree.h:707
openvdb::v12_1::tree::Tree::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition Tree.h:1504
openvdb::v12_1::tree::Tree::probeLeaf
const LeafNodeType * probeLeaf(const Coord &xyz) const
Definition Tree.h:598
openvdb::v12_1::tree::Tree::print
void print(std::ostream &os=std::cout, int verboseLevel=1) const override
Print statistics, memory usage and other information about this tree.
Definition Tree.h:2044
openvdb::v12_1::tree::Tree::combineExtended
void combineExtended(Tree &other, const ExtendedCombineOp &op, bool prune=false)
Definition Tree.h:1882
openvdb::v12_1::tree::Tree::attachAccessor
void attachAccessor(ValueAccessorBase< const Tree, false > &) const
Definition Tree.h:708
openvdb::v12_1::tree::Tree::getUnsafeAccessor
UnsafeAccessor getUnsafeAccessor()
Return an unsafe accessor that provides random read and write access to this tree's voxels.
Definition Tree.h:1399
openvdb::v12_1::tree::Tree::combine2
void combine2(const Tree &a, const OtherTreeType &b, const CombineOp &op, bool prune=false)
Definition Tree.h:1904
openvdb::v12_1::tree::Tree::beginNode
NodeCIter beginNode() const
Definition Tree.h:1039
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ConstUnsafeAccessor
ValueAccessor< const Tree, false > ConstUnsafeAccessor
Definition Tree.h:210
openvdb::v12_1::tree::Tree::modifyValue
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
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::LeafIter
LeafIteratorBase< Tree, typename RootNodeType::ChildOnIter > LeafIter
Definition Tree.h:1032
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ConstPtr
SharedPtr< const Tree > ConstPtr
Definition Tree.h:198
openvdb::v12_1::tree::Tree::readNonresidentBuffers
void readNonresidentBuffers() const override
Read all of this tree's data buffers that are not yet resident in memory (because delayed loading is ...
Definition Tree.h:1324
openvdb::v12_1::tree::Tree::Tree
Tree(const OtherTreeType &other, const ValueType &background, TopologyCopy)
Topology copy constructor from a tree of a different type.
Definition Tree.h:276
openvdb::v12_1::tree::Tree::cbeginRootDense
RootNodeType::ChildAllCIter cbeginRootDense() const
Definition Tree.h:1019
openvdb::v12_1::tree::Tree::getNodes
void getNodes(ArrayT &array) const
Definition Tree.h:1356
openvdb::v12_1::tree::Tree::denseFill
void denseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value and ensure that those voxels are a...
Definition Tree.h:1747
openvdb::v12_1::tree::Tree::evalLeafBoundingBox
bool evalLeafBoundingBox(CoordBBox &bbox) const override
Return in bbox the axis-aligned bounding box of all active tiles and leaf nodes with active values.
Definition Tree.h:1970
openvdb::v12_1::tree::Tree::stealNodes
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Definition Tree.h:654
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::clear
void clear()
openvdb::v12_1::tree::Tree::evalLeafDim
bool evalLeafDim(Coord &dim) const override
Return in dim the dimensions of the axis-aligned bounding box of all leaf nodes.
Definition Tree.h:2008
openvdb::v12_1::tree::Tree::cbeginRootChildren
RootNodeType::ChildOnCIter cbeginRootChildren() const
Definition Tree.h:1005
openvdb::v12_1::tree::Tree::setValue
void setValue(const Coord &xyz, const ValueType &value, AccessT &)
Set the value of the voxel at the given coordinates, mark the voxel as active, and update the given a...
Definition Tree.h:1568
openvdb::v12_1::tree::Tree::nodeCount
std::vector< Index64 > nodeCount() const override
Definition Tree.h:371
openvdb::v12_1::tree::Tree::cbeginNode
NodeCIter cbeginNode() const
Definition Tree.h:1040
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::background
const ValueType & background() const
Definition Tree.h:732
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::NodeCIter
NodeIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > NodeCIter
Definition Tree.h:1027
openvdb::v12_1::tree::Tree::operator=
Tree & operator=(const Tree &)=delete
openvdb::v12_1::tree::Tree::getNodeLog2Dims
static void getNodeLog2Dims(std::vector< Index > &dims)
Traverse the type hierarchy of nodes, and return, in dims, a list of the Log2Dims of nodes in order f...
Definition Tree.h:2035
openvdb::v12_1::tree::Tree::beginValueOff
ValueOffIter beginValueOff()
Return an iterator over inactive values (tile and voxel) across all nodes.
Definition Tree.h:1071
openvdb::v12_1::tree::Tree::getIndexRange
void getIndexRange(CoordBBox &bbox) const override
Min and max are both inclusive.
Definition Tree.h:735
openvdb::v12_1::tree::Tree::attachAccessor
void attachAccessor(ValueAccessorBase< const Tree, true > &) const
Definition Tree.h:1436
openvdb::v12_1::tree::Tree::readBuffers
void readBuffers(std::istream &, bool saveFloatAsHalf=false) override
Read all data buffers for this tree.
Definition Tree.h:1306
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::LeafNodeType
typename RootNodeType::LeafNodeType LeafNodeType
Definition Tree.h:203
openvdb::v12_1::tree::Tree::getConstAccessor
ConstAccessor getConstAccessor() const
Return an accessor that provides random read-only access to this tree's voxels.
Definition Tree.h:1413
openvdb::v12_1::tree::Tree::setValueOn
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition Tree.h:1576
openvdb::v12_1::tree::Tree::beginLeaf
LeafIter beginLeaf()
Return an iterator over all leaf nodes in this tree.
Definition Tree.h:1045
openvdb::v12_1::tree::Tree::sparseFill
void sparseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition Tree.h:1738
openvdb::v12_1::tree::Tree::Tree
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
openvdb::v12_1::tree::Tree::evalActiveVoxelDim
bool evalActiveVoxelDim(Coord &dim) const override
Return in dim the dimensions of the axis-aligned bounding box of all active voxels....
Definition Tree.h:1997
openvdb::v12_1::tree::Tree::~Tree
~Tree() override
Definition Tree.h:285
openvdb::v12_1::tree::Tree::probeConstNode
const NodeType * probeConstNode(const Coord &xyz) const
Definition Tree.h:1683
openvdb::v12_1::tree::Tree::hasActiveTiles
bool hasActiveTiles() const
Return true if this tree has any active tiles.
Definition Tree.h:495
openvdb::v12_1::tree::Tree::Tree
Tree(const ValueType &background)
Empty tree constructor.
Definition Tree.h:283
openvdb::v12_1::tree::Tree::clipUnallocatedNodes
void clipUnallocatedNodes() override
Replace with background tiles any nodes whose voxel buffers have not yet been allocated.
Definition Tree.h:1703
openvdb::v12_1::tree::Tree::setValueOn
void setValueOn(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:1584
openvdb::v12_1::tree::Tree::isValueOff
bool isValueOff(const Coord &xyz) const
Return true if the value at the given coordinates is inactive.
Definition Tree.h:493
openvdb::v12_1::tree::Tree::stealNodes
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
openvdb::v12_1::tree::Tree::topologyUnion
void topologyUnion(const Tree< OtherRootNodeType > &other, const bool preserveTiles=false)
Union this tree's set of active values with the active values of the other tree, whose ValueType may ...
Definition Tree.h:1803
openvdb::v12_1::tree::Tree::valueType
Name valueType() const override
Return the name of the type of a voxel's value (e.g., "float" or "vec3d")
Definition Tree.h:291
openvdb::v12_1::tree::Tree::combine2
void combine2(const Tree &a, const OtherTreeType &b, CombineOp &op, bool prune=false)
Definition Tree.h:1892
openvdb::v12_1::tree::Tree::treeDepth
Index treeDepth() const override
Return the depth of this tree.
Definition Tree.h:360
openvdb::v12_1::tree::Tree::root
const RootNodeType & root() const
Definition Tree.h:304
openvdb::v12_1::tree::Tree::beginValueAll
ValueAllCIter beginValueAll() const
Definition Tree.h:1060
openvdb::v12_1::tree::Tree::beginNode
NodeIter beginNode()
Return an iterator over all nodes in this tree.
Definition Tree.h:1038
openvdb::v12_1::tree::Tree::getAccessor
ConstAccessor getAccessor() const
Return an accessor that provides random read-only access to this tree's voxels.
Definition Tree.h:1406
openvdb::v12_1::tree::Tree::nonLeafCount
Index64 nonLeafCount() const override
Return the number of non-leaf nodes.
Definition Tree.h:389
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::AccessorRegistry
tbb::concurrent_hash_map< ValueAccessorBase< Tree, true > *, bool > AccessorRegistry
Definition Tree.h:1085
openvdb::v12_1::tree::Tree::beginValueAll
ValueAllIter beginValueAll()
Return an iterator over all values (tile and voxel) across all nodes.
Definition Tree.h:1059
openvdb::v12_1::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueOnIter
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOnIter > ValueOnIter
Definition Tree.h:1052
openvdb::v12_1::tree::ValueAccessorBase
This base class for ValueAccessors manages registration of an accessor with a tree so that the tree c...
Definition ValueAccessor.h:152
logging.h
OPENVDB_LOG_WARN
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form 'someVar << "some text" << ...'.
Definition logging.h:256
openvdb::v12_1::math::cwiseLessThan
bool cwiseLessThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition Mat.h:1015
openvdb::v12_1::math::cwiseGreaterThan
bool cwiseGreaterThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition Mat.h:1029
openvdb::v12_1::tools::countActiveLeafVoxels
Index64 countActiveLeafVoxels(const TreeT &tree, bool threaded=true)
Return the total number of active voxels stored in leaf nodes.
Definition Count.h:436
openvdb::v12_1::tools::minMax
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
openvdb::v12_1::tools::countInactiveVoxels
Index64 countInactiveVoxels(const TreeT &tree, bool threaded=true)
Return the total number of inactive voxels in the tree.
Definition Count.h:461
openvdb::v12_1::tools::countActiveVoxels
Index64 countActiveVoxels(const TreeT &tree, bool threaded=true)
Return the total number of active voxels in the tree.
Definition Count.h:413
openvdb::v12_1::tools::memUsage
Index64 memUsage(const TreeT &tree, bool threaded=true)
Return the total amount of memory in bytes occupied by this tree.
Definition Count.h:493
openvdb::v12_1::tools::countInactiveLeafVoxels
Index64 countInactiveLeafVoxels(const TreeT &tree, bool threaded=true)
Return the total number of inactive voxels stored in leaf nodes.
Definition Count.h:471
openvdb::v12_1::tools::countActiveTiles
Index64 countActiveTiles(const TreeT &tree, bool threaded=true)
Return the total number of active tiles in the tree.
Definition Count.h:482
openvdb::v12_1::tree::iter
Definition TreeIterator.h:30
openvdb::v12_1::tree
Definition PointDataGrid.h:170
openvdb::v12_1::tree::ValueAccessor
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels > > ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition ValueAccessor.h:86
openvdb::v12_1::util::formattedInt
FormattedInt< IntT > formattedInt(IntT n)
Definition Formats.h:118
openvdb::v12_1::util::printBytes
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)
openvdb::v12_1::Name
std::string Name
Definition Name.h:19
openvdb::v12_1::Index
Index32 Index
Definition Types.h:54
openvdb::v12_1::zeroVal
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
openvdb::v12_1::Index32
uint32_t Index32
Definition Types.h:52
openvdb::v12_1::Index64
uint64_t Index64
Definition Types.h:53
openvdb::v12_1::SharedPtr
std::shared_ptr< T > SharedPtr
Definition Types.h:114
openvdb::v12_1::MergePolicy
MergePolicy
Definition Types.h:577
openvdb::v12_1::MERGE_ACTIVE_STATES
@ MERGE_ACTIVE_STATES
Definition Types.h:578
openvdb::v12_1::MERGE_NODES
@ MERGE_NODES
Definition Types.h:579
openvdb::v12_1::MERGE_ACTIVE_STATES_AND_NODES
@ MERGE_ACTIVE_STATES_AND_NODES
Definition Types.h:580
openvdb::v12_1::typeNameAsString
const char * typeNameAsString()
Definition Types.h:587
openvdb
Definition Exceptions.h:13
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Types.h
openvdb::v12_1::tree::CombineOpAdapter
Helper class to adapt a three-argument (a, b, result) CombineOp functor into a single-argument functo...
Definition Tree.h:1834
openvdb::v12_1::tree::CombineOpAdapter::operator()
void operator()(CombineArgs< AValueT, BValueT > &args) const
Definition Tree.h:1837
openvdb::v12_1::tree::CombineOpAdapter::CombineOpAdapter
CombineOpAdapter(CombineOp &_op)
Definition Tree.h:1835
openvdb::v12_1::tree::CombineOpAdapter::op
CombineOp & op
Definition Tree.h:1841
openvdb::v12_1::tree::Tree3
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
openvdb::v12_1::tree::Tree3::Type
Tree< RootNode< InternalNode< LeafNode< T, N2 >, N1 > > > Type
Definition Tree.h:1120
openvdb::v12_1::tree::Tree4
Tree4<T, N1, N2, N3>::Type is the type of a four-level tree (Root, Internal, Internal,...
Definition Tree.h:1129
openvdb::v12_1::tree::Type::Type
Tree< RootNode< InternalNode< InternalNode< LeafNode< bool, N3 >, N2 >, N1 > > > Type
Definition Tree.h:1130
openvdb::v12_1::tree::Tree5
Tree5<T, N1, N2, N3, N4>::Type is the type of a five-level tree (Root, Internal, Internal,...
Definition Tree.h:1138
openvdb::v12_1::tree::Tree5::Type
Tree< RootNode< InternalNode< InternalNode< InternalNode< LeafNode< T, N4 >, N3 >, N2 >, N1 > > > Type
Definition Tree.h:1139
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::LeafCIter >::begin
static TreeT::LeafCIter begin(const TreeT &tree)
Definition Tree.h:1236
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::LeafIter >::begin
static TreeT::LeafIter begin(TreeT &tree)
Definition Tree.h:1232
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::NodeCIter >::begin
static TreeT::NodeCIter begin(const TreeT &tree)
Definition Tree.h:1228
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::NodeIter >::begin
static TreeT::NodeIter begin(TreeT &tree)
Definition Tree.h:1224
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildAllCIter >::begin
static TreeT::RootNodeType::ChildAllCIter begin(const TreeT &tree)
Definition Tree.h:1218
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildAllIter >::begin
static TreeT::RootNodeType::ChildAllIter begin(TreeT &tree)
Definition Tree.h:1212
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildOffCIter >::begin
static TreeT::RootNodeType::ChildOffCIter begin(const TreeT &tree)
Definition Tree.h:1206
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildOffIter >::begin
static TreeT::RootNodeType::ChildOffIter begin(TreeT &tree)
Definition Tree.h:1200
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildOnCIter >::begin
static TreeT::RootNodeType::ChildOnCIter begin(const TreeT &tree)
Definition Tree.h:1194
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildOnIter >::begin
static TreeT::RootNodeType::ChildOnIter begin(TreeT &tree)
Definition Tree.h:1188
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::ValueAllCIter >::begin
static TreeT::ValueAllCIter begin(const TreeT &tree)
Definition Tree.h:1260
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::ValueAllIter >::begin
static TreeT::ValueAllIter begin(TreeT &tree)
Definition Tree.h:1256
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::ValueOffCIter >::begin
static TreeT::ValueOffCIter begin(const TreeT &tree)
Definition Tree.h:1252
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::ValueOffIter >::begin
static TreeT::ValueOffIter begin(TreeT &tree)
Definition Tree.h:1248
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::ValueOnCIter >::begin
static TreeT::ValueOnCIter begin(const TreeT &tree)
Definition Tree.h:1244
openvdb::v12_1::tree::TreeIterTraits< TreeT, typename TreeT::ValueOnIter >::begin
static TreeT::ValueOnIter begin(TreeT &tree)
Definition Tree.h:1240
openvdb::v12_1::tree::TreeIterTraits
TreeIterTraits provides, for all tree iterators, a begin(tree) function that returns an iterator over...
Definition Tree.h:1185
openvdb::v12_1::tree::Tree::DeallocateNodes
Definition Tree.h:1094
openvdb::v12_1::tree::Tree::DeallocateNodes::DeallocateNodes
DeallocateNodes(std::vector< NodeType * > &nodes)
Definition Tree.h:1095
openvdb::v12_1::tree::Tree::DeallocateNodes::mNodes
NodeType **const mNodes
Definition Tree.h:1102
openvdb::v12_1::tree::Tree::DeallocateNodes::operator()
void operator()(const tbb::blocked_range< size_t > &range) const
Definition Tree.h:1097
openvdb::v12_1::tree::Tree::ValueConverter
ValueConverter<T>::Type is the type of a tree having the same hierarchy as this tree but a different ...
Definition Tree.h:219
openvdb::v12_1::tree::Tree::ValueConverter::Type
Tree< typename RootNodeType::template ValueConverter< OtherValueType >::Type > Type
Definition Tree.h:220
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218