37 #ifndef OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
49 #include <tbb/parallel_reduce.h>
66 const AttributeSet::Descriptor& descriptor);
72 template <
typename Po
intDataTree>
80 template <
typename Po
intDataTree>
82 const std::vector<Name>& groups);
90 template <
typename Po
intDataTree>
93 const bool compact =
true);
99 template <
typename Po
intDataTree>
101 const std::vector<Name>& groups);
106 template <
typename Po
intDataTree>
112 template <
typename Po
intDataTree>
124 template <
typename Po
intDataTree,
typename Po
intIndexTree>
127 const std::vector<short>& membership,
129 const bool remove =
false);
136 template <
typename Po
intDataTree>
139 const bool member =
true);
146 template <
typename Po
intDataTree,
typename FilterT>
149 const FilterT& filter);
155 namespace point_group_internal {
159 template<
typename Po
intDataTreeType>
168 : mTargetIndex(targetIndex)
169 , mSourceIndex(sourceIndex) { }
171 void operator()(
const typename LeafManagerT::LeafRange& range)
const {
173 for (
auto leaf = range.begin(); leaf; ++leaf) {
175 GroupHandle sourceGroup = leaf->groupHandle(mSourceIndex);
178 for (
auto iter = leaf->beginIndexAll(); iter; ++iter) {
179 const bool groupOn = sourceGroup.
get(*iter);
180 targetGroup.
set(*iter, groupOn);
193 template <
typename Po
intDataTree,
bool Member>
199 SetGroupOp(
const AttributeSet::Descriptor::GroupIndex& index)
202 void operator()(
const typename LeafManagerT::LeafRange& range)
const
204 for (
auto leaf = range.begin(); leaf; ++leaf) {
222 template <
typename Po
intDataTree,
typename Po
intIndexTree,
bool Remove>
235 : mIndexTree(indexTree)
236 , mMembership(membership)
239 void operator()(
const typename LeafManagerT::LeafRange& range)
const
241 for (
auto leaf = range.begin(); leaf; ++leaf) {
247 if (!pointIndexLeaf)
continue;
257 const IndexArray& indices = pointIndexLeaf->indices();
259 for (
const Index64 i: indices) {
261 group.
set(static_cast<Index>(index), mMembership[i]);
262 }
else if (mMembership[i] ==
short(1)) {
263 group.set(static_cast<Index>(index),
short(1));
282 template <
typename Po
intDataTree,
typename FilterT,
typename IterT =
typename Po
intDataTree::LeafNodeType::ValueAllCIter>
292 , mFilter(filter) { }
294 void operator()(
const typename LeafManagerT::LeafRange& range)
const
296 for (
auto leaf = range.begin(); leaf; ++leaf) {
302 auto iter = leaf->template beginIndex<IterT, FilterT>(mFilter);
304 for (; iter; ++iter) {
305 group.set(*iter,
true);
331 : mAttributeSet(attributeSet) { }
340 const Descriptor& descriptor = mAttributeSet.descriptor();
344 const size_t groupAttributes = descriptor.count(GroupAttributeArray::attributeType());
346 if (groupAttributes == 0)
return 0;
348 const size_t totalSlots = groupAttributes * this->groupBits();
352 const AttributeSet::Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
353 const size_t usedSlots = groupMap.size();
355 return totalSlots - usedSlots;
363 return this->unusedGroups() >= this->groupBits();
369 const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
373 std::vector<size_t> indices;
374 indices.reserve(groupMap.size());
375 for (
const auto& namePos : groupMap) {
376 indices.push_back(namePos.second);
379 std::sort(indices.begin(), indices.end());
384 for (
const size_t& index : indices) {
385 if (index != offset)
break;
395 std::vector<size_t> indices;
397 const Descriptor::NameToPosMap& map = mAttributeSet.descriptor().map();
399 for (
const auto& namePos : map) {
400 const AttributeArray* array = mAttributeSet.getConst(namePos.first);
402 indices.push_back(namePos.second);
413 targetOffset = this->nextUnusedOffset();
415 const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
417 for (
const auto& namePos : groupMap) {
421 if (namePos.second >= targetOffset) {
422 sourceName = namePos.first;
423 sourceOffset = namePos.second;
443 const AttributeSet::Descriptor& descriptor)
445 for (
auto it = groups.begin(); it != groups.end();) {
446 if (!descriptor.hasGroup(*it)) it = groups.erase(it);
455 template <
typename Po
intDataTree>
458 using Descriptor = AttributeSet::Descriptor;
459 using LeafManagerT =
typename tree::template LeafManager<PointDataTree>;
472 const AttributeSet& attributeSet = iter->attributeSet();
474 GroupInfo groupInfo(attributeSet);
478 if (descriptor->hasGroup(group))
return;
480 const bool hasUnusedGroup = groupInfo.unusedGroups() > 0;
484 if (!hasUnusedGroup) {
488 const Name groupName = descriptor->uniqueName(
"__group");
490 descriptor = descriptor->duplicateAppend(groupName, GroupAttributeArray::attributeType());
492 const size_t pos = descriptor->find(groupName);
496 AppendAttributeOp<PointDataTree> append(descriptor, pos);
497 LeafManagerT leafManager(tree);
498 tbb::parallel_for(leafManager.leafRange(), append);
509 assert(groupInfo.unusedGroups() > 0);
513 const size_t offset = groupInfo.nextUnusedOffset();
517 descriptor->setGroup(group, offset);
523 if (hasUnusedGroup)
setGroup(tree, group,
false);
530 template <
typename Po
intDataTree>
532 const std::vector<Name>& groups)
537 for (
const Name& name : groups) {
546 template <
typename Po
intDataTree>
549 using Descriptor = AttributeSet::Descriptor;
559 const AttributeSet& attributeSet = iter->attributeSet();
568 descriptor->dropGroup(group);
579 template <
typename Po
intDataTree>
581 const std::vector<Name>& groups)
583 for (
const Name& name : groups) {
596 template <
typename Po
intDataTree>
599 using Descriptor = AttributeSet::Descriptor;
607 const AttributeSet& attributeSet = iter->attributeSet();
608 GroupInfo groupInfo(attributeSet);
615 descriptor->clearGroups();
619 std::vector<size_t> indices = groupInfo.populateGroupIndices();
630 template <
typename Po
intDataTree>
633 using Descriptor = AttributeSet::Descriptor;
634 using GroupIndex = Descriptor::GroupIndex;
635 using LeafManagerT =
typename tree::template LeafManager<PointDataTree>;
644 const AttributeSet& attributeSet = iter->attributeSet();
645 GroupInfo groupInfo(attributeSet);
649 if (!groupInfo.canCompactGroups())
return;
661 size_t sourceOffset, targetOffset;
663 while (groupInfo.requiresMove(sourceName, sourceOffset, targetOffset)) {
665 const GroupIndex sourceIndex = attributeSet.
groupIndex(sourceOffset);
666 const GroupIndex targetIndex = attributeSet.
groupIndex(targetOffset);
668 CopyGroupOp<PointDataTree> copy(targetIndex, sourceIndex);
669 LeafManagerT leafManager(tree);
670 tbb::parallel_for(leafManager.leafRange(), copy);
672 descriptor->setGroup(sourceName, targetOffset);
677 std::vector<size_t> indices = groupInfo.populateGroupIndices();
679 const size_t totalAttributesToDrop = groupInfo.unusedGroups() / groupInfo.groupBits();
681 assert(totalAttributesToDrop <= indices.size());
683 std::vector<size_t> indicesToDrop(indices.end() - totalAttributesToDrop, indices.end());
692 template <
typename Po
intDataTree,
typename Po
intIndexTree>
695 const std::vector<short>& membership,
699 using Descriptor = AttributeSet::Descriptor;
700 using LeafManagerT =
typename tree::template LeafManager<PointDataTree>;
706 const AttributeSet& attributeSet = iter->attributeSet();
707 const Descriptor& descriptor = attributeSet.
descriptor();
709 if (!descriptor.hasGroup(group)) {
720 IndexTreeManager leafManager(indexTree);
722 const int64_t
max = tbb::parallel_reduce(leafManager.leafRange(), -1,
723 [](
const typename IndexTreeManager::LeafRange& range, int64_t value) -> int64_t {
724 for (
auto leaf = range.begin(); leaf; ++leaf) {
725 auto it = std::max_element(leaf->indices().begin(), leaf->indices().end());
726 value =
std::max(value, static_cast<int64_t>(*it));
730 [](
const int64_t a,
const int64_t b) {
735 if (
max != -1 && membership.size() <= static_cast<size_t>(
max)) {
737 " the maximum index within the provided index tree.");
741 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
742 LeafManagerT leafManager(tree);
747 SetGroupFromIndexOp<PointDataTree, PointIndexTree, true>
748 set(indexTree, membership, index);
749 tbb::parallel_for(leafManager.leafRange(), set);
752 SetGroupFromIndexOp<PointDataTree, PointIndexTree, false>
753 set(indexTree, membership, index);
754 tbb::parallel_for(leafManager.leafRange(), set);
762 template <
typename Po
intDataTree>
767 using Descriptor = AttributeSet::Descriptor;
768 using LeafManagerT =
typename tree::template LeafManager<PointDataTree>;
776 const AttributeSet& attributeSet = iter->attributeSet();
777 const Descriptor& descriptor = attributeSet.
descriptor();
779 if (!descriptor.hasGroup(group)) {
783 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
784 LeafManagerT leafManager(tree);
788 if (member) tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTree, true>(index));
789 else tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTree, false>(index));
796 template <
typename Po
intDataTree,
typename FilterT>
799 const FilterT& filter)
801 using Descriptor = AttributeSet::Descriptor;
802 using LeafManagerT =
typename tree::template LeafManager<PointDataTree>;
810 const AttributeSet& attributeSet = iter->attributeSet();
811 const Descriptor& descriptor = attributeSet.
descriptor();
813 if (!descriptor.hasGroup(group)) {
817 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
821 SetGroupByFilterOp<PointDataTree, FilterT> set(index, filter);
822 LeafManagerT leafManager(tree);
824 tbb::parallel_for(leafManager.leafRange(), set);
831 template <
typename Po
intDataTree>
835 const unsigned int seed = 0)
839 RandomFilter filter(tree, targetPoints, seed);
841 setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
848 template <
typename Po
intDataTree>
851 const float percentage = 10.0f,
852 const unsigned int seed = 0)
856 const int currentPoints = static_cast<int>(
pointCount(tree));
857 const int targetPoints = int(
math::Round((percentage *
float(currentPoints))/100.0f));
859 RandomFilter filter(tree, targetPoints, seed);
861 setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
873 #endif // OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED