OpenVDB 13.0.1
Loading...
Searching...
No Matches
NodeVisitor.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3//
4/// @file NodeVisitor.h
5///
6/// @author Dan Bailey
7///
8/// @brief Implementation of a depth-first node visitor.
9///
10/// @note This algorithm is single-threaded by design and intended for rare
11/// use cases where this is desirable. It is highly recommended to use
12/// the NodeManager or DynamicNodeManager for much greater threaded
13/// performance.
14
15#ifndef OPENVDB_TOOLS_NODE_VISITOR_HAS_BEEN_INCLUDED
16#define OPENVDB_TOOLS_NODE_VISITOR_HAS_BEEN_INCLUDED
17
18#include <openvdb/version.h>
19#include <openvdb/Types.h>
20
21namespace openvdb {
23namespace OPENVDB_VERSION_NAME {
24namespace tools {
25
26/// @brief Visit all nodes in the tree depth-first and apply a user-supplied
27/// functor to each node.
28///
29/// @param tree tree to be visited.
30/// @param op user-supplied functor, see examples for interface details.
31/// @param idx optional offset to start sequential node indexing from a
32/// non-zero index.
33/// @param topDown if true, visit parent nodes before their children
34/// (pre-order traversal). If false, visit children before
35/// their parent nodes (post-order traversal). Defaults to true.
36///
37/// @warning This method is single-threaded. Use the NodeManager or
38/// DynamicNodeManager for much greater threaded performance.
39///
40/// @par Example:
41/// @code
42/// Functor to offset all the active values of a tree.
43/// struct OffsetOp
44/// {
45/// OffsetOp(float v): mOffset(v) { }
46///
47/// template<typename NodeT>
48/// void operator()(NodeT& node, size_t) const
49/// {
50/// for (auto iter = node.beginValueOn(); iter; ++iter) {
51/// iter.setValue(iter.getValue() + mOffset);
52/// }
53/// }
54/// private:
55/// const float mOffset;
56/// };
57///
58/// // usage:
59/// OffsetOp op(3.0f);
60/// visitNodesDepthFirst(tree, op);
61///
62/// // Functor to offset all the active values of a tree. Note
63/// // this implementation also illustrates how different
64/// // computation can be applied to the different node types.
65/// template<typename TreeT>
66/// struct OffsetByLevelOp
67/// {
68/// using ValueT = typename TreeT::ValueType;
69/// using RootT = typename TreeT::RootNodeType;
70/// using LeafT = typename TreeT::LeafNodeType;
71/// OffsetByLevelOp(const ValueT& v) : mOffset(v) {}
72/// // Processes the root node.
73/// void operator()(RootT& root, size_t) const
74/// {
75/// for (auto iter = root.beginValueOn(); iter; ++iter) {
76/// iter.setValue(iter.getValue() + mOffset);
77/// }
78/// }
79/// // Processes the leaf nodes.
80/// void operator()(LeafT& leaf, size_t) const
81/// {
82/// for (auto iter = leaf.beginValueOn(); iter; ++iter) {
83/// iter.setValue(iter.getValue() + mOffset);
84/// }
85/// }
86/// // Processes the internal nodes.
87/// template<typename NodeT>
88/// void operator()(NodeT& node, size_t) const
89/// {
90/// for (auto iter = node.beginValueOn(); iter; ++iter) {
91/// iter.setValue(iter.getValue() + mOffset);
92/// }
93/// }
94/// private:
95/// const ValueT mOffset;
96/// };
97///
98/// // usage:
99/// OffsetByLevelOp<FloatTree> op(3.0f);
100/// visitNodesDepthFirst(tree, op);
101///
102/// @endcode
103///
104/// @par Here is an example when migrating from using the deprecated Tree::visit()
105/// method. The main difference between the Tree::visit() method and this new
106/// method is that the Tree::visit() method expected an object that can visit
107/// tiles, values and nodes. In contrast, the visitNodesDepthFirst() method
108/// visits only nodes and expects you to provide iteration over tiles and
109/// voxels.
110///
111/// @par Tree::visit() operator methods:
112///
113/// @code
114/// template <typename IterT>
115/// bool operator()(IterT &iter)
116/// {
117/// typename IterT::NonConstValueType value;
118/// typename IterT::ChildNodeType *child = iter.probeChild(value);
119///
120/// if (child)
121/// {
122/// // If it is a leaf, process it now
123/// if (child->getLevel() == 0)
124/// {
125/// processNode(*child);
126/// return true;
127/// }
128/// // Otherwise, we want to keep digging down
129/// return false;
130/// }
131///
132/// // No child, this is a constant node!
133/// if (iter.isValueOn())
134/// {
135/// openvdb::CoordBBox b;
136/// b.min() = iter.getCoord();
137/// b.max() = b.min().offsetBy(IterT::ChildNodeType::DIM);
138///
139/// processNodeBlock(b);
140/// }
141///
142/// // No need to dig further as there is no child.
143/// return true;
144/// }
145///
146/// bool operator()(typename GridType::TreeType::LeafNodeType::ChildAllIter &)
147/// { return true; }
148/// bool operator()(typename GridType::TreeType::LeafNodeType::ChildAllCIter &)
149/// { return true; }
150///
151/// @endcode
152///
153/// @par tools::visitNodesDepthFirst() operator methods:
154///
155/// @code
156/// using LeafT = typename GridType::TreeType::LeafNodeType;
157///
158/// template <typename NodeT>
159/// void operator()(const NodeT &node, size_t)
160/// {
161/// // iterate over active tiles
162/// for (auto iter = node.beginValueOn(); iter; ++iter)
163/// {
164/// openvdb::CoordBBox b;
165/// b.min() = iter.getCoord();
166/// b.max() = b.min().offsetBy(NodeT::ChildNodeType::DIM);
167///
168/// processNodeBlock(b);
169/// }
170/// }
171///
172/// void operator()(const LeafT &leaf, size_t)
173/// {
174/// processNode(leaf);
175/// }
176///
177/// @endcode
178template <typename TreeT, typename OpT>
179size_t visitNodesDepthFirst(TreeT& tree, OpT& op, size_t idx = 0, bool topDown = true);
180
181
182/// @brief Visit all nodes that are downstream of a specific node in
183/// depth-first order and apply a user-supplied functor to each node.
184///
185/// @note This uses the same operator interface as documented in
186/// visitNodesDepthFirst().
187///
188/// @note The LEVEL template argument can be used to reduce the traversal
189/// depth. For example, calling visit() with a RootNode and using
190/// NodeT::LEVEL-1 would not visit leaf nodes.
191template <typename NodeT, Index LEVEL = NodeT::LEVEL>
192struct DepthFirstNodeVisitor;
193
194
195////////////////////////////////////////
196
197
198template <typename NodeT, Index LEVEL>
200{
201 using NonConstChildType = typename NodeT::ChildNodeType;
203
204 template <typename OpT>
205 static size_t visit(NodeT& node, OpT& op, size_t idx = 0, bool topDown = true)
206 {
207 size_t offset = 0;
208 if (topDown) op(node, idx + offset++);
209 for (auto iter = node.beginChildOn(); iter; ++iter) {
211 *iter, op, idx + offset, topDown);
212 }
213 if (!topDown) op(node, idx + offset++);
214 return offset;
215 }
216};
217
218
219// terminate recursion
220template <typename NodeT>
221struct DepthFirstNodeVisitor<NodeT, 0>
222{
223 template <typename OpT>
224 static size_t visit(NodeT& node, OpT& op, size_t idx = 0, bool /*topDown*/ = true)
225 {
226 op(node, idx);
227 return size_t(1);
228 }
229};
230
231
232template <typename TreeT, typename OpT>
233size_t visitNodesDepthFirst(TreeT& tree, OpT& op, size_t idx, bool topDown)
234{
235 using NonConstRootNodeType = typename TreeT::RootNodeType;
236 using RootNodeType = typename CopyConstness<TreeT, NonConstRootNodeType>::Type;
237
238 return DepthFirstNodeVisitor<RootNodeType>::visit(tree.root(), op, idx, topDown);
239}
240
241
242} // namespace tools
243} // namespace OPENVDB_VERSION_NAME
244} // namespace openvdb
245
246#endif // OPENVDB_TOOLS_NODE_VISITOR_HAS_BEEN_INCLUDED
size_t visitNodesDepthFirst(TreeT &tree, OpT &op, size_t idx=0, bool topDown=true)
Visit all nodes in the tree depth-first and apply a user-supplied functor to each node.
Definition NodeVisitor.h:233
Definition PointDataGrid.h:170
Definition Exceptions.h:13
typename std::remove_const< ToType >::type Type
Definition Types.h:495
static size_t visit(NodeT &node, OpT &op, size_t idx=0, bool=true)
Definition NodeVisitor.h:224
Visit all nodes that are downstream of a specific node in depth-first order and apply a user-supplied...
Definition NodeVisitor.h:200
static size_t visit(NodeT &node, OpT &op, size_t idx=0, bool topDown=true)
Definition NodeVisitor.h:205
typename CopyConstness< NodeT, NonConstChildType >::Type ChildNodeType
Definition NodeVisitor.h:202
typename NodeT::ChildNodeType NonConstChildType
Definition NodeVisitor.h:201
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:284