OpenVDB  2.3.0
InternalNode.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2013 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 //
34 
35 #ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
36 #define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
37 
38 #include <boost/shared_array.hpp>
39 #include <boost/static_assert.hpp>
40 #include <openvdb/Platform.h>
41 #include <openvdb/util/NodeMasks.h>
42 #include <openvdb/io/Compression.h> // for io::readData(), etc.
43 #include <openvdb/math/Math.h> // for Abs(), isExactlyEqual()
44 #include <openvdb/version.h>
45 #include <openvdb/Types.h>
46 #include "Iterator.h"
47 #include "NodeUnion.h"
48 #include "Util.h"
49 
50 
51 namespace openvdb {
53 namespace OPENVDB_VERSION_NAME {
54 namespace tree {
55 
56 template<typename, Index, typename> struct SameInternalConfig; // forward declaration
57 
58 
59 template<typename _ChildNodeType, Index Log2Dim>
61 {
62 public:
63  typedef _ChildNodeType ChildNodeType;
64  typedef typename ChildNodeType::LeafNodeType LeafNodeType;
65  typedef typename ChildNodeType::ValueType ValueType;
68 
69  static const Index
70  LOG2DIM = Log2Dim,
71  TOTAL = Log2Dim + ChildNodeType::TOTAL,
72  DIM = 1 << TOTAL,
73  NUM_VALUES = 1 << (3 * Log2Dim),
74  LEVEL = 1 + ChildNodeType::LEVEL; // level 0 = leaf
75  static const Index64
76  NUM_VOXELS = uint64_t(1) << (3 * TOTAL); // total # of voxels represented by this node
77 
80  template<typename OtherValueType>
81  struct ValueConverter {
82  typedef InternalNode<typename ChildNodeType::template ValueConverter<
83  OtherValueType>::Type, Log2Dim> Type;
84  };
85 
89  template<typename OtherNodeType>
91  static const bool value =
93  };
94 
95 
97 
98  explicit InternalNode(const ValueType& offValue);
99 
100  InternalNode(const Coord&, const ValueType& value, bool active = false);
101 
103  InternalNode(const InternalNode&);
104 
106  template<typename OtherChildNodeType>
108 
110  template<typename OtherChildNodeType>
112  const ValueType& background, TopologyCopy);
113 
115  template<typename OtherChildNodeType>
117  const ValueType& offValue, const ValueType& onValue, TopologyCopy);
118 
119  virtual ~InternalNode();
120 
121 protected:
125 
126  // Type tags to disambiguate template instantiations
127  struct ValueOn {}; struct ValueOff {}; struct ValueAll {};
128  struct ChildOn {}; struct ChildOff {}; struct ChildAll {};
129 
130  // The following class templates implement the iterator interfaces specified in Iterator.h
131  // by providing getItem(), setItem() and/or modifyItem() methods.
132 
133  template<typename NodeT, typename ChildT, typename MaskIterT, typename TagT>
135  MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>
136  {
138  ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
139  MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {}
140 
141  ChildT& getItem(Index pos) const
142  {
143  assert(this->parent().isChildMaskOn(pos));
144  return *(this->parent().getChildNode(pos));
145  }
146 
147  // Note: setItem() can't be called on const iterators.
148  void setItem(Index pos, const ChildT& c) const { this->parent().resetChildNode(pos, &c); }
149 
150  // Note: modifyItem() isn't implemented, since it's not useful for child node pointers.
151  };// ChildIter
152 
153  template<typename NodeT, typename ValueT, typename MaskIterT, typename TagT>
155  MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>
156  {
158  ValueIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
159  MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {}
160 
161  const ValueT& getItem(Index pos) const { return this->parent().mNodes[pos].getValue(); }
162 
163  // Note: setItem() can't be called on const iterators.
164  void setItem(Index pos, const ValueT& v) const { this->parent().mNodes[pos].setValue(v); }
165 
166  // Note: modifyItem() can't be called on const iterators.
167  template<typename ModifyOp>
168  void modifyItem(Index pos, const ModifyOp& op) const
169  {
170  op(this->parent().mNodes[pos].getValue());
171  }
172  };// ValueIter
173 
174  template<typename NodeT, typename ChildT, typename ValueT, typename TagT>
175  struct DenseIter: public DenseIteratorBase<
176  MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
177  {
180 
182  DenseIter(const MaskDenseIterator& iter, NodeT* parent):
183  DenseIteratorBase<MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT>(iter, parent) {}
184 
185  bool getItem(Index pos, ChildT*& child, NonConstValueT& value) const
186  {
187  if (this->parent().isChildMaskOn(pos)) {
188  child = this->parent().getChildNode(pos);
189  return true;
190  }
191  child = NULL;
192  value = this->parent().mNodes[pos].getValue();
193  return false;
194  }
195 
196  // Note: setItem() can't be called on const iterators.
197  void setItem(Index pos, ChildT* child) const
198  {
199  this->parent().resetChildNode(pos, child);
200  }
201 
202  // Note: unsetItem() can't be called on const iterators.
203  void unsetItem(Index pos, const ValueT& value) const
204  {
205  this->parent().unsetChildNode(pos, value);
206  }
207  };// DenseIter
208 
209 public:
210  // Iterators (see Iterator.h for usage)
217 
224 
225  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mChildMask.beginOn(), this); }
226  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mChildMask.beginOff(), this); }
227  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mChildMask.beginDense(), this); }
228  ChildOnCIter beginChildOn() const { return cbeginChildOn(); }
229  ChildOffCIter beginChildOff() const { return cbeginChildOff(); }
230  ChildAllCIter beginChildAll() const { return cbeginChildAll(); }
231  ChildOnIter beginChildOn() { return ChildOnIter(mChildMask.beginOn(), this); }
232  ChildOffIter beginChildOff() { return ChildOffIter(mChildMask.beginOff(), this); }
233  ChildAllIter beginChildAll() { return ChildAllIter(mChildMask.beginDense(), this); }
234 
235  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
236  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
237  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mChildMask.beginOff(), this); }
238  ValueOnCIter beginValueOn() const { return cbeginValueOn(); }
239  ValueOffCIter beginValueOff() const { return cbeginValueOff(); }
240  ValueAllCIter beginValueAll() const { return cbeginValueAll(); }
241  ValueOnIter beginValueOn() { return ValueOnIter(mValueMask.beginOn(), this); }
242  ValueOffIter beginValueOff() { return ValueOffIter(mValueMask.beginOff(), this); }
243  ValueAllIter beginValueAll() { return ValueAllIter(mChildMask.beginOff(), this); }
244 
245 
246  static Index dim() { return DIM; }
247  static Index getLevel() { return LEVEL; }
248  static void getNodeLog2Dims(std::vector<Index>& dims);
249  static Index getChildDim() { return ChildNodeType::DIM; }
250 
252  static Index coordToOffset(const Coord& xyz);
255  static void offsetToLocalCoord(Index n, Coord& xyz);
257  Coord offsetToGlobalCoord(Index n) const;
258 
260  const Coord& origin() const { return mOrigin; }
262  void setOrigin(const Coord& origin) { mOrigin = origin; }
263 
264  Index32 leafCount() const;
265  Index32 nonLeafCount() const;
266  Index64 onVoxelCount() const;
267  Index64 offVoxelCount() const;
268  Index64 onLeafVoxelCount() const;
269  Index64 offLeafVoxelCount() const;
270  Index64 onTileCount() const;
271 
273  Index64 memUsage() const;
274 
279  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
280 
283  CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); }
284 
285  bool isEmpty() const { return mChildMask.isOff(); }
286 
290  bool isConstant(ValueType& constValue, bool& state,
291  const ValueType& tolerance = zeroVal<ValueType>()) const;
293  bool isInactive() const { return this->isChildMaskOff() && this->isValueMaskOff(); }
294 
296  bool isValueOn(const Coord& xyz) const;
298  bool isValueOn(Index offset) const { return mValueMask.isOn(offset); }
299 
301  bool hasActiveTiles() const;
302 
303  const ValueType& getValue(const Coord& xyz) const;
304  bool probeValue(const Coord& xyz, ValueType& value) const;
305 
308  Index getValueLevel(const Coord& xyz) const;
309 
312  const ValueType& getFirstValue() const;
315  const ValueType& getLastValue() const;
316 
318  void setActiveState(const Coord& xyz, bool on);
320  void setValueOnly(const Coord& xyz, const ValueType& value);
322  void setValueOn(const Coord& xyz);
324  void setValueOn(const Coord& xyz, const ValueType& value);
326  void setValueOff(const Coord& xyz);
328  void setValueOff(const Coord& xyz, const ValueType& value);
329 
332  template<typename ModifyOp>
333  void modifyValue(const Coord& xyz, const ModifyOp& op);
335  template<typename ModifyOp>
336  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op);
337 
342  template<typename AccessorT>
343  const ValueType& getValueAndCache(const Coord& xyz, AccessorT&) const;
344 
349  template<typename AccessorT>
350  bool isValueOnAndCache(const Coord& xyz, AccessorT&) const;
351 
356  template<typename AccessorT>
357  void setValueAndCache(const Coord& xyz, const ValueType& value, AccessorT&);
358 
363  template<typename AccessorT>
364  void setValueOnlyAndCache(const Coord& xyz, const ValueType& value, AccessorT&);
365 
371  template<typename ModifyOp, typename AccessorT>
372  void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&);
373 
378  template<typename ModifyOp, typename AccessorT>
379  void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&);
380 
385  template<typename AccessorT>
386  void setValueOffAndCache(const Coord& xyz, const ValueType& value, AccessorT&);
387 
392  template<typename AccessorT>
393  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&);
394 
400  template<typename AccessorT>
401  bool probeValueAndCache(const Coord& xyz, ValueType& value, AccessorT&) const;
402 
409  template<typename AccessorT>
410  Index getValueLevelAndCache(const Coord& xyz, AccessorT&) const;
411 
413  void setValuesOn();
414 
415 
416  //
417  // I/O
418  //
419  void writeTopology(std::ostream&, bool toHalf = false) const;
420  void readTopology(std::istream&, bool fromHalf = false);
421  void writeBuffers(std::ostream&, bool toHalf = false) const;
422  void readBuffers(std::istream&, bool fromHalf = false);
423 
424 
425  //
426  // Aux methods
427  //
430  void fill(const CoordBBox& bbox, const ValueType&, bool active = true);
431 
437  void signedFloodFill(const ValueType& background);
438 
444  void signedFloodFill(const ValueType& outside, const ValueType& inside);
445 
448  void negate();
449 
451  void voxelizeActiveTiles();
452 
460  template<typename DenseT>
461  void copyToDense(const CoordBBox& bbox, DenseT& dense) const;
462 
465  template<MergePolicy Policy>
466  void merge(InternalNode& other, const ValueType& background, const ValueType& otherBackground);
467 
470  template<MergePolicy Policy> void merge(const ValueType& tileValue, bool tileActive);
471 
484  template<typename OtherChildNodeType>
485  void topologyUnion(const InternalNode<OtherChildNodeType, Log2Dim>& other);
486 
500  template<typename OtherChildNodeType>
501  void topologyIntersection(const InternalNode<OtherChildNodeType, Log2Dim>& other,
502  const ValueType& background);
503 
515  template<typename OtherChildNodeType>
516  void topologyDifference(const InternalNode<OtherChildNodeType, Log2Dim>& other,
517  const ValueType& background);
518 
519  template<typename CombineOp>
520  void combine(InternalNode& other, CombineOp&);
521  template<typename CombineOp>
522  void combine(const ValueType& value, bool valueIsActive, CombineOp&);
523 
524  template<typename CombineOp, typename OtherNodeType /*= InternalNode*/>
525  void combine2(const InternalNode& other0, const OtherNodeType& other1, CombineOp&);
526  template<typename CombineOp, typename OtherNodeType /*= InternalNode*/>
527  void combine2(const ValueType& value, const OtherNodeType& other, bool valIsActive, CombineOp&);
528  template<typename CombineOp, typename OtherValueType>
529  void combine2(const InternalNode& other, const OtherValueType&, bool valIsActive, CombineOp&);
530 
536  template<typename BBoxOp> void visitActiveBBox(BBoxOp&) const;
537 
538  template<typename VisitorOp> void visit(VisitorOp&);
539  template<typename VisitorOp> void visit(VisitorOp&) const;
540 
541  template<typename OtherNodeType, typename VisitorOp>
542  void visit2Node(OtherNodeType& other, VisitorOp&);
543  template<typename OtherNodeType, typename VisitorOp>
544  void visit2Node(OtherNodeType& other, VisitorOp&) const;
545  template<typename IterT, typename VisitorOp>
546  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false);
547  template<typename IterT, typename VisitorOp>
548  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false) const;
549 
556  template<typename PruneOp> void pruneOp(PruneOp&);
557 
561  void prune(const ValueType& tolerance = zeroVal<ValueType>());
562 
565  void pruneInactive(const ValueType&);
566 
569  void pruneInactive();
570 
573  void addLeaf(LeafNodeType* leaf);
574 
577  template<typename AccessorT>
578  void addLeafAndCache(LeafNodeType* leaf, AccessorT&);
579 
588  template<typename NodeT>
589  NodeT* stealNode(const Coord& xyz, const ValueType& value, bool state);
590 
593  void addTile(Index level, const Coord& xyz, const ValueType& value, bool state);
594 
596  void addTile(Index offset, const ValueType& value, bool state);
597 
600  template<typename AccessorT>
601  void addTileAndCache(Index level, const Coord& xyz, const ValueType&, bool state, AccessorT&);
602 
604  template<typename NodeType> NodeType* probeNode(const Coord& xyz);
607  template<typename NodeType> const NodeType* probeConstNode(const Coord& xyz) const;
609 
611  template<typename NodeType, typename AccessorT>
614  NodeType* probeNodeAndCache(const Coord& xyz, AccessorT&);
615  template<typename NodeType, typename AccessorT>
616  const NodeType* probeConstNodeAndCache(const Coord& xyz, AccessorT&) const;
618 
620  LeafNodeType* probeLeaf(const Coord& xyz);
623  const LeafNodeType* probeConstLeaf(const Coord& xyz) const;
624  const LeafNodeType* probeLeaf(const Coord& xyz) const;
626 
628  template<typename AccessorT>
631  LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc);
632  template<typename AccessorT>
633  const LeafNodeType* probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const;
634  template<typename AccessorT>
635  const LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc) const;
637 
644  LeafNodeType* touchLeaf(const Coord& xyz);
645 
648  template<typename AccessorT>
649  LeafNodeType* touchLeafAndCache(const Coord& xyz, AccessorT&);
650 
653  void resetBackground(const ValueType& oldBackground, const ValueType& newBackground);
654 
657  template<typename OtherChildNodeType, Index OtherLog2Dim>
658  bool hasSameTopology(const InternalNode<OtherChildNodeType, OtherLog2Dim>* other) const;
659 
660 protected:
662  friend class IteratorBase<MaskOnIterator, InternalNode>;
668 
671  template<typename, Index> friend class InternalNode;
672 
673  // Mask accessors
674 public:
675  bool isValueMaskOn(Index n) const { return mValueMask.isOn(n); }
676  bool isValueMaskOn() const { return mValueMask.isOn(); }
677  bool isValueMaskOff(Index n) const { return mValueMask.isOff(n); }
678  bool isValueMaskOff() const { return mValueMask.isOff(); }
679  bool isChildMaskOn(Index n) const { return mChildMask.isOn(n); }
680  bool isChildMaskOff(Index n) const { return mChildMask.isOff(n); }
681  bool isChildMaskOff() const { return mChildMask.isOff(); }
682 protected:
684  void setValueMask(Index n, bool on) { mValueMask.set(n, mChildMask.isOn(n) ? false : on); }
688 
689  void makeChildNodeEmpty(Index n, const ValueType& value);
690  void setChildNode( Index i, ChildNodeType* child);//assumes a tile
691  void resetChildNode(Index i, ChildNodeType* child);//checks for an existing child
692  ChildNodeType* unsetChildNode(Index i, const ValueType& value);
693 
694  template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
695  static inline void doVisit(NodeT&, VisitorOp&);
696 
697  template<typename NodeT, typename OtherNodeT, typename VisitorOp,
698  typename ChildAllIterT, typename OtherChildAllIterT>
699  static inline void doVisit2Node(NodeT&, OtherNodeT&, VisitorOp&);
700 
701  template<typename NodeT, typename VisitorOp,
702  typename ChildAllIterT, typename OtherChildAllIterT>
703  static inline void doVisit2(NodeT&, OtherChildAllIterT&, VisitorOp&, bool otherIsLHS);
704 
709  ChildNodeType* getChildNode(Index n);
710  const ChildNodeType* getChildNode(Index n) const;
712 
713 
714  UnionType mNodes[NUM_VALUES];
717  Coord mOrigin;
718 }; // class InternalNode
719 
720 
722 
723 
725 template<typename ChildT1, Index Dim1, typename NodeT2>
728 struct SameInternalConfig {
729  static const bool value = false;
730 };
731 
732 template<typename ChildT1, Index Dim1, typename ChildT2>
733 struct SameInternalConfig<ChildT1, Dim1, InternalNode<ChildT2, Dim1> > {
734  static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
735 };
737 
738 
740 
741 
742 template<typename ChildT, Index Log2Dim>
743 inline
745 {
746  for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
747 }
748 
749 
750 template<typename ChildT, Index Log2Dim>
751 inline
752 InternalNode<ChildT, Log2Dim>::InternalNode(const Coord& origin, const ValueType& val, bool active):
753  mOrigin(origin[0] & ~(DIM - 1), // zero out the low-order bits
754  origin[1] & ~(DIM - 1),
755  origin[2] & ~(DIM - 1))
756 {
757  if (active) mValueMask.setOn();
758  for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(val);
759 }
760 
761 
762 template<typename ChildT, Index Log2Dim>
763 inline
765  mChildMask(other.mChildMask),
766  mValueMask(other.mValueMask),
767  mOrigin(other.mOrigin)
768 {
769  for (Index i = 0; i < NUM_VALUES; ++i) {
770  if (isChildMaskOn(i)) {
771  mNodes[i].setChild(new ChildNodeType(*(other.mNodes[i].getChild())));
772  } else {
773  mNodes[i].setValue(other.mNodes[i].getValue());
774  }
775  }
776 }
777 
778 
779 // Copy-construct from a node with the same configuration but a different ValueType.
780 template<typename ChildT, Index Log2Dim>
781 template<typename OtherChildNodeType>
782 inline
784  : mChildMask(other.mChildMask)
785  , mValueMask(other.mValueMask)
786  , mOrigin(other.mOrigin)
787 {
788  struct Local {
790  static inline ValueType
791  convertValue(const typename OtherChildNodeType::ValueType& val) { return ValueType(val); }
792  };
793 
794  for (Index i = 0; i < NUM_VALUES; ++i) {
795  if (other.mChildMask.isOff(i)) {
796  mNodes[i].setValue(Local::convertValue(other.mNodes[i].getValue()));
797  } else {
798  mNodes[i].setChild(new ChildNodeType(*(other.mNodes[i].getChild())));
799  }
800  }
801 }
802 
803 
804 template<typename ChildT, Index Log2Dim>
805 template<typename OtherChildNodeType>
806 inline
808  const ValueType& offValue, const ValueType& onValue, TopologyCopy):
809  mChildMask(other.mChildMask),
810  mValueMask(other.mValueMask),
811  mOrigin(other.mOrigin)
812 {
813  for (Index i = 0; i < NUM_VALUES; ++i) {
814  if (isChildMaskOn(i)) {
815  mNodes[i].setChild(new ChildNodeType(*(other.mNodes[i].getChild()),
816  offValue, onValue, TopologyCopy()));
817  } else {
818  mNodes[i].setValue(isValueMaskOn(i) ? onValue : offValue);
819  }
820  }
821 }
822 
823 template<typename ChildT, Index Log2Dim>
824 template<typename OtherChildNodeType>
825 inline
827  const ValueType& background, TopologyCopy):
828  mChildMask(other.mChildMask),
829  mValueMask(other.mValueMask),
830  mOrigin(other.mOrigin)
831 {
832  for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
833  for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
834  mNodes[iter.pos()].setChild(new ChildNodeType(*(other.mNodes[iter.pos()].getChild()),
835  background, TopologyCopy()));
836  }
837 }
838 
839 
840 template<typename ChildT, Index Log2Dim>
841 inline
843 {
844  for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
845  delete mNodes[iter.pos()].getChild();
846  }
847 }
848 
849 
851 
852 
853 template<typename ChildT, Index Log2Dim>
854 inline Index32
856 {
857  if (ChildNodeType::getLevel() == 0) return mChildMask.countOn();
858  Index32 sum = 0;
859  for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
860  sum += iter->leafCount();
861  }
862  return sum;
863 }
864 
865 
866 template<typename ChildT, Index Log2Dim>
867 inline Index32
869 {
870  Index32 sum = 1;
871  if (ChildNodeType::getLevel() == 0) return sum;
872  for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
873  sum += iter->nonLeafCount();
874  }
875  return sum;
876 }
877 
878 
879 template<typename ChildT, Index Log2Dim>
880 inline Index64
882 {
883  Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
884  for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
885  sum += iter->onVoxelCount();
886  }
887  return sum;
888 }
889 
890 
891 template<typename ChildT, Index Log2Dim>
892 inline Index64
894 {
895  Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
896  for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
897  sum += iter->offVoxelCount();
898  }
899  return sum;
900 }
901 
902 
903 template<typename ChildT, Index Log2Dim>
904 inline Index64
906 {
907  Index64 sum = 0;
908  for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
909  sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
910  }
911  return sum;
912 }
913 
914 
915 template<typename ChildT, Index Log2Dim>
916 inline Index64
918 {
919  Index64 sum = 0;
920  for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
921  sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
922  }
923  return sum;
924 }
925 
926 template<typename ChildT, Index Log2Dim>
927 inline Index64
929 {
930  Index64 sum = mValueMask.countOn();
931  for (ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
932  sum += iter->onTileCount();
933  }
934  return sum;
935 }
936 
937 template<typename ChildT, Index Log2Dim>
938 inline Index64
940 {
941  Index64 sum = NUM_VALUES * sizeof(UnionType) + mChildMask.memUsage()
942  + mValueMask.memUsage() + sizeof(mOrigin);
943  for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
944  sum += iter->memUsage();
945  }
946  return sum;
947 }
948 
949 
950 template<typename ChildT, Index Log2Dim>
951 inline void
952 InternalNode<ChildT, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const
953 {
954  if (bbox.isInside(this->getNodeBoundingBox())) return;
955 
956  for (ValueOnCIter i = this->cbeginValueOn(); i; ++i) {
957  bbox.expand(i.getCoord(), ChildT::DIM);
958  }
959  for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) {
960  i->evalActiveBoundingBox(bbox, visitVoxels);
961  }
962 }
963 
964 
966 
967 
968 template<typename ChildT, Index Log2Dim>
969 template<typename PruneOp>
970 inline void
972 {
973  for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
974  const Index i = iter.pos();
975  ChildT* child = mNodes[i].getChild();
976  if (!op(*child)) continue;
977  delete child;
978  mChildMask.setOff(i);
979  mValueMask.set(i, op.state);
980  mNodes[i].setValue(op.value);
981  }
982 
983 }
984 
985 
986 template<typename ChildT, Index Log2Dim>
987 inline void
989 {
990  TolerancePrune<ValueType> op(tolerance);
991  this->pruneOp(op);
992 }
993 
994 
995 template<typename ChildT, Index Log2Dim>
996 inline void
998 {
1000  this->pruneOp(op);
1001 }
1002 
1003 
1004 template<typename ChildT, Index Log2Dim>
1005 inline void
1007 {
1008  this->pruneInactive(this->getBackground());
1009 }
1010 
1011 
1013 
1014 
1015 template<typename ChildT, Index Log2Dim>
1016 template<typename NodeT>
1017 inline NodeT*
1018 InternalNode<ChildT, Log2Dim>::stealNode(const Coord& xyz, const ValueType& value, bool state)
1019 {
1020  if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1021  NodeT::LEVEL > ChildT::LEVEL) return NULL;
1023  const Index n = this->coordToOffset(xyz);
1024  if (mChildMask.isOff(n)) return NULL;
1025  ChildT* child = mNodes[n].getChild();
1026  if (boost::is_same<NodeT, ChildT>::value) {
1027  mChildMask.setOff(n);
1028  mValueMask.set(n, state);
1029  mNodes[n].setValue(value);
1030  }
1031  return (boost::is_same<NodeT, ChildT>::value)
1032  ? reinterpret_cast<NodeT*>(child)
1033  : child->template stealNode<NodeT>(xyz, value, state);
1035 }
1036 
1037 
1039 
1040 
1041 template<typename ChildT, Index Log2Dim>
1042 template<typename NodeT>
1043 inline NodeT*
1045 {
1046  if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1047  NodeT::LEVEL > ChildT::LEVEL) return NULL;
1049  const Index n = this->coordToOffset(xyz);
1050  if (mChildMask.isOff(n)) return NULL;
1051  ChildT* child = mNodes[n].getChild();
1052  return (boost::is_same<NodeT, ChildT>::value)
1053  ? reinterpret_cast<NodeT*>(child)
1054  : child->template probeNode<NodeT>(xyz);
1056 }
1057 
1058 
1059 template<typename ChildT, Index Log2Dim>
1060 template<typename NodeT, typename AccessorT>
1061 inline NodeT*
1062 InternalNode<ChildT, Log2Dim>::probeNodeAndCache(const Coord& xyz, AccessorT& acc)
1063 {
1064  if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1065  NodeT::LEVEL > ChildT::LEVEL) return NULL;
1067  const Index n = this->coordToOffset(xyz);
1068  if (mChildMask.isOff(n)) return NULL;
1069  ChildT* child = mNodes[n].getChild();
1070  acc.insert(xyz, child);
1071  return (boost::is_same<NodeT, ChildT>::value)
1072  ? reinterpret_cast<NodeT*>(child)
1073  : child->template probeNodeAndCache<NodeT>(xyz, acc);
1075 }
1076 
1077 
1078 template<typename ChildT, Index Log2Dim>
1079 template<typename NodeT>
1080 inline const NodeT*
1082 {
1083  if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1084  NodeT::LEVEL > ChildT::LEVEL) return NULL;
1086  const Index n = this->coordToOffset(xyz);
1087  if (mChildMask.isOff(n)) return NULL;
1088  const ChildT* child = mNodes[n].getChild();
1089  return (boost::is_same<NodeT, ChildT>::value)
1090  ? reinterpret_cast<const NodeT*>(child)
1091  : child->template probeConstNode<NodeT>(xyz);
1093 }
1094 
1095 
1096 template<typename ChildT, Index Log2Dim>
1097 template<typename NodeT, typename AccessorT>
1098 inline const NodeT*
1099 InternalNode<ChildT, Log2Dim>::probeConstNodeAndCache(const Coord& xyz, AccessorT& acc) const
1100 {
1101  if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1102  NodeT::LEVEL > ChildT::LEVEL) return NULL;
1104  const Index n = this->coordToOffset(xyz);
1105  if (mChildMask.isOff(n)) return NULL;
1106  const ChildT* child = mNodes[n].getChild();
1107  acc.insert(xyz, child);
1108  return (boost::is_same<NodeT, ChildT>::value)
1109  ? reinterpret_cast<const NodeT*>(child)
1110  : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1112 }
1113 
1114 
1116 
1117 
1118 template<typename ChildT, Index Log2Dim>
1119 inline typename ChildT::LeafNodeType*
1121 {
1122  return this->template probeNode<LeafNodeType>(xyz);
1123 }
1124 
1125 
1126 template<typename ChildT, Index Log2Dim>
1127 template<typename AccessorT>
1128 inline typename ChildT::LeafNodeType*
1129 InternalNode<ChildT, Log2Dim>::probeLeafAndCache(const Coord& xyz, AccessorT& acc)
1130 {
1131  return this->template probeNodeAndCache<LeafNodeType>(xyz, acc);
1132 }
1133 
1134 
1135 template<typename ChildT, Index Log2Dim>
1136 template<typename AccessorT>
1137 inline const typename ChildT::LeafNodeType*
1138 InternalNode<ChildT, Log2Dim>::probeLeafAndCache(const Coord& xyz, AccessorT& acc) const
1139 {
1140  return this->probeConstLeafAndCache(xyz, acc);
1141 }
1142 
1143 
1144 template<typename ChildT, Index Log2Dim>
1145 inline const typename ChildT::LeafNodeType*
1147 {
1148  return this->template probeConstNode<LeafNodeType>(xyz);
1149 }
1150 
1151 
1152 template<typename ChildT, Index Log2Dim>
1153 template<typename AccessorT>
1154 inline const typename ChildT::LeafNodeType*
1155 InternalNode<ChildT, Log2Dim>::probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const
1156 {
1157  return this->template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1158 }
1159 
1160 
1162 
1163 
1164 template<typename ChildT, Index Log2Dim>
1165 inline void
1167 {
1168  assert(leaf != NULL);
1169  const Coord& xyz = leaf->origin();
1170  const Index n = this->coordToOffset(xyz);
1171  ChildT* child = NULL;
1172  if (mChildMask.isOff(n)) {
1173  if (ChildT::LEVEL>0) {
1174  child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1175  } else {
1176  child = reinterpret_cast<ChildT*>(leaf);
1177  }
1178  this->setChildNode(n, child);
1179  } else {
1180  if (ChildT::LEVEL>0) {
1181  child = mNodes[n].getChild();
1182  } else {
1183  delete mNodes[n].getChild();
1184  child = reinterpret_cast<ChildT*>(leaf);
1185  mNodes[n].setChild(child);
1186  }
1187  }
1188  child->addLeaf(leaf);
1189 }
1190 
1191 
1192 template<typename ChildT, Index Log2Dim>
1193 template<typename AccessorT>
1194 inline void
1196 {
1197  assert(leaf != NULL);
1198  const Coord& xyz = leaf->origin();
1199  const Index n = this->coordToOffset(xyz);
1200  ChildT* child = NULL;
1201  if (mChildMask.isOff(n)) {
1202  if (ChildT::LEVEL>0) {
1203  child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1204  acc.insert(xyz, child);//we only cache internal nodes
1205  } else {
1206  child = reinterpret_cast<ChildT*>(leaf);
1207  }
1208  this->setChildNode(n, child);
1209  } else {
1210  if (ChildT::LEVEL>0) {
1211  child = mNodes[n].getChild();
1212  acc.insert(xyz, child);//we only cache internal nodes
1213  } else {
1214  delete mNodes[n].getChild();
1215  child = reinterpret_cast<ChildT*>(leaf);
1216  mNodes[n].setChild(child);
1217  }
1218  }
1219  child->addLeafAndCache(leaf, acc);
1220 }
1221 
1222 
1224 
1225 
1226 template<typename ChildT, Index Log2Dim>
1227 inline void
1229 {
1230  assert(n < NUM_VALUES);
1231  this->makeChildNodeEmpty(n, value);
1232  mValueMask.set(n, state);
1233 }
1234 
1235 
1236 template<typename ChildT, Index Log2Dim>
1237 inline void
1239  const ValueType& value, bool state)
1240 {
1241  if (LEVEL >= level) {
1242  const Index n = this->coordToOffset(xyz);
1243  if (mChildMask.isOff(n)) {// tile case
1244  if (LEVEL > level) {
1245  ChildT* child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1246  this->setChildNode(n, child);
1247  child->addTile(level, xyz, value, state);
1248  } else {
1249  mValueMask.set(n, state);
1250  mNodes[n].setValue(value);
1251  }
1252  } else {// child branch case
1253  ChildT* child = mNodes[n].getChild();
1254  if (LEVEL > level) {
1255  child->addTile(level, xyz, value, state);
1256  } else {
1257  delete child;
1258  mChildMask.setOff(n);
1259  mValueMask.set(n, state);
1260  mNodes[n].setValue(value);
1261  }
1262  }
1263  }
1264 }
1265 
1266 
1267 template<typename ChildT, Index Log2Dim>
1268 template<typename AccessorT>
1269 inline void
1271  const ValueType& value, bool state, AccessorT& acc)
1272 {
1273  if (LEVEL >= level) {
1274  const Index n = this->coordToOffset(xyz);
1275  if (mChildMask.isOff(n)) {// tile case
1276  if (LEVEL > level) {
1277  ChildT* child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1278  this->setChildNode(n, child);
1279  acc.insert(xyz, child);
1280  child->addTileAndCache(level, xyz, value, state, acc);
1281  } else {
1282  mValueMask.set(n, state);
1283  mNodes[n].setValue(value);
1284  }
1285  } else {// child branch case
1286  ChildT* child = mNodes[n].getChild();
1287  if (LEVEL > level) {
1288  acc.insert(xyz, child);
1289  child->addTileAndCache(level, xyz, value, state, acc);
1290  } else {
1291  delete child;
1292  mChildMask.setOff(n);
1293  mValueMask.set(n, state);
1294  mNodes[n].setValue(value);
1295  }
1296  }
1297  }
1298 }
1299 
1300 
1302 
1303 
1304 template<typename ChildT, Index Log2Dim>
1305 inline typename ChildT::LeafNodeType*
1307 {
1308  const Index n = this->coordToOffset(xyz);
1309  ChildT* child = NULL;
1310  if (mChildMask.isOff(n)) {
1311  child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1312  this->setChildNode(n, child);
1313  } else {
1314  child = mNodes[n].getChild();
1315  }
1316  return child->touchLeaf(xyz);
1317 }
1318 
1319 
1320 template<typename ChildT, Index Log2Dim>
1321 template<typename AccessorT>
1322 inline typename ChildT::LeafNodeType*
1323 InternalNode<ChildT, Log2Dim>::touchLeafAndCache(const Coord& xyz, AccessorT& acc)
1324 {
1325  const Index n = this->coordToOffset(xyz);
1326  if (mChildMask.isOff(n)) {
1327  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1328  }
1329  acc.insert(xyz, mNodes[n].getChild());
1330  return mNodes[n].getChild()->touchLeafAndCache(xyz, acc);
1331 }
1332 
1333 
1335 
1336 
1337 template<typename ChildT, Index Log2Dim>
1338 inline bool
1340  const ValueType& tolerance) const
1341 {
1342  bool allEqual = true, firstValue = true, valueState = true;
1343  ValueType value = zeroVal<ValueType>();
1344  for (Index i = 0; allEqual && i < NUM_VALUES; ++i) {
1345  if (this->isChildMaskOff(i)) {
1346  // If entry i is a value, check if it is within tolerance
1347  // and whether its active state matches the other entries.
1348  if (firstValue) {
1349  firstValue = false;
1350  valueState = isValueMaskOn(i);
1351  value = mNodes[i].getValue();
1352  } else {
1353  allEqual = (isValueMaskOn(i) == valueState)
1354  && math::isApproxEqual(mNodes[i].getValue(), value, tolerance);
1355  }
1356  } else {
1357  // If entry i is a child, check if the child is constant and within tolerance
1358  // and whether its active state matches the other entries.
1359  ValueType childValue = zeroVal<ValueType>();
1360  bool isChildOn = false;
1361  if (mNodes[i].getChild()->isConstant(childValue, isChildOn, tolerance)) {
1362  if (firstValue) {
1363  firstValue = false;
1364  valueState = isChildOn;
1365  value = childValue;
1366  } else {
1367  allEqual = (isChildOn == valueState)
1368  && math::isApproxEqual(childValue, value, tolerance);
1369  }
1370  } else { // child is not constant
1371  allEqual = false;
1372  }
1373  }
1374  }
1375  if (allEqual) {
1376  constValue = value;
1377  state = valueState;
1378  }
1379  return allEqual;
1380 }
1381 
1382 
1384 
1385 
1386 template<typename ChildT, Index Log2Dim>
1387 inline bool
1389 {
1390  const bool anyActiveTiles = !mValueMask.isOff();
1391  if (LEVEL==1 || anyActiveTiles) return anyActiveTiles;
1392  for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1393  if (iter->hasActiveTiles()) return true;
1394  }
1395  return false;
1396 }
1397 
1398 
1399 template<typename ChildT, Index Log2Dim>
1400 inline bool
1402 {
1403  const Index n = this->coordToOffset(xyz);
1404  if (this->isChildMaskOff(n)) return this->isValueMaskOn(n);
1405  return mNodes[n].getChild()->isValueOn(xyz);
1406 }
1407 
1408 template<typename ChildT, Index Log2Dim>
1409 template<typename AccessorT>
1410 inline bool
1411 InternalNode<ChildT, Log2Dim>::isValueOnAndCache(const Coord& xyz, AccessorT& acc) const
1412 {
1413  const Index n = this->coordToOffset(xyz);
1414  if (this->isChildMaskOff(n)) return this->isValueMaskOn(n);
1415  acc.insert(xyz, mNodes[n].getChild());
1416  return mNodes[n].getChild()->isValueOnAndCache(xyz, acc);
1417 }
1418 
1419 
1420 template<typename ChildT, Index Log2Dim>
1421 inline const typename ChildT::ValueType&
1423 {
1424  const Index n = this->coordToOffset(xyz);
1425  return this->isChildMaskOff(n) ? mNodes[n].getValue()
1426  : mNodes[n].getChild()->getValue(xyz);
1427 }
1428 
1429 template<typename ChildT, Index Log2Dim>
1430 template<typename AccessorT>
1431 inline const typename ChildT::ValueType&
1432 InternalNode<ChildT, Log2Dim>::getValueAndCache(const Coord& xyz, AccessorT& acc) const
1433 {
1434  const Index n = this->coordToOffset(xyz);
1435  if (this->isChildMaskOn(n)) {
1436  acc.insert(xyz, mNodes[n].getChild());
1437  return mNodes[n].getChild()->getValueAndCache(xyz, acc);
1438  }
1439  return mNodes[n].getValue();
1440 }
1441 
1442 
1443 template<typename ChildT, Index Log2Dim>
1444 inline Index
1446 {
1447  const Index n = this->coordToOffset(xyz);
1448  return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz);
1449 }
1450 
1451 template<typename ChildT, Index Log2Dim>
1452 template<typename AccessorT>
1453 inline Index
1454 InternalNode<ChildT, Log2Dim>::getValueLevelAndCache(const Coord& xyz, AccessorT& acc) const
1455 {
1456  const Index n = this->coordToOffset(xyz);
1457  if (this->isChildMaskOn(n)) {
1458  acc.insert(xyz, mNodes[n].getChild());
1459  return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc);
1460  }
1461  return LEVEL;
1462 }
1463 
1464 
1465 template<typename ChildT, Index Log2Dim>
1466 inline bool
1468 {
1469  const Index n = this->coordToOffset(xyz);
1470  if (this->isChildMaskOff(n)) {
1471  value = mNodes[n].getValue();
1472  return this->isValueMaskOn(n);
1473  }
1474  return mNodes[n].getChild()->probeValue(xyz, value);
1475 }
1476 
1477 template<typename ChildT, Index Log2Dim>
1478 template<typename AccessorT>
1479 inline bool
1481  ValueType& value, AccessorT& acc) const
1482 {
1483  const Index n = this->coordToOffset(xyz);
1484  if (this->isChildMaskOn(n)) {
1485  acc.insert(xyz, mNodes[n].getChild());
1486  return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc);
1487  }
1488  value = mNodes[n].getValue();
1489  return this->isValueMaskOn(n);
1490 }
1491 
1492 
1493 template<typename ChildT, Index Log2Dim>
1494 inline void
1496 {
1497  const Index n = this->coordToOffset(xyz);
1498  bool hasChild = this->isChildMaskOn(n);
1499  if (!hasChild && this->isValueMaskOn(n)) {
1500  // If the voxel belongs to a constant tile that is active,
1501  // a child subtree must be constructed.
1502  hasChild = true;
1503  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), /*active=*/true));
1504  }
1505  if (hasChild) mNodes[n].getChild()->setValueOff(xyz);
1506 }
1507 
1508 
1509 template<typename ChildT, Index Log2Dim>
1510 inline void
1512 {
1513  const Index n = this->coordToOffset(xyz);
1514  bool hasChild = this->isChildMaskOn(n);
1515  if (!hasChild && !this->isValueMaskOn(n)) {
1516  // If the voxel belongs to a constant tile that is inactive,
1517  // a child subtree must be constructed.
1518  hasChild = true;
1519  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), /*active=*/false));
1520  }
1521  if (hasChild) mNodes[n].getChild()->setValueOn(xyz);
1522 }
1523 
1524 
1525 template<typename ChildT, Index Log2Dim>
1526 inline void
1528 {
1529  const Index n = InternalNode::coordToOffset(xyz);
1530  bool hasChild = this->isChildMaskOn(n);
1531  if (!hasChild) {
1532  const bool active = this->isValueMaskOn(n);
1533  if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1534  // If the voxel belongs to a tile that is either active or that
1535  // has a constant value that is different from the one provided,
1536  // a child subtree must be constructed.
1537  hasChild = true;
1538  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1539  }
1540  }
1541  if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value);
1542 }
1543 
1544 template<typename ChildT, Index Log2Dim>
1545 template<typename AccessorT>
1546 inline void
1548  const ValueType& value, AccessorT& acc)
1549 {
1550  const Index n = InternalNode::coordToOffset(xyz);
1551  bool hasChild = this->isChildMaskOn(n);
1552  if (!hasChild) {
1553  const bool active = this->isValueMaskOn(n);
1554  if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1555  // If the voxel belongs to a tile that is either active or that
1556  // has a constant value that is different from the one provided,
1557  // a child subtree must be constructed.
1558  hasChild = true;
1559  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1560  }
1561  }
1562  if (hasChild) {
1563  ChildT* child = mNodes[n].getChild();
1564  acc.insert(xyz, child);
1565  child->setValueOffAndCache(xyz, value, acc);
1566  }
1567 }
1568 
1569 
1570 template<typename ChildT, Index Log2Dim>
1571 inline void
1573 {
1574  const Index n = this->coordToOffset(xyz);
1575  bool hasChild = this->isChildMaskOn(n);
1576  if (!hasChild) {
1577  const bool active = this->isValueMaskOn(n); // tile's active state
1578  if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1579  // If the voxel belongs to a tile that is either inactive or that
1580  // has a constant value that is different from the one provided,
1581  // a child subtree must be constructed.
1582  hasChild = true;
1583  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1584  }
1585  }
1586  if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value);
1587 }
1588 
1589 template<typename ChildT, Index Log2Dim>
1590 template<typename AccessorT>
1591 inline void
1593  const ValueType& value, AccessorT& acc)
1594 {
1595  const Index n = this->coordToOffset(xyz);
1596  bool hasChild = this->isChildMaskOn(n);
1597  if (!hasChild) {
1598  const bool active = this->isValueMaskOn(n);
1599  if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1600  // If the voxel belongs to a tile that is either inactive or that
1601  // has a constant value that is different from the one provided,
1602  // a child subtree must be constructed.
1603  hasChild = true;
1604  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1605  }
1606  }
1607  if (hasChild) {
1608  acc.insert(xyz, mNodes[n].getChild());
1609  mNodes[n].getChild()->setValueAndCache(xyz, value, acc);
1610  }
1611 }
1612 
1613 
1614 template<typename ChildT, Index Log2Dim>
1615 inline void
1617 {
1618  const Index n = this->coordToOffset(xyz);
1619  bool hasChild = this->isChildMaskOn(n);
1620  if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1621  // If the voxel has a tile value that is different from the one provided,
1622  // a child subtree must be constructed.
1623  const bool active = this->isValueMaskOn(n);
1624  hasChild = true;
1625  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1626  }
1627  if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value);
1628 }
1629 
1630 template<typename ChildT, Index Log2Dim>
1631 template<typename AccessorT>
1632 inline void
1634  const ValueType& value, AccessorT& acc)
1635 {
1636  const Index n = this->coordToOffset(xyz);
1637  bool hasChild = this->isChildMaskOn(n);
1638  if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1639  // If the voxel has a tile value that is different from the one provided,
1640  // a child subtree must be constructed.
1641  const bool active = this->isValueMaskOn(n);
1642  hasChild = true;
1643  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1644  }
1645  if (hasChild) {
1646  acc.insert(xyz, mNodes[n].getChild());
1647  mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc);
1648  }
1649 }
1650 
1651 
1652 template<typename ChildT, Index Log2Dim>
1653 inline void
1655 {
1656  const Index n = this->coordToOffset(xyz);
1657  bool hasChild = this->isChildMaskOn(n);
1658  if (!hasChild) {
1659  if (on != this->isValueMaskOn(n)) {
1660  // If the voxel belongs to a tile with the wrong active state,
1661  // then a child subtree must be constructed.
1662  // 'on' is the voxel's new state, therefore '!on' is the tile's current state
1663  hasChild = true;
1664  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1665  }
1666  }
1667  if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on);
1668 }
1669 
1670 template<typename ChildT, Index Log2Dim>
1671 template<typename AccessorT>
1672 inline void
1673 InternalNode<ChildT, Log2Dim>::setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& acc)
1674 {
1675  const Index n = this->coordToOffset(xyz);
1676  bool hasChild = this->isChildMaskOn(n);
1677  if (!hasChild) {
1678  if (on != this->isValueMaskOn(n)) {
1679  // If the voxel belongs to a tile with the wrong active state,
1680  // then a child subtree must be constructed.
1681  // 'on' is the voxel's new state, therefore '!on' is the tile's current state
1682  hasChild = true;
1683  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1684  }
1685  }
1686  if (hasChild) {
1687  ChildT* child = mNodes[n].getChild();
1688  acc.insert(xyz, child);
1689  child->setActiveStateAndCache(xyz, on, acc);
1690  }
1691 }
1692 
1693 
1694 template<typename ChildT, Index Log2Dim>
1695 inline void
1697 {
1698  mValueMask = !mChildMask;
1699  for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1700  mNodes[iter.pos()].getChild()->setValuesOn();
1701  }
1702 }
1703 
1704 
1705 template<typename ChildT, Index Log2Dim>
1706 template<typename ModifyOp>
1707 inline void
1708 InternalNode<ChildT, Log2Dim>::modifyValue(const Coord& xyz, const ModifyOp& op)
1709 {
1710  const Index n = InternalNode::coordToOffset(xyz);
1711  bool hasChild = this->isChildMaskOn(n);
1712  if (!hasChild) {
1713  // Need to create a child if the tile is inactive,
1714  // in order to activate voxel (x, y, z).
1715  const bool active = this->isValueMaskOn(n);
1716  bool createChild = !active;
1717  if (!createChild) {
1718  // Need to create a child if applying the functor
1719  // to the tile value produces a different value.
1720  const ValueType& tileVal = mNodes[n].getValue();
1721  ValueType modifiedVal = tileVal;
1722  op(modifiedVal);
1723  createChild = !math::isExactlyEqual(tileVal, modifiedVal);
1724  }
1725  if (createChild) {
1726  hasChild = true;
1727  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1728  }
1729  }
1730  if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op);
1731 }
1732 
1733 template<typename ChildT, Index Log2Dim>
1734 template<typename ModifyOp, typename AccessorT>
1735 inline void
1736 InternalNode<ChildT, Log2Dim>::modifyValueAndCache(const Coord& xyz, const ModifyOp& op,
1737  AccessorT& acc)
1738 {
1739  const Index n = InternalNode::coordToOffset(xyz);
1740  bool hasChild = this->isChildMaskOn(n);
1741  if (!hasChild) {
1742  // Need to create a child if the tile is inactive,
1743  // in order to activate voxel (x, y, z).
1744  const bool active = this->isValueMaskOn(n);
1745  bool createChild = !active;
1746  if (!createChild) {
1747  // Need to create a child if applying the functor
1748  // to the tile value produces a different value.
1749  const ValueType& tileVal = mNodes[n].getValue();
1750  ValueType modifiedVal = tileVal;
1751  op(modifiedVal);
1752  createChild = !math::isExactlyEqual(tileVal, modifiedVal);
1753  }
1754  if (createChild) {
1755  hasChild = true;
1756  this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1757  }
1758  }
1759  if (hasChild) {
1760  ChildNodeType* child = mNodes[n].getChild();
1761  acc.insert(xyz, child);
1762  child->modifyValueAndCache(xyz, op, acc);
1763  }
1764 }
1765 
1766 
1767 template<typename ChildT, Index Log2Dim>
1768 template<typename ModifyOp>
1769 inline void
1771 {
1772  const Index n = InternalNode::coordToOffset(xyz);
1773  bool hasChild = this->isChildMaskOn(n);
1774  if (!hasChild) {
1775  const bool tileState = this->isValueMaskOn(n);
1776  const ValueType& tileVal = mNodes[n].getValue();
1777  bool modifiedState = !tileState;
1778  ValueType modifiedVal = tileVal;
1779  op(modifiedVal, modifiedState);
1780  // Need to create a child if applying the functor to the tile
1781  // produces a different value or active state.
1782  if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) {
1783  hasChild = true;
1784  this->setChildNode(n, new ChildNodeType(xyz, tileVal, tileState));
1785  }
1786  }
1787  if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op);
1788 }
1789 
1790 template<typename ChildT, Index Log2Dim>
1791 template<typename ModifyOp, typename AccessorT>
1792 inline void
1794  const Coord& xyz, const ModifyOp& op, AccessorT& acc)
1795 {
1796  const Index n = InternalNode::coordToOffset(xyz);
1797  bool hasChild = this->isChildMaskOn(n);
1798  if (!hasChild) {
1799  const bool tileState = this->isValueMaskOn(n);
1800  const ValueType& tileVal = mNodes[n].getValue();
1801  bool modifiedState = !tileState;
1802  ValueType modifiedVal = tileVal;
1803  op(modifiedVal, modifiedState);
1804  // Need to create a child if applying the functor to the tile
1805  // produces a different value or active state.
1806  if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) {
1807  hasChild = true;
1808  this->setChildNode(n, new ChildNodeType(xyz, tileVal, tileState));
1809  }
1810  }
1811  if (hasChild) {
1812  ChildNodeType* child = mNodes[n].getChild();
1813  acc.insert(xyz, child);
1814  child->modifyValueAndActiveStateAndCache(xyz, op, acc);
1815  }
1816 }
1817 
1818 
1820 
1821 
1822 template<typename ChildT, Index Log2Dim>
1823 inline void
1824 InternalNode<ChildT, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1825 {
1826  Coord xyz, tileMin, tileMax;
1827  for (int x = bbox.min().x(); x <= bbox.max().x(); x = tileMax.x() + 1) {
1828  xyz.setX(x);
1829  for (int y = bbox.min().y(); y <= bbox.max().y(); y = tileMax.y() + 1) {
1830  xyz.setY(y);
1831  for (int z = bbox.min().z(); z <= bbox.max().z(); z = tileMax.z() + 1) {
1832  xyz.setZ(z);
1833 
1834  // Get the bounds of the tile that contains voxel (x, y, z).
1835  const Index n = this->coordToOffset(xyz);
1836  tileMin = this->offsetToGlobalCoord(n);
1837  tileMax = tileMin.offsetBy(ChildT::DIM - 1);
1838 
1839  if (xyz != tileMin || Coord::lessThan(bbox.max(), tileMax)) {
1840  // If the box defined by (xyz, bbox.max()) doesn't completely enclose
1841  // the tile to which xyz belongs, create a child node (or retrieve
1842  // the existing one).
1843  ChildT* child = NULL;
1844  if (this->isChildMaskOff(n)) {
1845  // Replace the tile with a newly-created child that is initialized
1846  // with the tile's value and active state.
1847  child = new ChildT(xyz, mNodes[n].getValue(), this->isValueMaskOn(n));
1848  this->setChildNode(n, child);
1849  } else {
1850  child = mNodes[n].getChild();
1851  }
1852 
1853  // Forward the fill request to the child.
1854  if (child) {
1855  child->fill(CoordBBox(xyz, Coord::minComponent(bbox.max(), tileMax)),
1856  value, active);
1857  }
1858 
1859  } else {
1860  // If the box given by (xyz, bbox.max()) completely encloses
1861  // the tile to which xyz belongs, create the tile (if it
1862  // doesn't already exist) and give it the fill value.
1863  this->makeChildNodeEmpty(n, value);
1864  mValueMask.set(n, active);
1865  }
1866  }
1867  }
1868  }
1869 }
1870 
1871 
1873 
1874 
1875 template<typename ChildT, Index Log2Dim>
1876 template<typename DenseT>
1877 inline void
1878 InternalNode<ChildT, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const
1879 {
1880  typedef typename DenseT::ValueType DenseValueType;
1881 
1882  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1883  const Coord& min = dense.bbox().min();
1884  for (Coord xyz = bbox.min(), max; xyz[0] <= bbox.max()[0]; xyz[0] = max[0] + 1) {
1885  for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] = max[1] + 1) {
1886  for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] = max[2] + 1) {
1887  const Index n = this->coordToOffset(xyz);
1888  // Get max coordinates of the child node that contains voxel xyz.
1889  max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
1890 
1891  // Get the bbox of the interection of bbox and the child node
1892  CoordBBox sub(xyz, Coord::minComponent(bbox.max(), max));
1893 
1894  if (this->isChildMaskOn(n)) {//is a child
1895  mNodes[n].getChild()->copyToDense(sub, dense);
1896  } else {//a tile value
1897  const ValueType value = mNodes[n].getValue();
1898  sub.translate(-min);
1899  DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
1900  for (Int32 x=sub.min()[0], ex=sub.max()[0]+1; x<ex; ++x) {
1901  DenseValueType* a1 = a0 + x*xStride;
1902  for (Int32 y=sub.min()[1], ey=sub.max()[1]+1; y<ey; ++y) {
1903  DenseValueType* a2 = a1 + y*yStride;
1904  for (Int32 z=sub.min()[2], ez=sub.max()[2]+1; z<ez; ++z, a2 += zStride) {
1905  *a2 = DenseValueType(value);
1906  }
1907  }
1908  }
1909  }
1910  }
1911  }
1912  }
1913 }
1914 
1915 
1917 
1918 
1919 template<typename ChildT, Index Log2Dim>
1920 inline void
1921 InternalNode<ChildT, Log2Dim>::writeTopology(std::ostream& os, bool toHalf) const
1922 {
1923  mChildMask.save(os);
1924  mValueMask.save(os);
1925 
1926  {
1927  // Copy all of this node's values into an array.
1928  boost::shared_array<ValueType> values(new ValueType[NUM_VALUES]);
1929  const ValueType zero = zeroVal<ValueType>();
1930  for (Index i = 0; i < NUM_VALUES; ++i) {
1931  values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero);
1932  }
1933  // Compress (optionally) and write out the contents of the array.
1934  io::writeCompressedValues(os, values.get(), NUM_VALUES, mValueMask, mChildMask, toHalf);
1935  }
1936  // Write out the child nodes in order.
1937  for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1938  iter->writeTopology(os, toHalf);
1939  }
1940 }
1941 
1942 
1943 template<typename ChildT, Index Log2Dim>
1944 inline void
1945 InternalNode<ChildT, Log2Dim>::readTopology(std::istream& is, bool fromHalf)
1946 {
1947  mChildMask.load(is);
1948  mValueMask.load(is);
1949 
1951  for (Index i = 0; i < NUM_VALUES; ++i) {
1952  if (this->isChildMaskOn(i)) {
1953  ChildNodeType* child =
1954  new ChildNodeType(offsetToGlobalCoord(i), zeroVal<ValueType>());
1955  mNodes[i].setChild(child);
1956  child->readTopology(is);
1957  } else {
1958  ValueType value;
1959  is.read(reinterpret_cast<char*>(&value), sizeof(ValueType));
1960  mNodes[i].setValue(value);
1961  }
1962  }
1963  } else {
1964  const bool oldVersion =
1966  const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
1967  {
1968  // Read in (and uncompress, if necessary) all of this node's values
1969  // into a contiguous array.
1970  boost::shared_array<ValueType> values(new ValueType[numValues]);
1971  io::readCompressedValues(is, values.get(), numValues, mValueMask, fromHalf);
1972 
1973  // Copy values from the array into this node's table.
1974  if (oldVersion) {
1975  Index n = 0;
1976  for (ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
1977  mNodes[iter.pos()].setValue(values[n++]);
1978  }
1979  assert(n == numValues);
1980  } else {
1981  for (ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
1982  mNodes[iter.pos()].setValue(values[iter.pos()]);
1983  }
1984  }
1985  }
1986  // Read in all child nodes and insert them into the table at their proper locations.
1987  for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1988  ChildNodeType* child = new ChildNodeType(iter.getCoord(), zeroVal<ValueType>());
1989  mNodes[iter.pos()].setChild(child);
1990  child->readTopology(is, fromHalf);
1991  }
1992  }
1993 }
1994 
1995 
1997 
1998 
1999 template<typename ChildT, Index Log2Dim>
2000 inline const typename ChildT::ValueType&
2002 {
2003  return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2004 }
2005 
2006 
2007 template<typename ChildT, Index Log2Dim>
2008 inline const typename ChildT::ValueType&
2010 {
2011  const Index n = NUM_VALUES - 1;
2012  return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2013 }
2014 
2015 
2017 
2018 
2019 template<typename ChildT, Index Log2Dim>
2020 inline void
2022 {
2023  this->signedFloodFill(background, math::negative(background));
2024 }
2025 
2026 
2027 template<typename ChildT, Index Log2Dim>
2028 inline void
2030  const ValueType& insideValue)
2031 {
2032  // First, flood fill all child nodes.
2033  for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2034  iter->signedFloodFill(outsideValue, insideValue);
2035  }
2036  const Index first = mChildMask.findFirstOn();
2037  if (first < NUM_VALUES) {
2038  bool xInside = math::isNegative(mNodes[first].getChild()->getFirstValue()),
2039  yInside = xInside, zInside = xInside;
2040  for (Index x = 0; x != (1 << Log2Dim); ++x) {
2041  const int x00 = x << (2 * Log2Dim); // offset for block(x, 0, 0)
2042  if (isChildMaskOn(x00)) {
2043  xInside = math::isNegative(mNodes[x00].getChild()->getLastValue());
2044  }
2045  yInside = xInside;
2046  for (Index y = 0; y != (1 << Log2Dim); ++y) {
2047  const Index xy0 = x00 + (y << Log2Dim); // offset for block(x, y, 0)
2048  if (isChildMaskOn(xy0)) {
2049  yInside = math::isNegative(mNodes[xy0].getChild()->getLastValue());
2050  }
2051  zInside = yInside;
2052  for (Index z = 0; z != (1 << Log2Dim); ++z) {
2053  const Index xyz = xy0 + z; // offset for block(x, y, z)
2054  if (isChildMaskOn(xyz)) {
2055  zInside = math::isNegative(mNodes[xyz].getChild()->getLastValue());
2056  } else {
2057  mNodes[xyz].setValue(zInside ? insideValue : outsideValue);
2058  }
2059  }
2060  }
2061  }
2062  } else {//no child nodes exist simply use the sign of the first tile value.
2063  const ValueType v = math::isNegative(mNodes[0].getValue()) ? insideValue : outsideValue;
2064  for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(v);
2065  }
2066 }
2067 
2068 
2069 template<typename ChildT, Index Log2Dim>
2070 inline void
2072 {
2073  for (Index i = 0; i < NUM_VALUES; ++i) {
2074  if (this->isChildMaskOn(i)) {
2075  mNodes[i].getChild()->negate();
2076  } else {
2077  mNodes[i].setValue(math::negative(mNodes[i].getValue()));
2078  }
2079  }
2080 
2081 }
2082 
2083 
2084 template<typename ChildT, Index Log2Dim>
2085 inline void
2087 {
2088  for (ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2089  this->setChildNode(iter.pos(), new ChildNodeType(iter.getCoord(), iter.getValue(), true));
2090  }
2091  for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) iter->voxelizeActiveTiles();
2092 }
2093 
2094 
2096 
2097 
2098 template<typename ChildT, Index Log2Dim>
2099 template<MergePolicy Policy>
2100 inline void
2102  const ValueType& background, const ValueType& otherBackground)
2103 {
2105 
2106  switch (Policy) {
2107 
2108  case MERGE_ACTIVE_STATES:
2109  default:
2110  {
2111  for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) {
2112  const Index n = iter.pos();
2113  if (mChildMask.isOn(n)) {
2114  // Merge this node's child with the other node's child.
2115  mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2116  background, otherBackground);
2117  } else if (mValueMask.isOff(n)) {
2118  // Replace this node's inactive tile with the other node's child
2119  // and replace the other node's child with a tile of undefined value
2120  // (which is okay since the other tree is assumed to be cannibalized
2121  // in the process of merging).
2122  ChildNodeType* child = other.mNodes[n].getChild();
2123  other.mChildMask.setOff(n);
2124  child->resetBackground(otherBackground, background);
2125  this->setChildNode(n, child);
2126  }
2127  }
2128 
2129  // Copy active tile values.
2130  for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) {
2131  const Index n = iter.pos();
2132  if (mValueMask.isOff(n)) {
2133  // Replace this node's child or inactive tile with the other node's active tile.
2134  this->makeChildNodeEmpty(n, iter.getValue());
2135  mValueMask.setOn(n);
2136  }
2137  }
2138  break;
2139  }
2140 
2141  case MERGE_NODES:
2142  {
2143  for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) {
2144  const Index n = iter.pos();
2145  if (mChildMask.isOn(n)) {
2146  // Merge this node's child with the other node's child.
2147  mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2148  } else {
2149  // Replace this node's tile (regardless of its active state) with
2150  // the other node's child and replace the other node's child with
2151  // a tile of undefined value (which is okay since the other tree
2152  // is assumed to be cannibalized in the process of merging).
2153  ChildNodeType* child = other.mNodes[n].getChild();
2154  other.mChildMask.setOff(n);
2155  child->resetBackground(otherBackground, background);
2156  this->setChildNode(n, child);
2157  }
2158  }
2159  break;
2160  }
2161 
2163  {
2164  // Transfer children from the other tree to this tree.
2165  for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) {
2166  const Index n = iter.pos();
2167  if (mChildMask.isOn(n)) {
2168  // Merge this node's child with the other node's child.
2169  mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2170  } else {
2171  // Replace this node's tile with the other node's child, leaving the other
2172  // node with an inactive tile of undefined value (which is okay since
2173  // the other tree is assumed to be cannibalized in the process of merging).
2174  ChildNodeType* child = other.mNodes[n].getChild();
2175  other.mChildMask.setOff(n);
2176  child->resetBackground(otherBackground, background);
2177  if (mValueMask.isOn(n)) {
2178  // Merge the child with this node's active tile.
2179  child->template merge<Policy>(mNodes[n].getValue(), /*on=*/true);
2180  mValueMask.setOff(n);
2181  }
2182  mChildMask.setOn(n);
2183  mNodes[n].setChild(child);
2184  }
2185  }
2186 
2187  // Merge active tiles into this tree.
2188  for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) {
2189  const Index n = iter.pos();
2190  if (mChildMask.isOn(n)) {
2191  // Merge the other node's active tile into this node's child.
2192  mNodes[n].getChild()->template merge<Policy>(iter.getValue(), /*on=*/true);
2193  } else if (mValueMask.isOff(n)) {
2194  // Replace this node's inactive tile with the other node's active tile.
2195  mNodes[n].setValue(iter.getValue());
2196  mValueMask.setOn(n);
2197  }
2198  }
2199  break;
2200  }
2201 
2202  }
2204 }
2205 
2206 
2207 template<typename ChildT, Index Log2Dim>
2208 template<MergePolicy Policy>
2209 inline void
2210 InternalNode<ChildT, Log2Dim>::merge(const ValueType& tileValue, bool tileActive)
2211 {
2213 
2214  if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return;
2215 
2216  // For MERGE_ACTIVE_STATES_AND_NODES, inactive tiles in the other tree are ignored.
2217  if (!tileActive) return;
2218 
2219  // Iterate over this node's children and inactive tiles.
2220  for (ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2221  const Index n = iter.pos();
2222  if (mChildMask.isOn(n)) {
2223  // Merge the other node's active tile into this node's child.
2224  mNodes[n].getChild()->template merge<Policy>(tileValue, /*on=*/true);
2225  } else {
2226  // Replace this node's inactive tile with the other node's active tile.
2227  iter.setValue(tileValue);
2228  mValueMask.setOn(n);
2229  }
2230  }
2232 }
2233 
2234 
2236 
2237 
2238 template<typename ChildT, Index Log2Dim>
2239 template<typename OtherChildT>
2240 inline void
2242 {
2243  typedef typename InternalNode<OtherChildT, Log2Dim>::ChildOnCIter OtherChildIter;
2244  typedef typename InternalNode<OtherChildT, Log2Dim>::ValueOnCIter OtherValueIter;
2245 
2246  // Loop over other node's child nodes
2247  for (OtherChildIter iter = other.cbeginChildOn(); iter; ++iter) {
2248  const Index i = iter.pos();
2249  if (mChildMask.isOn(i)) {//this has a child node
2250  mNodes[i].getChild()->topologyUnion(*iter);
2251  } else {// this is a tile so replace it with a child branch with identical topology
2252  ChildNodeType* child = new ChildNodeType(*iter, mNodes[i].getValue(), TopologyCopy());
2253  if (mValueMask.isOn(i)) {
2254  mValueMask.isOff(i);//we're replacing the active tile with a child branch
2255  child->setValuesOn();//activate all values since it was an active tile
2256  }
2257  mChildMask.setOn(i);
2258  mNodes[i].setChild(child);
2259  }
2260  }
2261  // Loop over other node's active tiles
2262  for (OtherValueIter iter = other.cbeginValueOn(); iter; ++iter) {
2263  const Index i = iter.pos();
2264  if (mChildMask.isOn(i)) {
2265  mNodes[i].getChild()->setValuesOn();
2266  } else if (mValueMask.isOff(i)) { //inactive tile
2267  mValueMask.setOn(i);
2268  }
2269  }
2270 }
2271 
2272 template<typename ChildT, Index Log2Dim>
2273 template<typename OtherChildT>
2274 inline void
2276  const ValueType& background)
2277 {
2278  // Loop over this node's child nodes
2279  for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2280  const Index i = iter.pos();
2281  if (other.mChildMask.isOn(i)) {//other also has a child node
2282  iter->topologyIntersection(*(other.mNodes[i].getChild()), background);
2283  } else if (other.mValueMask.isOff(i)) {//other is an inactive tile
2284  delete mNodes[i].getChild();//convert child to an inactive tile
2285  mNodes[i].setValue(background);
2286  mChildMask.setOff(i);
2287  mValueMask.setOff(i);
2288  }
2289  }
2290 
2291  // Loop over this node's active tiles
2292  for (ValueOnCIter iter = this->cbeginValueOn(); iter; ++iter) {
2293  const Index i = iter.pos();
2294  if (other.mChildMask.isOn(i)) {//other has a child node
2295  ChildNodeType* child = new ChildNodeType(*(other.mNodes[i].getChild()),
2296  *iter, TopologyCopy());
2297  this->setChildNode(i, child);//replace the active tile with a child branch
2298  } else if (other.mValueMask.isOff(i)) {//other is an inactive tile
2299  mValueMask.setOff(i);//convert active tile to an inactive tile
2300  }
2301  }
2302 }
2303 
2304 template<typename ChildT, Index Log2Dim>
2305 template<typename OtherChildT>
2306 inline void
2308  const ValueType& background)
2309 {
2310  typedef typename InternalNode<OtherChildT, Log2Dim>::ChildOnCIter OtherChildIter;
2311  typedef typename InternalNode<OtherChildT, Log2Dim>::ValueOnCIter OtherValueIter;
2312 
2313  // Loop over other node's child nodes
2314  for (OtherChildIter iter = other.cbeginChildOn(); iter; ++iter) {
2315  const Index i = iter.pos();
2316  if (mChildMask.isOn(i)) {//this has a child node
2317  mNodes[i].getChild()->topologyDifference(*iter, background);
2318  } else if (mValueMask.isOn(i)) {// this is an active tile
2319  ChildNodeType* child = new ChildNodeType(iter.getCoord(), mNodes[i].getValue(), true);
2320  child->topologyDifference(*iter, background);
2321  this->setChildNode(i, child);//we're replacing the active tile with a child branch
2322  }
2323  }
2324 
2325  // Loop over other node's active tiles
2326  for (OtherValueIter iter = other.cbeginValueOn(); iter; ++iter) {
2327  const Index i = iter.pos();
2328  if (mChildMask.isOn(i)) {//this has a child node
2329  delete mNodes[i].getChild();//convert child to an inactive tile
2330  mNodes[i].setValue(background);
2331  mChildMask.setOff(i);
2332  mValueMask.setOff(i);
2333  } else if (mValueMask.isOn(i)) {//this is an active tile
2334  mValueMask.setOff(i);//convert active tile to an inactive tile
2335  }
2336  }
2337 }
2338 
2340 
2341 
2342 template<typename ChildT, Index Log2Dim>
2343 template<typename CombineOp>
2344 inline void
2346 {
2347  const ValueType zero = zeroVal<ValueType>();
2348 
2350 
2351  for (Index i = 0; i < NUM_VALUES; ++i) {
2352  if (this->isChildMaskOff(i) && other.isChildMaskOff(i)) {
2353  // Both this node and the other node have constant values (tiles).
2354  // Combine the two values and store the result as this node's new tile value.
2355  op(args.setARef(mNodes[i].getValue())
2356  .setAIsActive(isValueMaskOn(i))
2357  .setBRef(other.mNodes[i].getValue())
2358  .setBIsActive(other.isValueMaskOn(i)));
2359  mNodes[i].setValue(args.result());
2360  mValueMask.set(i, args.resultIsActive());
2361  } else if (this->isChildMaskOn(i) && other.isChildMaskOff(i)) {
2362  // Combine this node's child with the other node's constant value.
2363  ChildNodeType* child = mNodes[i].getChild();
2364  assert(child);
2365  if (child) {
2366  child->combine(other.mNodes[i].getValue(), other.isValueMaskOn(i), op);
2367  }
2368  } else if (this->isChildMaskOff(i) && other.isChildMaskOn(i)) {
2369  // Combine this node's constant value with the other node's child.
2370  ChildNodeType* child = other.mNodes[i].getChild();
2371  assert(child);
2372  if (child) {
2373  // Combine this node's constant value with the other node's child,
2374  // but use a new functor in which the A and B values are swapped,
2375  // since the constant value is the A value, not the B value.
2377  child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp);
2378 
2379  // Steal the other node's child.
2380  other.mChildMask.setOff(i);
2381  other.mNodes[i].setValue(zero);
2382  this->setChildNode(i, child);
2383  }
2384 
2385  } else /*if (isChildMaskOn(i) && other.isChildMaskOn(i))*/ {
2386  // Combine this node's child with the other node's child.
2388  *child = mNodes[i].getChild(),
2389  *otherChild = other.mNodes[i].getChild();
2390  assert(child);
2391  assert(otherChild);
2392  if (child && otherChild) {
2393  child->combine(*otherChild, op);
2394  }
2395  }
2396  }
2397 }
2398 
2399 
2400 template<typename ChildT, Index Log2Dim>
2401 template<typename CombineOp>
2402 inline void
2403 InternalNode<ChildT, Log2Dim>::combine(const ValueType& value, bool valueIsActive, CombineOp& op)
2404 {
2406 
2407  for (Index i = 0; i < NUM_VALUES; ++i) {
2408  if (this->isChildMaskOff(i)) {
2409  // Combine this node's constant value with the given constant value.
2410  op(args.setARef(mNodes[i].getValue())
2411  .setAIsActive(isValueMaskOn(i))
2412  .setBRef(value)
2413  .setBIsActive(valueIsActive));
2414  mNodes[i].setValue(args.result());
2415  mValueMask.set(i, args.resultIsActive());
2416  } else /*if (isChildMaskOn(i))*/ {
2417  // Combine this node's child with the given constant value.
2418  ChildNodeType* child = mNodes[i].getChild();
2419  assert(child);
2420  if (child) child->combine(value, valueIsActive, op);
2421  }
2422  }
2423 }
2424 
2425 
2427 
2428 
2429 template<typename ChildT, Index Log2Dim>
2430 template<typename CombineOp, typename OtherNodeType>
2431 inline void
2432 InternalNode<ChildT, Log2Dim>::combine2(const InternalNode& other0, const OtherNodeType& other1,
2433  CombineOp& op)
2434 {
2436 
2437  for (Index i = 0; i < NUM_VALUES; ++i) {
2438  if (other0.isChildMaskOff(i) && other1.isChildMaskOff(i)) {
2439  op(args.setARef(other0.mNodes[i].getValue())
2440  .setAIsActive(other0.isValueMaskOn(i))
2441  .setBRef(other1.mNodes[i].getValue())
2442  .setBIsActive(other1.isValueMaskOn(i)));
2443  // Replace child i with a constant value.
2444  this->makeChildNodeEmpty(i, args.result());
2445  mValueMask.set(i, args.resultIsActive());
2446  } else {
2447  if (this->isChildMaskOff(i)) {
2448  // Add a new child with the same coordinates, etc. as the other node's child.
2449  const Coord& childOrigin = other0.isChildMaskOn(i)
2450  ? other0.mNodes[i].getChild()->origin()
2451  : other1.mNodes[i].getChild()->origin();
2452  this->setChildNode(i, new ChildNodeType(childOrigin, mNodes[i].getValue()));
2453  }
2454 
2455  if (other0.isChildMaskOff(i)) {
2456  // Combine node1's child with node0's constant value
2457  // and write the result into child i.
2458  mNodes[i].getChild()->combine2(other0.mNodes[i].getValue(),
2459  *other1.mNodes[i].getChild(), other0.isValueMaskOn(i), op);
2460  } else if (other1.isChildMaskOff(i)) {
2461  // Combine node0's child with node1's constant value
2462  // and write the result into child i.
2463  mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(),
2464  other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
2465  } else {
2466  // Combine node0's child with node1's child
2467  // and write the result into child i.
2468  mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(),
2469  *other1.mNodes[i].getChild(), op);
2470  }
2471  }
2472  }
2473 }
2474 
2475 
2476 template<typename ChildT, Index Log2Dim>
2477 template<typename CombineOp, typename OtherNodeType>
2478 inline void
2479 InternalNode<ChildT, Log2Dim>::combine2(const ValueType& value, const OtherNodeType& other,
2480  bool valueIsActive, CombineOp& op)
2481 {
2483 
2484  for (Index i = 0; i < NUM_VALUES; ++i) {
2485  if (other.isChildMaskOff(i)) {
2486  op(args.setARef(value)
2487  .setAIsActive(valueIsActive)
2488  .setBRef(other.mNodes[i].getValue())
2489  .setBIsActive(other.isValueMaskOn(i)));
2490  // Replace child i with a constant value.
2491  this->makeChildNodeEmpty(i, args.result());
2492  mValueMask.set(i, args.resultIsActive());
2493  } else {
2494  typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
2495  assert(otherChild);
2496  if (this->isChildMaskOff(i)) {
2497  // Add a new child with the same coordinates, etc.
2498  // as the other node's child.
2499  this->setChildNode(i, new ChildNodeType(*otherChild));
2500  }
2501  // Combine the other node's child with a constant value
2502  // and write the result into child i.
2503  mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
2504  }
2505  }
2506 }
2507 
2508 
2509 template<typename ChildT, Index Log2Dim>
2510 template<typename CombineOp, typename OtherValueType>
2511 inline void
2512 InternalNode<ChildT, Log2Dim>::combine2(const InternalNode& other, const OtherValueType& value,
2513  bool valueIsActive, CombineOp& op)
2514 {
2516 
2517  for (Index i = 0; i < NUM_VALUES; ++i) {
2518  if (other.isChildMaskOff(i)) {
2519  op(args.setARef(other.mNodes[i].getValue())
2520  .setAIsActive(other.isValueMaskOn(i))
2521  .setBRef(value)
2522  .setBIsActive(valueIsActive));
2523  // Replace child i with a constant value.
2524  this->makeChildNodeEmpty(i, args.result());
2525  mValueMask.set(i, args.resultIsActive());
2526  } else {
2527  ChildNodeType* otherChild = other.mNodes[i].getChild();
2528  assert(otherChild);
2529  if (this->isChildMaskOff(i)) {
2530  // Add a new child with the same coordinates, etc. as the other node's child.
2531  this->setChildNode(i,
2532  new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
2533  }
2534  // Combine the other node's child with a constant value
2535  // and write the result into child i.
2536  mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
2537  }
2538  }
2539 }
2540 
2541 
2543 
2544 
2545 template<typename ChildT, Index Log2Dim>
2546 template<typename BBoxOp>
2547 inline void
2549 {
2550  for (ValueOnCIter i = this->cbeginValueOn(); i; ++i) {
2551 #ifdef _MSC_VER
2552  op.operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), ChildNodeType::DIM));
2553 #else
2554  op.template operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), ChildNodeType::DIM));
2555 #endif
2556  }
2557  if (op.template descent<LEVEL>()) {
2558  for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) i->visitActiveBBox(op);
2559  } else {
2560  for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) {
2561 #ifdef _MSC_VER
2562  op.operator()<LEVEL>(i->getNodeBoundingBox());
2563 #else
2564  op.template operator()<LEVEL>(i->getNodeBoundingBox());
2565 #endif
2566  }
2567  }
2568 }
2569 
2570 
2571 template<typename ChildT, Index Log2Dim>
2572 template<typename VisitorOp>
2573 inline void
2575 {
2576  doVisit<InternalNode, VisitorOp, ChildAllIter>(*this, op);
2577 }
2578 
2579 
2580 template<typename ChildT, Index Log2Dim>
2581 template<typename VisitorOp>
2582 inline void
2584 {
2585  doVisit<const InternalNode, VisitorOp, ChildAllCIter>(*this, op);
2586 }
2587 
2588 
2589 template<typename ChildT, Index Log2Dim>
2590 template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
2591 inline void
2592 InternalNode<ChildT, Log2Dim>::doVisit(NodeT& self, VisitorOp& op)
2593 {
2594  typename NodeT::ValueType val;
2595  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2596  if (op(iter)) continue;
2597  if (typename ChildAllIterT::ChildNodeType* child = iter.probeChild(val)) {
2598  child->visit(op);
2599  }
2600  }
2601 }
2602 
2603 
2605 
2606 
2607 template<typename ChildT, Index Log2Dim>
2608 template<typename OtherNodeType, typename VisitorOp>
2609 inline void
2610 InternalNode<ChildT, Log2Dim>::visit2Node(OtherNodeType& other, VisitorOp& op)
2611 {
2612  doVisit2Node<InternalNode, OtherNodeType, VisitorOp, ChildAllIter,
2613  typename OtherNodeType::ChildAllIter>(*this, other, op);
2614 }
2615 
2616 
2617 template<typename ChildT, Index Log2Dim>
2618 template<typename OtherNodeType, typename VisitorOp>
2619 inline void
2620 InternalNode<ChildT, Log2Dim>::visit2Node(OtherNodeType& other, VisitorOp& op) const
2621 {
2622  doVisit2Node<const InternalNode, OtherNodeType, VisitorOp, ChildAllCIter,
2623  typename OtherNodeType::ChildAllCIter>(*this, other, op);
2624 }
2625 
2626 
2627 template<typename ChildT, Index Log2Dim>
2628 template<
2629  typename NodeT,
2630  typename OtherNodeT,
2631  typename VisitorOp,
2632  typename ChildAllIterT,
2633  typename OtherChildAllIterT>
2634 inline void
2635 InternalNode<ChildT, Log2Dim>::doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp& op)
2636 {
2637  // Allow the two nodes to have different ValueTypes, but not different dimensions.
2638  BOOST_STATIC_ASSERT(OtherNodeT::NUM_VALUES == NodeT::NUM_VALUES);
2639  BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
2640 
2641  typename NodeT::ValueType val;
2642  typename OtherNodeT::ValueType otherVal;
2643 
2644  ChildAllIterT iter = self.beginChildAll();
2645  OtherChildAllIterT otherIter = other.beginChildAll();
2646 
2647  for ( ; iter && otherIter; ++iter, ++otherIter)
2648  {
2649  const size_t skipBranch = static_cast<size_t>(op(iter, otherIter));
2650 
2651  typename ChildAllIterT::ChildNodeType* child =
2652  (skipBranch & 1U) ? NULL : iter.probeChild(val);
2653  typename OtherChildAllIterT::ChildNodeType* otherChild =
2654  (skipBranch & 2U) ? NULL : otherIter.probeChild(otherVal);
2655 
2656  if (child != NULL && otherChild != NULL) {
2657  child->visit2Node(*otherChild, op);
2658  } else if (child != NULL) {
2659  child->visit2(otherIter, op);
2660  } else if (otherChild != NULL) {
2661  otherChild->visit2(iter, op, /*otherIsLHS=*/true);
2662  }
2663  }
2664 }
2665 
2666 
2668 
2669 
2670 template<typename ChildT, Index Log2Dim>
2671 template<typename OtherChildAllIterType, typename VisitorOp>
2672 inline void
2673 InternalNode<ChildT, Log2Dim>::visit2(OtherChildAllIterType& otherIter,
2674  VisitorOp& op, bool otherIsLHS)
2675 {
2676  doVisit2<InternalNode, VisitorOp, ChildAllIter, OtherChildAllIterType>(
2677  *this, otherIter, op, otherIsLHS);
2678 }
2679 
2680 
2681 template<typename ChildT, Index Log2Dim>
2682 template<typename OtherChildAllIterType, typename VisitorOp>
2683 inline void
2684 InternalNode<ChildT, Log2Dim>::visit2(OtherChildAllIterType& otherIter,
2685  VisitorOp& op, bool otherIsLHS) const
2686 {
2687  doVisit2<const InternalNode, VisitorOp, ChildAllCIter, OtherChildAllIterType>(
2688  *this, otherIter, op, otherIsLHS);
2689 }
2690 
2691 
2692 template<typename ChildT, Index Log2Dim>
2693 template<typename NodeT, typename VisitorOp, typename ChildAllIterT, typename OtherChildAllIterT>
2694 inline void
2695 InternalNode<ChildT, Log2Dim>::doVisit2(NodeT& self, OtherChildAllIterT& otherIter,
2696  VisitorOp& op, bool otherIsLHS)
2697 {
2698  if (!otherIter) return;
2699 
2700  const size_t skipBitMask = (otherIsLHS ? 2U : 1U);
2701 
2702  typename NodeT::ValueType val;
2703  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2704  const size_t skipBranch = static_cast<size_t>(
2705  otherIsLHS ? op(otherIter, iter) : op(iter, otherIter));
2706 
2707  typename ChildAllIterT::ChildNodeType* child =
2708  (skipBranch & skipBitMask) ? NULL : iter.probeChild(val);
2709 
2710  if (child != NULL) child->visit2(otherIter, op, otherIsLHS);
2711  }
2712 }
2713 
2714 
2716 
2717 
2718 template<typename ChildT, Index Log2Dim>
2719 inline void
2720 InternalNode<ChildT, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
2721 {
2722  for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2723  iter->writeBuffers(os, toHalf);
2724  }
2725 }
2726 
2727 
2728 template<typename ChildT, Index Log2Dim>
2729 inline void
2730 InternalNode<ChildT, Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
2731 {
2732  for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2733  iter->readBuffers(is, fromHalf);
2734  }
2735 }
2736 
2737 
2739 
2740 
2741 template<typename ChildT, Index Log2Dim>
2742 void
2744 {
2745  dims.push_back(Log2Dim);
2746  ChildNodeType::getNodeLog2Dims(dims);
2747 }
2748 
2749 
2750 template<typename ChildT, Index Log2Dim>
2751 inline void
2753 {
2754  assert(n<(1<<3*Log2Dim));
2755  xyz.setX(n >> 2*Log2Dim);
2756  n &= ((1<<2*Log2Dim)-1);
2757  xyz.setY(n >> Log2Dim);
2758  xyz.setZ(n & ((1<<Log2Dim)-1));
2759 }
2760 
2761 
2762 template<typename ChildT, Index Log2Dim>
2763 inline Index
2765 {
2766  return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
2767  + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
2768  + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
2769 }
2770 
2771 
2772 template<typename ChildT, Index Log2Dim>
2773 inline Coord
2775 {
2776  Coord local;
2777  this->offsetToLocalCoord(n, local);
2778  local <<= ChildT::TOTAL;
2779  return local + this->origin();
2780 }
2781 
2782 
2784 
2785 
2786 template<typename ChildT, Index Log2Dim>
2787 inline void
2789  const ValueType& newBackground)
2790 {
2791  if (math::isExactlyEqual(oldBackground, newBackground)) return;
2792  for (Index i = 0; i < NUM_VALUES; ++i) {
2793  if (this->isChildMaskOn(i)) {
2794  mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
2795  } else if (this->isValueMaskOff(i)) {
2796  if (math::isApproxEqual(mNodes[i].getValue(), oldBackground)) {
2797  mNodes[i].setValue(newBackground);
2798  } else if (math::isApproxEqual(mNodes[i].getValue(), math::negative(oldBackground))) {
2799  mNodes[i].setValue(math::negative(newBackground));
2800  }
2801  }
2802  }
2803 }
2804 
2805 
2806 template<typename ChildT, Index Log2Dim>
2807 template<typename OtherChildNodeType, Index OtherLog2Dim>
2808 inline bool
2811 {
2812  if (Log2Dim != OtherLog2Dim || mChildMask != other->mChildMask ||
2813  mValueMask != other->mValueMask) return false;
2814  for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2815  if (!iter->hasSameTopology(other->mNodes[iter.pos()].getChild())) return false;
2816  }
2817  return true;
2818 }
2819 
2820 
2821 template<typename ChildT, Index Log2Dim>
2822 inline void
2824 {
2825  assert(child);
2826  if (this->isChildMaskOn(i)) {
2827  delete mNodes[i].getChild();
2828  } else {
2829  mChildMask.setOn(i);
2830  mValueMask.setOff(i);
2831  }
2832  mNodes[i].setChild(child);
2833 }
2834 
2835 template<typename ChildT, Index Log2Dim>
2836 inline void
2838 {
2839  assert(child);
2840  assert(mChildMask.isOff(i));
2841  mChildMask.setOn(i);
2842  mValueMask.setOff(i);
2843  mNodes[i].setChild(child);
2844 }
2845 
2846 
2847 template<typename ChildT, Index Log2Dim>
2848 inline ChildT*
2850 {
2851  if (this->isChildMaskOff(i)) {
2852  mNodes[i].setValue(value);
2853  return NULL;
2854  }
2855  ChildNodeType* child = mNodes[i].getChild();
2856  mChildMask.setOff(i);
2857  mNodes[i].setValue(value);
2858  return child;
2859 }
2860 
2861 
2862 template<typename ChildT, Index Log2Dim>
2863 inline void
2865 {
2866  delete this->unsetChildNode(n, value);
2867 }
2868 
2869 template<typename ChildT, Index Log2Dim>
2870 inline ChildT*
2872 {
2873  assert(this->isChildMaskOn(n));
2874  return mNodes[n].getChild();
2875 }
2876 
2877 
2878 template<typename ChildT, Index Log2Dim>
2879 inline const ChildT*
2881 {
2882  assert(this->isChildMaskOn(n));
2883  return mNodes[n].getChild();
2884 }
2885 
2886 } // namespace tree
2887 } // namespace OPENVDB_VERSION_NAME
2888 } // namespace openvdb
2889 
2890 #endif // OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
2891 
2892 // Copyright (c) 2012-2013 DreamWorks Animation LLC
2893 // All rights reserved. This software is distributed under the
2894 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
bool resultIsActive() const
Definition: Types.h:314
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by the node regardless of it...
Definition: InternalNode.h:283
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:158
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
void unsetItem(Index pos, const ValueT &value) const
Definition: InternalNode.h:203
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: InternalNode.h:262
static const Index NUM_VALUES
Definition: InternalNode.h:73
Definition: InternalNode.h:128
ValueOnCIter beginValueOn() const
Definition: InternalNode.h:238
void combine(FloatTreeT &lhsDist, IntTreeT &lhsIndex, FloatTreeT &rhsDist, IntTreeT &rhsIndex)
Definition: MeshToVolume.h:396
const ValueType & getLastValue() const
If the last entry in this node's table is a tile, return the tile's value. Otherwise, return the result of calling getLastValue() on the child.
Definition: InternalNode.h:2009
bool isInactive() const
Return true if this node has no children and only contains inactive values.
Definition: InternalNode.h:293
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:148
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition: Compression.h:381
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:393
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &)
Same as touchLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
void writeTopology(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:1921
void addLeaf(LeafNodeType *leaf)
Add the specified leaf to this node, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: InternalNode.h:1166
Index getValueLevelAndCache(const Coord &xyz, AccessorT &) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides...
Definition: InternalNode.h:1454
bool isConstant(ValueType &constValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: InternalNode.h:1339
ValueIter< InternalNode, const ValueType, MaskOffIterator, ValueAll > ValueAllIter
Definition: InternalNode.h:222
ChildAllCIter cbeginChildAll() const
Definition: InternalNode.h:227
NodeMaskType::OffIterator MaskOffIterator
Definition: InternalNode.h:123
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:303
Index64 onTileCount() const
Definition: InternalNode.h:928
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: InternalNode.h:1736
Index32 Index
Definition: Types.h:57
ChildT & getItem(Index pos) const
Definition: InternalNode.h:141
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
ChildNodeType::LeafNodeType LeafNodeType
Definition: InternalNode.h:64
bool isChildMaskOn(Index n) const
Definition: InternalNode.h:679
Definition: Types.h:341
ValueIter< InternalNode, const ValueType, MaskOffIterator, ValueOff > ValueOffIter
Definition: InternalNode.h:220
bool isValueMaskOff(Index n) const
Definition: InternalNode.h:677
NodeMaskType::DenseIterator MaskDenseIterator
Definition: InternalNode.h:124
Index64 offLeafVoxelCount() const
Definition: InternalNode.h:917
void pruneOp(PruneOp &)
Call the PruneOp functor for each child node and, if the functor returns true, prune the node and rep...
Definition: InternalNode.h:971
ValueIter< const InternalNode, const ValueType, MaskOnIterator, ValueOn > ValueOnCIter
Definition: InternalNode.h:219
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return NULL.
Definition: InternalNode.h:1146
void readBuffers(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:2730
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: InternalNode.h:2774
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1547
ValueOffCIter beginValueOff() const
Definition: InternalNode.h:239
const ValueType & getFirstValue() const
If the first entry in this node's table is a tile, return the tile's value. Otherwise, return the result of calling getFirstValue() on the child.
Definition: InternalNode.h:2001
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: InternalNode.h:1654
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:2720
ValueIter< InternalNode, const ValueType, MaskOnIterator, ValueOn > ValueOnIter
Definition: InternalNode.h:218
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
void voxelizeActiveTiles()
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: InternalNode.h:2086
ValueOffCIter cbeginValueOff() const
Definition: InternalNode.h:236
bool hasActiveTiles() const
Return true if this node or any of its child nodes have any active tiles.
Definition: InternalNode.h:1388
Definition: NodeMasks.h:188
void topologyDifference(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Difference this node's set of active values with the active values of the other node, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this node and inactive in the other node.
Definition: InternalNode.h:127
void setItem(Index pos, ChildT *child) const
Definition: InternalNode.h:197
UnionType mNodes[NUM_VALUES]
Definition: InternalNode.h:714
Helper class for use with Tree::pruneOp() to replace constant branches (to within the provided tolera...
Definition: tree/Util.h:47
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: InternalNode.h:988
ValueIter< const InternalNode, const ValueType, MaskOffIterator, ValueOff > ValueOffCIter
Definition: InternalNode.h:221
void readTopology(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:1945
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: InternalNode.h:1708
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: InternalNode.h:298
Index32 nonLeafCount() const
Definition: InternalNode.h:868
Index64 onLeafVoxelCount() const
Definition: InternalNode.h:905
NodeType * probeNodeAndCache(const Coord &xyz, AccessorT &)
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
const AValueType & result() const
Get the output value.
Definition: Types.h:295
ValueConverter::Type is the type of an InternalNode having the same child hierarchy and dimensions...
Definition: InternalNode.h:81
static Index getChildDim()
Definition: InternalNode.h:249
DenseIter< InternalNode, ChildNodeType, ValueType, ChildAll > ChildAllIter
Definition: InternalNode.h:215
LeafNodeType * touchLeaf(const Coord &xyz)
Return the leaf node that contains voxel (x, y, z). If no such node exists, create one...
Definition: InternalNode.h:1306
DenseIter()
Definition: InternalNode.h:181
void pruneInactive()
Reduce the memory footprint of this tree by replacing with background tiles any nodes whose values ar...
Definition: InternalNode.h:1006
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: InternalNode.h:2764
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Expand the specified bounding box so that it includes the active tiles of this internal node as well ...
Definition: InternalNode.h:952
static void doVisit(NodeT &, VisitorOp &)
Definition: InternalNode.h:2592
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return NULL.
Definition: InternalNode.h:1120
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:287
void merge(InternalNode &other, const ValueType &background, const ValueType &otherBackground)
Efficiently merge another tree into this tree using one of several schemes.
Definition: InternalNode.h:2101
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: InternalNode.h:1401
ChildOnIter beginChildOn()
Definition: InternalNode.h:231
void copyToDense(const CoordBBox &bbox, DenseT &dense) const
Copy into a dense grid the values of the voxels that lie within a given bounding box.
Definition: InternalNode.h:1878
const NodeType * probeConstNode(const Coord &xyz) const
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return NULL.
ValueAllCIter cbeginValueAll() const
Definition: InternalNode.h:237
ChildNodeType * unsetChildNode(Index i, const ValueType &value)
Definition: InternalNode.h:2849
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: InternalNode.h:1467
Definition: NodeMasks.h:219
ChildOffIter beginChildOff()
Definition: InternalNode.h:232
static void doVisit2Node(NodeT &, OtherNodeT &, VisitorOp &)
Definition: InternalNode.h:2635
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:265
ChildAllIter beginChildAll()
Definition: InternalNode.h:233
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:138
NodeMaskType mValueMask
Definition: InternalNode.h:715
Index64 offVoxelCount() const
Definition: InternalNode.h:893
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information for all active tiles and leaf nodes ...
Definition: InternalNode.h:2548
void setValuesOn()
Mark all values (both tiles and voxels) as active.
Definition: InternalNode.h:1696
void setItem(Index pos, const ValueT &v) const
Definition: InternalNode.h:164
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: InternalNode.h:1770
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: InternalNode.h:939
Definition: InternalNode.h:60
void signedFloodFill(const ValueType &background)
Overwrite each inactive value in this node and in any child nodes with a new value whose magnitude is...
Definition: InternalNode.h:2021
NodeMaskType mChildMask
Definition: InternalNode.h:715
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: InternalNode.h:1480
void addLeafAndCache(LeafNodeType *leaf, AccessorT &)
Same as addLeaf() except, if necessary, update the accessor with pointers to the nodes along the path...
Definition: InternalNode.h:1195
bool isOff(Index32 n) const
Return true if the nth bit is off.
Definition: NodeMasks.h:444
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:368
uint64_t Index64
Definition: Types.h:56
#define OPENVDB_VERSION_NAME
Definition: version.h:45
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: InternalNode.h:260
bool isValueMaskOff() const
Definition: InternalNode.h:678
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: InternalNode.h:1793
ValueIter< const InternalNode, const ValueType, MaskOffIterator, ChildOff > ChildOffCIter
Definition: InternalNode.h:214
ChildOnCIter cbeginChildOn() const
Definition: InternalNode.h:225
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:351
NodeUnion< ValueType, ChildNodeType > UnionType
Definition: InternalNode.h:66
InternalNode()
Definition: InternalNode.h:96
Definition: Types.h:223
_ChildNodeType ChildNodeType
Definition: InternalNode.h:63
const NodeType * probeConstNodeAndCache(const Coord &xyz, AccessorT &) const
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
ChildOffCIter cbeginChildOff() const
Definition: InternalNode.h:226
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: InternalNode.h:1511
void setItem(Index pos, const ChildT &c) const
Definition: InternalNode.h:148
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:58
ValueOnIter beginValueOn()
Definition: InternalNode.h:241
static Index dim()
Definition: InternalNode.h:246
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:497
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Change inactive tiles or voxels with value oldBackground to newBackground or -oldBackground to -newBa...
Definition: InternalNode.h:2788
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return NULL.
void topologyUnion(const InternalNode< OtherChildNodeType, Log2Dim > &other)
Union this branch's set of active values with the other branch's active values. The value type of the...
bool isValueMaskOn() const
Definition: InternalNode.h:676
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:211
Definition: InternalNode.h:128
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:121
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:388
void combine(InternalNode &other, CombineOp &)
Definition: InternalNode.h:2345
Index64 onVoxelCount() const
Definition: InternalNode.h:881
ChildOffCIter beginChildOff() const
Definition: InternalNode.h:229
ChildIter< const InternalNode, const ChildNodeType, MaskOnIterator, ChildOn > ChildOnCIter
Definition: InternalNode.h:212
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: InternalNode.h:1616
void negate()
Definition: InternalNode.h:2071
Index getValueLevel(const Coord &xyz) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides...
Definition: InternalNode.h:1445
uint32_t Index32
Definition: Types.h:55
void modifyItem(Index pos, const ModifyOp &op) const
Definition: InternalNode.h:168
DenseIter< const InternalNode, const ChildNodeType, ValueType, ChildAll > ChildAllCIter
Definition: InternalNode.h:216
int32_t Int32
Definition: Types.h:59
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1633
OPENVDB_IMPORT uint32_t getFormatVersion(std::istream &)
Return the file format version number associated with the given input stream.
ValueOffIter beginValueOff()
Definition: InternalNode.h:242
ChildNodeType * getChildNode(Index n)
Returns a pointer to the child node at the linear offset n.
Definition: InternalNode.h:2871
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
bool isChildMaskOff(Index n) const
Definition: InternalNode.h:680
Helper class for use with Tree::pruneOp() to replace inactive branches with more memory-efficient ina...
Definition: tree/Util.h:74
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition: InternalNode.h:717
NodeMaskType::OnIterator MaskOnIterator
Definition: InternalNode.h:122
Index pos() const
Identical to offset.
Definition: Iterator.h:94
void addTileAndCache(Index level, const Coord &xyz, const ValueType &, bool state, AccessorT &)
Same as addTile() except, if necessary, update the accessor with pointers to the nodes along the path...
Definition: InternalNode.h:1270
void makeChildNodeEmpty(Index n, const ValueType &value)
Definition: InternalNode.h:2864
ChildOnCIter beginChildOn() const
Definition: InternalNode.h:228
void setChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:2837
InternalNode< typename ChildNodeType::template ValueConverter< OtherValueType >::Type, Log2Dim > Type
Definition: InternalNode.h:83
void topologyIntersection(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Intersects this tree's set of active values with the active values of the other tree, whose ValueType may be different.
util::NodeMask< Log2Dim > NodeMaskType
Definition: InternalNode.h:67
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:122
const ValueType & getValue(const Coord &xyz) const
Definition: InternalNode.h:1422
bool hasSameTopology(const InternalNode< OtherChildNodeType, OtherLog2Dim > *other) const
Return true if the given tree branch has the same node and active value topology as this tree branch ...
Definition: InternalNode.h:2809
bool getItem(Index pos, ChildT *&child, NonConstValueT &value) const
Definition: InternalNode.h:185
ValueAllIter beginValueAll()
Definition: InternalNode.h:243
ValueIter< InternalNode, const ValueType, MaskOffIterator, ChildOff > ChildOffIter
Definition: InternalNode.h:213
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1592
DenseIteratorBase< MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT > BaseT
Definition: InternalNode.h:178
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
bool isApproxEqual(const Hermite &lhs, const Hermite &rhs)
Definition: Hermite.h:470
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: InternalNode.h:1018
static Index getLevel()
Definition: InternalNode.h:247
SameConfiguration::value is true if and only if OtherNodeType is the type of an Intern...
Definition: InternalNode.h:90
void visit2Node(OtherNodeType &other, VisitorOp &)
Definition: InternalNode.h:2610
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: InternalNode.h:1673
bool isEmpty() const
Definition: InternalNode.h:285
const ValueT & getItem(Index pos) const
Definition: InternalNode.h:161
BaseT::NonConstValueType NonConstValueT
Definition: InternalNode.h:179
static void offsetToLocalCoord(Index n, Coord &xyz)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: InternalNode.h:2752
ChildAllCIter beginChildAll() const
Definition: InternalNode.h:230
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:107
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: InternalNode.h:1495
Definition: NodeMasks.h:250
void fill(const CoordBBox &bbox, const ValueType &, bool active=true)
Set all voxels within an axis-aligned box to a constant value. (The min and max coordinates are inclu...
Definition: InternalNode.h:1824
void combine2(const InternalNode &other0, const OtherNodeType &other1, CombineOp &)
Definition: InternalNode.h:2432
void visit(VisitorOp &)
Definition: InternalNode.h:2574
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
Index32 leafCount() const
Definition: InternalNode.h:855
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: InternalNode.h:1411
bool isNegative(const Type &x)
Return true if x is less than zero.
Definition: Math.h:304
Definition: Types.h:380
ValueOnCIter cbeginValueOn() const
Definition: InternalNode.h:235
ValueIter< const InternalNode, const ValueType, MaskOffIterator, ValueAll > ValueAllCIter
Definition: InternalNode.h:223
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly creating a parent bran...
Definition: InternalNode.h:1238
bool isValueMaskOn(Index n) const
Definition: InternalNode.h:675
virtual ~InternalNode()
Definition: InternalNode.h:842
ChildIter()
Definition: InternalNode.h:137
ValueIter()
Definition: InternalNode.h:157
bool isChildMaskOff() const
Definition: InternalNode.h:681
ChildIter< InternalNode, ChildNodeType, MaskOnIterator, ChildOn > ChildOnIter
Definition: InternalNode.h:211
static void doVisit2(NodeT &, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: InternalNode.h:2695
static void getNodeLog2Dims(std::vector< Index > &dims)
Definition: InternalNode.h:2743
ChildNodeType::ValueType ValueType
Definition: InternalNode.h:65
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition: InternalNode.h:182
Definition: InternalNode.h:56
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition: Compression.h:277
ValueAllCIter beginValueAll() const
Definition: InternalNode.h:240
Definition: InternalNode.h:127
void resetChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:2823
boost::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:217