OpenVDB  6.2.0
Clip.h
Go to the documentation of this file.
1 //
3 // Copyright (c) DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 
35 
36 #ifndef OPENVDB_TOOLS_CLIP_HAS_BEEN_INCLUDED
37 #define OPENVDB_TOOLS_CLIP_HAS_BEEN_INCLUDED
38 
39 #include <openvdb/Grid.h>
40 #include <openvdb/math/Math.h> // for math::isNegative()
41 #include <openvdb/math/Maps.h> // for math::NonlinearFrustumMap
43 #include "GridTransformer.h" // for tools::resampleToMatch()
44 #include "Prune.h"
45 #include <tbb/blocked_range.h>
46 #include <tbb/parallel_reduce.h>
47 #include <type_traits> // for std::enable_if, std::is_same
48 #include <vector>
49 
50 
51 namespace openvdb {
53 namespace OPENVDB_VERSION_NAME {
54 namespace tools {
55 
64 template<typename GridType>
65 inline typename GridType::Ptr
66 clip(const GridType& grid, const BBoxd& bbox, bool keepInterior = true);
67 
75 template<typename GridType>
76 inline typename GridType::Ptr
77 clip(const GridType& grid, const math::NonlinearFrustumMap& frustum, bool keepInterior = true);
78 
91 template<typename GridType, typename MaskTreeType>
92 inline typename GridType::Ptr
93 clip(const GridType& grid, const Grid<MaskTreeType>& mask, bool keepInterior = true);
94 
95 
97 
98 
99 namespace clip_internal {
100 
101 // Use either MaskGrids or BoolGrids internally.
102 // (MaskGrids have a somewhat lower memory footprint.)
104 //using MaskValueType = bool;
105 
106 
107 template<typename TreeT>
109 {
110 public:
111  using ValueT = typename TreeT::ValueType;
112  using LeafNodeT = typename TreeT::LeafNodeType;
113 
114  MaskInteriorVoxels(const TreeT& tree): mAcc(tree) {}
115 
116  template<typename LeafNodeType>
117  void operator()(LeafNodeType& leaf, size_t /*leafIndex*/) const
118  {
119  const auto* refLeaf = mAcc.probeConstLeaf(leaf.origin());
120  if (refLeaf) {
121  for (auto iter = leaf.beginValueOff(); iter; ++iter) {
122  const auto pos = iter.pos();
123  leaf.setActiveState(pos, math::isNegative(refLeaf->getValue(pos)));
124  }
125  }
126  }
127 
128 private:
130 };
131 
132 
134 
135 
136 template<typename TreeT>
138 {
139 public:
140  using MaskTreeT = typename TreeT::template ValueConverter<MaskValueType>::Type;
142 
143  CopyLeafNodes(const TreeT&, const MaskLeafManagerT&);
144 
145  void run(bool threaded = true);
146 
147  typename TreeT::Ptr tree() const { return mNewTree; }
148 
149  CopyLeafNodes(CopyLeafNodes&, tbb::split);
150  void operator()(const tbb::blocked_range<size_t>&);
151  void join(const CopyLeafNodes& rhs) { mNewTree->merge(*rhs.mNewTree); }
152 
153 private:
154  const MaskTreeT* mClipMask;
155  const TreeT* mTree;
156  const MaskLeafManagerT* mLeafNodes;
157  typename TreeT::Ptr mNewTree;
158 };
159 
160 
161 template<typename TreeT>
162 CopyLeafNodes<TreeT>::CopyLeafNodes(const TreeT& tree, const MaskLeafManagerT& leafNodes)
163  : mTree(&tree)
164  , mLeafNodes(&leafNodes)
165  , mNewTree(new TreeT(mTree->background()))
166 {
167 }
168 
169 
170 template<typename TreeT>
172  : mTree(rhs.mTree)
173  , mLeafNodes(rhs.mLeafNodes)
174  , mNewTree(new TreeT(mTree->background()))
175 {
176 }
177 
178 
179 template<typename TreeT>
180 void
182 {
183  if (threaded) tbb::parallel_reduce(mLeafNodes->getRange(), *this);
184  else (*this)(mLeafNodes->getRange());
185 }
186 
187 
188 template<typename TreeT>
189 void
190 CopyLeafNodes<TreeT>::operator()(const tbb::blocked_range<size_t>& range)
191 {
192  tree::ValueAccessor<TreeT> acc(*mNewTree);
193  tree::ValueAccessor<const TreeT> refAcc(*mTree);
194 
195  for (auto n = range.begin(); n != range.end(); ++n) {
196  const auto& maskLeaf = mLeafNodes->leaf(n);
197  const auto& ijk = maskLeaf.origin();
198  const auto* refLeaf = refAcc.probeConstLeaf(ijk);
199 
200  auto* newLeaf = acc.touchLeaf(ijk);
201 
202  if (refLeaf) {
203  for (auto it = maskLeaf.cbeginValueOn(); it; ++it) {
204  const auto pos = it.pos();
205  newLeaf->setValueOnly(pos, refLeaf->getValue(pos));
206  newLeaf->setActiveState(pos, refLeaf->isValueOn(pos));
207  }
208  } else {
209  typename TreeT::ValueType value;
210  bool isActive = refAcc.probeValue(ijk, value);
211 
212  for (auto it = maskLeaf.cbeginValueOn(); it; ++it) {
213  const auto pos = it.pos();
214  newLeaf->setValueOnly(pos, value);
215  newLeaf->setActiveState(pos, isActive);
216  }
217  }
218  }
219 }
220 
221 
223 
224 
226 {
227  static const char* name() { return "bin"; }
228  static int radius() { return 2; }
229  static bool mipmap() { return false; }
230  static bool consistent() { return true; }
231 
232  template<class TreeT>
233  static bool sample(const TreeT& inTree,
234  const Vec3R& inCoord, typename TreeT::ValueType& result)
235  {
236  return inTree.probeValue(Coord::floor(inCoord), result);
237  }
238 };
239 
240 
242 
243 
244 // Convert a grid of one type to a grid of another type
245 template<typename FromGridT, typename ToGridT>
247 {
248  using FromGridCPtrT = typename FromGridT::ConstPtr;
249  using ToGridPtrT = typename ToGridT::Ptr;
250  ToGridPtrT operator()(const FromGridCPtrT& grid) { return ToGridPtrT(new ToGridT(*grid)); }
251 };
252 
253 // Partial specialization that avoids copying when
254 // the input and output grid types are the same
255 template<typename GridT>
256 struct ConvertGrid<GridT, GridT>
257 {
258  using GridCPtrT = typename GridT::ConstPtr;
259  GridCPtrT operator()(const GridCPtrT& grid) { return grid; }
260 };
261 
262 
264 
265 
266 // Convert a grid of arbitrary type to a mask grid with the same tree configuration
267 // and return a pointer to the new grid.
269 template<typename GridT>
270 inline typename std::enable_if<!std::is_same<MaskValueType, typename GridT::BuildType>::value,
271  typename GridT::template ValueConverter<MaskValueType>::Type::Ptr>::type
272 convertToMaskGrid(const GridT& grid)
273 {
274  using MaskGridT = typename GridT::template ValueConverter<MaskValueType>::Type;
275  auto mask = MaskGridT::create(/*background=*/false);
276  mask->topologyUnion(grid);
277  mask->setTransform(grid.constTransform().copy());
278  return mask;
279 }
280 
281 // Overload that avoids any processing if the input grid is already a mask grid
283 template<typename GridT>
284 inline typename std::enable_if<std::is_same<MaskValueType, typename GridT::BuildType>::value,
285  typename GridT::ConstPtr>::type
286 convertToMaskGrid(const GridT& grid)
287 {
288  return grid.copy(); // shallow copy
289 }
290 
291 
293 
294 
296 template<typename GridType>
297 inline typename GridType::Ptr
298 doClip(
299  const GridType& grid,
300  const typename GridType::template ValueConverter<MaskValueType>::Type& clipMask,
301  bool keepInterior)
302 {
303  using TreeT = typename GridType::TreeType;
304  using MaskTreeT = typename GridType::TreeType::template ValueConverter<MaskValueType>::Type;
305 
306  const auto gridClass = grid.getGridClass();
307  const auto& tree = grid.tree();
308 
309  MaskTreeT gridMask(false);
310  gridMask.topologyUnion(tree);
311 
312  if (gridClass == GRID_LEVEL_SET) {
313  tree::LeafManager<MaskTreeT> leafNodes(gridMask);
315 
317 
318  typename MaskTreeT::ValueAllIter iter(gridMask);
319  iter.setMaxDepth(MaskTreeT::ValueAllIter::LEAF_DEPTH - 1);
320 
321  for ( ; iter; ++iter) {
322  iter.setActiveState(math::isNegative(acc.getValue(iter.getCoord())));
323  }
324  }
325 
326  if (keepInterior) {
327  gridMask.topologyIntersection(clipMask.constTree());
328  } else {
329  gridMask.topologyDifference(clipMask.constTree());
330  }
331 
332 #if OPENVDB_ABI_VERSION_NUMBER <= 3
333  auto outGrid = grid.copy(CP_NEW);
334 #else
335  auto outGrid = grid.copyWithNewTree();
336 #endif
337  {
338  // Copy voxel values and states.
339  tree::LeafManager<const MaskTreeT> leafNodes(gridMask);
340  CopyLeafNodes<TreeT> maskOp(tree, leafNodes);
341  maskOp.run();
342  outGrid->setTree(maskOp.tree());
343  }
344  {
345  // Copy tile values and states.
347  tree::ValueAccessor<const MaskTreeT> maskAcc(gridMask);
348 
349  typename TreeT::ValueAllIter it(outGrid->tree());
350  it.setMaxDepth(TreeT::ValueAllIter::LEAF_DEPTH - 1);
351  for ( ; it; ++it) {
352  Coord ijk = it.getCoord();
353 
354  if (maskAcc.isValueOn(ijk)) {
355  typename TreeT::ValueType value;
356  bool isActive = refAcc.probeValue(ijk, value);
357 
358  it.setValue(value);
359  if (!isActive) it.setValueOff();
360  }
361  }
362  }
363 
364  outGrid->setTransform(grid.transform().copy());
365  if (gridClass != GRID_LEVEL_SET) outGrid->setGridClass(gridClass);
366 
367  return outGrid;
368 }
369 
370 } // namespace clip_internal
371 
372 
374 
375 
377 template<typename GridType>
378 inline typename GridType::Ptr
379 clip(const GridType& grid, const BBoxd& bbox, bool keepInterior)
380 {
381  using MaskValueT = clip_internal::MaskValueType;
382  using MaskGridT = typename GridType::template ValueConverter<MaskValueT>::Type;
383 
384  // Transform the world-space bounding box into the source grid's index space.
385  Vec3d idxMin, idxMax;
386  math::calculateBounds(grid.constTransform(), bbox.min(), bbox.max(), idxMin, idxMax);
387  CoordBBox region(Coord::floor(idxMin), Coord::floor(idxMax));
388  // Construct a boolean mask grid that is true inside the index-space bounding box
389  // and false everywhere else.
390  MaskGridT clipMask(/*background=*/false);
391  clipMask.fill(region, /*value=*/true, /*active=*/true);
392 
393  return clip_internal::doClip(grid, clipMask, keepInterior);
394 }
395 
396 
398 template<typename SrcGridType, typename ClipTreeType>
399 inline typename SrcGridType::Ptr
400 clip(const SrcGridType& srcGrid, const Grid<ClipTreeType>& clipGrid, bool keepInterior)
401 {
402  using MaskValueT = clip_internal::MaskValueType;
403  using ClipGridType = Grid<ClipTreeType>;
404  using SrcMaskGridType = typename SrcGridType::template ValueConverter<MaskValueT>::Type;
405  using ClipMaskGridType = typename ClipGridType::template ValueConverter<MaskValueT>::Type;
406 
407  // Convert the clipping grid to a boolean-valued mask grid with the same tree configuration.
408  auto maskGrid = clip_internal::convertToMaskGrid(clipGrid);
409 
410  // Resample the mask grid into the source grid's index space.
411  if (srcGrid.constTransform() != maskGrid->constTransform()) {
412  auto resampledMask = ClipMaskGridType::create(/*background=*/false);
413  resampledMask->setTransform(srcGrid.constTransform().copy());
414  tools::resampleToMatch<clip_internal::BoolSampler>(*maskGrid, *resampledMask);
415  tools::prune(resampledMask->tree());
416  maskGrid = resampledMask;
417  }
418 
419  // Convert the mask grid to a mask grid with the same tree configuration as the source grid.
420  auto clipMask = clip_internal::ConvertGrid<
421  /*from=*/ClipMaskGridType, /*to=*/SrcMaskGridType>()(maskGrid);
422 
423  // Clip the source grid against the mask grid.
424  return clip_internal::doClip(srcGrid, *clipMask, keepInterior);
425 }
426 
427 
429 template<typename GridType>
430 inline typename GridType::Ptr
431 clip(const GridType& inGrid, const math::NonlinearFrustumMap& frustumMap, bool keepInterior)
432 {
433  using ValueT = typename GridType::ValueType;
434  using TreeT = typename GridType::TreeType;
435  using LeafT = typename TreeT::LeafNodeType;
436 
437  const auto& gridXform = inGrid.transform();
438  const auto frustumIndexBBox = frustumMap.getBBox();
439 
440  // Return true if index-space point (i,j,k) lies inside the frustum.
441  auto frustumContainsCoord = [&](const Coord& ijk) -> bool {
442  auto xyz = gridXform.indexToWorld(ijk);
443  xyz = frustumMap.applyInverseMap(xyz);
444  return frustumIndexBBox.isInside(xyz);
445  };
446 
447  // Return the frustum index-space bounding box of the corners of
448  // the given grid index-space bounding box.
449  auto toFrustumIndexSpace = [&](const CoordBBox& inBBox) -> BBoxd {
450  const Coord bounds[2] = { inBBox.min(), inBBox.max() };
451  Coord ijk;
452  BBoxd outBBox;
453  for (int i = 0; i < 8; ++i) {
454  ijk[0] = bounds[(i & 1) >> 0][0];
455  ijk[1] = bounds[(i & 2) >> 1][1];
456  ijk[2] = bounds[(i & 4) >> 2][2];
457  auto xyz = gridXform.indexToWorld(ijk);
458  xyz = frustumMap.applyInverseMap(xyz);
459  outBBox.expand(xyz);
460  }
461  return outBBox;
462  };
463 
464  // Construct an output grid with the same transform and metadata as the input grid.
465 #if OPENVDB_ABI_VERSION_NUMBER <= 3
466  auto outGrid = inGrid.copy(CP_NEW);
467 #else
468  auto outGrid = inGrid.copyWithNewTree();
469 #endif
470  if (outGrid->getGridClass() == GRID_LEVEL_SET) {
471  // After clipping, a level set grid might no longer be a valid SDF.
472  outGrid->setGridClass(GRID_UNKNOWN);
473  }
474 
475  const auto& bg = outGrid->background();
476 
477  auto outAcc = outGrid->getAccessor();
478 
479  // Copy active and inactive tiles that intersect the clipping region
480  // from the input grid to the output grid.
481  // ("Clipping region" refers to either the interior or the exterior
482  // of the frustum, depending on the value of keepInterior.)
483  auto tileIter = inGrid.beginValueAll();
484  tileIter.setMaxDepth(GridType::ValueAllIter::LEAF_DEPTH - 1);
485  CoordBBox tileBBox;
486  for ( ; tileIter; ++tileIter) {
487  const bool tileActive = tileIter.isValueOn();
488  const auto& tileValue = tileIter.getValue();
489 
490  // Skip background tiles.
491  if (!tileActive && math::isApproxEqual(tileValue, bg)) continue;
492 
493  // Transform the tile's bounding box into frustum index space.
494  tileIter.getBoundingBox(tileBBox);
495  const auto tileFrustumBBox = toFrustumIndexSpace(tileBBox);
496 
497  // Determine whether any or all of the tile intersects the clipping region.
498  enum class CopyTile { kNone, kPartial, kFull };
499  auto copyTile = CopyTile::kNone;
500  if (keepInterior) {
501  if (frustumIndexBBox.isInside(tileFrustumBBox)) {
502  copyTile = CopyTile::kFull;
503  } else if (frustumIndexBBox.hasOverlap(tileFrustumBBox)) {
504  copyTile = CopyTile::kPartial;
505  }
506  } else {
507  if (!frustumIndexBBox.hasOverlap(tileFrustumBBox)) {
508  copyTile = CopyTile::kFull;
509  } else if (!frustumIndexBBox.isInside(tileFrustumBBox)) {
510  copyTile = CopyTile::kPartial;
511  }
512  }
513  switch (copyTile) {
514  case CopyTile::kNone:
515  break;
516  case CopyTile::kFull:
517  // Copy the entire tile.
518  outAcc.addTile(tileIter.getLevel(), tileBBox.min(), tileValue, tileActive);
519  break;
520  case CopyTile::kPartial:
521  // Copy only voxels inside the clipping region.
522  for (std::vector<CoordBBox> bboxVec = { tileBBox }; !bboxVec.empty(); ) {
523  // For efficiency, subdivide sufficiently large tiles and discard
524  // subregions based on additional bounding box intersection tests.
525  // The mimimum subregion size is chosen so that cost of the
526  // bounding box test is comparable to testing every voxel.
527  if (bboxVec.back().volume() > 64 && bboxVec.back().is_divisible()) {
528  // Subdivide this region in-place and append the other half to the list.
529  bboxVec.emplace_back(bboxVec.back(), tbb::split{});
530  continue;
531  }
532  auto subBBox = bboxVec.back();
533  bboxVec.pop_back();
534 
535  // Discard the subregion if it lies completely outside the clipping region.
536  if (keepInterior) {
537  if (!frustumIndexBBox.hasOverlap(toFrustumIndexSpace(subBBox))) continue;
538  } else {
539  if (frustumIndexBBox.isInside(toFrustumIndexSpace(subBBox))) continue;
540  }
541 
542  // Test every voxel within the subregion.
543  for (const auto& ijk: subBBox) {
544  if (frustumContainsCoord(ijk) == keepInterior) {
545  if (tileActive) {
546  outAcc.setValueOn(ijk, tileValue);
547  } else {
548  outAcc.setValueOff(ijk, tileValue);
549  }
550  }
551  }
552  }
553  break;
554  }
555  }
556  tools::prune(outGrid->tree());
557 
558  // Ensure that the output grid has the same leaf node topology as the input grid,
559  // with the exception of leaf nodes that lie completely outside the clipping region.
560  // (This operation is serial.)
561  for (auto leafIter = inGrid.constTree().beginLeaf(); leafIter; ++leafIter) {
562  const auto leafBBox = leafIter->getNodeBoundingBox();
563  const auto leafFrustumBBox = toFrustumIndexSpace(leafBBox);
564  if (keepInterior) {
565  if (frustumIndexBBox.hasOverlap(leafFrustumBBox)) {
566  outAcc.touchLeaf(leafBBox.min());
567  }
568  } else {
569  if (!frustumIndexBBox.hasOverlap(leafFrustumBBox)
570  || !frustumIndexBBox.isInside(leafFrustumBBox))
571  {
572  outAcc.touchLeaf(leafBBox.min());
573  }
574  }
575  }
576 
577  // In parallel across output leaf nodes, copy leaf voxels
578  // from the input grid to the output grid.
579  tree::LeafManager<TreeT> outLeafNodes{outGrid->tree()};
580  outLeafNodes.foreach(
581  [&](LeafT& leaf, size_t /*idx*/) {
582  auto inAcc = inGrid.getConstAccessor();
583  ValueT val;
584  for (auto voxelIter = leaf.beginValueAll(); voxelIter; ++voxelIter) {
585  const auto ijk = voxelIter.getCoord();
586  if (frustumContainsCoord(ijk) == keepInterior) {
587  const bool active = inAcc.probeValue(ijk, val);
588  voxelIter.setValue(val);
589  voxelIter.setValueOn(active);
590  }
591  }
592  }
593  );
594 
595  return outGrid;
596 }
597 
598 } // namespace tools
599 } // namespace OPENVDB_VERSION_NAME
600 } // namespace openvdb
601 
602 #endif // OPENVDB_TOOLS_CLIP_HAS_BEEN_INCLUDED
603 
604 // Copyright (c) DreamWorks Animation LLC
605 // All rights reserved. This software is distributed under the
606 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
static bool consistent()
Definition: Clip.h:230
const BBoxd & getBBox() const
Return the bounding box that defines the frustum in pre-image space.
Definition: Maps.h:2377
GridCPtrT operator()(const GridCPtrT &grid)
Definition: Clip.h:259
void run(bool threaded=true)
Definition: Clip.h:181
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
This map is composed of three steps. First it will take a box of size (Lx X Ly X Lz) defined by a mem...
Definition: Maps.h:1905
OPENVDB_API void calculateBounds(const Transform &t, const Vec3d &minWS, const Vec3d &maxWS, Vec3d &minIS, Vec3d &maxIS)
Calculate an axis-aligned bounding box in index space from an axis-aligned bounding box in world spac...
static int radius()
Definition: Clip.h:228
typename FromGridT::ConstPtr FromGridCPtrT
Definition: Clip.h:248
MaskInteriorVoxels(const TreeT &tree)
Definition: Clip.h:114
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:361
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
Definition: ValueAccessor.h:386
math::BBox< Vec3d > BBoxd
Definition: Types.h:91
void operator()(LeafNodeType &leaf, size_t) const
Definition: Clip.h:117
void join(const CopyLeafNodes &rhs)
Definition: Clip.h:151
typename TreeT::template ValueConverter< MaskValueType >::Type MaskTreeT
Definition: Clip.h:140
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
typename GridT::ConstPtr GridCPtrT
Definition: Clip.h:258
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:267
Vec3< double > Vec3d
Definition: Vec3.h:689
Defined various multi-threaded utility functions for trees.
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:342
void expand(ElementType padding)
Pad this bounding box.
Definition: BBox.h:348
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:128
ValueMask MaskValueType
Definition: Clip.h:103
bool isApproxEqual(const Type &a, const Type &b)
Return true if a is equal to b to within the default floating-point comparison tolerance.
Definition: Math.h:378
bool isNegative(const Type &x)
Return true if x is less than zero.
Definition: Math.h:338
Definition: Exceptions.h:40
Vec3d applyInverseMap(const Vec3d &in) const override
Return the pre-image of in under the map.
Definition: Maps.h:2117
TreeT::Ptr tree() const
Definition: Clip.h:147
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:358
Definition: Types.h:504
ToGridPtrT operator()(const FromGridCPtrT &grid)
Definition: Clip.h:250
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:422
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:264
Definition: Types.h:503
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
const Vec3T & max() const
Return a const reference to the maximum point of this bounding box.
Definition: BBox.h:91
void operator()(const tbb::blocked_range< size_t > &)
Definition: Clip.h:190
GridType::Ptr clip(const GridType &grid, const BBoxd &bbox, bool keepInterior=true)
Clip the given grid against a world-space bounding box and return a new grid containing the result...
Definition: Clip.h:379
typename TreeT::LeafNodeType LeafNodeT
Definition: Clip.h:112
const Vec3T & min() const
Return a const reference to the minimum point of this bounding box.
Definition: BBox.h:89
Definition: Types.h:118
static bool mipmap()
Definition: Clip.h:229
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:180
A LeafManager manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional au...
CopyLeafNodes(const TreeT &, const MaskLeafManagerT &)
Definition: Clip.h:162
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Definition: Clip.h:233
static const char * name()
Definition: Clip.h:227
typename ToGridT::Ptr ToGridPtrT
Definition: Clip.h:249
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:257
RangeType getRange(size_t grainsize=1) const
Return a tbb::blocked_range of leaf array indices.
Definition: LeafManager.h:382
typename TreeT::ValueType ValueT
Definition: Clip.h:111
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:523