HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Diagnostics.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2018 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 //
29 ///////////////////////////////////////////////////////////////////////////
30 ///
31 /// @file Diagnostics.h
32 ///
33 /// @author Ken Museth
34 ///
35 /// @brief Various diagnostic tools to identify potential issues with
36 /// for example narrow-band level sets or fog volumes
37 ///
38 #ifndef OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
39 #define OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
40 
41 #include <openvdb/Grid.h>
42 #include <openvdb/math/Math.h>
43 #include <openvdb/math/Vec3.h>
44 #include <openvdb/math/Stencils.h>
45 #include <openvdb/math/Operators.h>
47 #include <tbb/blocked_range.h>
48 #include <tbb/parallel_reduce.h>
49 #include <cmath> // for std::isnan(), std::isfinite()
50 #include <set>
51 #include <sstream>
52 #include <string>
53 #include <type_traits>
54 #include <vector>
55 
56 
57 namespace openvdb {
59 namespace OPENVDB_VERSION_NAME {
60 namespace tools {
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 
64 /// @brief Perform checks on a grid to see if it is a valid symmetric,
65 /// narrow-band level set.
66 ///
67 /// @param grid Grid to be checked
68 /// @param number Number of the checks to be performed (see below)
69 /// @return string with a message indicating the nature of the
70 /// issue. If no issue is detected the return string is empty.
71 ///
72 /// @details @a number refers to the following ordered list of
73 /// checks - always starting from the top.
74 /// Fast checks
75 /// 1: value type is floating point
76 /// 2: has level set class type
77 /// 3: has uniform scale
78 /// 4: background value is positive and n*dx
79 ///
80 /// Slower checks
81 /// 5: no active tiles
82 /// 6: all the values are finite, i.e not NaN or infinite
83 /// 7: active values in range between +-background
84 /// 8: abs of inactive values = background, i.e. assuming a symmetric
85 /// narrow band!
86 ///
87 /// Relatively slow check (however multithreaded)
88 /// 9: norm gradient is close to one, i.e. satisfied the Eikonal equation.
89 template<class GridType>
91 checkLevelSet(const GridType& grid, size_t number=9);
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 
95 /// @brief Perform checks on a grid to see if it is a valid fog volume.
96 ///
97 /// @param grid Grid to be checked
98 /// @param number Number of the checks to be performed (see below)
99 /// @return string with a message indicating the nature of the
100 /// issue. If no issue is detected the return string is empty.
101 ///
102 /// @details @a number refers to the following ordered list of
103 /// checks - always starting from the top.
104 /// Fast checks
105 /// 1: value type is floating point
106 /// 2: has FOG volume class type
107 /// 3: background value is zero
108 ///
109 /// Slower checks
110 /// 4: all the values are finite, i.e not NaN or infinite
111 /// 5: inactive values are zero
112 /// 6: active values are in the range [0,1]
113 template<class GridType>
115 checkFogVolume(const GridType& grid, size_t number=6);
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 
119 /// @brief Threaded method to find unique inactive values.
120 ///
121 /// @param grid A VDB volume.
122 /// @param values List of unique inactive values, returned by this method.
123 /// @param numValues Number of values to look for.
124 /// @return @c false if the @a grid has more than @a numValues inactive values.
125 template<class GridType>
126 bool
127 uniqueInactiveValues(const GridType& grid,
128  std::vector<typename GridType::ValueType>& values, size_t numValues);
129 
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 
133 /// @brief Checks NaN values
134 template<typename GridT, typename TreeIterT = typename GridT::ValueOnCIter>
135 struct CheckNan
136 {
138  using TileIterT = TreeIterT;
139  using VoxelIterT = typename tree::IterTraits<
140  typename TreeIterT::NodeT, typename TreeIterT::ValueIterT>::template
142 
143  /// @brief Default constructor
144  CheckNan() {}
145 
146  /// Return true if the scalar value is NaN
147  inline bool operator()(const ElementType& v) const { return std::isnan(v); }
148 
149  /// @brief This allows for vector values to be checked component-wise
150  template<typename T>
151  inline typename std::enable_if<VecTraits<T>::IsVec, bool>::type
152  operator()(const T& v) const
153  {
154  for (int i=0; i<VecTraits<T>::Size; ++i) if ((*this)(v[i])) return true;//should unroll
155  return false;
156  }
157 
158  /// @brief Return true if the tile at the iterator location is NaN
159  bool operator()(const TreeIterT &iter) const { return (*this)(*iter); }
160 
161  /// @brief Return true if the voxel at the iterator location is NaN
162  bool operator()(const VoxelIterT &iter) const { return (*this)(*iter); }
163 
164  /// @brief Return a string describing a failed check.
165  std::string str() const { return "NaN"; }
166 
167 };// CheckNan
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 
171 /// @brief Checks for infinite values, e.g. 1/0 or -1/0
172 template <typename GridT,
173  typename TreeIterT = typename GridT::ValueOnCIter>
174 struct CheckInf
175 {
177  using TileIterT = TreeIterT;
178  using VoxelIterT = typename tree::IterTraits<typename TreeIterT::NodeT,
179  typename TreeIterT::ValueIterT> ::template NodeConverter<
180  typename GridT::TreeType::LeafNodeType>::Type;
181 
182  /// @brief Default constructor
183  CheckInf() {}
184 
185  /// Return true if the value is infinite
186  inline bool operator()(const ElementType& v) const { return std::isinf(v); }
187 
188  /// Return true if any of the vector components are infinite.
189  template<typename T>
190  inline typename std::enable_if<VecTraits<T>::IsVec, bool>::type
191  operator()(const T& v) const
192  {
193  for (int i=0; i<VecTraits<T>::Size; ++i) if ((*this)(v[i])) return true;
194  return false;
195  }
196 
197  /// @brief Return true if the tile at the iterator location is infinite
198  bool operator()(const TreeIterT &iter) const { return (*this)(*iter); }
199 
200  /// @brief Return true if the tile at the iterator location is infinite
201  bool operator()(const VoxelIterT &iter) const { return (*this)(*iter); }
202 
203  /// @brief Return a string describing a failed check.
204  std::string str() const { return "infinite"; }
205 };// CheckInf
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 
209 /// @brief Checks for both NaN and inf values, i.e. any value that is not finite.
210 template <typename GridT,
211  typename TreeIterT = typename GridT::ValueOnCIter>
213 {
215  using TileIterT = TreeIterT;
216  using VoxelIterT = typename tree::IterTraits<typename TreeIterT::NodeT,
217  typename TreeIterT::ValueIterT> ::template NodeConverter<
218  typename GridT::TreeType::LeafNodeType>::Type;
219 
220  /// @brief Default constructor
222 
223  /// Return true if the value is NOT finite, i.e. it's NaN or infinite
224  inline bool operator()(const ElementType& v) const { return !std::isfinite(v); }
225 
226  /// Return true if any of the vector components are NaN or infinite.
227  template<typename T>
228  inline typename std::enable_if<VecTraits<T>::IsVec, bool>::type
229  operator()(const T& v) const {
230  for (int i=0; i<VecTraits<T>::Size; ++i) if ((*this)(v[i])) return true;
231  return false;
232  }
233 
234  /// @brief Return true if the tile at the iterator location is NaN or infinite.
235  bool operator()(const TreeIterT &iter) const { return (*this)(*iter); }
236 
237  /// @brief Return true if the tile at the iterator location is NaN or infinite.
238  bool operator()(const VoxelIterT &iter) const { return (*this)(*iter); }
239 
240  /// @brief Return a string describing a failed check.
241  std::string str() const { return "not finite"; }
242 };// CheckFinite
243 
244 ////////////////////////////////////////////////////////////////////////////////
245 
246 /// @brief Check that the magnitude of a value, a, is close to a fixed
247 /// magnitude, b, given a fixed tolerance c. That is | |a| - |b| | <= c
248 template <typename GridT,
249  typename TreeIterT = typename GridT::ValueOffCIter>
251 {
253  using TileIterT = TreeIterT;
254  using VoxelIterT = typename tree::IterTraits<typename TreeIterT::NodeT,
255  typename TreeIterT::ValueIterT> ::template NodeConverter<
256  typename GridT::TreeType::LeafNodeType>::Type;
257 
258  /// @brief Default constructor
261  : absVal(math::Abs(a)), tolVal(math::Abs(t))
262  {
263  }
264 
265  /// Return true if the magnitude of the value is not approximately
266  /// equal to totVal.
267  inline bool operator()(const ElementType& v) const
268  {
269  return math::Abs(math::Abs(v) - absVal) > tolVal;
270  }
271 
272  /// Return true if any of the vector components are infinite.
273  template<typename T>
274  inline typename std::enable_if<VecTraits<T>::IsVec, bool>::type
275  operator()(const T& v) const
276  {
277  for (int i=0; i<VecTraits<T>::Size; ++i) if ((*this)(v[i])) return true;
278  return false;
279  }
280 
281  /// @brief Return true if the tile at the iterator location is infinite
282  bool operator()(const TreeIterT &iter) const { return (*this)(*iter); }
283 
284  /// @brief Return true if the tile at the iterator location is infinite
285  bool operator()(const VoxelIterT &iter) const { return (*this)(*iter); }
286 
287  /// @brief Return a string describing a failed check.
288  std::string str() const
289  {
290  std::ostringstream ss;
291  ss << "not equal to +/-"<<absVal<<" with a tolerance of "<<tolVal;
292  return ss.str();
293  }
294 
296 };// CheckMagnitude
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 
300 /// @brief Checks a value against a range
301 template <typename GridT,
302  bool MinInclusive = true,//is min part of the range?
303  bool MaxInclusive = true,//is max part of the range?
304  typename TreeIterT = typename GridT::ValueOnCIter>
306 {
308  using TileIterT = TreeIterT;
309  using VoxelIterT = typename tree::IterTraits<typename TreeIterT::NodeT,
310  typename TreeIterT::ValueIterT> ::template NodeConverter<
311  typename GridT::TreeType::LeafNodeType>::Type;
312 
313  // @brief Constructor taking a range to be tested against.
314  CheckRange(const ElementType& _min, const ElementType& _max) : minVal(_min), maxVal(_max)
315  {
316  if (minVal > maxVal) {
317  OPENVDB_THROW(ValueError, "CheckRange: Invalid range (min > max)");
318  }
319  }
320 
321  /// Return true if the value is smaller than min or larger than max.
322  inline bool operator()(const ElementType& v) const
323  {
324  return (MinInclusive ? v<minVal : v<=minVal) ||
325  (MaxInclusive ? v>maxVal : v>=maxVal);
326  }
327 
328  /// Return true if any of the vector components are out of range.
329  template<typename T>
330  inline typename std::enable_if<VecTraits<T>::IsVec, bool>::type
331  operator()(const T& v) const {
332  for (int i=0; i<VecTraits<T>::Size; ++i) if ((*this)(v[i])) return true;
333  return false;
334  }
335 
336  /// @brief Return true if the voxel at the iterator location is out of range.
337  bool operator()(const TreeIterT &iter) const { return (*this)(*iter); }
338 
339  /// @brief Return true if the tile at the iterator location is out of range.
340  bool operator()(const VoxelIterT &iter) const { return (*this)(*iter); }
341 
342  /// @brief Return a string describing a failed check.
343  std::string str() const
344  {
345  std::ostringstream ss;
346  ss << "outside the value range " << (MinInclusive ? "[" : "]")
347  << minVal << "," << maxVal << (MaxInclusive ? "]" : "[");
348  return ss.str();
349  }
350 
352 };// CheckRange
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 
356 /// @brief Checks a value against a minimum
357 template <typename GridT,
358  typename TreeIterT = typename GridT::ValueOnCIter>
359 struct CheckMin
360 {
362  using TileIterT = TreeIterT;
363  using VoxelIterT = typename tree::IterTraits<typename TreeIterT::NodeT,
364  typename TreeIterT::ValueIterT> ::template NodeConverter<
365  typename GridT::TreeType::LeafNodeType>::Type;
366 
367  // @brief Constructor taking a minimum to be tested against.
368  CheckMin(const ElementType& _min) : minVal(_min) {}
369 
370  /// Return true if the value is smaller than min.
371  inline bool operator()(const ElementType& v) const { return v<minVal; }
372 
373  /// Return true if any of the vector components are smaller than min.
374  template<typename T>
375  inline typename std::enable_if<VecTraits<T>::IsVec, bool>::type
376  operator()(const T& v) const {
377  for (int i=0; i<VecTraits<T>::Size; ++i) if ((*this)(v[i])) return true;
378  return false;
379  }
380 
381  /// @brief Return true if the voxel at the iterator location is smaller than min.
382  bool operator()(const TreeIterT &iter) const { return (*this)(*iter); }
383 
384  /// @brief Return true if the tile at the iterator location is smaller than min.
385  bool operator()(const VoxelIterT &iter) const { return (*this)(*iter); }
386 
387  /// @brief Return a string describing a failed check.
388  std::string str() const
389  {
390  std::ostringstream ss;
391  ss << "smaller than "<<minVal;
392  return ss.str();
393  }
394 
396 };// CheckMin
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 
400 /// @brief Checks a value against a maximum
401 template <typename GridT,
402  typename TreeIterT = typename GridT::ValueOnCIter>
403 struct CheckMax
404 {
406  using TileIterT = TreeIterT;
407  using VoxelIterT = typename tree::IterTraits<typename TreeIterT::NodeT,
408  typename TreeIterT::ValueIterT> ::template NodeConverter<
409  typename GridT::TreeType::LeafNodeType>::Type;
410 
411  /// @brief Constructor taking a maximum to be tested against.
412  CheckMax(const ElementType& _max) : maxVal(_max) {}
413 
414  /// Return true if the value is larger than max.
415  inline bool operator()(const ElementType& v) const { return v>maxVal; }
416 
417  /// Return true if any of the vector components are larger than max.
418  template<typename T>
419  inline typename std::enable_if<VecTraits<T>::IsVec, bool>::type
420  operator()(const T& v) const {
421  for (int i=0; i<VecTraits<T>::Size; ++i) if ((*this)(v[i])) return true;
422  return false;
423  }
424 
425  /// @brief Return true if the tile at the iterator location is larger than max.
426  bool operator()(const TreeIterT &iter) const { return (*this)(*iter); }
427 
428  /// @brief Return true if the voxel at the iterator location is larger than max.
429  bool operator()(const VoxelIterT &iter) const { return (*this)(*iter); }
430 
431  /// @brief Return a string describing a failed check.
432  std::string str() const
433  {
434  std::ostringstream ss;
435  ss << "larger than "<<maxVal;
436  return ss.str();
437  }
438 
440 };// CheckMax
441 
442 ////////////////////////////////////////////////////////////////////////////////
443 
444 /// @brief Checks the norm of the gradient against a range, i.e.,
445 /// |&nabla;&Phi;| &isin; [min, max]
446 ///
447 /// @note Internally the test is performed as
448 /// |&nabla;&Phi;|&sup2; &isin; [min&sup2;, max&sup2;] for optimization reasons.
449 template<typename GridT,
450  typename TreeIterT = typename GridT::ValueOnCIter,
451  math::BiasedGradientScheme GradScheme = math::FIRST_BIAS>//math::WENO5_BIAS>
453 {
454  using ValueType = typename GridT::ValueType;
456  "openvdb::tools::CheckNormGrad requires a scalar, floating-point grid");
457  using TileIterT = TreeIterT;
458  using VoxelIterT = typename tree::IterTraits<typename TreeIterT::NodeT,
459  typename TreeIterT::ValueIterT> ::template NodeConverter<
460  typename GridT::TreeType::LeafNodeType>::Type;
461  using AccT = typename GridT::ConstAccessor;
462 
463  /// @brief Constructor taking a grid and a range to be tested against.
464  CheckNormGrad(const GridT& grid, const ValueType& _min, const ValueType& _max)
465  : acc(grid.getConstAccessor())
466  , invdx2(ValueType(1.0/math::Pow2(grid.voxelSize()[0])))
467  , minVal2(_min*_min)
468  , maxVal2(_max*_max)
469  {
470  if ( !grid.hasUniformVoxels() ) {
471  OPENVDB_THROW(ValueError, "CheckNormGrad: The transform must have uniform scale");
472  }
473  if (_min > _max) {
474  OPENVDB_THROW(ValueError, "CheckNormGrad: Invalid range (min > max)");
475  }
476  }
477 
479  : acc(other.acc.tree())
480  , invdx2(other.invdx2)
481  , minVal2(other.minVal2)
482  , maxVal2(other.maxVal2)
483  {
484  }
485 
486  /// Return true if the value is smaller than min or larger than max.
487  inline bool operator()(const ValueType& v) const { return v<minVal2 || v>maxVal2; }
488 
489  /// @brief Return true if zero is outside the range.
490  /// @note We assume that the norm of the gradient of a tile is always zero.
491  inline bool operator()(const TreeIterT&) const { return (*this)(ValueType(0)); }
492 
493  /// @brief Return true if the norm of the gradient at a voxel
494  /// location of the iterator is out of range.
495  inline bool operator()(const VoxelIterT &iter) const
496  {
497  const Coord ijk = iter.getCoord();
499  }
500 
501  /// @brief Return a string describing a failed check.
502  std::string str() const
503  {
504  std::ostringstream ss;
505  ss << "outside the range of NormGrad ["<<math::Sqrt(minVal2)<<","<<math::Sqrt(maxVal2)<<"]";
506  return ss.str();
507  }
508 
511 };// CheckNormGrad
512 
513 ////////////////////////////////////////////////////////////////////////////////
514 
515 /// @brief Checks the norm of the gradient at zero-crossing voxels against a range
516 /// @details CheckEikonal differs from CheckNormGrad in that it only
517 /// checks the norm of the gradient at voxel locations where the
518 /// FD-stencil crosses the zero isosurface!
519 template<typename GridT,
520  typename TreeIterT = typename GridT::ValueOnCIter,
521  typename StencilT = math::WenoStencil<GridT> >//math::GradStencil<GridT>
523 {
524  using ValueType = typename GridT::ValueType;
526  "openvdb::tools::CheckEikonal requires a scalar, floating-point grid");
527  using TileIterT = TreeIterT;
528  using VoxelIterT = typename tree::IterTraits<typename TreeIterT::NodeT,
529  typename TreeIterT::ValueIterT> ::template NodeConverter<
530  typename GridT::TreeType::LeafNodeType>::Type;
531 
532  /// @brief Constructor taking a grid and a range to be tested against.
533  CheckEikonal(const GridT& grid, const ValueType& _min, const ValueType& _max)
534  : stencil(grid), minVal(_min), maxVal(_max)
535  {
536  if ( !grid.hasUniformVoxels() ) {
537  OPENVDB_THROW(ValueError, "CheckEikonal: The transform must have uniform scale");
538  }
539  if (minVal > maxVal) {
540  OPENVDB_THROW(ValueError, "CheckEikonal: Invalid range (min > max)");
541  }
542  }
543 
545  : stencil(other.stencil.grid()), minVal(other.minVal), maxVal(other.maxVal)
546  {
547  }
548 
549  /// Return true if the value is smaller than min or larger than max.
550  inline bool operator()(const ValueType& v) const { return v<minVal || v>maxVal; }
551 
552  /// @brief Return true if zero is outside the range.
553  /// @note We assume that the norm of the gradient of a tile is always zero.
554  inline bool operator()(const TreeIterT&) const { return (*this)(ValueType(0)); }
555 
556  /// @brief Return true if the norm of the gradient at a
557  /// zero-crossing voxel location of the iterator is out of range.
558  inline bool operator()(const VoxelIterT &iter) const
559  {
560  stencil.moveTo(iter);
561  if (!stencil.zeroCrossing()) return false;
562  return (*this)(stencil.normSqGrad());
563  }
564 
565  /// @brief Return a string describing a failed check.
566  std::string str() const
567  {
568  std::ostringstream ss;
569  ss << "outside the range of NormGrad ["<<minVal<<","<<maxVal<<"]";
570  return ss.str();
571  }
572 
573  mutable StencilT stencil;
575 };// CheckEikonal
576 
577 ////////////////////////////////////////////////////////////////////////////////
578 
579 /// @brief Checks the divergence against a range
580 template<typename GridT,
581  typename TreeIterT = typename GridT::ValueOnCIter,
582  math::DScheme DiffScheme = math::CD_2ND>
584 {
585  using ValueType = typename GridT::ValueType;
588  "openvdb::tools::CheckDivergence requires a floating-point vector grid");
589  using TileIterT = TreeIterT;
590  using VoxelIterT = typename tree::IterTraits<typename TreeIterT::NodeT,
591  typename TreeIterT::ValueIterT>::template NodeConverter<
592  typename GridT::TreeType::LeafNodeType>::Type;
593  using AccT = typename GridT::ConstAccessor;
594 
595  /// @brief Constructor taking a grid and a range to be tested against.
596  CheckDivergence(const GridT& grid,
597  const ValueType& _min,
598  const ValueType& _max)
599  : acc(grid.getConstAccessor())
600  , invdx(ValueType(1.0/grid.voxelSize()[0]))
601  , minVal(_min)
602  , maxVal(_max)
603  {
604  if ( !grid.hasUniformVoxels() ) {
605  OPENVDB_THROW(ValueError, "CheckDivergence: The transform must have uniform scale");
606  }
607  if (minVal > maxVal) {
608  OPENVDB_THROW(ValueError, "CheckDivergence: Invalid range (min > max)");
609  }
610  }
611  /// Return true if the value is smaller than min or larger than max.
612  inline bool operator()(const ElementType& v) const { return v<minVal || v>maxVal; }
613 
614  /// @brief Return true if zero is outside the range.
615  /// @note We assume that the divergence of a tile is always zero.
616  inline bool operator()(const TreeIterT&) const { return (*this)(ElementType(0)); }
617 
618  /// @brief Return true if the divergence at a voxel location of
619  /// the iterator is out of range.
620  inline bool operator()(const VoxelIterT &iter) const
621  {
622  const Coord ijk = iter.getCoord();
623  return (*this)(invdx * math::ISDivergence<DiffScheme>::result(acc, ijk));
624  }
625 
626  /// @brief Return a string describing a failed check.
627  std::string str() const
628  {
629  std::ostringstream ss;
630  ss << "outside the range of divergence ["<<minVal<<","<<maxVal<<"]";
631  return ss.str();
632  }
633 
636 };// CheckDivergence
637 
638 ////////////////////////////////////////////////////////////////////////////////
639 
640 /// @brief Performs multithreaded diagnostics of a grid
641 /// @note More documentation will be added soon!
642 template <typename GridT>
643 class Diagnose
644 {
645 public:
646  using MaskType = typename GridT::template ValueConverter<bool>::Type;
647 
648  Diagnose(const GridT& grid) : mGrid(&grid), mMask(new MaskType()), mCount(0)
649  {
650  mMask->setTransform(grid.transformPtr()->copy());
651  }
652 
653  template <typename CheckT>
654  std::string check(const CheckT& check,
655  bool updateMask = false,
656  bool checkVoxels = true,
657  bool checkTiles = true,
658  bool checkBackground = true)
659  {
660  typename MaskType::TreeType* mask = updateMask ? &(mMask->tree()) : nullptr;
661  CheckValues<CheckT> cc(mask, mGrid, check);
662  std::ostringstream ss;
663  if (checkBackground) ss << cc.checkBackground();
664  if (checkTiles) ss << cc.checkTiles();
665  if (checkVoxels) ss << cc.checkVoxels();
666  mCount += cc.mCount;
667  return ss.str();
668  }
669 
670  //@{
671  /// @brief Return a boolean mask of all the values
672  /// (i.e. tiles and/or voxels) that have failed one or
673  /// more checks.
674  typename MaskType::ConstPtr mask() const { return mMask; }
675  typename MaskType::Ptr mask() { return mMask; }
676  //@}
677 
678  /// @brief Return the number of values (i.e. background, tiles or
679  /// voxels) that have failed one or more checks.
680  Index64 valueCount() const { return mMask->activeVoxelCount(); }
681 
682  /// @brief Return total number of failed checks
683  /// @note If only one check was performed and the mask was updated
684  /// failureCount equals valueCount.
685  Index64 failureCount() const { return mCount; }
686 
687  /// @brief Return a const reference to the grid
688  const GridT& grid() const { return *mGrid; }
689 
690  /// @brief Clear the mask and error counter
691  void clear() { mMask = new MaskType(); mCount = 0; }
692 
693 private:
694  // disallow copy construction and copy by assignment!
695  Diagnose(const Diagnose&);// not implemented
696  Diagnose& operator=(const Diagnose&);// not implemented
697 
698  const GridT* mGrid;
699  typename MaskType::Ptr mMask;
700  Index64 mCount;
701 
702  /// @brief Private class that performs the multithreaded checks
703  template <typename CheckT>
704  struct CheckValues
705  {
706  using MaskT = typename MaskType::TreeType;
707  using LeafT = typename GridT::TreeType::LeafNodeType;
708  using LeafManagerT = typename tree::LeafManager<const typename GridT::TreeType>;
709  const bool mOwnsMask;
710  MaskT* mMask;
711  const GridT* mGrid;
712  const CheckT mCheck;
713  Index64 mCount;
714 
715  CheckValues(MaskT* mask, const GridT* grid, const CheckT& check)
716  : mOwnsMask(false)
717  , mMask(mask)
718  , mGrid(grid)
719  , mCheck(check)
720  , mCount(0)
721  {
722  }
723  CheckValues(CheckValues& other, tbb::split)
724  : mOwnsMask(true)
725  , mMask(other.mMask ? new MaskT() : nullptr)
726  , mGrid(other.mGrid)
727  , mCheck(other.mCheck)
728  , mCount(0)
729  {
730  }
731  ~CheckValues() { if (mOwnsMask) delete mMask; }
732 
733  std::string checkBackground()
734  {
735  std::ostringstream ss;
736  if (mCheck(mGrid->background())) {
737  ++mCount;
738  ss << "Background is " + mCheck.str() << std::endl;
739  }
740  return ss.str();
741  }
742 
743  std::string checkTiles()
744  {
745  std::ostringstream ss;
746  const Index64 n = mCount;
747  typename CheckT::TileIterT i(mGrid->tree());
748  for (i.setMaxDepth(GridT::TreeType::RootNodeType::LEVEL - 1); i; ++i) {
749  if (mCheck(i)) {
750  ++mCount;
751  if (mMask) mMask->fill(i.getBoundingBox(), true, true);
752  }
753  }
754  if (const Index64 m = mCount - n) {
755  ss << m << " tile" << (m==1 ? " is " : "s are ") + mCheck.str() << std::endl;
756  }
757  return ss.str();
758  }
759 
760  std::string checkVoxels()
761  {
762  std::ostringstream ss;
763  LeafManagerT leafs(mGrid->tree());
764  const Index64 n = mCount;
765  tbb::parallel_reduce(leafs.leafRange(), *this);
766  if (const Index64 m = mCount - n) {
767  ss << m << " voxel" << (m==1 ? " is " : "s are ") + mCheck.str() << std::endl;
768  }
769  return ss.str();
770  }
771 
772  void operator()(const typename LeafManagerT::LeafRange& r)
773  {
774  using VoxelIterT = typename CheckT::VoxelIterT;
775  if (mMask) {
776  for (typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
777  typename MaskT::LeafNodeType* maskLeaf = nullptr;
778  for (VoxelIterT j = tree::IterTraits<LeafT, VoxelIterT>::begin(*i); j; ++j) {
779  if (mCheck(j)) {
780  ++mCount;
781  if (maskLeaf == nullptr) maskLeaf = mMask->touchLeaf(j.getCoord());
782  maskLeaf->setValueOn(j.pos(), true);
783  }
784  }
785  }
786  } else {
787  for (typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
788  for (VoxelIterT j = tree::IterTraits<LeafT, VoxelIterT>::begin(*i); j; ++j) {
789  if (mCheck(j)) ++mCount;
790  }
791  }
792  }
793  }
794  void join(const CheckValues& other)
795  {
796  if (mMask) mMask->merge(*(other.mMask), openvdb::MERGE_ACTIVE_STATES_AND_NODES);
797  mCount += other.mCount;
798  }
799  };//End of private class CheckValues
800 
801 };// End of public class Diagnose
802 
803 
804 ////////////////////////////////////////////////////////////////////////////////
805 
806 /// @brief Class that performs various types of checks on narrow-band level sets.
807 ///
808 /// @note The most common usage is to simply call CheckLevelSet::check()
809 template<class GridType>
811 {
812 public:
813  using ValueType = typename GridType::ValueType;
814  using MaskType = typename GridType::template ValueConverter<bool>::Type;
815 
816  CheckLevelSet(const GridType& grid) : mDiagnose(grid) {}
817 
818  //@{
819  /// @brief Return a boolean mask of all the values
820  /// (i.e. tiles and/or voxels) that have failed one or
821  /// more checks.
822  typename MaskType::ConstPtr mask() const { return mDiagnose.mask(); }
823  typename MaskType::Ptr mask() { return mDiagnose.mask(); }
824  //@}
825 
826  /// @brief Return the number of values (i.e. background, tiles or
827  /// voxels) that have failed one or more checks.
828  Index64 valueCount() const { return mDiagnose.valueCount(); }
829 
830  /// @brief Return total number of failed checks
831  /// @note If only one check was performed and the mask was updated
832  /// failureCount equals valueCount.
833  Index64 failureCount() const { return mDiagnose.failureCount(); }
834 
835  /// @brief Return a const reference to the grid
836  const GridType& grid() const { return mDiagnose.grid(); }
837 
838  /// @brief Clear the mask and error counter
839  void clear() { mDiagnose.clear(); }
840 
841  /// @brief Return a nonempty message if the grid's value type is a floating point.
842  ///
843  /// @note No run-time overhead
845  {
847  return test ? "" : "Value type is not floating point\n";
848  }
849 
850  /// @brief Return message if the grid's class is a level set.
851  ///
852  /// @note Small run-time overhead
854  {
855  const bool test = mDiagnose.grid().getGridClass() == GRID_LEVEL_SET;
856  return test ? "" : "Class type is not \"GRID_LEVEL_SET\"\n";
857  }
858 
859  /// @brief Return a nonempty message if the grid's transform does not have uniform scaling.
860  ///
861  /// @note Small run-time overhead
863  {
864  return mDiagnose.grid().hasUniformVoxels() ? "" : "Does not have uniform voxels\n";
865  }
866 
867  /// @brief Return a nonempty message if the background value is larger than or
868  /// equal to the halfWidth*voxelSize.
869  ///
870  /// @note Small run-time overhead
871  std::string checkBackground(Real halfWidth = LEVEL_SET_HALF_WIDTH) const
872  {
873  const Real w = mDiagnose.grid().background() / mDiagnose.grid().voxelSize()[0];
874  if (w < halfWidth) {
875  std::ostringstream ss;
876  ss << "The background value ("<< mDiagnose.grid().background()<<") is less than "
877  << halfWidth << " voxel units\n";
878  return ss.str();
879  }
880  return "";
881  }
882 
883  /// @brief Return a nonempty message if the grid has no active tile values.
884  ///
885  /// @note Medium run-time overhead
887  {
888  const bool test = mDiagnose.grid().tree().hasActiveTiles();
889  return test ? "Has active tile values\n" : "";
890  }
891 
892  /// @brief Return a nonempty message if any of the values are not finite. i.e. NaN or inf.
893  ///
894  /// @note Medium run-time overhead
895  std::string checkFinite(bool updateMask = false)
896  {
898  return mDiagnose.check(c, updateMask, /*voxel*/true, /*tiles*/true, /*background*/true);
899  }
900 
901  /// @brief Return a nonempty message if the active voxel values are out-of-range.
902  ///
903  /// @note Medium run-time overhead
904  std::string checkRange(bool updateMask = false)
905  {
906  const ValueType& background = mDiagnose.grid().background();
907  CheckRange<GridType> c(-background, background);
908  return mDiagnose.check(c, updateMask, /*voxel*/true, /*tiles*/false, /*background*/false);
909  }
910 
911  /// @brief Return a nonempty message if the the inactive values do not have a
912  /// magnitude equal to the background value.
913  ///
914  /// @note Medium run-time overhead
915  std::string checkInactiveValues(bool updateMask = false)
916  {
917  const ValueType& background = mDiagnose.grid().background();
919  return mDiagnose.check(c, updateMask, /*voxel*/true, /*tiles*/true, /*background*/false);
920  }
921 
922  /// @brief Return a nonempty message if the norm of the gradient of the
923  /// active voxels is out of the range minV to maxV.
924  ///
925  /// @note Significant run-time overhead
926  std::string checkEikonal(bool updateMask = false, ValueType minV = 0.5, ValueType maxV = 1.5)
927  {
928  CheckEikonal<GridType> c(mDiagnose.grid(), minV, maxV);
929  return mDiagnose.check(c, updateMask, /*voxel*/true, /*tiles*/false, /*background*/false);
930  }
931 
932  /// @brief Return a nonempty message if an error or issue is detected. Only
933  /// runs tests with a number lower than or equal to n, where:
934  ///
935  /// Fast checks
936  /// 1: value type is floating point
937  /// 2: has level set class type
938  /// 3: has uniform scale
939  /// 4: background value is positive and n*dx
940  ///
941  /// Slower checks
942  /// 5: no active tiles
943  /// 6: all the values are finite, i.e not NaN or infinite
944  /// 7: active values in range between +-background
945  /// 8: abs of inactive values = background, i.e. assuming a symmetric narrow band!
946  ///
947  /// Relatively slow check (however multi-threaded)
948  /// 9: norm of gradient at zero-crossings is one, i.e. satisfied the Eikonal equation.
949  std::string check(size_t n=9, bool updateMask = false)
950  {
951  std::string str = this->checkValueType();
952  if (str.empty() && n>1) str = this->checkClassType();
953  if (str.empty() && n>2) str = this->checkTransform();
954  if (str.empty() && n>3) str = this->checkBackground();
955  if (str.empty() && n>4) str = this->checkTiles();
956  if (str.empty() && n>5) str = this->checkFinite(updateMask);
957  if (str.empty() && n>6) str = this->checkRange(updateMask);
958  if (str.empty() && n>7) str = this->checkInactiveValues(updateMask);
959  if (str.empty() && n>8) str = this->checkEikonal(updateMask);
960  return str;
961  }
962 
963 private:
964  // disallow copy construction and copy by assignment!
965  CheckLevelSet(const CheckLevelSet&);// not implemented
966  CheckLevelSet& operator=(const CheckLevelSet&);// not implemented
967 
968  // Member data
969  Diagnose<GridType> mDiagnose;
970 };// CheckLevelSet
971 
972 template<class GridType>
974 checkLevelSet(const GridType& grid, size_t n)
975 {
976  CheckLevelSet<GridType> c(grid);
977  return c.check(n, false);
978 }
979 
980 ////////////////////////////////////////////////////////////////////////////////
981 
982 /// @brief Class that performs various types of checks on fog volumes.
983 ///
984 /// @note The most common usage is to simply call CheckFogVolume::check()
985 template<class GridType>
987 {
988 public:
989  using ValueType = typename GridType::ValueType;
990  using MaskType = typename GridType::template ValueConverter<bool>::Type;
991 
992  CheckFogVolume(const GridType& grid) : mDiagnose(grid) {}
993 
994  //@{
995  /// @brief Return a boolean mask of all the values
996  /// (i.e. tiles and/or voxels) that have failed one or
997  /// more checks.
998  typename MaskType::ConstPtr mask() const { return mDiagnose.mask(); }
999  typename MaskType::Ptr mask() { return mDiagnose.mask(); }
1000  //@}
1001 
1002  /// @brief Return the number of values (i.e. background, tiles or
1003  /// voxels) that have failed one or more checks.
1004  Index64 valueCount() const { return mDiagnose.valueCount(); }
1005 
1006  /// @brief Return total number of failed checks
1007  /// @note If only one check was performed and the mask was updated
1008  /// failureCount equals valueCount.
1009  Index64 failureCount() const { return mDiagnose.failureCount(); }
1010 
1011  /// @brief Return a const reference to the grid
1012  const GridType& grid() const { return mDiagnose.grid(); }
1013 
1014  /// @brief Clear the mask and error counter
1015  void clear() { mDiagnose.clear(); }
1016 
1017  /// @brief Return a nonempty message if the grid's value type is a floating point.
1018  ///
1019  /// @note No run-time overhead
1021  {
1022  static const bool test = std::is_floating_point<ValueType>::value;
1023  return test ? "" : "Value type is not floating point";
1024  }
1025 
1026  /// @brief Return a nonempty message if the grid's class is a level set.
1027  ///
1028  /// @note Small run-time overhead
1030  {
1031  const bool test = mDiagnose.grid().getGridClass() == GRID_FOG_VOLUME;
1032  return test ? "" : "Class type is not \"GRID_LEVEL_SET\"";
1033  }
1034 
1035  /// @brief Return a nonempty message if the background value is not zero.
1036  ///
1037  /// @note Small run-time overhead
1039  {
1040  if (!math::isApproxZero(mDiagnose.grid().background())) {
1041  std::ostringstream ss;
1042  ss << "The background value ("<< mDiagnose.grid().background()<<") is not zero";
1043  return ss.str();
1044  }
1045  return "";
1046  }
1047 
1048  /// @brief Return a nonempty message if any of the values are not finite. i.e. NaN or inf.
1049  ///
1050  /// @note Medium run-time overhead
1051  std::string checkFinite(bool updateMask = false)
1052  {
1054  return mDiagnose.check(c, updateMask, /*voxel*/true, /*tiles*/true, /*background*/true);
1055  }
1056 
1057  /// @brief Return a nonempty message if any of the inactive values are not zero.
1058  ///
1059  /// @note Medium run-time overhead
1060  std::string checkInactiveValues(bool updateMask = false)
1061  {
1063  return mDiagnose.check(c, updateMask, /*voxel*/true, /*tiles*/true, /*background*/true);
1064  }
1065 
1066  /// @brief Return a nonempty message if the active voxel values
1067  /// are out-of-range, i.e. not in the range [0,1].
1068  ///
1069  /// @note Medium run-time overhead
1070  std::string checkRange(bool updateMask = false)
1071  {
1072  CheckRange<GridType> c(0, 1);
1073  return mDiagnose.check(c, updateMask, /*voxel*/true, /*tiles*/true, /*background*/false);
1074  }
1075 
1076  /// @brief Return a nonempty message if an error or issue is detected. Only
1077  /// runs tests with a number lower than or equal to n, where:
1078  ///
1079  /// Fast checks
1080  /// 1: value type is floating point
1081  /// 2: has FOG volume class type
1082  /// 3: background value is zero
1083  ///
1084  /// Slower checks
1085  /// 4: all the values are finite, i.e not NaN or infinite
1086  /// 5: inactive values are zero
1087  /// 6: active values are in the range [0,1]
1088  std::string check(size_t n=6, bool updateMask = false)
1089  {
1090  std::string str = this->checkValueType();
1091  if (str.empty() && n>1) str = this->checkClassType();
1092  if (str.empty() && n>2) str = this->checkBackground();
1093  if (str.empty() && n>3) str = this->checkFinite(updateMask);
1094  if (str.empty() && n>4) str = this->checkInactiveValues(updateMask);
1095  if (str.empty() && n>5) str = this->checkRange(updateMask);
1096  return str;
1097  }
1098 
1099 private:
1100  // disallow copy construction and copy by assignment!
1101  CheckFogVolume(const CheckFogVolume&);// not implemented
1102  CheckFogVolume& operator=(const CheckFogVolume&);// not implemented
1103 
1104  // Member data
1105  Diagnose<GridType> mDiagnose;
1106 };// CheckFogVolume
1107 
1108 template<class GridType>
1110 checkFogVolume(const GridType& grid, size_t n)
1111 {
1112  CheckFogVolume<GridType> c(grid);
1113  return c.check(n, false);
1114 }
1115 
1116 
1117 ////////////////////////////////////////////////////////////////////////////////
1118 
1119 // Internal utility objects and implementation details
1120 
1121 
1122 namespace diagnostics_internal {
1123 
1124 
1125 template<typename TreeType>
1127 {
1128 public:
1130  using ValueType = typename TreeType::ValueType;
1131  using SetType = std::set<ValueType>;
1132 
1133  InactiveVoxelValues(LeafArray&, size_t numValues);
1134 
1135  void runParallel();
1136  void runSerial();
1137 
1138  void getInactiveValues(SetType&) const;
1139 
1140  inline InactiveVoxelValues(const InactiveVoxelValues<TreeType>&, tbb::split);
1141  inline void operator()(const tbb::blocked_range<size_t>&);
1142  inline void join(const InactiveVoxelValues<TreeType>&);
1143 
1144 private:
1145  LeafArray& mLeafArray;
1146  SetType mInactiveValues;
1147  size_t mNumValues;
1148 };// InactiveVoxelValues
1149 
1150 template<typename TreeType>
1152  : mLeafArray(leafs)
1153  , mInactiveValues()
1154  , mNumValues(numValues)
1155 {
1156 }
1157 
1158 template <typename TreeType>
1159 inline
1161  const InactiveVoxelValues<TreeType>& rhs, tbb::split)
1162  : mLeafArray(rhs.mLeafArray)
1163  , mInactiveValues()
1164  , mNumValues(rhs.mNumValues)
1165 {
1166 }
1167 
1168 template<typename TreeType>
1169 void
1171 {
1172  tbb::parallel_reduce(mLeafArray.getRange(), *this);
1173 }
1174 
1175 
1176 template<typename TreeType>
1177 void
1179 {
1180  (*this)(mLeafArray.getRange());
1181 }
1182 
1183 
1184 template<typename TreeType>
1185 inline void
1186 InactiveVoxelValues<TreeType>::operator()(const tbb::blocked_range<size_t>& range)
1187 {
1188  typename TreeType::LeafNodeType::ValueOffCIter iter;
1189 
1190  for (size_t n = range.begin(); n < range.end() && !tbb::task::self().is_cancelled(); ++n) {
1191  for (iter = mLeafArray.leaf(n).cbeginValueOff(); iter; ++iter) {
1192  mInactiveValues.insert(iter.getValue());
1193  }
1194 
1195  if (mInactiveValues.size() > mNumValues) {
1196  tbb::task::self().cancel_group_execution();
1197  }
1198  }
1199 }
1200 
1201 template<typename TreeType>
1202 inline void
1204 {
1205  mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1206 }
1207 
1208 template<typename TreeType>
1209 inline void
1211 {
1212  values.insert(mInactiveValues.begin(), mInactiveValues.end());
1213 }
1214 
1215 
1216 ////////////////////////////////////////
1217 
1218 
1219 template<typename TreeType>
1221 {
1222 public:
1224  using ValueType = typename TreeType::ValueType;
1225  using SetType = std::set<ValueType>;
1226 
1227  InactiveTileValues(size_t numValues);
1228 
1229  void runParallel(IterRange&);
1230  void runSerial(IterRange&);
1231 
1232  void getInactiveValues(SetType&) const;
1233 
1234  inline InactiveTileValues(const InactiveTileValues<TreeType>&, tbb::split);
1235  inline void operator()(IterRange&);
1236  inline void join(const InactiveTileValues<TreeType>&);
1237 
1238 private:
1239  SetType mInactiveValues;
1240  size_t mNumValues;
1241 };
1242 
1243 
1244 template<typename TreeType>
1246  : mInactiveValues()
1247  , mNumValues(numValues)
1248 {
1249 }
1250 
1251 template <typename TreeType>
1252 inline
1254  const InactiveTileValues<TreeType>& rhs, tbb::split)
1255  : mInactiveValues()
1256  , mNumValues(rhs.mNumValues)
1257 {
1258 }
1259 
1260 template<typename TreeType>
1261 void
1263 {
1264  tbb::parallel_reduce(range, *this);
1265 }
1266 
1267 
1268 template<typename TreeType>
1269 void
1271 {
1272  (*this)(range);
1273 }
1274 
1275 
1276 template<typename TreeType>
1277 inline void
1279 {
1280  for (; range && !tbb::task::self().is_cancelled(); ++range) {
1281  typename TreeType::ValueOffCIter iter = range.iterator();
1282  for (; iter; ++iter) {
1283  mInactiveValues.insert(iter.getValue());
1284  }
1285 
1286  if (mInactiveValues.size() > mNumValues) {
1287  tbb::task::self().cancel_group_execution();
1288  }
1289  }
1290 }
1291 
1292 template<typename TreeType>
1293 inline void
1295 {
1296  mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1297 }
1298 
1299 template<typename TreeType>
1300 inline void
1302 {
1303  values.insert(mInactiveValues.begin(), mInactiveValues.end());
1304 }
1305 
1306 } // namespace diagnostics_internal
1307 
1308 
1309 ////////////////////////////////////////
1310 
1311 
1312 template<class GridType>
1313 bool
1314 uniqueInactiveValues(const GridType& grid,
1315  std::vector<typename GridType::ValueType>& values, size_t numValues)
1316 {
1317  using TreeType = typename GridType::TreeType;
1318  using ValueType = typename GridType::ValueType;
1319  using SetType = std::set<ValueType>;
1320 
1321  SetType uniqueValues;
1322 
1323  { // Check inactive voxels
1324  TreeType& tree = const_cast<TreeType&>(grid.tree());
1325  tree::LeafManager<TreeType> leafs(tree);
1326  diagnostics_internal::InactiveVoxelValues<TreeType> voxelOp(leafs, numValues);
1327  voxelOp.runParallel();
1328  voxelOp.getInactiveValues(uniqueValues);
1329  }
1330 
1331  // Check inactive tiles
1332  if (uniqueValues.size() <= numValues) {
1333  typename TreeType::ValueOffCIter iter(grid.tree());
1334  iter.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 1);
1336 
1338  tileOp.runParallel(range);
1339 
1340  tileOp.getInactiveValues(uniqueValues);
1341  }
1342 
1343  values.clear();
1344  values.reserve(uniqueValues.size());
1345 
1346  typename SetType::iterator it = uniqueValues.begin();
1347  for ( ; it != uniqueValues.end(); ++it) {
1348  values.push_back(*it);
1349  }
1350 
1351  return values.size() <= numValues;
1352 }
1353 
1354 } // namespace tools
1355 } // namespace OPENVDB_VERSION_NAME
1356 } // namespace openvdb
1357 
1358 #endif // OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
1359 
1360 // Copyright (c) 2012-2018 DreamWorks Animation LLC
1361 // All rights reserved. This software is distributed under the
1362 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
bool operator()(const VoxelIterT &iter) const
Return true if the tile at the iterator location is NaN or infinite.
Definition: Diagnostics.h:238
std::string checkRange(bool updateMask=false)
Return a nonempty message if the active voxel values are out-of-range, i.e. not in the range [0...
Definition: Diagnostics.h:1070
std::string checkInactiveValues(bool updateMask=false)
Return a nonempty message if any of the inactive values are not zero.
Definition: Diagnostics.h:1060
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:141
cvex test(vector P=0;int unbound=3;export float s=0;export vector Cf=0;)
Definition: test.vfl:11
GLenum GLint * range
Definition: glcorearb.h:1924
MeshToVoxelEdgeData::EdgeData Abs(const MeshToVoxelEdgeData::EdgeData &x)
const IterT & iterator() const
Return a reference to this range's iterator.
bool operator()(const VoxelIterT &iter) const
Return true if the voxel at the iterator location is larger than max.
Definition: Diagnostics.h:429
bool operator()(const ElementType &v) const
Return true if the value is NOT finite, i.e. it's NaN or infinite.
Definition: Diagnostics.h:224
MaskType::Ptr mask()
Return a boolean mask of all the values (i.e. tiles and/or voxels) that have failed one or more check...
Definition: Diagnostics.h:999
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:218
bool operator()(const VoxelIterT &iter) const
Return true if the voxel at the iterator location is NaN.
Definition: Diagnostics.h:162
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:502
typename VecTraits< typename GridT::ValueType >::ElementType ElementType
Definition: Diagnostics.h:307
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:409
typename VecTraits< typename GridT::ValueType >::ElementType ElementType
Definition: Diagnostics.h:405
bool operator()(const VoxelIterT &iter) const
Return true if the divergence at a voxel location of the iterator is out of range.
Definition: Diagnostics.h:620
MaskType::ConstPtr mask() const
Return a boolean mask of all the values (i.e. tiles and/or voxels) that have failed one or more check...
Definition: Diagnostics.h:674
Type Pow2(Type x)
Return x2.
Definition: Math.h:502
typename GridType::template ValueConverter< bool >::Type MaskType
Definition: Diagnostics.h:814
Checks for both NaN and inf values, i.e. any value that is not finite.
Definition: Diagnostics.h:212
const GLdouble * v
Definition: glcorearb.h:836
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
std::string checkBackground() const
Return a nonempty message if the background value is not zero.
Definition: Diagnostics.h:1038
typename VecTraits< typename GridT::ValueType >::ElementType ElementType
Definition: Diagnostics.h:214
MaskType::Ptr mask()
Return a boolean mask of all the values (i.e. tiles and/or voxels) that have failed one or more check...
Definition: Diagnostics.h:823
static Accessor::ValueType result(const Accessor &grid, const Coord &ijk)
Definition: Operators.h:263
bool operator()(const ValueType &v) const
Return true if the value is smaller than min or larger than max.
Definition: Diagnostics.h:487
Index64 valueCount() const
Return the number of values (i.e. background, tiles or voxels) that have failed one or more checks...
Definition: Diagnostics.h:828
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:566
png_infop png_color_16p * background
Definition: png.h:2326
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:432
bool operator()(const ElementType &v) const
Return true if the value is larger than max.
Definition: Diagnostics.h:415
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:165
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
GLint GLuint mask
Definition: glcorearb.h:123
bool operator()(const TreeIterT &) const
Return true if zero is outside the range.
Definition: Diagnostics.h:554
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
CheckRange(const ElementType &_min, const ElementType &_max)
Definition: Diagnostics.h:314
typename VecTraits< typename GridT::ValueType >::ElementType ElementType
Definition: Diagnostics.h:361
bool operator()(const TreeIterT &iter) const
Return true if the tile at the iterator location is NaN.
Definition: Diagnostics.h:159
bool operator()(const TreeIterT &iter) const
Return true if the tile at the iterator location is NaN or infinite.
Definition: Diagnostics.h:235
bool operator()(const TreeIterT &iter) const
Return true if the tile at the iterator location is infinite.
Definition: Diagnostics.h:198
std::string checkFinite(bool updateMask=false)
Return a nonempty message if any of the values are not finite. i.e. NaN or inf.
Definition: Diagnostics.h:895
std::enable_if< VecTraits< T >::IsVec, bool >::type operator()(const T &v) const
Return true if any of the vector components are infinite.
Definition: Diagnostics.h:275
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:288
CheckEikonal(const GridT &grid, const ValueType &_min, const ValueType &_max)
Constructor taking a grid and a range to be tested against.
Definition: Diagnostics.h:533
typename VecTraits< typename GridT::ValueType >::ElementType ElementType
Definition: Diagnostics.h:137
png_uint_32 i
Definition: png.h:2877
std::enable_if< VecTraits< T >::IsVec, bool >::type operator()(const T &v) const
Return true if any of the vector components are smaller than min.
Definition: Diagnostics.h:376
Tolerance for floating-point comparison.
Definition: Math.h:117
Performs multithreaded diagnostics of a grid.
Definition: Diagnostics.h:643
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
std::enable_if< VecTraits< T >::IsVec, bool >::type operator()(const T &v) const
Return true if any of the vector components are larger than max.
Definition: Diagnostics.h:420
Index64 valueCount() const
Return the number of values (i.e. background, tiles or voxels) that have failed one or more checks...
Definition: Diagnostics.h:680
DScheme
Different discrete schemes used in the first derivatives.
bool operator()(const TreeIterT &iter) const
Return true if the tile at the iterator location is infinite.
Definition: Diagnostics.h:282
typename GridType::template ValueConverter< bool >::Type MaskType
Definition: Diagnostics.h:646
std::string checkTransform() const
Return a nonempty message if the grid's transform does not have uniform scaling.
Definition: Diagnostics.h:862
std::string checkFinite(bool updateMask=false)
Return a nonempty message if any of the values are not finite. i.e. NaN or inf.
Definition: Diagnostics.h:1051
CheckDivergence(const GridT &grid, const ValueType &_min, const ValueType &_max)
Constructor taking a grid and a range to be tested against.
Definition: Diagnostics.h:596
static std::string checkValueType()
Return a nonempty message if the grid's value type is a floating point.
Definition: Diagnostics.h:1020
GLdouble n
Definition: glcorearb.h:2007
bool operator()(const VoxelIterT &iter) const
Return true if the tile at the iterator location is out of range.
Definition: Diagnostics.h:340
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:204
Coord Abs(const Coord &xyz)
Definition: Coord.h:513
std::string check(const CheckT &check, bool updateMask=false, bool checkVoxels=true, bool checkTiles=true, bool checkBackground=true)
Definition: Diagnostics.h:654
bool operator()(const ElementType &v) const
Return true if the scalar value is NaN.
Definition: Diagnostics.h:147
bool operator()(const ElementType &v) const
Return true if the value is smaller than min.
Definition: Diagnostics.h:371
CheckMax(const ElementType &_max)
Constructor taking a maximum to be tested against.
Definition: Diagnostics.h:412
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
typename VecTraits< typename GridT::ValueType >::ElementType ElementType
Definition: Diagnostics.h:176
Checks a value against a maximum.
Definition: Diagnostics.h:403
std::string check(size_t n=9, bool updateMask=false)
Return a nonempty message if an error or issue is detected. Only runs tests with a number lower than ...
Definition: Diagnostics.h:949
std::string checkClassType() const
Return message if the grid's class is a level set.
Definition: Diagnostics.h:853
Index64 failureCount() const
Return total number of failed checks.
Definition: Diagnostics.h:1009
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:388
Index64 failureCount() const
Return total number of failed checks.
Definition: Diagnostics.h:833
std::string checkBackground(Real halfWidth=LEVEL_SET_HALF_WIDTH) const
Return a nonempty message if the background value is larger than or equal to the halfWidth*voxelSize...
Definition: Diagnostics.h:871
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:715
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:241
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
const GridType & grid() const
Return a const reference to the grid.
Definition: Diagnostics.h:1012
MaskType::ConstPtr mask() const
Return a boolean mask of all the values (i.e. tiles and/or voxels) that have failed one or more check...
Definition: Diagnostics.h:998
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:530
std::string checkFogVolume(const GridType &grid, size_t number=6)
Perform checks on a grid to see if it is a valid fog volume.
Definition: Diagnostics.h:1110
MaskType::Ptr mask()
Return a boolean mask of all the values (i.e. tiles and/or voxels) that have failed one or more check...
Definition: Diagnostics.h:675
static std::string checkValueType()
Return a nonempty message if the grid's value type is a floating point.
Definition: Diagnostics.h:844
bool operator()(const ElementType &v) const
Return true if the value is infinite.
Definition: Diagnostics.h:186
void clear()
Clear the mask and error counter.
Definition: Diagnostics.h:691
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1601
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:460
Checks the norm of the gradient at zero-crossing voxels against a range.
Definition: Diagnostics.h:522
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:320
bool operator()(const VoxelIterT &iter) const
Return true if the tile at the iterator location is infinite.
Definition: Diagnostics.h:285
bool operator()(const TreeIterT &iter) const
Return true if the voxel at the iterator location is smaller than min.
Definition: Diagnostics.h:382
std::string checkInactiveValues(bool updateMask=false)
Return a nonempty message if the the inactive values do not have a magnitude equal to the background ...
Definition: Diagnostics.h:915
std::enable_if< VecTraits< T >::IsVec, bool >::type operator()(const T &v) const
This allows for vector values to be checked component-wise.
Definition: Diagnostics.h:152
GLint GLfloat GLint stencil
Definition: glcorearb.h:1277
Checks the divergence against a range.
Definition: Diagnostics.h:583
static Accessor::ValueType::value_type result(const Accessor &grid, const Coord &ijk)
Definition: Operators.h:500
bool operator()(const VoxelIterT &iter) const
Return true if the tile at the iterator location is smaller than min.
Definition: Diagnostics.h:385
std::enable_if< VecTraits< T >::IsVec, bool >::type operator()(const T &v) const
Return true if any of the vector components are NaN or infinite.
Definition: Diagnostics.h:229
std::enable_if< VecTraits< T >::IsVec, bool >::type operator()(const T &v) const
Return true if any of the vector components are infinite.
Definition: Diagnostics.h:191
MaskType::ConstPtr mask() const
Return a boolean mask of all the values (i.e. tiles and/or voxels) that have failed one or more check...
Definition: Diagnostics.h:822
Checks the norm of the gradient against a range, i.e., |∇Φ| ∈ [min, max].
Definition: Diagnostics.h:452
GLsizei const GLfloat * value
Definition: glcorearb.h:823
Checks a value against a range.
Definition: Diagnostics.h:305
bool operator()(const ValueType &v) const
Return true if the value is smaller than min or larger than max.
Definition: Diagnostics.h:550
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:627
std::string check(size_t n=6, bool updateMask=false)
Return a nonempty message if an error or issue is detected. Only runs tests with a number lower than ...
Definition: Diagnostics.h:1088
std::string checkClassType() const
Return a nonempty message if the grid's class is a level set.
Definition: Diagnostics.h:1029
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:180
bool operator()(const ElementType &v) const
Definition: Diagnostics.h:267
bool operator()(const VoxelIterT &iter) const
Return true if the tile at the iterator location is infinite.
Definition: Diagnostics.h:201
std::string checkLevelSet(const GridType &grid, size_t number=9)
Perform checks on a grid to see if it is a valid symmetric, narrow-band level set.
Definition: Diagnostics.h:974
Index64 valueCount() const
Return the number of values (i.e. background, tiles or voxels) that have failed one or more checks...
Definition: Diagnostics.h:1004
bool operator()(const TreeIterT &iter) const
Return true if the voxel at the iterator location is out of range.
Definition: Diagnostics.h:337
std::string str() const
Return a string describing a failed check.
Definition: Diagnostics.h:343
Class that performs various types of checks on fog volumes.
Definition: Diagnostics.h:986
typename VecTraits< ValueType >::ElementType ElementType
Definition: Diagnostics.h:586
std::enable_if< VecTraits< T >::IsVec, bool >::type operator()(const T &v) const
Return true if any of the vector components are out of range.
Definition: Diagnostics.h:331
bool operator()(const ElementType &v) const
Return true if the value is smaller than min or larger than max.
Definition: Diagnostics.h:322
const GridT & grid() const
Return a const reference to the grid.
Definition: Diagnostics.h:688
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
This is a special 19-point stencil that supports optimal fifth-order WENO upwinding, second-order central differencing, Laplacian, and zero-crossing test.
Definition: Stencils.h:1348
bool operator()(const TreeIterT &) const
Return true if zero is outside the range.
Definition: Diagnostics.h:616
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
CheckMagnitude(const ElementType &a, const ElementType &t=math::Tolerance< ElementType >::value())
Default constructor.
Definition: Diagnostics.h:259
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:592
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
std::string checkRange(bool updateMask=false)
Return a nonempty message if the active voxel values are out-of-range.
Definition: Diagnostics.h:904
bool operator()(const TreeIterT &iter) const
Return true if the tile at the iterator location is larger than max.
Definition: Diagnostics.h:426
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Index64 failureCount() const
Return total number of failed checks.
Definition: Diagnostics.h:685
GLboolean r
Definition: glcorearb.h:1221
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:256
bool uniqueInactiveValues(const GridType &grid, std::vector< typename GridType::ValueType > &values, size_t numValues)
Threaded method to find unique inactive values.
Definition: Diagnostics.h:1314
std::string checkEikonal(bool updateMask=false, ValueType minV=0.5, ValueType maxV=1.5)
Return a nonempty message if the norm of the gradient of the active voxels is out of the range minV t...
Definition: Diagnostics.h:926
bool operator()(const VoxelIterT &iter) const
Return true if the norm of the gradient at a voxel location of the iterator is out of range...
Definition: Diagnostics.h:495
Class that performs various types of checks on narrow-band level sets.
Definition: Diagnostics.h:810
typename VecTraits< typename GridT::ValueType >::ElementType ElementType
Definition: Diagnostics.h:252
const GridType & grid() const
Return a const reference to the grid.
Definition: Diagnostics.h:836
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:365
Checks for infinite values, e.g. 1/0 or -1/0.
Definition: Diagnostics.h:174
std::string checkTiles() const
Return a nonempty message if the grid has no active tile values.
Definition: Diagnostics.h:886
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135
typename tree::IterTraits< typename TreeIterT::NodeT, typename TreeIterT::ValueIterT >::template NodeConverter< typename GridT::TreeType::LeafNodeType >::Type VoxelIterT
Definition: Diagnostics.h:311
bool operator()(const VoxelIterT &iter) const
Return true if the norm of the gradient at a zero-crossing voxel location of the iterator is out of r...
Definition: Diagnostics.h:558
void clear()
Clear the mask and error counter.
Definition: Diagnostics.h:1015
bool operator()(const ElementType &v) const
Return true if the value is smaller than min or larger than max.
Definition: Diagnostics.h:612
CheckNormGrad(const GridT &grid, const ValueType &_min, const ValueType &_max)
Constructor taking a grid and a range to be tested against.
Definition: Diagnostics.h:464
Checks a value against a minimum.
Definition: Diagnostics.h:359
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
void clear()
Clear the mask and error counter.
Definition: Diagnostics.h:839
typename GridType::template ValueConverter< bool >::Type MaskType
Definition: Diagnostics.h:990
bool operator()(const TreeIterT &) const
Return true if zero is outside the range.
Definition: Diagnostics.h:491
Check that the magnitude of a value, a, is close to a fixed magnitude, b, given a fixed tolerance c...
Definition: Diagnostics.h:250