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
@ MERGE_ACTIVE_STATES_AND_NODES
Definition: openvdb/Types.h:387
Definition: TreeIterator.h:1302
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
Tolerance for floating-point comparison.
Definition: Math.h:147
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:178
Coord Abs(const Coord &xyz)
Definition: Coord.h:515
static const Real LEVEL_SET_HALF_WIDTH
Definition: openvdb/Types.h:339
typename T::ValueType ElementType
Definition: openvdb/Types.h:204
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
@ CD_2ND
Definition: FiniteDifference.h:35
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
Type Pow2(Type x)
Return x2.
Definition: Math.h:551
DScheme
Different discrete schemes used in the first derivatives.
Definition: FiniteDifference.h:32
Divergence operator defined in index space using various first derivative schemes.
Definition: Operators.h:469
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Definition: openvdb/Exceptions.h:65
@ GRID_FOG_VOLUME
Definition: openvdb/Types.h:334
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition: Math.h:350
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
@ FIRST_BIAS
Definition: FiniteDifference.h:167
@ GRID_LEVEL_SET
Definition: openvdb/Types.h:333
double Real
Definition: openvdb/Types.h:56
uint64_t Index64
Definition: openvdb/Types.h:49
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 ...
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:764
Definition: openvdb/Exceptions.h:13
const IterT & iterator() const
Return a reference to this range's iterator.
Definition: TreeIterator.h:1323
Definition: Operators.h:227
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:165
Definition: TreeIterator.h:59