11 #ifndef OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED 12 #define OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED 20 #include <openvdb/thread/Threading.h> 23 #include <tbb/blocked_range.h> 24 #include <tbb/parallel_reduce.h> 30 #include <type_traits> 65 template<
class Gr
idType>
89 template<
class Gr
idType>
101 template<
class Gr
idType>
104 std::vector<typename GridType::ValueType>& values,
size_t numValues);
110 template<
typename Gr
idT,
typename TreeIterT =
typename Gr
idT::ValueOnCIter>
116 typename TreeIterT::NodeT,
typename TreeIterT::ValueIterT>::template
117 NodeConverter<typename GridT::TreeType::LeafNodeType>::Type;
127 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
130 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
135 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
141 std::string
str()
const {
return "NaN"; }
148 template <
typename GridT,
149 typename TreeIterT =
typename GridT::ValueOnCIter>
155 typename TreeIterT::ValueIterT> ::template NodeConverter<
156 typename GridT::TreeType::LeafNodeType>::Type;
166 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
169 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
174 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
180 std::string
str()
const {
return "infinite"; }
186 template <
typename GridT,
187 typename TreeIterT =
typename GridT::ValueOnCIter>
193 typename TreeIterT::ValueIterT> ::template NodeConverter<
194 typename GridT::TreeType::LeafNodeType>::Type;
204 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
206 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
211 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
217 std::string
str()
const {
return "not finite"; }
224 template <
typename GridT,
225 typename TreeIterT =
typename GridT::ValueOffCIter>
231 typename TreeIterT::ValueIterT> ::template NodeConverter<
232 typename GridT::TreeType::LeafNodeType>::Type;
237 : absVal(math::
Abs(a)), tolVal(math::
Abs(t))
250 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
253 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
258 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
266 std::ostringstream ss;
267 ss <<
"not equal to +/-"<<absVal<<
" with a tolerance of "<<tolVal;
277 template <
typename GridT,
278 bool MinInclusive =
true,
279 bool MaxInclusive =
true,
280 typename TreeIterT =
typename GridT::ValueOnCIter>
286 typename TreeIterT::ValueIterT> ::template NodeConverter<
287 typename GridT::TreeType::LeafNodeType>::Type;
292 if (minVal > maxVal) {
300 return (MinInclusive ? v<minVal : v<=minVal) ||
301 (MaxInclusive ? v>maxVal : v>=maxVal);
306 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
308 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
313 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
321 std::ostringstream ss;
322 ss <<
"outside the value range " << (MinInclusive ?
"[" :
"]")
323 << minVal <<
"," << maxVal << (MaxInclusive ?
"]" :
"[");
333 template <
typename GridT,
334 typename TreeIterT =
typename GridT::ValueOnCIter>
340 typename TreeIterT::ValueIterT> ::template NodeConverter<
341 typename GridT::TreeType::LeafNodeType>::Type;
351 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
353 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
358 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
366 std::ostringstream ss;
367 ss <<
"smaller than "<<minVal;
377 template <
typename GridT,
378 typename TreeIterT =
typename GridT::ValueOnCIter>
384 typename TreeIterT::ValueIterT> ::template NodeConverter<
385 typename GridT::TreeType::LeafNodeType>::Type;
395 inline typename std::enable_if<VecTraits<T>::IsVec,
bool>::type
397 for (
int i=0; i<VecTraits<T>::Size; ++i)
if ((*
this)(v[i]))
return true;
402 bool operator()(
const TreeIterT &iter)
const {
return (*
this)(*iter); }
410 std::ostringstream ss;
411 ss <<
"larger than "<<maxVal;
425 template<
typename GridT,
426 typename TreeIterT =
typename GridT::ValueOnCIter,
431 static_assert(std::is_floating_point<ValueType>::value,
432 "openvdb::tools::CheckNormGrad requires a scalar, floating-point grid");
435 typename TreeIterT::ValueIterT> ::template NodeConverter<
436 typename GridT::TreeType::LeafNodeType>::Type;
437 using AccT =
typename GridT::ConstAccessor;
441 : acc(grid.getConstAccessor())
446 if ( !grid.hasUniformVoxels() ) {
455 : acc(other.acc.tree())
456 , invdx2(other.invdx2)
457 , minVal2(other.minVal2)
458 , maxVal2(other.maxVal2)
473 const Coord ijk = iter.getCoord();
480 std::ostringstream ss;
495 template<
typename GridT,
496 typename TreeIterT =
typename GridT::ValueOnCIter,
501 static_assert(std::is_floating_point<ValueType>::value,
502 "openvdb::tools::CheckEikonal requires a scalar, floating-point grid");
505 typename TreeIterT::ValueIterT> ::template NodeConverter<
506 typename GridT::TreeType::LeafNodeType>::Type;
510 : stencil(grid), minVal(_min), maxVal(_max)
512 if ( !grid.hasUniformVoxels() ) {
515 if (minVal > maxVal) {
521 : stencil(other.stencil.grid()), minVal(other.minVal), maxVal(other.maxVal)
536 stencil.moveTo(iter);
537 if (!stencil.zeroCrossing())
return false;
538 return (*
this)(stencil.normSqGrad());
544 std::ostringstream ss;
545 ss <<
"outside the range of NormGrad ["<<minVal<<
","<<maxVal<<
"]";
556 template<
typename GridT,
557 typename TreeIterT =
typename GridT::ValueOnCIter,
563 static_assert(std::is_floating_point<ElementType>::value,
564 "openvdb::tools::CheckDivergence requires a floating-point vector grid");
567 typename TreeIterT::ValueIterT>::template NodeConverter<
568 typename GridT::TreeType::LeafNodeType>::Type;
569 using AccT =
typename GridT::ConstAccessor;
575 : acc(grid.getConstAccessor())
576 , invdx(
ValueType(1.0/grid.voxelSize()[0]))
580 if ( !grid.hasUniformVoxels() ) {
583 if (minVal > maxVal) {
598 const Coord ijk = iter.getCoord();
605 std::ostringstream ss;
606 ss <<
"outside the range of divergence ["<<minVal<<
","<<maxVal<<
"]";
618 template <
typename Gr
idT>
622 using MaskType =
typename GridT::template ValueConverter<bool>::Type;
626 mMask->setTransform(grid.transformPtr()->copy());
629 template <
typename CheckT>
630 std::string
check(
const CheckT& check,
631 bool updateMask =
false,
632 bool checkVoxels =
true,
633 bool checkTiles =
true,
634 bool checkBackground =
true)
636 typename MaskType::TreeType* mask = updateMask ? &(mMask->tree()) :
nullptr;
637 CheckValues<CheckT> cc(mask, mGrid, check);
638 std::ostringstream ss;
639 if (checkBackground) ss << cc.checkBackground();
640 if (checkTiles) ss << cc.checkTiles();
641 if (checkVoxels) ss << cc.checkVoxels();
650 typename MaskType::ConstPtr
mask()
const {
return mMask; }
651 typename MaskType::Ptr
mask() {
return mMask; }
664 const GridT&
grid()
const {
return *mGrid; }
675 typename MaskType::Ptr mMask;
679 template <
typename CheckT>
682 using MaskT =
typename MaskType::TreeType;
683 using LeafT =
typename GridT::TreeType::LeafNodeType;
685 const bool mOwnsMask;
691 CheckValues(MaskT* mask,
const GridT* grid,
const CheckT& check)
701 , mMask(other.mMask ?
new MaskT() :
nullptr)
703 , mCheck(other.mCheck)
707 ~CheckValues() {
if (mOwnsMask)
delete mMask; }
709 std::string checkBackground()
711 std::ostringstream ss;
712 if (mCheck(mGrid->background())) {
714 ss <<
"Background is " + mCheck.str() << std::endl;
719 std::string checkTiles()
721 std::ostringstream ss;
723 typename CheckT::TileIterT i(mGrid->tree());
724 for (i.setMaxDepth(GridT::TreeType::RootNodeType::LEVEL - 1); i; ++i) {
727 if (mMask) mMask->fill(i.getBoundingBox(),
true,
true);
730 if (
const Index64 m = mCount - n) {
731 ss << m <<
" tile" << (m==1 ?
" is " :
"s are ") + mCheck.str() << std::endl;
736 std::string checkVoxels()
738 std::ostringstream ss;
739 LeafManagerT leafs(mGrid->tree());
741 tbb::parallel_reduce(leafs.leafRange(), *
this);
742 if (
const Index64 m = mCount - n) {
743 ss << m <<
" voxel" << (m==1 ?
" is " :
"s are ") + mCheck.str() << std::endl;
748 void operator()(
const typename LeafManagerT::LeafRange& r)
750 using VoxelIterT =
typename CheckT::VoxelIterT;
752 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
753 typename MaskT::LeafNodeType* maskLeaf =
nullptr;
757 if (maskLeaf ==
nullptr) maskLeaf = mMask->touchLeaf(j.getCoord());
758 maskLeaf->setValueOn(j.pos(),
true);
763 for (
typename LeafManagerT::LeafRange::Iterator i=r.begin(); i; ++i) {
765 if (mCheck(j)) ++mCount;
770 void join(
const CheckValues& other)
773 mCount += other.mCount;
785 template<
class Gr
idType>
790 using MaskType =
typename GridType::template ValueConverter<bool>::Type;
798 typename MaskType::ConstPtr
mask()
const {
return mDiagnose.mask(); }
799 typename MaskType::Ptr
mask() {
return mDiagnose.mask(); }
822 static const bool test = std::is_floating_point<ValueType>::value;
823 return test ?
"" :
"Value type is not floating point\n";
831 const bool test = mDiagnose.grid().getGridClass() ==
GRID_LEVEL_SET;
832 return test ?
"" :
"Class type is not \"GRID_LEVEL_SET\"\n";
840 return mDiagnose.grid().hasUniformVoxels() ?
"" :
"Does not have uniform voxels\n";
849 const Real w = mDiagnose.grid().background() / mDiagnose.grid().voxelSize()[0];
851 std::ostringstream ss;
852 ss <<
"The background value ("<< mDiagnose.grid().background()<<
") is less than " 853 << halfWidth <<
" voxel units\n";
864 const bool test = mDiagnose.grid().tree().hasActiveTiles();
865 return test ?
"Has active tile values\n" :
"";
874 return mDiagnose.check(c, updateMask,
true,
true,
true);
882 const ValueType& background = mDiagnose.grid().background();
884 return mDiagnose.check(c, updateMask,
true,
false,
false);
893 const ValueType& background = mDiagnose.grid().background();
895 return mDiagnose.check(c, updateMask,
true,
true,
false);
905 return mDiagnose.check(c, updateMask,
true,
false,
false);
925 std::string
check(
size_t n=9,
bool updateMask =
false)
927 std::string str = this->checkValueType();
928 if (str.empty() && n>1) str = this->checkClassType();
929 if (str.empty() && n>2) str = this->checkTransform();
930 if (str.empty() && n>3) str = this->checkBackground();
931 if (str.empty() && n>4) str = this->checkTiles();
932 if (str.empty() && n>5) str = this->checkFinite(updateMask);
933 if (str.empty() && n>6) str = this->checkRange(updateMask);
934 if (str.empty() && n>7) str = this->checkInactiveValues(updateMask);
935 if (str.empty() && n>8) str = this->checkEikonal(updateMask);
948 template<
class Gr
idType>
953 return c.
check(n,
false);
961 template<
class Gr
idType>
966 using MaskType =
typename GridType::template ValueConverter<bool>::Type;
974 typename MaskType::ConstPtr
mask()
const {
return mDiagnose.mask(); }
975 typename MaskType::Ptr
mask() {
return mDiagnose.mask(); }
998 static const bool test = std::is_floating_point<ValueType>::value;
999 return test ?
"" :
"Value type is not floating point";
1008 return test ?
"" :
"Class type is not \"GRID_LEVEL_SET\"";
1017 std::ostringstream ss;
1018 ss <<
"The background value ("<< mDiagnose.grid().background()<<
") is not zero";
1030 return mDiagnose.check(c, updateMask,
true,
true,
true);
1039 return mDiagnose.check(c, updateMask,
true,
true,
true);
1049 return mDiagnose.check(c, updateMask,
true,
true,
false);
1064 std::string
check(
size_t n=6,
bool updateMask =
false)
1066 std::string str = this->checkValueType();
1067 if (str.empty() && n>1) str = this->checkClassType();
1068 if (str.empty() && n>2) str = this->checkBackground();
1069 if (str.empty() && n>3) str = this->checkFinite(updateMask);
1070 if (str.empty() && n>4) str = this->checkInactiveValues(updateMask);
1071 if (str.empty() && n>5) str = this->checkRange(updateMask);
1084 template<
class Gr
idType>
1089 return c.
check(n,
false);
1099 namespace diagnostics_internal {
1102 template<
typename TreeType>
1103 class InactiveVoxelValues
1107 using ValueType =
typename TreeType::ValueType;
1108 using SetType = std::set<ValueType>;
1110 InactiveVoxelValues(LeafArray&,
size_t numValues);
1115 void getInactiveValues(SetType&)
const;
1117 inline InactiveVoxelValues(
const InactiveVoxelValues<TreeType>&,
tbb::split);
1118 inline void operator()(
const tbb::blocked_range<size_t>&);
1119 inline void join(
const InactiveVoxelValues<TreeType>&);
1122 LeafArray& mLeafArray;
1123 SetType mInactiveValues;
1127 template<
typename TreeType>
1128 InactiveVoxelValues<TreeType>::InactiveVoxelValues(LeafArray& leafs,
size_t numValues)
1131 , mNumValues(numValues)
1135 template <
typename TreeType>
1137 InactiveVoxelValues<TreeType>::InactiveVoxelValues(
1138 const InactiveVoxelValues<TreeType>& rhs,
tbb::split)
1139 : mLeafArray(rhs.mLeafArray)
1141 , mNumValues(rhs.mNumValues)
1145 template<
typename TreeType>
1147 InactiveVoxelValues<TreeType>::runParallel()
1149 tbb::parallel_reduce(mLeafArray.getRange(), *
this);
1153 template<
typename TreeType>
1155 InactiveVoxelValues<TreeType>::runSerial()
1157 (*this)(mLeafArray.getRange());
1161 template<
typename TreeType>
1163 InactiveVoxelValues<TreeType>::operator()(
const tbb::blocked_range<size_t>& range)
1165 typename TreeType::LeafNodeType::ValueOffCIter iter;
1167 for (
size_t n = range.begin(); n < range.end() && !thread::isGroupExecutionCancelled(); ++n) {
1168 for (iter = mLeafArray.leaf(n).cbeginValueOff(); iter; ++iter) {
1169 mInactiveValues.insert(iter.getValue());
1172 if (mInactiveValues.size() > mNumValues) {
1173 thread::cancelGroupExecution();
1178 template<
typename TreeType>
1180 InactiveVoxelValues<TreeType>::join(
const InactiveVoxelValues<TreeType>& rhs)
1182 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1185 template<
typename TreeType>
1187 InactiveVoxelValues<TreeType>::getInactiveValues(SetType& values)
const 1189 values.insert(mInactiveValues.begin(), mInactiveValues.end());
1196 template<
typename TreeType>
1197 class InactiveTileValues
1201 using ValueType =
typename TreeType::ValueType;
1202 using SetType = std::set<ValueType>;
1204 InactiveTileValues(
size_t numValues);
1206 void runParallel(IterRange&);
1207 void runSerial(IterRange&);
1209 void getInactiveValues(SetType&)
const;
1211 inline InactiveTileValues(
const InactiveTileValues<TreeType>&,
tbb::split);
1212 inline void operator()(
const IterRange&);
1213 inline void join(
const InactiveTileValues<TreeType>&);
1216 SetType mInactiveValues;
1221 template<
typename TreeType>
1222 InactiveTileValues<TreeType>::InactiveTileValues(
size_t numValues)
1224 , mNumValues(numValues)
1228 template <
typename TreeType>
1230 InactiveTileValues<TreeType>::InactiveTileValues(
1231 const InactiveTileValues<TreeType>& rhs,
tbb::split)
1233 , mNumValues(rhs.mNumValues)
1237 template<
typename TreeType>
1239 InactiveTileValues<TreeType>::runParallel(IterRange& range)
1241 tbb::parallel_reduce(range, *
this);
1245 template<
typename TreeType>
1247 InactiveTileValues<TreeType>::runSerial(IterRange& range)
1253 template<
typename TreeType>
1255 InactiveTileValues<TreeType>::operator()(
const IterRange& range)
1257 for (IterRange it(range); it.test() && !thread::isGroupExecutionCancelled(); ++it) {
1258 typename TreeType::ValueOffCIter iter = it.iterator();
1259 for (; iter; ++iter) {
1260 mInactiveValues.insert(iter.getValue());
1263 if (mInactiveValues.size() > mNumValues) {
1264 thread::cancelGroupExecution();
1269 template<
typename TreeType>
1271 InactiveTileValues<TreeType>::join(
const InactiveTileValues<TreeType>& rhs)
1273 mInactiveValues.insert(rhs.mInactiveValues.begin(), rhs.mInactiveValues.end());
1276 template<
typename TreeType>
1278 InactiveTileValues<TreeType>::getInactiveValues(SetType& values)
const 1280 values.insert(mInactiveValues.begin(), mInactiveValues.end());
1290 template<
class Gr
idType>
1293 std::vector<typename GridType::ValueType>& values,
size_t numValues)
1295 using TreeType =
typename GridType::TreeType;
1296 using ValueType =
typename GridType::ValueType;
1297 using SetType = std::set<ValueType>;
1299 SetType uniqueValues;
1302 TreeType& tree =
const_cast<TreeType&
>(grid.tree());
1304 diagnostics_internal::InactiveVoxelValues<TreeType> voxelOp(leafs, numValues);
1305 voxelOp.runParallel();
1306 voxelOp.getInactiveValues(uniqueValues);
1310 if (uniqueValues.size() <= numValues) {
1311 typename TreeType::ValueOffCIter iter(grid.tree());
1312 iter.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 1);
1313 diagnostics_internal::InactiveTileValues<TreeType> tileOp(numValues);
1316 tileOp.runParallel(range);
1318 tileOp.getInactiveValues(uniqueValues);
1322 values.reserve(uniqueValues.size());
1324 typename SetType::iterator it = uniqueValues.begin();
1325 for ( ; it != uniqueValues.end(); ++it) {
1326 values.push_back(*it);
1329 return values.size() <= numValues;
1338 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 1340 #ifdef OPENVDB_INSTANTIATE_DIAGNOSTICS 1344 #define _FUNCTION(TreeT) \ 1345 std::string checkLevelSet(const Grid<TreeT>&, size_t) 1349 #define _FUNCTION(TreeT) \ 1350 std::string checkFogVolume(const Grid<TreeT>&, size_t) 1354 #define _FUNCTION(TreeT) \ 1355 bool uniqueInactiveValues(const Grid<TreeT>&, std::vector<TreeT::ValueType>&, size_t) 1359 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION 1366 #endif // OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
Type Pow2(Type x)
Return x2.
Definition: Math.h:548
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:1365
Tolerance for floating-point comparison.
Definition: Math.h:148
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
Definition: version.h.in:165
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Coord Abs(const Coord &xyz)
Definition: Coord.h:518
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Definition: Operators.h:230
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:164
uint64_t Index64
Definition: Types.h:53
typename T::ValueType ElementType
Definition: Types.h:247
Definition: TreeIterator.h:1303
Definition: Exceptions.h:65
Divergence operator defined in index space using various first derivative schemes.
Definition: Operators.h:472
void split(ContainerT &out, const std::string &in, const char delim)
Definition: Name.h:43
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:461
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:349
Definition: Exceptions.h:13
Definition: FiniteDifference.h:34
double Real
Definition: Types.h:60
Definition: TreeIterator.h:60
DScheme
Different discrete schemes used in the first derivatives.
Definition: FiniteDifference.h:31
GridType
List of types that are currently supported by NanoVDB.
Definition: NanoVDB.h:219
Definition: FiniteDifference.h:166
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition: version.h.in:162
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:761
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218