OpenVDB 7.0.0

Prune.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 //
9
10 #ifndef OPENVDB_TOOLS_PRUNE_HAS_BEEN_INCLUDED
11 #define OPENVDB_TOOLS_PRUNE_HAS_BEEN_INCLUDED
12
13 #include <openvdb/math/Math.h> // for isNegative and negative
14 #include <openvdb/Types.h>
15 #include <openvdb/tree/NodeManager.h>
16 #include <algorithm> // for std::nth_element()
17 #include <type_traits>
18
19 namespace openvdb {
20 OPENVDB_USE_VERSION_NAMESPACE
21 namespace OPENVDB_VERSION_NAME {
22 namespace tools {
23
36 template<typename TreeT>
37 inline void
38 prune(TreeT& tree,
39 typename TreeT::ValueType tolerance = zeroVal<typename TreeT::ValueType>(),
40 bool threaded = true,
41 size_t grainSize = 1);
42
43
52 template<typename TreeT>
53 inline void
54 pruneTiles(TreeT& tree,
55 typename TreeT::ValueType tolerance = zeroVal<typename TreeT::ValueType>(),
56 bool threaded = true,
57 size_t grainSize = 1);
58
59
66 template<typename TreeT>
67 inline void
68 pruneInactive(TreeT& tree, bool threaded = true, size_t grainSize = 1);
69
70
78 template<typename TreeT>
79 inline void
80 pruneInactiveWithValue(
81 TreeT& tree,
82 const typename TreeT::ValueType& value,
83 bool threaded = true,
84 size_t grainSize = 1);
85
86
99 template<typename TreeT>
100 inline void
101 pruneLevelSet(TreeT& tree,
102 bool threaded = true,
103 size_t grainSize = 1);
104
105
122 template<typename TreeT>
123 inline void
124 pruneLevelSet(TreeT& tree,
125 const typename TreeT::ValueType& outsideWidth,
126 const typename TreeT::ValueType& insideWidth,
127 bool threaded = true,
128 size_t grainSize = 1);
129
130
132
133
134 template<typename TreeT, Index TerminationLevel = 0>
135 class InactivePruneOp
136 {
137 public:
138 using ValueT = typename TreeT::ValueType;
139 using RootT = typename TreeT::RootNodeType;
140 using LeafT = typename TreeT::LeafNodeType;
141 static_assert(RootT::LEVEL > TerminationLevel, "TerminationLevel out of range");
142
143 InactivePruneOp(TreeT& tree) : mValue(tree.background())
144 {
145 tree.clearAllAccessors();//clear cache of nodes that could be pruned
146 }
147
148 InactivePruneOp(TreeT& tree, const ValueT& v) : mValue(v)
149 {
150 tree.clearAllAccessors();//clear cache of nodes that could be pruned
151 }
152
153 // Nothing to do at the leaf node level
154 void operator()(LeafT&) const {}
155
156 // Prune the child nodes of the internal nodes
157 template<typename NodeT>
158 void operator()(NodeT& node) const
159 {
160 if (NodeT::LEVEL > TerminationLevel) {
161 for (typename NodeT::ChildOnIter it=node.beginChildOn(); it; ++it) {
162 if (it->isInactive()) node.addTile(it.pos(), mValue, false);
163 }
164 }
165 }
166
167 // Prune the child nodes of the root node
168 void operator()(RootT& root) const
169 {
170 for (typename RootT::ChildOnIter it = root.beginChildOn(); it; ++it) {
171 if (it->isInactive()) root.addTile(it.getCoord(), mValue, false);
172 }
173 root.eraseBackgroundTiles();
174 }
175
176 private:
177 const ValueT mValue;
178 };// InactivePruneOp
179
180
181 template<typename TreeT, Index TerminationLevel = 0>
182 class TolerancePruneOp
183 {
184 public:
185 using ValueT = typename TreeT::ValueType;
186 using RootT = typename TreeT::RootNodeType;
187 using LeafT = typename TreeT::LeafNodeType;
188 static_assert(RootT::LEVEL > TerminationLevel, "TerminationLevel out of range");
189
190 TolerancePruneOp(TreeT& tree, const ValueT& tol) : mTolerance(tol)
191 {
192 tree.clearAllAccessors();//clear cache of nodes that could be pruned
193 }
194
195 // Prune the child nodes of the root node
196 inline void operator()(RootT& root) const
197 {
198 ValueT value;
199 bool state;
200 for (typename RootT::ChildOnIter it = root.beginChildOn(); it; ++it) {
201 if (this->isConstant(*it, value, state)) root.addTile(it.getCoord(), value, state);
202 }
203 root.eraseBackgroundTiles();
204 }
205
206 // Prune the child nodes of the internal nodes
207 template<typename NodeT>
208 inline void operator()(NodeT& node) const
209 {
210 if (NodeT::LEVEL > TerminationLevel) {
211 ValueT value;
212 bool state;
213 for (typename NodeT::ChildOnIter it=node.beginChildOn(); it; ++it) {
214 if (this->isConstant(*it, value, state)) node.addTile(it.pos(), value, state);
215 }
216 }
217 }
218
219 // Nothing to do at the leaf node level
220 inline void operator()(LeafT&) const {}
221
222 private:
223 // Private method specialized for leaf nodes
224 inline ValueT median(LeafT& leaf) const {return leaf.medianAll(leaf.buffer().data());}
225
226 // Private method for internal nodes
227 template<typename NodeT>
228 inline typename NodeT::ValueType median(NodeT& node) const
229 {
230 using UnionT = typename NodeT::UnionType;
231 UnionT* data = const_cast<UnionT*>(node.getTable());//never do this at home kids :)
232 static const size_t midpoint = (NodeT::NUM_VALUES - 1) >> 1;
233 auto op = [](const UnionT& a, const UnionT& b){return a.getValue() < b.getValue();};
234 std::nth_element(data, data + midpoint, data + NodeT::NUM_VALUES, op);
235 return data[midpoint].getValue();
236 }
237
238 // Specialization to nodes templated on booleans values
239 template<typename NodeT>
240 inline
241 typename std::enable_if<std::is_same<bool, typename NodeT::ValueType>::value, bool>::type
242 isConstant(NodeT& node, bool& value, bool& state) const
243 {
244 return node.isConstant(value, state, mTolerance);
245 }
246
247 // Nodes templated on non-boolean values
248 template<typename NodeT>
249 inline
250 typename std::enable_if<!std::is_same<bool, typename NodeT::ValueType>::value, bool>::type
251 isConstant(NodeT& node, ValueT& value, bool& state) const
252 {
253 ValueT tmp;
254 const bool test = node.isConstant(value, tmp, state, mTolerance);
255 if (test) value = this->median(node);
256 return test;
257 }
258
259 const ValueT mTolerance;
260 };// TolerancePruneOp
261
262
263 template<typename TreeT, Index TerminationLevel = 0>
264 class LevelSetPruneOp
265 {
266 public:
267 using ValueT = typename TreeT::ValueType;
268 using RootT = typename TreeT::RootNodeType;
269 using LeafT = typename TreeT::LeafNodeType;
270 static_assert(RootT::LEVEL > TerminationLevel, "TerminationLevel out of range");
271
272 LevelSetPruneOp(TreeT& tree)
273 : mOutside(tree.background())
274 , mInside(math::negative(mOutside))
275 {
276 if (math::isNegative(mOutside)) {
277 OPENVDB_THROW(ValueError,
278 "LevelSetPruneOp: the background value cannot be negative!");
279 }
280 tree.clearAllAccessors();//clear cache of nodes that could be pruned
281 }
282
283 LevelSetPruneOp(TreeT& tree, const ValueT& outside, const ValueT& inside)
284 : mOutside(outside)
285 , mInside(inside)
286 {
287 if (math::isNegative(mOutside)) {
288 OPENVDB_THROW(ValueError,
289 "LevelSetPruneOp: the outside value cannot be negative!");
290 }
291 if (!math::isNegative(mInside)) {
292 OPENVDB_THROW(ValueError,
293 "LevelSetPruneOp: the inside value must be negative!");
294 }
295 tree.clearAllAccessors();//clear cache of nodes that could be pruned
296 }
297
298 // Nothing to do at the leaf node level
299 void operator()(LeafT&) const {}
300
301 // Prune the child nodes of the internal nodes
302 template<typename NodeT>
303 void operator()(NodeT& node) const
304 {
305 if (NodeT::LEVEL > TerminationLevel) {
306 for (typename NodeT::ChildOnIter it=node.beginChildOn(); it; ++it) {
307 if (it->isInactive()) node.addTile(it.pos(), this->getTileValue(it), false);
308 }
309 }
310 }
311
312 // Prune the child nodes of the root node
313 void operator()(RootT& root) const
314 {
315 for (typename RootT::ChildOnIter it = root.beginChildOn(); it; ++it) {
316 if (it->isInactive()) root.addTile(it.getCoord(), this->getTileValue(it), false);
317 }
318 root.eraseBackgroundTiles();
319 }
320
321 private:
322 template <typename IterT>
323 inline ValueT getTileValue(const IterT& iter) const
324 {
325 return math::isNegative(iter->getFirstValue()) ? mInside : mOutside;
326 }
327
328 const ValueT mOutside, mInside;
329 };// LevelSetPruneOp
330
331
332 template<typename TreeT>
333 inline void
334 prune(TreeT& tree, typename TreeT::ValueType tol, bool threaded, size_t grainSize)
335 {
336 tree::NodeManager<TreeT, TreeT::DEPTH-2> nodes(tree);
337 TolerancePruneOp<TreeT> op(tree, tol);
338 nodes.foreachBottomUp(op, threaded, grainSize);
339 }
340
341
342 template<typename TreeT>
343 inline void
344 pruneTiles(TreeT& tree, typename TreeT::ValueType tol, bool threaded, size_t grainSize)
345 {
346 tree::NodeManager<TreeT, TreeT::DEPTH-3> nodes(tree);
347 TolerancePruneOp<TreeT> op(tree, tol);
348 nodes.foreachBottomUp(op, threaded, grainSize);
349 }
350
351
352 template<typename TreeT>
353 inline void
354 pruneInactive(TreeT& tree, bool threaded, size_t grainSize)
355 {
356 tree::NodeManager<TreeT, TreeT::DEPTH-2> nodes(tree);
357 InactivePruneOp<TreeT> op(tree);
358 nodes.foreachBottomUp(op, threaded, grainSize);
359 }
360
361
362 template<typename TreeT>
363 inline void
364 pruneInactiveWithValue(TreeT& tree, const typename TreeT::ValueType& v,
365 bool threaded, size_t grainSize)
366 {
367 tree::NodeManager<TreeT, TreeT::DEPTH-2> nodes(tree);
368 InactivePruneOp<TreeT> op(tree, v);
369 nodes.foreachBottomUp(op, threaded, grainSize);
370 }
371
372
373 template<typename TreeT>
374 inline void
375 pruneLevelSet(TreeT& tree,
376 const typename TreeT::ValueType& outside,
377 const typename TreeT::ValueType& inside,
378 bool threaded,
379 size_t grainSize)
380 {
381 tree::NodeManager<TreeT, TreeT::DEPTH-2> nodes(tree);
382 LevelSetPruneOp<TreeT> op(tree, outside, inside);
383 nodes.foreachBottomUp(op, threaded, grainSize);
384 }
385
386
387 template<typename TreeT>
388 inline void
389 pruneLevelSet(TreeT& tree, bool threaded, size_t grainSize)
390 {
391 tree::NodeManager<TreeT, TreeT::DEPTH-2> nodes(tree);
392 LevelSetPruneOp<TreeT> op(tree);
393 nodes.foreachBottomUp(op, threaded, grainSize);
394 }
395
396 } // namespace tools
397 } // namespace OPENVDB_VERSION_NAME
398 } // namespace openvdb
399
400 #endif // OPENVDB_TOOLS_PRUNE_HAS_BEEN_INCLUDED
openvdb::v7_0::tools::LevelSetPruneOp::operator()
void operator()(LeafT &) const
Definition: Prune.h:299
openvdb::v7_0::tools::LevelSetPruneOp::RootT
typename TreeT::RootNodeType RootT
Definition: Prune.h:268
NodeManager.h
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
openvdb::v7_0::tools::InactivePruneOp::InactivePruneOp
InactivePruneOp(TreeT &tree)
Definition: Prune.h:143
openvdb::v7_0::tools::LevelSetPruneOp::operator()
void operator()(RootT &root) const
Definition: Prune.h:313
Types.h
openvdb::v7_0::tools::TolerancePruneOp::operator()
void operator()(NodeT &node) const
Definition: Prune.h:208
openvdb::v7_0::tools::pruneLevelSet
void pruneLevelSet(TreeT &tree, const typename TreeT::ValueType &outsideWidth, const typename TreeT::ValueType &insideWidth, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose voxel values are all inactive with ina...
Definition: Prune.h:375
openvdb::v7_0::tools::TolerancePruneOp
Definition: Prune.h:182
openvdb::v7_0::tools::TolerancePruneOp::operator()
void operator()(LeafT &) const
Definition: Prune.h:220
openvdb::v7_0::tools::pruneTiles
void pruneTiles(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any non-leaf nodes whose values are all...
Definition: Prune.h:344
openvdb::v7_0::tools::InactivePruneOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: Prune.h:140
openvdb::v7_0::math::negative
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:81
openvdb::v7_0::tools::TolerancePruneOp::operator()
void operator()(RootT &root) const
Definition: Prune.h:196
openvdb::v7_0::tools::LevelSetPruneOp::ValueT
typename TreeT::ValueType ValueT
Definition: Prune.h:267
openvdb::v7_0::tools::LevelSetPruneOp::LevelSetPruneOp
LevelSetPruneOp(TreeT &tree, const ValueT &outside, const ValueT &inside)
Definition: Prune.h:283
openvdb::v7_0::tools::InactivePruneOp::ValueT
typename TreeT::ValueType ValueT
Definition: Prune.h:138
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v7_0::tools::TolerancePruneOp::ValueT
typename TreeT::ValueType ValueT
Definition: Prune.h:185
openvdb::v7_0::tools::InactivePruneOp::operator()
void operator()(LeafT &) const
Definition: Prune.h:154
openvdb::v7_0::tools::LevelSetPruneOp::LevelSetPruneOp
LevelSetPruneOp(TreeT &tree)
Definition: Prune.h:272
openvdb::v7_0::tree::NodeManager
To facilitate threading over the nodes of a tree, cache node pointers in linear arrays,...
Definition: NodeManager.h:31
openvdb::v7_0::math::isNegative
bool isNegative(const Type &x)
Return true if x is less than zero.
Definition: Math.h:311
openvdb::v7_0::tools::InactivePruneOp
Definition: Prune.h:135
openvdb::v7_0::tools::LevelSetPruneOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: Prune.h:269
openvdb::v7_0::tools::LevelSetPruneOp::operator()
void operator()(NodeT &node) const
Definition: Prune.h:303
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
openvdb::v7_0::tools::InactivePruneOp::operator()
void operator()(NodeT &node) const
Definition: Prune.h:158
openvdb::v7_0::tools::prune
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:334
openvdb::v7_0::tools::TolerancePruneOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: Prune.h:187
openvdb::v7_0::tools::LevelSetPruneOp
Definition: Prune.h:264
openvdb::v7_0::tools::InactivePruneOp::operator()
void operator()(RootT &root) const
Definition: Prune.h:168
openvdb::v7_0::tools::InactivePruneOp::InactivePruneOp
InactivePruneOp(TreeT &tree, const ValueT &v)
Definition: Prune.h:148
openvdb::v7_0::tools::TolerancePruneOp::RootT
typename TreeT::RootNodeType RootT
Definition: Prune.h:186
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
openvdb::v7_0::ValueError
Definition: Exceptions.h:65
openvdb
Definition: Exceptions.h:13
openvdb::v7_0::tools::pruneInactive
void pruneInactive(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with background tiles any nodes whose values are a...
Definition: Prune.h:354
openvdb::v7_0::tools::TolerancePruneOp::TolerancePruneOp
TolerancePruneOp(TreeT &tree, const ValueT &tol)
Definition: Prune.h:190
openvdb::v7_0::tools::InactivePruneOp::RootT
typename TreeT::RootNodeType RootT
Definition: Prune.h:139
openvdb::v7_0::tools::pruneInactiveWithValue
void pruneInactiveWithValue(TreeT &tree, const typename TreeT::ValueType &value, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing any nodes whose values are all inactive with tiles...
Definition: Prune.h:364
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:82