OpenVDB  2.3.0
LeafNode.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 
31 #ifndef OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
32 #define OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
33 
34 #include <iostream>
35 #include <algorithm> // for std::swap
36 #include <cstring> // for std::memcpy()
37 #include <boost/shared_ptr.hpp>
38 #include <boost/static_assert.hpp>
39 #include <boost/bind.hpp>
40 #include <tbb/blocked_range.h>
41 #include <tbb/parallel_for.h>
42 #include <openvdb/Types.h>
43 #include <openvdb/util/NodeMasks.h>
44 #include <openvdb/io/Compression.h> // for io::readData(), etc.
45 #include "Iterator.h"
46 #include "Util.h"
47 
48 
49 class TestLeaf;
50 template<typename> class TestLeafIO;
51 
52 namespace openvdb {
54 namespace OPENVDB_VERSION_NAME {
55 namespace tree {
56 
57 template<Index, typename> struct SameLeafConfig; // forward declaration
58 
59 
64 template<typename T, Index Log2Dim>
65 class LeafNode
66 {
67 public:
68  typedef T ValueType;
70  typedef boost::shared_ptr<LeafNode> Ptr;
72 
73  static const Index
74  LOG2DIM = Log2Dim, // needed by parent nodes
75  TOTAL = Log2Dim, // needed by parent nodes
76  DIM = 1 << TOTAL, // dimension along one coordinate direction
77  NUM_VALUES = 1 << 3 * Log2Dim,
78  NUM_VOXELS = NUM_VALUES, // total number of voxels represented by this node
79  SIZE = NUM_VALUES,
80  LEVEL = 0; // level 0 = leaf
81 
84  template<typename OtherValueType>
85  struct ValueConverter {
87  };
88 
91  template<typename OtherNodeType>
94  };
95 
96 
99  class Buffer
100  {
101  public:
103  Buffer(): mData(new ValueType[SIZE]) {}
105  Buffer(const ValueType& val) : mData(new ValueType[SIZE]) { this->fill(val); }
107  Buffer(const Buffer& other) : mData(new ValueType[SIZE]) { *this = other; }
109  ~Buffer() { delete [] mData; }
111  void fill(const ValueType& val)
112  {
113  ValueType* target = mData;
114  Index n = SIZE;
115  while (n--) *target++ = val;
116  }
118  const ValueType& getValue(Index i) const { assert(i < SIZE); return mData[i]; }
120  const ValueType& operator[](Index i) const { return this->getValue(i); }
122  void setValue(Index i, const ValueType& val) { assert(i < SIZE); mData[i] = val; }
124  Buffer& operator=(const Buffer& other)
125  {
126  ValueType* target = mData;
127  const ValueType* source = other.mData;
128  Index n = SIZE;
129  while (n--) *target++ = *source++;
130  return *this;
131  }
134  bool operator==(const Buffer& other) const
135  {
136  const ValueType* target = mData;
137  const ValueType* source = other.mData;
138  Index n = SIZE;
139  while (n && math::isExactlyEqual(*target++, *source++)) --n;
140  return n == 0;
141  }
144  bool operator!=(const Buffer& other) const { return !(other == *this); }
146  void swap(Buffer& other)
147  {
148  ValueType* tmp = mData;
149  mData = other.mData;
150  other.mData = tmp;
151  }
153  static Index memUsage() { return sizeof(ValueType*) + SIZE * sizeof(ValueType); }
155  static Index size() { return SIZE; }
156 
157  private:
160  ValueType& operator[](Index i) { assert(i < SIZE); return mData[i]; }
161 
162  friend class ::TestLeaf;
163  // Allow the parent LeafNode to access this Buffer's data pointer.
164  friend class LeafNode;
165 
166  ValueType* mData;
167  }; // class Buffer
168 
169 
171  LeafNode();
172 
177  explicit LeafNode(const Coord& coords,
178  const ValueType& value = zeroVal<ValueType>(),
179  bool active = false);
180 
182  LeafNode(const LeafNode&);
183 
185  template<typename OtherValueType>
186  explicit LeafNode(const LeafNode<OtherValueType, Log2Dim>& other);
187 
189  template<typename OtherValueType>
191  const ValueType& offValue, const ValueType& onValue, TopologyCopy);
192 
194  template<typename OtherValueType>
196  const ValueType& background, TopologyCopy);
197 
199  ~LeafNode();
200 
201  //
202  // Statistics
203  //
205  static Index log2dim() { return Log2Dim; }
207  static Index dim() { return DIM; }
209  static Index size() { return SIZE; }
211  static Index numValues() { return SIZE; }
213  static Index getLevel() { return LEVEL; }
215  static void getNodeLog2Dims(std::vector<Index>& dims) { dims.push_back(Log2Dim); }
217  static Index getChildDim() { return 1; }
219  static Index32 leafCount() { return 1; }
221  static Index32 nonLeafCount() { return 0; }
222 
224  Index64 onVoxelCount() const { return mValueMask.countOn(); }
226  Index64 offVoxelCount() const { return mValueMask.countOff(); }
227  Index64 onLeafVoxelCount() const { return onVoxelCount(); }
228  Index64 offLeafVoxelCount() const { return offVoxelCount(); }
229  static Index64 onTileCount() { return 0; }
230  static Index64 offTileCount() { return 0; }
232  bool isEmpty() const { return mValueMask.isOff(); }
234  bool isDense() const { return mValueMask.isOn(); }
235 
237  Index64 memUsage() const;
238 
242  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
243 
246  CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); }
247 
249  void setOrigin(const Coord& origin) { mOrigin = origin; }
251  const Coord& origin() const { return mOrigin; }
253  void getOrigin(Coord& origin) const { origin = mOrigin; }
254  void getOrigin(Int32& x, Int32& y, Int32& z) const { mOrigin.asXYZ(x, y, z); }
256 
258  static Index coordToOffset(const Coord& xyz);
261  static Coord offsetToLocalCoord(Index n);
263  Coord offsetToGlobalCoord(Index n) const;
264 
266  std::string str() const;
267 
270  template<typename OtherType, Index OtherLog2Dim>
271  bool hasSameTopology(const LeafNode<OtherType, OtherLog2Dim>* other) const;
272 
274  bool operator==(const LeafNode& other) const;
275  bool operator!=(const LeafNode& other) const { return !(other == *this); }
276 
277 protected:
281 
282  // Type tags to disambiguate template instantiations
283  struct ValueOn {}; struct ValueOff {}; struct ValueAll {};
284  struct ChildOn {}; struct ChildOff {}; struct ChildAll {};
285 
286  template<typename MaskIterT, typename NodeT, typename ValueT, typename TagT>
287  struct ValueIter:
288  // Derives from SparseIteratorBase, but can also be used as a dense iterator,
289  // if MaskIterT is a dense mask iterator type.
290  public SparseIteratorBase<
291  MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
292  {
294 
296  ValueIter(const MaskIterT& iter, NodeT* parent): BaseT(iter, parent) {}
297 
298  ValueT& getItem(Index pos) const { return this->parent().getValue(pos); }
299  ValueT& getValue() const { return this->parent().getValue(this->pos()); }
300 
301  // Note: setItem() can't be called on const iterators.
302  void setItem(Index pos, const ValueT& value) const
303  {
304  this->parent().setValueOnly(pos, value);
305  }
306  // Note: setValue() can't be called on const iterators.
307  void setValue(const ValueT& value) const
308  {
309  this->parent().setValueOnly(this->pos(), value);
310  }
311 
312  // Note: modifyItem() can't be called on const iterators.
313  template<typename ModifyOp>
314  void modifyItem(Index n, const ModifyOp& op) const { this->parent().modifyValue(n, op); }
315  // Note: modifyValue() can't be called on const iterators.
316  template<typename ModifyOp>
317  void modifyValue(const ModifyOp& op) const { this->parent().modifyValue(this->pos(), op); }
318  };
319 
321  template<typename MaskIterT, typename NodeT, typename TagT>
322  struct ChildIter:
323  public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>
324  {
326  ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
327  MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>(iter, parent) {}
328  };
329 
330  template<typename NodeT, typename ValueT, typename TagT>
331  struct DenseIter: public DenseIteratorBase<
332  MaskDenseIterator, DenseIter<NodeT, ValueT, TagT>, NodeT, /*ChildT=*/void, ValueT>
333  {
336 
338  DenseIter(const MaskDenseIterator& iter, NodeT* parent): BaseT(iter, parent) {}
339 
340  bool getItem(Index pos, void*& child, NonConstValueT& value) const
341  {
342  value = this->parent().getValue(pos);
343  child = NULL;
344  return false; // no child
345  }
346 
347  // Note: setItem() can't be called on const iterators.
348  //void setItem(Index pos, void* child) const {}
349 
350  // Note: unsetItem() can't be called on const iterators.
351  void unsetItem(Index pos, const ValueT& value) const
352  {
353  this->parent().setValueOnly(pos, value);
354  }
355  };
356 
357 public:
370 
371  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
372  ValueOnCIter beginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
373  ValueOnIter beginValueOn() { return ValueOnIter(mValueMask.beginOn(), this); }
374  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
375  ValueOffCIter beginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
376  ValueOffIter beginValueOff() { return ValueOffIter(mValueMask.beginOff(), this); }
377  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mValueMask.beginDense(), this); }
378  ValueAllCIter beginValueAll() const { return ValueAllCIter(mValueMask.beginDense(), this); }
379  ValueAllIter beginValueAll() { return ValueAllIter(mValueMask.beginDense(), this); }
380 
381  ValueOnCIter cendValueOn() const { return ValueOnCIter(mValueMask.endOn(), this); }
382  ValueOnCIter endValueOn() const { return ValueOnCIter(mValueMask.endOn(), this); }
383  ValueOnIter endValueOn() { return ValueOnIter(mValueMask.endOn(), this); }
384  ValueOffCIter cendValueOff() const { return ValueOffCIter(mValueMask.endOff(), this); }
385  ValueOffCIter endValueOff() const { return ValueOffCIter(mValueMask.endOff(), this); }
386  ValueOffIter endValueOff() { return ValueOffIter(mValueMask.endOff(), this); }
387  ValueAllCIter cendValueAll() const { return ValueAllCIter(mValueMask.endDense(), this); }
388  ValueAllCIter endValueAll() const { return ValueAllCIter(mValueMask.endDense(), this); }
389  ValueAllIter endValueAll() { return ValueAllIter(mValueMask.endDense(), this); }
390 
391  // Note that [c]beginChildOn() and [c]beginChildOff() actually return end iterators,
392  // because leaf nodes have no children.
393  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
394  ChildOnCIter beginChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
395  ChildOnIter beginChildOn() { return ChildOnIter(mValueMask.endOn(), this); }
396  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
397  ChildOffCIter beginChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
398  ChildOffIter beginChildOff() { return ChildOffIter(mValueMask.endOff(), this); }
399  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mValueMask.beginDense(), this); }
400  ChildAllCIter beginChildAll() const { return ChildAllCIter(mValueMask.beginDense(), this); }
401  ChildAllIter beginChildAll() { return ChildAllIter(mValueMask.beginDense(), this); }
402 
403  ChildOnCIter cendChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
404  ChildOnCIter endChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
405  ChildOnIter endChildOn() { return ChildOnIter(mValueMask.endOn(), this); }
406  ChildOffCIter cendChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
407  ChildOffCIter endChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
408  ChildOffIter endChildOff() { return ChildOffIter(mValueMask.endOff(), this); }
409  ChildAllCIter cendChildAll() const { return ChildAllCIter(mValueMask.endDense(), this); }
410  ChildAllCIter endChildAll() const { return ChildAllCIter(mValueMask.endDense(), this); }
411  ChildAllIter endChildAll() { return ChildAllIter(mValueMask.endDense(), this); }
412 
413  //
414  // Buffer management
415  //
418  void swap(Buffer& other) { mBuffer.swap(other); }
419  const Buffer& buffer() const { return mBuffer; }
420  Buffer& buffer() { return mBuffer; }
421 
422  //
423  // I/O methods
424  //
428  void readTopology(std::istream& is, bool fromHalf = false);
432  void writeTopology(std::ostream& os, bool toHalf = false) const;
433 
437  void readBuffers(std::istream& is, bool fromHalf = false);
441  void writeBuffers(std::ostream& os, bool toHalf = false) const;
442 
443  size_t streamingSize(bool toHalf = false) const;
444 
445  //
446  // Accessor methods
447  //
449  const ValueType& getValue(const Coord& xyz) const;
451  const ValueType& getValue(Index offset) const;
452 
456  bool probeValue(const Coord& xyz, ValueType& val) const;
460  bool probeValue(Index offset, ValueType& val) const;
461 
463  static Index getValueLevel(const Coord&) { return LEVEL; }
464 
466  void setActiveState(const Coord& xyz, bool on);
468  void setActiveState(Index offset, bool on) { assert(offset<SIZE); mValueMask.set(offset, on); }
469 
471  void setValueOnly(const Coord& xyz, const ValueType& val);
473  void setValueOnly(Index offset, const ValueType& val);
474 
476  void setValueOff(const Coord& xyz) { mValueMask.setOff(LeafNode::coordToOffset(xyz)); }
478  void setValueOff(Index offset) { assert(offset < SIZE); mValueMask.setOff(offset); }
479 
481  void setValueOff(const Coord& xyz, const ValueType& val);
483  void setValueOff(Index offset, const ValueType& val);
484 
486  void setValueOn(const Coord& xyz) { mValueMask.setOn(LeafNode::coordToOffset(xyz)); }
488  void setValueOn(Index offset) { assert(offset < SIZE); mValueMask.setOn(offset); }
490  void setValueOn(const Coord& xyz, const ValueType& val) {
491  this->setValueOn(LeafNode::coordToOffset(xyz), val);
492  }
494  void setValue(const Coord& xyz, const ValueType& val) { this->setValueOn(xyz, val); };
496  void setValueOn(Index offset, const ValueType& val) {
497  mBuffer[offset] = val;
498  mValueMask.setOn(offset);
499  }
500 
503  template<typename ModifyOp>
504  void modifyValue(Index offset, const ModifyOp& op)
505  {
506  op(mBuffer[offset]);
507  mValueMask.setOn(offset);
508  }
511  template<typename ModifyOp>
512  void modifyValue(const Coord& xyz, const ModifyOp& op)
513  {
514  this->modifyValue(this->coordToOffset(xyz), op);
515  }
516 
518  template<typename ModifyOp>
519  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
520  {
521  const Index offset = this->coordToOffset(xyz);
522  bool state = mValueMask.isOn(offset);
523  op(mBuffer[offset], state);
524  mValueMask.set(offset, state);
525  }
526 
528  void setValuesOn() { mValueMask.setOn(); }
530  void setValuesOff() { mValueMask.setOff(); }
531 
533  bool isValueOn(const Coord& xyz) const {return this->isValueOn(LeafNode::coordToOffset(xyz));}
535  bool isValueOn(Index offset) const { return mValueMask.isOn(offset); }
536 
538  static bool hasActiveTiles() { return false; }
539 
541  void fill(const CoordBBox& bbox, const ValueType&, bool active = true);
542 
544  void fill(const ValueType& value);
546  void fill(const ValueType& value, bool active);
547 
559  template<typename DenseT>
560  void copyToDense(const CoordBBox& bbox, DenseT& dense) const;
561 
578  template<typename DenseT>
579  void copyFromDense(const CoordBBox& bbox, const DenseT& dense,
580  const ValueType& background, const ValueType& tolerance);
581 
584  template<typename AccessorT>
585  const ValueType& getValueAndCache(const Coord& xyz, AccessorT&) const
586  {
587  return this->getValue(xyz);
588  }
589 
592  template<typename AccessorT>
593  bool isValueOnAndCache(const Coord& xyz, AccessorT&) const { return this->isValueOn(xyz); }
594 
597  template<typename AccessorT>
598  void setValueAndCache(const Coord& xyz, const ValueType& val, AccessorT&)
599  {
600  this->setValueOn(xyz, val);
601  }
602 
606  template<typename AccessorT>
607  void setValueOnlyAndCache(const Coord& xyz, const ValueType& val, AccessorT&)
608  {
609  this->setValueOnly(xyz, val);
610  }
611 
615  template<typename ModifyOp, typename AccessorT>
616  void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
617  {
618  this->modifyValue(xyz, op);
619  }
620 
623  template<typename ModifyOp, typename AccessorT>
624  void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
625  {
626  this->modifyValueAndActiveState(xyz, op);
627  }
628 
631  template<typename AccessorT>
632  void setValueOffAndCache(const Coord& xyz, const ValueType& value, AccessorT&)
633  {
634  this->setValueOff(xyz, value);
635  }
636 
640  template<typename AccessorT>
641  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&)
642  {
643  this->setActiveState(xyz, on);
644  }
645 
649  template<typename AccessorT>
650  bool probeValueAndCache(const Coord& xyz, ValueType& val, AccessorT&) const
651  {
652  return this->probeValue(xyz, val);
653  }
654 
658  template<typename AccessorT>
659  const ValueType& getValue(const Coord& xyz, bool& state, int& level, AccessorT&) const
660  {
661  const Index offset = this->coordToOffset(xyz);
662  state = mValueMask.isOn(offset);
663  level = LEVEL;
664  return mBuffer[offset];
665  }
666 
669  template<typename AccessorT>
670  static Index getValueLevelAndCache(const Coord&, AccessorT&) { return LEVEL; }
671 
675  const ValueType& getFirstValue() const { return mBuffer[0]; }
677  const ValueType& getLastValue() const { return mBuffer[SIZE - 1]; }
678 
681  void resetBackground(const ValueType& oldBackground, const ValueType& newBackground);
682 
688  void signedFloodFill(const ValueType& background);
689 
695  void signedFloodFill(const ValueType& outside, const ValueType& inside);
696 
697  void negate();
698 
700 
701  template<MergePolicy Policy> void merge(const LeafNode&);
702  template<MergePolicy Policy> void merge(const ValueType& tileValue, bool tileActive);
703  template<MergePolicy Policy>
704  void merge(const LeafNode& other, const ValueType& /*bg*/, const ValueType& /*otherBG*/);
705 
712  template<typename OtherType>
713  void topologyUnion(const LeafNode<OtherType, Log2Dim>& other);
714 
726  template<typename OtherType>
727  void topologyIntersection(const LeafNode<OtherType, Log2Dim>& other, const ValueType&);
728 
740  template<typename OtherType>
741  void topologyDifference(const LeafNode<OtherType, Log2Dim>& other, const ValueType&);
742 
743  template<typename CombineOp>
744  void combine(const LeafNode& other, CombineOp& op);
745  template<typename CombineOp>
746  void combine(const ValueType& value, bool valueIsActive, CombineOp& op);
747 
748  template<typename CombineOp, typename OtherType /*= ValueType*/>
749  void combine2(const LeafNode& other, const OtherType&, bool valueIsActive, CombineOp&);
750  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
751  void combine2(const ValueType&, const OtherNodeT& other, bool valueIsActive, CombineOp&);
752  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
753  void combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp&);
754 
760  template<typename BBoxOp> void visitActiveBBox(BBoxOp&) const;
761 
762  template<typename VisitorOp> void visit(VisitorOp&);
763  template<typename VisitorOp> void visit(VisitorOp&) const;
764 
765  template<typename OtherLeafNodeType, typename VisitorOp>
766  void visit2Node(OtherLeafNodeType& other, VisitorOp&);
767  template<typename OtherLeafNodeType, typename VisitorOp>
768  void visit2Node(OtherLeafNodeType& other, VisitorOp&) const;
769  template<typename IterT, typename VisitorOp>
770  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false);
771  template<typename IterT, typename VisitorOp>
772  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false) const;
773 
775  template<typename PruneOp> void pruneOp(PruneOp&) {}
777  void prune(const ValueType& /*tolerance*/ = zeroVal<ValueType>()) {}
778  void pruneInactive(const ValueType&) {}
779  void addLeaf(LeafNode*) {}
780  template<typename AccessorT>
781  void addLeafAndCache(LeafNode*, AccessorT&) {}
782  template<typename NodeT>
783  NodeT* stealNode(const Coord&, const ValueType&, bool) { return NULL; }
784  template<typename NodeT>
785  NodeT* probeNode(const Coord&) { return NULL; }
786  template<typename NodeT>
787  const NodeT* probeConstNode(const Coord&) const { return NULL; }
789 
790  void addTile(Index level, const Coord&, const ValueType&, bool);
791  void addTile(Index offset, const ValueType&, bool);
792  template<typename AccessorT>
793  void addTileAndCache(Index, const Coord&, const ValueType&, bool, AccessorT&);
794 
796  LeafNode* touchLeaf(const Coord&) { return this; }
798  template<typename AccessorT>
799  LeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
800  template<typename NodeT, typename AccessorT>
801  NodeT* probeNodeAndCache(const Coord&, AccessorT&)
802  {
804  if (!(boost::is_same<NodeT,LeafNode>::value)) return NULL;
805  return reinterpret_cast<NodeT*>(this);
807  }
808  LeafNode* probeLeaf(const Coord&) { return this; }
809  template<typename AccessorT>
810  LeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
812 
813  const LeafNode* probeConstLeaf(const Coord&) const { return this; }
815  template<typename AccessorT>
816  const LeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
817  template<typename AccessorT>
818  const LeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
819  const LeafNode* probeLeaf(const Coord&) const { return this; }
820  template<typename NodeT, typename AccessorT>
821  const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
822  {
824  if (!(boost::is_same<NodeT,LeafNode>::value)) return NULL;
825  return reinterpret_cast<const NodeT*>(this);
827  }
829 
833  bool isConstant(ValueType& constValue, bool& state,
834  const ValueType& tolerance = zeroVal<ValueType>()) const;
836  bool isInactive() const { return mValueMask.isOff(); }
837 
838 protected:
839  friend class ::TestLeaf;
840  template<typename> friend class ::TestLeafIO;
841 
842  // During topology-only construction, access is needed
843  // to protected/private members of other template instances.
844  template<typename, Index> friend class LeafNode;
845 
852 
853  // Allow iterators to call mask accessor methods (see below).
858 
864  Coord mOrigin;
865 
866  // Mask accessors
867 public:
868  bool isValueMaskOn(Index n) const { return mValueMask.isOn(n); }
869  bool isValueMaskOn() const { return mValueMask.isOn(); }
870  bool isValueMaskOff(Index n) const { return mValueMask.isOff(n); }
871  bool isValueMaskOff() const { return mValueMask.isOff(); }
872  const NodeMaskType& getValueMask() const { return mValueMask; }
873  NodeMaskType& getValueMask() { return mValueMask; }
874  void setValueMask(const NodeMaskType& mask) { mValueMask = mask; }
875  bool isChildMaskOn(Index) const { return false; } // leaf nodes have no children
876  bool isChildMaskOff(Index) const { return true; }
877  bool isChildMaskOff() const { return true; }
878 protected:
879  void setValueMask(Index n, bool on) { mValueMask.set(n, on); }
880  void setValueMaskOn(Index n) { mValueMask.setOn(n); }
881  void setValueMaskOff(Index n) { mValueMask.setOff(n); }
882 
884  static void evalNodeOrigin(Coord& xyz) { xyz &= ~(DIM - 1); }
885 
886  template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
887  static inline void doVisit(NodeT&, VisitorOp&);
888 
889  template<typename NodeT, typename OtherNodeT, typename VisitorOp,
890  typename ChildAllIterT, typename OtherChildAllIterT>
891  static inline void doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp&);
892 
893  template<typename NodeT, typename VisitorOp,
894  typename ChildAllIterT, typename OtherChildAllIterT>
895  static inline void doVisit2(NodeT& self, OtherChildAllIterT&, VisitorOp&, bool otherIsLHS);
896 
897 }; // end of LeafNode class
898 
899 
901 
902 
904 template<Index Dim1, typename NodeT2>
907 struct SameLeafConfig { static const bool value = false; };
908 
909 template<Index Dim1, typename T2>
910 struct SameLeafConfig<Dim1, LeafNode<T2, Dim1> > { static const bool value = true; };
912 
913 
915 
916 
917 template<typename T, Index Log2Dim>
918 inline
920  mValueMask(),//default is off!
921  mOrigin(0, 0, 0)
922 {
923 }
924 
925 
926 template<typename T, Index Log2Dim>
927 inline
928 LeafNode<T, Log2Dim>::LeafNode(const Coord& xyz, const ValueType& val, bool active):
929  mBuffer(val),
930  mValueMask(active),
931  mOrigin(xyz & (~(DIM - 1)))
932 {
933 }
934 
935 
936 template<typename T, Index Log2Dim>
937 inline
939  mBuffer(other.mBuffer),
940  mValueMask(other.mValueMask),
941  mOrigin(other.mOrigin)
942 {
943 }
944 
945 
946 // Copy-construct from a leaf node with the same configuration but a different ValueType.
947 template<typename T, Index Log2Dim>
948 template<typename OtherValueType>
949 inline
951  mValueMask(other.mValueMask),
952  mOrigin(other.mOrigin)
953 {
954  struct Local {
956  static inline ValueType convertValue(const OtherValueType& val) { return ValueType(val); }
957  };
958 
959  for (Index i = 0; i < SIZE; ++i) {
960  mBuffer[i] = Local::convertValue(other.mBuffer[i]);
961  }
962 }
963 
964 
965 template<typename T, Index Log2Dim>
966 template<typename OtherValueType>
967 inline
969  const ValueType& background, TopologyCopy):
970  mBuffer(background),
971  mValueMask(other.mValueMask),
972  mOrigin(other.mOrigin)
973 {
974 }
975 
976 
977 template<typename T, Index Log2Dim>
978 template<typename OtherValueType>
979 inline
981  const ValueType& offValue, const ValueType& onValue, TopologyCopy):
982  mValueMask(other.mValueMask),
983  mOrigin(other.mOrigin)
984 {
985  for (Index i = 0; i < SIZE; ++i) {
986  mBuffer[i] = (mValueMask.isOn(i) ? onValue : offValue);
987  }
988 }
989 
990 
991 template<typename T, Index Log2Dim>
992 inline
994 {
995 }
996 
997 
998 template<typename T, Index Log2Dim>
999 inline std::string
1001 {
1002  std::ostringstream ostr;
1003  ostr << "LeafNode @" << mOrigin << ": " << mBuffer;
1004  return ostr.str();
1005 }
1006 
1007 
1009 
1010 
1011 template<typename T, Index Log2Dim>
1012 inline Index
1014 {
1015  assert ((xyz[0] & (DIM-1u)) < DIM && (xyz[1] & (DIM-1u)) < DIM && (xyz[2] & (DIM-1u)) < DIM);
1016  return ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
1017  + ((xyz[1] & (DIM-1u)) << Log2Dim)
1018  + (xyz[2] & (DIM-1u));
1019 }
1020 
1021 template<typename T, Index Log2Dim>
1022 inline Coord
1024 {
1025  assert(n<(1<< 3*Log2Dim));
1026  Coord xyz;
1027  xyz.setX(n >> 2*Log2Dim);
1028  n &= ((1<<2*Log2Dim)-1);
1029  xyz.setY(n >> Log2Dim);
1030  xyz.setZ(n & ((1<<Log2Dim)-1));
1031  return xyz;
1032 }
1033 
1034 
1035 template<typename T, Index Log2Dim>
1036 inline Coord
1038 {
1039  return (this->offsetToLocalCoord(n) + this->origin());
1040 }
1041 
1042 
1044 
1045 
1046 template<typename ValueT, Index Log2Dim>
1047 inline const ValueT&
1049 {
1050  return this->getValue(LeafNode::coordToOffset(xyz));
1051 }
1052 
1053 template<typename ValueT, Index Log2Dim>
1054 inline const ValueT&
1056 {
1057  assert(offset < SIZE);
1058  return mBuffer[offset];
1059 }
1060 
1061 
1062 template<typename T, Index Log2Dim>
1063 inline bool
1064 LeafNode<T, Log2Dim>::probeValue(const Coord& xyz, ValueType& val) const
1065 {
1066  return this->probeValue(LeafNode::coordToOffset(xyz), val);
1067 }
1068 
1069 template<typename T, Index Log2Dim>
1070 inline bool
1072 {
1073  assert(offset < SIZE);
1074  val = mBuffer[offset];
1075  return mValueMask.isOn(offset);
1076 }
1077 
1078 
1079 template<typename T, Index Log2Dim>
1080 inline void
1081 LeafNode<T, Log2Dim>::setValueOff(const Coord& xyz, const ValueType& val)
1082 {
1083  this->setValueOff(LeafNode::coordToOffset(xyz), val);
1084 }
1085 
1086 template<typename T, Index Log2Dim>
1087 inline void
1089 {
1090  assert(offset < SIZE);
1091  mBuffer[offset] = val;
1092  mValueMask.setOff(offset);
1093 }
1094 
1095 
1096 template<typename T, Index Log2Dim>
1097 inline void
1098 LeafNode<T, Log2Dim>::setActiveState(const Coord& xyz, bool on)
1099 {
1100  mValueMask.set(this->coordToOffset(xyz), on);
1101 }
1102 
1103 
1104 template<typename T, Index Log2Dim>
1105 inline void
1106 LeafNode<T, Log2Dim>::setValueOnly(const Coord& xyz, const ValueType& val)
1107 {
1108  this->setValueOnly(LeafNode::coordToOffset(xyz), val);
1109 }
1110 
1111 template<typename T, Index Log2Dim>
1112 inline void
1114 {
1115  assert(offset<SIZE); mBuffer[offset] = val;
1116 }
1117 
1118 
1120 
1121 
1122 template<typename T, Index Log2Dim>
1123 inline void
1124 LeafNode<T, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1125 {
1126  for (Int32 x = bbox.min().x(); x <= bbox.max().x(); ++x) {
1127  const Index offsetX = (x & (DIM-1u)) << 2*Log2Dim;
1128  for (Int32 y = bbox.min().y(); y <= bbox.max().y(); ++y) {
1129  const Index offsetXY = offsetX + ((y & (DIM-1u)) << Log2Dim);
1130  for (Int32 z = bbox.min().z(); z <= bbox.max().z(); ++z) {
1131  const Index offset = offsetXY + (z & (DIM-1u));
1132  mBuffer[offset] = value;
1133  mValueMask.set(offset, active);
1134  }
1135  }
1136  }
1137 }
1138 
1139 template<typename T, Index Log2Dim>
1140 inline void
1142 {
1143  mBuffer.fill(value);
1144 }
1145 
1146 template<typename T, Index Log2Dim>
1147 inline void
1148 LeafNode<T, Log2Dim>::fill(const ValueType& value, bool active)
1149 {
1150  mBuffer.fill(value);
1151  mValueMask.set(active);
1152 }
1153 
1154 
1156 
1157 
1158 template<typename T, Index Log2Dim>
1159 template<typename DenseT>
1160 inline void
1161 LeafNode<T, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const
1162 {
1163  typedef typename DenseT::ValueType DenseValueType;
1164 
1165  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1166  const Coord& min = dense.bbox().min();
1167  DenseValueType* t0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // target array
1168  const T* s0 = &mBuffer[bbox.min()[2] & (DIM-1u)]; // source array
1169  for (Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1; x < ex; ++x) {
1170  DenseValueType* t1 = t0 + xStride * (x - min[0]);
1171  const T* s1 = s0 + ((x & (DIM-1u)) << 2*Log2Dim);
1172  for (Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1; y < ey; ++y) {
1173  DenseValueType* t2 = t1 + yStride * (y - min[1]);
1174  const T* s2 = s1 + ((y & (DIM-1u)) << Log2Dim);
1175  for (Int32 z = bbox.min()[2], ez = bbox.max()[2] + 1; z < ez; ++z, t2 += zStride) {
1176  *t2 = DenseValueType(*s2++);
1177  }
1178  }
1179  }
1180 }
1181 
1182 
1183 template<typename T, Index Log2Dim>
1184 template<typename DenseT>
1185 inline void
1186 LeafNode<T, Log2Dim>::copyFromDense(const CoordBBox& bbox, const DenseT& dense,
1187  const ValueType& background, const ValueType& tolerance)
1188 {
1189  typedef typename DenseT::ValueType DenseValueType;
1190 
1191  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1192  const Coord& min = dense.bbox().min();
1193 
1194  const DenseValueType* s0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // source
1195  const Int32 n0 = bbox.min()[2] & (DIM-1u);
1196  for (Int32 x = bbox.min()[0], ex = bbox.max()[0]+1; x < ex; ++x) {
1197  const DenseValueType* s1 = s0 + xStride * (x - min[0]);
1198  const Int32 n1 = n0 + ((x & (DIM-1u)) << 2*LOG2DIM);
1199  for (Int32 y = bbox.min()[1], ey = bbox.max()[1]+1; y < ey; ++y) {
1200  const DenseValueType* s2 = s1 + yStride * (y - min[1]);
1201  Int32 n2 = n1 + ((y & (DIM-1u)) << LOG2DIM);
1202  for (Int32 z = bbox.min()[2], ez = bbox.max()[2]+1; z < ez; ++z, ++n2, s2 += zStride) {
1203  if (math::isApproxEqual(background, ValueType(*s2), tolerance)) {
1204  mValueMask.setOff(n2);
1205  mBuffer[n2] = background;
1206  } else {
1207  mValueMask.setOn(n2);
1208  mBuffer[n2] = ValueType(*s2);
1209  }
1210  }
1211  }
1212  }
1213 }
1214 
1215 
1217 
1218 
1219 template<typename T, Index Log2Dim>
1220 inline void
1221 LeafNode<T, Log2Dim>::readTopology(std::istream& is, bool /*fromHalf*/)
1222 {
1223  mValueMask.load(is);
1224 }
1225 
1226 
1227 template<typename T, Index Log2Dim>
1228 inline void
1229 LeafNode<T, Log2Dim>::writeTopology(std::ostream& os, bool /*toHalf*/) const
1230 {
1231  mValueMask.save(os);
1232 }
1233 
1234 
1236 
1237 
1238 template<typename T, Index Log2Dim>
1239 inline void
1240 LeafNode<T,Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
1241 {
1242  // Read in the value mask.
1243  mValueMask.load(is);
1244 
1245  int8_t numBuffers = 1;
1247  // Read in the origin.
1248  is.read(reinterpret_cast<char*>(&mOrigin), sizeof(Coord::ValueType) * 3);
1249 
1250  // Read in the number of buffers, which should now always be one.
1251  is.read(reinterpret_cast<char*>(&numBuffers), sizeof(int8_t));
1252  }
1253 
1254  io::readCompressedValues(is, mBuffer.mData, SIZE, mValueMask, fromHalf);
1255 
1256  if (numBuffers > 1) {
1257  // Read in and discard auxiliary buffers that were created with earlier
1258  // versions of the library. (Auxiliary buffers are not mask compressed.)
1259  const bool zipped = io::getDataCompression(is) & io::COMPRESS_ZIP;
1260  Buffer temp;
1261  for (int i = 1; i < numBuffers; ++i) {
1262  if (fromHalf) {
1263  io::HalfReader<io::RealToHalf<T>::isReal, T>::read(is, temp.mData, SIZE, zipped);
1264  } else {
1265  io::readData<T>(is, temp.mData, SIZE, zipped);
1266  }
1267  }
1268  }
1269 }
1270 
1271 
1272 template<typename T, Index Log2Dim>
1273 inline void
1274 LeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
1275 {
1276  // Write out the value mask.
1277  mValueMask.save(os);
1278 
1279  io::writeCompressedValues(os, mBuffer.mData, SIZE,
1280  mValueMask, /*childMask=*/NodeMaskType(), toHalf);
1281 }
1282 
1283 
1285 
1286 
1287 template<typename T, Index Log2Dim>
1288 inline bool
1290 {
1291  return mOrigin == other.mOrigin &&
1292  mValueMask == other.mValueMask &&
1293  mBuffer == other.mBuffer;
1294 }
1295 
1296 
1297 template<typename T, Index Log2Dim>
1298 inline Index64
1300 {
1301  return mBuffer.memUsage() + sizeof(mOrigin) + mValueMask.memUsage();
1302 }
1303 
1304 
1305 template<typename T, Index Log2Dim>
1306 inline void
1307 LeafNode<T, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const
1308 {
1309  CoordBBox this_bbox = this->getNodeBoundingBox();
1310  if (bbox.isInside(this_bbox)) return;//this LeafNode is already enclosed in the bbox
1311  if (ValueOnCIter iter = this->cbeginValueOn()) {//any active values?
1312  if (visitVoxels) {//use voxel granularity?
1313  this_bbox.reset();
1314  for(; iter; ++iter) this_bbox.expand(this->offsetToLocalCoord(iter.pos()));
1315  this_bbox.translate(this->origin());
1316  }
1317  bbox.expand(this_bbox);
1318  }
1319 }
1320 
1321 
1322 template<typename T, Index Log2Dim>
1323 template<typename OtherType, Index OtherLog2Dim>
1324 inline bool
1326 {
1327  assert(other);
1328  return (Log2Dim == OtherLog2Dim && mValueMask == other->getValueMask());
1329 }
1330 
1331 
1332 template<typename T, Index Log2Dim>
1333 inline bool
1335  bool& state, const ValueType& tolerance) const
1336 {
1337  state = mValueMask.isOn();
1338 
1339  if (!(state || mValueMask.isOff())) return false;
1340 
1341  bool allEqual = true;
1342  const T value = mBuffer[0];
1343  for (Index i = 1; allEqual && i < SIZE; ++i) {
1345  allEqual = math::isApproxEqual(mBuffer[i], value, tolerance);
1346  }
1347  if (allEqual) constValue = value;
1348  return allEqual;
1349 }
1350 
1351 
1353 
1354 
1355 template<typename T, Index Log2Dim>
1356 inline void
1357 LeafNode<T, Log2Dim>::addTile(Index level, const Coord& xyz, const ValueType& val, bool active)
1358 {
1359  assert(level == 0);
1360  this->addTile(this->coordToOffset(xyz), val, active);
1361 }
1362 
1363 template<typename T, Index Log2Dim>
1364 inline void
1365 LeafNode<T, Log2Dim>::addTile(Index offset, const ValueType& val, bool active)
1366 {
1367  assert(offset < SIZE);
1368  setValueOnly(offset, val);
1369  setActiveState(offset, active);
1370 }
1371 
1372 template<typename T, Index Log2Dim>
1373 template<typename AccessorT>
1374 inline void
1376  const ValueType& val, bool active, AccessorT&)
1377 {
1378  this->addTile(level, xyz, val, active);
1379 }
1380 
1381 
1383 
1384 
1385 template<typename T, Index Log2Dim>
1386 inline void
1388 {
1389  this->signedFloodFill(background, math::negative(background));
1390 }
1391 
1392 template<typename T, Index Log2Dim>
1393 inline void
1395  const ValueType& insideValue)
1396 {
1397  const Index first = mValueMask.findFirstOn();
1398  if (first < SIZE) {
1399  bool xInside = math::isNegative(mBuffer[first]), yInside = xInside, zInside = xInside;
1400  for (Index x = 0; x != (1 << Log2Dim); ++x) {
1401  const Index x00 = x << (2 * Log2Dim);
1402  if (mValueMask.isOn(x00)) {
1403  xInside = math::isNegative(mBuffer[x00]); // element(x, 0, 0)
1404  }
1405  yInside = xInside;
1406  for (Index y = 0; y != (1 << Log2Dim); ++y) {
1407  const Index xy0 = x00 + (y << Log2Dim);
1408  if (mValueMask.isOn(xy0)) {
1409  yInside = math::isNegative(mBuffer[xy0]); // element(x, y, 0)
1410  }
1411  zInside = yInside;
1412  for (Index z = 0; z != (1 << Log2Dim); ++z) {
1413  const Index xyz = xy0 + z; // element(x, y, z)
1414  if (mValueMask.isOn(xyz)) {
1415  zInside = math::isNegative(mBuffer[xyz]);
1416  } else {
1417  mBuffer[xyz] = zInside ? insideValue : outsideValue;
1418  }
1419  }
1420  }
1421  }
1422  } else {// if no active voxels exist simply use the sign of the first value
1423  mBuffer.fill(math::isNegative(mBuffer[0]) ? insideValue : outsideValue);
1424  }
1425 }
1426 
1427 
1428 template<typename T, Index Log2Dim>
1429 inline void
1431  const ValueType& newBackground)
1432 {
1433  typename NodeMaskType::OffIterator iter;
1434  // For all inactive values...
1435  for (iter = this->mValueMask.beginOff(); iter; ++iter) {
1436  ValueType &inactiveValue = mBuffer[iter.pos()];
1437  if (math::isApproxEqual(inactiveValue, oldBackground)) {
1438  inactiveValue = newBackground;
1439  } else if (math::isApproxEqual(inactiveValue, math::negative(oldBackground))) {
1440  inactiveValue = math::negative(newBackground);
1441  }
1442  }
1443 }
1444 
1445 
1446 template<typename T, Index Log2Dim>
1447 template<MergePolicy Policy>
1448 inline void
1450 {
1452  if (Policy == MERGE_NODES) return;
1453  typename NodeMaskType::OnIterator iter = other.mValueMask.beginOn();
1454  for (; iter; ++iter) {
1455  const Index n = iter.pos();
1456  if (mValueMask.isOff(n)) {
1457  mBuffer[n] = other.mBuffer[n];
1458  mValueMask.setOn(n);
1459  }
1460  }
1462 }
1463 
1464 template<typename T, Index Log2Dim>
1465 template<MergePolicy Policy>
1466 inline void
1468  const ValueType& /*bg*/, const ValueType& /*otherBG*/)
1469 {
1470  this->template merge<Policy>(other);
1471 }
1472 
1473 template<typename T, Index Log2Dim>
1474 template<MergePolicy Policy>
1475 inline void
1476 LeafNode<T, Log2Dim>::merge(const ValueType& tileValue, bool tileActive)
1477 {
1479  if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return;
1480  if (!tileActive) return;
1481  // Replace all inactive values with the active tile value.
1482  for (typename NodeMaskType::OffIterator iter = mValueMask.beginOff(); iter; ++iter) {
1483  const Index n = iter.pos();
1484  mBuffer[n] = tileValue;
1485  mValueMask.setOn(n);
1486  }
1488 }
1489 
1490 
1491 template<typename T, Index Log2Dim>
1492 template<typename OtherType>
1493 inline void
1495 {
1496  mValueMask |= other.getValueMask();
1497 }
1498 
1499 template<typename T, Index Log2Dim>
1500 template<typename OtherType>
1501 inline void
1503  const ValueType&)
1504 {
1505  mValueMask &= other.getValueMask();
1506 }
1507 
1508 template<typename T, Index Log2Dim>
1509 template<typename OtherType>
1510 inline void
1512  const ValueType&)
1513 {
1514  mValueMask &= !other.getValueMask();
1515 }
1516 
1517 template<typename T, Index Log2Dim>
1518 inline void
1520 {
1521  for (Index i = 0; i < SIZE; ++i) {
1522  mBuffer[i] = -mBuffer[i];
1523  }
1524 }
1525 
1526 
1528 
1529 
1530 template<typename T, Index Log2Dim>
1531 template<typename CombineOp>
1532 inline void
1533 LeafNode<T, Log2Dim>::combine(const LeafNode& other, CombineOp& op)
1534 {
1535  CombineArgs<T> args;
1536  for (Index i = 0; i < SIZE; ++i) {
1537  op(args.setARef(mBuffer[i])
1538  .setAIsActive(mValueMask.isOn(i))
1539  .setBRef(other.mBuffer[i])
1540  .setBIsActive(other.mValueMask.isOn(i))
1541  .setResultRef(mBuffer[i]));
1542  mValueMask.set(i, args.resultIsActive());
1543  }
1544 }
1545 
1546 
1547 template<typename T, Index Log2Dim>
1548 template<typename CombineOp>
1549 inline void
1550 LeafNode<T, Log2Dim>::combine(const ValueType& value, bool valueIsActive, CombineOp& op)
1551 {
1552  CombineArgs<T> args;
1553  args.setBRef(value).setBIsActive(valueIsActive);
1554  for (Index i = 0; i < SIZE; ++i) {
1555  op(args.setARef(mBuffer[i])
1556  .setAIsActive(mValueMask.isOn(i))
1557  .setResultRef(mBuffer[i]));
1558  mValueMask.set(i, args.resultIsActive());
1559  }
1560 }
1561 
1562 
1564 
1565 
1566 template<typename T, Index Log2Dim>
1567 template<typename CombineOp, typename OtherType>
1568 inline void
1569 LeafNode<T, Log2Dim>::combine2(const LeafNode& other, const OtherType& value,
1570  bool valueIsActive, CombineOp& op)
1571 {
1573  args.setBRef(value).setBIsActive(valueIsActive);
1574  for (Index i = 0; i < SIZE; ++i) {
1575  op(args.setARef(other.mBuffer[i])
1576  .setAIsActive(other.mValueMask.isOn(i))
1577  .setResultRef(mBuffer[i]));
1578  mValueMask.set(i, args.resultIsActive());
1579  }
1580 }
1581 
1582 
1583 template<typename T, Index Log2Dim>
1584 template<typename CombineOp, typename OtherNodeT>
1585 inline void
1586 LeafNode<T, Log2Dim>::combine2(const ValueType& value, const OtherNodeT& other,
1587  bool valueIsActive, CombineOp& op)
1588 {
1590  args.setARef(value).setAIsActive(valueIsActive);
1591  for (Index i = 0; i < SIZE; ++i) {
1592  op(args.setBRef(other.mBuffer[i])
1593  .setBIsActive(other.mValueMask.isOn(i))
1594  .setResultRef(mBuffer[i]));
1595  mValueMask.set(i, args.resultIsActive());
1596  }
1597 }
1598 
1599 
1600 template<typename T, Index Log2Dim>
1601 template<typename CombineOp, typename OtherNodeT>
1602 inline void
1603 LeafNode<T, Log2Dim>::combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp& op)
1604 {
1606  for (Index i = 0; i < SIZE; ++i) {
1607  mValueMask.set(i, b0.mValueMask.isOn(i) || b1.mValueMask.isOn(i));
1608  op(args.setARef(b0.mBuffer[i])
1609  .setAIsActive(b0.mValueMask.isOn(i))
1610  .setBRef(b1.mBuffer[i])
1611  .setBIsActive(b1.mValueMask.isOn(i))
1612  .setResultRef(mBuffer[i]));
1613  mValueMask.set(i, args.resultIsActive());
1614  }
1615 }
1616 
1617 
1619 
1620 
1621 template<typename T, Index Log2Dim>
1622 template<typename BBoxOp>
1623 inline void
1625 {
1626  if (op.template descent<LEVEL>()) {
1627  for (ValueOnCIter i=this->cbeginValueOn(); i; ++i) {
1628 #ifdef _MSC_VER
1629  op.operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), 1));
1630 #else
1631  op.template operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), 1));
1632 #endif
1633  }
1634  } else {
1635 #ifdef _MSC_VER
1636  op.operator()<LEVEL>(this->getNodeBoundingBox());
1637 #else
1638  op.template operator()<LEVEL>(this->getNodeBoundingBox());
1639 #endif
1640  }
1641 }
1642 
1643 
1644 template<typename T, Index Log2Dim>
1645 template<typename VisitorOp>
1646 inline void
1648 {
1649  doVisit<LeafNode, VisitorOp, ChildAllIter>(*this, op);
1650 }
1651 
1652 
1653 template<typename T, Index Log2Dim>
1654 template<typename VisitorOp>
1655 inline void
1656 LeafNode<T, Log2Dim>::visit(VisitorOp& op) const
1657 {
1658  doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*this, op);
1659 }
1660 
1661 
1662 template<typename T, Index Log2Dim>
1663 template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
1664 inline void
1665 LeafNode<T, Log2Dim>::doVisit(NodeT& self, VisitorOp& op)
1666 {
1667  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
1668  op(iter);
1669  }
1670 }
1671 
1672 
1674 
1675 
1676 template<typename T, Index Log2Dim>
1677 template<typename OtherLeafNodeType, typename VisitorOp>
1678 inline void
1679 LeafNode<T, Log2Dim>::visit2Node(OtherLeafNodeType& other, VisitorOp& op)
1680 {
1681  doVisit2Node<LeafNode, OtherLeafNodeType, VisitorOp, ChildAllIter,
1682  typename OtherLeafNodeType::ChildAllIter>(*this, other, op);
1683 }
1684 
1685 
1686 template<typename T, Index Log2Dim>
1687 template<typename OtherLeafNodeType, typename VisitorOp>
1688 inline void
1689 LeafNode<T, Log2Dim>::visit2Node(OtherLeafNodeType& other, VisitorOp& op) const
1690 {
1691  doVisit2Node<const LeafNode, OtherLeafNodeType, VisitorOp, ChildAllCIter,
1692  typename OtherLeafNodeType::ChildAllCIter>(*this, other, op);
1693 }
1694 
1695 
1696 template<typename T, Index Log2Dim>
1697 template<
1698  typename NodeT,
1699  typename OtherNodeT,
1700  typename VisitorOp,
1701  typename ChildAllIterT,
1702  typename OtherChildAllIterT>
1703 inline void
1704 LeafNode<T, Log2Dim>::doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp& op)
1705 {
1706  // Allow the two nodes to have different ValueTypes, but not different dimensions.
1707  BOOST_STATIC_ASSERT(OtherNodeT::SIZE == NodeT::SIZE);
1708  BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
1709 
1710  ChildAllIterT iter = self.beginChildAll();
1711  OtherChildAllIterT otherIter = other.beginChildAll();
1712 
1713  for ( ; iter && otherIter; ++iter, ++otherIter) {
1714  op(iter, otherIter);
1715  }
1716 }
1717 
1718 
1720 
1721 
1722 template<typename T, Index Log2Dim>
1723 template<typename IterT, typename VisitorOp>
1724 inline void
1725 LeafNode<T, Log2Dim>::visit2(IterT& otherIter, VisitorOp& op, bool otherIsLHS)
1726 {
1727  doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(
1728  *this, otherIter, op, otherIsLHS);
1729 }
1730 
1731 
1732 template<typename T, Index Log2Dim>
1733 template<typename IterT, typename VisitorOp>
1734 inline void
1735 LeafNode<T, Log2Dim>::visit2(IterT& otherIter, VisitorOp& op, bool otherIsLHS) const
1736 {
1737  doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(
1738  *this, otherIter, op, otherIsLHS);
1739 }
1740 
1741 
1742 template<typename T, Index Log2Dim>
1743 template<
1744  typename NodeT,
1745  typename VisitorOp,
1746  typename ChildAllIterT,
1747  typename OtherChildAllIterT>
1748 inline void
1749 LeafNode<T, Log2Dim>::doVisit2(NodeT& self, OtherChildAllIterT& otherIter,
1750  VisitorOp& op, bool otherIsLHS)
1751 {
1752  if (!otherIter) return;
1753 
1754  if (otherIsLHS) {
1755  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
1756  op(otherIter, iter);
1757  }
1758  } else {
1759  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
1760  op(iter, otherIter);
1761  }
1762  }
1763 }
1764 
1765 
1767 
1768 
1769 template<typename T, Index Log2Dim>
1770 inline std::ostream&
1771 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer& buf)
1772 {
1773  for (Index32 i = 0, N = buf.size(); i < N; ++i) os << buf.mData[i] << ", ";
1774  return os;
1775 }
1776 
1777 } // namespace tree
1778 } // namespace OPENVDB_VERSION_NAME
1779 } // namespace openvdb
1780 
1781 
1783 
1784 
1785 // Specialization for LeafNodes of type bool
1786 #include "LeafNodeBool.h"
1787 
1788 #endif // OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
1789 
1790 // Copyright (c) 2012-2013 DreamWorks Animation LLC
1791 // All rights reserved. This software is distributed under the
1792 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
bool resultIsActive() const
Definition: Types.h:314
const ValueType & getFirstValue() const
Return a const reference to the first value in the buffer.
Definition: LeafNode.h:675
ValueT & getItem(Index pos) const
Definition: LeafNode.h:298
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
ChildOffCIter endChildOff() const
Definition: LeafNode.h:407
ChildIter< MaskOffIterator, LeafNode, ChildOff > ChildOffIter
Definition: LeafNode.h:366
DenseIteratorBase< MaskDenseIterator, DenseIter, NodeT, void, ValueT > BaseT
Definition: LeafNode.h:334
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNode.h:326
ChildAllIter endChildAll()
Definition: LeafNode.h:411
ValueOffCIter cendValueOff() const
Definition: LeafNode.h:384
ValueOffIter beginValueOff()
Definition: LeafNode.h:376
Index64 offVoxelCount() const
Return the number of voxels marked Off.
Definition: LeafNode.h:226
static Index log2dim()
Return log2 of the dimension of this LeafNode, e.g. 3 if dimensions are 8^3.
Definition: LeafNode.h:205
ChildOnIter beginChildOn()
Definition: LeafNode.h:395
void combine(const LeafNode &other, CombineOp &op)
Definition: LeafNode.h:1533
void combine2(const LeafNode &other, const OtherType &, bool valueIsActive, CombineOp &)
Definition: LeafNode.h:1569
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: LeafNode.h:476
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:593
void combine(FloatTreeT &lhsDist, IntTreeT &lhsIndex, FloatTreeT &rhsDist, IntTreeT &rhsIndex)
Definition: MeshToVolume.h:396
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 modifyValue(const ModifyOp &op) const
Definition: LeafNode.h:317
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: LeafNode.h:1387
ValueIter< MaskDenseIterator, const LeafNode, const ValueType, ValueAll > ValueAllCIter
Definition: LeafNode.h:363
ChildOffIter beginChildOff()
Definition: LeafNode.h:398
LeafNode< ValueType, Log2Dim > LeafNodeType
Definition: LeafNode.h:69
bool isChildMaskOn(Index) const
Definition: LeafNode.h:875
void swap(Buffer &other)
Exchange this node's data buffer with the given data buffer without changing the active states of the...
Definition: LeafNode.h:418
ChildIter< MaskOnIterator, LeafNode, ChildOn > ChildOnIter
Definition: LeafNode.h:364
Definition: LeafNode.h:50
void setActiveState(Index offset, bool on)
Set the active state of the voxel at the given offset but don't change its value. ...
Definition: LeafNode.h:468
Index64 onVoxelCount() const
Return the number of voxels marked On.
Definition: LeafNode.h:224
void prune(const ValueType &=zeroVal< ValueType >())
This function exists only to enable template instantiation.
Definition: LeafNode.h:777
void copyFromDense(const DenseT &dense, GridOrTreeT &sparse, const typename GridOrTreeT::ValueType &tolerance, bool serial=false)
Populate a sparse grid with the values of all of the voxels of a dense grid.
Definition: Dense.h:515
bool isValueMaskOn(Index n) const
Definition: LeafNode.h:868
Index64 offLeafVoxelCount() const
Definition: LeafNode.h:228
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: LeafNode.h:1037
bool operator!=(const Buffer &other) const
Definition: LeafNode.h:144
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition: LeafNode.h:338
void topologyIntersection(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Intersect 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 both of the original voxels were active.
Definition: LeafNode.h:1502
void visit2Node(OtherLeafNodeType &other, VisitorOp &)
Definition: LeafNode.h:1679
OnIterator beginOn() const
Definition: NodeMasks.h:332
void topologyUnion(const LeafNode< OtherType, Log2Dim > &other)
Union this node's set of active values with the active values of the other node, whose ValueType may ...
Definition: LeafNode.h:1494
ChildOnCIter cbeginChildOn() const
Definition: LeafNode.h:393
ValueConverter::Type is the type of a LeafNode having the same dimensions as this node but a diffe...
Definition: LeafNode.h:85
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:303
util::NodeMask< Log2Dim > NodeMaskType
Definition: LeafNode.h:71
bool hasSameTopology(const LeafNode< OtherType, OtherLog2Dim > *other) const
Return true if the given node (which may have a different ValueType than this node) has the same acti...
Definition: LeafNode.h:1325
ChildIter()
Definition: LeafNode.h:325
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: LeafNode.h:1161
void voxelizeActiveTiles()
Definition: LeafNode.h:699
ChildIter< MaskOffIterator, const LeafNode, ChildOff > ChildOffCIter
Definition: LeafNode.h:367
Index32 Index
Definition: Types.h:57
void swap(Buffer &other)
Replace the values in this Buffer with the values in the other Buffer.
Definition: LeafNode.h:146
void fill(const ValueType &val)
Populates the buffer with a constant value.
Definition: LeafNode.h:111
void negate()
Definition: LeafNode.h:1519
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: LeafNode.h:249
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
Definition: LeafNode.h:1289
ValueOnCIter cbeginValueOn() const
Definition: LeafNode.h:371
ValueIter< MaskDenseIterator, LeafNode, const ValueType, ValueAll > ValueAllIter
Definition: LeafNode.h:362
ValueAllIter beginValueAll()
Definition: LeafNode.h:379
static const Index SIZE
Definition: LeafNode.h:79
static void doVisit2Node(NodeT &self, OtherNodeT &other, VisitorOp &)
Definition: LeafNode.h:1704
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:446
void setValue(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: LeafNode.h:494
Index32 pos() const
Definition: NodeMasks.h:176
ChildAllCIter endChildAll() const
Definition: LeafNode.h:410
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: LeafNode.h:535
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: LeafNode.h:1023
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: LeafNode.h:616
void addLeaf(LeafNode *)
This function exists only to enable template instantiation.
Definition: LeafNode.h:779
DenseIter()
Definition: LeafNode.h:337
Definition: NodeMasks.h:188
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1048
ChildOnIter endChildOn()
Definition: LeafNode.h:405
void addLeafAndCache(LeafNode *, AccessorT &)
This function exists only to enable template instantiation.
Definition: LeafNode.h:781
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: LeafNode.h:1013
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as inactive.
Definition: LeafNode.h:632
ValueIter()
Definition: LeafNode.h:295
ValueOnIter beginValueOn()
Definition: LeafNode.h:373
void modifyValue(Index offset, const ModifyOp &op)
Apply a functor to the value of the voxel at the given offset and mark the voxel as active...
Definition: LeafNode.h:504
void readBuffers(std::istream &is, bool fromHalf=false)
Read buffers from a stream.
Definition: LeafNode.h:1240
void setValue(Index i, const ValueType &val)
Set the i'th value of the Buffer to the specified value.
Definition: LeafNode.h:122
ValueOnCIter endValueOn() const
Definition: LeafNode.h:382
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: LeafNode.h:486
ValueAllCIter endValueAll() const
Definition: LeafNode.h:388
ValueOnIter endValueOn()
Definition: LeafNode.h:383
const NodeT * probeConstNode(const Coord &) const
This function exists only to enable template instantiation.
Definition: LeafNode.h:787
Buffer()
Empty default constructor.
Definition: LeafNode.h:103
ValueOnCIter beginValueOn() const
Definition: LeafNode.h:372
bool operator!=(const LeafNode &other) const
Definition: LeafNode.h:275
static Index64 onTileCount()
Definition: LeafNode.h:229
static Index getChildDim()
Return the dimension of child nodes of this LeafNode, which is one for voxels.
Definition: LeafNode.h:217
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:287
static Index64 offTileCount()
Definition: LeafNode.h:230
Buffer(const ValueType &val)
Constructs a buffer populated with the specified value.
Definition: LeafNode.h:105
void setValuesOn()
Mark all voxels as active but don't change their values.
Definition: LeafNode.h:528
Definition: NodeMasks.h:219
ValueT & getValue() const
Definition: LeafNode.h:299
ChildOnCIter cendChildOn() const
Definition: LeafNode.h:403
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:265
ValueOffCIter cbeginValueOff() const
Definition: LeafNode.h:374
ChildOffCIter cbeginChildOff() const
Definition: LeafNode.h:396
ChildOffIter endChildOff()
Definition: LeafNode.h:408
LeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNode.h:810
void setValueOn(Index offset)
Mark the voxel at the given offset as active but don't change its value.
Definition: LeafNode.h:488
const ValueType & getValue(Index i) const
Return a const reference to the i'th element of the Buffer.
Definition: LeafNode.h:118
void unsetItem(Index pos, const ValueT &value) const
Definition: LeafNode.h:351
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
Stores the actual values in the LeafNode. Its dimension it fixed to 2^(3*Log2Dim) ...
Definition: LeafNode.h:99
#define OPENVDB_VERSION_NAME
Definition: version.h:45
ValueIter< MaskOffIterator, const LeafNode, const ValueType, ValueOff > ValueOffCIter
Definition: LeafNode.h:361
void setValue(const ValueT &value) const
Definition: LeafNode.h:307
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information. An additional level argument is pro...
Definition: LeafNode.h:1624
void visit(VisitorOp &)
Definition: LeafNode.h:1647
~Buffer()
Destructor.
Definition: LeafNode.h:109
static Index memUsage()
Return the memory-footprint of this Buffer in units of bytes.
Definition: LeafNode.h:153
static void doVisit(NodeT &, VisitorOp &)
Definition: LeafNode.h:1665
ValueIter< MaskOnIterator, LeafNode, const ValueType, ValueOn > ValueOnIter
Definition: LeafNode.h:358
NodeMaskType & getValueMask()
Definition: LeafNode.h:873
ChildAllCIter cbeginChildAll() const
Definition: LeafNode.h:399
void fill(const CoordBBox &bbox, const ValueType &, bool active=true)
Set all voxels within an axis-aligned box to the specified value and active state.
Definition: LeafNode.h:1124
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: LeafNode.h:624
LeafNode * probeLeaf(const Coord &)
Return a pointer to this node.
Definition: LeafNode.h:808
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNode.h:232
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:351
Index64 memUsage() const
Return the memory in bytes occupied by this node.
Definition: LeafNode.h:1299
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: LeafNode.h:1098
Definition: Types.h:223
Definition: Compression.h:166
bool isValueMaskOff() const
Definition: LeafNode.h:871
void addTileAndCache(Index, const Coord &, const ValueType &, bool, AccessorT &)
Definition: LeafNode.h:1375
void modifyItem(Index n, const ModifyOp &op) const
Definition: LeafNode.h:314
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:58
ChildOnCIter endChildOn() const
Definition: LeafNode.h:404
static Index getLevel()
Return the level of this node, which by definition is zero for LeafNodes.
Definition: LeafNode.h:213
NodeMaskType::OffIterator MaskOffIterator
Definition: LeafNode.h:279
ValueIter< MaskOnIterator, const LeafNode, const ValueType, ValueOn > ValueOnCIter
Definition: LeafNode.h:359
bool isValueMaskOn() const
Definition: LeafNode.h:869
bool isOn(Index32 n) const
Return true if the nth bit is on.
Definition: NodeMasks.h:438
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNode.h:801
ValueOffCIter beginValueOff() const
Definition: LeafNode.h:375
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:211
void setValueOn(Index offset, const ValueType &val)
Set the value of the voxel at the given offset and mark the voxel as active.
Definition: LeafNode.h:496
ChildAllCIter beginChildAll() const
Definition: LeafNode.h:400
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:121
bool isChildMaskOff(Index) const
Definition: LeafNode.h:876
bool isConstant(ValueType &constValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: LeafNode.h:1334
NodeT * probeNode(const Coord &)
This function exists only to enable template instantiation.
Definition: LeafNode.h:785
bool isDense() const
Return true if this node contains only active voxels.
Definition: LeafNode.h:234
bool isValueMaskOff(Index n) const
Definition: LeafNode.h:870
void addTile(Index level, const Coord &, const ValueType &, bool)
Definition: LeafNode.h:1357
ChildOffCIter cendChildOff() const
Definition: LeafNode.h:406
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: Types.h:305
void readTopology(std::istream &is, bool fromHalf=false)
Read in just the topology.
Definition: LeafNode.h:1221
static void doVisit2(NodeT &self, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: LeafNode.h:1749
NodeT * stealNode(const Coord &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNode.h:783
Definition: Compression.h:70
void setValueMask(const NodeMaskType &mask)
Definition: LeafNode.h:874
void setValueOn(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: LeafNode.h:490
uint32_t Index32
Definition: Types.h:55
const NodeMaskType & getValueMask() const
Definition: LeafNode.h:872
static Index dim()
Return the number of voxels in each coordinate dimension.
Definition: LeafNode.h:207
void getOrigin(Coord &origin) const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:253
int32_t Int32
Definition: Types.h:59
OPENVDB_IMPORT uint32_t getFormatVersion(std::istream &)
Return the file format version number associated with the given input stream.
static void getNodeLog2Dims(std::vector< Index > &dims)
Append the Log2Dim of this LeafNode to the specified vector.
Definition: LeafNode.h:215
bool probeValue(const Coord &xyz, ValueType &val) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:1064
Buffer(const Buffer &other)
Copy constructor.
Definition: LeafNode.h:107
bool getItem(Index pos, void *&child, NonConstValueT &value) const
Definition: LeafNode.h:340
void copyFromDense(const CoordBBox &bbox, const DenseT &dense, const ValueType &background, const ValueType &tolerance)
Copy from a dense grid into this node the values of the voxels that lie within a given bounding box...
Definition: LeafNode.h:1186
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:322
Index64 onLeafVoxelCount() const
Definition: LeafNode.h:227
Buffer & buffer()
Definition: LeafNode.h:420
Buffer & operator=(const Buffer &other)
Assigns the values in the other Buffer to this Buffer.
Definition: LeafNode.h:124
static Index size()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:209
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: LeafNode.h:512
void writeBuffers(std::ostream &os, bool toHalf=false) const
Write buffers to a stream.
Definition: LeafNode.h:1274
DenseIter< const LeafNode, const ValueType, ChildAll > ChildAllCIter
Definition: LeafNode.h:369
ChildOffCIter beginChildOff() const
Definition: LeafNode.h:397
Definition: LeafNode.h:57
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNode.h:821
SameConfiguration::value is true if and only if OtherNodeType is the type of a LeafNod...
Definition: LeafNode.h:92
NodeMaskType::DenseIterator MaskDenseIterator
Definition: LeafNode.h:280
ValueOnCIter cendValueOn() const
Definition: LeafNode.h:381
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:122
static void evalNodeOrigin(Coord &xyz)
Compute the origin of the leaf node that contains the voxel with the given coordinates.
Definition: LeafNode.h:884
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
Definition: LeafNode.h:1725
std::string str() const
Return a string representation of this node.
Definition: LeafNode.h:1000
void setValuesOff()
Mark all voxels as inactive but don't change their values.
Definition: LeafNode.h:530
const LeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNode.h:816
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNode.h:296
ChildIter< MaskOnIterator, const LeafNode, ChildOn > ChildOnCIter
Definition: LeafNode.h:365
void topologyDifference(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
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 LeafNode and inactive in the other LeafNode.
Definition: LeafNode.h:1511
const LeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNode.h:818
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Replace inactive occurrences of oldBackground with newBackground, and inactive occurrences of -oldBac...
Definition: LeafNode.h:1430
void getOrigin(Int32 &x, Int32 &y, Int32 &z) const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:254
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: LeafNode.h:519
LeafNode()
Default constructor.
Definition: LeafNode.h:919
bool isApproxEqual(const Hermite &lhs, const Hermite &rhs)
Definition: Hermite.h:470
void setValueMaskOn(Index n)
Definition: LeafNode.h:880
T ValueType
Definition: LeafNode.h:68
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition: LeafNode.h:864
bool isInactive() const
Return true if all of this node's values are inactive.
Definition: LeafNode.h:836
void setValueMaskOff(Index n)
Definition: LeafNode.h:881
ChildAllIter beginChildAll()
Definition: LeafNode.h:401
ValueOffIter endValueOff()
Definition: LeafNode.h:386
ValueAllCIter beginValueAll() const
Definition: LeafNode.h:378
ValueAllCIter cbeginValueAll() const
Definition: LeafNode.h:377
static Index getValueLevel(const Coord &)
Return the level (i.e., 0) at which leaf node values reside.
Definition: LeafNode.h:463
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:107
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Definition: LeafNode.h:1307
ChildOnCIter beginChildOn() const
Definition: LeafNode.h:394
const ValueType & operator[](Index i) const
Return a const reference to the i'th element of the Buffer.
Definition: LeafNode.h:120
void setItem(Index pos, const ValueT &value) const
Definition: LeafNode.h:302
void setValueOnlyAndCache(const Coord &xyz, const ValueType &val, AccessorT &)
Change the value of the voxel at the given coordinates but preserve its state.
Definition: LeafNode.h:607
boost::shared_ptr< LeafNode > Ptr
Definition: LeafNode.h:70
Definition: NodeMasks.h:250
const LeafNode * probeLeaf(const Coord &) const
Return a const pointer to this node.
Definition: LeafNode.h:819
BaseT::NonConstValueType NonConstValueT
Definition: LeafNode.h:335
void pruneInactive(const ValueType &)
This function exists only to enable template instantiation.
Definition: LeafNode.h:778
static Index32 nonLeafCount()
Return the non-leaf count for this node, which is zero.
Definition: LeafNode.h:221
void setValueAndCache(const Coord &xyz, const ValueType &val, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as active.
Definition: LeafNode.h:598
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
ValueAllIter endValueAll()
Definition: LeafNode.h:389
bool isNegative(const Type &x)
Return true if x is less than zero.
Definition: Math.h:304
ChildAllCIter cendChildAll() const
Definition: LeafNode.h:409
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:585
NodeMaskType mValueMask
Bitmask that determines which voxels are active.
Definition: LeafNode.h:862
void writeTopology(std::ostream &os, bool toHalf=false) const
Write out just the topology.
Definition: LeafNode.h:1229
void setValueOnly(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition: LeafNode.h:1106
void setValueOff(Index offset)
Mark the voxel at the given offset as inactive but don't change its value.
Definition: LeafNode.h:478
Definition: Types.h:380
void merge(const LeafNode &)
Definition: LeafNode.h:1449
ValueAllCIter cendValueAll() const
Definition: LeafNode.h:387
static bool hasActiveTiles()
Return false since leaf nodes never contain tiles.
Definition: LeafNode.h:538
ValueOffCIter endValueOff() const
Definition: LeafNode.h:385
static Index numValues()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:211
bool operator==(const Buffer &other) const
Definition: LeafNode.h:134
const ValueType & getValue(const Coord &xyz, bool &state, int &level, AccessorT &) const
Return the value of the voxel at the given coordinates and return its active state and level (i...
Definition: LeafNode.h:659
~LeafNode()
Destructor.
Definition: LeafNode.h:993
void setValueMask(Index n, bool on)
Definition: LeafNode.h:879
const Buffer & buffer() const
Definition: LeafNode.h:419
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:65
NodeMaskType::OnIterator MaskOnIterator
Definition: LeafNode.h:278
OPENVDB_IMPORT uint32_t getDataCompression(std::ios_base &)
Return a bitwise OR of compression option flags (COMPRESS_ZIP, COMPRESS_ACTIVE_MASK, etc.) specifying whether and how input data is compressed or output data should be compressed.
SparseIteratorBase< MaskIterT, ValueIter, NodeT, ValueT > BaseT
Definition: LeafNode.h:293
bool isChildMaskOff() const
Definition: LeafNode.h:877
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
Definition: LeafNode.h:246
static Index size()
Return the number of values represented in this Buffer.
Definition: LeafNode.h:155
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Set the active state of the voxel at the given coordinates without changing its value.
Definition: LeafNode.h:641
static Index getValueLevelAndCache(const Coord &, AccessorT &)
Return the LEVEL (=0) at which leaf node values reside.
Definition: LeafNode.h:670
LeafNode< OtherValueType, Log2Dim > Type
Definition: LeafNode.h:86
static Index32 leafCount()
Return the leaf count for this node, which is one.
Definition: LeafNode.h:219
bool probeValueAndCache(const Coord &xyz, ValueType &val, AccessorT &) const
Return true if the voxel at the given coordinates is active and return the voxel value in val...
Definition: LeafNode.h:650
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:533
ValueIter< MaskOffIterator, LeafNode, const ValueType, ValueOff > ValueOffIter
Definition: LeafNode.h:360
DenseIter< LeafNode, ValueType, ChildAll > ChildAllIter
Definition: LeafNode.h:368
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition: Compression.h:277
LeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNode.h:799
boost::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:217
Buffer mBuffer
Buffer containing the actual data values.
Definition: LeafNode.h:860
const ValueType & getLastValue() const
Return a const reference to the last value in the buffer.
Definition: LeafNode.h:677