OpenVDB  3.1.0
Tree.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2015 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 //
32 
33 #ifndef OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
34 #define OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
35 
36 #include <iostream>
37 #include <sstream>
38 #include <vector>
39 #include <boost/shared_ptr.hpp>
40 #include <boost/cstdint.hpp>
41 #include <tbb/atomic.h>
42 #include <tbb/concurrent_hash_map.h>
43 #include <openvdb/Types.h>
44 #include <openvdb/metadata/Metadata.h>
45 #include <openvdb/math/Math.h>
46 #include <openvdb/math/BBox.h>
47 #include <openvdb/util/Formats.h>
48 #include <openvdb/util/logging.h>
49 #include <openvdb/Platform.h>
50 #include "RootNode.h"
51 #include "InternalNode.h"
52 #include "LeafNode.h"
53 #include "TreeIterator.h"
54 #include "ValueAccessor.h"
55 
56 
57 namespace openvdb {
59 namespace OPENVDB_VERSION_NAME {
60 namespace tree {
61 
64 {
65 public:
66  typedef boost::shared_ptr<TreeBase> Ptr;
67  typedef boost::shared_ptr<const TreeBase> ConstPtr;
68 
69  TreeBase() {}
70  virtual ~TreeBase() {}
71 
73  virtual const Name& type() const = 0;
74 
76  virtual Name valueType() const = 0;
77 
79  virtual TreeBase::Ptr copy() const = 0;
80 
81  //
82  // Tree methods
83  //
86  virtual Metadata::Ptr getBackgroundValue() const { return Metadata::Ptr(); }
87 
95  virtual bool evalLeafBoundingBox(CoordBBox& bbox) const = 0;
96 
100  virtual bool evalLeafDim(Coord& dim) const = 0;
101 
109  virtual bool evalActiveVoxelBoundingBox(CoordBBox& bbox) const = 0;
110 
114  virtual bool evalActiveVoxelDim(Coord& dim) const = 0;
115 
116  virtual void getIndexRange(CoordBBox& bbox) const = 0;
117 
118 #ifndef OPENVDB_2_ABI_COMPATIBLE
119  virtual void clipUnallocatedNodes() = 0;
125 #endif
126 
127 
128  //
129  // Statistics
130  //
134  virtual Index treeDepth() const = 0;
136  virtual Index32 leafCount() const = 0;
138  virtual Index32 nonLeafCount() const = 0;
140  virtual Index64 activeLeafVoxelCount() const = 0;
142  virtual Index64 inactiveLeafVoxelCount() const = 0;
144  virtual Index64 activeVoxelCount() const = 0;
146  virtual Index64 inactiveVoxelCount() const = 0;
147 #ifndef OPENVDB_2_ABI_COMPATIBLE
148  virtual Index64 activeTileCount() const = 0;
150 #endif
151 
153  virtual Index64 memUsage() const { return 0; }
154 
155 
156  //
157  // I/O methods
158  //
162  virtual void readTopology(std::istream&, bool saveFloatAsHalf = false);
166  virtual void writeTopology(std::ostream&, bool saveFloatAsHalf = false) const;
167 
169  virtual void readBuffers(std::istream&, bool saveFloatAsHalf = false) = 0;
170 #ifndef OPENVDB_2_ABI_COMPATIBLE
171  virtual void readBuffers(std::istream&, const CoordBBox&, bool saveFloatAsHalf = false) = 0;
178  virtual void readNonresidentBuffers() const = 0;
179 #endif
180  virtual void writeBuffers(std::ostream&, bool saveFloatAsHalf = false) const = 0;
182 
190  virtual void print(std::ostream& os = std::cout, int verboseLevel = 1) const;
191 
192 private:
193  // Disallow copying of instances of this class.
194  //TreeBase(const TreeBase& other);
195  TreeBase& operator=(const TreeBase& other);
196 };
197 
198 
200 
201 
202 template<typename _RootNodeType>
203 class Tree: public TreeBase
204 {
205 public:
206  typedef boost::shared_ptr<Tree> Ptr;
207  typedef boost::shared_ptr<const Tree> ConstPtr;
208 
209  typedef _RootNodeType RootNodeType;
210  typedef typename RootNodeType::ValueType ValueType;
211  typedef typename RootNodeType::LeafNodeType LeafNodeType;
212 
213  static const Index DEPTH = RootNodeType::LEVEL + 1;
214 
221  template<typename OtherValueType>
222  struct ValueConverter {
224  };
225 
226 
227  Tree() {}
228 
230  Tree(const Tree& other): TreeBase(other), mRoot(other.mRoot)
231  {
232  }
233 
240  template<typename OtherRootType>
241  explicit Tree(const Tree<OtherRootType>& other): TreeBase(other), mRoot(other.root())
242  {
243  }
244 
255  template<typename OtherTreeType>
256  Tree(const OtherTreeType& other,
257  const ValueType& inactiveValue,
258  const ValueType& activeValue,
259  TopologyCopy):
260  TreeBase(other),
261  mRoot(other.root(), inactiveValue, activeValue, TopologyCopy())
262  {
263  }
264 
276  template<typename OtherTreeType>
277  Tree(const OtherTreeType& other, const ValueType& background, TopologyCopy):
278  TreeBase(other),
279  mRoot(other.root(), background, TopologyCopy())
280  {
281  }
282 
284  Tree(const ValueType& background): mRoot(background) {}
285 
286  virtual ~Tree() { releaseAllAccessors(); }
287 
289  virtual TreeBase::Ptr copy() const { return TreeBase::Ptr(new Tree(*this)); }
290 
292  virtual Name valueType() const { return typeNameAsString<ValueType>(); }
293 
295  static const Name& treeType();
297  virtual const Name& type() const { return this->treeType(); }
298 
299  bool operator==(const Tree&) const { OPENVDB_THROW(NotImplementedError, ""); }
300  bool operator!=(const Tree&) const { OPENVDB_THROW(NotImplementedError, ""); }
301 
303  RootNodeType& root() { return mRoot; }
305  const RootNodeType& root() const { return mRoot; }
307 
308 
309  //
310  // Tree methods
311  //
314  template<typename OtherRootNodeType>
315  bool hasSameTopology(const Tree<OtherRootNodeType>& other) const;
316 
317  virtual bool evalLeafBoundingBox(CoordBBox& bbox) const;
318  virtual bool evalActiveVoxelBoundingBox(CoordBBox& bbox) const;
319  virtual bool evalActiveVoxelDim(Coord& dim) const;
320  virtual bool evalLeafDim(Coord& dim) const;
321 
325  static void getNodeLog2Dims(std::vector<Index>& dims);
326 
327 
328  //
329  // I/O methods
330  //
334  virtual void readTopology(std::istream&, bool saveFloatAsHalf = false);
338  virtual void writeTopology(std::ostream&, bool saveFloatAsHalf = false) const;
340  virtual void readBuffers(std::istream&, bool saveFloatAsHalf = false);
341 #ifndef OPENVDB_2_ABI_COMPATIBLE
342  virtual void readBuffers(std::istream&, const CoordBBox&, bool saveFloatAsHalf = false);
349  virtual void readNonresidentBuffers() const;
350 #endif
351  virtual void writeBuffers(std::ostream&, bool saveFloatAsHalf = false) const;
353 
354  virtual void print(std::ostream& os = std::cout, int verboseLevel = 1) const;
355 
356 
357  //
358  // Statistics
359  //
363  virtual Index treeDepth() const { return DEPTH; }
365  virtual Index32 leafCount() const { return mRoot.leafCount(); }
367  virtual Index32 nonLeafCount() const { return mRoot.nonLeafCount(); }
369  virtual Index64 activeLeafVoxelCount() const { return mRoot.onLeafVoxelCount(); }
371  virtual Index64 inactiveLeafVoxelCount() const { return mRoot.offLeafVoxelCount(); }
373  virtual Index64 activeVoxelCount() const { return mRoot.onVoxelCount(); }
375  virtual Index64 inactiveVoxelCount() const;
377  Index64 activeTileCount() const { return mRoot.onTileCount(); }
378 
380  void evalMinMax(ValueType &min, ValueType &max) const;
381 
382  virtual Index64 memUsage() const { return sizeof(*this) + mRoot.memUsage(); }
383 
384 
385  //
386  // Voxel access methods (using signed indexing)
387  //
389  const ValueType& getValue(const Coord& xyz) const;
392  template<typename AccessT> const ValueType& getValue(const Coord& xyz, AccessT&) const;
393 
397  int getValueDepth(const Coord& xyz) const;
398 
400  void setActiveState(const Coord& xyz, bool on);
402  void setValueOnly(const Coord& xyz, const ValueType& value);
404  void setValueOn(const Coord& xyz);
406  void setValueOn(const Coord& xyz, const ValueType& value);
408  void setValue(const Coord& xyz, const ValueType& value);
411  template<typename AccessT> void setValue(const Coord& xyz, const ValueType& value, AccessT&);
413  void setValueOff(const Coord& xyz);
415  void setValueOff(const Coord& xyz, const ValueType& value);
416 
435  template<typename ModifyOp>
436  void modifyValue(const Coord& xyz, const ModifyOp& op);
437 
457  template<typename ModifyOp>
458  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op);
459 
462  bool probeValue(const Coord& xyz, ValueType& value) const;
463 
465  bool isValueOn(const Coord& xyz) const { return mRoot.isValueOn(xyz); }
467  bool isValueOff(const Coord& xyz) const { return !this->isValueOn(xyz); }
469  bool hasActiveTiles() const { return mRoot.hasActiveTiles(); }
470 
472  void clip(const CoordBBox&);
473 
474 #ifndef OPENVDB_2_ABI_COMPATIBLE
475  virtual void clipUnallocatedNodes();
481 #endif
482 
492  void fill(const CoordBBox& bbox, const ValueType& value, bool active = true);
493 
498  void prune(const ValueType& tolerance = zeroVal<ValueType>())
499  {
500  this->clearAllAccessors();
501  mRoot.prune(tolerance);
502  }
503 
506  void addLeaf(LeafNodeType& leaf) { mRoot.addLeaf(&leaf); }
507 
512  void addTile(Index level, const Coord& xyz, const ValueType& value, bool active);
513 
518  template<typename NodeT>
519  NodeT* stealNode(const Coord& xyz, const ValueType& value, bool active);
520 
526  LeafNodeType* touchLeaf(const Coord& xyz);
527 
529  template<typename NodeType> NodeType* probeNode(const Coord& xyz);
532  template<typename NodeType> const NodeType* probeConstNode(const Coord& xyz) const;
533  template<typename NodeType> const NodeType* probeNode(const Coord& xyz) const;
535 
537  LeafNodeType* probeLeaf(const Coord& xyz);
540  const LeafNodeType* probeConstLeaf(const Coord& xyz) const;
541  const LeafNodeType* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
543 
545  template<typename ArrayT> void getNodes(ArrayT& array) { mRoot.getNodes(array); }
568  template<typename ArrayT> void getNodes(ArrayT& array) const { mRoot.getNodes(array); }
570 
594  template<typename ArrayT>
595  void stealNodes(ArrayT& array) { mRoot.stealNodes(array); }
596  template<typename ArrayT>
597  void stealNodes(ArrayT& array, const ValueType& value, bool state)
598  {
599  mRoot.stealNodes(array, value, state);
600  }
601 
602  //
603  // Aux methods
604  //
607  bool empty() const { return mRoot.empty(); }
608 
610  void clear() { this->clearAllAccessors(); mRoot.clear(); }
611 
613  void clearAllAccessors();
614 
616  void attachAccessor(ValueAccessorBase<Tree, true>&) const;
619  void attachAccessor(ValueAccessorBase<const Tree, true>&) const;
621 
623  void attachAccessor(ValueAccessorBase<Tree, false>&) const {}
627 
629  void releaseAccessor(ValueAccessorBase<Tree, true>&) const;
631  void releaseAccessor(ValueAccessorBase<const Tree, true>&) const;
633 
635  void releaseAccessor(ValueAccessorBase<Tree, false>&) const {}
639 
642  virtual Metadata::Ptr getBackgroundValue() const;
643 
649  const ValueType& background() const { return mRoot.background(); }
650 
652  virtual void getIndexRange(CoordBBox& bbox) const { mRoot.getIndexRange(bbox); }
653 
655  void voxelizeActiveTiles();
656 
664  void merge(Tree& other, MergePolicy = MERGE_ACTIVE_STATES);
665 
679  template<typename OtherRootNodeType>
680  void topologyUnion(const Tree<OtherRootNodeType>& other);
681 
695  template<typename OtherRootNodeType>
696  void topologyIntersection(const Tree<OtherRootNodeType>& other);
697 
708  template<typename OtherRootNodeType>
709  void topologyDifference(const Tree<OtherRootNodeType>& other);
710 
755  template<typename CombineOp>
756  void combine(Tree& other, CombineOp& op, bool prune = false);
757 #ifndef _MSC_VER
758  template<typename CombineOp>
759  void combine(Tree& other, const CombineOp& op, bool prune = false);
760 #endif
761 
800  template<typename ExtendedCombineOp>
801  void combineExtended(Tree& other, ExtendedCombineOp& op, bool prune = false);
802 #ifndef _MSC_VER
803  template<typename ExtendedCombineOp>
804  void combineExtended(Tree& other, const ExtendedCombineOp& op, bool prune = false);
805 #endif
806 
835  template<typename CombineOp, typename OtherTreeType /*= Tree*/>
836  void combine2(const Tree& a, const OtherTreeType& b, CombineOp& op, bool prune = false);
837 #ifndef _MSC_VER
838  template<typename CombineOp, typename OtherTreeType /*= Tree*/>
839  void combine2(const Tree& a, const OtherTreeType& b, const CombineOp& op, bool prune = false);
840 #endif
841 
915  template<typename ExtendedCombineOp, typename OtherTreeType /*= Tree*/>
916  void combine2Extended(const Tree& a, const OtherTreeType& b, ExtendedCombineOp& op,
917  bool prune = false);
918 #ifndef _MSC_VER
919  template<typename ExtendedCombineOp, typename OtherTreeType /*= Tree*/>
920  void combine2Extended(const Tree& a, const OtherTreeType& b, const ExtendedCombineOp&,
921  bool prune = false);
922 #endif
923 
964  template<typename BBoxOp> void visitActiveBBox(BBoxOp& op) const { mRoot.visitActiveBBox(op); }
965 
1019  template<typename VisitorOp> void visit(VisitorOp& op);
1020  template<typename VisitorOp> void visit(const VisitorOp& op);
1021 
1026  template<typename VisitorOp> void visit(VisitorOp& op) const;
1027  template<typename VisitorOp> void visit(const VisitorOp& op) const;
1028 
1076  template<typename OtherTreeType, typename VisitorOp>
1077  void visit2(OtherTreeType& other, VisitorOp& op);
1078  template<typename OtherTreeType, typename VisitorOp>
1079  void visit2(OtherTreeType& other, const VisitorOp& op);
1080 
1091  template<typename OtherTreeType, typename VisitorOp>
1092  void visit2(OtherTreeType& other, VisitorOp& op) const;
1093  template<typename OtherTreeType, typename VisitorOp>
1094  void visit2(OtherTreeType& other, const VisitorOp& op) const;
1095 
1096 
1097  //
1098  // Iteration
1099  //
1101  typename RootNodeType::ChildOnCIter beginRootChildren() const { return mRoot.cbeginChildOn(); }
1103  typename RootNodeType::ChildOnCIter cbeginRootChildren() const { return mRoot.cbeginChildOn(); }
1104  typename RootNodeType::ChildOnIter beginRootChildren() { return mRoot.beginChildOn(); }
1106 
1108  typename RootNodeType::ChildOffCIter beginRootTiles() const { return mRoot.cbeginChildOff(); }
1110  typename RootNodeType::ChildOffCIter cbeginRootTiles() const { return mRoot.cbeginChildOff(); }
1111  typename RootNodeType::ChildOffIter beginRootTiles() { return mRoot.beginChildOff(); }
1113 
1115  typename RootNodeType::ChildAllCIter beginRootDense() const { return mRoot.cbeginChildAll(); }
1117  typename RootNodeType::ChildAllCIter cbeginRootDense() const { return mRoot.cbeginChildAll(); }
1118  typename RootNodeType::ChildAllIter beginRootDense() { return mRoot.beginChildAll(); }
1120 
1121 
1127 
1133 
1135  NodeIter beginNode() { return NodeIter(*this); }
1137  NodeCIter beginNode() const { return NodeCIter(*this); }
1138  NodeCIter cbeginNode() const { return NodeCIter(*this); }
1140 
1142  LeafIter beginLeaf() { return LeafIter(*this); }
1144  LeafCIter beginLeaf() const { return LeafCIter(*this); }
1145  LeafCIter cbeginLeaf() const { return LeafCIter(*this); }
1147 
1154 
1156  ValueAllIter beginValueAll() { return ValueAllIter(*this); }
1158  ValueAllCIter beginValueAll() const { return ValueAllCIter(*this); }
1159  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(*this); }
1161 
1162  ValueOnIter beginValueOn() { return ValueOnIter(*this); }
1164  ValueOnCIter beginValueOn() const { return ValueOnCIter(*this); }
1165  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(*this); }
1167 
1168  ValueOffIter beginValueOff() { return ValueOffIter(*this); }
1170  ValueOffCIter beginValueOff() const { return ValueOffCIter(*this); }
1171  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(*this); }
1173 
1176  template<typename IterT> IterT begin();
1179  template<typename CIterT> CIterT cbegin() const;
1180 
1181 
1182 protected:
1183  typedef tbb::concurrent_hash_map<ValueAccessorBase<Tree, true>*, bool> AccessorRegistry;
1184  typedef tbb::concurrent_hash_map<ValueAccessorBase<const Tree, true>*, bool> ConstAccessorRegistry;
1185 
1186  // Disallow assignment of instances of this class.
1187  Tree& operator=(const Tree&);
1188 
1191  void releaseAllAccessors();
1192 
1193 
1194  //
1195  // Data members
1196  //
1197  RootNodeType mRoot; // root node of the tree
1198  mutable AccessorRegistry mAccessorRegistry;
1199  mutable ConstAccessorRegistry mConstAccessorRegistry;
1200 
1201  static tbb::atomic<const Name*> sTreeTypeName;
1202 }; // end of Tree class
1203 
1204 template<typename _RootNodeType>
1205 tbb::atomic<const Name*> Tree<_RootNodeType>::sTreeTypeName;
1206 
1207 
1212 template<typename T, Index N1=4, Index N2=3>
1213 struct Tree3 {
1215 };
1216 
1217 
1222 template<typename T, Index N1=5, Index N2=4, Index N3=3>
1223 struct Tree4 {
1225 };
1226 
1231 template<typename T, Index N1=6, Index N2=5, Index N3=4, Index N4=3>
1232 struct Tree5 {
1235 };
1236 
1237 
1239 
1240 
1241 inline void
1242 TreeBase::readTopology(std::istream& is, bool /*saveFloatAsHalf*/)
1243 {
1244  int32_t bufferCount;
1245  is.read(reinterpret_cast<char*>(&bufferCount), sizeof(int32_t));
1246  if (bufferCount != 1) OPENVDB_LOG_WARN("multi-buffer trees are no longer supported");
1247 }
1248 
1249 
1250 inline void
1251 TreeBase::writeTopology(std::ostream& os, bool /*saveFloatAsHalf*/) const
1252 {
1253  int32_t bufferCount = 1;
1254  os.write(reinterpret_cast<char*>(&bufferCount), sizeof(int32_t));
1255 }
1256 
1257 
1258 inline void
1259 TreeBase::print(std::ostream& os, int /*verboseLevel*/) const
1260 {
1261  os << " Tree Type: " << type()
1262  << " Active Voxel Count: " << activeVoxelCount() << std::endl
1263  << " Inactive Voxel Count: " << inactiveVoxelCount() << std::endl
1264  << " Leaf Node Count: " << leafCount() << std::endl
1265  << " Non-leaf Node Count: " << nonLeafCount() << std::endl;
1266 }
1267 
1268 
1270 
1271 
1272 //
1273 // Type traits for tree iterators
1274 //
1275 
1278 template<typename TreeT, typename IterT> struct TreeIterTraits;
1279 
1280 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOnIter> {
1281  static typename TreeT::RootNodeType::ChildOnIter begin(TreeT& tree) {
1282  return tree.beginRootChildren();
1283  }
1284 };
1285 
1286 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOnCIter> {
1287  static typename TreeT::RootNodeType::ChildOnCIter begin(const TreeT& tree) {
1288  return tree.cbeginRootChildren();
1289  }
1290 };
1291 
1292 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOffIter> {
1293  static typename TreeT::RootNodeType::ChildOffIter begin(TreeT& tree) {
1294  return tree.beginRootTiles();
1295  }
1296 };
1297 
1298 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOffCIter> {
1299  static typename TreeT::RootNodeType::ChildOffCIter begin(const TreeT& tree) {
1300  return tree.cbeginRootTiles();
1301  }
1302 };
1303 
1304 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildAllIter> {
1305  static typename TreeT::RootNodeType::ChildAllIter begin(TreeT& tree) {
1306  return tree.beginRootDense();
1307  }
1308 };
1309 
1310 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildAllCIter> {
1311  static typename TreeT::RootNodeType::ChildAllCIter begin(const TreeT& tree) {
1312  return tree.cbeginRootDense();
1313  }
1314 };
1315 
1316 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::NodeIter> {
1317  static typename TreeT::NodeIter begin(TreeT& tree) { return tree.beginNode(); }
1318 };
1319 
1320 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::NodeCIter> {
1321  static typename TreeT::NodeCIter begin(const TreeT& tree) { return tree.cbeginNode(); }
1322 };
1323 
1324 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::LeafIter> {
1325  static typename TreeT::LeafIter begin(TreeT& tree) { return tree.beginLeaf(); }
1326 };
1327 
1328 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::LeafCIter> {
1329  static typename TreeT::LeafCIter begin(const TreeT& tree) { return tree.cbeginLeaf(); }
1330 };
1331 
1332 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOnIter> {
1333  static typename TreeT::ValueOnIter begin(TreeT& tree) { return tree.beginValueOn(); }
1334 };
1335 
1336 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOnCIter> {
1337  static typename TreeT::ValueOnCIter begin(const TreeT& tree) { return tree.cbeginValueOn(); }
1338 };
1339 
1340 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOffIter> {
1341  static typename TreeT::ValueOffIter begin(TreeT& tree) { return tree.beginValueOff(); }
1342 };
1343 
1344 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOffCIter> {
1345  static typename TreeT::ValueOffCIter begin(const TreeT& tree) { return tree.cbeginValueOff(); }
1346 };
1347 
1348 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueAllIter> {
1349  static typename TreeT::ValueAllIter begin(TreeT& tree) { return tree.beginValueAll(); }
1350 };
1351 
1352 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueAllCIter> {
1353  static typename TreeT::ValueAllCIter begin(const TreeT& tree) { return tree.cbeginValueAll(); }
1354 };
1355 
1356 
1357 template<typename RootNodeType>
1358 template<typename IterT>
1359 inline IterT
1361 {
1362  return TreeIterTraits<Tree, IterT>::begin(*this);
1363 }
1364 
1365 
1366 template<typename RootNodeType>
1367 template<typename IterT>
1368 inline IterT
1370 {
1371  return TreeIterTraits<Tree, IterT>::begin(*this);
1372 }
1373 
1374 
1376 
1377 
1378 template<typename RootNodeType>
1379 void
1380 Tree<RootNodeType>::readTopology(std::istream& is, bool saveFloatAsHalf)
1381 {
1382  this->clearAllAccessors();
1383  TreeBase::readTopology(is, saveFloatAsHalf);
1384  mRoot.readTopology(is, saveFloatAsHalf);
1385 }
1386 
1387 
1388 template<typename RootNodeType>
1389 void
1390 Tree<RootNodeType>::writeTopology(std::ostream& os, bool saveFloatAsHalf) const
1391 {
1392  TreeBase::writeTopology(os, saveFloatAsHalf);
1393  mRoot.writeTopology(os, saveFloatAsHalf);
1394 }
1395 
1396 
1397 template<typename RootNodeType>
1398 inline void
1399 Tree<RootNodeType>::readBuffers(std::istream &is, bool saveFloatAsHalf)
1400 {
1401  this->clearAllAccessors();
1402  mRoot.readBuffers(is, saveFloatAsHalf);
1403 }
1404 
1405 
1406 #ifndef OPENVDB_2_ABI_COMPATIBLE
1407 
1408 template<typename RootNodeType>
1409 inline void
1410 Tree<RootNodeType>::readBuffers(std::istream &is, const CoordBBox& bbox, bool saveFloatAsHalf)
1411 {
1412  this->clearAllAccessors();
1413  mRoot.readBuffers(is, bbox, saveFloatAsHalf);
1414 }
1415 
1416 
1417 template<typename RootNodeType>
1418 inline void
1420 {
1421  for (LeafCIter it = this->cbeginLeaf(); it; ++it) {
1422  // Retrieving the value of a leaf voxel forces loading of the leaf node's voxel buffer.
1423  it->getValue(Index(0));
1424  }
1425 }
1426 
1427 #endif // !OPENVDB_2_ABI_COMPATIBLE
1428 
1429 
1430 template<typename RootNodeType>
1431 inline void
1432 Tree<RootNodeType>::writeBuffers(std::ostream &os, bool saveFloatAsHalf) const
1433 {
1434  mRoot.writeBuffers(os, saveFloatAsHalf);
1435 }
1436 
1437 
1439 
1440 
1441 template<typename RootNodeType>
1442 inline void
1444 {
1445  typename AccessorRegistry::accessor a;
1446  mAccessorRegistry.insert(a, &accessor);
1447 }
1448 
1449 
1450 template<typename RootNodeType>
1451 inline void
1453 {
1454  typename ConstAccessorRegistry::accessor a;
1455  mConstAccessorRegistry.insert(a, &accessor);
1456 }
1457 
1458 
1459 template<typename RootNodeType>
1460 inline void
1462 {
1463  mAccessorRegistry.erase(&accessor);
1464 }
1465 
1466 
1467 template<typename RootNodeType>
1468 inline void
1470 {
1471  mConstAccessorRegistry.erase(&accessor);
1472 }
1473 
1474 
1475 template<typename RootNodeType>
1476 inline void
1478 {
1479  for (typename AccessorRegistry::iterator it = mAccessorRegistry.begin();
1480  it != mAccessorRegistry.end(); ++it)
1481  {
1482  if (it->first) it->first->clear();
1483  }
1484 
1485  for (typename ConstAccessorRegistry::iterator it = mConstAccessorRegistry.begin();
1486  it != mConstAccessorRegistry.end(); ++it)
1487  {
1488  if (it->first) it->first->clear();
1489  }
1490 }
1491 
1492 
1493 template<typename RootNodeType>
1494 inline void
1496 {
1497  mAccessorRegistry.erase(NULL);
1498  for (typename AccessorRegistry::iterator it = mAccessorRegistry.begin();
1499  it != mAccessorRegistry.end(); ++it)
1500  {
1501  it->first->release();
1502  }
1503  mAccessorRegistry.clear();
1504 
1505  mAccessorRegistry.erase(NULL);
1506  for (typename ConstAccessorRegistry::iterator it = mConstAccessorRegistry.begin();
1507  it != mConstAccessorRegistry.end(); ++it)
1508  {
1509  it->first->release();
1510  }
1511  mConstAccessorRegistry.clear();
1512 }
1513 
1514 
1516 
1517 
1518 template<typename RootNodeType>
1519 inline const typename RootNodeType::ValueType&
1520 Tree<RootNodeType>::getValue(const Coord& xyz) const
1521 {
1522  return mRoot.getValue(xyz);
1523 }
1524 
1525 
1526 template<typename RootNodeType>
1527 template<typename AccessT>
1528 inline const typename RootNodeType::ValueType&
1529 Tree<RootNodeType>::getValue(const Coord& xyz, AccessT& accessor) const
1530 {
1531  return accessor.getValue(xyz);
1532 }
1533 
1534 
1535 template<typename RootNodeType>
1536 inline int
1537 Tree<RootNodeType>::getValueDepth(const Coord& xyz) const
1538 {
1539  return mRoot.getValueDepth(xyz);
1540 }
1541 
1542 
1543 template<typename RootNodeType>
1544 inline void
1546 {
1547  mRoot.setValueOff(xyz);
1548 }
1549 
1550 
1551 template<typename RootNodeType>
1552 inline void
1553 Tree<RootNodeType>::setValueOff(const Coord& xyz, const ValueType& value)
1554 {
1555  mRoot.setValueOff(xyz, value);
1556 }
1557 
1558 
1559 template<typename RootNodeType>
1560 inline void
1561 Tree<RootNodeType>::setActiveState(const Coord& xyz, bool on)
1562 {
1563  mRoot.setActiveState(xyz, on);
1564 }
1565 
1566 
1567 template<typename RootNodeType>
1568 inline void
1569 Tree<RootNodeType>::setValue(const Coord& xyz, const ValueType& value)
1570 {
1571  mRoot.setValueOn(xyz, value);
1572 }
1573 
1574 template<typename RootNodeType>
1575 inline void
1576 Tree<RootNodeType>::setValueOnly(const Coord& xyz, const ValueType& value)
1577 {
1578  mRoot.setValueOnly(xyz, value);
1579 }
1580 
1581 template<typename RootNodeType>
1582 template<typename AccessT>
1583 inline void
1584 Tree<RootNodeType>::setValue(const Coord& xyz, const ValueType& value, AccessT& accessor)
1585 {
1586  accessor.setValue(xyz, value);
1587 }
1588 
1589 
1590 template<typename RootNodeType>
1591 inline void
1593 {
1594  mRoot.setActiveState(xyz, true);
1595 }
1596 
1597 
1598 template<typename RootNodeType>
1599 inline void
1600 Tree<RootNodeType>::setValueOn(const Coord& xyz, const ValueType& value)
1601 {
1602  mRoot.setValueOn(xyz, value);
1603 }
1604 
1605 
1606 template<typename RootNodeType>
1607 template<typename ModifyOp>
1608 inline void
1609 Tree<RootNodeType>::modifyValue(const Coord& xyz, const ModifyOp& op)
1610 {
1611  mRoot.modifyValue(xyz, op);
1612 }
1613 
1614 
1615 template<typename RootNodeType>
1616 template<typename ModifyOp>
1617 inline void
1618 Tree<RootNodeType>::modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1619 {
1620  mRoot.modifyValueAndActiveState(xyz, op);
1621 }
1622 
1623 
1624 template<typename RootNodeType>
1625 inline bool
1626 Tree<RootNodeType>::probeValue(const Coord& xyz, ValueType& value) const
1627 {
1628  return mRoot.probeValue(xyz, value);
1629 }
1630 
1631 
1633 
1634 
1635 template<typename RootNodeType>
1636 inline void
1637 Tree<RootNodeType>::addTile(Index level, const Coord& xyz,
1638  const ValueType& value, bool active)
1639 {
1640  mRoot.addTile(level, xyz, value, active);
1641 }
1642 
1643 
1644 template<typename RootNodeType>
1645 template<typename NodeT>
1646 inline NodeT*
1647 Tree<RootNodeType>::stealNode(const Coord& xyz, const ValueType& value, bool active)
1648 {
1649  this->clearAllAccessors();
1650  return mRoot.template stealNode<NodeT>(xyz, value, active);
1651 }
1652 
1653 
1654 template<typename RootNodeType>
1655 inline typename RootNodeType::LeafNodeType*
1657 {
1658  return mRoot.touchLeaf(xyz);
1659 }
1660 
1661 
1662 template<typename RootNodeType>
1663 inline typename RootNodeType::LeafNodeType*
1665 {
1666  return mRoot.probeLeaf(xyz);
1667 }
1668 
1669 
1670 template<typename RootNodeType>
1671 inline const typename RootNodeType::LeafNodeType*
1672 Tree<RootNodeType>::probeConstLeaf(const Coord& xyz) const
1673 {
1674  return mRoot.probeConstLeaf(xyz);
1675 }
1676 
1677 
1678 template<typename RootNodeType>
1679 template<typename NodeType>
1680 inline NodeType*
1682 {
1683  return mRoot.template probeNode<NodeType>(xyz);
1684 }
1685 
1686 
1687 template<typename RootNodeType>
1688 template<typename NodeType>
1689 inline const NodeType*
1690 Tree<RootNodeType>::probeNode(const Coord& xyz) const
1691 {
1692  return this->template probeConstNode<NodeType>(xyz);
1693 }
1694 
1695 
1696 template<typename RootNodeType>
1697 template<typename NodeType>
1698 inline const NodeType*
1699 Tree<RootNodeType>::probeConstNode(const Coord& xyz) const
1700 {
1701  return mRoot.template probeConstNode<NodeType>(xyz);
1702 }
1703 
1704 
1706 
1707 
1708 template<typename RootNodeType>
1709 inline void
1710 Tree<RootNodeType>::clip(const CoordBBox& bbox)
1711 {
1712  this->clearAllAccessors();
1713  return mRoot.clip(bbox);
1714 }
1715 
1716 
1717 #ifndef OPENVDB_2_ABI_COMPATIBLE
1718 template<typename RootNodeType>
1719 inline void
1721 {
1722  this->clearAllAccessors();
1723  for (LeafIter it = this->beginLeaf(); it; ) {
1724  const LeafNodeType* leaf = it.getLeaf();
1725  ++it; // advance the iterator before deleting the leaf node
1726  if (!leaf->isAllocated()) {
1727  this->addTile(/*level=*/0, leaf->origin(), this->background(), /*active=*/false);
1728  }
1729  }
1730 }
1731 #endif
1732 
1733 
1734 template<typename RootNodeType>
1735 inline void
1736 Tree<RootNodeType>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1737 {
1738  this->clearAllAccessors();
1739  return mRoot.fill(bbox, value, active);
1740 }
1741 
1742 
1743 template<typename RootNodeType>
1746 {
1747  Metadata::Ptr result;
1748  if (Metadata::isRegisteredType(valueType())) {
1749  typedef TypedMetadata<ValueType> MetadataT;
1750  result = Metadata::createMetadata(valueType());
1751  if (result->typeName() == MetadataT::staticTypeName()) {
1752  MetadataT* m = static_cast<MetadataT*>(result.get());
1753  m->value() = mRoot.background();
1754  }
1755  }
1756  return result;
1757 }
1758 
1759 
1761 
1762 
1763 template<typename RootNodeType>
1764 inline void
1766 {
1767  this->clearAllAccessors();
1768  mRoot.voxelizeActiveTiles();
1769 }
1770 
1771 
1772 template<typename RootNodeType>
1773 inline void
1775 {
1776  this->clearAllAccessors();
1777  other.clearAllAccessors();
1778  switch (policy) {
1779  case MERGE_ACTIVE_STATES:
1780  mRoot.template merge<MERGE_ACTIVE_STATES>(other.mRoot); break;
1781  case MERGE_NODES:
1782  mRoot.template merge<MERGE_NODES>(other.mRoot); break;
1784  mRoot.template merge<MERGE_ACTIVE_STATES_AND_NODES>(other.mRoot); break;
1785  }
1786 }
1787 
1788 
1789 template<typename RootNodeType>
1790 template<typename OtherRootNodeType>
1791 inline void
1793 {
1794  this->clearAllAccessors();
1795  mRoot.topologyUnion(other.root());
1796 }
1797 
1798 template<typename RootNodeType>
1799 template<typename OtherRootNodeType>
1800 inline void
1802 {
1803  this->clearAllAccessors();
1804  mRoot.topologyIntersection(other.root());
1805 }
1806 
1807 template<typename RootNodeType>
1808 template<typename OtherRootNodeType>
1809 inline void
1811 {
1812  this->clearAllAccessors();
1813  mRoot.topologyDifference(other.root());
1814 }
1815 
1817 
1818 
1821 template<typename AValueT, typename CombineOp, typename BValueT = AValueT>
1823 {
1824  CombineOpAdapter(CombineOp& _op): op(_op) {}
1825 
1827  op(args.a(), args.b(), args.result());
1828  }
1829 
1830  CombineOp& op;
1831 };
1832 
1833 
1834 template<typename RootNodeType>
1835 template<typename CombineOp>
1836 inline void
1837 Tree<RootNodeType>::combine(Tree& other, CombineOp& op, bool prune)
1838 {
1840  this->combineExtended(other, extendedOp, prune);
1841 }
1842 
1843 
1846 #ifndef _MSC_VER
1847 template<typename RootNodeType>
1848 template<typename CombineOp>
1849 inline void
1850 Tree<RootNodeType>::combine(Tree& other, const CombineOp& op, bool prune)
1851 {
1853  this->combineExtended(other, extendedOp, prune);
1854 }
1855 #endif
1856 
1857 
1858 template<typename RootNodeType>
1859 template<typename ExtendedCombineOp>
1860 inline void
1861 Tree<RootNodeType>::combineExtended(Tree& other, ExtendedCombineOp& op, bool prune)
1862 {
1863  this->clearAllAccessors();
1864  mRoot.combine(other.root(), op, prune);
1865 }
1866 
1867 
1870 #ifndef _MSC_VER
1871 template<typename RootNodeType>
1872 template<typename ExtendedCombineOp>
1873 inline void
1874 Tree<RootNodeType>::combineExtended(Tree& other, const ExtendedCombineOp& op, bool prune)
1875 {
1876  this->clearAllAccessors();
1877  mRoot.template combine<const ExtendedCombineOp>(other.mRoot, op, prune);
1878 }
1879 #endif
1880 
1881 
1882 template<typename RootNodeType>
1883 template<typename CombineOp, typename OtherTreeType>
1884 inline void
1885 Tree<RootNodeType>::combine2(const Tree& a, const OtherTreeType& b, CombineOp& op, bool prune)
1886 {
1888  this->combine2Extended(a, b, extendedOp, prune);
1889 }
1890 
1891 
1894 #ifndef _MSC_VER
1895 template<typename RootNodeType>
1896 template<typename CombineOp, typename OtherTreeType>
1897 inline void
1898 Tree<RootNodeType>::combine2(const Tree& a, const OtherTreeType& b, const CombineOp& op, bool prune)
1899 {
1901  this->combine2Extended(a, b, extendedOp, prune);
1902 }
1903 #endif
1904 
1905 
1906 template<typename RootNodeType>
1907 template<typename ExtendedCombineOp, typename OtherTreeType>
1908 inline void
1909 Tree<RootNodeType>::combine2Extended(const Tree& a, const OtherTreeType& b,
1910  ExtendedCombineOp& op, bool prune)
1911 {
1912  this->clearAllAccessors();
1913  mRoot.combine2(a.root(), b.root(), op, prune);
1914 }
1915 
1916 
1920 #ifndef _MSC_VER
1921 template<typename RootNodeType>
1922 template<typename ExtendedCombineOp, typename OtherTreeType>
1923 inline void
1924 Tree<RootNodeType>::combine2Extended(const Tree& a, const OtherTreeType& b,
1925  const ExtendedCombineOp& op, bool prune)
1926 {
1927  this->clearAllAccessors();
1928  mRoot.template combine2<const ExtendedCombineOp>(a.root(), b.root(), op, prune);
1929 }
1930 #endif
1931 
1932 
1934 
1935 
1936 template<typename RootNodeType>
1937 template<typename VisitorOp>
1938 inline void
1940 {
1941  this->clearAllAccessors();
1942  mRoot.template visit<VisitorOp>(op);
1943 }
1944 
1945 
1946 template<typename RootNodeType>
1947 template<typename VisitorOp>
1948 inline void
1949 Tree<RootNodeType>::visit(VisitorOp& op) const
1950 {
1951  mRoot.template visit<VisitorOp>(op);
1952 }
1953 
1954 
1957 template<typename RootNodeType>
1958 template<typename VisitorOp>
1959 inline void
1960 Tree<RootNodeType>::visit(const VisitorOp& op)
1961 {
1962  this->clearAllAccessors();
1963  mRoot.template visit<const VisitorOp>(op);
1964 }
1965 
1966 
1969 template<typename RootNodeType>
1970 template<typename VisitorOp>
1971 inline void
1972 Tree<RootNodeType>::visit(const VisitorOp& op) const
1973 {
1974  mRoot.template visit<const VisitorOp>(op);
1975 }
1976 
1977 
1979 
1980 
1981 template<typename RootNodeType>
1982 template<typename OtherTreeType, typename VisitorOp>
1983 inline void
1984 Tree<RootNodeType>::visit2(OtherTreeType& other, VisitorOp& op)
1985 {
1986  this->clearAllAccessors();
1987  typedef typename OtherTreeType::RootNodeType OtherRootNodeType;
1988  mRoot.template visit2<OtherRootNodeType, VisitorOp>(other.root(), op);
1989 }
1990 
1991 
1992 template<typename RootNodeType>
1993 template<typename OtherTreeType, typename VisitorOp>
1994 inline void
1995 Tree<RootNodeType>::visit2(OtherTreeType& other, VisitorOp& op) const
1996 {
1997  typedef typename OtherTreeType::RootNodeType OtherRootNodeType;
1998  mRoot.template visit2<OtherRootNodeType, VisitorOp>(other.root(), op);
1999 }
2000 
2001 
2004 template<typename RootNodeType>
2005 template<typename OtherTreeType, typename VisitorOp>
2006 inline void
2007 Tree<RootNodeType>::visit2(OtherTreeType& other, const VisitorOp& op)
2008 {
2009  this->clearAllAccessors();
2010  typedef typename OtherTreeType::RootNodeType OtherRootNodeType;
2011  mRoot.template visit2<OtherRootNodeType, const VisitorOp>(other.root(), op);
2012 }
2013 
2014 
2017 template<typename RootNodeType>
2018 template<typename OtherTreeType, typename VisitorOp>
2019 inline void
2020 Tree<RootNodeType>::visit2(OtherTreeType& other, const VisitorOp& op) const
2021 {
2022  typedef typename OtherTreeType::RootNodeType OtherRootNodeType;
2023  mRoot.template visit2<OtherRootNodeType, const VisitorOp>(other.root(), op);
2024 }
2025 
2026 
2028 
2029 
2030 template<typename RootNodeType>
2031 inline const Name&
2033 {
2034  if (sTreeTypeName == NULL) {
2035  std::vector<Index> dims;
2036  Tree::getNodeLog2Dims(dims);
2037  std::ostringstream ostr;
2038  ostr << "Tree_" << typeNameAsString<ValueType>();
2039  for (size_t i = 1, N = dims.size(); i < N; ++i) { // start from 1 to skip the RootNode
2040  ostr << "_" << dims[i];
2041  }
2042  Name* s = new Name(ostr.str());
2043  if (sTreeTypeName.compare_and_swap(s, NULL) != NULL) delete s;
2044  }
2045  return *sTreeTypeName;
2046 }
2047 
2048 
2049 template<typename RootNodeType>
2050 template<typename OtherRootNodeType>
2051 inline bool
2053 {
2054  return mRoot.hasSameTopology(other.root());
2055 }
2056 
2057 
2058 template<typename RootNodeType>
2059 Index64
2061 {
2062  Coord dim(0, 0, 0);
2063  this->evalActiveVoxelDim(dim);
2064  const Index64
2065  totalVoxels = dim.x() * dim.y() * dim.z(),
2066  activeVoxels = this->activeVoxelCount();
2067  assert(totalVoxels >= activeVoxels);
2068  return totalVoxels - activeVoxels;
2069 }
2070 
2071 
2072 template<typename RootNodeType>
2073 inline bool
2075 {
2076  bbox.reset(); // default invalid bbox
2077 
2078  if (this->empty()) return false; // empty
2079 
2080  mRoot.evalActiveBoundingBox(bbox, false);
2081 
2082  return true;// not empty
2083 }
2084 
2085 template<typename RootNodeType>
2086 inline bool
2088 {
2089  bbox.reset(); // default invalid bbox
2090 
2091  if (this->empty()) return false; // empty
2092 
2093  mRoot.evalActiveBoundingBox(bbox, true);
2094 
2095  return true;// not empty
2096 }
2097 
2098 
2099 template<typename RootNodeType>
2100 inline bool
2102 {
2103  CoordBBox bbox;
2104  bool notEmpty = this->evalActiveVoxelBoundingBox(bbox);
2105  dim = bbox.extents();
2106  return notEmpty;
2107 }
2108 
2109 
2110 template<typename RootNodeType>
2111 inline bool
2113 {
2114  CoordBBox bbox;
2115  bool notEmpty = this->evalLeafBoundingBox(bbox);
2116  dim = bbox.extents();
2117  return notEmpty;
2118 }
2119 
2120 
2121 template<typename RootNodeType>
2122 inline void
2123 Tree<RootNodeType>::evalMinMax(ValueType& minVal, ValueType& maxVal) const
2124 {
2125  minVal = maxVal = zeroVal<ValueType>();
2126  if (ValueOnCIter iter = this->cbeginValueOn()) {
2127  minVal = maxVal = *iter;
2128  for (++iter; iter; ++iter) {
2129  const ValueType& val = *iter;
2130  if (val < minVal) minVal = val;
2131  if (val > maxVal) maxVal = val;
2132  }
2133  }
2134 }
2135 
2136 
2137 template<typename RootNodeType>
2138 inline void
2139 Tree<RootNodeType>::getNodeLog2Dims(std::vector<Index>& dims)
2140 {
2141  dims.clear();
2142  RootNodeType::getNodeLog2Dims(dims);
2143 }
2144 
2145 
2146 template<typename RootNodeType>
2147 inline void
2148 Tree<RootNodeType>::print(std::ostream& os, int verboseLevel) const
2149 {
2150  if (verboseLevel <= 0) return;
2151 
2153  struct OnExit {
2154  std::ostream& os;
2155  std::streamsize savedPrecision;
2156  OnExit(std::ostream& _os): os(_os), savedPrecision(os.precision()) {}
2157  ~OnExit() { os.precision(savedPrecision); }
2158  };
2159  OnExit restorePrecision(os);
2160 
2161  std::vector<Index> dims;
2162  Tree::getNodeLog2Dims(dims);
2163 
2164  os << "Information about Tree:\n"
2165  << " Type: " << this->type() << "\n";
2166 
2167  os << " Configuration:\n";
2168 
2169  if (verboseLevel <= 1) {
2170  // Print node types and sizes.
2171  os << " Root(" << mRoot.getTableSize() << ")";
2172  if (dims.size() > 1) {
2173  for (size_t i = 1, N = dims.size() - 1; i < N; ++i) {
2174  os << ", Internal(" << (1 << dims[i]) << "^3)";
2175  }
2176  os << ", Leaf(" << (1 << *dims.rbegin()) << "^3)\n";
2177  }
2178  os << " Background value: " << mRoot.background() << "\n";
2179  return;
2180  }
2181 
2182  // The following is tree information that is expensive to extract.
2183 
2184  ValueType minVal = zeroVal<ValueType>(), maxVal = zeroVal<ValueType>();
2185  if (verboseLevel > 3) {
2186  // This forces loading of all non-resident nodes.
2187  this->evalMinMax(minVal, maxVal);
2188  }
2189 
2190  std::vector<Index64> nodeCount(dims.size());
2191 #ifndef OPENVDB_2_ABI_COMPATIBLE
2192  Index64 unallocatedLeafCount = 0;
2193 #endif
2194  for (NodeCIter it = cbeginNode(); it; ++it) {
2195  ++(nodeCount[it.getDepth()]);
2196 
2197 #ifndef OPENVDB_2_ABI_COMPATIBLE
2198  if (it.getLevel() == 0) {
2199  const LeafNodeType* leaf = NULL;
2200  it.getNode(leaf);
2201  if (leaf && !leaf->isAllocated()) ++unallocatedLeafCount;
2202  }
2203 #endif
2204  }
2205  Index64 totalNodeCount = 0;
2206  for (size_t i = 0; i < nodeCount.size(); ++i) totalNodeCount += nodeCount[i];
2207 
2208  // Print node types, counts and sizes.
2209  os << " Root(1 x " << mRoot.getTableSize() << ")";
2210  if (dims.size() > 1) {
2211  for (size_t i = 1, N = dims.size() - 1; i < N; ++i) {
2212  os << ", Internal(" << util::formattedInt(nodeCount[i]);
2213  os << " x " << (1 << dims[i]) << "^3)";
2214  }
2215  os << ", Leaf(" << util::formattedInt(*nodeCount.rbegin());
2216  os << " x " << (1 << *dims.rbegin()) << "^3)\n";
2217  }
2218  os << " Background value: " << mRoot.background() << "\n";
2219 
2220  // Statistics of topology and values
2221 
2222  if (verboseLevel > 3) {
2223  os << " Min value: " << minVal << "\n";
2224  os << " Max value: " << maxVal << "\n";
2225  }
2226 
2227  const uint64_t
2228  leafCount = *nodeCount.rbegin(),
2229  numActiveVoxels = this->activeVoxelCount(),
2230  numActiveLeafVoxels = this->activeLeafVoxelCount();
2231 
2232  os << " Number of active voxels: " << util::formattedInt(numActiveVoxels) << "\n";
2233 
2234  Coord dim(0, 0, 0);
2235  uint64_t totalVoxels = 0;
2236  if (numActiveVoxels) { // nonempty
2237  CoordBBox bbox;
2238  this->evalActiveVoxelBoundingBox(bbox);
2239  dim = bbox.extents();
2240  totalVoxels = dim.x() * uint64_t(dim.y()) * dim.z();
2241 
2242  os << " Bounding box of active voxels: " << bbox << "\n";
2243  os << " Dimensions of active voxels: "
2244  << dim[0] << " x " << dim[1] << " x " << dim[2] << "\n";
2245 
2246  const double activeRatio = (100.0 * double(numActiveVoxels)) / double(totalVoxels);
2247  os << " Percentage of active voxels: " << std::setprecision(3) << activeRatio << "%\n";
2248 
2249  if (leafCount > 0) {
2250  const double fillRatio = (100.0 * double(numActiveLeafVoxels))
2251  / (double(leafCount) * double(LeafNodeType::NUM_VOXELS));
2252  os << " Average leaf node fill ratio: " << fillRatio << "%\n";
2253  }
2254 
2255 #ifndef OPENVDB_2_ABI_COMPATIBLE
2256  if (verboseLevel > 2) {
2257  os << " Number of unallocated nodes: "
2258  << util::formattedInt(unallocatedLeafCount) << " ("
2259  << (100.0 * double(unallocatedLeafCount) / double(totalNodeCount)) << "%)\n";
2260  }
2261 #endif
2262  } else {
2263  os << " Tree is empty!\n";
2264  }
2265  os << std::flush;
2266 
2267  if (verboseLevel == 2) return;
2268 
2269  // Memory footprint in bytes
2270  const uint64_t
2271  actualMem = this->memUsage(),
2272  denseMem = sizeof(ValueType) * totalVoxels,
2273  voxelsMem = sizeof(ValueType) * numActiveLeafVoxels;
2275 
2276  os << "Memory footprint:\n";
2277  util::printBytes(os, actualMem, " Actual: ");
2278  util::printBytes(os, voxelsMem, " Active leaf voxels: ");
2279 
2280  if (numActiveVoxels) {
2281  util::printBytes(os, denseMem, " Dense equivalent: ");
2282  os << " Actual footprint is " << (100.0 * double(actualMem) / double(denseMem))
2283  << "% of an equivalent dense volume\n";
2284  os << " Leaf voxel footprint is " << (100.0 * double(voxelsMem) / double(actualMem))
2285  << "% of actual footprint\n";
2286  }
2287 }
2288 
2289 } // namespace tree
2290 } // namespace OPENVDB_VERSION_NAME
2291 } // namespace openvdb
2292 
2293 #endif // OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
2294 
2295 // Copyright (c) 2012-2015 DreamWorks Animation LLC
2296 // All rights reserved. This software is distributed under the
2297 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
static bool isRegisteredType(const Name &typeName)
Return true if the given type is known by the metadata type registry.
Tree5<T, N1, N2, N3, N4>::Type is the type of a five-level tree (Root, Internal, Internal, Internal, Leaf) with value type T and internal and leaf node log dimensions N1, N2, N3 and N4, respectively.
Definition: Tree.h:1232
virtual void readTopology(std::istream &, bool saveFloatAsHalf=false)
Read the tree topology from a stream.
Definition: Tree.h:1242
virtual Name valueType() const
Return the name of the type of a voxel&#39;s value (e.g., "float" or "vec3d")
Definition: Tree.h:292
boost::shared_ptr< Metadata > Ptr
Definition: metadata/Metadata.h:52
virtual Index64 activeVoxelCount() const
Return the total number of active voxels.
Definition: Tree.h:373
virtual ~TreeBase()
Definition: Tree.h:70
Templated metadata class to hold specific types.
Definition: metadata/Metadata.h:139
virtual Index64 inactiveLeafVoxelCount() const
Return the number of inactive voxels stored in leaf nodes.
Definition: Tree.h:371
Index32 Index
Definition: Types.h:58
#define OPENVDB_API
Helper macros for defining library symbol visibility.
Definition: Platform.h:195
TreeBase()
Definition: Tree.h:69
const BValueType & b() const
Get the B input value.
Definition: Types.h:331
virtual const Name & type() const
Return the name of this type of tree.
Definition: Tree.h:297
boost::shared_ptr< const TreeBase > ConstPtr
Definition: Tree.h:67
Tree(const OtherTreeType &other, const ValueType &background, TopologyCopy)
Topology copy constructor from a tree of a different type.
Definition: Tree.h:277
virtual Index64 memUsage() const
Return the total amount of memory in bytes occupied by this tree.
Definition: Tree.h:153
virtual Index64 memUsage() const
Return the total amount of memory in bytes occupied by this tree.
Definition: Tree.h:382
Base class for tree-traversal iterators over tile and voxel values.
Definition: TreeIterator.h:658
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOnIter > ValueOnIter
Definition: Tree.h:1150
static TreeT::ValueOnIter begin(TreeT &tree)
Definition: Tree.h:1333
bool operator!=(const Tree &) const
Definition: Tree.h:300
Tree(const Tree &other)
Deep copy constructor.
Definition: Tree.h:230
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOnCIter > ValueOnCIter
Definition: Tree.h:1151
tbb::concurrent_hash_map< ValueAccessorBase< Tree, true > *, bool > AccessorRegistry
Definition: Tree.h:1183
void clear()
Remove all tiles from this tree and all nodes other than the root node.
Definition: Tree.h:610
RootNodeType::ChildAllCIter cbeginRootDense() const
Return an iterator over all entries of the root node&#39;s table.
Definition: Tree.h:1117
TreeValueIteratorBase< Tree, typename RootNodeType::ValueAllIter > ValueAllIter
Definition: Tree.h:1148
Tree< RootNode< InternalNode< InternalNode< LeafNode< T, N3 >, N2 >, N1 > > > Type
Definition: Tree.h:1224
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOffIter > ValueOffIter
Definition: Tree.h:1152
ValueOnCIter cbeginValueOn() const
Return an iterator over active values (tile and voxel) across all nodes.
Definition: Tree.h:1165
bool hasActiveTiles() const
Return true if this tree has any active tiles.
Definition: Tree.h:469
bool isValueOn(const Coord &xyz) const
Return true if the value at the given coordinates is active.
Definition: Tree.h:465
void clearAllAccessors()
Clear all registered accessors.
Definition: Tree.h:1477
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
void releaseAccessor(ValueAccessorBase< const Tree, false > &) const
Dummy implementations.
Definition: Tree.h:637
MergePolicy
Definition: Types.h:257
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:1537
ValueOffCIter beginValueOff() const
Return an iterator over inactive values (tile and voxel) across all nodes.
Definition: Tree.h:1170
RootNodeType::ChildAllIter beginRootDense()
Return an iterator over all entries of the root node&#39;s table.
Definition: Tree.h:1118
virtual void writeTopology(std::ostream &, bool saveFloatAsHalf=false) const
Write the tree topology to a stream.
Definition: Tree.h:1251
void visitActiveBBox(BBoxOp &op) const
Use sparse traversal to call the given functor with bounding box information for all active tiles and...
Definition: Tree.h:964
virtual Index32 nonLeafCount() const
Return the number of non-leaf nodes.
Definition: Tree.h:367
uint32_t Index32
Definition: Types.h:56
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return NULL.
Definition: Tree.h:1672
OPENVDB_STATIC_SPECIALIZATION GridType::Ptr clip(const GridType &grid, const BBoxd &)
Clip the given grid against a world-space bounding box and return a new grid containing the result...
Definition: Clip.h:355
boost::shared_ptr< const Tree > ConstPtr
Definition: Tree.h:207
static TreeT::RootNodeType::ChildAllCIter begin(const TreeT &tree)
Definition: Tree.h:1311
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one that preserves the values and active states of all voxels.
Definition: Tree.h:1656
TreeIterTraits provides, for all tree iterators, a begin(tree) function that returns an iterator over...
Definition: Tree.h:1278
static TreeT::NodeCIter begin(const TreeT &tree)
Definition: Tree.h:1321
bool isValueOff(const Coord &xyz) const
Return true if the value at the given coordinates is inactive.
Definition: Tree.h:467
LeafIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > LeafCIter
Iterator over all leaf nodes in this tree.
Definition: Tree.h:1131
boost::shared_ptr< TreeBase > Ptr
Definition: Tree.h:66
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:1609
NodeCIter cbeginNode() const
Return an iterator over all nodes in this tree.
Definition: Tree.h:1138
FormattedInt< IntT > formattedInt(IntT n)
Definition: Formats.h:130
ValueOffCIter cbeginValueOff() const
Return an iterator over inactive values (tile and voxel) across all nodes.
Definition: Tree.h:1171
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:105
RootNodeType::ChildOnIter beginRootChildren()
Return an iterator over children of the root node.
Definition: Tree.h:1104
static TreeT::ValueAllCIter begin(const TreeT &tree)
Definition: Tree.h:1353
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:2052
RootNodeType::ValueType ValueType
Definition: Tree.h:210
ValueOnCIter beginValueOn() const
Return an iterator over active values (tile and voxel) across all nodes.
Definition: Tree.h:1164
Definition: Tree.h:203
static Metadata::Ptr createMetadata(const Name &typeName)
Create new metadata of the given type.
Index64 activeTileCount() const
Return the total number of active tiles.
Definition: Tree.h:377
Tree4<T, N1, N2, N3>::Type is the type of a four-level tree (Root, Internal, Internal, Leaf) with value type T and internal and leaf node log dimensions N1, N2 and N3, respectively.
Definition: Tree.h:1223
CombineOp & op
Definition: Tree.h:1830
Base class for typed trees.
Definition: Tree.h:63
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOffCIter > ValueOffCIter
Definition: Tree.h:1153
const AValueType & a() const
Get the A input value.
Definition: Types.h:329
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return NULL.
Definition: Tree.h:1664
static TreeT::LeafIter begin(TreeT &tree)
Definition: Tree.h:1325
static TreeT::RootNodeType::ChildOnIter begin(TreeT &tree)
Definition: Tree.h:1281
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: Tree.h:1592
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:506
static TreeT::ValueAllIter begin(TreeT &tree)
Definition: Tree.h:1349
Tree< typename RootNodeType::template ValueConverter< OtherValueType >::Type > Type
Definition: Tree.h:223
static TreeT::RootNodeType::ChildAllIter begin(TreeT &tree)
Definition: Tree.h:1305
Internal table nodes for OpenVDB trees.
RootNodeType mRoot
Definition: Tree.h:1197
static TreeT::NodeIter begin(TreeT &tree)
Definition: Tree.h:1317
#define OPENVDB_VERSION_NAME
Definition: version.h:43
static tbb::atomic< const Name * > sTreeTypeName
Definition: Tree.h:1201
const LeafNodeType * probeLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return NULL.
Definition: Tree.h:541
virtual TreeBase::Ptr copy() const
Return a pointer to a deep copy of this tree.
Definition: Tree.h:289
bool probeValue(const Coord &xyz, ValueType &value) const
Get the value of the voxel at the given coordinates.
Definition: Tree.h:1626
Tree< RootNode< InternalNode< InternalNode< InternalNode< LeafNode< T, N4 >, N3 >, N2 >, N1 > > > Type
Definition: Tree.h:1234
Base class for tree-traversal iterators over all nodes.
Definition: TreeIterator.h:977
void operator()(CombineArgs< AValueT, BValueT > &args) const
Definition: Tree.h:1826
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:498
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form &#39;someVar << "some text" << ...&#39;.
Definition: logging.h:39
NodeIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > NodeCIter
Iterator over all nodes in this tree.
Definition: Tree.h:1125
Tree(const Tree< OtherRootType > &other)
Value conversion deep copy constructor.
Definition: Tree.h:241
CombineOpAdapter(CombineOp &_op)
Definition: Tree.h:1824
const ValueType & background() const
Return this tree&#39;s background value.
Definition: Tree.h:649
static TreeT::RootNodeType::ChildOffIter begin(TreeT &tree)
Definition: Tree.h:1293
std::string Name
Definition: Name.h:44
Definition: Exceptions.h:39
Tree3<T, N1, N2>::Type is the type of a three-level tree (Root, Internal, Leaf) with value type T and...
Definition: Tree.h:1213
Definition: Types.h:419
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:347
static TreeT::RootNodeType::ChildOffCIter begin(const TreeT &tree)
Definition: Tree.h:1299
virtual Index treeDepth() const
Return the depth of this tree.
Definition: Tree.h:363
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:595
AccessorRegistry mAccessorRegistry
Definition: Tree.h:1198
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:1637
RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:211
ValueAllCIter cbeginValueAll() const
Return an iterator over all values (tile and voxel) across all nodes.
Definition: Tree.h:1159
LeafCIter beginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1144
tbb::concurrent_hash_map< ValueAccessorBase< const Tree, true > *, bool > ConstAccessorRegistry
Definition: Tree.h:1184
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)
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1145
void attachAccessor(ValueAccessorBase< const Tree, false > &) const
Dummy implementations.
Definition: Tree.h:625
Tree()
Definition: Tree.h:227
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: Tree.h:1545
const AValueType & result() const
Get the output value.
Definition: Types.h:334
Definition: Types.h:259
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: Tree.h:1520
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don&#39;t change its value.
Definition: Tree.h:1561
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:1569
virtual Index32 leafCount() const
Return the number of leaf nodes.
Definition: Tree.h:365
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Definition: Tree.h:597
Tree(const OtherTreeType &other, const ValueType &inactiveValue, const ValueType &activeValue, TopologyCopy)
Topology copy constructor from a tree of a different type.
Definition: Tree.h:256
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:304
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:109
_RootNodeType RootNodeType
Definition: Tree.h:209
static TreeT::LeafCIter begin(const TreeT &tree)
Definition: Tree.h:1329
Definition: Exceptions.h:84
bool operator==(const Tree &) const
Definition: Tree.h:299
The root node of an OpenVDB tree.
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don&#39;t change its active state.
Definition: Tree.h:1576
uint64_t Index64
Definition: Types.h:57
virtual ~Tree()
Definition: Tree.h:286
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:607
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: Tree.h:1618
static TreeT::ValueOnCIter begin(const TreeT &tree)
Definition: Tree.h:1337
ValueConverter<T>::Type is the type of a tree having the same hierarchy as this tree but a different ...
Definition: Tree.h:222
Helper class to adapt a three-argument (a, b, result) CombineOp functor into a single-argument functo...
Definition: Tree.h:1822
This base class for ValueAccessors manages registration of an accessor with a tree so that the tree c...
Definition: ValueAccessor.h:121
RootNodeType & root()
Return this tree&#39;s root node.
Definition: Tree.h:304
ValueAllCIter beginValueAll() const
Return an iterator over all values (tile and voxel) across all nodes.
Definition: Tree.h:1158
void getNodes(ArrayT &array) const
Adds all nodes of a certain type to a container with the following API:
Definition: Tree.h:568
const RootNodeType & root() const
Return this tree&#39;s root node.
Definition: Tree.h:305
static TreeT::ValueOffCIter begin(const TreeT &tree)
Definition: Tree.h:1345
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:1259
RootNodeType::ChildOffIter beginRootTiles()
Return an iterator over non-child entries of the root node&#39;s table.
Definition: Tree.h:1111
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
NodeCIter beginNode() const
Return an iterator over all nodes in this tree.
Definition: Tree.h:1137
virtual void writeBuffers(std::ostream &, bool saveFloatAsHalf=false) const
Write out all data buffers for this tree.
Definition: Tree.h:1432
RootNodeType::ChildOffCIter cbeginRootTiles() const
Return an iterator over non-child entries of the root node&#39;s table.
Definition: Tree.h:1110
Tree< RootNode< InternalNode< LeafNode< T, N2 >, N1 > > > Type
Definition: Tree.h:1214
ConstAccessorRegistry mConstAccessorRegistry
Definition: Tree.h:1199
virtual void getIndexRange(CoordBBox &bbox) const
Min and max are both inclusive.
Definition: Tree.h:652
static TreeT::ValueOffIter begin(TreeT &tree)
Definition: Tree.h:1341
Tree(const ValueType &background)
Empty tree constructor.
Definition: Tree.h:284
boost::shared_ptr< Tree > Ptr
Definition: Tree.h:206
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueAllCIter > ValueAllCIter
Definition: Tree.h:1149
static TreeT::RootNodeType::ChildOnCIter begin(const TreeT &tree)
Definition: Tree.h:1287
RootNodeType::ChildOnCIter cbeginRootChildren() const
Return an iterator over children of the root node.
Definition: Tree.h:1103
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels) ...
Definition: TreeIterator.h:1228
virtual Index64 activeLeafVoxelCount() const
Return the number of active voxels stored in leaf nodes.
Definition: Tree.h:369
virtual Metadata::Ptr getBackgroundValue() const
Return this tree&#39;s background value wrapped as metadata.
Definition: Tree.h:86