Go to the documentation of this file.
11 #ifndef OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
12 #define OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
20 #include <tbb/blocked_range.h>
21 #include <tbb/parallel_reduce.h>
26 #include <type_traits>
62 template<
class Gr
idType>
86 template<
class Gr
idType>
98 template<
class Gr
idType>
101 std::vector<typename GridType::ValueType>& values,
size_t numValues);
107 template<
typename Gr
idT,
typename TreeIterT =
typename Gr
idT::ValueOnCIter>
113 typename TreeIterT::NodeT,
typename TreeIterT::ValueIterT>::template
114 NodeConverter<typename GridT::TreeType::LeafNodeType>::Type;
124 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
127 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
132 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
138 std::string
str()
const {
return "NaN"; }
145 template <
typename GridT,
146 typename TreeIterT =
typename GridT::ValueOnCIter>
152 typename TreeIterT::ValueIterT> ::template NodeConverter<
153 typename GridT::TreeType::LeafNodeType>::Type;
163 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
166 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
171 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
177 std::string
str()
const {
return "infinite"; }
183 template <
typename GridT,
184 typename TreeIterT =
typename GridT::ValueOnCIter>
190 typename TreeIterT::ValueIterT> ::template NodeConverter<
191 typename GridT::TreeType::LeafNodeType>::Type;
201 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
203 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
208 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
214 std::string
str()
const {
return "not finite"; }
221 template <
typename GridT,
222 typename TreeIterT =
typename GridT::ValueOffCIter>
228 typename TreeIterT::ValueIterT> ::template NodeConverter<
229 typename GridT::TreeType::LeafNodeType>::Type;
234 : absVal(math::
Abs(a)), tolVal(math::
Abs(t))
247 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
250 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
255 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
263 std::ostringstream ss;
264 ss <<
"not equal to +/-"<<absVal<<
" with a tolerance of "<<tolVal;
274 template <
typename GridT,
275 bool MinInclusive =
true,
276 bool MaxInclusive =
true,
277 typename TreeIterT =
typename GridT::ValueOnCIter>
283 typename TreeIterT::ValueIterT> ::template NodeConverter<
284 typename GridT::TreeType::LeafNodeType>::Type;
289 if (minVal > maxVal) {
297 return (MinInclusive ? v<minVal : v<=minVal) ||
298 (MaxInclusive ? v>maxVal : v>=maxVal);
303 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
305 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
310 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
318 std::ostringstream ss;
319 ss <<
"outside the value range " << (MinInclusive ?
"[" :
"]")
320 << minVal <<
"," << maxVal << (MaxInclusive ?
"]" :
"[");
330 template <
typename GridT,
331 typename TreeIterT =
typename GridT::ValueOnCIter>
337 typename TreeIterT::ValueIterT> ::template NodeConverter<
338 typename GridT::TreeType::LeafNodeType>::Type;
348 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
350 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
355 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
363 std::ostringstream ss;
364 ss <<
"smaller than "<<minVal;
374 template <
typename GridT,
375 typename TreeIterT =
typename GridT::ValueOnCIter>
381 typename TreeIterT::ValueIterT> ::template NodeConverter<
382 typename GridT::TreeType::LeafNodeType>::Type;
392 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
394 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
399 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
407 std::ostringstream ss;
408 ss <<
"larger than "<<maxVal;
422 template<
typename GridT,
423 typename TreeIterT =
typename GridT::ValueOnCIter,
428 static_assert(std::is_floating_point<ValueType>::value,
429 "openvdb::tools::CheckNormGrad requires a scalar, floating-point grid");
432 typename TreeIterT::ValueIterT> ::template NodeConverter<
433 typename GridT::TreeType::LeafNodeType>::Type;
434 using AccT =
typename GridT::ConstAccessor;
438 : acc(grid.getConstAccessor())
443 if ( !grid.hasUniformVoxels() ) {
452 : acc(other.acc.tree())
453 , invdx2(other.invdx2)
454 , minVal2(other.minVal2)
455 , maxVal2(other.maxVal2)
470 const Coord ijk = iter.getCoord();
477 std::ostringstream ss;
492 template<
typename GridT,
493 typename TreeIterT =
typename GridT::ValueOnCIter,
498 static_assert(std::is_floating_point<ValueType>::value,
499 "openvdb::tools::CheckEikonal requires a scalar, floating-point grid");
502 typename TreeIterT::ValueIterT> ::template NodeConverter<
503 typename GridT::TreeType::LeafNodeType>::Type;
507 : stencil(grid), minVal(_min), maxVal(_max)
509 if ( !grid.hasUniformVoxels() ) {
512 if (minVal > maxVal) {
518 : stencil(other.stencil.grid()), minVal(other.minVal), maxVal(other.maxVal)
533 stencil.moveTo(iter);
534 if (!stencil.zeroCrossing())
return false;
535 return (*
this)(stencil.normSqGrad());
541 std::ostringstream ss;
542 ss <<
"outside the range of NormGrad ["<<minVal<<
","<<maxVal<<
"]";
553 template<
typename GridT,
554 typename TreeIterT =
typename GridT::ValueOnCIter,
560 static_assert(std::is_floating_point<ElementType>::value,
561 "openvdb::tools::CheckDivergence requires a floating-point vector grid");
564 typename TreeIterT::ValueIterT>::template NodeConverter<
565 typename GridT::TreeType::LeafNodeType>::Type;
566 using AccT =
typename GridT::ConstAccessor;
572 : acc(grid.getConstAccessor())
573 , invdx(
ValueType(1.0/grid.voxelSize()[0]))
577 if ( !grid.hasUniformVoxels() ) {
580 if (minVal > maxVal) {
595 const Coord ijk = iter.getCoord();
602 std::ostringstream ss;
603 ss <<
"outside the range of divergence ["<<minVal<<
","<<maxVal<<
"]";
615 template <
typename Gr
idT>
619 using MaskType =
typename GridT::template ValueConverter<bool>::Type;
623 mMask->setTransform(grid.transformPtr()->copy());
626 template <
typename CheckT>
627 std::string
check(
const CheckT& check,
628 bool updateMask =
false,
629 bool checkVoxels =
true,
630 bool checkTiles =
true,
631 bool checkBackground =
true)
633 typename MaskType::TreeType* mask = updateMask ? &(mMask->tree()) :
nullptr;
634 CheckValues<CheckT> cc(mask, mGrid, check);
635 std::ostringstream ss;
636 if (checkBackground) ss << cc.checkBackground();
637 if (checkTiles) ss << cc.checkTiles();
638 if (checkVoxels) ss << cc.checkVoxels();
644 typename MaskType::ConstPtr mask()
const {
return mMask; }
648 typename MaskType::Ptr
mask() {
return mMask; }
661 const GridT&
grid()
const {
return *mGrid; }
672 typename MaskType::Ptr mMask;
676 template <
typename CheckT>
679 using MaskT =
typename MaskType::TreeType;
680 using LeafT =
typename GridT::TreeType::LeafNodeType;
682 const bool mOwnsMask;
688 CheckValues(MaskT* mask,
const GridT* grid,
const CheckT& check)
696 CheckValues(CheckValues& other, tbb::split)
698 , mMask(other.mMask ? new MaskT() : nullptr)
700 , mCheck(other.mCheck)
704 ~CheckValues() {
if (mOwnsMask)
delete mMask; }
706 std::string checkBackground()
708 std::ostringstream ss;
709 if (mCheck(mGrid->background())) {
711 ss <<
"Background is " + mCheck.str() << std::endl;
716 std::string checkTiles()
718 std::ostringstream ss;
720 typename CheckT::TileIterT i(mGrid->tree());
721 for (i.setMaxDepth(GridT::TreeType::RootNodeType::LEVEL - 1); i; ++i) {
724 if (mMask) mMask->fill(i.getBoundingBox(),
true,
true);
727 if (
const Index64 m = mCount - n) {
728 ss << m <<
" tile" << (m==1 ?
" is " :
"s are ") + mCheck.str() << std::endl;
733 std::string checkVoxels()
735 std::ostringstream ss;
736 LeafManagerT leafs(mGrid->tree());
738 tbb::parallel_reduce(leafs.leafRange(), *
this);
739 if (
const Index64 m = mCount - n) {
740 ss << m <<
" voxel" << (m==1 ?
" is " :
"s are ") + mCheck.str() << std::endl;
745 void operator()(
const typename LeafManagerT::LeafRange& r)
747 using VoxelIterT =
typename CheckT::VoxelIterT;
749 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
750 typename MaskT::LeafNodeType* maskLeaf =
nullptr;
751 for (VoxelIterT j = tree::IterTraits<LeafT, VoxelIterT>::begin(*i); j; ++j) {
754 if (maskLeaf ==
nullptr) maskLeaf = mMask->touchLeaf(j.getCoord());
755 maskLeaf->setValueOn(j.pos(),
true);
760 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
761 for (VoxelIterT j = tree::IterTraits<LeafT, VoxelIterT>::begin(*i); j; ++j) {
762 if (mCheck(j)) ++mCount;
767 void join(
const CheckValues& other)
770 mCount += other.mCount;
782 template<
class Gr
idType>
787 using MaskType =
typename GridType::template ValueConverter<bool>::Type;
792 typename MaskType::ConstPtr mask()
const {
return mDiagnose.mask(); }
796 typename MaskType::Ptr
mask() {
return mDiagnose.mask(); }
809 const GridType&
grid()
const {
return mDiagnose.grid(); }
819 static const bool test = std::is_floating_point<ValueType>::value;
820 return test ?
"" :
"Value type is not floating point\n";
828 const bool test = mDiagnose.grid().getGridClass() ==
GRID_LEVEL_SET;
829 return test ?
"" :
"Class type is not \"GRID_LEVEL_SET\"\n";
837 return mDiagnose.grid().hasUniformVoxels() ?
"" :
"Does not have uniform voxels\n";
846 const Real w = mDiagnose.grid().background() / mDiagnose.grid().voxelSize()[0];
848 std::ostringstream ss;
849 ss <<
"The background value ("<< mDiagnose.grid().background()<<
") is less than "
850 << halfWidth <<
" voxel units\n";
861 const bool test = mDiagnose.grid().tree().hasActiveTiles();
862 return test ?
"Has active tile values\n" :
"";
871 return mDiagnose.check(c, updateMask,
true,
true,
true);
879 const ValueType& background = mDiagnose.grid().background();
881 return mDiagnose.check(c, updateMask,
true,
false,
false);
890 const ValueType& background = mDiagnose.grid().background();
892 return mDiagnose.check(c, updateMask,
true,
true,
false);
902 return mDiagnose.check(c, updateMask,
true,
false,
false);
922 std::string
check(
size_t n=9,
bool updateMask =
false)
924 std::string str = this->checkValueType();
925 if (str.empty() && n>1) str = this->checkClassType();
926 if (str.empty() && n>2) str = this->checkTransform();
927 if (str.empty() && n>3) str = this->checkBackground();
928 if (str.empty() && n>4) str = this->checkTiles();
929 if (str.empty() && n>5) str = this->checkFinite(updateMask);
930 if (str.empty() && n>6) str = this->checkRange(updateMask);
931 if (str.empty() && n>7) str = this->checkInactiveValues(updateMask);
932 if (str.empty() && n>8) str = this->checkEikonal(updateMask);
945 template<
class Gr
idType>
950 return c.
check(n,
false);
958 template<
class Gr
idType>
963 using MaskType =
typename GridType::template ValueConverter<bool>::Type;
968 typename MaskType::ConstPtr mask()
const {
return mDiagnose.mask(); }
972 typename MaskType::Ptr
mask() {
return mDiagnose.mask(); }
985 const GridType&
grid()
const {
return mDiagnose.grid(); }
995 static const bool test = std::is_floating_point<ValueType>::value;
996 return test ?
"" :
"Value type is not floating point";
1005 return test ?
"" :
"Class type is not \"GRID_LEVEL_SET\"";
1014 std::ostringstream ss;
1015 ss <<
"The background value ("<< mDiagnose.grid().background()<<
") is not zero";
1027 return mDiagnose.check(c, updateMask,
true,
true,
true);
1036 return mDiagnose.check(c, updateMask,
true,
true,
true);
1046 return mDiagnose.check(c, updateMask,
true,
true,
false);
1061 std::string
check(
size_t n=6,
bool updateMask =
false)
1063 std::string str = this->checkValueType();
1064 if (str.empty() && n>1) str = this->checkClassType();
1065 if (str.empty() && n>2) str = this->checkBackground();
1066 if (str.empty() && n>3) str = this->checkFinite(updateMask);
1067 if (str.empty() && n>4) str = this->checkInactiveValues(updateMask);
1068 if (str.empty() && n>5) str = this->checkRange(updateMask);
1081 template<
class Gr
idType>
1086 return c.
check(n,
false);
1095 namespace diagnostics_internal {
1098 template<
typename TreeType>
1111 void getInactiveValues(
SetType&)
const;
1114 inline void operator()(
const tbb::blocked_range<size_t>&);
1123 template<
typename TreeType>
1127 , mNumValues(numValues)
1131 template <
typename TreeType>
1135 : mLeafArray(rhs.mLeafArray)
1137 , mNumValues(rhs.mNumValues)
1141 template<
typename TreeType>
1145 tbb::parallel_reduce(mLeafArray.getRange(), *
this);
1149 template<
typename TreeType>
1153 (*this)(mLeafArray.getRange());
1157 template<
typename TreeType>
1161 typename TreeType::LeafNodeType::ValueOffCIter iter;
1163 for (
size_t n = range.begin(); n < range.end() && !tbb::task::self().is_cancelled(); ++n) {
1164 for (iter = mLeafArray.leaf(n).cbeginValueOff(); iter; ++iter) {
1165 mInactiveValues.insert(iter.getValue());
1168 if (mInactiveValues.size() > mNumValues) {
1169 tbb::task::self().cancel_group_execution();
1174 template<
typename TreeType>
1178 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1181 template<
typename TreeType>
1185 values.insert(mInactiveValues.begin(), mInactiveValues.end());
1192 template<
typename TreeType>
1217 template<
typename TreeType>
1220 , mNumValues(numValues)
1224 template <
typename TreeType>
1229 , mNumValues(rhs.mNumValues)
1233 template<
typename TreeType>
1237 tbb::parallel_reduce(range, *
this);
1241 template<
typename TreeType>
1249 template<
typename TreeType>
1253 for (; range && !tbb::task::self().is_cancelled(); ++range) {
1254 typename TreeType::ValueOffCIter iter = range.
iterator();
1255 for (; iter; ++iter) {
1256 mInactiveValues.insert(iter.getValue());
1259 if (mInactiveValues.size() > mNumValues) {
1260 tbb::task::self().cancel_group_execution();
1265 template<
typename TreeType>
1269 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1272 template<
typename TreeType>
1276 values.insert(mInactiveValues.begin(), mInactiveValues.end());
1285 template<
class Gr
idType>
1288 std::vector<typename GridType::ValueType>& values,
size_t numValues)
1290 using TreeType =
typename GridType::TreeType;
1291 using ValueType =
typename GridType::ValueType;
1292 using SetType = std::set<ValueType>;
1294 SetType uniqueValues;
1297 TreeType& tree =
const_cast<TreeType&
>(grid.tree());
1305 if (uniqueValues.size() <= numValues) {
1306 typename TreeType::ValueOffCIter iter(grid.tree());
1307 iter.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 1);
1317 values.reserve(uniqueValues.size());
1319 typename SetType::iterator it = uniqueValues.begin();
1320 for ( ; it != uniqueValues.end(); ++it) {
1321 values.push_back(*it);
1324 return values.size() <= numValues;
1331 #endif // OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
@ FIRST_BIAS
Definition: FiniteDifference.h:167
Divergence operator defined in index space using various first derivative schemes.
Definition: Operators.h:470
Definition: Operators.h:228
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
@ CD_2ND
Definition: FiniteDifference.h:35
@ GRID_FOG_VOLUME
Definition: Types.h:455
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:165
double Real
Definition: Types.h:37
DScheme
Different discrete schemes used in the first derivatives.
Definition: FiniteDifference.h:32
Type Pow2(Type x)
Return x2.
Definition: Math.h:495
Coord Abs(const Coord &xyz)
Definition: Coord.h:515
Tolerance for floating-point comparison.
Definition: Math.h:90
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:460
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:83
const IterT & iterator() const
Return a reference to this range's iterator.
Definition: TreeIterator.h:1328
Definition: TreeIterator.h:65
typename T::ValueType ElementType
Definition: Types.h:185
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:708
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition: Math.h:293
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
@ MERGE_ACTIVE_STATES_AND_NODES
Definition: Types.h:508
Definition: Exceptions.h:65
@ GRID_LEVEL_SET
Definition: Types.h:454
Definition: Exceptions.h:13
uint64_t Index64
Definition: Types.h:30
Definition: TreeIterator.h:1308
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:82