10 #ifndef OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
22 #include <tbb/parallel_reduce.h>
39 const AttributeSet::Descriptor& descriptor);
45 template <
typename Po
intDataTreeT>
53 template <
typename Po
intDataTreeT>
55 const std::vector<Name>& groups);
63 template <
typename Po
intDataTreeT>
64 inline void dropGroup( PointDataTreeT& tree,
66 const bool compact =
true);
72 template <
typename Po
intDataTreeT>
74 const std::vector<Name>& groups);
79 template <
typename Po
intDataTreeT>
85 template <
typename Po
intDataTreeT>
97 template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT>
98 inline void setGroup( PointDataTreeT& tree,
99 const PointIndexTreeT& indexTree,
100 const std::vector<short>& membership,
102 const bool remove =
false);
109 template <
typename Po
intDataTreeT>
110 inline void setGroup( PointDataTreeT& tree,
112 const bool member =
true);
119 template <
typename Po
intDataTreeT,
typename FilterT>
122 const FilterT& filter);
128 namespace point_group_internal {
132 template<
typename Po
intDataTreeType>
141 : mTargetIndex(targetIndex)
142 , mSourceIndex(sourceIndex) { }
144 void operator()(
const typename LeafManagerT::LeafRange& range)
const {
146 for (
auto leaf = range.begin(); leaf; ++leaf) {
148 GroupHandle sourceGroup = leaf->groupHandle(mSourceIndex);
151 for (
auto iter = leaf->beginIndexAll(); iter; ++iter) {
152 const bool groupOn = sourceGroup.
get(*iter);
153 targetGroup.
set(*iter, groupOn);
166 template <
typename Po
intDataTreeT,
bool Member>
172 SetGroupOp(
const AttributeSet::Descriptor::GroupIndex& index)
175 void operator()(
const typename LeafManagerT::LeafRange& range)
const
177 for (
auto leaf = range.begin(); leaf; ++leaf) {
195 template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT,
bool Remove>
208 : mIndexTree(indexTree)
209 , mMembership(membership)
212 void operator()(
const typename LeafManagerT::LeafRange& range)
const
214 for (
auto leaf = range.begin(); leaf; ++leaf) {
220 if (!pointIndexLeaf)
continue;
230 const IndexArray& indices = pointIndexLeaf->indices();
232 for (
const Index64 i: indices) {
234 group.
set(
static_cast<Index>(index), mMembership[i]);
235 }
else if (mMembership[i] ==
short(1)) {
236 group.
set(
static_cast<Index>(index),
short(1));
255 template <
typename Po
intDataTreeT,
typename FilterT,
typename IterT =
typename Po
intDataTreeT::LeafNodeType::ValueAllCIter>
260 using LeafNodeT =
typename PointDataTreeT::LeafNodeType;
265 , mFilter(filter) { }
267 void operator()(
const typename LeafManagerT::LeafRange& range)
const
269 for (
auto leaf = range.begin(); leaf; ++leaf) {
275 auto iter = leaf->template beginIndex<IterT, FilterT>(mFilter);
277 for (; iter; ++iter) {
278 group.
set(*iter,
true);
304 const AttributeSet::Descriptor& descriptor)
306 for (
auto it = groups.begin(); it != groups.end();) {
307 if (!descriptor.hasGroup(*it)) it = groups.erase(it);
316 template <
typename Po
intDataTreeT>
323 auto iter = tree.cbeginLeaf();
327 const AttributeSet& attributeSet = iter->attributeSet();
332 if (descriptor->hasGroup(group))
return;
334 const bool hasUnusedGroup = descriptor->unusedGroups() > 0;
338 if (!hasUnusedGroup) {
342 const Name groupName = descriptor->uniqueName(
"__group");
344 descriptor = descriptor->duplicateAppend(groupName, GroupAttributeArray::attributeType());
345 const size_t pos = descriptor->find(groupName);
351 [&](
typename PointDataTreeT::LeafNodeType& leaf,
size_t ) {
352 auto expected = leaf.attributeSet().descriptorPtr();
353 leaf.appendAttribute(*expected, descriptor, pos);
366 assert(descriptor->unusedGroups() > 0);
370 const size_t offset = descriptor->unusedGroupOffset();
374 descriptor->setGroup(group, offset);
380 if (hasUnusedGroup)
setGroup(tree, group,
false);
387 template <
typename Po
intDataTreeT>
389 const std::vector<Name>& groups)
394 for (
const Name& name : groups) {
403 template <
typename Po
intDataTreeT>
404 inline void dropGroup(PointDataTreeT& tree,
const Name& group,
const bool compact)
406 using Descriptor = AttributeSet::Descriptor;
412 auto iter = tree.cbeginLeaf();
416 const AttributeSet& attributeSet = iter->attributeSet();
425 descriptor->dropGroup(group);
436 template <
typename Po
intDataTreeT>
438 const std::vector<Name>& groups)
440 for (
const Name& name : groups) {
453 template <
typename Po
intDataTreeT>
456 using Descriptor = AttributeSet::Descriptor;
458 auto iter = tree.cbeginLeaf();
462 const AttributeSet& attributeSet = iter->attributeSet();
469 descriptor->clearGroups();
484 template <
typename Po
intDataTreeT>
487 using Descriptor = AttributeSet::Descriptor;
488 using GroupIndex = Descriptor::GroupIndex;
489 using LeafManagerT =
typename tree::template LeafManager<PointDataTreeT>;
493 auto iter = tree.cbeginLeaf();
497 const AttributeSet& attributeSet = iter->attributeSet();
501 if (!attributeSet.
descriptor().canCompactGroups())
return;
513 size_t sourceOffset, targetOffset;
515 while (descriptor->requiresGroupMove(sourceName, sourceOffset, targetOffset)) {
517 const GroupIndex sourceIndex = attributeSet.
groupIndex(sourceOffset);
518 const GroupIndex targetIndex = attributeSet.
groupIndex(targetOffset);
520 CopyGroupOp<PointDataTreeT> copy(targetIndex, sourceIndex);
521 LeafManagerT leafManager(tree);
522 tbb::parallel_for(leafManager.leafRange(), copy);
524 descriptor->setGroup(sourceName, targetOffset);
531 const size_t totalAttributesToDrop = descriptor->unusedGroups() / descriptor->groupBits();
533 assert(totalAttributesToDrop <= indices.size());
535 const std::vector<size_t> indicesToDrop(indices.end() - totalAttributesToDrop,
545 template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT>
547 const PointIndexTreeT& indexTree,
548 const std::vector<short>& membership,
552 using Descriptor = AttributeSet::Descriptor;
556 auto iter = tree.cbeginLeaf();
559 const AttributeSet& attributeSet = iter->attributeSet();
560 const Descriptor& descriptor = attributeSet.
descriptor();
562 if (!descriptor.hasGroup(group)) {
573 IndexTreeManager leafManager(indexTree);
575 const int64_t
max = tbb::parallel_reduce(leafManager.leafRange(), -1,
576 [](
const typename IndexTreeManager::LeafRange& range, int64_t value) -> int64_t {
577 for (auto leaf = range.begin(); leaf; ++leaf) {
578 auto it = std::max_element(leaf->indices().begin(), leaf->indices().end());
579 value = std::max(value, static_cast<int64_t>(*it));
583 [](
const int64_t a,
const int64_t b) {
588 if (
max != -1 && membership.size() <=
static_cast<size_t>(
max)) {
590 " the maximum index within the provided index tree.");
594 const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
595 LeafManagerT leafManager(tree);
600 SetGroupFromIndexOp<PointDataTreeT, PointIndexTreeT, true>
601 set(indexTree, membership, index);
602 tbb::parallel_for(leafManager.leafRange(), set);
605 SetGroupFromIndexOp<PointDataTreeT, PointIndexTreeT, false>
606 set(indexTree, membership, index);
607 tbb::parallel_for(leafManager.leafRange(), set);
615 template <
typename Po
intDataTreeT>
620 using Descriptor = AttributeSet::Descriptor;
625 auto iter = tree.cbeginLeaf();
629 const AttributeSet& attributeSet = iter->attributeSet();
630 const Descriptor& descriptor = attributeSet.
descriptor();
632 if (!descriptor.hasGroup(group)) {
636 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
637 LeafManagerT leafManager(tree);
641 if (member) tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTreeT, true>(index));
642 else tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTreeT, false>(index));
649 template <
typename Po
intDataTreeT,
typename FilterT>
652 const FilterT& filter)
654 using Descriptor = AttributeSet::Descriptor;
659 auto iter = tree.cbeginLeaf();
663 const AttributeSet& attributeSet = iter->attributeSet();
664 const Descriptor& descriptor = attributeSet.
descriptor();
666 if (!descriptor.hasGroup(group)) {
670 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
674 SetGroupByFilterOp<PointDataTreeT, FilterT> set(index, filter);
675 LeafManagerT leafManager(tree);
677 tbb::parallel_for(leafManager.leafRange(), set);
684 template <
typename Po
intDataTreeT>
688 const unsigned int seed = 0)
692 RandomFilter filter(tree, targetPoints, seed);
694 setGroupByFilter<PointDataTreeT, RandomFilter>(tree, group, filter);
701 template <
typename Po
intDataTreeT>
704 const float percentage = 10.0f,
705 const unsigned int seed = 0)
709 const int currentPoints =
static_cast<int>(
pointCount(tree));
710 const int targetPoints = int(
math::Round((percentage *
float(currentPoints))/100.0f));
712 RandomFilter filter(tree, targetPoints, seed);
714 setGroupByFilter<PointDataTreeT, RandomFilter>(tree, group, filter);
726 #endif // OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED