OpenVDB  8.0.1
RootNode.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
7 
8 #ifndef OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
9 #define OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
10 
11 #include <openvdb/Exceptions.h>
12 #include <openvdb/Types.h>
13 #include <openvdb/io/Compression.h> // for truncateRealToHalf()
14 #include <openvdb/math/Math.h> // for isZero(), isExactlyEqual(), etc.
15 #include <openvdb/math/BBox.h>
16 #include <openvdb/util/NodeMasks.h> // for backward compatibility only (see readTopology())
17 #include <openvdb/version.h>
18 #include <tbb/parallel_for.h>
19 #include <map>
20 #include <set>
21 #include <sstream>
22 #include <vector>
23 
24 
25 namespace openvdb {
27 namespace OPENVDB_VERSION_NAME {
28 namespace tree {
29 
30 // Forward declarations
31 template<typename HeadType, int HeadLevel> struct NodeChain;
32 template<typename, typename> struct SameRootConfig;
33 template<typename, typename, bool> struct RootNodeCopyHelper;
34 template<typename, typename, typename, bool> struct RootNodeCombineHelper;
35 
36 
37 template<typename ChildType>
38 class RootNode
39 {
40 public:
41  using ChildNodeType = ChildType;
42  using LeafNodeType = typename ChildType::LeafNodeType;
43  using ValueType = typename ChildType::ValueType;
44  using BuildType = typename ChildType::BuildType;
45 
46  static const Index LEVEL = 1 + ChildType::LEVEL; // level 0 = leaf
47 
50  static_assert(NodeChainType::Size == LEVEL + 1,
51  "wrong number of entries in RootNode node chain");
52 
55  template<typename OtherValueType>
56  struct ValueConverter {
58  };
59 
63  template<typename OtherNodeType>
66  };
67 
68 
70  RootNode();
71 
73  explicit RootNode(const ValueType& background);
74 
75  RootNode(const RootNode& other) { *this = other; }
76 
83  template<typename OtherChildType>
84  explicit RootNode(const RootNode<OtherChildType>& other) { *this = other; }
85 
94  template<typename OtherChildType>
96  const ValueType& background, const ValueType& foreground, TopologyCopy);
97 
108  template<typename OtherChildType>
109  RootNode(const RootNode<OtherChildType>& other, const ValueType& background, TopologyCopy);
110 
112  RootNode& operator=(const RootNode& other);
120  template<typename OtherChildType>
122 
123  ~RootNode() { this->clear(); }
124 
125 private:
126  struct Tile {
127  Tile(): value(zeroVal<ValueType>()), active(false) {}
128  Tile(const ValueType& v, bool b): value(v), active(b) {}
129  ValueType value;
130  bool active;
131  };
132 
133  // This lightweight struct pairs child pointers and tiles.
134  struct NodeStruct {
135  ChildType* child;
136  Tile tile;
137 
138  NodeStruct(): child(nullptr) {}
139  NodeStruct(ChildType& c): child(&c) {}
140  NodeStruct(const Tile& t): child(nullptr), tile(t) {}
141  NodeStruct(const NodeStruct&) = default;
142  NodeStruct& operator=(const NodeStruct&) = default;
143  ~NodeStruct() {}
144 
145  bool isChild() const { return child != nullptr; }
146  bool isTile() const { return child == nullptr; }
147  bool isTileOff() const { return isTile() && !tile.active; }
148  bool isTileOn() const { return isTile() && tile.active; }
149 
150  void set(ChildType& c) { delete child; child = &c; }
151  void set(const Tile& t) { delete child; child = nullptr; tile = t; }
152  ChildType& steal(const Tile& t) { ChildType* c=child; child=nullptr; tile=t; return *c; }
153  };
154 
155  using MapType = std::map<Coord, NodeStruct>;
156  using MapIter = typename MapType::iterator;
157  using MapCIter = typename MapType::const_iterator;
158 
159  using CoordSet = std::set<Coord>;
160  using CoordSetIter = typename CoordSet::iterator;
161  using CoordSetCIter = typename CoordSet::const_iterator;
162 
163  static void setTile(const MapIter& i, const Tile& t) { i->second.set(t); }
164  static void setChild(const MapIter& i, ChildType& c) { i->second.set(c); }
165  static Tile& getTile(const MapIter& i) { return i->second.tile; }
166  static const Tile& getTile(const MapCIter& i) { return i->second.tile; }
167  static ChildType& getChild(const MapIter& i) { return *(i->second.child); }
168  static const ChildType& getChild(const MapCIter& i) { return *(i->second.child); }
169  static ChildType& stealChild(const MapIter& i, const Tile& t) {return i->second.steal(t);}
170  static const ChildType& stealChild(const MapCIter& i,const Tile& t) {return i->second.steal(t);}
171 
172  static bool isChild(const MapCIter& i) { return i->second.isChild(); }
173  static bool isChild(const MapIter& i) { return i->second.isChild(); }
174  static bool isTile(const MapCIter& i) { return i->second.isTile(); }
175  static bool isTile(const MapIter& i) { return i->second.isTile(); }
176  static bool isTileOff(const MapCIter& i) { return i->second.isTileOff(); }
177  static bool isTileOff(const MapIter& i) { return i->second.isTileOff(); }
178  static bool isTileOn(const MapCIter& i) { return i->second.isTileOn(); }
179  static bool isTileOn(const MapIter& i) { return i->second.isTileOn(); }
180 
181  struct NullPred {
182  static inline bool test(const MapIter&) { return true; }
183  static inline bool test(const MapCIter&) { return true; }
184  };
185  struct ValueOnPred {
186  static inline bool test(const MapIter& i) { return isTileOn(i); }
187  static inline bool test(const MapCIter& i) { return isTileOn(i); }
188  };
189  struct ValueOffPred {
190  static inline bool test(const MapIter& i) { return isTileOff(i); }
191  static inline bool test(const MapCIter& i) { return isTileOff(i); }
192  };
193  struct ValueAllPred {
194  static inline bool test(const MapIter& i) { return isTile(i); }
195  static inline bool test(const MapCIter& i) { return isTile(i); }
196  };
197  struct ChildOnPred {
198  static inline bool test(const MapIter& i) { return isChild(i); }
199  static inline bool test(const MapCIter& i) { return isChild(i); }
200  };
201  struct ChildOffPred {
202  static inline bool test(const MapIter& i) { return isTile(i); }
203  static inline bool test(const MapCIter& i) { return isTile(i); }
204  };
205 
206  template<typename _RootNodeT, typename _MapIterT, typename FilterPredT>
207  class BaseIter
208  {
209  public:
210  using RootNodeT = _RootNodeT;
211  using MapIterT = _MapIterT; // either MapIter or MapCIter
212 
213  bool operator==(const BaseIter& other) const
214  {
215  return (mParentNode == other.mParentNode) && (mIter == other.mIter);
216  }
217  bool operator!=(const BaseIter& other) const { return !(*this == other); }
218 
219  RootNodeT* getParentNode() const { return mParentNode; }
221  RootNodeT& parent() const
222  {
223  if (!mParentNode) OPENVDB_THROW(ValueError, "iterator references a null parent node");
224  return *mParentNode;
225  }
226 
227  bool test() const { assert(mParentNode); return mIter != mParentNode->mTable.end(); }
228  operator bool() const { return this->test(); }
229 
230  void increment() { if (this->test()) { ++mIter; } this->skip(); }
231  bool next() { this->increment(); return this->test(); }
232  void increment(Index n) { for (Index i = 0; i < n && this->next(); ++i) {} }
233 
236  Index pos() const
237  {
238  return !mParentNode ? 0U : Index(std::distance(mParentNode->mTable.begin(), mIter));
239  }
240 
241  bool isValueOn() const { return RootNodeT::isTileOn(mIter); }
242  bool isValueOff() const { return RootNodeT::isTileOff(mIter); }
243  void setValueOn(bool on = true) const { mIter->second.tile.active = on; }
244  void setValueOff() const { mIter->second.tile.active = false; }
245 
247  Coord getCoord() const { return mIter->first; }
249  void getCoord(Coord& xyz) const { xyz = this->getCoord(); }
250 
251  protected:
252  BaseIter(): mParentNode(nullptr) {}
253  BaseIter(RootNodeT& parent, const MapIterT& iter): mParentNode(&parent), mIter(iter) {}
254 
255  void skip() { while (this->test() && !FilterPredT::test(mIter)) ++mIter; }
256 
257  RootNodeT* mParentNode;
258  MapIterT mIter;
259  }; // BaseIter
260 
261  template<typename RootNodeT, typename MapIterT, typename FilterPredT, typename ChildNodeT>
262  class ChildIter: public BaseIter<RootNodeT, MapIterT, FilterPredT>
263  {
264  public:
265  using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
266  using NodeType = RootNodeT;
267  using ValueType = NodeType;
268  using ChildNodeType = ChildNodeT;
269  using NonConstNodeType = typename std::remove_const<NodeType>::type;
270  using NonConstValueType = typename std::remove_const<ValueType>::type;
271  using NonConstChildNodeType = typename std::remove_const<ChildNodeType>::type;
272  using BaseT::mIter;
273 
274  ChildIter() {}
275  ChildIter(RootNodeT& parent, const MapIterT& iter): BaseT(parent, iter) { BaseT::skip(); }
276 
277  ChildIter& operator++() { BaseT::increment(); return *this; }
278 
279  ChildNodeT& getValue() const { return getChild(mIter); }
280  ChildNodeT& operator*() const { return this->getValue(); }
281  ChildNodeT* operator->() const { return &this->getValue(); }
282  }; // ChildIter
283 
284  template<typename RootNodeT, typename MapIterT, typename FilterPredT, typename ValueT>
285  class ValueIter: public BaseIter<RootNodeT, MapIterT, FilterPredT>
286  {
287  public:
288  using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
289  using NodeType = RootNodeT;
290  using ValueType = ValueT;
291  using NonConstNodeType = typename std::remove_const<NodeType>::type;
292  using NonConstValueType = typename std::remove_const<ValueT>::type;
293  using BaseT::mIter;
294 
295  ValueIter() {}
296  ValueIter(RootNodeT& parent, const MapIterT& iter): BaseT(parent, iter) { BaseT::skip(); }
297 
298  ValueIter& operator++() { BaseT::increment(); return *this; }
299 
300  ValueT& getValue() const { return getTile(mIter).value; }
301  ValueT& operator*() const { return this->getValue(); }
302  ValueT* operator->() const { return &(this->getValue()); }
303 
304  void setValue(const ValueT& v) const { assert(isTile(mIter)); getTile(mIter).value = v; }
305 
306  template<typename ModifyOp>
307  void modifyValue(const ModifyOp& op) const
308  {
309  assert(isTile(mIter));
310  op(getTile(mIter).value);
311  }
312  }; // ValueIter
313 
314  template<typename RootNodeT, typename MapIterT, typename ChildNodeT, typename ValueT>
315  class DenseIter: public BaseIter<RootNodeT, MapIterT, NullPred>
316  {
317  public:
318  using BaseT = BaseIter<RootNodeT, MapIterT, NullPred>;
319  using NodeType = RootNodeT;
320  using ValueType = ValueT;
321  using ChildNodeType = ChildNodeT;
322  using NonConstNodeType = typename std::remove_const<NodeType>::type;
323  using NonConstValueType = typename std::remove_const<ValueT>::type;
324  using NonConstChildNodeType = typename std::remove_const<ChildNodeT>::type;
325  using BaseT::mIter;
326 
327  DenseIter() {}
328  DenseIter(RootNodeT& parent, const MapIterT& iter): BaseT(parent, iter) {}
329 
330  DenseIter& operator++() { BaseT::increment(); return *this; }
331 
332  bool isChildNode() const { return isChild(mIter); }
333 
334  ChildNodeT* probeChild(NonConstValueType& value) const
335  {
336  if (isChild(mIter)) return &getChild(mIter);
337  value = getTile(mIter).value;
338  return nullptr;
339  }
340  bool probeChild(ChildNodeT*& child, NonConstValueType& value) const
341  {
342  child = this->probeChild(value);
343  return child != nullptr;
344  }
345  bool probeValue(NonConstValueType& value) const { return !this->probeChild(value); }
346 
347  void setChild(ChildNodeT& c) const { RootNodeT::setChild(mIter, c); }
348  void setChild(ChildNodeT* c) const { assert(c != nullptr); RootNodeT::setChild(mIter, *c); }
349  void setValue(const ValueT& v) const
350  {
351  if (isTile(mIter)) getTile(mIter).value = v;
355  else stealChild(mIter, Tile(v, /*active=*/true));
356  }
357  }; // DenseIter
358 
359 public:
360  using ChildOnIter = ChildIter<RootNode, MapIter, ChildOnPred, ChildType>;
361  using ChildOnCIter = ChildIter<const RootNode, MapCIter, ChildOnPred, const ChildType>;
362  using ChildOffIter = ValueIter<RootNode, MapIter, ChildOffPred, const ValueType>;
363  using ChildOffCIter = ValueIter<const RootNode, MapCIter, ChildOffPred, ValueType>;
364  using ChildAllIter = DenseIter<RootNode, MapIter, ChildType, ValueType>;
365  using ChildAllCIter = DenseIter<const RootNode, MapCIter, const ChildType, const ValueType>;
366 
367  using ValueOnIter = ValueIter<RootNode, MapIter, ValueOnPred, ValueType>;
368  using ValueOnCIter = ValueIter<const RootNode, MapCIter, ValueOnPred, const ValueType>;
369  using ValueOffIter = ValueIter<RootNode, MapIter, ValueOffPred, ValueType>;
370  using ValueOffCIter = ValueIter<const RootNode, MapCIter, ValueOffPred, const ValueType>;
371  using ValueAllIter = ValueIter<RootNode, MapIter, ValueAllPred, ValueType>;
372  using ValueAllCIter = ValueIter<const RootNode, MapCIter, ValueAllPred, const ValueType>;
373 
374 
375  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(*this, mTable.begin()); }
376  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(*this, mTable.begin()); }
377  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(*this, mTable.begin()); }
378  ChildOnCIter beginChildOn() const { return cbeginChildOn(); }
379  ChildOffCIter beginChildOff() const { return cbeginChildOff(); }
380  ChildAllCIter beginChildAll() const { return cbeginChildAll(); }
381  ChildOnIter beginChildOn() { return ChildOnIter(*this, mTable.begin()); }
382  ChildOffIter beginChildOff() { return ChildOffIter(*this, mTable.begin()); }
383  ChildAllIter beginChildAll() { return ChildAllIter(*this, mTable.begin()); }
384 
385  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(*this, mTable.begin()); }
386  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(*this, mTable.begin()); }
387  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(*this, mTable.begin()); }
388  ValueOnCIter beginValueOn() const { return cbeginValueOn(); }
389  ValueOffCIter beginValueOff() const { return cbeginValueOff(); }
390  ValueAllCIter beginValueAll() const { return cbeginValueAll(); }
391  ValueOnIter beginValueOn() { return ValueOnIter(*this, mTable.begin()); }
392  ValueOffIter beginValueOff() { return ValueOffIter(*this, mTable.begin()); }
393  ValueAllIter beginValueAll() { return ValueAllIter(*this, mTable.begin()); }
394 
396  Index64 memUsage() const;
397 
403  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
404 
407 
420  void setBackground(const ValueType& value, bool updateChildNodes);
421 
423  const ValueType& background() const { return mBackground; }
424 
426  bool isBackgroundTile(const Tile&) const;
428  bool isBackgroundTile(const MapIter&) const;
430  bool isBackgroundTile(const MapCIter&) const;
432 
434  size_t numBackgroundTiles() const;
437  size_t eraseBackgroundTiles();
438  inline void clear();
439 
441  bool empty() const { return mTable.size() == numBackgroundTiles(); }
442 
446  bool expand(const Coord& xyz);
447 
448  static Index getLevel() { return LEVEL; }
449  static void getNodeLog2Dims(std::vector<Index>& dims);
450  static Index getChildDim() { return ChildType::DIM; }
451 
453  Index getTableSize() const { return static_cast<Index>(mTable.size()); }
454 
455  Index getWidth() const { return this->getMaxIndex()[0] - this->getMinIndex()[0]; }
456  Index getHeight() const { return this->getMaxIndex()[1] - this->getMinIndex()[1]; }
457  Index getDepth() const { return this->getMaxIndex()[2] - this->getMinIndex()[2]; }
458 
460  Coord getMinIndex() const;
462  Coord getMaxIndex() const;
464  void getIndexRange(CoordBBox& bbox) const;
465 
468  template<typename OtherChildType>
469  bool hasSameTopology(const RootNode<OtherChildType>& other) const;
470 
472  template<typename OtherChildType>
473  static bool hasSameConfiguration(const RootNode<OtherChildType>& other);
474 
477  template<typename OtherChildType>
478  static bool hasCompatibleValueType(const RootNode<OtherChildType>& other);
479 
480  Index32 leafCount() const;
481  Index32 nonLeafCount() const;
482  Index32 childCount() const;
483  Index64 onVoxelCount() const;
484  Index64 offVoxelCount() const;
485  Index64 onLeafVoxelCount() const;
486  Index64 offLeafVoxelCount() const;
487  Index64 onTileCount() const;
488  void nodeCount(std::vector<Index32> &vec) const;
489 
490  bool isValueOn(const Coord& xyz) const;
491 
493  bool hasActiveTiles() const;
494 
495  const ValueType& getValue(const Coord& xyz) const;
496  bool probeValue(const Coord& xyz, ValueType& value) const;
497 
501  int getValueDepth(const Coord& xyz) const;
502 
504  void setActiveState(const Coord& xyz, bool on);
506  void setValueOnly(const Coord& xyz, const ValueType& value);
508  void setValueOn(const Coord& xyz, const ValueType& value);
510  void setValueOff(const Coord& xyz);
512  void setValueOff(const Coord& xyz, const ValueType& value);
513 
516  template<typename ModifyOp>
517  void modifyValue(const Coord& xyz, const ModifyOp& op);
519  template<typename ModifyOp>
520  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op);
521 
523  void fill(const CoordBBox& bbox, const ValueType& value, bool active = true);
532  void sparseFill(const CoordBBox& bbox, const ValueType& value, bool active = true)
533  {
534  this->fill(bbox, value, active);
535  }
537 
545  void denseFill(const CoordBBox& bbox, const ValueType& value, bool active = true);
546 
555  void voxelizeActiveTiles(bool threaded = true);
556 
562  template<typename DenseT>
563  void copyToDense(const CoordBBox& bbox, DenseT& dense) const;
564 
565 
566  //
567  // I/O
568  //
569  bool writeTopology(std::ostream&, bool toHalf = false) const;
570  bool readTopology(std::istream&, bool fromHalf = false);
571 
572  void writeBuffers(std::ostream&, bool toHalf = false) const;
573  void readBuffers(std::istream&, bool fromHalf = false);
574  void readBuffers(std::istream&, const CoordBBox&, bool fromHalf = false);
575 
576 
577  //
578  // Voxel access
579  //
584  template<typename AccessorT>
585  const ValueType& getValueAndCache(const Coord& xyz, AccessorT&) const;
590  template<typename AccessorT>
591  bool isValueOnAndCache(const Coord& xyz, AccessorT&) const;
592 
597  template<typename AccessorT>
598  void setValueAndCache(const Coord& xyz, const ValueType& value, AccessorT&);
599 
604  template<typename AccessorT>
605  void setValueOnlyAndCache(const Coord& xyz, const ValueType& value, AccessorT&);
606 
612  template<typename ModifyOp, typename AccessorT>
613  void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&);
614 
619  template<typename ModifyOp, typename AccessorT>
620  void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&);
621 
626  template<typename AccessorT>
627  void setValueOffAndCache(const Coord& xyz, const ValueType& value, AccessorT&);
628 
633  template<typename AccessorT>
634  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&);
635 
641  template<typename AccessorT>
642  bool probeValueAndCache(const Coord& xyz, ValueType& value, AccessorT&) const;
643 
649  template<typename AccessorT>
650  int getValueDepthAndCache(const Coord& xyz, AccessorT&) const;
651 
653  void clip(const CoordBBox&);
654 
660  void prune(const ValueType& tolerance = zeroVal<ValueType>());
661 
664  void addLeaf(LeafNodeType* leaf);
665 
668  template<typename AccessorT>
669  void addLeafAndCache(LeafNodeType* leaf, AccessorT&);
670 
679  template<typename NodeT>
680  NodeT* stealNode(const Coord& xyz, const ValueType& value, bool state);
681 
687  bool addChild(ChildType* child);
688 
691  void addTile(const Coord& xyz, const ValueType& value, bool state);
692 
696  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state);
697 
700  template<typename AccessorT>
701  void addTileAndCache(Index level, const Coord& xyz, const ValueType&, bool state, AccessorT&);
702 
708  LeafNodeType* touchLeaf(const Coord& xyz);
709 
712  template<typename AccessorT>
713  LeafNodeType* touchLeafAndCache(const Coord& xyz, AccessorT& acc);
714 
716  template <typename NodeT>
719  NodeT* probeNode(const Coord& xyz);
720  template <typename NodeT>
721  const NodeT* probeConstNode(const Coord& xyz) const;
723 
725  template<typename NodeT, typename AccessorT>
728  NodeT* probeNodeAndCache(const Coord& xyz, AccessorT& acc);
729  template<typename NodeT, typename AccessorT>
730  const NodeT* probeConstNodeAndCache(const Coord& xyz, AccessorT& acc) const;
732 
734  LeafNodeType* probeLeaf(const Coord& xyz);
737  const LeafNodeType* probeConstLeaf(const Coord& xyz) const;
738  const LeafNodeType* probeLeaf(const Coord& xyz) const;
740 
742  template<typename AccessorT>
745  LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc);
746  template<typename AccessorT>
747  const LeafNodeType* probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const;
748  template<typename AccessorT>
749  const LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc) const;
751 
752 
753  //
754  // Aux methods
755  //
756 
758  template<typename ArrayT> void getNodes(ArrayT& array);
781  template<typename ArrayT> void getNodes(ArrayT& array) const;
783 
785  template<typename ArrayT>
809  void stealNodes(ArrayT& array, const ValueType& value, bool state);
810  template<typename ArrayT>
811  void stealNodes(ArrayT& array) { this->stealNodes(array, mBackground, false); }
813 
821  template<MergePolicy Policy> void merge(RootNode& other);
822 
836  template<typename OtherChildType>
837  void topologyUnion(const RootNode<OtherChildType>& other);
838 
852  template<typename OtherChildType>
853  void topologyIntersection(const RootNode<OtherChildType>& other);
854 
865  template<typename OtherChildType>
866  void topologyDifference(const RootNode<OtherChildType>& other);
867 
868  template<typename CombineOp>
869  void combine(RootNode& other, CombineOp&, bool prune = false);
870 
871  template<typename CombineOp, typename OtherRootNode /*= RootNode*/>
872  void combine2(const RootNode& other0, const OtherRootNode& other1,
873  CombineOp& op, bool prune = false);
874 
880  template<typename BBoxOp> void visitActiveBBox(BBoxOp&) const;
881 
882  template<typename VisitorOp> void visit(VisitorOp&);
883  template<typename VisitorOp> void visit(VisitorOp&) const;
884 
885  template<typename OtherRootNodeType, typename VisitorOp>
886  void visit2(OtherRootNodeType& other, VisitorOp&);
887  template<typename OtherRootNodeType, typename VisitorOp>
888  void visit2(OtherRootNodeType& other, VisitorOp&) const;
889 
890 private:
893  template<typename> friend class RootNode;
894 
895  template<typename, typename, bool> friend struct RootNodeCopyHelper;
896  template<typename, typename, typename, bool> friend struct RootNodeCombineHelper;
897 
899  void initTable() {}
901  void resetTable(MapType& table) { mTable.swap(table); table.clear(); }
903  void resetTable(const MapType&) const {}
905 
906 #if OPENVDB_ABI_VERSION_NUMBER < 8
907  Index getChildCount() const;
908 #endif
909  Index getTileCount() const;
910  Index getActiveTileCount() const;
911  Index getInactiveTileCount() const;
912 
914  static Coord coordToKey(const Coord& xyz) { return xyz & ~(ChildType::DIM - 1); }
915 
917  void insertKeys(CoordSet&) const;
918 
920  bool hasKey(const Coord& key) const { return mTable.find(key) != mTable.end(); }
922  MapIter findKey(const Coord& key) { return mTable.find(key); }
925  MapCIter findKey(const Coord& key) const { return mTable.find(key); }
927 
928  MapIter findCoord(const Coord& xyz) { return mTable.find(coordToKey(xyz)); }
931  MapCIter findCoord(const Coord& xyz) const { return mTable.find(coordToKey(xyz)); }
933  MapIter findOrAddCoord(const Coord& xyz);
937 
942  template<typename OtherChildType>
943  static void enforceSameConfiguration(const RootNode<OtherChildType>& other);
944 
950  template<typename OtherChildType>
951  static void enforceCompatibleValueTypes(const RootNode<OtherChildType>& other);
952 
953  template<typename CombineOp, typename OtherRootNode /*= RootNode*/>
954  void doCombine2(const RootNode&, const OtherRootNode&, CombineOp&, bool prune);
955 
956  template<typename RootNodeT, typename VisitorOp, typename ChildAllIterT>
957  static inline void doVisit(RootNodeT&, VisitorOp&);
958 
959  template<typename RootNodeT, typename OtherRootNodeT, typename VisitorOp,
960  typename ChildAllIterT, typename OtherChildAllIterT>
961  static inline void doVisit2(RootNodeT&, OtherRootNodeT&, VisitorOp&);
962 
963 
964  MapType mTable;
965  ValueType mBackground;
966 }; // end of RootNode class
967 
968 
970 
971 
992 template<typename HeadT, int HeadLevel>
993 struct NodeChain {
994  using SubtreeT = typename NodeChain<typename HeadT::ChildNodeType, HeadLevel-1>::Type;
995  using Type = typename SubtreeT::template Append<HeadT>;
996 };
997 
999 template<typename HeadT>
1000 struct NodeChain<HeadT, /*HeadLevel=*/1> {
1002 };
1003 
1004 
1006 
1007 
1009 template<typename ChildT1, typename NodeT2>
1013  static const bool value = false;
1014 };
1015 
1016 template<typename ChildT1, typename ChildT2>
1017 struct SameRootConfig<ChildT1, RootNode<ChildT2> > {
1018  static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
1019 };
1021 
1022 
1024 
1025 
1026 template<typename ChildT>
1027 inline
1029 {
1030  this->initTable();
1031 }
1032 
1033 
1034 template<typename ChildT>
1035 inline
1036 RootNode<ChildT>::RootNode(const ValueType& background): mBackground(background)
1037 {
1038  this->initTable();
1039 }
1040 
1041 
1042 template<typename ChildT>
1043 template<typename OtherChildType>
1044 inline
1046  const ValueType& backgd, const ValueType& foregd, TopologyCopy):
1047  mBackground(backgd)
1048 {
1049  using OtherRootT = RootNode<OtherChildType>;
1050 
1051  enforceSameConfiguration(other);
1052 
1053  const Tile bgTile(backgd, /*active=*/false), fgTile(foregd, true);
1054  this->initTable();
1055 
1056  for (typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1057  mTable[i->first] = OtherRootT::isTile(i)
1058  ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1059  : NodeStruct(*(new ChildT(OtherRootT::getChild(i), backgd, foregd, TopologyCopy())));
1060  }
1061 }
1062 
1063 
1064 template<typename ChildT>
1065 template<typename OtherChildType>
1066 inline
1068  const ValueType& backgd, TopologyCopy):
1069  mBackground(backgd)
1070 {
1071  using OtherRootT = RootNode<OtherChildType>;
1072 
1073  enforceSameConfiguration(other);
1074 
1075  const Tile bgTile(backgd, /*active=*/false), fgTile(backgd, true);
1076  this->initTable();
1077  for (typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1078  mTable[i->first] = OtherRootT::isTile(i)
1079  ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1080  : NodeStruct(*(new ChildT(OtherRootT::getChild(i), backgd, TopologyCopy())));
1081  }
1082 }
1083 
1084 
1086 
1087 
1088 // This helper class is a friend of RootNode and is needed so that assignment
1089 // with value conversion can be specialized for compatible and incompatible
1090 // pairs of RootNode types.
1091 template<typename RootT, typename OtherRootT, bool Compatible = false>
1093 {
1094  static inline void copyWithValueConversion(RootT& self, const OtherRootT& other)
1095  {
1096  // If the two root nodes have different configurations or incompatible ValueTypes,
1097  // throw an exception.
1098  self.enforceSameConfiguration(other);
1099  self.enforceCompatibleValueTypes(other);
1100  // One of the above two tests should throw, so we should never get here:
1101  std::ostringstream ostr;
1102  ostr << "cannot convert a " << typeid(OtherRootT).name()
1103  << " to a " << typeid(RootT).name();
1104  OPENVDB_THROW(TypeError, ostr.str());
1105  }
1106 };
1107 
1108 // Specialization for root nodes of compatible types
1109 template<typename RootT, typename OtherRootT>
1110 struct RootNodeCopyHelper<RootT, OtherRootT, /*Compatible=*/true>
1111 {
1112  static inline void copyWithValueConversion(RootT& self, const OtherRootT& other)
1113  {
1114  using ValueT = typename RootT::ValueType;
1115  using ChildT = typename RootT::ChildNodeType;
1116  using NodeStruct = typename RootT::NodeStruct;
1117  using Tile = typename RootT::Tile;
1118  using OtherValueT = typename OtherRootT::ValueType;
1119  using OtherMapCIter = typename OtherRootT::MapCIter;
1120  using OtherTile = typename OtherRootT::Tile;
1121 
1122  struct Local {
1124  static inline ValueT convertValue(const OtherValueT& val) { return ValueT(val); }
1125  };
1126 
1127  self.mBackground = Local::convertValue(other.mBackground);
1128 
1129  self.clear();
1130  self.initTable();
1131 
1132  for (OtherMapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1133  if (other.isTile(i)) {
1134  // Copy the other node's tile, but convert its value to this node's ValueType.
1135  const OtherTile& otherTile = other.getTile(i);
1136  self.mTable[i->first] = NodeStruct(
1137  Tile(Local::convertValue(otherTile.value), otherTile.active));
1138  } else {
1139  // Copy the other node's child, but convert its values to this node's ValueType.
1140  self.mTable[i->first] = NodeStruct(*(new ChildT(other.getChild(i))));
1141  }
1142  }
1143  }
1144 };
1145 
1146 
1147 // Overload for root nodes of the same type as this node
1148 template<typename ChildT>
1149 inline RootNode<ChildT>&
1151 {
1152  if (&other != this) {
1153  mBackground = other.mBackground;
1154 
1155  this->clear();
1156  this->initTable();
1157 
1158  for (MapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1159  mTable[i->first] =
1160  isTile(i) ? NodeStruct(getTile(i)) : NodeStruct(*(new ChildT(getChild(i))));
1161  }
1162  }
1163  return *this;
1164 }
1165 
1166 // Overload for root nodes of different types
1167 template<typename ChildT>
1168 template<typename OtherChildType>
1169 inline RootNode<ChildT>&
1171 {
1172  using OtherRootT = RootNode<OtherChildType>;
1173  using OtherValueT = typename OtherRootT::ValueType;
1174  static const bool compatible = (SameConfiguration<OtherRootT>::value
1175  && CanConvertType</*from=*/OtherValueT, /*to=*/ValueType>::value);
1177  return *this;
1178 }
1179 
1180 
1182 
1183 template<typename ChildT>
1184 inline void
1185 RootNode<ChildT>::setBackground(const ValueType& background, bool updateChildNodes)
1186 {
1187  if (math::isExactlyEqual(background, mBackground)) return;
1188 
1189  if (updateChildNodes) {
1190  // Traverse the tree, replacing occurrences of mBackground with background
1191  // and -mBackground with -background.
1192  for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1193  ChildT *child = iter->second.child;
1194  if (child) {
1195  child->resetBackground(/*old=*/mBackground, /*new=*/background);
1196  } else {
1197  Tile& tile = getTile(iter);
1198  if (tile.active) continue;//only change inactive tiles
1199  if (math::isApproxEqual(tile.value, mBackground)) {
1200  tile.value = background;
1201  } else if (math::isApproxEqual(tile.value, math::negative(mBackground))) {
1202  tile.value = math::negative(background);
1203  }
1204  }
1205  }
1206  }
1207  mBackground = background;
1208 }
1209 
1210 template<typename ChildT>
1211 inline bool
1212 RootNode<ChildT>::isBackgroundTile(const Tile& tile) const
1213 {
1214  return !tile.active && math::isApproxEqual(tile.value, mBackground);
1215 }
1216 
1217 template<typename ChildT>
1218 inline bool
1219 RootNode<ChildT>::isBackgroundTile(const MapIter& iter) const
1220 {
1221  return isTileOff(iter) && math::isApproxEqual(getTile(iter).value, mBackground);
1222 }
1223 
1224 template<typename ChildT>
1225 inline bool
1226 RootNode<ChildT>::isBackgroundTile(const MapCIter& iter) const
1227 {
1228  return isTileOff(iter) && math::isApproxEqual(getTile(iter).value, mBackground);
1229 }
1230 
1231 
1232 template<typename ChildT>
1233 inline size_t
1235 {
1236  size_t count = 0;
1237  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1238  if (this->isBackgroundTile(i)) ++count;
1239  }
1240  return count;
1241 }
1242 
1243 
1244 template<typename ChildT>
1245 inline size_t
1247 {
1248  std::set<Coord> keysToErase;
1249  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1250  if (this->isBackgroundTile(i)) keysToErase.insert(i->first);
1251  }
1252  for (std::set<Coord>::iterator i = keysToErase.begin(), e = keysToErase.end(); i != e; ++i) {
1253  mTable.erase(*i);
1254  }
1255  return keysToErase.size();
1256 }
1257 
1258 
1260 
1261 
1262 template<typename ChildT>
1263 inline void
1264 RootNode<ChildT>::insertKeys(CoordSet& keys) const
1265 {
1266  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1267  keys.insert(i->first);
1268  }
1269 }
1270 
1271 
1272 template<typename ChildT>
1273 inline typename RootNode<ChildT>::MapIter
1274 RootNode<ChildT>::findOrAddCoord(const Coord& xyz)
1275 {
1276  const Coord key = coordToKey(xyz);
1277  std::pair<MapIter, bool> result = mTable.insert(
1278  typename MapType::value_type(key, NodeStruct(Tile(mBackground, /*active=*/false))));
1279  return result.first;
1280 }
1281 
1282 
1283 template<typename ChildT>
1284 inline bool
1286 {
1287  const Coord key = coordToKey(xyz);
1288  std::pair<MapIter, bool> result = mTable.insert(
1289  typename MapType::value_type(key, NodeStruct(Tile(mBackground, /*active=*/false))));
1290  return result.second; // return true if the key did not already exist
1291 }
1292 
1293 
1295 
1296 
1297 template<typename ChildT>
1298 inline void
1299 RootNode<ChildT>::getNodeLog2Dims(std::vector<Index>& dims)
1300 {
1301  dims.push_back(0); // magic number; RootNode has no Log2Dim
1302  ChildT::getNodeLog2Dims(dims);
1303 }
1304 
1305 
1306 template<typename ChildT>
1307 inline Coord
1309 {
1310  return mTable.empty() ? Coord(0) : mTable.begin()->first;
1311 }
1312 
1313 template<typename ChildT>
1314 inline Coord
1316 {
1317  return mTable.empty() ? Coord(0) : mTable.rbegin()->first + Coord(ChildT::DIM - 1);
1318 }
1319 
1320 
1321 template<typename ChildT>
1322 inline void
1324 {
1325  bbox.min() = this->getMinIndex();
1326  bbox.max() = this->getMaxIndex();
1327 }
1328 
1329 
1331 
1332 
1333 template<typename ChildT>
1334 template<typename OtherChildType>
1335 inline bool
1337 {
1338  using OtherRootT = RootNode<OtherChildType>;
1339  using OtherMapT = typename OtherRootT::MapType;
1340  using OtherIterT = typename OtherRootT::MapIter;
1341  using OtherCIterT = typename OtherRootT::MapCIter;
1342 
1343  if (!hasSameConfiguration(other)) return false;
1344 
1345  // Create a local copy of the other node's table.
1346  OtherMapT copyOfOtherTable = other.mTable;
1347 
1348  // For each entry in this node's table...
1349  for (MapCIter thisIter = mTable.begin(); thisIter != mTable.end(); ++thisIter) {
1350  if (this->isBackgroundTile(thisIter)) continue; // ignore background tiles
1351 
1352  // Fail if there is no corresponding entry in the other node's table.
1353  OtherCIterT otherIter = other.findKey(thisIter->first);
1354  if (otherIter == other.mTable.end()) return false;
1355 
1356  // Fail if this entry is a tile and the other is a child or vice-versa.
1357  if (isChild(thisIter)) {//thisIter points to a child
1358  if (OtherRootT::isTile(otherIter)) return false;
1359  // Fail if both entries are children, but the children have different topology.
1360  if (!getChild(thisIter).hasSameTopology(&OtherRootT::getChild(otherIter))) return false;
1361  } else {//thisIter points to a tile
1362  if (OtherRootT::isChild(otherIter)) return false;
1363  if (getTile(thisIter).active != OtherRootT::getTile(otherIter).active) return false;
1364  }
1365 
1366  // Remove tiles and child nodes with matching topology from
1367  // the copy of the other node's table. This is required since
1368  // the two root tables can include an arbitrary number of
1369  // background tiles and still have the same topology!
1370  copyOfOtherTable.erase(otherIter->first);
1371  }
1372  // Fail if the remaining entries in copyOfOtherTable are not all background tiles.
1373  for (OtherIterT i = copyOfOtherTable.begin(), e = copyOfOtherTable.end(); i != e; ++i) {
1374  if (!other.isBackgroundTile(i)) return false;
1375  }
1376  return true;
1377 }
1378 
1379 
1380 template<typename ChildT>
1381 template<typename OtherChildType>
1382 inline bool
1384 {
1385  std::vector<Index> thisDims, otherDims;
1386  RootNode::getNodeLog2Dims(thisDims);
1388  return (thisDims == otherDims);
1389 }
1390 
1391 
1392 template<typename ChildT>
1393 template<typename OtherChildType>
1394 inline void
1396 {
1397  std::vector<Index> thisDims, otherDims;
1398  RootNode::getNodeLog2Dims(thisDims);
1400  if (thisDims != otherDims) {
1401  std::ostringstream ostr;
1402  ostr << "grids have incompatible configurations (" << thisDims[0];
1403  for (size_t i = 1, N = thisDims.size(); i < N; ++i) ostr << " x " << thisDims[i];
1404  ostr << " vs. " << otherDims[0];
1405  for (size_t i = 1, N = otherDims.size(); i < N; ++i) ostr << " x " << otherDims[i];
1406  ostr << ")";
1407  OPENVDB_THROW(TypeError, ostr.str());
1408  }
1409 }
1410 
1411 
1412 template<typename ChildT>
1413 template<typename OtherChildType>
1414 inline bool
1416 {
1417  using OtherValueType = typename OtherChildType::ValueType;
1418  return CanConvertType</*from=*/OtherValueType, /*to=*/ValueType>::value;
1419 }
1420 
1421 
1422 template<typename ChildT>
1423 template<typename OtherChildType>
1424 inline void
1426 {
1427  using OtherValueType = typename OtherChildType::ValueType;
1429  std::ostringstream ostr;
1430  ostr << "values of type " << typeNameAsString<OtherValueType>()
1431  << " cannot be converted to type " << typeNameAsString<ValueType>();
1432  OPENVDB_THROW(TypeError, ostr.str());
1433  }
1434 }
1435 
1436 
1438 
1439 
1440 template<typename ChildT>
1441 inline Index64
1443 {
1444  Index64 sum = sizeof(*this);
1445  for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1446  if (const ChildT *child = iter->second.child) {
1447  sum += child->memUsage();
1448  }
1449  }
1450  return sum;
1451 }
1452 
1453 
1454 template<typename ChildT>
1455 inline void
1457 {
1458  for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1459  delete i->second.child;
1460  }
1461  mTable.clear();
1462 }
1463 
1464 
1465 template<typename ChildT>
1466 inline void
1468 {
1469  for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1470  if (const ChildT *child = iter->second.child) {
1471  child->evalActiveBoundingBox(bbox, visitVoxels);
1472  } else if (isTileOn(iter)) {
1473  bbox.expand(iter->first, ChildT::DIM);
1474  }
1475  }
1476 }
1477 
1478 
1479 #if OPENVDB_ABI_VERSION_NUMBER < 8
1480 template<typename ChildT>
1481 inline Index
1483  return this->childCount();
1484 }
1485 #endif
1486 
1487 
1488 template<typename ChildT>
1489 inline Index
1490 RootNode<ChildT>::getTileCount() const
1491 {
1492  Index sum = 0;
1493  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1494  if (isTile(i)) ++sum;
1495  }
1496  return sum;
1497 }
1498 
1499 
1500 template<typename ChildT>
1501 inline Index
1502 RootNode<ChildT>::getActiveTileCount() const
1503 {
1504  Index sum = 0;
1505  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1506  if (isTileOn(i)) ++sum;
1507  }
1508  return sum;
1509 }
1510 
1511 
1512 template<typename ChildT>
1513 inline Index
1514 RootNode<ChildT>::getInactiveTileCount() const
1515 {
1516  Index sum = 0;
1517  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1518  if (isTileOff(i)) ++sum;
1519  }
1520  return sum;
1521 }
1522 
1523 
1524 template<typename ChildT>
1525 inline Index32
1527 {
1528  Index32 sum = 0;
1529  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1530  if (isChild(i)) sum += getChild(i).leafCount();
1531  }
1532  return sum;
1533 }
1534 
1535 
1536 template<typename ChildT>
1537 inline Index32
1539 {
1540  Index32 sum = 1;
1541  if (ChildT::LEVEL != 0) {
1542  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1543  if (isChild(i)) sum += getChild(i).nonLeafCount();
1544  }
1545  }
1546  return sum;
1547 }
1548 
1549 
1550 template<typename ChildT>
1551 inline Index32
1553 {
1554  Index sum = 0;
1555  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1556  if (isChild(i)) ++sum;
1557  }
1558  return sum;
1559 }
1560 
1561 
1562 template<typename ChildT>
1563 inline Index64
1565 {
1566  Index64 sum = 0;
1567  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1568  if (isChild(i)) {
1569  sum += getChild(i).onVoxelCount();
1570  } else if (isTileOn(i)) {
1571  sum += ChildT::NUM_VOXELS;
1572  }
1573  }
1574  return sum;
1575 }
1576 
1577 
1578 template<typename ChildT>
1579 inline Index64
1581 {
1582  Index64 sum = 0;
1583  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1584  if (isChild(i)) {
1585  sum += getChild(i).offVoxelCount();
1586  } else if (isTileOff(i) && !this->isBackgroundTile(i)) {
1587  sum += ChildT::NUM_VOXELS;
1588  }
1589  }
1590  return sum;
1591 }
1592 
1593 
1594 template<typename ChildT>
1595 inline Index64
1597 {
1598  Index64 sum = 0;
1599  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1600  if (isChild(i)) sum += getChild(i).onLeafVoxelCount();
1601  }
1602  return sum;
1603 }
1604 
1605 
1606 template<typename ChildT>
1607 inline Index64
1609 {
1610  Index64 sum = 0;
1611  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1612  if (isChild(i)) sum += getChild(i).offLeafVoxelCount();
1613  }
1614  return sum;
1615 }
1616 
1617 template<typename ChildT>
1618 inline Index64
1620 {
1621  Index64 sum = 0;
1622  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1623  if (isChild(i)) {
1624  sum += getChild(i).onTileCount();
1625  } else if (isTileOn(i)) {
1626  sum += 1;
1627  }
1628  }
1629  return sum;
1630 }
1631 
1632 template<typename ChildT>
1633 inline void
1634 RootNode<ChildT>::nodeCount(std::vector<Index32> &vec) const
1635 {
1636  assert(vec.size() > LEVEL);
1637  Index32 sum = 0;
1638  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1639  if (isChild(i)) {
1640  ++sum;
1641  getChild(i).nodeCount(vec);
1642  }
1643  }
1644  vec[LEVEL] = 1;// one root node
1645  vec[ChildNodeType::LEVEL] = sum;
1646 }
1647 
1649 
1650 
1651 template<typename ChildT>
1652 inline bool
1654 {
1655  MapCIter iter = this->findCoord(xyz);
1656  if (iter == mTable.end() || isTileOff(iter)) return false;
1657  return isTileOn(iter) ? true : getChild(iter).isValueOn(xyz);
1658 }
1659 
1660 template<typename ChildT>
1661 inline bool
1663 {
1664  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1665  if (isChild(i) ? getChild(i).hasActiveTiles() : getTile(i).active) return true;
1666  }
1667  return false;
1668 }
1669 
1670 template<typename ChildT>
1671 template<typename AccessorT>
1672 inline bool
1673 RootNode<ChildT>::isValueOnAndCache(const Coord& xyz, AccessorT& acc) const
1674 {
1675  MapCIter iter = this->findCoord(xyz);
1676  if (iter == mTable.end() || isTileOff(iter)) return false;
1677  if (isTileOn(iter)) return true;
1678  acc.insert(xyz, &getChild(iter));
1679  return getChild(iter).isValueOnAndCache(xyz, acc);
1680 }
1681 
1682 
1683 template<typename ChildT>
1684 inline const typename ChildT::ValueType&
1686 {
1687  MapCIter iter = this->findCoord(xyz);
1688  return iter == mTable.end() ? mBackground
1689  : (isTile(iter) ? getTile(iter).value : getChild(iter).getValue(xyz));
1690 }
1691 
1692 template<typename ChildT>
1693 template<typename AccessorT>
1694 inline const typename ChildT::ValueType&
1695 RootNode<ChildT>::getValueAndCache(const Coord& xyz, AccessorT& acc) const
1696 {
1697  MapCIter iter = this->findCoord(xyz);
1698  if (iter == mTable.end()) return mBackground;
1699  if (isChild(iter)) {
1700  acc.insert(xyz, &getChild(iter));
1701  return getChild(iter).getValueAndCache(xyz, acc);
1702  }
1703  return getTile(iter).value;
1704 }
1705 
1706 
1707 template<typename ChildT>
1708 inline int
1710 {
1711  MapCIter iter = this->findCoord(xyz);
1712  return iter == mTable.end() ? -1
1713  : (isTile(iter) ? 0 : int(LEVEL) - int(getChild(iter).getValueLevel(xyz)));
1714 }
1715 
1716 template<typename ChildT>
1717 template<typename AccessorT>
1718 inline int
1719 RootNode<ChildT>::getValueDepthAndCache(const Coord& xyz, AccessorT& acc) const
1720 {
1721  MapCIter iter = this->findCoord(xyz);
1722  if (iter == mTable.end()) return -1;
1723  if (isTile(iter)) return 0;
1724  acc.insert(xyz, &getChild(iter));
1725  return int(LEVEL) - int(getChild(iter).getValueLevelAndCache(xyz, acc));
1726 }
1727 
1728 
1729 template<typename ChildT>
1730 inline void
1732 {
1733  MapIter iter = this->findCoord(xyz);
1734  if (iter != mTable.end() && !isTileOff(iter)) {
1735  if (isTileOn(iter)) {
1736  setChild(iter, *new ChildT(xyz, getTile(iter).value, /*active=*/true));
1737  }
1738  getChild(iter).setValueOff(xyz);
1739  }
1740 }
1741 
1742 
1743 template<typename ChildT>
1744 inline void
1746 {
1747  ChildT* child = nullptr;
1748  MapIter iter = this->findCoord(xyz);
1749  if (iter == mTable.end()) {
1750  if (on) {
1751  child = new ChildT(xyz, mBackground);
1752  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1753  } else {
1754  // Nothing to do; (x, y, z) is background and therefore already inactive.
1755  }
1756  } else if (isChild(iter)) {
1757  child = &getChild(iter);
1758  } else if (on != getTile(iter).active) {
1759  child = new ChildT(xyz, getTile(iter).value, !on);
1760  setChild(iter, *child);
1761  }
1762  if (child) child->setActiveState(xyz, on);
1763 }
1764 
1765 template<typename ChildT>
1766 template<typename AccessorT>
1767 inline void
1768 RootNode<ChildT>::setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& acc)
1769 {
1770  ChildT* child = nullptr;
1771  MapIter iter = this->findCoord(xyz);
1772  if (iter == mTable.end()) {
1773  if (on) {
1774  child = new ChildT(xyz, mBackground);
1775  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1776  } else {
1777  // Nothing to do; (x, y, z) is background and therefore already inactive.
1778  }
1779  } else if (isChild(iter)) {
1780  child = &getChild(iter);
1781  } else if (on != getTile(iter).active) {
1782  child = new ChildT(xyz, getTile(iter).value, !on);
1783  setChild(iter, *child);
1784  }
1785  if (child) {
1786  acc.insert(xyz, child);
1787  child->setActiveStateAndCache(xyz, on, acc);
1788  }
1789 }
1790 
1791 
1792 template<typename ChildT>
1793 inline void
1795 {
1796  ChildT* child = nullptr;
1797  MapIter iter = this->findCoord(xyz);
1798  if (iter == mTable.end()) {
1799  if (!math::isExactlyEqual(mBackground, value)) {
1800  child = new ChildT(xyz, mBackground);
1801  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1802  }
1803  } else if (isChild(iter)) {
1804  child = &getChild(iter);
1805  } else if (isTileOn(iter) || !math::isExactlyEqual(getTile(iter).value, value)) {
1806  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1807  setChild(iter, *child);
1808  }
1809  if (child) child->setValueOff(xyz, value);
1810 }
1811 
1812 template<typename ChildT>
1813 template<typename AccessorT>
1814 inline void
1815 RootNode<ChildT>::setValueOffAndCache(const Coord& xyz, const ValueType& value, AccessorT& acc)
1816 {
1817  ChildT* child = nullptr;
1818  MapIter iter = this->findCoord(xyz);
1819  if (iter == mTable.end()) {
1820  if (!math::isExactlyEqual(mBackground, value)) {
1821  child = new ChildT(xyz, mBackground);
1822  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1823  }
1824  } else if (isChild(iter)) {
1825  child = &getChild(iter);
1826  } else if (isTileOn(iter) || !math::isExactlyEqual(getTile(iter).value, value)) {
1827  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1828  setChild(iter, *child);
1829  }
1830  if (child) {
1831  acc.insert(xyz, child);
1832  child->setValueOffAndCache(xyz, value, acc);
1833  }
1834 }
1835 
1836 
1837 template<typename ChildT>
1838 inline void
1840 {
1841  ChildT* child = nullptr;
1842  MapIter iter = this->findCoord(xyz);
1843  if (iter == mTable.end()) {
1844  child = new ChildT(xyz, mBackground);
1845  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1846  } else if (isChild(iter)) {
1847  child = &getChild(iter);
1848  } else if (isTileOff(iter) || !math::isExactlyEqual(getTile(iter).value, value)) {
1849  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1850  setChild(iter, *child);
1851  }
1852  if (child) child->setValueOn(xyz, value);
1853 }
1854 
1855 template<typename ChildT>
1856 template<typename AccessorT>
1857 inline void
1858 RootNode<ChildT>::setValueAndCache(const Coord& xyz, const ValueType& value, AccessorT& acc)
1859 {
1860  ChildT* child = nullptr;
1861  MapIter iter = this->findCoord(xyz);
1862  if (iter == mTable.end()) {
1863  child = new ChildT(xyz, mBackground);
1864  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1865  } else if (isChild(iter)) {
1866  child = &getChild(iter);
1867  } else if (isTileOff(iter) || !math::isExactlyEqual(getTile(iter).value, value)) {
1868  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1869  setChild(iter, *child);
1870  }
1871  if (child) {
1872  acc.insert(xyz, child);
1873  child->setValueAndCache(xyz, value, acc);
1874  }
1875 }
1876 
1877 
1878 template<typename ChildT>
1879 inline void
1881 {
1882  ChildT* child = nullptr;
1883  MapIter iter = this->findCoord(xyz);
1884  if (iter == mTable.end()) {
1885  child = new ChildT(xyz, mBackground);
1886  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1887  } else if (isChild(iter)) {
1888  child = &getChild(iter);
1889  } else if (!math::isExactlyEqual(getTile(iter).value, value)) {
1890  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1891  setChild(iter, *child);
1892  }
1893  if (child) child->setValueOnly(xyz, value);
1894 }
1895 
1896 template<typename ChildT>
1897 template<typename AccessorT>
1898 inline void
1899 RootNode<ChildT>::setValueOnlyAndCache(const Coord& xyz, const ValueType& value, AccessorT& acc)
1900 {
1901  ChildT* child = nullptr;
1902  MapIter iter = this->findCoord(xyz);
1903  if (iter == mTable.end()) {
1904  child = new ChildT(xyz, mBackground);
1905  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1906  } else if (isChild(iter)) {
1907  child = &getChild(iter);
1908  } else if (!math::isExactlyEqual(getTile(iter).value, value)) {
1909  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1910  setChild(iter, *child);
1911  }
1912  if (child) {
1913  acc.insert(xyz, child);
1914  child->setValueOnlyAndCache(xyz, value, acc);
1915  }
1916 }
1917 
1918 
1919 template<typename ChildT>
1920 template<typename ModifyOp>
1921 inline void
1922 RootNode<ChildT>::modifyValue(const Coord& xyz, const ModifyOp& op)
1923 {
1924  ChildT* child = nullptr;
1925  MapIter iter = this->findCoord(xyz);
1926  if (iter == mTable.end()) {
1927  child = new ChildT(xyz, mBackground);
1928  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1929  } else if (isChild(iter)) {
1930  child = &getChild(iter);
1931  } else {
1932  // Need to create a child if the tile is inactive,
1933  // in order to activate voxel (x, y, z).
1934  bool createChild = isTileOff(iter);
1935  if (!createChild) {
1936  // Need to create a child if applying the functor
1937  // to the tile value produces a different value.
1938  const ValueType& tileVal = getTile(iter).value;
1939  ValueType modifiedVal = tileVal;
1940  op(modifiedVal);
1941  createChild = !math::isExactlyEqual(tileVal, modifiedVal);
1942  }
1943  if (createChild) {
1944  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1945  setChild(iter, *child);
1946  }
1947  }
1948  if (child) child->modifyValue(xyz, op);
1949 }
1950 
1951 template<typename ChildT>
1952 template<typename ModifyOp, typename AccessorT>
1953 inline void
1954 RootNode<ChildT>::modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT& acc)
1955 {
1956  ChildT* child = nullptr;
1957  MapIter iter = this->findCoord(xyz);
1958  if (iter == mTable.end()) {
1959  child = new ChildT(xyz, mBackground);
1960  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1961  } else if (isChild(iter)) {
1962  child = &getChild(iter);
1963  } else {
1964  // Need to create a child if the tile is inactive,
1965  // in order to activate voxel (x, y, z).
1966  bool createChild = isTileOff(iter);
1967  if (!createChild) {
1968  // Need to create a child if applying the functor
1969  // to the tile value produces a different value.
1970  const ValueType& tileVal = getTile(iter).value;
1971  ValueType modifiedVal = tileVal;
1972  op(modifiedVal);
1973  createChild = !math::isExactlyEqual(tileVal, modifiedVal);
1974  }
1975  if (createChild) {
1976  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1977  setChild(iter, *child);
1978  }
1979  }
1980  if (child) {
1981  acc.insert(xyz, child);
1982  child->modifyValueAndCache(xyz, op, acc);
1983  }
1984 }
1985 
1986 
1987 template<typename ChildT>
1988 template<typename ModifyOp>
1989 inline void
1991 {
1992  ChildT* child = nullptr;
1993  MapIter iter = this->findCoord(xyz);
1994  if (iter == mTable.end()) {
1995  child = new ChildT(xyz, mBackground);
1996  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1997  } else if (isChild(iter)) {
1998  child = &getChild(iter);
1999  } else {
2000  const Tile& tile = getTile(iter);
2001  bool modifiedState = tile.active;
2002  ValueType modifiedVal = tile.value;
2003  op(modifiedVal, modifiedState);
2004  // Need to create a child if applying the functor to the tile
2005  // produces a different value or active state.
2006  if (modifiedState != tile.active || !math::isExactlyEqual(modifiedVal, tile.value)) {
2007  child = new ChildT(xyz, tile.value, tile.active);
2008  setChild(iter, *child);
2009  }
2010  }
2011  if (child) child->modifyValueAndActiveState(xyz, op);
2012 }
2013 
2014 template<typename ChildT>
2015 template<typename ModifyOp, typename AccessorT>
2016 inline void
2018  const Coord& xyz, const ModifyOp& op, AccessorT& acc)
2019 {
2020  ChildT* child = nullptr;
2021  MapIter iter = this->findCoord(xyz);
2022  if (iter == mTable.end()) {
2023  child = new ChildT(xyz, mBackground);
2024  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2025  } else if (isChild(iter)) {
2026  child = &getChild(iter);
2027  } else {
2028  const Tile& tile = getTile(iter);
2029  bool modifiedState = tile.active;
2030  ValueType modifiedVal = tile.value;
2031  op(modifiedVal, modifiedState);
2032  // Need to create a child if applying the functor to the tile
2033  // produces a different value or active state.
2034  if (modifiedState != tile.active || !math::isExactlyEqual(modifiedVal, tile.value)) {
2035  child = new ChildT(xyz, tile.value, tile.active);
2036  setChild(iter, *child);
2037  }
2038  }
2039  if (child) {
2040  acc.insert(xyz, child);
2041  child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2042  }
2043 }
2044 
2045 
2046 template<typename ChildT>
2047 inline bool
2049 {
2050  MapCIter iter = this->findCoord(xyz);
2051  if (iter == mTable.end()) {
2052  value = mBackground;
2053  return false;
2054  } else if (isChild(iter)) {
2055  return getChild(iter).probeValue(xyz, value);
2056  }
2057  value = getTile(iter).value;
2058  return isTileOn(iter);
2059 }
2060 
2061 template<typename ChildT>
2062 template<typename AccessorT>
2063 inline bool
2064 RootNode<ChildT>::probeValueAndCache(const Coord& xyz, ValueType& value, AccessorT& acc) const
2065 {
2066  MapCIter iter = this->findCoord(xyz);
2067  if (iter == mTable.end()) {
2068  value = mBackground;
2069  return false;
2070  } else if (isChild(iter)) {
2071  acc.insert(xyz, &getChild(iter));
2072  return getChild(iter).probeValueAndCache(xyz, value, acc);
2073  }
2074  value = getTile(iter).value;
2075  return isTileOn(iter);
2076 }
2077 
2078 
2080 
2081 
2082 template<typename ChildT>
2083 inline void
2084 RootNode<ChildT>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
2085 {
2086  if (bbox.empty()) return;
2087 
2088  // Iterate over the fill region in axis-aligned, tile-sized chunks.
2089  // (The first and last chunks along each axis might be smaller than a tile.)
2090  Coord xyz, tileMax;
2091  for (int x = bbox.min().x(); x <= bbox.max().x(); x = tileMax.x() + 1) {
2092  xyz.setX(x);
2093  for (int y = bbox.min().y(); y <= bbox.max().y(); y = tileMax.y() + 1) {
2094  xyz.setY(y);
2095  for (int z = bbox.min().z(); z <= bbox.max().z(); z = tileMax.z() + 1) {
2096  xyz.setZ(z);
2097 
2098  // Get the bounds of the tile that contains voxel (x, y, z).
2099  Coord tileMin = coordToKey(xyz);
2100  tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2101 
2102  if (xyz != tileMin || Coord::lessThan(bbox.max(), tileMax)) {
2103  // If the box defined by (xyz, bbox.max()) doesn't completely enclose
2104  // the tile to which xyz belongs, create a child node (or retrieve
2105  // the existing one).
2106  ChildT* child = nullptr;
2107  MapIter iter = this->findKey(tileMin);
2108  if (iter == mTable.end()) {
2109  // No child or tile exists. Create a child and initialize it
2110  // with the background value.
2111  child = new ChildT(xyz, mBackground);
2112  mTable[tileMin] = NodeStruct(*child);
2113  } else if (isTile(iter)) {
2114  // Replace the tile with a newly-created child that is filled
2115  // with the tile's value and active state.
2116  const Tile& tile = getTile(iter);
2117  child = new ChildT(xyz, tile.value, tile.active);
2118  mTable[tileMin] = NodeStruct(*child);
2119  } else if (isChild(iter)) {
2120  child = &getChild(iter);
2121  }
2122  // Forward the fill request to the child.
2123  if (child) {
2124  const Coord tmp = Coord::minComponent(bbox.max(), tileMax);
2125  child->fill(CoordBBox(xyz, tmp), value, active);
2126  }
2127  } else {
2128  // If the box given by (xyz, bbox.max()) completely encloses
2129  // the tile to which xyz belongs, create the tile (if it
2130  // doesn't already exist) and give it the fill value.
2131  MapIter iter = this->findOrAddCoord(tileMin);
2132  setTile(iter, Tile(value, active));
2133  }
2134  }
2135  }
2136  }
2137 }
2138 
2139 
2140 template<typename ChildT>
2141 inline void
2142 RootNode<ChildT>::denseFill(const CoordBBox& bbox, const ValueType& value, bool active)
2143 {
2144  if (bbox.empty()) return;
2145 
2146  if (active && mTable.empty()) {
2147  // If this tree is empty, then a sparse fill followed by (threaded)
2148  // densification of active tiles is the more efficient approach.
2149  sparseFill(bbox, value, active);
2150  voxelizeActiveTiles(/*threaded=*/true);
2151  return;
2152  }
2153 
2154  // Iterate over the fill region in axis-aligned, tile-sized chunks.
2155  // (The first and last chunks along each axis might be smaller than a tile.)
2156  Coord xyz, tileMin, tileMax;
2157  for (int x = bbox.min().x(); x <= bbox.max().x(); x = tileMax.x() + 1) {
2158  xyz.setX(x);
2159  for (int y = bbox.min().y(); y <= bbox.max().y(); y = tileMax.y() + 1) {
2160  xyz.setY(y);
2161  for (int z = bbox.min().z(); z <= bbox.max().z(); z = tileMax.z() + 1) {
2162  xyz.setZ(z);
2163 
2164  // Get the bounds of the tile that contains voxel (x, y, z).
2165  tileMin = coordToKey(xyz);
2166  tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2167 
2168  // Retrieve the table entry for the tile that contains xyz,
2169  // or, if there is no table entry, add a background tile.
2170  const auto iter = findOrAddCoord(tileMin);
2171 
2172  if (isTile(iter)) {
2173  // If the table entry is a tile, replace it with a child node
2174  // that is filled with the tile's value and active state.
2175  const auto& tile = getTile(iter);
2176  auto* child = new ChildT{tileMin, tile.value, tile.active};
2177  setChild(iter, *child);
2178  }
2179  // Forward the fill request to the child.
2180  getChild(iter).denseFill(bbox, value, active);
2181  }
2182  }
2183  }
2184 }
2185 
2186 
2188 
2189 
2190 template<typename ChildT>
2191 inline void
2193 {
2194  // There is little point in threading over the root table since each tile
2195  // spans a huge index space (by default 4096^3) and hence we expect few
2196  // active tiles if any at all. In fact, you're very likely to run out of
2197  // memory if this method is called on a tree with root-level active tiles!
2198  for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2199  if (this->isTileOff(i)) continue;
2200  ChildT* child = i->second.child;
2201  if (child == nullptr) {
2202  // If this table entry is an active tile (i.e., not off and not a child node),
2203  // replace it with a child node filled with active tiles of the same value.
2204  child = new ChildT{i->first, this->getTile(i).value, true};
2205  i->second.child = child;
2206  }
2207  child->voxelizeActiveTiles(threaded);
2208  }
2209 }
2210 
2211 
2213 
2214 
2215 template<typename ChildT>
2216 template<typename DenseT>
2217 inline void
2218 RootNode<ChildT>::copyToDense(const CoordBBox& bbox, DenseT& dense) const
2219 {
2220  using DenseValueType = typename DenseT::ValueType;
2221 
2222  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2223  const Coord& min = dense.bbox().min();
2224  CoordBBox nodeBBox;
2225  for (Coord xyz = bbox.min(); xyz[0] <= bbox.max()[0]; xyz[0] = nodeBBox.max()[0] + 1) {
2226  for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] = nodeBBox.max()[1] + 1) {
2227  for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] = nodeBBox.max()[2] + 1) {
2228 
2229  // Get the coordinate bbox of the child node that contains voxel xyz.
2230  nodeBBox = CoordBBox::createCube(coordToKey(xyz), ChildT::DIM);
2231 
2232  // Get the coordinate bbox of the interection of inBBox and nodeBBox
2233  CoordBBox sub(xyz, Coord::minComponent(bbox.max(), nodeBBox.max()));
2234 
2235  MapCIter iter = this->findKey(nodeBBox.min());
2236  if (iter != mTable.end() && isChild(iter)) {//is a child
2237  getChild(iter).copyToDense(sub, dense);
2238  } else {//is background or a tile value
2239  const ValueType value = iter==mTable.end() ? mBackground : getTile(iter).value;
2240  sub.translate(-min);
2241  DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
2242  for (Int32 x=sub.min()[0], ex=sub.max()[0]+1; x<ex; ++x) {
2243  DenseValueType* a1 = a0 + x*xStride;
2244  for (Int32 y=sub.min()[1], ey=sub.max()[1]+1; y<ey; ++y) {
2245  DenseValueType* a2 = a1 + y*yStride;
2246  for (Int32 z=sub.min()[2], ez=sub.max()[2]+1; z<ez; ++z, a2 += zStride) {
2247  *a2 = DenseValueType(value);
2248  }
2249  }
2250  }
2251  }
2252  }
2253  }
2254  }
2255 }
2256 
2258 
2259 
2260 template<typename ChildT>
2261 inline bool
2262 RootNode<ChildT>::writeTopology(std::ostream& os, bool toHalf) const
2263 {
2264  if (!toHalf) {
2265  os.write(reinterpret_cast<const char*>(&mBackground), sizeof(ValueType));
2266  } else {
2267  ValueType truncatedVal = io::truncateRealToHalf(mBackground);
2268  os.write(reinterpret_cast<const char*>(&truncatedVal), sizeof(ValueType));
2269  }
2270  io::setGridBackgroundValuePtr(os, &mBackground);
2271 
2272  const Index numTiles = this->getTileCount(), numChildren = this->childCount();
2273  os.write(reinterpret_cast<const char*>(&numTiles), sizeof(Index));
2274  os.write(reinterpret_cast<const char*>(&numChildren), sizeof(Index));
2275 
2276  if (numTiles == 0 && numChildren == 0) return false;
2277 
2278  // Write tiles.
2279  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2280  if (isChild(i)) continue;
2281  os.write(reinterpret_cast<const char*>(i->first.asPointer()), 3 * sizeof(Int32));
2282  os.write(reinterpret_cast<const char*>(&getTile(i).value), sizeof(ValueType));
2283  os.write(reinterpret_cast<const char*>(&getTile(i).active), sizeof(bool));
2284  }
2285  // Write child nodes.
2286  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2287  if (isTile(i)) continue;
2288  os.write(reinterpret_cast<const char*>(i->first.asPointer()), 3 * sizeof(Int32));
2289  getChild(i).writeTopology(os, toHalf);
2290  }
2291 
2292  return true; // not empty
2293 }
2294 
2295 
2296 template<typename ChildT>
2297 inline bool
2298 RootNode<ChildT>::readTopology(std::istream& is, bool fromHalf)
2299 {
2300  // Delete the existing tree.
2301  this->clear();
2302 
2304  // Read and convert an older-format RootNode.
2305 
2306  // For backward compatibility with older file formats, read both
2307  // outside and inside background values.
2308  is.read(reinterpret_cast<char*>(&mBackground), sizeof(ValueType));
2309  ValueType inside;
2310  is.read(reinterpret_cast<char*>(&inside), sizeof(ValueType));
2311 
2312  io::setGridBackgroundValuePtr(is, &mBackground);
2313 
2314  // Read the index range.
2315  Coord rangeMin, rangeMax;
2316  is.read(reinterpret_cast<char*>(rangeMin.asPointer()), 3 * sizeof(Int32));
2317  is.read(reinterpret_cast<char*>(rangeMax.asPointer()), 3 * sizeof(Int32));
2318 
2319  this->initTable();
2320  Index tableSize = 0, log2Dim[4] = { 0, 0, 0, 0 };
2321  Int32 offset[3];
2322  for (int i = 0; i < 3; ++i) {
2323  offset[i] = rangeMin[i] >> ChildT::TOTAL;
2324  rangeMin[i] = offset[i] << ChildT::TOTAL;
2325  log2Dim[i] = 1 + util::FindHighestOn((rangeMax[i] >> ChildT::TOTAL) - offset[i]);
2326  tableSize += log2Dim[i];
2327  rangeMax[i] = (((1 << log2Dim[i]) + offset[i]) << ChildT::TOTAL) - 1;
2328  }
2329  log2Dim[3] = log2Dim[1] + log2Dim[2];
2330  tableSize = 1U << tableSize;
2331 
2332  // Read masks.
2333  util::RootNodeMask childMask(tableSize), valueMask(tableSize);
2334  childMask.load(is);
2335  valueMask.load(is);
2336 
2337  // Read child nodes/values.
2338  for (Index i = 0; i < tableSize; ++i) {
2339  // Compute origin = offset2coord(i).
2340  Index n = i;
2341  Coord origin;
2342  origin[0] = (n >> log2Dim[3]) + offset[0];
2343  n &= (1U << log2Dim[3]) - 1;
2344  origin[1] = (n >> log2Dim[2]) + offset[1];
2345  origin[2] = (n & ((1U << log2Dim[2]) - 1)) + offset[1];
2346  origin <<= ChildT::TOTAL;
2347 
2348  if (childMask.isOn(i)) {
2349  // Read in and insert a child node.
2350  ChildT* child = new ChildT(PartialCreate(), origin, mBackground);
2351  child->readTopology(is);
2352  mTable[origin] = NodeStruct(*child);
2353  } else {
2354  // Read in a tile value and insert a tile, but only if the value
2355  // is either active or non-background.
2356  ValueType value;
2357  is.read(reinterpret_cast<char*>(&value), sizeof(ValueType));
2358  if (valueMask.isOn(i) || (!math::isApproxEqual(value, mBackground))) {
2359  mTable[origin] = NodeStruct(Tile(value, valueMask.isOn(i)));
2360  }
2361  }
2362  }
2363  return true;
2364  }
2365 
2366  // Read a RootNode that was stored in the current format.
2367 
2368  is.read(reinterpret_cast<char*>(&mBackground), sizeof(ValueType));
2369  io::setGridBackgroundValuePtr(is, &mBackground);
2370 
2371  Index numTiles = 0, numChildren = 0;
2372  is.read(reinterpret_cast<char*>(&numTiles), sizeof(Index));
2373  is.read(reinterpret_cast<char*>(&numChildren), sizeof(Index));
2374 
2375  if (numTiles == 0 && numChildren == 0) return false;
2376 
2377  Int32 vec[3];
2378  ValueType value;
2379  bool active;
2380 
2381  // Read tiles.
2382  for (Index n = 0; n < numTiles; ++n) {
2383  is.read(reinterpret_cast<char*>(vec), 3 * sizeof(Int32));
2384  is.read(reinterpret_cast<char*>(&value), sizeof(ValueType));
2385  is.read(reinterpret_cast<char*>(&active), sizeof(bool));
2386  mTable[Coord(vec)] = NodeStruct(Tile(value, active));
2387  }
2388 
2389  // Read child nodes.
2390  for (Index n = 0; n < numChildren; ++n) {
2391  is.read(reinterpret_cast<char*>(vec), 3 * sizeof(Int32));
2392  Coord origin(vec);
2393  ChildT* child = new ChildT(PartialCreate(), origin, mBackground);
2394  child->readTopology(is, fromHalf);
2395  mTable[Coord(vec)] = NodeStruct(*child);
2396  }
2397 
2398  return true; // not empty
2399 }
2400 
2401 
2402 template<typename ChildT>
2403 inline void
2404 RootNode<ChildT>::writeBuffers(std::ostream& os, bool toHalf) const
2405 {
2406  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2407  if (isChild(i)) getChild(i).writeBuffers(os, toHalf);
2408  }
2409 }
2410 
2411 
2412 template<typename ChildT>
2413 inline void
2414 RootNode<ChildT>::readBuffers(std::istream& is, bool fromHalf)
2415 {
2416  for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2417  if (isChild(i)) getChild(i).readBuffers(is, fromHalf);
2418  }
2419 }
2420 
2421 
2422 template<typename ChildT>
2423 inline void
2424 RootNode<ChildT>::readBuffers(std::istream& is, const CoordBBox& clipBBox, bool fromHalf)
2425 {
2426  const Tile bgTile(mBackground, /*active=*/false);
2427 
2428  for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2429  if (isChild(i)) {
2430  // Stream in and clip the branch rooted at this child.
2431  // (We can't skip over children that lie outside the clipping region,
2432  // because buffers are serialized in depth-first order and need to be
2433  // unserialized in the same order.)
2434  ChildT& child = getChild(i);
2435  child.readBuffers(is, clipBBox, fromHalf);
2436  }
2437  }
2438  // Clip root-level tiles and prune children that were clipped.
2439  this->clip(clipBBox);
2440 }
2441 
2442 
2444 
2445 
2446 template<typename ChildT>
2447 inline void
2449 {
2450  const Tile bgTile(mBackground, /*active=*/false);
2451 
2452  // Iterate over a copy of this node's table so that we can modify the original.
2453  // (Copying the table copies child node pointers, not the nodes themselves.)
2454  MapType copyOfTable(mTable);
2455  for (MapIter i = copyOfTable.begin(), e = copyOfTable.end(); i != e; ++i) {
2456  const Coord& xyz = i->first; // tile or child origin
2457  CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1)); // tile or child bounds
2458  if (!clipBBox.hasOverlap(tileBBox)) {
2459  // This table entry lies completely outside the clipping region. Delete it.
2460  setTile(this->findCoord(xyz), bgTile); // delete any existing child node first
2461  mTable.erase(xyz);
2462  } else if (!clipBBox.isInside(tileBBox)) {
2463  // This table entry does not lie completely inside the clipping region
2464  // and must be clipped.
2465  if (isChild(i)) {
2466  getChild(i).clip(clipBBox, mBackground);
2467  } else {
2468  // Replace this tile with a background tile, then fill the clip region
2469  // with the tile's original value. (This might create a child branch.)
2470  tileBBox.intersect(clipBBox);
2471  const Tile& origTile = getTile(i);
2472  setTile(this->findCoord(xyz), bgTile);
2473  this->sparseFill(tileBBox, origTile.value, origTile.active);
2474  }
2475  } else {
2476  // This table entry lies completely inside the clipping region. Leave it intact.
2477  }
2478  }
2479  this->prune(); // also erases root-level background tiles
2480 }
2481 
2482 
2484 
2485 
2486 template<typename ChildT>
2487 inline void
2489 {
2490  bool state = false;
2491  ValueType value = zeroVal<ValueType>();
2492  for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2493  if (this->isTile(i)) continue;
2494  this->getChild(i).prune(tolerance);
2495  if (this->getChild(i).isConstant(value, state, tolerance)) {
2496  this->setTile(i, Tile(value, state));
2497  }
2498  }
2499  this->eraseBackgroundTiles();
2500 }
2501 
2502 
2504 
2505 
2506 template<typename ChildT>
2507 template<typename NodeT>
2508 inline NodeT*
2509 RootNode<ChildT>::stealNode(const Coord& xyz, const ValueType& value, bool state)
2510 {
2511  if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2512  NodeT::LEVEL > ChildT::LEVEL) return nullptr;
2514  MapIter iter = this->findCoord(xyz);
2515  if (iter == mTable.end() || isTile(iter)) return nullptr;
2516  return (std::is_same<NodeT, ChildT>::value)
2517  ? reinterpret_cast<NodeT*>(&stealChild(iter, Tile(value, state)))
2518  : getChild(iter).template stealNode<NodeT>(xyz, value, state);
2520 }
2521 
2522 
2524 
2525 
2526 template<typename ChildT>
2527 inline void
2529 {
2530  if (leaf == nullptr) return;
2531  ChildT* child = nullptr;
2532  const Coord& xyz = leaf->origin();
2533  MapIter iter = this->findCoord(xyz);
2534  if (iter == mTable.end()) {
2535  if (ChildT::LEVEL>0) {
2536  child = new ChildT(xyz, mBackground, false);
2537  } else {
2538  child = reinterpret_cast<ChildT*>(leaf);
2539  }
2540  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2541  } else if (isChild(iter)) {
2542  if (ChildT::LEVEL>0) {
2543  child = &getChild(iter);
2544  } else {
2545  child = reinterpret_cast<ChildT*>(leaf);
2546  setChild(iter, *child);//this also deletes the existing child node
2547  }
2548  } else {//tile
2549  if (ChildT::LEVEL>0) {
2550  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2551  } else {
2552  child = reinterpret_cast<ChildT*>(leaf);
2553  }
2554  setChild(iter, *child);
2555  }
2556  child->addLeaf(leaf);
2557 }
2558 
2559 
2560 template<typename ChildT>
2561 template<typename AccessorT>
2562 inline void
2564 {
2565  if (leaf == nullptr) return;
2566  ChildT* child = nullptr;
2567  const Coord& xyz = leaf->origin();
2568  MapIter iter = this->findCoord(xyz);
2569  if (iter == mTable.end()) {
2570  if (ChildT::LEVEL>0) {
2571  child = new ChildT(xyz, mBackground, false);
2572  } else {
2573  child = reinterpret_cast<ChildT*>(leaf);
2574  }
2575  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2576  } else if (isChild(iter)) {
2577  if (ChildT::LEVEL>0) {
2578  child = &getChild(iter);
2579  } else {
2580  child = reinterpret_cast<ChildT*>(leaf);
2581  setChild(iter, *child);//this also deletes the existing child node
2582  }
2583  } else {//tile
2584  if (ChildT::LEVEL>0) {
2585  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2586  } else {
2587  child = reinterpret_cast<ChildT*>(leaf);
2588  }
2589  setChild(iter, *child);
2590  }
2591  acc.insert(xyz, child);
2592  child->addLeafAndCache(leaf, acc);
2593 }
2594 
2595 template<typename ChildT>
2596 inline bool
2598 {
2599  if (!child) return false;
2600  const Coord& xyz = child->origin();
2601  MapIter iter = this->findCoord(xyz);
2602  if (iter == mTable.end()) {//background
2603  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2604  } else {//child or tile
2605  setChild(iter, *child);//this also deletes the existing child node
2606  }
2607  return true;
2608 }
2609 
2610 template<typename ChildT>
2611 inline void
2612 RootNode<ChildT>::addTile(const Coord& xyz, const ValueType& value, bool state)
2613 {
2614  MapIter iter = this->findCoord(xyz);
2615  if (iter == mTable.end()) {//background
2616  mTable[this->coordToKey(xyz)] = NodeStruct(Tile(value, state));
2617  } else {//child or tile
2618  setTile(iter, Tile(value, state));//this also deletes the existing child node
2619  }
2620 }
2621 
2622 template<typename ChildT>
2623 inline void
2625  const ValueType& value, bool state)
2626 {
2627  if (LEVEL >= level) {
2628  MapIter iter = this->findCoord(xyz);
2629  if (iter == mTable.end()) {//background
2630  if (LEVEL > level) {
2631  ChildT* child = new ChildT(xyz, mBackground, false);
2632  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2633  child->addTile(level, xyz, value, state);
2634  } else {
2635  mTable[this->coordToKey(xyz)] = NodeStruct(Tile(value, state));
2636  }
2637  } else if (isChild(iter)) {//child
2638  if (LEVEL > level) {
2639  getChild(iter).addTile(level, xyz, value, state);
2640  } else {
2641  setTile(iter, Tile(value, state));//this also deletes the existing child node
2642  }
2643  } else {//tile
2644  if (LEVEL > level) {
2645  ChildT* child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2646  setChild(iter, *child);
2647  child->addTile(level, xyz, value, state);
2648  } else {
2649  setTile(iter, Tile(value, state));
2650  }
2651  }
2652  }
2653 }
2654 
2655 
2656 template<typename ChildT>
2657 template<typename AccessorT>
2658 inline void
2659 RootNode<ChildT>::addTileAndCache(Index level, const Coord& xyz, const ValueType& value,
2660  bool state, AccessorT& acc)
2661 {
2662  if (LEVEL >= level) {
2663  MapIter iter = this->findCoord(xyz);
2664  if (iter == mTable.end()) {//background
2665  if (LEVEL > level) {
2666  ChildT* child = new ChildT(xyz, mBackground, false);
2667  acc.insert(xyz, child);
2668  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2669  child->addTileAndCache(level, xyz, value, state, acc);
2670  } else {
2671  mTable[this->coordToKey(xyz)] = NodeStruct(Tile(value, state));
2672  }
2673  } else if (isChild(iter)) {//child
2674  if (LEVEL > level) {
2675  ChildT* child = &getChild(iter);
2676  acc.insert(xyz, child);
2677  child->addTileAndCache(level, xyz, value, state, acc);
2678  } else {
2679  setTile(iter, Tile(value, state));//this also deletes the existing child node
2680  }
2681  } else {//tile
2682  if (LEVEL > level) {
2683  ChildT* child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2684  acc.insert(xyz, child);
2685  setChild(iter, *child);
2686  child->addTileAndCache(level, xyz, value, state, acc);
2687  } else {
2688  setTile(iter, Tile(value, state));
2689  }
2690  }
2691  }
2692 }
2693 
2694 
2696 
2697 
2698 template<typename ChildT>
2699 inline typename ChildT::LeafNodeType*
2701 {
2702  ChildT* child = nullptr;
2703  MapIter iter = this->findCoord(xyz);
2704  if (iter == mTable.end()) {
2705  child = new ChildT(xyz, mBackground, false);
2706  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2707  } else if (isChild(iter)) {
2708  child = &getChild(iter);
2709  } else {
2710  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2711  setChild(iter, *child);
2712  }
2713  return child->touchLeaf(xyz);
2714 }
2715 
2716 
2717 template<typename ChildT>
2718 template<typename AccessorT>
2719 inline typename ChildT::LeafNodeType*
2720 RootNode<ChildT>::touchLeafAndCache(const Coord& xyz, AccessorT& acc)
2721 {
2722  ChildT* child = nullptr;
2723  MapIter iter = this->findCoord(xyz);
2724  if (iter == mTable.end()) {
2725  child = new ChildT(xyz, mBackground, false);
2726  mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2727  } else if (isChild(iter)) {
2728  child = &getChild(iter);
2729  } else {
2730  child = new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2731  setChild(iter, *child);
2732  }
2733  acc.insert(xyz, child);
2734  return child->touchLeafAndCache(xyz, acc);
2735 }
2736 
2737 
2739 
2740 
2741 template<typename ChildT>
2742 template<typename NodeT>
2743 inline NodeT*
2745 {
2746  if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2747  NodeT::LEVEL > ChildT::LEVEL) return nullptr;
2749  MapIter iter = this->findCoord(xyz);
2750  if (iter == mTable.end() || isTile(iter)) return nullptr;
2751  ChildT* child = &getChild(iter);
2752  return (std::is_same<NodeT, ChildT>::value)
2753  ? reinterpret_cast<NodeT*>(child)
2754  : child->template probeNode<NodeT>(xyz);
2756 }
2757 
2758 
2759 template<typename ChildT>
2760 template<typename NodeT>
2761 inline const NodeT*
2763 {
2764  if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2765  NodeT::LEVEL > ChildT::LEVEL) return nullptr;
2767  MapCIter iter = this->findCoord(xyz);
2768  if (iter == mTable.end() || isTile(iter)) return nullptr;
2769  const ChildT* child = &getChild(iter);
2770  return (std::is_same<NodeT, ChildT>::value)
2771  ? reinterpret_cast<const NodeT*>(child)
2772  : child->template probeConstNode<NodeT>(xyz);
2774 }
2775 
2776 
2777 template<typename ChildT>
2778 inline typename ChildT::LeafNodeType*
2780 {
2781  return this->template probeNode<LeafNodeType>(xyz);
2782 }
2783 
2784 
2785 template<typename ChildT>
2786 inline const typename ChildT::LeafNodeType*
2788 {
2789  return this->template probeConstNode<LeafNodeType>(xyz);
2790 }
2791 
2792 
2793 template<typename ChildT>
2794 template<typename AccessorT>
2795 inline typename ChildT::LeafNodeType*
2796 RootNode<ChildT>::probeLeafAndCache(const Coord& xyz, AccessorT& acc)
2797 {
2798  return this->template probeNodeAndCache<LeafNodeType>(xyz, acc);
2799 }
2800 
2801 
2802 template<typename ChildT>
2803 template<typename AccessorT>
2804 inline const typename ChildT::LeafNodeType*
2805 RootNode<ChildT>::probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const
2806 {
2807  return this->template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
2808 }
2809 
2810 
2811 template<typename ChildT>
2812 template<typename AccessorT>
2813 inline const typename ChildT::LeafNodeType*
2814 RootNode<ChildT>::probeLeafAndCache(const Coord& xyz, AccessorT& acc) const
2815 {
2816  return this->probeConstLeafAndCache(xyz, acc);
2817 }
2818 
2819 
2820 template<typename ChildT>
2821 template<typename NodeT, typename AccessorT>
2822 inline NodeT*
2823 RootNode<ChildT>::probeNodeAndCache(const Coord& xyz, AccessorT& acc)
2824 {
2825  if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2826  NodeT::LEVEL > ChildT::LEVEL) return nullptr;
2828  MapIter iter = this->findCoord(xyz);
2829  if (iter == mTable.end() || isTile(iter)) return nullptr;
2830  ChildT* child = &getChild(iter);
2831  acc.insert(xyz, child);
2832  return (std::is_same<NodeT, ChildT>::value)
2833  ? reinterpret_cast<NodeT*>(child)
2834  : child->template probeNodeAndCache<NodeT>(xyz, acc);
2836 }
2837 
2838 
2839 template<typename ChildT>
2840 template<typename NodeT,typename AccessorT>
2841 inline const NodeT*
2842 RootNode<ChildT>::probeConstNodeAndCache(const Coord& xyz, AccessorT& acc) const
2843 {
2844  if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2845  NodeT::LEVEL > ChildT::LEVEL) return nullptr;
2847  MapCIter iter = this->findCoord(xyz);
2848  if (iter == mTable.end() || isTile(iter)) return nullptr;
2849  const ChildT* child = &getChild(iter);
2850  acc.insert(xyz, child);
2851  return (std::is_same<NodeT, ChildT>::value)
2852  ? reinterpret_cast<const NodeT*>(child)
2853  : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
2855 }
2856 
2857 
2859 
2860 template<typename ChildT>
2861 template<typename ArrayT>
2862 inline void
2864 {
2865  using NodePtr = typename ArrayT::value_type;
2866  static_assert(std::is_pointer<NodePtr>::value,
2867  "argument to getNodes() must be a pointer array");
2868  using NodeType = typename std::remove_pointer<NodePtr>::type;
2869  using NonConstNodeType = typename std::remove_const<NodeType>::type;
2870  static_assert(NodeChainType::template Contains<NonConstNodeType>,
2871  "can't extract non-const nodes from a const tree");
2872  using ArrayChildT = typename std::conditional<
2873  std::is_const<NodeType>::value, const ChildT, ChildT>::type;
2874 
2875  for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2876  if (ChildT* child = iter->second.child) {
2878  if (std::is_same<NodePtr, ArrayChildT*>::value) {
2879  array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
2880  } else {
2881  child->getNodes(array);//descent
2882  }
2884  }
2885  }
2886 }
2887 
2888 template<typename ChildT>
2889 template<typename ArrayT>
2890 inline void
2891 RootNode<ChildT>::getNodes(ArrayT& array) const
2892 {
2893  using NodePtr = typename ArrayT::value_type;
2894  static_assert(std::is_pointer<NodePtr>::value,
2895  "argument to getNodes() must be a pointer array");
2896  using NodeType = typename std::remove_pointer<NodePtr>::type;
2897  static_assert(std::is_const<NodeType>::value,
2898  "argument to getNodes() must be an array of const node pointers");
2899  using NonConstNodeType = typename std::remove_const<NodeType>::type;
2900  static_assert(NodeChainType::template Contains<NonConstNodeType>,
2901  "can't extract non-const nodes from a const tree");
2902 
2903  for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2904  if (const ChildNodeType *child = iter->second.child) {
2906  if (std::is_same<NodePtr, const ChildT*>::value) {
2907  array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
2908  } else {
2909  child->getNodes(array);//descent
2910  }
2912  }
2913  }
2914 }
2915 
2917 
2918 template<typename ChildT>
2919 template<typename ArrayT>
2920 inline void
2921 RootNode<ChildT>::stealNodes(ArrayT& array, const ValueType& value, bool state)
2922 {
2923  using NodePtr = typename ArrayT::value_type;
2924  static_assert(std::is_pointer<NodePtr>::value,
2925  "argument to stealNodes() must be a pointer array");
2926  using NodeType = typename std::remove_pointer<NodePtr>::type;
2927  using NonConstNodeType = typename std::remove_const<NodeType>::type;
2928  static_assert(NodeChainType::template Contains<NonConstNodeType>,
2929  "can't extract non-const nodes from a const tree");
2930  using ArrayChildT = typename std::conditional<
2931  std::is_const<NodeType>::value, const ChildT, ChildT>::type;
2932 
2933  for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2934  if (ChildT* child = iter->second.child) {
2936  if (std::is_same<NodePtr, ArrayChildT*>::value) {
2937  array.push_back(reinterpret_cast<NodePtr>(&stealChild(iter, Tile(value, state))));
2938  } else {
2939  child->stealNodes(array, value, state);//descent
2940  }
2942  }
2943  }
2944 }
2945 
2946 
2948 
2949 
2950 template<typename ChildT>
2951 template<MergePolicy Policy>
2952 inline void
2954 {
2956 
2957  switch (Policy) {
2958 
2959  default:
2960  case MERGE_ACTIVE_STATES:
2961  for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
2962  MapIter j = mTable.find(i->first);
2963  if (other.isChild(i)) {
2964  if (j == mTable.end()) { // insert other node's child
2965  ChildNodeType& child = stealChild(i, Tile(other.mBackground, /*on=*/false));
2966  child.resetBackground(other.mBackground, mBackground);
2967  mTable[i->first] = NodeStruct(child);
2968  } else if (isTile(j)) {
2969  if (isTileOff(j)) { // replace inactive tile with other node's child
2970  ChildNodeType& child = stealChild(i, Tile(other.mBackground, /*on=*/false));
2971  child.resetBackground(other.mBackground, mBackground);
2972  setChild(j, child);
2973  }
2974  } else { // merge both child nodes
2975  getChild(j).template merge<MERGE_ACTIVE_STATES>(getChild(i),
2976  other.mBackground, mBackground);
2977  }
2978  } else if (other.isTileOn(i)) {
2979  if (j == mTable.end()) { // insert other node's active tile
2980  mTable[i->first] = i->second;
2981  } else if (!isTileOn(j)) {
2982  // Replace anything except an active tile with the other node's active tile.
2983  setTile(j, Tile(other.getTile(i).value, true));
2984  }
2985  }
2986  }
2987  break;
2988 
2989  case MERGE_NODES:
2990  for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
2991  MapIter j = mTable.find(i->first);
2992  if (other.isChild(i)) {
2993  if (j == mTable.end()) { // insert other node's child
2994  ChildNodeType& child = stealChild(i, Tile(other.mBackground, /*on=*/false));
2995  child.resetBackground(other.mBackground, mBackground);
2996  mTable[i->first] = NodeStruct(child);
2997  } else if (isTile(j)) { // replace tile with other node's child
2998  ChildNodeType& child = stealChild(i, Tile(other.mBackground, /*on=*/false));
2999  child.resetBackground(other.mBackground, mBackground);
3000  setChild(j, child);
3001  } else { // merge both child nodes
3002  getChild(j).template merge<MERGE_NODES>(
3003  getChild(i), other.mBackground, mBackground);
3004  }
3005  }
3006  }
3007  break;
3008 
3010  for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3011  MapIter j = mTable.find(i->first);
3012  if (other.isChild(i)) {
3013  if (j == mTable.end()) {
3014  // Steal and insert the other node's child.
3015  ChildNodeType& child = stealChild(i, Tile(other.mBackground, /*on=*/false));
3016  child.resetBackground(other.mBackground, mBackground);
3017  mTable[i->first] = NodeStruct(child);
3018  } else if (isTile(j)) {
3019  // Replace this node's tile with the other node's child.
3020  ChildNodeType& child = stealChild(i, Tile(other.mBackground, /*on=*/false));
3021  child.resetBackground(other.mBackground, mBackground);
3022  const Tile tile = getTile(j);
3023  setChild(j, child);
3024  if (tile.active) {
3025  // Merge the other node's child with this node's active tile.
3026  child.template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3027  tile.value, tile.active);
3028  }
3029  } else /*if (isChild(j))*/ {
3030  // Merge the other node's child into this node's child.
3031  getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(getChild(i),
3032  other.mBackground, mBackground);
3033  }
3034  } else if (other.isTileOn(i)) {
3035  if (j == mTable.end()) {
3036  // Insert a copy of the other node's active tile.
3037  mTable[i->first] = i->second;
3038  } else if (isTileOff(j)) {
3039  // Replace this node's inactive tile with a copy of the other's active tile.
3040  setTile(j, Tile(other.getTile(i).value, true));
3041  } else if (isChild(j)) {
3042  // Merge the other node's active tile into this node's child.
3043  const Tile& tile = getTile(i);
3044  getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3045  tile.value, tile.active);
3046  }
3047  } // else if (other.isTileOff(i)) {} // ignore the other node's inactive tiles
3048  }
3049  break;
3050  }
3051 
3052  // Empty the other tree so as not to leave it in a partially cannibalized state.
3053  other.clear();
3054 
3056 }
3057 
3058 
3060 
3061 
3062 template<typename ChildT>
3063 template<typename OtherChildType>
3064 inline void
3066 {
3067  using OtherRootT = RootNode<OtherChildType>;
3068  using OtherCIterT = typename OtherRootT::MapCIter;
3069 
3070  enforceSameConfiguration(other);
3071 
3072  for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3073  MapIter j = mTable.find(i->first);
3074  if (other.isChild(i)) {
3075  if (j == mTable.end()) { // create child branch with identical topology
3076  mTable[i->first] = NodeStruct(
3077  *(new ChildT(other.getChild(i), mBackground, TopologyCopy())));
3078  } else if (this->isChild(j)) { // union with child branch
3079  this->getChild(j).topologyUnion(other.getChild(i));
3080  } else {// this is a tile so replace it with a child branch with identical topology
3081  ChildT* child = new ChildT(
3082  other.getChild(i), this->getTile(j).value, TopologyCopy());
3083  if (this->isTileOn(j)) child->setValuesOn();//this is an active tile
3084  this->setChild(j, *child);
3085  }
3086  } else if (other.isTileOn(i)) { // other is an active tile
3087  if (j == mTable.end()) { // insert an active tile
3088  mTable[i->first] = NodeStruct(Tile(mBackground, true));
3089  } else if (this->isChild(j)) {
3090  this->getChild(j).setValuesOn();
3091  } else if (this->isTileOff(j)) {
3092  this->setTile(j, Tile(this->getTile(j).value, true));
3093  }
3094  }
3095  }
3096 }
3097 
3098 template<typename ChildT>
3099 template<typename OtherChildType>
3100 inline void
3102 {
3103  using OtherRootT = RootNode<OtherChildType>;
3104  using OtherCIterT = typename OtherRootT::MapCIter;
3105 
3106  enforceSameConfiguration(other);
3107 
3108  std::set<Coord> tmp;//keys to erase
3109  for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3110  OtherCIterT j = other.mTable.find(i->first);
3111  if (this->isChild(i)) {
3112  if (j == other.mTable.end() || other.isTileOff(j)) {
3113  tmp.insert(i->first);//delete child branch
3114  } else if (other.isChild(j)) { // intersect with child branch
3115  this->getChild(i).topologyIntersection(other.getChild(j), mBackground);
3116  }
3117  } else if (this->isTileOn(i)) {
3118  if (j == other.mTable.end() || other.isTileOff(j)) {
3119  this->setTile(i, Tile(this->getTile(i).value, false));//turn inactive
3120  } else if (other.isChild(j)) { //replace with a child branch with identical topology
3121  ChildT* child =
3122  new ChildT(other.getChild(j), this->getTile(i).value, TopologyCopy());
3123  this->setChild(i, *child);
3124  }
3125  }
3126  }
3127  for (std::set<Coord>::iterator i = tmp.begin(), e = tmp.end(); i != e; ++i) {
3128  MapIter it = this->findCoord(*i);
3129  setTile(it, Tile()); // delete any existing child node first
3130  mTable.erase(it);
3131  }
3132 }
3133 
3134 template<typename ChildT>
3135 template<typename OtherChildType>
3136 inline void
3138 {
3139  using OtherRootT = RootNode<OtherChildType>;
3140  using OtherCIterT = typename OtherRootT::MapCIter;
3141 
3142  enforceSameConfiguration(other);
3143 
3144  for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3145  MapIter j = mTable.find(i->first);
3146  if (other.isChild(i)) {
3147  if (j == mTable.end() || this->isTileOff(j)) {
3148  //do nothing
3149  } else if (this->isChild(j)) { // difference with child branch
3150  this->getChild(j).topologyDifference(other.getChild(i), mBackground);
3151  } else if (this->isTileOn(j)) {
3152  // this is an active tile so create a child node and descent
3153  ChildT* child = new ChildT(j->first, this->getTile(j).value, true);
3154  child->topologyDifference(other.getChild(i), mBackground);
3155  this->setChild(j, *child);
3156  }
3157  } else if (other.isTileOn(i)) { // other is an active tile
3158  if (j == mTable.end() || this->isTileOff(j)) {
3159  // do nothing
3160  } else if (this->isChild(j)) {
3161  setTile(j, Tile()); // delete any existing child node first
3162  mTable.erase(j);
3163  } else if (this->isTileOn(j)) {
3164  this->setTile(j, Tile(this->getTile(j).value, false));
3165  }
3166  }
3167  }
3168 }
3169 
3171 
3172 
3173 template<typename ChildT>
3174 template<typename CombineOp>
3175 inline void
3176 RootNode<ChildT>::combine(RootNode& other, CombineOp& op, bool prune)
3177 {
3179 
3180  CoordSet keys;
3181  this->insertKeys(keys);
3182  other.insertKeys(keys);
3183 
3184  for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3185  MapIter iter = findOrAddCoord(*i), otherIter = other.findOrAddCoord(*i);
3186  if (isTile(iter) && isTile(otherIter)) {
3187  // Both this node and the other node have constant values (tiles).
3188  // Combine the two values and store the result as this node's new tile value.
3189  op(args.setARef(getTile(iter).value)
3190  .setAIsActive(isTileOn(iter))
3191  .setBRef(getTile(otherIter).value)
3192  .setBIsActive(isTileOn(otherIter)));
3193  setTile(iter, Tile(args.result(), args.resultIsActive()));
3194 
3195  } else if (isChild(iter) && isTile(otherIter)) {
3196  // Combine this node's child with the other node's constant value.
3197  ChildT& child = getChild(iter);
3198  child.combine(getTile(otherIter).value, isTileOn(otherIter), op);
3199 
3200  } else if (isTile(iter) && isChild(otherIter)) {
3201  // Combine this node's constant value with the other node's child,
3202  // but use a new functor in which the A and B values are swapped,
3203  // since the constant value is the A value, not the B value.
3205  ChildT& child = getChild(otherIter);
3206  child.combine(getTile(iter).value, isTileOn(iter), swappedOp);
3207 
3208  // Steal the other node's child.
3209  setChild(iter, stealChild(otherIter, Tile()));
3210 
3211  } else /*if (isChild(iter) && isChild(otherIter))*/ {
3212  // Combine this node's child with the other node's child.
3213  ChildT &child = getChild(iter), &otherChild = getChild(otherIter);
3214  child.combine(otherChild, op);
3215  }
3216  if (prune && isChild(iter)) getChild(iter).prune();
3217  }
3218 
3219  // Combine background values.
3220  op(args.setARef(mBackground).setBRef(other.mBackground));
3221  mBackground = args.result();
3222 
3223  // Empty the other tree so as not to leave it in a partially cannibalized state.
3224  other.clear();
3225 }
3226 
3227 
3229 
3230 
3231 // This helper class is a friend of RootNode and is needed so that combine2
3232 // can be specialized for compatible and incompatible pairs of RootNode types.
3233 template<typename CombineOp, typename RootT, typename OtherRootT, bool Compatible = false>
3235 {
3236  static inline void combine2(RootT& self, const RootT&, const OtherRootT& other1,
3237  CombineOp&, bool)
3238  {
3239  // If the two root nodes have different configurations or incompatible ValueTypes,
3240  // throw an exception.
3241  self.enforceSameConfiguration(other1);
3242  self.enforceCompatibleValueTypes(other1);
3243  // One of the above two tests should throw, so we should never get here:
3244  std::ostringstream ostr;
3245  ostr << "cannot combine a " << typeid(OtherRootT).name()
3246  << " into a " << typeid(RootT).name();
3247  OPENVDB_THROW(TypeError, ostr.str());
3248  }
3249 };
3250 
3251 // Specialization for root nodes of compatible types
3252 template<typename CombineOp, typename RootT, typename OtherRootT>
3253 struct RootNodeCombineHelper<CombineOp, RootT, OtherRootT, /*Compatible=*/true>
3254 {
3255  static inline void combine2(RootT& self, const RootT& other0, const OtherRootT& other1,
3256  CombineOp& op, bool prune)
3257  {
3258  self.doCombine2(other0, other1, op, prune);
3259  }
3260 };
3261 
3262 
3263 template<typename ChildT>
3264 template<typename CombineOp, typename OtherRootNode>
3265 inline void
3266 RootNode<ChildT>::combine2(const RootNode& other0, const OtherRootNode& other1,
3267  CombineOp& op, bool prune)
3268 {
3269  using OtherValueType = typename OtherRootNode::ValueType;
3270  static const bool compatible = (SameConfiguration<OtherRootNode>::value
3271  && CanConvertType</*from=*/OtherValueType, /*to=*/ValueType>::value);
3273  *this, other0, other1, op, prune);
3274 }
3275 
3276 
3277 template<typename ChildT>
3278 template<typename CombineOp, typename OtherRootNode>
3279 inline void
3280 RootNode<ChildT>::doCombine2(const RootNode& other0, const OtherRootNode& other1,
3281  CombineOp& op, bool prune)
3282 {
3283  enforceSameConfiguration(other1);
3284 
3285  using OtherValueT = typename OtherRootNode::ValueType;
3286  using OtherTileT = typename OtherRootNode::Tile;
3287  using OtherNodeStructT = typename OtherRootNode::NodeStruct;
3288  using OtherMapCIterT = typename OtherRootNode::MapCIter;
3289 
3291 
3292  CoordSet keys;
3293  other0.insertKeys(keys);
3294  other1.insertKeys(keys);
3295 
3296  const NodeStruct bg0(Tile(other0.mBackground, /*active=*/false));
3297  const OtherNodeStructT bg1(OtherTileT(other1.mBackground, /*active=*/false));
3298 
3299  for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3300  MapIter thisIter = this->findOrAddCoord(*i);
3301  MapCIter iter0 = other0.findKey(*i);
3302  OtherMapCIterT iter1 = other1.findKey(*i);
3303  const NodeStruct& ns0 = (iter0 != other0.mTable.end()) ? iter0->second : bg0;
3304  const OtherNodeStructT& ns1 = (iter1 != other1.mTable.end()) ? iter1->second : bg1;
3305  if (ns0.isTile() && ns1.isTile()) {
3306  // Both input nodes have constant values (tiles).
3307  // Combine the two values and add a new tile to this node with the result.
3308  op(args.setARef(ns0.tile.value)
3309  .setAIsActive(ns0.isTileOn())
3310  .setBRef(ns1.tile.value)
3311  .setBIsActive(ns1.isTileOn()));
3312  setTile(thisIter, Tile(args.result(), args.resultIsActive()));
3313  } else {
3314  if (!isChild(thisIter)) {
3315  // Add a new child with the same coordinates, etc. as the other node's child.
3316  const Coord& childOrigin =
3317  ns0.isChild() ? ns0.child->origin() : ns1.child->origin();
3318  setChild(thisIter, *(new ChildT(childOrigin, getTile(thisIter).value)));
3319  }
3320  ChildT& child = getChild(thisIter);
3321 
3322  if (ns0.isTile()) {
3323  // Combine node1's child with node0's constant value
3324  // and write the result into this node's child.
3325  child.combine2(ns0.tile.value, *ns1.child, ns0.isTileOn(), op);
3326  } else if (ns1.isTile()) {
3327  // Combine node0's child with node1's constant value
3328  // and write the result into this node's child.
3329  child.combine2(*ns0.child, ns1.tile.value, ns1.isTileOn(), op);
3330  } else {
3331  // Combine node0's child with node1's child
3332  // and write the result into this node's child.
3333  child.combine2(*ns0.child, *ns1.child, op);
3334  }
3335  }
3336  if (prune && isChild(thisIter)) getChild(thisIter).prune();
3337  }
3338 
3339  // Combine background values.
3340  op(args.setARef(other0.mBackground).setBRef(other1.mBackground));
3341  mBackground = args.result();
3342 }
3343 
3344 
3346 
3347 
3348 template<typename ChildT>
3349 template<typename BBoxOp>
3350 inline void
3352 {
3353  const bool descent = op.template descent<LEVEL>();
3354  for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3355  if (this->isTileOff(i)) continue;
3356  if (this->isChild(i) && descent) {
3357  this->getChild(i).visitActiveBBox(op);
3358  } else {
3359  op.template operator()<LEVEL>(CoordBBox::createCube(i->first, ChildT::DIM));
3360  }
3361  }
3362 }
3363 
3364 
3365 template<typename ChildT>
3366 template<typename VisitorOp>
3367 inline void
3369 {
3370  doVisit<RootNode, VisitorOp, ChildAllIter>(*this, op);
3371 }
3372 
3373 
3374 template<typename ChildT>
3375 template<typename VisitorOp>
3376 inline void
3377 RootNode<ChildT>::visit(VisitorOp& op) const
3378 {
3379  doVisit<const RootNode, VisitorOp, ChildAllCIter>(*this, op);
3380 }
3381 
3382 
3383 template<typename ChildT>
3384 template<typename RootNodeT, typename VisitorOp, typename ChildAllIterT>
3385 inline void
3386 RootNode<ChildT>::doVisit(RootNodeT& self, VisitorOp& op)
3387 {
3388  typename RootNodeT::ValueType val;
3389  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
3390  if (op(iter)) continue;
3391  if (typename ChildAllIterT::ChildNodeType* child = iter.probeChild(val)) {
3392  child->visit(op);
3393  }
3394  }
3395 }
3396 
3397 
3399 
3400 
3401 template<typename ChildT>
3402 template<typename OtherRootNodeType, typename VisitorOp>
3403 inline void
3404 RootNode<ChildT>::visit2(OtherRootNodeType& other, VisitorOp& op)
3405 {
3406  doVisit2<RootNode, OtherRootNodeType, VisitorOp, ChildAllIter,
3407  typename OtherRootNodeType::ChildAllIter>(*this, other, op);
3408 }
3409 
3410 
3411 template<typename ChildT>
3412 template<typename OtherRootNodeType, typename VisitorOp>
3413 inline void
3414 RootNode<ChildT>::visit2(OtherRootNodeType& other, VisitorOp& op) const
3415 {
3416  doVisit2<const RootNode, OtherRootNodeType, VisitorOp, ChildAllCIter,
3417  typename OtherRootNodeType::ChildAllCIter>(*this, other, op);
3418 }
3419 
3420 
3421 template<typename ChildT>
3422 template<
3423  typename RootNodeT,
3424  typename OtherRootNodeT,
3425  typename VisitorOp,
3426  typename ChildAllIterT,
3427  typename OtherChildAllIterT>
3428 inline void
3429 RootNode<ChildT>::doVisit2(RootNodeT& self, OtherRootNodeT& other, VisitorOp& op)
3430 {
3431  enforceSameConfiguration(other);
3432 
3433  typename RootNodeT::ValueType val;
3434  typename OtherRootNodeT::ValueType otherVal;
3435 
3436  // The two nodes are required to have corresponding table entries,
3437  // but since that might require background tiles to be added to one or both,
3438  // and the nodes might be const, we operate on shallow copies of the nodes instead.
3439  RootNodeT copyOfSelf(self.mBackground);
3440  copyOfSelf.mTable = self.mTable;
3441  OtherRootNodeT copyOfOther(other.mBackground);
3442  copyOfOther.mTable = other.mTable;
3443 
3444  // Add background tiles to both nodes as needed.
3445  CoordSet keys;
3446  self.insertKeys(keys);
3447  other.insertKeys(keys);
3448  for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3449  copyOfSelf.findOrAddCoord(*i);
3450  copyOfOther.findOrAddCoord(*i);
3451  }
3452 
3453  ChildAllIterT iter = copyOfSelf.beginChildAll();
3454  OtherChildAllIterT otherIter = copyOfOther.beginChildAll();
3455 
3456  for ( ; iter && otherIter; ++iter, ++otherIter)
3457  {
3458  const size_t skipBranch = static_cast<size_t>(op(iter, otherIter));
3459 
3460  typename ChildAllIterT::ChildNodeType* child =
3461  (skipBranch & 1U) ? nullptr : iter.probeChild(val);
3462  typename OtherChildAllIterT::ChildNodeType* otherChild =
3463  (skipBranch & 2U) ? nullptr : otherIter.probeChild(otherVal);
3464 
3465  if (child != nullptr && otherChild != nullptr) {
3466  child->visit2Node(*otherChild, op);
3467  } else if (child != nullptr) {
3468  child->visit2(otherIter, op);
3469  } else if (otherChild != nullptr) {
3470  otherChild->visit2(iter, op, /*otherIsLHS=*/true);
3471  }
3472  }
3473  // Remove any background tiles that were added above,
3474  // as well as any that were created by the visitors.
3475  copyOfSelf.eraseBackgroundTiles();
3476  copyOfOther.eraseBackgroundTiles();
3477 
3478  // If either input node is non-const, replace its table with
3479  // the (possibly modified) copy.
3480  self.resetTable(copyOfSelf.mTable);
3481  other.resetTable(copyOfOther.mTable);
3482 }
3483 
3484 } // namespace tree
3485 } // namespace OPENVDB_VERSION_NAME
3486 } // namespace openvdb
3487 
3488 #endif // OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:93
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
SIMD Intrinsic Headers.
Definition: Platform.h:92
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: openvdb/Types.h:429
CombineArgs & setBIsActive(bool b)
Set the active state of the B value.
Definition: openvdb/Types.h:497
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: openvdb/Types.h:481
CombineArgs & setAIsActive(bool b)
Set the active state of the A value.
Definition: openvdb/Types.h:495
const AValueType & result() const
Get the output value.
Definition: openvdb/Types.h:473
bool resultIsActive() const
Definition: openvdb/Types.h:492
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: openvdb/Types.h:483
Tag dispatch class that distinguishes constructors during file input.
Definition: openvdb/Types.h:548
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: openvdb/Types.h:542
Definition: openvdb/Exceptions.h:64
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
const Coord & min() const
Definition: Coord.h:321
void translate(const Coord &t)
Translate this bounding box by (tx, ty, tz).
Definition: Coord.h:458
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:418
bool empty() const
Return true if this bounding box is empty (i.e., encloses no coordinates).
Definition: Coord.h:356
const Coord & max() const
Definition: Coord.h:322
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:412
static CoordBBox inf()
Return an "infinite" bounding box, as defined by the Coord value range.
Definition: Coord.h:319
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:400
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition: Coord.h:444
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition: Coord.h:313
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
Coord & setX(Int32 x)
Definition: Coord.h:80
Int32 y() const
Definition: Coord.h:132
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:92
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:176
Coord & setY(Int32 y)
Definition: Coord.h:81
Int32 x() const
Definition: Coord.h:131
static bool lessThan(const Coord &a, const Coord &b)
Definition: Coord.h:209
Int32 z() const
Definition: Coord.h:133
const Int32 * asPointer() const
Definition: Coord.h:142
Coord & setZ(Int32 z)
Definition: Coord.h:82
void read(std::istream &is)
Definition: Coord.h:220
Definition: RootNode.h:39
static CoordBBox getNodeBoundingBox()
Return the bounding box of this RootNode, i.e., an infinite bounding box.
Definition: RootNode.h:406
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1858
DenseIter< RootNode, MapIter, ChildType, ValueType > ChildAllIter
Definition: RootNode.h:364
void visit(VisitorOp &)
Definition: RootNode.h:3368
static bool hasSameConfiguration(const RootNode< OtherChildType > &other)
Return false if the other node's dimensions don't match this node's.
Definition: RootNode.h:1383
int getValueDepth(const Coord &xyz) const
Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides.
Definition: RootNode.h:1709
RootNode & operator=(const RootNode< OtherChildType > &other)
Copy a root node of the same tree configuration as this node but a different ValueType.
ValueIter< const RootNode, MapCIter, ValueOffPred, const ValueType > ValueOffCIter
Definition: RootNode.h:370
RootNode(const RootNode &other)
Definition: RootNode.h:75
ChildOnCIter cbeginChildOn() const
Definition: RootNode.h:375
ChildOnCIter beginChildOn() const
Definition: RootNode.h:378
ChildOnIter beginChildOn()
Definition: RootNode.h:381
Index getDepth() const
Definition: RootNode.h:457
bool isValueOn(const Coord &xyz) const
Definition: RootNode.h:1653
ValueIter< const RootNode, MapCIter, ValueOnPred, const ValueType > ValueOnCIter
Definition: RootNode.h:368
void getIndexRange(CoordBBox &bbox) const
Return the current index range. Both min and max are inclusive.
Definition: RootNode.h:1323
void copyToDense(const CoordBBox &bbox, DenseT &dense) const
Copy into a dense grid the values of all voxels, both active and inactive, that intersect a given bou...
Definition: RootNode.h:2218
const ValueType & background() const
Return this node's background value.
Definition: RootNode.h:423
RootNode & operator=(const RootNode &other)
Copy a root node of the same type as this node.
Definition: RootNode.h:1150
Coord getMaxIndex() const
Return the largest index of the current tree.
Definition: RootNode.h:1315
ValueOffCIter cbeginValueOff() const
Definition: RootNode.h:386
void addLeafAndCache(LeafNodeType *leaf, AccessorT &)
Same as addLeaf() but, if necessary, update the given accessor with pointers to the nodes along the p...
Definition: RootNode.h:2563
static Index getChildDim()
Definition: RootNode.h:450
Index32 nonLeafCount() const
Definition: RootNode.h:1538
void combine(RootNode &other, CombineOp &, bool prune=false)
Definition: RootNode.h:3176
bool addChild(ChildType *child)
Add the given child node at the root level. If a child node with the same origin already exists,...
Definition: RootNode.h:2597
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: RootNode.h:2863
NodeT * stealNode(const Coord &xyz, const ValueType &value, bool state)
Return a pointer to the node of type NodeT that contains voxel (x, y, z) and replace it with a tile o...
Definition: RootNode.h:2509
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: RootNode.h:2192
ValueIter< RootNode, MapIter, ValueOffPred, ValueType > ValueOffIter
Definition: RootNode.h:369
ValueIter< RootNode, MapIter, ValueAllPred, ValueType > ValueAllIter
Definition: RootNode.h:371
Index64 onLeafVoxelCount() const
Definition: RootNode.h:1596
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: RootNode.h:2448
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition: RootNode.h:2779
static bool hasCompatibleValueType(const RootNode< OtherChildType > &other)
Definition: RootNode.h:1415
ValueAllCIter cbeginValueAll() const
Definition: RootNode.h:387
NodeT * probeNodeAndCache(const Coord &xyz, AccessorT &acc)
Same as probeNode() but, if necessary, update the given accessor with pointers to the nodes along the...
Definition: RootNode.h:2823
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: RootNode.h:2488
typename NodeChain< RootNode, LEVEL >::Type NodeChainType
NodeChainType is a list of this tree's node types, from LeafNodeType to RootNode.
Definition: RootNode.h:49
bool isBackgroundTile(const Tile &) const
Return true if the given tile is inactive and has the background value.
Definition: RootNode.h:1212
typename ChildType::LeafNodeType LeafNodeType
Definition: RootNode.h:42
size_t eraseBackgroundTiles()
Remove all background tiles.
Definition: RootNode.h:1246
void topologyDifference(const RootNode< OtherChildType > &other)
Difference this tree's set of active values with the active values of the other tree,...
Definition: RootNode.h:3137
ValueIter< RootNode, MapIter, ValueOnPred, ValueType > ValueOnIter
Definition: RootNode.h:367
ValueOnCIter beginValueOn() const
Definition: RootNode.h:388
void topologyUnion(const RootNode< OtherChildType > &other)
Union this tree's set of active values with the active values of the other tree, whose ValueType may ...
Definition: RootNode.h:3065
void merge(RootNode &other)
Efficiently merge another tree into this tree using one of several schemes.
Definition: RootNode.h:2953
ChildIter< RootNode, MapIter, ChildOnPred, ChildType > ChildOnIter
Definition: RootNode.h:360
Index64 offLeafVoxelCount() const
Definition: RootNode.h:1608
Index getWidth() const
Definition: RootNode.h:455
Index getTableSize() const
Return the number of entries in this node's table.
Definition: RootNode.h:453
void combine2(const RootNode &other0, const OtherRootNode &other1, CombineOp &op, bool prune=false)
Definition: RootNode.h:3266
const LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc) const
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: RootNode.h:1990
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1899
size_t numBackgroundTiles() const
Return the number of background tiles.
Definition: RootNode.h:1234
ValueIter< const RootNode, MapCIter, ChildOffPred, ValueType > ChildOffCIter
Definition: RootNode.h:363
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: RootNode.h:1880
bool empty() const
Return true if this node's table is either empty or contains only background tiles.
Definition: RootNode.h:441
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition: RootNode.h:2787
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition: RootNode.h:2084
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
ValueOffCIter beginValueOff() const
Definition: RootNode.h:389
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1815
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: RootNode.h:2528
ChildAllCIter cbeginChildAll() const
Definition: RootNode.h:377
void addTile(const Coord &xyz, const ValueType &value, bool state)
Add a tile containing voxel (x, y, z) at the root level, deleting the existing branch if necessary.
Definition: RootNode.h:2612
ChildAllIter beginChildAll()
Definition: RootNode.h:383
static Index getLevel()
Definition: RootNode.h:448
bool writeTopology(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2262
ValueIter< const RootNode, MapCIter, ValueAllPred, const ValueType > ValueAllCIter
Definition: RootNode.h:372
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1673
const NodeT * probeConstNodeAndCache(const Coord &xyz, AccessorT &acc) const
Definition: RootNode.h:2842
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: RootNode.h:2048
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: RootNode.h:1745
ValueOnIter beginValueOn()
Definition: RootNode.h:391
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:1954
void visit2(OtherRootNodeType &other, VisitorOp &)
Definition: RootNode.h:3404
ChildOffCIter cbeginChildOff() const
Definition: RootNode.h:376
ChildOffIter beginChildOff()
Definition: RootNode.h:382
Index64 onVoxelCount() const
Definition: RootNode.h:1564
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as touchLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
ChildOffCIter beginChildOff() const
Definition: RootNode.h:379
void addTileAndCache(Index level, const Coord &xyz, const ValueType &, bool state, AccessorT &)
Same as addTile() but, if necessary, update the given accessor with pointers to the nodes along the p...
Definition: RootNode.h:2659
typename ChildType::ValueType ValueType
Definition: RootNode.h:43
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: RootNode.h:1731
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2404
ValueOnCIter cbeginValueOn() const
Definition: RootNode.h:385
Index32 leafCount() const
Definition: RootNode.h:1526
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
Index32 childCount() const
Definition: RootNode.h:1552
Index64 onTileCount() const
Definition: RootNode.h:1619
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: RootNode.h:1922
void visitActiveBBox(BBoxOp &) const
Call the templated functor BBoxOp with bounding box information for all active tiles and leaf nodes i...
Definition: RootNode.h:3351
~RootNode()
Definition: RootNode.h:123
Index64 offVoxelCount() const
Definition: RootNode.h:1580
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition: RootNode.h:2700
typename ChildType::BuildType BuildType
Definition: RootNode.h:44
void setBackground(const ValueType &value, bool updateChildNodes)
Change inactive tiles or voxels with a value equal to +/- the old background to the specified value (...
Definition: RootNode.h:1185
DenseIter< const RootNode, MapCIter, const ChildType, const ValueType > ChildAllCIter
Definition: RootNode.h:365
bool hasSameTopology(const RootNode< OtherChildType > &other) const
Return true if the given tree has the same node and active value topology as this tree (but possibly ...
Definition: RootNode.h:1336
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: RootNode.h:2142
ChildAllCIter beginChildAll() const
Definition: RootNode.h:380
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: RootNode.h:1768
const LeafNodeType * probeLeaf(const Coord &xyz) const
void topologyIntersection(const RootNode< OtherChildType > &other)
Intersects this tree's set of active values with the active values of the other tree,...
Definition: RootNode.h:3101
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:
Definition: RootNode.h:2921
Index getHeight() const
Definition: RootNode.h:456
void clear()
Definition: RootNode.h:1456
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: RootNode.h:2064
const NodeT * probeConstNode(const Coord &xyz) const
Definition: RootNode.h:2762
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Expand the specified bbox so it includes the active tiles of this root node as well as all the active...
Definition: RootNode.h:1467
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
static void getNodeLog2Dims(std::vector< Index > &dims)
Definition: RootNode.h:1299
RootNode(const RootNode< OtherChildType > &other)
Construct a new tree that reproduces the topology and active states of a tree of a different ValueTyp...
Definition: RootNode.h:84
ValueOffIter beginValueOff()
Definition: RootNode.h:392
ValueIter< RootNode, MapIter, ChildOffPred, const ValueType > ChildOffIter
Definition: RootNode.h:362
void sparseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Definition: RootNode.h:532
Coord getMinIndex() const
Return the smallest index of the current tree.
Definition: RootNode.h:1308
ChildType ChildNodeType
Definition: RootNode.h:41
bool hasActiveTiles() const
Return true if this root node, or any of its child nodes, have active tiles.
Definition: RootNode.h:1662
int getValueDepthAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1719
const ValueType & getValue(const Coord &xyz) const
Definition: RootNode.h:1685
void nodeCount(std::vector< Index32 > &vec) const
Definition: RootNode.h:1634
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: RootNode.h:1442
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: RootNode.h:1839
void stealNodes(ArrayT &array)
Definition: RootNode.h:811
bool expand(const Coord &xyz)
Expand this node's table so that (x, y, z) is included in the index range.
Definition: RootNode.h:1285
void readBuffers(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2414
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:2017
ValueAllCIter beginValueAll() const
Definition: RootNode.h:390
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists,...
Definition: RootNode.h:2744
bool readTopology(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2298
ChildIter< const RootNode, MapCIter, ChildOnPred, const ChildType > ChildOnCIter
Definition: RootNode.h:361
ValueAllIter beginValueAll()
Definition: RootNode.h:393
friend class RootNode
Definition: RootNode.h:893
Definition: NodeMasks.h:1067
bool isOn(Index32 i) const
Definition: NodeMasks.h:1331
void load(std::istream &is)
Definition: NodeMasks.h:1372
T truncateRealToHalf(const T &val)
Return the given value truncated to 16-bit float precision.
Definition: Compression.h:216
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
OPENVDB_API void setGridBackgroundValuePtr(std::ios_base &, const void *background)
Specify (a pointer to) the background value of the grid currently being read from or written to the g...
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition: Math.h:407
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition: Mat3.h:611
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:444
bool operator!=(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Inequality operator, does exact floating point comparisons.
Definition: Vec3.h:485
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:477
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:127
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:103
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:334
GridType::Ptr clip(const GridType &grid, const BBoxd &bbox, bool keepInterior=true)
Clip the given grid against a world-space bounding box and return a new grid containing the result.
Definition: Clip.h:348
void copyToDense(const GridOrTreeT &sparse, DenseT &dense, bool serial=false)
Populate a dense grid with the values of voxels from a sparse grid, where the sparse grid intersects ...
Definition: Dense.h:421
Index32 FindHighestOn(Index32 v)
Return the most significant on bit of the given 32-bit value.
Definition: NodeMasks.h:159
Index32 Index
Definition: openvdb/Types.h:32
uint32_t Index32
Definition: openvdb/Types.h:30
@ OPENVDB_FILE_VERSION_ROOTNODE_MAP
Definition: version.h:184
int32_t Int32
Definition: openvdb/Types.h:34
uint64_t Index64
Definition: openvdb/Types.h:31
@ MERGE_ACTIVE_STATES
Definition: openvdb/Types.h:367
@ MERGE_NODES
Definition: openvdb/Types.h:368
@ MERGE_ACTIVE_STATES_AND_NODES
Definition: openvdb/Types.h:369
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:69
ValueType combine(const ValueType &v0, const ValueType &v1, const ValueType &v2, const openvdb::Vec3d &w)
Combine different value types.
Definition: AttributeTransferUtil.h:140
Definition: openvdb/Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
CanConvertType<FromType, ToType>::value is true if a value of type ToType can be constructed from a v...
Definition: openvdb/Types.h:263
Definition: openvdb/Types.h:520
A list of types (not necessarily unique)
Definition: TypeList.h:366
NodeChain<RootNodeType, RootNodeType::LEVEL>::Type is a openvdb::TypeList that lists the types of the...
Definition: RootNode.h:993
typename NodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition: RootNode.h:994
typename SubtreeT::template Append< HeadT > Type
Definition: RootNode.h:995
static void combine2(RootT &self, const RootT &other0, const OtherRootT &other1, CombineOp &op, bool prune)
Definition: RootNode.h:3255
static void combine2(RootT &self, const RootT &, const OtherRootT &other1, CombineOp &, bool)
Definition: RootNode.h:3236
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1112
Definition: RootNode.h:1093
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1094
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of a RootNod...
Definition: RootNode.h:64
ValueConverter<T>::Type is the type of a RootNode having the same child hierarchy as this node but a ...
Definition: RootNode.h:56
Definition: RootNode.h:1012
Library and file format version numbers.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153