OpenVDB  7.2.0
LeafNodeMask.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 #ifndef OPENVDB_TREE_LEAF_NODE_MASK_HAS_BEEN_INCLUDED
5 #define OPENVDB_TREE_LEAF_NODE_MASK_HAS_BEEN_INCLUDED
6 
7 #include <openvdb/version.h>
8 #include <openvdb/Types.h>
9 #include <openvdb/io/Compression.h> // for io::readData(), etc.
10 #include <openvdb/math/Math.h> // for math::isZero()
11 #include <openvdb/util/NodeMasks.h>
12 #include "LeafNode.h"
13 #include "Iterator.h"
14 #include <iostream>
15 #include <sstream>
16 #include <string>
17 #include <type_traits>
18 #include <vector>
19 
20 
21 namespace openvdb {
23 namespace OPENVDB_VERSION_NAME {
24 namespace tree {
25 
29 template<Index Log2Dim>
30 class LeafNode<ValueMask, Log2Dim>
31 {
32 public:
34  using BuildType = ValueMask;// this is a rare case where
35  using ValueType = bool;// value type != build type
36  using Buffer = LeafBuffer<ValueType, Log2Dim>;// buffer uses the bool specialization
39 
40  // These static declarations must be on separate lines to avoid VC9 compiler errors.
41  static const Index LOG2DIM = Log2Dim; // needed by parent nodes
42  static const Index TOTAL = Log2Dim; // needed by parent nodes
43  static const Index DIM = 1 << TOTAL; // dimension along one coordinate direction
44  static const Index NUM_VALUES = 1 << 3 * Log2Dim;
45  static const Index NUM_VOXELS = NUM_VALUES; // total number of voxels represented by this node
46  static const Index SIZE = NUM_VALUES;
47  static const Index LEVEL = 0; // level 0 = leaf
48 
51  template<typename OtherValueType>
52  struct ValueConverter { using Type = LeafNode<OtherValueType, Log2Dim>; };
53 
56  template<typename OtherNodeType>
57  struct SameConfiguration {
59  };
60 
62  LeafNode();
63 
68  explicit LeafNode(const Coord& xyz, bool value = false, bool dummy = false);
69 
71  LeafNode(PartialCreate, const Coord& xyz, bool value = false, bool dummy = false);
72 
74  LeafNode(const LeafNode&);
75 
77  template<typename OtherValueType>
78  explicit LeafNode(const LeafNode<OtherValueType, Log2Dim>& other);
79 
81  template<typename ValueType>
83 
85  template<typename ValueType>
88  LeafNode(const LeafNode<ValueType, Log2Dim>& other, bool offValue, bool onValue, TopologyCopy);
89  template<typename ValueType>
90  LeafNode(const LeafNode<ValueType, Log2Dim>& other, bool background, TopologyCopy);
92 
94  ~LeafNode();
95 
96  //
97  // Statistics
98  //
100  static Index log2dim() { return Log2Dim; }
102  static Index dim() { return DIM; }
104  static Index size() { return SIZE; }
106  static Index numValues() { return SIZE; }
108  static Index getLevel() { return LEVEL; }
110  static void getNodeLog2Dims(std::vector<Index>& dims) { dims.push_back(Log2Dim); }
112  static Index getChildDim() { return 1; }
114  static Index32 leafCount() { return 1; }
116  void nodeCount(std::vector<Index32> &) const {}
118  static Index32 nonLeafCount() { return 0; }
119 
121  Index64 onVoxelCount() const { return mBuffer.mData.countOn(); }
123  Index64 offVoxelCount() const { return mBuffer.mData.countOff(); }
124  Index64 onLeafVoxelCount() const { return this->onVoxelCount(); }
125  Index64 offLeafVoxelCount() const { return this->offVoxelCount(); }
126  static Index64 onTileCount() { return 0; }
127  static Index64 offTileCount() { return 0; }
128 
130  bool isEmpty() const { return mBuffer.mData.isOff(); }
132  bool isDense() const { return mBuffer.mData.isOn(); }
136  bool isAllocated() const { return true; }
140  bool allocate() { return true; }
141 
143  Index64 memUsage() const;
144 
148  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
149 
152  CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); }
153 
155  void setOrigin(const Coord& origin) { mOrigin = origin; }
157  const Coord& origin() const { return mOrigin; }
159  void getOrigin(Coord& origin) const { origin = mOrigin; }
160  void getOrigin(Int32& x, Int32& y, Int32& z) const { mOrigin.asXYZ(x, y, z); }
162 
164  static Index coordToOffset(const Coord& xyz);
167  static Coord offsetToLocalCoord(Index n);
169  Coord offsetToGlobalCoord(Index n) const;
170 
172  std::string str() const;
173 
176  template<typename OtherType, Index OtherLog2Dim>
177  bool hasSameTopology(const LeafNode<OtherType, OtherLog2Dim>* other) const;
178 
180  bool operator==(const LeafNode&) const;
181  bool operator!=(const LeafNode&) const;
182 
183  //
184  // Buffer management
185  //
188  void swap(Buffer& other) { mBuffer.swap(other); }
189  const Buffer& buffer() const { return mBuffer; }
190  Buffer& buffer() { return mBuffer; }
191 
192  //
193  // I/O methods
194  //
196  void readTopology(std::istream&, bool fromHalf = false);
198  void writeTopology(std::ostream&, bool toHalf = false) const;
199 
201  void readBuffers(std::istream&, bool fromHalf = false);
202  void readBuffers(std::istream& is, const CoordBBox&, bool fromHalf = false);
204  void writeBuffers(std::ostream&, bool toHalf = false) const;
205 
206  //
207  // Accessor methods
208  //
210  const bool& getValue(const Coord& xyz) const;
212  const bool& getValue(Index offset) const;
213 
217  bool probeValue(const Coord& xyz, bool& val) const;
218 
220  static Index getValueLevel(const Coord&) { return LEVEL; }
221 
223  void setActiveState(const Coord& xyz, bool on);
225  void setActiveState(Index offset, bool on) { assert(offset<SIZE); mBuffer.mData.set(offset, on); }
226 
228  void setValueOnly(const Coord& xyz, bool val);
230  void setValueOnly(Index offset, bool val) { assert(offset<SIZE); mBuffer.setValue(offset,val); }
231 
233  void setValueOff(const Coord& xyz) { mBuffer.mData.setOff(this->coordToOffset(xyz)); }
235  void setValueOff(Index offset) { assert(offset < SIZE); mBuffer.mData.setOff(offset); }
236 
238  void setValueOff(const Coord& xyz, bool val);
240  void setValueOff(Index offset, bool val);
241 
243  void setValueOn(const Coord& xyz) { mBuffer.mData.setOn(this->coordToOffset(xyz)); }
245  void setValueOn(Index offset) { assert(offset < SIZE); mBuffer.mData.setOn(offset); }
246 
248  void setValueOn(const Coord& xyz, bool val);
250  void setValue(const Coord& xyz, bool val) { this->setValueOn(xyz, val); }
252  void setValueOn(Index offset, bool val);
253 
256  template<typename ModifyOp>
257  void modifyValue(Index offset, const ModifyOp& op);
260  template<typename ModifyOp>
261  void modifyValue(const Coord& xyz, const ModifyOp& op);
262 
264  template<typename ModifyOp>
265  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op);
266 
268  void setValuesOn() { mBuffer.mData.setOn(); }
270  void setValuesOff() { mBuffer.mData.setOff(); }
271 
273  bool isValueOn(const Coord& xyz) const { return mBuffer.mData.isOn(this->coordToOffset(xyz)); }
275  bool isValueOn(Index offset) const { assert(offset < SIZE); return mBuffer.mData.isOn(offset); }
276 
278  static bool hasActiveTiles() { return false; }
279 
281  void clip(const CoordBBox&, bool background);
282 
284  void fill(const CoordBBox& bbox, bool value, bool = false);
286  void denseFill(const CoordBBox& bbox, bool value, bool = false) { this->fill(bbox, value); }
287 
289  void fill(const bool& value, bool dummy = false);
290 
302  template<typename DenseT>
303  void copyToDense(const CoordBBox& bbox, DenseT& dense) const;
304 
321  template<typename DenseT>
322  void copyFromDense(const CoordBBox& bbox, const DenseT& dense, bool background, bool tolerance);
323 
326  template<typename AccessorT>
327  const bool& getValueAndCache(const Coord& xyz, AccessorT&) const {return this->getValue(xyz);}
328 
331  template<typename AccessorT>
332  bool isValueOnAndCache(const Coord& xyz, AccessorT&) const { return this->isValueOn(xyz); }
333 
336  template<typename AccessorT>
337  void setValueAndCache(const Coord& xyz, bool val, AccessorT&) { this->setValueOn(xyz, val); }
338 
342  template<typename AccessorT>
343  void setValueOnlyAndCache(const Coord& xyz, bool val, AccessorT&) {this->setValueOnly(xyz,val);}
344 
347  template<typename AccessorT>
348  void setValueOffAndCache(const Coord& xyz, bool value, AccessorT&)
349  {
350  this->setValueOff(xyz, value);
351  }
352 
356  template<typename ModifyOp, typename AccessorT>
357  void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
358  {
359  this->modifyValue(xyz, op);
360  }
361 
364  template<typename ModifyOp, typename AccessorT>
365  void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
366  {
367  this->modifyValueAndActiveState(xyz, op);
368  }
369 
373  template<typename AccessorT>
374  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&)
375  {
376  this->setActiveState(xyz, on);
377  }
378 
382  template<typename AccessorT>
383  bool probeValueAndCache(const Coord& xyz, bool& val, AccessorT&) const
384  {
385  return this->probeValue(xyz, val);
386  }
387 
390  template<typename AccessorT>
391  static Index getValueLevelAndCache(const Coord&, AccessorT&) { return LEVEL; }
392 
396  const bool& getFirstValue() const { if (mBuffer.mData.isOn(0)) return Buffer::sOn; else return Buffer::sOff; }
400  const bool& getLastValue() const { if (mBuffer.mData.isOn(SIZE-1)) return Buffer::sOn; else return Buffer::sOff; }
401 
405  bool isConstant(bool& constValue, bool& state, bool tolerance = 0) const;
406 
412  bool medianAll() const;
413 
421  Index medianOn(ValueType &value) const;
422 
431  Index medianOff(ValueType &value) const;
432 
434  bool isInactive() const { return mBuffer.mData.isOff(); }
435 
438  void resetBackground(bool, bool) {}
439 
441  void negate() { mBuffer.mData.toggle(); }
442 
443  template<MergePolicy Policy>
444  void merge(const LeafNode& other, bool bg = false, bool otherBG = false);
445  template<MergePolicy Policy> void merge(bool tileValue, bool tileActive=false);
446 
449  void voxelizeActiveTiles(bool = true) {}
450 
457  template<typename OtherType>
458  void topologyUnion(const LeafNode<OtherType, Log2Dim>& other);
459 
471  template<typename OtherType>
472  void topologyIntersection(const LeafNode<OtherType, Log2Dim>& other, const bool&);
473 
485  template<typename OtherType>
486  void topologyDifference(const LeafNode<OtherType, Log2Dim>& other, const bool&);
487 
488  template<typename CombineOp>
489  void combine(const LeafNode& other, CombineOp& op);
490  template<typename CombineOp>
491  void combine(bool, bool valueIsActive, CombineOp& op);
492 
493  template<typename CombineOp, typename OtherType /*= bool*/>
494  void combine2(const LeafNode& other, const OtherType&, bool valueIsActive, CombineOp&);
495  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
496  void combine2(bool, const OtherNodeT& other, bool valueIsActive, CombineOp&);
497  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
498  void combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp&);
499 
504  template<typename BBoxOp> void visitActiveBBox(BBoxOp&) const;
505 
506  template<typename VisitorOp> void visit(VisitorOp&);
507  template<typename VisitorOp> void visit(VisitorOp&) const;
508 
509  template<typename OtherLeafNodeType, typename VisitorOp>
510  void visit2Node(OtherLeafNodeType& other, VisitorOp&);
511  template<typename OtherLeafNodeType, typename VisitorOp>
512  void visit2Node(OtherLeafNodeType& other, VisitorOp&) const;
513  template<typename IterT, typename VisitorOp>
514  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false);
515  template<typename IterT, typename VisitorOp>
516  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false) const;
517 
519  void prune(const ValueType& /*tolerance*/ = zeroVal<ValueType>()) {}
521  void addLeaf(LeafNode*) {}
522  template<typename AccessorT>
523  void addLeafAndCache(LeafNode*, AccessorT&) {}
524  template<typename NodeT>
525  NodeT* stealNode(const Coord&, const ValueType&, bool) { return nullptr; }
526  template<typename NodeT>
527  NodeT* probeNode(const Coord&) { return nullptr; }
528  template<typename NodeT>
529  const NodeT* probeConstNode(const Coord&) const { return nullptr; }
530  template<typename ArrayT> void getNodes(ArrayT&) const {}
531  template<typename ArrayT> void stealNodes(ArrayT&, const ValueType&, bool) {}
533 
534  void addTile(Index level, const Coord&, bool val, bool active);
535  void addTile(Index offset, bool val, bool active);
536  template<typename AccessorT>
537  void addTileAndCache(Index level, const Coord&, bool val, bool active, AccessorT&);
538 
540  LeafNode* touchLeaf(const Coord&) { return this; }
542  template<typename AccessorT>
543  LeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
544  LeafNode* probeLeaf(const Coord&) { return this; }
545  template<typename AccessorT>
546  LeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
547  template<typename NodeT, typename AccessorT>
548  NodeT* probeNodeAndCache(const Coord&, AccessorT&)
549  {
551  if (!(std::is_same<NodeT, LeafNode>::value)) return nullptr;
552  return reinterpret_cast<NodeT*>(this);
554  }
556 
557  const LeafNode* probeLeaf(const Coord&) const { return this; }
559  template<typename AccessorT>
560  const LeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
561  const LeafNode* probeConstLeaf(const Coord&) const { return this; }
562  template<typename AccessorT>
563  const LeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
564  template<typename NodeT, typename AccessorT>
565  const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
566  {
568  if (!(std::is_same<NodeT, LeafNode>::value)) return nullptr;
569  return reinterpret_cast<const NodeT*>(this);
571  }
573 
574  //
575  // Iterators
576  //
577 protected:
581 
582  template<typename MaskIterT, typename NodeT, typename ValueT>
583  struct ValueIter:
584  // Derives from SparseIteratorBase, but can also be used as a dense iterator,
585  // if MaskIterT is a dense mask iterator type.
586  public SparseIteratorBase<MaskIterT, ValueIter<MaskIterT, NodeT, ValueT>, NodeT, ValueT>
587  {
589 
591  ValueIter(const MaskIterT& iter, NodeT* parent): BaseT(iter, parent) {}
592 
593  const bool& getItem(Index pos) const { return this->parent().getValue(pos); }
594  const bool& getValue() const { return this->getItem(this->pos()); }
595 
596  // Note: setItem() can't be called on const iterators.
597  void setItem(Index pos, bool value) const { this->parent().setValueOnly(pos, value); }
598  // Note: setValue() can't be called on const iterators.
599  void setValue(bool value) const { this->setItem(this->pos(), value); }
600 
601  // Note: modifyItem() can't be called on const iterators.
602  template<typename ModifyOp>
603  void modifyItem(Index n, const ModifyOp& op) const { this->parent().modifyValue(n, op); }
604  // Note: modifyValue() can't be called on const iterators.
605  template<typename ModifyOp>
606  void modifyValue(const ModifyOp& op) const { this->modifyItem(this->pos(), op); }
607  };
608 
610  template<typename MaskIterT, typename NodeT>
611  struct ChildIter:
612  public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT>, NodeT, bool>
613  {
615  ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
616  MaskIterT, ChildIter<MaskIterT, NodeT>, NodeT, bool>(iter, parent) {}
617  };
618 
619  template<typename NodeT, typename ValueT>
620  struct DenseIter: public DenseIteratorBase<
621  MaskDenseIter, DenseIter<NodeT, ValueT>, NodeT, /*ChildT=*/void, ValueT>
622  {
625 
627  DenseIter(const MaskDenseIter& iter, NodeT* parent): BaseT(iter, parent) {}
628 
629  bool getItem(Index pos, void*& child, NonConstValueT& value) const
630  {
631  value = this->parent().getValue(pos);
632  child = nullptr;
633  return false; // no child
634  }
635 
636  // Note: setItem() can't be called on const iterators.
637  //void setItem(Index pos, void* child) const {}
638 
639  // Note: unsetItem() can't be called on const iterators.
640  void unsetItem(Index pos, const ValueT& val) const {this->parent().setValueOnly(pos, val);}
641  };
642 
643 public:
644  using ValueOnIter = ValueIter<MaskOnIter, LeafNode, const bool>;
645  using ValueOnCIter = ValueIter<MaskOnIter, const LeafNode, const bool>;
646  using ValueOffIter = ValueIter<MaskOffIter, LeafNode, const bool>;
647  using ValueOffCIter = ValueIter<MaskOffIter, const LeafNode, const bool>;
648  using ValueAllIter = ValueIter<MaskDenseIter, LeafNode, const bool>;
649  using ValueAllCIter = ValueIter<MaskDenseIter, const LeafNode, const bool>;
650  using ChildOnIter = ChildIter<MaskOnIter, LeafNode>;
651  using ChildOnCIter = ChildIter<MaskOnIter, const LeafNode>;
652  using ChildOffIter = ChildIter<MaskOffIter, LeafNode>;
653  using ChildOffCIter = ChildIter<MaskOffIter, const LeafNode>;
654  using ChildAllIter = DenseIter<LeafNode, bool>;
655  using ChildAllCIter = DenseIter<const LeafNode, const bool>;
656 
657  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mBuffer.mData.beginOn(), this); }
658  ValueOnCIter beginValueOn() const { return ValueOnCIter(mBuffer.mData.beginOn(), this); }
659  ValueOnIter beginValueOn() { return ValueOnIter(mBuffer.mData.beginOn(), this); }
660  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mBuffer.mData.beginOff(), this); }
661  ValueOffCIter beginValueOff() const { return ValueOffCIter(mBuffer.mData.beginOff(), this); }
662  ValueOffIter beginValueOff() { return ValueOffIter(mBuffer.mData.beginOff(), this); }
663  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mBuffer.mData.beginDense(), this); }
664  ValueAllCIter beginValueAll() const { return ValueAllCIter(mBuffer.mData.beginDense(), this); }
665  ValueAllIter beginValueAll() { return ValueAllIter(mBuffer.mData.beginDense(), this); }
666 
667  ValueOnCIter cendValueOn() const { return ValueOnCIter(mBuffer.mData.endOn(), this); }
668  ValueOnCIter endValueOn() const { return ValueOnCIter(mBuffer.mData.endOn(), this); }
669  ValueOnIter endValueOn() { return ValueOnIter(mBuffer.mData.endOn(), this); }
670  ValueOffCIter cendValueOff() const { return ValueOffCIter(mBuffer.mData.endOff(), this); }
671  ValueOffCIter endValueOff() const { return ValueOffCIter(mBuffer.mData.endOff(), this); }
672  ValueOffIter endValueOff() { return ValueOffIter(mBuffer.mData.endOff(), this); }
673  ValueAllCIter cendValueAll() const { return ValueAllCIter(mBuffer.mData.endDense(), this); }
674  ValueAllCIter endValueAll() const { return ValueAllCIter(mBuffer.mData.endDense(), this); }
675  ValueAllIter endValueAll() { return ValueAllIter(mBuffer.mData.endDense(), this); }
676 
677  // Note that [c]beginChildOn() and [c]beginChildOff() actually return end iterators,
678  // because leaf nodes have no children.
679  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mBuffer.mData.endOn(), this); }
680  ChildOnCIter beginChildOn() const { return ChildOnCIter(mBuffer.mData.endOn(), this); }
681  ChildOnIter beginChildOn() { return ChildOnIter(mBuffer.mData.endOn(), this); }
682  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mBuffer.mData.endOff(), this); }
683  ChildOffCIter beginChildOff() const { return ChildOffCIter(mBuffer.mData.endOff(), this); }
684  ChildOffIter beginChildOff() { return ChildOffIter(mBuffer.mData.endOff(), this); }
685  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mBuffer.mData.beginDense(), this); }
686  ChildAllCIter beginChildAll() const { return ChildAllCIter(mBuffer.mData.beginDense(), this); }
687  ChildAllIter beginChildAll() { return ChildAllIter(mBuffer.mData.beginDense(), this); }
688 
689  ChildOnCIter cendChildOn() const { return ChildOnCIter(mBuffer.mData.endOn(), this); }
690  ChildOnCIter endChildOn() const { return ChildOnCIter(mBuffer.mData.endOn(), this); }
691  ChildOnIter endChildOn() { return ChildOnIter(mBuffer.mData.endOn(), this); }
692  ChildOffCIter cendChildOff() const { return ChildOffCIter(mBuffer.mData.endOff(), this); }
693  ChildOffCIter endChildOff() const { return ChildOffCIter(mBuffer.mData.endOff(), this); }
694  ChildOffIter endChildOff() { return ChildOffIter(mBuffer.mData.endOff(), this); }
695  ChildAllCIter cendChildAll() const { return ChildAllCIter(mBuffer.mData.endDense(), this); }
696  ChildAllCIter endChildAll() const { return ChildAllCIter(mBuffer.mData.endDense(), this); }
697  ChildAllIter endChildAll() { return ChildAllIter(mBuffer.mData.endDense(), this); }
698 
699  //
700  // Mask accessors
701  //
702  bool isValueMaskOn(Index n) const { return mBuffer.mData.isOn(n); }
703  bool isValueMaskOn() const { return mBuffer.mData.isOn(); }
704  bool isValueMaskOff(Index n) const { return mBuffer.mData.isOff(n); }
705  bool isValueMaskOff() const { return mBuffer.mData.isOff(); }
706  const NodeMaskType& getValueMask() const { return mBuffer.mData; }
707  const NodeMaskType& valueMask() const { return mBuffer.mData; }
708  NodeMaskType& getValueMask() { return mBuffer.mData; }
709  void setValueMask(const NodeMaskType& mask) { mBuffer.mData = mask; }
710  bool isChildMaskOn(Index) const { return false; } // leaf nodes have no children
711  bool isChildMaskOff(Index) const { return true; }
712  bool isChildMaskOff() const { return true; }
713 protected:
714  void setValueMask(Index n, bool on) { mBuffer.mData.set(n, on); }
715  void setValueMaskOn(Index n) { mBuffer.mData.setOn(n); }
716  void setValueMaskOff(Index n) { mBuffer.mData.setOff(n); }
717 
719  static void evalNodeOrigin(Coord& xyz) { xyz &= ~(DIM - 1); }
720 
721  template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
722  static inline void doVisit(NodeT&, VisitorOp&);
723 
724  template<typename NodeT, typename OtherNodeT, typename VisitorOp,
725  typename ChildAllIterT, typename OtherChildAllIterT>
726  static inline void doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp&);
727 
728  template<typename NodeT, typename VisitorOp,
729  typename ChildAllIterT, typename OtherChildAllIterT>
730  static inline void doVisit2(NodeT& self, OtherChildAllIterT&, VisitorOp&, bool otherIsLHS);
731 
734 
736  Coord mOrigin;
737 
738 private:
741  template<typename, Index> friend class LeafNode;
742 
743  friend struct ValueIter<MaskOnIter, LeafNode, bool>;
744  friend struct ValueIter<MaskOffIter, LeafNode, bool>;
745  friend struct ValueIter<MaskDenseIter, LeafNode, bool>;
746  friend struct ValueIter<MaskOnIter, const LeafNode, bool>;
747  friend struct ValueIter<MaskOffIter, const LeafNode, bool>;
748  friend struct ValueIter<MaskDenseIter, const LeafNode, bool>;
749 
751  friend class IteratorBase<MaskOnIter, LeafNode>;
757 
758  template<typename, Index> friend class LeafBuffer;
759 
760 }; // class LeafNode<ValueMask>
761 
762 
764 
765 
766 template<Index Log2Dim>
767 inline
769  : mOrigin(0, 0, 0)
770 {
771 }
772 
773 template<Index Log2Dim>
774 inline
775 LeafNode<ValueMask, Log2Dim>::LeafNode(const Coord& xyz, bool value, bool active)
776  : mBuffer(value || active)
777  , mOrigin(xyz & (~(DIM - 1)))
778 {
779 }
780 
781 
782 template<Index Log2Dim>
783 inline
784 LeafNode<ValueMask, Log2Dim>::LeafNode(PartialCreate, const Coord& xyz, bool value, bool active)
785  : mBuffer(value || active)
786  , mOrigin(xyz & (~(DIM - 1)))
787 {
788 }
789 
790 
791 template<Index Log2Dim>
792 inline
794  : mBuffer(other.mBuffer)
795  , mOrigin(other.mOrigin)
796 {
797 }
798 
799 
800 // Copy-construct from a leaf node with the same configuration but a different ValueType.
801 template<Index Log2Dim>
802 template<typename ValueT>
803 inline
805  : mBuffer(other.valueMask())
806  , mOrigin(other.origin())
807 {
808 }
809 
810 
811 template<Index Log2Dim>
812 template<typename ValueT>
813 inline
815  bool, TopologyCopy)
816  : mBuffer(other.valueMask())// value = active state
817  , mOrigin(other.origin())
818 {
819 }
820 
821 
822 template<Index Log2Dim>
823 template<typename ValueT>
824 inline
826  : mBuffer(other.valueMask())// value = active state
827  , mOrigin(other.origin())
828 {
829 }
830 
831 
832 template<Index Log2Dim>
833 template<typename ValueT>
834 inline
836  bool offValue, bool onValue, TopologyCopy)
837  : mBuffer(other.valueMask())
838  , mOrigin(other.origin())
839 {
840  if (offValue==true) {
841  if (onValue==false) {
842  mBuffer.mData.toggle();
843  } else {
844  mBuffer.mData.setOn();
845  }
846  }
847 }
848 
849 
850 template<Index Log2Dim>
851 inline
853 {
854 }
855 
856 
858 
859 
860 template<Index Log2Dim>
861 inline Index64
863 {
864  // Use sizeof(*this) to capture alignment-related padding
865  return sizeof(*this);
866 }
867 
868 
869 template<Index Log2Dim>
870 inline void
871 LeafNode<ValueMask, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const
872 {
873  CoordBBox this_bbox = this->getNodeBoundingBox();
874  if (bbox.isInside(this_bbox)) return;//this LeafNode is already enclosed in the bbox
875  if (ValueOnCIter iter = this->cbeginValueOn()) {//any active values?
876  if (visitVoxels) {//use voxel granularity?
877  this_bbox.reset();
878  for(; iter; ++iter) this_bbox.expand(this->offsetToLocalCoord(iter.pos()));
879  this_bbox.translate(this->origin());
880  }
881  bbox.expand(this_bbox);
882  }
883 }
884 
885 
886 template<Index Log2Dim>
887 template<typename OtherType, Index OtherLog2Dim>
888 inline bool
890 {
891  assert(other);
892  return (Log2Dim == OtherLog2Dim && mBuffer.mData == other->getValueMask());
893 }
894 
895 
896 template<Index Log2Dim>
897 inline std::string
899 {
900  std::ostringstream ostr;
901  ostr << "LeafNode @" << mOrigin << ": ";
902  for (Index32 n = 0; n < SIZE; ++n) ostr << (mBuffer.mData.isOn(n) ? '#' : '.');
903  return ostr.str();
904 }
905 
906 
908 
909 
910 template<Index Log2Dim>
911 inline Index
913 {
914  assert ((xyz[0] & (DIM-1u)) < DIM && (xyz[1] & (DIM-1u)) < DIM && (xyz[2] & (DIM-1u)) < DIM);
915  return ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
916  + ((xyz[1] & (DIM-1u)) << Log2Dim)
917  + (xyz[2] & (DIM-1u));
918 }
919 
920 
921 template<Index Log2Dim>
922 inline Coord
924 {
925  assert(n < (1 << 3*Log2Dim));
926  Coord xyz;
927  xyz.setX(n >> 2*Log2Dim);
928  n &= ((1 << 2*Log2Dim) - 1);
929  xyz.setY(n >> Log2Dim);
930  xyz.setZ(n & ((1 << Log2Dim) - 1));
931  return xyz;
932 }
933 
934 
935 template<Index Log2Dim>
936 inline Coord
938 {
939  return (this->offsetToLocalCoord(n) + this->origin());
940 }
941 
942 
944 
945 
946 template<Index Log2Dim>
947 inline void
948 LeafNode<ValueMask, Log2Dim>::readTopology(std::istream& is, bool /*fromHalf*/)
949 {
950  mBuffer.mData.load(is);
951 }
952 
953 
954 template<Index Log2Dim>
955 inline void
956 LeafNode<ValueMask, Log2Dim>::writeTopology(std::ostream& os, bool /*toHalf*/) const
957 {
958  mBuffer.mData.save(os);
959 }
960 
961 
962 template<Index Log2Dim>
963 inline void
964 LeafNode<ValueMask, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& clipBBox, bool fromHalf)
965 {
966  // Boolean LeafNodes don't currently implement lazy loading.
967  // Instead, load the full buffer, then clip it.
968 
969  this->readBuffers(is, fromHalf);
970 
971  // Get this tree's background value.
972  bool background = false;
973  if (const void* bgPtr = io::getGridBackgroundValuePtr(is)) {
974  background = *static_cast<const bool*>(bgPtr);
975  }
976  this->clip(clipBBox, background);
977 }
978 
979 
980 template<Index Log2Dim>
981 inline void
982 LeafNode<ValueMask, Log2Dim>::readBuffers(std::istream& is, bool /*fromHalf*/)
983 {
984  // Read in the value mask = buffer.
985  mBuffer.mData.load(is);
986  // Read in the origin.
987  is.read(reinterpret_cast<char*>(&mOrigin), sizeof(Coord::ValueType) * 3);
988 }
989 
990 
991 template<Index Log2Dim>
992 inline void
993 LeafNode<ValueMask, Log2Dim>::writeBuffers(std::ostream& os, bool /*toHalf*/) const
994 {
995  // Write out the value mask = buffer.
996  mBuffer.mData.save(os);
997  // Write out the origin.
998  os.write(reinterpret_cast<const char*>(&mOrigin), sizeof(Coord::ValueType) * 3);
999 }
1000 
1001 
1003 
1004 
1005 template<Index Log2Dim>
1006 inline bool
1008 {
1009  return mOrigin == other.mOrigin && mBuffer == other.mBuffer;
1010 }
1011 
1012 
1013 template<Index Log2Dim>
1014 inline bool
1016 {
1017  return !(this->operator==(other));
1018 }
1019 
1020 
1022 
1023 
1024 template<Index Log2Dim>
1025 inline bool
1026 LeafNode<ValueMask, Log2Dim>::isConstant(bool& constValue, bool& state, bool) const
1027 {
1028  if (!mBuffer.mData.isConstant(state)) return false;
1029 
1030  constValue = state;
1031  return true;
1032 }
1033 
1034 
1036 
1037 template<Index Log2Dim>
1038 inline bool
1040 {
1041  const Index countTrue = mBuffer.mData.countOn();
1042  return countTrue > (NUM_VALUES >> 1);
1043 }
1044 
1045 template<Index Log2Dim>
1046 inline Index
1048 {
1049  const Index countTrueOn = mBuffer.mData.countOn();
1050  state = true;//since value and state are the same for this specialization of the leaf node
1051  return countTrueOn;
1052 }
1053 
1054 template<Index Log2Dim>
1055 inline Index
1057 {
1058  const Index countFalseOff = mBuffer.mData.countOff();
1059  state = false;//since value and state are the same for this specialization of the leaf node
1060  return countFalseOff;
1061 }
1062 
1063 
1065 
1066 
1067 template<Index Log2Dim>
1068 inline void
1069 LeafNode<ValueMask, Log2Dim>::addTile(Index /*level*/, const Coord& xyz, bool val, bool active)
1070 {
1071  this->addTile(this->coordToOffset(xyz), val, active);
1072 }
1073 
1074 template<Index Log2Dim>
1075 inline void
1076 LeafNode<ValueMask, Log2Dim>::addTile(Index offset, bool val, bool active)
1077 {
1078  assert(offset < SIZE);
1079  this->setValueOnly(offset, val);
1080  this->setActiveState(offset, active);
1081 }
1082 
1083 template<Index Log2Dim>
1084 template<typename AccessorT>
1085 inline void
1087  bool val, bool active, AccessorT&)
1088 {
1089  this->addTile(level, xyz, val, active);
1090 }
1091 
1092 
1094 
1095 
1096 template<Index Log2Dim>
1097 inline const bool&
1099 {
1100  // This *CANNOT* use operator ? because Visual C++
1101  if (mBuffer.mData.isOn(this->coordToOffset(xyz))) return Buffer::sOn; else return Buffer::sOff;
1102 }
1103 
1104 
1105 template<Index Log2Dim>
1106 inline const bool&
1108 {
1109  assert(offset < SIZE);
1110  // This *CANNOT* use operator ? for Windows
1111  if (mBuffer.mData.isOn(offset)) return Buffer::sOn; else return Buffer::sOff;
1112 }
1113 
1114 
1115 template<Index Log2Dim>
1116 inline bool
1117 LeafNode<ValueMask, Log2Dim>::probeValue(const Coord& xyz, bool& val) const
1118 {
1119  const Index offset = this->coordToOffset(xyz);
1120  val = mBuffer.mData.isOn(offset);
1121  return val;
1122 }
1123 
1124 
1125 template<Index Log2Dim>
1126 inline void
1127 LeafNode<ValueMask, Log2Dim>::setValueOn(const Coord& xyz, bool val)
1128 {
1129  this->setValueOn(this->coordToOffset(xyz), val);
1130 }
1131 
1132 
1133 template<Index Log2Dim>
1134 inline void
1136 {
1137  assert(offset < SIZE);
1138  mBuffer.mData.set(offset, val);
1139 }
1140 
1141 
1142 template<Index Log2Dim>
1143 inline void
1145 {
1146  this->setValueOnly(this->coordToOffset(xyz), val);
1147 }
1148 
1149 
1150 template<Index Log2Dim>
1151 inline void
1153 {
1154  mBuffer.mData.set(this->coordToOffset(xyz), on);
1155 }
1156 
1157 
1158 template<Index Log2Dim>
1159 inline void
1161 {
1162  this->setValueOff(this->coordToOffset(xyz), val);
1163 }
1164 
1165 
1166 template<Index Log2Dim>
1167 inline void
1169 {
1170  assert(offset < SIZE);
1171  mBuffer.mData.set(offset, val);
1172 }
1173 
1174 
1175 template<Index Log2Dim>
1176 template<typename ModifyOp>
1177 inline void
1179 {
1180  bool val = mBuffer.mData.isOn(offset);
1181  op(val);
1182  mBuffer.mData.set(offset, val);
1183 }
1184 
1185 
1186 template<Index Log2Dim>
1187 template<typename ModifyOp>
1188 inline void
1189 LeafNode<ValueMask, Log2Dim>::modifyValue(const Coord& xyz, const ModifyOp& op)
1190 {
1191  this->modifyValue(this->coordToOffset(xyz), op);
1192 }
1193 
1194 
1195 template<Index Log2Dim>
1196 template<typename ModifyOp>
1197 inline void
1198 LeafNode<ValueMask, Log2Dim>::modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1199 {
1200  const Index offset = this->coordToOffset(xyz);
1201  bool val = mBuffer.mData.isOn(offset), state = val;
1202  op(val, state);
1203  mBuffer.mData.set(offset, val);
1204 }
1205 
1206 
1208 
1209 
1210 template<Index Log2Dim>
1211 template<MergePolicy Policy>
1212 inline void
1213 LeafNode<ValueMask, Log2Dim>::merge(const LeafNode& other, bool /*bg*/, bool /*otherBG*/)
1214 {
1216  if (Policy == MERGE_NODES) return;
1217  mBuffer.mData |= other.mBuffer.mData;
1219 }
1220 
1221 template<Index Log2Dim>
1222 template<MergePolicy Policy>
1223 inline void
1225 {
1227  if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return;
1228  if (tileValue) mBuffer.mData.setOn();
1230 }
1231 
1232 
1234 
1235 
1236 template<Index Log2Dim>
1237 template<typename OtherType>
1238 inline void
1240 {
1241  mBuffer.mData |= other.valueMask();
1242 }
1243 
1244 
1245 template<Index Log2Dim>
1246 template<typename OtherType>
1247 inline void
1249  const bool&)
1250 {
1251  mBuffer.mData &= other.valueMask();
1252 }
1253 
1254 
1255 template<Index Log2Dim>
1256 template<typename OtherType>
1257 inline void
1259  const bool&)
1260 {
1261  mBuffer.mData &= !other.valueMask();
1262 }
1263 
1264 
1266 
1267 
1268 template<Index Log2Dim>
1269 inline void
1270 LeafNode<ValueMask, Log2Dim>::clip(const CoordBBox& clipBBox, bool background)
1271 {
1272  CoordBBox nodeBBox = this->getNodeBoundingBox();
1273  if (!clipBBox.hasOverlap(nodeBBox)) {
1274  // This node lies completely outside the clipping region. Fill it with background tiles.
1275  this->fill(nodeBBox, background, /*active=*/false);
1276  } else if (clipBBox.isInside(nodeBBox)) {
1277  // This node lies completely inside the clipping region. Leave it intact.
1278  return;
1279  }
1280 
1281  // This node isn't completely contained inside the clipping region.
1282  // Set any voxels that lie outside the region to the background value.
1283 
1284  // Construct a boolean mask that is on inside the clipping region and off outside it.
1285  NodeMaskType mask;
1286  nodeBBox.intersect(clipBBox);
1287  Coord xyz;
1288  int &x = xyz.x(), &y = xyz.y(), &z = xyz.z();
1289  for (x = nodeBBox.min().x(); x <= nodeBBox.max().x(); ++x) {
1290  for (y = nodeBBox.min().y(); y <= nodeBBox.max().y(); ++y) {
1291  for (z = nodeBBox.min().z(); z <= nodeBBox.max().z(); ++z) {
1292  mask.setOn(static_cast<Index32>(this->coordToOffset(xyz)));
1293  }
1294  }
1295  }
1296 
1297  // Set voxels that lie in the inactive region of the mask (i.e., outside
1298  // the clipping region) to the background value.
1299  for (MaskOffIter maskIter = mask.beginOff(); maskIter; ++maskIter) {
1300  this->setValueOff(maskIter.pos(), background);
1301  }
1302 }
1303 
1304 
1306 
1307 
1308 template<Index Log2Dim>
1309 inline void
1310 LeafNode<ValueMask, Log2Dim>::fill(const CoordBBox& bbox, bool value, bool)
1311 {
1312  auto clippedBBox = this->getNodeBoundingBox();
1313  clippedBBox.intersect(bbox);
1314  if (!clippedBBox) return;
1315 
1316  for (Int32 x = clippedBBox.min().x(); x <= clippedBBox.max().x(); ++x) {
1317  const Index offsetX = (x & (DIM-1u))<<2*Log2Dim;
1318  for (Int32 y = clippedBBox.min().y(); y <= clippedBBox.max().y(); ++y) {
1319  const Index offsetXY = offsetX + ((y & (DIM-1u))<< Log2Dim);
1320  for (Int32 z = clippedBBox.min().z(); z <= clippedBBox.max().z(); ++z) {
1321  const Index offset = offsetXY + (z & (DIM-1u));
1322  mBuffer.mData.set(offset, value);
1323  }
1324  }
1325  }
1326 }
1327 
1328 template<Index Log2Dim>
1329 inline void
1330 LeafNode<ValueMask, Log2Dim>::fill(const bool& value, bool)
1331 {
1332  mBuffer.fill(value);
1333 }
1334 
1335 
1337 
1338 
1339 template<Index Log2Dim>
1340 template<typename DenseT>
1341 inline void
1342 LeafNode<ValueMask, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const
1343 {
1344  using DenseValueType = typename DenseT::ValueType;
1345 
1346  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1347  const Coord& min = dense.bbox().min();
1348  DenseValueType* t0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // target array
1349  const Int32 n0 = bbox.min()[2] & (DIM-1u);
1350  for (Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1; x < ex; ++x) {
1351  DenseValueType* t1 = t0 + xStride * (x - min[0]);
1352  const Int32 n1 = n0 + ((x & (DIM-1u)) << 2*LOG2DIM);
1353  for (Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1; y < ey; ++y) {
1354  DenseValueType* t2 = t1 + yStride * (y - min[1]);
1355  Int32 n2 = n1 + ((y & (DIM-1u)) << LOG2DIM);
1356  for (Int32 z = bbox.min()[2], ez = bbox.max()[2] + 1; z < ez; ++z, t2 += zStride) {
1357  *t2 = DenseValueType(mBuffer.mData.isOn(n2++));
1358  }
1359  }
1360  }
1361 }
1362 
1363 
1364 template<Index Log2Dim>
1365 template<typename DenseT>
1366 inline void
1367 LeafNode<ValueMask, Log2Dim>::copyFromDense(const CoordBBox& bbox, const DenseT& dense,
1368  bool background, bool tolerance)
1369 {
1370  using DenseValueType = typename DenseT::ValueType;
1371  struct Local {
1372  inline static bool toBool(const DenseValueType& v) { return !math::isZero(v); }
1373  };
1374 
1375  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1376  const Coord& min = dense.bbox().min();
1377  const DenseValueType* s0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // source
1378  const Int32 n0 = bbox.min()[2] & (DIM-1u);
1379  for (Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1; x < ex; ++x) {
1380  const DenseValueType* s1 = s0 + xStride * (x - min[0]);
1381  const Int32 n1 = n0 + ((x & (DIM-1u)) << 2*LOG2DIM);
1382  for (Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1; y < ey; ++y) {
1383  const DenseValueType* s2 = s1 + yStride * (y - min[1]);
1384  Int32 n2 = n1 + ((y & (DIM-1u)) << LOG2DIM);
1385  for (Int32 z = bbox.min()[2], ez = bbox.max()[2]+1; z < ez; ++z, ++n2, s2 += zStride) {
1386  // Note: if tolerance is true (i.e., 1), then all boolean values compare equal.
1387  if (tolerance || (background == Local::toBool(*s2))) {
1388  mBuffer.mData.set(n2, background);
1389  } else {
1390  mBuffer.mData.set(n2, Local::toBool(*s2));
1391  }
1392  }
1393  }
1394  }
1395 }
1396 
1397 
1399 
1400 
1401 template<Index Log2Dim>
1402 template<typename CombineOp>
1403 inline void
1405 {
1406  CombineArgs<bool> args;
1407  for (Index i = 0; i < SIZE; ++i) {
1408  bool result = false, aVal = mBuffer.mData.isOn(i), bVal = other.mBuffer.mData.isOn(i);
1409  op(args.setARef(aVal)
1410  .setAIsActive(aVal)
1411  .setBRef(bVal)
1412  .setBIsActive(bVal)
1413  .setResultRef(result));
1414  mBuffer.mData.set(i, result);
1415  }
1416 }
1417 
1418 
1419 template<Index Log2Dim>
1420 template<typename CombineOp>
1421 inline void
1422 LeafNode<ValueMask, Log2Dim>::combine(bool value, bool valueIsActive, CombineOp& op)
1423 {
1424  CombineArgs<bool> args;
1425  args.setBRef(value).setBIsActive(valueIsActive);
1426  for (Index i = 0; i < SIZE; ++i) {
1427  bool result = false, aVal = mBuffer.mData.isOn(i);
1428  op(args.setARef(aVal)
1429  .setAIsActive(aVal)
1430  .setResultRef(result));
1431  mBuffer.mData.set(i, result);
1432  }
1433 }
1434 
1435 
1437 
1438 
1439 template<Index Log2Dim>
1440 template<typename CombineOp, typename OtherType>
1441 inline void
1442 LeafNode<ValueMask, Log2Dim>::combine2(const LeafNode& other, const OtherType& value,
1443  bool valueIsActive, CombineOp& op)
1444 {
1446  args.setBRef(value).setBIsActive(valueIsActive);
1447  for (Index i = 0; i < SIZE; ++i) {
1448  bool result = false, aVal = other.mBuffer.mData.isOn(i);
1449  op(args.setARef(aVal)
1450  .setAIsActive(aVal)
1451  .setResultRef(result));
1452  mBuffer.mData.set(i, result);
1453  }
1454 }
1455 
1456 
1457 template<Index Log2Dim>
1458 template<typename CombineOp, typename OtherNodeT>
1459 inline void
1460 LeafNode<ValueMask, Log2Dim>::combine2(bool value, const OtherNodeT& other,
1461  bool valueIsActive, CombineOp& op)
1462 {
1464  args.setARef(value).setAIsActive(valueIsActive);
1465  for (Index i = 0; i < SIZE; ++i) {
1466  bool result = false, bVal = other.mBuffer.mData.isOn(i);
1467  op(args.setBRef(bVal)
1468  .setBIsActive(bVal)
1469  .setResultRef(result));
1470  mBuffer.mData.set(i, result);
1471  }
1472 }
1473 
1474 
1475 template<Index Log2Dim>
1476 template<typename CombineOp, typename OtherNodeT>
1477 inline void
1478 LeafNode<ValueMask, Log2Dim>::combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp& op)
1479 {
1481  for (Index i = 0; i < SIZE; ++i) {
1482  bool result = false, b0Val = b0.mBuffer.mData.isOn(i), b1Val = b1.mBuffer.mData.isOn(i);
1483  op(args.setARef(b0Val)
1484  .setAIsActive(b0Val)
1485  .setBRef(b1Val)
1486  .setBIsActive(b1Val)
1487  .setResultRef(result));
1488  mBuffer.mData.set(i, result);
1489  }
1490 }
1491 
1492 
1494 
1495 template<Index Log2Dim>
1496 template<typename BBoxOp>
1497 inline void
1499 {
1500  if (op.template descent<LEVEL>()) {
1501  for (ValueOnCIter i=this->cbeginValueOn(); i; ++i) {
1502  op.template operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), 1));
1503  }
1504  } else {
1505  op.template operator()<LEVEL>(this->getNodeBoundingBox());
1506  }
1507 }
1508 
1509 
1510 template<Index Log2Dim>
1511 template<typename VisitorOp>
1512 inline void
1514 {
1515  doVisit<LeafNode, VisitorOp, ChildAllIter>(*this, op);
1516 }
1517 
1518 
1519 template<Index Log2Dim>
1520 template<typename VisitorOp>
1521 inline void
1523 {
1524  doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*this, op);
1525 }
1526 
1527 
1528 template<Index Log2Dim>
1529 template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
1530 inline void
1531 LeafNode<ValueMask, Log2Dim>::doVisit(NodeT& self, VisitorOp& op)
1532 {
1533  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
1534  op(iter);
1535  }
1536 }
1537 
1538 
1540 
1541 
1542 template<Index Log2Dim>
1543 template<typename OtherLeafNodeType, typename VisitorOp>
1544 inline void
1545 LeafNode<ValueMask, Log2Dim>::visit2Node(OtherLeafNodeType& other, VisitorOp& op)
1546 {
1547  doVisit2Node<LeafNode, OtherLeafNodeType, VisitorOp, ChildAllIter,
1548  typename OtherLeafNodeType::ChildAllIter>(*this, other, op);
1549 }
1550 
1551 
1552 template<Index Log2Dim>
1553 template<typename OtherLeafNodeType, typename VisitorOp>
1554 inline void
1555 LeafNode<ValueMask, Log2Dim>::visit2Node(OtherLeafNodeType& other, VisitorOp& op) const
1556 {
1557  doVisit2Node<const LeafNode, OtherLeafNodeType, VisitorOp, ChildAllCIter,
1558  typename OtherLeafNodeType::ChildAllCIter>(*this, other, op);
1559 }
1560 
1561 
1562 template<Index Log2Dim>
1563 template<
1564  typename NodeT,
1565  typename OtherNodeT,
1566  typename VisitorOp,
1567  typename ChildAllIterT,
1568  typename OtherChildAllIterT>
1569 inline void
1570 LeafNode<ValueMask, Log2Dim>::doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp& op)
1571 {
1572  // Allow the two nodes to have different ValueTypes, but not different dimensions.
1573  static_assert(OtherNodeT::SIZE == NodeT::SIZE,
1574  "can't visit nodes of different sizes simultaneously");
1575  static_assert(OtherNodeT::LEVEL == NodeT::LEVEL,
1576  "can't visit nodes at different tree levels simultaneously");
1577 
1578  ChildAllIterT iter = self.beginChildAll();
1579  OtherChildAllIterT otherIter = other.beginChildAll();
1580 
1581  for ( ; iter && otherIter; ++iter, ++otherIter) {
1582  op(iter, otherIter);
1583  }
1584 }
1585 
1586 
1588 
1589 
1590 template<Index Log2Dim>
1591 template<typename IterT, typename VisitorOp>
1592 inline void
1593 LeafNode<ValueMask, Log2Dim>::visit2(IterT& otherIter, VisitorOp& op, bool otherIsLHS)
1594 {
1595  doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(*this, otherIter, op, otherIsLHS);
1596 }
1597 
1598 
1599 template<Index Log2Dim>
1600 template<typename IterT, typename VisitorOp>
1601 inline void
1602 LeafNode<ValueMask, Log2Dim>::visit2(IterT& otherIter, VisitorOp& op, bool otherIsLHS) const
1603 {
1604  doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(*this, otherIter, op, otherIsLHS);
1605 }
1606 
1607 
1608 template<Index Log2Dim>
1609 template<
1610  typename NodeT,
1611  typename VisitorOp,
1612  typename ChildAllIterT,
1613  typename OtherChildAllIterT>
1614 inline void
1615 LeafNode<ValueMask, Log2Dim>::doVisit2(NodeT& self, OtherChildAllIterT& otherIter,
1616  VisitorOp& op, bool otherIsLHS)
1617 {
1618  if (!otherIter) return;
1619 
1620  if (otherIsLHS) {
1621  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
1622  op(otherIter, iter);
1623  }
1624  } else {
1625  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
1626  op(iter, otherIter);
1627  }
1628  }
1629 }
1630 
1631 } // namespace tree
1632 } // namespace OPENVDB_VERSION_NAME
1633 } // namespace openvdb
1634 
1635 #endif // OPENVDB_TREE_LEAF_NODE_MASK_HAS_BEEN_INCLUDED
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: LeafNodeMask.h:243
static void evalNodeOrigin(Coord &xyz)
Compute the origin of the leaf node that contains the voxel with the given coordinates.
Definition: LeafNodeMask.h:719
int32_t Int32
Definition: openvdb/Types.h:34
Buffer & buffer()
Definition: LeafNodeMask.h:190
ValueIter< MaskDenseIter, const LeafNode, const bool > ValueAllCIter
Definition: LeafNodeMask.h:649
DenseIter< const LeafNode, const ValueType, ChildAll > ChildAllCIter
Definition: LeafNode.h:289
ValueIter< MaskOnIter, const LeafNode, const bool > ValueOnCIter
Definition: LeafNodeMask.h:645
void visit2Node(OtherLeafNodeType &other, VisitorOp &)
Definition: LeafNode.h:1870
void setValuesOn()
Mark all voxels as active but don&#39;t change their values.
Definition: LeafNodeMask.h:268
ValueOffCIter beginValueOff() const
Definition: LeafNodeMask.h:661
void unsetItem(Index pos, const ValueT &val) const
Definition: LeafNodeMask.h:640
void setValueOnly(Index offset, bool val)
Set the value of the voxel at the given offset but don&#39;t change its active state. ...
Definition: LeafNodeMask.h:230
Index64 onLeafVoxelCount() const
Definition: LeafNodeMask.h:124
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:178
bool operator!=(const LeafNode &other) const
Definition: LeafNode.h:195
void denseFill(const CoordBBox &bbox, bool value, bool=false)
Set all voxels within an axis-aligned box to the specified value.
Definition: LeafNodeMask.h:286
Buffer mBuffer
Bitmask representing the values AND state of voxels.
Definition: LeafNodeMask.h:733
const NodeMaskType & valueMask() const
Definition: LeafNode.h:869
const bool & getLastValue() const
Return a const reference to the last entry in the buffer.
Definition: LeafNodeMask.h:400
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information. An additional level argument is pro...
Definition: LeafNode.h:1823
static Index dim()
Return the number of voxels in each dimension.
Definition: LeafNodeMask.h:102
Definition: NodeMasks.h:270
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
ValueIter< MaskOffIter, const LeafNode, const bool > ValueOffCIter
Definition: LeafNodeMask.h:647
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: LeafNode.h:1139
ChildOnCIter cbeginChildOn() const
Definition: LeafNodeMask.h:679
void setActiveState(Index offset, bool on)
Set the active state of the voxel at the given offset but don&#39;t change its value. ...
Definition: LeafNodeMask.h:225
const NodeMaskType & getValueMask() const
Definition: LeafNode.h:867
ChildOffCIter cbeginChildOff() const
Definition: LeafNodeMask.h:682
void setValueMask(const NodeMaskType &mask)
Definition: LeafNodeMask.h:709
bool probeValue(const Coord &xyz, ValueType &val) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:1079
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: LeafNode.h:1038
ChildAllCIter beginChildAll() const
Definition: LeafNode.h:320
DenseIter(const MaskDenseIter &iter, NodeT *parent)
Definition: LeafNodeMask.h:627
const NodeMaskType & getValueMask() const
Definition: LeafNodeMask.h:706
bool isDense() const
Return true if this node only contains active voxels.
Definition: LeafNodeMask.h:132
ChildAllIter endChildAll()
Definition: LeafNodeMask.h:697
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: openvdb/Types.h:481
Index64 offVoxelCount() const
Return the number of inactive voxels.
Definition: LeafNodeMask.h:123
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:334
static void getNodeLog2Dims(std::vector< Index > &dims)
Append the Log2Dim of this LeafNode to the specified vector.
Definition: LeafNodeMask.h:110
Index64 onVoxelCount() const
Return the number of active voxels.
Definition: LeafNodeMask.h:121
const LeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNodeMask.h:560
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: LeafNode.h:411
GridType::Ptr clip(const GridType &grid, const BBoxd &bbox, bool keepInterior=true)
Clip the given grid against a world-space bounding box and return a new grid containing the result...
Definition: Clip.h:348
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: LeafNode.h:1052
static const Index DIM
Definition: LeafNode.h:50
ChildOffIter beginChildOff()
Definition: LeafNodeMask.h:684
ValueOnCIter beginValueOn() const
Definition: LeafNodeMask.h:658
void topologyUnion(const LeafNode< OtherType, Log2Dim > &other)
Union this node&#39;s set of active values with the active values of the other node, whose ValueType may ...
Definition: LeafNode.h:1681
bool isChildMaskOn(Index) const
Definition: LeafNodeMask.h:710
void modifyItem(Index n, const ModifyOp &op) const
Definition: LeafNodeMask.h:603
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: LeafNodeMask.h:357
void setValueOn(Index offset)
Mark the voxel at the given offset as active but don&#39;t change its value.
Definition: LeafNodeMask.h:245
ValueOnCIter cbeginValueOn() const
Definition: LeafNodeMask.h:657
Index medianOn(ValueType &value, ValueType *tmp=nullptr) const
Computes the median value of all the active voxels in this node.
Definition: LeafNode.h:1531
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:1469
ValueIter< MaskOnIter, LeafNode, const bool > ValueOnIter
Definition: LeafNodeMask.h:644
const bool & getValue() const
Definition: LeafNodeMask.h:594
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:37
ChildAllCIter cendChildAll() const
Definition: LeafNodeMask.h:695
LeafNode specialization for values of type ValueMask that encodes both the active states and the bool...
Definition: LeafNodeMask.h:30
void addTileAndCache(Index, const Coord &, const ValueType &, bool, AccessorT &)
Definition: LeafNode.h:1599
void readBuffers(std::istream &is, bool fromHalf=false)
Read buffers from a stream.
Definition: LeafNode.h:1322
static Index numValues()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNodeMask.h:106
OffIterator beginOff() const
Definition: NodeMasks.h:354
void swap(Buffer &other)
Exchange this node&#39;s data buffer with the given data buffer without changing the active states of the...
Definition: LeafNodeMask.h:188
void visit(VisitorOp &)
Definition: LeafNode.h:1838
void writeTopology(std::ostream &os, bool toHalf=false) const
Write out just the topology.
Definition: LeafNode.h:1294
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: openvdb/Types.h:483
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:29
ValueOnCIter cendValueOn() const
Definition: LeafNodeMask.h:667
void setValueOnly(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates but don&#39;t change its active state.
Definition: LeafNode.h:1121
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:103
bool probeValueAndCache(const Coord &xyz, bool &val, AccessorT &) const
Return true if the voxel at the given coordinates is active and return the voxel value in val...
Definition: LeafNodeMask.h:383
bool operator!=(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Inequality operator, does exact floating point comparisons.
Definition: Vec3.h:479
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:307
void setValuesOff()
Mark all voxels as inactive but don&#39;t change their values.
Definition: LeafNodeMask.h:270
LeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNodeMask.h:546
bool isAllocated() const
Return true if memory for this node&#39;s buffer has been allocated.
Definition: LeafNodeMask.h:136
void setValue(const Coord &xyz, bool val)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: LeafNodeMask.h:250
NodeT * stealNode(const Coord &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:525
const Coord & origin() const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNode.h:172
ValueOffCIter cbeginValueOff() const
Definition: LeafNodeMask.h:660
DenseIter< const LeafNode, const bool > ChildAllCIter
Definition: LeafNodeMask.h:655
ValueAllCIter beginValueAll() const
Definition: LeafNodeMask.h:664
ChildOnIter endChildOn()
Definition: LeafNodeMask.h:691
SharedPtr< LeafNodeType > Ptr
Definition: LeafNodeMask.h:38
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don&#39;t change its value.
Definition: LeafNode.h:1113
ValueAllCIter endValueAll() const
Definition: LeafNodeMask.h:674
DenseIter< LeafNode, ValueType, ChildAll > ChildAllIter
Definition: LeafNode.h:288
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNodeMask.h:615
ValueOnIter endValueOn()
Definition: LeafNodeMask.h:669
uint64_t Index64
Definition: openvdb/Types.h:31
Definition: openvdb/Types.h:368
ChildOnCIter cendChildOn() const
Definition: LeafNodeMask.h:689
static bool hasActiveTiles()
Return false since leaf nodes never contain tiles.
Definition: LeafNodeMask.h:278
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNodeMask.h:273
void setValueOnlyAndCache(const Coord &xyz, bool val, AccessorT &)
Change the value of the voxel at the given coordinates but preserve its state.
Definition: LeafNodeMask.h:343
void modifyValue(const ModifyOp &op) const
Definition: LeafNodeMask.h:606
Definition: openvdb/Types.h:89
ChildOnCIter beginChildOn() const
Definition: LeafNodeMask.h:680
void setValue(bool value) const
Definition: LeafNodeMask.h:599
ValueAllCIter cendValueAll() const
Definition: LeafNodeMask.h:673
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: LeafNodeMask.h:275
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:114
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:94
void setValueMaskOff(Index n)
Definition: LeafNodeMask.h:716
void merge(const LeafNode &)
Definition: LeafNode.h:1632
ChildOffCIter beginChildOff() const
Definition: LeafNodeMask.h:683
void getOrigin(Int32 &x, Int32 &y, Int32 &z) const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNodeMask.h:160
const NodeT * probeConstNode(const Coord &) const
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:529
static void doVisit2(NodeT &self, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: LeafNode.h:1942
ValueIter< MaskDenseIter, LeafNode, const bool > ValueAllIter
Definition: LeafNodeMask.h:648
ValueAllIter endValueAll()
Definition: LeafNodeMask.h:675
ChildOnCIter endChildOn() const
Definition: LeafNodeMask.h:690
bool allocate()
Allocate memory for this node&#39;s buffer if it has not already been allocated.
Definition: LeafNodeMask.h:140
Index medianOff(ValueType &value, ValueType *tmp=nullptr) const
Computes the median value of all the inactive voxels in this node.
Definition: LeafNode.h:1555
typename NodeMaskType::DenseIterator MaskDenseIter
Definition: LeafNodeMask.h:580
ValueOnCIter cbeginValueOn() const
Definition: LeafNode.h:291
typename std::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:184
const NodeMaskType & valueMask() const
Definition: LeafNodeMask.h:707
bool isChildMaskOff() const
Definition: LeafNodeMask.h:712
ValueOffCIter endValueOff() const
Definition: LeafNodeMask.h:671
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:328
void addLeaf(LeafNode *)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:521
LeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNodeMask.h:543
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Definition: LeafNode.h:1451
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:471
ChildAllCIter endChildAll() const
Definition: LeafNodeMask.h:696
Definition: openvdb/Exceptions.h:13
Definition: openvdb/Types.h:369
ValueIter< MaskOffIter, LeafNode, const bool > ValueOffIter
Definition: LeafNodeMask.h:646
void negate()
Invert the bits of the voxels, i.e. states and values.
Definition: LeafNodeMask.h:441
Definition: PointDataGrid.h:170
Definition: NodeMasks.h:239
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
SIMD Intrinsic Headers.
Definition: Platform.h:105
typename NodeMaskType::OffIterator MaskOffIter
Definition: LeafNodeMask.h:579
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNodeMask.h:130
ValueOffIter beginValueOff()
Definition: LeafNodeMask.h:662
ValueOnIter beginValueOn()
Definition: LeafNodeMask.h:659
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNodeMask.h:548
bool isValueMaskOn(Index n) const
Definition: LeafNodeMask.h:702
Index64 memUsage() const
Return the memory in bytes occupied by this node.
Definition: LeafNode.h:1441
const LeafNode * probeConstLeaf(const Coord &) const
Return a const pointer to this node.
Definition: LeafNodeMask.h:561
void writeBuffers(std::ostream &os, bool toHalf=false) const
Write buffers to a stream.
Definition: LeafNode.h:1414
bool isValueMaskOff() const
Definition: LeafNodeMask.h:705
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
Definition: LeafNodeMask.h:152
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
Definition: LeafNode.h:1918
bool isValueMaskOn() const
Definition: LeafNodeMask.h:703
ValueType * mData
Definition: LeafBuffer.h:148
void getOrigin(Coord &origin) const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNodeMask.h:159
ChildOffCIter endChildOff() const
Definition: LeafNodeMask.h:693
void nodeCount(std::vector< Index32 > &) const
no-op
Definition: LeafNodeMask.h:116
static Index32 nonLeafCount()
Return the non-leaf count for this node, which is zero.
Definition: LeafNodeMask.h:118
Library and file format version numbers.
DenseIter< LeafNode, bool > ChildAllIter
Definition: LeafNodeMask.h:654
static Index getChildDim()
Return the dimension of child nodes of this LeafNode, which is one for voxels.
Definition: LeafNodeMask.h:112
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Set the active state of the voxel at the given coordinates without changing its value.
Definition: LeafNodeMask.h:374
OPENVDB_API const void * getGridBackgroundValuePtr(std::ios_base &)
Return a pointer to the background value of the grid currently being read from or written to the give...
void setValueOff(Index offset)
Mark the voxel at the given offset as inactive but don&#39;t change its value.
Definition: LeafNodeMask.h:235
void combine(const LeafNode &other, CombineOp &op)
Definition: LeafNode.h:1722
void getNodes(ArrayT &) const
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:530
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:568
uint32_t Index32
Definition: openvdb/Types.h:30
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNodeMask.h:591
bool isChildMaskOff(Index) const
Definition: LeafNodeMask.h:711
ChildOffCIter cendChildOff() const
Definition: LeafNodeMask.h:692
bool ValueType
Definition: LeafNodeMask.h:35
void setValueOffAndCache(const Coord &xyz, bool value, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as inactive.
Definition: LeafNodeMask.h:348
void topologyIntersection(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Intersect this node&#39;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:1689
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: LeafNode.h:450
static Index getLevel()
Return the level of this node, which by definition is zero for LeafNodes.
Definition: LeafNodeMask.h:108
void topologyDifference(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Difference this node&#39;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:1698
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:429
const LeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNodeMask.h:563
const bool & getValueAndCache(const Coord &xyz, AccessorT &) const
Return the value of the voxel at the given coordinates.
Definition: LeafNodeMask.h:327
void voxelizeActiveTiles(bool=true)
No-op.
Definition: LeafNodeMask.h:449
ValueAllIter beginValueAll()
Definition: LeafNodeMask.h:665
static const Index LOG2DIM
Definition: LeafNode.h:48
ChildIter< MaskOnIter, LeafNode > ChildOnIter
Definition: LeafNodeMask.h:650
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
Definition: LeafNode.h:1431
std::shared_ptr< T > SharedPtr
Definition: openvdb/Types.h:92
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:106
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node&#39;s local origin.
Definition: LeafNodeMask.h:155
static Index64 onTileCount()
Definition: LeafNodeMask.h:126
void combine2(const LeafNode &other, const OtherType &, bool valueIsActive, CombineOp &)
Definition: LeafNode.h:1762
ChildAllCIter cbeginChildAll() const
Definition: LeafNodeMask.h:685
bool getItem(Index pos, void *&child, NonConstValueT &value) const
Definition: LeafNodeMask.h:629
bool isValueMaskOff(Index n) const
Definition: LeafNodeMask.h:704
~LeafNode()
Destructor.
Definition: LeafNode.h:1008
NodeMaskType & getValueMask()
Definition: LeafNodeMask.h:708
typename BaseT::NonConstValueType NonConstValueT
Definition: LeafNodeMask.h:624
NodeT * probeNode(const Coord &)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:527
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:1222
void addLeafAndCache(LeafNode *, AccessorT &)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:523
static Index32 leafCount()
Return the leaf count for this node, which is one.
Definition: LeafNodeMask.h:114
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: LeafNode.h:401
static Index64 offTileCount()
Definition: LeafNodeMask.h:127
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: LeafNodeMask.h:365
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: LeafNodeMask.h:233
static Index getValueLevel(const Coord &)
Return the level (0) at which leaf node values reside.
Definition: LeafNodeMask.h:220
void resetBackground(bool, bool)
no-op since for this temaplte specialization voxel values and states are indistinguishable.
Definition: LeafNodeMask.h:438
ValueAllCIter cbeginValueAll() const
Definition: LeafNodeMask.h:663
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNodeMask.h:332
LeafNode()
Default constructor.
Definition: LeafNode.h:924
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition: LeafNodeMask.h:736
void setValueMaskOn(Index n)
Definition: LeafNodeMask.h:715
static Index log2dim()
Return log2 of the size of the buffer storage.
Definition: LeafNodeMask.h:100
Index64 offLeafVoxelCount() const
Definition: LeafNodeMask.h:125
void copyToDense(const GridOrTreeT &sparse, DenseT &dense, bool serial=false)
Populate a dense grid with the values of voxels from a sparse grid, where the sparse grid intersects ...
Definition: Dense.h:421
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: openvdb/Types.h:542
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1063
ValueOnCIter endValueOn() const
Definition: LeafNodeMask.h:668
void setItem(Index pos, bool value) const
Definition: LeafNodeMask.h:597
ValueOffCIter cendValueOff() const
Definition: LeafNodeMask.h:670
ChildIter< MaskOffIter, LeafNode > ChildOffIter
Definition: LeafNodeMask.h:652
void setValueAndCache(const Coord &xyz, bool val, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as active.
Definition: LeafNodeMask.h:337
void fill(const ValueType &)
Populate this buffer with a constant value.
Definition: LeafBuffer.h:247
static const Index NUM_VALUES
Definition: LeafNode.h:51
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:146
ChildIter< MaskOnIter, const LeafNode > ChildOnCIter
Definition: LeafNodeMask.h:651
typename NodeMaskType::OnIterator MaskOnIter
Definition: LeafNodeMask.h:578
ChildOnIter beginChildOn()
Definition: LeafNodeMask.h:681
ChildAllCIter beginChildAll() const
Definition: LeafNodeMask.h:686
static const Index SIZE
Definition: LeafNode.h:53
const Buffer & buffer() const
Definition: LeafNodeMask.h:189
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNodeMask.h:565
ValueOffIter endValueOff()
Definition: LeafNodeMask.h:672
static void doVisit2Node(NodeT &self, OtherNodeT &other, VisitorOp &)
Definition: LeafNode.h:1895
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:452
Index32 Index
Definition: openvdb/Types.h:32
ValueType medianAll(ValueType *tmp=nullptr) const
Computes the median value of all the active AND inactive voxels in this node.
Definition: LeafNode.h:1513
Tag dispatch class that distinguishes constructors during file input.
Definition: openvdb/Types.h:548
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: openvdb/Types.h:428
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: LeafNode.h:1477
ValueType combine(const ValueType &v0, const ValueType &v1, const ValueType &v2, const openvdb::Vec3d &w)
Combine different value types.
Definition: AttributeTransferUtil.h:140
ChildIter< MaskOffIter, const LeafNode > ChildOffCIter
Definition: LeafNodeMask.h:653
void addTile(Index level, const Coord &, const ValueType &, bool)
Definition: LeafNode.h:1582
ChildAllIter beginChildAll()
Definition: LeafNodeMask.h:687
void readTopology(std::istream &is, bool fromHalf=false)
Read in just the topology.
Definition: LeafNode.h:1286
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:1249
Definition: NodeMasks.h:208
LeafNode * probeLeaf(const Coord &)
Return a pointer to this node.
Definition: LeafNodeMask.h:544
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: LeafNode.h:1028
static Index size()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNodeMask.h:104
void setValueMask(Index n, bool on)
Definition: LeafNodeMask.h:714
static const Index LEVEL
Definition: LeafNode.h:54
const bool & getFirstValue() const
Return a const reference to the first entry in the buffer.
Definition: LeafNodeMask.h:396
static Index getValueLevelAndCache(const Coord &, AccessorT &)
Return the LEVEL (=0) at which leaf node values reside.
Definition: LeafNodeMask.h:391
bool isInactive() const
Return true if all of this node&#39;s values are inactive.
Definition: LeafNodeMask.h:434
void stealNodes(ArrayT &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:531
ChildOffIter endChildOff()
Definition: LeafNodeMask.h:694
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:1179
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
Definition: LeafNode.h:166
std::string str() const
Return a string representation of this node.
Definition: LeafNode.h:1015
static void doVisit(NodeT &, VisitorOp &)
Definition: LeafNode.h:1856
const bool & getItem(Index pos) const
Definition: LeafNodeMask.h:593