38 #ifndef OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED 39 #define OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED 47 #include <tbb/blocked_range.h> 48 #include <tbb/parallel_reduce.h> 53 #include <type_traits> 89 template<
class Gr
idType>
113 template<
class Gr
idType>
125 template<
class Gr
idType>
128 std::vector<typename GridType::ValueType>& values,
size_t numValues);
134 template<
typename Gr
idT,
typename TreeIterT =
typename Gr
idT::ValueOnCIter>
140 typename TreeIterT::NodeT,
typename TreeIterT::ValueIterT>::template
141 NodeConverter<typename GridT::TreeType::LeafNodeType>::Type;
151 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
154 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
159 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
165 std::string
str()
const {
return "NaN"; }
172 template <
typename GridT,
173 typename TreeIterT =
typename GridT::ValueOnCIter>
179 typename TreeIterT::ValueIterT> ::template NodeConverter<
180 typename GridT::TreeType::LeafNodeType>::Type;
190 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
193 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
198 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
204 std::string
str()
const {
return "infinite"; }
210 template <
typename GridT,
211 typename TreeIterT =
typename GridT::ValueOnCIter>
217 typename TreeIterT::ValueIterT> ::template NodeConverter<
218 typename GridT::TreeType::LeafNodeType>::Type;
228 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
230 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
235 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
241 std::string
str()
const {
return "not finite"; }
248 template <
typename GridT,
249 typename TreeIterT =
typename GridT::ValueOffCIter>
255 typename TreeIterT::ValueIterT> ::template NodeConverter<
256 typename GridT::TreeType::LeafNodeType>::Type;
261 : absVal(math::
Abs(a)), tolVal(math::
Abs(t))
274 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
277 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
282 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
290 std::ostringstream ss;
291 ss <<
"not equal to +/-"<<absVal<<
" with a tolerance of "<<tolVal;
301 template <
typename GridT,
302 bool MinInclusive =
true,
303 bool MaxInclusive =
true,
304 typename TreeIterT =
typename GridT::ValueOnCIter>
310 typename TreeIterT::ValueIterT> ::template NodeConverter<
311 typename GridT::TreeType::LeafNodeType>::Type;
316 if (minVal > maxVal) {
324 return (MinInclusive ? v<minVal : v<=minVal) ||
325 (MaxInclusive ? v>maxVal : v>=maxVal);
330 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
332 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
337 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
345 std::ostringstream ss;
346 ss <<
"outside the value range " << (MinInclusive ?
"[" :
"]")
347 << minVal <<
"," << maxVal << (MaxInclusive ?
"]" :
"[");
357 template <
typename GridT,
358 typename TreeIterT =
typename GridT::ValueOnCIter>
364 typename TreeIterT::ValueIterT> ::template NodeConverter<
365 typename GridT::TreeType::LeafNodeType>::Type;
375 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
377 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
382 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
390 std::ostringstream ss;
391 ss <<
"smaller than "<<minVal;
401 template <
typename GridT,
402 typename TreeIterT =
typename GridT::ValueOnCIter>
408 typename TreeIterT::ValueIterT> ::template NodeConverter<
409 typename GridT::TreeType::LeafNodeType>::Type;
419 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
421 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
426 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
434 std::ostringstream ss;
435 ss <<
"larger than "<<maxVal;
449 template<
typename GridT,
450 typename TreeIterT =
typename GridT::ValueOnCIter,
455 static_assert(std::is_floating_point<ValueType>::value,
456 "openvdb::tools::CheckNormGrad requires a scalar, floating-point grid");
459 typename TreeIterT::ValueIterT> ::template NodeConverter<
460 typename GridT::TreeType::LeafNodeType>::Type;
461 using AccT =
typename GridT::ConstAccessor;
465 : acc(grid.getConstAccessor())
470 if ( !grid.hasUniformVoxels() ) {
479 : acc(other.acc.tree())
480 , invdx2(other.invdx2)
481 , minVal2(other.minVal2)
482 , maxVal2(other.maxVal2)
497 const Coord ijk = iter.getCoord();
504 std::ostringstream ss;
519 template<
typename GridT,
520 typename TreeIterT =
typename GridT::ValueOnCIter,
525 static_assert(std::is_floating_point<ValueType>::value,
526 "openvdb::tools::CheckEikonal requires a scalar, floating-point grid");
529 typename TreeIterT::ValueIterT> ::template NodeConverter<
530 typename GridT::TreeType::LeafNodeType>::Type;
534 : stencil(grid), minVal(_min), maxVal(_max)
536 if ( !grid.hasUniformVoxels() ) {
539 if (minVal > maxVal) {
545 : stencil(other.stencil.grid()), minVal(other.minVal), maxVal(other.maxVal)
560 stencil.moveTo(iter);
561 if (!stencil.zeroCrossing())
return false;
562 return (*
this)(stencil.normSqGrad());
568 std::ostringstream ss;
569 ss <<
"outside the range of NormGrad ["<<minVal<<
","<<maxVal<<
"]";
580 template<
typename GridT,
581 typename TreeIterT =
typename GridT::ValueOnCIter,
587 static_assert(std::is_floating_point<ElementType>::value,
588 "openvdb::tools::CheckDivergence requires a floating-point vector grid");
591 typename TreeIterT::ValueIterT>::template NodeConverter<
592 typename GridT::TreeType::LeafNodeType>::Type;
593 using AccT =
typename GridT::ConstAccessor;
599 : acc(grid.getConstAccessor())
600 , invdx(
ValueType(1.0/grid.voxelSize()[0]))
604 if ( !grid.hasUniformVoxels() ) {
607 if (minVal > maxVal) {
622 const Coord ijk = iter.getCoord();
629 std::ostringstream ss;
630 ss <<
"outside the range of divergence ["<<minVal<<
","<<maxVal<<
"]";
642 template <
typename Gr
idT>
646 using MaskType =
typename GridT::template ValueConverter<bool>::Type;
650 mMask->setTransform(grid.transformPtr()->copy());
653 template <
typename CheckT>
654 std::string
check(
const CheckT& check,
655 bool updateMask =
false,
656 bool checkVoxels =
true,
657 bool checkTiles =
true,
658 bool checkBackground =
true)
660 typename MaskType::TreeType* mask = updateMask ? &(mMask->tree()) :
nullptr;
661 CheckValues<CheckT> cc(mask, mGrid, check);
662 std::ostringstream ss;
663 if (checkBackground) ss << cc.checkBackground();
664 if (checkTiles) ss << cc.checkTiles();
665 if (checkVoxels) ss << cc.checkVoxels();
671 typename MaskType::ConstPtr mask()
const {
return mMask; }
675 typename MaskType::Ptr
mask() {
return mMask; }
688 const GridT&
grid()
const {
return *mGrid; }
699 typename MaskType::Ptr mMask;
703 template <
typename CheckT>
706 using MaskT =
typename MaskType::TreeType;
707 using LeafT =
typename GridT::TreeType::LeafNodeType;
709 const bool mOwnsMask;
715 CheckValues(MaskT* mask,
const GridT* grid,
const CheckT& check)
723 CheckValues(CheckValues& other, tbb::split)
725 , mMask(other.mMask ? new MaskT() : nullptr)
727 , mCheck(other.mCheck)
731 ~CheckValues() {
if (mOwnsMask)
delete mMask; }
733 std::string checkBackground()
735 std::ostringstream ss;
736 if (mCheck(mGrid->background())) {
738 ss <<
"Background is " + mCheck.str() << std::endl;
743 std::string checkTiles()
745 std::ostringstream ss;
747 typename CheckT::TileIterT i(mGrid->tree());
748 for (i.setMaxDepth(GridT::TreeType::RootNodeType::LEVEL - 1); i; ++i) {
751 if (mMask) mMask->fill(i.getBoundingBox(),
true,
true);
754 if (
const Index64 m = mCount - n) {
755 ss << m <<
" tile" << (m==1 ?
" is " :
"s are ") + mCheck.str() << std::endl;
760 std::string checkVoxels()
762 std::ostringstream ss;
763 LeafManagerT leafs(mGrid->tree());
765 tbb::parallel_reduce(leafs.leafRange(), *
this);
766 if (
const Index64 m = mCount - n) {
767 ss << m <<
" voxel" << (m==1 ?
" is " :
"s are ") + mCheck.str() << std::endl;
772 void operator()(
const typename LeafManagerT::LeafRange& r)
774 using VoxelIterT =
typename CheckT::VoxelIterT;
776 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
777 typename MaskT::LeafNodeType* maskLeaf =
nullptr;
778 for (VoxelIterT j = tree::IterTraits<LeafT, VoxelIterT>::begin(*i); j; ++j) {
781 if (maskLeaf ==
nullptr) maskLeaf = mMask->touchLeaf(j.getCoord());
782 maskLeaf->setValueOn(j.pos(),
true);
787 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
788 for (VoxelIterT j = tree::IterTraits<LeafT, VoxelIterT>::begin(*i); j; ++j) {
789 if (mCheck(j)) ++mCount;
794 void join(
const CheckValues& other)
797 mCount += other.mCount;
809 template<
class Gr
idType>
814 using MaskType =
typename GridType::template ValueConverter<bool>::Type;
819 typename MaskType::ConstPtr mask()
const {
return mDiagnose.mask(); }
823 typename MaskType::Ptr
mask() {
return mDiagnose.mask(); }
836 const GridType&
grid()
const {
return mDiagnose.grid(); }
846 static const bool test = std::is_floating_point<ValueType>::value;
847 return test ?
"" :
"Value type is not floating point\n";
855 const bool test = mDiagnose.grid().getGridClass() ==
GRID_LEVEL_SET;
856 return test ?
"" :
"Class type is not \"GRID_LEVEL_SET\"\n";
864 return mDiagnose.grid().hasUniformVoxels() ?
"" :
"Does not have uniform voxels\n";
873 const Real w = mDiagnose.grid().background() / mDiagnose.grid().voxelSize()[0];
875 std::ostringstream ss;
876 ss <<
"The background value ("<< mDiagnose.grid().background()<<
") is less than " 877 << halfWidth <<
" voxel units\n";
888 const bool test = mDiagnose.grid().tree().hasActiveTiles();
889 return test ?
"Has active tile values\n" :
"";
898 return mDiagnose.check(c, updateMask,
true,
true,
true);
906 const ValueType& background = mDiagnose.grid().background();
908 return mDiagnose.check(c, updateMask,
true,
false,
false);
917 const ValueType& background = mDiagnose.grid().background();
919 return mDiagnose.check(c, updateMask,
true,
true,
false);
929 return mDiagnose.check(c, updateMask,
true,
false,
false);
949 std::string
check(
size_t n=9,
bool updateMask =
false)
951 std::string str = this->checkValueType();
952 if (str.empty() && n>1) str = this->checkClassType();
953 if (str.empty() && n>2) str = this->checkTransform();
954 if (str.empty() && n>3) str = this->checkBackground();
955 if (str.empty() && n>4) str = this->checkTiles();
956 if (str.empty() && n>5) str = this->checkFinite(updateMask);
957 if (str.empty() && n>6) str = this->checkRange(updateMask);
958 if (str.empty() && n>7) str = this->checkInactiveValues(updateMask);
959 if (str.empty() && n>8) str = this->checkEikonal(updateMask);
972 template<
class Gr
idType>
977 return c.
check(n,
false);
985 template<
class Gr
idType>
990 using MaskType =
typename GridType::template ValueConverter<bool>::Type;
995 typename MaskType::ConstPtr mask()
const {
return mDiagnose.mask(); }
999 typename MaskType::Ptr
mask() {
return mDiagnose.mask(); }
1012 const GridType&
grid()
const {
return mDiagnose.grid(); }
1022 static const bool test = std::is_floating_point<ValueType>::value;
1023 return test ?
"" :
"Value type is not floating point";
1032 return test ?
"" :
"Class type is not \"GRID_LEVEL_SET\"";
1041 std::ostringstream ss;
1042 ss <<
"The background value ("<< mDiagnose.grid().background()<<
") is not zero";
1054 return mDiagnose.check(c, updateMask,
true,
true,
true);
1063 return mDiagnose.check(c, updateMask,
true,
true,
true);
1073 return mDiagnose.check(c, updateMask,
true,
true,
false);
1088 std::string
check(
size_t n=6,
bool updateMask =
false)
1090 std::string str = this->checkValueType();
1091 if (str.empty() && n>1) str = this->checkClassType();
1092 if (str.empty() && n>2) str = this->checkBackground();
1093 if (str.empty() && n>3) str = this->checkFinite(updateMask);
1094 if (str.empty() && n>4) str = this->checkInactiveValues(updateMask);
1095 if (str.empty() && n>5) str = this->checkRange(updateMask);
1108 template<
class Gr
idType>
1113 return c.
check(n,
false);
1122 namespace diagnostics_internal {
1125 template<
typename TreeType>
1138 void getInactiveValues(
SetType&)
const;
1141 inline void operator()(
const tbb::blocked_range<size_t>&);
1150 template<
typename TreeType>
1154 , mNumValues(numValues)
1158 template <
typename TreeType>
1162 : mLeafArray(rhs.mLeafArray)
1164 , mNumValues(rhs.mNumValues)
1168 template<
typename TreeType>
1172 tbb::parallel_reduce(mLeafArray.getRange(), *
this);
1176 template<
typename TreeType>
1180 (*this)(mLeafArray.getRange());
1184 template<
typename TreeType>
1188 typename TreeType::LeafNodeType::ValueOffCIter iter;
1190 for (
size_t n = range.begin(); n < range.end() && !tbb::task::self().is_cancelled(); ++n) {
1191 for (iter = mLeafArray.leaf(n).cbeginValueOff(); iter; ++iter) {
1192 mInactiveValues.insert(iter.getValue());
1195 if (mInactiveValues.size() > mNumValues) {
1196 tbb::task::self().cancel_group_execution();
1201 template<
typename TreeType>
1205 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1208 template<
typename TreeType>
1212 values.insert(mInactiveValues.begin(), mInactiveValues.end());
1219 template<
typename TreeType>
1244 template<
typename TreeType>
1247 , mNumValues(numValues)
1251 template <
typename TreeType>
1256 , mNumValues(rhs.mNumValues)
1260 template<
typename TreeType>
1264 tbb::parallel_reduce(range, *
this);
1268 template<
typename TreeType>
1276 template<
typename TreeType>
1280 for (; range && !tbb::task::self().is_cancelled(); ++range) {
1281 typename TreeType::ValueOffCIter iter = range.
iterator();
1282 for (; iter; ++iter) {
1283 mInactiveValues.insert(iter.getValue());
1286 if (mInactiveValues.size() > mNumValues) {
1287 tbb::task::self().cancel_group_execution();
1292 template<
typename TreeType>
1296 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1299 template<
typename TreeType>
1303 values.insert(mInactiveValues.begin(), mInactiveValues.end());
1312 template<
class Gr
idType>
1315 std::vector<typename GridType::ValueType>& values,
size_t numValues)
1317 using TreeType =
typename GridType::TreeType;
1318 using ValueType =
typename GridType::ValueType;
1319 using SetType = std::set<ValueType>;
1321 SetType uniqueValues;
1324 TreeType& tree = const_cast<TreeType&>(grid.tree());
1332 if (uniqueValues.size() <= numValues) {
1333 typename TreeType::ValueOffCIter iter(grid.tree());
1334 iter.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 1);
1344 values.reserve(uniqueValues.size());
1346 typename SetType::iterator it = uniqueValues.begin();
1347 for ( ; it != uniqueValues.end(); ++it) {
1348 values.push_back(*it);
1351 return values.size() <= numValues;
1358 #endif // OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
uint64_t Index64
Definition: Types.h:60
Definition: TreeIterator.h:1351
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition: Math.h:320
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:715
This is a special 19-point stencil that supports optimal fifth-order WENO upwinding,...
Definition: Stencils.h:1348
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
DScheme
Different discrete schemes used in the first derivatives.
Definition: FiniteDifference.h:59
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
Divergence operator defined in index space using various first derivative schemes.
Definition: Operators.h:496
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:283
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
Definition: TreeIterator.h:108
Definition: Exceptions.h:40
Definition: Operators.h:254
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
Tolerance for floating-point comparison.
Definition: Math.h:117
Coord Abs(const Coord &xyz)
Definition: Coord.h:513
const IterT & iterator() const
Return a reference to this range's iterator.
Definition: TreeIterator.h:1372
Definition: FiniteDifference.h:62
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
Definition: Exceptions.h:92
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:192
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Definition: FiniteDifference.h:194
double Real
Definition: Types.h:67
Type Pow2(Type x)
Return x2.
Definition: Math.h:502
T ElementType
Definition: Types.h:218