38 #ifndef OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED 39 #define OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED 41 #include <openvdb/Grid.h> 42 #include <openvdb/math/Math.h> 43 #include <openvdb/math/Vec3.h> 44 #include <openvdb/math/Stencils.h> 45 #include <openvdb/math/Operators.h> 46 #include <openvdb/tree/LeafManager.h> 47 #include <tbb/blocked_range.h> 48 #include <tbb/parallel_reduce.h> 50 #include <boost/math/special_functions/fpclassify.hpp> 51 #include <boost/utility/enable_if.hpp> 85 template<
class Gr
idType>
109 template<
class Gr
idType>
121 template<
class Gr
idType>
124 std::vector<typename GridType::ValueType>& values,
size_t numValues);
130 template <
typename GridT,
131 typename TreeIterT =
typename GridT::ValueOnCIter>
137 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
143 inline bool operator()(
const ElementType& v)
const {
return boost::math::isnan(v); }
146 template <
typename T>
147 inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
150 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
155 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
158 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
161 std::string
str()
const {
return "NaN"; }
168 template <
typename GridT,
169 typename TreeIterT =
typename GridT::ValueOnCIter>
175 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
181 inline bool operator()(
const ElementType& v)
const {
return boost::math::isinf(v); }
184 template <
typename T>
inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
187 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
192 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
195 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
198 std::string
str()
const {
return "infinite"; }
204 template <
typename GridT,
205 typename TreeIterT =
typename GridT::ValueOnCIter>
211 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
217 inline bool operator()(
const ElementType& v)
const {
return !boost::math::isfinite(v); }
220 template <
typename T>
221 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); }
234 std::string
str()
const {
return "not finite"; }
241 template <
typename GridT,
242 typename TreeIterT =
typename GridT::ValueOffCIter>
248 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
253 : absVal(math::
Abs(a)), tolVal(math::
Abs(t))
265 template <
typename T>
inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
268 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
273 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
276 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
281 std::ostringstream ss;
282 ss <<
"not equal to +/-"<<absVal<<
" with a tolerance of "<<tolVal;
292 template <
typename GridT,
293 bool MinInclusive =
true,
294 bool MaxInclusive =
true,
295 typename TreeIterT =
typename GridT::ValueOnCIter>
301 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
304 CheckRange(
const ElementType& _min,
const ElementType& _max) : minVal(_min), maxVal(_max)
306 if (minVal > maxVal) {
314 return (MinInclusive ? v<minVal : v<=minVal) ||
315 (MaxInclusive ? v>maxVal : v>=maxVal);
319 template <
typename T>
320 inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
322 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
327 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
330 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
335 std::ostringstream ss;
336 ss <<
"outside the value range " << (MinInclusive ?
"[" :
"]")
337 << minVal <<
"," << maxVal << (MaxInclusive ?
"]" :
"[");
347 template <
typename GridT,
348 typename TreeIterT =
typename GridT::ValueOnCIter>
354 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
357 CheckMin(
const ElementType& _min) : minVal(_min) {}
360 inline bool operator()(
const ElementType& v)
const {
return v<minVal; }
363 template <
typename T>
364 inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
366 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
371 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
374 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
379 std::ostringstream ss;
380 ss <<
"smaller than "<<minVal;
390 template <
typename GridT,
391 typename TreeIterT =
typename GridT::ValueOnCIter>
397 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
400 CheckMax(
const ElementType& _max) : maxVal(_max) {}
403 inline bool operator()(
const ElementType& v)
const {
return v>maxVal; }
406 template <
typename T>
407 inline typename boost::enable_if_c<VecTraits<T>::IsVec,
bool>::type
409 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
414 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
417 bool operator()(
const VoxelIterT &iter)
const {
return (*
this)(*iter); }
422 std::ostringstream ss;
423 ss <<
"larger than "<<maxVal;
436 template<
typename GridT,
437 typename TreeIterT =
typename GridT::ValueOnCIter,
442 BOOST_STATIC_ASSERT(boost::is_floating_point<ValueType>::value);
445 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
446 typedef typename GridT::ConstAccessor
AccT;
449 CheckNormGrad(
const GridT& grid,
const ValueType& _min,
const ValueType& _max)
450 : acc(grid.getConstAccessor())
451 , invdx2(ValueType(1.0/math::
Pow2(grid.voxelSize()[0])))
455 if ( !grid.hasUniformVoxels() ) {
464 : acc(other.acc.tree())
465 , invdx2(other.invdx2)
466 , minVal2(other.minVal2)
467 , maxVal2(other.maxVal2)
472 inline bool operator()(
const ValueType& v)
const {
return v<minVal2 || v>maxVal2; }
476 inline bool operator()(
const TreeIterT&)
const {
return (*
this)(ValueType(0)); }
482 const Coord ijk = iter.getCoord();
489 std::ostringstream ss;
504 template<
typename GridT,
505 typename TreeIterT =
typename GridT::ValueOnCIter,
510 BOOST_STATIC_ASSERT(boost::is_floating_point<ValueType>::value);
513 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
516 CheckEikonal(
const GridT& grid,
const ValueType& _min,
const ValueType& _max)
517 : stencil(grid), minVal(_min), maxVal(_max)
519 if ( !grid.hasUniformVoxels() ) {
522 if (minVal > maxVal) {
528 : stencil(other.stencil.grid()), minVal(other.minVal), maxVal(other.maxVal)
533 inline bool operator()(
const ValueType& v)
const {
return v<minVal || v>maxVal; }
537 inline bool operator()(
const TreeIterT&)
const {
return (*
this)(ValueType(0)); }
543 stencil.moveTo(iter);
544 if (!stencil.zeroCrossing())
return false;
545 return (*
this)(stencil.normSqGrad());
551 std::ostringstream ss;
552 ss <<
"outside the range of NormGrad ["<<minVal<<
","<<maxVal<<
"]";
563 template<
typename GridT,
564 typename TreeIterT =
typename GridT::ValueOnCIter,
570 BOOST_STATIC_ASSERT(boost::is_floating_point<ElementType>::value);
573 ::template NodeConverter<typename GridT::TreeType::LeafNodeType>::Type
VoxelIterT;
574 typedef typename GridT::ConstAccessor
AccT;
578 const ValueType& _min,
579 const ValueType& _max)
580 : acc(grid.getConstAccessor())
581 , invdx(ValueType(1.0/grid.voxelSize()[0]))
585 if ( !grid.hasUniformVoxels() ) {
588 if (minVal > maxVal) {
593 inline bool operator()(
const ElementType& v)
const {
return v<minVal || v>maxVal; }
597 inline bool operator()(
const TreeIterT&)
const {
return (*
this)(ElementType(0)); }
603 const Coord ijk = iter.getCoord();
610 std::ostringstream ss;
611 ss <<
"outside the range of divergence ["<<minVal<<
","<<maxVal<<
"]";
623 template <
typename Gr
idT>
627 typedef typename GridT::template ValueConverter<bool>::Type
MaskType;
629 Diagnose(
const GridT& grid) : mGrid(&grid), mMask(new MaskType()), mCount(0)
631 mMask->setTransform(grid.transformPtr()->copy());
634 template <
typename CheckT>
635 std::string
check(
const CheckT& check,
636 bool updateMask =
false,
637 bool checkVoxels =
true,
638 bool checkTiles =
true,
639 bool checkBackground =
true)
641 typename MaskType::TreeType* mask = updateMask ? &(mMask->tree()) : NULL;
642 CheckValues<CheckT> cc(mask, mGrid, check);
643 std::ostringstream ss;
644 if (checkBackground) ss << cc.checkBackground();
645 if (checkTiles) ss << cc.checkTiles();
646 if (checkVoxels) ss << cc.checkVoxels();
652 typename MaskType::ConstPtr mask()
const {
return mMask; }
656 typename MaskType::Ptr
mask() {
return mMask; }
669 const GridT&
grid()
const {
return *mGrid; }
672 void clear() { mMask =
new MaskType(); mCount = 0; }
680 typename MaskType::Ptr mMask;
684 template <
typename CheckT>
687 typedef typename MaskType::TreeType MaskT;
688 typedef typename GridT::TreeType::LeafNodeType LeafT;
690 const bool mOwnsMask;
696 CheckValues(MaskT* mask,
const GridT* grid,
const CheckT& check)
704 CheckValues(CheckValues& other, tbb::split)
706 , mMask(other.mMask ?
new MaskT() : NULL)
708 , mCheck(other.mCheck)
712 ~CheckValues() {
if (mOwnsMask)
delete mMask; }
714 std::string checkBackground()
716 std::ostringstream ss;
717 if (mCheck(mGrid->background())) {
719 ss <<
"Background is " + mCheck.str() << std::endl;
724 std::string checkTiles()
726 std::ostringstream ss;
728 typename CheckT::TileIterT i(mGrid->tree());
729 for (i.setMaxDepth(GridT::TreeType::RootNodeType::LEVEL - 1); i; ++i) {
732 if (mMask) mMask->fill(i.getBoundingBox(),
true,
true);
735 if (
const Index64 m = mCount - n) {
736 ss << m <<
" tile" << (m==1 ?
" is " :
"s are ") + mCheck.str() << std::endl;
741 std::string checkVoxels()
743 std::ostringstream ss;
744 LeafManagerT leafs(mGrid->tree());
746 tbb::parallel_reduce(leafs.leafRange(), *
this);
747 if (
const Index64 m = mCount - n) {
748 ss << m <<
" voxel" << (m==1 ?
" is " :
"s are ") + mCheck.str() << std::endl;
753 void operator()(
const typename LeafManagerT::LeafRange& r)
755 typedef typename CheckT::VoxelIterT VoxelIterT;
757 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
758 typename MaskT::LeafNodeType* maskLeaf = NULL;
762 if (maskLeaf == NULL) maskLeaf = mMask->touchLeaf(j.getCoord());
763 maskLeaf->setValueOn(j.pos(),
true);
768 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
770 if (mCheck(j)) ++mCount;
775 void join(
const CheckValues& other)
778 mCount += other.mCount;
790 template<
class Gr
idType>
795 typedef typename GridType::template ValueConverter<bool>::Type
MaskType;
800 typename MaskType::ConstPtr mask()
const {
return mDiagnose.mask(); }
804 typename MaskType::Ptr
mask() {
return mDiagnose.mask(); }
817 const GridType&
grid()
const {
return mDiagnose.grid(); }
827 static const bool test = boost::is_floating_point<ValueType>::value;
828 return test ?
"" :
"Value type is not floating point\n";
836 const bool test = mDiagnose.grid().getGridClass() ==
GRID_LEVEL_SET;
837 return test ?
"" :
"Class type is not \"GRID_LEVEL_SET\"\n";
845 return mDiagnose.grid().hasUniformVoxels() ?
"" :
"Does not have uniform voxels\n";
854 const Real w = mDiagnose.grid().background() / mDiagnose.grid().voxelSize()[0];
856 std::ostringstream ss;
857 ss <<
"The background value ("<< mDiagnose.grid().background()<<
") is less than " 858 << halfWidth <<
" voxel units\n";
869 const bool test = mDiagnose.grid().tree().hasActiveTiles();
870 return test ?
"Has active tile values\n" :
"";
879 return mDiagnose.check(c, updateMask,
true,
true,
true);
887 const ValueType& background = mDiagnose.grid().background();
889 return mDiagnose.check(c, updateMask,
true,
false,
false);
898 const ValueType& background = mDiagnose.grid().background();
900 return mDiagnose.check(c, updateMask,
true,
true,
false);
907 std::string
checkEikonal(
bool updateMask =
false, ValueType minV = 0.5, ValueType maxV = 1.5)
910 return mDiagnose.check(c, updateMask,
true,
false,
false);
930 std::string
check(
size_t n=9,
bool updateMask =
false)
932 std::string str = this->checkValueType();
933 if (str.empty() && n>1) str = this->checkClassType();
934 if (str.empty() && n>2) str = this->checkTransform();
935 if (str.empty() && n>3) str = this->checkBackground();
936 if (str.empty() && n>4) str = this->checkTiles();
937 if (str.empty() && n>5) str = this->checkFinite(updateMask);
938 if (str.empty() && n>6) str = this->checkRange(updateMask);
939 if (str.empty() && n>7) str = this->checkInactiveValues(updateMask);
940 if (str.empty() && n>8) str = this->checkEikonal(updateMask);
953 template<
class Gr
idType>
958 return c.
check(n,
false);
966 template<
class Gr
idType>
971 typedef typename GridType::template ValueConverter<bool>::Type
MaskType;
976 typename MaskType::ConstPtr mask()
const {
return mDiagnose.mask(); }
980 typename MaskType::Ptr
mask() {
return mDiagnose.mask(); }
993 const GridType&
grid()
const {
return mDiagnose.grid(); }
1003 static const bool test = boost::is_floating_point<ValueType>::value;
1004 return test ?
"" :
"Value type is not floating point";
1013 return test ?
"" :
"Class type is not \"GRID_LEVEL_SET\"";
1022 std::ostringstream ss;
1023 ss <<
"The background value ("<< mDiagnose.grid().background()<<
") is not zero";
1035 return mDiagnose.check(c, updateMask,
true,
true,
true);
1044 return mDiagnose.check(c, updateMask,
true,
true,
true);
1054 return mDiagnose.check(c, updateMask,
true,
true,
false);
1069 std::string
check(
size_t n=6,
bool updateMask =
false)
1071 std::string str = this->checkValueType();
1072 if (str.empty() && n>1) str = this->checkClassType();
1073 if (str.empty() && n>2) str = this->checkBackground();
1074 if (str.empty() && n>3) str = this->checkFinite(updateMask);
1075 if (str.empty() && n>4) str = this->checkInactiveValues(updateMask);
1076 if (str.empty() && n>5) str = this->checkRange(updateMask);
1089 template<
class Gr
idType>
1094 return c.
check(n,
false);
1103 namespace diagnostics_internal {
1106 template<
typename TreeType>
1119 void getInactiveValues(SetType&)
const;
1122 inline void operator()(
const tbb::blocked_range<size_t>&);
1126 LeafArray& mLeafArray;
1127 SetType mInactiveValues;
1131 template<
typename TreeType>
1135 , mNumValues(numValues)
1139 template <
typename TreeType>
1143 : mLeafArray(rhs.mLeafArray)
1145 , mNumValues(rhs.mNumValues)
1149 template<
typename TreeType>
1153 tbb::parallel_reduce(mLeafArray.
getRange(), *
this);
1157 template<
typename TreeType>
1165 template<
typename TreeType>
1169 typename TreeType::LeafNodeType::ValueOffCIter iter;
1171 for (
size_t n = range.begin(); n < range.end() && !tbb::task::self().is_cancelled(); ++n) {
1172 for (iter = mLeafArray.
leaf(n).cbeginValueOff(); iter; ++iter) {
1173 mInactiveValues.insert(iter.getValue());
1176 if (mInactiveValues.size() > mNumValues) {
1177 tbb::task::self().cancel_group_execution();
1182 template<
typename TreeType>
1186 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1189 template<
typename TreeType>
1193 values.insert(mInactiveValues.begin(), mInactiveValues.end());
1200 template<
typename TreeType>
1220 SetType mInactiveValues;
1225 template<
typename TreeType>
1228 , mNumValues(numValues)
1232 template <
typename TreeType>
1237 , mNumValues(rhs.mNumValues)
1241 template<
typename TreeType>
1245 tbb::parallel_reduce(range, *
this);
1249 template<
typename TreeType>
1257 template<
typename TreeType>
1261 for (; range && !tbb::task::self().is_cancelled(); ++range) {
1262 typename TreeType::ValueOffCIter iter = range.
iterator();
1263 for (; iter; ++iter) {
1264 mInactiveValues.insert(iter.getValue());
1267 if (mInactiveValues.size() > mNumValues) {
1268 tbb::task::self().cancel_group_execution();
1273 template<
typename TreeType>
1277 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1280 template<
typename TreeType>
1284 values.insert(mInactiveValues.begin(), mInactiveValues.end());
1293 template<
class Gr
idType>
1296 std::vector<typename GridType::ValueType>& values,
size_t numValues)
1299 typedef typename GridType::TreeType TreeType;
1300 typedef typename GridType::ValueType
ValueType;
1301 typedef std::set<ValueType>
SetType;
1303 SetType uniqueValues;
1306 TreeType& tree =
const_cast<TreeType&
>(grid.tree());
1314 if (uniqueValues.size() <= numValues) {
1315 typename TreeType::ValueOffCIter iter(grid.tree());
1316 iter.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 1);
1326 values.reserve(uniqueValues.size());
1328 typename SetType::iterator it = uniqueValues.begin();
1329 for ( ; it != uniqueValues.end(); ++it) {
1330 values.push_back(*it);
1333 return values.size() <= numValues;
1340 #endif // OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
Definition: TreeIterator.h:1339
This is a special 19-point stencil that supports optimal fifth-order WENO upwinding, second-order central differencing, Laplacian, and zero-crossing test.
Definition: Stencils.h:1331
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:293
T ElementType
Definition: Types.h:148
Definition: Exceptions.h:88
Definition: TreeIterator.h:106
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:114
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:323
#define OPENVDB_VERSION_NAME
Definition: version.h:43
DScheme
Different discrete schemes used in the first derivatives.
Definition: FiniteDifference.h:59
const IterT & iterator() const
Return a reference to this range's iterator.
Definition: TreeIterator.h:1360
Definition: FiniteDifference.h:62
Definition: Exceptions.h:39
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:336
Divergence operator defined in index space using various first derivative schemes.
Definition: Operators.h:495
Type Pow2(Type x)
Return .
Definition: Math.h:514
Definition: FiniteDifference.h:194
double Real
Definition: Types.h:64
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:192
Tolerance for floating-point comparison.
Definition: Math.h:125
uint64_t Index64
Definition: Types.h:57
RangeType getRange(size_t grainsize=1) const
Return a tbb::blocked_range of leaf array indices.
Definition: LeafManager.h:347
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:709
Definition: Operators.h:253
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:212