11 #ifndef OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
12 #define OPENVDB_TOOLS_DIAGNOSTICS_HAS_BEEN_INCLUDED
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
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); }
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); }
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); }
224 template <
typename GridT,
225 typename TreeIterT =
typename GridT::ValueOffCIter>
231 typename TreeIterT::ValueIterT> ::template NodeConverter<
232 typename GridT::TreeType::LeafNodeType>
::Type;
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;
293 OPENVDB_THROW(ValueError,
"CheckRange: Invalid range (min > max)");
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,
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() ) {
447 OPENVDB_THROW(ValueError,
"CheckNormGrad: The transform must have uniform scale");
450 OPENVDB_THROW(ValueError,
"CheckNormGrad: Invalid range (min > max)");
473 const Coord ijk = iter.getCoord();
480 std::ostringstream ss;
495 template<
typename GridT,
496 typename TreeIterT =
typename GridT::ValueOnCIter,
502 "openvdb::tools::CheckEikonal requires a scalar, floating-point grid");
505 typename TreeIterT::ValueIterT> ::template NodeConverter<
506 typename GridT::TreeType::LeafNodeType>
::Type;
512 if ( !grid.hasUniformVoxels() ) {
513 OPENVDB_THROW(ValueError,
"CheckEikonal: The transform must have uniform scale");
516 OPENVDB_THROW(ValueError,
"CheckEikonal: Invalid range (min > max)");
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,
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())
580 if ( !grid.hasUniformVoxels() ) {
581 OPENVDB_THROW(ValueError,
"CheckDivergence: The transform must have uniform scale");
584 OPENVDB_THROW(ValueError,
"CheckDivergence: Invalid range (min > max)");
598 const Coord ijk = iter.getCoord();
605 std::ostringstream ss;
606 ss <<
"outside the range of divergence ["<<
minVal<<
","<<
maxVal<<
"]";
618 template <
typename Gr
idT>
626 mMask->setTransform(grid.transformPtr()->copy());
629 template <
typename CheckT>
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; }
711 std::ostringstream ss;
712 if (mCheck(mGrid->background())) {
714 ss <<
"Background is " + mCheck.str() << std::endl;
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;
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>
798 typename MaskType::ConstPtr
mask()
const {
return mDiagnose.
mask(); }
799 typename MaskType::Ptr
mask() {
return mDiagnose.
mask(); }
823 return test ?
"" :
"Value type is not floating point\n";
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);
884 return mDiagnose.
check(c, updateMask,
true,
false,
false);
895 return mDiagnose.
check(c, updateMask,
true,
true,
false);
905 return mDiagnose.
check(
c, updateMask,
true,
false,
false);
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);
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>
974 typename MaskType::ConstPtr
mask()
const {
return mDiagnose.
mask(); }
975 typename MaskType::Ptr
mask() {
return mDiagnose.
mask(); }
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);
1069 if (str.empty() && n>3) str = this->
checkFinite(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
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>
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
1200 using IterRange = tree::IteratorRange<typename TreeType::ValueOffCIter>;
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>
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;
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
cvex test(vector P=0;int unbound=3;export float s=0;export vector Cf=0;)
GridType
List of types that are currently supported by NanoVDB.
typename T::ValueType ElementType
GLsizei const GLchar *const * string
GLsizei const GLfloat * value
static Accessor::ValueType result(const Accessor &grid, const Coord &ijk)
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
GLboolean GLboolean GLboolean GLboolean a
#define OPENVDB_USE_VERSION_NAMESPACE
Tolerance for floating-point comparison.
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
DScheme
Different discrete schemes used in the first derivatives.
Coord Abs(const Coord &xyz)
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
float Sqrt(float x)
Return the square root of a floating-point value.
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
static Accessor::ValueType::value_type result(const Accessor &grid, const Coord &ijk)
GLenum GLsizei GLsizei GLint * values
This is a special 19-point stencil that supports optimal fifth-order WENO upwinding, second-order central differencing, Laplacian, and zero-crossing test.
GLubyte GLubyte GLubyte GLubyte w
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
GLint GLfloat GLint stencil
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
#define OPENVDB_THROW(exception, message)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.