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);
45template <
typename Po
intDataTreeT>
53template <
typename Po
intDataTreeT>
55 const std::vector<Name>& groups);
63template <
typename Po
intDataTreeT>
64inline void dropGroup( PointDataTreeT& tree,
66 const bool compact =
true);
72template <
typename Po
intDataTreeT>
74 const std::vector<Name>& groups);
79template <
typename Po
intDataTreeT>
85template <
typename Po
intDataTreeT>
97template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT>
98inline void setGroup( PointDataTreeT& tree,
99 const PointIndexTreeT& indexTree,
100 const std::vector<short>& membership,
102 const bool remove =
false);
109template <
typename Po
intDataTreeT>
110inline void setGroup( PointDataTreeT& tree,
112 const bool member =
true);
119template <
typename Po
intDataTreeT,
typename FilterT>
122 const FilterT& filter);
129namespace point_group_internal {
133template<
typename Po
intDataTreeType>
136 using LeafManagerT =
typename tree::LeafManager<PointDataTreeType>;
137 using LeafRangeT =
typename LeafManagerT::LeafRange;
138 using GroupIndex = AttributeSet::Descriptor::GroupIndex;
140 CopyGroupOp(
const GroupIndex& targetIndex,
141 const GroupIndex& sourceIndex)
142 : mTargetIndex(targetIndex)
143 , mSourceIndex(sourceIndex) { }
145 void operator()(
const typename LeafManagerT::LeafRange& range)
const {
147 for (
auto leaf = range.begin(); leaf; ++leaf) {
149 GroupHandle sourceGroup = leaf->groupHandle(mSourceIndex);
150 GroupWriteHandle targetGroup = leaf->groupWriteHandle(mTargetIndex);
152 for (
auto iter = leaf->beginIndexAll(); iter; ++iter) {
153 const bool groupOn = sourceGroup.get(*iter);
154 targetGroup.set(*iter, groupOn);
161 const GroupIndex mTargetIndex;
162 const GroupIndex mSourceIndex;
167template <
typename Po
intDataTreeT,
bool Member>
170 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
171 using GroupIndex = AttributeSet::Descriptor::GroupIndex;
173 SetGroupOp(
const AttributeSet::Descriptor::GroupIndex& index)
176 void operator()(
const typename LeafManagerT::LeafRange& range)
const
178 for (
auto leaf = range.begin(); leaf; ++leaf) {
182 GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
186 group.collapse(Member);
192 const GroupIndex& mIndex;
196template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT,
bool Remove>
197struct SetGroupFromIndexOp
199 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
200 using LeafRangeT =
typename LeafManagerT::LeafRange;
201 using PointIndexLeafNode =
typename PointIndexTreeT::LeafNodeType;
202 using IndexArray =
typename PointIndexLeafNode::IndexArray;
203 using GroupIndex = AttributeSet::Descriptor::GroupIndex;
204 using MembershipArray = std::vector<short>;
206 SetGroupFromIndexOp(
const PointIndexTreeT& indexTree,
207 const MembershipArray& membership,
208 const GroupIndex& index)
209 : mIndexTree(indexTree)
210 , mMembership(membership)
213 void operator()(
const typename LeafManagerT::LeafRange& range)
const
215 for (
auto leaf = range.begin(); leaf; ++leaf) {
219 const PointIndexLeafNode* pointIndexLeaf = mIndexTree.probeConstLeaf(leaf->origin());
221 if (!pointIndexLeaf)
continue;
225 GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
231 const IndexArray& indices = pointIndexLeaf->indices();
233 for (
const Index64 i: indices) {
235 group.set(
static_cast<Index>(index), mMembership[i]);
236 }
else if (mMembership[i] ==
short(1)) {
237 group.set(
static_cast<Index>(index),
short(1));
250 const PointIndexTreeT& mIndexTree;
251 const MembershipArray& mMembership;
252 const GroupIndex& mIndex;
256template <
typename Po
intDataTreeT,
typename FilterT,
typename IterT =
typename Po
intDataTreeT::LeafNodeType::ValueAllCIter>
257struct SetGroupByFilterOp
259 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
260 using LeafRangeT =
typename LeafManagerT::LeafRange;
261 using LeafNodeT =
typename PointDataTreeT::LeafNodeType;
262 using GroupIndex = AttributeSet::Descriptor::GroupIndex;
264 SetGroupByFilterOp(
const GroupIndex& index,
const FilterT& filter)
266 , mFilter(filter) { }
268 void operator()(
const typename LeafManagerT::LeafRange& range)
const
270 for (
auto leaf = range.begin(); leaf; ++leaf) {
274 GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
276 auto iter = leaf->template beginIndex<IterT, FilterT>(mFilter);
278 for (; iter; ++iter) {
279 group.set(*iter,
true);
290 const GroupIndex& mIndex;
291 const FilterT& mFilter;
306 const AttributeSet::Descriptor& descriptor)
308 for (
auto it = groups.begin(); it != groups.end();) {
309 if (!descriptor.hasGroup(*it)) it = groups.erase(it);
318template <
typename Po
intDataTreeT>
325 auto iter = tree.cbeginLeaf();
329 const AttributeSet& attributeSet = iter->attributeSet();
334 if (descriptor->hasGroup(group))
return;
336 const bool hasUnusedGroup = descriptor->unusedGroups() > 0;
340 if (!hasUnusedGroup) {
344 const Name groupName = descriptor->uniqueName(
"__group");
346 descriptor = descriptor->duplicateAppend(groupName, GroupAttributeArray::attributeType());
347 const size_t pos = descriptor->find(groupName);
353 [&](
typename PointDataTreeT::LeafNodeType& leaf,
size_t ) {
354 auto expected = leaf.attributeSet().descriptorPtr();
355 leaf.appendAttribute(*expected, descriptor, pos);
368 assert(descriptor->unusedGroups() > 0);
372 const size_t offset = descriptor->unusedGroupOffset();
376 descriptor->setGroup(group, offset);
382 if (hasUnusedGroup)
setGroup(tree, group,
false);
389template <
typename Po
intDataTreeT>
391 const std::vector<Name>& groups)
396 for (
const Name& name : groups) {
405template <
typename Po
intDataTreeT>
406inline void dropGroup(PointDataTreeT& tree,
const Name& group,
const bool compact)
408 using Descriptor = AttributeSet::Descriptor;
414 auto iter = tree.cbeginLeaf();
418 const AttributeSet& attributeSet = iter->attributeSet();
427 descriptor->dropGroup(group);
438template <
typename Po
intDataTreeT>
440 const std::vector<Name>& groups)
442 for (
const Name& name : groups) {
455template <
typename Po
intDataTreeT>
458 using Descriptor = AttributeSet::Descriptor;
460 auto iter = tree.cbeginLeaf();
464 const AttributeSet& attributeSet = iter->attributeSet();
471 descriptor->clearGroups();
486template <
typename Po
intDataTreeT>
489 using Descriptor = AttributeSet::Descriptor;
490 using GroupIndex = Descriptor::GroupIndex;
491 using LeafManagerT =
typename tree::template LeafManager<PointDataTreeT>;
493 using point_group_internal::CopyGroupOp;
495 auto iter = tree.cbeginLeaf();
499 const AttributeSet& attributeSet = iter->attributeSet();
503 if (!attributeSet.
descriptor().canCompactGroups())
return;
515 size_t sourceOffset, targetOffset;
517 while (descriptor->requiresGroupMove(sourceName, sourceOffset, targetOffset)) {
519 const GroupIndex sourceIndex = attributeSet.
groupIndex(sourceOffset);
520 const GroupIndex targetIndex = attributeSet.
groupIndex(targetOffset);
522 CopyGroupOp<PointDataTreeT> copy(targetIndex, sourceIndex);
523 LeafManagerT leafManager(tree);
524 tbb::parallel_for(leafManager.leafRange(), copy);
526 descriptor->setGroup(sourceName, targetOffset);
533 const size_t totalAttributesToDrop = descriptor->unusedGroups() / descriptor->groupBits();
535 assert(totalAttributesToDrop <= indices.size());
537 const std::vector<size_t> indicesToDrop(indices.end() - totalAttributesToDrop,
547template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT>
549 const PointIndexTreeT& indexTree,
550 const std::vector<short>& membership,
554 using Descriptor = AttributeSet::Descriptor;
556 using point_group_internal::SetGroupFromIndexOp;
558 auto iter = tree.cbeginLeaf();
561 const AttributeSet& attributeSet = iter->attributeSet();
562 const Descriptor& descriptor = attributeSet.
descriptor();
564 if (!descriptor.hasGroup(group)) {
575 IndexTreeManager leafManager(indexTree);
577 const int64_t max = tbb::parallel_reduce(leafManager.leafRange(), -1,
578 [](
const typename IndexTreeManager::LeafRange& range, int64_t
value) -> int64_t {
579 for (auto leaf = range.begin(); leaf; ++leaf) {
580 auto it = std::max_element(leaf->indices().begin(), leaf->indices().end());
581 value = std::max(value, static_cast<int64_t>(*it));
585 [](
const int64_t a,
const int64_t b) {
586 return std::max(a, b);
590 if (max != -1 && membership.size() <=
static_cast<size_t>(max)) {
592 " the maximum index within the provided index tree.");
596 const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
597 LeafManagerT leafManager(tree);
602 SetGroupFromIndexOp<PointDataTreeT, PointIndexTreeT, true>
603 set(indexTree, membership, index);
604 tbb::parallel_for(leafManager.leafRange(), set);
607 SetGroupFromIndexOp<PointDataTreeT, PointIndexTreeT, false>
608 set(indexTree, membership, index);
609 tbb::parallel_for(leafManager.leafRange(), set);
617template <
typename Po
intDataTreeT>
622 using Descriptor = AttributeSet::Descriptor;
625 using point_group_internal::SetGroupOp;
627 auto iter = tree.cbeginLeaf();
631 const AttributeSet& attributeSet = iter->attributeSet();
632 const Descriptor& descriptor = attributeSet.
descriptor();
634 if (!descriptor.hasGroup(group)) {
638 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
639 LeafManagerT leafManager(tree);
643 if (member) tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTreeT, true>(index));
644 else tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTreeT, false>(index));
651template <
typename Po
intDataTreeT,
typename FilterT>
654 const FilterT& filter)
656 using Descriptor = AttributeSet::Descriptor;
659 using point_group_internal::SetGroupByFilterOp;
661 auto iter = tree.cbeginLeaf();
665 const AttributeSet& attributeSet = iter->attributeSet();
666 const Descriptor& descriptor = attributeSet.
descriptor();
668 if (!descriptor.hasGroup(group)) {
672 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
676 SetGroupByFilterOp<PointDataTreeT, FilterT> set(index, filter);
677 LeafManagerT leafManager(tree);
679 tbb::parallel_for(leafManager.leafRange(), set);
686template <
typename Po
intDataTreeT>
690 const unsigned int seed = 0)
694 RandomFilter filter(tree, targetPoints, seed);
696 setGroupByFilter<PointDataTreeT, RandomFilter>(tree, group, filter);
703template <
typename Po
intDataTreeT>
706 const float percentage = 10.0f,
707 const unsigned int seed = 0)
711 const int currentPoints =
static_cast<int>(
pointCount(tree));
712 const int targetPoints = int(math::Round((percentage *
float(currentPoints))/100.0f));
714 RandomFilter filter(tree, targetPoints, seed);
716 setGroupByFilter<PointDataTreeT, RandomFilter>(tree, group, filter);
Set of Attribute Arrays which tracks metadata about each array.
ValueT value
Definition GridBuilder.h:1290
Index filters primarily designed to be used with a FilterIndexIter.
Point attribute manipulation in a VDB Point Grid.
Methods for counting points in VDB Point grids.
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Definition Exceptions.h:57
Definition Exceptions.h:59
Definition Exceptions.h:60
Ordered collection of uniquely-named attribute arrays.
Definition AttributeSet.h:39
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set's descriptor, which might be shared with other sets.
Definition AttributeSet.h:108
Util::GroupIndex groupIndex(const Name &groupName) const
Return the group index from the name of the group.
Descriptor & descriptor()
Return a reference to this attribute set's descriptor, which might be shared with other sets.
Definition AttributeSet.h:102
std::vector< size_t > groupAttributeIndices() const
Return the indices of the attribute arrays which are group attribute arrays.
Definition IndexFilter.h:229
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:85
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
std::vector< Index > IndexArray
Definition PointMove.h:161
void dropGroups(PointDataTreeT &tree, const std::vector< Name > &groups)
Drops existing groups from the VDB tree, the tree is compacted after dropping.
Definition PointGroup.h:439
void setGroup(PointDataTreeT &tree, const PointIndexTreeT &indexTree, const std::vector< short > &membership, const Name &group, const bool remove=false)
Sets group membership from a PointIndexTree-ordered vector.
Definition PointGroup.h:548
void setGroupByRandomPercentage(PointDataTreeT &tree, const Name &group, const float percentage=10.0f, const unsigned int seed=0)
Definition PointGroup.h:704
void deleteMissingPointGroups(std::vector< std::string > &groups, const AttributeSet::Descriptor &descriptor)
Delete any group that is not present in the Descriptor.
Definition PointGroup.h:305
void compactGroups(PointDataTreeT &tree)
Compacts existing groups of a VDB Tree to use less memory if possible.
Definition PointGroup.h:487
void appendGroup(PointDataTreeT &tree, const Name &group)
Appends a new empty group to the VDB tree.
Definition PointGroup.h:319
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition PointCount.h:88
void setGroupByRandomTarget(PointDataTreeT &tree, const Name &group, const Index64 targetPoints, const unsigned int seed=0)
Definition PointGroup.h:687
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition PointAttribute.h:380
void appendGroups(PointDataTreeT &tree, const std::vector< Name > &groups)
Appends new empty groups to the VDB tree.
Definition PointGroup.h:390
void setGroupByFilter(PointDataTreeT &tree, const Name &group, const FilterT &filter)
Sets group membership based on a provided filter.
Definition PointGroup.h:652
void dropGroup(PointDataTreeT &tree, const Name &group, const bool compact=true)
Drops an existing group from the VDB tree.
Definition PointGroup.h:406
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition PointDataGrid.h:1589
std::string Name
Definition Name.h:17
Index32 Index
Definition Types.h:54
uint64_t Index64
Definition Types.h:53
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
#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