OpenVDB 10.0.1
Loading...
Searching...
No Matches
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
182private:
183
184 // Cleans up internal data structures
185 void clear();
186
187 // builds internal data structures
188 void init(const TreeT &tree);
189
190 template<typename NodeT>
191 typename NodeT::NodeMaskType getBBoxMask(const CoordBBox &bbox, const NodeT* node) const;
192
193 // process leaf nodes
194 inline bool anyActiveValues(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const { return this->anyActiveVoxels(leaf, bbox); }
195 inline bool anyActiveVoxels(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const;
196 static bool anyActiveTiles( const typename TreeT::LeafNodeType*, const CoordBBox& ) {return false;}
197 void activeTiles(const typename TreeT::LeafNodeType*, const CoordBBox&, std::vector<TileDataT>&) const {;}// no-op
198 inline Index64 count(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const;
199
200 // process internal nodes
201 template<typename NodeT>
202 bool anyActiveValues(const NodeT* node, const CoordBBox &bbox) const;
203 template<typename NodeT>
204 bool anyActiveVoxels(const NodeT* node, const CoordBBox &bbox) const;
205 template<typename NodeT>
206 bool anyActiveTiles(const NodeT* node, const CoordBBox &bbox) const;
207 template<typename NodeT>
208 void activeTiles(const NodeT* node, const CoordBBox &bbox, std::vector<TileDataT> &tiles) const;
209 template<typename NodeT>
210 Index64 count(const NodeT* node, const CoordBBox &bbox) const;
211
212 using AccT = tree::ValueAccessor<const TreeT, false/* IsSafe */>;
213 using RootChildType = typename TreeT::RootNodeType::ChildNodeType;
214
215 struct RootChild;
216
217 AccT mAcc;
218 std::vector<TileDataT> mRootTiles;// cache bbox of child nodes (faster to cache than access RootNode)
219 std::vector<RootChild> mRootNodes;// cache bbox of active tiles (faster to cache than access RootNode)
220
221};// FindActiveValues class
222
223//////////////////////////////////////////////////////////////////////////////////////////
224
225template<typename TreeT>
226FindActiveValues<TreeT>::FindActiveValues(const TreeT& tree) : mAcc(tree), mRootTiles(), mRootNodes()
227{
228 this->init(tree);
229}
230
231template<typename TreeT>
233{
234 this->clear();
235}
236
237template<typename TreeT>
238void FindActiveValues<TreeT>::update(const TreeT& tree)
239{
240 this->clear();
241 mAcc = AccT(tree);
242 this->init(tree);
243}
244
245template<typename TreeT>
247{
248 mRootNodes.clear();
249 mRootTiles.clear();
250}
251
252template<typename TreeT>
253void FindActiveValues<TreeT>::init(const TreeT& tree)
254{
255 const auto &root = tree.root();
256 for (auto i = root.cbeginChildOn(); i; ++i) {
257 mRootNodes.emplace_back(i.getCoord(), &*i);
258 }
259 for (auto i = root.cbeginValueOn(); i; ++i) {
260 mRootTiles.emplace_back(root, i.getCoord(), *i);
261 }
262}
263
264template<typename TreeT>
265bool FindActiveValues<TreeT>::anyActiveValues(const CoordBBox &bbox, bool useAccessor) const
266{
267 // test early-out: the center of the bbox is active
268 if (useAccessor) {
269 if (mAcc.isValueOn( (bbox.min() + bbox.max())>>1 )) return true;
270 } else {
271 if (mAcc.tree().isValueOn( (bbox.min() + bbox.max())>>1 )) return true;
272 }
273
274 for (auto& tile : mRootTiles) {
275 if (tile.bbox.hasOverlap(bbox)) return true;
276 }
277 for (auto& node : mRootNodes) {
278 if (!node.bbox.hasOverlap(bbox)) {// no overlap
279 continue;
280 } else if (node.bbox.isInside(bbox)) {// bbox is inside the child node
281 return this->anyActiveValues(node.child, bbox);
282 } else if (this->anyActiveValues(node.child, bbox)) {// bbox overlaps the child node
283 return true;
284 }
285 }
286 return false;
287}
288
289template<typename TreeT>
291{
292 for (auto& node : mRootNodes) {
293 if (!node.bbox.hasOverlap(bbox)) {// no overlap
294 continue;
295 } else if (node.bbox.isInside(bbox)) {// bbox is inside the child node
296 return this->anyActiveVoxels(node.child, bbox);
297 } else if (this->anyActiveVoxels(node.child, bbox)) {// bbox overlaps the child node
298 return true;
299 }
300 }
301 return false;
302}
303
304template<typename TreeT>
306{
307 for (auto& tile : mRootTiles) {
308 if (tile.bbox.hasOverlap(bbox)) return true;
309 }
310 for (auto& node : mRootNodes) {
311 if (!node.bbox.hasOverlap(bbox)) {// no overlap
312 continue;
313 } else if (node.bbox.isInside(bbox)) {// bbox is inside the child node
314 return this->anyActiveTiles(node.child, bbox);
315 } else if (this->anyActiveTiles(node.child, bbox)) {// bbox overlaps the child node
316 return true;
317 }
318 }
319 return false;
320}
321
322template<typename TreeT>
324{
325 Index64 count = 0;
326 for (auto& tile : mRootTiles) {//loop over active tiles only
327 if (!tile.bbox.hasOverlap(bbox)) {
328 continue;//ignore non-overlapping tiles
329 } else if (tile.bbox.isInside(bbox)) {
330 return bbox.volume();// bbox is completely inside the active tile
331 } else if (bbox.isInside(tile.bbox)) {
332 count += RootChildType::NUM_VOXELS;
333 } else {// partial overlap between tile and bbox
334 auto tmp = tile.bbox;
335 tmp.intersect(bbox);
336 count += tmp.volume();
337 }
338 }
339 for (auto &node : mRootNodes) {//loop over child nodes of the root node only
340 if ( !node.bbox.hasOverlap(bbox) ) {
341 continue;//ignore non-overlapping child nodes
342 } else if ( node.bbox.isInside(bbox) ) {
343 return this->count(node.child, bbox);// bbox is completely inside the child node
344 } else {
345 count += this->count(node.child, bbox);
346 }
347 }
348 return count;
349}
350
351template<typename TreeT>
352std::vector<TileData<typename TreeT::ValueType> >
354{
355 std::vector<TileDataT> tiles;
356 for (auto& tile : mRootTiles) {//loop over active tiles only
357 if (!tile.bbox.hasOverlap(bbox)) {
358 continue;//ignore non-overlapping tiles
359 } else if (tile.bbox.isInside(bbox)) {// bbox is completely inside the active tile
360 tiles.emplace_back(bbox, tile.value, tile.level);
361 return tiles;
362 } else if (bbox.isInside(tile.bbox)) {// active tile is completely inside the bbox
363 tiles.push_back(tile);
364 } else {// partial overlap between tile and bbox
365 auto tmp = tile.bbox;
366 tmp.intersect(bbox);
367 tiles.emplace_back(tmp, tile.value, tile.level);
368 }
369 }
370 for (auto &node : mRootNodes) {//loop over child nodes of the root node only
371 if ( !node.bbox.hasOverlap(bbox) ) {
372 continue;//ignore non-overlapping child nodes
373 } else if ( node.bbox.isInside(bbox) ) {// bbox is completely inside the child node
374 this->activeTiles(node.child, bbox, tiles);
375 return tiles;
376 } else {// partial overlap between tile and child node
377 this->activeTiles(node.child, bbox, tiles);
378 }
379 }
380 return tiles;
381}
382
383template<typename TreeT>
384template<typename NodeT>
385typename NodeT::NodeMaskType FindActiveValues<TreeT>::getBBoxMask(const CoordBBox &bbox, const NodeT* node) const
386{
387 typename NodeT::NodeMaskType mask;// typically 32^3 or 16^3 bit mask
388 auto b = node->getNodeBoundingBox();
389 assert( bbox.hasOverlap(b) );
390 if ( bbox.isInside(b) ) {
391 mask.setOn();//node is completely inside the bbox so early out
392 } else {
393 b.intersect(bbox);// trim bounding box
394 // transform bounding box from global to local coordinates
395 b.min() &= NodeT::DIM-1u;
396 b.min() >>= NodeT::ChildNodeType::TOTAL;
397 b.max() &= NodeT::DIM-1u;
398 b.max() >>= NodeT::ChildNodeType::TOTAL;
399 assert( b.hasVolume() );
400 auto it = b.begin();// iterates over all the child nodes or tiles that intersects bbox
401 for (const Coord& ijk = *it; it; ++it) {
402 mask.setOn(ijk[2] + (ijk[1] << NodeT::LOG2DIM) + (ijk[0] << 2*NodeT::LOG2DIM));
403 }
404 }
405 return mask;
406}
407
408template<typename TreeT>
409template<typename NodeT>
410bool FindActiveValues<TreeT>::anyActiveValues(const NodeT* node, const CoordBBox &bbox) const
411{
412 // Generate a bit mask of the bbox coverage
413 auto mask = this->getBBoxMask(bbox, node);
414
415 // Check active tiles
416 const auto tmp = mask & node->getValueMask();// prune active the tile mask with the bbox mask
417 if (!tmp.isOff()) return true;
418
419 // Check child nodes
420 mask &= node->getChildMask();// prune the child mask with the bbox mask
421 const auto* table = node->getTable();
422 bool active = false;
423 for (auto i = mask.beginOn(); !active && i; ++i) {
424 active = this->anyActiveValues(table[i.pos()].getChild(), bbox);
425 }
426 return active;
427}
428
429template<typename TreeT>
430template<typename NodeT>
431bool FindActiveValues<TreeT>::anyActiveVoxels(const NodeT* node, const CoordBBox &bbox) const
432{
433 // Generate a bit mask of the bbox coverage
434 auto mask = this->getBBoxMask(bbox, node);
435
436 // Check child nodes
437 mask &= node->getChildMask();// prune the child mask with the bbox mask
438 const auto* table = node->getTable();
439 bool active = false;
440 for (auto i = mask.beginOn(); !active && i; ++i) {
441 active = this->anyActiveVoxels(table[i.pos()].getChild(), bbox);
442 }
443 return active;
444}
445
446template<typename TreeT>
447inline bool FindActiveValues<TreeT>::anyActiveVoxels(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const
448{
449 const auto &mask = leaf->getValueMask();
450
451 // check for two common cases that leads to early-out
452 if (bbox.isInside(leaf->getNodeBoundingBox())) return !mask.isOff();// leaf in inside the bbox
453 if (mask.isOn()) return true;// all values are active
454
455 bool active = false;
456 for (auto i = leaf->cbeginValueOn(); !active && i; ++i) {
457 active = bbox.isInside(i.getCoord());
458 }
459 return active;
460}
461
462template<typename TreeT>
463template<typename NodeT>
464bool FindActiveValues<TreeT>::anyActiveTiles(const NodeT* node, const CoordBBox &bbox) const
465{
466 // Generate a bit mask of the bbox coverage
467 auto mask = this->getBBoxMask(bbox, node);
468
469 // Check active tiles
470 const auto tmp = mask & node->getValueMask();// prune active the tile mask with the bbox mask
471 if (!tmp.isOff()) return true;
472
473 bool active = false;
474 if (NodeT::LEVEL>1) {// Only check child nodes if they are NOT leaf nodes
475 mask &= node->getChildMask();// prune the child mask with the bbox mask
476 const auto* table = node->getTable();
477 for (auto i = mask.beginOn(); !active && i; ++i) {
478 active = this->anyActiveTiles(table[i.pos()].getChild(), bbox);
479 }
480 }
481 return active;
482}
483
484template<typename TreeT>
485inline Index64 FindActiveValues<TreeT>::count(const typename TreeT::LeafNodeType* leaf, const CoordBBox &bbox ) const
486{
487 Index64 count = 0;
488 auto b = leaf->getNodeBoundingBox();
489 if (b.isInside(bbox)) { // leaf node is completely inside bbox
490 count = leaf->onVoxelCount();
491 } else if (leaf->isDense()) {
492 b.intersect(bbox);
493 count = b.volume();
494 } else if (b.hasOverlap(bbox)) {
495 for (auto i = leaf->cbeginValueOn(); i; ++i) {
496 if (bbox.isInside(i.getCoord())) ++count;
497 }
498 }
499 return count;
500}
501
502template<typename TreeT>
503template<typename NodeT>
504Index64 FindActiveValues<TreeT>::count(const NodeT* node, const CoordBBox &bbox) const
505{
506 Index64 count = 0;
507
508 // Generate a bit masks
509 auto mask = this->getBBoxMask(bbox, node);
510 const auto childMask = mask & node->getChildMask();// prune the child mask with the bbox mask
511 mask &= node->getValueMask();// prune active tile mask with the bbox mask
512 const auto* table = node->getTable();
513
514 {// Check child nodes
515 using ChildT = typename NodeT::ChildNodeType;
516 using RangeT = tbb::blocked_range<typename std::vector<const ChildT*>::iterator>;
517 std::vector<const ChildT*> childNodes(childMask.countOn());
518 int j=0;
519 for (auto i = childMask.beginOn(); i; ++i, ++j) childNodes[j] = table[i.pos()].getChild();
520 count += tbb::parallel_reduce( RangeT(childNodes.begin(), childNodes.end()), 0,
521 [&](const RangeT& r, Index64 sum)->Index64 {
522 for ( auto i = r.begin(); i != r.end(); ++i ) sum += this->count(*i, bbox);
523 return sum;
524 }, []( Index64 a, Index64 b )->Index64 { return a+b; }
525 );
526 }
527
528 {// Check active tiles
529 std::vector<Coord> coords(mask.countOn());
530 using RangeT = tbb::blocked_range<typename std::vector<Coord>::iterator>;
531 int j=0;
532 for (auto i = mask.beginOn(); i; ++i, ++j) coords[j] = node->offsetToGlobalCoord(i.pos());
533 count += tbb::parallel_reduce( RangeT(coords.begin(), coords.end()), 0,
534 [&bbox](const RangeT& r, Index64 sum)->Index64 {
535 for ( auto i = r.begin(); i != r.end(); ++i ) {
536 auto b = CoordBBox::createCube(*i, NodeT::ChildNodeType::DIM);
537 b.intersect(bbox);
538 sum += b.volume();
539 }
540 return sum;
541 }, []( Index64 a, Index64 b )->Index64 { return a+b; }
542 );
543 }
544
545 return count;
546}
547
548// process internal node
549template<typename TreeT>
550template<typename NodeT>
551void FindActiveValues<TreeT>::activeTiles(const NodeT* node, const CoordBBox &bbox, std::vector<TileDataT> &tiles) const
552{
553 // Generate a bit masks
554 auto mask = this->getBBoxMask(bbox, node);
555 const auto childMask = mask & node->getChildMask();// prune the child mask with the bbox mask
556 mask &= node->getValueMask();// prune active tile mask with the bbox mask
557
558 if (NodeT::LEVEL > 1) {// Only check child nodes if they are NOT leaf nodes
559 const auto* table = node->getTable();
560 for (auto i = childMask.beginOn(); i; ++i) this->activeTiles(table[i.pos()].getChild(), bbox, tiles);
561 }
562
563 const size_t tileCount = mask.countOn();
564 if (tileCount < 8) {// Serial processing of active tiles
565 for (auto iter = mask.beginOn(); iter; ++iter) {
566 tiles.emplace_back(*node, iter.pos());
567 tiles.back().bbox.intersect(bbox);
568 }
569 } else {// Parallel processing of active tiles
570 std::vector<TileDataT> tmp( tileCount );// for temporary thread-safe processing
571 int n = 0;
572 for (auto iter = mask.beginOn(); iter; ++iter) tmp[n++].level = iter.pos();// placeholder to support multi-threading
573 tbb::parallel_for(tbb::blocked_range<size_t>(0, tileCount, 8), [&](const tbb::blocked_range<size_t>& r) {
574 for ( size_t i = r.begin(); i != r.end(); ++i ) {
575 tmp[i] = TileDataT(*node, tmp[i].level);
576 tmp[i].bbox.intersect(bbox);
577 }
578 });
579 tiles.insert(tiles.end(), tmp.begin(), tmp.end());
580 }
581}
582
583template<typename TreeT>
585{
587 const RootChildType* child;
588 RootChild(const Coord& ijk = Coord(), const RootChildType* ptr = nullptr)
589 : bbox(CoordBBox::createCube(ijk, RootChildType::DIM)), child(ptr)
590 {
591 }
592};// RootChild struct
593
594//////////////////////////////////////////////////////////////////////////////////////////
595
596template<typename ValueType>
598{
600 ValueType value;
602 bool state;
603
604 /// @brief Default constructor
605 TileData() = default;
606
607 /// @brief Member data constructor
608 TileData(const CoordBBox &b, const ValueType &v, Index l, bool active = true)
609 : bbox(b), value(v), level(l), state(active) {}
610
611 /// @brief Constructor from a parent node and the linear offset to one of its tiles
612 ///
613 /// @warning This is an expert-only method since it assumes the linear offset to be valid,
614 /// i.e. within the rand of the dimension of the parent node and NOT corresponding
615 /// to a child node.
616 template <typename ParentNodeT>
617 TileData(const ParentNodeT &parent, Index childIdx)
618 : bbox(CoordBBox::createCube(parent.offsetToGlobalCoord(childIdx), parent.getChildDim()))
619 , level(parent.getLevel())
620 , state(true)
621 {
622 assert(childIdx < ParentNodeT::NUM_VALUES);
623 assert(parent.isChildMaskOff(childIdx));
624 assert(parent.isValueMaskOn(childIdx));
625 value = parent.getTable()[childIdx].getValue();
626 }
627
628 /// @brief Constructor form a parent node, the coordinate of the origin of one of its tiles,
629 /// and said tiles value.
630 template <typename ParentNodeT>
631 TileData(const ParentNodeT &parent, const Coord &ijk, const ValueType &v)
632 : bbox(CoordBBox::createCube(ijk, parent.getChildDim()))
633 , value(v)
634 , level(parent.getLevel())
635 , state(true)
636 {
637 }
638};// TileData struct
639
640//////////////////////////////////////////////////////////////////////////////////////////
641
642// Implementation of stand-alone function
643template<typename TreeT>
644bool
645anyActiveValues(const TreeT& tree, const CoordBBox &bbox)
646{
648 return op.anyActiveValues(bbox);
649}
650
651// Implementation of stand-alone function
652template<typename TreeT>
653bool
654anyActiveVoxels(const TreeT& tree, const CoordBBox &bbox)
655{
657 return op.anyActiveVoxels(bbox);
658}
659
660// Implementation of stand-alone function
661template<typename TreeT>
662bool
663anyActiveTiles(const TreeT& tree, const CoordBBox &bbox)
664{
666 return op.anyActiveTiles(bbox);
667}
668
669// Implementation of stand-alone function
670template<typename TreeT>
671bool
672noActiveValues(const TreeT& tree, const CoordBBox &bbox)
673{
675 return op.noActiveValues(bbox);
676}
677
678// Implementation of stand-alone function
679template<typename TreeT>
681countActiveValues(const TreeT& tree, const CoordBBox &bbox)
682{
683 return tools::countActiveVoxels(tree, bbox);
684}
685
686// Implementation of stand-alone function
687template<typename TreeT>
688std::vector<TileData<typename TreeT::ValueType>>
689activeTiles(const TreeT& tree, const CoordBBox &bbox)
690{
692 return op.activeTiles(bbox);
693}
694
695
696////////////////////////////////////////
697
698
699// Explicit Template Instantiation
700
701#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
702
703#ifdef OPENVDB_INSTANTIATE_FINDACTIVEVALUES
705#endif
706
707#define _FUNCTION(TreeT) \
708 bool anyActiveValues(const TreeT&, const CoordBBox&)
710#undef _FUNCTION
711
712#define _FUNCTION(TreeT) \
713 bool anyActiveVoxels(const TreeT&, const CoordBBox&)
715#undef _FUNCTION
716
717#define _FUNCTION(TreeT) \
718 bool anyActiveTiles(const TreeT&, const CoordBBox&)
720#undef _FUNCTION
721
722#define _FUNCTION(TreeT) \
723 bool noActiveValues(const TreeT&, const CoordBBox&)
725#undef _FUNCTION
726
727#define _FUNCTION(TreeT) \
728 Index64 countActiveValues(const TreeT&, const CoordBBox&)
730#undef _FUNCTION
731
732#define _FUNCTION(TreeT) \
733 std::vector<TileData<TreeT::ValueType>> activeTiles(const TreeT&, const CoordBBox&)
735#undef _FUNCTION
736
737#endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
738
739
740} // namespace tools
741} // namespace OPENVDB_VERSION_NAME
742} // namespace openvdb
743
744#endif // OPENVDB_TOOLS_FINDACTIVEVALUES_HAS_BEEN_INCLUDED
Functions to count tiles, nodes or voxels in a grid.
ValueT value
Definition: GridBuilder.h:1290
ChildT * child
Definition: GridBuilder.h:1289
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
const Coord & min() const
Definition: Coord.h:321
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:412
const Coord & max() const
Definition: Coord.h:322
Index64 volume() const
Return the integer volume of coordinates spanned by this bounding box.
Definition: Coord.h:385
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:400
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:232
bool anyActiveTiles(const CoordBBox &bbox) const
Returns true if the specified bounding box intersects any active tiles only.
Definition: FindActiveValues.h:305
bool anyActiveVoxels(const CoordBBox &bbox) const
Returns true if the specified bounding box intersects any active tiles only.
Definition: FindActiveValues.h:290
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:353
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:238
Index64 count(const CoordBBox &bbox) const
Returns the number of active voxels intersected by the specified bounding box.
Definition: FindActiveValues.h:323
bool anyActiveValues(const CoordBBox &bbox, bool useAccessor=false) const
Returns true if the specified bounding box intersects any active values.
Definition: FindActiveValues.h:265
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:681
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:645
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:689
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:663
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:654
Index64 countActiveVoxels(const TreeT &tree, bool threaded=true)
Return the total number of active voxels in the tree.
Definition: Count.h:413
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:672
Index32 Index
Definition: Types.h:54
uint64_t Index64
Definition: Types.h:53
Definition: Exceptions.h:13
Definition: FindActiveValues.h:585
RootChild(const Coord &ijk=Coord(), const RootChildType *ptr=nullptr)
Definition: FindActiveValues.h:588
const RootChildType * child
Definition: FindActiveValues.h:587
const CoordBBox bbox
Definition: FindActiveValues.h:586
Struct that encodes a bounding box, value and level of a tile.
Definition: FindActiveValues.h:598
TileData(const ParentNodeT &parent, Index childIdx)
Constructor from a parent node and the linear offset to one of its tiles.
Definition: FindActiveValues.h:617
TileData()=default
Default constructor.
bool state
Definition: FindActiveValues.h:602
ValueType value
Definition: FindActiveValues.h:600
CoordBBox bbox
Definition: FindActiveValues.h:599
Index level
Definition: FindActiveValues.h:601
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:631
TileData(const CoordBBox &b, const ValueType &v, Index l, bool active=true)
Member data constructor.
Definition: FindActiveValues.h:608
#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:212
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
Definition: version.h.in:160