OpenVDB  7.1.0
GridTransformer.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
6 
7 #ifndef OPENVDB_TOOLS_GRIDTRANSFORMER_HAS_BEEN_INCLUDED
8 #define OPENVDB_TOOLS_GRIDTRANSFORMER_HAS_BEEN_INCLUDED
9 
10 #include <openvdb/Grid.h>
11 #include <openvdb/Types.h>
12 #include <openvdb/math/Math.h> // for isApproxEqual()
14 #include "ChangeBackground.h"
15 #include "Interpolation.h"
16 #include "LevelSetRebuild.h" // for doLevelSetRebuild()
17 #include "SignedFloodFill.h" // for signedFloodFill
18 #include "Prune.h" // for pruneLevelSet
19 #include <tbb/blocked_range.h>
20 #include <tbb/parallel_reduce.h>
21 #include <cmath>
22 #include <functional>
23 
24 namespace openvdb {
26 namespace OPENVDB_VERSION_NAME {
27 namespace tools {
28 
52 template<typename Sampler, typename Interrupter, typename GridType>
53 inline void
54 resampleToMatch(const GridType& inGrid, GridType& outGrid, Interrupter& interrupter);
55 
77 template<typename Sampler, typename GridType>
78 inline void
79 resampleToMatch(const GridType& inGrid, GridType& outGrid);
80 
81 
83 
84 
85 namespace internal {
86 
90 template<typename Sampler, typename TreeT>
91 class TileSampler: public Sampler
92 {
93 public:
94  using ValueT = typename TreeT::ValueType;
95 
99  TileSampler(const CoordBBox& b, const ValueT& tileVal, bool on):
100  mBBox(b.min().asVec3d(), b.max().asVec3d()), mVal(tileVal), mActive(on), mEmpty(false)
101  {
102  mBBox.expand(-this->radius()); // shrink the bounding box by the sample radius
103  mEmpty = mBBox.empty();
104  }
105 
106  bool sample(const TreeT& inTree, const Vec3R& inCoord, ValueT& result) const
107  {
108  if (!mEmpty && mBBox.isInside(inCoord)) { result = mVal; return mActive; }
109  return Sampler::sample(inTree, inCoord, result);
110  }
111 
112 protected:
115  bool mActive, mEmpty;
116 };
117 
118 
121 template<typename TreeT>
122 class TileSampler<PointSampler, TreeT>: public PointSampler {
123 public:
124  TileSampler(const CoordBBox&, const typename TreeT::ValueType&, bool) {}
125 };
126 
129 template<typename TreeT>
131 public:
132  TileSampler(const CoordBBox&, const typename TreeT::ValueType&, bool) {}
133 };
134 
135 } // namespace internal
136 
137 
139 
140 
159 {
160 public:
162  using InterruptFunc = std::function<bool (void)>;
163 
164  GridResampler(): mThreaded(true), mTransformTiles(true) {}
165  virtual ~GridResampler() {}
166 
167  GridResampler(const GridResampler&) = default;
169 
171  void setThreaded(bool b) { mThreaded = b; }
173  bool threaded() const { return mThreaded; }
175  void setTransformTiles(bool b) { mTransformTiles = b; }
177  bool transformTiles() const { return mTransformTiles; }
178 
182  template<typename InterrupterType> void setInterrupter(InterrupterType&);
183 
184  template<typename Sampler, typename GridT, typename Transformer>
185  void transformGrid(const Transformer&,
186  const GridT& inGrid, GridT& outGrid) const;
187 
188 protected:
189  template<typename Sampler, typename GridT, typename Transformer>
190  void applyTransform(const Transformer&, const GridT& inGrid, GridT& outGrid) const;
191 
192  bool interrupt() const { return mInterrupt && mInterrupt(); }
193 
194 private:
195  template<typename Sampler, typename InTreeT, typename OutTreeT, typename Transformer>
196  static void transformBBox(const Transformer&, const CoordBBox& inBBox,
197  const InTreeT& inTree, OutTreeT& outTree, const InterruptFunc&,
198  const Sampler& = Sampler());
199 
200  template<typename Sampler, typename TreeT, typename Transformer>
201  class RangeProcessor;
202 
203  bool mThreaded, mTransformTiles;
204  InterruptFunc mInterrupt;
205 };
206 
207 
209 
210 
230 {
231 public:
233 
234  GridTransformer(const Mat4R& xform);
236  const Vec3R& pivot,
237  const Vec3R& scale,
238  const Vec3R& rotate,
239  const Vec3R& translate,
240  const std::string& xformOrder = "tsr",
241  const std::string& rotationOrder = "zyx");
242  ~GridTransformer() override = default;
243 
244  GridTransformer(const GridTransformer&) = default;
246 
247  const Mat4R& getTransform() const { return mTransform; }
248 
249  template<class Sampler, class GridT>
250  void transformGrid(const GridT& inGrid, GridT& outGrid) const;
251 
252 private:
253  struct MatrixTransform;
254 
255  inline void init(const Vec3R& pivot, const Vec3R& scale,
256  const Vec3R& rotate, const Vec3R& translate,
257  const std::string& xformOrder, const std::string& rotOrder);
258 
259  Vec3R mPivot;
260  Vec3i mMipLevels;
261  Mat4R mTransform, mPreScaleTransform, mPostScaleTransform;
262 };
263 
264 
266 
267 
268 namespace local_util {
269 
271 
277 template<typename T>
278 inline int
280  math::Vec3<T>& rotate, math::Vec3<T>& translate)
281 {
282  if (!math::isAffine(m)) return DECOMP_INVALID;
283 
284  // This is the translation in world space
285  translate = m.getTranslation();
286  // Extract translation.
287  const math::Mat3<T> xform = m.getMat3();
288 
289  const math::Vec3<T> unsignedScale(
290  (math::Vec3<T>(1, 0, 0) * xform).length(),
291  (math::Vec3<T>(0, 1, 0) * xform).length(),
292  (math::Vec3<T>(0, 0, 1) * xform).length());
293 
294  const bool hasUniformScale = unsignedScale.eq(math::Vec3<T>(unsignedScale[0]));
295 
296  bool hasRotation = false;
297  bool validDecomposition = false;
298 
299  T minAngle = std::numeric_limits<T>::max();
300 
301  // If the transformation matrix contains a reflection, test different negative scales
302  // to find a decomposition that favors the optimal resampling algorithm.
303  for (size_t n = 0; n < 8; ++n) {
304  const math::Vec3<T> signedScale(
305  n & 0x1 ? -unsignedScale.x() : unsignedScale.x(),
306  n & 0x2 ? -unsignedScale.y() : unsignedScale.y(),
307  n & 0x4 ? -unsignedScale.z() : unsignedScale.z());
308 
309  // Extract scale and potentially reflection.
310  const math::Mat3<T> mat = xform * math::scale<math::Mat3<T> >(signedScale).inverse();
311  if (mat.det() < T(0.0)) continue; // Skip if mat contains a reflection.
312 
313  const math::Vec3<T> tmpAngle = math::eulerAngles(mat, math::XYZ_ROTATION);
314 
315  const math::Mat3<T> rebuild =
316  math::rotation<math::Mat3<T> >(math::Vec3<T>(0, 0, 1), tmpAngle.z()) *
317  math::rotation<math::Mat3<T> >(math::Vec3<T>(0, 1, 0), tmpAngle.y()) *
318  math::rotation<math::Mat3<T> >(math::Vec3<T>(1, 0, 0), tmpAngle.x()) *
319  math::scale<math::Mat3<T> >(signedScale);
320 
321  if (xform.eq(rebuild)) {
322 
323  const T maxAngle = std::max(std::abs(tmpAngle[0]),
324  std::max(std::abs(tmpAngle[1]), std::abs(tmpAngle[2])));
325 
326  if (!(minAngle < maxAngle)) { // Update if less or equal.
327 
328  minAngle = maxAngle;
329  rotate = tmpAngle;
330  scale = signedScale;
331 
332  hasRotation = !rotate.eq(math::Vec3<T>::zero());
333  validDecomposition = true;
334 
335  if (hasUniformScale || !hasRotation) {
336  // Current decomposition is optimal.
337  break;
338  }
339  }
340  }
341  }
342 
343  if (!validDecomposition) {
344  // The decomposition is invalid if the transformation matrix contains shear.
345  return DECOMP_INVALID;
346  }
347  if (hasRotation && !hasUniformScale) {
348  // No unique decomposition if scale is nonuniform and rotation is nonzero.
349  return DECOMP_VALID;
350  }
351  return DECOMP_UNIQUE;
352 }
353 
354 } // namespace local_util
355 
356 
358 
359 
364 {
365  MatrixTransform(): mat(Mat4R::identity()), invMat(Mat4R::identity()) {}
366  MatrixTransform(const Mat4R& xform): mat(xform), invMat(xform.inverse()) {}
367 
368  bool isAffine() const { return math::isAffine(mat); }
369 
370  Vec3R transform(const Vec3R& pos) const { return mat.transformH(pos); }
371 
372  Vec3R invTransform(const Vec3R& pos) const { return invMat.transformH(pos); }
373 
374  Mat4R mat, invMat;
375 };
376 
377 
379 
380 
386 {
387 public:
390  ABTransform(const math::Transform& aXform, const math::Transform& bXform):
391  mAXform(aXform),
392  mBXform(bXform),
393  mIsAffine(mAXform.isLinear() && mBXform.isLinear()),
394  mIsIdentity(mIsAffine && mAXform == mBXform)
395  {}
396 
397  bool isAffine() const { return mIsAffine; }
398 
399  bool isIdentity() const { return mIsIdentity; }
400 
402  {
403  return mBXform.worldToIndex(mAXform.indexToWorld(pos));
404  }
405 
407  {
408  return mAXform.worldToIndex(mBXform.indexToWorld(pos));
409  }
410 
411  const math::Transform& getA() const { return mAXform; }
412  const math::Transform& getB() const { return mBXform; }
413 
414 private:
415  const math::Transform &mAXform, &mBXform;
416  const bool mIsAffine;
417  const bool mIsIdentity;
418 };
419 
420 
427 template<typename Sampler, typename Interrupter, typename GridType>
428 inline void
429 doResampleToMatch(const GridType& inGrid, GridType& outGrid, Interrupter& interrupter)
430 {
431  ABTransform xform(inGrid.transform(), outGrid.transform());
432 
433  if (Sampler::consistent() && xform.isIdentity()) {
434  // If the transforms of the input and output are identical, the
435  // output tree is simply a deep copy of the input tree.
436  outGrid.setTree(inGrid.tree().copy());
437  } else if (xform.isAffine()) {
438  // If the input and output transforms are both affine, create an
439  // input to output transform (in:index-to-world * out:world-to-index)
440  // and use the fast GridTransformer API.
441  Mat4R mat = xform.getA().baseMap()->getAffineMap()->getMat4() *
442  ( xform.getB().baseMap()->getAffineMap()->getMat4().inverse() );
443 
444  GridTransformer transformer(mat);
445  transformer.setInterrupter(interrupter);
446 
447  // Transform the input grid and store the result in the output grid.
448  transformer.transformGrid<Sampler>(inGrid, outGrid);
449  } else {
450  // If either the input or the output transform is non-affine,
451  // use the slower GridResampler API.
452  GridResampler resampler;
453  resampler.setInterrupter(interrupter);
454 
455  resampler.transformGrid<Sampler>(xform, inGrid, outGrid);
456  }
457 }
458 
459 
460 template<typename Sampler, typename Interrupter, typename GridType>
461 inline void
462 resampleToMatch(const GridType& inGrid, GridType& outGrid, Interrupter& interrupter)
463 {
464  if (inGrid.getGridClass() == GRID_LEVEL_SET) {
465  // If the input grid is a level set, resample it using the level set rebuild tool.
466 
467  if (inGrid.constTransform() == outGrid.constTransform()) {
468  // If the transforms of the input and output grids are identical,
469  // the output tree is simply a deep copy of the input tree.
470  outGrid.setTree(inGrid.tree().copy());
471  return;
472  }
473 
474  // If the output grid is a level set, resample the input grid to have the output grid's
475  // background value. Otherwise, preserve the input grid's background value.
476  using ValueT = typename GridType::ValueType;
477  const bool outIsLevelSet = outGrid.getGridClass() == openvdb::GRID_LEVEL_SET;
478 
480  const ValueT halfWidth = outIsLevelSet
481  ? ValueT(outGrid.background() * (1.0 / outGrid.voxelSize()[0]))
482  : ValueT(inGrid.background() * (1.0 / inGrid.voxelSize()[0]));
484 
485  typename GridType::Ptr tempGrid;
486  try {
487  tempGrid = doLevelSetRebuild(inGrid, /*iso=*/zeroVal<ValueT>(),
488  /*exWidth=*/halfWidth, /*inWidth=*/halfWidth,
489  &outGrid.constTransform(), &interrupter);
490  } catch (TypeError&) {
491  // The input grid is classified as a level set, but it has a value type
492  // that is not supported by the level set rebuild tool. Fall back to
493  // using the generic resampler.
494  tempGrid.reset();
495  }
496  if (tempGrid) {
497  outGrid.setTree(tempGrid->treePtr());
498  return;
499  }
500  }
501 
502  // If the input grid is not a level set, use the generic resampler.
503  doResampleToMatch<Sampler>(inGrid, outGrid, interrupter);
504 }
505 
506 
507 template<typename Sampler, typename GridType>
508 inline void
509 resampleToMatch(const GridType& inGrid, GridType& outGrid)
510 {
511  util::NullInterrupter interrupter;
512  resampleToMatch<Sampler>(inGrid, outGrid, interrupter);
513 }
514 
515 
517 
518 
519 inline
520 GridTransformer::GridTransformer(const Mat4R& xform):
521  mPivot(0, 0, 0),
522  mMipLevels(0, 0, 0),
523  mTransform(xform),
524  mPreScaleTransform(Mat4R::identity()),
525  mPostScaleTransform(Mat4R::identity())
526 {
527  Vec3R scale, rotate, translate;
528  if (local_util::decompose(mTransform, scale, rotate, translate)) {
529  // If the transform can be decomposed into affine components,
530  // use them to set up a mipmapping-like scheme for downsampling.
531  init(mPivot, scale, rotate, translate, "srt", "zyx");
532  }
533 }
534 
535 
536 inline
538  const Vec3R& pivot, const Vec3R& scale,
539  const Vec3R& rotate, const Vec3R& translate,
540  const std::string& xformOrder, const std::string& rotOrder):
541  mPivot(0, 0, 0),
542  mMipLevels(0, 0, 0),
543  mPreScaleTransform(Mat4R::identity()),
544  mPostScaleTransform(Mat4R::identity())
545 {
546  init(pivot, scale, rotate, translate, xformOrder, rotOrder);
547 }
548 
549 
551 
552 
553 inline void
554 GridTransformer::init(
555  const Vec3R& pivot, const Vec3R& scale,
556  const Vec3R& rotate, const Vec3R& translate,
557  const std::string& xformOrder, const std::string& rotOrder)
558 {
559  if (xformOrder.size() != 3) {
560  OPENVDB_THROW(ValueError, "invalid transform order (" + xformOrder + ")");
561  }
562  if (rotOrder.size() != 3) {
563  OPENVDB_THROW(ValueError, "invalid rotation order (" + rotOrder + ")");
564  }
565 
566  mPivot = pivot;
567 
568  // Scaling is handled via a mipmapping-like scheme of successive
569  // halvings of the tree resolution, until the remaining scale
570  // factor is greater than or equal to 1/2.
571  Vec3R scaleRemainder = scale;
572  for (int i = 0; i < 3; ++i) {
573  double s = std::fabs(scale(i));
574  if (s < 0.5) {
575  mMipLevels(i) = int(std::floor(-std::log(s)/std::log(2.0)));
576  scaleRemainder(i) = scale(i) * (1 << mMipLevels(i));
577  }
578  }
579 
580  // Build pre-scale and post-scale transform matrices based on
581  // the user-specified order of operations.
582  // Note that we iterate over the transform order string in reverse order
583  // (e.g., "t", "r", "s", given "srt"). This is because math::Mat matrices
584  // postmultiply row vectors rather than premultiplying column vectors.
585  mTransform = mPreScaleTransform = mPostScaleTransform = Mat4R::identity();
586  Mat4R* remainder = &mPostScaleTransform;
587  int rpos, spos, tpos;
588  rpos = spos = tpos = 3;
589  for (int ix = 2; ix >= 0; --ix) { // reverse iteration
590  switch (xformOrder[ix]) {
591 
592  case 'r':
593  rpos = ix;
594  mTransform.preTranslate(pivot);
595  remainder->preTranslate(pivot);
596 
597  int xpos, ypos, zpos;
598  xpos = ypos = zpos = 3;
599  for (int ir = 2; ir >= 0; --ir) {
600  switch (rotOrder[ir]) {
601  case 'x':
602  xpos = ir;
603  mTransform.preRotate(math::X_AXIS, rotate.x());
604  remainder->preRotate(math::X_AXIS, rotate.x());
605  break;
606  case 'y':
607  ypos = ir;
608  mTransform.preRotate(math::Y_AXIS, rotate.y());
609  remainder->preRotate(math::Y_AXIS, rotate.y());
610  break;
611  case 'z':
612  zpos = ir;
613  mTransform.preRotate(math::Z_AXIS, rotate.z());
614  remainder->preRotate(math::Z_AXIS, rotate.z());
615  break;
616  }
617  }
618  // Reject rotation order strings that don't contain exactly one
619  // instance of "x", "y" and "z".
620  if (xpos > 2 || ypos > 2 || zpos > 2) {
621  OPENVDB_THROW(ValueError, "invalid rotation order (" + rotOrder + ")");
622  }
623 
624  mTransform.preTranslate(-pivot);
625  remainder->preTranslate(-pivot);
626  break;
627 
628  case 's':
629  spos = ix;
630  mTransform.preTranslate(pivot);
631  mTransform.preScale(scale);
632  mTransform.preTranslate(-pivot);
633 
634  remainder->preTranslate(pivot);
635  remainder->preScale(scaleRemainder);
636  remainder->preTranslate(-pivot);
637  remainder = &mPreScaleTransform;
638  break;
639 
640  case 't':
641  tpos = ix;
642  mTransform.preTranslate(translate);
643  remainder->preTranslate(translate);
644  break;
645  }
646  }
647  // Reject transform order strings that don't contain exactly one
648  // instance of "t", "r" and "s".
649  if (tpos > 2 || rpos > 2 || spos > 2) {
650  OPENVDB_THROW(ValueError, "invalid transform order (" + xformOrder + ")");
651  }
652 }
653 
654 
656 
657 
658 template<typename InterrupterType>
659 void
660 GridResampler::setInterrupter(InterrupterType& interrupter)
661 {
662  mInterrupt = std::bind(&InterrupterType::wasInterrupted,
663  /*this=*/&interrupter, /*percent=*/-1);
664 }
665 
666 
667 template<typename Sampler, typename GridT, typename Transformer>
668 void
669 GridResampler::transformGrid(const Transformer& xform,
670  const GridT& inGrid, GridT& outGrid) const
671 {
672  tools::changeBackground(outGrid.tree(), inGrid.background());
673  applyTransform<Sampler>(xform, inGrid, outGrid);
674 }
675 
676 
677 template<class Sampler, class GridT>
678 void
679 GridTransformer::transformGrid(const GridT& inGrid, GridT& outGrid) const
680 {
681  tools::changeBackground(outGrid.tree(), inGrid.background());
682 
683  if (!Sampler::mipmap() || mMipLevels == Vec3i::zero()) {
684  // Skip the mipmapping step.
685  const MatrixTransform xform(mTransform);
686  applyTransform<Sampler>(xform, inGrid, outGrid);
687 
688  } else {
689  bool firstPass = true;
690  const typename GridT::ValueType background = inGrid.background();
691  typename GridT::Ptr tempGrid = GridT::create(background);
692 
693  if (!mPreScaleTransform.eq(Mat4R::identity())) {
694  firstPass = false;
695  // Apply the pre-scale transform to the input grid
696  // and store the result in a temporary grid.
697  const MatrixTransform xform(mPreScaleTransform);
698  applyTransform<Sampler>(xform, inGrid, *tempGrid);
699  }
700 
701  // While the scale factor along one or more axes is less than 1/2,
702  // scale the grid by half along those axes.
703  Vec3i count = mMipLevels; // # of halvings remaining per axis
704  while (count != Vec3i::zero()) {
705  MatrixTransform xform;
706  xform.mat.setTranslation(mPivot);
707  xform.mat.preScale(Vec3R(
708  count.x() ? .5 : 1, count.y() ? .5 : 1, count.z() ? .5 : 1));
709  xform.mat.preTranslate(-mPivot);
710  xform.invMat = xform.mat.inverse();
711 
712  if (firstPass) {
713  firstPass = false;
714  // Scale the input grid and store the result in a temporary grid.
715  applyTransform<Sampler>(xform, inGrid, *tempGrid);
716  } else {
717  // Scale the temporary grid and store the result in a transient grid,
718  // then swap the two and discard the transient grid.
719  typename GridT::Ptr destGrid = GridT::create(background);
720  applyTransform<Sampler>(xform, *tempGrid, *destGrid);
721  tempGrid.swap(destGrid);
722  }
723  // (3, 2, 1) -> (2, 1, 0) -> (1, 0, 0) -> (0, 0, 0), etc.
724  count = math::maxComponent(count - 1, Vec3i::zero());
725  }
726 
727  // Apply the post-scale transform and store the result in the output grid.
728  if (!mPostScaleTransform.eq(Mat4R::identity())) {
729  const MatrixTransform xform(mPostScaleTransform);
730  applyTransform<Sampler>(xform, *tempGrid, outGrid);
731  } else {
732  outGrid.setTree(tempGrid->treePtr());
733  }
734  }
735 }
736 
737 
739 
740 
741 template<class Sampler, class TreeT, typename Transformer>
742 class GridResampler::RangeProcessor
743 {
744 public:
745  using LeafIterT = typename TreeT::LeafCIter;
746  using TileIterT = typename TreeT::ValueAllCIter;
747  using LeafRange = typename tree::IteratorRange<LeafIterT>;
748  using TileRange = typename tree::IteratorRange<TileIterT>;
749  using InTreeAccessor = typename tree::ValueAccessor<const TreeT>;
750  using OutTreeAccessor = typename tree::ValueAccessor<TreeT>;
751 
752  RangeProcessor(const Transformer& xform, const CoordBBox& b, const TreeT& inT, TreeT& outT):
753  mIsRoot(true), mXform(xform), mBBox(b),
754  mInTree(inT), mOutTree(&outT), mInAcc(mInTree), mOutAcc(*mOutTree)
755  {}
756 
757  RangeProcessor(const Transformer& xform, const CoordBBox& b, const TreeT& inTree):
758  mIsRoot(false), mXform(xform), mBBox(b),
759  mInTree(inTree), mOutTree(new TreeT(inTree.background())),
760  mInAcc(mInTree), mOutAcc(*mOutTree)
761  {}
762 
763  ~RangeProcessor() { if (!mIsRoot) delete mOutTree; }
764 
766  RangeProcessor(RangeProcessor& other, tbb::split):
767  mIsRoot(false),
768  mXform(other.mXform),
769  mBBox(other.mBBox),
770  mInTree(other.mInTree),
771  mOutTree(new TreeT(mInTree.background())),
772  mInAcc(mInTree),
773  mOutAcc(*mOutTree),
774  mInterrupt(other.mInterrupt)
775  {}
776 
777  void setInterrupt(const InterruptFunc& f) { mInterrupt = f; }
778 
780  void operator()(LeafRange& r)
781  {
782  for ( ; r; ++r) {
783  if (interrupt()) break;
784  LeafIterT i = r.iterator();
785  CoordBBox bbox(i->origin(), i->origin() + Coord(i->dim()));
786  if (!mBBox.empty()) {
787  // Intersect the leaf node's bounding box with mBBox.
788  bbox = CoordBBox(
789  Coord::maxComponent(bbox.min(), mBBox.min()),
790  Coord::minComponent(bbox.max(), mBBox.max()));
791  }
792  if (!bbox.empty()) {
793  transformBBox<Sampler>(mXform, bbox, mInAcc, mOutAcc, mInterrupt);
794  }
795  }
796  }
797 
799  void operator()(TileRange& r)
800  {
801  for ( ; r; ++r) {
802  if (interrupt()) break;
803 
804  TileIterT i = r.iterator();
805  // Skip voxels and background tiles.
806  if (!i.isTileValue()) continue;
807  if (!i.isValueOn() && math::isApproxEqual(*i, mOutTree->background())) continue;
808 
809  CoordBBox bbox;
810  i.getBoundingBox(bbox);
811  if (!mBBox.empty()) {
812  // Intersect the tile's bounding box with mBBox.
813  bbox = CoordBBox(
814  Coord::maxComponent(bbox.min(), mBBox.min()),
815  Coord::minComponent(bbox.max(), mBBox.max()));
816  }
817  if (!bbox.empty()) {
822  internal::TileSampler<Sampler, InTreeAccessor>
823  sampler(bbox, i.getValue(), i.isValueOn());
824  transformBBox(mXform, bbox, mInAcc, mOutAcc, mInterrupt, sampler);
825  }
826  }
827  }
828 
830  void join(RangeProcessor& other)
831  {
832  if (!interrupt()) mOutTree->merge(*other.mOutTree);
833  }
834 
835 private:
836  bool interrupt() const { return mInterrupt && mInterrupt(); }
837 
838  const bool mIsRoot; // true if mOutTree is the top-level tree
839  Transformer mXform;
840  CoordBBox mBBox;
841  const TreeT& mInTree;
842  TreeT* mOutTree;
843  InTreeAccessor mInAcc;
844  OutTreeAccessor mOutAcc;
845  InterruptFunc mInterrupt;
846 };
847 
848 
850 
851 
852 template<class Sampler, class GridT, typename Transformer>
853 void
854 GridResampler::applyTransform(const Transformer& xform,
855  const GridT& inGrid, GridT& outGrid) const
856 {
857  using TreeT = typename GridT::TreeType;
858  const TreeT& inTree = inGrid.tree();
859  TreeT& outTree = outGrid.tree();
860 
861  using RangeProc = RangeProcessor<Sampler, TreeT, Transformer>;
862 
863  const GridClass gridClass = inGrid.getGridClass();
864 
865  if (gridClass != GRID_LEVEL_SET && mTransformTiles) {
866  // Independently transform the tiles of the input grid.
867  // Note: Tiles in level sets can only be background tiles, and they
868  // are handled more efficiently with a signed flood fill (see below).
869 
870  RangeProc proc(xform, CoordBBox(), inTree, outTree);
871  proc.setInterrupt(mInterrupt);
872 
873  typename RangeProc::TileIterT tileIter = inTree.cbeginValueAll();
874  tileIter.setMaxDepth(tileIter.getLeafDepth() - 1); // skip leaf nodes
875  typename RangeProc::TileRange tileRange(tileIter);
876 
877  if (mThreaded) {
878  tbb::parallel_reduce(tileRange, proc);
879  } else {
880  proc(tileRange);
881  }
882  }
883 
884  CoordBBox clipBBox;
885  if (gridClass == GRID_LEVEL_SET) {
886  // Inactive voxels in level sets can only be background voxels, and they
887  // are handled more efficiently with a signed flood fill (see below).
888  clipBBox = inGrid.evalActiveVoxelBoundingBox();
889  }
890 
891  // Independently transform the leaf nodes of the input grid.
892 
893  RangeProc proc(xform, clipBBox, inTree, outTree);
894  proc.setInterrupt(mInterrupt);
895 
896  typename RangeProc::LeafRange leafRange(inTree.cbeginLeaf());
897 
898  if (mThreaded) {
899  tbb::parallel_reduce(leafRange, proc);
900  } else {
901  proc(leafRange);
902  }
903 
904  // If the grid is a level set, mark inactive voxels as inside or outside.
905  if (gridClass == GRID_LEVEL_SET) {
906  tools::pruneLevelSet(outTree);
907  tools::signedFloodFill(outTree);
908  }
909 }
910 
911 
913 
914 
915 //static
916 template<class Sampler, class InTreeT, class OutTreeT, class Transformer>
917 void
918 GridResampler::transformBBox(
919  const Transformer& xform,
920  const CoordBBox& bbox,
921  const InTreeT& inTree,
922  OutTreeT& outTree,
923  const InterruptFunc& interrupt,
924  const Sampler& sampler)
925 {
926  using ValueT = typename OutTreeT::ValueType;
927 
928  // Transform the corners of the input tree's bounding box
929  // and compute the enclosing bounding box in the output tree.
930  Vec3R
931  inRMin(bbox.min().x(), bbox.min().y(), bbox.min().z()),
932  inRMax(bbox.max().x()+1, bbox.max().y()+1, bbox.max().z()+1),
933  outRMin = math::minComponent(xform.transform(inRMin), xform.transform(inRMax)),
934  outRMax = math::maxComponent(xform.transform(inRMin), xform.transform(inRMax));
935  for (int i = 0; i < 8; ++i) {
936  Vec3R corner(
937  i & 1 ? inRMax.x() : inRMin.x(),
938  i & 2 ? inRMax.y() : inRMin.y(),
939  i & 4 ? inRMax.z() : inRMin.z());
940  outRMin = math::minComponent(outRMin, xform.transform(corner));
941  outRMax = math::maxComponent(outRMax, xform.transform(corner));
942  }
943  Vec3i
944  outMin = local_util::floorVec3(outRMin) - Sampler::radius(),
945  outMax = local_util::ceilVec3(outRMax) + Sampler::radius();
946 
947  if (!xform.isAffine()) {
948  // If the transform is not affine, back-project each output voxel
949  // into the input tree.
950  Vec3R xyz, inXYZ;
951  Coord outXYZ;
952  int &x = outXYZ.x(), &y = outXYZ.y(), &z = outXYZ.z();
953  for (x = outMin.x(); x <= outMax.x(); ++x) {
954  if (interrupt && interrupt()) break;
955  xyz.x() = x;
956  for (y = outMin.y(); y <= outMax.y(); ++y) {
957  if (interrupt && interrupt()) break;
958  xyz.y() = y;
959  for (z = outMin.z(); z <= outMax.z(); ++z) {
960  xyz.z() = z;
961  inXYZ = xform.invTransform(xyz);
962  ValueT result;
963  if (sampler.sample(inTree, inXYZ, result)) {
964  outTree.setValueOn(outXYZ, result);
965  } else {
966  // Note: Don't overwrite existing active values with inactive values.
967  if (!outTree.isValueOn(outXYZ)) {
968  outTree.setValueOff(outXYZ, result);
969  }
970  }
971  }
972  }
973  }
974  } else { // affine
975  // Compute step sizes in the input tree that correspond to
976  // unit steps in x, y and z in the output tree.
977  const Vec3R
978  translation = xform.invTransform(Vec3R(0, 0, 0)),
979  deltaX = xform.invTransform(Vec3R(1, 0, 0)) - translation,
980  deltaY = xform.invTransform(Vec3R(0, 1, 0)) - translation,
981  deltaZ = xform.invTransform(Vec3R(0, 0, 1)) - translation;
982 
983 #if defined(__ICC)
984  const Vec3R dummy = deltaX;
988 #endif
989 
990  // Step by whole voxels through the output tree, sampling the
991  // corresponding fractional voxels of the input tree.
992  Vec3R inStartX = xform.invTransform(Vec3R(outMin));
993  Coord outXYZ;
994  int &x = outXYZ.x(), &y = outXYZ.y(), &z = outXYZ.z();
995  for (x = outMin.x(); x <= outMax.x(); ++x, inStartX += deltaX) {
996  if (interrupt && interrupt()) break;
997  Vec3R inStartY = inStartX;
998  for (y = outMin.y(); y <= outMax.y(); ++y, inStartY += deltaY) {
999  if (interrupt && interrupt()) break;
1000  Vec3R inXYZ = inStartY;
1001  for (z = outMin.z(); z <= outMax.z(); ++z, inXYZ += deltaZ) {
1002  ValueT result;
1003  if (sampler.sample(inTree, inXYZ, result)) {
1004  outTree.setValueOn(outXYZ, result);
1005  } else {
1006  // Note: Don't overwrite existing active values with inactive values.
1007  if (!outTree.isValueOn(outXYZ)) {
1008  outTree.setValueOff(outXYZ, result);
1009  }
1010  }
1011  }
1012  }
1013  }
1014  }
1015 } // GridResampler::transformBBox()
1016 
1017 } // namespace tools
1018 } // namespace OPENVDB_VERSION_NAME
1019 } // namespace openvdb
1020 
1021 #endif // OPENVDB_TOOLS_GRIDTRANSFORMER_HAS_BEEN_INCLUDED
openvdb::v7_1::math::Vec3< Real >
openvdb::v7_1::tools::GridResampler::GridResampler
GridResampler(const GridResampler &)=default
openvdb::v7_1::math::Vec3::x
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:83
OPENVDB_NO_TYPE_CONVERSION_WARNING_END
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_END
Definition: Platform.h:197
openvdb::v7_1::tools::GridTransformer::getTransform
const Mat4R & getTransform() const
Definition: GridTransformer.h:247
openvdb::v7_1::math::Mat4< Real >
openvdb::v7_1::math::isApproxEqual
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:371
openvdb::v7_1::tools::GridTransformer::GridTransformer
GridTransformer(const Mat4R &xform)
Definition: GridTransformer.h:520
openvdb::v7_1::tools::GridResampler
Definition: GridTransformer.h:159
openvdb::v7_1::math::Mat4::preScale
void preScale(const Vec3< T0 > &v)
Definition: Mat4.h:755
openvdb::v7_1::tools::StaggeredPointSampler
Definition: Interpolation.h:197
openvdb::v7_1::math::Z_AXIS
@ Z_AXIS
Definition: Math.h:872
openvdb::v7_1::math::XYZ_ROTATION
@ XYZ_ROTATION
Definition: Math.h:877
openvdb::v7_1::tools::signedFloodFill
void signedFloodFill(TreeOrLeafManagerT &tree, bool threaded=true, size_t grainSize=1, Index minLevel=0)
Set the values of all inactive voxels and tiles of a narrow-band level set from the signs of the acti...
Definition: SignedFloodFill.h:266
LevelSetRebuild.h
openvdb::v7_1::tools::ABTransform::isIdentity
bool isIdentity() const
Definition: GridTransformer.h:399
openvdb::v7_1::math::Mat3::det
T det() const
Determinant of matrix.
Definition: Mat3.h:500
openvdb::v7_1::tools::GridTransformer::MatrixTransform::MatrixTransform
MatrixTransform(const Mat4R &xform)
Definition: GridTransformer.h:366
Types.h
openvdb::v7_1::tools::changeBackground
void changeBackground(TreeOrLeafManagerT &tree, const typename TreeOrLeafManagerT::ValueType &background, bool threaded=true, size_t grainSize=32)
Replace the background value in all the nodes of a tree.
Definition: ChangeBackground.h:203
openvdb::v7_1::math::eulerAngles
Vec3< typename MatType::value_type > eulerAngles(const MatType &mat, RotationOrder rotationOrder, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the Euler angles composing the given rotation matrix.
Definition: Mat.h:338
openvdb::v7_1::math::Mat4::preRotate
void preRotate(Axis axis, T angle)
Left multiplies by a rotation clock-wiseabout the given axis into this matrix.
Definition: Mat4.h:817
openvdb::v7_1::tools::GridTransformer::MatrixTransform::isAffine
bool isAffine() const
Definition: GridTransformer.h:368
openvdb::v7_1::tools::internal::TileSampler::TileSampler
TileSampler(const CoordBBox &b, const ValueT &tileVal, bool on)
Definition: GridTransformer.h:99
openvdb::v7_1::tools::local_util::decompose
int decompose(const math::Mat4< T > &m, math::Vec3< T > &scale, math::Vec3< T > &rotate, math::Vec3< T > &translate)
Decompose an affine transform into scale, rotation (XYZ order), and translation components.
Definition: GridTransformer.h:279
openvdb::v7_1::tools::ABTransform::isAffine
bool isAffine() const
Definition: GridTransformer.h:397
openvdb::v7_1::math::maxComponent
Vec2< T > maxComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise maximum of the two vectors.
Definition: Vec2.h:512
openvdb::v7_1::tools::internal::TileSampler::mBBox
BBoxd mBBox
Definition: GridTransformer.h:113
openvdb::v7_1::tools::Sampler
Provises a unified interface for sampling, i.e. interpolation.
Definition: Interpolation.h:64
openvdb::v7_1::tools::GridTransformer::MatrixTransform::transform
Vec3R transform(const Vec3R &pos) const
Definition: GridTransformer.h:370
openvdb::v7_1::tools::ABTransform::transform
openvdb::Vec3R transform(const openvdb::Vec3R &pos) const
Definition: GridTransformer.h:401
openvdb::v7_1::math::Mat4::preTranslate
void preTranslate(const Vec3< T0 > &tr)
Left multiples by the specified translation, i.e. Trans * (*this)
Definition: Mat4.h:722
openvdb::v7_1::math::Coord::maxComponent
void maxComponent(const Coord &other)
Perform a component-wise maximum with the other Coord.
Definition: Coord.h:184
openvdb::v7_1::tools::local_util::DECOMP_VALID
@ DECOMP_VALID
Definition: GridTransformer.h:270
openvdb::v7_1::math::Transform::baseMap
MapBase::ConstPtr baseMap() const
Return a base pointer to the transformation map.
Definition: Transform.h:131
openvdb::v7_1::util::wasInterrupted
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:49
openvdb::v7_1::tools::GridResampler::Ptr
SharedPtr< GridResampler > Ptr
Definition: GridTransformer.h:161
openvdb::v7_1::tools::internal::TileSampler::sample
bool sample(const TreeT &inTree, const Vec3R &inCoord, ValueT &result) const
Definition: GridTransformer.h:106
openvdb::v7_1::tools::Sampler::sample
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Sample inTree at the floating-point index coordinate inCoord and store the result in result.
openvdb::v7_1::tools::composite::min
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:102
openvdb::v7_1::tools::GridResampler::applyTransform
void applyTransform(const Transformer &, const GridT &inGrid, GridT &outGrid) const
Definition: GridTransformer.h:854
openvdb::v7_1::math::Mat3
3x3 matrix class.
Definition: Mat3.h:29
openvdb::v7_1::tools::ABTransform::getA
const math::Transform & getA() const
Definition: GridTransformer.h:411
openvdb::v7_1::math::Coord::y
Int32 y() const
Definition: Coord.h:132
openvdb::v7_1::tools::local_util::DECOMP_UNIQUE
@ DECOMP_UNIQUE
Definition: GridTransformer.h:270
openvdb::v7_1::math::X_AXIS
@ X_AXIS
Definition: Math.h:870
openvdb::v7_1::tools::internal::TileSampler::ValueT
typename TreeT::ValueType ValueT
Definition: GridTransformer.h:94
openvdb::v7_1::tools::Sampler::mipmap
static bool mipmap()
openvdb::v7_1::GridClass
GridClass
Definition: Types.h:816
openvdb::v7_1::math::Vec3i
Vec3< int32_t > Vec3i
Definition: Vec3.h:659
openvdb::v7_1::math::scale
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:620
openvdb::v7_1::math::Mat4< Real >::identity
static const Mat4< Real > & identity()
Predefined constant for identity matrix.
Definition: Mat4.h:125
openvdb::v7_1::math::Coord::x
Int32 x() const
Definition: Coord.h:131
openvdb::v7_1::math::Mat4::getTranslation
Vec3< T > getTranslation() const
Return the translation component.
Definition: Mat4.h:328
Grid.h
openvdb::v7_1::tools::GridResampler::transformGrid
void transformGrid(const Transformer &, const GridT &inGrid, GridT &outGrid) const
Definition: GridTransformer.h:669
openvdb::v7_1::math::Vec3::y
T & y()
Definition: Vec3.h:84
openvdb::v7_1::tools::internal::TileSampler< PointSampler, TreeT >::TileSampler
TileSampler(const CoordBBox &, const typename TreeT::ValueType &, bool)
Definition: GridTransformer.h:124
openvdb::v7_1::util::NullInterrupter
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:26
openvdb::v7_1::math::mat3_internal::pivot
void pivot(int i, int j, Mat3< T > &S, Vec3< T > &D, Mat3< T > &Q)
Definition: Mat3.h:689
openvdb::v7_1::tools::GridResampler::transformTiles
bool transformTiles() const
Return true if tile processing is enabled.
Definition: GridTransformer.h:177
openvdb::v7_1::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
openvdb::v7_1::tools::GridResampler::GridResampler
GridResampler()
Definition: GridTransformer.h:164
openvdb::v7_1::tools::internal::TileSampler
A TileSampler wraps a grid sampler of another type (BoxSampler, QuadraticSampler, etc....
Definition: GridTransformer.h:92
openvdb::v7_1::math::Y_AXIS
@ Y_AXIS
Definition: Math.h:871
openvdb::v7_1::GRID_LEVEL_SET
@ GRID_LEVEL_SET
Definition: Types.h:818
openvdb::v7_1::math::Vec3::eq
bool eq(const Vec3< T > &v, T eps=static_cast< T >(1.0e-7)) const
Test if "this" vector is equivalent to vector v with tolerance of eps.
Definition: Vec3.h:131
openvdb::v7_1::tools::GridTransformer
A GridTransformer applies a geometric transformation to an input grid using one of several sampling s...
Definition: GridTransformer.h:230
openvdb::v7_1::tools::GridTransformer::MatrixTransform::invTransform
Vec3R invTransform(const Vec3R &pos) const
Definition: GridTransformer.h:372
openvdb::v7_1::tools::Sampler::radius
static int radius()
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v7_1::math::isAffine
bool isAffine(const Mat4< T > &m)
Definition: Mat4.h:1323
openvdb::v7_1::math::Vec3::z
T & z()
Definition: Vec3.h:85
Prune.h
Defined various multi-threaded utility functions for trees.
openvdb::v7_1::Vec3R
math::Vec3< Real > Vec3R
Definition: Types.h:49
openvdb::v7_1::tools::internal::TileSampler< StaggeredPointSampler, TreeT >::TileSampler
TileSampler(const CoordBBox &, const typename TreeT::ValueType &, bool)
Definition: GridTransformer.h:132
openvdb::v7_1::math::Mat3::eq
bool eq(const Mat3 &m, T eps=1.0e-8) const
Return true if this matrix is equivalent to m within a tolerance of eps.
Definition: Mat3.h:322
openvdb::v7_1::math::Mat4::getMat3
Mat3< T > getMat3() const
Definition: Mat4.h:316
openvdb::v7_1::tools::local_util::ceilVec3
Vec3i ceilVec3(const Vec3R &v)
Definition: Interpolation.h:591
openvdb::v7_1::tools::PointSampler
Definition: Interpolation.h:97
NullInterrupter.h
openvdb::v7_1::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
openvdb::v7_1::math::Coord::z
Int32 z() const
Definition: Coord.h:133
openvdb::v7_1::math::Mat4::eq
bool eq(const Mat4 &m, T eps=1.0e-8) const
Return true if this matrix is equivalent to m within a tolerance of eps.
Definition: Mat4.h:352
openvdb::v7_1::tools::ABTransform::getB
const math::Transform & getB() const
Definition: GridTransformer.h:412
Interpolation.h
openvdb::v7_1::tools::GridTransformer::transformGrid
void transformGrid(const GridT &inGrid, GridT &outGrid) const
Definition: GridTransformer.h:679
openvdb::v7_1::tools::GridResampler::interrupt
bool interrupt() const
Definition: GridTransformer.h:192
openvdb::v7_1::tools::pruneLevelSet
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:389
openvdb::v7_1::tools::local_util::floorVec3
Vec3i floorVec3(const Vec3R &v)
Definition: Interpolation.h:584
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:146
openvdb::v7_1::tools::GridTransformer::~GridTransformer
~GridTransformer() override=default
openvdb::v7_1::tools::resampleToMatch
void resampleToMatch(const GridType &inGrid, GridType &outGrid)
Resample an input grid into an output grid of the same type such that, after resampling,...
Definition: GridTransformer.h:509
openvdb::v7_1::math::BBox< Vec3d >
openvdb::v7_1::tools::GridResampler::operator=
GridResampler & operator=(const GridResampler &)=default
OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN
Bracket code with OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN/_END, to inhibit warnings about type conve...
Definition: Platform.h:196
openvdb::v7_1::math::CoordBBox::max
const Coord & max() const
Definition: Coord.h:322
SignedFloodFill.h
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
openvdb::v7_1::tools::GridResampler::threaded
bool threaded() const
Return true if threading is enabled.
Definition: GridTransformer.h:173
openvdb::v7_1::math::CoordBBox::min
const Coord & min() const
Definition: Coord.h:321
openvdb::v7_1::tools::GridResampler::setThreaded
void setThreaded(bool b)
Enable or disable threading. (Threading is enabled by default.)
Definition: GridTransformer.h:171
openvdb::v7_1::tools::GridTransformer::MatrixTransform
Definition: GridTransformer.h:364
openvdb::v7_1::tools::GridResampler::setTransformTiles
void setTransformTiles(bool b)
Enable or disable processing of tiles. (Enabled by default, except for level set grids....
Definition: GridTransformer.h:175
openvdb::v7_1::tree::ValueAccessor< const TreeT >
openvdb::v7_1::tools::internal::TileSampler::mVal
ValueT mVal
Definition: GridTransformer.h:114
openvdb::v7_1::tools::GridTransformer::MatrixTransform::invMat
Mat4R invMat
Definition: GridTransformer.h:374
openvdb::v7_1::Mat4R
math::Mat4< Real > Mat4R
Definition: Types.h:78
openvdb::v7_1::math::minComponent
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:503
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:94
openvdb::v7_1::tools::GridTransformer::MatrixTransform::mat
Mat4R mat
Definition: GridTransformer.h:374
openvdb::v7_1::tools::GridResampler::InterruptFunc
std::function< bool(void)> InterruptFunc
Definition: GridTransformer.h:162
openvdb::v7_1::tools::ABTransform
This class implements the Transformer functor interface (specifically, the isAffine(),...
Definition: GridTransformer.h:386
openvdb::v7_1::tools::GridTransformer::operator=
GridTransformer & operator=(const GridTransformer &)=default
ChangeBackground.h
Efficient multi-threaded replacement of the background values in tree.
openvdb::v7_1::math::Mat4::setTranslation
void setTranslation(const Vec3< T > &t)
Definition: Mat4.h:333
openvdb::v7_1::tools::internal::TileSampler::mEmpty
bool mEmpty
Definition: GridTransformer.h:115
openvdb::v7_1::tools::GridTransformer::MatrixTransform::MatrixTransform
MatrixTransform()
Definition: GridTransformer.h:365
openvdb::v7_1::math::Transform
Definition: Transform.h:40
openvdb::v7_1::math::rotation
MatType rotation(const Quat< typename MatType::value_type > &q, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the rotation matrix specified by the given quaternion.
Definition: Mat.h:177
openvdb::v7_1::ValueError
Definition: Exceptions.h:65
openvdb::v7_1::math::Mat4::inverse
Mat4 inverse(T tolerance=0) const
Definition: Mat4.h:504
openvdb::v7_1::tools::GridTransformer::GridTransformer
GridTransformer(const GridTransformer &)=default
openvdb
Definition: Exceptions.h:13
openvdb::v7_1::tools::doResampleToMatch
void doResampleToMatch(const GridType &inGrid, GridType &outGrid, Interrupter &interrupter)
Definition: GridTransformer.h:429
openvdb::v7_1::math::Coord::minComponent
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:176
openvdb::v7_1::tools::GridResampler::setInterrupter
void setInterrupter(InterrupterType &)
Allow processing to be aborted by providing an interrupter object. The interrupter will be queried pe...
Definition: GridTransformer.h:660
openvdb::v7_1::SharedPtr
std::shared_ptr< T > SharedPtr
Definition: Types.h:91
openvdb::v7_1::tree::IteratorRange
Definition: TreeIterator.h:1303
openvdb::v7_1::tools::ABTransform::ABTransform
ABTransform(const math::Transform &aXform, const math::Transform &bXform)
Definition: GridTransformer.h:390
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:82
openvdb::v7_1::tools::GridResampler::~GridResampler
virtual ~GridResampler()
Definition: GridTransformer.h:165
openvdb::v7_1::tools::ABTransform::invTransform
openvdb::Vec3R invTransform(const openvdb::Vec3R &pos) const
Definition: GridTransformer.h:406
openvdb::v7_1::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:106
openvdb::v7_1::TypeError
Definition: Exceptions.h:64
openvdb::v7_1::tools::local_util::DECOMP_INVALID
@ DECOMP_INVALID
Definition: GridTransformer.h:270