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