14#ifndef OPENVDB_POINTS_STATISTICS_HAS_BEEN_INCLUDED
15#define OPENVDB_POINTS_STATISTICS_HAS_BEEN_INCLUDED
24#include <tbb/parallel_reduce.h>
25#include <tbb/parallel_for.h>
45template <
typename ValueT,
46 typename CodecT = UnknownCodec,
47 typename FilterT = NullFilter,
48 typename PointDataTreeT>
49std::pair<ValueT, ValueT>
51 const std::string& attribute,
52 const FilterT& filter = NullFilter());
70template <
typename ValueT,
71 typename CodecT = UnknownCodec,
72 typename FilterT = NullFilter,
73 typename PointDataTreeT>
74typename ConvertElementType<ValueT, double>::Type
76 const std::string& attribute,
77 const FilterT& filter = NullFilter());
94template <
typename ValueT,
95 typename CodecT = UnknownCodec,
96 typename FilterT = NullFilter,
97 typename PointDataTreeT>
98typename PromoteType<ValueT>::Highest
100 const std::string& attribute,
101 const FilterT& filter = NullFilter());
124template <
typename ValueT,
125 typename CodecT = UnknownCodec,
126 typename FilterT = NullFilter,
127 typename PointDataTreeT>
129 const std::string& attribute,
132 const FilterT& filter = NullFilter(),
133 typename PointDataTreeT::template ValueConverter<ValueT>::Type* minTree =
nullptr,
134 typename PointDataTreeT::template ValueConverter<ValueT>::Type* maxTree =
nullptr);
166template <
typename ValueT,
167 typename CodecT = UnknownCodec,
168 typename FilterT = NullFilter,
169 typename PointDataTreeT,
170 typename ResultTreeT =
typename ConvertElementType<ValueT, double>::Type>
172 const std::string& attribute,
173 typename ConvertElementType<ValueT, double>::Type& average,
174 const FilterT& filter = NullFilter(),
175 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* averageTree =
nullptr);
206template <
typename ValueT,
207 typename CodecT = UnknownCodec,
208 typename FilterT = NullFilter,
209 typename PointDataTreeT,
210 typename ResultTreeT =
typename PromoteType<ValueT>::Highest>
212 const std::string& attribute,
213 typename PromoteType<ValueT>::Highest& total,
214 const FilterT& filter = NullFilter(),
215 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* totalTree =
nullptr);
220namespace statistics_internal
225template <
typename ValueT>
233 mMinMax.first = std::min(mMinMax.first, b);
234 mMinMax.second = std::max(mMinMax.second, b);
238 mMinMax.first = std::min(mMinMax.first, b.first);
239 mMinMax.second = std::max(mMinMax.second, b.second);
248template <
typename VecT,
bool MagResult = true>
250 :
public ScalarMinMax<typename ValueTraits<VecT>::ElementType>
257 inline void operator()(
const VecT& b) { this->BaseT::operator()(b.lengthSqr()); }
263template <
typename VecT>
269 : mLengths(), mMinMax(init, init) {
270 mLengths.first = init.lengthSqr();
271 mLengths.second = mLengths.first;
274 : mLengths(), mMinMax(init) {
275 mLengths.first = init.first.lengthSqr();
276 mLengths.second = init.second.lengthSqr();
282 if (l < mLengths.first) {
286 else if (l > mLengths.second) {
294 if (l < mLengths.first) {
296 mMinMax.first = b.first;
298 l = b.second.lengthSqr();
299 if (l > mLengths.second) {
301 mMinMax.second = b.second;
312template <
typename VecT>
321 mMinMax.first = math::minComponent(mMinMax.first, b);
322 mMinMax.second = math::maxComponent(mMinMax.second, b);
326 mMinMax.first = math::minComponent(mMinMax.first, b.first);
327 mMinMax.second = math::maxComponent(mMinMax.second, b.second);
333template <
typename ValueT,
337 typename PointDataTreeT>
339 const std::string& attribute,
340 typename ExtentOp::ExtentT& ext,
341 const FilterT& filter,
342 typename PointDataTreeT::template ValueConverter
343 <
typename ExtentOp::ExtentT::first_type>::Type*
const minTree =
nullptr,
344 typename PointDataTreeT::template ValueConverter
345 <
typename ExtentOp::ExtentT::second_type>::Type*
const maxTree =
nullptr)
347 static_assert(std::is_base_of<TreeBase, PointDataTreeT>::value,
348 "PointDataTreeT in instantiation of evalExtents is not an openvdb Tree type");
351 typename ExtentOp::ExtentT ext;
356 if (manager.
leafCount() == 0)
return false;
357 const size_t idx = manager.
leaf(0).attributeSet().find(attribute);
358 if (idx == AttributeSet::INVALID_POS)
return false;
361 std::vector<std::unique_ptr<typename ExtentOp::ExtentT>> values;
362 if (minTree || maxTree) values.resize(manager.
leafCount());
364 const ResultType result = tbb::parallel_reduce(manager.
leafRange(),
366 [idx, &filter, &values]
367 (
const auto& range, ResultType in) -> ResultType
369 for (
auto leaf = range.begin(); leaf; ++leaf) {
371 if (handle.
size() == 0)
continue;
372 if (filter.state() == index::ALL) {
374 ExtentOp op(handle.
get(0));
375 for (
size_t i = 1; i < size; ++i) {
376 assert(i <
size_t(std::numeric_limits<Index>::max()));
379 if (!values.empty()) {
380 values[leaf.pos()].reset(
new typename ExtentOp::ExtentT(op.get()));
382 if (in.data) op(in.ext);
387 auto iter = leaf->beginIndexOn(filter);
389 ExtentOp op(handle.
get(*iter));
391 for (; iter; ++iter) op(handle.
get(*iter));
392 if (!values.empty()) {
393 values[leaf.pos()].reset(
new typename ExtentOp::ExtentT(op.get()));
395 if (in.data) op(in.ext);
403 [](
const ResultType& a,
const ResultType& b) -> ResultType {
404 if (!b.data)
return a;
405 if (!a.data)
return b;
406 ExtentOp op(a.ext); op(b.ext);
417 if (minTree || maxTree) {
418 manager.
foreach([minTree, maxTree, &values]
419 (
const auto& leaf,
const size_t idx) {
420 const auto& v = values[idx];
421 if (v ==
nullptr)
return;
422 const Coord& origin = leaf.origin();
423 if (minTree) minTree->addTile(1, origin, v->first,
true);
424 if (maxTree) maxTree->addTile(1, origin, v->second,
true);
428 if (result.data) ext = result.ext;
432template <
typename ValueT,
435 typename PointDataTreeT,
436 typename std::enable_if<ValueTraits<ValueT>::IsVec,
int>::type = 0>
438 const std::string& attribute,
441 const FilterT& filter,
442 typename PointDataTreeT::template ValueConverter<ValueT>::Type* minTree,
443 typename PointDataTreeT::template ValueConverter<ValueT>::Type* maxTree)
446 const bool s =
evalExtents<ValueT, CodecT, FilterT,
448 (points, attribute, ext, filter, minTree, maxTree);
449 if (s) min = ext.first, max = ext.second;
453template <
typename ValueT,
456 typename PointDataTreeT,
457 typename std::enable_if<!ValueTraits<ValueT>::IsVec,
int>::type = 0>
458bool evalExtents(
const PointDataTreeT& points,
459 const std::string& attribute,
462 const FilterT& filter,
463 typename PointDataTreeT::template ValueConverter<ValueT>::Type* minTree,
464 typename PointDataTreeT::template ValueConverter<ValueT>::Type* maxTree)
466 typename ScalarMinMax<ValueT>::ExtentT ext;
467 const bool s = evalExtents<ValueT, CodecT, FilterT,
468 ScalarMinMax<ValueT>, PointDataTreeT>
469 (points, attribute, ext, filter, minTree, maxTree);
470 if (s) min = ext.first, max = ext.second;
476template <
typename ValueT,
479 typename PointDataTreeT>
481 const std::string& attribute,
484 const FilterT& filter,
485 typename PointDataTreeT::template ValueConverter<ValueT>::Type* minTree,
486 typename PointDataTreeT::template ValueConverter<ValueT>::Type* maxTree)
488 return statistics_internal::evalExtents<ValueT, CodecT, FilterT, PointDataTreeT>
489 (points, attribute, min, max, filter, minTree, maxTree);
492template <
typename ValueT,
495 typename PointDataTreeT,
496 typename ResultTreeT>
498 const std::string& attribute,
500 const FilterT& filter,
501 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* averageTree)
507 Sample(
const ResultT& _avg,
size_t _size) : avg(_avg), size(_size) {}
509 void add(
const ResultT& val)
512 const ResultT delta = val - avg;
513 avg = avg + (delta /
static_cast<double>(size));
516 void add(
const Sample& other)
518 assert(other.size > 0);
519 const double denom = 1.0 /
static_cast<double>(size + other.size);
520 const ResultT delta = other.avg - avg;
521 avg = avg + (denom * delta *
static_cast<double>(other.size));
525 ResultT avg;
size_t size;
528 static_assert(std::is_base_of<TreeBase, PointDataTreeT>::value,
529 "PointDataTreeT in instantiation of evalAverage is not an openvdb Tree type");
530 static_assert(std::is_constructible<ResultT, ValueT>::value,
531 "Target value in points::evalAverage is not constructible from the source value type.");
534 if (manager.
leafCount() == 0)
return false;
535 const size_t idx = manager.
leaf(0).attributeSet().find(attribute);
536 if (idx == AttributeSet::INVALID_POS)
return false;
538 std::vector<std::unique_ptr<Sample>> values;
541 [idx, &filter, &values] (
const auto& range) {
542 for (auto leaf = range.begin(); leaf; ++leaf) {
543 AttributeHandle<ValueT, CodecT> handle(leaf->constAttributeArray(idx));
544 size_t size = handle.size();
545 if (size == 0) continue;
546 if (filter.state() == index::ALL) {
547 std::unique_ptr<Sample> S(new Sample(ResultT(handle.get(0)), 1));
548 if (handle.isUniform()) {
549 S->avg = S->avg / static_cast<double>(size);
553 for (size_t i = 1; i < size; ++i) {
554 assert(i < size_t(std::numeric_limits<Index>::max()));
555 S->add(ResultT(handle.get(Index(i))));
558 values[leaf.pos()] = std::move(S);
561 auto iter = leaf->beginIndexOn(filter);
563 std::unique_ptr<Sample> S(new Sample(ResultT(handle.get(*iter)), 1));
565 for (; iter; ++iter, ++size) {
566 S->add(ResultT(handle.get(*iter)));
568 values[leaf.pos()] = std::move(S);
573 auto iter = values.cbegin();
574 while (iter != values.cend() && !(*iter)) ++iter;
575 if (iter == values.cend())
return false;
581 for (; iter != values.cend(); ++iter) {
582 if (*iter) S.add(**iter);
591 manager.foreach([averageTree, &values]
592 (
const auto& leaf,
const size_t idx) {
593 const auto& S = values[idx];
594 if (S ==
nullptr)
return;
595 const Coord& origin = leaf.origin();
596 averageTree->addTile(1, origin, S->avg,
true);
603template <
typename ValueT,
606 typename PointDataTreeT,
607 typename ResultTreeT>
609 const std::string& attribute,
611 const FilterT& filter,
612 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* totalTree)
617 static_assert(std::is_base_of<TreeBase, PointDataTreeT>::value,
618 "PointDataTreeT in instantiation of accumulate is not an openvdb Tree type");
619 static_assert(std::is_constructible<ResultT, ValueT>::value,
620 "Target value in points::accumulate is not constructible from the source value type.");
623 if (manager.
leafCount() == 0)
return false;
624 const size_t idx = manager.
leaf(0).attributeSet().find(attribute);
625 if (idx == AttributeSet::INVALID_POS)
return false;
627 std::vector<std::unique_ptr<ResultT>> values;
630 [idx, &filter, &values](
const auto& range) {
631 for (auto leaf = range.begin(); leaf; ++leaf) {
632 AttributeHandle<ValueT, CodecT> handle(leaf->constAttributeArray(idx));
633 if (handle.size() == 0) continue;
634 if (filter.state() == index::ALL) {
635 const size_t size = handle.isUniform() ? 1 : handle.size();
636 auto total = ResultT(handle.get(0));
637 for (size_t i = 1; i < size; ++i) {
638 assert(i < size_t(std::numeric_limits<Index>::max()));
639 total += ResultT(handle.get(Index(i)));
641 values[leaf.pos()].reset(new ResultT(total));
644 auto iter = leaf->beginIndexOn(filter);
646 auto total = ResultT(handle.get(*iter));
648 for (; iter; ++iter) total += ResultT(handle.get(*iter));
649 values[leaf.pos()].reset(new ResultT(total));
654 auto iter = values.cbegin();
655 while (iter != values.cend() && !(*iter)) ++iter;
656 if (iter == values.cend())
return false;
658 total = **iter; ++iter;
660 if (std::is_integral<ElementT>::value) {
661 using RangeT = tbb::blocked_range<const std::unique_ptr<ResultT>*>;
663 total = tbb::parallel_reduce(RangeT(&(*iter), (&values.back())+1, 32), total,
664 [](
const RangeT& range, ResultT p) -> ResultT {
665 for (const auto& r : range) if (r) p += *r;
667 }, std::plus<ResultT>());
670 for (; iter != values.cend(); ++iter) {
671 if (*iter) total += (**iter);
680 manager.foreach([totalTree, &values]
681 (
const auto& leaf,
const size_t idx) {
682 const auto& v = values[idx];
683 if (v ==
nullptr)
return;
684 const Coord& origin = leaf.origin();
685 totalTree->addTile(1, origin, *v,
true);
692template <
typename ValueT,
695 typename PointDataTreeT>
696std::pair<ValueT, ValueT>
698 const std::string& attribute,
699 const FilterT& filter)
701 std::pair<ValueT, ValueT> results {
702 zeroVal<ValueT>(), zeroVal<ValueT>()
704 evalMinMax<ValueT, CodecT, FilterT, PointDataTreeT>
705 (points, attribute, results.first, results.second, filter);
709template <
typename ValueT,
712 typename PointDataTreeT>
715 const std::string& attribute,
716 const FilterT& filter)
719 ConvertedT result = zeroVal<ConvertedT>();
720 evalAverage<ValueT, CodecT, FilterT, PointDataTreeT>(points, attribute, result, filter);
724template <
typename ValueT,
727 typename PointDataTreeT>
730 const std::string& attribute,
731 const FilterT& filter)
734 PromotedT result = zeroVal<PromotedT>();
735 accumulate<ValueT, CodecT, FilterT, PointDataTreeT>(points, attribute, result, filter);
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:25
Definition AttributeArray.h:836
Index size() const
Definition AttributeArray.h:858
ValueType get(Index n, Index m=0) const
Definition AttributeArray.h:2193
bool isUniform() const
Definition AttributeArray.h:2219
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:85
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition LeafManager.h:318
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition LeafManager.h:483
size_t leafCount() const
Return the number of leaf nodes.
Definition LeafManager.h:287
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition LeafManager.h:345
bool evalExtents(const PointDataTreeT &points, const std::string &attribute, typename ExtentOp::ExtentT &ext, const FilterT &filter, typename PointDataTreeT::template ValueConverter< typename ExtentOp::ExtentT::first_type >::Type *const minTree=nullptr, typename PointDataTreeT::template ValueConverter< typename ExtentOp::ExtentT::second_type >::Type *const maxTree=nullptr)
Definition PointStatistics.h:338
PromoteType< ValueT >::Highest accumulate(const PointDataTreeT &points, const std::string &attribute, const FilterT &filter=NullFilter())
Evaluates the total value of a point attribute.
Definition PointStatistics.h:729
std::pair< ValueT, ValueT > evalMinMax(const PointDataTreeT &points, const std::string &attribute, const FilterT &filter=NullFilter())
Evaluates the minimum and maximum values of a point attribute.
Definition PointStatistics.h:697
ConvertElementType< ValueT, double >::Type evalAverage(const PointDataTreeT &points, const std::string &attribute, const FilterT &filter=NullFilter())
Evaluates the average value of a point attribute.
Definition PointStatistics.h:714
Index32 Index
Definition Types.h:54
Definition Exceptions.h:13
SubT Type
Definition Types.h:281
typename T::ValueType ElementType
Definition Types.h:263
Vector component-wise op to evaluate the min/max of vector components and return the result as a vect...
Definition PointStatistics.h:314
void operator()(const ExtentT &b)
Definition PointStatistics.h:324
ExtentT mMinMax
Definition PointStatistics.h:330
ComponentExtent(const ExtentT &init)
Definition PointStatistics.h:317
ComponentExtent(const VecT &init)
Definition PointStatistics.h:316
void operator()(const VecT &b)
Definition PointStatistics.h:319
const ExtentT & get() const
Definition PointStatistics.h:318
std::pair< VecT, VecT > ExtentT
Definition PointStatistics.h:315
MagnitudeExtent(const ExtentT &init)
Definition PointStatistics.h:273
void operator()(const ExtentT &b)
Definition PointStatistics.h:291
typename ValueTraits< VecT >::ElementType ElementT
Definition PointStatistics.h:266
MagnitudeExtent(const VecT &init)
Definition PointStatistics.h:268
std::pair< ElementT, ElementT > mLengths
Definition PointStatistics.h:305
ExtentT mMinMax
Definition PointStatistics.h:306
void operator()(const VecT &b)
Definition PointStatistics.h:279
const ExtentT & get() const
Definition PointStatistics.h:278
std::pair< VecT, VecT > ExtentT
Definition PointStatistics.h:267
Vector squared magnitude op to evaluate the min/max of a vector attribute and return the result as a ...
Definition PointStatistics.h:251
MagnitudeExtent(const ExtentT &init)
Definition PointStatistics.h:256
typename ScalarMinMax< ElementT >::ExtentT ExtentT
Definition PointStatistics.h:253
void operator()(const ExtentT &b)
Definition PointStatistics.h:258
typename ValueTraits< VecT >::ElementType ElementT
Definition PointStatistics.h:252
MagnitudeExtent(const VecT &init)
Definition PointStatistics.h:255
void operator()(const VecT &b)
Definition PointStatistics.h:257
Scalar extent op to evaluate the min/max values of a single integral or floating point attribute type...
Definition PointStatistics.h:227
ScalarMinMax(const ExtentT &init)
Definition PointStatistics.h:230
std::pair< ValueT, ValueT > ExtentT
Definition PointStatistics.h:228
void operator()(const ExtentT &b)
Definition PointStatistics.h:236
void operator()(const ValueT &b)
Definition PointStatistics.h:231
ScalarMinMax(const ValueT &init)
Definition PointStatistics.h:229
ExtentT mMinMax
Definition PointStatistics.h:242
const ExtentT & get() const
Definition PointStatistics.h:241
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212