OpenVDB  12.0.0
LeafNodeBool.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #ifndef OPENVDB_TREE_LEAF_NODE_BOOL_HAS_BEEN_INCLUDED
5 #define OPENVDB_TREE_LEAF_NODE_BOOL_HAS_BEEN_INCLUDED
6 
7 #include <openvdb/Types.h>
8 #include <openvdb/io/Compression.h> // for io::readData(), etc.
9 #include <openvdb/util/Assert.h>
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 
26 /// @brief LeafNode specialization for values of type bool that stores both
27 /// the active states and the values of (2^Log2Dim)^3 voxels as bit masks
28 template<Index Log2Dim>
29 class LeafNode<bool, Log2Dim>
30 {
31 public:
33  using BuildType = bool;
34  using ValueType = bool;
38 
39  // These static declarations must be on separate lines to avoid VC9 compiler errors.
40  static const Index LOG2DIM = Log2Dim; // needed by parent nodes
41  static const Index TOTAL = Log2Dim; // needed by parent nodes
42  static const Index DIM = 1 << TOTAL; // dimension along one coordinate direction
43  static const Index NUM_VALUES = 1 << 3 * Log2Dim;
44  static const Index NUM_VOXELS = NUM_VALUES; // total number of voxels represented by this node
45  static const Index SIZE = NUM_VALUES;
46  static const Index LEVEL = 0; // level 0 = leaf
47 
48  /// @brief ValueConverter<T>::Type is the type of a LeafNode having the same
49  /// dimensions as this node but a different value type, T.
50  template<typename ValueType>
51  struct ValueConverter { using Type = LeafNode<ValueType, Log2Dim>; };
52 
53  /// @brief SameConfiguration<OtherNodeType>::value is @c true if and only if
54  /// OtherNodeType is the type of a LeafNode with the same dimensions as this node.
55  template<typename OtherNodeType>
56  struct SameConfiguration {
58  };
59 
60 
61  /// Default constructor
62  LeafNode();
63 
64  /// Constructor
65  /// @param xyz the coordinates of a voxel that lies within the node
66  /// @param value the initial value for all of this node's voxels
67  /// @param active the active state to which to initialize all voxels
68  explicit LeafNode(const Coord& xyz, bool value = false, bool active = false);
69 
70  /// "Partial creation" constructor used during file input
71  LeafNode(PartialCreate, const Coord& xyz, bool value = false, bool active = false);
72 
73  /// Deep copy constructor
74  LeafNode(const LeafNode&);
75 
76  /// Deep assignment operator
77  LeafNode& operator=(const LeafNode&) = default;
78 
79  /// Value conversion copy constructor
80  template<typename OtherValueType>
81  explicit LeafNode(const LeafNode<OtherValueType, Log2Dim>& other);
82 
83  /// @brief Deprecated topology copy constructor
84  /// @note This constructor initialises the bool buffer to the ValueMask
85  /// states (i.e. value will be true if the active state is on and
86  /// vice-versa). This is not really a "TopologyCopy" and is therefor
87  /// deprecated. Use the explicit mask/buffer constructor instead:
88  /// @code
89  /// // build new leaf node with the mask of 'a', but with the mask of
90  /// // 'b' as the the new value buffer.
91  /// const LeafNode a = ... ;
92  /// const LeafNode b = ... ;
93  /// const LeafNode copy(a.origin(), /*mask=*/a.getValueMask(),
94  /// /*buff=*/b.getValueMask());
95  /// @endcode
96  template<typename ValueType>
97  OPENVDB_DEPRECATED_MESSAGE("Use LeafNodeBool component constructor.")
98  LeafNode(const LeafNode<ValueType, Log2Dim>& other, TopologyCopy);
99 
100  /// @brief Construct a LeafNodeBool with its individual components
101  /// @param xyz Leaf origin
102  /// @param mask The ValueMask to copy
103  /// @param buff The LeafBuffer to copy (also constructable from a ValueMask)
104  /// @param trans Transient data (ignored until ABI 9)
105  LeafNode(const Coord& xyz,
106  const NodeMaskType& mask,
107  const Buffer& buff,
108  const Index32 trans = 0);
109 
110  //@{
111  /// @brief Topology copy constructors
112  template<typename ValueType>
113  LeafNode(const LeafNode<ValueType, Log2Dim>& other, bool offValue, bool onValue, TopologyCopy);
114  template<typename ValueType>
115  LeafNode(const LeafNode<ValueType, Log2Dim>& other, bool background, TopologyCopy);
116  //@}
117 
118  /// Destructor
119  ~LeafNode();
120 
121  //
122  // Statistics
123  //
124  /// Return log2 of the size of the buffer storage.
125  static Index log2dim() { return Log2Dim; }
126  /// Return the number of voxels in each dimension.
127  static Index dim() { return DIM; }
128  static Index size() { return SIZE; }
129  static Index numValues() { return SIZE; }
130  static Index getLevel() { return LEVEL; }
131  static void getNodeLog2Dims(std::vector<Index>& dims) { dims.push_back(Log2Dim); }
132  static Index getChildDim() { return 1; }
133 
134  static Index64 leafCount() { return 1; }
135  /// no-op
136  void nodeCount(std::vector<Index64> &) const {}
137  OPENVDB_DEPRECATED_MESSAGE("Use input type std::vector<Index64> for nodeCount.")
138  void nodeCount(std::vector<Index32> &) const {}
139  static Index64 nonLeafCount() { return 0; }
140 
141  /// Return the number of active voxels.
142  Index64 onVoxelCount() const { return mValueMask.countOn(); }
143  /// Return the number of inactive voxels.
144  Index64 offVoxelCount() const { return mValueMask.countOff(); }
145  Index64 onLeafVoxelCount() const { return onVoxelCount(); }
146  Index64 offLeafVoxelCount() const { return offVoxelCount(); }
147  static Index64 onTileCount() { return 0; }
148  static Index64 offTileCount() { return 0; }
149 
150  /// Return @c true if this node has no active voxels.
151  bool isEmpty() const { return mValueMask.isOff(); }
152  /// Return @c true if this node only contains active voxels.
153  bool isDense() const { return mValueMask.isOn(); }
154  /// @brief Return @c true if memory for this node's buffer has been allocated.
155  /// @details Currently, boolean leaf nodes don't support partial creation,
156  /// so this always returns @c true.
157  bool isAllocated() const { return true; }
158  /// @brief Allocate memory for this node's buffer if it has not already been allocated.
159  /// @details Currently, boolean leaf nodes don't support partial creation,
160  /// so this has no effect.
161  bool allocate() { return true; }
162 
163  /// Return the memory in bytes occupied by this node.
164  Index64 memUsage() const;
165  Index64 memUsageIfLoaded() const;
166 
167  /// Expand the given bounding box so that it includes this leaf node's active voxels.
168  /// If visitVoxels is false this LeafNode will be approximated as dense, i.e. with all
169  /// voxels active. Else the individual active voxels are visited to produce a tight bbox.
170  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
171 
172  /// @brief Return the bounding box of this node, i.e., the full index space
173  /// spanned by this leaf node.
174  CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); }
175 
176  /// Set the grid index coordinates of this node's local origin.
177  void setOrigin(const Coord& origin) { mOrigin = origin; }
178  //@{
179  /// Return the grid index coordinates of this node's local origin.
180  const Coord& origin() const { return mOrigin; }
181  void getOrigin(Coord& origin) const { origin = mOrigin; }
182  void getOrigin(Int32& x, Int32& y, Int32& z) const { mOrigin.asXYZ(x, y, z); }
183  //@}
184 
185  /// Return the linear table offset of the given global or local coordinates.
186  static Index coordToOffset(const Coord& xyz);
187  /// @brief Return the local coordinates for a linear table offset,
188  /// where offset 0 has coordinates (0, 0, 0).
189  static Coord offsetToLocalCoord(Index n);
190  /// Return the global coordinates for a linear table offset.
191  Coord offsetToGlobalCoord(Index n) const;
192 
193  /// Return the transient data value.
194  Index32 transientData() const { return mTransientData; }
195  /// Set the transient data value.
196  void setTransientData(Index32 transientData) { mTransientData = transientData; }
197 
198  /// Return a string representation of this node.
199  std::string str() const;
200 
201  /// @brief Return @c true if the given node (which may have a different @c ValueType
202  /// than this node) has the same active value topology as this node.
203  template<typename OtherType, Index OtherLog2Dim>
204  bool hasSameTopology(const LeafNode<OtherType, OtherLog2Dim>* other) const;
205 
206  /// Check for buffer equivalence by value.
207  bool operator==(const LeafNode&) const;
208  bool operator!=(const LeafNode&) const;
209 
210  //
211  // Buffer management
212  //
213  /// @brief Exchange this node's data buffer with the given data buffer
214  /// without changing the active states of the values.
215  void swap(Buffer& other) { mBuffer.swap(other); }
216  const Buffer& buffer() const { return mBuffer; }
217  Buffer& buffer() { return mBuffer; }
218 
219  //
220  // I/O methods
221  //
222  /// Read in just the topology.
223  void readTopology(std::istream&, bool fromHalf = false);
224  /// Write out just the topology.
225  void writeTopology(std::ostream&, bool toHalf = false) const;
226 
227  /// Read in the topology and the origin.
228  void readBuffers(std::istream&, bool fromHalf = false);
229  void readBuffers(std::istream& is, const CoordBBox&, bool fromHalf = false);
230  /// Write out the topology and the origin.
231  void writeBuffers(std::ostream&, bool toHalf = false) const;
232 
233  //
234  // Accessor methods
235  //
236  /// Return the value of the voxel at the given coordinates.
237  const bool& getValue(const Coord& xyz) const;
238  /// Return the value of the voxel at the given offset.
239  const bool& getValue(Index offset) const;
240 
241  /// @brief Return @c true if the voxel at the given coordinates is active.
242  /// @param xyz the coordinates of the voxel to be probed
243  /// @param[out] val the value of the voxel at the given coordinates
244  bool probeValue(const Coord& xyz, bool& val) const;
245  /// @brief Return @c true if the voxel at the given offset is active.
246  /// @param offset the linear offset of the voxel to be probed
247  /// @param[out] val the value of the voxel at the given coordinates
248  bool probeValue(Index offset, bool& val) const;
249 
250  /// Return the level (0) at which leaf node values reside.
251  static Index getValueLevel(const Coord&) { return LEVEL; }
252 
253  /// Set the active state of the voxel at the given coordinates but don't change its value.
254  void setActiveState(const Coord& xyz, bool on);
255  /// Set the active state of the voxel at the given offset but don't change its value.
256  void setActiveState(Index offset, bool on) { OPENVDB_ASSERT(offset<SIZE); mValueMask.set(offset, on); }
257 
258  /// Set the value of the voxel at the given coordinates but don't change its active state.
259  void setValueOnly(const Coord& xyz, bool val);
260  /// Set the value of the voxel at the given offset but don't change its active state.
261  void setValueOnly(Index offset, bool val) { OPENVDB_ASSERT(offset<SIZE); mBuffer.setValue(offset,val); }
262 
263  /// Mark the voxel at the given coordinates as inactive but don't change its value.
264  void setValueOff(const Coord& xyz) { mValueMask.setOff(this->coordToOffset(xyz)); }
265  /// Mark the voxel at the given offset as inactive but don't change its value.
266  void setValueOff(Index offset) { OPENVDB_ASSERT(offset < SIZE); mValueMask.setOff(offset); }
267 
268  /// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
269  void setValueOff(const Coord& xyz, bool val);
270  /// Set the value of the voxel at the given offset and mark the voxel as inactive.
271  void setValueOff(Index offset, bool val);
272 
273  /// Mark the voxel at the given coordinates as active but don't change its value.
274  void setValueOn(const Coord& xyz) { mValueMask.setOn(this->coordToOffset(xyz)); }
275  /// Mark the voxel at the given offset as active but don't change its value.
276  void setValueOn(Index offset) { OPENVDB_ASSERT(offset < SIZE); mValueMask.setOn(offset); }
277 
278  /// Set the value of the voxel at the given coordinates and mark the voxel as active.
279  void setValueOn(const Coord& xyz, bool val);
280  /// Set the value of the voxel at the given coordinates and mark the voxel as active.
281  void setValue(const Coord& xyz, bool val) { this->setValueOn(xyz, val); }
282  /// Set the value of the voxel at the given offset and mark the voxel as active.
283  void setValueOn(Index offset, bool val);
284 
285  /// @brief Apply a functor to the value of the voxel at the given offset
286  /// and mark the voxel as active.
287  template<typename ModifyOp>
288  void modifyValue(Index offset, const ModifyOp& op);
289  /// @brief Apply a functor to the value of the voxel at the given coordinates
290  /// and mark the voxel as active.
291  template<typename ModifyOp>
292  void modifyValue(const Coord& xyz, const ModifyOp& op);
293 
294  /// Apply a functor to the voxel at the given coordinates.
295  template<typename ModifyOp>
296  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op);
297 
298  /// Mark all voxels as active but don't change their values.
299  void setValuesOn() { mValueMask.setOn(); }
300  /// Mark all voxels as inactive but don't change their values.
301  void setValuesOff() { mValueMask.setOff(); }
302 
303  /// Return @c true if the voxel at the given coordinates is active.
304  bool isValueOn(const Coord& xyz) const { return this->isValueOn(this->coordToOffset(xyz)); }
305  /// Return @c true if the voxel at the given offset is active.
306  bool isValueOn(Index offset) const { OPENVDB_ASSERT(offset < SIZE); return mValueMask.isOn(offset); }
307  /// Return @c true if the voxel at the given coordinates is inactive.
308  bool isValueOff(const Coord& xyz) const { return this->isValueOff(this->coordToOffset(xyz)); }
309  /// Return @c true if the voxel at the given offset is inactive.
310  bool isValueOff(Index offset) const { OPENVDB_ASSERT(offset < SIZE); return mValueMask.isOff(offset); }
311 
312  /// Return @c false since leaf nodes never contain tiles.
313  static bool hasActiveTiles() { return false; }
314 
315  /// Set all voxels that lie outside the given axis-aligned box to the background.
316  void clip(const CoordBBox&, bool background);
317 
318  /// Set all voxels within an axis-aligned box to the specified value and active state.
319  void fill(const CoordBBox& bbox, bool value, bool active = true);
320  /// Set all voxels within an axis-aligned box to the specified value and active state.
321  void denseFill(const CoordBBox& bbox, bool val, bool on = true) { this->fill(bbox, val, on); }
322 
323  /// Set all voxels to the specified value but don't change their active states.
324  void fill(const bool& value);
325  /// Set all voxels to the specified value and active state.
326  void fill(const bool& value, bool active);
327 
328  /// @brief Copy into a dense grid the values of the voxels that lie within
329  /// a given bounding box.
330  ///
331  /// @param bbox inclusive bounding box of the voxels to be copied into the dense grid
332  /// @param dense dense grid with a stride in @e z of one (see tools::Dense
333  /// in tools/Dense.h for the required API)
334  ///
335  /// @note @a bbox is assumed to be identical to or contained in the coordinate domains
336  /// of both the dense grid and this node, i.e., no bounds checking is performed.
337  /// @note Consider using tools::CopyToDense in tools/Dense.h
338  /// instead of calling this method directly.
339  template<typename DenseT>
340  void copyToDense(const CoordBBox& bbox, DenseT& dense) const;
341 
342  /// @brief Copy from a dense grid into this node the values of the voxels
343  /// that lie within a given bounding box.
344  /// @details Only values that are different (by more than the given tolerance)
345  /// from the background value will be active. Other values are inactive
346  /// and truncated to the background value.
347  ///
348  /// @param bbox inclusive bounding box of the voxels to be copied into this node
349  /// @param dense dense grid with a stride in @e z of one (see tools::Dense
350  /// in tools/Dense.h for the required API)
351  /// @param background background value of the tree that this node belongs to
352  /// @param tolerance tolerance within which a value equals the background value
353  ///
354  /// @note @a bbox is assumed to be identical to or contained in the coordinate domains
355  /// of both the dense grid and this node, i.e., no bounds checking is performed.
356  /// @note Consider using tools::CopyFromDense in tools/Dense.h
357  /// instead of calling this method directly.
358  template<typename DenseT>
359  void copyFromDense(const CoordBBox& bbox, const DenseT& dense, bool background, bool tolerance);
360 
361  /// @brief Return the value of the voxel at the given coordinates.
362  /// @note Used internally by ValueAccessor.
363  template<typename AccessorT>
364  const bool& getValueAndCache(const Coord& xyz, AccessorT&) const {return this->getValue(xyz);}
365 
366  /// @brief Return @c true if the voxel at the given coordinates is active.
367  /// @note Used internally by ValueAccessor.
368  template<typename AccessorT>
369  bool isValueOnAndCache(const Coord& xyz, AccessorT&) const { return this->isValueOn(xyz); }
370 
371  /// @brief Change the value of the voxel at the given coordinates and mark it as active.
372  /// @note Used internally by ValueAccessor.
373  template<typename AccessorT>
374  void setValueAndCache(const Coord& xyz, bool val, AccessorT&) { this->setValueOn(xyz, val); }
375 
376  /// @brief Change the value of the voxel at the given coordinates
377  /// but preserve its state.
378  /// @note Used internally by ValueAccessor.
379  template<typename AccessorT>
380  void setValueOnlyAndCache(const Coord& xyz, bool val, AccessorT&) {this->setValueOnly(xyz,val);}
381 
382  /// @brief Change the value of the voxel at the given coordinates and mark it as inactive.
383  /// @note Used internally by ValueAccessor.
384  template<typename AccessorT>
385  void setValueOffAndCache(const Coord& xyz, bool value, AccessorT&)
386  {
387  this->setValueOff(xyz, value);
388  }
389 
390  /// @brief Apply a functor to the value of the voxel at the given coordinates
391  /// and mark the voxel as active.
392  /// @note Used internally by ValueAccessor.
393  template<typename ModifyOp, typename AccessorT>
394  void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
395  {
396  this->modifyValue(xyz, op);
397  }
398 
399  /// Apply a functor to the voxel at the given coordinates.
400  /// @note Used internally by ValueAccessor.
401  template<typename ModifyOp, typename AccessorT>
402  void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
403  {
404  this->modifyValueAndActiveState(xyz, op);
405  }
406 
407  /// @brief Set the active state of the voxel at the given coordinates
408  /// without changing its value.
409  /// @note Used internally by ValueAccessor.
410  template<typename AccessorT>
411  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&)
412  {
413  this->setActiveState(xyz, on);
414  }
415 
416  /// @brief Return @c true if the voxel at the given coordinates is active
417  /// and return the voxel value in @a val.
418  /// @note Used internally by ValueAccessor.
419  template<typename AccessorT>
420  bool probeValueAndCache(const Coord& xyz, bool& val, AccessorT&) const
421  {
422  return this->probeValue(xyz, val);
423  }
424 
425  /// @brief Return the LEVEL (=0) at which leaf node values reside.
426  /// @note Used internally by ValueAccessor.
427  template<typename AccessorT>
428  static Index getValueLevelAndCache(const Coord&, AccessorT&) { return LEVEL; }
429 
430  /// @brief Return a const reference to the first entry in the buffer.
431  /// @note Since it's actually a reference to a static data member
432  /// it should not be converted to a non-const pointer!
433  const bool& getFirstValue() const { if (mValueMask.isOn(0)) return Buffer::sOn; else return Buffer::sOff; }
434  /// @brief Return a const reference to the last entry in the buffer.
435  /// @note Since it's actually a reference to a static data member
436  /// it should not be converted to a non-const pointer!
437  const bool& getLastValue() const { if (mValueMask.isOn(SIZE-1)) return Buffer::sOn; else return Buffer::sOff; }
438 
439  /// Return @c true if all of this node's voxels have the same active state
440  /// and are equal to within the given tolerance, and return the value in
441  /// @a constValue and the active state in @a state.
442  bool isConstant(bool& constValue, bool& state, bool tolerance = 0) const;
443 
444  /// @brief Computes the median value of all the active and inactive voxels in this node.
445  /// @return The median value.
446  ///
447  /// @details The median for boolean values is defined as the mode
448  /// of the values, i.e. the value that occurs most often.
449  bool medianAll() const;
450 
451  /// @brief Computes the median value of all the active voxels in this node.
452  /// @return The number of active voxels.
453  /// @param value Updated with the median value of all the active voxels.
454  ///
455  /// @details The median for boolean values is defined as the mode
456  /// of the values, i.e. the value that occurs most often.
457  Index medianOn(ValueType &value) const;
458 
459  /// @brief Computes the median value of all the inactive voxels in this node.
460  /// @return The number of inactive voxels.
461  /// @param value Updated with the median value of all the inactive voxels.
462  ///
463  /// @details The median for boolean values is defined as the mode
464  /// of the values, i.e. the value that occurs most often.
465  Index medianOff(ValueType &value) const;
466 
467  /// Return @c true if all of this node's values are inactive.
468  bool isInactive() const { return mValueMask.isOff(); }
469 
470  //
471  // Unsafe methods
472  //
473  // These methods are not in fact unsafe, but are only offered so that
474  // the same methods can be called on both internal nodes and leaf nodes.
475 
476  /// Return the value of the voxel at the given offset.
477  const bool& getValueUnsafe(Index offset) const { return this->getValue(offset); }
478  /// Return true if the voxel at the given offset is active and set value.
479  bool getValueUnsafe(Index offset, bool& value) const { return this->probeValue(offset, value); }
480  /// Set the active state of the voxel at the given offset but don't change its value.
481  void setActiveStateUnsafe(Index offset, bool on) { this->setActiveState(offset, on); }
482  /// Set the value of the voxel at the given coordinates but don't change its active state.
483  void setValueOnlyUnsafe(Index offset, const bool& value) { return this->setValueOnly(offset, value); }
484  /// Mark the voxel at the given offset as active but don't change its value.
485  void setValueOnUnsafe(Index offset) { this->setValueOn(offset); }
486  /// Set the value of the voxel at the given coordinates and mark the voxel as active.
487  void setValueOnUnsafe(Index offset, const bool& value) { this->setValueOn(offset, value); }
488  /// Mark the voxel at the given offset as inactive but don't change its value.
489  void setValueOffUnsafe(Index offset) { this->setValueOff(offset); }
490  /// Set the value of the voxel at the given coordinates and mark the voxel as active.
491  void setValueOffUnsafe(Index offset, const bool& value) { this->setValueOff(offset, value); }
492 
493  void resetBackground(bool oldBackground, bool newBackground);
494 
495  void negate() { mBuffer.mData.toggle(); }
496 
497  template<MergePolicy Policy>
498  void merge(const LeafNode& other, bool bg = false, bool otherBG = false);
499  template<MergePolicy Policy> void merge(bool tileValue, bool tileActive);
500 
501  /// @brief No-op
502  /// @details This function exists only to enable template instantiation.
503  void voxelizeActiveTiles(bool = true) {}
504 
505  /// @brief Union this node's set of active values with the active values
506  /// of the other node, whose @c ValueType may be different. So a
507  /// resulting voxel will be active if either of the original voxels
508  /// were active.
509  ///
510  /// @note This operation modifies only active states, not values.
511  template<typename OtherType>
512  void topologyUnion(const LeafNode<OtherType, Log2Dim>& other, const bool preserveTiles = false);
513 
514  /// @brief Intersect this node's set of active values with the active values
515  /// of the other node, whose @c ValueType may be different. So a
516  /// resulting voxel will be active only if both of the original voxels
517  /// were active.
518  ///
519  /// @details The last dummy argument is required to match the signature
520  /// for InternalNode::topologyIntersection.
521  ///
522  /// @note This operation modifies only active states, not
523  /// values. Also note that this operation can result in all voxels
524  /// being inactive so consider subsequently calling prune.
525  template<typename OtherType>
526  void topologyIntersection(const LeafNode<OtherType, Log2Dim>& other, const bool&);
527 
528  /// @brief Difference this node's set of active values with the active values
529  /// of the other node, whose @c ValueType may be different. So a
530  /// resulting voxel will be active only if the original voxel is
531  /// active in this LeafNode and inactive in the other LeafNode.
532  ///
533  /// @details The last dummy argument is required to match the signature
534  /// for InternalNode::topologyDifference.
535  ///
536  /// @note This operation modifies only active states, not values.
537  /// Also, because it can deactivate all of this node's voxels,
538  /// consider subsequently calling prune.
539  template<typename OtherType>
540  void topologyDifference(const LeafNode<OtherType, Log2Dim>& other, const bool&);
541 
542  template<typename CombineOp>
543  void combine(const LeafNode& other, CombineOp& op);
544  template<typename CombineOp>
545  void combine(bool, bool valueIsActive, CombineOp& op);
546 
547  template<typename CombineOp, typename OtherType /*= bool*/>
548  void combine2(const LeafNode& other, const OtherType&, bool valueIsActive, CombineOp&);
549  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
550  void combine2(bool, const OtherNodeT& other, bool valueIsActive, CombineOp&);
551  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
552  void combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp&);
553 
554  //@{
555  /// This function exists only to enable template instantiation.
556  void prune(const ValueType& /*tolerance*/ = zeroVal<ValueType>()) {}
557  void addLeaf(LeafNode*) {}
558  template<typename AccessorT>
559  void addLeafAndCache(LeafNode*, AccessorT&) {}
560  template<typename NodeT>
561  NodeT* stealNode(const Coord&, const ValueType&, bool) { return nullptr; }
562  template<typename NodeT>
563  NodeT* probeNode(const Coord&) { return nullptr; }
564  template<typename NodeT>
565  const NodeT* probeConstNode(const Coord&) const { return nullptr; }
566  template<typename ArrayT> void getNodes(ArrayT&) const {}
567  template<typename ArrayT> void stealNodes(ArrayT&, const ValueType&, bool) {}
568  //@}
569 
570  void addTile(Index level, const Coord&, bool val, bool active);
571  void addTile(Index offset, bool val, bool active);
572  template<typename AccessorT>
573  void addTileAndCache(Index level, const Coord&, bool val, bool active, AccessorT&);
574 
575  //@{
576  /// @brief Return a pointer to this node.
577  LeafNode* touchLeaf(const Coord&) { return this; }
578  template<typename AccessorT>
579  LeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
580  LeafNode* probeLeaf(const Coord&) { return this; }
581  template<typename AccessorT>
582  LeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
583  template<typename NodeT, typename AccessorT>
584  NodeT* probeNodeAndCache(const Coord&, AccessorT&)
585  {
587  if (!(std::is_same<NodeT, LeafNode>::value)) return nullptr;
588  return reinterpret_cast<NodeT*>(this);
590  }
591  //@}
592  //@{
593  /// @brief Return a @const pointer to this node.
594  const LeafNode* probeLeaf(const Coord&) const { return this; }
595  template<typename AccessorT>
596  const LeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
597  const LeafNode* probeConstLeaf(const Coord&) const { return this; }
598  template<typename AccessorT>
599  const LeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
600  template<typename NodeT, typename AccessorT>
601  const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
602  {
604  if (!(std::is_same<NodeT, LeafNode>::value)) return nullptr;
605  return reinterpret_cast<const NodeT*>(this);
607  }
608  //@}
609 
610  //
611  // Iterators
612  //
613 protected:
617 
618  template<typename MaskIterT, typename NodeT, typename ValueT>
619  struct ValueIter:
620  // Derives from SparseIteratorBase, but can also be used as a dense iterator,
621  // if MaskIterT is a dense mask iterator type.
622  public SparseIteratorBase<MaskIterT, ValueIter<MaskIterT, NodeT, ValueT>, NodeT, ValueT>
623  {
625 
627  ValueIter(const MaskIterT& iter, NodeT* parent): BaseT(iter, parent) {}
628 
629  const bool& getItem(Index pos) const { return this->parent().getValue(pos); }
630  const bool& getValue() const { return this->getItem(this->pos()); }
631 
632  // Note: setItem() can't be called on const iterators.
633  void setItem(Index pos, bool value) const { this->parent().setValueOnly(pos, value); }
634  // Note: setValue() can't be called on const iterators.
635  void setValue(bool value) const { this->setItem(this->pos(), value); }
636 
637  // Note: modifyItem() can't be called on const iterators.
638  template<typename ModifyOp>
639  void modifyItem(Index n, const ModifyOp& op) const { this->parent().modifyValue(n, op); }
640  // Note: modifyValue() can't be called on const iterators.
641  template<typename ModifyOp>
642  void modifyValue(const ModifyOp& op) const { this->modifyItem(this->pos(), op); }
643  };
644 
645  /// Leaf nodes have no children, so their child iterators have no get/set accessors.
646  template<typename MaskIterT, typename NodeT>
647  struct ChildIter:
648  public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT>, NodeT, bool>
649  {
651  ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
652  MaskIterT, ChildIter<MaskIterT, NodeT>, NodeT, bool>(iter, parent) {}
653  };
654 
655  template<typename NodeT, typename ValueT>
656  struct DenseIter: public DenseIteratorBase<
657  MaskDenseIter, DenseIter<NodeT, ValueT>, NodeT, /*ChildT=*/void, ValueT>
658  {
661 
663  DenseIter(const MaskDenseIter& iter, NodeT* parent): BaseT(iter, parent) {}
664 
665  bool getItem(Index pos, void*& child, NonConstValueT& value) const
666  {
667  value = this->parent().getValue(pos);
668  child = nullptr;
669  return false; // no child
670  }
671 
672  // Note: setItem() can't be called on const iterators.
673  //void setItem(Index pos, void* child) const {}
674 
675  // Note: unsetItem() can't be called on const iterators.
676  void unsetItem(Index pos, const ValueT& val) const {this->parent().setValueOnly(pos, val);}
677  };
678 
679 public:
680  using ValueOnIter = ValueIter<MaskOnIter, LeafNode, const bool>;
681  using ValueOnCIter = ValueIter<MaskOnIter, const LeafNode, const bool>;
682  using ValueOffIter = ValueIter<MaskOffIter, LeafNode, const bool>;
683  using ValueOffCIter = ValueIter<MaskOffIter, const LeafNode, const bool>;
684  using ValueAllIter = ValueIter<MaskDenseIter, LeafNode, const bool>;
685  using ValueAllCIter = ValueIter<MaskDenseIter, const LeafNode, const bool>;
686  using ChildOnIter = ChildIter<MaskOnIter, LeafNode>;
687  using ChildOnCIter = ChildIter<MaskOnIter, const LeafNode>;
688  using ChildOffIter = ChildIter<MaskOffIter, LeafNode>;
689  using ChildOffCIter = ChildIter<MaskOffIter, const LeafNode>;
690  using ChildAllIter = DenseIter<LeafNode, bool>;
691  using ChildAllCIter = DenseIter<const LeafNode, const bool>;
692 
693  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
694  ValueOnCIter beginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
695  ValueOnIter beginValueOn() { return ValueOnIter(mValueMask.beginOn(), this); }
696  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
697  ValueOffCIter beginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
698  ValueOffIter beginValueOff() { return ValueOffIter(mValueMask.beginOff(), this); }
699  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mValueMask.beginDense(), this); }
700  ValueAllCIter beginValueAll() const { return ValueAllCIter(mValueMask.beginDense(), this); }
701  ValueAllIter beginValueAll() { return ValueAllIter(mValueMask.beginDense(), this); }
702 
703  ValueOnCIter cendValueOn() const { return ValueOnCIter(mValueMask.endOn(), this); }
704  ValueOnCIter endValueOn() const { return ValueOnCIter(mValueMask.endOn(), this); }
705  ValueOnIter endValueOn() { return ValueOnIter(mValueMask.endOn(), this); }
706  ValueOffCIter cendValueOff() const { return ValueOffCIter(mValueMask.endOff(), this); }
707  ValueOffCIter endValueOff() const { return ValueOffCIter(mValueMask.endOff(), this); }
708  ValueOffIter endValueOff() { return ValueOffIter(mValueMask.endOff(), this); }
709  ValueAllCIter cendValueAll() const { return ValueAllCIter(mValueMask.endDense(), this); }
710  ValueAllCIter endValueAll() const { return ValueAllCIter(mValueMask.endDense(), this); }
711  ValueAllIter endValueAll() { return ValueAllIter(mValueMask.endDense(), this); }
712 
713  // Note that [c]beginChildOn() and [c]beginChildOff() actually return end iterators,
714  // because leaf nodes have no children.
715  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
716  ChildOnCIter beginChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
717  ChildOnIter beginChildOn() { return ChildOnIter(mValueMask.endOn(), this); }
718  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
719  ChildOffCIter beginChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
720  ChildOffIter beginChildOff() { return ChildOffIter(mValueMask.endOff(), this); }
721  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mValueMask.beginDense(), this); }
722  ChildAllCIter beginChildAll() const { return ChildAllCIter(mValueMask.beginDense(), this); }
723  ChildAllIter beginChildAll() { return ChildAllIter(mValueMask.beginDense(), this); }
724 
725  ChildOnCIter cendChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
726  ChildOnCIter endChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
727  ChildOnIter endChildOn() { return ChildOnIter(mValueMask.endOn(), this); }
728  ChildOffCIter cendChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
729  ChildOffCIter endChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
730  ChildOffIter endChildOff() { return ChildOffIter(mValueMask.endOff(), this); }
731  ChildAllCIter cendChildAll() const { return ChildAllCIter(mValueMask.endDense(), this); }
732  ChildAllCIter endChildAll() const { return ChildAllCIter(mValueMask.endDense(), this); }
733  ChildAllIter endChildAll() { return ChildAllIter(mValueMask.endDense(), this); }
734 
735  //
736  // Mask accessors
737  //
738  bool isValueMaskOn(Index n) const { return mValueMask.isOn(n); }
739  bool isValueMaskOn() const { return mValueMask.isOn(); }
740  bool isValueMaskOff(Index n) const { return mValueMask.isOff(n); }
741  bool isValueMaskOff() const { return mValueMask.isOff(); }
742  const NodeMaskType& getValueMask() const { return mValueMask; }
743  const NodeMaskType& valueMask() const { return mValueMask; }
744  NodeMaskType& getValueMask() { return mValueMask; }
745  void setValueMask(const NodeMaskType& mask) { mValueMask = mask; }
746  bool isChildMaskOn(Index) const { return false; } // leaf nodes have no children
747  bool isChildMaskOff(Index) const { return true; }
748  bool isChildMaskOff() const { return true; }
749 protected:
750  void setValueMask(Index n, bool on) { mValueMask.set(n, on); }
751  void setValueMaskOn(Index n) { mValueMask.setOn(n); }
752  void setValueMaskOff(Index n) { mValueMask.setOff(n); }
753 
754  /// Compute the origin of the leaf node that contains the voxel with the given coordinates.
755  static void evalNodeOrigin(Coord& xyz) { xyz &= ~(DIM - 1); }
756 
757  /// Bitmask that determines which voxels are active
759  /// Bitmask representing the values of voxels
761  /// Global grid index coordinates (x,y,z) of the local origin of this node
762  Coord mOrigin;
763  /// Transient data (not serialized)
764  Index32 mTransientData = 0;
765 
766 private:
767  /// @brief During topology-only construction, access is needed
768  /// to protected/private members of other template instances.
769  template<typename, Index> friend class LeafNode;
770 
771  friend struct ValueIter<MaskOnIter, LeafNode, bool>;
772  friend struct ValueIter<MaskOffIter, LeafNode, bool>;
773  friend struct ValueIter<MaskDenseIter, LeafNode, bool>;
774  friend struct ValueIter<MaskOnIter, const LeafNode, bool>;
775  friend struct ValueIter<MaskOffIter, const LeafNode, bool>;
776  friend struct ValueIter<MaskDenseIter, const LeafNode, bool>;
777 
778  //@{
779  /// Allow iterators to call mask accessor methods (see below).
780  /// @todo Make mask accessors public?
784  //@}
785 
786 }; // class LeafNode<bool>
787 
788 
789 ////////////////////////////////////////
790 
791 
792 template<Index Log2Dim>
793 inline
795  : mOrigin(0, 0, 0)
796 {
797 }
798 
799 
800 template<Index Log2Dim>
801 inline
802 LeafNode<bool, Log2Dim>::LeafNode(const Coord& xyz, bool value, bool active)
803  : mValueMask(active)
804  , mBuffer(value)
805  , mOrigin(xyz & (~(DIM - 1)))
806 {
807 }
808 
809 
810 template<Index Log2Dim>
811 inline
812 LeafNode<bool, Log2Dim>::LeafNode(PartialCreate, const Coord& xyz, bool value, bool active)
813  : mValueMask(active)
814  , mBuffer(value)
815  , mOrigin(xyz & (~(DIM - 1)))
816 {
817  /// @todo For now, this is identical to the non-PartialCreate constructor.
818  /// Consider modifying the Buffer class to allow it to be constructed
819  /// without allocating a bitmask.
820 }
821 
822 
823 template<Index Log2Dim>
824 inline
825 LeafNode<bool, Log2Dim>::LeafNode(const LeafNode &other)
826  : mValueMask(other.valueMask())
827  , mBuffer(other.mBuffer)
828  , mOrigin(other.mOrigin)
829  , mTransientData(other.mTransientData)
830 {
831 }
832 
833 
834 // Copy-construct from a leaf node with the same configuration but a different ValueType.
835 template<Index Log2Dim>
836 template<typename ValueT>
837 inline
839  : mValueMask(other.valueMask())
840  , mOrigin(other.origin())
841  , mTransientData(other.mTransientData)
842 {
843  struct Local {
844  /// @todo Consider using a value conversion functor passed as an argument instead.
845  static inline bool convertValue(const ValueT& val) { return bool(val); }
846  };
847 
848  for (Index i = 0; i < SIZE; ++i) {
849  mBuffer.setValue(i, Local::convertValue(other.mBuffer[i]));
850  }
851 }
852 
853 
854 template<Index Log2Dim>
855 template<typename ValueT>
856 inline
858  bool background, TopologyCopy)
859  : mValueMask(other.valueMask())
860  , mBuffer(background)
861  , mOrigin(other.origin())
862  , mTransientData(other.mTransientData)
863 {
864 }
865 
866 
867 template<Index Log2Dim>
868 template<typename ValueT>
869 inline
871  : mValueMask(other.valueMask())
872  , mBuffer(other.valueMask())// value = active state
873  , mOrigin(other.origin())
874  , mTransientData(other.mTransientData)
875 {
876 }
877 
878 template<Index Log2Dim>
879 inline
881  const NodeMaskType& mask,
882  const Buffer& buff,
883  const Index32 trans)
884  : mValueMask(mask)
885  , mBuffer(buff)
886  , mOrigin(xyz & (~(DIM - 1)))
887  , mTransientData(trans)
888 {
889 }
890 
891 template<Index Log2Dim>
892 template<typename ValueT>
893 inline
895  bool offValue, bool onValue, TopologyCopy)
896  : mValueMask(other.valueMask())
897  , mBuffer(offValue)
898  , mOrigin(other.origin())
899  , mTransientData(other.mTransientData)
900 {
901  for (Index i = 0; i < SIZE; ++i) {
902  if (mValueMask.isOn(i)) {
903  mBuffer.setValue(i, onValue);
904  }
905  }
906 }
907 
908 
909 template<Index Log2Dim>
910 inline
912 {
913 }
914 
915 
916 ////////////////////////////////////////
917 
918 
919 template<Index Log2Dim>
920 inline Index64
922 {
923  // Use sizeof(*this) to capture alignment-related padding
924  return sizeof(*this);
925 }
926 
927 
928 template<Index Log2Dim>
929 inline Index64
931 {
932  // Use sizeof(*this) to capture alignment-related padding
933  return sizeof(*this);
934 }
935 
936 
937 template<Index Log2Dim>
938 inline void
939 LeafNode<bool, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const
940 {
941  CoordBBox this_bbox = this->getNodeBoundingBox();
942  if (bbox.isInside(this_bbox)) return;//this LeafNode is already enclosed in the bbox
943  if (ValueOnCIter iter = this->cbeginValueOn()) {//any active values?
944  if (visitVoxels) {//use voxel granularity?
945  this_bbox.reset();
946  for(; iter; ++iter) this_bbox.expand(this->offsetToLocalCoord(iter.pos()));
947  this_bbox.translate(this->origin());
948  }
949  bbox.expand(this_bbox);
950  }
951 }
952 
953 
954 template<Index Log2Dim>
955 template<typename OtherType, Index OtherLog2Dim>
956 inline bool
958 {
959  OPENVDB_ASSERT(other);
960  return (Log2Dim == OtherLog2Dim && mValueMask == other->getValueMask());
961 }
962 
963 
964 template<Index Log2Dim>
965 inline std::string
967 {
968  std::ostringstream ostr;
969  ostr << "LeafNode @" << mOrigin << ": ";
970  for (Index32 n = 0; n < SIZE; ++n) ostr << (mValueMask.isOn(n) ? '#' : '.');
971  return ostr.str();
972 }
973 
974 
975 ////////////////////////////////////////
976 
977 
978 template<Index Log2Dim>
979 inline Index
981 {
982  OPENVDB_ASSERT((xyz[0] & (DIM-1u)) < DIM && (xyz[1] & (DIM-1u)) < DIM && (xyz[2] & (DIM-1u)) < DIM);
983  return ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
984  + ((xyz[1] & (DIM-1u)) << Log2Dim)
985  + (xyz[2] & (DIM-1u));
986 }
987 
988 
989 template<Index Log2Dim>
990 inline Coord
992 {
993  OPENVDB_ASSERT(n < (1 << 3*Log2Dim));
994  Coord xyz;
995  xyz.setX(n >> 2*Log2Dim);
996  n &= ((1 << 2*Log2Dim) - 1);
997  xyz.setY(n >> Log2Dim);
998  xyz.setZ(n & ((1 << Log2Dim) - 1));
999  return xyz;
1000 }
1001 
1002 
1003 template<Index Log2Dim>
1004 inline Coord
1006 {
1007  return (this->offsetToLocalCoord(n) + this->origin());
1008 }
1009 
1010 
1011 ////////////////////////////////////////
1012 
1013 
1014 template<Index Log2Dim>
1015 inline void
1016 LeafNode<bool, Log2Dim>::readTopology(std::istream& is, bool /*fromHalf*/)
1017 {
1018  mValueMask.load(is);
1019 }
1020 
1021 
1022 template<Index Log2Dim>
1023 inline void
1024 LeafNode<bool, Log2Dim>::writeTopology(std::ostream& os, bool /*toHalf*/) const
1025 {
1026  mValueMask.save(os);
1027 }
1028 
1029 
1030 template<Index Log2Dim>
1031 inline void
1032 LeafNode<bool, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& clipBBox, bool fromHalf)
1033 {
1034  // Boolean LeafNodes don't currently implement lazy loading.
1035  // Instead, load the full buffer, then clip it.
1036 
1037  this->readBuffers(is, fromHalf);
1038 
1039  // Get this tree's background value.
1040  bool background = false;
1041  if (const void* bgPtr = io::getGridBackgroundValuePtr(is)) {
1042  background = *static_cast<const bool*>(bgPtr);
1043  }
1044  this->clip(clipBBox, background);
1045 }
1046 
1047 
1048 template<Index Log2Dim>
1049 inline void
1050 LeafNode<bool, Log2Dim>::readBuffers(std::istream& is, bool /*fromHalf*/)
1051 {
1052  // Read in the value mask.
1053  mValueMask.load(is);
1054  // Read in the origin.
1055  is.read(reinterpret_cast<char*>(&mOrigin), sizeof(Coord::ValueType) * 3);
1056 
1058  // Read in the mask for the voxel values.
1059  mBuffer.mData.load(is);
1060  } else {
1061  // Older files stored one or more bool arrays.
1062 
1063  // Read in the number of buffers, which should now always be one.
1064  int8_t numBuffers = 0;
1065  is.read(reinterpret_cast<char*>(&numBuffers), sizeof(int8_t));
1066 
1067  // Read in the buffer.
1068  // (Note: prior to the bool leaf optimization, buffers were always compressed.)
1069  std::unique_ptr<bool[]> buf{new bool[SIZE]};
1070  io::readData<bool>(is, buf.get(), SIZE, /*isCompressed=*/true);
1071 
1072  // Transfer values to mBuffer.
1073  mBuffer.mData.setOff();
1074  for (Index i = 0; i < SIZE; ++i) {
1075  if (buf[i]) mBuffer.mData.setOn(i);
1076  }
1077 
1078  if (numBuffers > 1) {
1079  // Read in and discard auxiliary buffers that were created with
1080  // earlier versions of the library.
1081  for (int i = 1; i < numBuffers; ++i) {
1082  io::readData<bool>(is, buf.get(), SIZE, /*isCompressed=*/true);
1083  }
1084  }
1085  }
1086 }
1087 
1088 
1089 template<Index Log2Dim>
1090 inline void
1091 LeafNode<bool, Log2Dim>::writeBuffers(std::ostream& os, bool /*toHalf*/) const
1092 {
1093  // Write out the value mask.
1094  mValueMask.save(os);
1095  // Write out the origin.
1096  os.write(reinterpret_cast<const char*>(&mOrigin), sizeof(Coord::ValueType) * 3);
1097  // Write out the voxel values.
1098  mBuffer.mData.save(os);
1099 }
1100 
1101 
1102 ////////////////////////////////////////
1103 
1104 
1105 template<Index Log2Dim>
1106 inline bool
1107 LeafNode<bool, Log2Dim>::operator==(const LeafNode& other) const
1108 {
1109  return mOrigin == other.mOrigin &&
1110  mValueMask == other.valueMask() &&
1111  mBuffer == other.mBuffer;
1112 }
1113 
1114 
1115 template<Index Log2Dim>
1116 inline bool
1117 LeafNode<bool, Log2Dim>::operator!=(const LeafNode& other) const
1118 {
1119  return !(this->operator==(other));
1120 }
1121 
1122 
1123 ////////////////////////////////////////
1124 
1125 
1126 template<Index Log2Dim>
1127 inline bool
1128 LeafNode<bool, Log2Dim>::isConstant(bool& constValue, bool& state, bool tolerance) const
1129 {
1130  if (!mValueMask.isConstant(state)) return false;
1131 
1132  // Note: if tolerance is true (i.e., 1), then all boolean values compare equal.
1133  if (!tolerance && !(mBuffer.mData.isOn() || mBuffer.mData.isOff())) return false;
1134 
1135  constValue = mBuffer.mData.isOn();
1136  return true;
1137 }
1138 
1139 ////////////////////////////////////////
1140 
1141 template<Index Log2Dim>
1142 inline bool
1144 {
1145  const Index countTrue = mBuffer.mData.countOn();
1146  return countTrue > (NUM_VALUES >> 1);
1147 }
1148 
1149 template<Index Log2Dim>
1150 inline Index
1152 {
1153  const NodeMaskType tmp = mBuffer.mData & mValueMask;//both true and active
1154  const Index countTrueOn = tmp.countOn(), countOn = mValueMask.countOn();
1155  state = countTrueOn > (NUM_VALUES >> 1);
1156  return countOn;
1157 }
1158 
1159 template<Index Log2Dim>
1160 inline Index
1162 {
1163  const NodeMaskType tmp = mBuffer.mData & (!mValueMask);//both true and inactive
1164  const Index countTrueOff = tmp.countOn(), countOff = mValueMask.countOff();
1165  state = countTrueOff > (NUM_VALUES >> 1);
1166  return countOff;
1167 }
1168 
1169 ////////////////////////////////////////
1170 
1171 
1172 template<Index Log2Dim>
1173 inline void
1174 LeafNode<bool, Log2Dim>::addTile(Index /*level*/, const Coord& xyz, bool val, bool active)
1175 {
1176  this->addTile(this->coordToOffset(xyz), val, active);
1177 }
1178 
1179 template<Index Log2Dim>
1180 inline void
1181 LeafNode<bool, Log2Dim>::addTile(Index offset, bool val, bool active)
1182 {
1183  OPENVDB_ASSERT(offset < SIZE);
1184  this->setValueOnly(offset, val);
1185  this->setActiveState(offset, active);
1186 }
1187 
1188 template<Index Log2Dim>
1189 template<typename AccessorT>
1190 inline void
1192  bool val, bool active, AccessorT&)
1193 {
1194  this->addTile(level, xyz, val, active);
1195 }
1196 
1197 
1198 ////////////////////////////////////////
1199 
1200 
1201 template<Index Log2Dim>
1202 inline const bool&
1203 LeafNode<bool, Log2Dim>::getValue(const Coord& xyz) const
1204 {
1205  // This *CANNOT* use operator ? because Visual C++
1206  if (mBuffer.mData.isOn(this->coordToOffset(xyz))) return Buffer::sOn; else return Buffer::sOff;
1207 }
1208 
1209 
1210 template<Index Log2Dim>
1211 inline const bool&
1213 {
1214  OPENVDB_ASSERT(offset < SIZE);
1215  // This *CANNOT* use operator ? for Windows
1216  if (mBuffer.mData.isOn(offset)) return Buffer::sOn; else return Buffer::sOff;
1217 }
1218 
1219 
1220 template<Index Log2Dim>
1221 inline bool
1222 LeafNode<bool, Log2Dim>::probeValue(const Coord& xyz, bool& val) const
1223 {
1224  return this->probeValue(this->coordToOffset(xyz), val);
1225 }
1226 
1227 template<Index Log2Dim>
1228 inline bool
1230 {
1231  OPENVDB_ASSERT(offset < SIZE);
1232  val = mBuffer.mData.isOn(offset);
1233  return mValueMask.isOn(offset);
1234 }
1235 
1236 template<Index Log2Dim>
1237 inline void
1238 LeafNode<bool, Log2Dim>::setValueOn(const Coord& xyz, bool val)
1239 {
1240  this->setValueOn(this->coordToOffset(xyz), val);
1241 }
1242 
1243 
1244 template<Index Log2Dim>
1245 inline void
1247 {
1248  OPENVDB_ASSERT(offset < SIZE);
1249  mValueMask.setOn(offset);
1250  mBuffer.mData.set(offset, val);
1251 }
1252 
1253 
1254 template<Index Log2Dim>
1255 inline void
1256 LeafNode<bool, Log2Dim>::setValueOnly(const Coord& xyz, bool val)
1257 {
1258  this->setValueOnly(this->coordToOffset(xyz), val);
1259 }
1260 
1261 
1262 template<Index Log2Dim>
1263 inline void
1265 {
1266  mValueMask.set(this->coordToOffset(xyz), on);
1267 }
1268 
1269 
1270 template<Index Log2Dim>
1271 inline void
1272 LeafNode<bool, Log2Dim>::setValueOff(const Coord& xyz, bool val)
1273 {
1274  this->setValueOff(this->coordToOffset(xyz), val);
1275 }
1276 
1277 
1278 template<Index Log2Dim>
1279 inline void
1281 {
1282  OPENVDB_ASSERT(offset < SIZE);
1283  mValueMask.setOff(offset);
1284  mBuffer.mData.set(offset, val);
1285 }
1286 
1287 
1288 template<Index Log2Dim>
1289 template<typename ModifyOp>
1290 inline void
1291 LeafNode<bool, Log2Dim>::modifyValue(Index offset, const ModifyOp& op)
1292 {
1293  bool val = mBuffer.mData.isOn(offset);
1294  op(val);
1295  mBuffer.mData.set(offset, val);
1296  mValueMask.setOn(offset);
1297 }
1298 
1299 
1300 template<Index Log2Dim>
1301 template<typename ModifyOp>
1302 inline void
1303 LeafNode<bool, Log2Dim>::modifyValue(const Coord& xyz, const ModifyOp& op)
1304 {
1305  this->modifyValue(this->coordToOffset(xyz), op);
1306 }
1307 
1308 
1309 template<Index Log2Dim>
1310 template<typename ModifyOp>
1311 inline void
1312 LeafNode<bool, Log2Dim>::modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1313 {
1314  const Index offset = this->coordToOffset(xyz);
1315  bool val = mBuffer.mData.isOn(offset), state = mValueMask.isOn(offset);
1316  op(val, state);
1317  mBuffer.mData.set(offset, val);
1318  mValueMask.set(offset, state);
1319 }
1320 
1321 
1322 ////////////////////////////////////////
1323 
1324 
1325 template<Index Log2Dim>
1326 inline void
1327 LeafNode<bool, Log2Dim>::resetBackground(bool oldBackground, bool newBackground)
1328 {
1329  if (newBackground != oldBackground) {
1330  // Flip mBuffer's background bits and zero its foreground bits.
1331  NodeMaskType bgMask = !(mBuffer.mData | mValueMask);
1332  // Overwrite mBuffer's background bits, leaving its foreground bits intact.
1333  mBuffer.mData = (mBuffer.mData & mValueMask) | bgMask;
1334  }
1335 }
1336 
1337 
1338 ////////////////////////////////////////
1339 
1340 
1341 template<Index Log2Dim>
1342 template<MergePolicy Policy>
1343 inline void
1344 LeafNode<bool, Log2Dim>::merge(const LeafNode& other, bool /*bg*/, bool /*otherBG*/)
1345 {
1347  if (Policy == MERGE_NODES) return;
1348  for (typename NodeMaskType::OnIterator iter = other.valueMask().beginOn(); iter; ++iter) {
1349  const Index n = iter.pos();
1350  if (mValueMask.isOff(n)) {
1351  mBuffer.mData.set(n, other.mBuffer.mData.isOn(n));
1352  mValueMask.setOn(n);
1353  }
1354  }
1356 }
1357 
1358 template<Index Log2Dim>
1359 template<MergePolicy Policy>
1360 inline void
1361 LeafNode<bool, Log2Dim>::merge(bool tileValue, bool tileActive)
1362 {
1364  if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return;
1365  if (!tileActive) return;
1366  // Replace all inactive values with the active tile value.
1367  if (tileValue) mBuffer.mData |= !mValueMask; // -0=>1, +0=>0, -1=>1, +1=>1 (-,+ = off,on)
1368  else mBuffer.mData &= mValueMask; // -0=>0, +0=>0, -1=>0, +1=>1
1369  mValueMask.setOn();
1371 }
1372 
1373 
1374 ////////////////////////////////////////
1375 
1376 
1377 template<Index Log2Dim>
1378 template<typename OtherType>
1379 inline void
1381 {
1382  mValueMask |= other.valueMask();
1383 }
1384 
1385 
1386 template<Index Log2Dim>
1387 template<typename OtherType>
1388 inline void
1390  const bool&)
1391 {
1392  mValueMask &= other.valueMask();
1393 }
1394 
1395 
1396 template<Index Log2Dim>
1397 template<typename OtherType>
1398 inline void
1400  const bool&)
1401 {
1402  mValueMask &= !other.valueMask();
1403 }
1404 
1405 
1406 ////////////////////////////////////////
1407 
1408 
1409 template<Index Log2Dim>
1410 inline void
1411 LeafNode<bool, Log2Dim>::clip(const CoordBBox& clipBBox, bool background)
1412 {
1413  CoordBBox nodeBBox = this->getNodeBoundingBox();
1414  if (!clipBBox.hasOverlap(nodeBBox)) {
1415  // This node lies completely outside the clipping region. Fill it with background tiles.
1416  this->fill(nodeBBox, background, /*active=*/false);
1417  } else if (clipBBox.isInside(nodeBBox)) {
1418  // This node lies completely inside the clipping region. Leave it intact.
1419  return;
1420  }
1421 
1422  // This node isn't completely contained inside the clipping region.
1423  // Set any voxels that lie outside the region to the background value.
1424 
1425  // Construct a boolean mask that is on inside the clipping region and off outside it.
1426  NodeMaskType mask;
1427  nodeBBox.intersect(clipBBox);
1428  Coord xyz;
1429  int &x = xyz.x(), &y = xyz.y(), &z = xyz.z();
1430  for (x = nodeBBox.min().x(); x <= nodeBBox.max().x(); ++x) {
1431  for (y = nodeBBox.min().y(); y <= nodeBBox.max().y(); ++y) {
1432  for (z = nodeBBox.min().z(); z <= nodeBBox.max().z(); ++z) {
1433  mask.setOn(static_cast<Index32>(this->coordToOffset(xyz)));
1434  }
1435  }
1436  }
1437 
1438  // Set voxels that lie in the inactive region of the mask (i.e., outside
1439  // the clipping region) to the background value.
1440  for (MaskOffIter maskIter = mask.beginOff(); maskIter; ++maskIter) {
1441  this->setValueOff(maskIter.pos(), background);
1442  }
1443 }
1444 
1445 
1446 ////////////////////////////////////////
1447 
1448 
1449 template<Index Log2Dim>
1450 inline void
1451 LeafNode<bool, Log2Dim>::fill(const CoordBBox& bbox, bool value, bool active)
1452 {
1453  auto clippedBBox = this->getNodeBoundingBox();
1454  clippedBBox.intersect(bbox);
1455  if (!clippedBBox) return;
1456 
1457  for (Int32 x = clippedBBox.min().x(); x <= clippedBBox.max().x(); ++x) {
1458  const Index offsetX = (x & (DIM-1u))<<2*Log2Dim;
1459  for (Int32 y = clippedBBox.min().y(); y <= clippedBBox.max().y(); ++y) {
1460  const Index offsetXY = offsetX + ((y & (DIM-1u))<< Log2Dim);
1461  for (Int32 z = clippedBBox.min().z(); z <= clippedBBox.max().z(); ++z) {
1462  const Index offset = offsetXY + (z & (DIM-1u));
1463  mValueMask.set(offset, active);
1464  mBuffer.mData.set(offset, value);
1465  }
1466  }
1467  }
1468 }
1469 
1470 template<Index Log2Dim>
1471 inline void
1473 {
1474  mBuffer.fill(value);
1475 }
1476 
1477 template<Index Log2Dim>
1478 inline void
1479 LeafNode<bool, Log2Dim>::fill(const bool& value, bool active)
1480 {
1481  mBuffer.fill(value);
1482  mValueMask.set(active);
1483 }
1484 
1485 
1486 ////////////////////////////////////////
1487 
1488 
1489 template<Index Log2Dim>
1490 template<typename DenseT>
1491 inline void
1492 LeafNode<bool, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const
1493 {
1494  using DenseValueType = typename DenseT::ValueType;
1495 
1496  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1497  const Coord& min = dense.bbox().min();
1498  DenseValueType* t0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // target array
1499  const Int32 n0 = bbox.min()[2] & (DIM-1u);
1500  for (Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1; x < ex; ++x) {
1501  DenseValueType* t1 = t0 + xStride * (x - min[0]);
1502  const Int32 n1 = n0 + ((x & (DIM-1u)) << 2*LOG2DIM);
1503  for (Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1; y < ey; ++y) {
1504  DenseValueType* t2 = t1 + yStride * (y - min[1]);
1505  Int32 n2 = n1 + ((y & (DIM-1u)) << LOG2DIM);
1506  for (Int32 z = bbox.min()[2], ez = bbox.max()[2] + 1; z < ez; ++z, t2 += zStride) {
1507  *t2 = DenseValueType(mBuffer.mData.isOn(n2++));
1508  }
1509  }
1510  }
1511 }
1512 
1513 
1514 template<Index Log2Dim>
1515 template<typename DenseT>
1516 inline void
1517 LeafNode<bool, Log2Dim>::copyFromDense(const CoordBBox& bbox, const DenseT& dense,
1518  bool background, bool tolerance)
1519 {
1520  using DenseValueType = typename DenseT::ValueType;
1521  struct Local {
1522  inline static bool toBool(const DenseValueType& v) { return !math::isZero(v); }
1523  };
1524 
1525  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1526  const Coord& min = dense.bbox().min();
1527  const DenseValueType* s0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // source
1528  const Int32 n0 = bbox.min()[2] & (DIM-1u);
1529  for (Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1; x < ex; ++x) {
1530  const DenseValueType* s1 = s0 + xStride * (x - min[0]);
1531  const Int32 n1 = n0 + ((x & (DIM-1u)) << 2*LOG2DIM);
1532  for (Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1; y < ey; ++y) {
1533  const DenseValueType* s2 = s1 + yStride * (y - min[1]);
1534  Int32 n2 = n1 + ((y & (DIM-1u)) << LOG2DIM);
1535  for (Int32 z = bbox.min()[2], ez = bbox.max()[2]+1; z < ez; ++z, ++n2, s2 += zStride) {
1536  // Note: if tolerance is true (i.e., 1), then all boolean values compare equal.
1537  if (tolerance || (background == Local::toBool(*s2))) {
1538  mValueMask.setOff(n2);
1539  mBuffer.mData.set(n2, background);
1540  } else {
1541  mValueMask.setOn(n2);
1542  mBuffer.mData.set(n2, Local::toBool(*s2));
1543  }
1544  }
1545  }
1546  }
1547 }
1548 
1549 
1550 ////////////////////////////////////////
1551 
1552 
1553 template<Index Log2Dim>
1554 template<typename CombineOp>
1555 inline void
1556 LeafNode<bool, Log2Dim>::combine(const LeafNode& other, CombineOp& op)
1557 {
1558  CombineArgs<bool> args;
1559  for (Index i = 0; i < SIZE; ++i) {
1560  bool result = false, aVal = mBuffer.mData.isOn(i), bVal = other.mBuffer.mData.isOn(i);
1561  op(args.setARef(aVal)
1562  .setAIsActive(mValueMask.isOn(i))
1563  .setBRef(bVal)
1564  .setBIsActive(other.valueMask().isOn(i))
1565  .setResultRef(result));
1566  mValueMask.set(i, args.resultIsActive());
1567  mBuffer.mData.set(i, result);
1568  }
1569 }
1570 
1571 
1572 template<Index Log2Dim>
1573 template<typename CombineOp>
1574 inline void
1575 LeafNode<bool, Log2Dim>::combine(bool value, bool valueIsActive, CombineOp& op)
1576 {
1577  CombineArgs<bool> args;
1578  args.setBRef(value).setBIsActive(valueIsActive);
1579  for (Index i = 0; i < SIZE; ++i) {
1580  bool result = false, aVal = mBuffer.mData.isOn(i);
1581  op(args.setARef(aVal)
1582  .setAIsActive(mValueMask.isOn(i))
1583  .setResultRef(result));
1584  mValueMask.set(i, args.resultIsActive());
1585  mBuffer.mData.set(i, result);
1586  }
1587 }
1588 
1589 
1590 ////////////////////////////////////////
1591 
1592 
1593 template<Index Log2Dim>
1594 template<typename CombineOp, typename OtherType>
1595 inline void
1596 LeafNode<bool, Log2Dim>::combine2(const LeafNode& other, const OtherType& value,
1597  bool valueIsActive, CombineOp& op)
1598 {
1600  args.setBRef(value).setBIsActive(valueIsActive);
1601  for (Index i = 0; i < SIZE; ++i) {
1602  bool result = false, aVal = other.mBuffer.mData.isOn(i);
1603  op(args.setARef(aVal)
1604  .setAIsActive(other.valueMask().isOn(i))
1605  .setResultRef(result));
1606  mValueMask.set(i, args.resultIsActive());
1607  mBuffer.mData.set(i, result);
1608  }
1609 }
1610 
1611 
1612 template<Index Log2Dim>
1613 template<typename CombineOp, typename OtherNodeT>
1614 inline void
1615 LeafNode<bool, Log2Dim>::combine2(bool value, const OtherNodeT& other,
1616  bool valueIsActive, CombineOp& op)
1617 {
1619  args.setARef(value).setAIsActive(valueIsActive);
1620  for (Index i = 0; i < SIZE; ++i) {
1621  bool result = false, bVal = other.mBuffer.mData.isOn(i);
1622  op(args.setBRef(bVal)
1623  .setBIsActive(other.valueMask().isOn(i))
1624  .setResultRef(result));
1625  mValueMask.set(i, args.resultIsActive());
1626  mBuffer.mData.set(i, result);
1627  }
1628 }
1629 
1630 
1631 template<Index Log2Dim>
1632 template<typename CombineOp, typename OtherNodeT>
1633 inline void
1634 LeafNode<bool, Log2Dim>::combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp& op)
1635 {
1637  for (Index i = 0; i < SIZE; ++i) {
1638  // Default behavior: output voxel is active if either input voxel is active.
1639  mValueMask.set(i, b0.valueMask().isOn(i) || b1.valueMask().isOn(i));
1640 
1641  bool result = false, b0Val = b0.mBuffer.mData.isOn(i), b1Val = b1.mBuffer.mData.isOn(i);
1642  op(args.setARef(b0Val)
1643  .setAIsActive(b0.valueMask().isOn(i))
1644  .setBRef(b1Val)
1645  .setBIsActive(b1.valueMask().isOn(i))
1646  .setResultRef(result));
1647  mValueMask.set(i, args.resultIsActive());
1648  mBuffer.mData.set(i, result);
1649  }
1650 }
1651 
1652 
1653 } // namespace tree
1654 } // namespace OPENVDB_VERSION_NAME
1655 } // namespace openvdb
1656 
1657 #endif // OPENVDB_TREE_LEAF_NODE_BOOL_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: LeafNodeBool.h:274
NodeT * stealNode(const Coord &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNodeBool.h:561
ValueAllCIter cbeginValueAll() const
Definition: LeafNodeBool.h:699
ValueOnIter beginValueOn()
Definition: LeafNodeBool.h:695
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNodeBool.h:369
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:38
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:422
void setValueMask(const NodeMaskType &mask)
Definition: LeafNodeBool.h:745
ValueType medianAll(ValueType *tmp=nullptr) const
Computes the median value of all the active AND inactive voxels in this node.
Definition: LeafNode.h:1541
void setValuesOff()
Mark all voxels as inactive but don&#39;t change their values.
Definition: LeafNodeBool.h:301
void readBuffers(std::istream &is, bool fromHalf=false)
Read buffers from a stream.
Definition: LeafNode.h:1334
void addLeafAndCache(LeafNode *, AccessorT &)
This function exists only to enable template instantiation.
Definition: LeafNodeBool.h:559
Index64 onVoxelCount() const
Return the number of active voxels.
Definition: LeafNodeBool.h:142
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: LeafNodeBool.h:264
bool isChildMaskOff() const
Definition: LeafNodeBool.h:748
const bool & getItem(Index pos) const
Definition: LeafNodeBool.h:629
ValueOnCIter cbeginValueOn() const
Definition: LeafNode.h:300
void setValue(const Coord &xyz, bool val)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: LeafNodeBool.h:281
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: LeafNode.h:459
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:568
ValueAllCIter cendValueAll() const
Definition: LeafNodeBool.h:709
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
Definition: LeafNode.h:1449
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:29
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:1234
Buffer mBuffer
Bitmask representing the values of voxels.
Definition: LeafNodeBool.h:760
LeafNode()
Default constructor.
Definition: LeafNode.h:932
ValueIter< MaskOffIter, LeafNode, const bool > ValueOffIter
Definition: LeafNodeBool.h:682
ValueOnCIter beginValueOn() const
Definition: LeafNodeBool.h:694
static Index64 nonLeafCount()
Definition: LeafNodeBool.h:139
void readTopology(std::istream &is, bool fromHalf=false)
Read in just the topology.
Definition: LeafNode.h:1298
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
bool getValueUnsafe(Index offset, bool &value) const
Return true if the voxel at the given offset is active and set value.
Definition: LeafNodeBool.h:479
Index64 memUsageIfLoaded(const TreeT &tree, bool threaded=true)
Return the deserialized memory usage of this tree. This is not necessarily equal to the current memor...
Definition: Count.h:502
ChildAllCIter beginChildAll() const
Definition: LeafNodeBool.h:722
void setValueOffUnsafe(Index offset, const bool &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: LeafNodeBool.h:491
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Set the active state of the voxel at the given coordinates without changing its value.
Definition: LeafNodeBool.h:411
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:438
ValueIter< MaskDenseIter, LeafNode, const bool > ValueAllIter
Definition: LeafNodeBool.h:684
void setValueOff(Index offset)
Mark the voxel at the given offset as inactive but don&#39;t change its value.
Definition: LeafNodeBool.h:266
uint64_t Index64
Definition: Types.h:53
ValueOffIter beginValueOff()
Definition: LeafNodeBool.h:698
DenseIter< LeafNode, bool > ChildAllIter
Definition: LeafNodeBool.h:690
Index64 offVoxelCount() const
Return the number of inactive voxels.
Definition: LeafNodeBool.h:144
LeafNode specialization for values of type bool that stores both the active states and the values of ...
Definition: LeafNodeBool.h:29
bool resultIsActive() const
Definition: Types.h:632
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:452
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition: LeafNodeBool.h:762
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:1718
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: LeafNode.h:410
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
Definition: LeafNode.h:170
SharedPtr< LeafNodeType > Ptr
Definition: LeafNodeBool.h:37
ValueOffCIter endValueOff() const
Definition: LeafNodeBool.h:707
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: LeafNodeBool.h:402
ChildIter< MaskOnIter, LeafNode > ChildOnIter
Definition: LeafNodeBool.h:686
const bool & getFirstValue() const
Return a const reference to the first entry in the buffer.
Definition: LeafNodeBool.h:433
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: LeafNodeBool.h:420
ValueIter< MaskOnIter, LeafNode, const bool > ValueOnIter
Definition: LeafNodeBool.h:680
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:1125
void voxelizeActiveTiles(bool=true)
No-op.
Definition: LeafNodeBool.h:503
const Coord & origin() const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNodeBool.h:180
bool BuildType
Definition: LeafNodeBool.h:33
static const Index DIM
Definition: LeafNode.h:51
ValueAllIter endValueAll()
Definition: LeafNodeBool.h:711
LeafNode * touchLeaf(const Coord &)
Return a pointer to this node.
Definition: LeafNodeBool.h:577
void combine(const LeafNode &other, CombineOp &op)
Definition: LeafNode.h:1751
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1075
void setValueOnUnsafe(Index offset, const bool &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: LeafNodeBool.h:487
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:307
bool isValueOff(const Coord &xyz) const
Return true if the voxel at the given coordinates is inactive.
Definition: LeafNodeBool.h:308
LeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNodeBool.h:582
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: LeafNode.h:420
Definition: NodeMasks.h:270
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:352
static Index numValues()
Definition: LeafNodeBool.h:129
void setValueOffUnsafe(Index offset)
Mark the voxel at the given offset as inactive but don&#39;t change its value.
Definition: LeafNodeBool.h:489
static Index64 onTileCount()
Definition: LeafNodeBool.h:147
typename NodeMaskType::OnIterator MaskOnIter
Definition: LeafNodeBool.h:614
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:1261
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNodeBool.h:304
Definition: NodeMasks.h:239
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: LeafNode.h:1050
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Replace inactive occurrences of oldBackground with newBackground, and inactive occurrences of -oldBac...
Definition: LeafNode.h:1639
Definition: Coord.h:590
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node&#39;s local origin.
Definition: LeafNodeBool.h:177
ChildAllCIter cbeginChildAll() const
Definition: LeafNodeBool.h:721
bool getItem(Index pos, void *&child, NonConstValueT &value) const
Definition: LeafNodeBool.h:665
static const Index SIZE
Definition: LeafNode.h:54
NodeMaskType mValueMask
Bitmask that determines which voxels are active.
Definition: LeafNodeBool.h:758
void negate()
Definition: LeafNodeBool.h:495
ValueOnCIter endValueOn() const
Definition: LeafNodeBool.h:704
void setValueOnlyUnsafe(Index offset, const bool &value)
Set the value of the voxel at the given coordinates but don&#39;t change its active state.
Definition: LeafNodeBool.h:483
int32_t Int32
Definition: Types.h:56
ValueIter< MaskOnIter, const LeafNode, const bool > ValueOnCIter
Definition: LeafNodeBool.h:681
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: LeafNodeBool.h:256
Index32 Index
Definition: Types.h:54
ChildOffCIter endChildOff() const
Definition: LeafNodeBool.h:729
bool isValueOff(Index offset) const
Return true if the voxel at the given offset is inactive.
Definition: LeafNodeBool.h:310
const Coord & origin() const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNode.h:176
const NodeMaskType & valueMask() const
Definition: LeafNodeBool.h:743
OutGridT XformOp & op
Definition: ValueTransformer.h:139
bool allocate()
Allocate memory for this node&#39;s buffer if it has not already been allocated.
Definition: LeafNodeBool.h:161
ChildIter< MaskOnIter, const LeafNode > ChildOnCIter
Definition: LeafNodeBool.h:687
void setTransientData(Index32 transientData)
Set the transient data value.
Definition: LeafNodeBool.h:196
ChildAllIter endChildAll()
Definition: LeafNodeBool.h:733
void swap(Buffer &other)
Exchange this node&#39;s data buffer with the given data buffer without changing the active states of the...
Definition: LeafNodeBool.h:215
ValueOffCIter cbeginValueOff() const
Definition: LeafNodeBool.h:696
const bool & getValue() const
Definition: LeafNodeBool.h:630
ChildOffCIter beginChildOff() const
Definition: LeafNodeBool.h:719
void setValueOn(Index offset)
Mark the voxel at the given offset as active but don&#39;t change its value.
Definition: LeafNodeBool.h:276
void merge(const LeafNode &)
Definition: LeafNode.h:1661
const LeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNodeBool.h:599
void addTile(Index level, const Coord &, const ValueType &, bool)
Definition: LeafNode.h:1610
const bool & getValueAndCache(const Coord &xyz, AccessorT &) const
Return the value of the voxel at the given coordinates.
Definition: LeafNodeBool.h:364
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: LeafNode.h:1040
Index64 memUsage() const
Return the memory in bytes occupied by this node.
Definition: LeafNode.h:1459
void set(Index32 n, bool On)
Set the nth bit to the specified state.
Definition: NodeMasks.h:462
DenseIter(const MaskDenseIter &iter, NodeT *parent)
Definition: LeafNodeBool.h:663
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:474
typename NodeMaskType::OffIterator MaskOffIter
Definition: LeafNodeBool.h:615
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Definition: LeafNode.h:1479
static const Index LOG2DIM
Definition: LeafNode.h:49
OutGridT XformOp bool bool MergePolicy merge
Definition: ValueTransformer.h:141
const NodeMaskType & getValueMask() const
Definition: LeafNodeBool.h:742
bool operator!=(const LeafNode &other) const
Definition: LeafNode.h:204
ChildOffCIter cendChildOff() const
Definition: LeafNodeBool.h:728
DenseIter< const LeafNode, const bool > ChildAllCIter
Definition: LeafNodeBool.h:691
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: Types.h:623
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:1133
void writeBuffers(std::ostream &os, bool toHalf=false) const
Write buffers to a stream.
Definition: LeafNode.h:1432
Definition: NodeMasks.h:208
Index64 memUsage(const TreeT &tree, bool threaded=true)
Return the total amount of memory in bytes occupied by this tree.
Definition: Count.h:493
ValueOnIter endValueOn()
Definition: LeafNodeBool.h:705
static bool hasActiveTiles()
Return false since leaf nodes never contain tiles.
Definition: LeafNodeBool.h:313
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:621
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:1727
std::shared_ptr< T > SharedPtr
Definition: Types.h:114
void getOrigin(Coord &origin) const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNodeBool.h:181
void addLeaf(LeafNode *)
This function exists only to enable template instantiation.
Definition: LeafNodeBool.h:557
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:337
const LeafNode * probeLeaf(const Coord &) const
Return a const pointer to this node.
Definition: LeafNodeBool.h:594
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
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:1497
ChildOnCIter endChildOn() const
Definition: LeafNodeBool.h:726
ChildOffCIter cbeginChildOff() const
Definition: LeafNodeBool.h:718
ChildAllCIter endChildAll() const
Definition: LeafNodeBool.h:732
void setActiveStateUnsafe(Index offset, bool on)
Set the active state of the voxel at the given offset but don&#39;t change its value. ...
Definition: LeafNodeBool.h:481
ValueAllIter beginValueAll()
Definition: LeafNodeBool.h:701
const NodeT * probeConstNode(const Coord &) const
This function exists only to enable template instantiation.
Definition: LeafNodeBool.h:565
Definition: Types.h:508
uint32_t countOn(uint64_t v)
Definition: Util.h:622
ValueOnCIter cbeginValueOn() const
Definition: LeafNodeBool.h:693
void writeTopology(std::ostream &os, bool toHalf=false) const
Write out just the topology.
Definition: LeafNode.h:1306
static const Index NUM_VALUES
Definition: LeafNode.h:52
bool ValueType
Definition: LeafNodeBool.h:34
const LeafNode * probeConstLeaf(const Coord &) const
Return a const pointer to this node.
Definition: LeafNodeBool.h:597
void stealNodes(ArrayT &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNodeBool.h:567
ChildOnCIter cbeginChildOn() const
Definition: LeafNodeBool.h:715
ChildOffIter beginChildOff()
Definition: LeafNodeBool.h:720
NodeMaskType & getValueMask()
Definition: LeafNodeBool.h:744
void setValue(Index i, const ValueType &)
Set the i&#39;th value of this buffer to the specified value.
Definition: LeafBuffer.h:233
Definition: Exceptions.h:13
bool isValueMaskOff(Index n) const
Definition: LeafNodeBool.h:740
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNodeBool.h:151
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:140
ChildIter< MaskOffIter, const LeafNode > ChildOffCIter
Definition: LeafNodeBool.h:689
ValueOffCIter beginValueOff() const
Definition: LeafNodeBool.h:697
void setItem(Index pos, bool value) const
Definition: LeafNodeBool.h:633
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNodeBool.h:584
Index medianOn(ValueType &value, ValueType *tmp=nullptr) const
Computes the median value of all the active voxels in this node.
Definition: LeafNode.h:1559
Index32 countOn() const
Return the total number of on bits.
Definition: NodeMasks.h:443
void setValueMaskOff(Index n)
Definition: LeafNodeBool.h:752
LeafNode * probeLeaf(const Coord &)
Return a pointer to this node.
Definition: LeafNodeBool.h:580
Index64 onLeafVoxelCount() const
Definition: LeafNodeBool.h:145
void setValueMask(Index n, bool on)
Definition: LeafNodeBool.h:750
void unsetItem(Index pos, const ValueT &val) const
Definition: LeafNodeBool.h:676
void nodeCount(std::vector< Index64 > &) const
no-op
Definition: LeafNodeBool.h:136
static Index getLevel()
Definition: LeafNodeBool.h:130
void setValueOffAndCache(const Coord &xyz, bool value, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as inactive.
Definition: LeafNodeBool.h:385
static Index dim()
Return the number of voxels in each dimension.
Definition: LeafNodeBool.h:127
static Index getValueLevel(const Coord &)
Return the level (0) at which leaf node values reside.
Definition: LeafNodeBool.h:251
std::string str() const
Return a string representation of this node.
Definition: LeafNode.h:1027
bool isOn(Index32 n) const
Return true if the nth bit is on.
Definition: NodeMasks.h:502
LeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNodeBool.h:579
ChildOffIter endChildOff()
Definition: LeafNodeBool.h:730
static Index64 offTileCount()
Definition: LeafNodeBool.h:148
bool isValueMaskOff() const
Definition: LeafNodeBool.h:741
void setValueOnUnsafe(Index offset)
Mark the voxel at the given offset as active but don&#39;t change its value.
Definition: LeafNodeBool.h:485
OutGridT const XformOp bool bool
Definition: ValueTransformer.h:609
bool isConstant(bool &isOn) const
Definition: NodeMasks.h:526
void denseFill(const CoordBBox &bbox, bool val, bool on=true)
Set all voxels within an axis-aligned box to the specified value and active state.
Definition: LeafNodeBool.h:321
ValueOnCIter cendValueOn() const
Definition: LeafNodeBool.h:703
void addTileAndCache(Index, const Coord &, const ValueType &, bool, AccessorT &)
Definition: LeafNode.h:1627
ValueAllCIter beginValueAll() const
Definition: LeafNodeBool.h:700
ChildIter< MaskOffIter, LeafNode > ChildOffIter
Definition: LeafNodeBool.h:688
void setValue(bool value) const
Definition: LeafNodeBool.h:635
const bool & getLastValue() const
Return a const reference to the last entry in the buffer.
Definition: LeafNodeBool.h:437
ValueIter< MaskDenseIter, const LeafNode, const bool > ValueAllCIter
Definition: LeafNodeBool.h:685
typename BaseT::NonConstValueType NonConstValueT
Definition: LeafNodeBool.h:660
void prune(const ValueType &=zeroVal< ValueType >())
This function exists only to enable template instantiation.
Definition: LeafNodeBool.h:556
bool isValueMaskOn(Index n) const
Definition: LeafNodeBool.h:738
Index64 memUsageIfLoaded() const
Definition: LeafNode.h:1469
ValueOffCIter cendValueOff() const
Definition: LeafNodeBool.h:706
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:569
static Index getValueLevelAndCache(const Coord &, AccessorT &)
Return the LEVEL (=0) at which leaf node values reside.
Definition: LeafNodeBool.h:428
static void getNodeLog2Dims(std::vector< Index > &dims)
Definition: LeafNodeBool.h:131
static Index getChildDim()
Definition: LeafNodeBool.h:132
static Index64 leafCount()
Definition: LeafNodeBool.h:134
const LeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNodeBool.h:596
bool probeValue(const Coord &xyz, ValueType &val) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:1091
OnIterator beginOn() const
Definition: NodeMasks.h:352
OffIterator beginOff() const
Definition: NodeMasks.h:354
typename NodeMaskType::DenseIterator MaskDenseIter
Definition: LeafNodeBool.h:616
const NodeMaskType & getValueMask() const
Definition: LeafNode.h:884
uint32_t Index32
Definition: Types.h:52
ValueOffIter endValueOff()
Definition: LeafNodeBool.h:708
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: LeafNodeBool.h:394
void getNodes(ArrayT &) const
This function exists only to enable template instantiation.
Definition: LeafNodeBool.h:566
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNodeBool.h:651
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: LeafNode.h:1064
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:141
Index64 offLeafVoxelCount() const
Definition: LeafNodeBool.h:146
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...
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: LeafNode.h:1505
NodeT * probeNode(const Coord &)
This function exists only to enable template instantiation.
Definition: LeafNodeBool.h:563
ChildOnCIter beginChildOn() const
Definition: LeafNodeBool.h:716
Index32 countOff() const
Return the total number of on bits.
Definition: NodeMasks.h:450
const bool & getValueUnsafe(Index offset) const
Return the value of the voxel at the given offset.
Definition: LeafNodeBool.h:477
void topologyUnion(const LeafNode< OtherType, Log2Dim > &other, const bool preserveTiles=false)
Union this node&#39;s set of active values with the active values of the other node, whose ValueType may ...
Definition: LeafNode.h:1710
void modifyItem(Index n, const ModifyOp &op) const
Definition: LeafNodeBool.h:639
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: LeafNode.h:1151
bool isChildMaskOn(Index) const
Definition: LeafNodeBool.h:746
void setValuesOn()
Mark all voxels as active but don&#39;t change their values.
Definition: LeafNodeBool.h:299
typename std::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:184
ChildAllCIter cendChildAll() const
Definition: LeafNodeBool.h:731
void modifyValue(const ModifyOp &op) const
Definition: LeafNodeBool.h:642
void getOrigin(Int32 &x, Int32 &y, Int32 &z) const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNodeBool.h:182
const NodeMaskType & valueMask() const
Definition: LeafNode.h:886
void setValueMaskOn(Index n)
Definition: LeafNodeBool.h:751
bool isAllocated() const
Return true if memory for this node&#39;s buffer has been allocated.
Definition: LeafNodeBool.h:157
static void evalNodeOrigin(Coord &xyz)
Compute the origin of the leaf node that contains the voxel with the given coordinates.
Definition: LeafNodeBool.h:755
bool isValueMaskOn() const
Definition: LeafNodeBool.h:739
void setValueAndCache(const Coord &xyz, bool val, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as active.
Definition: LeafNodeBool.h:374
static Index size()
Definition: LeafNodeBool.h:128
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:683
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:106
bool isChildMaskOff(Index) const
Definition: LeafNodeBool.h:747
Index medianOff(ValueType &value, ValueType *tmp=nullptr) const
Computes the median value of all the inactive voxels in this node.
Definition: LeafNode.h:1583
bool isDense() const
Return true if this node only contains active voxels.
Definition: LeafNodeBool.h:153
ChildOnIter beginChildOn()
Definition: LeafNodeBool.h:717
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: LeafNodeBool.h:306
~LeafNode()
Destructor.
Definition: LeafNode.h:1020
void load(std::istream &is)
Definition: NodeMasks.h:569
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
ValueAllCIter endValueAll() const
Definition: LeafNodeBool.h:710
void save(std::ostream &os) const
Definition: NodeMasks.h:565
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:457
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNodeBool.h:627
void combine2(const LeafNode &other, const OtherType &, bool valueIsActive, CombineOp &)
Definition: LeafNode.h:1791
ValueType combine(const ValueType &v0, const ValueType &v1, const ValueType &v2, const openvdb::Vec3d &w)
Combine different value types.
Definition: AttributeTransferUtil.h:141
ChildAllIter beginChildAll()
Definition: LeafNodeBool.h:723
Definition: PointDataGrid.h:171
Buffer & buffer()
Definition: LeafNodeBool.h:217
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:178
void setValueOnlyAndCache(const Coord &xyz, bool val, AccessorT &)
Change the value of the voxel at the given coordinates but preserve its state.
Definition: LeafNodeBool.h:380
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition: Platform.h:148
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: LeafNodeBool.h:261
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
Definition: LeafNodeBool.h:174
void fill(const ValueType &)
Populate this buffer with a constant value.
Definition: LeafBuffer.h:275
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:1191
Index32 transientData() const
Return the transient data value.
Definition: LeafNodeBool.h:194
ChildOnCIter cendChildOn() const
Definition: LeafNodeBool.h:725
bool isOff(Index32 n) const
Return true if the nth bit is off.
Definition: NodeMasks.h:508
bool operator!=(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Inequality operator, does exact floating point comparisons.
Definition: Vec3.h:482
ChildOnIter endChildOn()
Definition: LeafNodeBool.h:727
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:114
bool isInactive() const
Return true if all of this node&#39;s values are inactive.
Definition: LeafNodeBool.h:468
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNodeBool.h:601
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:689
ValueIter< MaskOffIter, const LeafNode, const bool > ValueOffCIter
Definition: LeafNodeBool.h:683
const Buffer & buffer() const
Definition: LeafNodeBool.h:216