OpenVDB 9.0.0
FindActiveValues.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4///////////////////////////////////////////////////////////////////////////
5//
6/// @file FindActiveValues.h
7///
8/// @author Ken Museth
9///
10/// @brief Finds the active values and tiles in a tree that intersects a bounding box.
11/// Methods are provided that count the number of active values and tiles,
12/// test for the existence of active values and tiles, and return a list of
13/// the active tiles that intersect a bbox.
14///
15/// @warning For repeated calls to the free-standing functions defined below
16/// consider instead creating an instance of FindActiveValues
17/// and then repeatedly call its member methods. This assumes the tree
18/// to be constant between calls but is sightly faster.
19///
20///////////////////////////////////////////////////////////////////////////
21
22#ifndef OPENVDB_TOOLS_FINDACTIVEVALUES_HAS_BEEN_INCLUDED
23#define OPENVDB_TOOLS_FINDACTIVEVALUES_HAS_BEEN_INCLUDED
24
25#include <vector>
26#include <openvdb/version.h> // for OPENVDB_VERSION_NAME
27#include <openvdb/Types.h>
29#include <openvdb/openvdb.h>
30
31#include "Count.h" // tools::countActiveVoxels()
32
33#include <tbb/blocked_range.h>
34#include <tbb/parallel_for.h>
35#include <tbb/parallel_reduce.h>
36
37namespace openvdb {
39namespace OPENVDB_VERSION_NAME {
40namespace tools {
41
42/// @brief Struct that encodes a bounding box, value and level of a tile
43///
44/// @details The bbox of a tiles is trimmed to the bounding box that probed it.
45/// The level is typically defined as: 1 is 8^3, 2 is 128^3, and 3 is 4096^3.
46template<typename ValueType>
47struct TileData;
48
49/// @brief Returns true if the bounding box intersects any of the active
50/// values in a tree, i.e. either active voxels or active tiles.
51///
52/// @warning For repeated calls to this method consider instead creating an instance of
53/// FindActiveValues and then repeatedly call anyActiveValues(). This assumes the tree
54/// to be constant between calls but is slightly faster.
55///
56/// @param tree const tree to be tested for active values.
57/// @param bbox index bounding box which is intersected against the active values.
58template<typename TreeT>
59bool
60anyActiveValues(const TreeT& tree, const CoordBBox &bbox);
61
62/// @brief Returns true if the bounding box intersects any of the active
63/// voxels in a tree, i.e. ignores active tile values.
64///
65/// @note In VDB voxels by definition reside in the leaf nodes ONLY. So this method
66/// ignores active tile values that reside higher up in the VDB tree structure.
67///
68/// @warning For repeated calls to this method consider instead creating an instance of
69/// FindActiveValues and then repeatedly call anyActiveVoxels(). This assumes the tree
70/// to be constant between calls but is slightly faster.
71///
72/// @param tree const tree to be tested for active voxels.
73/// @param bbox index bounding box which is intersected against the active voxels.
74template<typename TreeT>
75bool
76anyActiveVoxels(const TreeT& tree, const CoordBBox &bbox);
77
78/// @brief Returns true if the bounding box intersects any of the active
79/// tiles in a tree, i.e. ignores active leaf values.
80///
81/// @warning For repeated calls to this method consider instead creating an instance of
82/// FindActiveValues and then repeatedly call anyActiveTiles(). This assumes the tree
83/// to be constant between calls but is slightly faster.
84///
85/// @param tree const tree to be tested for active tiles.
86/// @param bbox index bounding box which is intersected against the active tiles.
87template<typename TreeT>
88bool
89anyActiveTiles(const TreeT& tree, const CoordBBox &bbox);
90
91/// @brief Returns true if the bounding box intersects none of the active
92/// values in a tree, i.e. neither active voxels or active tiles.
93///
94/// @warning For repeated calls to this method consider instead creating an instance of
95/// FindActiveValues and then repeatedly call noActiveValues(). This assumes the tree
96/// to be constant between calls but is slightly faster.
97///
98/// @param tree const tree to be tested for active values.
99/// @param bbox index bounding box which is intersected against the active values.
100template<typename TreeT>
101bool
102noActiveValues(const TreeT& tree, const CoordBBox &bbox);
103
104/// @brief Returns the number of active values that intersects a bounding box intersects,
105/// i.e. the count includes both active voxels and virtual voxels in active tiles.
106///
107/// @warning For repeated calls to this method consider instead creating an instance of
108/// FindActiveValues and then repeatedly call count(). This assumes the tree
109/// to be constant between calls but is slightly faster.
110///
111/// @param tree const tree to be tested for active values.
112/// @param bbox index bounding box which is intersected against the active values.
113template<typename TreeT>
115countActiveValues(const TreeT& tree, const CoordBBox &bbox);
116
117/// @brief Return a vector with bounding boxes that represents all the intersections
118/// between active tiles in the tree and the specified bounding box.
119///
120/// @warning For repeated calls to this method consider instead creating an instance of
121/// FindActiveValues and then repeatedly call count(). This assumes the tree
122/// to be constant between calls but is slightly faster.
123///
124/// @param tree const tree to be tested for active tiles.
125/// @param bbox index bounding box which is intersected against the active tiles.
126template<typename TreeT>
127std::vector<TileData<typename TreeT::ValueType>>
128activeTiles(const TreeT& tree, const CoordBBox &bbox);
129
130//////////////////////////////////////////////////////////////////////////////////////////
131
132/// @brief Finds the active values in a tree which intersects a bounding box.
133///
134/// @details Two methods are provided, one that count the number of active values
135/// and one that simply tests if any active values intersect the bbox.
136///
137/// @warning Tree nodes are cached by this class so it's important that the tree is not
138/// modified after this class is instantiated and before its methods are called.
139template<typename TreeT>
141{
142public:
143
145
146 /// @brief Constructor from a const tree, which is assumed not to be modified after construction.
147 FindActiveValues(const TreeT& tree);
148
149 /// @brief Default destructor
151
152 /// @brief Initiate this class with a new (or modified) tree.
153 void update(const TreeT& tree);
154
155 /// @brief Returns true if the specified bounding box intersects any active values.
156 ///
157 /// @warning Using a ValueAccessor (i.e. useAccessor = true) can improve performance for especially
158 /// small bounding boxes, but at the cost of no thread-safety. So if multiple threads are
159 /// calling this method concurrently use the default setting, useAccessor = false.
160 bool anyActiveValues(const CoordBBox &bbox, bool useAccessor = false) const;
161
162 /// @brief Returns true if the specified bounding box intersects any active tiles only.
163 bool anyActiveVoxels(const CoordBBox &bbox) const;
164
165 /// @brief Returns true if the specified bounding box intersects any active tiles only.
166 bool anyActiveTiles(const CoordBBox &bbox) const;
167
168 /// @brief Returns true if the specified bounding box does not intersect any active values.
169 ///
170 /// @warning Using a ValueAccessor (i.e. useAccessor = true) can improve performance for especially
171 /// small bounding boxes, but at the cost of no thread-safety. So if multiple threads are
172 /// calling this method concurrently use the default setting, useAccessor = false.
173 bool noActiveValues(const CoordBBox &bbox, bool useAccessor = false) const { return !this->anyActiveValues(bbox, useAccessor); }
174
175 /// @brief Returns the number of active voxels intersected by the specified bounding box.
176 Index64 count(const CoordBBox &bbox) const;
177
178 /// @brief Return a vector with bounding boxes that represents all the intersections
179 /// between active tiles in the tree and the specified bounding box.
180 std::vector<TileDataT> activeTiles(const CoordBBox &bbox) const;
181
182 OPENVDB_DEPRECATED_MESSAGE("Use anyActiveValues() instead") inline bool any(const CoordBBox &bbox, bool useAccessor = false) const
183 {
184 return this->anyActiveValues(bbox, useAccessor);
185 }
186 OPENVDB_DEPRECATED_MESSAGE("Use noActiveValues() instead") inline bool none(const CoordBBox &bbox, bool useAccessor = false) const
187 {
188 return this->noActiveValues(bbox, useAccessor);
189 }
190
191private:
192
193 // Cleans up internal data structures
194 void clear();
195
196 // builds internal data structures
197 void init(const TreeT &tree);
198
199 template<typename NodeT>
200 typename NodeT::NodeMaskType getBBoxMask(const CoordBBox &bbox, const NodeT* node) const;
201
202 // process leaf nodes
203 inline bool anyActiveValues(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const { return this->anyActiveVoxels(leaf, bbox); }
204 inline bool anyActiveVoxels(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const;
205 static bool anyActiveTiles( const typename TreeT::LeafNodeType*, const CoordBBox& ) {return false;}
206 void activeTiles(const typename TreeT::LeafNodeType*, const CoordBBox&, std::vector<TileDataT>&) const {;}// no-op
207 inline Index64 count(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const;
208
209 // process internal nodes
210 template<typename NodeT>
211 bool anyActiveValues(const NodeT* node, const CoordBBox &bbox) const;
212 template<typename NodeT>
213 bool anyActiveVoxels(const NodeT* node, const CoordBBox &bbox) const;
214 template<typename NodeT>
215 bool anyActiveTiles(const NodeT* node, const CoordBBox &bbox) const;
216 template<typename NodeT>
217 void activeTiles(const NodeT* node, const CoordBBox &bbox, std::vector<TileDataT> &tiles) const;
218 template<typename NodeT>
219 Index64 count(const NodeT* node, const CoordBBox &bbox) const;
220
221 using AccT = tree::ValueAccessor<const TreeT, false/* IsSafe */>;
222 using RootChildType = typename TreeT::RootNodeType::ChildNodeType;
223
224 struct RootChild;
225
226 AccT mAcc;
227 std::vector<TileDataT> mRootTiles;// cache bbox of child nodes (faster to cache than access RootNode)
228 std::vector<RootChild> mRootNodes;// cache bbox of active tiles (faster to cache than access RootNode)
229
230};// FindActiveValues class
231
232//////////////////////////////////////////////////////////////////////////////////////////
233
234template<typename TreeT>
235FindActiveValues<TreeT>::FindActiveValues(const TreeT& tree) : mAcc(tree), mRootTiles(), mRootNodes()
236{
237 this->init(tree);
238}
239
240template<typename TreeT>
242{
243 this->clear();
244}
245
246template<typename TreeT>
247void FindActiveValues<TreeT>::update(const TreeT& tree)
248{
249 this->clear();
250 mAcc = AccT(tree);
251 this->init(tree);
252}
253
254template<typename TreeT>
256{
257 mRootNodes.clear();
258 mRootTiles.clear();
259}
260
261template<typename TreeT>
262void FindActiveValues<TreeT>::init(const TreeT& tree)
263{
264 const auto &root = tree.root();
265 for (auto i = root.cbeginChildOn(); i; ++i) {
266 mRootNodes.emplace_back(i.getCoord(), &*i);
267 }
268 for (auto i = root.cbeginValueOn(); i; ++i) {
269 mRootTiles.emplace_back(root, i.getCoord(), *i);
270 }
271}
272
273template<typename TreeT>
274bool FindActiveValues<TreeT>::anyActiveValues(const CoordBBox &bbox, bool useAccessor) const
275{
276 // test early-out: the center of the bbox is active
277 if (useAccessor) {
278 if (mAcc.isValueOn( (bbox.min() + bbox.max())>>1 )) return true;
279 } else {
280 if (mAcc.tree().isValueOn( (bbox.min() + bbox.max())>>1 )) return true;
281 }
282
283 for (auto& tile : mRootTiles) {
284 if (tile.bbox.hasOverlap(bbox)) return true;
285 }
286 for (auto& node : mRootNodes) {
287 if (!node.bbox.hasOverlap(bbox)) {// no overlap
288 continue;
289 } else if (node.bbox.isInside(bbox)) {// bbox is inside the child node
290 return this->anyActiveValues(node.child, bbox);
291 } else if (this->anyActiveValues(node.child, bbox)) {// bbox overlaps the child node
292 return true;
293 }
294 }
295 return false;
296}
297
298template<typename TreeT>
300{
301 for (auto& node : mRootNodes) {
302 if (!node.bbox.hasOverlap(bbox)) {// no overlap
303 continue;
304 } else if (node.bbox.isInside(bbox)) {// bbox is inside the child node
305 return this->anyActiveVoxels(node.child, bbox);
306 } else if (this->anyActiveVoxels(node.child, bbox)) {// bbox overlaps the child node
307 return true;
308 }
309 }
310 return false;
311}
312
313template<typename TreeT>
315{
316 for (auto& tile : mRootTiles) {
317 if (tile.bbox.hasOverlap(bbox)) return true;
318 }
319 for (auto& node : mRootNodes) {
320 if (!node.bbox.hasOverlap(bbox)) {// no overlap
321 continue;
322 } else if (node.bbox.isInside(bbox)) {// bbox is inside the child node
323 return this->anyActiveTiles(node.child, bbox);
324 } else if (this->anyActiveTiles(node.child, bbox)) {// bbox overlaps the child node
325 return true;
326 }
327 }
328 return false;
329}
330
331template<typename TreeT>
333{
334 Index64 count = 0;
335 for (auto& tile : mRootTiles) {//loop over active tiles only
336 if (!tile.bbox.hasOverlap(bbox)) {
337 continue;//ignore non-overlapping tiles
338 } else if (tile.bbox.isInside(bbox)) {
339 return bbox.volume();// bbox is completely inside the active tile
340 } else if (bbox.isInside(tile.bbox)) {
341 count += RootChildType::NUM_VOXELS;
342 } else {// partial overlap between tile and bbox
343 auto tmp = tile.bbox;
344 tmp.intersect(bbox);
345 count += tmp.volume();
346 }
347 }
348 for (auto &node : mRootNodes) {//loop over child nodes of the root node only
349 if ( !node.bbox.hasOverlap(bbox) ) {
350 continue;//ignore non-overlapping child nodes
351 } else if ( node.bbox.isInside(bbox) ) {
352 return this->count(node.child, bbox);// bbox is completely inside the child node
353 } else {
354 count += this->count(node.child, bbox);
355 }
356 }
357 return count;
358}
359
360template<typename TreeT>
361std::vector<TileData<typename TreeT::ValueType> >
363{
364 std::vector<TileDataT> tiles;
365 for (auto& tile : mRootTiles) {//loop over active tiles only
366 if (!tile.bbox.hasOverlap(bbox)) {
367 continue;//ignore non-overlapping tiles
368 } else if (tile.bbox.isInside(bbox)) {// bbox is completely inside the active tile
369 tiles.emplace_back(bbox, tile.value, tile.level);
370 return tiles;
371 } else if (bbox.isInside(tile.bbox)) {// active tile is completely inside the bbox
372 tiles.push_back(tile);
373 } else {// partial overlap between tile and bbox
374 auto tmp = tile.bbox;
375 tmp.intersect(bbox);
376 tiles.emplace_back(tmp, tile.value, tile.level);
377 }
378 }
379 for (auto &node : mRootNodes) {//loop over child nodes of the root node only
380 if ( !node.bbox.hasOverlap(bbox) ) {
381 continue;//ignore non-overlapping child nodes
382 } else if ( node.bbox.isInside(bbox) ) {// bbox is completely inside the child node
383 this->activeTiles(node.child, bbox, tiles);
384 return tiles;
385 } else {// partial overlap between tile and child node
386 this->activeTiles(node.child, bbox, tiles);
387 }
388 }
389 return tiles;
390}
391
392template<typename TreeT>
393template<typename NodeT>
394typename NodeT::NodeMaskType FindActiveValues<TreeT>::getBBoxMask(const CoordBBox &bbox, const NodeT* node) const
395{
396 typename NodeT::NodeMaskType mask;// typically 32^3 or 16^3 bit mask
397 auto b = node->getNodeBoundingBox();
398 assert( bbox.hasOverlap(b) );
399 if ( bbox.isInside(b) ) {
400 mask.setOn();//node is completely inside the bbox so early out
401 } else {
402 b.intersect(bbox);// trim bounding box
403 // transform bounding box from global to local coordinates
404 b.min() &= NodeT::DIM-1u;
405 b.min() >>= NodeT::ChildNodeType::TOTAL;
406 b.max() &= NodeT::DIM-1u;
407 b.max() >>= NodeT::ChildNodeType::TOTAL;
408 assert( b.hasVolume() );
409 auto it = b.begin();// iterates over all the child nodes or tiles that intersects bbox
410 for (const Coord& ijk = *it; it; ++it) {
411 mask.setOn(ijk[2] + (ijk[1] << NodeT::LOG2DIM) + (ijk[0] << 2*NodeT::LOG2DIM));
412 }
413 }
414 return mask;
415}
416
417template<typename TreeT>
418template<typename NodeT>
419bool FindActiveValues<TreeT>::anyActiveValues(const NodeT* node, const CoordBBox &bbox) const
420{
421 // Generate a bit mask of the bbox coverage
422 auto mask = this->getBBoxMask(bbox, node);
423
424 // Check active tiles
425 const auto tmp = mask & node->getValueMask();// prune active the tile mask with the bbox mask
426 if (!tmp.isOff()) return true;
427
428 // Check child nodes
429 mask &= node->getChildMask();// prune the child mask with the bbox mask
430 const auto* table = node->getTable();
431 bool active = false;
432 for (auto i = mask.beginOn(); !active && i; ++i) {
433 active = this->anyActiveValues(table[i.pos()].getChild(), bbox);
434 }
435 return active;
436}
437
438template<typename TreeT>
439template<typename NodeT>
440bool FindActiveValues<TreeT>::anyActiveVoxels(const NodeT* node, const CoordBBox &bbox) const
441{
442 // Generate a bit mask of the bbox coverage
443 auto mask = this->getBBoxMask(bbox, node);
444
445 // Check child nodes
446 mask &= node->getChildMask();// prune the child mask with the bbox mask
447 const auto* table = node->getTable();
448 bool active = false;
449 for (auto i = mask.beginOn(); !active && i; ++i) {
450 active = this->anyActiveVoxels(table[i.pos()].getChild(), bbox);
451 }
452 return active;
453}
454
455template<typename TreeT>
456inline bool FindActiveValues<TreeT>::anyActiveVoxels(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const
457{
458 const auto &mask = leaf->getValueMask();
459
460 // check for two common cases that leads to early-out
461 if (bbox.isInside(leaf->getNodeBoundingBox())) return !mask.isOff();// leaf in inside the bbox
462 if (mask.isOn()) return true;// all values are active
463
464 bool active = false;
465 for (auto i = leaf->cbeginValueOn(); !active && i; ++i) {
466 active = bbox.isInside(i.getCoord());
467 }
468 return active;
469}
470
471template<typename TreeT>
472template<typename NodeT>
473bool FindActiveValues<TreeT>::anyActiveTiles(const NodeT* node, const CoordBBox &bbox) const
474{
475 // Generate a bit mask of the bbox coverage
476 auto mask = this->getBBoxMask(bbox, node);
477
478 // Check active tiles
479 const auto tmp = mask & node->getValueMask();// prune active the tile mask with the bbox mask
480 if (!tmp.isOff()) return true;
481
482 bool active = false;
483 if (NodeT::LEVEL>1) {// Only check child nodes if they are NOT leaf nodes
484 mask &= node->getChildMask();// prune the child mask with the bbox mask
485 const auto* table = node->getTable();
486 for (auto i = mask.beginOn(); !active && i; ++i) {
487 active = this->anyActiveTiles(table[i.pos()].getChild(), bbox);
488 }
489 }
490 return active;
491}
492
493template<typename TreeT>
494inline Index64 FindActiveValues<TreeT>::count(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const
495{
496 Index64 count = 0;
497 auto b = leaf->getNodeBoundingBox();
498 if (b.isInside(bbox)) { // leaf node is completely inside bbox
499 count = leaf->onVoxelCount();
500 } else if (leaf->isDense()) {
501 b.intersect(bbox);
502 count = b.volume();
503 } else if (b.hasOverlap(bbox)) {
504 for (auto i = leaf->cbeginValueOn(); i; ++i) {
505 if (bbox.isInside(i.getCoord())) ++count;
506 }
507 }
508 return count;
509}
510
511template<typename TreeT>
512template<typename NodeT>
513Index64 FindActiveValues<TreeT>::count(const NodeT* node, const CoordBBox &bbox) const
514{
515 Index64 count = 0;
516
517 // Generate a bit masks
518 auto mask = this->getBBoxMask(bbox, node);
519 const auto childMask = mask & node->getChildMask();// prune the child mask with the bbox mask
520 mask &= node->getValueMask();// prune active tile mask with the bbox mask
521 const auto* table = node->getTable();
522
523 {// Check child nodes
524 using ChildT = typename NodeT::ChildNodeType;
525 using RangeT = tbb::blocked_range<typename std::vector<const ChildT*>::iterator>;
526 std::vector<const ChildT*> childNodes(childMask.countOn());
527 int j=0;
528 for (auto i = childMask.beginOn(); i; ++i, ++j) childNodes[j] = table[i.pos()].getChild();
529 count += tbb::parallel_reduce( RangeT(childNodes.begin(), childNodes.end()), 0,
530 [&](const RangeT& r, Index64 sum)->Index64 {
531 for ( auto i = r.begin(); i != r.end(); ++i ) sum += this->count(*i, bbox);
532 return sum;
533 }, []( Index64 a, Index64 b )->Index64 { return a+b; }
534 );
535 }
536
537 {// Check active tiles
538 std::vector<Coord> coords(mask.countOn());
539 using RangeT = tbb::blocked_range<typename std::vector<Coord>::iterator>;
540 int j=0;
541 for (auto i = mask.beginOn(); i; ++i, ++j) coords[j] = node->offsetToGlobalCoord(i.pos());
542 count += tbb::parallel_reduce( RangeT(coords.begin(), coords.end()), 0,
543 [&bbox](const RangeT& r, Index64 sum)->Index64 {
544 for ( auto i = r.begin(); i != r.end(); ++i ) {
545 auto b = CoordBBox::createCube(*i, NodeT::ChildNodeType::DIM);
546 b.intersect(bbox);
547 sum += b.volume();
548 }
549 return sum;
550 }, []( Index64 a, Index64 b )->Index64 { return a+b; }
551 );
552 }
553
554 return count;
555}
556
557// process internal node
558template<typename TreeT>
559template<typename NodeT>
560void FindActiveValues<TreeT>::activeTiles(const NodeT* node, const CoordBBox &bbox, std::vector<TileDataT> &tiles) const
561{
562 // Generate a bit masks
563 auto mask = this->getBBoxMask(bbox, node);
564 const auto childMask = mask & node->getChildMask();// prune the child mask with the bbox mask
565 mask &= node->getValueMask();// prune active tile mask with the bbox mask
566
567 if (NodeT::LEVEL > 1) {// Only check child nodes if they are NOT leaf nodes
568 const auto* table = node->getTable();
569 for (auto i = childMask.beginOn(); i; ++i) this->activeTiles(table[i.pos()].getChild(), bbox, tiles);
570 }
571
572 const size_t tileCount = mask.countOn();
573 if (tileCount < 8) {// Serial processing of active tiles
574 for (auto iter = mask.beginOn(); iter; ++iter) {
575 tiles.emplace_back(*node, iter.pos());
576 tiles.back().bbox.intersect(bbox);
577 }
578 } else {// Parallel processing of active tiles
579 std::vector<TileDataT> tmp( tileCount );// for temporary thread-safe processing
580 int n = 0;
581 for (auto iter = mask.beginOn(); iter; ++iter) tmp[n++].level = iter.pos();// placeholder to support multi-threading
582 tbb::parallel_for(tbb::blocked_range<size_t>(0, tileCount, 8), [&](const tbb::blocked_range<size_t>& r) {
583 for ( size_t i = r.begin(); i != r.end(); ++i ) {
584 tmp[i] = TileDataT(*node, tmp[i].level);
585 tmp[i].bbox.intersect(bbox);
586 }
587 });
588 tiles.insert(tiles.end(), tmp.begin(), tmp.end());
589 }
590}
591
592template<typename TreeT>
594{
596 const RootChildType* child;
597 RootChild(const Coord& ijk = Coord(), const RootChildType* ptr = nullptr)
598 : bbox(CoordBBox::createCube(ijk, RootChildType::DIM)), child(ptr)
599 {
600 }
601};// RootChild struct
602
603//////////////////////////////////////////////////////////////////////////////////////////
604
605template<typename ValueType>
607{
609 ValueType value;
611 bool state;
612
613 /// @brief Default constructor
614 TileData() = default;
615
616 /// @brief Member data constructor
617 TileData(const CoordBBox &b, const ValueType &v, Index l, bool active = true)
618 : bbox(b), value(v), level(l), state(active) {}
619
620 /// @brief Constructor from a parent node and the linear offset to one of its tiles
621 ///
622 /// @warning This is an expert-only method since it assumes the linear offset to be valid,
623 /// i.e. within the rand of the dimension of the parent node and NOT corresponding
624 /// to a child node.
625 template <typename ParentNodeT>
626 TileData(const ParentNodeT &parent, Index childIdx)
627 : bbox(CoordBBox::createCube(parent.offsetToGlobalCoord(childIdx), parent.getChildDim()))
628 , level(parent.getLevel())
629 , state(true)
630 {
631 assert(childIdx < ParentNodeT::NUM_VALUES);
632 assert(parent.isChildMaskOff(childIdx));
633 assert(parent.isValueMaskOn(childIdx));
634 value = parent.getTable()[childIdx].getValue();
635 }
636
637 /// @brief Constructor form a parent node, the coordinate of the origin of one of its tiles,
638 /// and said tiles value.
639 template <typename ParentNodeT>
640 TileData(const ParentNodeT &parent, const Coord &ijk, const ValueType &v)
641 : bbox(CoordBBox::createCube(ijk, parent.getChildDim()))
642 , value(v)
643 , level(parent.getLevel())
644 , state(true)
645 {
646 }
647};// TileData struct
648
649//////////////////////////////////////////////////////////////////////////////////////////
650
651// Implementation of stand-alone function
652template<typename TreeT>
653bool
654anyActiveValues(const TreeT& tree, const CoordBBox &bbox)
655{
657 return op.anyActiveValues(bbox);
658}
659
660// Implementation of stand-alone function
661template<typename TreeT>
662bool
663anyActiveVoxels(const TreeT& tree, const CoordBBox &bbox)
664{
666 return op.anyActiveVoxels(bbox);
667}
668
669// Implementation of stand-alone function
670template<typename TreeT>
671bool
672anyActiveTiles(const TreeT& tree, const CoordBBox &bbox)
673{
675 return op.anyActiveTiles(bbox);
676}
677
678// Implementation of stand-alone function
679template<typename TreeT>
680bool
681noActiveValues(const TreeT& tree, const CoordBBox &bbox)
682{
684 return op.noActiveValues(bbox);
685}
686
687// Implementation of stand-alone function
688template<typename TreeT>
690countActiveValues(const TreeT& tree, const CoordBBox &bbox)
691{
692 return tools::countActiveVoxels(tree, bbox);
693}
694
695// Implementation of stand-alone function
696template<typename TreeT>
697std::vector<TileData<typename TreeT::ValueType>>
698activeTiles(const TreeT& tree, const CoordBBox &bbox)
699{
701 return op.activeTiles(bbox);
702}
703
704
705////////////////////////////////////////
706
707
708// Explicit Template Instantiation
709
710#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
711
712#ifdef OPENVDB_INSTANTIATE_FINDACTIVEVALUES
714#endif
715
716#define _FUNCTION(TreeT) \
717 bool anyActiveValues(const TreeT&, const CoordBBox&)
719#undef _FUNCTION
720
721#define _FUNCTION(TreeT) \
722 bool anyActiveVoxels(const TreeT&, const CoordBBox&)
724#undef _FUNCTION
725
726#define _FUNCTION(TreeT) \
727 bool anyActiveTiles(const TreeT&, const CoordBBox&)
729#undef _FUNCTION
730
731#define _FUNCTION(TreeT) \
732 bool noActiveValues(const TreeT&, const CoordBBox&)
734#undef _FUNCTION
735
736#define _FUNCTION(TreeT) \
737 Index64 countActiveValues(const TreeT&, const CoordBBox&)
739#undef _FUNCTION
740
741#define _FUNCTION(TreeT) \
742 std::vector<TileData<TreeT::ValueType>> activeTiles(const TreeT&, const CoordBBox&)
744#undef _FUNCTION
745
746#endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
747
748
749} // namespace tools
750} // namespace OPENVDB_VERSION_NAME
751} // namespace openvdb
752
753#endif // OPENVDB_TOOLS_FINDACTIVEVALUES_HAS_BEEN_INCLUDED
Functions to count tiles, nodes or voxels in a grid.
ValueT value
Definition: GridBuilder.h:1287
ChildT * child
Definition: GridBuilder.h:1286
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition: Platform.h:123
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:248
const Coord & min() const
Definition: Coord.h:320
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:411
const Coord & max() const
Definition: Coord.h:321
Index64 volume() const
Return the integer volume of coordinates spanned by this bounding box.
Definition: Coord.h:384
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:399
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
Finds the active values in a tree which intersects a bounding box.
Definition: FindActiveValues.h:141
~FindActiveValues()
Default destructor.
Definition: FindActiveValues.h:241
bool anyActiveTiles(const CoordBBox &bbox) const
Returns true if the specified bounding box intersects any active tiles only.
Definition: FindActiveValues.h:314
bool anyActiveVoxels(const CoordBBox &bbox) const
Returns true if the specified bounding box intersects any active tiles only.
Definition: FindActiveValues.h:299
std::vector< TileDataT > activeTiles(const CoordBBox &bbox) const
Return a vector with bounding boxes that represents all the intersections between active tiles in the...
Definition: FindActiveValues.h:362
bool noActiveValues(const CoordBBox &bbox, bool useAccessor=false) const
Returns true if the specified bounding box does not intersect any active values.
Definition: FindActiveValues.h:173
void update(const TreeT &tree)
Initiate this class with a new (or modified) tree.
Definition: FindActiveValues.h:247
Index64 count(const CoordBBox &bbox) const
Returns the number of active voxels intersected by the specified bounding box.
Definition: FindActiveValues.h:332
bool anyActiveValues(const CoordBBox &bbox, bool useAccessor=false) const
Returns true if the specified bounding box intersects any active values.
Definition: FindActiveValues.h:274
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
Level getLevel()
Return the current logging level.
Definition: logging.h:141
Index64 countActiveValues(const TreeT &tree, const CoordBBox &bbox)
Returns the number of active values that intersects a bounding box intersects, i.e....
Definition: FindActiveValues.h:690
bool anyActiveValues(const TreeT &tree, const CoordBBox &bbox)
Returns true if the bounding box intersects any of the active values in a tree, i....
Definition: FindActiveValues.h:654
std::vector< TileData< typename TreeT::ValueType > > activeTiles(const TreeT &tree, const CoordBBox &bbox)
Return a vector with bounding boxes that represents all the intersections between active tiles in the...
Definition: FindActiveValues.h:698
bool anyActiveTiles(const TreeT &tree, const CoordBBox &bbox)
Returns true if the bounding box intersects any of the active tiles in a tree, i.e....
Definition: FindActiveValues.h:672
bool anyActiveVoxels(const TreeT &tree, const CoordBBox &bbox)
Returns true if the bounding box intersects any of the active voxels in a tree, i....
Definition: FindActiveValues.h:663
Index64 countActiveVoxels(const TreeT &tree, bool threaded=true)
Return the total number of active voxels in the tree.
Definition: Count.h:328
bool noActiveValues(const TreeT &tree, const CoordBBox &bbox)
Returns true if the bounding box intersects none of the active values in a tree, i....
Definition: FindActiveValues.h:681
Index32 Index
Definition: Types.h:54
uint64_t Index64
Definition: Types.h:53
Definition: Exceptions.h:13
Definition: FindActiveValues.h:594
RootChild(const Coord &ijk=Coord(), const RootChildType *ptr=nullptr)
Definition: FindActiveValues.h:597
const RootChildType * child
Definition: FindActiveValues.h:596
const CoordBBox bbox
Definition: FindActiveValues.h:595
Struct that encodes a bounding box, value and level of a tile.
Definition: FindActiveValues.h:607
TileData(const ParentNodeT &parent, Index childIdx)
Constructor from a parent node and the linear offset to one of its tiles.
Definition: FindActiveValues.h:626
TileData()=default
Default constructor.
bool state
Definition: FindActiveValues.h:611
ValueType value
Definition: FindActiveValues.h:609
CoordBBox bbox
Definition: FindActiveValues.h:608
Index level
Definition: FindActiveValues.h:610
TileData(const ParentNodeT &parent, const Coord &ijk, const ValueType &v)
Constructor form a parent node, the coordinate of the origin of one of its tiles, and said tiles valu...
Definition: FindActiveValues.h:640
TileData(const CoordBBox &b, const ValueType &v, Index l, bool active=true)
Member data constructor.
Definition: FindActiveValues.h:617
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
Definition: version.h.in:150