10 #ifndef OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
22 #include <tbb/parallel_reduce.h>
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>
129 namespace point_group_internal {
133 template<
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;
167 template <
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));
192 const GroupIndex& mIndex;
196 template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT,
bool Remove>
197 struct SetGroupFromIndexOp
199 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
200 using LeafRangeT =
typename LeafManagerT::LeafRange;
201 using PointIndexLeafNode =
typename PointIndexTreeT::LeafNodeType;
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));
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;
256 template <
typename Po
intDataTreeT,
typename FilterT,
typename IterT =
typename Po
intDataTreeT::LeafNodeType::ValueAllCIter>
257 struct 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;
308 for (
auto it = groups.begin(); it != groups.end();) {
309 if (!descriptor.hasGroup(*it)) it = groups.erase(it);
318 template <
typename Po
intDataTreeT>
322 OPENVDB_THROW(KeyError,
"Cannot use an empty group name as a key.");
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);
389 template <
typename Po
intDataTreeT>
391 const std::vector<Name>&
groups)
405 template <
typename Po
intDataTreeT>
411 OPENVDB_THROW(KeyError,
"Cannot use an empty group name as a key.");
414 auto iter = tree.cbeginLeaf();
418 const AttributeSet& attributeSet = iter->attributeSet();
427 descriptor->dropGroup(group);
438 template <
typename Po
intDataTreeT>
440 const std::vector<Name>&
groups)
455 template <
typename Po
intDataTreeT>
460 auto iter = tree.cbeginLeaf();
464 const AttributeSet& attributeSet = iter->attributeSet();
471 descriptor->clearGroups();
486 template <
typename Po
intDataTreeT>
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);
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,
547 template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT>
549 const PointIndexTreeT& indexTree,
550 const std::vector<short>& membership,
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)) {
565 OPENVDB_THROW(LookupError,
"Group must exist on Tree before defining membership.");
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());
585 [](
const int64_t
a,
const int64_t
b) {
590 if (max != -1 && membership.size() <=
static_cast<size_t>(
max)) {
591 OPENVDB_THROW(IndexError,
"Group membership vector size must be larger than "
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);
607 SetGroupFromIndexOp<PointDataTreeT, PointIndexTreeT, false>
608 set(indexTree, membership, index);
617 template <
typename Po
intDataTreeT>
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)) {
635 OPENVDB_THROW(LookupError,
"Group must exist on Tree before defining membership.");
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));
651 template <
typename Po
intDataTreeT,
typename FilterT>
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)) {
669 OPENVDB_THROW(LookupError,
"Group must exist on Tree before defining membership.");
672 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
676 SetGroupByFilterOp<PointDataTreeT, FilterT> set(index, filter);
677 LeafManagerT leafManager(tree);
686 template <
typename Po
intDataTreeT>
690 const unsigned int seed = 0)
694 RandomFilter
filter(tree, targetPoints, seed);
696 setGroupByFilter<PointDataTreeT, RandomFilter>(tree,
group,
filter);
703 template <
typename Po
intDataTreeT>
706 const float percentage = 10.0
f,
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.0
f));
714 RandomFilter
filter(tree, targetPoints, seed);
716 setGroupByFilter<PointDataTreeT, RandomFilter>(tree,
group,
filter);
728 #endif // OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
GLboolean GLboolean GLboolean b
Descriptor & descriptor()
Return a reference to this attribute set's descriptor, which might be shared with other sets...
Util::GroupIndex groupIndex(const Name &groupName) const
Return the group index from the name of the group.
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
void compactGroups(PointDataTreeT &tree)
Compacts existing groups of a VDB Tree to use less memory if possible.
void appendGroup(PointDataTreeT &tree, const Name &group)
Appends a new empty group to the VDB tree.
#define OPENVDB_USE_VERSION_NAMESPACE
Index filters primarily designed to be used with a FilterIndexIter.
GLuint const GLchar * name
void setGroupByRandomPercentage(PointDataTreeT &tree, const Name &group, const float percentage=10.0f, const unsigned int seed=0)
void dropGroup(PointDataTreeT &tree, const Name &group, const bool compact=true)
Drops an existing group from the VDB tree.
void deleteMissingPointGroups(std::vector< std::string > &groups, const AttributeSet::Descriptor &descriptor)
Delete any group that is not present in the Descriptor.
std::vector< Index > IndexArray
std::vector< size_t > groupAttributeIndices() const
Return the indices of the attribute arrays which are group attribute arrays.
Methods for counting points in VDB Point grids.
float Round(float x)
Return x rounded to the nearest integer.
void appendGroups(PointDataTreeT &tree, const std::vector< Name > &groups)
Appends new empty groups to the VDB tree.
GLboolean GLboolean GLboolean GLboolean a
GLsizei GLenum const void * indices
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
void dropGroups(PointDataTreeT &tree, const std::vector< Name > &groups)
Drops existing groups from the VDB tree, the tree is compacted after dropping.
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
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.
void setGroupByFilter(PointDataTreeT &tree, const Name &group, const FilterT &filter)
Sets group membership based on a provided filter.
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.
GLuint GLdouble GLdouble GLint GLint const GLdouble * points
Point attribute manipulation in a VDB Point Grid.
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.
Set of Attribute Arrays which tracks metadata about each array.
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
Ordered collection of uniquely-named attribute arrays.
GLsizei const GLfloat * value
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set's descriptor, which might be shared with other sets...
#define OPENVDB_THROW(exception, message)
void setGroupByRandomTarget(PointDataTreeT &tree, const Name &group, const Index64 targetPoints, const unsigned int seed=0)