OpenVDB  7.0.0
PointGroup.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
9 
10 #ifndef OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
12 
13 #include <openvdb/openvdb.h>
14 
15 #include "IndexIterator.h" // FilterTraits
16 #include "IndexFilter.h" // FilterTraits
17 #include "AttributeSet.h"
18 #include "PointDataGrid.h"
19 #include "PointAttribute.h"
20 #include "PointCount.h"
21 
22 #include <tbb/parallel_reduce.h>
23 
24 #include <algorithm>
25 #include <random>
26 #include <string>
27 #include <vector>
28 
29 namespace openvdb {
31 namespace OPENVDB_VERSION_NAME {
32 namespace points {
33 
38 inline void deleteMissingPointGroups( std::vector<std::string>& groups,
39  const AttributeSet::Descriptor& descriptor);
40 
45 template <typename PointDataTree>
46 inline void appendGroup(PointDataTree& tree,
47  const Name& group);
48 
53 template <typename PointDataTree>
54 inline void appendGroups(PointDataTree& tree,
55  const std::vector<Name>& groups);
56 
63 template <typename PointDataTree>
64 inline void dropGroup( PointDataTree& tree,
65  const Name& group,
66  const bool compact = true);
67 
72 template <typename PointDataTree>
73 inline void dropGroups( PointDataTree& tree,
74  const std::vector<Name>& groups);
75 
79 template <typename PointDataTree>
80 inline void dropGroups( PointDataTree& tree);
81 
85 template <typename PointDataTree>
86 inline void compactGroups(PointDataTree& tree);
87 
97 template <typename PointDataTree, typename PointIndexTree>
98 inline void setGroup( PointDataTree& tree,
99  const PointIndexTree& indexTree,
100  const std::vector<short>& membership,
101  const Name& group,
102  const bool remove = false);
103 
109 template <typename PointDataTree>
110 inline void setGroup( PointDataTree& tree,
111  const Name& group,
112  const bool member = true);
113 
119 template <typename PointDataTree, typename FilterT>
120 inline void setGroupByFilter( PointDataTree& tree,
121  const Name& group,
122  const FilterT& filter);
123 
124 
126 
127 
128 namespace point_group_internal {
129 
130 
132 template<typename PointDataTreeType>
133 struct CopyGroupOp {
134 
136  using LeafRangeT = typename LeafManagerT::LeafRange;
137  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
138 
139  CopyGroupOp(const GroupIndex& targetIndex,
140  const GroupIndex& sourceIndex)
141  : mTargetIndex(targetIndex)
142  , mSourceIndex(sourceIndex) { }
143 
144  void operator()(const typename LeafManagerT::LeafRange& range) const {
145 
146  for (auto leaf = range.begin(); leaf; ++leaf) {
147 
148  GroupHandle sourceGroup = leaf->groupHandle(mSourceIndex);
149  GroupWriteHandle targetGroup = leaf->groupWriteHandle(mTargetIndex);
150 
151  for (auto iter = leaf->beginIndexAll(); iter; ++iter) {
152  const bool groupOn = sourceGroup.get(*iter);
153  targetGroup.set(*iter, groupOn);
154  }
155  }
156  }
157 
159 
162 };
163 
164 
166 template <typename PointDataTree, bool Member>
168 {
170  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
171 
172  SetGroupOp(const AttributeSet::Descriptor::GroupIndex& index)
173  : mIndex(index) { }
174 
175  void operator()(const typename LeafManagerT::LeafRange& range) const
176  {
177  for (auto leaf = range.begin(); leaf; ++leaf) {
178 
179  // obtain the group attribute array
180 
181  GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
182 
183  // set the group value
184 
185  group.collapse(Member);
186  }
187  }
188 
190 
192 }; // struct SetGroupOp
193 
194 
195 template <typename PointDataTree, typename PointIndexTree, bool Remove>
197 {
199  using LeafRangeT = typename LeafManagerT::LeafRange;
200  using PointIndexLeafNode = typename PointIndexTree::LeafNodeType;
202  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
203  using MembershipArray = std::vector<short>;
204 
206  const MembershipArray& membership,
207  const GroupIndex& index)
208  : mIndexTree(indexTree)
209  , mMembership(membership)
210  , mIndex(index) { }
211 
212  void operator()(const typename LeafManagerT::LeafRange& range) const
213  {
214  for (auto leaf = range.begin(); leaf; ++leaf) {
215 
216  // obtain the PointIndexLeafNode (using the origin of the current leaf)
217 
218  const PointIndexLeafNode* pointIndexLeaf = mIndexTree.probeConstLeaf(leaf->origin());
219 
220  if (!pointIndexLeaf) continue;
221 
222  // obtain the group attribute array
223 
224  GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
225 
226  // initialise the attribute storage
227 
228  Index64 index = 0;
229 
230  const IndexArray& indices = pointIndexLeaf->indices();
231 
232  for (const Index64 i: indices) {
233  if (Remove) {
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));
237  }
238  index++;
239  }
240 
241  // attempt to compact the array
242 
243  group.compact();
244  }
245  }
246 
248 
252 }; // struct SetGroupFromIndexOp
253 
254 
255 template <typename PointDataTree, typename FilterT, typename IterT = typename PointDataTree::LeafNodeType::ValueAllCIter>
257 {
259  using LeafRangeT = typename LeafManagerT::LeafRange;
261  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
262 
263  SetGroupByFilterOp( const GroupIndex& index, const FilterT& filter)
264  : mIndex(index)
265  , mFilter(filter) { }
266 
267  void operator()(const typename LeafManagerT::LeafRange& range) const
268  {
269  for (auto leaf = range.begin(); leaf; ++leaf) {
270 
271  // obtain the group attribute array
272 
273  GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
274 
275  auto iter = leaf->template beginIndex<IterT, FilterT>(mFilter);
276 
277  for (; iter; ++iter) {
278  group.set(*iter, true);
279  }
280 
281  // attempt to compact the array
282 
283  group.compact();
284  }
285  }
286 
288 
290  const FilterT& mFilter; // beginIndex takes a copy of mFilter
291 }; // struct SetGroupByFilterOp
292 
293 
295 
296 
299 {
300 public:
301  using Descriptor = AttributeSet::Descriptor;
302 
303  GroupInfo(const AttributeSet& attributeSet)
304  : mAttributeSet(attributeSet) { }
305 
307  static size_t groupBits() { return sizeof(GroupType) * CHAR_BIT; }
308 
311  size_t unusedGroups() const
312  {
313  const Descriptor& descriptor = mAttributeSet.descriptor();
314 
315  // compute total slots (one slot per bit of the group attributes)
316 
317  const size_t groupAttributes = descriptor.count(GroupAttributeArray::attributeType());
318 
319  if (groupAttributes == 0) return 0;
320 
321  const size_t totalSlots = groupAttributes * this->groupBits();
322 
323  // compute slots in use
324 
325  const AttributeSet::Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
326  const size_t usedSlots = groupMap.size();
327 
328  return totalSlots - usedSlots;
329  }
330 
332  bool canCompactGroups() const
333  {
334  // can compact if more unused groups than in one group attribute array
335 
336  return this->unusedGroups() >= this->groupBits();
337  }
338 
340  size_t nextUnusedOffset() const
341  {
342  const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
343 
344  // build a list of group indices
345 
346  std::vector<size_t> indices;
347  indices.reserve(groupMap.size());
348  for (const auto& namePos : groupMap) {
349  indices.push_back(namePos.second);
350  }
351 
352  std::sort(indices.begin(), indices.end());
353 
354  // return first index not present
355 
356  size_t offset = 0;
357  for (const size_t& index : indices) {
358  if (index != offset) break;
359  offset++;
360  }
361 
362  return offset;
363  }
364 
366  std::vector<size_t> populateGroupIndices() const
367  {
368  std::vector<size_t> indices;
369 
370  const Descriptor::NameToPosMap& map = mAttributeSet.descriptor().map();
371 
372  for (const auto& namePos : map) {
373  const AttributeArray* array = mAttributeSet.getConst(namePos.first);
374  if (isGroup(*array)) {
375  indices.push_back(namePos.second);
376  }
377  }
378 
379  return indices;
380  }
381 
384  bool requiresMove(Name& sourceName, size_t& sourceOffset, size_t& targetOffset) const {
385 
386  targetOffset = this->nextUnusedOffset();
387 
388  const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
389 
390  for (const auto& namePos : groupMap) {
391 
392  // move only required if source comes after the target
393 
394  if (namePos.second >= targetOffset) {
395  sourceName = namePos.first;
396  sourceOffset = namePos.second;
397  return true;
398  }
399  }
400 
401  return false;
402  }
403 
404 private:
405  const AttributeSet& mAttributeSet;
406 }; // class GroupInfo
407 
408 
409 } // namespace point_group_internal
410 
411 
413 
414 
415 inline void deleteMissingPointGroups( std::vector<std::string>& groups,
416  const AttributeSet::Descriptor& descriptor)
417 {
418  for (auto it = groups.begin(); it != groups.end();) {
419  if (!descriptor.hasGroup(*it)) it = groups.erase(it);
420  else ++it;
421  }
422 }
423 
424 
426 
427 
428 template <typename PointDataTreeT>
429 inline void appendGroup(PointDataTreeT& tree, const Name& group)
430 {
432 
433  if (group.empty()) {
434  OPENVDB_THROW(KeyError, "Cannot use an empty group name as a key.");
435  }
436 
437  auto iter = tree.cbeginLeaf();
438 
439  if (!iter) return;
440 
441  const AttributeSet& attributeSet = iter->attributeSet();
442  auto descriptor = attributeSet.descriptorPtr();
443  GroupInfo groupInfo(attributeSet);
444 
445  // don't add if group already exists
446 
447  if (descriptor->hasGroup(group)) return;
448 
449  const bool hasUnusedGroup = groupInfo.unusedGroups() > 0;
450 
451  // add a new group attribute if there are no unused groups
452 
453  if (!hasUnusedGroup) {
454 
455  // find a new internal group name
456 
457  const Name groupName = descriptor->uniqueName("__group");
458 
459  descriptor = descriptor->duplicateAppend(groupName, GroupAttributeArray::attributeType());
460  const size_t pos = descriptor->find(groupName);
461 
462  // insert new group attribute
463 
464  tree::LeafManager<PointDataTreeT> leafManager(tree);
465  leafManager.foreach(
466  [&](typename PointDataTreeT::LeafNodeType& leaf, size_t /*idx*/) {
467  auto expected = leaf.attributeSet().descriptorPtr();
468  leaf.appendAttribute(*expected, descriptor, pos);
469  }, /*threaded=*/true
470  );
471  }
472  else {
473  // make the descriptor unique before we modify the group map
474 
475  makeDescriptorUnique(tree);
476  descriptor = attributeSet.descriptorPtr();
477  }
478 
479  // ensure that there are now available groups
480 
481  assert(groupInfo.unusedGroups() > 0);
482 
483  // find next unused offset
484 
485  const size_t offset = groupInfo.nextUnusedOffset();
486 
487  // add the group mapping to the descriptor
488 
489  descriptor->setGroup(group, offset);
490 
491  // if there was an unused group then we did not need to append a new attribute, so
492  // we must manually clear membership in the new group as its bits may have been
493  // previously set
494 
495  if (hasUnusedGroup) setGroup(tree, group, false);
496 }
497 
498 
500 
501 
502 template <typename PointDataTree>
503 inline void appendGroups(PointDataTree& tree,
504  const std::vector<Name>& groups)
505 {
506  // TODO: could be more efficient by appending multiple groups at once
507  // instead of one-by-one, however this is likely not that common a use case
508 
509  for (const Name& name : groups) {
510  appendGroup(tree, name);
511  }
512 }
513 
514 
516 
517 
518 template <typename PointDataTree>
519 inline void dropGroup(PointDataTree& tree, const Name& group, const bool compact)
520 {
521  using Descriptor = AttributeSet::Descriptor;
522 
523  if (group.empty()) {
524  OPENVDB_THROW(KeyError, "Cannot use an empty group name as a key.");
525  }
526 
527  auto iter = tree.cbeginLeaf();
528 
529  if (!iter) return;
530 
531  const AttributeSet& attributeSet = iter->attributeSet();
532 
533  // make the descriptor unique before we modify the group map
534 
535  makeDescriptorUnique(tree);
536  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
537 
538  // now drop the group
539 
540  descriptor->dropGroup(group);
541 
542  if (compact) {
543  compactGroups(tree);
544  }
545 }
546 
547 
549 
550 
551 template <typename PointDataTree>
552 inline void dropGroups( PointDataTree& tree,
553  const std::vector<Name>& groups)
554 {
555  for (const Name& name : groups) {
556  dropGroup(tree, name, /*compact=*/false);
557  }
558 
559  // compaction done once for efficiency
560 
561  compactGroups(tree);
562 }
563 
564 
566 
567 
568 template <typename PointDataTree>
569 inline void dropGroups( PointDataTree& tree)
570 {
571  using Descriptor = AttributeSet::Descriptor;
572 
574 
575  auto iter = tree.cbeginLeaf();
576 
577  if (!iter) return;
578 
579  const AttributeSet& attributeSet = iter->attributeSet();
580  GroupInfo groupInfo(attributeSet);
581 
582  // make the descriptor unique before we modify the group map
583 
584  makeDescriptorUnique(tree);
585  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
586 
587  descriptor->clearGroups();
588 
589  // find all indices for group attribute arrays
590 
591  std::vector<size_t> indices = groupInfo.populateGroupIndices();
592 
593  // drop these attributes arrays
594 
595  dropAttributes(tree, indices);
596 }
597 
598 
600 
601 
602 template <typename PointDataTree>
603 inline void compactGroups(PointDataTree& tree)
604 {
605  using Descriptor = AttributeSet::Descriptor;
606  using GroupIndex = Descriptor::GroupIndex;
607  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
608 
611 
612  auto iter = tree.cbeginLeaf();
613 
614  if (!iter) return;
615 
616  const AttributeSet& attributeSet = iter->attributeSet();
617  GroupInfo groupInfo(attributeSet);
618 
619  // early exit if not possible to compact
620 
621  if (!groupInfo.canCompactGroups()) return;
622 
623  // make the descriptor unique before we modify the group map
624 
625  makeDescriptorUnique(tree);
626  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
627 
628  // generate a list of group offsets and move them (one-by-one)
629  // TODO: improve this algorithm to move multiple groups per array at once
630  // though this is likely not that common a use case
631 
632  Name sourceName;
633  size_t sourceOffset, targetOffset;
634 
635  while (groupInfo.requiresMove(sourceName, sourceOffset, targetOffset)) {
636 
637  const GroupIndex sourceIndex = attributeSet.groupIndex(sourceOffset);
638  const GroupIndex targetIndex = attributeSet.groupIndex(targetOffset);
639 
640  CopyGroupOp<PointDataTree> copy(targetIndex, sourceIndex);
641  LeafManagerT leafManager(tree);
642  tbb::parallel_for(leafManager.leafRange(), copy);
643 
644  descriptor->setGroup(sourceName, targetOffset);
645  }
646 
647  // drop unused attribute arrays
648 
649  std::vector<size_t> indices = groupInfo.populateGroupIndices();
650 
651  const size_t totalAttributesToDrop = groupInfo.unusedGroups() / groupInfo.groupBits();
652 
653  assert(totalAttributesToDrop <= indices.size());
654 
655  std::vector<size_t> indicesToDrop(indices.end() - totalAttributesToDrop, indices.end());
656 
657  dropAttributes(tree, indicesToDrop);
658 }
659 
660 
662 
663 
664 template <typename PointDataTree, typename PointIndexTree>
665 inline void setGroup( PointDataTree& tree,
666  const PointIndexTree& indexTree,
667  const std::vector<short>& membership,
668  const Name& group,
669  const bool remove)
670 {
671  using Descriptor = AttributeSet::Descriptor;
672  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
674 
675  auto iter = tree.cbeginLeaf();
676  if (!iter) return;
677 
678  const AttributeSet& attributeSet = iter->attributeSet();
679  const Descriptor& descriptor = attributeSet.descriptor();
680 
681  if (!descriptor.hasGroup(group)) {
682  OPENVDB_THROW(LookupError, "Group must exist on Tree before defining membership.");
683  }
684 
685  {
686  // Check that that the largest index in the PointIndexTree is smaller than the size
687  // of the membership vector. The index tree will be used to lookup membership
688  // values. If the index tree was constructed with nan positions, this index will
689  // differ from the PointDataTree count
690 
691  using IndexTreeManager = tree::LeafManager<const PointIndexTree>;
692  IndexTreeManager leafManager(indexTree);
693 
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));
699  }
700  return value;
701  },
702  [](const int64_t a, const int64_t b) {
703  return std::max(a, b);
704  }
705  );
706 
707  if (max != -1 && membership.size() <= static_cast<size_t>(max)) {
708  OPENVDB_THROW(IndexError, "Group membership vector size must be larger than "
709  " the maximum index within the provided index tree.");
710  }
711  }
712 
713  const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
714  LeafManagerT leafManager(tree);
715 
716  // set membership
717 
718  if (remove) {
719  SetGroupFromIndexOp<PointDataTree, PointIndexTree, true>
720  set(indexTree, membership, index);
721  tbb::parallel_for(leafManager.leafRange(), set);
722  }
723  else {
724  SetGroupFromIndexOp<PointDataTree, PointIndexTree, false>
725  set(indexTree, membership, index);
726  tbb::parallel_for(leafManager.leafRange(), set);
727  }
728 }
729 
730 
732 
733 
734 template <typename PointDataTree>
735 inline void setGroup( PointDataTree& tree,
736  const Name& group,
737  const bool member)
738 {
739  using Descriptor = AttributeSet::Descriptor;
740  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
741 
743 
744  auto iter = tree.cbeginLeaf();
745 
746  if (!iter) return;
747 
748  const AttributeSet& attributeSet = iter->attributeSet();
749  const Descriptor& descriptor = attributeSet.descriptor();
750 
751  if (!descriptor.hasGroup(group)) {
752  OPENVDB_THROW(LookupError, "Group must exist on Tree before defining membership.");
753  }
754 
755  const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
756  LeafManagerT leafManager(tree);
757 
758  // set membership based on member variable
759 
760  if (member) tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTree, true>(index));
761  else tbb::parallel_for(leafManager.leafRange(), SetGroupOp<PointDataTree, false>(index));
762 }
763 
764 
766 
767 
768 template <typename PointDataTree, typename FilterT>
769 inline void setGroupByFilter( PointDataTree& tree,
770  const Name& group,
771  const FilterT& filter)
772 {
773  using Descriptor = AttributeSet::Descriptor;
774  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
775 
777 
778  auto iter = tree.cbeginLeaf();
779 
780  if (!iter) return;
781 
782  const AttributeSet& attributeSet = iter->attributeSet();
783  const Descriptor& descriptor = attributeSet.descriptor();
784 
785  if (!descriptor.hasGroup(group)) {
786  OPENVDB_THROW(LookupError, "Group must exist on Tree before defining membership.");
787  }
788 
789  const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
790 
791  // set membership using filter
792 
793  SetGroupByFilterOp<PointDataTree, FilterT> set(index, filter);
794  LeafManagerT leafManager(tree);
795 
796  tbb::parallel_for(leafManager.leafRange(), set);
797 }
798 
799 
801 
802 
803 template <typename PointDataTree>
805  const Name& group,
806  const Index64 targetPoints,
807  const unsigned int seed = 0)
808 {
810 
811  RandomFilter filter(tree, targetPoints, seed);
812 
813  setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
814 }
815 
816 
818 
819 
820 template <typename PointDataTree>
822  const Name& group,
823  const float percentage = 10.0f,
824  const unsigned int seed = 0)
825 {
827 
828  const int currentPoints = static_cast<int>(pointCount(tree));
829  const int targetPoints = int(math::Round((percentage * float(currentPoints))/100.0f));
830 
831  RandomFilter filter(tree, targetPoints, seed);
832 
833  setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
834 }
835 
836 
838 
839 
840 } // namespace points
841 } // namespace OPENVDB_VERSION_NAME
842 } // namespace openvdb
843 
844 
845 #endif // OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:175
Definition: Exceptions.h:57
typename PointIndexTree::LeafNodeType PointIndexLeafNode
Definition: PointGroup.h:200
bool requiresMove(Name &sourceName, size_t &sourceOffset, size_t &targetOffset) const
Definition: PointGroup.h:384
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition: PointAttribute.h:370
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointGroup.h:199
void compactGroups(PointDataTree &tree)
Compacts existing groups of a VDB Tree to use less memory if possible.
Definition: PointGroup.h:603
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
std::vector< size_t > populateGroupIndices() const
Return vector of indices correlating to the group attribute arrays.
Definition: PointGroup.h:366
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:82
std::string Name
Definition: Name.h:17
const FilterT & mFilter
Definition: PointGroup.h:290
Base class for storing attribute data.
Definition: AttributeArray.h:92
Methods for counting points in VDB Point grids.
AttributeSet::Descriptor Descriptor
Definition: PointGroup.h:301
tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointIndexLeafNode< PointIndex32, 3 >, 4 >, 5 > >> PointIndexTree
Point index tree configured to match the default OpenVDB tree configuration.
Definition: PointIndexGrid.h:56
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:144
Descriptor & descriptor()
Return a reference to this attribute set&#39;s descriptor, which might be shared with other sets...
Definition: AttributeSet.h:98
const GroupIndex mTargetIndex
Definition: PointGroup.h:160
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:766
Definition: Exceptions.h:59
void setGroupByRandomTarget(PointDataTree &tree, const Name &group, const Index64 targetPoints, const unsigned int seed=0)
Definition: PointGroup.h:804
void setGroup(PointDataTree &tree, const Name &group, const bool member=true)
Sets membership for the specified group for all points (on/off).
Definition: PointGroup.h:735
Point attribute manipulation in a VDB Point Grid.
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:258
GroupInfo(const AttributeSet &attributeSet)
Definition: PointGroup.h:303
Index filters primarily designed to be used with a FilterIndexIter.
SetGroupByFilterOp(const GroupIndex &index, const FilterT &filter)
Definition: PointGroup.h:263
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:212
std::vector< short > MembershipArray
Definition: PointGroup.h:203
typename PointDataTree::LeafNodeType LeafNodeT
Definition: PointGroup.h:260
Definition: AttributeGroup.h:75
typename PointIndexLeafNode::IndexArray IndexArray
Definition: PointGroup.h:201
uint8_t GroupType
Definition: AttributeGroup.h:23
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:66
size_t unusedGroups() const
Definition: PointGroup.h:311
size_t nextUnusedOffset() const
Return the next empty group slot.
Definition: PointGroup.h:340
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointGroup.h:259
const GroupIndex & mIndex
Definition: PointGroup.h:289
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1157
const GroupIndex & mIndex
Definition: PointGroup.h:191
Definition: IndexFilter.h:226
Definition: Exceptions.h:13
Convenience class with methods for analyzing group data.
Definition: PointGroup.h:298
std::vector< Index > IndexArray
Definition: PointMove.h:161
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:198
bool canCompactGroups() const
Return true if there are sufficient empty slots to allow compacting.
Definition: PointGroup.h:332
const MembershipArray & mMembership
Definition: PointGroup.h:250
Index Iterators.
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:82
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:137
bool collapse(bool on)
Set membership for the whole array and attempt to collapse.
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:267
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:202
void deleteMissingPointGroups(std::vector< std::string > &groups, const AttributeSet::Descriptor &descriptor)
Delete any group that is not present in the Descriptor.
Definition: PointGroup.h:415
void appendGroups(PointDataTree &tree, const std::vector< Name > &groups)
Appends new empty groups to the VDB tree.
Definition: PointGroup.h:503
const GroupIndex mSourceIndex
Definition: PointGroup.h:161
const GroupIndex & mIndex
Definition: PointGroup.h:251
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:185
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:496
typename tree::LeafManager< PointDataTreeType > LeafManagerT
Definition: PointGroup.h:135
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: PointDataGrid.h:1587
Definition: Exceptions.h:60
void appendGroup(PointDataTreeT &tree, const Name &group)
Definition: PointGroup.h:429
void setGroupByFilter(PointDataTree &tree, const Name &group, const FilterT &filter)
Sets group membership based on a provided filter.
Definition: PointGroup.h:769
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Set membership on or off for the specified group.
Definition: PointGroup.h:167
typename LeafManagerT::LeafRange LeafRangeT
Definition: PointGroup.h:136
Definition: Tree.h:176
Copy a group attribute value from one group offset to another.
Definition: PointGroup.h:133
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:261
void dropGroup(PointDataTree &tree, const Name &group, const bool compact=true)
Drops an existing group from the VDB tree.
Definition: PointGroup.h:519
uint64_t Index64
Definition: Types.h:30
SetGroupOp(const AttributeSet::Descriptor::GroupIndex &index)
Definition: PointGroup.h:172
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:169
AttributeSet::Descriptor::GroupIndex GroupIndex
Definition: PointGroup.h:170
static size_t groupBits()
Return the number of bits in a group (typically 8)
Definition: PointGroup.h:307
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > >> PointDataTree
Point index tree configured to match the default VDB configurations.
Definition: PointDataGrid.h:189
SetGroupFromIndexOp(const PointIndexTree &indexTree, const MembershipArray &membership, const GroupIndex &index)
Definition: PointGroup.h:205
void setGroupByRandomPercentage(PointDataTree &tree, const Name &group, const float percentage=10.0f, const unsigned int seed=0)
Definition: PointGroup.h:821
Util::GroupIndex groupIndex(const Name &groupName) const
Return the group index from the name of the group.
CopyGroupOp(const GroupIndex &targetIndex, const GroupIndex &sourceIndex)
Definition: PointGroup.h:139
Definition: AttributeGroup.h:103
Set of Attribute Arrays which tracks metadata about each array.
void dropGroups(PointDataTree &tree)
Drops all existing groups from the VDB tree, the tree is compacted after dropping.
Definition: PointGroup.h:569
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:35
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:106
const PointIndexTree & mIndexTree
Definition: PointGroup.h:249
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set&#39;s descriptor, which might be shared with other sets...
Definition: AttributeSet.h:104