OpenVDB  9.0.1
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 
37 namespace openvdb {
39 namespace OPENVDB_VERSION_NAME {
40 namespace 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.
46 template<typename ValueType>
47 struct 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.
58 template<typename TreeT>
59 bool
60 anyActiveValues(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.
74 template<typename TreeT>
75 bool
76 anyActiveVoxels(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.
87 template<typename TreeT>
88 bool
89 anyActiveTiles(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.
100 template<typename TreeT>
101 bool
102 noActiveValues(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.
113 template<typename TreeT>
114 Index64
115 countActiveValues(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.
126 template<typename TreeT>
127 std::vector<TileData<typename TreeT::ValueType>>
128 activeTiles(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.
139 template<typename TreeT>
141 {
142 public:
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
150  ~FindActiveValues();
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 
191 private:
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 
234 template<typename TreeT>
235 FindActiveValues<TreeT>::FindActiveValues(const TreeT& tree) : mAcc(tree), mRootTiles(), mRootNodes()
236 {
237  this->init(tree);
238 }
239 
240 template<typename TreeT>
242 {
243  this->clear();
244 }
245 
246 template<typename TreeT>
247 void FindActiveValues<TreeT>::update(const TreeT& tree)
248 {
249  this->clear();
250  mAcc = AccT(tree);
251  this->init(tree);
252 }
253 
254 template<typename TreeT>
256 {
257  mRootNodes.clear();
258  mRootTiles.clear();
259 }
260 
261 template<typename TreeT>
262 void 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 
273 template<typename TreeT>
274 bool 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 
298 template<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 
313 template<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 
331 template<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 
360 template<typename TreeT>
361 std::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 
392 template<typename TreeT>
393 template<typename NodeT>
394 typename 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 
417 template<typename TreeT>
418 template<typename NodeT>
419 bool 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 
438 template<typename TreeT>
439 template<typename NodeT>
440 bool 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 
455 template<typename TreeT>
456 inline 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 
471 template<typename TreeT>
472 template<typename NodeT>
473 bool 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 
493 template<typename TreeT>
494 inline 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 
511 template<typename TreeT>
512 template<typename NodeT>
513 Index64 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
558 template<typename TreeT>
559 template<typename NodeT>
560 void 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 
592 template<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 
605 template<typename ValueType>
606 struct TileData
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
652 template<typename TreeT>
653 bool
654 anyActiveValues(const TreeT& tree, const CoordBBox &bbox)
655 {
656  FindActiveValues<TreeT> op(tree);
657  return op.anyActiveValues(bbox);
658 }
659 
660 // Implementation of stand-alone function
661 template<typename TreeT>
662 bool
663 anyActiveVoxels(const TreeT& tree, const CoordBBox &bbox)
664 {
665  FindActiveValues<TreeT> op(tree);
666  return op.anyActiveVoxels(bbox);
667 }
668 
669 // Implementation of stand-alone function
670 template<typename TreeT>
671 bool
672 anyActiveTiles(const TreeT& tree, const CoordBBox &bbox)
673 {
674  FindActiveValues<TreeT> op(tree);
675  return op.anyActiveTiles(bbox);
676 }
677 
678 // Implementation of stand-alone function
679 template<typename TreeT>
680 bool
681 noActiveValues(const TreeT& tree, const CoordBBox &bbox)
682 {
683  FindActiveValues<TreeT> op(tree);
684  return op.noActiveValues(bbox);
685 }
686 
687 // Implementation of stand-alone function
688 template<typename TreeT>
689 Index64
690 countActiveValues(const TreeT& tree, const CoordBBox &bbox)
691 {
692  return tools::countActiveVoxels(tree, bbox);
693 }
694 
695 // Implementation of stand-alone function
696 template<typename TreeT>
697 std::vector<TileData<typename TreeT::ValueType>>
698 activeTiles(const TreeT& tree, const CoordBBox &bbox)
699 {
700  FindActiveValues<TreeT> op(tree);
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
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 isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:226
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
Definition: version.h.in:150
TileData< typename TreeT::ValueType > TileDataT
Definition: FindActiveValues.h:144
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. ignores active leaf values.
Definition: FindActiveValues.h:672
bool anyActiveValues(const CoordBBox &bbox, bool useAccessor=false) const
Returns true if the specified bounding box intersects any active values.
Definition: FindActiveValues.h:274
RootChild(const Coord &ijk=Coord(), const RootChildType *ptr=nullptr)
Definition: FindActiveValues.h:597
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
ValueType value
Definition: FindActiveValues.h:609
~FindActiveValues()
Default destructor.
Definition: FindActiveValues.h:241
Index level
Definition: FindActiveValues.h:610
void update(const TreeT &tree)
Initiate this class with a new (or modified) tree.
Definition: FindActiveValues.h:247
Definition: FindActiveValues.h:593
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
const CoordBBox bbox
Definition: FindActiveValues.h:595
Index64 countActiveVoxels(const TreeT &tree, bool threaded=true)
Return the total number of active voxels in the tree.
Definition: Count.h:328
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition: ValueAccessor.h:110
Struct that encodes a bounding box, value and level of a tile.
Definition: FindActiveValues.h:47
Index64 countActiveValues(const TreeT &tree, const CoordBBox &bbox)
Returns the number of active values that intersects a bounding box intersects, i.e. the count includes both active voxels and virtual voxels in active tiles.
Definition: FindActiveValues.h:690
Finds the active values in a tree which intersects a bounding box.
Definition: FindActiveValues.h:140
uint64_t Index64
Definition: Types.h:53
Definition: Exceptions.h:13
bool anyActiveValues(const TreeT &tree, const CoordBBox &bbox)
Returns true if the bounding box intersects any of the active values in a tree, i.e. either active voxels or active tiles.
Definition: FindActiveValues.h:654
Level getLevel()
Return the current logging level.
Definition: logging.h:141
const RootChildType * child
Definition: FindActiveValues.h:596
Index32 Index
Definition: Types.h:54
bool anyActiveVoxels(const TreeT &tree, const CoordBBox &bbox)
Returns true if the bounding box intersects any of the active voxels in a tree, i.e. ignores active tile values.
Definition: FindActiveValues.h:663
bool anyActiveVoxels(const CoordBBox &bbox) const
Returns true if the specified bounding box intersects any active tiles only.
Definition: FindActiveValues.h:299
Functions to count tiles, nodes or voxels in a grid.
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
bool anyActiveTiles(const CoordBBox &bbox) const
Returns true if the specified bounding box intersects any active tiles only.
Definition: FindActiveValues.h:314
Index64 count(const CoordBBox &bbox) const
Returns the number of active voxels intersected by the specified bounding box.
Definition: FindActiveValues.h:332
bool noActiveValues(const TreeT &tree, const CoordBBox &bbox)
Returns true if the bounding box intersects none of the active values in a tree, i.e. neither active voxels or active tiles.
Definition: FindActiveValues.h:681
CoordBBox bbox
Definition: FindActiveValues.h:608
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
TileData(const CoordBBox &b, const ValueType &v, Index l, bool active=true)
Member data constructor.
Definition: FindActiveValues.h:617
TileData(const ParentNodeT &parent, Index childIdx)
Constructor from a parent node and the linear offset to one of its tiles.
Definition: FindActiveValues.h:626
bool state
Definition: FindActiveValues.h:611
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
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition: Platform.h:123
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202