31 #ifndef OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
32 #define OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
34 #include <openvdb/Grid.h>
35 #include <openvdb/math/Math.h>
36 #include <openvdb/math/Vec3.h>
37 #include <openvdb/math/Operators.h>
38 #include <openvdb/tree/LeafManager.h>
39 #include <tbb/blocked_range.h>
40 #include <tbb/parallel_reduce.h>
42 #include <boost/math/special_functions/fpclassify.hpp>
43 #include <boost/utility/enable_if.hpp>
82 template<
class Gr
idType>
85 std::vector<typename GridType::ValueType>& values,
size_t numValues);
91 template <
typename GridT,
92 typename TreeIterT =
typename GridT::ValueOnCIter>
98 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
104 inline bool operator()(
const ElementType& v)
const {
return boost::math::isnan(v); }
107 template <
typename T>
108 inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
111 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
116 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
119 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
122 std::string
str()
const {
return "nan"; }
127 template <
typename GridT,
128 typename TreeIterT =
typename GridT::ValueOnCIter>
134 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
140 inline bool operator()(
const ElementType& v)
const {
return boost::math::isinf(v); }
143 template <
typename T>
inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
146 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
151 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
154 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
157 std::string
str()
const {
return "infinite"; }
161 template <
typename GridT,
162 typename TreeIterT =
typename GridT::ValueOnCIter>
168 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
174 inline bool operator()(
const ElementType& v)
const {
return !boost::math::isfinite(v); }
177 template <
typename T>
178 inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
180 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
185 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
188 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
191 std::string
str()
const {
return "not finite"; }
196 template <
typename GridT,
197 typename TreeIterT =
typename GridT::ValueOffCIter>
203 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
208 : absVal(math::
Abs(a)), tolVal(math::
Abs(t))
220 template <
typename T>
inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
223 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
228 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
231 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
236 std::ostringstream ss;
237 ss <<
"not equal to +/-"<<absVal<<
" with a tolerance of "<<tolVal;
245 template <
typename GridT,
246 bool MinInclusive =
true,
247 bool MaxInclusive =
true,
248 typename TreeIterT =
typename GridT::ValueOnCIter>
254 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
257 CheckRange(
const ElementType& _min,
const ElementType& _max) : minVal(_min), maxVal(_max)
264 return (MinInclusive ? v<minVal : v<=minVal) ||
265 (MaxInclusive ? v>maxVal : v>=maxVal);
269 template <
typename T>
270 inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
272 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
277 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
280 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
285 std::ostringstream ss;
286 ss <<
"outside the range " << (MinInclusive ?
"[" :
"]")
287 << minVal <<
"," << maxVal << (MaxInclusive ?
"]" :
"[");
295 template <
typename GridT,
296 typename TreeIterT =
typename GridT::ValueOnCIter>
302 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
305 CheckMin(
const ElementType& _min) : minVal(_min) {}
308 inline bool operator()(
const ElementType& v)
const {
return v<minVal; }
311 template <
typename T>
312 inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
314 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
319 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
322 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
327 std::ostringstream ss;
328 ss <<
"smaller then "<<minVal;
336 template <
typename GridT,
337 typename TreeIterT =
typename GridT::ValueOnCIter>
343 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
346 CheckMax(
const ElementType& _max) : maxVal(_max) {}
349 inline bool operator()(
const ElementType& v)
const {
return v>maxVal; }
352 template <
typename T>
353 inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
355 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
360 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
363 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
368 std::ostringstream ss;
369 ss <<
"larger then "<<maxVal;
377 template<
typename GridT,
378 typename TreeIterT =
typename GridT::ValueOnCIter,
383 BOOST_STATIC_ASSERT(boost::is_floating_point<ValueType>::value);
386 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
387 typedef typename GridT::ConstAccessor
AccT;
390 CheckNormGrad(
const GridT& grid,
const ValueType& _min,
const ValueType& _max)
391 : acc(grid.getConstAccessor())
392 , invdx2(ValueType(1.0/math::
Pow2(grid.voxelSize()[0])))
396 if ( !grid.hasUniformVoxels() ) {
398 "The transform must have uniform scale for CheckNormGrad to function");
403 : acc(other.acc.tree())
404 , invdx2(other.invdx2)
405 , minVal(other.minVal)
406 , maxVal(other.maxVal)
412 if (&other !=
this) {
413 acc = AccT(other.
acc.tree());
422 inline bool operator()(
const ValueType& v)
const {
return v<minVal || v>maxVal; }
426 inline bool operator()(
const TreeIterT&)
const {
return (*
this)(ValueType(0)); }
432 const Coord ijk = iter.getCoord();
439 std::ostringstream ss;
440 ss <<
"outside the range ["<<minVal<<
","<<maxVal<<
"]";
449 template<
typename GridT,
450 typename TreeIterT =
typename GridT::ValueOnCIter,
456 BOOST_STATIC_ASSERT(boost::is_floating_point<ElementType>::value);
459 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
460 typedef typename GridT::ConstAccessor
AccT;
464 const ValueType& _min,
465 const ValueType& _max)
466 : acc(grid.getConstAccessor())
467 , invdx(ValueType(1.0/grid.voxelSize()[0]))
471 if ( !grid.hasUniformVoxels() ) {
473 "The transform must have uniform scale for CheckDivergence to function");
477 inline bool operator()(
const ElementType& v)
const {
return v<minVal || v>maxVal; }
481 inline bool operator()(
const TreeIterT&)
const {
return (*
this)(ElementType(0)); }
487 const Coord ijk = iter.getCoord();
494 std::ostringstream ss;
495 ss <<
"outside the range ["<<minVal<<
","<<maxVal<<
"]";
505 template <
typename Gr
idT>
509 typedef typename GridT::template ValueConverter<bool>::Type
MaskType;
511 Diagnose(
const GridT& grid) : mGrid(&grid), mMask(new MaskType()), mCount(0)
513 mMask->setTransform(grid.transformPtr()->copy());
516 template <
typename CheckT>
517 std::string
check(
const CheckT& check,
518 bool updateMask =
false,
519 bool checkVoxels =
true,
520 bool checkTiles =
true,
521 bool checkBackground =
true)
523 typename MaskType::TreeType* mask = updateMask ? &(mMask->tree()) : NULL;
524 CheckValues<CheckT> cc(mask, mGrid, check);
525 std::ostringstream ss;
526 if (checkBackground) ss << cc.checkBackground();
527 if (checkTiles) ss << cc.checkTiles();
528 if (checkVoxels) ss << cc.checkVoxels();
536 typename MaskType::ConstPtr
mask()
const {
return mMask; }
549 typename MaskType::Ptr mMask;
553 template <
typename CheckT>
556 typedef typename MaskType::TreeType MaskT;
557 typedef typename GridT::TreeType::LeafNodeType LeafT;
559 const bool mOwnsMask;
565 CheckValues(MaskT* mask,
const GridT* grid,
const CheckT& check)
573 CheckValues(CheckValues& other, tbb::split)
575 , mMask(other.mMask ? new MaskT() : NULL)
577 , mCheck(other.mCheck)
581 ~CheckValues() {
if (mOwnsMask)
delete mMask; }
583 std::string checkBackground()
585 std::ostringstream ss;
586 if (mCheck(mGrid->background())) {
588 ss <<
"Background is " + mCheck.str() << std::endl;
593 std::string checkTiles()
595 std::ostringstream ss;
597 typename CheckT::TileIterT i(mGrid->tree());
598 for (i.setMaxDepth(GridT::TreeType::RootNodeType::LEVEL - 1); i; ++i) {
601 if (mMask) mMask->fill(i.getBoundingBox(),
true,
true);
604 if (
const Index64 m = mCount - n) {
605 ss << m << (m==1?
" tile is ":
" tiles are ") + mCheck.str() << std::endl;
610 std::string checkVoxels()
612 std::ostringstream ss;
613 LeafManagerT leafs(mGrid->tree());
615 tbb::parallel_reduce(leafs.leafRange(), *
this);
616 if (
const Index64 m = mCount - n) {
617 ss << m << (m==1?
" voxel is ":
" voxels are ") + mCheck.str() << std::endl;
622 void operator()(
const typename LeafManagerT::LeafRange& r)
624 typedef typename CheckT::VoxelIterT VoxelIterT;
626 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
627 typename MaskT::LeafNodeType* maskLeaf = NULL;
628 for (VoxelIterT j = tree::IterTraits<LeafT, VoxelIterT>::begin(*i); j; ++j) {
631 if (maskLeaf == NULL) maskLeaf = mMask->touchLeaf(j.getCoord());
632 maskLeaf->setValueOn(j.pos(),
true);
637 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
638 for (VoxelIterT j = tree::IterTraits<LeafT, VoxelIterT>::begin(*i); j; ++j) {
639 if (mCheck(j)) ++mCount;
644 void join(
const CheckValues& other)
647 mCount += other.mCount;
659 namespace diagnostics_internal {
662 template<
typename TreeType>
675 void getInactiveValues(SetType&)
const;
678 inline void operator()(
const tbb::blocked_range<size_t>&);
682 LeafArray& mLeafArray;
683 SetType mInactiveValues;
687 template<
typename TreeType>
691 , mNumValues(numValues)
695 template <
typename TreeType>
699 : mLeafArray(rhs.mLeafArray)
701 , mNumValues(rhs.mNumValues)
705 template<
typename TreeType>
709 tbb::parallel_reduce(mLeafArray.getRange(), *
this);
713 template<
typename TreeType>
717 (*this)(mLeafArray.getRange());
721 template<
typename TreeType>
725 typename TreeType::LeafNodeType::ValueOffCIter iter;
727 for (
size_t n = range.begin(); n < range.end() && !tbb::task::self().is_cancelled(); ++n) {
728 for (iter = mLeafArray.leaf(n).cbeginValueOff(); iter; ++iter) {
729 mInactiveValues.insert(iter.getValue());
732 if (mInactiveValues.size() > mNumValues) {
733 tbb::task::self().cancel_group_execution();
738 template<
typename TreeType>
742 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
745 template<
typename TreeType>
749 values.insert(mInactiveValues.begin(), mInactiveValues.end());
756 template<
typename TreeType>
776 SetType mInactiveValues;
781 template<
typename TreeType>
784 , mNumValues(numValues)
788 template <
typename TreeType>
793 , mNumValues(rhs.mNumValues)
797 template<
typename TreeType>
801 tbb::parallel_reduce(range, *
this);
805 template<
typename TreeType>
813 template<
typename TreeType>
817 for (; range && !tbb::task::self().is_cancelled(); ++range) {
818 typename TreeType::ValueOffCIter iter = range.
iterator();
819 for (; iter; ++iter) {
820 mInactiveValues.insert(iter.getValue());
823 if (mInactiveValues.size() > mNumValues) {
824 tbb::task::self().cancel_group_execution();
829 template<
typename TreeType>
833 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
836 template<
typename TreeType>
840 values.insert(mInactiveValues.begin(), mInactiveValues.end());
849 template<
class Gr
idType>
852 std::vector<typename GridType::ValueType>& values,
size_t numValues)
855 typedef typename GridType::TreeType TreeType;
856 typedef typename GridType::ValueType ValueType;
857 typedef std::set<ValueType> SetType;
859 SetType uniqueValues;
862 TreeType& tree =
const_cast<TreeType&
>(grid.tree());
870 if (uniqueValues.size() <= numValues) {
871 typename TreeType::ValueOffCIter iter(grid.tree());
872 iter.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 1);
882 values.reserve(uniqueValues.size());
884 typename SetType::iterator it = uniqueValues.begin();
885 for ( ; it != uniqueValues.end(); ++it) {
886 values.push_back(*it);
889 return values.size() <= numValues;
896 #endif // OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:284
uint64_t Index64
Definition: Types.h:58
T ElementType
Definition: Types.h:152
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
Type Pow2(Type x)
Return .
Definition: Math.h:498
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
Definition: FiniteDifference.h:62
Definition: Exceptions.h:86
DScheme
Different discrete schemes used in the first derivatives.
Definition: FiniteDifference.h:59
#define OPENVDB_VERSION_NAME
Definition: version.h:43
const IterT & iterator() const
Return a reference to this range's iterator.
Definition: TreeIterator.h:1360
Definition: Exceptions.h:39
Divergence operator defined in index space using various first derivative schemes.
Definition: Operators.h:495
Definition: TreeIterator.h:1339
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:192
Definition: TreeIterator.h:106
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
Definition: FiniteDifference.h:194
Definition: Operators.h:251
Tolerance for floating-point comparison.
Definition: Math.h:116