OpenVDB  12.0.0
Activate.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 Activate.h
5 ///
6 /// @brief Implementation of topological activation/deactivation
7 ///
8 /// @author Ken Museth
9 ///
10 
11 #ifndef OPENVDB_TOOLS_ACTIVATE_HAS_BEEN_INCLUDED
12 #define OPENVDB_TOOLS_ACTIVATE_HAS_BEEN_INCLUDED
13 
14 #include <openvdb/Types.h>
15 #include <openvdb/Grid.h>
16 #include <openvdb/math/Math.h> // for isApproxEqual()
18 #include <openvdb/openvdb.h>
20 
21 
22 namespace openvdb {
24 namespace OPENVDB_VERSION_NAME {
25 namespace tools {
26 
27 /// @brief Mark as active any inactive tiles or voxels in the given grid or tree
28 /// whose values are equal to @a value (optionally to within the given @a tolerance).
29 template<typename GridOrTree>
30 void activate(
31  GridOrTree&,
32  const typename GridOrTree::ValueType& value,
33  const typename GridOrTree::ValueType& tolerance = zeroVal<typename GridOrTree::ValueType>(),
34  const bool threaded = true
35 );
36 
37 
38 /// @brief Mark as inactive any active tiles or voxels in the given grid or tree
39 /// whose values are equal to @a value (optionally to within the given @a tolerance).
40 template<typename GridOrTree>
41 void deactivate(
42  GridOrTree&,
43  const typename GridOrTree::ValueType& value,
44  const typename GridOrTree::ValueType& tolerance = zeroVal<typename GridOrTree::ValueType>(),
45  const bool threaded = true
46 );
47 
48 
49 ////////////////////////////////////////
50 
51 
52 /// @cond OPENVDB_DOCS_INTERNAL
53 
54 namespace activate_internal {
55 
56 template<typename TreeT, bool IgnoreTolerance = false>
57 struct ActivateOp
58 {
59 public:
60  using RootT = typename TreeT::RootNodeType;
61  using LeafT = typename TreeT::LeafNodeType;
62  using ValueT = typename TreeT::ValueType;
63 
64  explicit ActivateOp(const ValueT& value,
65  const ValueT& tolerance = zeroVal<ValueT>())
66  : mValue(value)
67  , mTolerance(tolerance) { }
68 
69  inline bool check(const ValueT& value) const {
70  // math::isApproxEqual is marginally more expensive,
71  // so opt to do direct comparison if tolerance is ignored
72  if (IgnoreTolerance) return value == mValue;
73  return math::isApproxEqual(value, mValue, mTolerance);
74  }
75 
76  bool operator()(RootT& root, size_t) const
77  {
78  for (auto it = root.beginValueOff(); it; ++it) {
79  if (check(*it)) it.setValueOn(/*on=*/true);
80  }
81  return true;
82  }
83 
84  template<typename NodeT>
85  bool operator()(NodeT& node, size_t) const
86  {
87  // only iterate if there are inactive tiles
88  if (!node.isValueMaskOn()) {
89  for (auto it = node.beginValueOff(); it; ++it) {
90  // Skip child nodes, they'll be processed separately
91  // (InteralNode ValueOff iterators don't automatically
92  // skip these).
93  if (node.isChildMaskOn(it.pos())) continue;
94  if (check(*it)) it.setValueOn(/*on=*/true);
95  }
96  }
97  // return false if there are no child nodes below this node
98  return !node.isChildMaskOff();
99  }
100 
101  bool operator()(LeafT& leaf, size_t) const
102  {
103  // early-exit if there are no inactive values
104  if (leaf.isValueMaskOn()) return true;
105  for (auto it = leaf.beginValueOff(); it; ++it) {
106  if (check(*it)) it.setValueOn(/*on=*/true);
107  }
108  return true;
109  }
110 
111 private:
112  const ValueT mValue;
113  const ValueT mTolerance;
114 };// ActivateOp
115 
116 template<typename TreeT, bool IgnoreTolerance = false>
117 struct DeactivateOp
118 {
119 public:
120  using RootT = typename TreeT::RootNodeType;
121  using LeafT = typename TreeT::LeafNodeType;
122  using ValueT = typename TreeT::ValueType;
123 
124  explicit DeactivateOp(const ValueT& value,
125  const ValueT& tolerance = zeroVal<ValueT>())
126  : mValue(value)
127  , mTolerance(tolerance) { }
128 
129  inline bool check(const ValueT& value) const {
130  if (IgnoreTolerance) return value == mValue;
131  return math::isApproxEqual(value, mValue, mTolerance);
132  }
133 
134  bool operator()(RootT& root, size_t) const
135  {
136  for (auto it = root.beginValueOn(); it; ++it) {
137  if (check(*it)) it.setValueOn(/*on=*/false);
138  }
139  return true;
140  }
141 
142  template<typename NodeT>
143  bool operator()(NodeT& node, size_t) const
144  {
145  // only iterate if there are active tiles
146  if (!node.isValueMaskOff()) {
147  for (auto it = node.beginValueOn(); it; ++it) {
148  if (check(*it)) it.setValueOn(/*on=*/false);
149  }
150  }
151  // return false if there are no child nodes below this node
152  return !node.isChildMaskOff();
153  }
154 
155  bool operator()(LeafT& leaf, size_t) const
156  {
157  // early-exit if there are no active values
158  if (leaf.isValueMaskOff()) return true;
159  for (auto it = leaf.beginValueOn(); it; ++it) {
160  if (check(*it)) it.setValueOn(/*on=*/false);
161  }
162  return true;
163  }
164 
165 private:
166  const ValueT mValue;
167  const ValueT mTolerance;
168 };// DeactivateOp
169 
170 } // namespace activate_internal
171 
172 /// @endcond
173 
174 
175 ////////////////////////////////////////
176 
177 
178 template<typename GridOrTree>
179 void activate(GridOrTree& gridOrTree,
180  const typename GridOrTree::ValueType& value,
181  const typename GridOrTree::ValueType& tolerance,
182  const bool threaded)
183 {
184  using Adapter = TreeAdapter<GridOrTree>;
185  using TreeType = typename Adapter::TreeType;
186  using ValueType = typename TreeType::ValueType;
187 
188  TreeType& tree = Adapter::tree(gridOrTree);
189 
190  tree::DynamicNodeManager<TreeType> nodeManager(tree);
191 
192  if (tolerance == zeroVal<ValueType>()) {
193  activate_internal::ActivateOp<TreeType, /*IgnoreTolerance=*/true> op(value);
194  nodeManager.foreachTopDown(op, threaded);
195  } else {
196  activate_internal::ActivateOp<TreeType> op(value, tolerance);
197  nodeManager.foreachTopDown(op, threaded);
198  }
199 }
200 
201 
202 template<typename GridOrTree>
203 void deactivate(GridOrTree& gridOrTree,
204  const typename GridOrTree::ValueType& value,
205  const typename GridOrTree::ValueType& tolerance,
206  const bool threaded)
207 {
208  using Adapter = TreeAdapter<GridOrTree>;
209  using TreeType = typename Adapter::TreeType;
210  using ValueType = typename TreeType::ValueType;
211 
212  TreeType& tree = Adapter::tree(gridOrTree);
213 
214  tree::DynamicNodeManager<TreeType> nodeManager(tree);
215 
216  if (tolerance == zeroVal<ValueType>()) {
217  activate_internal::DeactivateOp<TreeType, /*IgnoreTolerance=*/true> op(value);
218  nodeManager.foreachTopDown(op, threaded);
219  } else {
220  activate_internal::DeactivateOp<TreeType> op(value, tolerance);
221  nodeManager.foreachTopDown(op, threaded);
222  }
223 }
224 
225 
226 ////////////////////////////////////////
227 
228 
229 // Explicit Template Instantiation
230 
231 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
232 
233 #ifdef OPENVDB_INSTANTIATE_ACTIVATE
235 #endif
236 
237 #define _FUNCTION(TreeT) \
238  void activate(TreeT&, const TreeT::ValueType&, const TreeT::ValueType&, const bool)
240 #undef _FUNCTION
241 
242 #define _FUNCTION(TreeT) \
243  void activate(Grid<TreeT>&, const TreeT::ValueType&, const TreeT::ValueType&, const bool)
245 #undef _FUNCTION
246 
247 #define _FUNCTION(TreeT) \
248  void deactivate(TreeT&, const TreeT::ValueType&, const TreeT::ValueType&, const bool)
250 #undef _FUNCTION
251 
252 #define _FUNCTION(TreeT) \
253  void deactivate(Grid<TreeT>&, const TreeT::ValueType&, const TreeT::ValueType&, const bool)
255 #undef _FUNCTION
256 
257 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
258 
259 
260 } // namespace tools
261 } // namespace OPENVDB_VERSION_NAME
262 } // namespace openvdb
263 
264 #endif // OPENVDB_TOOLS_ACTIVATE_HAS_BEEN_INCLUDED
void foreachTopDown(const NodeOp &op, bool threaded=true, size_t leafGrainSize=1, size_t nonLeafGrainSize=1)
Threaded method that applies a user-supplied functor to all the nodes in the tree.
Definition: NodeManager.h:977
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
void deactivate(GridOrTree &, const typename GridOrTree::ValueType &value, const typename GridOrTree::ValueType &tolerance=zeroVal< typename GridOrTree::ValueType >(), const bool threaded=true)
Mark as inactive any active tiles or voxels in the given grid or tree whose values are equal to value...
Definition: Activate.h:203
Definition: NodeManager.h:37
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition: Math.h:406
OutGridT XformOp & op
Definition: ValueTransformer.h:139
#define OPENVDB_ALL_TREE_INSTANTIATE(Function)
Definition: version.h.in:166
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1059
OutGridT XformOp bool threaded
Definition: ValueTransformer.h:140
Definition: Exceptions.h:13
void activate(GridOrTree &, const typename GridOrTree::ValueType &value, const typename GridOrTree::ValueType &tolerance=zeroVal< typename GridOrTree::ValueType >(), const bool threaded=true)
Mark as active any inactive tiles or voxels in the given grid or tree whose values are equal to value...
Definition: Activate.h:179
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
#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:218