OpenVDB  11.0.0
Iterator.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 //
4 /// @file tree/Iterator.h
5 ///
6 /// @author Peter Cucka and Ken Museth
7 
8 #ifndef OPENVDB_TREE_ITERATOR_HAS_BEEN_INCLUDED
9 #define OPENVDB_TREE_ITERATOR_HAS_BEEN_INCLUDED
10 
11 #include <sstream>
12 #include <type_traits>
13 #include <openvdb/util/NodeMasks.h>
14 #include <openvdb/Exceptions.h>
15 
16 namespace openvdb {
18 namespace OPENVDB_VERSION_NAME {
19 namespace tree {
20 
21 /// @brief Base class for iterators over internal and leaf nodes
22 ///
23 /// This class is typically not instantiated directly, since it doesn't provide methods
24 /// to dereference the iterator. Those methods (@vdblink::tree::SparseIteratorBase::operator*()
25 /// operator*()@endlink, @vdblink::tree::SparseIteratorBase::setValue() setValue()@endlink, etc.)
26 /// are implemented in the @vdblink::tree::SparseIteratorBase sparse@endlink and
27 /// @vdblink::tree::DenseIteratorBase dense@endlink iterator subclasses.
28 template<typename MaskIterT, typename NodeT>
30 {
31 public:
32  IteratorBase(): mParentNode(nullptr) {}
33  IteratorBase(const MaskIterT& iter, NodeT* parent): mParentNode(parent), mMaskIter(iter) {}
34  IteratorBase(const IteratorBase&) = default;
35  IteratorBase& operator=(const IteratorBase&) = default;
36 
37  bool operator==(const IteratorBase& other) const
38  {
39  return (mParentNode == other.mParentNode) && (mMaskIter == other.mMaskIter);
40  }
41  bool operator!=(const IteratorBase& other) const
42  {
43  return !(*this == other);
44  }
45 
46  /// Return a pointer to the node (if any) over which this iterator is iterating.
47  NodeT* getParentNode() const { return mParentNode; }
48  /// @brief Return a reference to the node over which this iterator is iterating.
49  /// @throw ValueError if there is no parent node.
50  NodeT& parent() const
51  {
52  if (!mParentNode) OPENVDB_THROW(ValueError, "iterator references a null node");
53  return *mParentNode;
54  }
55 
56  /// Return this iterator's position as an index into the parent node's table.
57  Index offset() const { return mMaskIter.offset(); }
58 
59  /// Identical to offset
60  Index pos() const { return mMaskIter.offset(); }
61 
62  /// Return @c true if this iterator is not yet exhausted.
63  bool test() const { return mMaskIter.test(); }
64  /// Return @c true if this iterator is not yet exhausted.
65  operator bool() const { return this->test(); }
66 
67  /// Advance to the next item in the parent node's table.
68  bool next() { return mMaskIter.next(); }
69  /// Advance to the next item in the parent node's table.
70  void increment() { mMaskIter.increment(); }
71  /// Advance to the next item in the parent node's table.
72  IteratorBase& operator++() { this->increment(); return *this; }
73  /// Advance @a n items in the parent node's table.
74  void increment(Index n) { mMaskIter.increment(n); }
75 
76  /// @brief Return @c true if this iterator is pointing to an active value.
77  /// Return @c false if it is pointing to either an inactive value or a child node.
78  bool isValueOn() const { return parent().isValueMaskOn(this->pos()); }
79  /// @brief If this iterator is pointing to a value, set the value's active state.
80  /// Otherwise, do nothing.
81  void setValueOn(bool on = true) const { parent().setValueMask(this->pos(), on); }
82  /// @brief If this iterator is pointing to a value, mark the value as inactive.
83  /// @details If this iterator is pointing to a child node, then the current item
84  /// in the parent node's table is required to be inactive. In that case,
85  /// this method has no effect.
86  void setValueOff() const { parent().mValueMask.setOff(this->pos()); }
87 
88  /// Return the coordinates of the item to which this iterator is pointing.
89  Coord getCoord() const { return parent().offsetToGlobalCoord(this->pos()); }
90  /// Return in @a xyz the coordinates of the item to which this iterator is pointing.
91  void getCoord(Coord& xyz) const { xyz = this->getCoord(); }
92 
93 private:
94  /// @note This parent node pointer is mutable, because setValueOn() and
95  /// setValueOff(), though const, need to call non-const methods on the parent.
96  /// There is a distinction between a const iterator (e.g., const ValueOnIter),
97  /// which is an iterator that can't be incremented, and an iterator over
98  /// a const node (e.g., ValueOnCIter), which might be const or non-const itself
99  /// but can't call non-const methods like setValue() on the node.
100  mutable NodeT* mParentNode;
101  MaskIterT mMaskIter;
102 }; // class IteratorBase
103 
104 
105 ////////////////////////////////////////
106 
107 
108 /// @brief Base class for sparse iterators over internal and leaf nodes
109 template<
110  typename MaskIterT, // mask iterator type (OnIterator, OffIterator, etc.)
111  typename IterT, // SparseIteratorBase subclass (the "Curiously Recurring Template Pattern")
112  typename NodeT, // type of node over which to iterate
113  typename ItemT> // type of value to which this iterator points
114 struct SparseIteratorBase: public IteratorBase<MaskIterT, NodeT>
115 {
116  using NodeType = NodeT;
117  using ValueType = ItemT;
118  using NonConstNodeType = typename std::remove_const<NodeT>::type;
119  using NonConstValueType = typename std::remove_const<ItemT>::type;
120  static const bool IsSparseIterator = true, IsDenseIterator = false;
121 
123  SparseIteratorBase(const MaskIterT& iter, NodeT* parent):
124  IteratorBase<MaskIterT, NodeT>(iter, parent) {}
125 
126  /// @brief Return the item at the given index in the parent node's table.
127  /// @note All subclasses must implement this accessor.
128  ItemT& getItem(Index) const;
129  /// @brief Set the value of the item at the given index in the parent node's table.
130  /// @note All non-const iterator subclasses must implement this accessor.
131  void setItem(Index, const ItemT&) const;
132 
133  /// Return a reference to the item to which this iterator is pointing.
134  ItemT& operator*() const { return this->getValue(); }
135  /// Return a pointer to the item to which this iterator is pointing.
136  ItemT* operator->() const { return &(this->operator*()); }
137 
138  /// Return the item to which this iterator is pointing.
139  ItemT& getValue() const
140  {
141  return static_cast<const IterT*>(this)->getItem(this->pos()); // static polymorphism
142  }
143  /// @brief Set the value of the item to which this iterator is pointing.
144  /// (Not valid for const iterators.)
145  void setValue(const ItemT& value) const
146  {
147  static_assert(!std::is_const<NodeT>::value, "setValue() not allowed for const iterators");
148  static_cast<const IterT*>(this)->setItem(this->pos(), value); // static polymorphism
149  }
150  /// @brief Apply a functor to the item to which this iterator is pointing.
151  /// (Not valid for const iterators.)
152  /// @param op a functor of the form <tt>void op(ValueType&) const</tt> that modifies
153  /// its argument in place
154  /// @see Tree::modifyValue()
155  template<typename ModifyOp>
156  void modifyValue(const ModifyOp& op) const
157  {
158  static_assert(!std::is_const<NodeT>::value,
159  "modifyValue() not allowed for const iterators");
160  static_cast<const IterT*>(this)->modifyItem(this->pos(), op); // static polymorphism
161  }
162 }; // class SparseIteratorBase
163 
164 
165 ////////////////////////////////////////
166 
167 
168 /// @brief Base class for dense iterators over internal and leaf nodes
169 /// @note Dense iterators have no @c %operator*() or @c %operator->(),
170 /// because their return type would have to vary depending on whether
171 /// the iterator is pointing to a value or a child node.
172 template<
173  typename MaskIterT, // mask iterator type (typically a DenseIterator)
174  typename IterT, // DenseIteratorBase subclass (the "Curiously Recurring Template Pattern")
175  typename NodeT, // type of node over which to iterate
176  typename SetItemT, // type of set value (ChildNodeType, for non-leaf nodes)
177  typename UnsetItemT> // type of unset value (ValueType, usually)
178 struct DenseIteratorBase: public IteratorBase<MaskIterT, NodeT>
179 {
180  using NodeType = NodeT;
181  using ValueType = UnsetItemT;
182  using ChildNodeType = SetItemT;
183  using NonConstNodeType = typename std::remove_const<NodeT>::type;
184  using NonConstValueType = typename std::remove_const<UnsetItemT>::type;
185  using NonConstChildNodeType = typename std::remove_const<SetItemT>::type;
186  static const bool IsSparseIterator = false, IsDenseIterator = true;
187 
189  DenseIteratorBase(const MaskIterT& iter, NodeT* parent):
190  IteratorBase<MaskIterT, NodeT>(iter, parent) {}
191 
192  /// @brief Return @c true if the item at the given index in the parent node's table
193  /// is a set value and return either the set value in @a child or the unset value
194  /// in @a value.
195  /// @note All subclasses must implement this accessor.
196  bool getItem(Index, SetItemT*& child, NonConstValueType& value) const;
197  /// @brief Set the value of the item at the given index in the parent node's table.
198  /// @note All non-const iterator subclasses must implement this accessor.
199  void setItem(Index, SetItemT*) const;
200  /// @brief "Unset" the value of the item at the given index in the parent node's table.
201  /// @note All non-const iterator subclasses must implement this accessor.
202  void unsetItem(Index, const UnsetItemT&) const;
203 
204  /// Return @c true if this iterator is pointing to a child node.
205  bool isChildNode() const { return this->parent().isChildMaskOn(this->pos()); }
206 
207  /// @brief If this iterator is pointing to a child node, return a pointer to the node.
208  /// Otherwise, return nullptr and, in @a value, the value to which this iterator is pointing.
209  SetItemT* probeChild(NonConstValueType& value) const
210  {
211  SetItemT* child = nullptr;
212  static_cast<const IterT*>(this)->getItem(this->pos(), child, value); // static polymorphism
213  return child;
214  }
215  /// @brief If this iterator is pointing to a child node, return @c true and return
216  /// a pointer to the child node in @a child. Otherwise, return @c false and return
217  /// the value to which this iterator is pointing in @a value.
218  bool probeChild(SetItemT*& child, NonConstValueType& value) const
219  {
220  child = probeChild(value);
221  return (child != nullptr);
222  }
223 
224  /// @brief Return @c true if this iterator is pointing to a value and return
225  /// the value in @a value. Otherwise, return @c false.
226  bool probeValue(NonConstValueType& value) const
227  {
228  SetItemT* child = nullptr;
229  const bool isChild = static_cast<const IterT*>(this)-> // static polymorphism
230  getItem(this->pos(), child, value);
231  return !isChild;
232  }
233 
234  /// @brief Replace with the given child node the item in the parent node's table
235  /// to which this iterator is pointing.
236  void setChild(SetItemT* child) const
237  {
238  static_cast<const IterT*>(this)->setItem(this->pos(), child); // static polymorphism
239  }
240 
241  /// @brief Replace with the given value the item in the parent node's table
242  /// to which this iterator is pointing.
243  void setValue(const UnsetItemT& value) const
244  {
245  static_cast<const IterT*>(this)->unsetItem(this->pos(), value); // static polymorphism
246  }
247 }; // struct DenseIteratorBase
248 
249 } // namespace tree
250 } // namespace OPENVDB_VERSION_NAME
251 } // namespace openvdb
252 
253 #endif // OPENVDB_TREE_ITERATOR_HAS_BEEN_INCLUDED
Definition: Exceptions.h:65
SetItemT * probeChild(NonConstValueType &value) const
If this iterator is pointing to a child node, return a pointer to the node. Otherwise, return nullptr and, in value, the value to which this iterator is pointing.
Definition: Iterator.h:209
bool next()
Advance to the next item in the parent node&#39;s table.
Definition: Iterator.h:68
IteratorBase(const MaskIterT &iter, NodeT *parent)
Definition: Iterator.h:33
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:29
bool operator!=(const IteratorBase &other) const
Definition: Iterator.h:41
DenseIteratorBase(const MaskIterT &iter, NodeT *parent)
Definition: Iterator.h:189
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition: Mat3.h:597
void setChild(SetItemT *child) const
Replace with the given child node the item in the parent node&#39;s table to which this iterator is point...
Definition: Iterator.h:236
bool isChildNode() const
Return true if this iterator is pointing to a child node.
Definition: Iterator.h:205
void getCoord(Coord &xyz) const
Return in xyz the coordinates of the item to which this iterator is pointing.
Definition: Iterator.h:91
void increment(Index n)
Advance n items in the parent node&#39;s table.
Definition: Iterator.h:74
Index pos() const
Identical to offset.
Definition: Iterator.h:60
NodeT * getParentNode() const
Return a pointer to the node (if any) over which this iterator is iterating.
Definition: Iterator.h:47
NodeT & parent() const
Return a reference to the node over which this iterator is iterating.
Definition: Iterator.h:50
ItemT & operator*() const
Return a reference to the item to which this iterator is pointing.
Definition: Iterator.h:134
IteratorBase & operator++()
Advance to the next item in the parent node&#39;s table.
Definition: Iterator.h:72
Coord getCoord() const
Return the coordinates of the item to which this iterator is pointing.
Definition: Iterator.h:89
bool test() const
Return true if this iterator is not yet exhausted.
Definition: Iterator.h:63
void setValueOff() const
If this iterator is pointing to a value, mark the value as inactive.
Definition: Iterator.h:86
Definition: Exceptions.h:13
SparseIteratorBase()
Definition: Iterator.h:122
Index offset() const
Return this iterator&#39;s position as an index into the parent node&#39;s table.
Definition: Iterator.h:57
void setValue(const UnsetItemT &value) const
Replace with the given value the item in the parent node&#39;s table to which this iterator is pointing...
Definition: Iterator.h:243
ItemT & getValue() const
Return the item to which this iterator is pointing.
Definition: Iterator.h:139
bool probeValue(NonConstValueType &value) const
Return true if this iterator is pointing to a value and return the value in value. Otherwise, return false.
Definition: Iterator.h:226
bool isValueOn() const
Return true if this iterator is pointing to an active value. Return false if it is pointing to either...
Definition: Iterator.h:78
Index32 Index
Definition: Types.h:54
SparseIteratorBase(const MaskIterT &iter, NodeT *parent)
Definition: Iterator.h:123
bool operator==(const IteratorBase &other) const
Definition: Iterator.h:37
bool probeChild(SetItemT *&child, NonConstValueType &value) const
If this iterator is pointing to a child node, return true and return a pointer to the child node in c...
Definition: Iterator.h:218
DenseIteratorBase()
Definition: Iterator.h:188
void increment()
Advance to the next item in the parent node&#39;s table.
Definition: Iterator.h:70
void setValueOn(bool on=true) const
If this iterator is pointing to a value, set the value&#39;s active state. Otherwise, do nothing...
Definition: Iterator.h:81
void setValue(const ItemT &value) const
Set the value of the item to which this iterator is pointing. (Not valid for const iterators...
Definition: Iterator.h:145
ItemT * operator->() const
Return a pointer to the item to which this iterator is pointing.
Definition: Iterator.h:136
void modifyValue(const ModifyOp &op) const
Apply a functor to the item to which this iterator is pointing. (Not valid for const iterators...
Definition: Iterator.h:156
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:114
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:178
IteratorBase()
Definition: Iterator.h:32
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212