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
intDataTree>
53 template <
typename Po
intDataTree>
55 const std::vector<Name>& groups);
63 template <
typename Po
intDataTree>
66 const bool compact =
true);
72 template <
typename Po
intDataTree>
74 const std::vector<Name>& groups);
79 template <
typename Po
intDataTree>
85 template <
typename Po
intDataTree>
97 template <
typename Po
intDataTree,
typename Po
intIndexTree>
100 const std::vector<short>& membership,
102 const bool remove =
false);
109 template <
typename Po
intDataTree>
112 const bool member =
true);
119 template <
typename Po
intDataTree,
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
intDataTree,
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
intDataTree,
typename Po
intIndexTree,
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
intDataTree,
typename FilterT,
typename IterT =
typename Po
intDataTree::LeafNodeType::ValueAllCIter>
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 : mAttributeSet(attributeSet) { }
313 const Descriptor& descriptor = mAttributeSet.descriptor();
317 const size_t groupAttributes = descriptor.count(GroupAttributeArray::attributeType());
319 if (groupAttributes == 0)
return 0;
321 const size_t totalSlots = groupAttributes * this->groupBits();
325 const AttributeSet::Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
326 const size_t usedSlots = groupMap.size();
328 return totalSlots - usedSlots;
336 return this->unusedGroups() >= this->groupBits();
342 const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
346 std::vector<size_t> indices;
347 indices.reserve(groupMap.size());
348 for (
const auto& namePos : groupMap) {
349 indices.push_back(namePos.second);
352 std::sort(indices.begin(), indices.end());
357 for (
const size_t& index : indices) {
358 if (index != offset)
break;
368 std::vector<size_t> indices;
370 const Descriptor::NameToPosMap& map = mAttributeSet.descriptor().map();
372 for (
const auto& namePos : map) {
373 const AttributeArray* array = mAttributeSet.getConst(namePos.first);
375 indices.push_back(namePos.second);
386 targetOffset = this->nextUnusedOffset();
388 const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
390 for (
const auto& namePos : groupMap) {
394 if (namePos.second >= targetOffset) {
395 sourceName = namePos.first;
396 sourceOffset = namePos.second;
416 const AttributeSet::Descriptor& descriptor)
418 for (
auto it = groups.begin(); it != groups.end();) {
419 if (!descriptor.hasGroup(*it)) it = groups.erase(it);
428 template <
typename Po
intDataTreeT>
437 auto iter = tree.cbeginLeaf();
441 const AttributeSet& attributeSet = iter->attributeSet();
443 GroupInfo groupInfo(attributeSet);
447 if (descriptor->hasGroup(group))
return;
449 const bool hasUnusedGroup = groupInfo.unusedGroups() > 0;
453 if (!hasUnusedGroup) {
457 const Name groupName = descriptor->uniqueName(
"__group");
459 descriptor = descriptor->duplicateAppend(groupName, GroupAttributeArray::attributeType());
460 const size_t pos = descriptor->find(groupName);
466 [&](
typename PointDataTreeT::LeafNodeType& leaf,
size_t ) {
467 auto expected = leaf.attributeSet().descriptorPtr();
468 leaf.appendAttribute(*expected, descriptor, pos);
481 assert(groupInfo.unusedGroups() > 0);
485 const size_t offset = groupInfo.nextUnusedOffset();
489 descriptor->setGroup(group, offset);
495 if (hasUnusedGroup)
setGroup(tree, group,
false);
502 template <
typename Po
intDataTree>
504 const std::vector<Name>& groups)
509 for (
const Name& name : groups) {
518 template <
typename Po
intDataTree>
521 using Descriptor = AttributeSet::Descriptor;
531 const AttributeSet& attributeSet = iter->attributeSet();
540 descriptor->dropGroup(group);
551 template <
typename Po
intDataTree>
553 const std::vector<Name>& groups)
555 for (
const Name& name : groups) {
568 template <
typename Po
intDataTree>
571 using Descriptor = AttributeSet::Descriptor;
579 const AttributeSet& attributeSet = iter->attributeSet();
580 GroupInfo groupInfo(attributeSet);
587 descriptor->clearGroups();
591 std::vector<size_t> indices = groupInfo.populateGroupIndices();
602 template <
typename Po
intDataTree>
605 using Descriptor = AttributeSet::Descriptor;
606 using GroupIndex = Descriptor::GroupIndex;
607 using LeafManagerT =
typename tree::template LeafManager<PointDataTree>;
616 const AttributeSet& attributeSet = iter->attributeSet();
617 GroupInfo groupInfo(attributeSet);
621 if (!groupInfo.canCompactGroups())
return;
633 size_t sourceOffset, targetOffset;
635 while (groupInfo.requiresMove(sourceName, sourceOffset, targetOffset)) {
637 const GroupIndex sourceIndex = attributeSet.
groupIndex(sourceOffset);
638 const GroupIndex targetIndex = attributeSet.
groupIndex(targetOffset);
640 CopyGroupOp<PointDataTree> copy(targetIndex, sourceIndex);
641 LeafManagerT leafManager(tree);
642 tbb::parallel_for(leafManager.leafRange(), copy);
644 descriptor->setGroup(sourceName, targetOffset);
649 std::vector<size_t> indices = groupInfo.populateGroupIndices();
651 const size_t totalAttributesToDrop = groupInfo.unusedGroups() / groupInfo.groupBits();
653 assert(totalAttributesToDrop <= indices.size());
655 std::vector<size_t> indicesToDrop(indices.end() - totalAttributesToDrop, indices.end());
664 template <
typename Po
intDataTree,
typename Po
intIndexTree>
667 const std::vector<short>& membership,
671 using Descriptor = AttributeSet::Descriptor;
672 using LeafManagerT =
typename tree::template LeafManager<PointDataTree>;
678 const AttributeSet& attributeSet = iter->attributeSet();
679 const Descriptor& descriptor = attributeSet.
descriptor();
681 if (!descriptor.hasGroup(group)) {
692 IndexTreeManager leafManager(indexTree);
694 const int64_t
max = tbb::parallel_reduce(leafManager.leafRange(), -1,
695 [](
const typename IndexTreeManager::LeafRange& range, int64_t value) -> int64_t {
696 for (auto leaf = range.begin(); leaf; ++leaf) {
697 auto it = std::max_element(leaf->indices().begin(), leaf->indices().end());
698 value = std::max(value, static_cast<int64_t>(*it));
702 [](
const int64_t a,
const int64_t b) {
707 if (
max != -1 && membership.size() <=
static_cast<size_t>(
max)) {
709 " the maximum index within the provided index tree.");
713 const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
714 LeafManagerT leafManager(tree);
719 SetGroupFromIndexOp<PointDataTree, PointIndexTree, true>
720 set(indexTree, membership, index);
721 tbb::parallel_for(leafManager.leafRange(), set);
724 SetGroupFromIndexOp<PointDataTree, PointIndexTree, false>
725 set(indexTree, membership, index);
726 tbb::parallel_for(leafManager.leafRange(), set);
734 template <
typename Po
intDataTree>
739 using Descriptor = AttributeSet::Descriptor;
740 using LeafManagerT =
typename tree::template LeafManager<PointDataTree>;
748 const AttributeSet& attributeSet = iter->attributeSet();
749 const Descriptor& descriptor = attributeSet.
descriptor();
751 if (!descriptor.hasGroup(group)) {
755 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
756 LeafManagerT leafManager(tree);
760 if (member) tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTree, true>(index));
761 else tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTree, false>(index));
768 template <
typename Po
intDataTree,
typename FilterT>
771 const FilterT& filter)
773 using Descriptor = AttributeSet::Descriptor;
774 using LeafManagerT =
typename tree::template LeafManager<PointDataTree>;
782 const AttributeSet& attributeSet = iter->attributeSet();
783 const Descriptor& descriptor = attributeSet.
descriptor();
785 if (!descriptor.hasGroup(group)) {
789 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
793 SetGroupByFilterOp<PointDataTree, FilterT> set(index, filter);
794 LeafManagerT leafManager(tree);
796 tbb::parallel_for(leafManager.leafRange(), set);
803 template <
typename Po
intDataTree>
807 const unsigned int seed = 0)
811 RandomFilter filter(tree, targetPoints, seed);
813 setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
820 template <
typename Po
intDataTree>
823 const float percentage = 10.0f,
824 const unsigned int seed = 0)
828 const int currentPoints =
static_cast<int>(
pointCount(tree));
829 const int targetPoints = int(
math::Round((percentage *
float(currentPoints))/100.0f));
831 RandomFilter filter(tree, targetPoints, seed);
833 setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
845 #endif // OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED