OpenVDB  3.2.0
Interpolation.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2016 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 //
66 
67 #ifndef OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
68 #define OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
69 
70 #include <cmath>
71 #include <boost/shared_ptr.hpp>
72 #include <openvdb/version.h> // for OPENVDB_VERSION_NAME
73 #include <openvdb/Platform.h> // for round()
74 #include <openvdb/math/Math.h>// for SmoothUnitStep
75 #include <openvdb/math/Transform.h> // for Transform
76 #include <openvdb/Grid.h>
77 #include <openvdb/tree/ValueAccessor.h>
78 
79 namespace openvdb {
81 namespace OPENVDB_VERSION_NAME {
82 namespace tools {
83 
89 template <size_t Order, bool Staggered = false>
90 struct Sampler
91 {
92  BOOST_STATIC_ASSERT(Order < 3);
93  static const char* name();
94  static int radius();
95  static bool mipmap();
96  static bool consistent();
97  static bool staggered();
98  static size_t order();
99 
104  template<class TreeT>
105  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
106  typename TreeT::ValueType& result);
107 
111  template<class TreeT>
112  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
113 };
114 
116 
117 // The following samplers operate in voxel space.
118 // When the samplers are applied to grids holding vector or other non-scalar data,
119 // the data is assumed to be collocated. For example, using the BoxSampler on a grid
120 // with ValueType Vec3f assumes that all three elements in a vector can be assigned
121 // the same physical location. Consider using the GridSampler below instead.
122 
124 {
125  static const char* name() { return "point"; }
126  static int radius() { return 0; }
127  static bool mipmap() { return false; }
128  static bool consistent() { return true; }
129  static bool staggered() { return false; }
130  static size_t order() { return 0; }
131 
135  template<class TreeT>
136  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
137  typename TreeT::ValueType& result);
138 
141  template<class TreeT>
142  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
143 };
144 
145 
147 {
148  static const char* name() { return "box"; }
149  static int radius() { return 1; }
150  static bool mipmap() { return true; }
151  static bool consistent() { return true; }
152  static bool staggered() { return false; }
153  static size_t order() { return 1; }
154 
158  template<class TreeT>
159  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
160  typename TreeT::ValueType& result);
161 
164  template<class TreeT>
165  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
166 
169  template<class ValueT, class TreeT, size_t N>
170  static inline void getValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk);
171 
175  template<class ValueT, class TreeT, size_t N>
176  static inline bool probeValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk);
177 
180  template<class ValueT, size_t N>
181  static inline void extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT& vMax);
182 
184  template<class ValueT, size_t N>
185  static inline ValueT trilinearInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw);
186 };
187 
188 
190 {
191  static const char* name() { return "quadratic"; }
192  static int radius() { return 1; }
193  static bool mipmap() { return true; }
194  static bool consistent() { return false; }
195  static bool staggered() { return false; }
196  static size_t order() { return 2; }
197 
201  template<class TreeT>
202  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
203  typename TreeT::ValueType& result);
204 
207  template<class TreeT>
208  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
209 
210  template<class ValueT, size_t N>
211  static inline ValueT triquadraticInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw);
212 };
213 
214 
216 
217 
218 // The following samplers operate in voxel space and are designed for Vec3
219 // staggered grid data (e.g., fluid simulations using the Marker-and-Cell approach
220 // associate elements of the velocity vector with different physical locations:
221 // the faces of a cube).
222 
224 {
225  static const char* name() { return "point"; }
226  static int radius() { return 0; }
227  static bool mipmap() { return false; }
228  static bool consistent() { return false; }
229  static bool staggered() { return true; }
230  static size_t order() { return 0; }
231 
235  template<class TreeT>
236  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
237  typename TreeT::ValueType& result);
238 
241  template<class TreeT>
242  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
243 };
244 
245 
247 {
248  static const char* name() { return "box"; }
249  static int radius() { return 1; }
250  static bool mipmap() { return true; }
251  static bool consistent() { return false; }
252  static bool staggered() { return true; }
253  static size_t order() { return 1; }
254 
258  template<class TreeT>
259  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
260  typename TreeT::ValueType& result);
261 
264  template<class TreeT>
265  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
266 };
267 
268 
270 {
271  static const char* name() { return "quadratic"; }
272  static int radius() { return 1; }
273  static bool mipmap() { return true; }
274  static bool consistent() { return false; }
275  static bool staggered() { return true; }
276  static size_t order() { return 2; }
277 
281  template<class TreeT>
282  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
283  typename TreeT::ValueType& result);
284 
287  template<class TreeT>
288  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
289 };
290 
291 
293 
294 
309 template<typename GridOrTreeType, typename SamplerType>
311 {
312 public:
313  typedef boost::shared_ptr<GridSampler> Ptr;
314  typedef typename GridOrTreeType::ValueType ValueType;
318 
320  explicit GridSampler(const GridType& grid)
321  : mTree(&(grid.tree())), mTransform(&(grid.transform())) {}
322 
325  GridSampler(const TreeType& tree, const math::Transform& transform)
326  : mTree(&tree), mTransform(&transform) {}
327 
328  const math::Transform& transform() const { return *mTransform; }
329 
334  template<typename RealType>
335  ValueType sampleVoxel(const RealType& x, const RealType& y, const RealType& z) const
336  {
337  return this->isSample(Vec3d(x,y,z));
338  }
339 
344  ValueType sampleVoxel(typename Coord::ValueType i,
345  typename Coord::ValueType j,
346  typename Coord::ValueType k) const
347  {
348  return this->isSample(Coord(i,j,k));
349  }
350 
353  ValueType isSample(const Coord& ijk) const { return mTree->getValue(ijk); }
354 
357  ValueType isSample(const Vec3d& ispoint) const
358  {
359  ValueType result = zeroVal<ValueType>();
360  SamplerType::sample(*mTree, ispoint, result);
361  return result;
362  }
363 
366  ValueType wsSample(const Vec3d& wspoint) const
367  {
368  ValueType result = zeroVal<ValueType>();
369  SamplerType::sample(*mTree, mTransform->worldToIndex(wspoint), result);
370  return result;
371  }
372 
373 private:
374  const TreeType* mTree;
375  const math::Transform* mTransform;
376 }; // class GridSampler
377 
378 
391 template<typename TreeT, typename SamplerType>
392 class GridSampler<tree::ValueAccessor<TreeT>, SamplerType>
393 {
394 public:
395  typedef boost::shared_ptr<GridSampler> Ptr;
396  typedef typename TreeT::ValueType ValueType;
397  typedef TreeT TreeType;
400 
403  GridSampler(const AccessorType& acc,
404  const math::Transform& transform)
405  : mAccessor(&acc), mTransform(&transform) {}
406 
407  const math::Transform& transform() const { return *mTransform; }
408 
413  template<typename RealType>
414  ValueType sampleVoxel(const RealType& x, const RealType& y, const RealType& z) const
415  {
416  return this->isSample(Vec3d(x,y,z));
417  }
418 
423  ValueType sampleVoxel(typename Coord::ValueType i,
424  typename Coord::ValueType j,
425  typename Coord::ValueType k) const
426  {
427  return this->isSample(Coord(i,j,k));
428  }
429 
432  ValueType isSample(const Coord& ijk) const { return mAccessor->getValue(ijk); }
433 
436  ValueType isSample(const Vec3d& ispoint) const
437  {
438  ValueType result = zeroVal<ValueType>();
439  SamplerType::sample(*mAccessor, ispoint, result);
440  return result;
441  }
442 
445  ValueType wsSample(const Vec3d& wspoint) const
446  {
447  ValueType result = zeroVal<ValueType>();
448  SamplerType::sample(*mAccessor, mTransform->worldToIndex(wspoint), result);
449  return result;
450  }
451 
452 private:
453  const AccessorType* mAccessor;//not thread-safe!
454  const math::Transform* mTransform;
455 };//Specialization of GridSampler
456 
457 
459 
460 
470 template<typename GridOrTreeT,
471  typename SamplerT>
473 {
474 public:
475  typedef typename GridOrTreeT::ValueType ValueType;
479 
483  DualGridSampler(const GridType& sourceGrid,
484  const math::Transform& targetXform)
485  : mSourceTree(&(sourceGrid.tree()))
486  , mSourceXform(&(sourceGrid.transform()))
487  , mTargetXform(&targetXform)
488  , mAligned(targetXform == *mSourceXform)
489  {
490  }
495  DualGridSampler(const TreeType& sourceTree,
496  const math::Transform& sourceXform,
497  const math::Transform& targetXform)
498  : mSourceTree(&sourceTree)
499  , mSourceXform(&sourceXform)
500  , mTargetXform(&targetXform)
501  , mAligned(targetXform == sourceXform)
502  {
503  }
506  inline ValueType operator()(const Coord& ijk) const
507  {
508  if (mAligned) return mSourceTree->getValue(ijk);
509  const Vec3R world = mTargetXform->indexToWorld(ijk);
510  return SamplerT::sample(*mSourceTree, mSourceXform->worldToIndex(world));
511  }
513  inline bool isAligned() const { return mAligned; }
514 private:
515  const TreeType* mSourceTree;
516  const math::Transform* mSourceXform;
517  const math::Transform* mTargetXform;
518  const bool mAligned;
519 };// DualGridSampler
520 
522 template<typename TreeT,
523  typename SamplerT>
524 class DualGridSampler<tree::ValueAccessor<TreeT>, SamplerT>
525 {
526  public:
527  typedef typename TreeT::ValueType ValueType;
528  typedef TreeT TreeType;
531 
536  DualGridSampler(const AccessorType& sourceAccessor,
537  const math::Transform& sourceXform,
538  const math::Transform& targetXform)
539  : mSourceAcc(&sourceAccessor)
540  , mSourceXform(&sourceXform)
541  , mTargetXform(&targetXform)
542  , mAligned(targetXform == sourceXform)
543  {
544  }
547  inline ValueType operator()(const Coord& ijk) const
548  {
549  if (mAligned) return mSourceAcc->getValue(ijk);
550  const Vec3R world = mTargetXform->indexToWorld(ijk);
551  return SamplerT::sample(*mSourceAcc, mSourceXform->worldToIndex(world));
552  }
554  inline bool isAligned() const { return mAligned; }
555 private:
556  const AccessorType* mSourceAcc;
557  const math::Transform* mSourceXform;
558  const math::Transform* mTargetXform;
559  const bool mAligned;
560 };//Specialization of DualGridSampler
561 
563 
564 
565 // Class to derive the normalized alpha mask
566 template <typename GridT,
567  typename MaskT,
568  typename SamplerT = tools::BoxSampler,
569  typename FloatT = float>
571 {
572 public:
573  BOOST_STATIC_ASSERT(boost::is_floating_point<FloatT>::value);
574  typedef GridT GridType;
575  typedef MaskT MaskType;
576  typedef SamplerT SamlerType;
577  typedef FloatT FloatType;
578 
579  AlphaMask(const GridT& grid, const MaskT& mask, FloatT min, FloatT max, bool invert)
580  : mAcc(mask.tree())
581  , mSampler(mAcc, mask.transform() , grid.transform())
582  , mMin(min)
583  , mInvNorm(1/(max-min))
584  , mInvert(invert)
585  {
586  assert(min < max);
587  }
588 
589  inline bool operator()(const Coord& xyz, FloatT& a, FloatT& b) const
590  {
591  a = math::SmoothUnitStep( (mSampler(xyz) - mMin) * mInvNorm );//smooth mapping to 0->1
592  b = 1 - a;
593  if (mInvert) std::swap(a,b);
594  return a>0;
595  }
596 
597 protected:
598  typedef typename MaskType::ConstAccessor AccT;
599  AccT mAcc;
601  const FloatT mMin, mInvNorm;
602  const bool mInvert;
603 };// AlphaMask
604 
606 
607 namespace local_util {
608 
609 inline Vec3i
610 floorVec3(const Vec3R& v)
611 {
612  return Vec3i(int(std::floor(v(0))), int(std::floor(v(1))), int(std::floor(v(2))));
613 }
614 
615 
616 inline Vec3i
617 ceilVec3(const Vec3R& v)
618 {
619  return Vec3i(int(std::ceil(v(0))), int(std::ceil(v(1))), int(std::ceil(v(2))));
620 }
621 
622 
623 inline Vec3i
624 roundVec3(const Vec3R& v)
625 {
626  return Vec3i(int(::round(v(0))), int(::round(v(1))), int(::round(v(2))));
627 }
628 
629 } // namespace local_util
630 
631 
633 
634 
635 template<class TreeT>
636 inline bool
637 PointSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
638  typename TreeT::ValueType& result)
639 {
640  return inTree.probeValue(Coord(local_util::roundVec3(inCoord)), result);
641 }
642 
643 template<class TreeT>
644 inline typename TreeT::ValueType
645 PointSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
646 {
647  return inTree.getValue(Coord(local_util::roundVec3(inCoord)));
648 }
649 
650 
652 
653 template<class ValueT, class TreeT, size_t N>
654 inline void
655 BoxSampler::getValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk)
656 {
657  data[0][0][0] = inTree.getValue(ijk); // i, j, k
658 
659  ijk[2] += 1;
660  data[0][0][1] = inTree.getValue(ijk); // i, j, k + 1
661 
662  ijk[1] += 1;
663  data[0][1][1] = inTree.getValue(ijk); // i, j+1, k + 1
664 
665  ijk[2] -= 1;
666  data[0][1][0] = inTree.getValue(ijk); // i, j+1, k
667 
668  ijk[0] += 1;
669  ijk[1] -= 1;
670  data[1][0][0] = inTree.getValue(ijk); // i+1, j, k
671 
672  ijk[2] += 1;
673  data[1][0][1] = inTree.getValue(ijk); // i+1, j, k + 1
674 
675  ijk[1] += 1;
676  data[1][1][1] = inTree.getValue(ijk); // i+1, j+1, k + 1
677 
678  ijk[2] -= 1;
679  data[1][1][0] = inTree.getValue(ijk); // i+1, j+1, k
680 }
681 
682 template<class ValueT, class TreeT, size_t N>
683 inline bool
684 BoxSampler::probeValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk)
685 {
686  bool hasActiveValues = false;
687  hasActiveValues |= inTree.probeValue(ijk, data[0][0][0]); // i, j, k
688 
689  ijk[2] += 1;
690  hasActiveValues |= inTree.probeValue(ijk, data[0][0][1]); // i, j, k + 1
691 
692  ijk[1] += 1;
693  hasActiveValues |= inTree.probeValue(ijk, data[0][1][1]); // i, j+1, k + 1
694 
695  ijk[2] -= 1;
696  hasActiveValues |= inTree.probeValue(ijk, data[0][1][0]); // i, j+1, k
697 
698  ijk[0] += 1;
699  ijk[1] -= 1;
700  hasActiveValues |= inTree.probeValue(ijk, data[1][0][0]); // i+1, j, k
701 
702  ijk[2] += 1;
703  hasActiveValues |= inTree.probeValue(ijk, data[1][0][1]); // i+1, j, k + 1
704 
705  ijk[1] += 1;
706  hasActiveValues |= inTree.probeValue(ijk, data[1][1][1]); // i+1, j+1, k + 1
707 
708  ijk[2] -= 1;
709  hasActiveValues |= inTree.probeValue(ijk, data[1][1][0]); // i+1, j+1, k
710 
711  return hasActiveValues;
712 }
713 
714 template<class ValueT, size_t N>
715 inline void
716 BoxSampler::extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT &vMax)
717 {
718  vMin = vMax = data[0][0][0];
719  vMin = math::Min(vMin, data[0][0][1]);
720  vMax = math::Max(vMax, data[0][0][1]);
721  vMin = math::Min(vMin, data[0][1][0]);
722  vMax = math::Max(vMax, data[0][1][0]);
723  vMin = math::Min(vMin, data[0][1][1]);
724  vMax = math::Max(vMax, data[0][1][1]);
725  vMin = math::Min(vMin, data[1][0][0]);
726  vMax = math::Max(vMax, data[1][0][0]);
727  vMin = math::Min(vMin, data[1][0][1]);
728  vMax = math::Max(vMax, data[1][0][1]);
729  vMin = math::Min(vMin, data[1][1][0]);
730  vMax = math::Max(vMax, data[1][1][0]);
731  vMin = math::Min(vMin, data[1][1][1]);
732  vMax = math::Max(vMax, data[1][1][1]);
733 }
734 
735 
736 template<class ValueT, size_t N>
737 inline ValueT
738 BoxSampler::trilinearInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw)
739 {
740  // Trilinear interpolation:
741  // The eight surrounding latice values are used to construct the result. \n
742  // result(x,y,z) =
743  // v000 (1-x)(1-y)(1-z) + v001 (1-x)(1-y)z + v010 (1-x)y(1-z) + v011 (1-x)yz
744  // + v100 x(1-y)(1-z) + v101 x(1-y)z + v110 xy(1-z) + v111 xyz
745 
746  ValueT resultA, resultB;
747 
748  resultA = data[0][0][0] + ValueT((data[0][0][1] - data[0][0][0]) * uvw[2]);
749  resultB = data[0][1][0] + ValueT((data[0][1][1] - data[0][1][0]) * uvw[2]);
750  ValueT result1 = resultA + ValueT((resultB-resultA) * uvw[1]);
751 
752  resultA = data[1][0][0] + ValueT((data[1][0][1] - data[1][0][0]) * uvw[2]);
753  resultB = data[1][1][0] + ValueT((data[1][1][1] - data[1][1][0]) * uvw[2]);
754  ValueT result2 = resultA + ValueT((resultB - resultA) * uvw[1]);
755 
756  return result1 + ValueT(uvw[0] * (result2 - result1));
757 }
758 
759 
760 template<class TreeT>
761 inline bool
762 BoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
763  typename TreeT::ValueType& result)
764 {
765  typedef typename TreeT::ValueType ValueT;
766 
767  const Vec3i inIdx = local_util::floorVec3(inCoord);
768  const Vec3R uvw = inCoord - inIdx;
769 
770  // Retrieve the values of the eight voxels surrounding the
771  // fractional source coordinates.
772  ValueT data[2][2][2];
773 
774  const bool hasActiveValues = BoxSampler::probeValues(data, inTree, Coord(inIdx));
775 
776  result = BoxSampler::trilinearInterpolation(data, uvw);
777 
778  return hasActiveValues;
779 }
780 
781 
782 template<class TreeT>
783 inline typename TreeT::ValueType
784 BoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
785 {
786  typedef typename TreeT::ValueType ValueT;
787 
788  const Vec3i inIdx = local_util::floorVec3(inCoord);
789  const Vec3R uvw = inCoord - inIdx;
790 
791  // Retrieve the values of the eight voxels surrounding the
792  // fractional source coordinates.
793  ValueT data[2][2][2];
794 
795  BoxSampler::getValues(data, inTree, Coord(inIdx));
796 
797  return BoxSampler::trilinearInterpolation(data, uvw);
798 }
799 
800 
802 
803 template<class ValueT, size_t N>
804 inline ValueT
805 QuadraticSampler::triquadraticInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw)
806 {
808  ValueT vx[3];
809  for (int dx = 0; dx < 3; ++dx) {
810  ValueT vy[3];
811  for (int dy = 0; dy < 3; ++dy) {
812  // Fit a parabola to three contiguous samples in z
813  // (at z=-1, z=0 and z=1), then evaluate the parabola at z',
814  // where z' is the fractional part of inCoord.z, i.e.,
815  // inCoord.z - inIdx.z. The coefficients come from solving
816  //
817  // | (-1)^2 -1 1 || a | | v0 |
818  // | 0 0 1 || b | = | v1 |
819  // | 1^2 1 1 || c | | v2 |
820  //
821  // for a, b and c.
822  const ValueT* vz = &data[dx][dy][0];
823  const ValueT
824  az = static_cast<ValueT>(0.5 * (vz[0] + vz[2]) - vz[1]),
825  bz = static_cast<ValueT>(0.5 * (vz[2] - vz[0])),
826  cz = static_cast<ValueT>(vz[1]);
827  vy[dy] = static_cast<ValueT>(uvw.z() * (uvw.z() * az + bz) + cz);
828  }//loop over y
829  // Fit a parabola to three interpolated samples in y, then
830  // evaluate the parabola at y', where y' is the fractional
831  // part of inCoord.y.
832  const ValueT
833  ay = static_cast<ValueT>(0.5 * (vy[0] + vy[2]) - vy[1]),
834  by = static_cast<ValueT>(0.5 * (vy[2] - vy[0])),
835  cy = static_cast<ValueT>(vy[1]);
836  vx[dx] = static_cast<ValueT>(uvw.y() * (uvw.y() * ay + by) + cy);
837  }//loop over x
838  // Fit a parabola to three interpolated samples in x, then
839  // evaluate the parabola at the fractional part of inCoord.x.
840  const ValueT
841  ax = static_cast<ValueT>(0.5 * (vx[0] + vx[2]) - vx[1]),
842  bx = static_cast<ValueT>(0.5 * (vx[2] - vx[0])),
843  cx = static_cast<ValueT>(vx[1]);
844  return static_cast<ValueT>(uvw.x() * (uvw.x() * ax + bx) + cx);
845 }
846 
847 template<class TreeT>
848 inline bool
849 QuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
850  typename TreeT::ValueType& result)
851 {
852  typedef typename TreeT::ValueType ValueT;
853 
854  const Vec3i inIdx = local_util::floorVec3(inCoord), inLoIdx = inIdx - Vec3i(1, 1, 1);
855  const Vec3R uvw = inCoord - inIdx;
856 
857  // Retrieve the values of the 27 voxels surrounding the
858  // fractional source coordinates.
859  bool active = false;
860  ValueT data[3][3][3];
861  for (int dx = 0, ix = inLoIdx.x(); dx < 3; ++dx, ++ix) {
862  for (int dy = 0, iy = inLoIdx.y(); dy < 3; ++dy, ++iy) {
863  for (int dz = 0, iz = inLoIdx.z(); dz < 3; ++dz, ++iz) {
864  if (inTree.probeValue(Coord(ix, iy, iz), data[dx][dy][dz])) active = true;
865  }
866  }
867  }
868 
869  result = QuadraticSampler::triquadraticInterpolation(data, uvw);
870 
871  return active;
872 }
873 
874 template<class TreeT>
875 inline typename TreeT::ValueType
876 QuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
877 {
878  typedef typename TreeT::ValueType ValueT;
879 
880  const Vec3i inIdx = local_util::floorVec3(inCoord), inLoIdx = inIdx - Vec3i(1, 1, 1);
881  const Vec3R uvw = inCoord - inIdx;
882 
883  // Retrieve the values of the 27 voxels surrounding the
884  // fractional source coordinates.
885  ValueT data[3][3][3];
886  for (int dx = 0, ix = inLoIdx.x(); dx < 3; ++dx, ++ix) {
887  for (int dy = 0, iy = inLoIdx.y(); dy < 3; ++dy, ++iy) {
888  for (int dz = 0, iz = inLoIdx.z(); dz < 3; ++dz, ++iz) {
889  data[dx][dy][dz] = inTree.getValue(Coord(ix, iy, iz));
890  }
891  }
892  }
893 
894  return QuadraticSampler::triquadraticInterpolation(data, uvw);
895 }
896 
897 
899 
900 
901 template<class TreeT>
902 inline bool
903 StaggeredPointSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
904  typename TreeT::ValueType& result)
905 {
906  typedef typename TreeT::ValueType ValueType;
907 
908  ValueType tempX, tempY, tempZ;
909  bool active = false;
910 
911  active = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0, 0), tempX) || active;
912  active = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0.5, 0), tempY) || active;
913  active = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0, 0.5), tempZ) || active;
914 
915  result.x() = tempX.x();
916  result.y() = tempY.y();
917  result.z() = tempZ.z();
918 
919  return active;
920 }
921 
922 template<class TreeT>
923 inline typename TreeT::ValueType
924 StaggeredPointSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
925 {
926  typedef typename TreeT::ValueType ValueT;
927 
928  const ValueT tempX = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0.0, 0.0));
929  const ValueT tempY = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.5, 0.0));
930  const ValueT tempZ = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.0, 0.5));
931 
932  return ValueT(tempX.x(), tempY.y(), tempZ.z());
933 }
934 
935 
937 
938 
939 template<class TreeT>
940 inline bool
941 StaggeredBoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
942  typename TreeT::ValueType& result)
943 {
944  typedef typename TreeT::ValueType ValueType;
945 
946  ValueType tempX, tempY, tempZ;
947  tempX = tempY = tempZ = zeroVal<ValueType>();
948  bool active = false;
949 
950  active = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0, 0), tempX) || active;
951  active = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0.5, 0), tempY) || active;
952  active = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0, 0.5), tempZ) || active;
953 
954  result.x() = tempX.x();
955  result.y() = tempY.y();
956  result.z() = tempZ.z();
957 
958  return active;
959 }
960 
961 template<class TreeT>
962 inline typename TreeT::ValueType
963 StaggeredBoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
964 {
965  typedef typename TreeT::ValueType ValueT;
966 
967  const ValueT tempX = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0.0, 0.0));
968  const ValueT tempY = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.5, 0.0));
969  const ValueT tempZ = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.0, 0.5));
970 
971  return ValueT(tempX.x(), tempY.y(), tempZ.z());
972 }
973 
974 
976 
977 
978 template<class TreeT>
979 inline bool
980 StaggeredQuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
981  typename TreeT::ValueType& result)
982 {
983  typedef typename TreeT::ValueType ValueType;
984 
985  ValueType tempX, tempY, tempZ;
986  bool active = false;
987 
988  active = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0, 0), tempX) || active;
989  active = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0.5, 0), tempY) || active;
990  active = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0, 0.5), tempZ) || active;
991 
992  result.x() = tempX.x();
993  result.y() = tempY.y();
994  result.z() = tempZ.z();
995 
996  return active;
997 }
998 
999 template<class TreeT>
1000 inline typename TreeT::ValueType
1001 StaggeredQuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
1002 {
1003  typedef typename TreeT::ValueType ValueT;
1004 
1005  const ValueT tempX = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0.0, 0.0));
1006  const ValueT tempY = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.5, 0.0));
1007  const ValueT tempZ = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.0, 0.5));
1008 
1009  return ValueT(tempX.x(), tempY.y(), tempZ.z());
1010 }
1011 
1013 
1014 template <>
1015 struct Sampler<0, false> : public PointSampler {};
1016 
1017 template <>
1018 struct Sampler<1, false> : public BoxSampler {};
1019 
1020 template <>
1021 struct Sampler<2, false> : public QuadraticSampler {};
1022 
1023 template <>
1024 struct Sampler<0, true> : public StaggeredPointSampler {};
1025 
1026 template <>
1027 struct Sampler<1, true> : public StaggeredBoxSampler {};
1028 
1029 template <>
1030 struct Sampler<2, true> : public StaggeredQuadraticSampler {};
1031 
1032 } // namespace tools
1033 } // namespace OPENVDB_VERSION_NAME
1034 } // namespace openvdb
1035 
1036 #endif // OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
1037 
1038 // Copyright (c) 2012-2016 DreamWorks Animation LLC
1039 // All rights reserved. This software is distributed under the
1040 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
bool isAligned() const
Return true if the two grids are aligned.
Definition: Interpolation.h:513
static bool staggered()
Definition: Interpolation.h:229
ValueType wsSample(const Vec3d &wspoint) const
Sample in world space.
Definition: Interpolation.h:366
static bool staggered()
Definition: Interpolation.h:252
MaskT MaskType
Definition: Interpolation.h:575
static size_t order()
Definition: Interpolation.h:130
Vec3i ceilVec3(const Vec3R &v)
Definition: Interpolation.h:617
static bool mipmap()
Definition: Interpolation.h:127
static bool mipmap()
Definition: Interpolation.h:273
TreeAdapter< GridOrTreeType >::AccessorType AccessorType
Definition: Interpolation.h:317
T & z()
Definition: Vec3.h:99
const math::Transform & transform() const
Definition: Interpolation.h:407
static bool consistent()
Definition: Interpolation.h:228
GridSampler(const TreeType &tree, const math::Transform &transform)
Definition: Interpolation.h:325
static bool staggered()
Definition: Interpolation.h:152
ValueType isSample(const Coord &ijk) const
Sample value in integer index space.
Definition: Interpolation.h:432
ValueType isSample(const Coord &ijk) const
Sample value in integer index space.
Definition: Interpolation.h:353
bool isAligned() const
Return true if the two grids are aligned.
Definition: Interpolation.h:554
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:622
Vec3i roundVec3(const Vec3R &v)
Definition: Interpolation.h:624
static size_t order()
Definition: Interpolation.h:230
static const char * name()
Definition: Interpolation.h:191
TreeAdapter< GridOrTreeType >::TreeType TreeType
Definition: Interpolation.h:316
static const char * name()
Definition: Interpolation.h:125
Int32 ValueType
Definition: Coord.h:55
ValueType isSample(const Vec3d &ispoint) const
Sample in fractional index space.
Definition: Interpolation.h:436
FloatT FloatType
Definition: Interpolation.h:577
static bool staggered()
Definition: Interpolation.h:275
static int radius()
Definition: Interpolation.h:226
static bool staggered()
Definition: Interpolation.h:195
static int radius()
Definition: Interpolation.h:192
static bool consistent()
Definition: Interpolation.h:128
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
DualGridSampler(const GridType &sourceGrid, const math::Transform &targetXform)
Grid and transform constructor.
Definition: Interpolation.h:483
boost::shared_ptr< GridSampler > Ptr
Definition: Interpolation.h:313
static bool consistent()
Definition: Interpolation.h:151
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:132
static int radius()
Definition: Interpolation.h:272
TreeAdapter< GridOrTreeT >::GridType GridType
Definition: Interpolation.h:476
Type SmoothUnitStep(Type x)
Return 0 if x < 0, 1 if x > 1 or else .
Definition: Math.h:272
static bool mipmap()
Definition: Interpolation.h:150
Definition: Interpolation.h:246
const math::Transform & transform() const
Definition: Interpolation.h:328
ValueType sampleVoxel(typename Coord::ValueType i, typename Coord::ValueType j, typename Coord::ValueType k) const
Sample value in integer index space.
Definition: Interpolation.h:423
Vec3< int32_t > Vec3i
Definition: Vec3.h:648
static size_t order()
Definition: Interpolation.h:196
static const char * name()
Definition: Interpolation.h:271
static const char * name()
Definition: Interpolation.h:248
ValueType isSample(const Vec3d &ispoint) const
Sample in fractional index space.
Definition: Interpolation.h:357
ValueType sampleVoxel(const RealType &x, const RealType &y, const RealType &z) const
Sample a point in index space in the grid.
Definition: Interpolation.h:335
ValueType operator()(const Coord &ijk) const
Return the value of the source grid at the index coordinates, ijk, relative to the target grid (or it...
Definition: Interpolation.h:506
Provises a unified interface for sampling, i.e. interpolation.
Definition: Interpolation.h:90
static const char * name()
Definition: Interpolation.h:225
Definition: Interpolation.h:146
#define OPENVDB_VERSION_NAME
Definition: version.h:43
This is a simple convenience class that allows for sampling from a source grid into the index space o...
Definition: Interpolation.h:472
Vec3< double > Vec3d
Definition: Vec3.h:651
Definition: Interpolation.h:223
static const char * name()
Definition: Interpolation.h:148
tools::DualGridSampler< AccT, SamplerT > mSampler
Definition: Interpolation.h:600
tree::ValueAccessor< TreeT > AccessorType
Definition: Interpolation.h:530
static int radius()
Definition: Interpolation.h:249
AlphaMask(const GridT &grid, const MaskT &mask, FloatT min, FloatT max, bool invert)
Definition: Interpolation.h:579
DualGridSampler(const TreeType &sourceTree, const math::Transform &sourceXform, const math::Transform &targetXform)
Tree and transform constructor.
Definition: Interpolation.h:495
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:97
Calculate an axis-aligned bounding box in index space from a bounding sphere in world space...
Definition: Transform.h:66
Definition: Interpolation.h:570
static bool consistent()
Definition: Interpolation.h:274
GridSampler(const AccessorType &acc, const math::Transform &transform)
Definition: Interpolation.h:403
boost::shared_ptr< GridSampler > Ptr
Definition: Interpolation.h:395
Definition: Exceptions.h:39
static int radius()
Definition: Interpolation.h:126
ValueType wsSample(const Vec3d &wspoint) const
Sample in world space.
Definition: Interpolation.h:445
SamplerT SamlerType
Definition: Interpolation.h:576
ValueType sampleVoxel(const RealType &x, const RealType &y, const RealType &z) const
Sample a point in index space in the grid.
Definition: Interpolation.h:414
static bool mipmap()
Definition: Interpolation.h:193
static bool consistent()
Definition: Interpolation.h:194
GridT GridType
Definition: Interpolation.h:574
_TreeType TreeType
Definition: Grid.h:900
bool operator()(const Coord &xyz, FloatT &a, FloatT &b) const
Definition: Interpolation.h:589
static int radius()
Definition: Interpolation.h:149
Vec3i floorVec3(const Vec3R &v)
Definition: Interpolation.h:610
static size_t order()
Definition: Interpolation.h:253
Definition: Interpolation.h:189
ValueType operator()(const Coord &ijk) const
Return the value of the source grid at the index coordinates, ijk, relative to the target grid...
Definition: Interpolation.h:547
T & y()
Definition: Vec3.h:98
GridOrTreeType::ValueType ValueType
Definition: Interpolation.h:314
AccT mAcc
Definition: Interpolation.h:599
MaskType::ConstAccessor AccT
Definition: Interpolation.h:598
const FloatT mMin
Definition: Interpolation.h:601
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:561
tree::ValueAccessor< TreeT > AccessorType
Definition: Interpolation.h:399
math::Vec3< Real > Vec3R
Definition: Types.h:76
math::Extrema extrema(const IterT &iter, bool threaded=true)
Iterate over a scalar grid and compute extrema (min/max) of the values of the voxels that are visited...
Definition: Statistics.h:379
static bool consistent()
Definition: Interpolation.h:251
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
static size_t order()
Definition: Interpolation.h:276
GridOrTreeT::ValueType ValueType
Definition: Interpolation.h:475
const bool mInvert
Definition: Interpolation.h:602
static bool mipmap()
Definition: Interpolation.h:227
DualGridSampler(const AccessorType &sourceAccessor, const math::Transform &sourceXform, const math::Transform &targetXform)
ValueAccessor and transform constructor.
Definition: Interpolation.h:536
static bool staggered()
Definition: Interpolation.h:129
static size_t order()
Definition: Interpolation.h:153
Class that provides the interface for continuous sampling of values in a tree.
Definition: Interpolation.h:310
Definition: Interpolation.h:123
ValueType sampleVoxel(typename Coord::ValueType i, typename Coord::ValueType j, typename Coord::ValueType k) const
Sample value in integer index space.
Definition: Interpolation.h:344
TreeAdapter< GridOrTreeT >::TreeType TreeType
Definition: Interpolation.h:477
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
GridSampler(const GridType &grid)
Definition: Interpolation.h:320
TreeAdapter< GridOrTreeType >::GridType GridType
Definition: Interpolation.h:315
TreeAdapter< GridType >::AccessorType AccessorType
Definition: Interpolation.h:478
static bool mipmap()
Definition: Interpolation.h:250
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:128