9 #ifndef OPENVDB_POINTS_POINT_GROUP_IMPL_HAS_BEEN_INCLUDED
10 #define OPENVDB_POINTS_POINT_GROUP_IMPL_HAS_BEEN_INCLUDED
19 namespace point_group_internal {
23 template<
typename Po
intDataTreeType>
26 using LeafManagerT =
typename tree::LeafManager<PointDataTreeType>;
27 using LeafRangeT =
typename LeafManagerT::LeafRange;
28 using GroupIndex = AttributeSet::Descriptor::GroupIndex;
30 CopyGroupOp(
const GroupIndex& targetIndex,
31 const GroupIndex& sourceIndex)
32 : mTargetIndex(targetIndex)
33 , mSourceIndex(sourceIndex) { }
35 void operator()(
const typename LeafManagerT::LeafRange&
range)
const {
37 for (
auto leaf = range.begin(); leaf; ++leaf) {
39 GroupHandle sourceGroup = leaf->groupHandle(mSourceIndex);
40 GroupWriteHandle targetGroup = leaf->groupWriteHandle(mTargetIndex);
42 for (
auto iter = leaf->beginIndexAll(); iter; ++iter) {
43 const bool groupOn = sourceGroup.get(*iter);
44 targetGroup.set(*iter, groupOn);
51 const GroupIndex mTargetIndex;
52 const GroupIndex mSourceIndex;
57 template <
typename Po
intDataTreeT,
bool Member>
60 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
61 using GroupIndex = AttributeSet::Descriptor::GroupIndex;
63 SetGroupOp(
const AttributeSet::Descriptor::GroupIndex&
index)
66 void operator()(
const typename LeafManagerT::LeafRange& range)
const
68 for (
auto leaf = range.begin(); leaf; ++leaf) {
72 GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
82 const GroupIndex& mIndex;
86 template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT,
bool Remove>
87 struct SetGroupFromIndexOp
89 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
90 using LeafRangeT =
typename LeafManagerT::LeafRange;
91 using PointIndexLeafNode =
typename PointIndexTreeT::LeafNodeType;
93 using GroupIndex = AttributeSet::Descriptor::GroupIndex;
94 using MembershipArray = std::vector<short>;
96 SetGroupFromIndexOp(
const PointIndexTreeT& indexTree,
97 const MembershipArray& membership,
98 const GroupIndex&
index)
99 : mIndexTree(indexTree)
100 , mMembership(membership)
103 void operator()(
const typename LeafManagerT::LeafRange& range)
const
105 for (
auto leaf = range.begin(); leaf; ++leaf) {
109 const PointIndexLeafNode* pointIndexLeaf = mIndexTree.probeConstLeaf(leaf->origin());
111 if (!pointIndexLeaf)
continue;
115 GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
123 for (
const Index64 i: indices) {
125 group.set(static_cast<Index>(index), mMembership[i]);
126 }
else if (mMembership[i] ==
short(1)) {
127 group.set(static_cast<Index>(index),
short(1));
140 const PointIndexTreeT& mIndexTree;
141 const MembershipArray& mMembership;
142 const GroupIndex& mIndex;
146 template <
typename Po
intDataTreeT,
typename FilterT,
typename IterT =
typename Po
intDataTreeT::LeafNodeType::ValueAllCIter>
147 struct SetGroupByFilterOp
149 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
150 using LeafRangeT =
typename LeafManagerT::LeafRange;
151 using LeafNodeT =
typename PointDataTreeT::LeafNodeType;
152 using GroupIndex = AttributeSet::Descriptor::GroupIndex;
154 SetGroupByFilterOp(
const GroupIndex& index,
const FilterT&
filter)
156 , mFilter(filter) { }
158 void operator()(
const typename LeafManagerT::LeafRange& range)
const
160 for (
auto leaf = range.begin(); leaf; ++leaf) {
164 GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
166 auto iter = leaf->template beginIndex<IterT, FilterT>(mFilter);
168 for (; iter; ++iter) {
169 group.set(*iter,
true);
180 const GroupIndex& mIndex;
181 const FilterT& mFilter;
198 for (
auto it = groups.begin(); it != groups.end();) {
199 if (!descriptor.hasGroup(*it)) it = groups.erase(it);
208 template <
typename Po
intDataTreeT>
212 OPENVDB_THROW(KeyError,
"Cannot use an empty group name as a key.");
215 auto iter = tree.cbeginLeaf();
219 const AttributeSet& attributeSet = iter->attributeSet();
224 if (descriptor->hasGroup(group))
return;
226 const bool hasUnusedGroup = descriptor->unusedGroups() > 0;
230 if (!hasUnusedGroup) {
234 const Name groupName = descriptor->uniqueName(
"__group");
236 descriptor = descriptor->duplicateAppend(groupName, GroupAttributeArray::attributeType());
237 const size_t pos = descriptor->find(groupName);
243 [&](
typename PointDataTreeT::LeafNodeType& leaf,
size_t ) {
244 auto expected = leaf.attributeSet().descriptorPtr();
245 leaf.appendAttribute(*expected, descriptor, pos);
258 assert(descriptor->unusedGroups() > 0);
262 const size_t offset = descriptor->unusedGroupOffset();
266 descriptor->setGroup(group, offset);
272 if (hasUnusedGroup)
setGroup(tree, group,
false);
279 template <
typename Po
intDataTreeT>
281 const std::vector<Name>& groups)
295 template <
typename Po
intDataTreeT>
296 inline void dropGroup(PointDataTreeT& tree,
const Name& group,
const bool compact)
301 OPENVDB_THROW(KeyError,
"Cannot use an empty group name as a key.");
304 auto iter = tree.cbeginLeaf();
308 const AttributeSet& attributeSet = iter->attributeSet();
317 descriptor->dropGroup(group);
328 template <
typename Po
intDataTreeT>
330 const std::vector<Name>& groups)
345 template <
typename Po
intDataTreeT>
350 auto iter = tree.cbeginLeaf();
354 const AttributeSet& attributeSet = iter->attributeSet();
361 descriptor->clearGroups();
376 template <
typename Po
intDataTreeT>
380 using GroupIndex = Descriptor::GroupIndex;
381 using LeafManagerT =
typename tree::template LeafManager<PointDataTreeT>;
383 using point_group_internal::CopyGroupOp;
385 auto iter = tree.cbeginLeaf();
389 const AttributeSet& attributeSet = iter->attributeSet();
393 if (!attributeSet.
descriptor().canCompactGroups())
return;
405 size_t sourceOffset, targetOffset;
407 while (descriptor->requiresGroupMove(sourceName, sourceOffset, targetOffset)) {
409 const GroupIndex sourceIndex = attributeSet.
groupIndex(sourceOffset);
410 const GroupIndex targetIndex = attributeSet.
groupIndex(targetOffset);
412 CopyGroupOp<PointDataTreeT>
copy(targetIndex, sourceIndex);
413 LeafManagerT leafManager(tree);
416 descriptor->setGroup(sourceName, targetOffset);
423 const size_t totalAttributesToDrop = descriptor->unusedGroups() / descriptor->groupBits();
425 assert(totalAttributesToDrop <= indices.size());
427 const std::vector<size_t> indicesToDrop(indices.end() - totalAttributesToDrop,
437 template <
typename Po
intDataTreeT,
typename Po
intIndexTreeT>
439 const PointIndexTreeT& indexTree,
440 const std::vector<short>& membership,
446 using point_group_internal::SetGroupFromIndexOp;
448 auto iter = tree.cbeginLeaf();
451 const AttributeSet& attributeSet = iter->attributeSet();
452 const Descriptor& descriptor = attributeSet.
descriptor();
454 if (!descriptor.hasGroup(group)) {
455 OPENVDB_THROW(LookupError,
"Group must exist on Tree before defining membership.");
465 IndexTreeManager leafManager(indexTree);
467 const int64_t
max = tbb::parallel_reduce(leafManager.leafRange(), -1,
468 [](
const typename IndexTreeManager::LeafRange&
range, int64_t
value) -> int64_t {
469 for (
auto leaf = range.begin(); leaf; ++leaf) {
470 auto it = std::max_element(leaf->indices().begin(), leaf->indices().end());
475 [](
const int64_t
a,
const int64_t
b) {
480 if (max != -1 && membership.size() <=
static_cast<size_t>(
max)) {
481 OPENVDB_THROW(IndexError,
"Group membership vector size must be larger than "
482 " the maximum index within the provided index tree.");
486 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
487 LeafManagerT leafManager(tree);
492 SetGroupFromIndexOp<PointDataTreeT, PointIndexTreeT, true>
493 set(indexTree, membership, index);
497 SetGroupFromIndexOp<PointDataTreeT, PointIndexTreeT, false>
498 set(indexTree, membership, index);
507 template <
typename Po
intDataTreeT>
515 using point_group_internal::SetGroupOp;
517 auto iter = tree.cbeginLeaf();
521 const AttributeSet& attributeSet = iter->attributeSet();
522 const Descriptor& descriptor = attributeSet.
descriptor();
524 if (!descriptor.hasGroup(group)) {
525 OPENVDB_THROW(LookupError,
"Group must exist on Tree before defining membership.");
528 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
529 LeafManagerT leafManager(tree);
533 if (member)
tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTreeT, true>(index));
534 else tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTreeT, false>(index));
541 template <
typename Po
intDataTreeT,
typename FilterT>
549 using point_group_internal::SetGroupByFilterOp;
551 auto iter = tree.cbeginLeaf();
555 const AttributeSet& attributeSet = iter->attributeSet();
556 const Descriptor& descriptor = attributeSet.
descriptor();
558 if (!descriptor.hasGroup(group)) {
559 OPENVDB_THROW(LookupError,
"Group must exist on Tree before defining membership.");
562 const Descriptor::GroupIndex index = attributeSet.
groupIndex(group);
566 SetGroupByFilterOp<PointDataTreeT, FilterT> set(index, filter);
567 LeafManagerT leafManager(tree);
576 template <
typename Po
intDataTreeT>
580 const unsigned int seed = 0)
584 RandomFilter
filter(tree, targetPoints, seed);
586 setGroupByFilter<PointDataTreeT, RandomFilter>(tree, group,
filter);
593 template <
typename Po
intDataTreeT>
596 const float percentage = 10.0
f,
597 const unsigned int seed = 0)
601 const int currentPoints =
static_cast<int>(
pointCount(tree));
602 const int targetPoints =
int(
math::Round((percentage *
float(currentPoints))/100.0
f));
604 RandomFilter
filter(tree, targetPoints, seed);
606 setGroupByFilter<PointDataTreeT, RandomFilter>(tree, group,
filter);
614 #endif // OPENVDB_POINTS_POINT_GROUP_IMPL_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))
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
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.
GLsizei GLenum const void * indices
GLdouble GLdouble GLint GLint const GLdouble * points
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.
GLsizei const GLfloat * value
void appendGroup(PointDataTreeT &tree, const Name &group)
Appends a new empty group to the VDB tree.
GLboolean GLboolean GLboolean GLboolean a
#define OPENVDB_USE_VERSION_NAMESPACE
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)
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.
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.
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.
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter, const bool inCoreOnly, const bool threaded)
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.
GLuint const GLchar * name
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.
GLboolean GLboolean GLboolean b
void setGroup(PointDataTreeT &tree, const PointIndexTreeT &indexTree, const std::vector< short > &membership, const Name &group, const bool remove)
Sets group membership from a PointIndexTree-ordered vector.
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
Ordered collection of uniquely-named attribute arrays.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
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)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter