15 #ifndef NANOVDB_GRIDSTATS_H_HAS_BEEN_INCLUDED 16 #define NANOVDB_GRIDSTATS_H_HAS_BEEN_INCLUDED 18 #include "../NanoVDB.h" 22 #ifdef NANOVDB_USE_TBB 23 #include <tbb/parallel_reduce.h> 45 template<
typename BuildT>
50 template<typename ValueT, int Rank = TensorTraits<ValueT>::Rank>
54 template<
typename ValueT>
63 : mMin(
std::numeric_limits<ValueT>::
max())
64 , mMax(
std::numeric_limits<ValueT>::lowest())
101 this->
min(other.mMin);
102 this->
max(other.mMax);
105 const ValueT&
min()
const {
return mMin; }
106 const ValueT&
max()
const {
return mMax; }
107 operator bool()
const {
return mMin <= mMax; }
111 static constexpr
size_t size() {
return 0; }
115 template<
typename VecT>
119 using Real =
typename VecT::ValueType;
131 : scalar(v.lengthSqr())
135 Pair& operator=(
const Pair&) =
default;
136 bool operator<(
const Pair& rhs)
const {
return scalar < rhs.scalar; }
153 , mMax(
std::numeric_limits<
Real>::lowest())
187 if (other.mMin < mMin) {
190 if (mMax < other.mMax) {
195 const VecT&
min()
const {
return mMin.vector; }
196 const VecT&
max()
const {
return mMax.vector; }
197 operator bool()
const {
return !(mMax < mMin); }
201 static constexpr
size_t size() {
return 0; }
206 template<typename ValueT, int Rank = TensorTraits<ValueT>::Rank>
217 template<
typename ValueT>
247 const double delta = double(val) - mAvg;
248 mAvg += delta / double(mSize);
249 mAux += delta * (double(val) - mAvg);
255 const double denom = 1.0 / double(mSize + n);
256 const double delta = double(val) - mAvg;
257 mAvg += denom * delta * double(n);
258 mAux += denom * delta * delta * double(mSize) * double(n);
267 if (other.mSize > 0) {
268 const double denom = 1.0 / double(mSize + other.mSize);
269 const double delta = other.mAvg - mAvg;
270 mAvg += denom * delta * double(other.mSize);
271 mAux += other.mAux + denom * delta * delta * double(mSize) * double(other.mSize);
273 mSize += other.mSize;
282 size_t size()
const {
return mSize; }
286 double avg()
const {
return mAvg; }
287 double mean()
const {
return mAvg; }
294 double var()
const {
return mSize < 2 ? 0.0 : mAux / double(mSize); }
301 double std()
const {
return sqrt(this->var()); }
314 template<
typename ValueT>
335 typename BaseT::Pair tmp(val);
338 const double delta = tmp.scalar - mAvg;
339 mAvg += delta / double(mSize);
340 mAux += delta * (tmp.scalar - mAvg);
346 typename BaseT::Pair tmp(val);
347 const double denom = 1.0 / double(mSize + n);
348 const double delta = tmp.scalar - mAvg;
349 mAvg += denom * delta * double(n);
350 mAux += denom * delta * delta * double(mSize) * double(n);
359 if (other.mSize > 0) {
360 const double denom = 1.0 / double(mSize + other.mSize);
361 const double delta = other.mAvg - mAvg;
362 mAvg += denom * delta * double(other.mSize);
363 mAux += other.mAux + denom * delta * delta * double(mSize) * double(other.mSize);
365 mSize += other.mSize;
374 size_t size()
const {
return mSize; }
378 double avg()
const {
return mAvg; }
379 double mean()
const {
return mAvg; }
386 double var()
const {
return mSize < 2 ? 0.0 : mAux / double(mSize); }
393 double std()
const {
return sqrt(this->var()); }
399 template<
typename ValueT>
408 static constexpr
size_t size() {
return 0; }
417 template<
typename Gr
idT,
typename StatsT = Stats<
typename Gr
idT::ValueType>>
421 using TreeT =
typename GridT::TreeType;
422 using ValueT =
typename TreeT::ValueType;
423 using BuildT =
typename TreeT::BuildType;
424 using Node0 =
typename TreeT::Node0;
425 using Node1 =
typename TreeT::Node1;
426 using Node2 =
typename TreeT::Node2;
427 using RootT =
typename TreeT::Node3;
429 static constexpr
bool DO_STATS = StatsT::hasMinMax() || StatsT::hasAverage() || StatsT::hasStdDeviation();
433 void process( GridT& );
434 void process( TreeT& );
435 void process( RootT& );
438 template<
typename NodeT>
441 template<
typename DataT,
int Rank>
443 template<
typename DataT,
int Rank>
445 template<
typename DataT>
448 template<
typename T,
typename FlagT>
450 setFlag(
const T&,
const T&, FlagT& flag)
const { flag &= ~FlagT(1); }
452 template<
typename T,
typename FlagT>
454 setFlag(
const T&
min,
const T&
max, FlagT& flag)
const;
459 void operator()(GridT& grid, ValueT delta = ValueT(0));
463 template<
typename Gr
idT,
typename StatsT>
476 bbox[0].minComponent(other.
bbox[0]);
477 bbox[1].maxComponent(other.
bbox[1]);
484 template<
typename Gr
idT,
typename StatsT>
488 this->process( grid );
493 template<
typename Gr
idT,
typename StatsT>
494 template<
typename DataT,
int Rank>
498 data->setMin(e.min());
499 data->setMax(e.max());
502 template<
typename Gr
idT,
typename StatsT>
503 template<
typename DataT,
int Rank>
507 data->setMin(s.min());
508 data->setMax(s.max());
509 data->setAvg(s.avg());
510 data->setDev(s.std());
515 template<
typename Gr
idT,
typename StatsT>
516 template<
typename T,
typename FlagT>
521 if (mDelta > 0 && (min > mDelta || max < -mDelta)) {
530 template<
typename Gr
idT,
typename StatsT>
533 this->process( grid.tree() );
536 auto& data = *grid.data();
537 const auto& indexBBox = grid.tree().root().bbox();
538 if (indexBBox.empty()) {
540 data.setBBoxOn(
false);
550 const Coord min = indexBBox[0];
553 auto& worldBBox = data.mWorldBBox;
554 const auto& map = grid.map();
555 worldBBox[0] = worldBBox[1] = map.applyMap(
Vec3d(min[0], min[1], min[2]));
556 worldBBox.expand(map.applyMap(
Vec3d(min[0], min[1], max[2])));
557 worldBBox.expand(map.applyMap(
Vec3d(min[0], max[1], min[2])));
558 worldBBox.expand(map.applyMap(
Vec3d(max[0], min[1], min[2])));
559 worldBBox.expand(map.applyMap(
Vec3d(max[0], max[1], min[2])));
560 worldBBox.expand(map.applyMap(
Vec3d(max[0], min[1], max[2])));
561 worldBBox.expand(map.applyMap(
Vec3d(min[0], max[1], max[2])));
562 worldBBox.expand(map.applyMap(
Vec3d(max[0], max[1], max[2])));
563 data.setBBoxOn(
true);
567 data.setMinMaxOn(StatsT::hasMinMax());
568 data.setAverageOn(StatsT::hasAverage());
569 data.setStdDeviationOn(StatsT::hasStdDeviation());
574 template<
typename Gr
idT,
typename StatsT>
577 this->process( tree.root() );
582 template<
typename Gr
idT,
typename StatsT>
585 using ChildT = Node2;
586 auto &data = *root.data();
587 if (data.mTableSize == 0) {
588 data.mMinimum = data.mMaximum = data.mBackground;
589 data.mAverage = data.mStdDevi = 0;
594 for (uint32_t i = 0; i < data.mTableSize; ++i) {
595 auto* tile = data.tile(i);
596 if (tile->isChild()) {
597 total.
add( this->process( *data.getChild(tile) ) );
598 }
else if (tile->state) {
600 const Coord ijk = tile->origin();
601 total.
bbox[0].minComponent(ijk);
602 total.
bbox[1].maxComponent(ijk +
Coord(ChildT::DIM - 1));
604 total.
stats.add(tile->value, ChildT::NUM_VALUES);
608 this->setStats(&data, total.
stats);
609 if (total.
bbox.empty()) {
610 std::cerr <<
"\nWarning: input tree only contained inactive root tiles!" 611 <<
"\nWhile not strictly an error it's rather suspicious!\n";
614 data.mBBox = total.
bbox;
620 template<
typename Gr
idT,
typename StatsT>
621 template<
typename NodeT>
626 using ChildT =
typename NodeT::ChildNodeType;
629 auto* data = node.data();
632 if (
const auto tileCount = data->mValueMask.countOn()) {
634 for (
auto it = data->mValueMask.beginOn(); it; ++it) {
636 total.
stats.add( data->mTable[*it].value, ChildT::NUM_VALUES );
638 const Coord ijk = node.offsetToGlobalCoord(*it);
639 total.
bbox[0].minComponent(ijk);
640 total.
bbox[1].maxComponent(ijk +
Coord(int32_t(ChildT::DIM) - 1));
645 if (
const size_t childCount = data->mChildMask.countOn()) {
646 #ifndef NANOVDB_USE_TBB 647 for (
auto it = data->mChildMask.beginOn(); it; ++it) {
648 total.
add( this->process( *data->getChild(*it) ) );
651 std::unique_ptr<ChildT*[]> childNodes(
new ChildT*[childCount]);
652 ChildT **ptr = childNodes.get();
653 for (
auto it = data->mChildMask.beginOn(); it; ++it) {
654 *ptr++ = data->getChild( *it );
656 using RangeT = tbb::blocked_range<size_t>;
657 total.
add( tbb::parallel_reduce(RangeT(0, childCount),
NodeStats(),
659 for(
size_t i=r.begin(); i!=r.end(); ++i){
660 local.
add( this->process( *childNodes[i] ) );
668 data->mBBox = total.
bbox;
669 if (total.
bbox.empty()) {
670 data->mFlags &= ~uint32_t(1);
671 data->mFlags &= ~uint32_t(2);
673 data->mFlags |= uint32_t(2);
675 this->setStats(data, total.
stats);
676 this->setFlag(data->mMinimum, data->mMaximum, data->mFlags);
684 template<
typename Gr
idT,
typename StatsT>
688 static_assert(Node0::SIZE == 512u,
"Invalid size of leaf nodes");
690 auto *data = leaf.data();
691 if (
auto activeCount = data->mValueMask.countOn()) {
692 data->mFlags |= uint8_t(2);
695 local.
bbox[0] = local.
bbox[1] = data->mBBoxMin;
696 local.
bbox[1] +=
Coord(data->mBBoxDif[0], data->mBBoxDif[1], data->mBBoxDif[2]);
698 for (
auto it = data->mValueMask.beginOn(); it; ++it) {
699 local.
stats.add(data->getValue(*it));
701 this->setStats(data, local.
stats);
702 this->setFlag(data->getMin(), data->getMax(), data->mFlags);
705 data->mFlags &= ~uint8_t(2);
712 template<
typename BuildT>
716 using ValueT =
typename GridT::ValueType;
729 throw std::runtime_error(
"gridStats: Unsupported statistics mode.");
735 #endif // NANOVDB_GRIDSTATS_H_HAS_BEEN_INCLUDED static constexpr bool hasMinMax()
Definition: GridStats.h:409
double RealT
Definition: GridStats.h:222
double variance() const
Return the population variance.
Definition: GridStats.h:295
Extrema & add(const Extrema &other)
Definition: GridStats.h:185
static constexpr bool hasAverage()
Definition: GridStats.h:279
NoopStats()
Definition: GridStats.h:403
VecT ValueType
Definition: GridStats.h:150
double mAvg
Definition: GridStats.h:224
Template specialization of Extrema on scalar value types, i.e. rank = 0.
Definition: GridStats.h:55
double variance() const
Return the population variance.
Definition: GridStats.h:387
static constexpr bool hasAverage()
Definition: GridStats.h:371
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition: NanoVDB.h:2307
double var() const
Return the population variance.
Definition: GridStats.h:386
double mAvg
Definition: GridStats.h:321
static constexpr bool hasStdDeviation()
Definition: GridStats.h:411
StatsT stats
Definition: GridStats.h:466
const ValueT & min() const
Definition: GridStats.h:105
double var() const
Return the population variance.
Definition: GridStats.h:294
static constexpr bool hasMinMax()
Definition: GridStats.h:198
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
static constexpr bool hasStdDeviation()
Definition: GridStats.h:200
static constexpr bool hasStdDeviation()
Definition: GridStats.h:280
CoordBBox bbox
Definition: GridStats.h:468
static constexpr bool hasStdDeviation()
Definition: GridStats.h:372
Stats & add(const ValueT &val, uint64_t n)
Add n samples with constant value val.
Definition: GridStats.h:344
NodeStats()
Definition: GridStats.h:470
static constexpr size_t size()
Definition: GridStats.h:408
double avg() const
Return the arithmetic mean, i.e. average, value.
Definition: GridStats.h:378
Stats & add(const ValueT &val, uint64_t n)
Add n samples with constant value val.
Definition: GridStats.h:253
ValueT mMin
Definition: GridStats.h:58
double avg() const
Return the arithmetic mean, i.e. average, value.
Definition: GridStats.h:286
const VecT & max() const
Definition: GridStats.h:196
NoopStats & add(const NoopStats &)
Definition: GridStats.h:407
static constexpr bool hasAverage()
Definition: GridStats.h:199
Stats & add(const Stats &other)
Add the samples from the other Stats instance.
Definition: GridStats.h:265
Extrema & add(const VecT &v, uint64_t)
Definition: GridStats.h:184
Stats & add(const Stats &other)
Add the samples from the other Stats instance.
Definition: GridStats.h:357
Pair(const VecT &v)
Definition: GridStats.h:130
Definition: NanoVDB.h:184
Extrema()
Definition: GridStats.h:62
static constexpr bool hasStdDeviation()
Definition: GridStats.h:110
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
Stats()
Definition: GridStats.h:325
Extrema & add(const ValueT &v)
Definition: GridStats.h:92
static constexpr bool hasMinMax()
Definition: GridStats.h:370
Stats()
Definition: GridStats.h:228
Custom Range class that is compatible with the tbb::blocked_range classes.
ValueT ValueType
Definition: GridStats.h:402
Extrema()
Definition: GridStats.h:151
Extrema(const VecT &a, const VecT &b)
Definition: GridStats.h:161
NodeStats & add(const NodeStats &other)
Definition: GridStats.h:472
ValueT ValueType
Definition: GridStats.h:324
static constexpr bool hasMinMax()
Definition: GridStats.h:278
bool operator<(const Pair &rhs) const
Definition: GridStats.h:136
NoopStats(const ValueT &)
Definition: GridStats.h:404
Definition: NanoVDB.h:1524
static constexpr bool hasAverage()
Definition: GridStats.h:109
Extrema(const VecT &v)
Definition: GridStats.h:156
size_t mSize
Definition: GridStats.h:223
Definition: GridStats.h:51
Extrema & min(const ValueT &v)
Definition: GridStats.h:78
size_t mSize
Definition: GridStats.h:320
ValueT value
Definition: GridBuilder.h:1287
void gridStats(NanoGrid< BuildT > &grid, StatsMode mode=StatsMode::Default)
Re-computes the min/max, stats and bbox information for an existing NanoVDB Grid. ...
Definition: GridStats.h:713
NoopStats & add(const ValueT &, uint64_t)
Definition: GridStats.h:406
Definition: GridStats.h:464
double std() const
Return the standard deviation (=Sqrt(variance)) as defined from the (biased) population variance...
Definition: GridStats.h:301
Allows for the construction of NanoVDB grids without any dependecy.
Definition: GridStats.h:418
double std() const
Return the standard deviation (=Sqrt(variance)) as defined from the (biased) population variance...
Definition: GridStats.h:393
const VecT & min() const
Definition: GridStats.h:195
Extrema & add(const Extrema &other)
Definition: GridStats.h:99
void operator()(GridT &grid, ValueT delta=ValueT(0))
Definition: GridStats.h:485
Extrema & min(const VecT &v)
Definition: GridStats.h:167
Real scalar
Definition: GridStats.h:122
Stats & add(const ValueT &val)
Add a single sample.
Definition: GridStats.h:333
double mean() const
Return the arithmetic mean, i.e. average, value.
Definition: GridStats.h:287
Stats & add(const ValueT &val)
Add a single sample.
Definition: GridStats.h:243
ValueT ValueType
Definition: GridStats.h:61
double mean() const
Return the arithmetic mean, i.e. average, value.
Definition: GridStats.h:379
StatsMode
Grid flags which indicate what extra information is present in the grid buffer.
Definition: GridStats.h:32
No-op Stats class.
Definition: GridStats.h:400
Pair(Real s)
Definition: GridStats.h:125
double stdDev() const
Return the standard deviation (=Sqrt(variance)) as defined from the (biased) population variance...
Definition: GridStats.h:302
Extrema & max(const VecT &v)
Definition: GridStats.h:175
typename VecT::ValueType Real
Definition: GridStats.h:119
static constexpr bool hasAverage()
Definition: GridStats.h:410
const ValueT & max() const
Definition: GridStats.h:106
double stdDev() const
Return the standard deviation (=Sqrt(variance)) as defined from the (biased) population variance...
Definition: GridStats.h:394
static constexpr size_t size()
Definition: GridStats.h:111
Definition: GridStats.h:207
static constexpr size_t size()
Definition: GridStats.h:201
Extrema(const ValueT &v)
Definition: GridStats.h:67
Extrema & add(const ValueT &v, uint64_t)
Definition: GridStats.h:98
VecT vector
Definition: GridStats.h:123
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition: NanoVDB.h:859
Extrema(const ValueT &a, const ValueT &b)
Definition: GridStats.h:72
Extrema & add(const Pair &p)
Definition: GridStats.h:138
Extrema & add(const VecT &v)
Definition: GridStats.h:183
static constexpr bool hasMinMax()
Definition: GridStats.h:108
size_t size() const
Definition: GridStats.h:282
C++11 implementation of std::is_same.
Definition: NanoVDB.h:326
Stats(const ValueT &val)
Definition: GridStats.h:235
Extrema & max(const ValueT &v)
Definition: GridStats.h:85
size_t size() const
Definition: GridStats.h:374
NoopStats & add(const ValueT &)
Definition: GridStats.h:405
double RealT
Definition: GridStats.h:319