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> 45 template <
typename ValueT,
46 typename CodecT = UnknownCodec,
47 typename FilterT = NullFilter,
48 typename PointDataTreeT>
49 std::pair<ValueT, ValueT>
51 const std::string& attribute,
52 const FilterT& filter = NullFilter());
70 template <
typename ValueT,
71 typename CodecT = UnknownCodec,
72 typename FilterT = NullFilter,
73 typename PointDataTreeT>
76 const std::string& attribute,
77 const FilterT& filter = NullFilter());
94 template <
typename ValueT,
95 typename CodecT = UnknownCodec,
96 typename FilterT = NullFilter,
97 typename PointDataTreeT>
100 const std::string& attribute,
101 const FilterT& filter = NullFilter());
124 template <
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);
166 template <
typename ValueT,
167 typename CodecT = UnknownCodec,
168 typename FilterT = NullFilter,
169 typename PointDataTreeT,
172 const std::string& attribute,
174 const FilterT& filter = NullFilter(),
175 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* averageTree =
nullptr);
206 template <
typename ValueT,
207 typename CodecT = UnknownCodec,
208 typename FilterT = NullFilter,
209 typename PointDataTreeT,
212 const std::string& attribute,
214 const FilterT& filter = NullFilter(),
215 typename PointDataTreeT::template ValueConverter<ResultTreeT>::Type* totalTree =
nullptr);
220 namespace statistics_internal
225 template <
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);
241 inline const ExtentT&
get()
const {
return mMinMax; }
248 template <
typename VecT,
bool MagResult = true>
250 :
public ScalarMinMax<typename ValueTraits<VecT>::ElementType>
257 inline void operator()(
const VecT& b) { this->BaseT::operator()(b.lengthSqr()); }
263 template <
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();
278 inline const ExtentT&
get()
const {
return mMinMax; }
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;
312 template <
typename VecT>
318 inline const ExtentT&
get()
const {
return mMinMax; }
333 template <
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)
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;
373 const size_t size = handle.
isUniform() ? 1 : handle.size();
374 ExtentOp op(handle.get(0));
375 for (
size_t i = 1; i < size; ++i) {
377 op(handle.get(
Index(i)));
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;
432 template <
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;
453 template <
typename ValueT,
456 typename PointDataTreeT,
457 typename std::enable_if<!ValueTraits<ValueT>::IsVec,
int>::type = 0>
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)
467 const bool s =
evalExtents<ValueT, CodecT, FilterT,
469 (points, attribute, ext, filter, minTree, maxTree);
470 if (s) min = ext.first, max = ext.second;
476 template <
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);
492 template <
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;
529 "PointDataTreeT in instantiation of evalAverage is not an openvdb Tree type");
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) {
544 size_t size = handle.
size();
545 if (size == 0)
continue;
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) {
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) && iter != values.cend()) ++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);
603 template <
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)
618 "PointDataTreeT in instantiation of accumulate is not an openvdb Tree type");
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) {
633 if (handle.size() == 0)
continue;
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) {
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) && iter != values.cend()) ++iter;
656 if (iter == values.cend())
return false;
658 total = **iter; ++iter;
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);
692 template <
typename ValueT,
695 typename PointDataTreeT>
696 std::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);
709 template <
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);
724 template <
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);
743 #endif // OPENVDB_POINTS_STATISTICS_HAS_BEEN_INCLUDED ScalarMinMax(const ValueT &init)
Definition: PointStatistics.h:229
void operator()(const ExtentT &b)
Definition: PointStatistics.h:291
bool isUniform() const
Definition: AttributeArray.h:2175
void operator()(const ExtentT &b)
Definition: PointStatistics.h:236
std::pair< VecT, VecT > ExtentT
Definition: PointStatistics.h:267
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
MagnitudeExtent(const VecT &init)
Definition: PointStatistics.h:255
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
ComponentExtent(const ExtentT &init)
Definition: PointStatistics.h:317
std::pair< ValueTraits< VecT >::ElementType, ValueTraits< VecT >::ElementType > ExtentT
Definition: PointStatistics.h:228
std::pair< VecT, VecT > ExtentT
Definition: PointStatistics.h:315
ExtentT mMinMax
Definition: PointStatistics.h:330
void operator()(const ValueT &b)
Definition: PointStatistics.h:231
typename T::ValueType ElementType
Definition: Types.h:263
bool evalAverage(const PointDataTreeT &points, const std::string &attribute, typename ConvertElementType< ValueT, double >::Type &average, const FilterT &filter=NullFilter(), typename PointDataTreeT::template ValueConverter< ResultTreeT >::Type *averageTree=nullptr)
Evaluates the average value of a point attribute and returns whether the value is valid...
Definition: PointStatistics.h:497
MagnitudeExtent(const ExtentT &init)
Definition: PointStatistics.h:273
ScalarMinMax(const ExtentT &init)
Definition: PointStatistics.h:230
typename ValueTraits< VecT >::ElementType ElementT
Definition: PointStatistics.h:266
Scalar extent op to evaluate the min/max values of a single integral or floating point attribute type...
Definition: PointStatistics.h:226
void operator()(const VecT &b)
Definition: PointStatistics.h:279
MagnitudeExtent(const ExtentT &init)
Definition: PointStatistics.h:256
Vector component-wise op to evaluate the min/max of vector components and return the result as a vect...
Definition: PointStatistics.h:313
typename ScalarMinMax< ElementT >::ExtentT ExtentT
Definition: PointStatistics.h:253
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:287
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
SubT Type
Definition: Types.h:281
ExtentT mMinMax
Definition: PointStatistics.h:242
Definition: IndexIterator.h:43
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
Index32 Index
Definition: Types.h:54
MagnitudeExtent(const VecT &init)
Definition: PointStatistics.h:268
bool evalExtents(const PointDataTreeT &points, const std::string &attribute, ValueT &min, ValueT &max, const FilterT &filter, typename PointDataTreeT::template ValueConverter< ValueT >::Type *minTree, typename PointDataTreeT::template ValueConverter< ValueT >::Type *maxTree)
Definition: PointStatistics.h:437
Index size() const
Definition: AttributeArray.h:833
Vector squared magnitude op to evaluate the min/max of a vector attribute and return the result as a ...
Definition: PointStatistics.h:249
void operator()(const ExtentT &b)
Definition: PointStatistics.h:324
void operator()(const ExtentT &b)
Definition: PointStatistics.h:258
Definition: AttributeArray.h:810
std::pair< ElementT, ElementT > mLengths
Definition: PointStatistics.h:305
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
bool accumulate(const PointDataTreeT &points, const std::string &attribute, typename PromoteType< ValueT >::Highest &total, const FilterT &filter=NullFilter(), typename PointDataTreeT::template ValueConverter< ResultTreeT >::Type *totalTree=nullptr)
Evaluates the total value of a point attribute and returns whether the value is valid. Optionally constructs localised total value trees.
Definition: PointStatistics.h:608
bool evalMinMax(const PointDataTreeT &points, const std::string &attribute, ValueT &min, ValueT &max, const FilterT &filter=NullFilter(), typename PointDataTreeT::template ValueConverter< ValueT >::Type *minTree=nullptr, typename PointDataTreeT::template ValueConverter< ValueT >::Type *maxTree=nullptr)
Evaluates the minimum and maximum values of a point attribute and returns whether the values are vali...
Definition: PointStatistics.h:480
void operator()(const VecT &b)
Definition: PointStatistics.h:319
void operator()(const VecT &b)
Definition: PointStatistics.h:257
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:508
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:318
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
ComponentExtent(const VecT &init)
Definition: PointStatistics.h:316
Vec2< T > maxComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise maximum of the two vectors.
Definition: Vec2.h:517
typename ValueTraits< VecT >::ElementType ElementT
Definition: PointStatistics.h:252
ExtentT mMinMax
Definition: PointStatistics.h:306
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202